Deprecated macro usage for connected line, redirecting, and CCSS

This commit adds GoSub alternatives to connected line, redirecting, and CCSS
macro hooks so that macro can finally be deprecated.  This also adds
deprecation warnings for those features when used and in documentation.

Review: https://reviewboard.asterisk.org/r/1760/
(closes issue SWP-4256)


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@357013 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/11.2
Kinsey Moore 13 years ago
parent 3cf09f40f7
commit 1fac2fba4b

@ -35,6 +35,11 @@ res_ais:
Dialplan Functions: Dialplan Functions:
- MAILBOX_EXISTS has been deprecated. Use VM_INFO with the 'exists' parameter - MAILBOX_EXISTS has been deprecated. Use VM_INFO with the 'exists' parameter
instead. instead.
- Macro has been deprecated in favor of GoSub. For redirecting and connected
line purposes use the following variables instead of their macro equivalents:
REDIRECTING_SEND_SUB, REDIRECTING_SEND_SUB_ARGS,
CONNECTED_LINE_SEND_SUB, CONNECTED_LINE_SEND_SUB_ARGS.
func_enum: func_enum:
- ENUM query functions now return a count of -1 on lookup error to - ENUM query functions now return a count of -1 on lookup error to
@ -62,6 +67,10 @@ AMI:
- DBDelTree now correctly returns an error when 0 rows are deleted just as - DBDelTree now correctly returns an error when 0 rows are deleted just as
the DBDel action does. the DBDel action does.
CCSS:
- Macro is deprecated. Use cc_callback_sub instead of cc_callback_macro
in channel configurations.
app_meetme: app_meetme:
- The 'c' option (announce user count) will now work even if the 'q' (quiet) - The 'c' option (announce user count) will now work even if the 'q' (quiet)
option is enabled. option is enabled.

@ -956,7 +956,8 @@ static void do_forward(struct chanlist *o,
ast_party_redirecting_init(&redirecting); ast_party_redirecting_init(&redirecting);
ast_party_redirecting_copy(&redirecting, &c->redirecting); ast_party_redirecting_copy(&redirecting, &c->redirecting);
ast_channel_unlock(c); ast_channel_unlock(c);
if (ast_channel_redirecting_macro(c, in, &redirecting, 1, 0)) { if (ast_channel_redirecting_sub(c, in, &redirecting, 0) &&
ast_channel_redirecting_macro(c, in, &redirecting, 1, 0)) {
ast_channel_update_redirecting(in, &redirecting, NULL); ast_channel_update_redirecting(in, &redirecting, NULL);
} }
ast_party_redirecting_free(&redirecting); ast_party_redirecting_free(&redirecting);
@ -1105,7 +1106,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "%s answered %s\n", ast_channel_name(c), ast_channel_name(in)); ast_verb(3, "%s answered %s\n", ast_channel_name(c), ast_channel_name(in));
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) { if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
if (o->pending_connected_update) { if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) { if (ast_channel_connected_line_sub(c, in, &o->connected, 0) &&
ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL); ast_channel_update_connected_line(in, &o->connected, NULL);
} }
} else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) { } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
@ -1175,7 +1177,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "%s answered %s\n", ast_channel_name(c), ast_channel_name(in)); ast_verb(3, "%s answered %s\n", ast_channel_name(c), ast_channel_name(in));
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) { if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
if (o->pending_connected_update) { if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) { if (ast_channel_connected_line_sub(c, in, &o->connected, 0) &&
ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL); ast_channel_update_connected_line(in, &o->connected, NULL);
} }
} else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) { } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
@ -1308,7 +1311,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_party_connected_line_free(&connected); ast_party_connected_line_free(&connected);
o->pending_connected_update = 1; o->pending_connected_update = 1;
} else { } else {
if (ast_channel_connected_line_macro(c, in, f, 1, 1)) { if (ast_channel_connected_line_sub(c, in, f, 1) &&
ast_channel_connected_line_macro(c, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen); ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
} }
} }
@ -1329,7 +1333,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "Redirecting update to %s prevented.\n", ast_channel_name(in)); ast_verb(3, "Redirecting update to %s prevented.\n", ast_channel_name(in));
} else if (single) { } else if (single) {
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(c), ast_channel_name(in)); ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(c), ast_channel_name(in));
if (ast_channel_redirecting_macro(c, in, f, 1, 1)) { if (ast_channel_redirecting_sub(c, in, f, 1) &&
ast_channel_redirecting_macro(c, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
} }
pa->sentringing = 0; pa->sentringing = 0;
@ -1488,12 +1493,14 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen); ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
break; break;
case AST_CONTROL_CONNECTED_LINE: case AST_CONTROL_CONNECTED_LINE:
if (ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) { if (ast_channel_connected_line_sub(in, o->chan, f, 1) &&
ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen); ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
} }
break; break;
case AST_CONTROL_REDIRECTING: case AST_CONTROL_REDIRECTING:
if (ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) { if (ast_channel_redirecting_sub(in, o->chan, f, 1) &&
ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen); ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
} }
break; break;

