aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-01 20:57:31 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-01 20:57:31 +0000
commitce47d41510edcdf1f7d36852350df02afc5f6014 (patch)
tree22c7cb967cc375a45f8cabb0f6c6998b7b5f674a
parentd79b32623f5a7917a0e2feef2cc14ef894104431 (diff)
Add the ability to execute connected line interception macros.
When connected line updates are received or generated in the middle of an application call, it is now possible to execute a macro to manipulate the connected line data. This way, phone numbers may be manipulated to be more presentable to users, names may be changed for...whatever reason, or whatever else needs to be done may be. Review: https://reviewboard.asterisk.org/r/256 AST-165 git-svn-id: http://svn.digium.com/svn/asterisk/trunk@198727 f38db490-d61c-443f-a65b-d21fe96a405b
-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;