Asterisk - The Open Source Telephony Project  21.4.1
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>

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 maintaining 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 accessing 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.
 
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, size_t *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 contexts. More...
 
static int lua_register_switches (lua_State *L)
 Register dialplan switches for our pbx_lua contexts. 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.
 
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 = "da6642af068ee5e6490c5b1d2cc1d238" , .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 const 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 size_t 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 const 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.

Function Documentation

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

References ast_autoservice_start().

Referenced by lua_create_autoservice_functions().

701 {
702  struct ast_channel *chan;
703 
704  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
705  if (lua_toboolean(L, -1)) {
706  /* autservice already running */
707  lua_pop(L, 1);
708  return 0;
709  }
710  lua_pop(L, 1);
711 
712  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
713  chan = lua_touserdata(L, -1);
714  lua_pop(L, 1);
715 
716  ast_autoservice_start(chan);
717 
718  lua_pushboolean(L, 1);
719  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
720  return 0;
721 }
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
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 765 of file pbx_lua.c.

Referenced by lua_create_autoservice_functions().

766 {
767  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
768  return 1;
769 }
static int lua_autoservice_stop ( lua_State *  L)
static

[lua_CFunction] Tell pbx_lua to stop maintaining 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 733 of file pbx_lua.c.

References ast_autoservice_stop().

Referenced by lua_create_autoservice_functions().

734 {
735  struct ast_channel *chan;
736 
737  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
738  if (!lua_toboolean(L, -1)) {
739  /* no autservice running */
740  lua_pop(L, 1);
741  return 0;
742  }
743  lua_pop(L, 1);
744 
745  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
746  chan = lua_touserdata(L, -1);
747  lua_pop(L, 1);
748 
749  ast_autoservice_stop(chan);
750 
751  lua_pushboolean(L, 0);
752  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
753  return 0;
754 }
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
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 779 of file pbx_lua.c.

References ast_check_hangup().

Referenced by lua_create_hangup_function().

780 {
781  struct ast_channel *chan;
782  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
783  chan = lua_touserdata(L, -1);
784  lua_pop(L, 1);
785 
786  lua_pushboolean(L, ast_check_hangup(chan));
787  return 1;
788 }
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
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 636 of file pbx_lua.c.

Referenced by lua_func_read(), and lua_pbx_exec().

636  {
637  int concat = 0;
638  int i = start + 1;
639 
640  if (start <= nargs && !lua_isnil(L, start)) {
641  lua_pushvalue(L, start);
642  concat += 1;
643  }
644 
645  for (; i <= nargs; i++) {
646  if (lua_isnil(L, i)) {
647  lua_pushliteral(L, ",");
648  concat += 1;
649  } else {
650  lua_pushliteral(L, ",");
651  lua_pushvalue(L, i);
652  concat += 2;
653  }
654  }
655 
656  lua_concat(L, concat);
657 }
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 450 of file pbx_lua.c.

References lua_pbx_findapp().

Referenced by lua_load_extensions().

451 {
452  lua_newtable(L);
453  luaL_newmetatable(L, "app");
454 
455  lua_pushstring(L, "__index");
456  lua_pushcfunction(L, &lua_pbx_findapp);
457  lua_settable(L, -3);
458 
459  lua_setmetatable(L, -2);
460  lua_setglobal(L, "app");
461 }
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) ...
Definition: pbx_lua.c:155
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 507 of file pbx_lua.c.

References lua_pbx_exec().

Referenced by lua_load_extensions().

508 {
509  luaL_newmetatable(L, "application");
510 
511  lua_pushstring(L, "__call");
512  lua_pushcfunction(L, &lua_pbx_exec);
513  lua_settable(L, -3);
514 
515  lua_pop(L, 1);
516 }
static int lua_pbx_exec(lua_State *L)
[lua_CFunction] This function is part of the 'application' metatable and is used to execute applicati...
Definition: pbx_lua.c:187
static void lua_create_autoservice_functions ( lua_State *  L)
static

Create the autoservice functions.

Parameters
Lthe lua_State to use

Definition at line 523 of file pbx_lua.c.

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

Referenced by lua_load_extensions().

