Mon Oct 8 12:39:11 2012

Asterisk developer's documentation


bridge_builtin_features.c File Reference

Built in bridging features. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_technology.h"
#include "asterisk/frame.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/astobj2.h"

Go to the source code of this file.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int attended_abort_transfer (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Attended transfer abort feature.
static int attended_threeway_transfer (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Attended transfer feature to turn it into a threeway call.
static struct ast_channeldial_transfer (struct ast_channel *caller, const char *exten, const char *context)
 Helper function that creates an outgoing channel and returns it immediately.
static int feature_attended_transfer (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Internal built in feature for attended transfers.
static int feature_blind_transfer (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Internal built in feature for blind transfers.
static int feature_hangup (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 Internal built in feature for hangup.
static int grab_transfer (struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
 Helper function that presents dialtone and grabs extension.
static int load_module (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Built in bridging features" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static struct ast_module_infoast_module_info = &__mod_info


Detailed Description

Built in bridging features.

Author:
Joshua Colp <jcolp@digium.com>

Definition in file bridge_builtin_features.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 266 of file bridge_builtin_features.c.

static void __unreg_module ( void   )  [static]

Definition at line 266 of file bridge_builtin_features.c.

static int attended_abort_transfer ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
) [static]

Attended transfer abort feature.

Definition at line 140 of file bridge_builtin_features.c.

References ao2_lock, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_LIST_FIRST, AST_LIST_LAST, and ast_bridge_channel::bridge.

Referenced by feature_attended_transfer().

00141 {
00142    struct ast_bridge_channel *called_bridge_channel = NULL;
00143 
00144    /* It is possible (albeit unlikely) that the bridge channels list may change, so we have to ensure we do all of our magic while locked */
00145    ao2_lock(bridge);
00146 
00147    if (AST_LIST_FIRST(&bridge->channels) != bridge_channel) {
00148       called_bridge_channel = AST_LIST_FIRST(&bridge->channels);
00149    } else {
00150       called_bridge_channel = AST_LIST_LAST(&bridge->channels);
00151    }
00152 
00153    /* Now we basically eject the other channel from the bridge. This will cause their thread to hang them up, and our own code to consider the transfer failed. */
00154    if (called_bridge_channel) {
00155       ast_bridge_change_state(called_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00156    }
00157 
00158    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00159 
00160    ao2_unlock(bridge);
00161 
00162    return 0;
00163 }

static int attended_threeway_transfer ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
) [static]

Attended transfer feature to turn it into a threeway call.

Definition at line 132 of file bridge_builtin_features.c.

References ast_bridge_change_state(), and AST_BRIDGE_CHANNEL_STATE_DEPART.

Referenced by feature_attended_transfer().

00133 {
00134    /* This is sort of abusing the depart state but in this instance it is only going to be handled in the below function so it is okay */
00135    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
00136    return 0;
00137 }

static struct ast_channel* dial_transfer ( struct ast_channel caller,
const char *  exten,
const char *  context 
) [static]

Helper function that creates an outgoing channel and returns it immediately.

Definition at line 72 of file bridge_builtin_features.c.

References ast_call(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock_both, ast_channel_unlock, ast_connected_line_copy_from_caller(), ast_hangup(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_request(), ast_channel::caller, cause, and ast_channel::connected.

Referenced by feature_attended_transfer(), and feature_blind_transfer().

00073 {
00074    char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
00075    struct ast_channel *chan;
00076    int cause;
00077 
00078    /* Fill the variable with the extension and context we want to call */
00079    snprintf(destination, sizeof(destination), "%s@%s", exten, context);
00080 
00081    /* Now we request that chan_local prepare to call the destination */
00082    if (!(chan = ast_request("Local", caller->nativeformats, caller, destination, &cause))) {
00083       return NULL;
00084    }
00085 
00086    /* Before we actually dial out let's inherit appropriate information. */
00087    ast_channel_lock_both(caller, chan);
00088    ast_connected_line_copy_from_caller(&chan->connected, &caller->caller);
00089    ast_channel_inherit_variables(caller, chan);
00090    ast_channel_datastore_inherit(caller, chan);
00091    ast_channel_unlock(chan);
00092    ast_channel_unlock(caller);
00093 
00094    /* Since the above worked fine now we actually call it and return the channel */
00095    if (ast_call(chan, destination, 0)) {
00096       ast_hangup(chan);
00097       return NULL;
00098    }
00099 
00100    return chan;
00101 }

static int feature_attended_transfer ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
) [static]

Internal built in feature for attended transfers.

Definition at line 166 of file bridge_builtin_features.c.

References ast_bridge_features_attended_transfer::abort, AST_BRIDGE_BUILTIN_HANGUP, AST_BRIDGE_CAPABILITY_1TO1MIX, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DEPART, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_features_cleanup(), ast_bridge_features_enable(), ast_bridge_features_hook(), ast_bridge_features_init(), ast_bridge_features_set_flag(), AST_BRIDGE_FLAG_DISSOLVE, ast_bridge_impart(), ast_bridge_join(), ast_bridge_new(), AST_DIGIT_ANY, ast_hangup(), AST_MAX_EXTENSION, ast_stream_and_wait(), ast_strlen_zero(), attended_abort_transfer(), attended_threeway_transfer(), ast_bridge_channel::chan, ast_bridge_features_attended_transfer::complete, ast_channel::context, ast_bridge_features_attended_transfer::context, context, dial_transfer(), exten, grab_transfer(), and ast_bridge_features_attended_transfer::threeway.

Referenced by load_module().

00167 {
00168    char exten[AST_MAX_EXTENSION] = "";
00169    struct ast_channel *chan = NULL;
00170    struct ast_bridge *attended_bridge = NULL;
00171    struct ast_bridge_features caller_features, called_features;
00172    enum ast_bridge_channel_state attended_bridge_result;
00173    struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
00174    const char *context = (attended_transfer && !ast_strlen_zero(attended_transfer->context) ? attended_transfer->context : bridge_channel->chan->context);
00175 
00176    /* Grab the extension to transfer to */
00177    if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
00178       ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
00179       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00180       return 0;
00181    }
00182 
00183    /* Get a channel that is the destination we wish to call */
00184    if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
00185       ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00186       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00187       return 0;
00188    }
00189 
00190    /* Create a bridge to use to talk to the person we are calling */
00191    if (!(attended_bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) {
00192       ast_hangup(chan);
00193       ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00194       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00195       return 0;
00196    }
00197 
00198    /* Setup our called features structure so that if they hang up we immediately get thrown out of the bridge */
00199    ast_bridge_features_init(&called_features);
00200    ast_bridge_features_set_flag(&called_features, AST_BRIDGE_FLAG_DISSOLVE);
00201 
00202    /* This is how this is going down, we are imparting the channel we called above into this bridge first */
00203    ast_bridge_impart(attended_bridge, chan, NULL, &called_features);
00204 
00205    /* Before we join setup a features structure with the hangup option, just in case they want to use DTMF */
00206    ast_bridge_features_init(&caller_features);
00207    ast_bridge_features_enable(&caller_features, AST_BRIDGE_BUILTIN_HANGUP,
00208                (attended_transfer && !ast_strlen_zero(attended_transfer->complete) ? attended_transfer->complete : "*1"), NULL);
00209    ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->threeway) ? attended_transfer->threeway : "*2"),
00210              attended_threeway_transfer, NULL);
00211    ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->abort) ? attended_transfer->abort : "*3"),
00212              attended_abort_transfer, NULL);
00213 
00214    /* 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 */
00215    attended_bridge_result = ast_bridge_join(attended_bridge, bridge_channel->chan, NULL, &caller_features);
00216 
00217    /* Since the above returned the caller features structure is of no more use */
00218    ast_bridge_features_cleanup(&caller_features);
00219 
00220    /* Drop the channel we are transferring to out of the above bridge since it has ended */
00221    if ((attended_bridge_result != AST_BRIDGE_CHANNEL_STATE_HANGUP) && !ast_bridge_depart(attended_bridge, chan)) {
00222       /* If the user wants to turn this into a threeway transfer then do so, otherwise they take our place */
00223       if (attended_bridge_result == AST_BRIDGE_CHANNEL_STATE_DEPART) {
00224          /* We want to impart them upon the bridge and just have us return to it as normal */
00225          ast_bridge_impart(bridge, chan, NULL, NULL);
00226       } else {
00227          ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
00228       }
00229    } else {
00230       ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00231       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00232    }
00233 
00234    /* Now that all channels are out of it we can destroy the bridge and the called features structure */
00235    ast_bridge_features_cleanup(&called_features);
00236    ast_bridge_destroy(attended_bridge);
00237 
00238    return 0;
00239 }

