[asterisk-commits] mmichelson: branch mmichelson/more_transfer r386945 - /team/mmichelson/more_t...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Apr 30 09:19:46 CDT 2013


Author: mmichelson
Date: Tue Apr 30 09:19:42 2013
New Revision: 386945

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386945
Log:
Refactor manager bridge action to be more bridge-y.

This makes use of the channel's current bridge disposition and
simply moves the channel if possible. Otherwise, the channel is
yanked and placed into the new bridge by force.

Currently, there are a couple of issues with this:

1) Refcounts are all over the place. I can probably get away with
a couple of well-placed RAII_VAR macros.
2) I'm currently not playing a courtesy tone to the channel if it
is bridged. This probably can be done by queuing a bridge action either
before or after moving the channel into the new bridge.


Modified:
    team/mmichelson/more_transfer/main/features.c

Modified: team/mmichelson/more_transfer/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/more_transfer/main/features.c?view=diff&rev=386945&r1=386944&r2=386945
==============================================================================
--- team/mmichelson/more_transfer/main/features.c (original)
+++ team/mmichelson/more_transfer/main/features.c Tue Apr 30 09:19:42 2013
@@ -7172,6 +7172,45 @@
 	return 0;
 }
 
+static int add_to_bridge(struct ast_bridge *bridge, struct ast_channel *chan,
+		char buf[], size_t size, int play_tone)
+{
+	RAII_VAR(struct ast_bridge *, chan_bridge, NULL, ao2_cleanup);
+	struct ast_channel *bridge_chan;
+
+	ast_channel_lock(chan);
+	chan_bridge = ast_channel_get_bridge(chan);
+	ast_channel_unlock(chan);
+
+	if (chan_bridge) {
+		/* XXX Is there a way to play the tone to chan before moving it? A
+		 * bridge action on the channel's bridge_channel perhaps?
+		 */
+		return ast_bridge_move(bridge, chan_bridge, chan, NULL, 1);
+	}
+
+	/* Slightly less easy case. We need to yank channel A from
+	 * where he currently is and impart him into our bridge.
+	 */
+	bridge_chan = ast_channel_yank(chan);
+	if (!bridge_chan) {
+		snprintf(buf, size, "Could not gain control of channel %s\n", ast_channel_name(chan));
+		return -1;
+	}
+	if (play_tone && !ast_strlen_zero(xfersound) && !ast_streamfile(bridge_chan,
+				xfersound, ast_channel_language(bridge_chan))) {
+		if (ast_waitstream(bridge_chan, "") < 0) {
+			ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n",
+					ast_channel_name(bridge_chan));
+		}
+	}
+	if (ast_bridge_impart(bridge, bridge_chan, NULL, NULL, 1)) {
+		snprintf(buf, size, "Could not add %s to the bridge\n", ast_channel_name(chan));
+		return -1;
+	}
+	return 0;
+}
+
 /*!
  * \brief Bridge channels together
  * \param s
@@ -7187,12 +7226,13 @@
  */
 static int action_bridge(struct mansession *s, const struct message *m)
 {
+	/* XXX Refcounts need addressing */
 	const char *channela = astman_get_header(m, "Channel1");
 	const char *channelb = astman_get_header(m, "Channel2");
 	const char *playtone = astman_get_header(m, "Tone");
-	struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
-	struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
-	struct ast_bridge_thread_obj *tobj = NULL;
+	struct ast_channel *chana = NULL;
+	struct ast_channel *chanb = NULL;
+	struct ast_bridge *bridge;
 	char buf[256];
 
 	/* make sure valid channels were specified */
@@ -7204,95 +7244,35 @@
 	/* Start with chana */
 	chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
 	if (!chana) {
-		snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
+		snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela);
 		astman_send_error(s, m, buf);
 		return 0;
 	}
 
