Wed Jan 27 20:02:45 2016

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>

Go to the source code of this file.

Defines

#define LUA_BUF_SIZE   4096
#define LUA_EXT_DATA_SIZE   8192

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_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 = "ac1f6a56484a8820659555499174e588" , .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_RECURSIVE_MUTEX_INITIALIZER_NP , 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().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1569 of file pbx_lua.c.

static void __unreg_module ( void   )  [static]

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

01236 {
01237    int res;
01238    lua_State *L;
01239    struct ast_module_user *u = ast_module_user_add(chan);
01240    if (!u) {
01241       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01242       return 0;
01243    }
01244 
01245    L = lua_get_state(chan);
01246    if (!L) {
01247       ast_module_user_remove(u);
01248       return 0;
01249    }
01250 
01251    res = lua_find_extension(L, context, exten, priority, &canmatch, 0);
01252 
01253    if (!chan) lua_close(L);
01254    ast_module_user_remove(u);
01255    return res;
01256 }

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 1282 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(), and lua_update_registry().

01283 {
01284    int res, error_func;
01285    lua_State *L;
01286    struct ast_module_user *u = ast_module_user_add(chan);
01287    if (!u) {
01288       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01289       return -1;
01290    }
01291    
01292    L = lua_get_state(chan);
01293    if (!L) {
01294       ast_module_user_remove(u);
01295       return -1;
01296    }
01297 
01298    lua_pushcfunction(L, &lua_error_function);
01299    error_func = lua_gettop(L);
01300 
01301    /* push the extension function onto the stack */
01302    if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
01303       lua_pop(L, 1); /* pop the debug function */
01304       ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
01305       if (!chan) lua_close(L);
01306       ast_module_user_remove(u);
01307       return -1;
01308    }
01309 
01310    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
01311    if (lua_toboolean(L, -1)) {
01312       ast_autoservice_start(chan);
01313    }
01314    lua_pop(L, 1);
01315 
01316    lua_update_registry(L, context, exten, priority);
01317    
01318    lua_pushstring(L, context);
01319    lua_pushstring(L, exten);
01320    
01321    res = lua_pcall(L, 2, 0, error_func);
01322    if (res) {
01323       if (res == LUA_ERRRUN) {
01324          res = -1;
01325          if (lua_isnumber(L, -1)) {
01326             res = lua_tointeger(L, -1);
01327          } else if (lua_isstring(L, -1)) {
01328             const char *error = lua_tostring(L, -1);
01329             ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
01330          }
01331       } else if (res == LUA_ERRERR) {
01332          res = -1;
01333          ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
01334       } else if (res == LUA_ERRMEM) {
01335          res = -1;
01336          ast_log(LOG_ERROR, "Memory allocation error\n");
01337       }
01338       lua_pop(L, 1);
01339    }
01340    lua_remove(L, error_func);
01341 
01342    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
01343    if (lua_toboolean(L, -1)) {
01344       ast_autoservice_stop(chan);
01345    }
01346    lua_pop(L, 1);
01347 
01348    if (!chan) lua_close(L);
01349    ast_module_user_remove(u);
01350    return res;
01351 }

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 1212 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 exec().

01213 {
01214    int res;
01215    lua_State *L;
01216    struct ast_module_user *u = ast_module_user_add(chan);
01217    if (!u) {
01218       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01219       return 0;
01220    }
01221 
01222    L = lua_get_state(chan);
01223    if (!L) {
01224       ast_module_user_remove(u);
01225       return 0;
01226    }
01227 
01228    res = lua_find_extension(L, context, exten, priority, &exists, 0);
01229 
01230    if (!chan) lua_close(L);
01231    ast_module_user_remove(u);
01232    return res;
01233 }

static int load_module ( void   )  [static]

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

01551 {
01552    int res;
01553 
01554    if ((res = load_or_reload_lua_stuff()))
01555       return res;
01556 
01557    if (ast_register_switch(&lua_switch)) {
01558       ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
01559       return AST_MODULE_LOAD_DECLINE;
01560    }
01561 
01562    return AST_MODULE_LOAD_SUCCESS;
01563 }

static int load_or_reload_lua_stuff ( void   )  [static]

Definition at line 1513 of file pbx_lua.c.

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

Referenced by load_module(), and reload().

