[svn-commits] file: branch file/bridging r90431 - in /team/file/bridging: apps/ main/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sat Dec 1 20:52:12 CST 2007


Author: file
Date: Sat Dec  1 20:52:11 2007
New Revision: 90431

URL: http://svn.digium.com/view/asterisk?view=rev&rev=90431
Log:
Add support for swapping and change app_bridgetest to do it. Basically this allows you to join a bridge or impart a channel on a bridge while simultaneously having another channel thrown out of the same bridge in the same operation.

Modified:
    team/file/bridging/apps/app_bridgetest.c
    team/file/bridging/main/bridging.c

Modified: team/file/bridging/apps/app_bridgetest.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/apps/app_bridgetest.c?view=diff&rev=90431&r1=90430&r2=90431
==============================================================================
--- team/file/bridging/apps/app_bridgetest.c (original)
+++ team/file/bridging/apps/app_bridgetest.c Sat Dec  1 20:52:11 2007
@@ -94,7 +94,9 @@
 	/* Put the dialed channel into the bridge via async */
 	ast_bridge_impart(bridge, ast_dial_answered(dial), NULL, NULL);
 
-	ast_bridge_join(bridge, chan, NULL, NULL);
+	ast_safe_sleep(chan, 1000);
+
+	ast_bridge_join(bridge, chan, ast_dial_answered(dial), NULL);
 	
 	ast_bridge_destroy(bridge);
 

Modified: team/file/bridging/main/bridging.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/bridging.c?view=diff&rev=90431&r1=90430&r2=90431
==============================================================================
--- team/file/bridging/main/bridging.c (original)
+++ team/file/bridging/main/bridging.c Sat Dec  1 20:52:11 2007
@@ -107,16 +107,25 @@
 	return current ? 0 : -1;
 }
 
+/*! \brief Helper function to find a bridge channel given a channel */
+static struct ast_bridge_channel *find_bridge_channel(struct ast_bridge *bridge, struct ast_channel *chan)
+{
+	struct ast_bridge_channel *bridge_channel = NULL;
+
+	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, list) {
+		if (bridge_channel->chan == chan)
+			break;
+	}
+
+	return bridge_channel;
+}
+
 /*! \brief Internal function to handle when a channel or bridge needs servicing */
 static void bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd)
 {
 	/* If no bridge channel has been provided and the actual channel has been provided find it */
-	if (chan && !bridge_channel) {
-		AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, list) {
-			if (bridge_channel->chan == chan)
-				break;
-		}
-	}
+	if (chan && !bridge_channel)
+		bridge_channel = find_bridge_channel(bridge, chan);
 
 	/* If a bridge channel with actual channel is present read a frame and handle it */
 	if (chan && bridge_channel) {
@@ -178,10 +187,6 @@
 			
 			ast_debug(1, "Rebuild of bridge array on %p went from %d to %d.\n", bridge, count, i);
 			count = i;
-			
-			if (!count)
-				break;
-
 			bridge->rebuild = 0;
 		} else if (count >= 2) {
 			int i = 0;
@@ -192,10 +197,14 @@
 		}
 
 		ast_mutex_unlock(&bridge->lock);
-		winner = ast_waitfor_n(cs, count, &to);
+		if (count)
+			winner = ast_waitfor_n(cs, count, &to);
+		else
+			usleep(1);
 		ast_mutex_lock(&bridge->lock);
-
-		bridge_handle_trip(bridge, NULL, winner, -1);
+		
+		if (count)
+			bridge_handle_trip(bridge, NULL, winner, -1);
 	}
 
 	return 0;
@@ -591,28 +600,28 @@
 {
 	int formats[2] = {bridge_channel->chan->readformat, bridge_channel->chan->writeformat};
 
-	/* Before we actually become part of this bridge make sure we are in the signalling wait state */
-	bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
-
-	/* Make the bridged channel part of the bridge */
+	/* Add ourselves in to the channels in the bridge */
 	AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, list);
 
 	/* Notify the bridge thread that a new bridged channel is part of the bridge, this will cause it to rebuild the bridge array */
 	bridge->rebuild = 1;
 
-	/* If smart bridging is enabled perform the operation to see if the underlying bridge technology needs to change */
-	if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART))
-		smart_bridge_operation(bridge, bridge_channel, bridge->num);
-
-	/* Of course if this is the first channel we actually have to create the bridge thread if the technology wants it */
-	if ((bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
-		if ((bridge->thread == AST_PTHREADT_NULL) && (ast_pthread_create(&bridge->thread, NULL, bridge_thread, bridge))) {
-			ast_debug(1, "Failed to create bridge thread for %p\n", bridge);
-			return -1;
-		} else {
-			ast_debug(1, "Poked thread servicing bridge %p\n", bridge);
-			/* Poke the bridge out of it's poll if there */
-			pthread_kill(bridge->thread, SIGURG);
+	/* If this channel is part of a swap operation don't bother optimizing or starting a thread, it doesn't matter */
+	if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_SWAP) {
+		/* If smart bridging is enabled perform the operation to see if the underlying bridge technology needs to change */
+		if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART))
+			smart_bridge_operation(bridge, bridge_channel, bridge->num);
+		
+		/* Of course if this is the first channel we actually have to create the bridge thread if the technology wants it */
+		if ((bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
+			if ((bridge->thread == AST_PTHREADT_NULL) && (ast_pthread_create(&bridge->thread, NULL, bridge_thread, bridge))) {
+				ast_debug(1, "Failed to create bridge thread for %p\n", bridge);
+				return -1;
+			} else {
+				ast_debug(1, "Poked thread servicing bridge %p\n", bridge);
+				/* Poke the bridge out of it's poll if there */
+				pthread_kill(bridge->thread, SIGURG);
+			}
 		}
 	}
 
@@ -625,6 +634,9 @@
 		if (bridge->technology->join(bridge, bridge_channel))
 			ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge->technology->name, bridge_channel, bridge);
 	}
