Asterisk - The Open Source Telephony Project  18.5.0
Macros | Functions | Variables
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.

Macros

#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)
 
struct ast_moduleAST_MODULE_SELF_SYM (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) More...
 
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) More...
 
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) More...
 
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) More...
 
static void lua_concat_args (lua_State *L, int start, int nargs)
 Concatenate a list of lua function arguments into a comma separated string. More...
 
static void lua_create_app_table (lua_State *L)
 Create the global 'app' table for executing applications. More...
 
static void lua_create_application_metatable (lua_State *L)
 Create the 'application' metatable, used to execute asterisk applications from lua. More...
 
static void lua_create_autoservice_functions (lua_State *L)
 Create the autoservice functions. More...
 
static void lua_create_channel_table (lua_State *L)
 Create the global 'channel' table for accesing channel variables. More...
 
static void lua_create_hangup_function (lua_State *L)
 Create the hangup check function. More...
 
static void lua_create_variable_metatable (lua_State *L)
 Create the 'variable' metatable, used to retrieve channel variables. More...
 
static void lua_datastore_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 The fixup function for the lua_datastore. More...
 
static int lua_error_function (lua_State *L)
 [lua_CFunction] Handle lua errors (for access from lua, don't call directly) More...
 
static int lua_extension_cmp (lua_State *L)
 [lua_CFunction] Compare two extensions (for access from lua, don't call directly) More...
 
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. More...
 
static void lua_free_extensions ()
 Free the internal extensions buffer. More...
 
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) More...
 
static lua_State * lua_get_state (struct ast_channel *chan)
 Get the lua_State for this channel. More...
 
static int lua_get_variable (lua_State *L)
 [lua_CFunction] Return a lua 'variable' object (for access from lua, don't call directly) More...
 
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) More...
 
static int lua_load_extensions (lua_State *L, struct ast_channel *chan)
 Load the extensions.lua file from the internal buffer. More...
 
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) More...
 
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) More...
 
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. More...
 
static char * lua_read_extensions_file (lua_State *L, long *size, int *file_not_openable)
 Load the extensions.lua file in to a buffer and execute the file. More...
 
static int lua_register_hints (lua_State *L)
 Register dialplan hints for our pbx_lua contexs. More...
 
static int lua_register_switches (lua_State *L)
 Register dialplan switches for our pbx_lua contexs. More...
 
static int lua_reload_extensions (lua_State *L)
 Reload the extensions file and update the internal buffers if it loads correctly. More...
 
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) More...
 
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) More...
 
static int lua_sort_extensions (lua_State *L)
 Store the sort order of each context. More...
 
static void lua_state_destroy (void *data)
 The destructor for lua_datastore. More...
 
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. More...
 
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, }
 
static const 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, 0} }
 
static long config_file_size = 0
 
static struct ast_contextlocal_contexts = NULL
 
static struct ast_hashtablocal_table = NULL
 
static const 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 mnich.nosp@m.olso.nosp@m.n@dig.nosp@m.ium..nosp@m.com

Definition in file pbx_lua.c.

Macro Definition Documentation

◆ LUA_BUF_SIZE

#define LUA_BUF_SIZE   4096

Definition at line 56 of file pbx_lua.c.

Referenced by lua_get_variable(), and lua_get_variable_value().

◆ LUA_EXT_DATA_SIZE

#define LUA_EXT_DATA_SIZE   8192

Definition at line 54 of file pbx_lua.c.

Referenced by lua_pbx_exec().

◆ LUA_GOTO_DETECTED

#define LUA_GOTO_DETECTED   5

Definition at line 61 of file pbx_lua.c.

Referenced by exec(), and lua_pbx_exec().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1700 of file pbx_lua.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1700 of file pbx_lua.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1700 of file pbx_lua.c.

◆ canmatch()

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

1359 {
1360  int res;
1361  lua_State *L;
1362  struct ast_module_user *u = ast_module_user_add(chan);
1363  if (!u) {
1364  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1365  return 0;
1366  }
1367 
1368  L = lua_get_state(chan);
1369  if (!L) {
1371  return 0;
1372  }
1373 
1375 
1376  if (!chan) lua_close(L);
1378  return res;
1379 }
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.
Definition: pbx_lua.c:1493
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int priority
#define ast_module_user_remove(user)
Definition: module.h:427
#define ast_log
Definition: astobj2.c:42
#define ast_module_user_add(chan)
Definition: module.h:426
#define LOG_ERROR
Definition: logger.h:285
static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1358
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static lua_State * lua_get_state(struct ast_channel *chan)
Get the lua_State for this channel.
Definition: pbx_lua.c:1273

◆ exec()

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

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

1406 {
1407  int res, error_func;
1408  lua_State *L;
1409  struct ast_module_user *u = ast_module_user_add(chan);
1410  if (!u) {
1411  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1412  return -1;
1413  }
1414 
1415  L = lua_get_state(chan);
1416  if (!L) {
1418  return -1;
1419  }
1420 
1421  lua_pushcfunction(L, &lua_error_function);
1422  error_func = lua_gettop(L);
1423 
1424  /* push the extension function onto the stack */
1425  if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
1426  lua_pop(L, 1); /* pop the debug function */
1427  ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
1428  if (!chan) lua_close(L);
1430  return -1;
1431  }
1432 
1433  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
1434  if (lua_toboolean(L, -1)) {
1435  ast_autoservice_start(chan);
1436  }
1437  lua_pop(L, 1);
1438 
1440 
1441  lua_pushstring(L, context);
1442  lua_pushstring(L, exten);
1443 
1444  res = lua_pcall(L, 2, 0, error_func);
1445  if (res) {
1446  if (res == LUA_ERRRUN) {
1447  res = -1;
1448  if (lua_isnumber(L, -1)) {
1449  res = lua_tointeger(L, -1);
1450 
1451  if (res == LUA_GOTO_DETECTED) {
1452  res = 0;
1453  }
1454  } else if (lua_isstring(L, -1)) {
1455  const char *error = lua_tostring(L, -1);
1456  ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
1457  }
1458  } else if (res == LUA_ERRERR) {
1459  res = -1;
1460  ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
1461  } else if (res == LUA_ERRMEM) {
1462  res = -1;
1463  ast_log(LOG_ERROR, "Memory allocation error\n");
1464  }
1465  lua_pop(L, 1);
1466  }
1467  lua_remove(L, error_func);
1468 
1469  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
1470  if (lua_toboolean(L, -1)) {
1471  ast_autoservice_stop(chan);
1472  }
1473  lua_pop(L, 1);
1474 
1475  if (!chan) lua_close(L);
1477  return res;
1478 }
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.
Definition: pbx_lua.c:1493
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
static int priority
#define ast_module_user_remove(user)
Definition: module.h:427
#define ast_log
Definition: astobj2.c:42
#define LUA_GOTO_DETECTED
Definition: pbx_lua.c:61
#define ast_module_user_add(chan)
Definition: module.h:426
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
#define LOG_ERROR
Definition: logger.h:285
static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1335
static int lua_error_function(lua_State *L)
[lua_CFunction] Handle lua errors (for access from lua, don&#39;t call directly)
Definition: pbx_lua.c:791
int error(const char *format,...)
Definition: utils/frame.c:999
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static lua_State * lua_get_state(struct ast_channel *chan)
Get the lua_State for this channel.
Definition: pbx_lua.c:1273
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.
Definition: pbx_lua.c:404

◆ exists()

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

1336 {
1337  int res;
1338  lua_State *L;
1339  struct ast_module_user *u = ast_module_user_add(chan);
1340  if (!u) {
1341  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1342  return 0;
1343  }
1344 
1345  L = lua_get_state(chan);
1346  if (!L) {
1348  return 0;
1349  }
1350 
1351  res = lua_find_extension(L, context, exten, priority, &exists, 0);
1352 
1353  if (!chan) lua_close(L);
1355  return res;
1356 }
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.
Definition: pbx_lua.c:1493
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int priority
#define ast_module_user_remove(user)
Definition: module.h:427
#define ast_log
Definition: astobj2.c:42
#define ast_module_user_add(chan)
Definition: module.h:426
#define LOG_ERROR
Definition: logger.h:285
static int exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1335
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static lua_State * lua_get_state(struct ast_channel *chan)
Get the lua_State for this channel.
Definition: pbx_lua.c:1273

◆ load_module()

static int load_module ( void  )
static

Definition at line 1680 of file pbx_lua.c.

References ast_log, AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_INFO(), AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_EXTENDED, ast_register_switch(), ASTERISK_GPL_KEY, load_or_reload_lua_stuff(), LOG_ERROR, reload(), and unload_module().

1681 {
1682  int res;
1683 
1684  if ((res = load_or_reload_lua_stuff()))
1685  return res;
1686 
1688  ast_log(LOG_ERROR, "Unable to register LUA PBX switch\n");
1689  return AST_MODULE_LOAD_FAILURE;
1690  }
1691 
1692  return AST_MODULE_LOAD_SUCCESS;
1693 }
static int load_or_reload_lua_stuff(void)
Definition: pbx_lua.c:1640
#define ast_log
Definition: astobj2.c:42
static struct ast_switch lua_switch
Definition: pbx_lua.c:1630
#define LOG_ERROR
Definition: logger.h:285
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx_switch.c:58
Module could not be loaded properly.
Definition: module.h:102

