[asterisk-commits] mmichelson: branch group/issue8824 r167604 - /team/group/issue8824/main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 7 17:17:36 CST 2009


Author: mmichelson
Date: Wed Jan  7 17:17:35 2009
New Revision: 167604

URL: http://svn.digium.com/view/asterisk?view=rev&rev=167604
Log:
Make attended transfers show correct connected line information for all parties
involved


Modified:
    team/group/issue8824/main/features.c

Modified: team/group/issue8824/main/features.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/main/features.c?view=diff&rev=167604&r1=167603&r2=167604
==============================================================================
--- team/group/issue8824/main/features.c (original)
+++ team/group/issue8824/main/features.c Wed Jan  7 17:17:35 2009
@@ -1284,7 +1284,7 @@
 	struct ast_bridge_config bconfig;
 	struct ast_frame *f;
 	int l;
-	struct ast_party_connected_line connected_line;
+	struct ast_party_connected_line connected_line = {{0,},};
 
 	ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
 	set_peers(&transferer, &transferee, peer, chan, sense);
@@ -1367,6 +1367,15 @@
 		memset(&bconfig,0,sizeof(struct ast_bridge_config));
 		ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
 		ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
+		/* We need to get the transferer's connected line information copied
+		 * at this point because he is likely to hang up during the bridge with
+		 * newchan. This info will be used down below before bridging the 
+		 * transferee and newchan
+		 *
+		 * As a result, we need to be sure to free this data before returning
+		 * or overwriting it.
+		 */
+		ast_party_connected_line_copy(&connected_line, &transferer->connected);
 		res = ast_bridge_call(transferer, newchan, &bconfig);
 		if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
 			ast_hangup(newchan);
@@ -1374,10 +1383,12 @@
 				ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
 			finishup(transferee);
 			transferer->_softhangup = 0;
+			ast_party_connected_line_free(&connected_line);
 			return AST_FEATURE_RETURN_SUCCESS;
 		}
 		if (check_compat(transferee, newchan)) {
 			finishup(transferee);
+			ast_party_connected_line_free(&connected_line);
 			return -1;
 		}
 		ast_indicate(transferee, AST_CONTROL_UNHOLD);
@@ -1388,8 +1399,125 @@
 		 || ast_check_hangup(transferee)
 		 || ast_check_hangup(newchan)) {
 			ast_hangup(newchan);
+			ast_party_connected_line_free(&connected_line);
 			return -1;
 		}
