aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/app_dial.c35
-rw-r--r--apps/app_directed_pickup.c4
-rw-r--r--apps/app_macro.c1
-rw-r--r--apps/app_queue.c13
-rw-r--r--channels/chan_sip.c65
-rw-r--r--doc/tex/channelvariables.tex7
-rw-r--r--include/asterisk/app.h20
-rw-r--r--include/asterisk/channel.h28
-rw-r--r--main/app.c22
-rw-r--r--main/channel.c48
-rw-r--r--main/dial.c5
-rw-r--r--main/features.c59
12 files changed, 242 insertions, 65 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 249c0dcb8..92000abde 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -937,7 +937,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "%s answered %s\n", c->name, in->name);
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
if (o->connected.id.number) {
- ast_channel_update_connected_line(in, &o->connected);
+ if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
+ ast_channel_update_connected_line(in, &o->connected);
+ }
} else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
ast_channel_lock(c);
ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
@@ -987,7 +989,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "%s answered %s\n", c->name, in->name);
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
if (o->connected.id.number) {
- ast_channel_update_connected_line(in, &o->connected);
+ if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
+ ast_channel_update_connected_line(in, &o->connected);
+ }
} else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
ast_channel_lock(c);
ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
@@ -1076,8 +1080,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_party_connected_line_set(&o->connected, &connected);
ast_party_connected_line_free(&connected);
} else {
- ast_verb(3, "%s connected line has changed, passing it to %s\n", c->name, in->name);
- ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ if (ast_channel_connected_line_macro(c, in, f, 1, 1)) {
+ ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ }
}
break;
case AST_CONTROL_REDIRECTING:
@@ -1198,15 +1203,19 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
if (ast_write(outgoing->chan, f))
ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
}
- if (single && (f->frametype == AST_FRAME_CONTROL) &&
- ((f->subclass == AST_CONTROL_HOLD) ||
- (f->subclass == AST_CONTROL_UNHOLD) ||
- (f->subclass == AST_CONTROL_VIDUPDATE) ||
- (f->subclass == AST_CONTROL_SRCUPDATE) ||
- (f->subclass == AST_CONTROL_CONNECTED_LINE) ||
- (f->subclass == AST_CONTROL_REDIRECTING))) {
- ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
- ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
+ if (single && (f->frametype == AST_FRAME_CONTROL)) {
+ if ((f->subclass == AST_CONTROL_HOLD) ||
+ (f->subclass == AST_CONTROL_UNHOLD) ||
+ (f->subclass == AST_CONTROL_VIDUPDATE) ||
+ (f->subclass == AST_CONTROL_SRCUPDATE) ||
+ (f->subclass == AST_CONTROL_REDIRECTING)) {
+ ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
+ ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
+ } else if (f->subclass == AST_CONTROL_CONNECTED_LINE) {
+ if (ast_channel_connected_line_macro(in, outgoing->chan, f, 0, 1)) {
+ ast_indicate_data(outgoing->chan, f->subclass, f->data.ptr, f->datalen);
+ }
+ }
}
ast_frfree(f);
}
diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c
index 2696b4440..2e196a7d8 100644
--- a/apps/app_directed_pickup.c
+++ b/apps/app_directed_pickup.c
@@ -98,7 +98,9 @@ static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
connected_caller = target->connected;
connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- ast_channel_update_connected_line(chan, &connected_caller);
+ if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
+ ast_channel_update_connected_line(chan, &connected_caller);
+ }
ast_channel_lock(chan);
ast_connected_line_copy_from_caller(&connected_caller, &chan->cid);
diff --git a/apps/app_macro.c b/apps/app_macro.c
index 1db3b27a8..f3a6b546e 100644
--- a/apps/app_macro.c
+++ b/apps/app_macro.c
@@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
+#include "asterisk/app.h"
/*** DOCUMENTATION
<application name="Macro" language="en_US">
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 346794776..3d367f663 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -3092,7 +3092,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
if (o->connected.id.number) {
- ast_channel_update_connected_line(in, &o->connected);
+ if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
+ ast_channel_update_connected_line(in, &o->connected);
+ }
} else if (o->update_connectedline) {
ast_channel_lock(o->chan);
ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
@@ -3192,7 +3194,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
if (o->connected.id.number) {
- ast_channel_update_connected_line(in, &o->connected);
+ if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
+ ast_channel_update_connected_line(in, &o->connected);
+ }
} else if (o->update_connectedline) {
ast_channel_lock(o->chan);
ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
@@ -3252,8 +3256,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_party_connected_line_set(&o->connected, &connected);
ast_party_connected_line_free(&connected);
} else {
- ast_verb(3, "%s connected line has changed, passing it to %s\n", ochan_name, inchan_name);
- ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
+ ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ }
}
break;
case AST_CONTROL_REDIRECTING:
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 9de562630..0913438d4 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -20407,6 +20407,8 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
/* Chan 2: Call from Asterisk to target */
int res = 0;
struct sip_pvt *targetcall_pvt;
+ struct ast_party_connected_line connected_to_transferee;
+ struct ast_party_connected_line connected_to_target;
/* Check if the call ID of the replaces header does exist locally */
if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag,
@@ -20474,6 +20476,13 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
transferer->callid,
target.chan1->name,
target.chan1->uniqueid);
+ ast_party_connected_line_init(&connected_to_transferee);
+ ast_party_connected_line_init(&connected_to_target);
+ /* No need to lock current->chan1 here since it was locked in sipsock_read */
+ ast_party_connected_line_copy(&connected_to_transferee, &current->chan1->connected);
+ /* No need to lock target.chan1 here since it was locked in get_sip_pvt_byid_locked */
+ ast_party_connected_line_copy(&connected_to_target, &target.chan1->connected);
+ connected_to_target.source = connected_to_transferee.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
res = attempt_transfer(current, &target);
sip_pvt_unlock(targetcall_pvt);
if (res) {
@@ -20484,8 +20493,6 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
ast_channel_unlock(targetcall_pvt->owner);
ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER);
} else {
- struct ast_party_connected_line connected_caller;
-
/* Transfer succeeded! */
const char *xfersound = pbx_builtin_getvar_helper(target.chan1, "ATTENDED_TRANSFER_COMPLETE_SOUND");
@@ -20501,45 +20508,29 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
ast_channel_unlock(targetcall_pvt->owner);
}
- ast_party_connected_line_init(&connected_caller);
+ /* By forcing the masquerade, we know that target.chan1 and target.chan2 are bridged. We then
+ * can queue connected line updates where they need to go.
+ *
+ * No need to lock target.chan1 here since it was previously locked in get_sip_pvt_byid_locked
+ */
+ if (target.chan1->masq) {
+ /* If the channel thread already did the masquerade, then we don't need to do anything */
+ ast_do_masquerade(target.chan1);
+ }
if (target.chan2) {
- if (current->chan2) {
- /* Tell each of the other channels to whom they are now connected */
- ast_channel_lock(current->chan2);
- ast_connected_line_copy_from_caller(&connected_caller, &current->chan2->cid);
- ast_channel_unlock(current->chan2);
- connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(target.chan2, &connected_caller);
- ast_channel_lock(target.chan2);
- ast_connected_line_copy_from_caller(&connected_caller, &target.chan2->cid);
- ast_channel_unlock(target.chan2);
- connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(current->chan2, &connected_caller);
- ast_party_connected_line_free(&connected_caller);
- }
+ ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee);
+ ast_channel_queue_connected_line_update(target.chan2, &connected_to_target);
} else {
- /* Notify the first other party that they are connected to someone else assuming that target.chan1
- has progressed far enough through the dialplan to have its called party information set. */
- if (current->chan2) {
- ast_channel_lock(target.chan1);
- ast_party_connected_line_copy(&connected_caller, &target.chan1->connected);
- ast_channel_unlock(target.chan1);
- connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(current->chan2, &connected_caller);
- ast_party_connected_line_free(&connected_caller);
- }
-
- /* We can't indicate to the called channel directly so we force the masquerade to complete
- and queue and update to be read and passed-through */
- ast_channel_lock(target.chan1);
- ast_do_masquerade(target.chan1);
- ast_channel_unlock(target.chan1);
-
- ast_party_connected_line_collect_caller(&connected_caller, &target.chan1->cid);
- connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_queue_connected_line_update(target.chan1, &connected_caller);
+ /* Since target.chan1 isn't actually connected to another channel, there is no way for us
+ * to queue a frame so that its connected line status will be updated. Instead, we have to
+ * change it directly. Since we are not the channel thread, we cannot run a connected line
+ * interception macro on target.chan1
+ */
+ ast_channel_update_connected_line(target.chan1, &connected_to_target);
}
}
+ ast_party_connected_line_free(&connected_to_target);
+ ast_party_connected_line_free(&connected_to_transferee);
if (targetcall_pvt)
ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt");
return 1;
diff --git a/doc/tex/channelvariables.tex b/doc/tex/channelvariables.tex
index 0a7e81022..6b549ef9d 100644
--- a/doc/tex/channelvariables.tex
+++ b/doc/tex/channelvariables.tex
@@ -1005,3 +1005,10 @@ ${OSPOUTTOKEN} OSP token to use for out_bound call
${OSPOUTTIMELIMIT} Duration limit for out_bound call
${OSPRESULTS} Number of remained destinations
\end{verbatim}
+
+\subsection{Connected line digit manipulation}
+\begin{verbatim}
+${CONNECTED_LINE_SEND_CALLEE_MACRO} Macro to call before sending a connected line update to the callee
+${CONNECTED_LINE_SEND_CALLEE_MACRO_ARGS} Arguments to pass to ${CONNECTED_LINE_SEND_CALLEE_MACRO}
+${CONNECTED_LINE_SEND_CALLER_MACRO} Macro to call before sending a connected line update to the caller
+${CONNECTED_LINE_SEND_CALLER_MACRO_ARGS} Arguments to pass to ${CONNECTED_LINE_SEND_CALLER_MACRO}
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index d442e5292..da947b5d7 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -109,6 +109,26 @@ int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxl
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd);
/*!
+ * \since 1.6.3
+ * \brief Run a macro on a channel, placing a second channel into autoservice.
+ *
+ * This is a shorthand method that makes it very easy to run a macro 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_macro. A
+ * deadlock could result, otherwise.
+ *
+ * \param autoservice_chan A channel to place into autoservice while the macro is run
+ * \param macro_chan The channel to run the macro on
+ * \param macro_name The name of the macro to run
+ * \param macro_args The arguments to pass to the macro
+ * \retval 0 success
+ * \retval -1 failure
+ */
+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);
+
+/*!
* \brief Set voicemail function callbacks
* \param[in] inboxcount2_func set function pointer
* \param[in] sayname_func set function pointer
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 193d0ff34..6bfb7b6d5 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -2550,6 +2550,34 @@ void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_p
*/
void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
+/*!
+ * \since 1.6.3
+ * \brief Run a connected line interception macro 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 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.
+ *
+ * \param autoservice_chan Channel to place into autoservice while the macro is running.
+ * 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
+ * determine which macro we need to run.
+ * \param connected_info Either an ast_party_connected_line or ast_frame pointer of type
+ * AST_CONTROL_CONNECTED_LINE
+ * \param caller If true, then run CONNECTED_LINE_CALLER_SEND_MACRO, otherwise run
+ * CONNECTED_LINE_CALLEE_SEND_MACRO
+ * \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 macro does not exist, or there was an error while attempting to
+ * run the macro
+ *
+ * \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
+ * '0'
+ */
+int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
diff --git a/main/app.c b/main/app.c
index 72af3e085..eacefabd0 100644
--- a/main/app.c
+++ b/main/app.c
@@ -203,6 +203,28 @@ int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int
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)
+{
+ struct ast_app *macro_app;
+ int res;
+ char buf[1024];
+
+ macro_app = pbx_findapp("Macro");
+ if (!macro_app) {
+ ast_log(LOG_WARNING, "Cannot run macro '%s' because the 'Macro' application in not available\n", macro_name);
+ return -1;
+ }
+ snprintf(buf, sizeof(buf), "%s%s%s", macro_name, ast_strlen_zero(macro_args) ? "" : ",", S_OR(macro_args, ""));
+ if (autoservice_chan) {
+ ast_autoservice_start(autoservice_chan);
+ }
+ res = pbx_exec(macro_chan, macro_app, buf);
+ if (autoservice_chan) {
+ ast_autoservice_stop(autoservice_chan);
+ }
+ return res;
+}
+
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_inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL;
diff --git a/main/channel.c b/main/channel.c
index bd997def6..d9ce2efbf 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -5008,13 +5008,19 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
int bridge_exit = 0;
switch (f->subclass) {
+ case AST_CONTROL_REDIRECTING:
+ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
+ break;
+ case AST_CONTROL_CONNECTED_LINE:
+ if (ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
+ ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
+ }
+ break;
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_T38:
case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_CONNECTED_LINE:
- case AST_CONTROL_REDIRECTING:
ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
if (jb_in_use) {
ast_jb_empty_and_reset(c0, c1);
@@ -6503,6 +6509,44 @@ void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct
ast_queue_control_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
}
+int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const void *connected_info, int caller, int frame)
+{
+ const char *macro;
+ const char *macro_args;
+ union {
+ const struct ast_frame *frame;
+ const struct ast_party_connected_line *connected;
+ } pointer;
+ int retval;
+
+ if (frame) {
+ pointer.frame = connected_info;
+ } else {
+ pointer.connected = connected_info;
+ }
+
+ ast_channel_lock(macro_chan);
+ macro = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO" : "CONNECTED_LINE_CALLEE_SEND_MACRO"), ""));
+ macro_args = ast_strdupa(S_OR(pbx_builtin_getvar_helper(macro_chan, caller ? "CONNECTED_LINE_CALLER_SEND_MACRO_ARGS" : "CONNECTED_LINE_CALLEE_SEND_MACRO_ARGS"), ""));
+ ast_channel_unlock(macro_chan);
+
+ if (ast_strlen_zero(macro)) {
+ return -1;
+ }
+
+ if (frame) {
+ ast_connected_line_parse_data(pointer.frame->data.ptr, pointer.frame->datalen, &macro_chan->connected);
+ } else {
+ ast_party_connected_line_copy(&macro_chan->connected, pointer.connected);
+ }
+
+ if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) {
+ ast_channel_update_connected_line(macro_chan, &macro_chan->connected);
+ }
+
+ return retval;
+}
+
/* DO NOT PUT ADDITIONAL FUNCTIONS BELOW THIS BOUNDARY
*
* ONLY FUNCTIONS FOR PROVIDING BACKWARDS ABI COMPATIBILITY BELONG HERE
diff --git a/main/dial.c b/main/dial.c
index d38b4829d..1f65f50c7 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dial.h"
#include "asterisk/pbx.h"
#include "asterisk/musiconhold.h"
+#include "asterisk/app.h"
/*! \brief Main dialing structure. Contains global options, channels being dialed, and more! */
struct ast_dial {
@@ -430,7 +431,9 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
break;
case AST_CONTROL_CONNECTED_LINE:
ast_verb(3, "%s connected line has changed, passing it to %s\n", channel->owner->name, chan->name);
- ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
+ if (ast_channel_connected_line_macro(channel->owner, chan, fr, 1, 1)) {
+ ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, fr->data.ptr, fr->datalen);
+ }
break;
case AST_CONTROL_REDIRECTING:
ast_verb(3, "%s redirecting info has changed, passing it to %s\n", channel->owner->name, chan->name);
diff --git a/main/features.c b/main/features.c
index 6e3570e63..6c15f258d 100644
--- a/main/features.c
+++ b/main/features.c
@@ -1377,6 +1377,9 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
/* Set the channel's new extension, since it exists, using transferer context */
ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
+ if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
+ ast_channel_update_connected_line(transferee, &transferer->connected);
+ }
set_c_e_p(transferee, transferer_real_context, xferto, 0);
}
check_goto_on_transfer(transferer);
@@ -1635,13 +1638,43 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
/* Due to a limitation regarding when callerID is set on a Local channel,
* we use the transferer's connected line information here.
*/
+
+ /* xferchan is transferee, and newchan is the transfer target
+ * So...in a transfer, who is the caller and who is the callee?
+ *
+ * When the call is originally made, it is clear who is caller and callee.
+ * When a transfer occurs, it is my humble opinion that the transferee becomes
+ * the caller, and the transfer target is the callee.
+ *
+ * The problem is that these macros were set with the intention of the original
+ * caller and callee taking those roles. A transfer can totally mess things up,
+ * to be technical. What sucks even more is that you can't effectively change
+ * the macros in the dialplan during the call from the transferer to the transfer
+ * target because the transferee is stuck with whatever role he originally had.
+ *
+ * I think the answer here is just to make sure that it is well documented that
+ * during a transfer, the transferee is the "caller" and the transfer target
+ * is the "callee."
+ *
+ * This means that if party A calls party B, and party A transfers party B to
+ * party C, then B has switched roles for the call. Now party B will have the
+ * caller macro called on his channel instead of the callee macro.
+ *
+ * Luckily, the method by which the bridge is launched here ensures that the
+ * transferee is the "chan" on the bridge and the transfer target is the "peer,"
+ * so my idea for the roles post-transfer does not require extensive code changes.
+ */
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(xferchan, &connected_line);
+ if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
+ ast_channel_update_connected_line(xferchan, &connected_line);
+ }
ast_channel_lock(xferchan);
ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
ast_channel_unlock(xferchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(newchan, &connected_line);
+ if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
+ ast_channel_update_connected_line(newchan, &connected_line);
+ }
ast_party_connected_line_free(&connected_line);
if (ast_stream_and_wait(newchan, xfersound, ""))
@@ -1749,12 +1782,16 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_connected_line_copy_from_caller(&connected_line, &newchan->cid);
ast_channel_unlock(newchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(xferchan, &connected_line);
+ if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
+ ast_channel_update_connected_line(xferchan, &connected_line);
+ }
ast_channel_lock(xferchan);
ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
ast_channel_unlock(xferchan);
connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_channel_update_connected_line(newchan, &connected_line);
+ if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
+ ast_channel_update_connected_line(newchan, &connected_line);
+ }
ast_party_connected_line_free(&connected_line);
@@ -2370,7 +2407,9 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
ready=1;
break;
} else if (f->subclass == AST_CONTROL_CONNECTED_LINE) {
- ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ if (ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
+ ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
+ }
} else if (f->subclass != -1) {
ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass);
}
@@ -2766,9 +2805,13 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
case -1:
ast_indicate(other, f->subclass);
break;
+ case AST_CONTROL_CONNECTED_LINE:
+ if (!ast_channel_connected_line_macro(who, other, f, who != chan, 1)) {
+ break;
+ }
+ /* The implied "else" falls through purposely */
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
- case AST_CONTROL_CONNECTED_LINE:
ast_indicate_data(other, f->subclass, f->data.ptr, f->datalen);
break;
case AST_CONTROL_OPTION:
@@ -4546,7 +4589,9 @@ int ast_pickup_call(struct ast_channel *chan)
connected_caller = cur->connected;
connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- ast_channel_update_connected_line(chan, &connected_caller);
+ if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
+ ast_channel_update_connected_line(chan, &connected_caller);
+ }
ast_party_connected_line_collect_caller(&connected_caller, &chan->cid);
connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;