#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 1339 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().
01340 { 01341 int res; 01342 lua_State *L; 01343 struct ast_module_user *u = ast_module_user_add(chan); 01344 if (!u) { 01345 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01346 return 0; 01347 } 01348 01349 L = lua_get_state(chan); 01350 if (!L) { 01351 ast_module_user_remove(u); 01352 return 0; 01353 } 01354 01355 res = lua_find_extension(L, context, exten, priority, &canmatch, 0); 01356 01357 if (!chan) lua_close(L); 01358 ast_module_user_remove(u); 01359 return res; 01360 }
| 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 1386 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().
01387 { 01388 int res, error_func; 01389 lua_State *L; 01390 struct ast_module_user *u = ast_module_user_add(chan); 01391 if (!u) { 01392 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01393 return -1; 01394 } 01395 01396 L = lua_get_state(chan); 01397 if (!L) { 01398 ast_module_user_remove(u); 01399 return -1; 01400 } 01401 01402 lua_pushcfunction(L, &lua_error_function); 01403 error_func = lua_gettop(L); 01404 01405 /* push the extension function onto the stack */ 01406 if (!lua_find_extension(L, context, exten, priority, &exists, 1)) { 01407 lua_pop(L, 1); /* pop the debug function */ 01408 ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context); 01409 if (!chan) lua_close(L); 01410 ast_module_user_remove(u); 01411 return -1; 01412 } 01413 01414 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 01415 if (lua_toboolean(L, -1)) { 01416 ast_autoservice_start(chan); 01417 } 01418 lua_pop(L, 1); 01419 01420 lua_update_registry(L, context, exten, priority); 01421 01422 lua_pushstring(L, context); 01423 lua_pushstring(L, exten); 01424 01425 res = lua_pcall(L, 2, 0, error_func); 01426 if (res) { 01427 if (res == LUA_ERRRUN) { 01428 res = -1; 01429 if (lua_isnumber(L, -1)) { 01430 res = lua_tointeger(L, -1); 01431 01432 if (res == LUA_GOTO_DETECTED) { 01433 res = 0; 01434 } 01435 } else if (lua_isstring(L, -1)) { 01436 const char *error = lua_tostring(L, -1); 01437 ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error); 01438 } 01439 } else if (res == LUA_ERRERR) { 01440 res = -1; 01441 ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n"); 01442 } else if (res == LUA_ERRMEM) { 01443 res = -1; 01444 ast_log(LOG_ERROR, "Memory allocation error\n"); 01445 } 01446 lua_pop(L, 1); 01447 } 01448 lua_remove(L, error_func); 01449 01450 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 01451 if (lua_toboolean(L, -1)) { 01452 ast_autoservice_stop(chan); 01453 } 01454 lua_pop(L, 1); 01455 01456 if (!chan) lua_close(L); 01457 ast_module_user_remove(u); 01458 return res; 01459 }
| 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 1316 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().
01317 { 01318 int res; 01319 lua_State *L; 01320 struct ast_module_user *u = ast_module_user_add(chan); 01321 if (!u) { 01322 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01323 return 0; 01324 } 01325 01326 L = lua_get_state(chan); 01327 if (!L) { 01328 ast_module_user_remove(u); 01329 return 0; 01330 } 01331 01332 res = lua_find_extension(L, context, exten, priority, &exists, 0); 01333 01334 if (!chan) lua_close(L); 01335 ast_module_user_remove(u); 01336 return res; 01337 }
| static int load_module | ( | void | ) | [static] |
Definition at line 1650 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.
01651 { 01652 int res; 01653 01654 if ((res = load_or_reload_lua_stuff())) 01655 return res; 01656 01657 if (ast_register_switch(&lua_switch)) { 01658 ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n"); 01659 return AST_MODULE_LOAD_DECLINE; 01660 } 01661 01662 return AST_MODULE_LOAD_SUCCESS; 01663 }
| static int load_or_reload_lua_stuff | ( | void | ) | [static] |
Definition at line 1617 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().
01618 { 01619 int res = AST_MODULE_LOAD_SUCCESS; 01620 01621 lua_State *L = luaL_newstate(); 01622 if (!L) { 01623 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); 01624 return AST_MODULE_LOAD_DECLINE; 01625 } 01626 01627 if (lua_reload_extensions(L)) { 01628 const char *error = lua_tostring(L, -1); 01629 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error); 01630 res = AST_MODULE_LOAD_DECLINE; 01631 } 01632 01633 lua_close(L); 01634 return res; 01635 }
| 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 698 of file pbx_lua.c.
References ast_autoservice_start().
Referenced by lua_create_autoservice_functions().
00699 { 00700 struct ast_channel *chan; 00701 00702 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00703 if (lua_toboolean(L, -1)) { 00704 /* autservice already running */ 00705 lua_pop(L, 1); 00706 return 0; 00707 } 00708 lua_pop(L, 1); 00709 00710 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00711 chan = lua_touserdata(L, -1); 00712 lua_pop(L, 1); 00713 00714 ast_autoservice_start(chan); 00715 00716 lua_pushboolean(L, 1); 00717 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); 00718 return 0; 00719 }
| 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 763 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 731 of file pbx_lua.c.
References ast_autoservice_stop().
Referenced by lua_create_autoservice_functions().
00732 { 00733 struct ast_channel *chan; 00734 00735 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00736 if (!lua_toboolean(L, -1)) { 00737 /* no autservice running */ 00738 lua_pop(L, 1); 00739 return 0; 00740 } 00741 lua_pop(L, 1); 00742 00743 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00744 chan = lua_touserdata(L, -1); 00745 lua_pop(L, 1); 00746 00747 ast_autoservice_stop(chan); 00748 00749 lua_pushboolean(L, 0); 00750 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); 00751 return 0; 00752 }
| 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 777 of file pbx_lua.c.
References ast_check_hangup().
Referenced by lua_create_hangup_function().
00778 { 00779 struct ast_channel *chan; 00780 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00781 chan = lua_touserdata(L, -1); 00782 lua_pop(L, 1); 00783 00784 lua_pushboolean(L, ast_check_hangup(chan)); 00785 return 1; 00786 }
| 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 634 of file pbx_lua.c.
Referenced by lua_func_read(), and lua_pbx_exec().
00634 { 00635 int concat = 0; 00636 int i = start + 1; 00637 00638 if (start <= nargs && !lua_isnil(L, start)) { 00639 lua_pushvalue(L, start); 00640 concat += 1; 00641 } 00642 00643 for (; i <= nargs; i++) { 00644 if (lua_isnil(L, i)) { 00645 lua_pushliteral(L, ","); 00646 concat += 1; 00647 } else { 00648 lua_pushliteral(L, ","); 00649 lua_pushvalue(L, i); 00650 concat += 2; 00651 } 00652 } 00653 00654 lua_concat(L, concat); 00655 }
| 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 448 of file pbx_lua.c.
References lua_pbx_findapp().
Referenced by lua_load_extensions().
00449 { 00450 lua_newtable(L); 00451 luaL_newmetatable(L, "app"); 00452 00453 lua_pushstring(L, "__index"); 00454 lua_pushcfunction(L, &lua_pbx_findapp); 00455 lua_settable(L, -3); 00456 00457 lua_setmetatable(L, -2); 00458 lua_setglobal(L, "app"); 00459 }
| 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 505 of file pbx_lua.c.
References lua_pbx_exec().
Referenced by lua_load_extensions().
00506 { 00507 luaL_newmetatable(L, "application"); 00508 00509 lua_pushstring(L, "__call"); 00510 lua_pushcfunction(L, &lua_pbx_exec); 00511 lua_settable(L, -3); 00512 00513 lua_pop(L, 1); 00514 }
| static void lua_create_autoservice_functions | ( | lua_State * | L | ) | [static] |
Create the autoservice functions.
| L | the lua_State to use |
Definition at line 521 of file pbx_lua.c.
References lua_autoservice_start(), lua_autoservice_status(), and lua_autoservice_stop().
Referenced by lua_load_extensions().
00522 { 00523 lua_pushcfunction(L, &lua_autoservice_start); 00524 lua_setglobal(L, "autoservice_start"); 00525 00526 lua_pushcfunction(L, &lua_autoservice_stop); 00527 lua_setglobal(L, "autoservice_stop"); 00528 00529 lua_pushcfunction(L, &lua_autoservice_status); 00530 lua_setglobal(L, "autoservice_status"); 00531 00532 lua_pushboolean(L, 1); 00533 lua_setfield(L, LUA_REGISTRYINDEX, "autoservice"); 00534 }
| 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 466 of file pbx_lua.c.
References lua_get_variable(), and lua_set_variable().
Referenced by lua_load_extensions().
00467 { 00468 lua_newtable(L); 00469 luaL_newmetatable(L, "channel_data"); 00470 00471 lua_pushstring(L, "__index"); 00472 lua_pushcfunction(L, &lua_get_variable); 00473 lua_settable(L, -3); 00474 00475 lua_pushstring(L, "__newindex"); 00476 lua_pushcfunction(L, &lua_set_variable); 00477 lua_settable(L, -3); 00478 00479 lua_setmetatable(L, -2); 00480 lua_setglobal(L, "channel"); 00481 }
| static void lua_create_hangup_function | ( | lua_State * | L | ) | [static] |
Create the hangup check function.
| L | the lua_State to use |
Definition at line 541 of file pbx_lua.c.
References lua_check_hangup().
Referenced by lua_load_extensions().
00542 { 00543 lua_pushcfunction(L, &lua_check_hangup); 00544 lua_setglobal(L, "check_hangup"); 00545 }
| 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 488 of file pbx_lua.c.
References lua_func_read().
Referenced by lua_load_extensions().
00489 { 00490 luaL_newmetatable(L, "variable"); 00491 00492 lua_pushstring(L, "__call"); 00493 lua_pushcfunction(L, &lua_func_read); 00494 lua_settable(L, -3); 00495 00496 lua_pop(L, 1); 00497 }
| 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 794 of file pbx_lua.c.
Referenced by exec(), and lua_read_extensions_file().
00795 { 00796 int message_index; 00797 00798 /* pass number arguments right through back to asterisk*/ 00799 if (lua_isnumber(L, -1)) { 00800 return 1; 00801 } 00802 00803 /* if we are here then we have a string error message, let's attach a 00804 * backtrace to it */ 00805 message_index = lua_gettop(L); 00806 00807 /* prepare to prepend a new line to the traceback */ 00808 lua_pushliteral(L, "\n"); 00809 00810 lua_getglobal(L, "debug"); 00811 lua_getfield(L, -1, "traceback"); 00812 lua_remove(L, -2); /* remove the 'debug' table */ 00813 00814 lua_pushvalue(L, message_index); 00815 lua_remove(L, message_index); 00816 00817 lua_pushnumber(L, 2); 00818 00819 lua_call(L, 2, 1); 00820 00821 /* prepend the new line we prepared above */ 00822 lua_concat(L, 2); 00823 00824 return 1; 00825 }
| 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 1055 of file pbx_lua.c.
References ast_extension_cmp().
Referenced by lua_sort_extensions().
01056 { 01057 const char *a = luaL_checkstring(L, -2); 01058 const char *b = luaL_checkstring(L, -1); 01059 01060 if (ast_extension_cmp(a, b) == -1) 01061 lua_pushboolean(L, 1); 01062 else 01063 lua_pushboolean(L, 0); 01064 01065 return 1; 01066 }
| 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 1474 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().
01475 { 01476 int context_table, context_order_table, i; 01477 01478 ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority); 01479 if (priority != 1) 01480 return 0; 01481 01482 /* load the 'extensions' table */ 01483 lua_getglobal(L, "extensions"); 01484 if (lua_isnil(L, -1)) { 01485 ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n"); 01486 lua_pop(L, 1); 01487 return 0; 01488 } 01489 01490 /* load the given context */ 01491 lua_getfield(L, -1, context); 01492 if (lua_isnil(L, -1)) { 01493 lua_pop(L, 2); 01494 return 0; 01495 } 01496 01497 /* remove the extensions table */ 01498 lua_remove(L, -2); 01499 01500 context_table = lua_gettop(L); 01501 01502 /* load the extensions order table for this context */ 01503 lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order"); 01504 lua_getfield(L, -1, context); 01505 01506 lua_remove(L, -2); /* remove the extensions order table */ 01507 01508 context_order_table = lua_gettop(L); 01509 01510 /* step through the extensions looking for a match */ 01511 for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) { 01512 int e_index_copy, match = 0; 01513 const char *e; 01514 01515 lua_pushinteger(L, i); 01516 lua_gettable(L, context_order_table); 01517 lua_gettop(L); 01518 01519 /* copy the key at the top of the stack for use later */ 01520 lua_pushvalue(L, -1); 01521 e_index_copy = lua_gettop(L); 01522 01523 if (!(e = lua_tostring(L, e_index_copy))) { 01524 lua_pop(L, 2); 01525 continue; 01526 } 01527 01528 /* make sure this is not the 'include' extension */ 01529 if (!strcasecmp(e, "include")) { 01530 lua_pop(L, 2); 01531 continue; 01532 } 01533 01534 if (func == &matchmore) 01535 match = ast_extension_close(e, exten, E_MATCHMORE); 01536 else if (func == &canmatch) 01537 match = ast_extension_close(e, exten, E_CANMATCH); 01538 else 01539 match = ast_extension_match(e, exten); 01540 01541 /* the extension matching functions return 0 on fail, 1 on 01542 * match, 2 on earlymatch */ 01543 01544 if (!match) { 01545 /* pop the copy and the extension */ 01546 lua_pop(L, 2); 01547 continue; /* keep trying */ 01548 } 01549 01550 if (func == &matchmore && match == 2) { 01551 /* We match an extension ending in '!'. The decision in 01552 * this case is final and counts as no match. */ 01553 lua_pop(L, 4); 01554 return 0; 01555 } 01556 01557 /* remove the context table, the context order table, the 01558 * extension, and the extension copy (or replace the extension 01559 * with the corresponding function) */ 01560 if (push_func) { 01561 lua_pop(L, 1); /* pop the copy */ 01562 lua_gettable(L, context_table); 01563 lua_insert(L, -3); 01564 lua_pop(L, 2); 01565 } else { 01566 lua_pop(L, 4); 01567 } 01568 01569 return 1; 01570 } 01571 01572 /* load the includes for this context */ 01573 lua_getfield(L, context_table, "include"); 01574 if (lua_isnil(L, -1)) { 01575 lua_pop(L, 3); 01576 return 0; 01577 } 01578 01579 /* remove the context and the order table*/ 01580 lua_remove(L, context_order_table); 01581 lua_remove(L, context_table); 01582 01583 /* Now try any includes we have in this context */ 01584 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { 01585 const char *c = lua_tostring(L, -1); 01586 if (!c) 01587 continue; 01588 01589 if (lua_find_extension(L, c, exten, priority, func, push_func)) { 01590 /* remove the value, the key, and the includes table 01591 * from the stack. Leave the function behind if 01592 * necessary */ 01593 01594 if (push_func) 01595 lua_insert(L, -4); 01596 01597 lua_pop(L, 3); 01598 return 1; 01599 } 01600 } 01601 01602 /* pop the includes table */ 01603 lua_pop(L, 1); 01604 return 0; 01605 }
| static void lua_free_extensions | ( | void | ) | [static] |
Free the internal extensions buffer.
Definition at line 1233 of file pbx_lua.c.
References ast_free, ast_mutex_lock, ast_mutex_unlock, and config_file_lock.
Referenced by unload_module().
01234 { 01235 ast_mutex_lock(&config_file_lock); 01236 config_file_size = 0; 01237 ast_free(config_file_data); 01238 ast_mutex_unlock(&config_file_lock); 01239 }
| 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 673 of file pbx_lua.c.
References lua_concat_args(), and lua_push_variable_table().
Referenced by lua_create_variable_metatable().
00674 { 00675 int nargs = lua_gettop(L); 00676 00677 /* build a string in the form of "func_name(arg1,arg2,arg3)" */ 00678 lua_getfield(L, 1, "name"); 00679 lua_pushliteral(L, "("); 00680 lua_concat_args(L, 2, nargs); 00681 lua_pushliteral(L, ")"); 00682 lua_concat(L, 4); 00683 00684 lua_push_variable_table(L); 00685 return 1; 00686 }
| 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 1254 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().
01255 { 01256 struct ast_datastore *datastore = NULL; 01257 lua_State *L; 01258 01259 if (!chan) { 01260 lua_State *L = luaL_newstate(); 01261 if (!L) { 01262 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); 01263 return NULL; 01264 } 01265 01266 if (lua_load_extensions(L, NULL)) { 01267 const char *error = lua_tostring(L, -1); 01268 ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error); 01269 lua_close(L); 01270 return NULL; 01271 } 01272 return L; 01273 } else { 01274 ast_channel_lock(chan); 01275 datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL); 01276 ast_channel_unlock(chan); 01277 01278 if (!datastore) { 01279 /* nothing found, allocate a new lua state */ 01280 datastore = ast_datastore_alloc(&lua_datastore, NULL); 01281 if (!datastore) { 01282 ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n"); 01283 return NULL; 01284 } 01285 01286 datastore->data = luaL_newstate(); 01287 if (!datastore->data) { 01288 ast_datastore_free(datastore); 01289 ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); 01290 return NULL; 01291 } 01292 01293 ast_channel_lock(chan); 01294 ast_channel_datastore_add(chan, datastore); 01295 ast_channel_unlock(chan); 01296 01297 L = datastore->data; 01298 01299 if (lua_load_extensions(L, chan)) { 01300 const char *error = lua_tostring(L, -1); 01301 ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", ast_channel_name(chan), error); 01302 01303 ast_channel_lock(chan); 01304 ast_channel_datastore_remove(chan, datastore); 01305 ast_channel_unlock(chan); 01306 01307 ast_datastore_free(datastore); 01308 return NULL; 01309 } 01310 } 01311 01312 return datastore->data; 01313 } 01314 }
| 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 559 of file pbx_lua.c.
References ast_strlen_zero(), LUA_BUF_SIZE, lua_push_variable_table(), name, pbx_retrieve_variable(), value, and ast_channel::varshead.
Referenced by lua_create_channel_table().
00560 { 00561 struct ast_channel *chan; 00562 const char *name = luaL_checkstring(L, 2); 00563 char *value = NULL; 00564 char *workspace = alloca(LUA_BUF_SIZE); 00565 workspace[0] = '\0'; 00566 00567 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00568 chan = lua_touserdata(L, -1); 00569 lua_pop(L, 1); 00570 00571 lua_pushvalue(L, 2); 00572 lua_push_variable_table(L); 00573 00574 /* if this is not a request for a dialplan funciton attempt to retrieve 00575 * the value of the variable */ 00576 if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') { 00577 pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead); 00578 } 00579 00580 if (value) { 00581 lua_pushstring(L, value); 00582 lua_setfield(L, -2, "value"); 00583 } 00584 00585 return 1; 00586 }
| 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_autoservice_start(), ast_autoservice_stop(), ast_func_read(), ast_strdupa, ast_strlen_zero(), LUA_BUF_SIZE, name, pbx_retrieve_variable(), value, and ast_channel::varshead.
Referenced by lua_push_variable_table().
00303 { 00304 struct ast_channel *chan; 00305 char *value = NULL, *name; 00306 char *workspace = 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, &chan->varshead); 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 1155 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().
01156 { 01157 01158 /* store a pointer to this channel */ 01159 lua_pushlightuserdata(L, chan); 01160 lua_setfield(L, LUA_REGISTRYINDEX, "channel"); 01161 01162 luaL_openlibs(L); 01163 01164 /* load and sort extensions */ 01165 ast_mutex_lock(&config_file_lock); 01166 if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua") 01167 || lua_pcall(L, 0, LUA_MULTRET, 0) 01168 || lua_sort_extensions(L)) { 01169 ast_mutex_unlock(&config_file_lock); 01170 return 1; 01171 } 01172 ast_mutex_unlock(&config_file_lock); 01173 01174 /* now we setup special tables and functions */ 01175 01176 lua_create_app_table(L); 01177 lua_create_channel_table(L); 01178 01179 lua_create_variable_metatable(L); 01180 lua_create_application_metatable(L); 01181 01182 lua_create_autoservice_functions(L); 01183 lua_create_hangup_function(L); 01184 01185 return 0; 01186 }
| 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_name(), ast_debug, ast_strdupa, ast_verb, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, context, ast_channel::exten, exten, lua_concat_args(), LUA_EXT_DATA_SIZE, LUA_GOTO_DETECTED, lua_update_registry(), pbx_exec(), pbx_findapp(), ast_channel::priority, 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(chan->context); 00216 exten = ast_strdupa(chan->exten); 00217 priority = chan->priority; 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, chan->context)) { 00250 lua_pushstring(L, context); 00251 lua_pushstring(L, chan->context); 00252 lua_pushliteral(L, "context"); 00253 } else if (strcmp(exten, chan->exten)) { 00254 lua_pushstring(L, exten); 00255 lua_pushstring(L, chan->exten); 00256 lua_pushliteral(L, "exten"); 00257 } else if (priority != chan->priority) { 00258 lua_pushinteger(L, priority); 00259 lua_pushinteger(L, chan->priority); 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 | |
| name | the name of the variable |
Definition at line 427 of file pbx_lua.c.
References lua_get_variable_value(), and lua_set_variable_value().
Referenced by lua_func_read(), and lua_get_variable().
00428 { 00429 lua_newtable(L); 00430 luaL_getmetatable(L, "variable"); 00431 lua_setmetatable(L, -2); 00432 00433 lua_insert(L, -2); /* move the table after the name */ 00434 lua_setfield(L, -2, "name"); 00435 00436 lua_pushcfunction(L, &lua_get_variable_value); 00437 lua_setfield(L, -2, "get"); 00438 00439 lua_pushcfunction(L, &lua_set_variable_value); 00440 lua_setfield(L, -2, "set"); 00441 }
| 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 1078 of file pbx_lua.c.
References 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().
01079 { 01080 FILE *f; 01081 int error_func; 01082 char *data; 01083 char *path = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); 01084 sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config); 01085 01086 if (!(f = fopen(path, "r"))) { 01087 lua_pushstring(L, "cannot open '"); 01088 lua_pushstring(L, path); 01089 lua_pushstring(L, "' for reading: "); 01090 lua_pushstring(L, strerror(errno)); 01091 lua_concat(L, 4); 01092 01093 return NULL; 01094 } 01095 01096 if (fseek(f, 0l, SEEK_END)) { 01097 fclose(f); 01098 lua_pushliteral(L, "error determining the size of the config file"); 01099 return NULL; 01100 } 01101 01102 *size = ftell(f); 01103 01104 if (fseek(f, 0l, SEEK_SET)) { 01105 *size = 0; 01106 fclose(f); 01107 lua_pushliteral(L, "error reading config file"); 01108 return NULL; 01109 } 01110 01111 if (!(data = ast_malloc(*size))) { 01112 *size = 0; 01113 fclose(f); 01114 lua_pushstring(L, "not enough memory"); 01115 return NULL; 01116 } 01117 01118 if (fread(data, sizeof(char), *size, f) != *size) { 01119 *size = 0; 01120 fclose(f); 01121 lua_pushliteral(L, "problem reading configuration file"); 01122 return NULL; 01123 } 01124 fclose(f); 01125 01126 lua_pushcfunction(L, &lua_error_function); 01127 error_func = lua_gettop(L); 01128 01129 if (luaL_loadbuffer(L, data, *size, "extensions.lua") 01130 || lua_pcall(L, 0, LUA_MULTRET, error_func) 01131 || lua_sort_extensions(L) 01132 || lua_register_switches(L) 01133 || lua_register_hints(L)) { 01134 ast_free(data); 01135 data = NULL; 01136 *size = 0; 01137 } 01138 01139 lua_remove(L, error_func); 01140 return data; 01141 }
| 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 975 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().
00976 { 00977 int hints; 00978 struct ast_context *con = NULL; 00979 00980 /* create the hash table for our contexts */ 00981 /* XXX do we ever need to destroy this? pbx_config does not */ 00982 if (!local_table) 00983 local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); 00984 00985 /* load the 'hints' table */ 00986 lua_getglobal(L, "hints"); 00987 hints = lua_gettop(L); 00988 if (lua_isnil(L, -1)) { 00989 /* hints table not found, move along */ 00990 lua_pop(L, 1); 00991 return 0; 00992 } 00993 00994 /* iterate through the hints table and register each context and 00995 * the hints that go along with it 00996 */ 00997 for (lua_pushnil(L); lua_next(L, hints); lua_pop(L, 1)) { 00998 int context = lua_gettop(L); 00999 int context_name = context - 1; 01000 const char *context_str = lua_tostring(L, context_name); 01001 01002 /* find or create this context */ 01003 con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar); 01004 if (!con) { 01005 /* remove hints table and context key and value */ 01006 lua_pop(L, 3); 01007 lua_pushstring(L, "Failed to find or create context\n"); 01008 return 1; 01009 } 01010 01011 /* register each hint */ 01012 for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) { 01013 const char *hint_value = lua_tostring(L, -1); 01014 const char *hint_name; 01015 01016 /* the hint value is not a string, ignore it */ 01017 if (!hint_value) { 01018 continue; 01019 } 01020 01021 /* copy the name then convert it to a string */ 01022 lua_pushvalue(L, -2); 01023 if (!(hint_name = lua_tostring(L, -1))) { 01024 /* ignore non-string value */ 01025 lua_pop(L, 1); 01026 continue; 01027 } 01028 01029 if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar)) { 01030 /* remove hints table, hint name, hint value, 01031 * key copy, context name, and contex table */ 01032 lua_pop(L, 6); 01033 lua_pushstring(L, "Error creating hint\n"); 01034 return 1; 01035 } 01036 01037 /* pop the name copy */ 01038 lua_pop(L, 1); 01039 } 01040 } 01041 01042 /* remove the hints table */ 01043 lua_pop(L, 1); 01044 01045 return 0; 01046 }
| 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 917 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().
00918 { 00919 int extensions; 00920 struct ast_context *con = NULL; 00921 00922 /* create the hash table for our contexts */ 00923 /* XXX do we ever need to destroy this? pbx_config does not */ 00924 if (!local_table) 00925 local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); 00926 00927 /* load the 'extensions' table */ 00928 lua_getglobal(L, "extensions"); 00929 extensions = lua_gettop(L); 00930 if (lua_isnil(L, -1)) { 00931 lua_pop(L, 1); 00932 lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n"); 00933 return 1; 00934 } 00935 00936 /* iterate through the extensions table and register a context and 00937 * dialplan switch for each lua context 00938 */ 00939 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) { 00940 int context = lua_gettop(L); 00941 int context_name = context - 1; 00942 const char *context_str = lua_tostring(L, context_name); 00943 00944 /* find or create this context */ 00945 con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar); 00946 if (!con) { 00947 /* remove extensions table and context key and value */ 00948 lua_pop(L, 3); 00949 lua_pushstring(L, "Failed to find or create context\n"); 00950 return 1; 00951 } 00952 00953 /* register the switch */ 00954 if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) { 00955 /* remove extensions table and context key and value */ 00956 lua_pop(L, 3); 00957 lua_pushstring(L, "Unable to create switch for context\n"); 00958 return 1; 00959 } 00960 } 00961 00962 /* remove the extensions table */ 00963 lua_pop(L, 1); 00964 return 0; 00965 }
| 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 1198 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().
01199 { 01200 long size = 0; 01201 char *data = NULL; 01202 01203 luaL_openlibs(L); 01204 01205 if (!(data = lua_read_extensions_file(L, &size))) { 01206 return 1; 01207 } 01208 01209 ast_mutex_lock(&config_file_lock); 01210 01211 if (config_file_data) 01212 ast_free(config_file_data); 01213 01214 config_file_data = data; 01215 config_file_size = size; 01216 01217 /* merge our new contexts */ 01218 ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); 01219 /* merge_contexts_and_delete will actually, at the correct moment, 01220 set the global dialplan pointers to your local_contexts and local_table. 01221 It then will free up the old tables itself. Just be sure not to 01222 hang onto the pointers. */ 01223 local_table = NULL; 01224 local_contexts = NULL; 01225 01226 ast_mutex_unlock(&config_file_lock); 01227 return 0; 01228 }
| 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 599 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().
00600 { 00601 struct ast_channel *chan; 00602 int autoservice; 00603 const char *name = luaL_checkstring(L, 2); 00604 const char *value = luaL_checkstring(L, 3); 00605 00606 lua_getfield(L, LUA_REGISTRYINDEX, "channel"); 00607 chan = lua_touserdata(L, -1); 00608 lua_pop(L, 1); 00609 00610 lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); 00611 autoservice = lua_toboolean(L, -1); 00612 lua_pop(L, 1); 00613 00614 if (autoservice) 00615 ast_autoservice_stop(chan); 00616 00617 pbx_builtin_setvar_helper(chan, name, value); 00618 00619 if (autoservice) 00620 ast_autoservice_start(chan); 00621 00622 return 0; 00623 }
| 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 835 of file pbx_lua.c.
References context, exten, and lua_extension_cmp().
Referenced by lua_load_extensions(), and lua_read_extensions_file().
00836 { 00837 int extensions, extensions_order; 00838 00839 /* create the extensions_order table */ 00840 lua_newtable(L); 00841 lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order"); 00842 lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order"); 00843 extensions_order = lua_gettop(L); 00844 00845 /* sort each context in the extensions table */ 00846 /* load the 'extensions' table */ 00847 lua_getglobal(L, "extensions"); 00848 extensions = lua_gettop(L); 00849 if (lua_isnil(L, -1)) { 00850 lua_pop(L, 1); 00851 lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n"); 00852 return 1; 00853 } 00854 00855 /* iterate through the extensions table and create a 00856 * matching table (holding the sort order) in the 00857 * extensions_order table for each context that is found 00858 */ 00859 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) { 00860 int context = lua_gettop(L); 00861 int context_name = context - 1; 00862 int context_order; 00863 00864 /* copy the context_name to be used as the key for the 00865 * context_order table in the extensions_order table later */ 00866 lua_pushvalue(L, context_name); 00867 00868 /* create the context_order table */ 00869 lua_newtable(L); 00870 context_order = lua_gettop(L); 00871 00872 /* iterate through this context an popluate the corrisponding 00873 * table in the extensions_order table */ 00874 for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) { 00875 int exten = lua_gettop(L) - 1; 00876 00877 lua_pushinteger(L, lua_objlen(L, context_order) + 1); 00878 lua_pushvalue(L, exten); 00879 lua_settable(L, context_order); 00880 } 00881 lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */ 00882 00883 /* now sort the new table */ 00884 00885 /* push the table.sort function */ 00886 lua_getglobal(L, "table"); 00887 lua_getfield(L, -1, "sort"); 00888 lua_remove(L, -2); /* remove the 'table' table */ 00889 00890 /* push the context_order table */ 00891 lua_pushvalue(L, context_name); 00892 lua_gettable(L, extensions_order); 00893 00894 /* push the comp function */ 00895 lua_pushcfunction(L, &lua_extension_cmp); 00896 00897 if (lua_pcall(L, 2, 0, 0)) { 00898 lua_insert(L, -5); 00899 lua_pop(L, 4); 00900 return 1; 00901 } 00902 } 00903 00904 /* remove the extensions table and the extensions_order table */ 00905 lua_pop(L, 2); 00906 return 0; 00907 }
| 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 1362 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().
01363 { 01364 int res; 01365 lua_State *L; 01366 struct ast_module_user *u = ast_module_user_add(chan); 01367 if (!u) { 01368 ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n"); 01369 return 0; 01370 } 01371 01372 L = lua_get_state(chan); 01373 if (!L) { 01374 ast_module_user_remove(u); 01375 return 0; 01376 } 01377 01378 res = lua_find_extension(L, context, exten, priority, &matchmore, 0); 01379 01380 if (!chan) lua_close(L); 01381 ast_module_user_remove(u); 01382 return res; 01383 }
| static int reload | ( | void | ) | [static] |
Definition at line 1645 of file pbx_lua.c.
References load_or_reload_lua_stuff().
01646 { 01647 return load_or_reload_lua_stuff(); 01648 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 1637 of file pbx_lua.c.
References ast_context_destroy(), ast_unregister_switch(), and lua_free_extensions().
01638 { 01639 ast_context_destroy(NULL, registrar); 01640 ast_unregister_switch(&lua_switch); 01641 lua_free_extensions(); 01642 return 0; 01643 }
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