◆ load_or_reload_lua_stuff()

static int load_or_reload_lua_stuff ( void  )
static

Definition at line 1640 of file pbx_lua.c.

References ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, error(), loaded, LOG_ERROR, and lua_reload_extensions().

Referenced by load_module(), and reload().

1641 {
1642  int res = AST_MODULE_LOAD_SUCCESS;
1643  int loaded = 0;
1644 
1645  lua_State *L = luaL_newstate();
1646  if (!L) {
1647  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1648  return AST_MODULE_LOAD_FAILURE;
1649  }
1650 
1651  loaded = lua_reload_extensions(L);
1652  if (loaded) {
1653  const char *error = lua_tostring(L, -1);
1654  ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
1655 
1656  if (loaded < 0) {
1658  } else {
1660  }
1661  }
1662 
1663  lua_close(L);
1664  return res;
1665 }
static int loaded
Definition: cdr_csv.c:58
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static int lua_reload_extensions(lua_State *L)
Reload the extensions file and update the internal buffers if it loads correctly. ...
Definition: pbx_lua.c:1213
Module could not be loaded properly.
Definition: module.h:102
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int error(const char *format,...)
Definition: utils/frame.c:999

◆ lua_autoservice_start()

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

References ast_autoservice_start().

Referenced by lua_create_autoservice_functions().

696 {
697  struct ast_channel *chan;
698 
699  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
700  if (lua_toboolean(L, -1)) {
701  /* autservice already running */
702  lua_pop(L, 1);
703  return 0;
704  }
705  lua_pop(L, 1);
706 
707  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
708  chan = lua_touserdata(L, -1);
709  lua_pop(L, 1);
710 
711  ast_autoservice_start(chan);
712 
713  lua_pushboolean(L, 1);
714  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
715  return 0;
716 }
Main Channel structure associated with a channel.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200

◆ lua_autoservice_status()

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
Lthe lua_State to use
Returns
This function returns the status of the autoservice flag as a boolean to its lua caller.

Definition at line 760 of file pbx_lua.c.

Referenced by lua_create_autoservice_functions().

761 {
762  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
763  return 1;
764 }

◆ lua_autoservice_stop()

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

References ast_autoservice_stop().

Referenced by lua_create_autoservice_functions().

729 {
730  struct ast_channel *chan;
731 
732  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
733  if (!lua_toboolean(L, -1)) {
734  /* no autservice running */
735  lua_pop(L, 1);
736  return 0;
737  }
738  lua_pop(L, 1);
739 
740  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
741  chan = lua_touserdata(L, -1);
742  lua_pop(L, 1);
743 
744  ast_autoservice_stop(chan);
745 
746  lua_pushboolean(L, 0);
747  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
748  return 0;
749 }
Main Channel structure associated with a channel.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266

◆ lua_check_hangup()

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
Lthe lua_State to use
Returns
This function returns true if the channel was hungup

Definition at line 774 of file pbx_lua.c.

References ast_check_hangup().

Referenced by lua_create_hangup_function().

775 {
776  struct ast_channel *chan;
777  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
778  chan = lua_touserdata(L, -1);
779  lua_pop(L, 1);
780 
781  lua_pushboolean(L, ast_check_hangup(chan));
782  return 1;
783 }
Main Channel structure associated with a channel.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445

◆ lua_concat_args()

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
Lthe lua_State to use
startthe index of the first argument
nargsthe number of args

The resulting string will be left on the top of the stack.

Definition at line 631 of file pbx_lua.c.

Referenced by lua_func_read(), and lua_pbx_exec().

631  {
632  int concat = 0;
633  int i = start + 1;
634 
635  if (start <= nargs && !lua_isnil(L, start)) {
636  lua_pushvalue(L, start);
637  concat += 1;
638  }
639 
640  for (; i <= nargs; i++) {
641  if (lua_isnil(L, i)) {
642  lua_pushliteral(L, ",");
643  concat += 1;
644  } else {
645  lua_pushliteral(L, ",");
646  lua_pushvalue(L, i);
647  concat += 2;
648  }
649  }
650 
651  lua_concat(L, concat);
652 }

◆ lua_create_app_table()

static void lua_create_app_table ( lua_State *  L)
static

Create the global 'app' table for executing applications.

Parameters
Lthe lua_State to use

Definition at line 445 of file pbx_lua.c.

References lua_pbx_findapp().

Referenced by lua_load_extensions().

446 {
447  lua_newtable(L);
448  luaL_newmetatable(L, "app");
449 
450  lua_pushstring(L, "__index");
451  lua_pushcfunction(L, &lua_pbx_findapp);
452  lua_settable(L, -3);
453 
454  lua_setmetatable(L, -2);
455  lua_setglobal(L, "app");
456 }
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&#39;t call directly) ...
Definition: pbx_lua.c:155

◆ lua_create_application_metatable()

static void lua_create_application_metatable ( lua_State *  L)
static

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

Parameters
Lthe lua_State to use

Definition at line 502 of file pbx_lua.c.

References lua_pbx_exec().

Referenced by lua_load_extensions().

