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_channel * | dial_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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
Built in bridging features.
Definition in file bridge_builtin_features.c.
| 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::channels.
Referenced by feature_attended_transfer().
{
struct ast_bridge_channel *called_bridge_channel = NULL;
/* 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 */
ao2_lock(bridge);
if (AST_LIST_FIRST(&bridge->channels) != bridge_channel) {
called_bridge_channel = AST_LIST_FIRST(&bridge->channels);
} else {
called_bridge_channel = AST_LIST_LAST(&bridge->channels);
}
/* 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. */
if (called_bridge_channel) {
ast_bridge_change_state(called_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
}
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ao2_unlock(bridge);
return 0;
}
| 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().
{
/* 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 */
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
return 0;
}
| static struct ast_channel* dial_transfer | ( | struct ast_channel * | caller, |
| const char * | exten, | ||
| const char * | context | ||
| ) | [static, read] |
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, ast_channel::connected, and ast_channel::nativeformats.
Referenced by feature_attended_transfer(), and feature_blind_transfer().
{
char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
struct ast_channel *chan;
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, caller, destination, &cause))) {
return NULL;
}
/* Before we actually dial out let's inherit appropriate information. */
ast_channel_lock_both(caller, chan);
ast_connected_line_copy_from_caller(&chan->connected, &caller->caller);
ast_channel_inherit_variables(caller, chan);
ast_channel_datastore_inherit(caller, chan);
ast_channel_unlock(chan);
ast_channel_unlock(caller);
/* 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;
}
| 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, context, ast_bridge_features_attended_transfer::context, ast_channel::context, dial_transfer(), exten, grab_transfer(), and ast_bridge_features_attended_transfer::threeway.
Referenced by load_module().
{
char exten[AST_MAX_EXTENSION] = "";
struct ast_channel *chan = NULL;
struct ast_bridge *attended_bridge = NULL;
struct ast_bridge_features caller_features, called_features;
enum ast_bridge_channel_state attended_bridge_result;
struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
const char *context = (attended_transfer && !ast_strlen_zero(attended_transfer->context) ? attended_transfer->context : bridge_channel->chan->context);
/* Grab the extension to transfer to */
if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
return 0;
}
/* Get a channel that is the destination we wish to call */
if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
ast_bridge_change_state(bridge_channel, 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, "beeperr", AST_DIGIT_ANY);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
return 0;
}
/* Setup our called features structure so that if they hang up we immediately get thrown out of the bridge */
ast_bridge_features_init(&called_features);
ast_bridge_features_set_flag(&called_features, AST_BRIDGE_FLAG_DISSOLVE);
/* 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, &called_features);
/* Before we join setup a features structure with the hangup option, just in case they want to use DTMF */
ast_bridge_features_init(&caller_features);
ast_bridge_features_enable(&caller_features, AST_BRIDGE_BUILTIN_HANGUP,
(attended_transfer && !ast_strlen_zero(attended_transfer->complete) ? attended_transfer->complete : "*1"), NULL);
ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->threeway) ? attended_transfer->threeway : "*2"),
attended_threeway_transfer, NULL);
ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->abort) ? attended_transfer->abort : "*3"),
attended_abort_transfer, NULL);
/* 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 */
attended_bridge_result = ast_bridge_join(attended_bridge, bridge_channel->chan, NULL, &caller_features);
/* Since the above returned the caller features structure is of no more use */
ast_bridge_features_cleanup(&caller_features);
/* Drop the channel we are transferring to out of the above bridge since it has ended */
if ((attended_bridge_result != AST_BRIDGE_CHANNEL_STATE_HANGUP) && !ast_bridge_depart(attended_bridge, chan)) {
/* If the user wants to turn this into a threeway transfer then do so, otherwise they take our place */
if (attended_bridge_result == AST_BRIDGE_CHANNEL_STATE_DEPART) {
/* We want to impart them upon the bridge and just have us return to it as normal */
ast_bridge_impart(bridge, chan, NULL, NULL);
} else {
ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
}
} else {
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
}
/* Now that all channels are out of it we can destroy the bridge and the called features structure */
ast_bridge_features_cleanup(&called_features);
ast_bridge_destroy(attended_bridge);
return 0;
}
| 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_bridge_features_blind_transfer::context, context, ast_channel::context, dial_transfer(), exten, and grab_transfer().
Referenced by load_module().
{
char exten[AST_MAX_EXTENSION] = "";
struct ast_channel *chan = NULL;
struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
const char *context = (blind_transfer && !ast_strlen_zero(blind_transfer->context) ? blind_transfer->context : bridge_channel->chan->context);
/* Grab the extension to transfer to */
if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
return 0;
}
/* Get a channel that is the destination we wish to call */
if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
ast_bridge_change_state(bridge_channel, 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;
}
| 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().
{
/* This is very simple, we basically change the state on the bridge channel to end and the core takes care of the rest */
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
return 0;
}
| 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(), and ast_stream_and_wait().
Referenced by feature_attended_transfer(), and feature_blind_transfer().
{
int res;
/* Play the simple "transfer" prompt out and wait */
res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
ast_stopstream(chan);
/* If the person hit a DTMF digit while the above played back stick it into the buffer */
if (res) {
exten[0] = (char)res;
}
/* Drop to dialtone so they can enter the extension they want to transfer to */
res = ast_app_dtget(chan, context, exten, exten_len, 100, 1000);
return res;
}
| 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(), feature_hangup(), and ast_module_info::self.
{
ast_bridge_features_register(AST_BRIDGE_BUILTIN_BLINDTRANSFER, feature_blind_transfer, NULL);
ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, feature_attended_transfer, NULL);
ast_bridge_features_register(AST_BRIDGE_BUILTIN_HANGUP, feature_hangup, NULL);
/* Bump up our reference count so we can't be unloaded */
ast_module_ref(ast_module_info->self);
return AST_MODULE_LOAD_SUCCESS;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 249 of file bridge_builtin_features.c.
{
return 0;
}
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 = AST_BUILDOPT_SUM, .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.