[asterisk-commits] rmudgett: branch group/bridge_construction r382467 - in /team/group/bridge_co...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Mar 5 14:01:10 CST 2013
Author: rmudgett
Date: Tue Mar 5 14:01:06 2013
New Revision: 382467
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=382467
Log:
Make ast_bridge_depart() channels able to move to other bridges.
Code is simplified as a bonus.
Modified:
team/group/bridge_construction/apps/app_confbridge.c
team/group/bridge_construction/bridges/bridge_builtin_features.c
team/group/bridge_construction/include/asterisk/bridging.h
team/group/bridge_construction/include/asterisk/channel.h
team/group/bridge_construction/main/bridging.c
team/group/bridge_construction/main/channel_internal_api.c
Modified: team/group/bridge_construction/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/apps/app_confbridge.c?view=diff&rev=382467&r1=382466&r2=382467
==============================================================================
--- team/group/bridge_construction/apps/app_confbridge.c (original)
+++ team/group/bridge_construction/apps/app_confbridge.c Tue Mar 5 14:01:06 2013
@@ -1490,7 +1490,7 @@
}
ast_debug(1, "Departing underlying channel '%s' from bridge '%p'\n", ast_channel_name(underlying_channel), conference_bridge->bridge);
- ast_bridge_depart(conference_bridge->bridge, underlying_channel);
+ ast_bridge_depart(underlying_channel);
ast_mutex_unlock(&conference_bridge->playback_lock);
Modified: team/group/bridge_construction/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/bridges/bridge_builtin_features.c?view=diff&rev=382467&r1=382466&r2=382467
==============================================================================
--- team/group/bridge_construction/bridges/bridge_builtin_features.c (original)
+++ team/group/bridge_construction/bridges/bridge_builtin_features.c Tue Mar 5 14:01:06 2013
@@ -283,10 +283,10 @@
/* Wait for peer thread to exit bridge and die. */
if (!ast_autoservice_start(bridge_channel->chan)) {
- ast_bridge_depart(attended_bridge, peer);
+ ast_bridge_depart(peer);
ast_autoservice_stop(bridge_channel->chan);
} else {
- ast_bridge_depart(attended_bridge, peer);
+ ast_bridge_depart(peer);
}
/* Now that all channels are out of it we can destroy the bridge and the feature structures */
Modified: team/group/bridge_construction/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/include/asterisk/bridging.h?view=diff&rev=382467&r1=382466&r2=382467
==============================================================================
--- team/group/bridge_construction/include/asterisk/bridging.h (original)
+++ team/group/bridge_construction/include/asterisk/bridging.h Tue Mar 5 14:01:06 2013
@@ -91,8 +91,6 @@
AST_BRIDGE_CHANNEL_STATE_HANGUP,
/*! Bridged channel was ast_bridge_depart() from the bridge without being hung up */
AST_BRIDGE_CHANNEL_STATE_DEPART,
- /*! Bridged channel was ast_bridge_depart() from the bridge during AST_BRIDGE_CHANNEL_STATE_END */
- AST_BRIDGE_CHANNEL_STATE_DEPART_END,
};
/*! \brief Return values for bridge technology write function */
@@ -152,7 +150,7 @@
unsigned int just_joined:1;
/*! TRUE if the channel is suspended from the bridge. */
unsigned int suspended:1;
- /*! TRUE if the imparted channel must wait for an explicit depart from the bridge to reclaim the channel. */
+ /*! TRUE if the channel must wait for an ast_bridge_depart to reclaim the channel. */
unsigned int depart_wait:1;
/*! Features structure for features that are specific to this channel */
struct ast_bridge_features *features;
@@ -271,8 +269,6 @@
struct ast_callid *callid;
/*! Linked list of channels participating in the bridge */
AST_LIST_HEAD_NOLOCK(, ast_bridge_channel) channels;
- /*! Linked list of channels removed from the bridge and waiting to be departed. */
- AST_LIST_HEAD_NOLOCK(, ast_bridge_channel) depart_wait;
/*! Queue of actions to perform on the bridge. */
AST_LIST_HEAD_NOLOCK(, ast_frame) action_queue;
};
@@ -447,7 +443,6 @@
/*!
* \brief Depart a channel from a bridge
*
- * \param bridge Bridge to depart from
* \param chan Channel to depart
*
* \retval 0 on success
@@ -456,17 +451,17 @@
* Example usage:
*
* \code
- * ast_bridge_depart(bridge, chan);
- * \endcode
- *
- * This removes the channel pointed to by the chan pointer from the bridge
- * pointed to by the bridge pointer and gives control to the calling thread.
+ * ast_bridge_depart(chan);
+ * \endcode
+ *
+ * This removes the channel pointed to by the chan pointer from any bridge
+ * it may be in and gives control to the calling thread.
* This does not hang up the channel.
*
* \note This API call can only be used on channels that were added to the bridge
* using the ast_bridge_impart API call with the independent flag FALSE.
*/
-int ast_bridge_depart(struct ast_bridge *bridge, struct ast_channel *chan);
+int ast_bridge_depart(struct ast_channel *chan);
/*!
* \brief Remove a channel from a bridge
Modified: team/group/bridge_construction/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/include/asterisk/channel.h?view=diff&rev=382467&r1=382466&r2=382467
==============================================================================
--- team/group/bridge_construction/include/asterisk/channel.h (original)
+++ team/group/bridge_construction/include/asterisk/channel.h Tue Mar 5 14:01:06 2013
@@ -4032,6 +4032,9 @@
struct ast_bridge *ast_channel_internal_bridge(const struct ast_channel *chan);
void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value);
+struct ast_bridge_channel *ast_channel_internal_bridge_channel(const struct ast_channel *chan);
+void ast_channel_internal_bridge_channel_set(struct ast_channel *chan, struct ast_bridge_channel *value);
+
struct ast_channel *ast_channel_internal_bridged_channel(const struct ast_channel *chan);
void ast_channel_internal_bridged_channel_set(struct ast_channel *chan, struct ast_channel *value);
Modified: team/group/bridge_construction/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/main/bridging.c?view=diff&rev=382467&r1=382466&r2=382467
==============================================================================
--- team/group/bridge_construction/main/bridging.c (original)
+++ team/group/bridge_construction/main/bridging.c Tue Mar 5 14:01:06 2013
@@ -934,7 +934,6 @@
/* There should not be any channels left in the bridge. */
ast_assert(AST_LIST_EMPTY(&bridge->channels));
- ast_assert(AST_LIST_EMPTY(&bridge->depart_wait));
ao2_lock(bridge);
if (bridge->thread != AST_PTHREADT_NULL) {
@@ -1629,9 +1628,6 @@
ast_format_copy(&formats[0], ast_channel_readformat(bridge_channel->chan));
ast_format_copy(&formats[1], ast_channel_writeformat(bridge_channel->chan));
-
- /* Record the thread that will be the owner of us */
- bridge_channel->thread = pthread_self();
ast_debug(1, "Joining bridge channel %p(%s) to bridge %p\n",
bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->bridge);
@@ -1712,23 +1708,10 @@
/* See if we need to dissolve the bridge itself if they hung up */
switch (bridge_channel->state) {
case AST_BRIDGE_CHANNEL_STATE_END:
- case AST_BRIDGE_CHANNEL_STATE_DEPART_END:
bridge_check_dissolve(bridge_channel->bridge, bridge_channel);
break;
default:
break;
- }
-
- if (bridge_channel->depart_wait) {
- switch (bridge_channel->state) {
- case AST_BRIDGE_CHANNEL_STATE_DEPART:
- case AST_BRIDGE_CHANNEL_STATE_DEPART_END:
- break;
- default:
- /* Put the channel into the ast_bridge_depart wait list. */
- AST_LIST_INSERT_TAIL(&bridge_channel->bridge->depart_wait, bridge_channel, entry);
- break;
- }
}
ao2_unlock(bridge_channel->bridge);
@@ -2117,6 +2100,8 @@
}
/* Initialize various other elements of the bridge channel structure that we can't do above */
+ ast_channel_internal_bridge_channel_set(chan, bridge_channel);
+ bridge_channel->thread = pthread_self();
bridge_channel->chan = chan;
bridge_channel->swap = swap;
bridge_channel->features = features;
@@ -2125,6 +2110,7 @@
state = bridge_channel->state;
/* Cleanup all the data in the bridge channel after it leaves the bridge. */
+ ast_channel_internal_bridge_channel_set(chan, NULL);
bridge_channel->chan = NULL;
bridge_channel->swap = NULL;
bridge_channel->features = NULL;
@@ -2180,6 +2166,7 @@
chan = bridge_channel->chan;
/* cleanup */
+ ast_channel_internal_bridge_channel_set(bridge_channel->chan, NULL);
bridge_channel->chan = NULL;
bridge_channel->swap = NULL;
ast_bridge_features_destroy(bridge_channel->features);
@@ -2187,19 +2174,6 @@
ao2_ref(bridge_channel, -1);
- switch (state) {
- case AST_BRIDGE_CHANNEL_STATE_DEPART:
- case AST_BRIDGE_CHANNEL_STATE_DEPART_END:
- ast_log(LOG_ERROR, "Independently imparted channel was departed: %s\n",
- ast_channel_name(chan));
- ast_assert(0);
- /* fallthrough */
- case AST_BRIDGE_CHANNEL_STATE_HANGUP:
- case AST_BRIDGE_CHANNEL_STATE_END:
- default:
- break;
- }
-
ast_after_bridge_goto_run(chan);
return NULL;
}
@@ -2216,6 +2190,7 @@
}
/* Setup various parameters */
+ ast_channel_internal_bridge_channel_set(chan, bridge_channel);
bridge_channel->chan = chan;
bridge_channel->swap = swap;
bridge_channel->features = features;
@@ -2238,6 +2213,7 @@
}
if (res) {
/* cleanup */
+ ast_channel_internal_bridge_channel_set(chan, NULL);
bridge_channel->chan = NULL;
bridge_channel->swap = NULL;
ast_bridge_features_destroy(bridge_channel->features);
@@ -2250,66 +2226,41 @@
return 0;
}
-int ast_bridge_depart(struct ast_bridge *bridge, struct ast_channel *chan)
+int ast_bridge_depart(struct ast_channel *chan)
{
struct ast_bridge_channel *bridge_channel;
- pthread_t thread;
-
- ao2_lock(bridge);
-
- do {
- /* Try to find the channel that we want to depart */
- bridge_channel = find_bridge_channel(bridge, chan);
- if (bridge_channel) {
- /* Channel is still in the bridge. */
- if (!bridge_channel->depart_wait) {
- ast_log(LOG_ERROR, "Bridged channel cannot be departed: %s\n",
- ast_channel_name(bridge_channel->chan));
- ao2_unlock(bridge);
- return -1;
- }
- ao2_lock(bridge_channel);
- switch (bridge_channel->state) {
- case AST_BRIDGE_CHANNEL_STATE_END:
- ast_bridge_change_state_nolock(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART_END);
- break;
- case AST_BRIDGE_CHANNEL_STATE_DEPART:
- case AST_BRIDGE_CHANNEL_STATE_DEPART_END:
- /*
- * Should never happen. It likely means that
- * ast_bridge_depart() is called by two threads for the same
- * channel.
- */
- ast_assert(0);
- break;
- default:
- ast_bridge_change_state_nolock(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
- break;
- }
- ao2_unlock(bridge_channel);
- break;
- }
-
- /* Was the channel already removed from the bridge? */
- AST_LIST_TRAVERSE_SAFE_BEGIN(&bridge->depart_wait, bridge_channel, entry) {
- if (bridge_channel->chan == chan) {
- AST_LIST_REMOVE_CURRENT(entry);
- break;
- }
- }
- AST_LIST_TRAVERSE_SAFE_END;
- if (!bridge_channel) {
- /* Channel does not exist. */
- ao2_unlock(bridge);
- return -1;
- }
- } while (0);
- thread = bridge_channel->thread;
-
- ao2_unlock(bridge);
+
+ bridge_channel = ast_channel_internal_bridge_channel(chan);
+ if (!bridge_channel || !bridge_channel->depart_wait) {
+ ast_log(LOG_ERROR, "Channel %s cannot be departed.\n",
+ ast_channel_name(chan));
+ /*
+ * Should never happen. It likely means that
+ * ast_bridge_depart() is called by two threads for the same
+ * channel, the channel was never imparted to be departed, or it
+ * has already been departed.
+ */
+ ast_assert(0);
+ return -1;
+ }
+
+ /* We are claiming the reference held by the depart thread. */
+
+ ao2_lock(bridge_channel);
+ switch (bridge_channel->state) {
+ case AST_BRIDGE_CHANNEL_STATE_WAIT:
+ ast_bridge_change_state_nolock(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+ break;
+ default:
+ /* The channel is already leaving the bridge. */
+ break;
+ }
+ ao2_unlock(bridge_channel);
/* Wait for the depart thread to die */
- pthread_join(thread, NULL);
+ pthread_join(bridge_channel->thread, NULL);
+
+ ast_channel_internal_bridge_channel_set(chan, NULL);
/* We can get rid of the bridge_channel after the depart thread has died. */
ao2_ref(bridge_channel, -1);
Modified: team/group/bridge_construction/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/main/channel_internal_api.c?view=diff&rev=382467&r1=382466&r2=382467
==============================================================================
--- team/group/bridge_construction/main/channel_internal_api.c (original)
+++ team/group/bridge_construction/main/channel_internal_api.c Tue Mar 5 14:01:06 2013
@@ -188,6 +188,7 @@
/* BUGBUG the bridge pointer must change to an ast_channel_bridge pointer because it will never change while the channel is in the bridging system whereas the bridge could change. */
struct ast_bridge *bridge; /*!< Bridge this channel is participating in */
+ struct ast_bridge_channel *bridge_channel;/*!< The bridge_channel this channel is linked with. */
struct ast_timer *timer; /*!< timer object that provided timingfd */
char context[AST_MAX_CONTEXT]; /*!< Dialplan: Current extension context */
@@ -1252,6 +1253,15 @@
chan->bridge = value;
}
+struct ast_bridge_channel *ast_channel_internal_bridge_channel(const struct ast_channel *chan)
+{
+ return chan->bridge_channel;
+}
+void ast_channel_internal_bridge_channel_set(struct ast_channel *chan, struct ast_bridge_channel *value)
+{
+ chan->bridge_channel = value;
+}
+
struct ast_channel *ast_channel_internal_bridged_channel(const struct ast_channel *chan)
{
return chan->bridged_channel;
More information about the asterisk-commits
mailing list