01514 {
01515    int res = AST_MODULE_LOAD_SUCCESS;
01516 
01517    lua_State *L = luaL_newstate();
01518    if (!L) {
01519       ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01520       return AST_MODULE_LOAD_DECLINE;
01521    }
01522 
01523    if (lua_reload_extensions(L)) {
01524       const char *error = lua_tostring(L, -1);
01525       ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01526       res = AST_MODULE_LOAD_DECLINE;
01527    }
01528 
01529    if (!res) {
01530       ast_log(LOG_NOTICE, "Lua PBX Switch loaded.\n");
01531    }
01532    lua_close(L);
01533    return res;
01534 }

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.

Returns:
This function returns the result of the ast_autoservice_start() function as a boolean to its lua caller.

Definition at line 665 of file pbx_lua.c.

References ast_autoservice_start().

Referenced by lua_create_autoservice_functions().

00666 {
00667    struct ast_channel *chan;
00668    int res;
00669 
00670    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00671    if (lua_toboolean(L, -1)) {
00672       /* autoservice already running */
00673       return 1;
00674    }
00675    lua_pop(L, 1);
00676 
00677    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00678    chan = lua_touserdata(L, -1);
00679    lua_pop(L, 1);
00680 
00681    res = ast_autoservice_start(chan);
00682 
00683    lua_pushboolean(L, !res);
00684    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00685 
00686    lua_pushboolean(L, !res);
00687    return 1;
00688 }

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

Referenced by lua_create_autoservice_functions().

00738 {
00739    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00740    return 1;
00741 }

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.

Returns:
This function returns the result of the ast_autoservice_stop() function as a boolean to its lua caller.

Definition at line 703 of file pbx_lua.c.

References ast_autoservice_stop().

Referenced by lua_create_autoservice_functions().

00704 {
00705    struct ast_channel *chan;
00706    int res;
00707 
00708    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00709    if (!lua_toboolean(L, -1)) {
00710       /* no autoservice running */
00711       return 1;
00712    }
00713    lua_pop(L, 1);
00714 
00715    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00716    chan = lua_touserdata(L, -1);
00717    lua_pop(L, 1);
00718 
00719    res = ast_autoservice_stop(chan);
00720 
00721    lua_pushboolean(L, 0);
00722    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00723 
00724    lua_pushboolean(L, !res);
00725    return 1;
00726 }

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

References ast_check_hangup().

Referenced by lua_create_hangup_function().

00752 {
00753    struct ast_channel *chan;
00754    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00755    chan = lua_touserdata(L, -1);
00756    lua_pop(L, 1);
00757 
00758    lua_pushboolean(L, ast_check_hangup(chan));
00759    return 1;
00760 }

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

Referenced by lua_func_read(), and lua_pbx_exec().

00598                                                                 {
00599    int concat = 0;
00600    int i = start + 1;
00601 
00602    if (start <= nargs && !lua_isnil(L, start)) {
00603       lua_pushvalue(L, start);
00604       concat += 1;
00605    }
00606 
00607    for (; i <= nargs; i++) {
00608       if (lua_isnil(L, i)) {
00609          lua_pushliteral(L, ",");
00610          concat += 1;
00611       } else {
00612          lua_pushliteral(L, ",");
00613          lua_pushvalue(L, i);
00614          concat += 2;
00615       }
00616    }
00617 
00618    lua_concat(L, concat);
00619 }

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

References lua_pbx_findapp().

Referenced by lua_load_extensions().

00413 {
00414    lua_newtable(L);
00415    luaL_newmetatable(L, "app");
00416 
00417    lua_pushstring(L, "__index");
00418    lua_pushcfunction(L, &lua_pbx_findapp);
00419    lua_settable(L, -3);
00420 
00421    lua_setmetatable(L, -2);
00422    lua_setglobal(L, "app");
00423 }

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

References lua_pbx_exec().

Referenced by lua_load_extensions().

00470 {
00471    luaL_newmetatable(L, "application");
00472 
00473    lua_pushstring(L, "__call");
00474    lua_pushcfunction(L, &lua_pbx_exec);
00475    lua_settable(L, -3);
00476 
00477    lua_pop(L, 1);
00478 }

static void lua_create_autoservice_functions ( lua_State *  L  )  [static]

Create the autoservice functions.

Parameters:
L the lua_State to use

Definition at line 485 of file pbx_lua.c.

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

Referenced by lua_load_extensions().

00486 {
00487    lua_pushcfunction(L, &lua_autoservice_start);
00488    lua_setglobal(L, "autoservice_start");
00489    
00490    lua_pushcfunction(L, &lua_autoservice_stop);
00491    lua_setglobal(L, "autoservice_stop");
00492 
00493    lua_pushcfunction(L, &lua_autoservice_status);
00494    lua_setglobal(L, "autoservice_status");
00495 
00496    lua_pushboolean(L, 0);
00497    lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
00498 }

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

