[svn-commits] rmudgett: trunk r390613 - /trunk/main/bridging.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jun 5 19:16:24 CDT 2013


Author: rmudgett
Date: Wed Jun  5 19:16:23 2013
New Revision: 390613

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390613
Log:
Misc core external attended transfer fixes.

* Fix external attended transfer bridge move/swap method.  One of the
transferrer channels was not kicked out of the bridge.

* Fix several off-nominal extended attended transfer paths.  Mainly the
channels involved needed to be hung up or kicked out of the bridge.

Modified:
    trunk/main/bridging.c

Modified: trunk/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridging.c?view=diff&rev=390613&r1=390612&r2=390613
==============================================================================
--- trunk/main/bridging.c (original)
+++ trunk/main/bridging.c Wed Jun  5 19:16:23 2013
@@ -2020,7 +2020,10 @@
 static void after_bridge_move_channel(struct ast_channel *chan_bridged, void *data)
 {
 	RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
-	ast_channel_move(chan_target, chan_bridged);
+
+	if (ast_channel_move(chan_target, chan_bridged)) {
+		ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
+	}
 }
 
 static void after_bridge_move_channel_fail(enum ast_after_bridge_cb_reason reason, void *data)
@@ -2028,7 +2031,8 @@
 	RAII_VAR(struct ast_channel *, chan_target, data, ao2_cleanup);
 
 	ast_log(LOG_WARNING, "Unable to complete transfer: %s\n",
-			ast_after_bridge_cb_reason_string(reason));
+		ast_after_bridge_cb_reason_string(reason));
+	ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
 }
 
 static void bridge_channel_attended_transfer(struct ast_bridge_channel *bridge_channel,
@@ -2040,21 +2044,22 @@
 	chan_target = ast_channel_get_by_name(target_chan_name);
 	if (!chan_target) {
 		/* Dang, it disappeared somehow */
+		bridge_handle_hangup(bridge_channel);
 		return;
 	}
 
-	{
-		SCOPED_CHANNELLOCK(lock, bridge_channel);
-		chan_bridged = bridge_channel->chan;
-		if (!chan_bridged) {
-			return;
-		}
-		ao2_ref(chan_bridged, +1);
-	}
+	ast_bridge_channel_lock(bridge_channel);
+	chan_bridged = bridge_channel->chan;
+	ast_assert(chan_bridged != NULL);
+	ao2_ref(chan_bridged, +1);
+	ast_bridge_channel_unlock(bridge_channel);
 
 	if (ast_after_bridge_callback_set(chan_bridged, after_bridge_move_channel,
-			after_bridge_move_channel_fail, ast_channel_ref(chan_target))) {
-		return;
+		after_bridge_move_channel_fail, ast_channel_ref(chan_target))) {
+		ast_softhangup(chan_target, AST_SOFTHANGUP_DEV);
+
+		/* Release the ref we tried to pass to ast_after_bridge_callback_set(). */
+		ast_channel_unref(chan_target);
 	}
 	bridge_handle_hangup(bridge_channel);
 }
@@ -5363,11 +5368,11 @@
 	}
 
 	ast_copy_string(unbridged_chan_name, ast_channel_name(unbridged_chan),
-			sizeof(unbridged_chan_name));
+		sizeof(unbridged_chan_name));
 
 	ast_bridge_channel_queue_action_data(transferee_bridge_channel,
-			AST_BRIDGE_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
-			sizeof(unbridged_chan_name));
+		AST_BRIDGE_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
+		sizeof(unbridged_chan_name));
 
 	return 0;
 }
@@ -5502,6 +5507,7 @@
 
 	{
 		SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
+
 		channels = ast_bridge_peers_nolock(bridge);
 		if (!channels) {
 			return AST_BRIDGE_TRANSFER_FAIL;
@@ -5564,11 +5570,17 @@
 	struct ast_bridge_channel *bridged_to_source;
 
 	bridged_to_source = ast_bridge_channel_peer(source_bridge_channel);
-	if (bridged_to_source && bridged_to_source->state == AST_BRIDGE_CHANNEL_STATE_WAIT
-			&& !ast_test_flag(&bridged_to_source->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE)) {
+	if (bridged_to_source
+		&& bridged_to_source->state == AST_BRIDGE_CHANNEL_STATE_WAIT
+		&& !ast_test_flag(&bridged_to_source->features->feature_flags,
+			AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE)) {
 		bridged_to_source->swap = swap_channel;
-		return bridge_move_do(dest_bridge, bridged_to_source, 1) ?
-			AST_BRIDGE_TRANSFER_FAIL : AST_BRIDGE_TRANSFER_SUCCESS;
+		if (bridge_move_do(dest_bridge, bridged_to_source, 1)) {
+			return AST_BRIDGE_TRANSFER_FAIL;
+		}
+		/* Must kick the source channel out of its bridge. */
+		ast_bridge_change_state(source_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+		return AST_BRIDGE_TRANSFER_SUCCESS;
 	} else {
 		return AST_BRIDGE_TRANSFER_INVALID;
 	}




More information about the svn-commits mailing list