|
|
|
@ -50,7 +50,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|
|
|
|
static char *config = "extensions.lua";
|
|
|
|
|
static char *registrar = "pbx_lua";
|
|
|
|
|
|
|
|
|
|
#ifdef LOW_MEMORY
|
|
|
|
|
#define LUA_EXT_DATA_SIZE 256
|
|
|
|
|
#else
|
|
|
|
|
#define LUA_EXT_DATA_SIZE 8192
|
|
|
|
|
#endif
|
|
|
|
|
#define LUA_BUF_SIZE 4096
|
|
|
|
|
|
|
|
|
|
/* This value is used by the lua engine to signal that a Goto or dialplan jump
|
|
|
|
@ -83,7 +87,7 @@ static int lua_check_hangup(lua_State *L);
|
|
|
|
|
static int lua_error_function(lua_State *L);
|
|
|
|
|
|
|
|
|
|
static void lua_update_registry(lua_State *L, const char *context, const char *exten, int priority);
|
|
|
|
|
static void lua_push_variable_table(lua_State *L, const char *name);
|
|
|
|
|
static void lua_push_variable_table(lua_State *L);
|
|
|
|
|
static void lua_create_app_table(lua_State *L);
|
|
|
|
|
static void lua_create_channel_table(lua_State *L);
|
|
|
|
|
static void lua_create_variable_metatable(lua_State *L);
|
|
|
|
@ -91,6 +95,7 @@ static void lua_create_application_metatable(lua_State *L);
|
|
|
|
|
static void lua_create_autoservice_functions(lua_State *L);
|
|
|
|
|
static void lua_create_hangup_function(lua_State *L);
|
|
|
|
|
static void lua_detect_goto(lua_State *L);
|
|
|
|
|
static void lua_concat_args(lua_State *L, int start, int nargs);
|
|
|
|
|
|
|
|
|
|
static void lua_state_destroy(void *data);
|
|
|
|
|
static void lua_datastore_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
|
|
|
|
@ -184,15 +189,13 @@ static int lua_pbx_findapp(lua_State *L)
|
|
|
|
|
static int lua_pbx_exec(lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
int res, nargs = lua_gettop(L);
|
|
|
|
|
char data[LUA_EXT_DATA_SIZE] = "";
|
|
|
|
|
char *data_next = data, *app_name;
|
|
|
|
|
char *context, *exten;
|
|
|
|
|
const char *data = "";
|
|
|
|
|
char *app_name, *context, *exten;
|
|
|
|
|
char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
|
|
|
|
|
int priority, autoservice;
|
|
|
|
|
size_t data_left = sizeof(data);
|
|
|
|
|
struct ast_app *app;
|
|
|
|
|
struct ast_channel *chan;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_getfield(L, 1, "name");
|
|
|
|
|
app_name = ast_strdupa(lua_tostring(L, -1));
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
@ -223,21 +226,9 @@ static int lua_pbx_exec(lua_State *L)
|
|
|
|
|
priority = lua_tointeger(L, -1);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
|
|
lua_concat_args(L, 2, nargs);
|
|
|
|
|
data = lua_tostring(L, -1);
|
|
|
|
|
|
|
|
|
|
if (nargs > 1) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!lua_isnil(L, 2))
|
|
|
|
|
ast_build_string(&data_next, &data_left, "%s", luaL_checkstring(L, 2));
|
|
|
|
|
|
|
|
|
|
for (i = 3; i <= nargs; i++) {
|
|
|
|
|
if (lua_isnil(L, i))
|
|
|
|
|
ast_build_string(&data_next, &data_left, ",");
|
|
|
|
|
else
|
|
|
|
|
ast_build_string(&data_next, &data_left, ",%s", luaL_checkstring(L, i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
|
|
|
|
|
exten, context, priority,
|
|
|
|
|
term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
|
|
|
|
@ -252,7 +243,10 @@ static int lua_pbx_exec(lua_State *L)
|
|
|
|
|
ast_autoservice_stop(chan);
|
|
|
|
|
|
|
|
|
|
res = pbx_exec(chan, app, data);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_pop(L, 1); /* pop data */
|
|
|
|
|
data = "";
|
|
|
|
|
|
|
|
|
|
if (autoservice)
|
|
|
|
|
ast_autoservice_start(chan);
|
|
|
|
|
|
|
|
|
@ -459,16 +453,18 @@ static void lua_update_registry(lua_State *L, const char *context, const char *e
|
|
|
|
|
* \brief 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.
|
|
|
|
|
*
|
|
|
|
|
* \param L the lua_State to use
|
|
|
|
|
* \param name the name of the variable
|
|
|
|
|
*/
|
|
|
|
|
static void lua_push_variable_table(lua_State *L, const char *name)
|
|
|
|
|
static void lua_push_variable_table(lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
lua_newtable(L);
|
|
|
|
|
luaL_getmetatable(L, "variable");
|
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
|
|
|
|
|
|
lua_pushstring(L, name);
|
|
|
|
|
lua_insert(L, -2); /* move the table after the name */
|
|
|
|
|
lua_setfield(L, -2, "name");
|
|
|
|
|
|
|
|
|
|
lua_pushcfunction(L, &lua_get_variable_value);
|
|
|
|
@ -597,7 +593,7 @@ static void lua_create_hangup_function(lua_State *L)
|
|
|
|
|
static int lua_get_variable(lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
struct ast_channel *chan;
|
|
|
|
|
char *name = ast_strdupa(luaL_checkstring(L, 2));
|
|
|
|
|
const char *name = luaL_checkstring(L, 2);
|
|
|
|
|
char *value = NULL;
|
|
|
|
|
char *workspace = alloca(LUA_BUF_SIZE);
|
|
|
|
|
workspace[0] = '\0';
|
|
|
|
@ -606,7 +602,8 @@ static int lua_get_variable(lua_State *L)
|
|
|
|
|
chan = lua_touserdata(L, -1);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
|
|
lua_push_variable_table(L, name);
|
|
|
|
|
lua_pushvalue(L, 2);
|
|
|
|
|
lua_push_variable_table(L);
|
|
|
|
|
|
|
|
|
|
/* if this is not a request for a dialplan funciton attempt to retrieve
|
|
|
|
|
* the value of the variable */
|
|
|
|
@ -659,6 +656,38 @@ static int lua_set_variable(lua_State *L)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Concatenate a list of lua function arguments into a comma separated
|
|
|
|
|
* string.
|
|
|
|
|
* \param L the lua_State to use
|
|
|
|
|
* \param start the index of the first argument
|
|
|
|
|
* \param nargs the number of args
|
|
|
|
|
*
|
|
|
|
|
* The resulting string will be left on the top of the stack.
|
|
|
|
|
*/
|
|
|
|
|
static void lua_concat_args(lua_State *L, int start, int nargs) {
|
|
|
|
|
int concat = 0;
|
|
|
|
|
int i = start + 1;
|
|
|
|
|
|
|
|
|
|
if (!lua_isnil(L, start)) {
|
|
|
|
|
lua_pushvalue(L, start);
|
|
|
|
|
concat += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (; i <= nargs; i++) {
|
|
|
|
|
if (lua_isnil(L, i)) {
|
|
|
|
|
lua_pushliteral(L, ",");
|
|
|
|
|
concat += 1;
|
|
|
|
|
} else {
|
|
|
|
|
lua_pushliteral(L, ",");
|
|
|
|
|
lua_pushvalue(L, i);
|
|
|
|
|
concat += 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lua_concat(L, concat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief [lua_CFunction] Create a 'variable' object for accessing a dialplan
|
|
|
|
|
* function (for access from lua, don't call directly)
|
|
|
|
@ -678,34 +707,15 @@ static int lua_set_variable(lua_State *L)
|
|
|
|
|
static int lua_func_read(lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
|
char fullname[LUA_EXT_DATA_SIZE] = "";
|
|
|
|
|
char *fullname_next = fullname, *name;
|
|
|
|
|
size_t fullname_left = sizeof(fullname);
|
|
|
|
|
|
|
|
|
|
lua_getfield(L, 1, "name");
|
|
|
|
|
name = ast_strdupa(lua_tostring(L, -1));
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
|
|
ast_build_string(&fullname_next, &fullname_left, "%s(", name);
|
|
|
|
|
|
|
|
|
|
if (nargs > 1) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!lua_isnil(L, 2))
|
|
|
|
|
ast_build_string(&fullname_next, &fullname_left, "%s", luaL_checkstring(L, 2));
|
|
|
|
|
|
|
|
|
|
for (i = 3; i <= nargs; i++) {
|
|
|
|
|
if (lua_isnil(L, i))
|
|
|
|
|
ast_build_string(&fullname_next, &fullname_left, ",");
|
|
|
|
|
else
|
|
|
|
|
ast_build_string(&fullname_next, &fullname_left, ",%s", luaL_checkstring(L, i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* build a string in the form of "func_name(arg1,arg2,arg3)" */
|
|
|
|
|
lua_getfield(L, 1, "name");
|
|
|
|
|
lua_pushliteral(L, "(");
|
|
|
|
|
lua_concat_args(L, 2, nargs);
|
|
|
|
|
lua_pushliteral(L, ")");
|
|
|
|
|
lua_concat(L, 4);
|
|
|
|
|
|
|
|
|
|
ast_build_string(&fullname_next, &fullname_left, ")");
|
|
|
|
|
|
|
|
|
|
lua_push_variable_table(L, fullname);
|
|
|
|
|
|
|
|
|
|
lua_push_variable_table(L);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|