References lua_get_variable(), and lua_set_variable().

Referenced by lua_load_extensions().

00431 {
00432    lua_newtable(L);
00433    luaL_newmetatable(L, "channel_data");
00434 
00435    lua_pushstring(L, "__index");
00436    lua_pushcfunction(L, &lua_get_variable);
00437    lua_settable(L, -3);
00438 
00439    lua_pushstring(L, "__newindex");
00440    lua_pushcfunction(L, &lua_set_variable);
00441    lua_settable(L, -3);
00442 
00443    lua_setmetatable(L, -2);
00444    lua_setglobal(L, "channel");
00445 }

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

References lua_check_hangup().

Referenced by lua_load_extensions().

00506 {
00507    lua_pushcfunction(L, &lua_check_hangup);
00508    lua_setglobal(L, "check_hangup");
00509 }

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

References lua_func_read().

Referenced by lua_load_extensions().

00453 {
00454    luaL_newmetatable(L, "variable");
00455 
00456    lua_pushstring(L, "__call");
00457    lua_pushcfunction(L, &lua_func_read);
00458    lua_settable(L, -3);
00459 
00460    lua_pop(L, 1);
00461 }

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

00134 {
00135    lua_State *L = data;
00136    lua_pushlightuserdata(L, new_chan);
00137    lua_setfield(L, LUA_REGISTRYINDEX, "channel");
00138 }

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

Referenced by exec(), and lua_read_extensions_file().

00769 {
00770    int message_index;
00771 
00772    /* pass number arguments right through back to asterisk*/
00773    if (lua_isnumber(L, -1)) {
00774       return 1;
00775    }
00776 
00777    /* if we are here then we have a string error message, let's attach a
00778     * backtrace to it */
00779    message_index = lua_gettop(L);
00780 
00781    /* prepare to prepend a new line to the traceback */
00782    lua_pushliteral(L, "\n");
00783 
00784    lua_getglobal(L, "debug");
00785    lua_getfield(L, -1, "traceback");
00786    lua_remove(L, -2); /* remove the 'debug' table */
00787 
00788    lua_pushvalue(L, message_index);
00789    lua_remove(L, message_index);
00790 
00791    lua_pushnumber(L, 2);
00792 
00793    lua_call(L, 2, 1);
00794 
00795    /* prepend the new line we prepared above */
00796    lua_concat(L, 2);
00797 
00798    return 1;
00799 }

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

References ast_extension_cmp().

Referenced by lua_sort_extensions().

00953 {
00954    const char *a = luaL_checkstring(L, -2);
00955    const char *b = luaL_checkstring(L, -1);
00956 
00957    if (ast_extension_cmp(a, b) == -1)
00958       lua_pushboolean(L, 1);
00959    else
00960       lua_pushboolean(L, 0);
00961 
00962    return 1;
00963 }

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

