diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | apps/app_dial.c | 19 | ||||
-rw-r--r-- | apps/app_queue.c | 17 | ||||
-rw-r--r-- | include/asterisk/utils.h | 6 | ||||
-rw-r--r-- | main/features.c | 80 | ||||
-rw-r--r-- | main/utils.c | 9 |
6 files changed, 95 insertions, 40 deletions
@@ -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 ------------ diff --git a/apps/app_dial.c b/apps/app_dial.c index fbd4ef68b..902b78144 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -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; diff --git a/apps/app_queue.c b/apps/app_queue.c index d372a50ba..7a91384b8 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -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); diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index e3b98435a..c33f42322 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -429,6 +429,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 \param find The character to find diff --git a/main/features.c b/main/features.c index 96c528def..71be7d3f7 100644 --- a/main/features.c +++ b/main/features.c @@ -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: diff --git a/main/utils.c b/main/utils.c index 050200b1f..ffcd37c2a 100644 --- a/main/utils.c +++ b/main/utils.c @@ -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; |