static int feature_blind_transfer ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
) [static]

Internal built in feature for blind transfers.

Definition at line 104 of file bridge_builtin_features.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_impart(), AST_DIGIT_ANY, AST_MAX_EXTENSION, ast_stream_and_wait(), ast_strlen_zero(), ast_bridge_channel::chan, ast_channel::context, ast_bridge_features_blind_transfer::context, context, dial_transfer(), exten, and grab_transfer().

Referenced by load_module().

00105 {
00106    char exten[AST_MAX_EXTENSION] = "";
00107    struct ast_channel *chan = NULL;
00108    struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
00109    const char *context = (blind_transfer && !ast_strlen_zero(blind_transfer->context) ? blind_transfer->context : bridge_channel->chan->context);
00110 
00111    /* Grab the extension to transfer to */
00112    if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
00113       ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
00114       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00115       return 0;
00116    }
00117 
00118    /* Get a channel that is the destination we wish to call */
00119    if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
00120       ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00121       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00122       return 0;
00123    }
00124 
00125    /* This is sort of the fun part. We impart the above channel onto the bridge, and have it take our place. */
00126    ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
00127 
00128    return 0;
00129 }

static int feature_hangup ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
) [static]

Internal built in feature for hangup.

Definition at line 242 of file bridge_builtin_features.c.