503 {
504  luaL_newmetatable(L, "application");
505 
506  lua_pushstring(L, "__call");
507  lua_pushcfunction(L, &lua_pbx_exec);
508  lua_settable(L, -3);
509 
510  lua_pop(L, 1);
511 }
static int lua_pbx_exec(lua_State *L)
[lua_CFunction] This function is part of the &#39;application&#39; metatable and is used to execute applicati...
Definition: pbx_lua.c:186

◆ lua_create_autoservice_functions()

static void lua_create_autoservice_functions ( lua_State *  L)
static

Create the autoservice functions.

Parameters
Lthe lua_State to use

Definition at line 518 of file pbx_lua.c.

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

Referenced by lua_load_extensions().

519 {
520  lua_pushcfunction(L, &lua_autoservice_start);
521  lua_setglobal(L, "autoservice_start");
522 
523  lua_pushcfunction(L, &lua_autoservice_stop);
524  lua_setglobal(L, "autoservice_stop");
525 
526  lua_pushcfunction(L, &lua_autoservice_status);
527  lua_setglobal(L, "autoservice_status");
528 
529  lua_pushboolean(L, 1);
530  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
531 }
static int lua_autoservice_start(lua_State *L)
[lua_CFunction] Tell pbx_lua to maintain an autoservice on this channel (for access from lua...
Definition: pbx_lua.c:695
static int lua_autoservice_status(lua_State *L)
[lua_CFunction] Get the status of the autoservice flag (for access from lua, don&#39;t call directly) ...
Definition: pbx_lua.c:760
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...
Definition: pbx_lua.c:728

◆ lua_create_channel_table()

static void lua_create_channel_table ( lua_State *  L)
static

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

Parameters
Lthe lua_State to use

Definition at line 463 of file pbx_lua.c.

References lua_get_variable(), and lua_set_variable().

Referenced by lua_load_extensions().

464 {
465  lua_newtable(L);
466  luaL_newmetatable(L, "channel_data");
467 
468  lua_pushstring(L, "__index");
469  lua_pushcfunction(L, &lua_get_variable);
470  lua_settable(L, -3);
471 
472  lua_pushstring(L, "__newindex");
473  lua_pushcfunction(L, &lua_set_variable);
474  lua_settable(L, -3);
475 
476  lua_setmetatable(L, -2);
477  lua_setglobal(L, "channel");
478 }
static int lua_get_variable(lua_State *L)
[lua_CFunction] Return a lua &#39;variable&#39; object (for access from lua, don&#39;t call directly) ...
Definition: pbx_lua.c:556
static int lua_set_variable(lua_State *L)
[lua_CFunction] Set the value of a channel variable or dialplan function (for access from lua...
Definition: pbx_lua.c:596

◆ lua_create_hangup_function()

static void lua_create_hangup_function ( lua_State *  L)
static

Create the hangup check function.

Parameters
Lthe lua_State to use

Definition at line 538 of file pbx_lua.c.

References lua_check_hangup().

Referenced by lua_load_extensions().

539 {
540  lua_pushcfunction(L, &lua_check_hangup);
541  lua_setglobal(L, "check_hangup");
542 }
static int lua_check_hangup(lua_State *L)
[lua_CFunction] Check if this channel has been hungup or not (for access from lua, don&#39;t call directly)
Definition: pbx_lua.c:774

◆ lua_create_variable_metatable()

static void lua_create_variable_metatable ( lua_State *  L)
static

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

Parameters
Lthe lua_State to use

Definition at line 485 of file pbx_lua.c.

References lua_func_read().

Referenced by lua_load_extensions().

486 {
487  luaL_newmetatable(L, "variable");
488 
489  lua_pushstring(L, "__call");
490  lua_pushcfunction(L, &lua_func_read);
491  lua_settable(L, -3);
492 
493  lua_pop(L, 1);
494 }
static int lua_func_read(lua_State *L)
[lua_CFunction] Create a &#39;variable&#39; object for accessing a dialplan function (for access from lua...
Definition: pbx_lua.c:670

◆ lua_datastore_fixup()

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
datathe datastore data, in this case it will be a lua_State
old_chanthe channel we are moving from
new_chanthe channel we are moving to

This function updates our internal channel pointer.

Definition at line 137 of file pbx_lua.c.

138 {
139  lua_State *L = data;
140  lua_pushlightuserdata(L, new_chan);
141  lua_setfield(L, LUA_REGISTRYINDEX, "channel");
142 }
const char * data

◆ lua_error_function()

static int lua_error_function ( lua_State *  L)
static

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

Parameters
Lthe lua_State to use

Definition at line 791 of file pbx_lua.c.

Referenced by exec(), and lua_read_extensions_file().

792 {
793  int message_index;
794 
795  /* pass number arguments right through back to asterisk*/
796  if (lua_isnumber(L, -1)) {
797  return 1;
798  }
799 
800  /* if we are here then we have a string error message, let's attach a
801  * backtrace to it */
802  message_index = lua_gettop(L);
803 
804  /* prepare to prepend a new line to the traceback */
805  lua_pushliteral(L, "\n");
806 
807  lua_getglobal(L, "debug");
808  if (!lua_istable(L, -1)) {
809  /* Have no 'debug' table for whatever reason */
810  lua_pop(L, 2);
811  /* Original err message is on stack top now */
812  return 1;
813  }
814  lua_getfield(L, -1, "traceback");
815  if (!lua_isfunction(L, -1)) {
816  /* Same here for traceback function */
817  lua_pop(L, 3);
818  /* Original err message is on stack top now */
819  return 1;
820  }
821  lua_remove(L, -2); /* remove the 'debug' table */
822 
823  lua_pushvalue(L, message_index);
824  lua_remove(L, message_index);
825 
826  lua_pushnumber(L, 2);
827 
828  lua_call(L, 2, 1);
829 
830  /* prepend the new line we prepared above */
831  lua_concat(L, 2);
832 
833  return 1;
834 }

◆ lua_extension_cmp()

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

References a, ast_extension_cmp(), and b.

Referenced by lua_sort_extensions().

1068 {
1069  const char *a = luaL_checkstring(L, -2);
1070  const char *b = luaL_checkstring(L, -1);
1071 
1072  if (ast_extension_cmp(a, b) == -1)
1073  lua_pushboolean(L, 1);
1074  else
1075  lua_pushboolean(L, 0);
1076 
1077  return 1;
1078 }
int ast_extension_cmp(const char *a, const char *b)
Determine if one extension should match before another.
Definition: pbx.c:2183
static struct test_val b
static struct test_val a

◆ lua_find_extension()

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
Lthe lua_State to use
contextthe context to look in
extenthe extension to look up
prioritythe priority to check, '1' is the only valid priority
functhe calling func, used to adjust matching behavior between, match, canmatch, and matchmore
push_funcwhether or not to push the lua function for the given extension onto the stack

Definition at line 1493 of file pbx_lua.c.

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

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

1494 {
1495  int context_table, context_order_table, i;
1496 
1497  ast_debug(2, "Looking up %s@%s:%i\n", exten, context, priority);
1498  if (priority != 1)
1499  return 0;
1500 
1501  /* load the 'extensions' table */
1502  lua_getglobal(L, "extensions");
1503  if (lua_isnil(L, -1)) {
1504  ast_log(LOG_ERROR, "Unable to find 'extensions' table in extensions.lua\n");
1505  lua_pop(L, 1);
1506  return 0;
1507  }
1508 
1509  /* load the given context */
1510  lua_getfield(L, -1, context);
1511  if (lua_isnil(L, -1)) {
1512  lua_pop(L, 2);
1513  return 0;
1514  }
1515 
1516  /* remove the extensions table */
1517  lua_remove(L, -2);
1518 
1519  context_table = lua_gettop(L);
1520 
1521  /* load the extensions order table for this context */
1522  lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
1523  lua_getfield(L, -1, context);
1524 
1525  lua_remove(L, -2); /* remove the extensions order table */
1526 
1527  context_order_table = lua_gettop(L);
1528 
1529  /* step through the extensions looking for a match */
1530 #if LUA_VERSION_NUM < 502
1531  for (i = 1; i < lua_objlen(L, context_order_table) + 1; i++) {
1532 #else
1533  for (i = 1; i < lua_rawlen(L, context_order_table) + 1; i++) {
1534 #endif
1535  int e_index_copy, match = 0;
1536  const char *e;
1537 
1538  lua_pushinteger(L, i);
1539  lua_gettable(L, context_order_table);
1540  lua_gettop(L);
1541 
1542  /* copy the key at the top of the stack for use later */
1543  lua_pushvalue(L, -1);
1544  e_index_copy = lua_gettop(L);
1545 
1546  if (!(e = lua_tostring(L, e_index_copy))) {
1547  lua_pop(L, 2);
1548  continue;
1549  }
1550 
1551  /* make sure this is not the 'include' extension */
1552  if (!strcasecmp(e, "include")) {
1553  lua_pop(L, 2);
1554  continue;
1555  }
1556 
1557  if (func == &matchmore)
1558  match = ast_extension_close(e, exten, E_MATCHMORE);
1559  else if (func == &canmatch)
1560  match = ast_extension_close(e, exten, E_CANMATCH);
1561  else
1562  match = ast_extension_match(e, exten);
1563 
1564  /* the extension matching functions return 0 on fail, 1 on
1565  * match, 2 on earlymatch */
1566 
1567  if (!match) {
1568  /* pop the copy and the extension */
1569  lua_pop(L, 2);
1570  continue; /* keep trying */
1571  }
1572 
1573  if (func == &matchmore && match == 2) {
1574  /* We match an extension ending in '!'. The decision in
1575  * this case is final and counts as no match. */
1576  lua_pop(L, 4);
1577  return 0;
1578  }
1579 
1580  /* remove the context table, the context order table, the
1581  * extension, and the extension copy (or replace the extension
1582  * with the corresponding function) */
1583  if (push_func) {
1584  lua_pop(L, 1); /* pop the copy */
1585  lua_gettable(L, context_table);
1586  lua_insert(L, -3);
1587  lua_pop(L, 2);
1588  } else {
1589  lua_pop(L, 4);
1590  }
1591 
1592  return 1;
1593  }
1594 
1595  /* load the includes for this context */
1596  lua_getfield(L, context_table, "include");
1597  if (lua_isnil(L, -1)) {
1598  lua_pop(L, 3);
1599  return 0;
1600  }
1601 
1602  /* remove the context and the order table*/
1603  lua_remove(L, context_order_table);
1604  lua_remove(L, context_table);
1605 
1606  /* Now try any includes we have in this context */
1607  for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
1608  const char *c = lua_tostring(L, -1);
1609  if (!c)
1610  continue;
1611 
1612  if (lua_find_extension(L, c, exten, priority, func, push_func)) {
1613  /* remove the value, the key, and the includes table
1614  * from the stack. Leave the function behind if
1615  * necessary */
1616 
1617  if (push_func)
1618  lua_insert(L, -4);
1619 
1620  lua_pop(L, 3);
1621  return 1;
1622  }
1623  }
1624 
1625  /* pop the includes table */
1626  lua_pop(L, 1);
1627  return 0;
1628 }
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.
Definition: pbx_lua.c:1493
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1381
static struct test_val c
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
static int priority
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static int canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1358
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: extconf.c:4297
int ast_extension_close(const char *pattern, const char *data, int needmore)
Definition: pbx.c:2418
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ lua_free_extensions()

static void lua_free_extensions ( void  )
static

Free the internal extensions buffer.

Definition at line 1252 of file pbx_lua.c.

References ast_free, ast_mutex_lock, ast_mutex_unlock, config_file_data, config_file_lock, and config_file_size.

Referenced by unload_module().

1253 {
1255  config_file_size = 0;
1258 }
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t config_file_lock
Definition: pbx_lua.c:106
static long config_file_size
Definition: pbx_lua.c:108
static char * config_file_data
Definition: pbx_lua.c:107
#define ast_free(a)
Definition: astmm.h:182
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ lua_func_read()

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

References lua_concat_args(), and lua_push_variable_table().

Referenced by lua_create_variable_metatable().

671 {
672  int nargs = lua_gettop(L);
673 
674  /* build a string in the form of "func_name(arg1,arg2,arg3)" */
675  lua_getfield(L, 1, "name");
676  lua_pushliteral(L, "(");
677  lua_concat_args(L, 2, nargs);
678  lua_pushliteral(L, ")");
679  lua_concat(L, 4);
680 
682  return 1;
683 }
static void lua_concat_args(lua_State *L, int start, int nargs)
Concatenate a list of lua function arguments into a comma separated string.
Definition: pbx_lua.c:631
static void lua_push_variable_table(lua_State *L)
Push a &#39;variable&#39; table on the stack for access the channel variable with the given name...
Definition: pbx_lua.c:424

◆ lua_get_state()

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 1273 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, error(), LOG_ERROR, lua_load_extensions(), and NULL.

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

1274 {
1275  struct ast_datastore *datastore = NULL;
1276  lua_State *L;
1277 
1278  if (!chan) {
1279  L = luaL_newstate();
1280  if (!L) {
1281  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1282  return NULL;
1283  }
1284 
1285  if (lua_load_extensions(L, NULL)) {
1286  const char *error = lua_tostring(L, -1);
1287  ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
1288  lua_close(L);
1289  return NULL;
1290  }
1291  return L;
1292  } else {
1293  ast_channel_lock(chan);
1294  datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
1295  ast_channel_unlock(chan);
1296 
1297  if (!datastore) {
1298  /* nothing found, allocate a new lua state */
1299  datastore = ast_datastore_alloc(&lua_datastore, NULL);
1300  if (!datastore) {
1301  ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
1302  return NULL;
1303  }
1304 
1305  datastore->data = luaL_newstate();
1306  if (!datastore->data) {
1307  ast_datastore_free(datastore);
1308  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1309  return NULL;
1310  }
1311 
1312  ast_channel_lock(chan);
1313  ast_channel_datastore_add(chan, datastore);
1314  ast_channel_unlock(chan);
1315 
1316  L = datastore->data;
1317 
1318  if (lua_load_extensions(L, chan)) {
1319  const char *error = lua_tostring(L, -1);
1320  ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", ast_channel_name(chan), error);
1321 
1322  ast_channel_lock(chan);
1323  ast_channel_datastore_remove(chan, datastore);
1324  ast_channel_unlock(chan);
1325 
1326  ast_datastore_free(datastore);
1327  return NULL;
1328  }
1329  }
1330 
1331  return datastore->data;
1332  }
1333 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_log
Definition: astobj2.c:42
static const struct ast_datastore_info lua_datastore
Definition: pbx_lua.c:113
static int lua_load_extensions(lua_State *L, struct ast_channel *chan)
Load the extensions.lua file from the internal buffer.
Definition: pbx_lua.c:1170
#define LOG_ERROR
Definition: logger.h:285
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70
const char * ast_channel_name(const struct ast_channel *chan)
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399

◆ lua_get_variable()

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

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

Referenced by lua_create_channel_table().

557 {
558  struct ast_channel *chan;
559  const char *name = luaL_checkstring(L, 2);
560  char *value = NULL;
561  char *workspace = ast_alloca(LUA_BUF_SIZE);
562  workspace[0] = '\0';
563 
564  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
565  chan = lua_touserdata(L, -1);
566  lua_pop(L, 1);
567 
568  lua_pushvalue(L, 2);
570 
571  /* if this is not a request for a dialplan funciton attempt to retrieve
572  * the value of the variable */
573  if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') {
574  pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan));
575  }
576 
577  if (value) {
578  lua_pushstring(L, value);
579  lua_setfield(L, -2, "value");
580  }
581 
582  return 1;
583 }
Main Channel structure associated with a channel.
static void lua_push_variable_table(lua_State *L)
Push a &#39;variable&#39; table on the stack for access the channel variable with the given name...
Definition: pbx_lua.c:424
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
static const char name[]
Definition: cdr_mysql.c:74
#define LUA_BUF_SIZE
Definition: pbx_lua.c:56

◆ lua_get_variable_value()

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

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

Referenced by lua_push_variable_table().

301 {
302  struct ast_channel *chan;
303  char *value = NULL, *name;
304  char *workspace = ast_alloca(LUA_BUF_SIZE);
305  int autoservice;
306 
307  workspace[0] = '\0';
308 
309  if (!lua_istable(L, 1)) {
310  lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value");
311  return lua_error(L);
312  }
313 
314  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
315  chan = lua_touserdata(L, -1);
316  lua_pop(L, 1);
317 
318  lua_getfield(L, 1, "name");
319  name = ast_strdupa(lua_tostring(L, -1));
320  lua_pop(L, 1);
321 
322  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
323  autoservice = lua_toboolean(L, -1);
324  lua_pop(L, 1);
325 
326  if (autoservice)
327  ast_autoservice_stop(chan);
328 
329  /* if this is a dialplan function then use ast_func_read(), otherwise
330  * use pbx_retrieve_variable() */
331  if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') {
332  value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace;
333  } else {
334  pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan));
335  }
336 
337  if (autoservice)
338  ast_autoservice_start(chan);
339 
340  if (value) {
341  lua_pushstring(L, value);
342  } else {
343  lua_pushnil(L);
344  }
345 
346  return 1;
347 }
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
Main Channel structure associated with a channel.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
static const char name[]
Definition: cdr_mysql.c:74
#define LUA_BUF_SIZE
Definition: pbx_lua.c:56

