[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