[asterisk-commits] mmichelson: branch mmichelson/more_transfer r389565 - in /team/mmichelson/mor...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 23 13:07:01 CDT 2013


Author: mmichelson
Date: Thu May 23 13:06:57 2013
New Revision: 389565

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389565
Log:
Latest findings blah blah blah


Modified:
    team/mmichelson/more_transfer/include/asterisk/bridging.h
    team/mmichelson/more_transfer/main/bridging.c

Modified: team/mmichelson/more_transfer/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/more_transfer/include/asterisk/bridging.h?view=diff&rev=389565&r1=389564&r2=389565
==============================================================================
--- team/mmichelson/more_transfer/include/asterisk/bridging.h (original)
+++ team/mmichelson/more_transfer/include/asterisk/bridging.h Thu May 23 13:06:57 2013
@@ -902,6 +902,7 @@
  *
  * \param chan_bridge First bridge being tested
  * \param peer_bridge Second bridge being tested
+ * \param unreal_in_bridges True if unreal channels to be optimzed out are already in the bridges
  *
  * This determines if two bridges allow for unreal channel optimization
  * to occur between them. The function does not require for unreal channels
@@ -917,7 +918,7 @@
  * \returns Optimization allowability for the bridges
  */
 enum ast_bridge_optimization ast_bridges_allow_optimization(struct ast_bridge *chan_bridge,
-		struct ast_bridge *peer_bridge);
+		struct ast_bridge *peer_bridge, int unreal_in_bridges);
 
 /*!
  * \brief Try locking the bridge_channel.

Modified: team/mmichelson/more_transfer/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/more_transfer/main/bridging.c?view=diff&rev=389565&r1=389564&r2=389565
==============================================================================
--- team/mmichelson/more_transfer/main/bridging.c (original)
+++ team/mmichelson/more_transfer/main/bridging.c Thu May 23 13:06:57 2013
@@ -3874,7 +3874,7 @@
  * \brief Indicates allowability of a swap optimization
  */
 enum bridge_allow_swap {
-	/*! Bridges cannot allow for a swap optimization to occure */
+	/*! Bridges cannot allow for a swap optimization to occur */
 	SWAP_PROHIBITED,
 	/*! Bridge swap optimization can occur into the chan_bridge */
 	SWAP_TO_CHAN_BRIDGE,
@@ -3897,9 +3897,11 @@
 	int peer_priority;
 
 	if (!ast_test_flag(&chan_bridge->feature_flags,
-			AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM)
+			AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM |
+			AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY)
 		&& !ast_test_flag(&peer_bridge->feature_flags,
-			AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM)) {
+			AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM |
+			AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY)) {
 		/*
 		 * Can swap either way.  Swap to the higher priority merge
 		 * bridge.
@@ -4121,7 +4123,7 @@
 }
 
 enum ast_bridge_optimization ast_bridges_allow_optimization(struct ast_bridge *chan_bridge,
-		struct ast_bridge *peer_bridge)
+		struct ast_bridge *peer_bridge, int unreal_in_bridges)
 {
 	struct merge_direction merge;
 
@@ -4139,7 +4141,7 @@
 		break;
 	}
 
-	if (bridges_allow_merge_optimization(chan_bridge, peer_bridge, 2, &merge) != MERGE_ALLOWED) {
+	if (bridges_allow_merge_optimization(chan_bridge, peer_bridge, unreal_in_bridges ? 2 : 0, &merge) != MERGE_ALLOWED) {
 		return AST_BRIDGE_OPTIMIZE_PROHIBITED;
 	}
 
@@ -5467,11 +5469,18 @@
 static struct ast_bridge *acquire_bridge(struct ast_channel *chan)
 {
 	struct ast_bridge *bridge;
+	int bridge_invalid_for_transfer;
 
 	ast_channel_lock(chan);
 	bridge = ast_channel_get_bridge(chan);
 	ast_channel_unlock(chan);
-	if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)) {
+
+	ast_bridge_lock(bridge);
+	bridge_invalid_for_transfer = ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY) ||
+			ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
+	ast_bridge_unlock(bridge);
+
+	if (bridge_invalid_for_transfer) {
 		ao2_ref(bridge, -1);
 		bridge = NULL;
 	}
@@ -5484,25 +5493,24 @@
  * \brief Performs an attended transfer by moving a channel from one bridge to another
  *
  * The channel that is bridged to the source_channel is moved into the dest_bridge from
- * the source_bridge. The swap_channel is swapped out of the dest_bridge and placed in
- * the source_bridge.
- *
- * \note dest_bridge and source_bridge MUST be locked before calling this function.
+ * the source_bridge_channel's bridge. The swap_channel is swapped out of the dest_bridge and placed in
+ * the source_bridge_channel's bridge.
+ *
+ * \note dest_bridge and source_bridge_channel's bridge MUST be locked before calling this function.
  *
  * \param dest_bridge The final bridge for the attended transfer
- * \param source_bridge The bridge from which a channel is moved
  * \param source_channel Channel who is bridged to the channel that will move
  * \param swap_channel Channel to be swapped out of the dest_bridge
  * \return The success or failure of the swap attempt
  */
 static enum ast_transfer_result bridge_swap_attended_transfer(struct ast_bridge *dest_bridge,
-		struct ast_bridge *source_bridge, struct ast_bridge_channel *source_bridge_channel,
-		struct ast_channel *swap_channel)
+		struct ast_bridge_channel *source_bridge_channel, struct ast_channel *swap_channel)
 {
 	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) {
+	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;
@@ -5541,11 +5549,11 @@
 			to_target_bridge_channel,
 	};
 
-	switch (ast_bridges_allow_optimization(to_transferee_bridge, to_target_bridge)) {
+	switch (ast_bridges_allow_optimization(to_transferee_bridge, to_target_bridge, 0)) {
 	case AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE:
-		return bridge_swap_attended_transfer(to_transferee_bridge, to_target_bridge, to_target_bridge_channel, to_transferee);
+		return bridge_swap_attended_transfer(to_transferee_bridge, to_target_bridge_channel, to_transferee);
 	case AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE:
-		return bridge_swap_attended_transfer(to_target_bridge, to_transferee_bridge, to_transferee_bridge_channel, to_transfer_target);
+		return bridge_swap_attended_transfer(to_target_bridge, to_transferee_bridge_channel, to_transfer_target);
 	case AST_BRIDGE_OPTIMIZE_MERGE_TO_CHAN_BRIDGE:
 		bridge_merge_do(to_transferee_bridge, to_target_bridge, kick_me, ARRAY_LEN(kick_me));
 		return AST_BRIDGE_TRANSFER_SUCCESS;
@@ -5554,6 +5562,14 @@
 		return AST_BRIDGE_TRANSFER_SUCCESS;
 	case AST_BRIDGE_OPTIMIZE_PROHIBITED:
 	default:
+		/* Just because optimization wasn't doable doesn't necessarily mean
+		 * that we can actually perform the transfer. Some reasons for non-optimization
+		 * indicate bridge invalidity, so let's check those before proceeding.
+		 */
+		if (to_transferee_bridge->inhibit_merge || to_transferee_bridge->dissolved ||
+				to_target_bridge->inhibit_merge || to_target_bridge->dissolved) {
+			return AST_BRIDGE_TRANSFER_INVALID;
+		}
 		return attended_transfer_bridge(to_transferee, to_transfer_target,
 			to_transferee_bridge, to_target_bridge);
 	}




More information about the asterisk-commits mailing list