Asterisk - The Open Source Telephony Project  18.5.0
pbx_lua.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2007, Digium, Inc.
5  *
6  * Matthew Nicholson <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  *
22  * \author Matthew Nicholson <[email protected]>
23  * \brief Lua PBX Switch
24  *
25  */
26 
27 /*** MODULEINFO
28  <depend>lua</depend>
29  <support_level>extended</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include "asterisk/logger.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/module.h"
38 #include "asterisk/cli.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/term.h"
41 #include "asterisk/paths.h"
42 #include "asterisk/hashtab.h"
43 
44 #include <lua.h>
45 #include <lauxlib.h>
46 #include <lualib.h>
47 
48 static char *config = "extensions.lua";
49 static char *registrar = "pbx_lua";
50 
51 #ifdef LOW_MEMORY
52 #define LUA_EXT_DATA_SIZE 256
53 #else
54 #define LUA_EXT_DATA_SIZE 8192
55 #endif
56 #define LUA_BUF_SIZE 4096
57 
58 /* This value is used by the lua engine to signal that a Goto or dialplan jump
59  * was detected. Ensure this value does not conflict with any values dialplan
60  * applications might return */
61 #define LUA_GOTO_DETECTED 5
62 
63 static char *lua_read_extensions_file(lua_State *L, long *size, int *file_not_openable);
64 static int lua_load_extensions(lua_State *L, struct ast_channel *chan);
65 static int lua_reload_extensions(lua_State *L);
66 static void lua_free_extensions(void);
67 static int lua_sort_extensions(lua_State *L);
68 static int lua_register_switches(lua_State *L);
69 static int lua_register_hints(lua_State *L);
70 static int lua_extension_cmp(lua_State *L);
71 static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func);
72 static int lua_pbx_findapp(lua_State *L);
73 static int lua_pbx_exec(lua_State *L);
74 
75 static int lua_get_variable_value(lua_State *L);
76 static int lua_set_variable_value(lua_State *L);
77 static int lua_get_variable(lua_State *L);
78 static int lua_set_variable(lua_State *L);
79 static int lua_func_read(lua_State *L);
80 
81 static int lua_autoservice_start(lua_State *L);
82 static int lua_autoservice_stop(lua_State *L);
83 static int lua_autoservice_status(lua_State *L);
84 static int lua_check_hangup(lua_State *L);
85 static int lua_error_function(lua_State *L);
86 
87 static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority);
88 static void lua_push_variable_table(lua_State *L);
89 static void lua_create_app_table(lua_State *L);
90 static void lua_create_channel_table(lua_State *L);
91 static void lua_create_variable_metatable(lua_State *L);
92 static void lua_create_application_metatable(lua_State *L);
93 static void lua_create_autoservice_functions(lua_State *L);
94 static void lua_create_hangup_function(lua_State *L);
95 static void lua_concat_args(lua_State *L, int start, int nargs);
96 
97 static void lua_state_destroy(void *data);
98 static void lua_datastore_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
99 static lua_State *lua_get_state(struct ast_channel *chan);
100 
101 static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
102 static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
103 static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
104 static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
105 
107 static char *config_file_data = NULL;
108 static long config_file_size = 0;
109 
110 static struct ast_context *local_contexts = NULL;
111 static struct ast_hashtab *local_table = NULL;
112 
113 static const struct ast_datastore_info lua_datastore = {
114  .type = "lua",
115  .destroy = lua_state_destroy,
116  .chan_fixup = lua_datastore_fixup,
117 };
118 
119 
120 /*!
121  * \brief The destructor for lua_datastore
122  */
123 static void lua_state_destroy(void *data)
124 {
125  if (data)
126  lua_close(data);
127 }
128 
129 /*!
130  * \brief The fixup function for the lua_datastore.
131  * \param data the datastore data, in this case it will be a lua_State
132  * \param old_chan the channel we are moving from
133  * \param new_chan the channel we are moving to
134  *
135  * This function updates our internal channel pointer.
136  */
137 static void lua_datastore_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
138 {
139  lua_State *L = data;
140  lua_pushlightuserdata(L, new_chan);
141  lua_setfield(L, LUA_REGISTRYINDEX, "channel");
142 }
143 
144 /*!
145  * \brief [lua_CFunction] Find an app and return it in a lua table (for access from lua, don't
146  * call directly)
147  *
148  * This function would be called in the following example as it would be found
149  * in extensions.lua.
150  *
151  * \code
152  * app.dial
153  * \endcode
154  */
155 static int lua_pbx_findapp(lua_State *L)
156 {
157  const char *app_name = luaL_checkstring(L, 2);
158 
159  lua_newtable(L);
160 
161  lua_pushstring(L, "name");
162  lua_pushstring(L, app_name);
163  lua_settable(L, -3);
164 
165  luaL_getmetatable(L, "application");
166  lua_setmetatable(L, -2);
167 
168  return 1;
169 }
170 
171 /*!
172  * \brief [lua_CFunction] This function is part of the 'application' metatable
173  * and is used to execute applications similar to pbx_exec() (for access from
174  * lua, don't call directly)
175  *
176  * \param L the lua_State to use
177  * \return nothing
178  *
179  * This funciton is executed as the '()' operator for apps accessed through the
180  * 'app' table.
181  *
182  * \code
183  * app.playback('demo-congrats')
184  * \endcode
185  */
186 static int lua_pbx_exec(lua_State *L)
187 {
188  int res, nargs = lua_gettop(L);
189  const char *data = "";
190  char *app_name, *context, *exten;
191  char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
192  int priority, autoservice;
193  struct ast_app *app;
194  struct ast_channel *chan;
195 
196  lua_getfield(L, 1, "name");
197  app_name = ast_strdupa(lua_tostring(L, -1));
198  lua_pop(L, 1);
199 
200  if (!(app = pbx_findapp(app_name))) {
201  lua_pushstring(L, "application '");
202  lua_pushstring(L, app_name);
203  lua_pushstring(L, "' not found");
204  lua_concat(L, 3);
205  return lua_error(L);
206  }
207 
208 
209  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
210  chan = lua_touserdata(L, -1);
211  lua_pop(L, 1);
212 
213  context = ast_strdupa(ast_channel_context(chan));
214  exten = ast_strdupa(ast_channel_exten(chan));
215  priority = ast_channel_priority(chan);
216 
217  lua_concat_args(L, 2, nargs);
218  data = lua_tostring(L, -1);
219 
220  ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
221  exten, context, priority,
222  term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
223  term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
224  term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));
225 
226  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
227  autoservice = lua_toboolean(L, -1);
228  lua_pop(L, 1);
229 
230  if (autoservice)
231  ast_autoservice_stop(chan);
232 
233  res = pbx_exec(chan, app, data);
234 
235  lua_pop(L, 1); /* pop data */
236  data = "";
237 
238  if (autoservice)
239  ast_autoservice_start(chan);
240 
241  /* error executing an application, report it */
242  if (res) {
243  lua_pushinteger(L, res);
244  return lua_error(L);
245  }
246 
247  if (strcmp(context, ast_channel_context(chan))) {
248  lua_pushstring(L, context);
249  lua_pushstring(L, ast_channel_context(chan));
250  lua_pushliteral(L, "context");
251  } else if (strcmp(exten, ast_channel_exten(chan))) {
252  lua_pushstring(L, exten);
253  lua_pushstring(L, ast_channel_exten(chan));
254  lua_pushliteral(L, "exten");
255  } else if (priority != ast_channel_priority(chan)) {
256  lua_pushinteger(L, priority);
257  lua_pushinteger(L, ast_channel_priority(chan));
258  lua_pushliteral(L, "priority");
259  } else {
260  /* no goto - restore the original position back
261  * to lua state, in case this was a recursive dialplan
262  * call (a dialplan application re-entering dialplan) */
263  lua_update_registry(L, context, exten, priority);
264  return 0;
265  }
266 
267  /* goto detected - construct error message */
268  lua_insert(L, -3);
269 
270  lua_pushliteral(L, " changed from ");
271  lua_insert(L, -3);
272 
273  lua_pushliteral(L, " to ");
274  lua_insert(L, -2);
275 
276  lua_concat(L, 5);
277 
278  ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1));
279  lua_pop(L, 1);
280 
281  /* let the lua engine know it needs to return control to the pbx */
282  lua_pushinteger(L, LUA_GOTO_DETECTED);
283  lua_error(L);
284 
285  return 0;
286 }
287 
288 /*!
289  * \brief [lua_CFunction] Used to get the value of a variable or dialplan
290  * function (for access from lua, don't call directly)
291  *
292  * The value of the variable or function is returned. This function is the
293  * 'get()' function in the following example as would be seen in
294  * extensions.lua.
295  *
296  * \code
297  * channel.variable:get()
298  * \endcode
299  */
300 static int lua_get_variable_value(lua_State *L)
301 {
302  struct ast_channel *chan;
303  char *value = NULL, *name;
304  char *workspace = ast_alloca(LUA_BUF_SIZE);
305  int autoservice;
306 
307  workspace[0] = '\0';
308 
309  if (!lua_istable(L, 1)) {
310  lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value");
311  return lua_error(L);
312  }
313 
314  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
315  chan = lua_touserdata(L, -1);
316  lua_pop(L, 1);
317 
318  lua_getfield(L, 1, "name");
319  name = ast_strdupa(lua_tostring(L, -1));
320  lua_pop(L, 1);
321 
322  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
323  autoservice = lua_toboolean(L, -1);
324  lua_pop(L, 1);
325 
326  if (autoservice)
327  ast_autoservice_stop(chan);
328 
329  /* if this is a dialplan function then use ast_func_read(), otherwise
330  * use pbx_retrieve_variable() */
331  if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') {
332  value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace;
333  } else {
334  pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan));
335  }
336 
337  if (autoservice)
338  ast_autoservice_start(chan);
339 
340  if (value) {
341  lua_pushstring(L, value);
342  } else {
343  lua_pushnil(L);
344  }
345 
346  return 1;
347 }
348 
349 /*!
350  * \brief [lua_CFunction] Used to set the value of a variable or dialplan
351  * function (for access from lua, don't call directly)
352  *
353  * This function is the 'set()' function in the following example as would be
354  * seen in extensions.lua.
355  *
356  * \code
357  * channel.variable:set("value")
358  * \endcode
359  */
360 static int lua_set_variable_value(lua_State *L)
361 {
362  const char *name, *value;
363  struct ast_channel *chan;
364  int autoservice;
365 
366  if (!lua_istable(L, 1)) {
367  lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable");
368  return lua_error(L);
369  }
370 
371  lua_getfield(L, 1, "name");
372  name = ast_strdupa(lua_tostring(L, -1));
373  lua_pop(L, 1);
374 
375  value = luaL_checkstring(L, 2);
376 
377  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
378  chan = lua_touserdata(L, -1);
379  lua_pop(L, 1);
380 
381  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
382  autoservice = lua_toboolean(L, -1);
383  lua_pop(L, 1);
384 
385  if (autoservice)
386  ast_autoservice_stop(chan);
387 
388  pbx_builtin_setvar_helper(chan, name, value);
389 
390  if (autoservice)
391  ast_autoservice_start(chan);
392 
393  return 0;
394 }
395 
396 /*!
397  * \brief Update the lua registry with the given context, exten, and priority.
398  *
399  * \param L the lua_State to use
400  * \param context the new context
401  * \param exten the new exten
402  * \param priority the new priority
403  */
404 static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority)
405 {
406  lua_pushstring(L, context);
407  lua_setfield(L, LUA_REGISTRYINDEX, "context");
408 
409  lua_pushstring(L, exten);
410  lua_setfield(L, LUA_REGISTRYINDEX, "exten");
411 
412  lua_pushinteger(L, priority);
413  lua_setfield(L, LUA_REGISTRYINDEX, "priority");
414 }
415 
416 /*!
417  * \brief Push a 'variable' table on the stack for access the channel variable
418  * with the given name.
419  *
420  * The value on the top of the stack is popped and used as the name.
421  *
422  * \param L the lua_State to use
423  */
424 static void lua_push_variable_table(lua_State *L)
425 {
426  lua_newtable(L);
427  luaL_getmetatable(L, "variable");
428  lua_setmetatable(L, -2);
429 
430  lua_insert(L, -2); /* move the table after the name */
431  lua_setfield(L, -2, "name");
432 
433  lua_pushcfunction(L, &lua_get_variable_value);
434  lua_setfield(L, -2, "get");
435 
436  lua_pushcfunction(L, &lua_set_variable_value);
437  lua_setfield(L, -2, "set");
438 }
439 
440 /*!
441  * \brief Create the global 'app' table for executing applications
442  *
443  * \param L the lua_State to use
444  */
445 static void lua_create_app_table(lua_State *L)
446 {
447  lua_newtable(L);
448  luaL_newmetatable(L, "app");
449 
450  lua_pushstring(L, "__index");
451  lua_pushcfunction(L, &lua_pbx_findapp);
452  lua_settable(L, -3);
453 
454  lua_setmetatable(L, -2);
455  lua_setglobal(L, "app");
456 }
457 
458 /*!
459  * \brief Create the global 'channel' table for accesing channel variables
460  *
461  * \param L the lua_State to use
462  */
463 static void lua_create_channel_table(lua_State *L)
464 {
465  lua_newtable(L);
466  luaL_newmetatable(L, "channel_data");
467 
468  lua_pushstring(L, "__index");
469  lua_pushcfunction(L, &lua_get_variable);
470  lua_settable(L, -3);
471 
472  lua_pushstring(L, "__newindex");
473  lua_pushcfunction(L, &lua_set_variable);
474  lua_settable(L, -3);
475 
476  lua_setmetatable(L, -2);
477  lua_setglobal(L, "channel");
478 }
479 
480 /*!
481  * \brief Create the 'variable' metatable, used to retrieve channel variables
482  *
483  * \param L the lua_State to use
484  */
485 static void lua_create_variable_metatable(lua_State *L)
486 {
487  luaL_newmetatable(L, "variable");
488 
489  lua_pushstring(L, "__call");
490  lua_pushcfunction(L, &lua_func_read);
491  lua_settable(L, -3);
492 
493  lua_pop(L, 1);
494 }
495 
496 /*!
497  * \brief Create the 'application' metatable, used to execute asterisk
498  * applications from lua
499  *
500  * \param L the lua_State to use
501  */
502 static void lua_create_application_metatable(lua_State *L)
503 {
504  luaL_newmetatable(L, "application");
505 
506  lua_pushstring(L, "__call");
507  lua_pushcfunction(L, &lua_pbx_exec);
508  lua_settable(L, -3);
509 
510  lua_pop(L, 1);
511 }
512 
513 /*!
514  * \brief Create the autoservice functions
515  *
516  * \param L the lua_State to use
517  */
518 static void lua_create_autoservice_functions(lua_State *L)
519 {
520  lua_pushcfunction(L, &lua_autoservice_start);
521  lua_setglobal(L, "autoservice_start");
522 
523  lua_pushcfunction(L, &lua_autoservice_stop);
524  lua_setglobal(L, "autoservice_stop");
525 
526  lua_pushcfunction(L, &lua_autoservice_status);
527  lua_setglobal(L, "autoservice_status");
528 
529  lua_pushboolean(L, 1);
530  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
531 }
532 
533 /*!
534  * \brief Create the hangup check function
535  *
536  * \param L the lua_State to use
537  */
538 static void lua_create_hangup_function(lua_State *L)
539 {
540  lua_pushcfunction(L, &lua_check_hangup);
541  lua_setglobal(L, "check_hangup");
542 }
543 
544 /*!
545  * \brief [lua_CFunction] Return a lua 'variable' object (for access from lua, don't call
546  * directly)
547  *
548  * This function is called to lookup a variable construct a 'variable' object.
549  * It would be called in the following example as would be seen in
550  * extensions.lua.
551  *
552  * \code
553  * channel.variable
554  * \endcode
555  */
556 static int lua_get_variable(lua_State *L)
557 {
558  struct ast_channel *chan;
559  const char *name = luaL_checkstring(L, 2);
560  char *value = NULL;
561  char *workspace = ast_alloca(LUA_BUF_SIZE);
562  workspace[0] = '\0';
563 
564  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
565  chan = lua_touserdata(L, -1);
566  lua_pop(L, 1);
567 
568  lua_pushvalue(L, 2);
570 
571  /* if this is not a request for a dialplan funciton attempt to retrieve
572  * the value of the variable */
573  if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') {
574  pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan));
575  }
576 
577  if (value) {
578  lua_pushstring(L, value);
579  lua_setfield(L, -2, "value");
580  }
581 
582  return 1;
583 }
584 
585 /*!
586  * \brief [lua_CFunction] Set the value of a channel variable or dialplan
587  * function (for access from lua, don't call directly)
588  *
589  * This function is called to set a variable or dialplan function. It would be
590  * called in the following example as would be seen in extensions.lua.
591  *
592  * \code
593  * channel.variable = "value"
594  * \endcode
595  */
596 static int lua_set_variable(lua_State *L)
597 {
598  struct ast_channel *chan;
599  int autoservice;
600  const char *name = luaL_checkstring(L, 2);
601  const char *value = luaL_checkstring(L, 3);
602 
603  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
604  chan = lua_touserdata(L, -1);
605  lua_pop(L, 1);
606 
607  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
608  autoservice = lua_toboolean(L, -1);
609  lua_pop(L, 1);
610 
611  if (autoservice)
612  ast_autoservice_stop(chan);
613 
614  pbx_builtin_setvar_helper(chan, name, value);
615 
616  if (autoservice)
617  ast_autoservice_start(chan);
618 
619  return 0;
620 }
621 
622 /*!
623  * \brief Concatenate a list of lua function arguments into a comma separated
624  * string.
625  * \param L the lua_State to use
626  * \param start the index of the first argument
627  * \param nargs the number of args
628  *
629  * The resulting string will be left on the top of the stack.
630  */
631 static void lua_concat_args(lua_State *L, int start, int nargs) {
632  int concat = 0;
633  int i = start + 1;
634 
635  if (start <= nargs && !lua_isnil(L, start)) {
636  lua_pushvalue(L, start);
637  concat += 1;
638  }
639 
640  for (; i <= nargs; i++) {
641  if (lua_isnil(L, i)) {
642  lua_pushliteral(L, ",");
643  concat += 1;
644  } else {
645  lua_pushliteral(L, ",");
646  lua_pushvalue(L, i);
647  concat += 2;
648  }
649  }
650 
651  lua_concat(L, concat);
652 }
653 
654 /*!
655  * \brief [lua_CFunction] Create a 'variable' object for accessing a dialplan
656  * function (for access from lua, don't call directly)
657  *
658  * This function is called to create a 'variable' object to access a dialplan
659  * function. It would be called in the following example as would be seen in
660  * extensions.lua.
661  *
662  * \code
663  * channel.func("arg1", "arg2", "arg3")
664  * \endcode
665  *
666  * To actually do anything with the resulting value you must use the 'get()'
667  * and 'set()' methods (the reason is the resulting value is not a value, but
668  * an object in the form of a lua table).
669  */
670 static int lua_func_read(lua_State *L)
671 {
672  int nargs = lua_gettop(L);
673 
674  /* build a string in the form of "func_name(arg1,arg2,arg3)" */
675  lua_getfield(L, 1, "name");
676  lua_pushliteral(L, "(");
677  lua_concat_args(L, 2, nargs);
678  lua_pushliteral(L, ")");
679  lua_concat(L, 4);
680 
682  return 1;
683 }
684 
685 /*!
686  * \brief [lua_CFunction] Tell pbx_lua to maintain an autoservice on this
687  * channel (for access from lua, don't call directly)
688  *
689  * \param L the lua_State to use
690  *
691  * This function will set a flag that will cause pbx_lua to maintain an
692  * autoservice on this channel. The autoservice will automatically be stopped
693  * and restarted before calling applications and functions.
694  */
695 static int lua_autoservice_start(lua_State *L)
696 {
697  struct ast_channel *chan;
698 
699  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
700  if (lua_toboolean(L, -1)) {
701  /* autservice already running */
702  lua_pop(L, 1);
703  return 0;
704  }
705  lua_pop(L, 1);
706 
707  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
708  chan = lua_touserdata(L, -1);
709  lua_pop(L, 1);
710 
711  ast_autoservice_start(chan);
712 
713  lua_pushboolean(L, 1);
714  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
715  return 0;
716 }
717 
718 /*!
719  * \brief [lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on
720  * this channel (for access from lua, don't call directly)
721  *
722  * \param L the lua_State to use
723  *
724  * This function will stop any autoservice running and turn off the autoservice
725  * flag. If this function returns false, it's probably because no autoservice
726  * was running to begin with.
727  */
728 static int lua_autoservice_stop(lua_State *L)
729 {
730  struct ast_channel *chan;
731 
732  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
733  if (!lua_toboolean(L, -1)) {
734  /* no autservice running */
735  lua_pop(L, 1);
736  return 0;
737  }
738  lua_pop(L, 1);
739 
740  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
741  chan = lua_touserdata(L, -1);
742  lua_pop(L, 1);
743 
744  ast_autoservice_stop(chan);
745 
746  lua_pushboolean(L, 0);
747  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
748  return 0;
749 }
750 
751 /*!
752  * \brief [lua_CFunction] Get the status of the autoservice flag (for access
753  * from lua, don't call directly)
754  *
755  * \param L the lua_State to use
756  *
757  * \return This function returns the status of the autoservice flag as a
758  * boolean to its lua caller.
759  */
760 static int lua_autoservice_status(lua_State *L)
761 {
762  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
763  return 1;
764 }
765 
766 /*!
767  * \brief [lua_CFunction] Check if this channel has been hungup or not (for
768  * access from lua, don't call directly)
769  *
770  * \param L the lua_State to use
771  *
772  * \return This function returns true if the channel was hungup
773  */
774 static int lua_check_hangup(lua_State *L)
775 {
776  struct ast_channel *chan;
777  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
778  chan = lua_touserdata(L, -1);
779  lua_pop(L, 1);
780 
781  lua_pushboolean(L, ast_check_hangup(chan));
782  return 1;
783 }
784 
785 /*!
786  * \brief [lua_CFunction] Handle lua errors (for access from lua, don't call
787  * directly)
788  *
789  * \param L the lua_State to use
790  */
791 static int lua_error_function(lua_State *L)
792 {
793  int message_index;
794 
795  /* pass number arguments right through back to asterisk*/
796  if (lua_isnumber(L, -1)) {
797  return 1;
798  }
799 
800  /* if we are here then we have a string error message, let's attach a
801  * backtrace to it */
802  message_index = lua_gettop(L);
803 
804  /* prepare to prepend a new line to the traceback */
805  lua_pushliteral(L, "\n");
806 
807  lua_getglobal(L, "debug");
808  if (!lua_istable(L, -1)) {
809  /* Have no 'debug' table for whatever reason */
810  lua_pop(L, 2);
811  /* Original err message is on stack top now */
812  return 1;
813  }
814  lua_getfield(L, -1, "traceback");
815  if (!lua_isfunction(L, -1)) {
816  /* Same here for traceback function */
817  lua_pop(L, 3);
818  /* Original err message is on stack top now */
819  return 1;
820  }
821  lua_remove(L, -2); /* remove the 'debug' table */
822 
823  lua_pushvalue(L, message_index);
824  lua_remove(L, message_index);
825 
826  lua_pushnumber(L, 2);
827 
828  lua_call(L, 2, 1);
829 
830  /* prepend the new line we prepared above */
831  lua_concat(L, 2);
832 
833  return 1;
834 }
835 
836 /*!
837  * \brief Store the sort order of each context
838 
839  * In the event of an error, an error string will be pushed onto the lua stack.
840  *
841  * \retval 0 success
842  * \retval 1 failure
843  */
844 static int lua_sort_extensions(lua_State *L)
845 {
846  int extensions, extensions_order;
847 
848  /* create the extensions_order table */
849  lua_newtable(L);
850  lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order");
851  lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
852  extensions_order = lua_gettop(L);
853 
854  /* sort each context in the extensions table */
855  /* load the 'extensions' table */
856  lua_getglobal(L, "extensions");
857  extensions = lua_gettop(L);
858  if (lua_isnil(L, -1)) {
859  lua_pop(L, 1);
860  lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
861  return 1;
862  }
863 
864  /* iterate through the extensions table and create a
865  * matching table (holding the sort order) in the
866  * extensions_order table for each context that is found
867  */
868  for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
869  int context = lua_gettop(L);
870  int context_name = context - 1;
871  int context_order;
872 
873  /* copy the context_name to be used as the key for the
874  * context_order table in the extensions_order table later */
875  lua_pushvalue(L, context_name);
876 
877  /* create the context_order table */
878  lua_newtable(L);
879  context_order = lua_gettop(L);
880 
881  /* iterate through this context an popluate the corrisponding
882  * table in the extensions_order table */
883  for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
884  int exten = lua_gettop(L) - 1;
885 #if LUA_VERSION_NUM < 502
886  lua_pushinteger(L, lua_objlen(L, context_order) + 1);
887 #else
888  lua_pushinteger(L, lua_rawlen(L, context_order) + 1);
889 #endif
890  lua_pushvalue(L, exten);
891  lua_settable(L, context_order);
892  }
893  lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */
894 
895  /* now sort the new table */
896 
897  /* push the table.sort function */
898  lua_getglobal(L, "table");
899  lua_getfield(L, -1, "sort");
900  lua_remove(L, -2); /* remove the 'table' table */
901 
902  /* push the context_order table */
903  lua_pushvalue(L, context_name);
904  lua_gettable(L, extensions_order);
905 
906  /* push the comp function */
907  lua_pushcfunction(L, &lua_extension_cmp);
908 
909  if (lua_pcall(L, 2, 0, 0)) {
910  lua_insert(L, -5);
911  lua_pop(L, 4);
912  return 1;
913  }
914  }
915 
916  /* remove the extensions table and the extensions_order table */
917  lua_pop(L, 2);
918  return 0;
919 }
920 
921 /*!
922  * \brief Register dialplan switches for our pbx_lua contexs.
923  *
924  * In the event of an error, an error string will be pushed onto the lua stack.
925  *
926  * \retval 0 success
927  * \retval 1 failure
928  */
929 static int lua_register_switches(lua_State *L)
930 {
931  int extensions;
932  struct ast_context *con = NULL;
933 
934  /* create the hash table for our contexts */
935  /* XXX do we ever need to destroy this? pbx_config does not */
936  if (!local_table)
938 
939  /* load the 'extensions' table */
940  lua_getglobal(L, "extensions");
941  extensions = lua_gettop(L);
942  if (lua_isnil(L, -1)) {
943  lua_pop(L, 1);
944  lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
945  return 1;
946  }
947 
948  /* iterate through the extensions table and register a context and
949  * dialplan switch for each lua context
950  */
951  for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
952  int context = lua_gettop(L);
953  int context_name = context - 1;
954  const char *context_str = lua_tostring(L, context_name);
955 
956  /* find or create this context */
957  con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
958  if (!con) {
959  /* remove extensions table and context key and value */
960  lua_pop(L, 3);
961  lua_pushstring(L, "Failed to find or create context\n");
962  return 1;
963  }
964 
965  /* register the switch */
966  if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
967  /* remove extensions table and context key and value */
968  lua_pop(L, 3);
969  lua_pushstring(L, "Unable to create switch for context\n");
970  return 1;
971  }
972  }
973 
974  /* remove the extensions table */
975  lua_pop(L, 1);
976  return 0;
977 }
978 
979 /*!
980  * \brief Register dialplan hints for our pbx_lua contexs.
981  *
982  * In the event of an error, an error string will be pushed onto the lua stack.
983  *
984  * \retval 0 success
985  * \retval 1 failure
986  */
987 static int lua_register_hints(lua_State *L)
988 {
989  int hints;
990  struct ast_context *con = NULL;
991 
992  /* create the hash table for our contexts */
993  /* XXX do we ever need to destroy this? pbx_config does not */
994  if (!local_table)
996 
997  /* load the 'hints' table */
998  lua_getglobal(L, "hints");
999  hints = lua_gettop(L);
1000  if (lua_isnil(L, -1)) {
1001  /* hints table not found, move along */
1002  lua_pop(L, 1);
1003  return 0;
1004  }
1005 
1006  /* iterate through the hints table and register each context and
1007  * the hints that go along with it
1008  */
1009  for (lua_pushnil(L); lua_next(L, hints); lua_pop(L, 1)) {
1010  int context = lua_gettop(L);
1011  int context_name = context - 1;
1012  const char *context_str = lua_tostring(L, context_name);
1013 
1014  /* find or create this context */
1015  con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
1016  if (!con) {
1017  /* remove hints table and context key and value */
1018  lua_pop(L, 3);
1019  lua_pushstring(L, "Failed to find or create context\n");
1020  return 1;
1021  }
1022 
1023  /* register each hint */
1024  for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
1025  const char *hint_value = lua_tostring(L, -1);
1026  const char *hint_name;
1027 
1028  /* the hint value is not a string, ignore it */
1029  if (!hint_value) {
1030  continue;
1031  }
1032 
1033  /* copy the name then convert it to a string */
1034  lua_pushvalue(L, -2);
1035  if (!(hint_name = lua_tostring(L, -1))) {
1036  /* ignore non-string value */
1037  lua_pop(L, 1);
1038  continue;
1039  }
1040 
1041  if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar, NULL, 0)) {
1042  /* remove hints table, hint name, hint value,
1043  * key copy, context name, and contex table */
1044  lua_pop(L, 6);
1045  lua_pushstring(L, "Error creating hint\n");
1046  return 1;
1047  }
1048 
1049  /* pop the name copy */
1050  lua_pop(L, 1);
1051  }
1052  }
1053 
1054  /* remove the hints table */
1055  lua_pop(L, 1);
1056 
1057  return 0;
1058 }
1059 
1060 /*!
1061  * \brief [lua_CFunction] Compare two extensions (for access from lua, don't
1062  * call directly)
1063  *
1064  * This function returns true if the first extension passed should match after
1065  * the second. It behaves like the '<' operator.
1066  */
1067 static int lua_extension_cmp(lua_State *L)
1068 {
1069  const char *a = luaL_checkstring(L, -2);
1070  const char *b = luaL_checkstring(L, -1);
1071 
1072  if (ast_extension_cmp(a, b) == -1)
1073  lua_pushboolean(L, 1);
1074  else
1075  lua_pushboolean(L, 0);
1076 
1077  return 1;
1078 }
1079 
1080 /*!
1081  * \brief Load the extensions.lua file in to a buffer and execute the file
1082  *
1083  * \param L the lua_State to use
1084  * \param size a pointer to store the size of the buffer
1085  * \param file_not_openable a pointer to store if config file could be opened
1086  *
1087  * \note The caller is expected to free the buffer at some point.
1088  *
1089  * \return a pointer to the buffer
1090  */
1091 static char *lua_read_extensions_file(lua_State *L, long *size, int *file_not_openable)
1092 {
1093  FILE *f;
1094  int error_func;
1095  char *data;
1096  char *path = ast_alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
1097  sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
1098 
1099  if (!(f = fopen(path, "r"))) {
1100  lua_pushstring(L, "cannot open '");
1101  lua_pushstring(L, path);
1102  lua_pushstring(L, "' for reading: ");
1103  lua_pushstring(L, strerror(errno));
1104  lua_concat(L, 4);
1105 
1106  *file_not_openable = 1;
1107 
1108  return NULL;
1109  }
1110 
1111  if (fseek(f, 0l, SEEK_END)) {
1112  fclose(f);
1113  lua_pushliteral(L, "error determining the size of the config file");
1114  return NULL;
1115  }
1116 
1117  *size = ftell(f);
1118 
1119  if (fseek(f, 0l, SEEK_SET)) {
1120  *size = 0;
1121  fclose(f);
1122  lua_pushliteral(L, "error reading config file");
1123  return NULL;
1124  }
1125 
1126  if (!(data = ast_malloc(*size))) {
1127  *size = 0;
1128  fclose(f);
1129  lua_pushstring(L, "not enough memory");
1130  return NULL;
1131  }
1132 
1133  if (fread(data, sizeof(char), *size, f) != *size) {
1134  *size = 0;
1135  fclose(f);
1136  lua_pushliteral(L, "problem reading configuration file");
1137  return NULL;
1138  }
1139  fclose(f);
1140 
1141  lua_pushcfunction(L, &lua_error_function);
1142  error_func = lua_gettop(L);
1143 
1144  if (luaL_loadbuffer(L, data, *size, "extensions.lua")
1145  || lua_pcall(L, 0, LUA_MULTRET, error_func)
1146  || lua_sort_extensions(L)
1147  || lua_register_switches(L)
1148  || lua_register_hints(L)) {
1149  ast_free(data);
1150  data = NULL;
1151  *size = 0;
1152  }
1153 
1154  lua_remove(L, error_func);
1155  return data;
1156 }
1157 
1158 /*!
1159  * \brief Load the extensions.lua file from the internal buffer
1160  *
1161  * \param L the lua_State to use
1162  * \param chan channel to work on
1163  *
1164  * This function also sets up some constructs used by the extensions.lua file.
1165  * In the event of an error, an error string will be pushed onto the lua stack.
1166  *
1167  * \retval 0 success
1168  * \retval 1 failure
1169  */
1170 static int lua_load_extensions(lua_State *L, struct ast_channel *chan)
1171 {
1172 
1173  /* store a pointer to this channel */
1174  lua_pushlightuserdata(L, chan);
1175  lua_setfield(L, LUA_REGISTRYINDEX, "channel");
1176 
1177  luaL_openlibs(L);
1178 
1179  /* load and sort extensions */
1181  if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
1182  || lua_pcall(L, 0, LUA_MULTRET, 0)
1183  || lua_sort_extensions(L)) {
1185  return 1;
1186  }
1188 
1189  /* now we setup special tables and functions */
1190 
1193 
1196 
1199 
1200  return 0;
1201 }
1202 
1203 /*!
1204  * \brief Reload the extensions file and update the internal buffers if it
1205  * loads correctly.
1206  *
1207  * \warning This function should not be called on a lua_State returned from
1208  * lua_get_state().
1209  *
1210  * \param L the lua_State to use (must be freshly allocated with
1211  * luaL_newstate(), don't use lua_get_state())
1212  */
1213 static int lua_reload_extensions(lua_State *L)
1214 {
1215  long size = 0;
1216  char *data = NULL;
1217  int file_not_openable = 0;
1218 
1219  luaL_openlibs(L);
1220 
1221  if (!(data = lua_read_extensions_file(L, &size, &file_not_openable))) {
1222  if (file_not_openable) {
1223  return -1;
1224  }
1225  return 1;
1226  }
1227 
1229 
1230  if (config_file_data)
1232 
1233  config_file_data = data;
1234  config_file_size = size;
1235 
1236  /* merge our new contexts */
1237  ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
1238  /* merge_contexts_and_delete will actually, at the correct moment,
1239  set the global dialplan pointers to your local_contexts and local_table.
1240  It then will free up the old tables itself. Just be sure not to
1241  hang onto the pointers. */
1242  local_table = NULL;
1243  local_contexts = NULL;
1244 
1246  return 0;
1247 }
1248 
1249 /*!
1250  * \brief Free the internal extensions buffer.
1251  */
1252 static void lua_free_extensions()
1253 {
1255  config_file_size = 0;
1258 }
1259 
1260 /*!
1261  * \brief Get the lua_State for this channel
1262  *
1263  * If no channel is passed then a new state is allocated. States with no
1264  * channel assocatied with them should only be used for matching extensions.
1265  * If the channel does not yet have a lua state associated with it, one will be
1266  * created.
1267  *
1268  * \note If no channel was passed then the caller is expected to free the state
1269  * using lua_close().
1270  *
1271  * \return a lua_State
1272  */
1273 static lua_State *lua_get_state(struct ast_channel *chan)
1274 {
1275  struct ast_datastore *datastore = NULL;
1276  lua_State *L;
1277 
1278  if (!chan) {
1279  L = luaL_newstate();
1280  if (!L) {
1281  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1282  return NULL;
1283  }
1284 
1285  if (lua_load_extensions(L, NULL)) {
1286  const char *error = lua_tostring(L, -1);
1287  ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
1288  lua_close(L);
1289  return NULL;
1290  }
1291  return L;
1292  } else {
1293  ast_channel_lock(chan);
1294  datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
1295  ast_channel_unlock(chan);
1296 
1297  if (!datastore) {
1298  /* nothing found, allocate a new lua state */
1299  datastore = ast_datastore_alloc(&lua_datastore, NULL);
1300  if (!datastore) {
1301  ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
1302  return NULL;
1303  }
1304 
1305  datastore->data = luaL_newstate();
1306  if (!datastore->data) {
1307  ast_datastore_free(datastore);
1308  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1309  return NULL;
1310  }
1311 
1312  ast_channel_lock(chan);
1313  ast_channel_datastore_add(chan, datastore);
1314  ast_channel_unlock(chan);
1315 
1316  L = datastore->data;
1317 
1318  if (lua_load_extensions(L, chan)) {
1319  const char *error = lua_tostring(L, -1);
1320  ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", ast_channel_name(chan), error);
1321 
1322  ast_channel_lock(chan);
1323  ast_channel_datastore_remove(chan, datastore);
1324  ast_channel_unlock(chan);
1325 
1326  ast_datastore_free(datastore);
1327  return NULL;
1328  }
1329  }
1330 
1331  return datastore->data;
1332  }
1333 }
1334 
1335 static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
1336 {
1337  int res;
1338  lua_State *L;
1339  struct ast_module_user *u = ast_module_user_add(chan);
1340  if (!u) {
1341  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1342  return 0;
1343  }
1344 
1345  L = lua_get_state(chan);
1346  if (!L) {
1348  return 0;
1349  }
1350 
1351  res = lua_find_extension(L, context, exten, priority, &exists, 0);
1352 
1353  if (!chan) lua_close(L);
1355  return res;
1356 }
1357 
1358 static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
1359 {
1360  int res;
1361  lua_State *L;
1362  struct ast_module_user *u = ast_module_user_add(chan);
1363  if (!u) {
1364  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1365  return 0;
1366  }
1367 
1368  L = lua_get_state(chan);
1369  if (!L) {
1371  return 0;
1372  }
1373 
1374  res = lua_find_extension(L, context, exten, priority, &canmatch, 0);
1375 
1376  if (!chan) lua_close(L);
1378  return res;
1379 }
1380 
1381 static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
1382 {
1383  int res;
1384  lua_State *L;
1385  struct ast_module_user *u = ast_module_user_add(chan);
1386  if (!u) {
1387  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1388  return 0;
1389  }
1390 
1391  L = lua_get_state(chan);
1392  if (!L) {
1394  return 0;
1395  }
1396 
1397  res = lua_find_extension(L, context, exten, priority, &matchmore, 0);
1398 
1399  if (!chan) lua_close(L);
1401  return res;
1402 }
1403 
1404 
1405 static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
1406 {
1407  int res, error_func;
1408  lua_State *L;
1409  struct ast_module_user *u = ast_module_user_add(chan);
1410  if (!u) {
1411  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1412  return -1;
1413  }
1414 
1415  L = lua_get_state(chan);
1416  if (!L) {
1418  return -1;
1419  }
1420 
1421  lua_pushcfunction(L, &lua_error_function);
1422  error_func = lua_gettop(L);
1423 
1424  /* push the extension function onto the stack */
1425  if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
1426  lua_pop(L, 1); /* pop the debug function */
1427  ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
1428  if (!chan) lua_close(L);
1430  return -1;
1431  }
1432 
1433  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
1434  if (lua_toboolean(L, -1)) {
1435  ast_autoservice_start(chan);
1436  }
1437  lua_pop(L, 1);
1438 
1439  lua_update_registry(L, context, exten, priority);
1440 
1441  lua_pushstring(L, context);
1442  lua_pushstring(L, exten);
1443 
1444  res = lua_pcall(L, 2, 0, error_func);
1445  if (res) {
1446  if (res == LUA_ERRRUN) {
1447  res = -1;
1448  if (lua_isnumber(L, -1)) {
1449  res = lua_tointeger(L, -1);
1450 
1451  if (res == LUA_GOTO_DETECTED) {
1452  res = 0;
1453  }
1454  } else if (lua_isstring(L, -1)) {
1455  const char *error = lua_tostring(L, -1);
1456  ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
1457  }
1458  } else if (res == LUA_ERRERR) {
1459  res = -1;
1460  ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
1461  } else if (res == LUA_ERRMEM) {
1462  res = -1;
1463  ast_log(LOG_ERROR, "Memory allocation error\n");
1464  }
1465  lua_pop(L, 1);
1466  }
1467  lua_remove(L, error_func);
1468 
1469  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
1470  if (lua_toboolean(L, -1)) {
1471  ast_autoservice_stop(chan);
1472  }
1473  lua_pop(L, 1);
1474 
1475  if (!chan) lua_close(L);
1477  return res;
1478 }
1479 
1480 /*!
1481  * \brief Locate an extensions and optionally push the matching function on the
1482  * stack
1483  *
1484  * \param L the lua_State to use
1485  * \param context the context to look in
1486  * \param exten the extension to look up
1487  * \param priority the priority to check, '1' is the only valid priority
1488  * \param func the calling func, used to adjust matching behavior between,
1489  * match, canmatch, and matchmore
1490  * \param push_func whether or not to push the lua function for the given
1491  * extension onto the stack
1492  */
1493 static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
1494 {
1495  int context_table, context_order_table, i;
1496 
1497  ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
1498  if (priority != 1)
1499  return 0;
1500 
1501  /* load the 'extensions' table */
1502  lua_getglobal(L, "extensions");
1503  if (lua_isnil(L, -1)) {
1504  ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
1505  lua_pop(L, 1);
1506  return 0;
1507  }
1508 
1509  /* load the given context */
1510  lua_getfield(L, -1, context);
1511  if (lua_isnil(L, -1)) {
1512  lua_pop(L, 2);
1513  return 0;
1514  }
1515 
1516  /* remove the extensions table */
1517  lua_remove(L, -2);
1518 
1519  context_table = lua_gettop(L);
1520 
1521  /* load the extensions order table for this context */
1522  lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
1523  lua_getfield(L, -1, context);
1524 
1525  lua_remove(L, -2); /* remove the extensions order table */
1526 
1527  context_order_table = lua_gettop(L);
1528 
1529  /* step through the extensions looking for a match */
1530 #if LUA_VERSION_NUM < 502
1531  for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
1532 #else
1533  for (i = 1; i < lua_rawlen(L, context_order_table) + 1; i++) {
1534 #endif
1535  int e_index_copy, match = 0;
1536  const char *e;
1537 
1538  lua_pushinteger(L, i);
1539  lua_gettable(L, context_order_table);
1540  lua_gettop(L);
1541 
1542  /* copy the key at the top of the stack for use later */
1543  lua_pushvalue(L, -1);
1544  e_index_copy = lua_gettop(L);
1545 
1546  if (!(e = lua_tostring(L, e_index_copy))) {
1547  lua_pop(L, 2);
1548  continue;
1549  }
1550 
1551  /* make sure this is not the 'include' extension */
1552  if (!strcasecmp(e, "include")) {
1553  lua_pop(L, 2);
1554  continue;
1555  }
1556 
1557  if (func == &matchmore)
1558  match = ast_extension_close(e, exten, E_MATCHMORE);
1559  else if (func == &canmatch)
1560  match = ast_extension_close(e, exten, E_CANMATCH);
1561  else
1562  match = ast_extension_match(e, exten);
1563 
1564  /* the extension matching functions return 0 on fail, 1 on
1565  * match, 2 on earlymatch */
1566 
1567  if (!match) {
1568  /* pop the copy and the extension */
1569  lua_pop(L, 2);
1570  continue; /* keep trying */
1571  }
1572 
1573  if (func == &matchmore && match == 2) {
1574  /* We match an extension ending in '!'. The decision in
1575  * this case is final and counts as no match. */
1576  lua_pop(L, 4);
1577  return 0;
1578  }
1579 
1580  /* remove the context table, the context order table, the
1581  * extension, and the extension copy (or replace the extension
1582  * with the corresponding function) */
1583  if (push_func) {
1584  lua_pop(L, 1); /* pop the copy */
1585  lua_gettable(L, context_table);
1586  lua_insert(L, -3);
1587  lua_pop(L, 2);
1588  } else {
1589  lua_pop(L, 4);
1590  }
1591 
1592  return 1;
1593  }
1594 
1595  /* load the includes for this context */
1596  lua_getfield(L, context_table, "include");
1597  if (lua_isnil(L, -1)) {
1598  lua_pop(L, 3);
1599  return 0;
1600  }
1601 
1602  /* remove the context and the order table*/
1603  lua_remove(L, context_order_table);
1604  lua_remove(L, context_table);
1605 
1606  /* Now try any includes we have in this context */
1607  for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
1608  const char *c = lua_tostring(L, -1);
1609  if (!c)
1610  continue;
1611 
1612  if (lua_find_extension(L, c, exten, priority, func, push_func)) {
1613  /* remove the value, the key, and the includes table
1614  * from the stack. Leave the function behind if
1615  * necessary */
1616 
1617  if (push_func)
1618  lua_insert(L, -4);
1619 
1620  lua_pop(L, 3);
1621  return 1;
1622  }
1623  }
1624 
1625  /* pop the includes table */
1626  lua_pop(L, 1);
1627  return 0;
1628 }
1629 
1630 static struct ast_switch lua_switch = {
1631  .name = "Lua",
1632  .description = "Lua PBX Switch",
1633  .exists = exists,
1634  .canmatch = canmatch,
1635  .exec = exec,
1636  .matchmore = matchmore,
1637 };
1638 
1639 
1641 {
1642  int res = AST_MODULE_LOAD_SUCCESS;
1643  int loaded = 0;
1644 
1645  lua_State *L = luaL_newstate();
1646  if (!L) {
1647  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1648  return AST_MODULE_LOAD_FAILURE;
1649  }
1650 
1651  loaded = lua_reload_extensions(L);
1652  if (loaded) {
1653  const char *error = lua_tostring(L, -1);
1654  ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
1655 
1656  if (loaded < 0) {
1658  } else {
1660  }
1661  }
1662 
1663  lua_close(L);
1664  return res;
1665 }
1666 
1667 static int unload_module(void)
1668 {
1670  ast_unregister_switch(&lua_switch);
1672  return 0;
1673 }
1674 
1675 static int reload(void)
1676 {
1677  return load_or_reload_lua_stuff();
1678 }
1679 
1680 static int load_module(void)
1681 {
1682  int res;
1683 
1684  if ((res = load_or_reload_lua_stuff()))
1685  return res;
1686 
1687  if (ast_register_switch(&lua_switch)) {
1688  ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
1689  return AST_MODULE_LOAD_FAILURE;
1690  }
1691 
1692  return AST_MODULE_LOAD_SUCCESS;
1693 }
1694 
1696  .support_level = AST_MODULE_SUPPORT_EXTENDED,
1697  .load = load_module,
1698  .unload = unload_module,
1699  .reload = reload,
1700 );
const char * type
Definition: datastore.h:32
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: ael_main.c:589
static int lua_autoservice_start(lua_State *L)
[lua_CFunction] Tell pbx_lua to maintain an autoservice on this channel (for access from lua...
Definition: pbx_lua.c:695
static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
Locate an extensions and optionally push the matching function on the stack.
Definition: pbx_lua.c:1493
static struct ast_hashtab * local_table
Definition: pbx_lua.c:111
#define ast_channel_lock(chan)
Definition: channel.h:2945
static int reload(void)
Definition: pbx_lua.c:1675
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
static char * registrar
Definition: pbx_lua.c:49
Asterisk main include file. File version handling, generic pbx functions.
static int lua_get_variable_value(lua_State *L)
[lua_CFunction] Used to get the value of a variable or dialplan function (for access from lua...
Definition: pbx_lua.c:300
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
static void lua_create_application_metatable(lua_State *L)
Create the &#39;application&#39; metatable, used to execute asterisk applications from lua.
Definition: pbx_lua.c:502
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
static void lua_create_variable_metatable(lua_State *L)
Create the &#39;variable&#39; metatable, used to retrieve channel variables.
Definition: pbx_lua.c:485
#define LUA_EXT_DATA_SIZE
Definition: pbx_lua.c:54
static void lua_state_destroy(void *data)
The destructor for lua_datastore.
Definition: pbx_lua.c:123
static void lua_concat_args(lua_State *L, int start, int nargs)
Concatenate a list of lua function arguments into a comma separated string.
Definition: pbx_lua.c:631
int ast_extension_cmp(const char *a, const char *b)
Determine if one extension should match before another.
Definition: pbx.c:2183
static int tmp()
Definition: bt_open.c:389
Generic (perhaps overly so) hashtable implementation Hash Table support in Asterisk.
static int lua_autoservice_status(lua_State *L)
[lua_CFunction] Get the status of the autoservice flag (for access from lua, don&#39;t call directly) ...
Definition: pbx_lua.c:760
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: ael_main.c:370
static int lua_autoservice_stop(lua_State *L)
[lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on this channel (for access from lua...
Definition: pbx_lua.c:728
static int loaded
Definition: cdr_csv.c:58
Structure for a data store type.
Definition: datastore.h:31
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx_switch.c:76
static void lua_create_app_table(lua_State *L)
Create the global &#39;app&#39; table for executing applications.
Definition: pbx_lua.c:445
static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1381
static char * lua_read_extensions_file(lua_State *L, long *size, int *file_not_openable)
Load the extensions.lua file in to a buffer and execute the file.
Definition: pbx_lua.c:1091
static int lua_sort_extensions(lua_State *L)
Store the sort order of each context.
Definition: pbx_lua.c:844
#define ast_mutex_lock(a)
Definition: lock.h:187
static void lua_push_variable_table(lua_State *L)
Push a &#39;variable&#39; table on the stack for access the channel variable with the given name...
Definition: pbx_lua.c:424
static struct test_val c
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96
static int load_or_reload_lua_stuff(void)
Definition: pbx_lua.c:1640
int value
Definition: syslog.c:37
static int priority
#define ast_module_user_remove(user)
Definition: module.h:427
static struct ao2_container * hints
Definition: pbx.c:801
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:463
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition: hashtab.c:84
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define COLOR_BRCYAN
Definition: term.h:60
static const char context_name[]
Utility functions.
static int lua_check_hangup(lua_State *L)
[lua_CFunction] Check if this channel has been hungup or not (for access from lua, don&#39;t call directly)
Definition: pbx_lua.c:774
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * name
Definition: pbx.h:162
static int lua_register_switches(lua_State *L)
Register dialplan switches for our pbx_lua contexs.
Definition: pbx_lua.c:929
static ast_mutex_t config_file_lock
Definition: pbx_lua.c:106
static char * config
Definition: pbx_lua.c:48
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int lua_extension_cmp(lua_State *L)
[lua_CFunction] Compare two extensions (for access from lua, don&#39;t call directly) ...
Definition: pbx_lua.c:1067
static int lua_get_variable(lua_State *L)
[lua_CFunction] Return a lua &#39;variable&#39; object (for access from lua, don&#39;t call directly) ...
Definition: pbx_lua.c:556
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
static long config_file_size
Definition: pbx_lua.c:108
static const struct ast_datastore_info lua_datastore
Definition: pbx_lua.c:113
#define LUA_GOTO_DETECTED
Definition: pbx_lua.c:61
static int lua_func_read(lua_State *L)
[lua_CFunction] Create a &#39;variable&#39; object for accessing a dialplan function (for access from lua...
Definition: pbx_lua.c:670
static struct ast_context * local_contexts
Definition: pbx_lua.c:110
static int lua_pbx_findapp(lua_State *L)
[lua_CFunction] Find an app and return it in a lua table (for access from lua, don&#39;t call directly) ...
Definition: pbx_lua.c:155
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int unload_module(void)
Definition: pbx_lua.c:1667
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static char * config_file_data
Definition: pbx_lua.c:107
static struct ast_switch lua_switch
Definition: pbx_lua.c:1630
#define PRIORITY_HINT
Definition: pbx.h:54
int() ast_switch_f(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
Definition: pbx.h:156
static int lua_load_extensions(lua_State *L, struct ast_channel *chan)
Load the extensions.lua file from the internal buffer.
Definition: pbx_lua.c:1170
#define ast_module_user_add(chan)
Definition: module.h:426
const char * ast_channel_exten(const struct ast_channel *chan)
Core PBX routines and definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
static void lua_create_hangup_function(lua_State *L)
Create the hangup check function.
Definition: pbx_lua.c:538
struct ast_channel * chan
Definition: loader.c:128
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
#define COLOR_BRMAGENTA
Definition: term.h:58
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
static int load_module(void)
Definition: pbx_lua.c:1680
static void lua_create_autoservice_functions(lua_State *L)
Create the autoservice functions.
Definition: pbx_lua.c:518
#define LOG_ERROR
Definition: logger.h:285
static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1358
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
Definition: conf2ael.c:639
static int lua_reload_extensions(lua_State *L)
Reload the extensions file and update the internal buffers if it loads correctly. ...
Definition: pbx_lua.c:1213
int errno
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1335
static int lua_set_variable(lua_State *L)
[lua_CFunction] Set the value of a channel variable or dialplan function (for access from lua...
Definition: pbx_lua.c:596
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int lua_error_function(lua_State *L)
[lua_CFunction] Handle lua errors (for access from lua, don&#39;t call directly)
Definition: pbx_lua.c:791
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
static int lua_register_hints(lua_State *L)
Register dialplan hints for our pbx_lua contexs.
Definition: pbx_lua.c:987
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: extconf.c:4297
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: ael_main.c:596
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx_switch.c:58
Module could not be loaded properly.
Definition: module.h:102
int ast_extension_close(const char *pattern, const char *data, int needmore)
Definition: pbx.c:2418
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static void lua_datastore_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
The fixup function for the lua_datastore.
Definition: pbx_lua.c:137
static void lua_free_extensions(void)
Free the internal extensions buffer.
Definition: pbx_lua.c:1252
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static int lua_set_variable_value(lua_State *L)
[lua_CFunction] Used to set the value of a variable or dialplan function (for access from lua...
Definition: pbx_lua.c:360
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1405
void * data
Definition: datastore.h:70
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Add an extension to an extension context, this time with an ast_context *.
Definition: pbx.c:7299
Standard Command Line Interface.
ast_app: A registered application
Definition: pbx_app.c:45
const char * ast_channel_name(const struct ast_channel *chan)
static void lua_create_channel_table(lua_State *L)
Create the global &#39;channel&#39; table for accesing channel variables.
Definition: pbx_lua.c:463
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: conf2ael.c:625
static struct test_val b
const char * ast_channel_context(const struct ast_channel *chan)
Handy terminal functions for vt* terms.
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Definition: hashtab.h:261
#define LUA_BUF_SIZE
Definition: pbx_lua.c:56
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
static const char app[]
Definition: app_mysql.c:62
Asterisk module definitions.
static lua_State * lua_get_state(struct ast_channel *chan)
Get the lua_State for this channel.
Definition: pbx_lua.c:1273
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
static int lua_pbx_exec(lua_State *L)
[lua_CFunction] This function is part of the &#39;application&#39; metatable and is used to execute applicati...
Definition: pbx_lua.c:186
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
#define ast_mutex_unlock(a)
Definition: lock.h:188
static struct test_val a
static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority)
Update the lua registry with the given context, exten, and priority.
Definition: pbx_lua.c:404