[asterisk-commits] file: branch file/bridging r92043 - in /team/file/bridging: include/asterisk/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Dec 9 17:00:01 CST 2007


Author: file
Date: Sun Dec  9 17:00:00 2007
New Revision: 92043

URL: http://svn.digium.com/view/asterisk?view=rev&rev=92043
Log:
Add experimental code for merging bridges, specifically the part that moves the channels from the old bridge to the new one.

Modified:
    team/file/bridging/include/asterisk/bridging.h
    team/file/bridging/main/bridging.c

Modified: team/file/bridging/include/asterisk/bridging.h
URL: http://svn.digium.com/view/asterisk/team/file/bridging/include/asterisk/bridging.h?view=diff&rev=92043&r1=92042&r2=92043
==============================================================================
--- team/file/bridging/include/asterisk/bridging.h (original)
+++ team/file/bridging/include/asterisk/bridging.h Sun Dec  9 17:00:00 2007
@@ -51,6 +51,7 @@
 	AST_BRIDGE_CHANNEL_STATE_DEPART,   /*! Depart from the bridge */
 	AST_BRIDGE_CHANNEL_STATE_SWAP,     /*! Channel is being swapped out */
 	AST_BRIDGE_CHANNEL_STATE_FEATURE,  /*! Channel is currently executing a feature */
+	AST_BRIDGE_CHANNEL_STATE_MERGE,    /*! Channel is part of a bridge merge operation */
 };
 
 /*! \brief Flags used for bridge features */

Modified: team/file/bridging/main/bridging.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/bridging.c?view=diff&rev=92043&r1=92042&r2=92043
==============================================================================
--- team/file/bridging/main/bridging.c (original)
+++ team/file/bridging/main/bridging.c Sun Dec  9 17:00:00 2007
@@ -645,6 +645,16 @@
 			bridge_channel_join_multithreaded(bridge, bridge_channel);
 		else
 			bridge_channel_join_singlethreaded(bridge, bridge_channel);
+		/* If the above exited because of a merge operation update our own reference to the new bridge and go back to waiting */
+		if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_MERGE) {
+			struct ast_bridge *old_bridge = bridge;
+			/* This is sort of crazy but basically the old bridge can't go away yet and we still have a lock on it, we can therefore update our own reference to point to the new bridge, give up the lock on the old bridge, and decrement the channel count on the old bridge. Once every other channel does this as well the old bridge can be destroyed and all will be well. */
+			bridge = bridge_channel->chan->bridge;
+			ast_mutex_unlock(&old_bridge->lock);
+			ast_atomic_fetchadd_int(&old_bridge->num, -1);
+			ast_mutex_lock(&bridge->lock);
+			bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
+		}
 	}
 
 	/* If the bridge technology wants notification that this channel is leaving the bridge, give it it */
@@ -939,7 +949,7 @@
  */
 int ast_bridge_merge(struct ast_bridge *bridge0, struct ast_bridge *bridge1)
 {
-//	struct ast_bridge_channel *bridge_channel = NULL;
+	struct ast_bridge_channel *bridge_channel = NULL;
 
 	ast_mutex_lock(&bridge0->lock);
 
@@ -984,7 +994,33 @@
 		ast_debug(1, "Reacquired lock on bridge %p, now performing merge to %p\n", bridge1, bridge0);
 	}
 
-	/* TODO: Move channels from bridge1 to bridge0 _SAFELY_ */
+	/* Move channels from bridge1 to bridge0 */
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&bridge1->channels, bridge_channel, list) {
+		/* Tell the old bridge they are leaving */
+		if (bridge1->technology->leave) {
+			ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
+			if (bridge1->technology->leave(bridge1, bridge_channel))
+			    ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
+		}
+		/* Now actually remove them from the list, but don't decrement the channel count... this is important */
+		AST_LIST_REMOVE_CURRENT(list);
+		/* Change the state to merge. This tells the bridged channel to update their own bridge pointer to the new bridge and decrement the channel count. */
+		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_MERGE);
+		/* Now make this channel compatible with the new bridge */
+		bridge_make_compatible(bridge0, bridge_channel);
+		/* Update the bridged channel to point to the new bridge */
+		bridge_channel->chan->bridge = bridge0;
+		/* And add them in list and count wise */
+		AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, list);
+		ast_atomic_fetchadd_int(&bridge0->num, +1);
+		/* The last step is to simply tell the new bridge they are joining */
+		if (bridge0->technology->join) {
+			ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
+			if (bridge0->technology->join(bridge0, bridge_channel))
+				ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END;
 
 	ast_debug(1, "Bridge %p has been merged into bridge %p\n", bridge1, bridge0);
 




More information about the asterisk-commits mailing list