[asterisk-commits] rmudgett: trunk r396877 - in /trunk: include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Aug 16 15:48:15 CDT 2013


Author: rmudgett
Date: Fri Aug 16 15:48:13 2013
New Revision: 396877

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=396877
Log:
Fix CLI "bridge kick <bridge> <channel>" to check if the bridge needs dissolving.

SIP/foo -- Local;1==Local;2 -- .... -- Local;1==Local;2 -- SIP/bar
Kick a ;1 channel and the chain toward SIP/foo goes away.
Kick a ;2 channel and the chain toward SIP/bar goes away.

This can leave a local channel chain between the kicked ;1 and ;2 channels
that are orphaned until you manually request one of those channels to
hangup or request the bridge to dissolve.

* Added ast_bridge_kick() as a companion to ast_bridge_remove().  The
functional difference is that ast_bridge_kick() may dissolve the bridge as
a result of the channel leaving the bridge.

* Made CLI "bridge kick <bridge> <channel>" use ast_bridge_kick() instead
of ast_bridge_remove() so the bridge can dissolve if needed.

* Renamed bridge_channel_handle_hangup() to ast_bridge_channel_kick() and
made it accessible to other files.

Modified:
    trunk/include/asterisk/bridge.h
    trunk/include/asterisk/bridge_channel.h
    trunk/main/bridge.c
    trunk/main/bridge_channel.c

Modified: trunk/include/asterisk/bridge.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridge.h?view=diff&rev=396877&r1=396876&r2=396877
==============================================================================
--- trunk/include/asterisk/bridge.h (original)
+++ trunk/include/asterisk/bridge.h Fri Aug 16 15:48:13 2013
@@ -563,6 +563,37 @@
 int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan);
 
 /*!
+ * \brief Kick a channel from a bridge
+ *
+ * \param bridge Bridge that the channel is to be kicked from
+ * \param chan Channel to kick
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ *
+ * Example usage:
+ *
+ * \code
+ * ast_bridge_kick(bridge, chan);
+ * \endcode
+ *
+ * \details
+ * This kicks the channel pointed to by the chan pointer from
+ * the bridge pointed to by the bridge pointer and requests that
+ * it be hung up.  Control over the channel will NOT be given to
+ * the calling thread.
+ *
+ * \note The functional difference between ast_bridge_kick() and
+ * ast_bridge_remove() is that the bridge may dissolve as a
+ * result of the channel being kicked.
+ *
+ * \note This API call can be used on channels that were added
+ * to the bridge using both ast_bridge_join and
+ * ast_bridge_impart.
+ */
+int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan);
+
+/*!
  * \brief Merge two bridges together
  *
  * \param dst_bridge Destination bridge of merge.

Modified: trunk/include/asterisk/bridge_channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridge_channel.h?view=diff&rev=396877&r1=396876&r2=396877
==============================================================================
--- trunk/include/asterisk/bridge_channel.h (original)
+++ trunk/include/asterisk/bridge_channel.h Fri Aug 16 15:48:13 2013
@@ -583,6 +583,19 @@
 int ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid,
 	const char *parker_uuid, const char *app_data);
 
+/*!
+ * \brief Kick the channel out of the bridge.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel is being kicked or hungup.
+ *
+ * \note This is intended to be called by bridge hooks and the
+ * bridge channel thread.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: trunk/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge.c?view=diff&rev=396877&r1=396876&r2=396877
==============================================================================
--- trunk/main/bridge.c (original)
+++ trunk/main/bridge.c Fri Aug 16 15:48:13 2013
@@ -1679,6 +1679,31 @@
 	ast_bridge_unlock(bridge);
 
 	return 0;
+}
+
+static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
+{
+	ast_bridge_channel_kick(bridge_channel);
+}
+
+int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan)
+{
+	struct ast_bridge_channel *bridge_channel;
+	int res;
+
+	ast_bridge_lock(bridge);
+
+	/* Try to find the channel that we want to kick. */
+	if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
+		ast_bridge_unlock(bridge);
+		return -1;
+	}
+
+	res = ast_bridge_channel_queue_callback(bridge_channel, kick_it, NULL, 0);
+
+	ast_bridge_unlock(bridge);
+
+	return res;
 }
 
 /*!
@@ -4651,25 +4676,9 @@
 		return CLI_SUCCESS;
 	}
 
-/*
- * BUGBUG the CLI kick needs to get the bridge to decide if it should dissolve.
- *
- * Likely the best way to do this is to add a kick method.  The
- * basic bridge class can then decide to dissolve the bridge if
- * one of two channels is kicked.
- *
- * SIP/foo -- Local;1==Local;2 -- .... -- Local;1==Local;2 -- SIP/bar
- * Kick a ;1 channel and the chain toward SIP/foo goes away.
- * Kick a ;2 channel and the chain toward SIP/bar goes away.
- *
- * This can leave a local channel chain between the kicked ;1
- * and ;2 channels that are orphaned until you manually request
- * one of those channels to hangup or request the bridge to
- * dissolve.
- */
 	ast_cli(a->fd, "Kicking channel '%s' from bridge '%s'\n",
 		ast_channel_name(chan), a->argv[2]);
