Sat Apr 26 2014 22:01:39

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