@ -1304,7 +1304,8 @@ static int app_exec(struct ast_channel *chan, const char *data)
/* Update connected line to caller if available. */ /* Update connected line to caller if available. */
if (targs.pending_out_connected_update) { if (targs.pending_out_connected_update) {
if (ast_channel_connected_line_macro(outbound, caller, &targs.connected_out, 1, 0)) { if (ast_channel_connected_line_sub(outbound, caller, &targs.connected_out, 0) &&
ast_channel_connected_line_macro(outbound, caller, &targs.connected_out, 1, 0)) {
ast_channel_update_connected_line(caller, &targs.connected_out, NULL); ast_channel_update_connected_line(caller, &targs.connected_out, NULL);
} }
} }
@ -1329,7 +1330,8 @@ static int app_exec(struct ast_channel *chan, const char *data)
/* Update connected line to winner if changed. */ /* Update connected line to winner if changed. */
if (targs.pending_in_connected_update) { if (targs.pending_in_connected_update) {
if (ast_channel_connected_line_macro(caller, outbound, &targs.connected_in, 0, 0)) { if (ast_channel_connected_line_sub(caller, outbound, &targs.connected_in, 0) &&
ast_channel_connected_line_macro(caller, outbound, &targs.connected_in, 0, 0)) {
ast_channel_update_connected_line(outbound, &targs.connected_in, NULL); ast_channel_update_connected_line(outbound, &targs.connected_in, NULL);
} }
} }

@ -3645,7 +3645,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name); ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) { if (update_connectedline) {
if (o->pending_connected_update) { if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) { if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL); ast_channel_update_connected_line(in, &o->connected, NULL);
} }
} else if (!o->dial_callerid_absent) { } else if (!o->dial_callerid_absent) {
@ -3744,8 +3745,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_party_redirecting_init(&redirecting); ast_party_redirecting_init(&redirecting);
ast_party_redirecting_copy(&redirecting, &o->chan->redirecting); ast_party_redirecting_copy(&redirecting, &o->chan->redirecting);
ast_channel_unlock(o->chan); ast_channel_unlock(o->chan);
res = ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0); if ((res = ast_channel_redirecting_sub(o->chan, in, &redirecting, 0)) &&
if (res) { (res = ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0))) {
ast_channel_update_redirecting(in, &redirecting, NULL); ast_channel_update_redirecting(in, &redirecting, NULL);
} }
ast_party_redirecting_free(&redirecting); ast_party_redirecting_free(&redirecting);
@ -3774,7 +3775,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name); ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) { if (update_connectedline) {
if (o->pending_connected_update) { if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) { if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL); ast_channel_update_connected_line(in, &o->connected, NULL);
} }
} else if (!o->dial_callerid_absent) { } else if (!o->dial_callerid_absent) {
@ -3858,7 +3860,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_party_connected_line_free(&connected); ast_party_connected_line_free(&connected);
o->pending_connected_update = 1; o->pending_connected_update = 1;
} else { } else {
if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) { if (ast_channel_connected_line_sub(o->chan, in, f, 1) &&
ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen); ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
} }
} }
@ -3879,7 +3882,8 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "Redirecting update to %s prevented\n", inchan_name); ast_verb(3, "Redirecting update to %s prevented\n", inchan_name);
} else if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) { } else if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ochan_name, inchan_name); ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ochan_name, inchan_name);
if (ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) { if (ast_channel_redirecting_sub(o->chan, in, f, 1) &&
ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen); ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
} }
} }

@ -187,6 +187,12 @@
; ;
;cc_callback_macro= ;cc_callback_macro=
; ;
; Alternatively, the administrator may run a subroutine. By default
; there is no callback subroutine configured. The subroutine should
; be specified in the format: [[context,]exten,]priority
;
;cc_callback_sub=
;
; When using an ISDN phone and a generic CC agent, Asterisk is unable ; When using an ISDN phone and a generic CC agent, Asterisk is unable
; to determine the dialstring that should be used when calling back ; to determine the dialstring that should be used when calling back
; the original caller. Furthermore, if you desire to use any dialstring- ; the original caller. Furthermore, if you desire to use any dialstring-

