Thu Oct 11 06:36:51 2012

Asterisk developer's documentation


pbx_lua.c File Reference

Lua PBX Switch. More...

#include "asterisk.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/term.h"
#include "asterisk/paths.h"
#include "asterisk/hashtab.h"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

Include dependency graph for pbx_lua.c:

Go to the source code of this file.

Defines

#define LUA_BUF_SIZE   4096
#define LUA_EXT_DATA_SIZE   8192
#define LUA_GOTO_DETECTED   5

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int load_module (void)
static int load_or_reload_lua_stuff (void)
static int lua_autoservice_start (lua_State *L)
 [lua_CFunction] Tell pbx_lua to maintain an autoservice on this channel (for access from lua, don't call directly)
static int lua_autoservice_status (lua_State *L)
 [lua_CFunction] Get the status of the autoservice flag (for access from lua, don't call directly)
static int lua_autoservice_stop (lua_State *L)
 [lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on this channel (for access from lua, don't call directly)
static int lua_check_hangup (lua_State *L)
 [lua_CFunction] Check if this channel has been hungup or not (for access from lua, don't call directly)
static void lua_concat_args (lua_State *L, int start, int nargs)
 Concatenate a list of lua function arguments into a comma separated string.
static void lua_create_app_table (lua_State *L)
 Create the global 'app' table for executing applications.
static void lua_create_application_metatable (lua_State *L)
 Create the 'application' metatable, used to execute asterisk applications from lua.
static void lua_create_autoservice_functions (lua_State *L)
 Create the autoservice functions.
static void lua_create_channel_table (lua_State *L)
 Create the global 'channel' table for accesing channel variables.
static void lua_create_hangup_function (lua_State *L)
 Create the hangup check function.
static void lua_create_variable_metatable (lua_State *L)
 Create the 'variable' metatable, used to retrieve channel variables.
static void lua_datastore_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 The fixup function for the lua_datastore.
static int lua_error_function (lua_State *L)
 [lua_CFunction] Handle lua errors (for access from lua, don't call directly)
static int lua_extension_cmp (lua_State *L)
 [lua_CFunction] Compare two extensions (for access from lua, don't call directly)
static int lua_find_extension (lua_State *L, const char *context, const char *exten, int priority, ast_switch_f *func, int push_func)
 Locate an extensions and optionally push the matching function on the stack.
static void lua_free_extensions ()
 Free the internal extensions buffer.
static int lua_func_read (lua_State *L)
 [lua_CFunction] Create a 'variable' object for accessing a dialplan function (for access from lua, don't call directly)
static lua_State * lua_get_state (struct ast_channel *chan)
 Get the lua_State for this channel.
static int lua_get_variable (lua_State *L)
 [lua_CFunction] Return a lua 'variable' object (for access from lua, don't call directly)
static int lua_get_variable_value (lua_State *L)
 [lua_CFunction] Used to get the value of a variable or dialplan function (for access from lua, don't call directly)
static int lua_load_extensions (lua_State *L, struct ast_channel *chan)
 Load the extensions.lua file from the internal buffer.
static int lua_pbx_exec (lua_State *L)
 [lua_CFunction] This function is part of the 'application' metatable and is used to execute applications similar to pbx_exec() (for access from lua, don't call directly)
static int lua_pbx_findapp (lua_State *L)
 [lua_CFunction] Find an app and return it in a lua table (for access from lua, don't call directly)
static void lua_push_variable_table (lua_State *L)
 Push a 'variable' table on the stack for access the channel variable with the given name.
static char * lua_read_extensions_file (lua_State *L, long *size)
 Load the extensions.lua file in to a buffer and execute the file.
static int lua_register_hints (lua_State *L)
 Register dialplan hints for our pbx_lua contexs.
static int lua_register_switches (lua_State *L)
 Register dialplan switches for our pbx_lua contexs.
static int lua_reload_extensions (lua_State *L)
 Reload the extensions file and update the internal buffers if it loads correctly.
static int lua_set_variable (lua_State *L)
 [lua_CFunction] Set the value of a channel variable or dialplan function (for access from lua, don't call directly)
static int lua_set_variable_value (lua_State *L)
 [lua_CFunction] Used to set the value of a variable or dialplan function (for access from lua, don't call directly)
static int lua_sort_extensions (lua_State *L)
 Store the sort order of each context.
static void lua_state_destroy (void *data)
 The destructor for lua_datastore.
static void lua_update_registry (lua_State *L, const char *context, const char *exten, int priority)
 Update the lua registry with the given context, exten, and priority.
static int matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int reload (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Lua PBX Switch" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static struct ast_module_infoast_module_info = &__mod_info
static char * config = "extensions.lua"
static char * config_file_data = NULL
static ast_mutex_t config_file_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static long config_file_size = 0
static struct ast_contextlocal_contexts = NULL
static struct ast_hashtablocal_table = NULL
static struct ast_datastore_info lua_datastore
static struct ast_switch lua_switch
static char * registrar = "pbx_lua"


Detailed Description

Lua PBX Switch.

Author:
Matthew Nicholson <mnicholson@digium.com>

Definition in file pbx_lua.c.


Define Documentation

#define LUA_BUF_SIZE   4096

Definition at line 58 of file pbx_lua.c.

Referenced by lua_get_variable(), and lua_get_variable_value().

#define LUA_EXT_DATA_SIZE   8192

Definition at line 56 of file pbx_lua.c.

Referenced by lua_pbx_exec().

#define LUA_GOTO_DETECTED   5

Definition at line 63 of file pbx_lua.c.

Referenced by exec(), and lua_pbx_exec().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1668 of file pbx_lua.c.

static void __unreg_module ( void   )  [static]

Definition at line 1668 of file pbx_lua.c.

static int canmatch ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 1338 of file pbx_lua.c.

References ast_log(), ast_module_user_add, ast_module_user_remove, LOG_ERROR, lua_find_extension(), and lua_get_state().

Referenced by lua_find_extension().

01339 {
01340    int res;
01341    lua_State *L;
01342    struct ast_module_user *u = ast_module_user_add(chan);
01343    if (!u) {
01344       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01345       return 0;
01346    }
01347 
01348    L = lua_get_state(chan);
01349    if (!L) {
01350       ast_module_user_remove(u);
01351       return 0;
01352    }
01353 
01354    res = lua_find_extension(L, context, exten, priority, &canmatch, 0);
01355 
01356    if (!chan) lua_close(L);
01357    ast_module_user_remove(u);
01358    return res;
01359 }

static int exec ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 1385 of file pbx_lua.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_log(), ast_module_user_add, ast_module_user_remove, exists(), LOG_ERROR, lua_error_function(), lua_find_extension(), lua_get_state(), LUA_GOTO_DETECTED, and lua_update_registry().

01386 {
01387    int res, error_func;
01388    lua_State *L;
01389    struct ast_module_user *u = ast_module_user_add(chan);
01390    if (!u) {
01391       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01392       return -1;
01393    }
01394    
01395    L = lua_get_state(chan);
01396    if (!L) {
01397       ast_module_user_remove(u);
01398       return -1;
01399    }
01400 
01401    lua_pushcfunction(L, &lua_error_function);
01402    error_func = lua_gettop(L);
01403 
01404    /* push the extension function onto the stack */
01405    if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
01406       lua_pop(L, 1); /* pop the debug function */
01407       ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
01408       if (!chan) lua_close(L);
01409       ast_module_user_remove(u);
01410       return -1;
01411    }
01412 
01413    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
01414    if (lua_toboolean(L, -1)) {
01415       ast_autoservice_start(chan);
01416    }
01417    lua_pop(L, 1);
01418 
01419    lua_update_registry(L, context, exten, priority);
01420    
01421    lua_pushstring(L, context);
01422    lua_pushstring(L, exten);
01423    
01424    res = lua_pcall(L, 2, 0, error_func);
01425    if (res) {
01426       if (res == LUA_ERRRUN) {
01427          res = -1;
01428          if (lua_isnumber(L, -1)) {
01429             res = lua_tointeger(L, -1);
01430 
01431             if (res == LUA_GOTO_DETECTED) {
01432                res = 0;
01433             }
01434          } else if (lua_isstring(L, -1)) {
01435             const char *error = lua_tostring(L, -1);
01436             ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
01437          }
01438       } else if (res == LUA_ERRERR) {
01439          res = -1;
01440          ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
01441       } else if (res == LUA_ERRMEM) {
01442          res = -1;
01443          ast_log(LOG_ERROR, "Memory allocation error\n");
01444       }
01445       lua_pop(L, 1);
01446    }
01447    lua_remove(L, error_func);
01448 
01449    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
01450    if (lua_toboolean(L, -1)) {
01451       ast_autoservice_stop(chan);
01452    }
01453    lua_pop(L, 1);
01454 
01455    if (!chan) lua_close(L);
01456    ast_module_user_remove(u);
01457    return res;
01458 }

static int exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 1315 of file pbx_lua.c.

References ast_log(), ast_module_user_add, ast_module_user_remove, exists(), LOG_ERROR, lua_find_extension(), and lua_get_state().

01316 {
01317    int res;
01318    lua_State *L;
01319    struct ast_module_user *u = ast_module_user_add(chan);
01320    if (!u) {
01321       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01322       return 0;
01323    }
01324 
01325    L = lua_get_state(chan);
01326    if (!L) {
01327       ast_module_user_remove(u);
01328       return 0;
01329    }
01330 
01331    res = lua_find_extension(L, context, exten, priority, &exists, 0);
01332 
01333    if (!chan) lua_close(L);
01334    ast_module_user_remove(u);
01335    return res;
01336 }

static int load_module ( void   )  [static]

Definition at line 1649 of file pbx_lua.c.

References ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_switch(), load_or_reload_lua_stuff(), and LOG_ERROR.

01650 {
01651    int res;
01652 
01653    if ((res = load_or_reload_lua_stuff()))
01654       return res;
01655 
01656    if (ast_register_switch(&lua_switch)) {
01657       ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
01658       return AST_MODULE_LOAD_DECLINE;
01659    }
01660 
01661    return AST_MODULE_LOAD_SUCCESS;
01662 }

static int load_or_reload_lua_stuff ( void   )  [static]

Definition at line 1616 of file pbx_lua.c.

References ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, LOG_ERROR, and lua_reload_extensions().

Referenced by load_module(), and reload().

01617 {
01618    int res = AST_MODULE_LOAD_SUCCESS;
01619 
01620    lua_State *L = luaL_newstate();
01621    if (!L) {
01622       ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01623       return AST_MODULE_LOAD_DECLINE;
01624    }
01625 
01626    if (lua_reload_extensions(L)) {
01627       const char *error = lua_tostring(L, -1);
01628       ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01629       res = AST_MODULE_LOAD_DECLINE;
01630    }
01631 
01632    lua_close(L);
01633    return res;
01634 }

static int lua_autoservice_start ( lua_State *  L  )  [static]

[lua_CFunction] Tell pbx_lua to maintain an autoservice on this channel (for access from lua, don't call directly)

Parameters:
L the lua_State to use
This function will set a flag that will cause pbx_lua to maintain an autoservice on this channel. The autoservice will automatically be stopped and restarted before calling applications and functions.

Definition at line 697 of file pbx_lua.c.

References ast_autoservice_start().

Referenced by lua_create_autoservice_functions().

00698 {
00699    struct ast_channel *chan;
00700 
00701    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00702    if (lua_toboolean(L, -1)) {
00703       /* autservice already running */
00704       lua_pop(L, 1);
00705       return 0;
00706    }
00707    lua_pop(L, 1);
00708 
00709    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00710    chan = lua_touserdata(L, -1);
00711    lua_pop(L, 1);
00712 
00713    ast_autoservice_start(chan);
00714 
00715    lua_pushboolean(L, 1);
00716    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00717    return 0;
00718 }

static int lua_autoservice_status ( lua_State *  L  )  [static]

[lua_CFunction] Get the status of the autoservice flag (for access from lua, don't call directly)

Parameters:
L the lua_State to use
Returns:
This function returns the status of the autoservice flag as a boolean to its lua caller.

Definition at line 762 of file pbx_lua.c.

Referenced by lua_create_autoservice_functions().

00763 {
00764    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00765    return 1;
00766 }

static int lua_autoservice_stop ( lua_State *  L  )  [static]

[lua_CFunction] Tell pbx_lua to stop maintaning an autoservice on this channel (for access from lua, don't call directly)

Parameters:
L the lua_State to use
This function will stop any autoservice running and turn off the autoservice flag. If this function returns false, it's probably because no autoservice was running to begin with.

Definition at line 730 of file pbx_lua.c.

References ast_autoservice_stop().

Referenced by lua_create_autoservice_functions().

00731 {
00732    struct ast_channel *chan;
00733 
00734    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00735    if (!lua_toboolean(L, -1)) {
00736       /* no autservice running */
00737       lua_pop(L, 1);
00738       return 0;
00739    }
00740    lua_pop(L, 1);
00741 
00742    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00743    chan = lua_touserdata(L, -1);
00744    lua_pop(L, 1);
00745 
00746    ast_autoservice_stop(chan);
00747 
00748    lua_pushboolean(L, 0);
00749    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00750    return 0;
00751 }

static int lua_check_hangup ( lua_State *  L  )  [static]

[lua_CFunction] Check if this channel has been hungup or not (for access from lua, don't call directly)

Parameters:
L the lua_State to use
Returns:
This function returns true if the channel was hungup

Definition at line 776 of file pbx_lua.c.

References ast_check_hangup().

Referenced by lua_create_hangup_function().

00777 {
00778    struct ast_channel *chan;
00779    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00780    chan = lua_touserdata(L, -1);
00781    lua_pop(L, 1);
00782 
00783    lua_pushboolean(L, ast_check_hangup(chan));
00784    return 1;
00785 }

static void lua_concat_args ( lua_State *  L,
int  start,
int  nargs 
) [static]

Concatenate a list of lua function arguments into a comma separated string.

Parameters:
L the lua_State to use
start the index of the first argument
nargs the number of args
The resulting string will be left on the top of the stack.

Definition at line 633 of file pbx_lua.c.

Referenced by lua_func_read(), and lua_pbx_exec().

00633                                                                 {
00634    int concat = 0;
00635    int i = start + 1;
00636 
00637    if (start <= nargs && !lua_isnil(L, start)) {
00638       lua_pushvalue(L, start);
00639       concat += 1;
00640    }
00641 
00642    for (; i <= nargs; i++) {
00643       if (lua_isnil(L, i)) {
00644          lua_pushliteral(L, ",");
00645          concat += 1;
00646       } else {
00647          lua_pushliteral(L, ",");
00648          lua_pushvalue(L, i);
00649          concat += 2;
00650       }
00651    }
00652 
00653    lua_concat(L, concat);
00654 }

static void lua_create_app_table ( lua_State *  L  )  [static]

Create the global 'app' table for executing applications.

Parameters:
L the lua_State to use

Definition at line 447 of file pbx_lua.c.

References lua_pbx_findapp().

Referenced by lua_load_extensions().

00448 {
00449    lua_newtable(L);
00450    luaL_newmetatable(L, "app");
00451 
00452    lua_pushstring(L, "__index");
00453    lua_pushcfunction(L, &lua_pbx_findapp);
00454    lua_settable(L, -3);
00455 
00456    lua_setmetatable(L, -2);
00457    lua_setglobal(L, "app");
00458 }

static void lua_create_application_metatable ( lua_State *  L  )  [static]

Create the 'application' metatable, used to execute asterisk applications from lua.

Parameters:
L the lua_State to use

Definition at line 504 of file pbx_lua.c.

References lua_pbx_exec().

Referenced by lua_load_extensions().

00505 {
00506    luaL_newmetatable(L, "application");
00507 
00508    lua_pushstring(L, "__call");
00509    lua_pushcfunction(L, &lua_pbx_exec);
00510    lua_settable(L, -3);
00511 
00512    lua_pop(L, 1);
00513 }

static void lua_create_autoservice_functions ( lua_State *  L  )  [static]

Create the autoservice functions.

Parameters:
L the lua_State to use

Definition at line 520 of file pbx_lua.c.

References lua_autoservice_start(), lua_autoservice_status(), and lua_autoservice_stop().

Referenced by lua_load_extensions().

00521 {
00522    lua_pushcfunction(L, &lua_autoservice_start);
00523    lua_setglobal(L, "autoservice_start");
00524    
00525    lua_pushcfunction(L, &lua_autoservice_stop);
00526    lua_setglobal(L, "autoservice_stop");
00527 
00528    lua_pushcfunction(L, &lua_autoservice_status);
00529    lua_setglobal(L, "autoservice_status");
00530 
00531    lua_pushboolean(L, 1);
00532    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00533 }

static void lua_create_channel_table ( lua_State *  L  )  [static]

Create the global 'channel' table for accesing channel variables.

Parameters:
L the lua_State to use

Definition at line 465 of file pbx_lua.c.

References lua_get_variable(), and lua_set_variable().

Referenced by lua_load_extensions().

00466 {
00467    lua_newtable(L);
00468    luaL_newmetatable(L, "channel_data");
00469 
00470    lua_pushstring(L, "__index");
00471    lua_pushcfunction(L, &lua_get_variable);
00472    lua_settable(L, -3);
00473 
00474    lua_pushstring(L, "__newindex");
00475    lua_pushcfunction(L, &lua_set_variable);
00476    lua_settable(L, -3);
00477 
00478    lua_setmetatable(L, -2);
00479    lua_setglobal(L, "channel");
00480 }

static void lua_create_hangup_function ( lua_State *  L  )  [static]

Create the hangup check function.

Parameters:
L the lua_State to use

Definition at line 540 of file pbx_lua.c.

References lua_check_hangup().

Referenced by lua_load_extensions().

00541 {
00542    lua_pushcfunction(L, &lua_check_hangup);
00543    lua_setglobal(L, "check_hangup");
00544 }

static void lua_create_variable_metatable ( lua_State *  L  )  [static]

Create the 'variable' metatable, used to retrieve channel variables.

Parameters:
L the lua_State to use

Definition at line 487 of file pbx_lua.c.

References lua_func_read().

Referenced by lua_load_extensions().

00488 {
00489    luaL_newmetatable(L, "variable");
00490 
00491    lua_pushstring(L, "__call");
00492    lua_pushcfunction(L, &lua_func_read);
00493    lua_settable(L, -3);
00494 
00495    lua_pop(L, 1);
00496 }

static void lua_datastore_fixup ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
) [static]

The fixup function for the lua_datastore.

Parameters:
data the datastore data, in this case it will be a lua_State
old_chan the channel we are moving from
new_chan the channel we are moving to
This function updates our internal channel pointer.

Definition at line 139 of file pbx_lua.c.

00140 {
00141    lua_State *L = data;
00142    lua_pushlightuserdata(L, new_chan);
00143    lua_setfield(L, LUA_REGISTRYINDEX, "channel");
00144 }

static int lua_error_function ( lua_State *  L  )  [static]

[lua_CFunction] Handle lua errors (for access from lua, don't call directly)

Parameters:
L the lua_State to use

Definition at line 793 of file pbx_lua.c.

Referenced by exec(), and lua_read_extensions_file().

00794 {
00795    int message_index;
00796 
00797    /* pass number arguments right through back to asterisk*/
00798    if (lua_isnumber(L, -1)) {
00799       return 1;
00800    }
00801 
00802    /* if we are here then we have a string error message, let's attach a
00803     * backtrace to it */
00804    message_index = lua_gettop(L);
00805 
00806    /* prepare to prepend a new line to the traceback */
00807    lua_pushliteral(L, "\n");
00808 
00809    lua_getglobal(L, "debug");
00810    lua_getfield(L, -1, "traceback");
00811    lua_remove(L, -2); /* remove the 'debug' table */
00812 
00813    lua_pushvalue(L, message_index);
00814    lua_remove(L, message_index);
00815 
00816    lua_pushnumber(L, 2);
00817 
00818    lua_call(L, 2, 1);
00819 
00820    /* prepend the new line we prepared above */
00821    lua_concat(L, 2);
00822 
00823    return 1;
00824 }

static int lua_extension_cmp ( lua_State *  L  )  [static]

[lua_CFunction] Compare two extensions (for access from lua, don't call directly)

This function returns true if the first extension passed should match after the second. It behaves like the '<' operator.

Definition at line 1054 of file pbx_lua.c.

References ast_extension_cmp().

Referenced by lua_sort_extensions().

01055 {
01056    const char *a = luaL_checkstring(L, -2);
01057    const char *b = luaL_checkstring(L, -1);
01058 
01059    if (ast_extension_cmp(a, b) == -1)
01060       lua_pushboolean(L, 1);
01061    else
01062       lua_pushboolean(L, 0);
01063 
01064    return 1;
01065 }

static int lua_find_extension ( lua_State *  L,
const char *  context,
const char *  exten,
int  priority,
ast_switch_f func,
int  push_func 
) [static]

Locate an extensions and optionally push the matching function on the stack.

Parameters:
L the lua_State to use
context the context to look in
exten the extension to look up
priority the priority to check, '1' is the only valid priority
func the calling func, used to adjust matching behavior between, match, canmatch, and matchmore
push_func whether or not to push the lua function for the given extension onto the stack

Definition at line 1473 of file pbx_lua.c.

References ast_debug, ast_extension_close(), ast_extension_match(), ast_log(), canmatch(), E_CANMATCH, E_MATCHMORE, LOG_ERROR, match(), and matchmore().

Referenced by canmatch(), exec(), exists(), and matchmore().

01474 {
01475    int context_table, context_order_table, i;
01476 
01477    ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
01478    if (priority != 1)
01479       return 0;
01480 
01481    /* load the 'extensions' table */
01482    lua_getglobal(L, "extensions");
01483    if (lua_isnil(L, -1)) {
01484       ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
01485       lua_pop(L, 1);
01486       return 0;
01487    }
01488 
01489    /* load the given context */
01490    lua_getfield(L, -1, context);
01491    if (lua_isnil(L, -1)) {
01492       lua_pop(L, 2);
01493       return 0;
01494    }
01495 
01496    /* remove the extensions table */
01497    lua_remove(L, -2);
01498 
01499    context_table = lua_gettop(L);
01500 
01501    /* load the extensions order table for this context */
01502    lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
01503    lua_getfield(L, -1, context);
01504 
01505    lua_remove(L, -2);  /* remove the extensions order table */
01506 
01507    context_order_table = lua_gettop(L);
01508    
01509    /* step through the extensions looking for a match */
01510    for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
01511       int e_index_copy, match = 0;
01512       const char *e;
01513 
01514       lua_pushinteger(L, i);
01515       lua_gettable(L, context_order_table);
01516       lua_gettop(L);
01517 
01518       /* copy the key at the top of the stack for use later */
01519       lua_pushvalue(L, -1);
01520       e_index_copy = lua_gettop(L);
01521 
01522       if (!(e = lua_tostring(L, e_index_copy))) {
01523          lua_pop(L, 2);
01524          continue;
01525       }
01526 
01527       /* make sure this is not the 'include' extension */
01528       if (!strcasecmp(e, "include")) {
01529          lua_pop(L, 2);
01530          continue;
01531       }
01532 
01533       if (func == &matchmore)
01534          match = ast_extension_close(e, exten, E_MATCHMORE);
01535       else if (func == &canmatch)
01536          match = ast_extension_close(e, exten, E_CANMATCH);
01537       else
01538          match = ast_extension_match(e, exten);
01539 
01540       /* the extension matching functions return 0 on fail, 1 on
01541        * match, 2 on earlymatch */
01542 
01543       if (!match) {
01544          /* pop the copy and the extension */
01545          lua_pop(L, 2);
01546          continue;   /* keep trying */
01547       }
01548 
01549       if (func == &matchmore && match == 2) {
01550          /* We match an extension ending in '!'. The decision in
01551           * this case is final and counts as no match. */
01552          lua_pop(L, 4);
01553          return 0;
01554       }
01555 
01556       /* remove the context table, the context order table, the
01557        * extension, and the extension copy (or replace the extension
01558        * with the corresponding function) */
01559       if (push_func) {
01560          lua_pop(L, 1);  /* pop the copy */
01561          lua_gettable(L, context_table);
01562          lua_insert(L, -3);
01563          lua_pop(L, 2);
01564       } else {
01565          lua_pop(L, 4);
01566       }
01567 
01568       return 1;
01569    }
01570 
01571    /* load the includes for this context */
01572    lua_getfield(L, context_table, "include");
01573    if (lua_isnil(L, -1)) {
01574       lua_pop(L, 3);
01575       return 0;
01576    }
01577 
01578    /* remove the context and the order table*/
01579    lua_remove(L, context_order_table);
01580    lua_remove(L, context_table);
01581 
01582    /* Now try any includes we have in this context */
01583    for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
01584       const char *c = lua_tostring(L, -1);
01585       if (!c)
01586          continue;
01587 
01588       if (lua_find_extension(L, c, exten, priority, func, push_func)) {
01589          /* remove the value, the key, and the includes table
01590           * from the stack.  Leave the function behind if
01591           * necessary */
01592 
01593          if (push_func)
01594             lua_insert(L, -4);
01595 
01596          lua_pop(L, 3);
01597          return 1;
01598       }
01599    }
01600 
01601    /* pop the includes table */
01602    lua_pop(L, 1);
01603    return 0;
01604 }

static void lua_free_extensions ( void   )  [static]

Free the internal extensions buffer.

Definition at line 1232 of file pbx_lua.c.

References ast_free, ast_mutex_lock, ast_mutex_unlock, and config_file_lock.

Referenced by unload_module().

static int lua_func_read ( lua_State *  L  )  [static]

[lua_CFunction] Create a 'variable' object for accessing a dialplan function (for access from lua, don't call directly)

This function is called to create a 'variable' object to access a dialplan function. It would be called in the following example as would be seen in extensions.lua.

 channel.func("arg1", "arg2", "arg3")

To actually do anything with the resulting value you must use the 'get()' and 'set()' methods (the reason is the resulting value is not a value, but an object in the form of a lua table).

Definition at line 672 of file pbx_lua.c.

References lua_concat_args(), and lua_push_variable_table().

Referenced by lua_create_variable_metatable().

00673 {
00674    int nargs = lua_gettop(L);
00675 
00676    /* build a string in the form of "func_name(arg1,arg2,arg3)" */
00677    lua_getfield(L, 1, "name");
00678    lua_pushliteral(L, "(");
00679    lua_concat_args(L, 2, nargs);
00680    lua_pushliteral(L, ")");
00681    lua_concat(L, 4);
00682 
00683    lua_push_variable_table(L);
00684    return 1;
00685 }

static lua_State * lua_get_state ( struct ast_channel chan  )  [static]

Get the lua_State for this channel.

If no channel is passed then a new state is allocated. States with no channel assocatied with them should only be used for matching extensions. If the channel does not yet have a lua state associated with it, one will be created.

Note:
If no channel was passed then the caller is expected to free the state using lua_close().
Returns:
a lua_State

Definition at line 1253 of file pbx_lua.c.

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), ast_log(), ast_datastore::data, LOG_ERROR, and lua_load_extensions().

Referenced by canmatch(), exec(), exists(), and matchmore().

01254 {
01255    struct ast_datastore *datastore = NULL;
01256    lua_State *L;
01257 
01258    if (!chan) {
01259       L = luaL_newstate();
01260       if (!L) {
01261          ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01262          return NULL;
01263       }
01264 
01265       if (lua_load_extensions(L, NULL)) {
01266          const char *error = lua_tostring(L, -1);
01267          ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01268          lua_close(L);
01269          return NULL;
01270       }
01271       return L;
01272    } else {
01273       ast_channel_lock(chan);
01274       datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
01275       ast_channel_unlock(chan);
01276 
01277       if (!datastore) {
01278          /* nothing found, allocate a new lua state */
01279          datastore = ast_datastore_alloc(&lua_datastore, NULL);
01280          if (!datastore) {
01281             ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
01282             return NULL;
01283          }
01284 
01285          datastore->data = luaL_newstate();
01286          if (!datastore->data) {
01287             ast_datastore_free(datastore);
01288             ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01289             return NULL;
01290          }
01291 
01292          ast_channel_lock(chan);
01293          ast_channel_datastore_add(chan, datastore);
01294          ast_channel_unlock(chan);
01295 
01296          L = datastore->data;
01297 
01298          if (lua_load_extensions(L, chan)) {
01299             const char *error = lua_tostring(L, -1);
01300             ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", ast_channel_name(chan), error);
01301 
01302             ast_channel_lock(chan);
01303             ast_channel_datastore_remove(chan, datastore);
01304             ast_channel_unlock(chan);
01305 
01306             ast_datastore_free(datastore);
01307             return NULL;
01308          }
01309       }
01310 
01311       return datastore->data;
01312    }
01313 }

static int lua_get_variable ( lua_State *  L  )  [static]

[lua_CFunction] Return a lua 'variable' object (for access from lua, don't call directly)

This function is called to lookup a variable construct a 'variable' object. It would be called in the following example as would be seen in extensions.lua.

 channel.variable

Definition at line 558 of file pbx_lua.c.

References ast_alloca, ast_channel_varshead(), ast_strlen_zero(), LUA_BUF_SIZE, lua_push_variable_table(), name, pbx_retrieve_variable(), and value.

Referenced by lua_create_channel_table().

00559 {
00560    struct ast_channel *chan;
00561    const char *name = luaL_checkstring(L, 2);
00562    char *value = NULL;
00563    char *workspace = ast_alloca(LUA_BUF_SIZE);
00564    workspace[0] = '\0';
00565    
00566    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00567    chan = lua_touserdata(L, -1);
00568    lua_pop(L, 1);
00569 
00570    lua_pushvalue(L, 2);
00571    lua_push_variable_table(L);
00572    
00573    /* if this is not a request for a dialplan funciton attempt to retrieve
00574     * the value of the variable */
00575    if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') {
00576       pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan));
00577    }
00578 
00579    if (value) {
00580       lua_pushstring(L, value);
00581       lua_setfield(L, -2, "value");
00582    }
00583 
00584    return 1;   
00585 }

static int lua_get_variable_value ( lua_State *  L  )  [static]

[lua_CFunction] Used to get the value of a variable or dialplan function (for access from lua, don't call directly)

The value of the variable or function is returned. This function is the 'get()' function in the following example as would be seen in extensions.lua.

 channel.variable:get()

Definition at line 302 of file pbx_lua.c.

References ast_alloca, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_varshead(), ast_func_read(), ast_strdupa, ast_strlen_zero(), LUA_BUF_SIZE, name, pbx_retrieve_variable(), and value.

Referenced by lua_push_variable_table().

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 }

static int lua_load_extensions ( lua_State *  L,
struct ast_channel chan 
) [static]

Load the extensions.lua file from the internal buffer.

Parameters:
L the lua_State to use
chan channel to work on
This function also sets up some constructs used by the extensions.lua file. In the event of an error, an error string will be pushed onto the lua stack.

Return values:
0 success
1 failure

Definition at line 1154 of file pbx_lua.c.

References ast_mutex_lock, ast_mutex_unlock, config_file_lock, lua_create_app_table(), lua_create_application_metatable(), lua_create_autoservice_functions(), lua_create_channel_table(), lua_create_hangup_function(), lua_create_variable_metatable(), and lua_sort_extensions().

Referenced by lua_get_state().

01155 {
01156    
01157    /* store a pointer to this channel */
01158    lua_pushlightuserdata(L, chan);
01159    lua_setfield(L, LUA_REGISTRYINDEX, "channel");
01160    
01161    luaL_openlibs(L);
01162 
01163    /* load and sort extensions */
01164    ast_mutex_lock(&config_file_lock);
01165    if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
01166          || lua_pcall(L, 0, LUA_MULTRET, 0)
01167          || lua_sort_extensions(L)) {
01168       ast_mutex_unlock(&config_file_lock);
01169       return 1;
01170    }
01171    ast_mutex_unlock(&config_file_lock);
01172 
01173    /* now we setup special tables and functions */
01174 
01175    lua_create_app_table(L);
01176    lua_create_channel_table(L);
01177 
01178    lua_create_variable_metatable(L);
01179    lua_create_application_metatable(L);
01180 
01181    lua_create_autoservice_functions(L);
01182    lua_create_hangup_function(L);
01183 
01184    return 0;
01185 }

static int lua_pbx_exec ( lua_State *  L  )  [static]

[lua_CFunction] This function is part of the 'application' metatable and is used to execute applications similar to pbx_exec() (for access from lua, don't call directly)

Parameters:
L the lua_State to use
Returns:
nothing
This funciton is executed as the '()' operator for apps accessed through the 'app' table.

 app.playback('demo-congrats')

Definition at line 188 of file pbx_lua.c.

References app, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_context(), ast_channel_exten(), ast_channel_name(), ast_channel_priority(), ast_debug, ast_strdupa, ast_verb, COLOR_BRCYAN, COLOR_BRMAGENTA, context, exten, lua_concat_args(), LUA_EXT_DATA_SIZE, LUA_GOTO_DETECTED, lua_update_registry(), pbx_exec(), pbx_findapp(), and term_color().

Referenced by lua_create_application_metatable().

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 }

static int lua_pbx_findapp ( lua_State *  L  )  [static]

[lua_CFunction] Find an app and return it in a lua table (for access from lua, don't call directly)

This function would be called in the following example as it would be found in extensions.lua.

 app.dial

Definition at line 157 of file pbx_lua.c.

Referenced by lua_create_app_table().

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 }

static void lua_push_variable_table ( lua_State *  L  )  [static]

Push a 'variable' table on the stack for access the channel variable with the given name.

The value on the top of the stack is popped and used as the name.

Parameters:
L the lua_State to use

Definition at line 426 of file pbx_lua.c.

References lua_get_variable_value(), and lua_set_variable_value().

Referenced by lua_func_read(), and lua_get_variable().

00427 {
00428    lua_newtable(L);
00429    luaL_getmetatable(L, "variable");
00430    lua_setmetatable(L, -2);
00431 
00432    lua_insert(L, -2); /* move the table after the name */
00433    lua_setfield(L, -2, "name");
00434    
00435    lua_pushcfunction(L, &lua_get_variable_value);
00436    lua_setfield(L, -2, "get");
00437    
00438    lua_pushcfunction(L, &lua_set_variable_value);
00439    lua_setfield(L, -2, "set");
00440 }

static char * lua_read_extensions_file ( lua_State *  L,
long *  size 
) [static]

Load the extensions.lua file in to a buffer and execute the file.

Parameters:
L the lua_State to use
size a pointer to store the size of the buffer
Note:
The caller is expected to free the buffer at some point.
Returns:
a pointer to the buffer

Definition at line 1077 of file pbx_lua.c.

References ast_alloca, ast_config_AST_CONFIG_DIR, ast_free, ast_malloc, errno, f, lua_error_function(), lua_register_hints(), lua_register_switches(), and lua_sort_extensions().

Referenced by lua_reload_extensions().

01078 {
01079    FILE *f;
01080    int error_func;
01081    char *data;
01082    char *path = ast_alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
01083    sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
01084 
01085    if (!(f = fopen(path, "r"))) {
01086       lua_pushstring(L, "cannot open '");
01087       lua_pushstring(L, path);
01088       lua_pushstring(L, "' for reading: ");
01089       lua_pushstring(L, strerror(errno));
01090       lua_concat(L, 4);
01091 
01092       return NULL;
01093    }
01094 
01095    if (fseek(f, 0l, SEEK_END)) {
01096       fclose(f);
01097       lua_pushliteral(L, "error determining the size of the config file");
01098       return NULL;
01099    }
01100 
01101    *size = ftell(f);
01102 
01103    if (fseek(f, 0l, SEEK_SET)) {
01104       *size = 0;
01105       fclose(f);
01106       lua_pushliteral(L, "error reading config file");
01107       return NULL;
01108    }
01109 
01110    if (!(data = ast_malloc(*size))) {
01111       *size = 0;
01112       fclose(f);
01113       lua_pushstring(L, "not enough memory");
01114       return NULL;
01115    }
01116 
01117    if (fread(data, sizeof(char), *size, f) != *size) {
01118       *size = 0;
01119       fclose(f);
01120       lua_pushliteral(L, "problem reading configuration file");
01121       return NULL;
01122    }
01123    fclose(f);
01124 
01125    lua_pushcfunction(L, &lua_error_function);
01126    error_func = lua_gettop(L);
01127 
01128    if (luaL_loadbuffer(L, data, *size, "extensions.lua")
01129          || lua_pcall(L, 0, LUA_MULTRET, error_func)
01130          || lua_sort_extensions(L)
01131          || lua_register_switches(L)
01132          || lua_register_hints(L)) {
01133       ast_free(data);
01134       data = NULL;
01135       *size = 0;
01136    }
01137 
01138    lua_remove(L, error_func);
01139    return data;
01140 }

static int lua_register_hints ( lua_State *  L  )  [static]

Register dialplan hints for our pbx_lua contexs.

In the event of an error, an error string will be pushed onto the lua stack.

Return values:
0 success
1 failure

Definition at line 974 of file pbx_lua.c.

References ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), context, hints, and PRIORITY_HINT.

Referenced by lua_read_extensions_file().

00975 {
00976    int hints;
00977    struct ast_context *con = NULL;
00978 
00979    /* create the hash table for our contexts */
00980    /* XXX do we ever need to destroy this? pbx_config does not */
00981    if (!local_table)
00982       local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
00983 
00984    /* load the 'hints' table */
00985    lua_getglobal(L, "hints");
00986    hints = lua_gettop(L);
00987    if (lua_isnil(L, -1)) {
00988       /* hints table not found, move along */
00989       lua_pop(L, 1);
00990       return 0;
00991    }
00992 
00993    /* iterate through the hints table and register each context and
00994     * the hints that go along with it
00995     */
00996    for (lua_pushnil(L); lua_next(L, hints); lua_pop(L, 1)) {
00997       int context = lua_gettop(L);
00998       int context_name = context - 1;
00999       const char *context_str = lua_tostring(L, context_name);
01000 
01001       /* find or create this context */
01002       con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
01003       if (!con) {
01004          /* remove hints table and context key and value */
01005          lua_pop(L, 3);
01006          lua_pushstring(L, "Failed to find or create context\n");
01007          return 1;
01008       }
01009 
01010       /* register each hint */
01011       for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
01012          const char *hint_value = lua_tostring(L, -1);
01013          const char *hint_name;
01014 
01015          /* the hint value is not a string, ignore it */
01016          if (!hint_value) {
01017             continue;
01018          }
01019 
01020          /* copy the name then convert it to a string */
01021          lua_pushvalue(L, -2);
01022          if (!(hint_name = lua_tostring(L, -1))) {
01023             /* ignore non-string value */
01024             lua_pop(L, 1);
01025             continue;
01026          }
01027 
01028          if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar)) {
01029             /* remove hints table, hint name, hint value,
01030              * key copy, context name, and contex table */
01031             lua_pop(L, 6);
01032             lua_pushstring(L, "Error creating hint\n");
01033             return 1;
01034          }
01035 
01036          /* pop the name copy */
01037          lua_pop(L, 1);
01038       }
01039    }
01040 
01041    /* remove the hints table */
01042    lua_pop(L, 1);
01043 
01044    return 0;
01045 }

static int lua_register_switches ( lua_State *  L  )  [static]

Register dialplan switches for our pbx_lua contexs.

In the event of an error, an error string will be pushed onto the lua stack.

Return values:
0 success
1 failure

Definition at line 916 of file pbx_lua.c.

References ast_context_add_switch2(), ast_context_find_or_create(), ast_hashtab_compare_contexts(), ast_hashtab_create(), ast_hashtab_hash_contexts(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), and context.

Referenced by lua_read_extensions_file().

00917 {
00918    int extensions;
00919    struct ast_context *con = NULL;
00920 
00921    /* create the hash table for our contexts */
00922    /* XXX do we ever need to destroy this? pbx_config does not */
00923    if (!local_table)
00924       local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
00925 
00926    /* load the 'extensions' table */
00927    lua_getglobal(L, "extensions");
00928    extensions = lua_gettop(L);
00929    if (lua_isnil(L, -1)) {
00930       lua_pop(L, 1);
00931       lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00932       return 1;
00933    }
00934 
00935    /* iterate through the extensions table and register a context and
00936     * dialplan switch for each lua context
00937     */
00938    for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00939       int context = lua_gettop(L);
00940       int context_name = context - 1;
00941       const char *context_str = lua_tostring(L, context_name);
00942 
00943       /* find or create this context */
00944       con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
00945       if (!con) {
00946          /* remove extensions table and context key and value */
00947          lua_pop(L, 3);
00948          lua_pushstring(L, "Failed to find or create context\n");
00949          return 1;
00950       }
00951 
00952       /* register the switch */
00953       if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
00954          /* remove extensions table and context key and value */
00955          lua_pop(L, 3);
00956          lua_pushstring(L, "Unable to create switch for context\n");
00957          return 1;
00958       }
00959    }
00960    
00961    /* remove the extensions table */
00962    lua_pop(L, 1);
00963    return 0;
00964 }

static int lua_reload_extensions ( lua_State *  L  )  [static]

Reload the extensions file and update the internal buffers if it loads correctly.

Warning:
This function should not be called on a lua_State returned from lua_get_state().
Parameters:
L the lua_State to use (must be freshly allocated with luaL_newstate(), don't use lua_get_state())

Definition at line 1197 of file pbx_lua.c.

References ast_free, ast_merge_contexts_and_delete(), ast_mutex_lock, ast_mutex_unlock, config_file_lock, and lua_read_extensions_file().

Referenced by load_or_reload_lua_stuff().

01198 {
01199    long size = 0;
01200    char *data = NULL;
01201 
01202    luaL_openlibs(L);
01203 
01204    if (!(data = lua_read_extensions_file(L, &size))) {
01205       return 1;
01206    }
01207 
01208    ast_mutex_lock(&config_file_lock);
01209 
01210    if (config_file_data)
01211       ast_free(config_file_data);
01212 
01213    config_file_data = data;
01214    config_file_size = size;
01215    
01216    /* merge our new contexts */
01217    ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
01218    /* merge_contexts_and_delete will actually, at the correct moment, 
01219       set the global dialplan pointers to your local_contexts and local_table.
01220       It then will free up the old tables itself. Just be sure not to
01221       hang onto the pointers. */
01222    local_table = NULL;
01223    local_contexts = NULL;
01224 
01225    ast_mutex_unlock(&config_file_lock);
01226    return 0;
01227 }

static int lua_set_variable ( lua_State *  L  )  [static]

[lua_CFunction] Set the value of a channel variable or dialplan function (for access from lua, don't call directly)

This function is called to set a variable or dialplan function. It would be called in the following example as would be seen in extensions.lua.

 channel.variable = "value"

Definition at line 598 of file pbx_lua.c.

References ast_autoservice_start(), ast_autoservice_stop(), name, pbx_builtin_setvar_helper(), and value.

Referenced by lua_create_channel_table().

00599 {
00600    struct ast_channel *chan;
00601    int autoservice;
00602    const char *name = luaL_checkstring(L, 2);
00603    const char *value = luaL_checkstring(L, 3);
00604 
00605    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00606    chan = lua_touserdata(L, -1);
00607    lua_pop(L, 1);
00608 
00609    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00610    autoservice = lua_toboolean(L, -1);
00611    lua_pop(L, 1);
00612 
00613    if (autoservice)
00614       ast_autoservice_stop(chan);
00615 
00616    pbx_builtin_setvar_helper(chan, name, value);
00617    
00618    if (autoservice)
00619       ast_autoservice_start(chan);
00620 
00621    return 0;
00622 }

static int lua_set_variable_value ( lua_State *  L  )  [static]

[lua_CFunction] Used to set the value of a variable or dialplan function (for access from lua, don't call directly)

This function is the 'set()' function in the following example as would be seen in extensions.lua.

 channel.variable:set("value")

Definition at line 362 of file pbx_lua.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_strdupa, name, pbx_builtin_setvar_helper(), and value.

Referenced by lua_push_variable_table().

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 }

static int lua_sort_extensions ( lua_State *  L  )  [static]

Store the sort order of each context.

In the event of an error, an error string will be pushed onto the lua stack.

Return values:
0 success
1 failure

Definition at line 834 of file pbx_lua.c.

References context, exten, and lua_extension_cmp().

Referenced by lua_load_extensions(), and lua_read_extensions_file().

00835 {
00836    int extensions, extensions_order;
00837 
00838    /* create the extensions_order table */
00839    lua_newtable(L);
00840    lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order");
00841    lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
00842    extensions_order = lua_gettop(L);
00843 
00844    /* sort each context in the extensions table */
00845    /* load the 'extensions' table */
00846    lua_getglobal(L, "extensions");
00847    extensions = lua_gettop(L);
00848    if (lua_isnil(L, -1)) {
00849       lua_pop(L, 1);
00850       lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00851       return 1;
00852    }
00853 
00854    /* iterate through the extensions table and create a
00855     * matching table (holding the sort order) in the
00856     * extensions_order table for each context that is found
00857     */
00858    for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00859       int context = lua_gettop(L);
00860       int context_name = context - 1;
00861       int context_order;
00862 
00863       /* copy the context_name to be used as the key for the
00864        * context_order table in the extensions_order table later */
00865       lua_pushvalue(L, context_name);
00866 
00867       /* create the context_order table */
00868       lua_newtable(L);
00869       context_order = lua_gettop(L);
00870 
00871       /* iterate through this context an popluate the corrisponding
00872        * table in the extensions_order table */
00873       for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
00874          int exten = lua_gettop(L) - 1;
00875 
00876          lua_pushinteger(L, lua_objlen(L, context_order) + 1);
00877          lua_pushvalue(L, exten);
00878          lua_settable(L, context_order);
00879       }
00880       lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */
00881 
00882       /* now sort the new table */
00883 
00884       /* push the table.sort function */
00885       lua_getglobal(L, "table");
00886       lua_getfield(L, -1, "sort");
00887       lua_remove(L, -2); /* remove the 'table' table */
00888 
00889       /* push the context_order table */
00890       lua_pushvalue(L, context_name);
00891       lua_gettable(L, extensions_order);
00892 
00893       /* push the comp function */
00894       lua_pushcfunction(L, &lua_extension_cmp);
00895 
00896       if (lua_pcall(L, 2, 0, 0)) {
00897          lua_insert(L, -5);
00898          lua_pop(L, 4);
00899          return 1;
00900       }
00901    }
00902    
00903    /* remove the extensions table and the extensions_order table */
00904    lua_pop(L, 2);
00905    return 0;
00906 }

static void lua_state_destroy ( void *  data  )  [static]

The destructor for lua_datastore.

Definition at line 125 of file pbx_lua.c.

00126 {
00127    if (data)
00128       lua_close(data);
00129 }

static void lua_update_registry ( lua_State *  L,
const char *  context,
const char *  exten,
int  priority 
) [static]

Update the lua registry with the given context, exten, and priority.

Parameters:
L the lua_State to use
context the new context
exten the new exten
priority the new priority

Definition at line 406 of file pbx_lua.c.

Referenced by exec(), and lua_pbx_exec().

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 }

static int matchmore ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 1361 of file pbx_lua.c.

References ast_log(), ast_module_user_add, ast_module_user_remove, LOG_ERROR, lua_find_extension(), and lua_get_state().

Referenced by complete_dpreply(), and lua_find_extension().

01362 {
01363    int res;
01364    lua_State *L;
01365    struct ast_module_user *u = ast_module_user_add(chan);
01366    if (!u) {
01367       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01368       return 0;
01369    }
01370 
01371    L = lua_get_state(chan);
01372    if (!L) {
01373       ast_module_user_remove(u);
01374       return 0;
01375    }
01376    
01377    res = lua_find_extension(L, context, exten, priority, &matchmore, 0);
01378 
01379    if (!chan) lua_close(L);
01380    ast_module_user_remove(u);
01381    return res;
01382 }

static int reload ( void   )  [static]

Definition at line 1644 of file pbx_lua.c.

References load_or_reload_lua_stuff().

01645 {
01646    return load_or_reload_lua_stuff();
01647 }

static int unload_module ( void   )  [static]

Definition at line 1636 of file pbx_lua.c.

References ast_context_destroy(), ast_unregister_switch(), and lua_free_extensions().

01637 {
01638    ast_context_destroy(NULL, registrar);
01639    ast_unregister_switch(&lua_switch);
01640    lua_free_extensions();
01641    return 0;
01642 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Lua PBX Switch" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1668 of file pbx_lua.c.

Definition at line 1668 of file pbx_lua.c.

char* config = "extensions.lua" [static]

Definition at line 50 of file pbx_lua.c.

char* config_file_data = NULL [static]

Definition at line 109 of file pbx_lua.c.

ast_mutex_t config_file_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 108 of file pbx_lua.c.

Referenced by lua_free_extensions(), lua_load_extensions(), and lua_reload_extensions().

long config_file_size = 0 [static]

Definition at line 110 of file pbx_lua.c.

struct ast_context* local_contexts = NULL [static]

Definition at line 112 of file pbx_lua.c.

struct ast_hashtab* local_table = NULL [static]

Definition at line 113 of file pbx_lua.c.

Initial value:

 {
   .type = "lua",
   .destroy = lua_state_destroy,
   .chan_fixup = lua_datastore_fixup,
}

Definition at line 115 of file pbx_lua.c.

struct ast_switch lua_switch [static]

Definition at line 1606 of file pbx_lua.c.

char* registrar = "pbx_lua" [static]

Definition at line 51 of file pbx_lua.c.


Generated on Thu Oct 11 06:36:51 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6