◆ lua_load_extensions()

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

Load the extensions.lua file from the internal buffer.

Parameters
Lthe lua_State to use
chanchannel 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
0success
1failure

Definition at line 1170 of file pbx_lua.c.

References ast_mutex_lock, ast_mutex_unlock, config_file_data, config_file_lock, config_file_size, 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().

1171 {
1172 
1173  /* store a pointer to this channel */
1174  lua_pushlightuserdata(L, chan);
1175  lua_setfield(L, LUA_REGISTRYINDEX, "channel");
1176 
1177  luaL_openlibs(L);
1178 
1179  /* load and sort extensions */
1181  if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
1182  || lua_pcall(L, 0, LUA_MULTRET, 0)
1183  || lua_sort_extensions(L)) {
1185  return 1;
1186  }
1188 
1189  /* now we setup special tables and functions */
1190 
1193 
1196 
1199 
1200  return 0;
1201 }
static void lua_create_application_metatable(lua_State *L)
Create the &#39;application&#39; metatable, used to execute asterisk applications from lua.
Definition: pbx_lua.c:502
static void lua_create_variable_metatable(lua_State *L)
Create the &#39;variable&#39; metatable, used to retrieve channel variables.
Definition: pbx_lua.c:485
static void lua_create_app_table(lua_State *L)
Create the global &#39;app&#39; table for executing applications.
Definition: pbx_lua.c:445
static int lua_sort_extensions(lua_State *L)
Store the sort order of each context.
Definition: pbx_lua.c:844
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t config_file_lock
Definition: pbx_lua.c:106
static long config_file_size
Definition: pbx_lua.c:108
static char * config_file_data
Definition: pbx_lua.c:107
static void lua_create_hangup_function(lua_State *L)
Create the hangup check function.
Definition: pbx_lua.c:538
static void lua_create_autoservice_functions(lua_State *L)
Create the autoservice functions.
Definition: pbx_lua.c:518
static void lua_create_channel_table(lua_State *L)
Create the global &#39;channel&#39; table for accesing channel variables.
Definition: pbx_lua.c:463
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ lua_pbx_exec()

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

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

