#include "asterisk.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/term.h"
#include "asterisk/paths.h"
#include "asterisk/hashtab.h"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

Go to the source code of this file.
Defines | |
| #define | LUA_BUF_SIZE 4096 |
| #define | LUA_EXT_DATA_SIZE 8192 |
| #define | LUA_GOTO_DETECTED 5 |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| static int | exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| static int | exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| static int | load_module (void) |
| static int | load_or_reload_lua_stuff (void) |
| static int | lua_autoservice_start (lua_State *L) |
| [lua_CFunction] Tell pbx_lua to maintain an autoservice on this channel (for access from lua, don't call directly) | |
| 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) | |
| static int | lua_autoservice_stop (lua_State *L) |
| [lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on this channel (for access from lua, don't call directly) | |
| static int | lua_check_hangup (lua_State *L) |
| [lua_CFunction] Check if this channel has been hungup or not (for access from lua, don't call directly) | |
| static void | lua_concat_args (lua_State *L, int start, int nargs) |
| Concatenate a list of lua function arguments into a comma separated string. | |
| static void | lua_create_app_table (lua_State *L) |
| Create the global 'app' table for executing applications. | |
| static void | lua_create_application_metatable (lua_State *L) |
| Create the 'application' metatable, used to execute asterisk applications from lua. | |
| static void | lua_create_autoservice_functions (lua_State *L) |
| Create the autoservice functions. | |
| static void | lua_create_channel_table (lua_State *L) |
| Create the global 'channel' table for accesing channel variables. | |
| static void | lua_create_hangup_function (lua_State *L) |
| Create the hangup check function. | |
| static void | lua_create_variable_metatable (lua_State *L) |
| Create the 'variable' metatable, used to retrieve channel variables. | |
| static void | lua_datastore_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan) |
| The fixup function for the lua_datastore. | |
| static int | lua_error_function (lua_State *L) |
| [lua_CFunction] Handle lua errors (for access from lua, don't call directly) | |
| static int | lua_extension_cmp (lua_State *L) |
| [lua_CFunction] Compare two extensions (for access from lua, don't call directly) | |
| 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. | |
| static void | lua_free_extensions () |
| Free the internal extensions buffer. | |
| static int | lua_func_read (lua_State *L) |
| [lua_CFunction] Create a 'variable' object for accessing a dialplan function (for access from lua, don't call directly) | |
| static lua_State * | lua_get_state (struct ast_channel *chan) |
| Get the lua_State for this channel. | |
| static int | lua_get_variable (lua_State *L) |
| [lua_CFunction] Return a lua 'variable' object (for access from lua, don't call directly) | |
| 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, don't call directly) | |
| static int | lua_load_extensions (lua_State *L, struct ast_channel *chan) |
| Load the extensions.lua file from the internal buffer. | |
| static int | lua_pbx_exec (lua_State *L) |
| [lua_CFunction] This function is part of the 'application' metatable and is used to execute applications similar to pbx_exec() (for access from lua, don't call directly) | |
| 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) | |
| 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. | |
| static char * | lua_read_extensions_file (lua_State *L, long *size) |
| Load the extensions.lua file in to a buffer and execute the file. | |
| static int | lua_register_hints (lua_State *L) |
| Register dialplan hints for our pbx_lua contexs. | |
| static int | lua_register_switches (lua_State *L) |
| Register dialplan switches for our pbx_lua contexs. | |
| static int | lua_reload_extensions (lua_State *L) |
| Reload the extensions file and update the internal buffers if it loads correctly. | |
| static int | lua_set_variable (lua_State *L) |
| [lua_CFunction] Set the value of a channel variable or dialplan function (for access from lua, don't call directly) | |
| 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, don't call directly) | |
| static int | lua_sort_extensions (lua_State *L) |
| Store the sort order of each context. | |
| static void | lua_state_destroy (void *data) |
| The destructor for lua_datastore. | |
| 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. | |
| static int | matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) |
| static int | reload (void) |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Lua PBX Switch" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static char * | config = "extensions.lua" |
| static char * | config_file_data = NULL |
| static ast_mutex_t | config_file_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| static long | config_file_size = 0 |
| static struct ast_context * | local_contexts = NULL |
| static struct ast_hashtab * | local_table = NULL |
| static struct ast_datastore_info | lua_datastore |
| static struct ast_switch | lua_switch |
| static char * | registrar = "pbx_lua" |
Definition in file pbx_lua.c.
| #define LUA_BUF_SIZE 4096 |
Definition at line 58 of file pbx_lua.c.
Referenced by lua_get_variable(), and lua_get_variable_value().
| #define LUA_EXT_DATA_SIZE 8192 |
| #define LUA_GOTO_DETECTED 5 |
| static int canmatch | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 1338 of file pbx_lua.c.
References ast_log(), ast_module_user_add, ast_module_user_remove, LOG_ERROR, lua_find_extension(), and lua_get_state().
Referenced by lua_find_extension().
01339 { 01340 int res; 01341 lua_State *L; 01342 struct ast_module_user *u = ast_module_user_add(chan); 01343 if (!u) { 01344 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01345 return 0; 01346 } 01347 01348 L = lua_get_state(chan); 01349 if (!L) { 01350 ast_module_user_remove(u); 01351 return 0; 01352 } 01353 01354 res = lua_find_extension(L, context, exten, priority, &canmatch, 0); 01355 01356 if (!chan) lua_close(L); 01357 ast_module_user_remove(u); 01358 return res; 01359 }
| static int exec | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 1385 of file pbx_lua.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_log(), ast_module_user_add, ast_module_user_remove, exists(), LOG_ERROR, lua_error_function(), lua_find_extension(), lua_get_state(), LUA_GOTO_DETECTED, and lua_update_registry().
01386 { 01387 int res, error_func; 01388 lua_State *L; 01389 struct ast_module_user *u = ast_module_user_add(chan); 01390 if (!u) { 01391 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01392 return -1; 01393 } 01394 01395 L = lua_get_state(chan); 01396 if (!L) { 01397 ast_module_user_remove(u); 01398 return -1; 01399 } 01400 01401 lua_pushcfunction(L, &lua_error_function); 01402 error_func = lua_gettop(L); 01403 01404 /* push the extension function onto the stack */ 01405 if (!lua_find_extension(L, context, exten, priority, &exists, 1)) { 01406 lua_pop(L, 1); /* pop the debug function */ 01407 ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context); 01408 if (!chan) lua_close(L); 01409 ast_module_user_remove(u); 01410 return -1; 01411 } 01412 01413 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 01414 if (lua_toboolean(L, -1)) { 01415 ast_autoservice_start(chan); 01416 } 01417 lua_pop(L, 1); 01418 01419 lua_update_registry(L, context, exten, priority); 01420 01421 lua_pushstring(L, context); 01422 lua_pushstring(L, exten); 01423 01424 res = lua_pcall(L, 2, 0, error_func); 01425 if (res) { 01426 if (res == LUA_ERRRUN) { 01427 res = -1; 01428 if (lua_isnumber(L, -1)) { 01429 res = lua_tointeger(L, -1); 01430 01431 if (res == LUA_GOTO_DETECTED) { 01432 res = 0; 01433 } 01434 } else if (lua_isstring(L, -1)) { 01435 const char *error = lua_tostring(L, -1); 01436 ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error); 01437 } 01438 } else if (res == LUA_ERRERR) { 01439 res = -1; 01440 ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n"); 01441 } else if (res == LUA_ERRMEM) { 01442 res = -1; 01443 ast_log(LOG_ERROR, "Memory allocation error\n"); 01444 } 01445 lua_pop(L, 1); 01446 } 01447 lua_remove(L, error_func); 01448 01449 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 01450 if (lua_toboolean(L, -1)) { 01451 ast_autoservice_stop(chan); 01452 } 01453 lua_pop(L, 1); 01454 01455 if (!chan) lua_close(L); 01456 ast_module_user_remove(u); 01457 return res; 01458 }
| static int exists | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 1315 of file pbx_lua.c.
References ast_log(), ast_module_user_add, ast_module_user_remove, exists(), LOG_ERROR, lua_find_extension(), and lua_get_state().
01316 { 01317 int res; 01318 lua_State *L; 01319 struct ast_module_user *u = ast_module_user_add(chan); 01320 if (!u) { 01321 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01322 return 0; 01323 } 01324 01325 L = lua_get_state(chan); 01326 if (!L) { 01327 ast_module_user_remove(u); 01328 return 0; 01329 } 01330 01331 res = lua_find_extension(L, context, exten, priority, &exists, 0); 01332 01333 if (!chan) lua_close(L); 01334 ast_module_user_remove(u); 01335 return res; 01336 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1649 of file pbx_lua.c.
References ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_switch(), load_or_reload_lua_stuff(), and LOG_ERROR.
01650 { 01651 int res; 01652 01653 if ((res = load_or_reload_lua_stuff())) 01654 return res; 01655 01656 if (ast_register_switch(&lua_switch)) { 01657 ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n"); 01658 return AST_MODULE_LOAD_DECLINE; 01659 } 01660 01661 return AST_MODULE_LOAD_SUCCESS; 01662 }
| static int load_or_reload_lua_stuff | ( | void | ) | [static] |
Definition at line 1616 of file pbx_lua.c.
References ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, LOG_ERROR, and lua_reload_extensions().
Referenced by load_module(), and reload().
01617 { 01618 int res = AST_MODULE_LOAD_SUCCESS; 01619 01620 lua_State *L = luaL_newstate(); 01621 if (!L) { 01622 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); 01623 return AST_MODULE_LOAD_DECLINE; 01624 } 01625 01626 if (lua_reload_extensions(L)) { 01627 const char *error = lua_tostring(L, -1); 01628 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error); 01629 res = AST_MODULE_LOAD_DECLINE; 01630 } 01631 01632 lua_close(L); 01633 return res; 01634 }
| static int lua_autoservice_start | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Tell pbx_lua to maintain an autoservice on this channel (for access from lua, don't call directly)
| L | the lua_State to use |
Definition at line 697 of file pbx_lua.c.
References ast_autoservice_start().
Referenced by lua_create_autoservice_functions().
00698 { 00699 struct ast_channel *chan; 00700 00701 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00702 if (lua_toboolean(L, -1)) { 00703 /* autservice already running */ 00704 lua_pop(L, 1); 00705 return 0; 00706 } 00707 lua_pop(L, 1); 00708 00709 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00710 chan = lua_touserdata(L, -1); 00711 lua_pop(L, 1); 00712 00713 ast_autoservice_start(chan); 00714 00715 lua_pushboolean(L, 1); 00716 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); 00717 return 0; 00718 }
| static int lua_autoservice_status | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Get the status of the autoservice flag (for access from lua, don't call directly)
| L | the lua_State to use |
Definition at line 762 of file pbx_lua.c.
Referenced by lua_create_autoservice_functions().
| static int lua_autoservice_stop | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on this channel (for access from lua, don't call directly)
| L | the lua_State to use |
Definition at line 730 of file pbx_lua.c.
References ast_autoservice_stop().
Referenced by lua_create_autoservice_functions().
00731 { 00732 struct ast_channel *chan; 00733 00734 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00735 if (!lua_toboolean(L, -1)) { 00736 /* no autservice running */ 00737 lua_pop(L, 1); 00738 return 0; 00739 } 00740 lua_pop(L, 1); 00741 00742 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00743 chan = lua_touserdata(L, -1); 00744 lua_pop(L, 1); 00745 00746 ast_autoservice_stop(chan); 00747 00748 lua_pushboolean(L, 0); 00749 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); 00750 return 0; 00751 }
| static int lua_check_hangup | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Check if this channel has been hungup or not (for access from lua, don't call directly)
| L | the lua_State to use |
Definition at line 776 of file pbx_lua.c.
References ast_check_hangup().
Referenced by lua_create_hangup_function().
00777 { 00778 struct ast_channel *chan; 00779 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00780 chan = lua_touserdata(L, -1); 00781 lua_pop(L, 1); 00782 00783 lua_pushboolean(L, ast_check_hangup(chan)); 00784 return 1; 00785 }
| static void lua_concat_args | ( | lua_State * | L, | |
| int | start, | |||
| int | nargs | |||
| ) | [static] |
Concatenate a list of lua function arguments into a comma separated string.
| L | the lua_State to use | |
| start | the index of the first argument | |
| nargs | the number of args |
Definition at line 633 of file pbx_lua.c.
Referenced by lua_func_read(), and lua_pbx_exec().
00633 { 00634 int concat = 0; 00635 int i = start + 1; 00636 00637 if (start <= nargs && !lua_isnil(L, start)) { 00638 lua_pushvalue(L, start); 00639 concat += 1; 00640 } 00641 00642 for (; i <= nargs; i++) { 00643 if (lua_isnil(L, i)) { 00644 lua_pushliteral(L, ","); 00645 concat += 1; 00646 } else { 00647 lua_pushliteral(L, ","); 00648 lua_pushvalue(L, i); 00649 concat += 2; 00650 } 00651 } 00652 00653 lua_concat(L, concat); 00654 }
| static void lua_create_app_table | ( | lua_State * | L | ) | [static] |
Create the global 'app' table for executing applications.
| L | the lua_State to use |
Definition at line 447 of file pbx_lua.c.
References lua_pbx_findapp().
Referenced by lua_load_extensions().
00448 { 00449 lua_newtable(L); 00450 luaL_newmetatable(L, "app"); 00451 00452 lua_pushstring(L, "__index"); 00453 lua_pushcfunction(L, &lua_pbx_findapp); 00454 lua_settable(L, -3); 00455 00456 lua_setmetatable(L, -2); 00457 lua_setglobal(L, "app"); 00458 }
| static void lua_create_application_metatable | ( | lua_State * | L | ) | [static] |
Create the 'application' metatable, used to execute asterisk applications from lua.
| L | the lua_State to use |
Definition at line 504 of file pbx_lua.c.
References lua_pbx_exec().
Referenced by lua_load_extensions().
00505 { 00506 luaL_newmetatable(L, "application"); 00507 00508 lua_pushstring(L, "__call"); 00509 lua_pushcfunction(L, &lua_pbx_exec); 00510 lua_settable(L, -3); 00511 00512 lua_pop(L, 1); 00513 }
| static void lua_create_autoservice_functions | ( | lua_State * | L | ) | [static] |
Create the autoservice functions.
| L | the lua_State to use |
Definition at line 520 of file pbx_lua.c.
References lua_autoservice_start(), lua_autoservice_status(), and lua_autoservice_stop().
Referenced by lua_load_extensions().
00521 { 00522 lua_pushcfunction(L, &lua_autoservice_start); 00523 lua_setglobal(L, "autoservice_start"); 00524 00525 lua_pushcfunction(L, &lua_autoservice_stop); 00526 lua_setglobal(L, "autoservice_stop"); 00527 00528 lua_pushcfunction(L, &lua_autoservice_status); 00529 lua_setglobal(L, "autoservice_status"); 00530 00531 lua_pushboolean(L, 1); 00532 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); 00533 }
| static void lua_create_channel_table | ( | lua_State * | L | ) | [static] |
Create the global 'channel' table for accesing channel variables.
| L | the lua_State to use |
Definition at line 465 of file pbx_lua.c.
References lua_get_variable(), and lua_set_variable().
Referenced by lua_load_extensions().
00466 { 00467 lua_newtable(L); 00468 luaL_newmetatable(L, "channel_data"); 00469 00470 lua_pushstring(L, "__index"); 00471 lua_pushcfunction(L, &lua_get_variable); 00472 lua_settable(L, -3); 00473 00474 lua_pushstring(L, "__newindex"); 00475 lua_pushcfunction(L, &lua_set_variable); 00476 lua_settable(L, -3); 00477 00478 lua_setmetatable(L, -2); 00479 lua_setglobal(L, "channel"); 00480 }
| static void lua_create_hangup_function | ( | lua_State * | L | ) | [static] |
Create the hangup check function.
| L | the lua_State to use |
Definition at line 540 of file pbx_lua.c.
References lua_check_hangup().
Referenced by lua_load_extensions().
00541 { 00542 lua_pushcfunction(L, &lua_check_hangup); 00543 lua_setglobal(L, "check_hangup"); 00544 }
| static void lua_create_variable_metatable | ( | lua_State * | L | ) | [static] |
Create the 'variable' metatable, used to retrieve channel variables.
| L | the lua_State to use |
Definition at line 487 of file pbx_lua.c.
References lua_func_read().
Referenced by lua_load_extensions().
00488 { 00489 luaL_newmetatable(L, "variable"); 00490 00491 lua_pushstring(L, "__call"); 00492 lua_pushcfunction(L, &lua_func_read); 00493 lua_settable(L, -3); 00494 00495 lua_pop(L, 1); 00496 }
| static void lua_datastore_fixup | ( | void * | data, | |
| struct ast_channel * | old_chan, | |||
| struct ast_channel * | new_chan | |||
| ) | [static] |
The fixup function for the lua_datastore.
| data | the datastore data, in this case it will be a lua_State | |
| old_chan | the channel we are moving from | |
| new_chan | the channel we are moving to |
Definition at line 139 of file pbx_lua.c.
00140 { 00141 lua_State *L = data; 00142 lua_pushlightuserdata(L, new_chan); 00143 lua_setfield(L, LUA_REGISTRYINDEX, "channel"); 00144 }
| static int lua_error_function | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Handle lua errors (for access from lua, don't call directly)
| L | the lua_State to use |
Definition at line 793 of file pbx_lua.c.
Referenced by exec(), and lua_read_extensions_file().
00794 { 00795 int message_index; 00796 00797 /* pass number arguments right through back to asterisk*/ 00798 if (lua_isnumber(L, -1)) { 00799 return 1; 00800 } 00801 00802 /* if we are here then we have a string error message, let's attach a 00803 * backtrace to it */ 00804 message_index = lua_gettop(L); 00805 00806 /* prepare to prepend a new line to the traceback */ 00807 lua_pushliteral(L, "\n"); 00808 00809 lua_getglobal(L, "debug"); 00810 lua_getfield(L, -1, "traceback"); 00811 lua_remove(L, -2); /* remove the 'debug' table */ 00812 00813 lua_pushvalue(L, message_index); 00814 lua_remove(L, message_index); 00815 00816 lua_pushnumber(L, 2); 00817 00818 lua_call(L, 2, 1); 00819 00820 /* prepend the new line we prepared above */ 00821 lua_concat(L, 2); 00822 00823 return 1; 00824 }
| static int lua_extension_cmp | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Compare two extensions (for access from lua, don't call directly)
This function returns true if the first extension passed should match after the second. It behaves like the '<' operator.
Definition at line 1054 of file pbx_lua.c.
References ast_extension_cmp().
Referenced by lua_sort_extensions().
01055 { 01056 const char *a = luaL_checkstring(L, -2); 01057 const char *b = luaL_checkstring(L, -1); 01058 01059 if (ast_extension_cmp(a, b) == -1) 01060 lua_pushboolean(L, 1); 01061 else 01062 lua_pushboolean(L, 0); 01063 01064 return 1; 01065 }
| static int lua_find_extension | ( | lua_State * | L, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| ast_switch_f * | func, | |||
| int | push_func | |||
| ) | [static] |
Locate an extensions and optionally push the matching function on the stack.
| L | the lua_State to use | |
| context | the context to look in | |
| exten | the extension to look up | |
| priority | the priority to check, '1' is the only valid priority | |
| func | the calling func, used to adjust matching behavior between, match, canmatch, and matchmore | |
| push_func | whether or not to push the lua function for the given extension onto the stack |
Definition at line 1473 of file pbx_lua.c.
References ast_debug, ast_extension_close(), ast_extension_match(), ast_log(), canmatch(), E_CANMATCH, E_MATCHMORE, LOG_ERROR, match(), and matchmore().
Referenced by canmatch(), exec(), exists(), and matchmore().
01474 { 01475 int context_table, context_order_table, i; 01476 01477 ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority); 01478 if (priority != 1) 01479 return 0; 01480 01481 /* load the 'extensions' table */ 01482 lua_getglobal(L, "extensions"); 01483 if (lua_isnil(L, -1)) { 01484 ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n"); 01485 lua_pop(L, 1); 01486 return 0; 01487 } 01488 01489 /* load the given context */ 01490 lua_getfield(L, -1, context); 01491 if (lua_isnil(L, -1)) { 01492 lua_pop(L, 2); 01493 return 0; 01494 } 01495 01496 /* remove the extensions table */ 01497 lua_remove(L, -2); 01498 01499 context_table = lua_gettop(L); 01500 01501 /* load the extensions order table for this context */ 01502 lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order"); 01503 lua_getfield(L, -1, context); 01504 01505 lua_remove(L, -2); /* remove the extensions order table */ 01506 01507 context_order_table = lua_gettop(L); 01508 01509 /* step through the extensions looking for a match */ 01510 for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) { 01511 int e_index_copy, match = 0; 01512 const char *e; 01513 01514 lua_pushinteger(L, i); 01515 lua_gettable(L, context_order_table); 01516 lua_gettop(L); 01517 01518 /* copy the key at the top of the stack for use later */ 01519 lua_pushvalue(L, -1); 01520 e_index_copy = lua_gettop(L); 01521 01522 if (!(e = lua_tostring(L, e_index_copy))) { 01523 lua_pop(L, 2); 01524 continue; 01525 } 01526 01527 /* make sure this is not the 'include' extension */ 01528 if (!strcasecmp(e, "include")) { 01529 lua_pop(L, 2); 01530 continue; 01531 } 01532 01533 if (func == &matchmore) 01534 match = ast_extension_close(e, exten, E_MATCHMORE); 01535 else if (func == &canmatch) 01536 match = ast_extension_close(e, exten, E_CANMATCH); 01537 else 01538 match = ast_extension_match(e, exten); 01539 01540 /* the extension matching functions return 0 on fail, 1 on 01541 * match, 2 on earlymatch */ 01542 01543 if (!match) { 01544 /* pop the copy and the extension */ 01545 lua_pop(L, 2); 01546 continue; /* keep trying */ 01547 } 01548 01549 if (func == &matchmore && match == 2) { 01550 /* We match an extension ending in '!'. The decision in 01551 * this case is final and counts as no match. */ 01552 lua_pop(L, 4); 01553 return 0; 01554 } 01555 01556 /* remove the context table, the context order table, the 01557 * extension, and the extension copy (or replace the extension 01558 * with the corresponding function) */ 01559 if (push_func) { 01560 lua_pop(L, 1); /* pop the copy */ 01561 lua_gettable(L, context_table); 01562 lua_insert(L, -3); 01563 lua_pop(L, 2); 01564 } else { 01565 lua_pop(L, 4); 01566 } 01567 01568 return 1; 01569 } 01570 01571 /* load the includes for this context */ 01572 lua_getfield(L, context_table, "include"); 01573 if (lua_isnil(L, -1)) { 01574 lua_pop(L, 3); 01575 return 0; 01576 } 01577 01578 /* remove the context and the order table*/ 01579 lua_remove(L, context_order_table); 01580 lua_remove(L, context_table); 01581 01582 /* Now try any includes we have in this context */ 01583 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { 01584 const char *c = lua_tostring(L, -1); 01585 if (!c) 01586 continue; 01587 01588 if (lua_find_extension(L, c, exten, priority, func, push_func)) { 01589 /* remove the value, the key, and the includes table 01590 * from the stack. Leave the function behind if 01591 * necessary */ 01592 01593 if (push_func) 01594 lua_insert(L, -4); 01595 01596 lua_pop(L, 3); 01597 return 1; 01598 } 01599 } 01600 01601 /* pop the includes table */ 01602 lua_pop(L, 1); 01603 return 0; 01604 }
| static void lua_free_extensions | ( | void | ) | [static] |
Free the internal extensions buffer.
Definition at line 1232 of file pbx_lua.c.
References ast_free, ast_mutex_lock, ast_mutex_unlock, and config_file_lock.
Referenced by unload_module().
01233 { 01234 ast_mutex_lock(&config_file_lock); 01235 config_file_size = 0; 01236 ast_free(config_file_data); 01237 ast_mutex_unlock(&config_file_lock); 01238 }
| static int lua_func_read | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Create a 'variable' object for accessing a dialplan function (for access from lua, don't call directly)
This function is called to create a 'variable' object to access a dialplan function. It would be called in the following example as would be seen in extensions.lua.
channel.func("arg1", "arg2", "arg3")
To actually do anything with the resulting value you must use the 'get()' and 'set()' methods (the reason is the resulting value is not a value, but an object in the form of a lua table).
Definition at line 672 of file pbx_lua.c.
References lua_concat_args(), and lua_push_variable_table().
Referenced by lua_create_variable_metatable().
00673 { 00674 int nargs = lua_gettop(L); 00675 00676 /* build a string in the form of "func_name(arg1,arg2,arg3)" */ 00677 lua_getfield(L, 1, "name"); 00678 lua_pushliteral(L, "("); 00679 lua_concat_args(L, 2, nargs); 00680 lua_pushliteral(L, ")"); 00681 lua_concat(L, 4); 00682 00683 lua_push_variable_table(L); 00684 return 1; 00685 }
| static lua_State * lua_get_state | ( | struct ast_channel * | chan | ) | [static] |
Get the lua_State for this channel.
If no channel is passed then a new state is allocated. States with no channel assocatied with them should only be used for matching extensions. If the channel does not yet have a lua state associated with it, one will be created.
Definition at line 1253 of file pbx_lua.c.
References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_log(), ast_datastore::data, LOG_ERROR, and lua_load_extensions().
Referenced by canmatch(), exec(), exists(), and matchmore().
01254 { 01255 struct ast_datastore *datastore = NULL; 01256 lua_State *L; 01257 01258 if (!chan) { 01259 L = luaL_newstate(); 01260 if (!L) { 01261 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); 01262 return NULL; 01263 } 01264 01265 if (lua_load_extensions(L, NULL)) { 01266 const char *error = lua_tostring(L, -1); 01267 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error); 01268 lua_close(L); 01269 return NULL; 01270 } 01271 return L; 01272 } else { 01273 ast_channel_lock(chan); 01274 datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL); 01275 ast_channel_unlock(chan); 01276 01277 if (!datastore) { 01278 /* nothing found, allocate a new lua state */ 01279 datastore = ast_datastore_alloc(&lua_datastore, NULL); 01280 if (!datastore) { 01281 ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n"); 01282 return NULL; 01283 } 01284 01285 datastore->data = luaL_newstate(); 01286 if (!datastore->data) { 01287 ast_datastore_free(datastore); 01288 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); 01289 return NULL; 01290 } 01291 01292 ast_channel_lock(chan); 01293 ast_channel_datastore_add(chan, datastore); 01294 ast_channel_unlock(chan); 01295 01296 L = datastore->data; 01297 01298 if (lua_load_extensions(L, chan)) { 01299 const char *error = lua_tostring(L, -1); 01300 ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", ast_channel_name(chan), error); 01301 01302 ast_channel_lock(chan); 01303 ast_channel_datastore_remove(chan, datastore); 01304 ast_channel_unlock(chan); 01305 01306 ast_datastore_free(datastore); 01307 return NULL; 01308 } 01309 } 01310 01311 return datastore->data; 01312 } 01313 }
| static int lua_get_variable | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Return a lua 'variable' object (for access from lua, don't call directly)
This function is called to lookup a variable construct a 'variable' object. It would be called in the following example as would be seen in extensions.lua.
channel.variable
Definition at line 558 of file pbx_lua.c.
References ast_alloca, ast_channel_varshead(), ast_strlen_zero(), LUA_BUF_SIZE, lua_push_variable_table(), name, pbx_retrieve_variable(), and value.
Referenced by lua_create_channel_table().
00559 { 00560 struct ast_channel *chan; 00561 const char *name = luaL_checkstring(L, 2); 00562 char *value = NULL; 00563 char *workspace = ast_alloca(LUA_BUF_SIZE); 00564 workspace[0] = '\0'; 00565 00566 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00567 chan = lua_touserdata(L, -1); 00568 lua_pop(L, 1); 00569 00570 lua_pushvalue(L, 2); 00571 lua_push_variable_table(L); 00572 00573 /* if this is not a request for a dialplan funciton attempt to retrieve 00574 * the value of the variable */ 00575 if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') { 00576 pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan)); 00577 } 00578 00579 if (value) { 00580 lua_pushstring(L, value); 00581 lua_setfield(L, -2, "value"); 00582 } 00583 00584 return 1; 00585 }
| static int lua_get_variable_value | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Used to get the value of a variable or dialplan function (for access from lua, don't call directly)
The value of the variable or function is returned. This function is the 'get()' function in the following example as would be seen in extensions.lua.
channel.variable:get()
Definition at line 302 of file pbx_lua.c.
References ast_alloca, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_varshead(), ast_func_read(), ast_strdupa, ast_strlen_zero(), LUA_BUF_SIZE, name, pbx_retrieve_variable(), and value.
Referenced by lua_push_variable_table().
00303 { 00304 struct ast_channel *chan; 00305 char *value = NULL, *name; 00306 char *workspace = ast_alloca(LUA_BUF_SIZE); 00307 int autoservice; 00308 00309 workspace[0] = '\0'; 00310 00311 if (!lua_istable(L, 1)) { 00312 lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value"); 00313 return lua_error(L); 00314 } 00315 00316 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00317 chan = lua_touserdata(L, -1); 00318 lua_pop(L, 1); 00319 00320 lua_getfield(L, 1, "name"); 00321 name = ast_strdupa(lua_tostring(L, -1)); 00322 lua_pop(L, 1); 00323 00324 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00325 autoservice = lua_toboolean(L, -1); 00326 lua_pop(L, 1); 00327 00328 if (autoservice) 00329 ast_autoservice_stop(chan); 00330 00331 /* if this is a dialplan function then use ast_func_read(), otherwise 00332 * use pbx_retrieve_variable() */ 00333 if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') { 00334 value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace; 00335 } else { 00336 pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan)); 00337 } 00338 00339 if (autoservice) 00340 ast_autoservice_start(chan); 00341 00342 if (value) { 00343 lua_pushstring(L, value); 00344 } else { 00345 lua_pushnil(L); 00346 } 00347 00348 return 1; 00349 }
| static int lua_load_extensions | ( | lua_State * | L, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Load the extensions.lua file from the internal buffer.
| L | the lua_State to use | |
| chan | channel to work on |
| 0 | success | |
| 1 | failure |
Definition at line 1154 of file pbx_lua.c.
References ast_mutex_lock, ast_mutex_unlock, config_file_lock, lua_create_app_table(), lua_create_application_metatable(), lua_create_autoservice_functions(), lua_create_channel_table(), lua_create_hangup_function(), lua_create_variable_metatable(), and lua_sort_extensions().
Referenced by lua_get_state().
01155 { 01156 01157 /* store a pointer to this channel */ 01158 lua_pushlightuserdata(L, chan); 01159 lua_setfield(L, LUA_REGISTRYINDEX, "channel"); 01160 01161 luaL_openlibs(L); 01162 01163 /* load and sort extensions */ 01164 ast_mutex_lock(&config_file_lock); 01165 if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua") 01166 || lua_pcall(L, 0, LUA_MULTRET, 0) 01167 || lua_sort_extensions(L)) { 01168 ast_mutex_unlock(&config_file_lock); 01169 return 1; 01170 } 01171 ast_mutex_unlock(&config_file_lock); 01172 01173 /* now we setup special tables and functions */ 01174 01175 lua_create_app_table(L); 01176 lua_create_channel_table(L); 01177 01178 lua_create_variable_metatable(L); 01179 lua_create_application_metatable(L); 01180 01181 lua_create_autoservice_functions(L); 01182 lua_create_hangup_function(L); 01183 01184 return 0; 01185 }
| static int lua_pbx_exec | ( | lua_State * | L | ) | [static] |
[lua_CFunction] This function is part of the 'application' metatable and is used to execute applications similar to pbx_exec() (for access from lua, don't call directly)
| L | the lua_State to use |
app.playback('demo-congrats')
Definition at line 188 of file pbx_lua.c.
References app, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_context(), ast_channel_exten(), ast_channel_name(), ast_channel_priority(), ast_debug, ast_strdupa, ast_verb, COLOR_BRCYAN, COLOR_BRMAGENTA, context, exten, lua_concat_args(), LUA_EXT_DATA_SIZE, LUA_GOTO_DETECTED, lua_update_registry(), pbx_exec(), pbx_findapp(), and term_color().
Referenced by lua_create_application_metatable().
00189 { 00190 int res, nargs = lua_gettop(L); 00191 const char *data = ""; 00192 char *app_name, *context, *exten; 00193 char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE]; 00194 int priority, autoservice; 00195 struct ast_app *app; 00196 struct ast_channel *chan; 00197 00198 lua_getfield(L, 1, "name"); 00199 app_name = ast_strdupa(lua_tostring(L, -1)); 00200 lua_pop(L, 1); 00201 00202 if (!(app = pbx_findapp(app_name))) { 00203 lua_pushstring(L, "application '"); 00204 lua_pushstring(L, app_name); 00205 lua_pushstring(L, "' not found"); 00206 lua_concat(L, 3); 00207 return lua_error(L); 00208 } 00209 00210 00211 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00212 chan = lua_touserdata(L, -1); 00213 lua_pop(L, 1); 00214 00215 context = ast_strdupa(ast_channel_context(chan)); 00216 exten = ast_strdupa(ast_channel_exten(chan)); 00217 priority = ast_channel_priority(chan); 00218 00219 lua_concat_args(L, 2, nargs); 00220 data = lua_tostring(L, -1); 00221 00222 ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n", 00223 exten, context, priority, 00224 term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)), 00225 term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)), 00226 term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3))); 00227 00228 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00229 autoservice = lua_toboolean(L, -1); 00230 lua_pop(L, 1); 00231 00232 if (autoservice) 00233 ast_autoservice_stop(chan); 00234 00235 res = pbx_exec(chan, app, data); 00236 00237 lua_pop(L, 1); /* pop data */ 00238 data = ""; 00239 00240 if (autoservice) 00241 ast_autoservice_start(chan); 00242 00243 /* error executing an application, report it */ 00244 if (res) { 00245 lua_pushinteger(L, res); 00246 return lua_error(L); 00247 } 00248 00249 if (strcmp(context, ast_channel_context(chan))) { 00250 lua_pushstring(L, context); 00251 lua_pushstring(L, ast_channel_context(chan)); 00252 lua_pushliteral(L, "context"); 00253 } else if (strcmp(exten, ast_channel_exten(chan))) { 00254 lua_pushstring(L, exten); 00255 lua_pushstring(L, ast_channel_exten(chan)); 00256 lua_pushliteral(L, "exten"); 00257 } else if (priority != ast_channel_priority(chan)) { 00258 lua_pushinteger(L, priority); 00259 lua_pushinteger(L, ast_channel_priority(chan)); 00260 lua_pushliteral(L, "priority"); 00261 } else { 00262 /* no goto - restore the original position back 00263 * to lua state, in case this was a recursive dialplan 00264 * call (a dialplan application re-entering dialplan) */ 00265 lua_update_registry(L, context, exten, priority); 00266 return 0; 00267 } 00268 00269 /* goto detected - construct error message */ 00270 lua_insert(L, -3); 00271 00272 lua_pushliteral(L, " changed from "); 00273 lua_insert(L, -3); 00274 00275 lua_pushliteral(L, " to "); 00276 lua_insert(L, -2); 00277 00278 lua_concat(L, 5); 00279 00280 ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1)); 00281 lua_pop(L, 1); 00282 00283 /* let the lua engine know it needs to return control to the pbx */ 00284 lua_pushinteger(L, LUA_GOTO_DETECTED); 00285 lua_error(L); 00286 00287 return 0; 00288 }
| static int lua_pbx_findapp | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Find an app and return it in a lua table (for access from lua, don't call directly)
This function would be called in the following example as it would be found in extensions.lua.
app.dial
Definition at line 157 of file pbx_lua.c.
Referenced by lua_create_app_table().
00158 { 00159 const char *app_name = luaL_checkstring(L, 2); 00160 00161 lua_newtable(L); 00162 00163 lua_pushstring(L, "name"); 00164 lua_pushstring(L, app_name); 00165 lua_settable(L, -3); 00166 00167 luaL_getmetatable(L, "application"); 00168 lua_setmetatable(L, -2); 00169 00170 return 1; 00171 }
| static void lua_push_variable_table | ( | lua_State * | L | ) | [static] |
Push a 'variable' table on the stack for access the channel variable with the given name.
The value on the top of the stack is popped and used as the name.
| L | the lua_State to use |
Definition at line 426 of file pbx_lua.c.
References lua_get_variable_value(), and lua_set_variable_value().
Referenced by lua_func_read(), and lua_get_variable().
00427 { 00428 lua_newtable(L); 00429 luaL_getmetatable(L, "variable"); 00430 lua_setmetatable(L, -2); 00431 00432 lua_insert(L, -2); /* move the table after the name */ 00433 lua_setfield(L, -2, "name"); 00434 00435 lua_pushcfunction(L, &lua_get_variable_value); 00436 lua_setfield(L, -2, "get"); 00437 00438 lua_pushcfunction(L, &lua_set_variable_value); 00439 lua_setfield(L, -2, "set"); 00440 }
| static char * lua_read_extensions_file | ( | lua_State * | L, | |
| long * | size | |||
| ) | [static] |
Load the extensions.lua file in to a buffer and execute the file.
| L | the lua_State to use | |
| size | a pointer to store the size of the buffer |
Definition at line 1077 of file pbx_lua.c.
References ast_alloca, ast_config_AST_CONFIG_DIR, ast_free, ast_malloc, errno, f, lua_error_function(), lua_register_hints(), lua_register_switches(), and lua_sort_extensions().
Referenced by lua_reload_extensions().
01078 { 01079 FILE *f; 01080 int error_func; 01081 char *data; 01082 char *path = ast_alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); 01083 sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config); 01084 01085 if (!(f = fopen(path, "r"))) { 01086 lua_pushstring(L, "cannot open '"); 01087 lua_pushstring(L, path); 01088 lua_pushstring(L, "' for reading: "); 01089 lua_pushstring(L, strerror(errno)); 01090 lua_concat(L, 4); 01091 01092 return NULL; 01093 } 01094 01095 if (fseek(f, 0l, SEEK_END)) { 01096 fclose(f); 01097 lua_pushliteral(L, "error determining the size of the config file"); 01098 return NULL; 01099 } 01100 01101 *size = ftell(f); 01102 01103 if (fseek(f, 0l, SEEK_SET)) { 01104 *size = 0; 01105 fclose(f); 01106 lua_pushliteral(L, "error reading config file"); 01107 return NULL; 01108 } 01109 01110 if (!(data = ast_malloc(*size))) { 01111 *size = 0; 01112 fclose(f); 01113 lua_pushstring(L, "not enough memory"); 01114 return NULL; 01115 } 01116 01117 if (fread(data, sizeof(char), *size, f) != *size) { 01118 *size = 0; 01119 fclose(f); 01120 lua_pushliteral(L, "problem reading configuration file"); 01121 return NULL; 01122 } 01123 fclose(f); 01124 01125 lua_pushcfunction(L, &lua_error_function); 01126 error_func = lua_gettop(L); 01127 01128 if (luaL_loadbuffer(L, data, *size, "extensions.lua") 01129 || lua_pcall(L, 0, LUA_MULTRET, error_func) 01130 || lua_sort_extensions(L) 01131 || lua_register_switches(L) 01132 || lua_register_hints(L)) { 01133 ast_free(data); 01134 data = NULL; 01135 *size = 0; 01136 } 01137 01138 lua_remove(L, error_func); 01139 return data; 01140 }
| static int lua_register_hints | ( | lua_State * | L | ) | [static] |
Register dialplan hints for our pbx_lua contexs.
In the event of an error, an error string will be pushed onto the lua stack.
| 0 | success | |
| 1 | failure |
Definition at line 974 of file pbx_lua.c.
References ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), context, hints, and PRIORITY_HINT.
Referenced by lua_read_extensions_file().
00975 { 00976 int hints; 00977 struct ast_context *con = NULL; 00978 00979 /* create the hash table for our contexts */ 00980 /* XXX do we ever need to destroy this? pbx_config does not */ 00981 if (!local_table) 00982 local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); 00983 00984 /* load the 'hints' table */ 00985 lua_getglobal(L, "hints"); 00986 hints = lua_gettop(L); 00987 if (lua_isnil(L, -1)) { 00988 /* hints table not found, move along */ 00989 lua_pop(L, 1); 00990 return 0; 00991 } 00992 00993 /* iterate through the hints table and register each context and 00994 * the hints that go along with it 00995 */ 00996 for (lua_pushnil(L); lua_next(L, hints); lua_pop(L, 1)) { 00997 int context = lua_gettop(L); 00998 int context_name = context - 1; 00999 const char *context_str = lua_tostring(L, context_name); 01000 01001 /* find or create this context */ 01002 con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar); 01003 if (!con) { 01004 /* remove hints table and context key and value */ 01005 lua_pop(L, 3); 01006 lua_pushstring(L, "Failed to find or create context\n"); 01007 return 1; 01008 } 01009 01010 /* register each hint */ 01011 for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) { 01012 const char *hint_value = lua_tostring(L, -1); 01013 const char *hint_name; 01014 01015 /* the hint value is not a string, ignore it */ 01016 if (!hint_value) { 01017 continue; 01018 } 01019 01020 /* copy the name then convert it to a string */ 01021 lua_pushvalue(L, -2); 01022 if (!(hint_name = lua_tostring(L, -1))) { 01023 /* ignore non-string value */ 01024 lua_pop(L, 1); 01025 continue; 01026 } 01027 01028 if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar)) { 01029 /* remove hints table, hint name, hint value, 01030 * key copy, context name, and contex table */ 01031 lua_pop(L, 6); 01032 lua_pushstring(L, "Error creating hint\n"); 01033 return 1; 01034 } 01035 01036 /* pop the name copy */ 01037 lua_pop(L, 1); 01038 } 01039 } 01040 01041 /* remove the hints table */ 01042 lua_pop(L, 1); 01043 01044 return 0; 01045 }
| static int lua_register_switches | ( | lua_State * | L | ) | [static] |
Register dialplan switches for our pbx_lua contexs.
In the event of an error, an error string will be pushed onto the lua stack.
| 0 | success | |
| 1 | failure |
Definition at line 916 of file pbx_lua.c.
References ast_context_add_switch2(), ast_context_find_or_create(), ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), and context.
Referenced by lua_read_extensions_file().
00917 { 00918 int extensions; 00919 struct ast_context *con = NULL; 00920 00921 /* create the hash table for our contexts */ 00922 /* XXX do we ever need to destroy this? pbx_config does not */ 00923 if (!local_table) 00924 local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); 00925 00926 /* load the 'extensions' table */ 00927 lua_getglobal(L, "extensions"); 00928 extensions = lua_gettop(L); 00929 if (lua_isnil(L, -1)) { 00930 lua_pop(L, 1); 00931 lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n"); 00932 return 1; 00933 } 00934 00935 /* iterate through the extensions table and register a context and 00936 * dialplan switch for each lua context 00937 */ 00938 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) { 00939 int context = lua_gettop(L); 00940 int context_name = context - 1; 00941 const char *context_str = lua_tostring(L, context_name); 00942 00943 /* find or create this context */ 00944 con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar); 00945 if (!con) { 00946 /* remove extensions table and context key and value */ 00947 lua_pop(L, 3); 00948 lua_pushstring(L, "Failed to find or create context\n"); 00949 return 1; 00950 } 00951 00952 /* register the switch */ 00953 if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) { 00954 /* remove extensions table and context key and value */ 00955 lua_pop(L, 3); 00956 lua_pushstring(L, "Unable to create switch for context\n"); 00957 return 1; 00958 } 00959 } 00960 00961 /* remove the extensions table */ 00962 lua_pop(L, 1); 00963 return 0; 00964 }
| static int lua_reload_extensions | ( | lua_State * | L | ) | [static] |
Reload the extensions file and update the internal buffers if it loads correctly.
| L | the lua_State to use (must be freshly allocated with luaL_newstate(), don't use lua_get_state()) |
Definition at line 1197 of file pbx_lua.c.
References ast_free, ast_merge_contexts_and_delete(), ast_mutex_lock, ast_mutex_unlock, config_file_lock, and lua_read_extensions_file().
Referenced by load_or_reload_lua_stuff().
01198 { 01199 long size = 0; 01200 char *data = NULL; 01201 01202 luaL_openlibs(L); 01203 01204 if (!(data = lua_read_extensions_file(L, &size))) { 01205 return 1; 01206 } 01207 01208 ast_mutex_lock(&config_file_lock); 01209 01210 if (config_file_data) 01211 ast_free(config_file_data); 01212 01213 config_file_data = data; 01214 config_file_size = size; 01215 01216 /* merge our new contexts */ 01217 ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); 01218 /* merge_contexts_and_delete will actually, at the correct moment, 01219 set the global dialplan pointers to your local_contexts and local_table. 01220 It then will free up the old tables itself. Just be sure not to 01221 hang onto the pointers. */ 01222 local_table = NULL; 01223 local_contexts = NULL; 01224 01225 ast_mutex_unlock(&config_file_lock); 01226 return 0; 01227 }
| static int lua_set_variable | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Set the value of a channel variable or dialplan function (for access from lua, don't call directly)
This function is called to set a variable or dialplan function. It would be called in the following example as would be seen in extensions.lua.
channel.variable = "value"
Definition at line 598 of file pbx_lua.c.
References ast_autoservice_start(), ast_autoservice_stop(), name, pbx_builtin_setvar_helper(), and value.
Referenced by lua_create_channel_table().
00599 { 00600 struct ast_channel *chan; 00601 int autoservice; 00602 const char *name = luaL_checkstring(L, 2); 00603 const char *value = luaL_checkstring(L, 3); 00604 00605 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00606 chan = lua_touserdata(L, -1); 00607 lua_pop(L, 1); 00608 00609 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00610 autoservice = lua_toboolean(L, -1); 00611 lua_pop(L, 1); 00612 00613 if (autoservice) 00614 ast_autoservice_stop(chan); 00615 00616 pbx_builtin_setvar_helper(chan, name, value); 00617 00618 if (autoservice) 00619 ast_autoservice_start(chan); 00620 00621 return 0; 00622 }
| static int lua_set_variable_value | ( | lua_State * | L | ) | [static] |
[lua_CFunction] Used to set the value of a variable or dialplan function (for access from lua, don't call directly)
This function is the 'set()' function in the following example as would be seen in extensions.lua.
channel.variable:set("value")
Definition at line 362 of file pbx_lua.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_strdupa, name, pbx_builtin_setvar_helper(), and value.
Referenced by lua_push_variable_table().
00363 { 00364 const char *name, *value; 00365 struct ast_channel *chan; 00366 int autoservice; 00367 00368 if (!lua_istable(L, 1)) { 00369 lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable"); 00370 return lua_error(L); 00371 } 00372 00373 lua_getfield(L, 1, "name"); 00374 name = ast_strdupa(lua_tostring(L, -1)); 00375 lua_pop(L, 1); 00376 00377 value = luaL_checkstring(L, 2); 00378 00379 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00380 chan = lua_touserdata(L, -1); 00381 lua_pop(L, 1); 00382 00383 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00384 autoservice = lua_toboolean(L, -1); 00385 lua_pop(L, 1); 00386 00387 if (autoservice) 00388 ast_autoservice_stop(chan); 00389 00390 pbx_builtin_setvar_helper(chan, name, value); 00391 00392 if (autoservice) 00393 ast_autoservice_start(chan); 00394 00395 return 0; 00396 }
| static int lua_sort_extensions | ( | lua_State * | L | ) | [static] |
Store the sort order of each context.
In the event of an error, an error string will be pushed onto the lua stack.
| 0 | success | |
| 1 | failure |
Definition at line 834 of file pbx_lua.c.
References context, exten, and lua_extension_cmp().
Referenced by lua_load_extensions(), and lua_read_extensions_file().
00835 { 00836 int extensions, extensions_order; 00837 00838 /* create the extensions_order table */ 00839 lua_newtable(L); 00840 lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order"); 00841 lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order"); 00842 extensions_order = lua_gettop(L); 00843 00844 /* sort each context in the extensions table */ 00845 /* load the 'extensions' table */ 00846 lua_getglobal(L, "extensions"); 00847 extensions = lua_gettop(L); 00848 if (lua_isnil(L, -1)) { 00849 lua_pop(L, 1); 00850 lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n"); 00851 return 1; 00852 } 00853 00854 /* iterate through the extensions table and create a 00855 * matching table (holding the sort order) in the 00856 * extensions_order table for each context that is found 00857 */ 00858 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) { 00859 int context = lua_gettop(L); 00860 int context_name = context - 1; 00861 int context_order; 00862 00863 /* copy the context_name to be used as the key for the 00864 * context_order table in the extensions_order table later */ 00865 lua_pushvalue(L, context_name); 00866 00867 /* create the context_order table */ 00868 lua_newtable(L); 00869 context_order = lua_gettop(L); 00870 00871 /* iterate through this context an popluate the corrisponding 00872 * table in the extensions_order table */ 00873 for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) { 00874 int exten = lua_gettop(L) - 1; 00875 00876 lua_pushinteger(L, lua_objlen(L, context_order) + 1); 00877 lua_pushvalue(L, exten); 00878 lua_settable(L, context_order); 00879 } 00880 lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */ 00881 00882 /* now sort the new table */ 00883 00884 /* push the table.sort function */ 00885 lua_getglobal(L, "table"); 00886 lua_getfield(L, -1, "sort"); 00887 lua_remove(L, -2); /* remove the 'table' table */ 00888 00889 /* push the context_order table */ 00890 lua_pushvalue(L, context_name); 00891 lua_gettable(L, extensions_order); 00892 00893 /* push the comp function */ 00894 lua_pushcfunction(L, &lua_extension_cmp); 00895 00896 if (lua_pcall(L, 2, 0, 0)) { 00897 lua_insert(L, -5); 00898 lua_pop(L, 4); 00899 return 1; 00900 } 00901 } 00902 00903 /* remove the extensions table and the extensions_order table */ 00904 lua_pop(L, 2); 00905 return 0; 00906 }
| static void lua_state_destroy | ( | void * | data | ) | [static] |
| static void lua_update_registry | ( | lua_State * | L, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority | |||
| ) | [static] |
Update the lua registry with the given context, exten, and priority.
| L | the lua_State to use | |
| context | the new context | |
| exten | the new exten | |
| priority | the new priority |
Definition at line 406 of file pbx_lua.c.
Referenced by exec(), and lua_pbx_exec().
00407 { 00408 lua_pushstring(L, context); 00409 lua_setfield(L, LUA_REGISTRYINDEX, "context"); 00410 00411 lua_pushstring(L, exten); 00412 lua_setfield(L, LUA_REGISTRYINDEX, "exten"); 00413 00414 lua_pushinteger(L, priority); 00415 lua_setfield(L, LUA_REGISTRYINDEX, "priority"); 00416 }
| static int matchmore | ( | struct ast_channel * | chan, | |
| const char * | context, | |||
| const char * | exten, | |||
| int | priority, | |||
| const char * | callerid, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 1361 of file pbx_lua.c.
References ast_log(), ast_module_user_add, ast_module_user_remove, LOG_ERROR, lua_find_extension(), and lua_get_state().
Referenced by complete_dpreply(), and lua_find_extension().
01362 { 01363 int res; 01364 lua_State *L; 01365 struct ast_module_user *u = ast_module_user_add(chan); 01366 if (!u) { 01367 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01368 return 0; 01369 } 01370 01371 L = lua_get_state(chan); 01372 if (!L) { 01373 ast_module_user_remove(u); 01374 return 0; 01375 } 01376 01377 res = lua_find_extension(L, context, exten, priority, &matchmore, 0); 01378 01379 if (!chan) lua_close(L); 01380 ast_module_user_remove(u); 01381 return res; 01382 }
| static int reload | ( | void | ) | [static] |
Definition at line 1644 of file pbx_lua.c.
References load_or_reload_lua_stuff().
01645 { 01646 return load_or_reload_lua_stuff(); 01647 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1636 of file pbx_lua.c.
References ast_context_destroy(), ast_unregister_switch(), and lua_free_extensions().
01637 { 01638 ast_context_destroy(NULL, registrar); 01639 ast_unregister_switch(&lua_switch); 01640 lua_free_extensions(); 01641 return 0; 01642 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Lua PBX Switch" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
char* config_file_data = NULL [static] |
ast_mutex_t config_file_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
Definition at line 108 of file pbx_lua.c.
Referenced by lua_free_extensions(), lua_load_extensions(), and lua_reload_extensions().
long config_file_size = 0 [static] |
struct ast_context* local_contexts = NULL [static] |
struct ast_hashtab* local_table = NULL [static] |
struct ast_datastore_info lua_datastore [static] |
Initial value:
{
.type = "lua",
.destroy = lua_state_destroy,
.chan_fixup = lua_datastore_fixup,
}
struct ast_switch lua_switch [static] |
1.5.6