524 {
525  lua_pushcfunction(L, &lua_autoservice_start);
526  lua_setglobal(L, "autoservice_start");
527 
528  lua_pushcfunction(L, &lua_autoservice_stop);
529  lua_setglobal(L, "autoservice_stop");
530 
531  lua_pushcfunction(L, &lua_autoservice_status);
532  lua_setglobal(L, "autoservice_status");
533 
534  lua_pushboolean(L, 1);
535  lua_setfield(L, LUA_REGISTRYINDEX, "autoservice");
536 }
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:700
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) ...
Definition: pbx_lua.c:765
static int lua_autoservice_stop(lua_State *L)
[lua_CFunction] Tell pbx_lua to stop maintaining an autoservice on this channel (for access from lua...
Definition: pbx_lua.c:733
static void lua_create_channel_table ( lua_State *  L)
static

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

Parameters
Lthe lua_State to use

Definition at line 468 of file pbx_lua.c.

References lua_get_variable(), and lua_set_variable().

Referenced by lua_load_extensions().

469 {
470  lua_newtable(L);
471  luaL_newmetatable(L, "channel_data");
472 
473  lua_pushstring(L, "__index");
474  lua_pushcfunction(L, &lua_get_variable);
475  lua_settable(L, -3);
476 
477  lua_pushstring(L, "__newindex");
478  lua_pushcfunction(L, &lua_set_variable);
479  lua_settable(L, -3);
480 
481  lua_setmetatable(L, -2);
482  lua_setglobal(L, "channel");
483 }
static int lua_get_variable(lua_State *L)
[lua_CFunction] Return a lua 'variable' object (for access from lua, don't call directly) ...
Definition: pbx_lua.c:561
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:601
static void lua_create_hangup_function ( lua_State *  L)
static

Create the hangup check function.

Parameters
Lthe lua_State to use

Definition at line 543 of file pbx_lua.c.

References lua_check_hangup().

Referenced by lua_load_extensions().

544 {
545  lua_pushcfunction(L, &lua_check_hangup);
546  lua_setglobal(L, "check_hangup");
547 }
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)
Definition: pbx_lua.c:779
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 490 of file pbx_lua.c.

References lua_func_read().

Referenced by lua_load_extensions().

491 {
492  luaL_newmetatable(L, "variable");
493 
494  lua_pushstring(L, "__call");
495  lua_pushcfunction(L, &lua_func_read);
496  lua_settable(L, -3);
497 
498  lua_pop(L, 1);
499 }
static int lua_func_read(lua_State *L)
[lua_CFunction] Create a 'variable' object for accessing a dialplan function (for access from lua...
Definition: pbx_lua.c:675
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
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 796 of file pbx_lua.c.

Referenced by lua_read_extensions_file().

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

References ast_extension_cmp().

Referenced by lua_sort_extensions().

1073 {
1074  const char *a = luaL_checkstring(L, -2);
1075  const char *b = luaL_checkstring(L, -1);
1076 
1077  if (ast_extension_cmp(a, b) == -1)
1078  lua_pushboolean(L, 1);
1079  else
1080  lua_pushboolean(L, 0);
1081 
1082  return 1;
1083 }
int ast_extension_cmp(const char *a, const char *b)
Determine if one extension should match before another.
Definition: pbx.c:2197
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 1498 of file pbx_lua.c.

References ast_context_destroy(), ast_debug, ast_extension_match(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_switch(), ast_unregister_switch(), ASTERISK_GPL_KEY, lua_free_extensions(), lua_reload_extensions(), and ast_switch::name.

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

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

References lua_concat_args(), and lua_push_variable_table().

Referenced by lua_create_variable_metatable().

676 {
677  int nargs = lua_gettop(L);
678 
679  /* build a string in the form of "func_name(arg1,arg2,arg3)" */
680  lua_getfield(L, 1, "name");
681  lua_pushliteral(L, "(");
682  lua_concat_args(L, 2, nargs);
683  lua_pushliteral(L, ")");
684  lua_concat(L, 4);
685 
687  return 1;
688 }
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:636
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...
Definition: pbx_lua.c:429
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 1278 of file pbx_lua.c.

References ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_datastore_free(), ast_datastore::data, and lua_load_extensions().

1279 {
1280  struct ast_datastore *datastore = NULL;
1281  lua_State *L;
1282 
1283  if (!chan) {
1284  L = luaL_newstate();
1285  if (!L) {
1286  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1287  return NULL;
1288  }
1289 
1290  if (lua_load_extensions(L, NULL)) {
1291  const char *error = lua_tostring(L, -1);
1292  ast_log(LOG_ERROR, "Error loading extensions.lua: %s\n", error);
1293  lua_close(L);
1294  return NULL;
1295  }
1296  return L;
1297  } else {
1298  ast_channel_lock(chan);
1299  datastore = ast_channel_datastore_find(chan, &lua_datastore, NULL);
1300  ast_channel_unlock(chan);
1301 
1302  if (!datastore) {
1303  /* nothing found, allocate a new lua state */
1304  datastore = ast_datastore_alloc(&lua_datastore, NULL);
1305  if (!datastore) {
1306  ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n");
1307  return NULL;
1308  }
1309 
1310  datastore->data = luaL_newstate();
1311  if (!datastore->data) {
1312  ast_datastore_free(datastore);
1313  ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n");
1314  return NULL;
1315  }
1316 
1317  ast_channel_lock(chan);
1318  ast_channel_datastore_add(chan, datastore);
1319  ast_channel_unlock(chan);
1320 
1321  L = datastore->data;
1322 
1323  if (lua_load_extensions(L, chan)) {
1324  const char *error = lua_tostring(L, -1);
1325  ast_log(LOG_ERROR, "Error loading extensions.lua for %s: %s\n", ast_channel_name(chan), error);
1326 
1327  ast_channel_lock(chan);
1328  ast_channel_datastore_remove(chan, datastore);
1329  ast_channel_unlock(chan);
1330 
1331  ast_datastore_free(datastore);
1332  return NULL;
1333  }
1334  }
1335 
1336  return datastore->data;
1337  }
1338 }
Structure for a data store object.
Definition: datastore.h:64
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:2399
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
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:1175
void * data
Definition: datastore.h:66
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
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.

1 channel.variable

Definition at line 561 of file pbx_lua.c.

References ast_alloca, lua_push_variable_table(), ast_channel::name, and pbx_retrieve_variable().

Referenced by lua_create_channel_table().

562 {
563  struct ast_channel *chan;
564  const char *name = luaL_checkstring(L, 2);
565  char *value = NULL;
566  char *workspace = ast_alloca(LUA_BUF_SIZE);
567  workspace[0] = '\0';
568 
569  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
570  chan = lua_touserdata(L, -1);
571  lua_pop(L, 1);
572 
573  lua_pushvalue(L, 2);
575 
576  /* if this is not a request for a dialplan funciton attempt to retrieve
577  * the value of the variable */
578  if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') {
579  pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan));
580  }
581 
582  if (value) {
583  lua_pushstring(L, value);
584  lua_setfield(L, -2, "value");
585  }
586 
587  return 1;
588 }
Main Channel structure associated with a channel.
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...
Definition: pbx_lua.c:429
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
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.
const ast_string_field name
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.