01367 {
01368    int context_table, context_order_table, i;
01369 
01370    ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
01371    if (priority != 1)
01372       return 0;
01373 
01374    /* load the 'extensions' table */
01375    lua_getglobal(L, "extensions");
01376    if (lua_isnil(L, -1)) {
01377       ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
01378       lua_pop(L, 1);
01379       return 0;
01380    }
01381 
01382    /* load the given context */
01383    lua_getfield(L, -1, context);
01384    if (lua_isnil(L, -1)) {
01385       lua_pop(L, 2);
01386       return 0;
01387    }
01388 
01389    /* remove the extensions table */
01390    lua_remove(L, -2);
01391 
01392    context_table = lua_gettop(L);
01393 
01394    /* load the extensions order table for this context */
01395    lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
01396    lua_getfield(L, -1, context);
01397 
01398    lua_remove(L, -2);  /* remove the extensions order table */
01399 
01400    context_order_table = lua_gettop(L);
01401 
01402    /* step through the extensions looking for a match */
01403 #if LUA_VERSION_NUM < 502
01404    for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
01405 #else
01406    for (i = 1; i < lua_rawlen(L, context_order_table) + 1; i++) {
01407 #endif
01408       int e_index_copy, match = 0;
01409       const char *e;
01410 
01411       lua_pushinteger(L, i);
01412       lua_gettable(L, context_order_table);
01413       lua_gettop(L);
01414 
01415       /* copy the key at the top of the stack for use later */
01416       lua_pushvalue(L, -1);
01417       e_index_copy = lua_gettop(L);
01418 
01419       if (!(e = lua_tostring(L, e_index_copy))) {
01420          lua_pop(L, 2);
01421          continue;
01422       }
01423 
01424       /* make sure this is not the 'include' extension */
01425       if (!strcasecmp(e, "include")) {
01426          lua_pop(L, 2);
01427          continue;
01428       }
01429 
01430       if (func == &matchmore)
01431          match = ast_extension_close(e, exten, E_MATCHMORE);
01432       else if (func == &canmatch)
01433          match = ast_extension_close(e, exten, E_CANMATCH);
01434       else
01435          match = ast_extension_match(e, exten);
01436 
01437       /* the extension matching functions return 0 on fail, 1 on
01438        * match, 2 on earlymatch */
01439 
01440       if (!match) {
01441          /* pop the copy and the extension */
01442          lua_pop(L, 2);
01443          continue;   /* keep trying */
01444       }
01445 
01446       if (func == &matchmore && match == 2) {
01447          /* We match an extension ending in '!'. The decision in
01448           * this case is final and counts as no match. */
01449          lua_pop(L, 4);
01450          return 0;
01451       }
01452 
01453       /* remove the context table, the context order table, the
01454        * extension, and the extension copy (or replace the extension
01455        * with the corresponding function) */
01456       if (push_func) {
01457          lua_pop(L, 1);  /* pop the copy */
01458          lua_gettable(L, context_table);
01459          lua_insert(L, -3);
01460          lua_pop(L, 2);
01461       } else {
01462          lua_pop(L, 4);
01463       }
01464 
01465       return 1;
01466    }
01467 
01468    /* load the includes for this context */
01469    lua_getfield(L, context_table, "include");
01470    if (lua_isnil(L, -1)) {
01471       lua_pop(L, 3);
01472       return 0;
01473    }
01474 
01475    /* remove the context and the order table*/
01476    lua_remove(L, context_order_table);
01477    lua_remove(L, context_table);
01478 
01479    /* Now try any includes we have in this context */
01480    for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
01481       const char *c = lua_tostring(L, -1);
01482       if (!c)
01483          continue;
01484 
01485       if (lua_find_extension(L, c, exten, priority, func, push_func)) {
01486          /* remove the value, the key, and the includes table
01487           * from the stack.  Leave the function behind if
01488           * necessary */
01489 
01490          if (push_func)
01491             lua_insert(L, -4);
01492 
01493          lua_pop(L, 3);
01494          return 1;
01495       }
01496    }
01497 
01498    /* pop the includes table */
01499    lua_pop(L, 1);
01500    return 0;
01501 }

static void lua_free_extensions ( void   )  [static]

Free the internal extensions buffer.

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

References lua_concat_args(), and lua_push_variable_table().

Referenced by lua_create_variable_metatable().

00638 {
00639    int nargs = lua_gettop(L);
00640 
00641    /* build a string in the form of "func_name(arg1,arg2,arg3)" */
00642    lua_getfield(L, 1, "name");
00643    lua_pushliteral(L, "(");
00644    lua_concat_args(L, 2, nargs);
00645    lua_pushliteral(L, ")");
00646    lua_concat(L, 4);
00647 
00648    lua_push_variable_table(L);
00649    return 1;
00650 }

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

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, 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().

01151 {
01152    struct ast_datastore *datastore = NULL;
01153    lua_State *L;
01154 
01155    if (!chan) {
01156       lua_State *L = luaL_newstate();
01157       if (!L) {
01158          ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01159          return NULL;
01160       }
01161 
01162       if (lua_load_extensions(L, NULL)) {
01163          const char *error = lua_tostring(L, -1);
01164          ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
01165          lua_close(L);
01166          return NULL;
01167       }
01168       return L;
01169    } else {
01170       ast_channel_lock(chan);
01171       datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
01172       ast_channel_unlock(chan);
01173 
01174       if (!datastore) {
01175          /* nothing found, allocate a new lua state */
01176          datastore = ast_datastore_alloc(&lua_datastore, NULL);
01177          if (!datastore) {
01178             ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
01179             return NULL;
01180          }
01181 
01182          datastore->data = luaL_newstate();
01183          if (!datastore->data) {
01184             ast_datastore_free(datastore);
01185             ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
01186             return NULL;
01187          }
01188 
01189          ast_channel_lock(chan);
01190          ast_channel_datastore_add(chan, datastore);
01191          ast_channel_unlock(chan);
01192 
01193          L = datastore->data;
01194 
01195          if (lua_load_extensions(L, chan)) {
01196             const char *error = lua_tostring(L, -1);
01197             ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", chan->name, error);
01198 
01199             ast_channel_lock(chan);
01200             ast_channel_datastore_remove(chan, datastore);
01201             ast_channel_unlock(chan);
01202 
01203             ast_datastore_free(datastore);
01204             return NULL;
01205          }
01206       }
01207 
01208       return datastore->data;
01209    }
01210 }

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

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

