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