Returns
LUA error
1 channel.variable:get()

Definition at line 303 of file pbx_lua.c.

References ast_alloca, ast_autoservice_start(), ast_autoservice_stop(), ast_func_read(), ast_strdupa, ast_channel::name, and pbx_retrieve_variable().

Referenced by lua_push_variable_table().

304 {
305  struct ast_channel *chan;
306  char *value = NULL, *name;
307  char *workspace = ast_alloca(LUA_BUF_SIZE);
308  int autoservice;
309 
310  workspace[0] = '\0';
311 
312  if (!lua_istable(L, 1)) {
313  lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value");
314  return lua_error(L);
315  }
316 
317  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
318  chan = lua_touserdata(L, -1);
319  lua_pop(L, 1);
320 
321  lua_getfield(L, 1, "name");
322  name = ast_strdupa(lua_tostring(L, -1));
323  lua_pop(L, 1);
324 
325  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
326  autoservice = lua_toboolean(L, -1);
327  lua_pop(L, 1);
328 
329  if (autoservice)
330  ast_autoservice_stop(chan);
331 
332  /* if this is a dialplan function then use ast_func_read(), otherwise
333  * use pbx_retrieve_variable() */
334  if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') {
335  value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace;
336  } else {
337  pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan));
338  }
339 
340  if (autoservice)
341  ast_autoservice_start(chan);
342 
343  if (value) {
344  lua_pushstring(L, value);
345  } else {
346  lua_pushnil(L);
347  }
348 
349  return 1;
350 }
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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
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:288
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.
const ast_string_field name
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 1175 of file pbx_lua.c.

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