00524 {
00525    struct ast_channel *chan;
00526    const char *name = luaL_checkstring(L, 2);
00527    char *value = NULL;
00528    char *workspace = ast_alloca(LUA_BUF_SIZE);
00529    workspace[0] = '\0';
00530    
00531    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00532    chan = lua_touserdata(L, -1);
00533    lua_pop(L, 1);
00534 
00535    lua_pushvalue(L, 2);
00536    lua_push_variable_table(L);
00537    
00538    /* if this is not a request for a dialplan funciton attempt to retrieve
00539     * the value of the variable */
00540    if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') {
00541       pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead);
00542    }
00543 
00544    if (value) {
00545       lua_pushstring(L, value);
00546       lua_setfield(L, -2, "value");
00547    }
00548 
00549    return 1;   
00550 }

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

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

00267 {
00268    struct ast_channel *chan;
00269    char *value = NULL, *name;
00270    char *workspace = ast_alloca(LUA_BUF_SIZE);
00271    int autoservice;
00272 
00273    workspace[0] = '\0';
00274 
00275    if (!lua_istable(L, 1)) {
00276       lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value");
00277       return lua_error(L);
00278    }
00279    
00280    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00281    chan = lua_touserdata(L, -1);
00282    lua_pop(L, 1);
00283 
00284    lua_getfield(L, 1, "name");
00285    name = ast_strdupa(lua_tostring(L, -1));
00286    lua_pop(L, 1);
00287    
00288    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00289    autoservice = lua_toboolean(L, -1);
00290    lua_pop(L, 1);
00291 
00292    if (autoservice)
00293       ast_autoservice_stop(chan);
00294    
00295    /* if this is a dialplan function then use ast_func_read(), otherwise
00296     * use pbx_retrieve_variable() */
00297    if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') {
00298       value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace;
00299    } else {
00300       pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, &chan->varshead);
00301    }
00302    
00303    if (autoservice)
00304       ast_autoservice_start(chan);
00305 
00306    if (value) {
00307       lua_pushstring(L, value);
00308    } else {
00309       lua_pushnil(L);
00310    }
00311 
00312    return 1;
00313 }

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

01052 {
01053    
01054    /* store a pointer to this channel */
01055    lua_pushlightuserdata(L, chan);
01056    lua_setfield(L, LUA_REGISTRYINDEX, "channel");
01057    
01058    luaL_openlibs(L);
01059 
01060    /* load and sort extensions */
01061    ast_mutex_lock(&config_file_lock);
01062    if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
01063          || lua_pcall(L, 0, LUA_MULTRET, 0)
01064          || lua_sort_extensions(L)) {
01065       ast_mutex_unlock(&config_file_lock);
01066       return 1;
01067    }
01068    ast_mutex_unlock(&config_file_lock);
01069 
01070    /* now we setup special tables and functions */
01071 
01072    lua_create_app_table(L);
01073    lua_create_channel_table(L);
01074 
01075    lua_create_variable_metatable(L);
01076    lua_create_application_metatable(L);
01077 
01078    lua_create_autoservice_functions(L);
01079    lua_create_hangup_function(L);
01080 
01081    return 0;
01082 }

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

References app, ast_autoservice_start(), ast_autoservice_stop(), ast_strdupa, ast_verb, COLOR_BRCYAN, COLOR_BRMAGENTA, context, exten, lua_concat_args(), LUA_EXT_DATA_SIZE, pbx_exec(), pbx_findapp(), and term_color().

Referenced by lua_create_application_metatable().

