[asterisk-commits] file: branch file/bridging r106323 - /team/file/bridging/main/bridging.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Mar 5 20:51:43 CST 2008


Author: file
Date: Wed Mar  5 20:51:43 2008
New Revision: 106323

URL: http://svn.digium.com/view/asterisk?view=rev&rev=106323
Log:
Add basic blind and attended transfer feature hooks.

Modified:
    team/file/bridging/main/bridging.c

Modified: team/file/bridging/main/bridging.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/bridging.c?view=diff&rev=106323&r1=106322&r2=106323
==============================================================================
--- team/file/bridging/main/bridging.c (original)
+++ team/file/bridging/main/bridging.c Wed Mar  5 20:51:43 2008
@@ -1268,10 +1268,37 @@
 	return res;
 }
 
+/*! \brief Helper function that creates an outgoing channel and returns it immediately */
+static struct ast_channel *dial_transfer(const struct ast_channel *caller, const char *exten, const char *context)
+{
+	char destination[AST_MAX_EXTENSION+AST_MAX_CONTEXT+1] = "";
+	struct ast_channel *chan = NULL;
+	int cause;
+
+	/* Fill the variable with the extension and context we want to call */
+	snprintf(destination, sizeof(destination), "%s@%s", exten, context);
+
+	/* Now we request that chan_local prepare to call the destination */
+	if (!(chan = ast_request("Local", caller->nativeformats, destination, &cause)))
+		return NULL;
+
+	/* Before we actually dial out let's inherit the appropriate dialplan variables */
+	ast_channel_inherit_variables(caller, chan);
+
+	/* Since the above worked fine now we actually call it and return the channel */
+	if (ast_call(chan, destination, 0)) {
+		ast_hangup(chan);
+		return NULL;
+	}
+
+	return chan;
+}
+
 /*! \brief Internal built in feature for blind transfers */
 static int feature_blind_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
 	char exten[AST_MAX_EXTENSION] = "";
+	struct ast_channel *chan = NULL;
 
 	/* Grab the extension to transfer to */
 	if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), bridge_channel->chan->context)) {
@@ -1280,7 +1307,15 @@
 		return 0;
 	}
 
-	bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
+	/* Get a channel that is the destination we wish to call */
+	if (!(chan = dial_transfer(bridge_channel->chan, exten, bridge_channel->chan->context))) {
+		ast_stream_and_wait(bridge_channel->chan, "beep", AST_DIGIT_ANY);
+		bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
+		return 0;
+	}
+
+	/* This is sort of the fun part. We impart the above channel onto the bridge, and have it take our place. */
+	ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
 
 	return 0;
 }
@@ -1289,6 +1324,9 @@
 static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
 	char exten[AST_MAX_EXTENSION] = "";
+	struct ast_channel *chan = NULL;
+	struct ast_bridge *attended_bridge = NULL;
+	struct ast_bridge_features features;
 
 	/* Grab the extension to transfer to */
 	if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), bridge_channel->chan->context)) {
@@ -1297,7 +1335,42 @@
 		return 0;
 	}
 
-	bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
+	/* Get a channel that is the destination we wish to call */
+	if (!(chan = dial_transfer(bridge_channel->chan, exten, bridge_channel->chan->context))) {
+		ast_stream_and_wait(bridge_channel->chan, "beep", AST_DIGIT_ANY);
+		bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
+		return 0;
+	}
+
+	/* Create a bridge to use to talk to the person we are calling */
+	if (!(attended_bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) {
+		ast_hangup(chan);
+		ast_stream_and_wait(bridge_channel->chan, "beep", AST_DIGIT_ANY);
+		bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
+		return 0;
+	}
+
+	/* 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);
+
+	/* 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, "*");
+
+	/* 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 */
+	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);
+
+	/* Drop the channel we are transferring to out of the above bridge since it has ended */
+	ast_bridge_depart(attended_bridge, chan);
+
+	/* Now that all channels are out of it we can destroy the bridge */
+	ast_bridge_destroy(attended_bridge);
+
+	/* Just like in a blind transfer we impart this new channel upon the bridge in our place, once done we will be a goner */
+	ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
 
 	return 0;
 }




More information about the asterisk-commits mailing list