Referenced by lua_create_application_metatable().

187 {
188  int res, nargs = lua_gettop(L);
189  const char *data = "";
190  char *app_name, *context, *exten;
191  char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
192  int priority, autoservice;
193  struct ast_app *app;
194  struct ast_channel *chan;
195 
196  lua_getfield(L, 1, "name");
197  app_name = ast_strdupa(lua_tostring(L, -1));
198  lua_pop(L, 1);
199 
200  if (!(app = pbx_findapp(app_name))) {
201  lua_pushstring(L, "application '");
202  lua_pushstring(L, app_name);
203  lua_pushstring(L, "' not found");
204  lua_concat(L, 3);
205  return lua_error(L);
206  }
207 
208 
209  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
210  chan = lua_touserdata(L, -1);
211  lua_pop(L, 1);
212 
213  context = ast_strdupa(ast_channel_context(chan));
214  exten = ast_strdupa(ast_channel_exten(chan));
215  priority = ast_channel_priority(chan);
216 
217  lua_concat_args(L, 2, nargs);
218  data = lua_tostring(L, -1);
219 
220  ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
221  exten, context, priority,
222  term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
223  term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
224  term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));
225 
226  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
227  autoservice = lua_toboolean(L, -1);
228  lua_pop(L, 1);
229 
230  if (autoservice)
231  ast_autoservice_stop(chan);
232 
233  res = pbx_exec(chan, app, data);
234 
235  lua_pop(L, 1); /* pop data */
236  data = "";
237 
238  if (autoservice)
239  ast_autoservice_start(chan);
240 
241  /* error executing an application, report it */
242  if (res) {
243  lua_pushinteger(L, res);
244  return lua_error(L);
245  }
246 
247  if (strcmp(context, ast_channel_context(chan))) {
248  lua_pushstring(L, context);
249  lua_pushstring(L, ast_channel_context(chan));
250  lua_pushliteral(L, "context");
251  } else if (strcmp(exten, ast_channel_exten(chan))) {
252  lua_pushstring(L, exten);
253  lua_pushstring(L, ast_channel_exten(chan));
254  lua_pushliteral(L, "exten");
255  } else if (priority != ast_channel_priority(chan)) {
256  lua_pushinteger(L, priority);
257  lua_pushinteger(L, ast_channel_priority(chan));
258  lua_pushliteral(L, "priority");
259  } else {
260  /* no goto - restore the original position back
261  * to lua state, in case this was a recursive dialplan
262  * call (a dialplan application re-entering dialplan) */
263  lua_update_registry(L, context, exten, priority);
264  return 0;
265  }
266 
267  /* goto detected - construct error message */
268  lua_insert(L, -3);
269 
270  lua_pushliteral(L, " changed from ");
271  lua_insert(L, -3);
272 
273  lua_pushliteral(L, " to ");
274  lua_insert(L, -2);
275 
276  lua_concat(L, 5);
277 
278  ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1));
279  lua_pop(L, 1);
280 
281  /* let the lua engine know it needs to return control to the pbx */
282  lua_pushinteger(L, LUA_GOTO_DETECTED);
283  lua_error(L);
284 
285  return 0;
286 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
#define LUA_EXT_DATA_SIZE
Definition: pbx_lua.c:54
static void lua_concat_args(lua_State *L, int start, int nargs)
Concatenate a list of lua function arguments into a comma separated string.
Definition: pbx_lua.c:631
static int tmp()
Definition: bt_open.c:389
const char * data
static int priority
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:463
#define COLOR_BRCYAN
Definition: term.h:60
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define LUA_GOTO_DETECTED
Definition: pbx_lua.c:61
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_exten(const struct ast_channel *chan)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
#define COLOR_BRMAGENTA
Definition: term.h:58
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
ast_app: A registered application
Definition: pbx_app.c:45
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
static const char app[]
Definition: app_mysql.c:62
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.
Definition: pbx_lua.c:404