00183 {
00184    int res, nargs = lua_gettop(L);
00185    const char *data = "";
00186    char *app_name, *context, *exten;
00187    char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
00188    int priority, autoservice;
00189    struct ast_app *app;
00190    struct ast_channel *chan;
00191 
00192    lua_getfield(L, 1, "name");
00193    app_name = ast_strdupa(lua_tostring(L, -1));
00194    lua_pop(L, 1);
00195    
00196    if (!(app = pbx_findapp(app_name))) {
00197       lua_pushstring(L, "application '");
00198       lua_pushstring(L, app_name);
00199       lua_pushstring(L, "' not found");
00200       lua_concat(L, 3);
00201       return lua_error(L);
00202    }
00203    
00204 
00205    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00206    chan = lua_touserdata(L, -1);
00207    lua_pop(L, 1);
00208    
00209    
00210    lua_getfield(L, LUA_REGISTRYINDEX, "context");
00211    context = ast_strdupa(lua_tostring(L, -1));
00212    lua_pop(L, 1);
00213    
00214    lua_getfield(L, LUA_REGISTRYINDEX, "exten");
00215    exten = ast_strdupa(lua_tostring(L, -1));
00216    lua_pop(L, 1);
00217    
00218    lua_getfield(L, LUA_REGISTRYINDEX, "priority");
00219    priority = lua_tointeger(L, -1);
00220    lua_pop(L, 1);
00221 
00222    lua_concat_args(L, 2, nargs);
00223    data = lua_tostring(L, -1);
00224 
00225    ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
00226          exten, context, priority,
00227          term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
00228          term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
00229          term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));
00230 
00231    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00232    autoservice = lua_toboolean(L, -1);
00233    lua_pop(L, 1);
00234 
00235    if (autoservice)
00236       ast_autoservice_stop(chan);
00237 
00238    res = pbx_exec(chan, app, data);
00239 
00240    lua_pop(L, 1); /* pop data */
00241    data = "";
00242 
00243    if (autoservice)
00244       ast_autoservice_start(chan);
00245 
00246    /* error executing an application, report it */
00247    if (res) {
00248       lua_pushinteger(L, res);
00249       return lua_error(L);
00250    }
00251    return 0;
00252 }

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

Referenced by lua_create_app_table().

00152 {
00153    const char *app_name = luaL_checkstring(L, 2);
00154    
00155    lua_newtable(L);
00156 
00157    lua_pushstring(L, "name");
00158    lua_pushstring(L, app_name);
00159    lua_settable(L, -3);
00160 
00161    luaL_getmetatable(L, "application");
00162    lua_setmetatable(L, -2);
00163 
00164    return 1;
00165 }

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

References lua_get_variable_value(), and lua_set_variable_value().

Referenced by lua_func_read(), and lua_get_variable().

00392 {
00393    lua_newtable(L);
00394    luaL_getmetatable(L, "variable");
00395    lua_setmetatable(L, -2);
00396 
00397    lua_insert(L, -2); /* move the table after the name */
00398    lua_setfield(L, -2, "name");
00399    
00400    lua_pushcfunction(L, &lua_get_variable_value);
00401    lua_setfield(L, -2, "get");
00402    
00403    lua_pushcfunction(L, &lua_set_variable_value);
00404    lua_setfield(L, -2, "set");
00405 }

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

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

Referenced by lua_reload_extensions().

00976 {
00977    FILE *f;
00978    int error_func;
00979    char *data;
00980    char *path = ast_alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
00981    sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
00982 
00983    if (!(f = fopen(path, "r"))) {
00984       lua_pushstring(L, "cannot open '");
00985       lua_pushstring(L, path);
00986       lua_pushstring(L, "' for reading: ");
00987       lua_pushstring(L, strerror(errno));
00988       lua_concat(L, 4);
00989 
00990       return NULL;
00991    }
00992 
00993    if (fseek(f, 0l, SEEK_END)) {
00994       fclose(f);
00995       lua_pushliteral(L, "error determining the size of the config file");
00996       return NULL;
00997    }
00998 
00999    *size = ftell(f);
01000 
01001    if (fseek(f, 0l, SEEK_SET)) {
01002       *size = 0;
01003       fclose(f);
01004       lua_pushliteral(L, "error reading config file");
01005       return NULL;
01006    }
01007 
01008    if (!(data = ast_malloc(*size))) {
01009       *size = 0;
01010       fclose(f);
01011       lua_pushstring(L, "not enough memory");
01012       return NULL;
01013    }
01014 
01015    if (fread(data, sizeof(char), *size, f) != *size) {
01016       *size = 0;
01017       fclose(f);
01018       lua_pushliteral(L, "problem reading configuration file");
01019       return NULL;
01020    }
01021    fclose(f);
01022 
01023    lua_pushcfunction(L, &lua_error_function);
01024    error_func = lua_gettop(L);
01025 
01026    if (luaL_loadbuffer(L, data, *size, "extensions.lua")
01027          || lua_pcall(L, 0, LUA_MULTRET, error_func)
01028          || lua_sort_extensions(L)
01029          || lua_register_switches(L)) {
01030       ast_free(data);
01031       data = NULL;
01032       *size = 0;
01033    }
01034 
01035    lua_remove(L, error_func);
01036    return data;
01037 }

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