-	ast_bridge_remove(bridge, chan);
+	ast_bridge_kick(bridge, chan);
 
 	return CLI_SUCCESS;
 }

Modified: trunk/main/bridge_channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridge_channel.c?view=diff&rev=396877&r1=396876&r2=396877
==============================================================================
--- trunk/main/bridge_channel.c (original)
+++ trunk/main/bridge_channel.c Fri Aug 16 15:48:13 2013
@@ -263,16 +263,7 @@
 	}
 }
 
-/*!
-* \internal
-* \brief Handle bridge hangup event.
-* \since 12.0.0
-*
-* \param bridge_channel Which channel is hanging up.
-*
-* \return Nothing
-*/
-static void bridge_channel_handle_hangup(struct ast_bridge_channel *bridge_channel)
+void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel)
 {
 	struct ast_bridge_features *features = bridge_channel->features;
 	struct ast_bridge_hook *hook;
@@ -522,7 +513,7 @@
 	}
 	if (run_app_helper(bridge_channel->chan, app_name, S_OR(app_args, ""))) {
 		/* Break the bridge if the app returns non-zero. */
-		bridge_channel_handle_hangup(bridge_channel);
+		ast_bridge_channel_kick(bridge_channel);
 	}
 	if (moh_class) {
 		ast_bridge_channel_write_unhold(bridge_channel);
@@ -1100,7 +1091,7 @@
 		 * here if the hook did not already change the state.
 		 */
 		if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
-			bridge_channel_handle_hangup(bridge_channel);
+			ast_bridge_channel_kick(bridge_channel);
 		}
 	} else if (features->dtmf_passthrough) {
 		/* Stream any collected DTMF to the other channels. */
@@ -1213,7 +1204,7 @@
 		struct blind_transfer_data *blind_data)
 {
 	ast_async_goto(bridge_channel->chan, blind_data->context, blind_data->exten, 1);
-	bridge_channel_handle_hangup(bridge_channel);
+	ast_bridge_channel_kick(bridge_channel);
 }
 
 /*!
@@ -1229,7 +1220,7 @@
 	chan_target = ast_channel_get_by_name(target_chan_name);
 	if (!chan_target) {
 		/* Dang, it disappeared somehow */
-		bridge_channel_handle_hangup(bridge_channel);
+		ast_bridge_channel_kick(bridge_channel);
 		return;
 	}
 
@@ -1246,7 +1237,7 @@
 		/* Release the ref we tried to pass to ast_bridge_set_after_callback(). */
 		ast_channel_unref(chan_target);
 	}
-	bridge_channel_handle_hangup(bridge_channel);
+	ast_bridge_channel_kick(bridge_channel);
 }
 
 /*!
@@ -1674,14 +1665,14 @@
 	}
 
 	if (!frame) {
-		bridge_channel_handle_hangup(bridge_channel);
+		ast_bridge_channel_kick(bridge_channel);
 		return;
 	}
 	switch (frame->frametype) {
 	case AST_FRAME_CONTROL:
 		switch (frame->subclass.integer) {
 		case AST_CONTROL_HANGUP:
-			bridge_channel_handle_hangup(bridge_channel);
+			ast_bridge_channel_kick(bridge_channel);
 			ast_frfree(frame);
 			return;
 /* BUGBUG This is where incoming HOLD/UNHOLD memory should register.  Write UNHOLD into bridge when this channel is pulled. */




More information about the asterisk-commits mailing list