[asterisk-commits] mmichelson: trunk r198727 - in /trunk: apps/ channels/ doc/tex/ include/aster...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jun 1 15:57:35 CDT 2009


Author: mmichelson
Date: Mon Jun  1 15:57:31 2009
New Revision: 198727

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=198727
Log:
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


Modified:
    trunk/apps/app_dial.c
    trunk/apps/app_directed_pickup.c
    trunk/apps/app_macro.c
    trunk/apps/app_queue.c
    trunk/channels/chan_sip.c
    trunk/doc/tex/channelvariables.tex
    trunk/include/asterisk/app.h
    trunk/include/asterisk/channel.h
    trunk/main/app.c
    trunk/main/channel.c
    trunk/main/dial.c
    trunk/main/features.c

Modified: trunk/apps/app_dial.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/apps/app_dial.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/apps/app_dial.c (original)
+++ trunk/apps/app_dial.c Mon Jun  1 15:57:31 2009
@@ -937,7 +937,9 @@
 					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 @@
 						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 @@
 						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 @@
 				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);
 		}

Modified: trunk/apps/app_directed_pickup.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/apps/app_directed_pickup.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/apps/app_directed_pickup.c (original)
+++ trunk/apps/app_directed_pickup.c Mon Jun  1 15:57:31 2009
@@ -98,7 +98,9 @@
 
 	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);

Modified: trunk/apps/app_macro.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/apps/app_macro.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/apps/app_macro.c (original)
+++ trunk/apps/app_macro.c Mon Jun  1 15:57:31 2009
@@ -36,6 +36,7 @@
 #include "asterisk/config.h"
 #include "asterisk/utils.h"
 #include "asterisk/lock.h"
+#include "asterisk/app.h"
 
 /*** DOCUMENTATION
 	<application name="Macro" language="en_US">

Modified: trunk/apps/app_queue.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/apps/app_queue.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Mon Jun  1 15:57:31 2009
@@ -3092,7 +3092,9 @@
 					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 @@
 								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 @@
 								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:

Modified: trunk/channels/chan_sip.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Mon Jun  1 15:57:31 2009
@@ -20407,6 +20407,8 @@
 					/* 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 @@
 		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 @@
 			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 @@
 			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;

Modified: trunk/doc/tex/channelvariables.tex
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/doc/tex/channelvariables.tex?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/doc/tex/channelvariables.tex (original)
+++ trunk/doc/tex/channelvariables.tex Mon Jun  1 15:57:31 2009
@@ -1005,3 +1005,10 @@
 ${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}

Modified: trunk/include/asterisk/app.h
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/include/asterisk/app.h?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/include/asterisk/app.h (original)
+++ trunk/include/asterisk/app.h Mon Jun  1 15:57:31 2009
@@ -109,6 +109,26 @@
 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

Modified: trunk/include/asterisk/channel.h
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Mon Jun  1 15:57:31 2009
@@ -2550,6 +2550,34 @@
  */
 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

Modified: trunk/main/app.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/main/app.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/main/app.c (original)
+++ trunk/main/app.c Mon Jun  1 15:57:31 2009
@@ -200,6 +200,28 @@
 
 	res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
 
+	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;
 }
 

Modified: trunk/main/channel.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/main/channel.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Mon Jun  1 15:57:31 2009
@@ -5008,13 +5008,19 @@
 			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 @@
 	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

Modified: trunk/main/dial.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/main/dial.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/main/dial.c (original)
+++ trunk/main/dial.c Mon Jun  1 15:57:31 2009
@@ -37,6 +37,7 @@
 #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 @@
 			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);

Modified: trunk/main/features.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/main/features.c?view=diff&rev=198727&r1=198726&r2=198727
==============================================================================
--- trunk/main/features.c (original)
+++ trunk/main/features.c Mon Jun  1 15:57:31 2009
@@ -1377,6 +1377,9 @@
 			/* 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 @@
 		/* 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 @@
 		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 @@
 					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 @@
 			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 @@
 
 	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;




More information about the asterisk-commits mailing list