◆ lua_pbx_findapp()

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

References app_name().

Referenced by lua_create_app_table().

156 {
157  const char *app_name = luaL_checkstring(L, 2);
158 
159  lua_newtable(L);
160 
161  lua_pushstring(L, "name");
162  lua_pushstring(L, app_name);
163  lua_settable(L, -3);
164 
165  luaL_getmetatable(L, "application");
166  lua_setmetatable(L, -2);
167 
168  return 1;
169 }
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463

◆ lua_push_variable_table()

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
Lthe lua_State to use

Definition at line 424 of file pbx_lua.c.

References lua_get_variable_value(), and lua_set_variable_value().

Referenced by lua_func_read(), and lua_get_variable().

425 {
426  lua_newtable(L);
427  luaL_getmetatable(L, "variable");
428  lua_setmetatable(L, -2);
429 
430  lua_insert(L, -2); /* move the table after the name */
431  lua_setfield(L, -2, "name");
432 
433  lua_pushcfunction(L, &lua_get_variable_value);
434  lua_setfield(L, -2, "get");
435 
436  lua_pushcfunction(L, &lua_set_variable_value);
437  lua_setfield(L, -2, "set");
438 }
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...
Definition: pbx_lua.c:300
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...
Definition: pbx_lua.c:360

◆ lua_read_extensions_file()

static char * lua_read_extensions_file ( lua_State *  L,
long *  size,
int *  file_not_openable 
)
static

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

Parameters
Lthe lua_State to use
sizea pointer to store the size of the buffer
file_not_openablea pointer to store if config file could be opened
Note
The caller is expected to free the buffer at some point.
Returns
a pointer to the buffer

Definition at line 1091 of file pbx_lua.c.

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

Referenced by lua_reload_extensions().

1092 {
1093  FILE *f;
1094  int error_func;
1095  char *data;
1096  char *path = ast_alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2);
1097  sprintf(path, "%s/%s", ast_config_AST_CONFIG_DIR, config);
1098 
1099  if (!(f = fopen(path, "r"))) {
1100  lua_pushstring(L, "cannot open '");
1101  lua_pushstring(L, path);
1102  lua_pushstring(L, "' for reading: ");
1103  lua_pushstring(L, strerror(errno));
1104  lua_concat(L, 4);
1105 
1106  *file_not_openable = 1;
1107 
1108  return NULL;
1109  }
1110 
1111  if (fseek(f, 0l, SEEK_END)) {
1112  fclose(f);
1113  lua_pushliteral(L, "error determining the size of the config file");
1114  return NULL;
1115  }
1116 
1117  *size = ftell(f);
1118 
1119  if (fseek(f, 0l, SEEK_SET)) {
1120  *size = 0;
1121  fclose(f);
1122  lua_pushliteral(L, "error reading config file");
1123  return NULL;
1124  }
1125 
1126  if (!(data = ast_malloc(*size))) {
1127  *size = 0;
1128  fclose(f);
1129  lua_pushstring(L, "not enough memory");
1130  return NULL;
1131  }
1132 
1133  if (fread(data, sizeof(char), *size, f) != *size) {
1134  *size = 0;
1135  fclose(f);
1136  lua_pushliteral(L, "problem reading configuration file");
1137  return NULL;
1138  }
1139  fclose(f);
1140 
1141  lua_pushcfunction(L, &lua_error_function);
1142  error_func = lua_gettop(L);
1143 
1144  if (luaL_loadbuffer(L, data, *size, "extensions.lua")
1145  || lua_pcall(L, 0, LUA_MULTRET, error_func)
1146  || lua_sort_extensions(L)
1147  || lua_register_switches(L)
1148  || lua_register_hints(L)) {
1149  ast_free(data);
1150  data = NULL;
1151  *size = 0;
1152  }
1153 
1154  lua_remove(L, error_func);
1155  return data;
1156 }
static int lua_sort_extensions(lua_State *L)
Store the sort order of each context.
Definition: pbx_lua.c:844
#define NULL
Definition: resample.c:96
const char * data
static int lua_register_switches(lua_State *L)
Register dialplan switches for our pbx_lua contexs.
Definition: pbx_lua.c:929
static char * config
Definition: pbx_lua.c:48
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
int errno
static int lua_error_function(lua_State *L)
[lua_CFunction] Handle lua errors (for access from lua, don&#39;t call directly)
Definition: pbx_lua.c:791
#define ast_free(a)
Definition: astmm.h:182
static int lua_register_hints(lua_State *L)
Register dialplan hints for our pbx_lua contexs.
Definition: pbx_lua.c:987

◆ lua_register_hints()

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
0success
1failure

Definition at line 987 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, context_name, hints, NULL, PRIORITY_HINT, and registrar.

Referenced by lua_read_extensions_file().

988 {
989  int hints;
990  struct ast_context *con = NULL;
991 
992  /* create the hash table for our contexts */
993  /* XXX do we ever need to destroy this? pbx_config does not */
994  if (!local_table)
996 
997  /* load the 'hints' table */
998  lua_getglobal(L, "hints");
999  hints = lua_gettop(L);
1000  if (lua_isnil(L, -1)) {
1001  /* hints table not found, move along */
1002  lua_pop(L, 1);
1003  return 0;
1004  }
1005 
1006  /* iterate through the hints table and register each context and
1007  * the hints that go along with it
1008  */
1009  for (lua_pushnil(L); lua_next(L, hints); lua_pop(L, 1)) {
1010  int context = lua_gettop(L);
1011  int context_name = context - 1;
1012  const char *context_str = lua_tostring(L, context_name);
1013 
1014  /* find or create this context */
1016  if (!con) {
1017  /* remove hints table and context key and value */
1018  lua_pop(L, 3);
1019  lua_pushstring(L, "Failed to find or create context\n");
1020  return 1;
1021  }
1022 
1023  /* register each hint */
1024  for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
1025  const char *hint_value = lua_tostring(L, -1);
1026  const char *hint_name;
1027 
1028  /* the hint value is not a string, ignore it */
1029  if (!hint_value) {
1030  continue;
1031  }
1032 
1033  /* copy the name then convert it to a string */
1034  lua_pushvalue(L, -2);
1035  if (!(hint_name = lua_tostring(L, -1))) {
1036  /* ignore non-string value */
1037  lua_pop(L, 1);
1038  continue;
1039  }
1040 
1041  if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar, NULL, 0)) {
1042  /* remove hints table, hint name, hint value,
1043  * key copy, context name, and contex table */
1044  lua_pop(L, 6);
1045  lua_pushstring(L, "Error creating hint\n");
1046  return 1;
1047  }
1048 
1049  /* pop the name copy */
1050  lua_pop(L, 1);
1051  }
1052  }
1053 
1054  /* remove the hints table */
1055  lua_pop(L, 1);
1056 
1057  return 0;
1058 }
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: ael_main.c:589
static struct ast_hashtab * local_table
Definition: pbx_lua.c:111
static char * registrar
Definition: pbx_lua.c:49
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
#define NULL
Definition: resample.c:96
static struct ao2_container * hints
Definition: pbx.c:801
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition: hashtab.c:84
static const char context_name[]
static struct ast_context * local_contexts
Definition: pbx_lua.c:110
#define PRIORITY_HINT
Definition: pbx.h:54
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: ael_main.c:596
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Add an extension to an extension context, this time with an ast_context *.
Definition: pbx.c:7299
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Definition: hashtab.h:261
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ lua_register_switches()

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
0success
1failure