+		xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
+		if (!xferchan) {
+			ast_hangup(newchan);
+			ast_party_connected_line_free(&connected_line);
+			return -1;
+		}
+		/* Make formats okay */
+		xferchan->visible_indication = transferer->visible_indication;
+		xferchan->readformat = transferee->readformat;
+		xferchan->writeformat = transferee->writeformat;
+		ast_channel_masquerade(xferchan, transferee);
+		ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
+		xferchan->_state = AST_STATE_UP;
+		ast_clear_flag(xferchan, AST_FLAGS_ALL);
+		xferchan->_softhangup = 0;
+		if ((f = ast_read(xferchan)))
+			ast_frfree(f);
+		newchan->_state = AST_STATE_UP;
+		ast_clear_flag(newchan, AST_FLAGS_ALL);
+		newchan->_softhangup = 0;
+		if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
+			ast_hangup(xferchan);
+			ast_hangup(newchan);
+			ast_party_connected_line_free(&connected_line);
+			return -1;
+		}
+		tobj->chan = newchan;
+		tobj->peer = xferchan;
+		tobj->bconfig = *config;
+
+		if (tobj->bconfig.end_bridge_callback_data_fixup) {
+			tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
+		}
+
+		/* Due to a limitation regarding when callerID is set on a Local channel,
+		 * we use the transferer's connected line information here.
+		 */
+		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+		ast_connected_line_update(xferchan, &connected_line);
+		/* We need to free the allocated information in connected_line before overwriting
+		 * the info with the callerid of xferchan. Otherwise, there would be a memory leak
+		 */
+		ast_party_connected_line_free(&connected_line);
+		ast_party_connected_line_collect_caller(&connected_line, &xferchan->cid);
+		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+		ast_connected_line_update(newchan, &connected_line);
+
+		if (ast_stream_and_wait(newchan, xfersound, ""))
+			ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+		ast_bridge_call_thread_launch(tobj);
+		return -1;      /* XXX meaning the channel is bridged ? */
+	} else if (!ast_check_hangup(transferee)) {
+		/* act as blind transfer */
+		if (ast_autoservice_stop(transferee) < 0) {
+			ast_hangup(newchan);
+			return -1;
+		}
+
+		if (!newchan) {
+			unsigned int tries = 0;
+			char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
+
+			transferer_tech = strsep(&transferer_name, "/");
+			transferer_name = strsep(&transferer_name, "-");
+
+			if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
+				ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
+				if (ast_stream_and_wait(transferee, "beeperr", ""))
+					return -1;
+				return AST_FEATURE_RETURN_SUCCESS;
+			}
+
+			ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
+			newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
+				transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
+			while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
+				/* Trying to transfer again */
+				ast_autoservice_start(transferee);
+				ast_indicate(transferee, AST_CONTROL_HOLD);
+
+				newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
+					xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
+				if (ast_autoservice_stop(transferee) < 0) {
+					if (newchan)
+						ast_hangup(newchan);
+					return -1;
+				}
+				if (!newchan) {
+					/* Transfer failed, sleeping */
+					ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
+					ast_safe_sleep(transferee, atxferloopdelay);
+					ast_debug(1, "Trying to callback...\n");
+					newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
+						transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
+				}
+				tries++;
+			}
+		}
+		if (!newchan)
+			return -1;
+
+		/* newchan is up, we should prepare transferee and bridge them */
+		if (check_compat(transferee, newchan)) {
+			finishup(transferee);
+			return -1;
+		}
+		ast_indicate(transferee, AST_CONTROL_UNHOLD);
+
+		if ((ast_waitfordigit(transferee, 100) < 0)
+		   || (ast_waitfordigit(newchan, 100) < 0)
+		   || ast_check_hangup(transferee)
+		   || ast_check_hangup(newchan)) {
+			ast_hangup(newchan);
+			return -1;
+		}
+
 		xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
 		if (!xferchan) {
 			ast_hangup(newchan);
@@ -1417,114 +1545,6 @@
 		tobj->chan = newchan;
 		tobj->peer = xferchan;
 		tobj->bconfig = *config;
-
-		if (tobj->bconfig.end_bridge_callback_data_fixup) {
-			tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
-		}
-
-		ast_party_connected_line_collect_caller(&connected_line, &newchan->cid);
-		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-		ast_connected_line_update(xferchan, &connected_line);
-		ast_party_connected_line_collect_caller(&connected_line, &xferchan->cid);
-		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-		ast_connected_line_update(newchan, &connected_line);
-
-		if (ast_stream_and_wait(newchan, xfersound, ""))
-			ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
-		ast_bridge_call_thread_launch(tobj);
-		return -1;      /* XXX meaning the channel is bridged ? */
-	} else if (!ast_check_hangup(transferee)) {
-		/* act as blind transfer */
-		if (ast_autoservice_stop(transferee) < 0) {
-			ast_hangup(newchan);
-			return -1;
-		}
-
-		if (!newchan) {
-			unsigned int tries = 0;
-			char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
-
-			transferer_tech = strsep(&transferer_name, "/");
-			transferer_name = strsep(&transferer_name, "-");
-
-			if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
-				ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
-				if (ast_stream_and_wait(transferee, "beeperr", ""))
-					return -1;
-				return AST_FEATURE_RETURN_SUCCESS;
-			}
-
-			ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
-			newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
-				transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
-			while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
-				/* Trying to transfer again */
-				ast_autoservice_start(transferee);
-				ast_indicate(transferee, AST_CONTROL_HOLD);
-
-				newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
-					xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
-				if (ast_autoservice_stop(transferee) < 0) {
-					if (newchan)
-						ast_hangup(newchan);
-					return -1;
-				}
-				if (!newchan) {
-					/* Transfer failed, sleeping */
-					ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
-					ast_safe_sleep(transferee, atxferloopdelay);
-					ast_debug(1, "Trying to callback...\n");
-					newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
-						transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
-				}
-				tries++;
-			}
-		}
-		if (!newchan)
-			return -1;
-
-		/* newchan is up, we should prepare transferee and bridge them */
-		if (check_compat(transferee, newchan)) {
-			finishup(transferee);
-			return -1;
-		}
-		ast_indicate(transferee, AST_CONTROL_UNHOLD);
-
-		if ((ast_waitfordigit(transferee, 100) < 0)
-		   || (ast_waitfordigit(newchan, 100) < 0)
-		   || ast_check_hangup(transferee)
-		   || ast_check_hangup(newchan)) {
-			ast_hangup(newchan);
-			return -1;
-		}
-
-		xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
-		if (!xferchan) {
-			ast_hangup(newchan);
-			return -1;
-		}
-		/* Make formats okay */
-		xferchan->visible_indication = transferer->visible_indication;
-		xferchan->readformat = transferee->readformat;
-		xferchan->writeformat = transferee->writeformat;
-		ast_channel_masquerade(xferchan, transferee);
-		ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
-		xferchan->_state = AST_STATE_UP;
-		ast_clear_flag(xferchan, AST_FLAGS_ALL);
-		xferchan->_softhangup = 0;
-		if ((f = ast_read(xferchan)))
-			ast_frfree(f);
-		newchan->_state = AST_STATE_UP;
-		ast_clear_flag(newchan, AST_FLAGS_ALL);
-		newchan->_softhangup = 0;
-		if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
-			ast_hangup(xferchan);
-			ast_hangup(newchan);
-			return -1;
-		}
-		tobj->chan = newchan;
-		tobj->peer = xferchan;
-		tobj->bconfig = *config;
 		
 		if (tobj->bconfig.end_bridge_callback_data_fixup) {
 			tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
@@ -2028,6 +2048,8 @@
 	ast_channel_inherit_variables(caller, chan);	
 	pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
 		
+	ast_copy_caller_to_connected(&chan->connected, &caller->cid);
+	
 	if (ast_call(chan, data, timeout)) {
 		ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
 		goto done;




More information about the asterisk-commits mailing list