[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