1176 {
1177 
1178  /* store a pointer to this channel */
1179  lua_pushlightuserdata(L, chan);
1180  lua_setfield(L, LUA_REGISTRYINDEX, "channel");
1181 
1182  luaL_openlibs(L);
1183 
1184  /* load and sort extensions */
1185  ast_mutex_lock(&config_file_lock);
1186  if (luaL_loadbuffer(L, config_file_data, config_file_size, "extensions.lua")
1187  || lua_pcall(L, 0, LUA_MULTRET, 0)
1188  || lua_sort_extensions(L)) {
1189  ast_mutex_unlock(&config_file_lock);
1190  return 1;
1191  }
1192  ast_mutex_unlock(&config_file_lock);
1193 
1194  /* now we setup special tables and functions */
1195 
1198 
1201 
1204 
1205  return 0;
1206 }
static void lua_create_application_metatable(lua_State *L)
Create the 'application' metatable, used to execute asterisk applications from lua.
Definition: pbx_lua.c:507
static void lua_create_variable_metatable(lua_State *L)
Create the 'variable' metatable, used to retrieve channel variables.
Definition: pbx_lua.c:490
static void lua_create_app_table(lua_State *L)
Create the global 'app' table for executing applications.
Definition: pbx_lua.c:450
static int lua_sort_extensions(lua_State *L)
Store the sort order of each context.
Definition: pbx_lua.c:849
static void lua_create_hangup_function(lua_State *L)
Create the hangup check function.
Definition: pbx_lua.c:543
static void lua_create_autoservice_functions(lua_State *L)
Create the autoservice functions.
Definition: pbx_lua.c:523
static void lua_create_channel_table(lua_State *L)
Create the global 'channel' table for accessing channel variables.
Definition: pbx_lua.c:468
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

This funciton is executed as the '()' operator for apps accessed through the 'app' table.

Returns
LUA error
1 app.playback('demo-congrats')

Definition at line 187 of file pbx_lua.c.

References app_name(), ast_autoservice_start(), ast_autoservice_stop(), ast_debug, ast_strdupa, lua_concat_args(), lua_update_registry(), pbx_exec(), pbx_findapp(), and term_color().

Referenced by lua_create_application_metatable().

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

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

References lua_get_variable_value(), and lua_set_variable_value().

Referenced by lua_func_read(), and lua_get_variable().

