Fri Jul 24 00:41:01 2009

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

Generated on Fri Jul 24 00:41:01 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7