@ -131,9 +131,29 @@ int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int
* \retval 0 success * \retval 0 success
* \retval -1 failure * \retval -1 failure
*/ */
int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel
*macro_chan, const char * const macro_name, const char * const macro_args); *macro_chan, const char * const macro_name, const char * const macro_args);
/*!
* \since 11
* \brief Run a subroutine on a channel, placing a second channel into autoservice.
*
* This is a shorthand method that makes it very easy to run a subroutine on any given
* channel. It is perfectly reasonable to supply a NULL autoservice_chan here in case
* there is no channel to place into autoservice. It is very important that the
* autoservice_chan parameter is not locked prior to calling ast_app_run_sub. A
* deadlock could result, otherwise.
*
* \param autoservice_chan A channel to place into autoservice while the subroutine is run
* \param sub_chan The channel to run the subroutine on
* \param name The name of the subroutine to run
* \param args The arguments to pass to the subroutien
* \retval 0 success
* \retval -1 failure
*/
int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel
*sub_chan, const char * const name, const char * const args);
/*! /*!
* \brief Set voicemail function callbacks * \brief Set voicemail function callbacks
* \param[in] has_voicemail_func set function pointer * \param[in] has_voicemail_func set function pointer

@ -386,11 +386,28 @@ const char *ast_get_cc_callback_macro(struct ast_cc_config_params *config);
* \since 1.8 * \since 1.8
* \brief Set the callback_macro name * \brief Set the callback_macro name
* \param config The configuration to set the callback_macro on * \param config The configuration to set the callback_macro on
* \param value The new callback macro we want to change to * \param value The new callback macro we want to change to
* \retval void * \retval void
*/ */
void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value); void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value);
/*!
* \since 11
* \brief Get the name of the callback subroutine
* \param config The configuration to retrieve the callback_sub from
* \return The callback_sub name
*/
const char *ast_get_cc_callback_sub(struct ast_cc_config_params *config);
/*!
* \since 11
* \brief Set the callback subroutine name
* \param config The configuration to set the callback_sub on
* \param value The new callback subroutine we want to change to
* \retval void
*/
void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char * const value);
/* END CONFIGURATION FUNCTIONS */ /* END CONFIGURATION FUNCTIONS */
/* BEGIN AGENT/MONITOR REGISTRATION API */ /* BEGIN AGENT/MONITOR REGISTRATION API */

