Thu Sep 7 01:03:02 2017

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

Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1