00895 {
00896    int extensions;
00897    struct ast_context *con = NULL;
00898 
00899    /* create the hash table for our contexts */
00900    /* XXX do we ever need to destroy this? pbx_config does not */
00901    if (!local_table)
00902       local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
00903 
00904    /* load the 'extensions' table */
00905    lua_getglobal(L, "extensions");
00906    extensions = lua_gettop(L);
00907    if (lua_isnil(L, -1)) {
00908       lua_pop(L, 1);
00909       lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00910       return 1;
00911    }
00912 
00913    /* iterate through the extensions table and register a context and
00914     * dialplan switch for each lua context
00915     */
00916    for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00917       int context = lua_gettop(L);
00918       int context_name = context - 1;
00919       const char *context_str = lua_tostring(L, context_name);
00920 
00921       /* find or create this context */
00922       con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
00923       if (!con) {
00924          /* remove extensions table and context key and value */
00925          lua_pop(L, 3);
00926          lua_pushstring(L, "Failed to find or create context\n");
00927          return 1;
00928       }
00929 
00930       /* register the switch */
00931       if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
00932          /* remove extensions table and context key and value */
00933          lua_pop(L, 3);
00934          lua_pushstring(L, "Unable to create switch for context\n");
00935          return 1;
00936       }
00937    }
00938    
00939    /* remove the extensions table */
00940    lua_pop(L, 1);
00941    return 0;
00942 }

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

01095 {
01096    long size = 0;
01097    char *data = NULL;
01098 
01099    luaL_openlibs(L);
01100 
01101    if (!(data = lua_read_extensions_file(L, &size))) {
01102       return 1;
01103    }
01104 
01105    ast_mutex_lock(&config_file_lock);
01106 
01107    if (config_file_data)
01108       ast_free(config_file_data);
01109 
01110    config_file_data = data;
01111    config_file_size = size;
01112    
01113    /* merge our new contexts */
01114    ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
01115    /* merge_contexts_and_delete will actually, at the correct moment, 
01116       set the global dialplan pointers to your local_contexts and local_table.
01117       It then will free up the old tables itself. Just be sure not to
01118       hang onto the pointers. */
01119    local_table = NULL;
01120    local_contexts = NULL;
01121 
01122    ast_mutex_unlock(&config_file_lock);
01123    return 0;
01124 }

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

00564 {
00565    struct ast_channel *chan;
00566    int autoservice;
00567    const char *name = luaL_checkstring(L, 2);
00568    const char *value = luaL_checkstring(L, 3);
00569 
00570    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00571    chan = lua_touserdata(L, -1);
00572    lua_pop(L, 1);
00573 
00574    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00575    autoservice = lua_toboolean(L, -1);
00576    lua_pop(L, 1);
00577 
00578    if (autoservice)
00579       ast_autoservice_stop(chan);
00580 
00581    pbx_builtin_setvar_helper(chan, name, value);
00582    
00583    if (autoservice)
00584       ast_autoservice_start(chan);
00585 
00586    return 0;
00587 }

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

00327 {
00328    const char *name, *value;
00329    struct ast_channel *chan;
00330    int autoservice;
00331 
00332    if (!lua_istable(L, 1)) {
00333       lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable");
00334       return lua_error(L);
00335    }
00336 
00337    lua_getfield(L, 1, "name");
00338    name = ast_strdupa(lua_tostring(L, -1));
00339    lua_pop(L, 1);
00340 
00341    value = luaL_checkstring(L, 2);
00342    
00343    lua_getfield(L, LUA_REGISTRYINDEX, "channel");
00344    chan = lua_touserdata(L, -1);
00345    lua_pop(L, 1);
00346 
00347    lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
00348    autoservice = lua_toboolean(L, -1);
00349    lua_pop(L, 1);
00350 
00351    if (autoservice)
00352       ast_autoservice_stop(chan);
00353 
00354    pbx_builtin_setvar_helper(chan, name, value);
00355    
00356    if (autoservice)
00357       ast_autoservice_start(chan);
00358 
00359    return 0;
00360 }

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

References context, exten, and lua_extension_cmp().

Referenced by lua_load_extensions(), and lua_read_extensions_file().