Definition at line 929 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(), context, context_name, NULL, and registrar.

Referenced by lua_read_extensions_file().

930 {
931  int extensions;
932  struct ast_context *con = NULL;
933 
934  /* create the hash table for our contexts */
935  /* XXX do we ever need to destroy this? pbx_config does not */
936  if (!local_table)
938 
939  /* load the 'extensions' table */
940  lua_getglobal(L, "extensions");
941  extensions = lua_gettop(L);
942  if (lua_isnil(L, -1)) {
943  lua_pop(L, 1);
944  lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
945  return 1;
946  }
947 
948  /* iterate through the extensions table and register a context and
949  * dialplan switch for each lua context
950  */
951  for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
952  int context = lua_gettop(L);
953  int context_name = context - 1;
954  const char *context_str = lua_tostring(L, context_name);
955 
956  /* find or create this context */
958  if (!con) {
959  /* remove extensions table and context key and value */
960  lua_pop(L, 3);
961  lua_pushstring(L, "Failed to find or create context\n");
962  return 1;
963  }
964 
965  /* register the switch */
966  if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
967  /* remove extensions table and context key and value */
968  lua_pop(L, 3);
969  lua_pushstring(L, "Unable to create switch for context\n");
970  return 1;
971  }
972  }
973 
974  /* remove the extensions table */
975  lua_pop(L, 1);
976  return 0;
977 }
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: ael_main.c:589
static struct ast_hashtab * local_table
Definition: pbx_lua.c:111
static char * registrar
Definition: pbx_lua.c:49
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: ael_main.c:370
#define NULL
Definition: resample.c:96
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition: hashtab.c:84
static const char context_name[]
static struct ast_context * local_contexts
Definition: pbx_lua.c:110
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: ael_main.c:596
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Definition: hashtab.h:261
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284

