[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r384483 - in /team/rmudgett/bridge_pha...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 1 12:56:51 CDT 2013


Author: rmudgett
Date: Mon Apr  1 12:56:47 2013
New Revision: 384483

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384483
Log:
* Made pulling a channel check if the bridge needs to be dissolved.

* Add AST_BRIDGE_FLAG_DISSOLVE_EMPTY support.

* Add dissolving bridge method to eliminate external references to a
bridge that is being dissolved.

* Fix ast_channel bridg_channel pointer after a DTMF atxfer.

Modified:
    team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c
    team/rmudgett/bridge_phase/include/asterisk/bridging.h
    team/rmudgett/bridge_phase/main/bridging.c
    team/rmudgett/bridge_phase/main/features.c

Modified: team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c?view=diff&rev=384483&r1=384482&r2=384483
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c Mon Apr  1 12:56:47 2013
@@ -329,6 +329,18 @@
 	 */
 	ast_bridge_join(attended_bridge, bridge_channel->chan, NULL, &caller_features, NULL, 0);
 
+/*
+ * BUGBUG there is a small window where the channel does not point to the bridge_channel.
+ *
+ * This window is expected to go away when atxfer is redesigned
+ * to fully support existing functionality.  There will be one
+ * and only one ast_bridge_channel structure per channel.
+ */
+	/* Point the channel back to the original bridge_channel. */
+	ast_channel_lock(bridge_channel->chan);
+	ast_channel_internal_bridge_channel_set(bridge_channel->chan, bridge_channel);
+	ast_channel_unlock(bridge_channel->chan);
+
 	/* Wait for peer thread to exit bridge and die. */
 	if (!ast_autoservice_start(bridge_channel->chan)) {
 		ast_bridge_depart(peer);

Modified: team/rmudgett/bridge_phase/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/bridging.h?view=diff&rev=384483&r1=384482&r2=384483
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/bridging.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/bridging.h Mon Apr  1 12:56:47 2013
@@ -246,6 +246,19 @@
 typedef void (*ast_bridge_destructor_fn)(struct ast_bridge *self);
 
 /*!
+ * \brief The bridge is being dissolved.
+ *
+ * \param self Bridge to operate upon.
+ *
+ * \details
+ * The bridge is being dissolved.  Remove any external
+ * references to the bridge so it can be destroyed.
+ *
+ * \return Nothing
+ */
+typedef void (*ast_bridge_dissolving_fn)(struct ast_bridge *self);
+
+/*!
  * \brief Can this channel be pushed into the bridge.
  *
  * \param self Bridge to operate upon.
@@ -322,6 +335,8 @@
 	const char *name;
 	/*! Destroy the bridge. */
 	ast_bridge_destructor_fn destroy;
+	/*! The bridge is being dissolved.  Remove any references to the bridge. */
+	ast_bridge_dissolving_fn dissolving;
 	/*! TRUE if can push the bridge channel into the bridge. */
 	ast_bridge_can_push_channel_fn can_push;
 	/*! Push the bridge channel into the bridge. */

Modified: team/rmudgett/bridge_phase/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging.c?view=diff&rev=384483&r1=384482&r2=384483
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging.c (original)
+++ team/rmudgett/bridge_phase/main/bridging.c Mon Apr  1 12:56:47 2013
@@ -379,6 +379,82 @@
 
 /*!
  * \internal
+ * \brief Dissolve the bridge.
+ * \since 12.0.0
+ *
+ * \param bridge Bridge to eject all channels
+ *
+ * \details
+ * Force out all channels that are not already going out of the
+ * bridge.  Any new channels joining will leave immediately.
+ *
+ * \note On entry, bridge is already locked.
+ *
+ * \return Nothing
+ */
+static void bridge_dissolve(struct ast_bridge *bridge)
+{
+	struct ast_bridge_channel *bridge_channel;
+
+	if (bridge->dissolved) {
+		return;
+	}
+	bridge->dissolved = 1;
+
+	ast_debug(1, "Bridge %s: dissolving bridge\n", bridge->uniqueid);
+
+/* BUGBUG need a cause code on the bridge for the later ejected channels. */
+	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
+		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+	}
+	bridge->v_table->dissolving(bridge);
+}
+
+/*!
+ * \internal
+ * \brief Check if a bridge should dissolve and do it.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Channel causing the check.
+ *
+ * \note On entry, bridge_channel->bridge is already locked.
+ *
+ * \return Nothing
+ */
+static void bridge_dissolve_check(struct ast_bridge_channel *bridge_channel)
+{
+	struct ast_bridge *bridge = bridge_channel->bridge;
+
+	if (bridge->dissolved) {
+		return;
+	}
+
+	if (!bridge->num_channels
+		&& ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_EMPTY)) {
+		/* Last channel leaving the bridge turns off the lights. */
+		bridge_dissolve(bridge);
+		return;
+	}
+
+	switch (bridge_channel->state) {
+	case AST_BRIDGE_CHANNEL_STATE_END:
+		/* Do we need to dissolve the bridge because this channel hung up? */
+		if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_HANGUP)
+			|| (bridge_channel->features
+				&& bridge_channel->features->usable
+				&& ast_test_flag(&bridge_channel->features->feature_flags,
+					AST_BRIDGE_FLAG_DISSOLVE_HANGUP))) {
+			bridge_dissolve(bridge);
+			return;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+/*!
+ * \internal
  * \brief Pull the bridge channel out of its current bridge.
  * \since 12.0.0
  *
@@ -420,6 +496,8 @@
 	AST_LIST_REMOVE(&bridge->channels, bridge_channel, entry);
 	bridge->v_table->pull(bridge, bridge_channel);
 
+	bridge_dissolve_check(bridge_channel);
+
 	bridge->reconfigured = 1;
 }
 
@@ -492,53 +570,6 @@
 	}
 
 	bridge->reconfigured = 1;
-}
-
-/*!
- * \internal
- * \brief Force out all channels that are not already going out of the bridge.
- * \since 12.0.0
- *
- * \param bridge Bridge to eject all channels
- *
- * \note On entry, bridge is already locked.
- *
- * \return Nothing
- */
-static void bridge_force_out_all(struct ast_bridge *bridge)
-{
-	struct ast_bridge_channel *bridge_channel;
-
-	bridge->dissolved = 1;
-
-/* BUGBUG need a cause code on the bridge for the later ejected channels. */
-	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
-		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
-	}
-}
-
-/*!
- * \internal
- * \brief Check if a bridge should dissolve and then do it.
- * \since 12.0.0
- *
- * \param bridge_channel Channel causing the check.
- *
- * \note On entry, bridge_channel->bridge is already locked.
- *
- * \return Nothing
- */
-static void bridge_check_dissolve(struct ast_bridge_channel *bridge_channel)
-{
-	if (!ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_HANGUP)
-		&& (!bridge_channel->features
-			|| !bridge_channel->features->usable
-			|| !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE_HANGUP))) {
-		return;
-	}
-
-	ast_debug(1, "Bridge %s: dissolving bridge\n", bridge_channel->bridge->uniqueid);
-	bridge_force_out_all(bridge_channel->bridge);
 }
 
 /*! \brief Internal function to handle DTMF from a channel */
