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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Mar 6 10:47:24 CST 2008


Author: file
Date: Thu Mar  6 10:47:24 2008
New Revision: 106394

URL: http://svn.digium.com/view/asterisk?view=rev&rev=106394
Log:
Add support for setting feature flags on a per-bridged channel basis. This is useful in the case of the attended transfer hook because we want to abort the transfer if the other party hangs up. This also fixes a bug where a channel that was leaving a bridge did not tell the bridge to rebuild, thus potentially leaving it's own channel pointer (which may be in valid) still being serviced.

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=106394&r1=106393&r2=106394
==============================================================================
--- team/file/bridging/include/asterisk/bridging.h (original)
+++ team/file/bridging/include/asterisk/bridging.h Thu Mar  6 10:47:24 2008
@@ -109,6 +109,7 @@
 
 struct ast_bridge_features {
 	AST_LIST_HEAD_NOLOCK(, ast_bridge_features_hook) hooks;                   /*! Attached hooks */
+	struct ast_flags feature_flags;                                           /*! Feature flags */
 	int usable:1;                                                             /*! Whether this should be considered usable or not */
 };
 
@@ -236,6 +237,13 @@
  */
 int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf);
 
+/*! \brief Set a flag on a bridge features structure
+ * \param features Bridge features structure
+ * \param flag Flag to enable
+ * \return Returns 0 on success, -1 on failure
+ */
+int ast_bridge_features_set_flag(struct ast_bridge_features *features, int flag);
+
 /*! \brief Initialize bridge features structure
  * \param features Bridge featues structure
  * \return Returns 0 on success, -1 on failure

Modified: team/file/bridging/main/bridging.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/bridging.c?view=diff&rev=106394&r1=106393&r2=106394
==============================================================================
--- team/file/bridging/main/bridging.c (original)
+++ team/file/bridging/main/bridging.c Thu Mar  6 10:47:24 2008
@@ -127,18 +127,18 @@
 }
 
 /*! \brief Internal function to see whether a bridge should dissolve, and if so do it */
-static void bridge_check_dissolve(struct ast_bridge *bridge)
-{
-	struct ast_bridge_channel *bridge_channel = NULL;
-
-	if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE))
+static void bridge_check_dissolve(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
+{
+	struct ast_bridge_channel *bridge_channel2 = NULL;
+
+	if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE) && (!bridge_channel->features || !bridge_channel->features->usable || !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE)))
 		return;
 
 	ast_debug(1, "Dissolving bridge %p\n", bridge);
 
-	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, list) {
-		if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_END && bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_DEPART)
-			ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
+	AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, list) {
+		if (bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_END && bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_DEPART)
+			ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
 	}
 
 	/* Since all the channels are going away let's go ahead and stop our on thread */
@@ -187,7 +187,7 @@
 			/* Signal the thread that is handling the bridged channel that it should be ended */
 			ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
 			/* Perform bridge dissolving stuff if needed */
-			bridge_check_dissolve(bridge);
+			bridge_check_dissolve(bridge, bridge_channel);
 		} else {
 			if (frame->frametype == AST_FRAME_DTMF_BEGIN)
 				frame = bridge_handle_dtmf(bridge, bridge_channel, frame);
@@ -828,6 +828,9 @@
 			smart_bridge_operation(bridge, NULL, bridge->num-1);
 	}
 
+	/* Queue a rebuild on the bridge since we left */
+	ast_bridge_rebuild(bridge);
+
 	/* Restore original formats if need be */
 	if (bridge_channel->chan->readformat != formats[0]) {
 		ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]);
@@ -1336,7 +1339,7 @@
 	char exten[AST_MAX_EXTENSION] = "";
 	struct ast_channel *chan = NULL;
 	struct ast_bridge *attended_bridge = NULL;
-	struct ast_bridge_features features;
+	struct ast_bridge_features caller_features, called_features;
 	enum ast_bridge_channel_state attended_bridge_result;
 
 	/* Grab the extension to transfer to */