◆ lua_reload_extensions()

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
Lthe lua_State to use (must be freshly allocated with luaL_newstate(), don't use lua_get_state())

Definition at line 1213 of file pbx_lua.c.

References ast_free, ast_merge_contexts_and_delete(), ast_mutex_lock, ast_mutex_unlock, config_file_data, config_file_lock, config_file_size, lua_read_extensions_file(), NULL, and registrar.

Referenced by load_or_reload_lua_stuff().

1214 {
1215  long size = 0;
1216  char *data = NULL;
1217  int file_not_openable = 0;
1218 
1219  luaL_openlibs(L);
1220 
1221  if (!(data = lua_read_extensions_file(L, &size, &file_not_openable))) {
1222  if (file_not_openable) {
1223  return -1;
1224  }
1225  return 1;
1226  }
1227 
1229 
1230  if (config_file_data)
1232 
1233  config_file_data = data;
1234  config_file_size = size;
1235 
1236  /* merge our new contexts */
1238  /* merge_contexts_and_delete will actually, at the correct moment,
1239  set the global dialplan pointers to your local_contexts and local_table.
1240  It then will free up the old tables itself. Just be sure not to
1241  hang onto the pointers. */
1242  local_table = NULL;
1243  local_contexts = NULL;
1244 
1246  return 0;
1247 }
static struct ast_hashtab * local_table
Definition: pbx_lua.c:111
static char * registrar
Definition: pbx_lua.c:49
static char * lua_read_extensions_file(lua_State *L, long *size, int *file_not_openable)
Load the extensions.lua file in to a buffer and execute the file.
Definition: pbx_lua.c:1091
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
static ast_mutex_t config_file_lock
Definition: pbx_lua.c:106
static long config_file_size
Definition: pbx_lua.c:108
static struct ast_context * local_contexts
Definition: pbx_lua.c:110
static char * config_file_data
Definition: pbx_lua.c:107
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
Definition: conf2ael.c:639
#define ast_free(a)
Definition: astmm.h:182
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ lua_set_variable()

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

597 {
598  struct ast_channel *chan;
599  int autoservice;
600  const char *name = luaL_checkstring(L, 2);
601  const char *value = luaL_checkstring(L, 3);
602 
603  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
604  chan = lua_touserdata(L, -1);
605  lua_pop(L, 1);
606 
607  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
608  autoservice = lua_toboolean(L, -1);
609  lua_pop(L, 1);
610 
611  if (autoservice)
612  ast_autoservice_stop(chan);
613 
614  pbx_builtin_setvar_helper(chan, name, value);
615 
616  if (autoservice)
617  ast_autoservice_start(chan);
618 
619  return 0;
620 }
Main Channel structure associated with a channel.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
int value
Definition: syslog.c:37
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
static const char name[]
Definition: cdr_mysql.c:74
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...

◆ lua_set_variable_value()

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

361 {
362  const char *name, *value;
363  struct ast_channel *chan;
364  int autoservice;
365 
366  if (!lua_istable(L, 1)) {
367  lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable");
368  return lua_error(L);
369  }
370 
371  lua_getfield(L, 1, "name");
372  name = ast_strdupa(lua_tostring(L, -1));
373  lua_pop(L, 1);
374 
375  value = luaL_checkstring(L, 2);
376 
377  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
378  chan = lua_touserdata(L, -1);
379  lua_pop(L, 1);
380 
381  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
382  autoservice = lua_toboolean(L, -1);
383  lua_pop(L, 1);
384 
385  if (autoservice)
386  ast_autoservice_stop(chan);
387 
388  pbx_builtin_setvar_helper(chan, name, value);
389 
390  if (autoservice)
391  ast_autoservice_start(chan);
392 
393  return 0;
394 }
Main Channel structure associated with a channel.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
int value
Definition: syslog.c:37
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
static const char name[]
Definition: cdr_mysql.c:74
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...

◆ lua_sort_extensions()

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
0success
1failure

Definition at line 844 of file pbx_lua.c.

References context, context_name, exten, and lua_extension_cmp().

Referenced by lua_load_extensions(), and lua_read_extensions_file().

845 {
846  int extensions, extensions_order;
847 
848  /* create the extensions_order table */
849  lua_newtable(L);
850  lua_setfield(L, LUA_REGISTRYINDEX, "extensions_order");
851  lua_getfield(L, LUA_REGISTRYINDEX, "extensions_order");
852  extensions_order = lua_gettop(L);
853 
854  /* sort each context in the extensions table */
855  /* load the 'extensions' table */
856  lua_getglobal(L, "extensions");
857  extensions = lua_gettop(L);
858  if (lua_isnil(L, -1)) {
859  lua_pop(L, 1);
860  lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
861  return 1;
862  }
863 
864  /* iterate through the extensions table and create a
865  * matching table (holding the sort order) in the
866  * extensions_order table for each context that is found
867  */
868  for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
869  int context = lua_gettop(L);
870  int context_name = context - 1;
871  int context_order;
872 
873  /* copy the context_name to be used as the key for the
874  * context_order table in the extensions_order table later */
875  lua_pushvalue(L, context_name);
876 
877  /* create the context_order table */
878  lua_newtable(L);
879  context_order = lua_gettop(L);
880 
881  /* iterate through this context an popluate the corrisponding
882  * table in the extensions_order table */
883  for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
884  int exten = lua_gettop(L) - 1;
885 #if LUA_VERSION_NUM < 502
886  lua_pushinteger(L, lua_objlen(L, context_order) + 1);
887 #else
888  lua_pushinteger(L, lua_rawlen(L, context_order) + 1);
889 #endif
890  lua_pushvalue(L, exten);
891  lua_settable(L, context_order);
892  }
893  lua_settable(L, extensions_order); /* put the context_order table in the extensions_order table */
894 
895  /* now sort the new table */
896 
897  /* push the table.sort function */
898  lua_getglobal(L, "table");
899  lua_getfield(L, -1, "sort");
900  lua_remove(L, -2); /* remove the 'table' table */
901 
902  /* push the context_order table */
903  lua_pushvalue(L, context_name);
904  lua_gettable(L, extensions_order);
905 
906  /* push the comp function */
907  lua_pushcfunction(L, &lua_extension_cmp);
908 
909  if (lua_pcall(L, 2, 0, 0)) {
910  lua_insert(L, -5);
911  lua_pop(L, 4);
912  return 1;
913  }
914  }
915 
916  /* remove the extensions table and the extensions_order table */
917  lua_pop(L, 2);
918  return 0;
919 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static const char context_name[]
static int lua_extension_cmp(lua_State *L)
[lua_CFunction] Compare two extensions (for access from lua, don&#39;t call directly) ...
Definition: pbx_lua.c:1067
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ lua_state_destroy()

static void lua_state_destroy ( void *  data)
static

The destructor for lua_datastore.

Definition at line 123 of file pbx_lua.c.

124 {
125  if (data)
126  lua_close(data);
127 }
const char * data

◆ lua_update_registry()

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
Lthe lua_State to use
contextthe new context
extenthe new exten
prioritythe new priority

Definition at line 404 of file pbx_lua.c.

Referenced by exec(), and lua_pbx_exec().

405 {
406  lua_pushstring(L, context);
407  lua_setfield(L, LUA_REGISTRYINDEX, "context");
408 
409  lua_pushstring(L, exten);
410  lua_setfield(L, LUA_REGISTRYINDEX, "exten");
411 
412  lua_pushinteger(L, priority);
413  lua_setfield(L, LUA_REGISTRYINDEX, "priority");
414 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int priority
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ matchmore()

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

1382 {
1383  int res;
1384  lua_State *L;
1385  struct ast_module_user *u = ast_module_user_add(chan);
1386  if (!u) {
1387  ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
1388  return 0;
1389  }
1390 
1391  L = lua_get_state(chan);
1392  if (!L) {
1394  return 0;
1395  }
1396 
1398 
1399  if (!chan) lua_close(L);
1401  return res;
1402 }
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.
Definition: pbx_lua.c:1493
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_lua.c:1381
static int priority
#define ast_module_user_remove(user)
Definition: module.h:427
#define ast_log
Definition: astobj2.c:42
#define ast_module_user_add(chan)
Definition: module.h:426
#define LOG_ERROR
Definition: logger.h:285
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static lua_State * lua_get_state(struct ast_channel *chan)
Get the lua_State for this channel.
Definition: pbx_lua.c:1273

◆ reload()

static int reload ( void  )
static

Definition at line 1675 of file pbx_lua.c.

References load_or_reload_lua_stuff().

Referenced by load_module().

1676 {
1677  return load_or_reload_lua_stuff();
1678 }
static int load_or_reload_lua_stuff(void)
Definition: pbx_lua.c:1640

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1667 of file pbx_lua.c.

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

Referenced by load_module().

1668 {
1672  return 0;
1673 }
static char * registrar
Definition: pbx_lua.c:49
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx_switch.c:76
#define NULL
Definition: resample.c:96
static struct ast_switch lua_switch
Definition: pbx_lua.c:1630
static void lua_free_extensions(void)
Free the internal extensions buffer.
Definition: pbx_lua.c:1252
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: conf2ael.c:625

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, }
static

Definition at line 1700 of file pbx_lua.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1700 of file pbx_lua.c.

◆ config

char* config = "extensions.lua"
static

Definition at line 48 of file pbx_lua.c.

Referenced by lua_read_extensions_file().

◆ config_file_data

char* config_file_data = NULL
static

Definition at line 107 of file pbx_lua.c.

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

◆ config_file_lock

ast_mutex_t config_file_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 106 of file pbx_lua.c.

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

◆ config_file_size

long config_file_size = 0
static

Definition at line 108 of file pbx_lua.c.

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

◆ local_contexts

struct ast_context* local_contexts = NULL
static

Definition at line 110 of file pbx_lua.c.

◆ local_table

struct ast_hashtab* local_table = NULL
static

Definition at line 111 of file pbx_lua.c.

◆ lua_datastore

const struct ast_datastore_info lua_datastore
static
Initial value:
= {
.type = "lua",
.destroy = lua_state_destroy,
.chan_fixup = lua_datastore_fixup,
}
static void lua_state_destroy(void *data)
The destructor for lua_datastore.
Definition: pbx_lua.c:123
static void lua_datastore_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
The fixup function for the lua_datastore.
Definition: pbx_lua.c:137

Definition at line 113 of file pbx_lua.c.

◆ lua_switch

struct ast_switch lua_switch
static

Definition at line 1630 of file pbx_lua.c.

◆ registrar

char* registrar = "pbx_lua"
static