References ast_bridge_change_state(), and AST_BRIDGE_CHANNEL_STATE_END.

Referenced by load_module().

00243 {
00244    /* This is very simple, we basically change the state on the bridge channel to end and the core takes care of the rest */
00245    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00246    return 0;
00247 }

static int grab_transfer ( struct ast_channel chan,
char *  exten,
size_t  exten_len,
const char *  context 
) [static]

Helper function that presents dialtone and grabs extension.

Definition at line 52 of file bridge_builtin_features.c.

References ast_app_dtget(), AST_DIGIT_ANY, ast_stopstream(), ast_stream_and_wait(), and asent::chan.

Referenced by feature_attended_transfer(), and feature_blind_transfer().

00053 {
00054    int res;
00055 
00056    /* Play the simple "transfer" prompt out and wait */
00057    res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
00058    ast_stopstream(chan);
00059 
00060    /* If the person hit a DTMF digit while the above played back stick it into the buffer */
00061    if (res) {
00062       exten[0] = (char)res;
00063    }
00064 
00065    /* Drop to dialtone so they can enter the extension they want to transfer to */
00066    res = ast_app_dtget(chan, context, exten, exten_len, 100, 1000);
00067 
00068    return res;
00069 }

static int load_module ( void   )  [static]

Definition at line 254 of file bridge_builtin_features.c.

References AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, AST_BRIDGE_BUILTIN_BLINDTRANSFER, AST_BRIDGE_BUILTIN_HANGUP, ast_bridge_features_register(), AST_MODULE_LOAD_SUCCESS, ast_module_ref(), feature_attended_transfer(), feature_blind_transfer(), and feature_hangup().

static int unload_module ( void   )  [static]

Definition at line 249 of file bridge_builtin_features.c.

00250 {
00251    return 0;
00252 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Built in bridging features" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 266 of file bridge_builtin_features.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 266 of file bridge_builtin_features.c.


Generated on Mon Oct 8 12:39:11 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7