@ -3418,30 +3418,56 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
* \since 1.8 * \since 1.8
* \brief Run a connected line interception macro and update a channel's connected line * \brief Run a connected line interception macro and update a channel's connected line
* information * information
* \deprecated You should use the ast_channel_connected_line_sub() function instead.
* *
* Whenever we want to update a channel's connected line information, we may need to run * Whenever we want to update a channel's connected line information, we may need to run
* a macro so that an administrator can manipulate the information before sending it * a macro so that an administrator can manipulate the information before sending it
* out. This function both runs the macro and sends the update to the channel. * out. This function both runs the macro and sends the update to the channel.
* *
* \param autoservice_chan Channel to place into autoservice while the macro is running. * \param autoservice_chan Channel to place into autoservice while the macro is running.
* It is perfectly safe for this to be NULL * It is perfectly safe for this to be NULL
* \param macro_chan The channel to run the macro on. Also the channel from which we * \param macro_chan The channel to run the macro on. Also the channel from which we
* determine which macro we need to run. * determine which macro we need to run.
* \param connected_info Either an ast_party_connected_line or ast_frame pointer of type * \param connected_info Either an ast_party_connected_line or ast_frame pointer of type
* AST_CONTROL_CONNECTED_LINE * AST_CONTROL_CONNECTED_LINE
* \param caller If true, then run CONNECTED_LINE_CALLER_SEND_MACRO, otherwise run * \param is_caller If true, then run CONNECTED_LINE_CALLER_SEND_MACRO with arguments from
* CONNECTED_LINE_CALLEE_SEND_MACRO * CONNECTED_LINE_CALLER_SEND_MACRO_ARGS, otherwise run CONNECTED_LINE_CALLEE_SEND_MACRO
* with arguments from CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS
* \param frame If true, then connected_info is an ast_frame pointer, otherwise it is an * \param frame If true, then connected_info is an ast_frame pointer, otherwise it is an
* ast_party_connected_line pointer. * ast_party_connected_line pointer.
* \retval 0 Success * \retval 0 Success
* \retval -1 Either the macro does not exist, or there was an error while attempting to * \retval -1 Either the macro does not exist, or there was an error while attempting to
* run the macro * run the macro
* *
* \todo Have multiple return codes based on the MACRO_RESULT * \todo Have multiple return codes based on the MACRO_RESULT
* \todo Make constants so that caller and frame can be more expressive than just '1' and * \todo Make constants so that caller and frame can be more expressive than just '1' and
* '0' * '0'
*/
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int frame);
/*!
* \since 11
* \brief Run a connected line interception subroutine and update a channel's connected line
* information
*
* Whenever we want to update a channel's connected line information, we may need to run
* a subroutine so that an administrator can manipulate the information before sending it
* out. This function both runs the subroutine specified by CONNECTED_LINE_SEND_SUB and
* sends the update to the channel.
*
* \param autoservice_chan Channel to place into autoservice while the sub is running.
* It is perfectly safe for this to be NULL
* \param sub_chan The channel to run the subroutine on. Also the channel from which we
* determine which subroutine we need to run.
* \param connected_info Either an ast_party_connected_line or ast_frame pointer of type
* AST_CONTROL_CONNECTED_LINE
* \param frame If true, then connected_info is an ast_frame pointer, otherwise it is an
* ast_party_connected_line pointer.
* \retval 0 Success
* \retval -1 Either the subroutine does not exist, or there was an error while attempting to
* run the subroutine
*/ */
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame); int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame);
/*! /*!
* \brief Insert into an astdata tree, the channel structure. * \brief Insert into an astdata tree, the channel structure.
@ -3467,6 +3493,7 @@ int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct as
/*! /*!
* \since 1.8 * \since 1.8
* \brief Run a redirecting interception macro and update a channel's redirecting information * \brief Run a redirecting interception macro and update a channel's redirecting information
* \deprecated You should use the ast_channel_redirecting_sub() function instead.
* *
* \details * \details
* Whenever we want to update a channel's redirecting information, we may need to run * Whenever we want to update a channel's redirecting information, we may need to run
@ -3479,8 +3506,9 @@ int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct as
* determine which macro we need to run. * determine which macro we need to run.
* \param redirecting_info Either an ast_party_redirecting or ast_frame pointer of type * \param redirecting_info Either an ast_party_redirecting or ast_frame pointer of type
* AST_CONTROL_REDIRECTING * AST_CONTROL_REDIRECTING
* \param is_caller If true, then run REDIRECTING_CALLER_SEND_MACRO, otherwise run * \param is_caller If true, then run REDIRECTING_CALLER_SEND_MACRO with arguments from
* REDIRECTING_CALLEE_SEND_MACRO * REDIRECTING_CALLER_SEND_MACRO_ARGS, otherwise run REDIRECTING_CALLEE_SEND_MACRO with
* arguments from REDIRECTING_CALLEE_SEND_MACRO_ARGS
* \param is_frame If true, then redirecting_info is an ast_frame pointer, otherwise it is an * \param is_frame If true, then redirecting_info is an ast_frame pointer, otherwise it is an
* ast_party_redirecting pointer. * ast_party_redirecting pointer.
* *
@ -3494,6 +3522,31 @@ int ast_channel_data_cmp_structure(const struct ast_data_search *tree, struct as
*/ */
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame); int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame);
/*!
* \since 11
* \brief Run a redirecting interception subroutine and update a channel's redirecting information
*
* \details
* Whenever we want to update a channel's redirecting information, we may need to run
* a subroutine so that an administrator can manipulate the information before sending it
* out. This function both runs the subroutine specified by REDIRECTING_SEND_SUB and
* sends the update to the channel.
*
* \param autoservice_chan Channel to place into autoservice while the subroutine is running.
* It is perfectly safe for this to be NULL
* \param sub_chan The channel to run the subroutine on. Also the channel from which we
* determine which subroutine we need to run.
* \param redirecting_info Either an ast_party_redirecting or ast_frame pointer of type
* AST_CONTROL_REDIRECTING
* \param is_frame If true, then redirecting_info is an ast_frame pointer, otherwise it is an
* ast_party_redirecting pointer.
*
* \retval 0 Success
* \retval -1 Either the subroutine does not exist, or there was an error while attempting to
* run the subroutine
*/
int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *redirecting_info, int is_frame);
#include "asterisk/ccss.h" #include "asterisk/ccss.h"
/*! /*!

@ -247,28 +247,79 @@ int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int
return res; return res;
} }
int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char * const macro_name, const char * const macro_args) static int app_exec_dialplan(struct ast_channel *autoservice_chan, struct ast_channel *exec_chan, const char * const args, int use_gosub)
{ {
struct ast_app *macro_app;
struct ast_app *app;
int res; int res;
char buf[1024]; char * app_type = use_gosub ? "GoSub" : "Macro";
macro_app = pbx_findapp("Macro"); app = pbx_findapp(app_type);
if (!macro_app) { if (!app) {
ast_log(LOG_WARNING, "Cannot run macro '%s' because the 'Macro' application in not available\n", macro_name); ast_log(LOG_WARNING, "Cannot run '%s' because the '%s' application is not available\n", args, app_type);
return -1; return -1;
} }
snprintf(buf, sizeof(buf), "%s%s%s", macro_name, ast_strlen_zero(macro_args) ? "" : ",", S_OR(macro_args, ""));
if (autoservice_chan) { if (autoservice_chan) {
ast_autoservice_start(autoservice_chan); ast_autoservice_start(autoservice_chan);
} }
res = pbx_exec(macro_chan, macro_app, buf); res = pbx_exec(exec_chan, app, args);
if (use_gosub && !res) {
struct ast_pbx_args gosub_args = {{0}};
struct ast_pbx *pbx = ast_channel_pbx(exec_chan);
/* supress warning about a pbx already being on the channel */
ast_channel_pbx_set(exec_chan, NULL);
gosub_args.no_hangup_chan = 1;
ast_pbx_run_args(exec_chan, &gosub_args);
if (ast_channel_pbx(exec_chan)) {
ast_free(ast_channel_pbx(exec_chan));
}
ast_channel_pbx_set(exec_chan, pbx);
}
if (autoservice_chan) { if (autoservice_chan) {
ast_autoservice_stop(autoservice_chan); ast_autoservice_stop(autoservice_chan);
} }
return res; return res;
} }
int ast_app_run_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char * const name, const char * const args)
{
char buf[1024];
snprintf(buf, sizeof(buf), "%s%s%s", name, ast_strlen_zero(args) ? "" : ",", S_OR(args, ""));
return app_exec_dialplan(autoservice_chan, macro_chan, buf, 0);
}
int ast_app_run_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char * const location, const char * const args)
{
char buf[1024];
size_t offset = snprintf(buf, sizeof(buf), "%s", location);
/* need to bump the priority by one if we already have a pbx */
if (ast_channel_pbx(sub_chan)) {
int iprio;
const char * priority = location;
const char * next = strchr(priority,',');
/* jump to the priority portion of the location */
if (next) {
priority = next + 1;
}
next = strchr(priority,',');
if (next) {
priority = next + 1;
}
/* if the priority isn't numeric, it's as if we never took this branch... */
if (sscanf(priority, "%d", &iprio)) {
offset = priority - location;
iprio++;
if (offset < sizeof(buf)) {
offset += snprintf(buf + offset, sizeof(buf) - offset, "%d", iprio);
}
}
}
if (offset < sizeof(buf)) {
snprintf(buf + offset, sizeof(buf) - offset, "%s%s%s", ast_strlen_zero(args) ? "" : "(", S_OR(args, ""), ast_strlen_zero(args) ? "" : ")");
}
return app_exec_dialplan(autoservice_chan, sub_chan, buf, 1);
}
static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL; static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
static int (*ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL; static int (*ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
static int (*ast_inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL; static int (*ast_inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL;

@ -156,6 +156,7 @@ struct ast_cc_config_params {
unsigned int cc_max_agents; unsigned int cc_max_agents;
unsigned int cc_max_monitors; unsigned int cc_max_monitors;
char cc_callback_macro[AST_MAX_EXTENSION]; char cc_callback_macro[AST_MAX_EXTENSION];
char cc_callback_sub[AST_MAX_EXTENSION];
char cc_agent_dialstring[AST_MAX_EXTENSION]; char cc_agent_dialstring[AST_MAX_EXTENSION];
}; };
@ -654,6 +655,7 @@ static const struct ast_cc_config_params cc_default_params = {
.cc_max_agents = CC_MAX_AGENTS_DEFAULT, .cc_max_agents = CC_MAX_AGENTS_DEFAULT,
.cc_max_monitors = CC_MAX_MONITORS_DEFAULT, .cc_max_monitors = CC_MAX_MONITORS_DEFAULT,
.cc_callback_macro = "", .cc_callback_macro = "",
.cc_callback_sub = "",
.cc_agent_dialstring = "", .cc_agent_dialstring = "",
}; };
@ -751,6 +753,8 @@ int ast_cc_get_param(struct ast_cc_config_params *params, const char * const nam
if (!strcasecmp(name, "cc_callback_macro")) { if (!strcasecmp(name, "cc_callback_macro")) {
value = ast_get_cc_callback_macro(params); value = ast_get_cc_callback_macro(params);
} else if (!strcasecmp(name, "cc_callback_sub")) {
value = ast_get_cc_callback_sub(params);
} else if (!strcasecmp(name, "cc_agent_policy")) { } else if (!strcasecmp(name, "cc_agent_policy")) {
value = agent_policy_to_str(ast_get_cc_agent_policy(params)); value = agent_policy_to_str(ast_get_cc_agent_policy(params));
} else if (!strcasecmp(name, "cc_monitor_policy")) { } else if (!strcasecmp(name, "cc_monitor_policy")) {
@ -800,6 +804,9 @@ int ast_cc_set_param(struct ast_cc_config_params *params, const char * const nam
} else if (!strcasecmp(name, "cc_callback_macro")) { } else if (!strcasecmp(name, "cc_callback_macro")) {
ast_set_cc_callback_macro(params, value); ast_set_cc_callback_macro(params, value);
return 0; return 0;
} else if (!strcasecmp(name, "cc_callback_sub")) {
ast_set_cc_callback_sub(params, value);
return 0;
} }
if (!sscanf(value, "%30u", &value_as_uint) == 1) { if (!sscanf(value, "%30u", &value_as_uint) == 1) {
@ -836,6 +843,7 @@ int ast_cc_is_config_param(const char * const name)
!strcasecmp(name, "cc_max_agents") || !strcasecmp(name, "cc_max_agents") ||
!strcasecmp(name, "cc_max_monitors") || !strcasecmp(name, "cc_max_monitors") ||
!strcasecmp(name, "cc_callback_macro") || !strcasecmp(name, "cc_callback_macro") ||
!strcasecmp(name, "cc_callback_sub") ||
!strcasecmp(name, "cc_agent_dialstring") || !strcasecmp(name, "cc_agent_dialstring") ||
!strcasecmp(name, "cc_recall_timer")); !strcasecmp(name, "cc_recall_timer"));
} }
@ -978,8 +986,14 @@ const char *ast_get_cc_callback_macro(struct ast_cc_config_params *config)
return config->cc_callback_macro; return config->cc_callback_macro;
} }
const char *ast_get_cc_callback_sub(struct ast_cc_config_params *config)
{
return config->cc_callback_sub;
}
void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value) void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char * const value)
{ {
ast_log(LOG_WARNING, "Usage of cc_callback_macro is deprecated. Please use cc_callback_sub instead.\n");
if (ast_strlen_zero(value)) { if (ast_strlen_zero(value)) {
config->cc_callback_macro[0] = '\0'; config->cc_callback_macro[0] = '\0';
} else { } else {
@ -987,6 +1001,15 @@ void ast_set_cc_callback_macro(struct ast_cc_config_params *config, const char *
} }
} }
void ast_set_cc_callback_sub(struct ast_cc_config_params *config, const char * const value)
{
if (ast_strlen_zero(value)) {
config->cc_callback_sub[0] = '\0';
} else {
ast_copy_string(config->cc_callback_sub, value, sizeof(config->cc_callback_sub));
}
}
struct cc_monitor_backend { struct cc_monitor_backend {
AST_LIST_ENTRY(cc_monitor_backend) next; AST_LIST_ENTRY(cc_monitor_backend) next;
const struct ast_cc_monitor_callbacks *callbacks; const struct ast_cc_monitor_callbacks *callbacks;
@ -2651,6 +2674,7 @@ static void *generic_recall(void *data)
int reason; int reason;
struct ast_channel *chan; struct ast_channel *chan;
const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params); const char *callback_macro = ast_get_cc_callback_macro(agent->cc_params);
const char *callback_sub = ast_get_cc_callback_sub(agent->cc_params);
unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000; unsigned int recall_timer = ast_get_cc_recall_timer(agent->cc_params) * 1000;
struct ast_format tmp_fmt; struct ast_format tmp_fmt;
struct ast_format_cap *tmp_cap = ast_format_cap_alloc_nolock(); struct ast_format_cap *tmp_cap = ast_format_cap_alloc_nolock();
@ -2700,6 +2724,16 @@ static void *generic_recall(void *data)
return NULL; return NULL;
} }
} }
if (!ast_strlen_zero(callback_sub)) {
ast_log_dynamic_level(cc_logger_level, "Core %d: There's a callback subroutine configured for agent %s\n",
agent->core_id, agent->device_name);
if (ast_app_run_sub(NULL, chan, callback_sub, NULL)) {
ast_cc_failed(agent->core_id, "Callback subroutine to %s failed. Maybe a hangup?", agent->device_name);
ast_hangup(chan);
return NULL;
}
}
ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", agent->device_name); ast_cc_agent_recalling(agent->core_id, "Generic agent %s is recalling", agent->device_name);
ast_pbx_start(chan); ast_pbx_start(chan);
return NULL; return NULL;