+
+	/* Before entering ensure the state is set to wait to begin with */
+	bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
 
 	/* Pass ourselves off to our respective threading model */
 	while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
@@ -641,12 +653,15 @@
 			ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge->technology->name, bridge_channel, bridge);
 	}
 
-	/* Remove ourselves from the bridge */
-	AST_LIST_REMOVE(&bridge->channels, bridge_channel, list);
-
-	/* And for my last trick... perform the smart bridge operation yet again */
-	if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART))
-		smart_bridge_operation(bridge, NULL, bridge->num-1);
+	/* If this channel is exiting the bridge in a swap state then we need not remove them or perform the smart bridge operation, it doesn't matter */
+	if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_SWAP) {
+		/* Remove ourselves from the bridge */
+		AST_LIST_REMOVE(&bridge->channels, bridge_channel, list);
+		
+		/* And for my last trick... perform the smart bridge operation yet again */
+		if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART))
+			smart_bridge_operation(bridge, NULL, bridge->num-1);
+	}
 
 	/* Restore original formats if need be */
 	if (bridge_channel->chan->readformat != formats[0]) {
@@ -698,6 +713,22 @@
 
 	/* Boom, record the bridge this channel is part of */
 	chan->bridge = bridge;
+
+	/* If this is being performed as a swap operation look for the other channel and set both up as swap */
+	if (swap) {
+		struct ast_bridge_channel *swap_channel = NULL;
+		if ((swap_channel = find_bridge_channel(bridge, swap))) {
+			ast_debug(1, "Removing bridge channel %p from bridge %p and setting it to a swap state\n", swap_channel, bridge);
+			AST_LIST_REMOVE(&bridge->channels, swap_channel, list);
+			ast_bridge_change_state(swap_channel, AST_BRIDGE_CHANNEL_STATE_SWAP);
+			bridge_channel.state = AST_BRIDGE_CHANNEL_STATE_SWAP;
+			/* We purposely unlock here to give time for the above to happen */
+			ast_debug(1, "Releasing bridge lock on %p to ensure swap operation\n", bridge);
+			ast_mutex_unlock(&bridge->lock);
+			usleep(1);
+			ast_mutex_lock(&bridge->lock);
+		}
+	}
 
 	/* Off to the bridge we go... */
 	state = bridge_channel_join(bridge, &bridge_channel);
@@ -777,8 +808,30 @@
 	/* Setup synchronization for our thread */
 	ast_cond_init(&bridge_channel->cond, NULL);
 
+	/* Lock the bridge as we are potentially going to muck with it now */
+	ast_mutex_lock(&bridge->lock);
+
 	/* Before we actually hand over this channel to the other thread increment the bridge channel number so the bridge can't go away */
 	ast_atomic_fetchadd_int(&bridge->num, +1);
+
+	/* If this is being performed as a swap operation look for the other channel and set both up as swap */
+	if (swap) {
+		struct ast_bridge_channel *swap_channel = NULL;
+		if ((swap_channel = find_bridge_channel(bridge, swap))) {
+			ast_debug(1, "Removing bridge channel %p from bridge %p and setting it to a swap state\n", swap_channel, bridge);
+			AST_LIST_REMOVE(&bridge->channels, swap_channel, list);
+			ast_bridge_change_state(swap_channel, AST_BRIDGE_CHANNEL_STATE_SWAP);
+			bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_SWAP;
+			/* We purposely unlock here to give it time for the above to happen */
+			ast_debug(1, "Releasing bridge lock on %p to ensure swap operation\n", bridge);
+			ast_mutex_unlock(&bridge->lock);
+			usleep(1);
+			ast_mutex_lock(&bridge->lock);
+		}
+	}
+
+	/* All done mucking about */
+	ast_mutex_unlock(&bridge->lock);
 
 	/* Now we can create the thread to handle this channel and be done with things */
 	if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
@@ -804,13 +857,7 @@
 	ast_mutex_lock(&bridge->lock);
 
 	/* Look for channel in the bridge */
-	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, list) {
-		if (bridge_channel->chan == chan)
-			break;
-	}
-
-	/* If one does not exist we can't very well depart it */
-	if (!bridge_channel) {
+	if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
 		ast_mutex_unlock(&bridge->lock);
 		return -1;
 	}




More information about the svn-commits mailing list