430 {
431  lua_newtable(L);
432  luaL_getmetatable(L, "variable");
433  lua_setmetatable(L, -2);
434 
435  lua_insert(L, -2); /* move the table after the name */
436  lua_setfield(L, -2, "name");
437 
438  lua_pushcfunction(L, &lua_get_variable_value);
439  lua_setfield(L, -2, "get");
440 
441  lua_pushcfunction(L, &lua_set_variable_value);
442  lua_setfield(L, -2, "set");
443 }
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:303
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:365
static char * lua_read_extensions_file ( lua_State *  L,
size_t *  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 1096 of file pbx_lua.c.

References ast_alloca, ast_malloc, ast_context::data, lua_error_function(), lua_register_hints(), lua_register_switches(), and lua_sort_extensions().

Referenced by lua_reload_extensions().

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

Register dialplan hints for our pbx_lua contexts.

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

Return values
0success
1failure

Definition at line 992 of file pbx_lua.c.

References ast_add_extension2(), ast_context_find_or_create(), ast_hashtab_compare_contexts(), ast_hashtab_create, ast_hashtab_newsize_java(), ast_hashtab_resize_java(), hints, PRIORITY_HINT, and ast_context::registrar.

Referenced by lua_read_extensions_file().

993 {
994  int hints;
995  struct ast_context *con = NULL;
996 
997  /* create the hash table for our contexts */
998  /* XXX do we ever need to destroy this? pbx_config does not */
999  if (!local_table)
1000  local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
1001 
1002  /* load the 'hints' table */
1003  lua_getglobal(L, "hints");
1004  hints = lua_gettop(L);
1005  if (lua_isnil(L, -1)) {
1006  /* hints table not found, move along */
1007  lua_pop(L, 1);
1008  return 0;
1009  }
1010 
1011  /* iterate through the hints table and register each context and
1012  * the hints that go along with it
1013  */
1014  for (lua_pushnil(L); lua_next(L, hints); lua_pop(L, 1)) {
1015  int context = lua_gettop(L);
1016  int context_name = context - 1;
1017  const char *context_str = lua_tostring(L, context_name);
1018 
1019  /* find or create this context */
1020  con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
1021  if (!con) {
1022  /* remove hints table and context key and value */
1023  lua_pop(L, 3);
1024  lua_pushstring(L, "Failed to find or create context\n");
1025  return 1;
1026  }
1027 
1028  /* register each hint */
1029  for (lua_pushnil(L); lua_next(L, context); lua_pop(L, 1)) {
1030  const char *hint_value = lua_tostring(L, -1);
1031  const char *hint_name;
1032 
1033  /* the hint value is not a string, ignore it */
1034  if (!hint_value) {
1035  continue;
1036  }
1037 
1038  /* copy the name then convert it to a string */
1039  lua_pushvalue(L, -2);
1040  if (!(hint_name = lua_tostring(L, -1))) {
1041  /* ignore non-string value */
1042  lua_pop(L, 1);
1043  continue;
1044  }
1045 
1046  if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar, NULL, 0)) {
1047  /* remove hints table, hint name, hint value,
1048  * key copy, context name, and contex table */
1049  lua_pop(L, 6);
1050  lua_pushstring(L, "Error creating hint\n");
1051  return 1;
1052  }
1053 
1054  /* pop the name copy */
1055  lua_pop(L, 1);
1056  }
1057  }
1058 
1059  /* remove the hints table */
1060  lua_pop(L, 1);
1061 
1062  return 0;
1063 }
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: ael_main.c:589
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: main/hashtab.c:127
static struct ao2_container * hints
Definition: pbx.c:806
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: main/hashtab.c:84
const char * registrar
Definition: pbx.c:286
#define PRIORITY_HINT
Definition: pbx.h:54
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:7257
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
Definition: hashtab.h:254
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:6149
ast_context: An extension context
Definition: pbx.c:284
static int lua_register_switches ( lua_State *  L)
static

Register dialplan switches for our pbx_lua contexts.

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

Return values
0success
1failure

Definition at line 934 of file pbx_lua.c.

References ast_context_add_switch2(), ast_context_find_or_create(), ast_hashtab_compare_contexts(), ast_hashtab_create, ast_hashtab_newsize_java(), ast_hashtab_resize_java(), and ast_context::registrar.

Referenced by lua_read_extensions_file().

935 {
936  int extensions;
937  struct ast_context *con = NULL;
938 
939  /* create the hash table for our contexts */
940  /* XXX do we ever need to destroy this? pbx_config does not */
941  if (!local_table)
942  local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
943 
944  /* load the 'extensions' table */
945  lua_getglobal(L, "extensions");
946  extensions = lua_gettop(L);
947  if (lua_isnil(L, -1)) {
948  lua_pop(L, 1);
949  lua_pushstring(L, "Unable to find 'extensions' table in extensions.lua\n");
950  return 1;
951  }
952 
953  /* iterate through the extensions table and register a context and
954  * dialplan switch for each lua context
955  */
956  for (lua_pushnil(L); lua_next(L, extensions); lua_pop(L, 1)) {
957  int context = lua_gettop(L);
958  int context_name = context - 1;
959  const char *context_str = lua_tostring(L, context_name);
960 
961  /* find or create this context */
962  con = ast_context_find_or_create(&local_contexts, local_table, context_str, registrar);
963  if (!con) {
964  /* remove extensions table and context key and value */
965  lua_pop(L, 3);
966  lua_pushstring(L, "Failed to find or create context\n");
967  return 1;
968  }
969 
970  /* register the switch */
971  if (ast_context_add_switch2(con, "Lua", "", 0, registrar)) {
972  /* remove extensions table and context key and value */
973  lua_pop(L, 3);
974  lua_pushstring(L, "Unable to create switch for context\n");
975  return 1;
976  }
977  }
978 
979  /* remove the extensions table */
980  lua_pop(L, 1);
981  return 0;
982 }
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: ael_main.c:589
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: main/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
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: main/hashtab.c:84
const char * registrar
Definition: pbx.c:286
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
Definition: hashtab.h:254
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:6149
ast_context: An extension context
Definition: pbx.c:284
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 1218 of file pbx_lua.c.

