summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2012-06-14 23:22:53 +0000
committerRichard Mudgett <rmudgett@digium.com>2012-06-14 23:22:53 +0000
commitf8746d0009d7f54eb55fe804d320b30e628ad9bb (patch)
tree207388fca29fa5a75d0a6c6651d3b19f694480f1 /main
parentaaa591447d908ef41404e75b7ed350eef56f905f (diff)
Allow non-normal execution routines to be able to run on hungup channels.
* Make non-normal dialplan execution routines be able to run on a hung up channel. This is preparation work for hangup handler routines. * Fixed ability to support relative non-normal dialplan execution routines. (i.e., The context and exten are optional for the specified dialplan location.) Predial routines are the only non-normal routines that it makes sense to optionally omit the context and exten. Setting a hangup handler also needs this ability. * Fix Return application being able to restore a dialplan location exactly. Channels without a PBX may not have context or exten set. * Fixes non-normal execution routines like connected line interception and predial leaving the dialplan execution stack unbalanced. Errors like missing Return statements, popping too many stack frames using StackPop, or an application returning non-zero could leave the dialplan stack unbalanced. * Fixed the AGI gosub application so it cleans up the dialplan execution stack and handles the autoloop priority increments correctly. * Eliminated the need for the gosub_virtual_context return location. Review: https://reviewboard.asterisk.org/r/1984/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@368985 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/app.c109
-rw-r--r--main/ccss.c4
-rw-r--r--main/channel.c6
3 files changed, 45 insertions, 74 deletions
diff --git a/main/app.c b/main/app.c
index 8cc22c6c7..210ef1168 100644
--- a/main/app.c
+++ b/main/app.c
@@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h"
#include "asterisk/threadstorage.h"
#include "asterisk/test.h"
+#include "asterisk/module.h"
AST_THREADSTORAGE_PUBLIC(ast_str_thread_global_buf);
@@ -312,82 +313,52 @@ int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *
return res;
}
-int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args)
+static const struct ast_app_stack_funcs *app_stack_callbacks;
+
+void ast_install_stack_functions(const struct ast_app_stack_funcs *funcs)
{
- struct ast_app *sub_app;
- const char *saved_context;
- const char *saved_exten;
- int saved_priority;
- int saved_autoloopflag;
- int res;
+ app_stack_callbacks = funcs;
+}
+
+const char *ast_app_expand_sub_args(struct ast_channel *chan, const char *args)
+{
+ const struct ast_app_stack_funcs *funcs;
+ const char *new_args;
- sub_app = pbx_findapp("Gosub");
- if (!sub_app) {
+ funcs = app_stack_callbacks;
+ if (!funcs || !funcs->expand_sub_args) {
ast_log(LOG_WARNING,
- "Cannot run 'Gosub(%s)'. The application is not available.\n", sub_args);
- return -1;
- }
- if (autoservice_chan) {
- ast_autoservice_start(autoservice_chan);
+ "Cannot expand 'Gosub(%s)' arguments. The app_stack module is not available.\n",
+ args);
+ return NULL;
}
+ ast_module_ref(funcs->module);
- ast_channel_lock(sub_chan);
-
- /* Save current dialplan location */
- saved_context = ast_strdupa(ast_channel_context(sub_chan));
- saved_exten = ast_strdupa(ast_channel_exten(sub_chan));
- saved_priority = ast_channel_priority(sub_chan);
-
- /*
- * Save flag to restore at the end so we don't have to play with
- * the priority in the gosub location string.
- */
- saved_autoloopflag = ast_test_flag(ast_channel_flags(sub_chan), AST_FLAG_IN_AUTOLOOP);
- ast_clear_flag(ast_channel_flags(sub_chan), AST_FLAG_IN_AUTOLOOP);
-
- /* Set known location for Gosub to return - 1 */
- ast_channel_context_set(sub_chan, "gosub_virtual_context");
- ast_channel_exten_set(sub_chan, "s");
- ast_channel_priority_set(sub_chan, 1 - 1);
-
- ast_debug(4, "%s Original location: %s,%s,%d\n", ast_channel_name(sub_chan),
- saved_context, saved_exten, saved_priority);
-
- ast_channel_unlock(sub_chan);
- res = pbx_exec(sub_chan, sub_app, sub_args);
- ast_debug(4, "Gosub exited with status %d\n", res);
- ast_channel_lock(sub_chan);
- if (!res) {
- struct ast_pbx_args gosub_args = {{0}};
- struct ast_pbx *saved_pbx;
-
- /* supress warning about a pbx already being on the channel */
- saved_pbx = ast_channel_pbx(sub_chan);
- ast_channel_pbx_set(sub_chan, NULL);
+ new_args = funcs->expand_sub_args(chan, args);
+ ast_module_unref(funcs->module);
+ return new_args;
+}
- ast_channel_unlock(sub_chan);
- gosub_args.no_hangup_chan = 1;
- ast_pbx_run_args(sub_chan, &gosub_args);
- ast_channel_lock(sub_chan);
+int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
+{
+ const struct ast_app_stack_funcs *funcs;
+ int res;
- /* Restore pbx. */
- ast_free(ast_channel_pbx(sub_chan));
- ast_channel_pbx_set(sub_chan, saved_pbx);
+ funcs = app_stack_callbacks;
+ if (!funcs || !funcs->run_sub) {
+ ast_log(LOG_WARNING,
+ "Cannot run 'Gosub(%s)'. The app_stack module is not available.\n",
+ sub_args);
+ return -1;
}
+ ast_module_ref(funcs->module);
- ast_debug(4, "%s Ending location: %s,%s,%d\n", ast_channel_name(sub_chan),
- ast_channel_context(sub_chan), ast_channel_exten(sub_chan),
- ast_channel_priority(sub_chan));
-
- /* Restore flag */
- ast_set2_flag(ast_channel_flags(sub_chan), saved_autoloopflag, AST_FLAG_IN_AUTOLOOP);
-
- /* Restore dialplan location */
- ast_channel_context_set(sub_chan, saved_context);
- ast_channel_exten_set(sub_chan, saved_exten);
- ast_channel_priority_set(sub_chan, saved_priority);
+ if (autoservice_chan) {
+ ast_autoservice_start(autoservice_chan);
+ }
- ast_channel_unlock(sub_chan);
+ res = funcs->run_sub(sub_chan, sub_args, ignore_hangup);
+ ast_module_unref(funcs->module);
if (autoservice_chan) {
ast_autoservice_stop(autoservice_chan);
@@ -395,14 +366,14 @@ int ast_app_exec_sub(struct ast_channel *autoservice_chan, struct ast_channel *s
return res;
}
-int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_location, const char *sub_args)
+int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_location, const char *sub_args, int ignore_hangup)
{
int res;
char *args_str;
size_t args_len;
if (ast_strlen_zero(sub_args)) {
- return ast_app_exec_sub(autoservice_chan, sub_chan, sub_location);
+ return ast_app_exec_sub(autoservice_chan, sub_chan, sub_location, ignore_hangup);
}
/* Create the Gosub application argument string. */
@@ -413,7 +384,7 @@ int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *su
}
snprintf(args_str, args_len, "%s(%s)", sub_location, sub_args);
- res = ast_app_exec_sub(autoservice_chan, sub_chan, args_str);
+ res = ast_app_exec_sub(autoservice_chan, sub_chan, args_str, ignore_hangup);
ast_free(args_str);
return res;
}
diff --git a/main/ccss.c b/main/ccss.c
index fe748e98c..b27823aaa 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -2724,7 +2724,7 @@ static void *generic_recall(void *data)
if (!ast_strlen_zero(callback_macro)) {
ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback macro configured for agent %s\n",
agent->core_id, agent->device_name);
- if (ast_app_run_macro(NULL, chan, callback_macro, NULL)) {
+ if (ast_app_exec_macro(NULL, chan, callback_macro)) {
ast_cc_failed(agent->core_id, "Callback macro to %s failed. Maybe a hangup?", agent->device_name);
ast_hangup(chan);
return NULL;
@@ -2734,7 +2734,7 @@ static void *generic_recall(void *data)
if (!ast_strlen_zero(callback_sub)) {
ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback subroutine configured for agent %s\n",
agent->core_id, agent->device_name);
- if (ast_app_run_sub(NULL, chan, callback_sub, NULL)) {
+ if (ast_app_exec_sub(NULL, chan, callback_sub, 0)) {
ast_cc_failed(agent->core_id, "Callback subroutine to %s failed. Maybe a hangup?", agent->device_name);
ast_hangup(chan);
return NULL;
diff --git a/main/channel.c b/main/channel.c
index 6b3621dae..b9fc0b5d8 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -5729,7 +5729,7 @@ int ast_pre_call(struct ast_channel *chan, const char *sub_args)
return res;
}
ast_channel_unlock(chan);
- return ast_app_exec_sub(NULL, chan, sub_args);
+ return ast_app_exec_sub(NULL, chan, sub_args, 0);
}
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
@@ -9801,7 +9801,7 @@ int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct
}
ast_channel_unlock(sub_chan);
- retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args);
+ retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0);
if (!retval) {
struct ast_party_connected_line saved_connected;
@@ -9844,7 +9844,7 @@ int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast
}
ast_channel_unlock(sub_chan);
- retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args);
+ retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args, 0);
if (!retval) {
struct ast_party_redirecting saved_redirecting;