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
certified/11.2
Jonathan Rose 13 years ago
parent c5b3db1956
commit c6979ff581

@ -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_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_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_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;

Loading…
Cancel
Save