From 0910773077f065a45e975c1a5914be084d9a4bdc Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Thu, 9 Feb 2017 11:01:22 -0500 Subject: [PATCH] manager: Restore Originate failure behavior from Asterisk 11 In Asterisk 11, if the 'Originate' AMI command failed to connect the provided Channel while in extension mode, a 'failed' extension would be looked up and run. This was, I believe, unintentionally removed in 51b6c49. This patch restores that behavior. This also adds an enum for the various 'synchronous' modes in an attempt to make them meaningful. ASTERISK-26115 #close Reported by: Nasir Iqbal Change-Id: I8afbd06725e99610e02adb529137d4800c05345d --- apps/app_originate.c | 10 ++++++---- funcs/func_periodic_hook.c | 4 ++-- include/asterisk/pbx.h | 29 +++++++++++++++++++++-------- main/manager.c | 15 +++++++++++---- main/pbx.c | 2 +- pbx/pbx_spool.c | 10 ++++++---- res/res_clioriginate.c | 8 ++++++-- 7 files changed, 53 insertions(+), 25 deletions(-) diff --git a/apps/app_originate.c b/apps/app_originate.c index cf4ef8ef38..8edccc720f 100644 --- a/apps/app_originate.c +++ b/apps/app_originate.c @@ -242,15 +242,17 @@ static int originate_exec(struct ast_channel *chan, const char *data) chantech, chandata, args.arg1, exten, priority); ast_pbx_outgoing_exten_predial(chantech, cap_slin, chandata, - timeout * 1000, args.arg1, exten, priority, &outgoing_status, 1, NULL, - NULL, NULL, NULL, NULL, 0, NULL, predial_callee); + timeout * 1000, args.arg1, exten, priority, &outgoing_status, + AST_OUTGOING_WAIT, NULL, NULL, NULL, NULL, NULL, 0, NULL, + predial_callee); } else if (!strcasecmp(args.type, "app")) { ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n", chantech, chandata, args.arg1, S_OR(args.arg2, "")); ast_pbx_outgoing_app_predial(chantech, cap_slin, chandata, - timeout * 1000, args.arg1, args.arg2, &outgoing_status, 1, NULL, - NULL, NULL, NULL, NULL, NULL, predial_callee); + timeout * 1000, args.arg1, args.arg2, &outgoing_status, + AST_OUTGOING_WAIT, NULL, NULL, NULL, NULL, NULL, NULL, + predial_callee); } else { ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n", args.type); diff --git a/funcs/func_periodic_hook.c b/funcs/func_periodic_hook.c index aae2abc90e..f8e79b326a 100644 --- a/funcs/func_periodic_hook.c +++ b/funcs/func_periodic_hook.c @@ -181,8 +181,8 @@ static void *hook_launch_thread(void *data) }; ast_pbx_outgoing_exten("Local", NULL, full_exten_name, 60, - arg->context, arg->exten, 1, NULL, 0, NULL, NULL, &chan_name_var, - NULL, NULL, 1, NULL); + arg->context, arg->exten, 1, NULL, AST_OUTGOING_NO_WAIT, + NULL, NULL, &chan_name_var, NULL, NULL, 1, NULL); hook_thread_arg_destroy(arg); diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index 386f3c38bc..008cfd3cbf 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -1144,6 +1144,12 @@ int ast_async_goto(struct ast_channel *chan, const char *context, const char *ex */ int ast_async_goto_by_name(const char *chan, const char *context, const char *exten, int priority); +enum ast_pbx_outgoing_sync { + AST_OUTGOING_NO_WAIT = 0, /*!< Don't wait for originated call to answer */ + AST_OUTGOING_WAIT = 1, /*!< Wait for originated call to answer */ + AST_OUTGOING_WAIT_COMPLETE = 2, /*!< Wait for originated call to answer and hangup */ +}; + /*! * \brief Synchronously or asynchronously make an outbound call and send it to a * particular extension @@ -1157,11 +1163,15 @@ int ast_async_goto_by_name(const char *chan, const char *context, const char *ex * \param priority The destination priority for the outbound channel * \param reason Optional. If provided, the dialed status of the outgoing channel. * Codes are AST_CONTROL_xxx values. Valid only if synchronous is non-zero. - * \param synchronous If zero then don't wait for anything. - * If one then block until the outbound channel answers or the call fails. - * If greater than one then wait for the call to complete or if the call doesn't - * answer and failed@context exists then run a channel named OutgoingSpoolFailed - * at failed@context. + * \param synchronous defined by the ast_pbx_outgoing_sync enum. + * If \c AST_OUTGOING_NO_WAIT then don't wait for anything. + * If \c AST_OUTGOING_WAIT then block until the outbound channel answers or + * the call fails. + * If \c AST_OUTGOING_WAIT_COMPLETE then wait for the call to complete or + * fail. + * If \c AST_OUTGOING_WAIT or \c AST_OUTGOING_WAIT_COMPLETE is specified, + * the call doesn't answer, and \c failed@context exists then run a channel + * named \c OutgoingSpoolFailed at \c failed@context. * \param cid_num The caller ID number to set on the outbound channel * \param cid_name The caller ID name to set on the outbound channel * \param vars Variables to set on the outbound channel @@ -1201,9 +1211,12 @@ int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, * \param appdata Data to pass to the application * \param reason Optional. If provided, the dialed status of the outgoing channel. * Codes are AST_CONTROL_xxx values. Valid only if synchronous is non-zero. - * \param synchronous If zero then don't wait for anything. - * If one then block until the outbound channel answers or the call fails. - * If greater than one then wait for the call to complete. + * \param synchronous defined by the ast_pbx_outgoing_sync enum. + * If \c AST_OUTGOING_NO_WAIT then don't wait for anything. + * If \c AST_OUTGOING_WAIT then block until the outbound channel answers or + * the call fails. + * If \c AST_OUTGOING_WAIT_COMPLETE then wait for the call to complete or + * fail. * \param cid_num The caller ID number to set on the outbound channel * \param cid_name The caller ID name to set on the outbound channel * \param vars Variables to set on the outbound channel diff --git a/main/manager.c b/main/manager.c index dfe056438d..a25497fd32 100644 --- a/main/manager.c +++ b/main/manager.c @@ -5130,13 +5130,15 @@ static void *fast_originate(void *data) if (!ast_strlen_zero(in->app)) { res = ast_pbx_outgoing_app(in->tech, in->cap, in->data, - in->timeout, in->app, in->appdata, &reason, 1, + in->timeout, in->app, in->appdata, &reason, + AST_OUTGOING_WAIT, S_OR(in->cid_num, NULL), S_OR(in->cid_name, NULL), in->vars, in->account, &chan, &assignedids); } else { res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data, - in->timeout, in->context, in->exten, in->priority, &reason, 1, + in->timeout, in->context, in->exten, in->priority, &reason, + AST_OUTGOING_WAIT, S_OR(in->cid_num, NULL), S_OR(in->cid_name, NULL), in->vars, in->account, &chan, in->early_media, &assignedids); @@ -5607,11 +5609,16 @@ static int action_originate(struct mansession *s, const struct message *m) } } } else if (!ast_strlen_zero(app)) { - res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL, assignedids.uniqueid ? &assignedids : NULL); + res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, + AST_OUTGOING_WAIT, l, n, vars, account, NULL, + assignedids.uniqueid ? &assignedids : NULL); ast_variables_destroy(vars); } else { if (exten && context && pi) { - res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early, assignedids.uniqueid ? &assignedids : NULL); + res = ast_pbx_outgoing_exten(tech, cap, data, to, + context, exten, pi, &reason, AST_OUTGOING_WAIT, + l, n, vars, account, NULL, bridge_early, + assignedids.uniqueid ? &assignedids : NULL); ast_variables_destroy(vars); } else { astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); diff --git a/main/pbx.c b/main/pbx.c index 3e35a3a14c..47e0b0eda0 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -7876,7 +7876,7 @@ int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, early_media, assignedids, predial_callee); if (res < 0 /* Call failed to get connected for some reason. */ - && 1 < synchronous + && 0 < synchronous && ast_exists_extension(NULL, context, "failed", 1, NULL)) { struct ast_channel *failed; diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c index dcd2ce7342..ba91d66ab8 100644 --- a/pbx/pbx_spool.c +++ b/pbx/pbx_spool.c @@ -397,15 +397,17 @@ static void *attempt_thread(void *data) int res, reason; if (!ast_strlen_zero(o->app)) { ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries); - res = ast_pbx_outgoing_app(o->tech, o->capabilities, o->dest, o->waittime * 1000, - o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, + res = ast_pbx_outgoing_app(o->tech, o->capabilities, o->dest, + o->waittime * 1000, o->app, o->data, &reason, + AST_OUTGOING_WAIT_COMPLETE, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL); } else { ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries); res = ast_pbx_outgoing_exten(o->tech, o->capabilities, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, - 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL, - ast_test_flag(&o->options, SPOOL_FLAG_EARLY_MEDIA), NULL); + AST_OUTGOING_WAIT_COMPLETE, o->cid_num, o->cid_name, + o->vars, o->account, NULL, ast_test_flag(&o->options, SPOOL_FLAG_EARLY_MEDIA), + NULL); } if (res) { ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason)); diff --git a/res/res_clioriginate.c b/res/res_clioriginate.c index 37df8ed658..3ea89d8c9e 100644 --- a/res/res_clioriginate.c +++ b/res/res_clioriginate.c @@ -72,7 +72,9 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app return CLI_FAILURE; } ast_format_cap_append(cap, ast_format_slin, 0); - ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL, NULL); + ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, + &reason, AST_OUTGOING_NO_WAIT, NULL, NULL, NULL, NULL, + NULL, NULL); ao2_ref(cap, -1); return CLI_SUCCESS; @@ -116,7 +118,9 @@ static char *orig_exten(int fd, const char *chan, const char *data) return CLI_FAILURE; } ast_format_cap_append(cap, ast_format_slin, 0); - ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL); + ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, + exten, 1, &reason, AST_OUTGOING_NO_WAIT, NULL, NULL, + NULL, NULL, NULL, 0, NULL); ao2_ref(cap, -1); return CLI_SUCCESS;