mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 03:20:57 +00:00
Fix lua goto detection to prevent unexpected behavior with confbridge
A bug in the pbx_lua goto detection was causing the dialplan to hangup unexpectedly after confbridge exited if it had called lua dialplan code during execution. Patch-by: Timo Teras Acked-by: Matt Nicholson (closes issue ASTERISK-18976) ........ Merged revisions 349928 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@349929 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
116
pbx/pbx_lua.c
116
pbx/pbx_lua.c
@@ -94,7 +94,6 @@ static void lua_create_variable_metatable(lua_State *L);
|
||||
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);
|
||||
@@ -213,19 +212,10 @@ static int lua_pbx_exec(lua_State *L)
|
||||
chan = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
context = ast_strdupa(chan->context);
|
||||
exten = ast_strdupa(chan->exten);
|
||||
priority = chan->priority;
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "context");
|
||||
context = ast_strdupa(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "exten");
|
||||
exten = ast_strdupa(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "priority");
|
||||
priority = lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_concat_args(L, 2, nargs);
|
||||
data = lua_tostring(L, -1);
|
||||
|
||||
@@ -256,75 +246,51 @@ static int lua_pbx_exec(lua_State *L)
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
lua_detect_goto(L);
|
||||
if (strcmp(context, chan->context)) {
|
||||
lua_pushstring(L, context);
|
||||
lua_pushstring(L, chan->context);
|
||||
lua_pushliteral(L, "context");
|
||||
} else if (strcmp(exten, chan->exten)) {
|
||||
lua_pushstring(L, exten);
|
||||
lua_pushstring(L, chan->exten);
|
||||
lua_pushliteral(L, "exten");
|
||||
} else if (priority != chan->priority) {
|
||||
lua_pushinteger(L, priority);
|
||||
lua_pushinteger(L, chan->priority);
|
||||
lua_pushliteral(L, "priority");
|
||||
} else {
|
||||
/* no goto - restore the original position back
|
||||
* to lua state, in case this was a recursive dialplan
|
||||
* call (a dialplan application re-entering dialplan) */
|
||||
lua_update_registry(L, context, exten, priority);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* goto detected - construct error message */
|
||||
lua_insert(L, -3);
|
||||
|
||||
lua_pushliteral(L, " changed from ");
|
||||
lua_insert(L, -3);
|
||||
|
||||
lua_pushliteral(L, " to ");
|
||||
lua_insert(L, -2);
|
||||
|
||||
lua_concat(L, 5);
|
||||
|
||||
ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
/* let the lua engine know it needs to return control to the pbx */
|
||||
lua_pushinteger(L, LUA_GOTO_DETECTED);
|
||||
lua_error(L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Detect if a Goto or other dialplan jump has been executed and return
|
||||
* control to the pbx engine.
|
||||
*/
|
||||
static void lua_detect_goto(lua_State *L)
|
||||
{
|
||||
struct ast_channel *chan;
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "channel");
|
||||
chan = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
/* check context */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "context");
|
||||
lua_pushstring(L, chan->context);
|
||||
if (!lua_equal(L, -1, -2)) {
|
||||
lua_pushliteral(L, "context");
|
||||
goto e_goto_detected;
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
|
||||
/* check exten */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "exten");
|
||||
lua_pushstring(L, chan->exten);
|
||||
if (!lua_equal(L, -1, -2)) {
|
||||
lua_pushliteral(L, "exten");
|
||||
goto e_goto_detected;
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
|
||||
/* check priority */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "priority");
|
||||
lua_pushinteger(L, chan->priority);
|
||||
if (!lua_equal(L, -1, -2)) {
|
||||
lua_pushliteral(L, "priority");
|
||||
goto e_goto_detected;
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
return;
|
||||
|
||||
e_goto_detected:
|
||||
/* format our debug message */
|
||||
lua_insert(L, -3);
|
||||
|
||||
lua_pushliteral(L, " changed from ");
|
||||
lua_insert(L, -3);
|
||||
|
||||
lua_pushliteral(L, " to ");
|
||||
lua_insert(L, -2);
|
||||
|
||||
lua_concat(L, 5);
|
||||
|
||||
ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
/* let the lua engine know it needs to return control to the pbx */
|
||||
lua_pushinteger(L, LUA_GOTO_DETECTED);
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief [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.
|
||||
|
Reference in New Issue
Block a user