@ -3819,7 +3819,8 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
ast_party_connected_line_free(&connected); ast_party_connected_line_free(&connected);
break; break;
} }
if (ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) { if (ast_channel_connected_line_sub(NULL, chan, &connected, 0) &&
ast_channel_connected_line_macro(NULL, chan, &connected, 1, 0)) {
ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE,
read_action_payload->payload, read_action_payload->payload,
read_action_payload->payload_size); read_action_payload->payload_size);
@ -5237,7 +5238,8 @@ static void call_forward_inherit(struct ast_channel *new_chan, struct ast_channe
ast_channel_lock(orig); ast_channel_lock(orig);
ast_party_redirecting_copy(&redirecting, &orig->redirecting); ast_party_redirecting_copy(&redirecting, &orig->redirecting);
ast_channel_unlock(orig); ast_channel_unlock(orig);
if (ast_channel_redirecting_macro(orig, parent, &redirecting, 1, 0)) { if (ast_channel_redirecting_sub(orig, parent, &redirecting, 0) &&
ast_channel_redirecting_macro(orig, parent, &redirecting, 1, 0)) {
ast_channel_update_redirecting(parent, &redirecting, NULL); ast_channel_update_redirecting(parent, &redirecting, NULL);
} }
ast_party_redirecting_free(&redirecting); ast_party_redirecting_free(&redirecting);
@ -7128,12 +7130,14 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
break; break;
case AST_CONTROL_REDIRECTING: case AST_CONTROL_REDIRECTING:
if (ast_channel_redirecting_macro(who, other, f, other == c0, 1)) { if (ast_channel_redirecting_sub(who, other, f, 1) &&
ast_channel_redirecting_macro(who, other, f, other == c0, 1)) {
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
} }
break; break;
case AST_CONTROL_CONNECTED_LINE: case AST_CONTROL_CONNECTED_LINE:
if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) { if (ast_channel_connected_line_sub(who, other, f, 1) &&
ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
} }
break; break;
@ -9362,6 +9366,7 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int is_frame) int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int is_caller, int is_frame)
{ {
static int deprecation_warning = 0;
const char *macro; const char *macro;
const char *macro_args; const char *macro_args;
int retval; int retval;
@ -9379,6 +9384,10 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc
return -1; return -1;
} }
if (!deprecation_warning) {
deprecation_warning = 1;
ast_log(LOG_WARNING, "Usage of CONNECTED_LINE_CALLE[ER]_SEND_MACRO is deprecated. Please use CONNECTED_LINE_SEND_SUB instead.\n");
}
if (is_frame) { if (is_frame) {
const struct ast_frame *frame = connected_info; const struct ast_frame *frame = connected_info;
@ -9401,6 +9410,7 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc
int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame) int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *redirecting_info, int is_caller, int is_frame)
{ {
static int deprecation_warning = 0;
const char *macro; const char *macro;
const char *macro_args; const char *macro_args;
int retval; int retval;
@ -9418,6 +9428,10 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a
return -1; return -1;
} }
if (!deprecation_warning) {
deprecation_warning = 1;
ast_log(LOG_WARNING, "Usage of REDIRECTING_CALLE[ER]_SEND_MACRO is deprecated. Please use REDIRECTING_SEND_SUB instead.\n");
}
if (is_frame) { if (is_frame) {
const struct ast_frame *frame = redirecting_info; const struct ast_frame *frame = redirecting_info;
@ -9439,6 +9453,81 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a
return retval; return retval;
} }
int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int is_frame)
{
const char *sub;
const char *sub_args;
int retval;
ast_channel_lock(sub_chan);
sub = pbx_builtin_getvar_helper(sub_chan, "CONNECTED_LINE_SEND_SUB");
sub = ast_strdupa(S_OR(sub, ""));
sub_args = pbx_builtin_getvar_helper(sub_chan, "CONNECTED_LINE_SEND_SUB_ARGS");
sub_args = ast_strdupa(S_OR(sub_args, ""));
if (ast_strlen_zero(sub)) {
ast_channel_unlock(sub_chan);
return -1;
}
if (is_frame) {
const struct ast_frame *frame = connected_info;
ast_connected_line_parse_data(frame->data.ptr, frame->datalen, &sub_chan->connected);
} else {
const struct ast_party_connected_line *connected = connected_info;
ast_party_connected_line_copy(&sub_chan->connected, connected);
}
ast_channel_unlock(sub_chan);
if (!(retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args))) {
ast_channel_lock(sub_chan);
ast_channel_update_connected_line(sub_chan, &sub_chan->connected, NULL);
ast_channel_unlock(sub_chan);
}
return retval;
}
int ast_channel_redirecting_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *redirecting_info, int is_frame)
{
const char *sub;
const char *sub_args;
int retval;
ast_channel_lock(sub_chan);
sub = pbx_builtin_getvar_helper(sub_chan, "REDIRECTING_SEND_SUB");
sub = ast_strdupa(S_OR(sub, ""));
sub_args = pbx_builtin_getvar_helper(sub_chan, "REDIRECTING_SEND_SUB_ARGS");
sub_args = ast_strdupa(S_OR(sub_args, ""));
if (ast_strlen_zero(sub)) {
ast_channel_unlock(sub_chan);
return -1;
}
if (is_frame) {
const struct ast_frame *frame = redirecting_info;
ast_redirecting_parse_data(frame->data.ptr, frame->datalen, &sub_chan->redirecting);
} else {
const struct ast_party_redirecting *redirecting = redirecting_info;
ast_party_redirecting_copy(&sub_chan->redirecting, redirecting);
}
ast_channel_unlock(sub_chan);
retval = ast_app_run_sub(autoservice_chan, sub_chan, sub, sub_args);
if (!retval) {
ast_channel_lock(sub_chan);
ast_channel_update_redirecting(sub_chan, &sub_chan->redirecting, NULL);
ast_channel_unlock(sub_chan);
}
return retval;
}
static void *channel_cc_params_copy(void *data) static void *channel_cc_params_copy(void *data)
{ {
const struct ast_cc_config_params *src = data; const struct ast_cc_config_params *src = data;

@ -437,13 +437,15 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
break; break;
case AST_CONTROL_CONNECTED_LINE: case AST_CONTROL_CONNECTED_LINE:
ast_verb(3, "%s connected line has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan)); ast_verb(3, "%s connected line has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
if (ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) { if (ast_channel_connected_line_sub(channel->owner, chan, fr, 1) &&
ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen); ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
} }
break; break;
case AST_CONTROL_REDIRECTING: case AST_CONTROL_REDIRECTING:
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan)); ast_verb(3, "%s redirecting info has changed, passing it to %s\n", ast_channel_name(channel->owner), ast_channel_name(chan));
if (ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) { if (ast_channel_redirecting_sub(channel->owner, chan, fr, 1) &&
ast_channel_redirecting_macro(channel->owner, chan, fr, 1, 1)) {
ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen); ast_indicate_data(chan, AST_CONTROL_REDIRECTING, fr->data.ptr, fr->datalen);
} }
break; break;

