mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
Merge "app_dial: Add the "Q" option to set the cause on unanswered channels" into 13
This commit is contained in:
6
CHANGES
6
CHANGES
@@ -83,6 +83,12 @@ Core
|
|||||||
notify systemd of its state using sd_notify. Use 'Type=notify' in
|
notify systemd of its state using sd_notify. Use 'Type=notify' in
|
||||||
asterisk.service.
|
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 ----------
|
--- Functionality changes from Asterisk 13.10.0 to Asterisk 13.11.0 ----------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
@@ -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
|
<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>
|
it is provided. The current extension is used if a database family/key is not specified.</para>
|
||||||
</option>
|
</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">
|
<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
|
<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>
|
party until the called channel has answered.</para>
|
||||||
@@ -520,6 +539,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
<example title="Dial with call length limit">
|
<example title="Dial with call length limit">
|
||||||
same => n,Dial(PJSIP/alice,,L(60000:30000:10000))
|
same => n,Dial(PJSIP/alice,,L(60000:30000:10000))
|
||||||
</example>
|
</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">
|
<example title="Dial with pre-dial subroutines">
|
||||||
[default]
|
[default]
|
||||||
|
|
||||||
@@ -684,6 +706,7 @@ enum {
|
|||||||
#define OPT_PREDIAL_CALLEE (1LLU << 41)
|
#define OPT_PREDIAL_CALLEE (1LLU << 41)
|
||||||
#define OPT_PREDIAL_CALLER (1LLU << 42)
|
#define OPT_PREDIAL_CALLER (1LLU << 42)
|
||||||
#define OPT_RING_WITH_EARLY_MEDIA (1LLU << 43)
|
#define OPT_RING_WITH_EARLY_MEDIA (1LLU << 43)
|
||||||
|
#define OPT_HANGUPCAUSE (1LLU << 44)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OPT_ARG_ANNOUNCE = 0,
|
OPT_ARG_ANNOUNCE = 0,
|
||||||
@@ -705,6 +728,7 @@ enum {
|
|||||||
OPT_ARG_FORCE_CID_PRES,
|
OPT_ARG_FORCE_CID_PRES,
|
||||||
OPT_ARG_PREDIAL_CALLEE,
|
OPT_ARG_PREDIAL_CALLEE,
|
||||||
OPT_ARG_PREDIAL_CALLER,
|
OPT_ARG_PREDIAL_CALLER,
|
||||||
|
OPT_ARG_HANGUPCAUSE,
|
||||||
/* note: this entry _MUST_ be the last one in the enum */
|
/* note: this entry _MUST_ be the last one in the enum */
|
||||||
OPT_ARG_ARRAY_SIZE
|
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_ARG('O', OPT_OPERMODE, OPT_ARG_OPERMODE),
|
||||||
AST_APP_OPTION('p', OPT_SCREENING),
|
AST_APP_OPTION('p', OPT_SCREENING),
|
||||||
AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
|
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_ARG('r', OPT_RINGBACK, OPT_ARG_RINGBACK),
|
||||||
AST_APP_OPTION('R', OPT_RING_WITH_EARLY_MEDIA),
|
AST_APP_OPTION('R', OPT_RING_WITH_EARLY_MEDIA),
|
||||||
AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
|
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);
|
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 */
|
/* Hang up a tree of stuff */
|
||||||
struct chanlist *outgoing;
|
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))) {
|
while ((outgoing = AST_LIST_REMOVE_HEAD(out_chans, node))) {
|
||||||
/* Hangup any existing lines we have open */
|
/* Hangup any existing lines we have open */
|
||||||
if (outgoing->chan && (outgoing->chan != exception)) {
|
if (outgoing->chan && (outgoing->chan != exception)) {
|
||||||
if (answered_elsewhere) {
|
if (hangupcause >= 0) {
|
||||||
/* This is for the channel drivers */
|
/* 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);
|
ast_hangup(outgoing->chan);
|
||||||
}
|
}
|
||||||
@@ -2763,6 +2788,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
|||||||
} else {
|
} else {
|
||||||
const char *number;
|
const char *number;
|
||||||
int dial_end_raised = 0;
|
int dial_end_raised = 0;
|
||||||
|
int cause = -1;
|
||||||
|
|
||||||
if (ast_test_flag64(&opts, OPT_CALLER_ANSWER))
|
if (ast_test_flag64(&opts, OPT_CALLER_ANSWER))
|
||||||
ast_answer(chan);
|
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
|
/* 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
|
we will always return with -1 so that it is hung up properly after the
|
||||||
conversation. */
|
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 appropriate, log that we have a destination channel and set the answer time */
|
||||||
if (ast_channel_name(peer))
|
if (ast_channel_name(peer))
|
||||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", 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);
|
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);
|
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
|
||||||
ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
|
ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user