Wed Aug 18 22:33:54 2010

Asterisk developer's documentation


pbx_lua.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2007, Digium, Inc.
00005  *
00006  * Matthew Nicholson <mnicholson@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! 
00020  * \file
00021  *
00022  * \author Matthew Nicholson <mnicholson@digium.com>
00023  * \brief Lua PBX Switch
00024  *
00025  */
00026 
00027 /*** MODULEINFO
00028    <depend>lua</depend>
00029  ***/
00030 
00031 #include "asterisk.h"
00032 
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 231190 $")
00034 
00035 #include "asterisk/logger.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/module.h"
00039 #include "asterisk/cli.h"
00040 #include "asterisk/utils.h"
00041 #include "asterisk/term.h"
00042 #include "asterisk/paths.h"
00043 #include "asterisk/hashtab.h"
00044 
00045 #ifdef LUA51_PREFIX
00046 #include <lua5.1/lua.h>
00047 #include <lua5.1/lauxlib.h>
00048 #include <lua5.1/lualib.h>
00049 #else
00050 #include <lua.h>
00051 #include <lauxlib.h>
00052 #include <lualib.h>
00053 #endif
00054 
00055 static char *config = "extensions.lua";
00056 static char *registrar = "pbx_lua";
00057 
00058 #define LUA_EXT_DATA_SIZE 256
00059 #define LUA_BUF_SIZE 4096
00060 
00061 static char *lua_read_extensions_file(lua_State *L, long *size);
00062 static int lua_load_extensions(lua_State *L, struct ast_channel *chan);
00063 static int lua_reload_extensions(lua_State *L);
00064 static void lua_free_extensions(void);
00065 static int lua_sort_extensions(lua_State *L);
00066 static int lua_register_switches(lua_State *L);
00067 static int lua_extension_cmp(lua_State *L);
00068 static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func);
00069 static int lua_pbx_findapp(lua_State *L);
00070 static int lua_pbx_exec(lua_State *L);
00071 
00072 static int lua_get_variable_value(lua_State *L);
00073 static int lua_set_variable_value(lua_State *L);
00074 static int lua_get_variable(lua_State *L);
00075 static int lua_set_variable(lua_State *L);
00076 static int lua_func_read(lua_State *L);
00077 
00078 static int lua_autoservice_start(lua_State *L);
00079 static int lua_autoservice_stop(lua_State *L);
00080 static int lua_autoservice_status(lua_State *L);
00081 static int lua_check_hangup(lua_State *L);
00082 static int lua_error_function(lua_State *L);
00083 
00084 static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority);
00085 static void lua_push_variable_table(lua_State *L, const char *name);
00086 static void lua_create_app_table(lua_State *L);
00087 static void lua_create_channel_table(lua_State *L);
00088 static void lua_create_variable_metatable(lua_State *L);
00089 static void lua_create_application_metatable(lua_State *L);
00090 static void lua_create_autoservice_functions(lua_State *L);
00091 static void lua_create_hangup_function(lua_State *L);
00092 
00093 void lua_state_destroy(void *data);
00094 static lua_State *lua_get_state(struct ast_channel *chan);
00095 
00096 static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00097 static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00098 static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00099 static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data);
00100 
00101 AST_MUTEX_DEFINE_STATIC(config_file_lock);
00102 char *config_file_data = NULL;
00103 long config_file_size = 0;
00104 
00105 static struct ast_context *local_contexts = NULL;
00106 static struct ast_hashtab *local_table = NULL;
00107 
00108 static const struct ast_datastore_info lua_datastore = {
00109    .type = "lua",
00110    .destroy = lua_state_destroy,
00111 };
00112 
00113 
00114 /*!
00115  * \brief The destructor for lua_datastore
00116  */
00117 void lua_state_destroy(void *data)
00118 {
00119    if (data)
00120       lua_close(data);
00121 }
00122 
00123 /*!
00124  * \brief [lua_CFunction] Find an app and return it in a lua table (for access from lua, don't
00125  * call directly)
00126  *
00127  * This function would be called in the following example as it would be found
00128  * in extensions.lua.
00129  *
00130  * \code
00131  * app.dial
00132  * \endcode
00133  */
00134 static int lua_pbx_findapp(lua_State *L)
00135 {
00136    const char *app_name = luaL_checkstring(L, 2);
00137    
00138    lua_newtable(L);
00139 
00140    lua_pushstring(L, "name");
00141    lua_pushstring(L, app_name);
00142    lua_settable(L, -3);
00143 
00144    luaL_getmetatable(L, "application");
00145    lua_setmetatable(L, -2);
00146 
00147    return 1;
00148 }
00149 
00150 /*!
00151  * \brief [lua_CFunction] This function is part of the 'application' metatable
00152  * and is used to execute applications similar to pbx_exec() (for access from
00153  * lua, don't call directly)
00154  *
00155  * \param L the lua_State to use
00156  * \return nothing
00157  *
00158  * This funciton is executed as the '()' operator for apps accessed through the
00159  * 'app' table.
00160  *
00161  * \code
00162  * app.playback('demo-congrats')
00163  * \endcode
00164  */
00165 static int lua_pbx_exec(lua_State *L)
00166 {
00167    int res, nargs = lua_gettop(L);
00168    char data[LUA_EXT_DATA_SIZE] = "";
00169    char *data_next = data, *app_name;
00170    char *context, *exten;
00171    char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
00172    int priority, autoservice;
00173    size_t data_left = sizeof(data);
00174    struct ast_app *app;
00175    struct ast_channel *chan;
00176    
00177    lua_getfield(L, 1, "name");
00178    app_name = ast_strdupa(lua_tostring(L, -1));
00179    lua_pop(L, 1);
00180    
00181    if (!(app = pbx_findapp(app_name))) {
00182       lua_pushstring(L, "application '");
00183       lua_pushstring(L, app_name);
00184       lua_pushstring(L, "' not found");
00185       lua_concat(L, 3);
00186       return lua_error(L);
00187    }
00188    
00189 
00190    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00191    chan = lua_touserdata(L, -1);
00192    lua_pop(L, 1);
00193    
00194    
00195    lua_getfield(L, LUA_REGISTRYINDEX, "context");
00196    context = ast_strdupa(lua_tostring(L, -1));
00197    lua_pop(L, 1);
00198    
00199    lua_getfield(L, LUA_REGISTRYINDEX, "exten");
00200    exten = ast_strdupa(lua_tostring(L, -1));
00201    lua_pop(L, 1);
00202    
00203    lua_getfield(L, LUA_REGISTRYINDEX, "priority");
00204    priority = lua_tointeger(L, -1);
00205    lua_pop(L, 1);
00206 
00207 
00208    if (nargs > 1) {
00209       int i;
00210 
00211       if (!lua_isnil(L, 2))
00212          ast_build_string(&data_next, &data_left, "%s", luaL_checkstring(L, 2));
00213 
00214       for (i = 3; i <= nargs; i++) {
00215          if (lua_isnil(L, i))
00216             ast_build_string(&data_next, &data_left, ",");
00217          else
00218             ast_build_string(&data_next, &data_left, ",%s", luaL_checkstring(L, i));
00219       }
00220    }
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, chan->name, 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    if (autoservice)
00238       ast_autoservice_start(chan);
00239 
00240    /* error executing an application, report it */
00241    if (res) {
00242       lua_pushinteger(L, res);
00243       return lua_error(L);
00244    }
00245    return 0;
00246 }
00247 
00248 /*!
00249  * \brief [lua_CFunction] Used to get the value of a variable or dialplan
00250  * function (for access from lua, don't call directly)
00251  * 
00252  * The value of the variable or function is returned.  This function is the
00253  * 'get()' function in the following example as would be seen in
00254  * extensions.lua.
00255  *
00256  * \code
00257  * channel.variable:get()
00258  * \endcode
00259  */
00260 static int lua_get_variable_value(lua_State *L)
00261 {
00262    struct ast_channel *chan;
00263    char *value = NULL, *name;
00264    char *workspace = alloca(LUA_BUF_SIZE);
00265    int autoservice;
00266 
00267    workspace[0] = '\0';
00268 
00269    if (!lua_istable(L, 1)) {
00270       lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value");
00271       return lua_error(L);
00272    }
00273    
00274    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00275    chan = lua_touserdata(L, -1);
00276    lua_pop(L, 1);
00277 
00278    lua_getfield(L, 1, "name");
00279    name = ast_strdupa(lua_tostring(L, -1));
00280    lua_pop(L, 1);
00281    
00282    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00283    autoservice = lua_toboolean(L, -1);
00284    lua_pop(L, 1);
00285 
00286    if (autoservice)
00287       ast_autoservice_stop(chan);
00288    
00289    /* if this is a dialplan function then use ast_func_read(), otherwise
00290     * use pbx_retrieve_variable() */
00291    if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') {
00292       value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace;
00293    } else {
00294       pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead);
00295    }
00296    
00297    if (autoservice)
00298       ast_autoservice_start(chan);
00299 
00300    if (value) {
00301       lua_pushstring(L, value);
00302    } else {
00303       lua_pushnil(L);
00304    }
00305 
00306    return 1;
00307 }
00308 
00309 /*!
00310  * \brief [lua_CFunction] Used to set the value of a variable or dialplan
00311  * function (for access from lua, don't call directly)
00312  * 
00313  * This function is the 'set()' function in the following example as would be
00314  * seen in extensions.lua.
00315  *
00316  * \code
00317  * channel.variable:set("value")
00318  * \endcode
00319  */
00320 static int lua_set_variable_value(lua_State *L)
00321 {
00322    const char *name, *value;
00323    struct ast_channel *chan;
00324    int autoservice;
00325 
00326    if (!lua_istable(L, 1)) {
00327       lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable");
00328       return lua_error(L);
00329    }
00330 
00331    lua_getfield(L, 1, "name");
00332    name = ast_strdupa(lua_tostring(L, -1));
00333    lua_pop(L, 1);
00334 
00335    value = luaL_checkstring(L, 2);
00336    
00337    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00338    chan = lua_touserdata(L, -1);
00339    lua_pop(L, 1);
00340 
00341    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00342    autoservice = lua_toboolean(L, -1);
00343    lua_pop(L, 1);
00344 
00345    if (autoservice)
00346       ast_autoservice_stop(chan);
00347 
00348    pbx_builtin_setvar_helper(chan, name, value);
00349    
00350    if (autoservice)
00351       ast_autoservice_start(chan);
00352 
00353    return 0;
00354 }
00355 
00356 /*!
00357  * \brief Update the lua registry with the given context, exten, and priority.
00358  *
00359  * \param L the lua_State to use
00360  * \param context the new context
00361  * \param exten the new exten
00362  * \param priority the new priority
00363  */
00364 static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority)
00365 {
00366    lua_pushstring(L, context);
00367    lua_setfield(L, LUA_REGISTRYINDEX, "context");
00368 
00369    lua_pushstring(L, exten);
00370    lua_setfield(L, LUA_REGISTRYINDEX, "exten");
00371 
00372    lua_pushinteger(L, priority);
00373    lua_setfield(L, LUA_REGISTRYINDEX, "priority");
00374 }
00375 
00376 /*!
00377  * \brief Push a 'variable' table on the stack for access the channel variable
00378  * with the given name.
00379  *
00380  * \param L the lua_State to use
00381  * \param name the name of the variable
00382  */
00383 static void lua_push_variable_table(lua_State *L, const char *name)
00384 {
00385    lua_newtable(L);
00386    luaL_getmetatable(L, "variable");
00387    lua_setmetatable(L, -2);
00388 
00389    lua_pushstring(L, name);
00390    lua_setfield(L, -2, "name");
00391    
00392    lua_pushcfunction(L, &lua_get_variable_value);
00393    lua_setfield(L, -2, "get");
00394    
00395    lua_pushcfunction(L, &lua_set_variable_value);
00396    lua_setfield(L, -2, "set");
00397 }
00398 
00399 /*!
00400  * \brief Create the global 'app' table for executing applications
00401  *
00402  * \param L the lua_State to use
00403  */
00404 static void lua_create_app_table(lua_State *L)
00405 {
00406    lua_newtable(L);
00407    luaL_newmetatable(L, "app");
00408 
00409    lua_pushstring(L, "__index");
00410    lua_pushcfunction(L, &lua_pbx_findapp);
00411    lua_settable(L, -3);
00412 
00413    lua_setmetatable(L, -2);
00414    lua_setglobal(L, "app");
00415 }
00416 
00417 /*!
00418  * \brief Create the global 'channel' table for accesing channel variables
00419  *
00420  * \param L the lua_State to use
00421  */
00422 static void lua_create_channel_table(lua_State *L)
00423 {
00424    lua_newtable(L);
00425    luaL_newmetatable(L, "channel_data");
00426 
00427    lua_pushstring(L, "__index");
00428    lua_pushcfunction(L, &lua_get_variable);
00429    lua_settable(L, -3);
00430 
00431    lua_pushstring(L, "__newindex");
00432    lua_pushcfunction(L, &lua_set_variable);
00433    lua_settable(L, -3);
00434 
00435    lua_setmetatable(L, -2);
00436    lua_setglobal(L, "channel");
00437 }
00438 
00439 /*!
00440  * \brief Create the 'variable' metatable, used to retrieve channel variables
00441  *
00442  * \param L the lua_State to use
00443  */
00444 static void lua_create_variable_metatable(lua_State *L)
00445 {
00446    luaL_newmetatable(L, "variable");
00447 
00448    lua_pushstring(L, "__call");
00449    lua_pushcfunction(L, &lua_func_read);
00450    lua_settable(L, -3);
00451 
00452    lua_pop(L, 1);
00453 }
00454 
00455 /*!
00456  * \brief Create the 'application' metatable, used to execute asterisk
00457  * applications from lua 
00458  *
00459  * \param L the lua_State to use
00460  */
00461 static void lua_create_application_metatable(lua_State *L)
00462 {
00463    luaL_newmetatable(L, "application");
00464 
00465    lua_pushstring(L, "__call");
00466    lua_pushcfunction(L, &lua_pbx_exec);
00467    lua_settable(L, -3);
00468 
00469    lua_pop(L, 1);
00470 }
00471 
00472 /*!
00473  * \brief Create the autoservice functions
00474  *
00475  * \param L the lua_State to use
00476  */
00477 static void lua_create_autoservice_functions(lua_State *L)
00478 {
00479    lua_pushcfunction(L, &lua_autoservice_start);
00480    lua_setglobal(L, "autoservice_start");
00481    
00482    lua_pushcfunction(L, &lua_autoservice_stop);
00483    lua_setglobal(L, "autoservice_stop");
00484 
00485    lua_pushcfunction(L, &lua_autoservice_status);
00486    lua_setglobal(L, "autoservice_status");
00487 
00488    lua_pushboolean(L, 0);
00489    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00490 }
00491 
00492 /*!
00493  * \brief Create the hangup check function
00494  *
00495  * \param L the lua_State to use
00496  */
00497 static void lua_create_hangup_function(lua_State *L)
00498 {
00499    lua_pushcfunction(L, &lua_check_hangup);
00500    lua_setglobal(L, "check_hangup");
00501 }
00502 
00503 /*!
00504  * \brief [lua_CFunction] Return a lua 'variable' object (for access from lua, don't call
00505  * directly)
00506  * 
00507  * This function is called to lookup a variable construct a 'variable' object.
00508  * It would be called in the following example as would be seen in
00509  * extensions.lua.
00510  *
00511  * \code
00512  * channel.variable
00513  * \endcode
00514  */
00515 static int lua_get_variable(lua_State *L)
00516 {
00517    struct ast_channel *chan;
00518    char *name = ast_strdupa(luaL_checkstring(L, 2));
00519    char *value = NULL;
00520    char *workspace = alloca(LUA_BUF_SIZE);
00521    workspace[0] = '\0';
00522    
00523    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00524    chan = lua_touserdata(L, -1);
00525    lua_pop(L, 1);
00526 
00527    lua_push_variable_table(L, name);
00528    
00529    /* if this is not a request for a dialplan funciton attempt to retrieve
00530     * the value of the variable */
00531    if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') {
00532       pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead);
00533    }
00534 
00535    if (value) {
00536       lua_pushstring(L, value);
00537       lua_setfield(L, -2, "value");
00538    }
00539 
00540    return 1;   
00541 }
00542 
00543 /*!
00544  * \brief [lua_CFunction] Set the value of a channel variable or dialplan
00545  * function (for access from lua, don't call directly)
00546  * 
00547  * This function is called to set a variable or dialplan function.  It would be
00548  * called in the following example as would be seen in extensions.lua.
00549  *
00550  * \code
00551  * channel.variable = "value"
00552  * \endcode
00553  */
00554 static int lua_set_variable(lua_State *L)
00555 {
00556    struct ast_channel *chan;
00557    int autoservice;
00558    const char *name = luaL_checkstring(L, 2);
00559    const char *value = luaL_checkstring(L, 3);
00560 
00561    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00562    chan = lua_touserdata(L, -1);
00563    lua_pop(L, 1);
00564 
00565    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00566    autoservice = lua_toboolean(L, -1);
00567    lua_pop(L, 1);
00568 
00569    if (autoservice)
00570       ast_autoservice_stop(chan);
00571 
00572    pbx_builtin_setvar_helper(chan, name, value);
00573    
00574    if (autoservice)
00575       ast_autoservice_start(chan);
00576 
00577    return 0;
00578 }
00579 
00580 /*!
00581  * \brief [lua_CFunction] Create a 'variable' object for accessing a dialplan
00582  * function (for access from lua, don't call directly)
00583  * 
00584  * This function is called to create a 'variable' object to access a dialplan
00585  * function.  It would be called in the following example as would be seen in
00586  * extensions.lua.
00587  *
00588  * \code
00589  * channel.func("arg1", "arg2", "arg3")
00590  * \endcode
00591  *
00592  * To actually do anything with the resulting value you must use the 'get()'
00593  * and 'set()' methods (the reason is the resulting value is not a value, but
00594  * an object in the form of a lua table).
00595  */
00596 static int lua_func_read(lua_State *L)
00597 {
00598    int nargs = lua_gettop(L);
00599    char fullname[LUA_EXT_DATA_SIZE] = "";
00600    char *fullname_next = fullname, *name;
00601    size_t fullname_left = sizeof(fullname);
00602    
00603    lua_getfield(L, 1, "name");
00604    name = ast_strdupa(lua_tostring(L, -1));
00605    lua_pop(L, 1);
00606 
00607    ast_build_string(&fullname_next, &fullname_left, "%s(", name);
00608    
00609    if (nargs > 1) {
00610       int i;
00611 
00612       if (!lua_isnil(L, 2))
00613          ast_build_string(&fullname_next, &fullname_left, "%s", luaL_checkstring(L, 2));
00614 
00615       for (i = 3; i <= nargs; i++) {
00616          if (lua_isnil(L, i))
00617             ast_build_string(&fullname_next, &fullname_left, ",");
00618          else
00619             ast_build_string(&fullname_next, &fullname_left, ",%s", luaL_checkstring(L, i));
00620       }
00621    }
00622 
00623    ast_build_string(&fullname_next, &fullname_left, ")");
00624    
00625    lua_push_variable_table(L, fullname);
00626    
00627    return 1;
00628 }
00629 
00630 /*!
00631  * \brief [lua_CFunction] Tell pbx_lua to maintain an autoservice on this
00632  * channel (for access from lua, don't call directly)
00633  *
00634  * \param L the lua_State to use
00635  *
00636  * This function will set a flag that will cause pbx_lua to maintain an
00637  * autoservice on this channel.  The autoservice will automatically be stopped
00638  * and restarted before calling applications and functions.
00639  *
00640  * \return This function returns the result of the ast_autoservice_start()
00641  * function as a boolean to its lua caller.
00642  */
00643 static int lua_autoservice_start(lua_State *L)
00644 {
00645    struct ast_channel *chan;
00646    int res;
00647 
00648    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00649    chan = lua_touserdata(L, -1);
00650    lua_pop(L, 1);
00651 
00652    res = ast_autoservice_start(chan);
00653 
00654    lua_pushboolean(L, !res);
00655    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00656 
00657    lua_pushboolean(L, !res);
00658    return 1;
00659 }
00660 
00661 /*!
00662  * \brief [lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on
00663  * this channel (for access from lua, don't call directly)
00664  *
00665  * \param L the lua_State to use
00666  *
00667  * This function will stop any autoservice running and turn off the autoservice
00668  * flag.  If this function returns false, it's probably because no autoservice
00669  * was running to begin with.
00670  *
00671  * \return This function returns the result of the ast_autoservice_stop()
00672  * function as a boolean to its lua caller.
00673  */
00674 static int lua_autoservice_stop(lua_State *L)
00675 {
00676    struct ast_channel *chan;
00677    int res;
00678 
00679    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00680    chan = lua_touserdata(L, -1);
00681    lua_pop(L, 1);
00682 
00683    res = ast_autoservice_stop(chan);
00684 
00685    lua_pushboolean(L, 0);
00686    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00687 
00688    lua_pushboolean(L, !res);
00689    return 1;
00690 }
00691 
00692 /*!
00693  * \brief [lua_CFunction] Get the status of the autoservice flag (for access
00694  * from lua, don't call directly)
00695  *
00696  * \param L the lua_State to use
00697  *
00698  * \return This function returns the status of the autoservice flag as a
00699  * boolean to its lua caller.
00700  */
00701 static int lua_autoservice_status(lua_State *L)
00702 {
00703    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00704    return 1;
00705 }
00706 
00707 /*!
00708  * \brief [lua_CFunction] Check if this channel has been hungup or not (for
00709  * access from lua, don't call directly)
00710  *
00711  * \param L the lua_State to use
00712  *
00713  * \return This function returns true if the channel was hungup
00714  */
00715 static int lua_check_hangup(lua_State *L)
00716 {
00717    struct ast_channel *chan;
00718    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00719    chan = lua_touserdata(L, -1);
00720    lua_pop(L, 1);
00721 
00722    lua_pushboolean(L, ast_check_hangup(chan));
00723    return 1;
00724 }
00725 
00726 /*!
00727  * \brief [lua_CFunction] Handle lua errors (for access from lua, don't call
00728  * directly)
00729  *
00730  * \param L the lua_State to use
00731  */
00732 static int lua_error_function(lua_State *L)
00733 {
00734    int message_index;
00735 
00736    /* pass number arguments right through back to asterisk*/
00737    if (lua_isnumber(L, -1)) {
00738       return 1;
00739    }
00740 
00741    /* if we are here then we have a string error message, let's attach a
00742     * backtrace to it */
00743    message_index = lua_gettop(L);
00744 
00745    lua_getglobal(L, "debug");
00746    lua_getfield(L, -1, "traceback");
00747    lua_remove(L, -2); /* remove the 'debug' table */
00748 
00749    lua_pushvalue(L, message_index);
00750    lua_remove(L, message_index);
00751 
00752    lua_pushnumber(L, 2);
00753 
00754    lua_call(L, 2, 1);
00755 
00756    return 1;
00757 }
00758 
00759 /*!
00760  * \brief Store the sort order of each context
00761  
00762  * In the event of an error, an error string will be pushed onto the lua stack.
00763  *
00764  * \retval 0 success
00765  * \retval 1 failure
00766  */
00767 static int lua_sort_extensions(lua_State *L)
00768 {
00769    int extensions, extensions_order;
00770 
00771    /* create the extensions_order table */
00772    lua_newtable(L);
00773    lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order");
00774    lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
00775    extensions_order = lua_gettop(L);
00776 
00777    /* sort each context in the extensions table */
00778    /* load the 'extensions' table */
00779    lua_getglobal(L, "extensions");
00780    extensions = lua_gettop(L);
00781    if (lua_isnil(L, -1)) {
00782       lua_pop(L, 1);
00783       lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00784       return 1;
00785    }
00786 
00787    /* iterate through the extensions table and create a
00788     * matching table (holding the sort order) in the
00789     * extensions_order table for each context that is found
00790     */
00791    for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00792       int context = lua_gettop(L);
00793       int context_name = context - 1;
00794       int context_order;
00795 
00796       lua_pushvalue(L, context_name);
00797       lua_newtable(L);
00798       context_order = lua_gettop(L);
00799 
00800       /* iterate through this context an popluate the corrisponding
00801        * table in the extensions_order table */
00802       for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
00803          int exten = lua_gettop(L) - 1;
00804 
00805          lua_pushinteger(L, lua_objlen(L, context_order) + 1);
00806          lua_pushvalue(L, exten);
00807          lua_settable(L, context_order);
00808       }
00809       lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */
00810 
00811       /* now sort the new table */
00812 
00813       /* push the table.sort function */
00814       lua_getglobal(L, "table");
00815       lua_getfield(L, -1, "sort");
00816       lua_remove(L, -2); /* remove the 'table' table */
00817 
00818       /* push the context_order table */
00819       lua_pushvalue(L, context_name);
00820       lua_gettable(L, extensions_order);
00821 
00822       /* push the comp function */
00823       lua_pushcfunction(L, &lua_extension_cmp);
00824 
00825       if (lua_pcall(L, 2, 0, 0)) {
00826          lua_insert(L, -5);
00827          lua_pop(L, 4);
00828          return 1;
00829       }
00830    }
00831    
00832    /* remove the extensions table and the extensions_order table */
00833    lua_pop(L, 2);
00834    return 0;
00835 }
00836 
00837 /*!
00838  * \brief Register dialplan switches for our pbx_lua contexs.
00839  *
00840  * In the event of an error, an error string will be pushed onto the lua stack.
00841  *
00842  * \retval 0 success
00843  * \retval 1 failure
00844  */
00845 static int lua_register_switches(lua_State *L)
00846 {
00847    int extensions;
00848    struct ast_context *con = NULL;
00849 
00850    /* create the hash table for our contexts */
00851    /* XXX do we ever need to destroy this? pbx_config does not */
00852    if (!local_table)
00853       local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
00854 
00855    /* load the 'extensions' table */
00856    lua_getglobal(L, "extensions");
00857    extensions = lua_gettop(L);
00858    if (lua_isnil(L, -1)) {
00859       lua_pop(L, 1);
00860       lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00861       return 1;
00862    }
00863 
00864    /* iterate through the extensions table and register a context and
00865     * dialplan switch for each lua context
00866     */
00867    for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00868       int context = lua_gettop(L);
00869       int context_name = context - 1;
00870       const char *context_str = lua_tostring(L, context_name);
00871 
00872       /* find or create this context */
00873       con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
00874       if (!con) {
00875          /* remove extensions table and context key and value */
00876          lua_pop(L, 3);
00877          lua_pushstring(L, "Failed to find or create context\n");
00878          return 1;
00879       }
00880 
00881       /* register the switch */
00882       if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
00883          /* remove extensions table and context key and value */
00884          lua_pop(L, 3);
00885          lua_pushstring(L, "Unable to create switch for context\n");
00886          return 1;
00887       }
00888    }
00889    
00890    /* remove the extensions table */
00891    lua_pop(L, 1);
00892    return 0;
00893 }
00894 
00895 
00896 /*!
00897  * \brief [lua_CFunction] Compare two extensions (for access from lua, don't
00898  * call directly)
00899  *
00900  * This function returns true if the first extension passed should match after
00901  * the second.  It behaves like the '<' operator.
00902  */
00903 static int lua_extension_cmp(lua_State *L)
00904 {
00905    const char *a = luaL_checkstring(L, -2);
00906    const char *b = luaL_checkstring(L, -1);
00907 
00908    if (ast_extension_cmp(a, b) == -1)
00909       lua_pushboolean(L, 1);
00910    else
00911       lua_pushboolean(L, 0);
00912 
00913    return 1;
00914 }
00915 
00916 /*!
00917  * \brief Load the extensions.lua file in to a buffer and execute the file
00918  *
00919  * \param L the lua_State to use
00920  * \param size a pointer to store the size of the buffer
00921  *
00922  * \note The caller is expected to free the buffer at some point.
00923  *
00924  * \return a pointer to the buffer
00925  */
00926 static char *lua_read_extensions_file(lua_State *L, long *size)
00927 {
00928    FILE *f;
00929    char *data;
00930    char *path = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
00931    sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
00932 
00933    if (!(f = fopen(path, "r"))) {
00934       lua_pushstring(L, "cannot open '");
00935       lua_pushstring(L, path);
00936       lua_pushstring(L, "' for reading: ");
00937       lua_pushstring(L, strerror(errno));
00938       lua_concat(L, 4);
00939 
00940       return NULL;
00941    }
00942 
00943    fseek(f, 0l, SEEK_END);
00944    *size = ftell(f);
00945 
00946    fseek(f, 0l, SEEK_SET);
00947 
00948    if (!(data = ast_malloc(*size))) {
00949       *size = 0;
00950       fclose(f);
00951       lua_pushstring(L, "not enough memory");
00952       return NULL;
00953    }
00954 
00955    if (fread(data, sizeof(char), *size, f) != *size) {
00956       ast_log(LOG_WARNING, "fread() failed: %s\n", strerror(errno));
00957    }
00958    fclose(f);
00959 
00960    if (luaL_loadbuffer(L, data, *size, "extensions.lua")
00961          || lua_pcall(L, 0, LUA_MULTRET, 0)
00962          || lua_sort_extensions(L)
00963          || lua_register_switches(L)) {
00964       ast_free(data);
00965       data = NULL;
00966       *size = 0;
00967    }
00968    return data;
00969 }
00970 
00971 /*!
00972  * \brief Load the extensions.lua file from the internal buffer
00973  *
00974  * \param L the lua_State to use
00975  * \param chan channel to work on
00976  *
00977  * This function also sets up some constructs used by the extensions.lua file.
00978  * In the event of an error, an error string will be pushed onto the lua stack.
00979  *
00980  * \retval 0 success
00981  * \retval 1 failure
00982  */
00983 static int lua_load_extensions(lua_State *L, struct ast_channel *chan)
00984 {
00985    
00986    /* store a pointer to this channel */
00987    lua_pushlightuserdata(L, chan);
00988    lua_setfield(L, LUA_REGISTRYINDEX, "channel");
00989    
00990    luaL_openlibs(L);
00991 
00992    /* load and sort extensions */
00993    ast_mutex_lock(&config_file_lock);
00994    if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
00995          || lua_pcall(L, 0, LUA_MULTRET, 0)
00996          || lua_sort_extensions(L)) {
00997       ast_mutex_unlock(&config_file_lock);
00998       return 1;
00999    }
01000    ast_mutex_unlock(&config_file_lock);
01001 
01002    /* now we setup special tables and functions */
01003 
01004    lua_create_app_table(L);
01005    lua_create_channel_table(L);
01006 
01007    lua_create_variable_metatable(L);
01008    lua_create_application_metatable(L);
01009 
01010    lua_create_autoservice_functions(L);
01011    lua_create_hangup_function(L);
01012 
01013    return 0;
01014 }
01015 
01016 /*!
01017  * \brief Reload the extensions file and update the internal buffers if it
01018  * loads correctly.
01019  *
01020  * \warning This function should not be called on a lua_State returned from
01021  * lua_get_state().
01022  *
01023  * \param L the lua_State to use (must be freshly allocated with
01024  * luaL_newstate(), don't use lua_get_state())
01025  */
01026 static int lua_reload_extensions(lua_State *L)
01027 {
01028    long size = 0;
01029    char *data = NULL;
01030 
01031    luaL_openlibs(L);
01032 
01033    if (!(data = lua_read_extensions_file(L, &size))) {
01034       return 1;
01035    }
01036 
01037    ast_mutex_lock(&config_file_lock);
01038 
01039    if (config_file_data)
01040       ast_free(config_file_data);
01041 
01042    config_file_data = data;
01043    config_file_size = size;
01044    
01045    /* merge our new contexts */
01046    ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
01047    /* merge_contexts_and_delete will actually, at the correct moment, 
01048       set the global dialplan pointers to your local_contexts and local_table.
01049       It then will free up the old tables itself. Just be sure not to
01050       hang onto the pointers. */
01051    local_table = NULL;
01052    local_contexts = NULL;
01053 
01054    ast_mutex_unlock(&config_file_lock);
01055    return 0;
01056 }
01057 
01058 /*!
01059  * \brief Free the internal extensions buffer.
01060  */
01061 static void lua_free_extensions()
01062 {
01063    ast_mutex_lock(&config_file_lock);
01064    config_file_size = 0;
01065    ast_free(config_file_data);
01066    ast_mutex_unlock(&config_file_lock);
01067 }
01068 
01069 /*!
01070  * \brief Get the lua_State for this channel
01071  *
01072  * If no channel is passed then a new state is allocated.  States with no
01073  * channel assocatied with them should only be used for matching extensions.
01074  * If the channel does not yet have a lua state associated with it, one will be
01075  * created.
01076  *
01077  * \note If no channel was passed then the caller is expected to free the state
01078  * using lua_close().
01079  *
01080  * \return a lua_State
01081  */
01082 static lua_State *lua_get_state(struct ast_channel *chan)
01083 {
01084    struct ast_datastore *datastore = NULL;
01085    lua_State *L;
01086 
01087    if (!chan) {
01088       lua_State *L = luaL_newstate();
01089       if (!L) {
01090          ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01091          return NULL;
01092       }
01093 
01094       if (lua_load_extensions(L, NULL)) {
01095          const char *error = lua_tostring(L, -1);
01096          ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01097          lua_close(L);
01098          return NULL;
01099       }
01100       return L;
01101    } else {
01102       ast_channel_lock(chan);
01103       datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
01104       ast_channel_unlock(chan);
01105 
01106       if (!datastore) {
01107          /* nothing found, allocate a new lua state */
01108          datastore = ast_datastore_alloc(&lua_datastore, NULL);
01109          if (!datastore) {
01110             ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
01111             return NULL;
01112          }
01113 
01114          datastore->data = luaL_newstate();
01115          if (!datastore->data) {
01116             ast_datastore_free(datastore);
01117             ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01118             return NULL;
01119          }
01120 
01121          ast_channel_lock(chan);
01122          ast_channel_datastore_add(chan, datastore);
01123          ast_channel_unlock(chan);
01124 
01125          L = datastore->data;
01126 
01127          if (lua_load_extensions(L, chan)) {
01128             const char *error = lua_tostring(L, -1);
01129             ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", chan->name, error);
01130 
01131             ast_channel_lock(chan);
01132             ast_channel_datastore_remove(chan, datastore);
01133             ast_channel_unlock(chan);
01134 
01135             ast_datastore_free(datastore);
01136             return NULL;
01137          }
01138       }
01139 
01140       return datastore->data;
01141    }
01142 }
01143 
01144 static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01145 {
01146    int res;
01147    lua_State *L;
01148    struct ast_module_user *u = ast_module_user_add(chan);
01149    if (!u) {
01150       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01151       return 0;
01152    }
01153 
01154    L = lua_get_state(chan);
01155    if (!L) {
01156       ast_module_user_remove(u);
01157       return 0;
01158    }
01159 
01160    res = lua_find_extension(L, context, exten, priority, &exists, 0);
01161 
01162    if (!chan) lua_close(L);
01163    ast_module_user_remove(u);
01164    return res;
01165 }
01166 
01167 static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01168 {
01169    int res;
01170    lua_State *L;
01171    struct ast_module_user *u = ast_module_user_add(chan);
01172    if (!u) {
01173       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01174       return 0;
01175    }
01176 
01177    L = lua_get_state(chan);
01178    if (!L) {
01179       ast_module_user_remove(u);
01180       return 0;
01181    }
01182 
01183    res = lua_find_extension(L, context, exten, priority, &canmatch, 0);
01184 
01185    if (!chan) lua_close(L);
01186    ast_module_user_remove(u);
01187    return res;
01188 }
01189 
01190 static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01191 {
01192    int res;
01193    lua_State *L;
01194    struct ast_module_user *u = ast_module_user_add(chan);
01195    if (!u) {
01196       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01197       return 0;
01198    }
01199 
01200    L = lua_get_state(chan);
01201    if (!L) {
01202       ast_module_user_remove(u);
01203       return 0;
01204    }
01205    
01206    res = lua_find_extension(L, context, exten, priority, &matchmore, 0);
01207 
01208    if (!chan) lua_close(L);
01209    ast_module_user_remove(u);
01210    return res;
01211 }
01212 
01213 
01214 static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
01215 {
01216    int res, error_func;
01217    lua_State *L;
01218    struct ast_module_user *u = ast_module_user_add(chan);
01219    if (!u) {
01220       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01221       return -1;
01222    }
01223    
01224    L = lua_get_state(chan);
01225    if (!L) {
01226       ast_module_user_remove(u);
01227       return -1;
01228    }
01229 
01230    lua_pushcfunction(L, &lua_error_function);
01231    error_func = lua_gettop(L);
01232 
01233    /* push the extension function onto the stack */
01234    if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
01235       lua_pop(L, 1); /* pop the debug function */
01236       ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
01237       if (!chan) lua_close(L);
01238       ast_module_user_remove(u);
01239       return -1;
01240    }
01241       
01242    lua_update_registry(L, context, exten, priority);
01243    
01244    lua_pushstring(L, context);
01245    lua_pushstring(L, exten);
01246    
01247    res = lua_pcall(L, 2, 0, error_func);
01248    if (res) {
01249       if (res == LUA_ERRRUN) {
01250          res = -1;
01251          if (lua_isnumber(L, -1)) {
01252             res = lua_tointeger(L, -1);
01253          } else if (lua_isstring(L, -1)) {
01254             const char *error = lua_tostring(L, -1);
01255             ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
01256          }
01257       } else if (res == LUA_ERRERR) {
01258          res = -1;
01259          ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
01260       } else if (res == LUA_ERRMEM) {
01261          res = -1;
01262          ast_log(LOG_ERROR, "Memory allocation error\n");
01263       }
01264       lua_pop(L, 1);
01265    }
01266    lua_remove(L, error_func);
01267    if (!chan) lua_close(L);
01268    ast_module_user_remove(u);
01269    return res;
01270 }
01271 
01272 /*!
01273  * \brief Locate an extensions and optionally push the matching function on the
01274  * stack
01275  *
01276  * \param L the lua_State to use
01277  * \param context the context to look in
01278  * \param exten the extension to look up
01279  * \param priority the priority to check, '1' is the only valid priority
01280  * \param func the calling func, used to adjust matching behavior between,
01281  * match, canmatch, and matchmore
01282  * \param push_func whether or not to push the lua function for the given
01283  * extension onto the stack
01284  */
01285 static int lua_find_extension(lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
01286 {
01287    int context_table, context_order_table, i;
01288 
01289    ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
01290    if (priority != 1)
01291       return 0;
01292 
01293    /* load the 'extensions' table */
01294    lua_getglobal(L, "extensions");
01295    if (lua_isnil(L, -1)) {
01296       ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
01297       lua_pop(L, 1);
01298       return 0;
01299    }
01300 
01301    /* load the given context */
01302    lua_getfield(L, -1, context);
01303    if (lua_isnil(L, -1)) {
01304       lua_pop(L, 2);
01305       return 0;
01306    }
01307 
01308    /* remove the extensions table */
01309    lua_remove(L, -2);
01310 
01311    context_table = lua_gettop(L);
01312 
01313    /* load the extensions order table for this context */
01314    lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
01315    lua_getfield(L, -1, context);
01316 
01317    lua_remove(L, -2);  /* remove the extensions order table */
01318 
01319    context_order_table = lua_gettop(L);
01320    
01321    /* step through the extensions looking for a match */
01322    for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
01323       int e_index, e_index_copy, match = 0;
01324       const char *e;
01325 
01326       lua_pushinteger(L, i);
01327       lua_gettable(L, context_order_table);
01328       e_index = lua_gettop(L);
01329 
01330       /* copy the key at the top of the stack for use later */
01331       lua_pushvalue(L, -1);
01332       e_index_copy = lua_gettop(L);
01333 
01334       if (!(e = lua_tostring(L, e_index_copy))) {
01335          lua_pop(L, 2);
01336          continue;
01337       }
01338 
01339       /* make sure this is not the 'include' extension */
01340       if (!strcasecmp(e, "include")) {
01341          lua_pop(L, 2);
01342          continue;
01343       }
01344 
01345       if (func == &matchmore)
01346          match = ast_extension_close(e, exten, E_MATCHMORE);
01347       else if (func == &canmatch)
01348          match = ast_extension_close(e, exten, E_CANMATCH);
01349       else
01350          match = ast_extension_match(e, exten);
01351 
01352       /* the extension matching functions return 0 on fail, 1 on
01353        * match, 2 on earlymatch */
01354 
01355       if (!match) {
01356          /* pop the copy and the extension */
01357          lua_pop(L, 2);
01358          continue;   /* keep trying */
01359       }
01360 
01361       if (func == &matchmore && match == 2) {
01362          /* We match an extension ending in '!'. The decision in
01363           * this case is final and counts as no match. */
01364          lua_pop(L, 4);
01365          return 0;
01366       }
01367 
01368       /* remove the context table, the context order table, the
01369        * extension, and the extension copy (or replace the extension
01370        * with the corresponding function) */
01371       if (push_func) {
01372          lua_pop(L, 1);  /* pop the copy */
01373          lua_gettable(L, context_table);
01374          lua_insert(L, -3);
01375          lua_pop(L, 2);
01376       } else {
01377          lua_pop(L, 4);
01378       }
01379 
01380       return 1;
01381    }
01382 
01383    /* load the includes for this context */
01384    lua_getfield(L, context_table, "include");
01385    if (lua_isnil(L, -1)) {
01386       lua_pop(L, 3);
01387       return 0;
01388    }
01389 
01390    /* remove the context and the order table*/
01391    lua_remove(L, context_order_table);
01392    lua_remove(L, context_table);
01393 
01394    /* Now try any includes we have in this context */
01395    for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
01396       const char *c = lua_tostring(L, -1);
01397       if (!c)
01398          continue;
01399 
01400       if (lua_find_extension(L, c, exten, priority, func, push_func)) {
01401          /* remove the value, the key, and the includes table
01402           * from the stack.  Leave the function behind if
01403           * necessary */
01404 
01405          if (push_func)
01406             lua_insert(L, -4);
01407 
01408          lua_pop(L, 3);
01409          return 1;
01410       }
01411    }
01412 
01413    /* pop the includes table */
01414    lua_pop(L, 1);
01415    return 0;
01416 }
01417 
01418 static struct ast_switch lua_switch = {
01419         .name     = "Lua",
01420         .description = "Lua PBX Switch",
01421         .exists      = exists,
01422         .canmatch = canmatch,
01423         .exec     = exec,
01424         .matchmore   = matchmore,
01425 };
01426 
01427 
01428 static int load_or_reload_lua_stuff(void)
01429 {
01430    int res = AST_MODULE_LOAD_SUCCESS;
01431 
01432    lua_State *L = luaL_newstate();
01433    if (!L) {
01434       ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01435       return AST_MODULE_LOAD_DECLINE;
01436    }
01437 
01438    if (lua_reload_extensions(L)) {
01439       const char *error = lua_tostring(L, -1);
01440       ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01441       res = AST_MODULE_LOAD_DECLINE;
01442    }
01443 
01444    lua_close(L);
01445    return res;
01446 }
01447 
01448 static int unload_module(void)
01449 {
01450    ast_context_destroy(NULL, registrar);
01451    ast_unregister_switch(&lua_switch);
01452    lua_free_extensions();
01453    return 0;
01454 }
01455 
01456 static int reload(void)
01457 {
01458    return load_or_reload_lua_stuff();
01459 }
01460 
01461 static int load_module(void)
01462 {
01463    int res;
01464 
01465    if ((res = load_or_reload_lua_stuff()))
01466       return res;
01467 
01468    if (ast_register_switch(&lua_switch)) {
01469       ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
01470       return AST_MODULE_LOAD_DECLINE;
01471    }
01472 
01473    return AST_MODULE_LOAD_SUCCESS;
01474 }
01475 
01476 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Lua PBX Switch",
01477       .load = load_module,
01478       .unload = unload_module,
01479       .reload = reload,
01480           );
01481 

Generated on Wed Aug 18 22:33:54 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7