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