[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