@ -2408,7 +2408,8 @@ static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_chann
* Party B was the caller to party C and is the last known mode * Party B was the caller to party C and is the last known mode
* for party B. * for party B.
*/ */
if (ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) { if (ast_channel_connected_line_sub(transferee, transferer, connected_line, 0) &&
ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
ast_channel_update_connected_line(transferer, connected_line, NULL); ast_channel_update_connected_line(transferer, connected_line, NULL);
} }
ast_party_connected_line_free(connected_line); ast_party_connected_line_free(connected_line);
@ -2816,7 +2817,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_party_connected_line_copy(&connected_line, &transferer->connected); ast_party_connected_line_copy(&connected_line, &transferer->connected);
ast_channel_unlock(transferer); ast_channel_unlock(transferer);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) { if (ast_channel_connected_line_sub(newchan, xferchan, &connected_line, 0) &&
ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
ast_channel_update_connected_line(xferchan, &connected_line, NULL); ast_channel_update_connected_line(xferchan, &connected_line, NULL);
} }
@ -2825,7 +2827,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller); ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
ast_channel_unlock(xferchan); ast_channel_unlock(xferchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) { if (ast_channel_connected_line_sub(xferchan, newchan, &connected_line, 0) &&
ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
ast_channel_update_connected_line(newchan, &connected_line, NULL); ast_channel_update_connected_line(newchan, &connected_line, NULL);
} }
@ -3614,7 +3617,8 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
ast_party_connected_line_free(&connected); ast_party_connected_line_free(&connected);
} else { } else {
ast_autoservice_start(transferee); ast_autoservice_start(transferee);
if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) { if (ast_channel_connected_line_sub(chan, caller, f, 1) &&
ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
f->data.ptr, f->datalen); f->data.ptr, f->datalen);
} }
@ -3623,7 +3627,8 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
} else if (f->subclass.integer == AST_CONTROL_REDIRECTING) { } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
if (!caller_hungup) { if (!caller_hungup) {
ast_autoservice_start(transferee); ast_autoservice_start(transferee);
if (ast_channel_redirecting_macro(chan, caller, f, 1, 1)) { if (ast_channel_redirecting_sub(chan, caller, f, 1) &&
ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
ast_indicate_data(caller, AST_CONTROL_REDIRECTING, ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
f->data.ptr, f->datalen); f->data.ptr, f->datalen);
} }
@ -4151,16 +4156,16 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a
ast_indicate(other, f->subclass.integer); ast_indicate(other, f->subclass.integer);
break; break;
case AST_CONTROL_CONNECTED_LINE: case AST_CONTROL_CONNECTED_LINE:
if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) { if (ast_channel_connected_line_sub(who, other, f, 1) &&
break; ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
} }
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
break; break;
case AST_CONTROL_REDIRECTING: case AST_CONTROL_REDIRECTING:
if (!ast_channel_redirecting_macro(who, other, f, who != chan, 1)) { if (ast_channel_redirecting_sub(who, other, f, 1) &&
break; ast_channel_redirecting_macro(who, other, f, who != chan, 1)) {
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
} }
ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
break; break;
case AST_CONTROL_AOC: case AST_CONTROL_AOC:
case AST_CONTROL_HOLD: case AST_CONTROL_HOLD:
@ -5172,7 +5177,8 @@ static int parked_call_exec(struct ast_channel *chan, const char *data)
ast_connected_line_copy_from_caller(&connected, &chan->caller); ast_connected_line_copy_from_caller(&connected, &chan->caller);
ast_channel_unlock(chan); ast_channel_unlock(chan);
connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
if (ast_channel_connected_line_macro(chan, peer, &connected, 0, 0)) { if (ast_channel_connected_line_sub(chan, peer, &connected, 0) &&
ast_channel_connected_line_macro(chan, peer, &connected, 0, 0)) {
ast_channel_update_connected_line(peer, &connected, NULL); ast_channel_update_connected_line(peer, &connected, NULL);
} }
@ -5187,7 +5193,8 @@ static int parked_call_exec(struct ast_channel *chan, const char *data)
ast_connected_line_copy_from_caller(&connected, &peer->caller); ast_connected_line_copy_from_caller(&connected, &peer->caller);
ast_channel_unlock(peer); ast_channel_unlock(peer);
connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
if (ast_channel_connected_line_macro(peer, chan, &connected, 1, 0)) { if (ast_channel_connected_line_sub(peer, chan, &connected, 0) &&
ast_channel_connected_line_macro(peer, chan, &connected, 1, 0)) {
ast_channel_update_connected_line(chan, &connected, NULL); ast_channel_update_connected_line(chan, &connected, NULL);
} }
@ -7319,7 +7326,8 @@ int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
ast_party_connected_line_copy(&connected_caller, &target->connected); ast_party_connected_line_copy(&connected_caller, &target->connected);
ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */ ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) { if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0) &&
ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
ast_channel_update_connected_line(chan, &connected_caller, NULL); ast_channel_update_connected_line(chan, &connected_caller, NULL);
} }
ast_party_connected_line_free(&connected_caller); ast_party_connected_line_free(&connected_caller);

@ -917,12 +917,14 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a
} }
ast_frfree(fr); ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) { } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) { if (ast_channel_connected_line_sub(who, other, fr, 1) &&
ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
} }
ast_frfree(fr); ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) { } else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) { if (ast_channel_redirecting_sub(who, other, fr, 1) &&
ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
} }
ast_frfree(fr); ast_frfree(fr);
@ -1206,12 +1208,14 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
} }
ast_frfree(fr); ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) { } else if (fr->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
if (ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) { if (ast_channel_connected_line_sub(who, other, fr, 1) &&
ast_channel_connected_line_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
} }
ast_frfree(fr); ast_frfree(fr);
} else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) { } else if (fr->subclass.integer == AST_CONTROL_REDIRECTING) {
if (ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) { if (ast_channel_redirecting_sub(who, other, fr, 1) &&
ast_channel_redirecting_macro(who, other, fr, other == c0, 1)) {
ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen);
} }
ast_frfree(fr); ast_frfree(fr);

Loading…
Cancel
Save