mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 03:20:57 +00:00
Adds F option to Bridge application
Similar to dial and queue F option. (Closes issue ASTERISK-19282) Reported by: To Patches: bridge_f-v3.diff uploaded by To (license 6347) Review: https://reviewboard.asterisk.org/r/1825/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@360227 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -130,6 +130,10 @@ Applications
|
||||
when using multiple options (so that j option could be used without having to
|
||||
manually specify timezone and format) There are other beneftis eg. format can
|
||||
now be used without specifying time zone as well.
|
||||
* Added 'F()' option to Queue and Bridge. Similar to the dial option, these can
|
||||
be supplied with arguments indicating where the callee should go after the caller
|
||||
is hung up, or without options specified, the priority after the Queue/Bridge
|
||||
will be used.
|
||||
|
||||
Parking
|
||||
------------
|
||||
|
@@ -1615,13 +1615,6 @@ static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void replace_macro_delimiter(char *s)
|
||||
{
|
||||
for (; *s; s++)
|
||||
if (*s == '^')
|
||||
*s = ',';
|
||||
}
|
||||
|
||||
/* returns true if there is a valid privacy reply */
|
||||
static int valid_priv_reply(struct ast_flags64 *opts, int res)
|
||||
{
|
||||
@@ -2628,7 +2621,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
||||
ast_clear_flag(ast_channel_cdr(chan), AST_CDR_FLAG_DIALED);
|
||||
ast_clear_flag(ast_channel_cdr(peer), AST_CDR_FLAG_DIALED);
|
||||
|
||||
replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
|
||||
ast_replace_subargument_delimiter(opt_args[OPT_ARG_GOTO]);
|
||||
ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
|
||||
/* peer goes to the same context and extension as chan, so just copy info from chan*/
|
||||
ast_channel_context_set(peer, ast_channel_context(chan));
|
||||
@@ -2659,7 +2652,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
||||
ast_channel_context_set(peer, ast_channel_context(chan));
|
||||
ast_channel_exten_set(peer, ast_channel_exten(chan));
|
||||
|
||||
replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
|
||||
ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
|
||||
res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
|
||||
ast_debug(1, "Macro exited with status %d\n", res);
|
||||
res = 0;
|
||||
@@ -2699,7 +2692,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
||||
res = -1;
|
||||
/* perform a transfer to a new extension */
|
||||
if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
|
||||
replace_macro_delimiter(macro_transfer_dest);
|
||||
ast_replace_subargument_delimiter(macro_transfer_dest);
|
||||
if (!ast_parseable_goto(chan, macro_transfer_dest))
|
||||
ast_set_flag64(peerflags, OPT_GO_ON);
|
||||
}
|
||||
@@ -2724,7 +2717,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
||||
theapp = pbx_findapp("Gosub");
|
||||
|
||||
if (theapp && !res9) {
|
||||
replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
|
||||
ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
|
||||
|
||||
/* Set where we came from */
|
||||
ast_channel_context_set(peer, "app_dial_gosub_virtual_context");
|
||||
@@ -2814,7 +2807,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
||||
res = -1;
|
||||
/* perform a transfer to a new extension */
|
||||
if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/
|
||||
replace_macro_delimiter(gosub_transfer_dest);
|
||||
ast_replace_subargument_delimiter(gosub_transfer_dest);
|
||||
if (!ast_parseable_goto(chan, gosub_transfer_dest))
|
||||
ast_set_flag64(peerflags, OPT_GO_ON);
|
||||
}
|
||||
@@ -2928,7 +2921,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
|
||||
}
|
||||
if (!ast_check_hangup(peer) && ast_test_flag64(&opts, OPT_CALLEE_GO_ON)) {
|
||||
if(!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
|
||||
replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
|
||||
ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
|
||||
ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
|
||||
} else { /* F() */
|
||||
int goto_res;
|
||||
|
@@ -1305,21 +1305,6 @@ static void set_queue_result(struct ast_channel *chan, enum queue_result res)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Converts delimited '^' characters in a target priority/extension/context string
|
||||
* to commas so that they can be used with ast_parseable_goto.
|
||||
* \param s string that '^' characters are being replaced in.
|
||||
*/
|
||||
static void replace_macro_delimiter(char *s)
|
||||
{
|
||||
for (; *s; s++) {
|
||||
if (*s == '^') {
|
||||
*s = ',';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *int2strat(int strategy)
|
||||
{
|
||||
int x;
|
||||
@@ -5326,7 +5311,7 @@ static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char *
|
||||
|
||||
if (!ast_check_hangup(peer) && ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
|
||||
if (!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
|
||||
replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
|
||||
ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
|
||||
|
||||
if (ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]) == AST_PBX_SUCCESS) {
|
||||
ast_pbx_start(peer);
|
||||
|
@@ -428,6 +428,12 @@ int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, v
|
||||
|
||||
/* End of thread management support */
|
||||
|
||||
/*!
|
||||
\brief Replace '^' in a string with ','
|
||||
\param s String within which to replace characters
|
||||
*/
|
||||
void ast_replace_subargument_delimiter(char *s);
|
||||
|
||||
/*!
|
||||
\brief Process a string to find and replace characters
|
||||
\param start The string to analyze
|
||||
|
@@ -127,6 +127,36 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
<option name="p">
|
||||
<para>Play a courtesy tone to <replaceable>channel</replaceable>.</para>
|
||||
</option>
|
||||
<option name="F" argsep="^">
|
||||
<argument name="context" required="false" />
|
||||
<argument name="exten" required="false" />
|
||||
<argument name="priority" required="true" />
|
||||
<para>When the bridger hangs up, transfer the <emphasis>bridged</emphasis> party
|
||||
to the specified destination and <emphasis>start</emphasis> execution at that location.</para>
|
||||
<note>
|
||||
<para>Any channel variables you want the called channel to inherit from the caller channel must be
|
||||
prefixed with one or two underbars ('_').</para>
|
||||
</note>
|
||||
<note>
|
||||
<para>This option will override the 'x' option</para>
|
||||
</note>
|
||||
</option>
|
||||
<option name="F">
|
||||
<para>When the bridger hangs up, transfer the <emphasis>bridged</emphasis> party
|
||||
to the next priority of the current extension and <emphasis>start</emphasis> execution
|
||||
at that location.</para>
|
||||
<note>
|
||||
<para>Any channel variables you want the called channel to inherit from the caller channel must be
|
||||
prefixed with one or two underbars ('_').</para>
|
||||
</note>
|
||||
<note>
|
||||
<para>Using this option from a Macro() or GoSub() might not make sense as there would be no return points.</para>
|
||||
</note>
|
||||
<note>
|
||||
<para>This option will override the 'x' option</para>
|
||||
</note>
|
||||
</option>
|
||||
|
||||
<option name="h">
|
||||
<para>Allow the called party to hang up by sending the
|
||||
<replaceable>*</replaceable> DTMF digit.</para>
|
||||
@@ -7397,17 +7427,20 @@ enum {
|
||||
OPT_CALLEE_PARK = (1 << 9),
|
||||
OPT_CALLER_PARK = (1 << 10),
|
||||
OPT_CALLEE_KILL = (1 << 11),
|
||||
OPT_CALLEE_GO_ON = (1 << 12),
|
||||
};
|
||||
|
||||
enum {
|
||||
OPT_ARG_DURATION_LIMIT = 0,
|
||||
OPT_ARG_DURATION_STOP,
|
||||
OPT_ARG_CALLEE_GO_ON,
|
||||
/* note: this entry _MUST_ be the last one in the enum */
|
||||
OPT_ARG_ARRAY_SIZE,
|
||||
};
|
||||
|
||||
AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
|
||||
AST_APP_OPTION('p', BRIDGE_OPT_PLAYTONE),
|
||||
AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
|
||||
AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
|
||||
AST_APP_OPTION('H', OPT_CALLER_HANGUP),
|
||||
AST_APP_OPTION('k', OPT_CALLEE_PARK),
|
||||
@@ -7668,18 +7701,43 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
|
||||
|
||||
/* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
|
||||
pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
|
||||
if (!ast_check_hangup(final_dest_chan) && !ast_test_flag(&opts, OPT_CALLEE_KILL)) {
|
||||
ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
|
||||
ast_channel_context(final_dest_chan), ast_channel_exten(final_dest_chan),
|
||||
ast_channel_priority(final_dest_chan), ast_channel_name(final_dest_chan));
|
||||
if (!ast_check_hangup(final_dest_chan)) {
|
||||
if (ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
|
||||
char *caller_context = ast_strdupa(ast_channel_context(chan));
|
||||
char *caller_extension = ast_strdupa(ast_channel_exten(chan));
|
||||
int caller_priority = ast_channel_priority(chan);
|
||||
|
||||
if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
|
||||
ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", ast_channel_name(final_dest_chan));
|
||||
ast_hangup(final_dest_chan);
|
||||
} else
|
||||
ast_debug(1, "SUCCESS continuing PBX on chan %s\n", ast_channel_name(final_dest_chan));
|
||||
if (!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
|
||||
ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
|
||||
/* Set current dialplan position to bridger dialplan position */
|
||||
ast_goto_if_exists(final_dest_chan, caller_context, caller_extension, caller_priority);
|
||||
/* Then perform the goto */
|
||||
if (ast_parseable_goto(final_dest_chan, opt_args[OPT_ARG_CALLEE_GO_ON]) == AST_PBX_SUCCESS) {
|
||||
ast_pbx_start(final_dest_chan);
|
||||
} else {
|
||||
ast_hangup(final_dest_chan);
|
||||
}
|
||||
} else { /* F() */
|
||||
if (ast_goto_if_exists(final_dest_chan, caller_context, caller_extension, caller_priority + 1) == AST_PBX_GOTO_FAILED) {
|
||||
ast_hangup(final_dest_chan);
|
||||
} else {
|
||||
ast_pbx_start(final_dest_chan);
|
||||
}
|
||||
}
|
||||
} else if (!ast_test_flag(&opts, OPT_CALLEE_KILL)) {
|
||||
ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
|
||||
ast_channel_context(final_dest_chan), ast_channel_exten(final_dest_chan),
|
||||
ast_channel_priority(final_dest_chan), ast_channel_name(final_dest_chan));
|
||||
|
||||
if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
|
||||
ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", ast_channel_name(final_dest_chan));
|
||||
ast_hangup(final_dest_chan);
|
||||
} else {
|
||||
ast_debug(1, "SUCCESS continuing PBX on chan %s\n", ast_channel_name(final_dest_chan));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_debug(1, "hangup chan %s since the other endpoint has hung up or the x flag was passed\n", ast_channel_name(final_dest_chan));
|
||||
ast_debug(1, "hangup chan %s since the other endpoint has hung up or the x flag was passed\n", ast_channel_name(final_dest_chan));
|
||||
ast_hangup(final_dest_chan);
|
||||
}
|
||||
done:
|
||||
|
@@ -1464,6 +1464,15 @@ long int ast_random(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
void ast_replace_subargument_delimiter(char *s)
|
||||
{
|
||||
for (; *s; s++) {
|
||||
if (*s == '^') {
|
||||
*s = ',';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
|
||||
{
|
||||
char *dataPut = start;
|
||||
|
Reference in New Issue
Block a user