[Asterisk-code-review] app dial: Add the "Q" option to set the cause on unanswered... (asterisk[13])

Joshua Colp asteriskteam at digium.com
Tue Oct 11 14:57:59 CDT 2016


Joshua Colp has submitted this change and it was merged.

Change subject: app_dial:  Add the "Q" option to set the cause on unanswered channels
......................................................................


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
---
M CHANGES
M apps/app_dial.c
2 files changed, 57 insertions(+), 5 deletions(-)

Approvals:
  Richard Mudgett: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, approved; Verified



diff --git a/CHANGES b/CHANGES
index 4a86682..11b3574 100644
--- a/CHANGES
+++ b/CHANGES
@@ -83,6 +83,12 @@
     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 7b7c702..8938981 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -375,6 +375,25 @@
 					<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>
@@ -519,6 +538,9 @@
 			</example>
 			<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&PJSIP/bob,,Q(NO_ANSWER))
 			</example>
 			<example title="Dial with pre-dial subroutines">
 			[default]
@@ -684,6 +706,7 @@
 #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 @@
 	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_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 @@
 	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 @@
 	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 @@
 	} 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 @@
 		/* 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 @@
 	}
 
 	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);
 

-- 
To view, visit https://gerrit.asterisk.org/4033
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I71742e0919aaa16784c30a2b2e73fbeed7672e47
Gerrit-PatchSet: 7
Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-Owner: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Matt Jordan <mjordan at digium.com>
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>



More information about the asterisk-code-review mailing list