@@ -929,6 +960,7 @@
 	if (!v_table
 		|| !v_table->name
 		|| !v_table->destroy
+		|| !v_table->dissolving
 		|| !v_table->can_push
 		|| !v_table->push
 		|| !v_table->pull
@@ -1007,6 +1039,21 @@
 
 /*!
  * \internal
+ * \brief The bridge is being dissolved.
+ * \since 12.0.0
+ *
+ * \param self Bridge to operate upon.
+ *
+ * \return Nothing
+ */
+static void bridge_base_dissolving(struct ast_bridge *self)
+{
+/* BUGBUG unlink from the global bridges container. */
+	/*! \todo BUGBUG bridge_base_dissolving() not written */
+}
+
+/*!
+ * \internal
  * \brief ast_bridge base can_push method.
  * \since 12.0.0
  *
@@ -1081,6 +1128,7 @@
 struct ast_bridge_methods ast_bridge_base_v_table = {
 	.name = "base",
 	.destroy = bridge_base_destroy,
+	.dissolving = bridge_base_dissolving,
 	.can_push = bridge_base_can_push,
 	.push = bridge_base_push,
 	.pull = bridge_base_pull,
@@ -1113,7 +1161,7 @@
 {
 	ast_debug(1, "Bridge %s: telling all channels to leave the party\n", bridge->uniqueid);
 	ast_bridge_lock(bridge);
-	bridge_force_out_all(bridge);
+	bridge_dissolve(bridge);
 	ast_bridge_unlock(bridge);
 
 	ao2_ref(bridge, -1);
@@ -1388,8 +1436,8 @@
 	bridge->reconfigured = 0;
 	if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART)
 		&& smart_bridge_operation(bridge)) {
-		/* Smart bridge failed.  Dissolve the bridge. */
-		bridge_force_out_all(bridge);
+		/* Smart bridge failed. */
+		bridge_dissolve(bridge);
 		return;
 	}
 	bridge_complete_join(bridge);
@@ -1975,15 +2023,6 @@
 	ast_bridge_channel_pull(bridge_channel);
 	ast_bridge_reconfigured(bridge_channel->bridge);
 
-	/* See if we need to dissolve the bridge itself if they hung up */
-	switch (bridge_channel->state) {
-	case AST_BRIDGE_CHANNEL_STATE_END:
-		bridge_check_dissolve(bridge_channel);
-		break;
-	default:
-		break;
-	}
-
 	ast_bridge_unlock(bridge_channel->bridge);
 
 	/* Flush any unhandled wr_queue frames. */

Modified: team/rmudgett/bridge_phase/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/features.c?view=diff&rev=384483&r1=384482&r2=384483
==============================================================================
--- team/rmudgett/bridge_phase/main/features.c (original)
+++ team/rmudgett/bridge_phase/main/features.c Mon Apr  1 12:56:47 2013
@@ -4542,7 +4542,7 @@
 /* BUGBUG need to create the basic bridge class that will manage the DTMF feature hooks. */
 	bridge = ast_bridge_base_new(
 		AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_MULTIMIX,
-		AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_SMART);
+		AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_DISSOLVE_EMPTY | AST_BRIDGE_FLAG_SMART);
 	if (!bridge) {
 		ast_bridge_features_destroy(peer_features);
 		ast_bridge_features_cleanup(&chan_features);




More information about the asterisk-commits mailing list