Fri Feb 10 06:36:59 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 1669 of file pbx_lua.c.

static void __unreg_module ( void   )  [static]

Definition at line 1669 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 1339 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().

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

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 1386 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().

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

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 1316 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().

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

static int load_module ( void   )  [static]

Definition at line 1650 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.

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

static int load_or_reload_lua_stuff ( void   )  [static]

Definition at line 1617 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().

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

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 698 of file pbx_lua.c.

References ast_autoservice_start().

Referenced by lua_create_autoservice_functions().

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 }

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 763 of file pbx_lua.c.

Referenced by lua_create_autoservice_functions().

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

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 731 of file pbx_lua.c.

References ast_autoservice_stop().

Referenced by lua_create_autoservice_functions().

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 }

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 777 of file pbx_lua.c.

References ast_check_hangup().

Referenced by lua_create_hangup_function().

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 }

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 634 of file pbx_lua.c.

Referenced by lua_func_read(), and lua_pbx_exec().

00634                                                                 {
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 }

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 448 of file pbx_lua.c.

References lua_pbx_findapp().

Referenced by lua_load_extensions().

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 }

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 505 of file pbx_lua.c.

References lua_pbx_exec().

Referenced by lua_load_extensions().

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 }

static void lua_create_autoservice_functions ( lua_State *  L  )  [static]

Create the autoservice functions.

Parameters:
L the lua_State to use

Definition at line 521 of file pbx_lua.c.

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

Referenced by lua_load_extensions().

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 }

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 466 of file pbx_lua.c.

References lua_get_variable(), and lua_set_variable().

Referenced by lua_load_extensions().

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 }

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 541 of file pbx_lua.c.

References lua_check_hangup().

Referenced by lua_load_extensions().

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

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 488 of file pbx_lua.c.

References lua_func_read().

Referenced by lua_load_extensions().

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 }

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 794 of file pbx_lua.c.

Referenced by exec(), and lua_read_extensions_file().

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 }

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 1055 of file pbx_lua.c.

References ast_extension_cmp().

Referenced by lua_sort_extensions().

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

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 1474 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().

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

static void lua_free_extensions ( void   )  [static]

Free the internal extensions buffer.

Definition at line 1233 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 673 of file pbx_lua.c.

References lua_concat_args(), and lua_push_variable_table().

Referenced by lua_create_variable_metatable().

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 }

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 1254 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().

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

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 559 of file pbx_lua.c.

References ast_strlen_zero(), LUA_BUF_SIZE, lua_push_variable_table(), name, pbx_retrieve_variable(), value, and ast_channel::varshead.

Referenced by lua_create_channel_table().

00560 {
00561    struct ast_channel *chan;
00562    const char *name = luaL_checkstring(L, 2);
00563    char *value = NULL;
00564    char *workspace = 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, &chan->varshead);
00578    }
00579 
00580    if (value) {
00581       lua_pushstring(L, value);
00582       lua_setfield(L, -2, "value");
00583    }
00584 
00585    return 1;   
00586 }

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_autoservice_start(), ast_autoservice_stop(), ast_func_read(), ast_strdupa, ast_strlen_zero(), LUA_BUF_SIZE, name, pbx_retrieve_variable(), value, and ast_channel::varshead.

Referenced by lua_push_variable_table().

00303 {
00304    struct ast_channel *chan;
00305    char *value = NULL, *name;
00306    char *workspace = 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, &chan->varshead);
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 1155 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().

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

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_name(), ast_debug, ast_strdupa, ast_verb, COLOR_BRCYAN, COLOR_BRMAGENTA, ast_channel::context, context, ast_channel::exten, exten, lua_concat_args(), LUA_EXT_DATA_SIZE, LUA_GOTO_DETECTED, lua_update_registry(), pbx_exec(), pbx_findapp(), ast_channel::priority, 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(chan->context);
00216    exten = ast_strdupa(chan->exten);
00217    priority = chan->priority;
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, chan->context)) {
00250       lua_pushstring(L, context);
00251       lua_pushstring(L, chan->context);
00252       lua_pushliteral(L, "context");
00253    } else if (strcmp(exten, chan->exten)) {
00254       lua_pushstring(L, exten);
00255       lua_pushstring(L, chan->exten);
00256       lua_pushliteral(L, "exten");
00257    } else if (priority != chan->priority) {
00258       lua_pushinteger(L, priority);
00259       lua_pushinteger(L, chan->priority);
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
name the name of the variable

Definition at line 427 of file pbx_lua.c.

References lua_get_variable_value(), and lua_set_variable_value().

Referenced by lua_func_read(), and lua_get_variable().

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 }

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 1078 of file pbx_lua.c.

References 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().

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

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 975 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().

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

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 917 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().

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

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 1198 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().

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

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 599 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().

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 }

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 835 of file pbx_lua.c.

References context, exten, and lua_extension_cmp().

Referenced by lua_load_extensions(), and lua_read_extensions_file().

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 
00877          lua_pushinteger(L, lua_objlen(L, context_order) + 1);
00878          lua_pushvalue(L, exten);
00879          lua_settable(L, context_order);
00880       }
00881       lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */
00882 
00883       /* now sort the new table */
00884 
00885       /* push the table.sort function */
00886       lua_getglobal(L, "table");
00887       lua_getfield(L, -1, "sort");
00888       lua_remove(L, -2); /* remove the 'table' table */
00889 
00890       /* push the context_order table */
00891       lua_pushvalue(L, context_name);
00892       lua_gettable(L, extensions_order);
00893 
00894       /* push the comp function */
00895       lua_pushcfunction(L, &lua_extension_cmp);
00896 
00897       if (lua_pcall(L, 2, 0, 0)) {
00898          lua_insert(L, -5);
00899          lua_pop(L, 4);
00900          return 1;
00901       }
00902    }
00903    
00904    /* remove the extensions table and the extensions_order table */
00905    lua_pop(L, 2);
00906    return 0;
00907 }

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 1362 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().

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

static int reload ( void   )  [static]

Definition at line 1645 of file pbx_lua.c.

References load_or_reload_lua_stuff().

01646 {
01647    return load_or_reload_lua_stuff();
01648 }

static int unload_module ( void   )  [static]

Definition at line 1637 of file pbx_lua.c.

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

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


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 1669 of file pbx_lua.c.

Definition at line 1669 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 1607 of file pbx_lua.c.

char* registrar = "pbx_lua" [static]

Definition at line 51 of file pbx_lua.c.


Generated on Fri Feb 10 06:36:59 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6