Fri Jul 15 2011 11:58:29

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