00810 {
00811    int extensions, extensions_order;
00812 
00813    /* create the extensions_order table */
00814    lua_newtable(L);
00815    lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order");
00816    lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
00817    extensions_order = lua_gettop(L);
00818 
00819    /* sort each context in the extensions table */
00820    /* load the 'extensions' table */
00821    lua_getglobal(L, "extensions");
00822    extensions = lua_gettop(L);
00823    if (lua_isnil(L, -1)) {
00824       lua_pop(L, 1);
00825       lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
00826       return 1;
00827    }
00828 
00829    /* iterate through the extensions table and create a
00830     * matching table (holding the sort order) in the
00831     * extensions_order table for each context that is found
00832     */
00833    for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
00834       int context = lua_gettop(L);
00835       int context_name = context - 1;
00836       int context_order;
00837 
00838       /* copy the context_name to be used as the key for the
00839        * context_order table in the extensions_order table later */
00840       lua_pushvalue(L, context_name);
00841 
00842       /* create the context_order table */
00843       lua_newtable(L);
00844       context_order = lua_gettop(L);
00845 
00846       /* iterate through this context an popluate the corrisponding
00847        * table in the extensions_order table */
00848       for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
00849          int exten = lua_gettop(L) - 1;
00850 #if LUA_VERSION_NUM < 502
00851          lua_pushinteger(L, lua_objlen(L, context_order) + 1);
00852 #else
00853          lua_pushinteger(L, lua_rawlen(L, context_order) + 1);
00854 #endif
00855          lua_pushvalue(L, exten);
00856          lua_settable(L, context_order);
00857       }
00858       lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */
00859 
00860       /* now sort the new table */
00861 
00862       /* push the table.sort function */
00863       lua_getglobal(L, "table");
00864       lua_getfield(L, -1, "sort");
00865       lua_remove(L, -2); /* remove the 'table' table */
00866 
00867       /* push the context_order table */
00868       lua_pushvalue(L, context_name);
00869       lua_gettable(L, extensions_order);
00870 
00871       /* push the comp function */
00872       lua_pushcfunction(L, &lua_extension_cmp);
00873 
00874       if (lua_pcall(L, 2, 0, 0)) {
00875          lua_insert(L, -5);
00876          lua_pop(L, 4);
00877          return 1;
00878       }
00879    }
00880    
00881    /* remove the extensions table and the extensions_order table */
00882    lua_pop(L, 2);
00883    return 0;
00884 }

static void lua_state_destroy ( void *  data  )  [static]

The destructor for lua_datastore.

Definition at line 119 of file pbx_lua.c.

00120 {
00121    if (data)
00122       lua_close(data);
00123 }

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

Referenced by exec().

00371 {
00372    lua_pushstring(L, context);
00373    lua_setfield(L, LUA_REGISTRYINDEX, "context");
00374 
00375    lua_pushstring(L, exten);
00376    lua_setfield(L, LUA_REGISTRYINDEX, "exten");
00377 
00378    lua_pushinteger(L, priority);
00379    lua_setfield(L, LUA_REGISTRYINDEX, "priority");
00380 }

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

01259 {
01260    int res;
01261    lua_State *L;
01262    struct ast_module_user *u = ast_module_user_add(chan);
01263    if (!u) {
01264       ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
01265       return 0;
01266    }
01267 
01268    L = lua_get_state(chan);
01269    if (!L) {
01270       ast_module_user_remove(u);
01271       return 0;
01272    }
01273    
01274    res = lua_find_extension(L, context, exten, priority, &matchmore, 0);
01275 
01276    if (!chan) lua_close(L);
01277    ast_module_user_remove(u);
01278    return res;
01279 }

static int reload ( void   )  [static]

Definition at line 1545 of file pbx_lua.c.

References load_or_reload_lua_stuff().

01546 {
01547    return load_or_reload_lua_stuff();
01548 }

static int unload_module ( void   )  [static]

Definition at line 1536 of file pbx_lua.c.

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

01537 {
01538    ast_context_destroy(NULL, registrar);
01539    ast_unregister_switch(&lua_switch);
01540    lua_free_extensions();
01541    ast_log(LOG_NOTICE, "Lua PBX Switch unloaded.\n");
01542    return 0;
01543 }


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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1569 of file pbx_lua.c.

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

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

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

struct ast_context* local_contexts = NULL [static]

Definition at line 106 of file pbx_lua.c.

struct ast_hashtab* local_table = NULL [static]

Definition at line 107 of file pbx_lua.c.

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

Definition at line 109 of file pbx_lua.c.

struct ast_switch lua_switch [static]

Definition at line 1503 of file pbx_lua.c.

char* registrar = "pbx_lua" [static]

Definition at line 51 of file pbx_lua.c.


Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1