-	/* Answer the channels if needed */
-	if (ast_channel_state(chana) != AST_STATE_UP)
-		ast_answer(chana);
-
-	/* create the placeholder channels and grab the other channels */
-	if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
-		NULL, NULL, ast_channel_linkedid(chana), 0, "Bridge/%s", ast_channel_name(chana)))) {
-		astman_send_error(s, m, "Unable to create temporary channel!");
-		chana = ast_channel_unref(chana);
-		return 0;
-	}
-
-	if (do_bridge_masquerade(chana, tmpchana)) {
-		snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channela);
-		astman_send_error(s, m, buf);
-		ast_hangup(tmpchana);
-		chana = ast_channel_unref(chana);
-		return 0;
-	}
-
-	chana = ast_channel_unref(chana);
-
-	/* now do chanb */
 	chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
 	if (!chanb) {
-		snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
+		snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb);
 		astman_send_error(s, m, buf);
-		ast_hangup(tmpchana);
 		return 0;
 	}
 
-	/* Answer the channels if needed */
-	if (ast_channel_state(chanb) != AST_STATE_UP)
-		ast_answer(chanb);
-
-	/* create the placeholder channels and grab the other channels */
-	if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
-		NULL, NULL, ast_channel_linkedid(chanb), 0, "Bridge/%s", ast_channel_name(chanb)))) {
-		astman_send_error(s, m, "Unable to create temporary channels!");
-		ast_hangup(tmpchana);
-		chanb = ast_channel_unref(chanb);
+	bridge = ast_bridge_basic_new();
+	if (!bridge) {
+		astman_send_error(s, m, "Unable to create bridge\n");
 		return 0;
 	}
 
-	if (do_bridge_masquerade(chanb, tmpchanb)) {
-		snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channelb);
+	if (add_to_bridge(bridge, chana, buf, sizeof(buf), ast_true(playtone))) {
 		astman_send_error(s, m, buf);
-		ast_hangup(tmpchana);
-		ast_hangup(tmpchanb);
-		chanb = ast_channel_unref(chanb);
 		return 0;
 	}
 
-	chanb = ast_channel_unref(chanb);
-
-	/* make the channels compatible, send error if we fail doing so */
-	if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
-		ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb));
-		astman_send_error(s, m, "Could not make channels compatible for manager bridge");
-		ast_hangup(tmpchana);
-		ast_hangup(tmpchanb);
+	if (add_to_bridge(bridge, chanb, buf, sizeof(buf), ast_true(playtone))) {
+		astman_send_error(s, m, buf);
 		return 0;
 	}
 
-	/* setup the bridge thread object and start the bridge */
-	if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
-		ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb), strerror(errno));
-		astman_send_error(s, m, "Unable to spawn a new bridge thread");
-		ast_hangup(tmpchana);
-		ast_hangup(tmpchanb);
-		return 0;
-	}
-
-	tobj->chan = tmpchanb;
-	tobj->peer = tmpchana;
-	tobj->return_to_pbx = 1;
-
-	if (ast_true(playtone)) {
-		if (!ast_strlen_zero(xfersound) && !ast_streamfile(tmpchanb, xfersound, ast_channel_language(tmpchanb))) {
-			if (ast_waitstream(tmpchanb, "") < 0)
-				ast_log(LOG_WARNING, "Failed to play a courtesy tone on chan %s\n", ast_channel_name(tmpchanb));
-		}
-	}
-
+#if 0
 	chans[0] = tmpchana;
 	chans[1] = tmpchanb;
 	/*** DOCUMENTATION
@@ -7315,9 +7295,7 @@
 				"Response: Success\r\n"
 				"Channel1: %s\r\n"
 				"Channel2: %s\r\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb));
-
-/* BUGBUG there seems to be no COLP update here. */
-	bridge_call_thread_launch(tobj);
+#endif
 
 	astman_send_ack(s, m, "Launched bridge thread with success");
 




More information about the asterisk-commits mailing list