48static const char *
config =
"extensions.lua";
52#define LUA_EXT_DATA_SIZE 256
54#define LUA_EXT_DATA_SIZE 8192
56#define LUA_BUF_SIZE 4096
61#define LUA_GOTO_DETECTED 5
140 lua_pushlightuserdata(L, new_chan);
141 lua_setfield(L, LUA_REGISTRYINDEX,
"channel");
157 const char *
app_name = luaL_checkstring(L, 2);
161 lua_pushstring(L,
"name");
165 luaL_getmetatable(L,
"application");
166 lua_setmetatable(L, -2);
189 int res, nargs = lua_gettop(L);
190 const char *data =
"";
197 lua_getfield(L, 1,
"name");
202 lua_pushstring(L,
"application '");
204 lua_pushstring(L,
"' not found");
210 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
211 chan = lua_touserdata(L, -1);
219 data = lua_tostring(L, -1);
221 ast_verb(3,
"Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
227 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
228 autoservice = lua_toboolean(L, -1);
244 lua_pushinteger(L, res);
251 lua_pushliteral(L,
"context");
253 lua_pushstring(L,
exten);
255 lua_pushliteral(L,
"exten");
259 lua_pushliteral(L,
"priority");
271 lua_pushliteral(L,
" changed from ");
274 lua_pushliteral(L,
" to ");
279 ast_debug(2,
"Goto detected: %s\n", lua_tostring(L, -1));
312 if (!lua_istable(L, 1)) {
313 lua_pushstring(L,
"User probably used '.' instead of ':' for retrieving a channel variable value");
317 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
318 chan = lua_touserdata(L, -1);
321 lua_getfield(L, 1,
"name");
325 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
326 autoservice = lua_toboolean(L, -1);
344 lua_pushstring(L,
value);
371 if (!lua_istable(L, 1)) {
372 lua_pushstring(L,
"User probably used '.' instead of ':' for setting a channel variable");
376 lua_getfield(L, 1,
"name");
380 value = luaL_checkstring(L, 2);
382 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
383 chan = lua_touserdata(L, -1);
386 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
387 autoservice = lua_toboolean(L, -1);
412 lua_setfield(L, LUA_REGISTRYINDEX,
"context");
414 lua_pushstring(L,
exten);
415 lua_setfield(L, LUA_REGISTRYINDEX,
"exten");
418 lua_setfield(L, LUA_REGISTRYINDEX,
"priority");
432 luaL_getmetatable(L,
"variable");
433 lua_setmetatable(L, -2);
436 lua_setfield(L, -2,
"name");
439 lua_setfield(L, -2,
"get");
442 lua_setfield(L, -2,
"set");
453 luaL_newmetatable(L,
"app");
455 lua_pushstring(L,
"__index");
459 lua_setmetatable(L, -2);
460 lua_setglobal(L,
"app");
471 luaL_newmetatable(L,
"channel_data");
473 lua_pushstring(L,
"__index");
477 lua_pushstring(L,
"__newindex");
481 lua_setmetatable(L, -2);
482 lua_setglobal(L,
"channel");
492 luaL_newmetatable(L,
"variable");
494 lua_pushstring(L,
"__call");
509 luaL_newmetatable(L,
"application");
511 lua_pushstring(L,
"__call");
526 lua_setglobal(L,
"autoservice_start");
529 lua_setglobal(L,
"autoservice_stop");
532 lua_setglobal(L,
"autoservice_status");
534 lua_pushboolean(L, 1);
535 lua_setfield(L, LUA_REGISTRYINDEX,
"autoservice");
546 lua_setglobal(L,
"check_hangup");
564 const char *
name = luaL_checkstring(L, 2);
569 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
570 chan = lua_touserdata(L, -1);
583 lua_pushstring(L,
value);
584 lua_setfield(L, -2,
"value");
605 const char *
name = luaL_checkstring(L, 2);
606 const char *
value = luaL_checkstring(L, 3);
608 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
609 chan = lua_touserdata(L, -1);
612 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
613 autoservice = lua_toboolean(L, -1);
640 if (start <= nargs && !lua_isnil(L, start)) {
641 lua_pushvalue(L, start);
645 for (; i <= nargs; i++) {
646 if (lua_isnil(L, i)) {
647 lua_pushliteral(L,
",");
650 lua_pushliteral(L,
",");
656 lua_concat(L, concat);
677 int nargs = lua_gettop(L);
680 lua_getfield(L, 1,
"name");
681 lua_pushliteral(L,
"(");
683 lua_pushliteral(L,
")");
704 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
705 if (lua_toboolean(L, -1)) {
712 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
713 chan = lua_touserdata(L, -1);
718 lua_pushboolean(L, 1);
719 lua_setfield(L, LUA_REGISTRYINDEX,
"autoservice");
737 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
738 if (!lua_toboolean(L, -1)) {
745 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
746 chan = lua_touserdata(L, -1);
751 lua_pushboolean(L, 0);
752 lua_setfield(L, LUA_REGISTRYINDEX,
"autoservice");
767 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
782 lua_getfield(L, LUA_REGISTRYINDEX,
"channel");
783 chan = lua_touserdata(L, -1);
801 if (lua_isnumber(L, -1)) {
807 message_index = lua_gettop(L);
810 lua_pushliteral(L,
"\n");
812 lua_getglobal(L,
"debug");
813 if (!lua_istable(L, -1)) {
819 lua_getfield(L, -1,
"traceback");
820 if (!lua_isfunction(L, -1)) {
828 lua_pushvalue(L, message_index);
829 lua_remove(L, message_index);
831 lua_pushnumber(L, 2);
851 int extensions, extensions_order;
855 lua_setfield(L, LUA_REGISTRYINDEX,
"extensions_order");
856 lua_getfield(L, LUA_REGISTRYINDEX,
"extensions_order");
857 extensions_order = lua_gettop(L);
861 lua_getglobal(L,
"extensions");
862 extensions = lua_gettop(L);
863 if (lua_isnil(L, -1)) {
865 lua_pushstring(L,
"Unable to find 'extensions' table in extensions.lua\n");
873 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
884 context_order = lua_gettop(L);
888 for (lua_pushnil(L); lua_next(L,
context); lua_pop(L, 1)) {
889 int exten = lua_gettop(L) - 1;
890#if LUA_VERSION_NUM < 502
891 lua_pushinteger(L, lua_objlen(L, context_order) + 1);
893 lua_pushinteger(L, lua_rawlen(L, context_order) + 1);
895 lua_pushvalue(L,
exten);
896 lua_settable(L, context_order);
898 lua_settable(L, extensions_order);
903 lua_getglobal(L,
"table");
904 lua_getfield(L, -1,
"sort");
909 lua_gettable(L, extensions_order);
914 if (lua_pcall(L, 2, 0, 0)) {
945 lua_getglobal(L,
"extensions");
946 extensions = lua_gettop(L);
947 if (lua_isnil(L, -1)) {
949 lua_pushstring(L,
"Unable to find 'extensions' table in extensions.lua\n");
956 for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
959 const char *context_str = lua_tostring(L,
context_name);
966 lua_pushstring(L,
"Failed to find or create context\n");
974 lua_pushstring(L,
"Unable to create switch for context\n");
1003 lua_getglobal(L,
"hints");
1004 hints = lua_gettop(L);
1005 if (lua_isnil(L, -1)) {
1014 for (lua_pushnil(L); lua_next(L,
hints); lua_pop(L, 1)) {
1017 const char *context_str = lua_tostring(L,
context_name);
1024 lua_pushstring(L,
"Failed to find or create context\n");
1029 for (lua_pushnil(L); lua_next(L,
context); lua_pop(L, 1)) {
1030 const char *hint_value = lua_tostring(L, -1);
1031 const char *hint_name;
1039 lua_pushvalue(L, -2);
1040 if (!(hint_name = lua_tostring(L, -1))) {
1046 if (
ast_add_extension2(con, 0, hint_name,
PRIORITY_HINT,
NULL,
NULL, hint_value,
NULL,
NULL,
registrar,
NULL, 0)) {
1050 lua_pushstring(L,
"Error creating hint\n");
1074 const char *
a = luaL_checkstring(L, -2);
1075 const char *
b = luaL_checkstring(L, -1);
1078 lua_pushboolean(L, 1);
1080 lua_pushboolean(L, 0);
1104 if (!(f = fopen(path,
"r"))) {
1105 lua_pushstring(L,
"cannot open '");
1106 lua_pushstring(L, path);
1107 lua_pushstring(L,
"' for reading: ");
1108 lua_pushstring(L, strerror(
errno));
1111 *file_not_openable = 1;
1116 if (fseek(f, 0l, SEEK_END)) {
1118 lua_pushliteral(L,
"error determining the size of the config file");
1124 if (fseek(f, 0l, SEEK_SET)) {
1127 lua_pushliteral(L,
"error reading config file");
1134 lua_pushstring(L,
"not enough memory");
1138 if (fread(
data,
sizeof(
char), *size, f) != *size) {
1141 lua_pushliteral(L,
"problem reading configuration file");
1147 error_func = lua_gettop(L);
1149 if (luaL_loadbuffer(L,
data, *size,
"extensions.lua")
1150 || lua_pcall(L, 0, LUA_MULTRET, error_func)
1159 lua_remove(L, error_func);
1179 lua_pushlightuserdata(L, chan);
1180 lua_setfield(L, LUA_REGISTRYINDEX,
"channel");
1187 || lua_pcall(L, 0, LUA_MULTRET, 0)
1222 int file_not_openable = 0;
1227 if (file_not_openable) {
1284 L = luaL_newstate();
1291 const char *
error = lua_tostring(L, -1);
1310 datastore->
data = luaL_newstate();
1311 if (!datastore->
data) {
1321 L = datastore->
data;
1324 const char *
error = lua_tostring(L, -1);
1336 return datastore->
data;
1346 ast_log(
LOG_ERROR,
"Error adjusting use count, probably could not allocate memory\n");
1358 if (!
chan) lua_close(L);
1369 ast_log(
LOG_ERROR,
"Error adjusting use count, probably could not allocate memory\n");
1381 if (!
chan) lua_close(L);
1392 ast_log(
LOG_ERROR,
"Error adjusting use count, probably could not allocate memory\n");
1404 if (!
chan) lua_close(L);
1412 int res, error_func;
1416 ast_log(
LOG_ERROR,
"Error adjusting use count, probably could not allocate memory\n");
1427 error_func = lua_gettop(L);
1433 if (!
chan) lua_close(L);
1438 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
1439 if (lua_toboolean(L, -1)) {
1447 lua_pushstring(L, exten);
1449 res = lua_pcall(L, 2, 0, error_func);
1451 if (res == LUA_ERRRUN) {
1453 if (lua_isnumber(L, -1)) {
1454 res = lua_tointeger(L, -1);
1459 }
else if (lua_isstring(L, -1)) {
1460 const char *
error = lua_tostring(L, -1);
1463 }
else if (res == LUA_ERRERR) {
1465 ast_log(
LOG_ERROR,
"Error in the lua error handler (this is probably a bug in pbx_lua)\n");
1466 }
else if (res == LUA_ERRMEM) {
1472 lua_remove(L, error_func);
1474 lua_getfield(L, LUA_REGISTRYINDEX,
"autoservice");
1475 if (lua_toboolean(L, -1)) {
1480 if (!
chan) lua_close(L);
1500 int context_table, context_order_table;
1508 lua_getglobal(L,
"extensions");
1509 if (lua_isnil(L, -1)) {
1510 ast_log(
LOG_ERROR,
"Unable to find 'extensions' table in extensions.lua\n");
1517 if (lua_isnil(L, -1)) {
1525 context_table = lua_gettop(L);
1528 lua_getfield(L, LUA_REGISTRYINDEX,
"extensions_order");
1533 context_order_table = lua_gettop(L);
1536#if LUA_VERSION_NUM < 502
1537 for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
1539 for (i = 1; i < lua_rawlen(L, context_order_table) + 1; i++) {
1541 int e_index_copy,
match = 0;
1544 lua_pushinteger(L, i);
1545 lua_gettable(L, context_order_table);
1549 lua_pushvalue(L, -1);
1550 e_index_copy = lua_gettop(L);
1552 if (!(e = lua_tostring(L, e_index_copy))) {
1558 if (!strcasecmp(e,
"include")) {
1591 lua_gettable(L, context_table);
1602 lua_getfield(L, context_table,
"include");
1603 if (lua_isnil(L, -1)) {
1609 lua_remove(L, context_order_table);
1610 lua_remove(L, context_table);
1613 for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
1614 const char *
c = lua_tostring(L, -1);
1638 .description =
"Lua PBX Switch",
1651 lua_State *L = luaL_newstate();
1659 const char *
error = lua_tostring(L, -1);
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_malloc(len)
A wrapper for malloc()
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define ast_channel_lock(chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Standard Command Line Interface.
#define ast_datastore_alloc(info, uid)
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
static const char context_name[]
Generic (perhaps overly so) hashtable implementation Hash Table support in Asterisk.
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define ast_mutex_unlock(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
#define ast_module_user_remove(user)
@ AST_MODULE_SUPPORT_EXTENDED
#define ast_module_user_add(chan)
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_CONFIG_DIR
static struct ao2_container * hints
Core PBX routines and definitions.
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Add an extension to an extension context, this time with an ast_context *.
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
unsigned int ast_hashtab_hash_contexts(const void *obj)
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
int ast_extension_close(const char *pattern, const char *data, int needmore)
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
int() ast_switch_f(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
int ast_extension_cmp(const char *a, const char *b)
Determine if one extension should match before another.
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
struct ast_app * pbx_findapp(const char *app)
Look up an application.
const char * app_name(struct ast_app *app)
static int lua_error_function(lua_State *L)
[lua_CFunction] Handle lua errors (for access from lua, don't call directly)
static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
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 load_or_reload_lua_stuff(void)
static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static void lua_create_hangup_function(lua_State *L)
Create the hangup check function.
static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static void lua_create_application_metatable(lua_State *L)
Create the 'application' metatable, used to execute asterisk applications from lua.
static struct ast_switch lua_switch
static int lua_set_variable(lua_State *L)
[lua_CFunction] Set the value of a channel variable or dialplan function (for access from lua,...
static void lua_free_extensions(void)
Free the internal extensions buffer.
#define LUA_GOTO_DETECTED
static const struct ast_datastore_info lua_datastore
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,...
static void lua_create_autoservice_functions(lua_State *L)
Create the autoservice functions.
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 int lua_check_hangup(lua_State *L)
[lua_CFunction] Check if this channel has been hungup or not (for access from lua,...
static void lua_create_app_table(lua_State *L)
Create the global 'app' table for executing applications.
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 lua_reload_extensions(lua_State *L)
Reload the extensions file and update the internal buffers if it loads correctly.
static const char * config
static int lua_autoservice_start(lua_State *L)
[lua_CFunction] Tell pbx_lua to maintain an autoservice on this channel (for access from lua,...
static int lua_func_read(lua_State *L)
[lua_CFunction] Create a 'variable' object for accessing a dialplan function (for access from lua,...
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,...
static struct ast_context * local_contexts
static int lua_autoservice_stop(lua_State *L)
[lua_CFunction] Tell pbx_lua to stop maintaining an autoservice on this channel (for access from lua,...
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 int lua_register_hints(lua_State *L)
Register dialplan hints for our pbx_lua contexts.
#define LUA_EXT_DATA_SIZE
static int lua_pbx_exec(lua_State *L)
[lua_CFunction] This function is part of the 'application' metatable and is used to execute applicati...
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 const char * registrar
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 char * config_file_data
static void lua_create_channel_table(lua_State *L)
Create the global 'channel' table for accessing channel variables.
static void lua_create_variable_metatable(lua_State *L)
Create the 'variable' metatable, used to retrieve channel variables.
static size_t config_file_size
static int load_module(void)
static int lua_sort_extensions(lua_State *L)
Store the sort order of each context.
static int lua_load_extensions(lua_State *L, struct ast_channel *chan)
Load the extensions.lua file from the internal buffer.
static int unload_module(void)
static lua_State * lua_get_state(struct ast_channel *chan)
Get the lua_State for this channel.
static int lua_register_switches(lua_State *L)
Register dialplan switches for our pbx_lua contexts.
static int lua_get_variable(lua_State *L)
[lua_CFunction] Return a lua 'variable' object (for access from lua, don't call directly)
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 char * lua_read_extensions_file(lua_State *L, size_t *size, int *file_not_openable)
Load the extensions.lua file in to a buffer and execute the file.
static struct ast_hashtab * local_table
static ast_mutex_t config_file_lock
static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static void lua_state_destroy(void *data)
The destructor for lua_datastore.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
ast_app: A registered application
Main Channel structure associated with a channel.
char exten[AST_MAX_EXTENSION]
ast_context: An extension context
Structure for a data store type.
Structure for a data store object.
struct ast_channel * chan
Handy terminal functions for vt* terms.
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
int error(const char *format,...)