diff options
-rw-r--r-- | configs/extensions.lua.sample | 9 | ||||
-rw-r--r-- | include/asterisk/hashtab.h | 6 | ||||
-rw-r--r-- | pbx/pbx_lua.c | 78 |
3 files changed, 82 insertions, 11 deletions
diff --git a/configs/extensions.lua.sample b/configs/extensions.lua.sample index 8aee734b4..44b9b81b5 100644 --- a/configs/extensions.lua.sample +++ b/configs/extensions.lua.sample @@ -18,15 +18,6 @@ TRUNKMSD = 1 -- representing a context. Extensions are defined in each context. See below -- for examples. -- --- This file can be automatically included in the extensions.conf file using --- the 'utils/build-extensions-conf.lua' script and a #exec statement in --- extensions.conf. --- --- #exec /usr/bin/utils/build-extensions.conf.lua -c --- --- The 'execincludes' option must be set to 'yes' in the [options] section of --- asterisk.conf for this to work properly. --- -- Extension names may be numbers, letters, or combinations thereof. If -- an extension name is prefixed by a '_' character, it is interpreted as -- a pattern rather than a literal. In patterns, some characters have diff --git a/include/asterisk/hashtab.h b/include/asterisk/hashtab.h index ed9a95e84..aa4dc59db 100644 --- a/include/asterisk/hashtab.h +++ b/include/asterisk/hashtab.h @@ -198,7 +198,11 @@ struct ast_hashtab * ast_hashtab_create(int initial_buckets, /*! * \brief This func will free the hash table and all its memory. - * \note It doesn't touch the objects stored in it + * \note It doesn't touch the objects stored in it, unless you + * specify a destroy func; it will call that func for each + * object in the hashtab, remove all the objects, and then + * free the hashtab itself. If no destroyfunc is specified + * then the routine will assume you will free it yourself. * \param tab * \param objdestroyfunc */ diff --git a/pbx/pbx_lua.c b/pbx/pbx_lua.c index 6a98e302a..13158d758 100644 --- a/pbx/pbx_lua.c +++ b/pbx/pbx_lua.c @@ -40,12 +40,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/utils.h" #include "asterisk/term.h" #include "asterisk/paths.h" +#include "asterisk/hashtab.h" #include <lua5.1/lua.h> #include <lua5.1/lauxlib.h> #include <lua5.1/lualib.h> static char *config = "extensions.lua"; +static char *registrar = "pbx_lua"; #define LUA_EXT_DATA_SIZE 256 #define LUA_BUF_SIZE 4096 @@ -55,6 +57,7 @@ static int lua_load_extensions(lua_State *L, struct ast_channel *chan); static int lua_reload_extensions(lua_State *L); static void lua_free_extensions(void); static int lua_sort_extensions(lua_State *L); +static int lua_register_switches(lua_State *L); static int lua_extension_cmp(lua_State *L); static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func); static int lua_pbx_findapp(lua_State *L); @@ -92,6 +95,9 @@ AST_MUTEX_DEFINE_STATIC(config_file_lock); char *config_file_data = NULL; long config_file_size = 0; +static struct ast_context *local_contexts = NULL; +static struct ast_hashtab *local_table = NULL; + static const struct ast_datastore_info lua_datastore = { .type = "lua", .destroy = lua_state_destroy, @@ -789,6 +795,65 @@ static int lua_sort_extensions(lua_State *L) } /*! + * \brief Register dialplan switches for our pbx_lua contexs. + * + * In the event of an error, an error string will be pushed onto the lua stack. + * + * \retval 0 success + * \retval 1 failure + */ +static int lua_register_switches(lua_State *L) +{ + int extensions; + struct ast_context *con = NULL; + + /* create the hash table for our contexts */ + /* XXX do we ever need to destroy this? pbx_config does not */ + if (!local_table) + local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0); + + /* load the 'extensions' table */ + lua_getglobal(L, "extensions"); + extensions = lua_gettop(L); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n"); + return 1; + } + + /* iterate through the extensions table and register a context and + * dialplan switch for each lua context + */ + for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) { + int context = lua_gettop(L); + int context_name = context - 1; + const char *context_str = lua_tostring(L, context_name); + + /* find or create this context */ + con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar); + if (!con) { + /* remove extensions table and context key and value */ + lua_pop(L, 3); + lua_pushstring(L, "Failed to find or create context\n"); + return 1; + } + + /* register the switch */ + if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) { + /* remove extensions table and context key and value */ + lua_pop(L, 3); + lua_pushstring(L, "Unable to create switch for context\n"); + return 1; + } + } + + /* remove the extensions table */ + lua_pop(L, 1); + return 0; +} + + +/*! * \brief [lua_CFunction] Compare two extensions (for access from lua, don't * call directly) * @@ -852,7 +917,8 @@ static char *lua_read_extensions_file(lua_State *L, long *size) if (luaL_loadbuffer(L, data, *size, "extensions.lua") || lua_pcall(L, 0, LUA_MULTRET, 0) - || lua_sort_extensions(L)) { + || lua_sort_extensions(L) + || lua_register_switches(L)) { ast_free(data); data = NULL; *size = 0; @@ -933,6 +999,15 @@ static int lua_reload_extensions(lua_State *L) config_file_data = data; config_file_size = size; + + /* merge our new contexts */ + ast_merge_contexts_and_delete(&local_contexts, local_table, registrar); + /* merge_contexts_and_delete will actually, at the correct moment, + set the global dialplan pointers to your local_contexts and local_table. + It then will free up the old tables itself. Just be sure not to + hang onto the pointers. */ + local_table = NULL; + local_contexts = NULL; ast_mutex_unlock(&config_file_lock); return 0; @@ -1320,6 +1395,7 @@ static int load_or_reload_lua_stuff(void) static int unload_module(void) { + ast_context_destroy(NULL, registrar); ast_unregister_switch(&lua_switch); lua_free_extensions(); return 0; |