References ast_merge_contexts_and_delete(), ast_context::data, lua_read_extensions_file(), and ast_context::registrar.

Referenced by lua_find_extension().

1219 {
1220  size_t size = 0;
1221  char *data = NULL;
1222  int file_not_openable = 0;
1223 
1224  luaL_openlibs(L);
1225 
1226  if (!(data = lua_read_extensions_file(L, &size, &file_not_openable))) {
1227  if (file_not_openable) {
1228  return -1;
1229  }
1230  return 1;
1231  }
1232 
1233  ast_mutex_lock(&config_file_lock);
1234 
1235  if (config_file_data)
1236  ast_free(config_file_data);
1237 
1238  config_file_data = data;
1239  config_file_size = size;
1240 
1241  /* merge our new contexts */
1242  ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
1243  /* merge_contexts_and_delete will actually, at the correct moment,
1244  set the global dialplan pointers to your local_contexts and local_table.
1245  It then will free up the old tables itself. Just be sure not to
1246  hang onto the pointers. */
1247  local_table = NULL;
1248  local_contexts = NULL;
1249 
1250  ast_mutex_unlock(&config_file_lock);
1251  return 0;
1252 }
const char * registrar
Definition: pbx.c:286
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: pbx.c:6426
static char * lua_read_extensions_file(lua_State *L, size_t *size, int *file_not_openable)
Load the extensions.lua file in to a buffer and execute the file.
Definition: pbx_lua.c:1096
char data[]
Definition: pbx.c:304
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.

1 channel.variable = "value"

Definition at line 601 of file pbx_lua.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_channel::name, and pbx_builtin_setvar_helper().

Referenced by lua_create_channel_table().

602 {
603  struct ast_channel *chan;
604  int autoservice;
605  const char *name = luaL_checkstring(L, 2);
606  const char *value = luaL_checkstring(L, 3);
607 
608  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
609  chan = lua_touserdata(L, -1);
610  lua_pop(L, 1);
611 
612  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
613  autoservice = lua_toboolean(L, -1);
614  lua_pop(L, 1);
615 
616  if (autoservice)
617  ast_autoservice_stop(chan);
618 
619  pbx_builtin_setvar_helper(chan, name, value);
620 
621  if (autoservice)
622  ast_autoservice_start(chan);
623 
624  return 0;
625 }
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 ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
const ast_string_field name
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...
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.

Returns
LUA error
1 channel.variable:set("value")

Definition at line 365 of file pbx_lua.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_strdupa, ast_channel::name, and pbx_builtin_setvar_helper().

Referenced by lua_push_variable_table().

366 {
367  const char *name, *value;
368  struct ast_channel *chan;
369  int autoservice;
370 
371  if (!lua_istable(L, 1)) {
372  lua_pushstring(L, "User probably used '.' instead of ':' for setting a channel variable");
373  return lua_error(L);
374  }
375 
376  lua_getfield(L, 1, "name");
377  name = ast_strdupa(lua_tostring(L, -1));
378  lua_pop(L, 1);
379 
380  value = luaL_checkstring(L, 2);
381 
382  lua_getfield(L, LUA_REGISTRYINDEX, "channel");
383  chan = lua_touserdata(L, -1);
384  lua_pop(L, 1);
385 
386  lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
387  autoservice = lua_toboolean(L, -1);
388  lua_pop(L, 1);
389 
390  if (autoservice)
391  ast_autoservice_stop(chan);
392 
393  pbx_builtin_setvar_helper(chan, name, value);
394 
395  if (autoservice)
396  ast_autoservice_start(chan);
397 
398  return 0;
399 }
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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
const ast_string_field name
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...
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 849 of file pbx_lua.c.

References ast_channel::context, ast_channel::exten, and lua_extension_cmp().

Referenced by lua_load_extensions(), and lua_read_extensions_file().

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

Referenced by lua_pbx_exec().

410 {
411  lua_pushstring(L, context);
412  lua_setfield(L, LUA_REGISTRYINDEX, "context");
413 
414  lua_pushstring(L, exten);
415  lua_setfield(L, LUA_REGISTRYINDEX, "exten");
416 
417  lua_pushinteger(L, priority);
418  lua_setfield(L, LUA_REGISTRYINDEX, "priority");
419 }
char context[AST_MAX_CONTEXT]
char exten[AST_MAX_EXTENSION]

Variable Documentation

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.