@@ -1361,22 +1364,26 @@
 		return 0;
 	}
 
+	/* Setup our called features structure so that if they hang up we immediately get thrown out of the bridge */
+	ast_bridge_features_init(&called_features);
+	ast_bridge_features_set_flag(&called_features, AST_BRIDGE_FLAG_DISSOLVE);
+
 	/* This is how this is going down, we are imparting the channel we called above into this bridge first */
-	ast_bridge_impart(attended_bridge, chan, NULL, NULL);
+	ast_bridge_impart(attended_bridge, chan, NULL, &called_features);
 
 	/* Before we join setup a features structure with the hangup option, just in case they want to use DTMF */
-	ast_bridge_features_init(&features);
-	ast_bridge_features_enable(&features, AST_BRIDGE_BUILTIN_HANGUP, "*");
-	ast_bridge_features_hook(&features, "#", attended_threeway_transfer, NULL);
+	ast_bridge_features_init(&caller_features);
+	ast_bridge_features_enable(&caller_features, AST_BRIDGE_BUILTIN_HANGUP, "*");
+	ast_bridge_features_hook(&caller_features, "#", attended_threeway_transfer, NULL);
 
 	/* But for the caller we want to join the bridge in a blocking fashion so we don't spin around in this function doing nothing while waiting */
-	attended_bridge_result = ast_bridge_join(attended_bridge, bridge_channel->chan, NULL, &features);
-
-	/* Since the above returned the features structure is of no more use and just needs to be cleaned up, or else we leak memory and that makes me sad. */
-	ast_bridge_features_cleanup(&features);
+	attended_bridge_result = ast_bridge_join(attended_bridge, bridge_channel->chan, NULL, &caller_features);
+
+	/* Since the above returned the caller features structure is of no more use */
+	ast_bridge_features_cleanup(&caller_features);
 
 	/* Drop the channel we are transferring to out of the above bridge since it has ended */
-	if (!ast_bridge_depart(attended_bridge, chan)) {
+	if ((attended_bridge_result != AST_BRIDGE_CHANNEL_STATE_HANGUP) && !ast_bridge_depart(attended_bridge, chan)) {
 		/* If the user wants to turn this into a threeway transfer then do so, otherwise they take our place */
 		if (attended_bridge_result == AST_BRIDGE_CHANNEL_STATE_DEPART) {
 			/* We want to impart them upon the bridge and just have us return to it as normal */
@@ -1386,10 +1393,12 @@
 			ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
 		}
 	} else {
+		ast_stream_and_wait(bridge_channel->chan, "beep", AST_DIGIT_ANY);
 		bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
 	}
 
-	/* Now that all channels are out of it we can destroy the bridge */
+	/* Now that all channels are out of it we can destroy the bridge and the called features structure */
+	ast_bridge_features_cleanup(&called_features);
 	ast_bridge_destroy(attended_bridge);
 
 	return 0;
@@ -1402,7 +1411,7 @@
 	bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_END;
 	/* See if the bridge needs to dissolve away */
 	ast_mutex_lock(&bridge->lock);
-	bridge_check_dissolve(bridge);
+	bridge_check_dissolve(bridge, bridge_channel);
 	ast_mutex_unlock(&bridge->lock);
 	return 0;
 }
@@ -1439,6 +1448,18 @@
 	return ast_bridge_features_hook(features, dtmf, callback, NULL);
 }
 
+/*! \brief Set a flag on a bridge features structure
+ * \param features Bridge features structure
+ * \param flag Flag to enable
+ * \return Returns 0 on success, -1 on failure
+ */
+int ast_bridge_features_set_flag(struct ast_bridge_features *features, int flag)
+{
+	ast_set_flag(&features->feature_flags, flag);
+	features->usable = 1;
+	return 0;
+}
+
 /*! \brief Initialize bridge features structure
  * \param features Bridge featues structure
  * \return Returns 0 on success, -1 on failure




More information about the asterisk-commits mailing list