summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Joseph <gjoseph@digium.com>2016-10-06 08:58:26 -0600
committerGeorge Joseph <gjoseph@digium.com>2016-10-11 11:05:16 -0600
commitf919edc4e26389725a6d2dc32e7bcbbd79d4ef40 (patch)
tree4dbb486aa80d0d12e6b0750af3acdfaaa4eeb821
parentf166681c121265b92a9091bdafab9980c086b9d2 (diff)
app_dial: Add the "Q" option to set the cause on unanswered channels
The "Q" option will set the cause on the unanswered channels when another channel answers. It overrides the default of ANSWERED_ELSEWHERE. NOTE: chan_sip does not support setting the cause on a CANCEL to anything other than ANSWERED_ELSEWHERE. ASTERISK-26446 #close Change-Id: I71742e0919aaa16784c30a2b2e73fbeed7672e47
-rw-r--r--CHANGES6
-rw-r--r--apps/app_dial.c56
2 files changed, 57 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index 4a866829a..11b357419 100644
--- a/CHANGES
+++ b/CHANGES
@@ -83,6 +83,12 @@ Core
notify systemd of its state using sd_notify. Use 'Type=notify' in
asterisk.service.
+app_dial
+------------------
+ * Added the "Q" option which sets the Q.850/Q.931 cause on unanswered channels
+ when another channel answers the call. The default of ANSWERED_ELSEWHERE
+ is unchanged.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.10.0 to Asterisk 13.11.0 ----------
------------------------------------------------------------------------------
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 7b7c70201..893898100 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -375,6 +375,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<para>Enable privacy mode. Use <replaceable>x</replaceable> as the family/key in the AstDB database if
it is provided. The current extension is used if a database family/key is not specified.</para>
</option>
+ <option name="Q">
+ <argument name="cause" required="true"/>
+ <para>Specify the Q.850/Q.931 <replaceable>cause</replaceable> to send on
+ unanswered channels when another channel answers the call.
+ As with <literal>Hangup()</literal>, <replaceable>cause</replaceable>
+ can be a numeric cause code or a name such as
+ <literal>NO_ANSWER</literal>,
+ <literal>USER_BUSY</literal>,
+ <literal>CALL_REJECTED</literal> or
+ <literal>ANSWERED_ELSEWHERE</literal> (the default if Q isn't specified).
+ You can also specify <literal>0</literal> or <literal>NONE</literal>
+ to send no cause. See the <filename>causes.h</filename> file for the
+ full list of valid causes and names.
+ </para>
+ <note>
+ <para>chan_sip does not support setting the cause on a CANCEL to anything
+ other than ANSWERED_ELSEWHERE.</para>
+ </note>
+ </option>
<option name="r">
<para>Default: Indicate ringing to the calling party, even if the called party isn't actually ringing. Pass no audio to the calling
party until the called channel has answered.</para>
@@ -520,6 +539,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<example title="Dial with call length limit">
same => n,Dial(PJSIP/alice,,L(60000:30000:10000))
</example>
+ <example title="Dial alice and bob and send NO_ANSWER to bob instead of ANSWERED_ELSEWHERE when alice answers">
+ same => n,Dial(PJSIP/alice&amp;PJSIP/bob,,Q(NO_ANSWER))
+ </example>
<example title="Dial with pre-dial subroutines">
[default]
@@ -684,6 +706,7 @@ enum {
#define OPT_PREDIAL_CALLEE (1LLU << 41)
#define OPT_PREDIAL_CALLER (1LLU << 42)
#define OPT_RING_WITH_EARLY_MEDIA (1LLU << 43)
+#define OPT_HANGUPCAUSE (1LLU << 44)
enum {
OPT_ARG_ANNOUNCE = 0,
@@ -705,6 +728,7 @@ enum {
OPT_ARG_FORCE_CID_PRES,
OPT_ARG_PREDIAL_CALLEE,
OPT_ARG_PREDIAL_CALLER,
+ OPT_ARG_HANGUPCAUSE,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE
};
@@ -738,6 +762,7 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
AST_APP_OPTION_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
AST_APP_OPTION('p', OPT_SCREENING),
AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
+ AST_APP_OPTION_ARG('Q', OPT_HANGUPCAUSE, OPT_ARG_HANGUPCAUSE),
AST_APP_OPTION_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK),
AST_APP_OPTION('R', OPT_RING_WITH_EARLY_MEDIA),
AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
@@ -796,7 +821,7 @@ static void chanlist_free(struct chanlist *outgoing)
ast_free(outgoing);
}
-static void hanguptree(struct dial_head *out_chans, struct ast_channel *exception, int answered_elsewhere)
+static void hanguptree(struct dial_head *out_chans, struct ast_channel *exception, int hangupcause)
{
/* Hang up a tree of stuff */
struct chanlist *outgoing;
@@ -804,9 +829,9 @@ static void hanguptree(struct dial_head *out_chans, struct ast_channel *exceptio
while ((outgoing = AST_LIST_REMOVE_HEAD(out_chans, node))) {
/* Hangup any existing lines we have open */
if (outgoing->chan && (outgoing->chan != exception)) {
- if (answered_elsewhere) {
+ if (hangupcause >= 0) {
/* This is for the channel drivers */
- ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
+ ast_channel_hangupcause_set(outgoing->chan, hangupcause);
}
ast_hangup(outgoing->chan);
}
@@ -2763,6 +2788,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
} else {
const char *number;
int dial_end_raised = 0;
+ int cause = -1;
if (ast_test_flag64(&opts, OPT_CALLER_ANSWER))
ast_answer(chan);
@@ -2773,7 +2799,23 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
/* Ah ha! Someone answered within the desired timeframe. Of course after this
we will always return with -1 so that it is hung up properly after the
conversation. */
- hanguptree(&out_chans, peer, 1);
+
+ if (ast_test_flag64(&opts, OPT_HANGUPCAUSE)
+ && !ast_strlen_zero(opt_args[OPT_ARG_HANGUPCAUSE])) {
+ cause = ast_str2cause(opt_args[OPT_ARG_HANGUPCAUSE]);
+ if (cause <= 0) {
+ if (!strcasecmp(opt_args[OPT_ARG_HANGUPCAUSE], "NONE")) {
+ cause = 0;
+ } else if (sscanf(opt_args[OPT_ARG_HANGUPCAUSE], "%30d", &cause) != 1
+ || cause < 0) {
+ ast_log(LOG_WARNING, "Invalid cause given to Dial(...Q(<cause>)): \"%s\"\n",
+ opt_args[OPT_ARG_HANGUPCAUSE]);
+ cause = -1;
+ }
+ }
+ }
+ hanguptree(&out_chans, peer, cause >= 0 ? cause : AST_CAUSE_ANSWERED_ELSEWHERE);
+
/* If appropriate, log that we have a destination channel and set the answer time */
if (ast_channel_name(peer))
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ast_channel_name(peer));
@@ -3177,7 +3219,11 @@ out:
}
ast_channel_early_bridge(chan, NULL);
- hanguptree(&out_chans, NULL, ast_channel_hangupcause(chan)==AST_CAUSE_ANSWERED_ELSEWHERE || ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE) ? 1 : 0 ); /* forward 'answered elsewhere' if we received it */
+ /* forward 'answered elsewhere' if we received it */
+ hanguptree(&out_chans, NULL,
+ ast_channel_hangupcause(chan) == AST_CAUSE_ANSWERED_ELSEWHERE
+ || ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE)
+ ? AST_CAUSE_ANSWERED_ELSEWHERE : -1);
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);