Fri Nov 12 11:53:55 2010

Asterisk developer's documentation


bridging.c File Reference

Channel Bridging API. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_technology.h"
#include "asterisk/app.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
Include dependency graph for bridging.c:

Go to the source code of this file.

Data Structures

struct  bridge_technologies

Defines

#define BRIDGE_ARRAY_GROW   32
#define BRIDGE_ARRAY_START   128

Functions

int __ast_bridge_technology_register (struct ast_bridge_technology *technology, struct ast_module *module)
 Register a bridge technology for use.
void ast_bridge_change_state (struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state)
 Change the state of a bridged channel.
int ast_bridge_check (int capabilities)
 See if it is possible to create a bridge.
int ast_bridge_depart (struct ast_bridge *bridge, struct ast_channel *chan)
 Depart a channel from a bridge.
int ast_bridge_destroy (struct ast_bridge *bridge)
 Destroy a bridge.
int ast_bridge_dtmf_stream (struct ast_bridge *bridge, const char *dtmf, struct ast_channel *chan)
 Play a DTMF stream into a bridge, optionally not to a given channel.
int ast_bridge_features_cleanup (struct ast_bridge_features *features)
 Clean up the contents of a bridge features structure.
int ast_bridge_features_enable (struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config)
 Enable a built in feature on a bridge features structure.
int ast_bridge_features_hook (struct ast_bridge_features *features, const char *dtmf, ast_bridge_features_hook_callback callback, void *hook_pvt)
 Attach a custom hook to a bridge features structure.
int ast_bridge_features_init (struct ast_bridge_features *features)
 Initialize bridge features structure.
int ast_bridge_features_register (enum ast_bridge_builtin_feature feature, ast_bridge_features_hook_callback callback, const char *dtmf)
 Register a handler for a built in feature.
int ast_bridge_features_set_flag (struct ast_bridge_features *features, enum ast_bridge_feature_flags flag)
 Set a flag on a bridge features structure.
int ast_bridge_features_unregister (enum ast_bridge_builtin_feature feature)
 Unregister a handler for a built in feature.
void ast_bridge_handle_trip (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd)
 Feed notification that a frame is waiting on a channel into the bridging core.
int ast_bridge_impart (struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
 Impart (non-blocking) a channel on a bridge.
enum ast_bridge_channel_state ast_bridge_join (struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
 Join (blocking) a channel to a bridge.
int ast_bridge_merge (struct ast_bridge *bridge0, struct ast_bridge *bridge1)
 Merge two bridges together.
struct ast_bridgeast_bridge_new (int capabilities, int flags)
 Create a new bridge.
int ast_bridge_remove (struct ast_bridge *bridge, struct ast_channel *chan)
 Remove a channel from a bridge.
int ast_bridge_suspend (struct ast_bridge *bridge, struct ast_channel *chan)
 Suspend a channel temporarily from a bridge.
void ast_bridge_technology_suspend (struct ast_bridge_technology *technology)
 Suspend a bridge technology from consideration.
int ast_bridge_technology_unregister (struct ast_bridge_technology *technology)
 Unregister a bridge technology from use.
void ast_bridge_technology_unsuspend (struct ast_bridge_technology *technology)
 Unsuspend a bridge technology.
int ast_bridge_unsuspend (struct ast_bridge *bridge, struct ast_channel *chan)
 Unsuspend a channel from a bridge.
static void bridge_array_add (struct ast_bridge *bridge, struct ast_channel *chan)
 Helper function to add a channel to the bridge array.
static void bridge_array_remove (struct ast_bridge *bridge, struct ast_channel *chan)
 Helper function to remove a channel from the bridge array.
static void bridge_channel_dtmf_stream (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Internal function that plays back DTMF on a bridge channel.
static void bridge_channel_feature (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Internal function that executes a feature on a bridge channel.
static enum
ast_bridge_channel_state 
bridge_channel_join (struct ast_bridge_channel *bridge_channel)
 Join a channel to a bridge and handle anything the bridge may want us to do.
static enum
ast_bridge_channel_state 
bridge_channel_join_multithreaded (struct ast_bridge_channel *bridge_channel)
 Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve.
static enum
ast_bridge_channel_state 
bridge_channel_join_singlethreaded (struct ast_bridge_channel *bridge_channel)
 Run in a singlethreaded model. Each joined channel yields itself to the main bridge thread. TODO: Improve.
static void bridge_channel_suspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Internal function that suspends a channel from a bridge.
static void * bridge_channel_thread (void *data)
 Thread responsible for imparted bridged channels.
static void bridge_channel_unsuspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Internal function that unsuspends a channel from a bridge.
static void bridge_check_dissolve (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 Internal function to see whether a bridge should dissolve, and if so do it.
static int bridge_drop_control_frame (int subclass)
 Internal function used to determine whether a control frame should be dropped or not.
static struct ast_framebridge_handle_dtmf (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 Internal function to handle DTMF from a channel.
static int bridge_make_compatible (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static void bridge_poke (struct ast_bridge *bridge)
 Helper function to poke the bridge thread.
static void * bridge_thread (void *data)
 Bridge thread function.
static void destroy_bridge (void *obj)
static struct
ast_bridge_technology
find_best_technology (int capabilities)
 Helper function used to find the "best" bridge technology given a specified capabilities.
static struct ast_bridge_channelfind_bridge_channel (struct ast_bridge *bridge, struct ast_channel *chan)
 Helper function to find a bridge channel given a channel.
static int generic_thread_loop (struct ast_bridge *bridge)
 Generic thread loop, TODO: Rethink this/improve it.
static int smart_bridge_operation (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int count)
 Perform the smart bridge operation. Basically sees if a new bridge technology should be used instead of the current one.

Variables

static char builtin_features_dtmf [AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING]
static void * builtin_features_handlers [AST_BRIDGE_BUILTIN_END]

Detailed Description

Channel Bridging API.

Author:
Joshua Colp <jcolp@digium.com>

Definition in file bridging.c.


Define Documentation

#define BRIDGE_ARRAY_GROW   32

Definition at line 51 of file bridging.c.

Referenced by bridge_array_add().

#define BRIDGE_ARRAY_START   128

Definition at line 48 of file bridging.c.

Referenced by ast_bridge_new().


Function Documentation

int __ast_bridge_technology_register ( struct ast_bridge_technology technology,
struct ast_module mod 
)

Register a bridge technology for use.

Parameters:
technology The bridge technology to register
module The module that is registering the bridge technology
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_technology_register(&simple_bridge_tech);

This registers a bridge technology declared as the structure simple_bridge_tech with the bridging core and makes it available for use when creating bridges.

Definition at line 59 of file bridging.c.

References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), ast_verbose, ast_bridge_technology::capabilities, ast_bridge_technology::entry, LOG_WARNING, ast_bridge_technology::mod, ast_bridge_technology::name, option_verbose, VERBOSE_PREFIX_2, and ast_bridge_technology::write.

00060 {
00061    struct ast_bridge_technology *current = NULL;
00062 
00063    /* Perform a sanity check to make sure the bridge technology conforms to our needed requirements */
00064    if (ast_strlen_zero(technology->name) || !technology->capabilities || !technology->write) {
00065       ast_log(LOG_WARNING, "Bridge technology %s failed registration sanity check.\n", technology->name);
00066       return -1;
00067    }
00068 
00069    AST_RWLIST_WRLOCK(&bridge_technologies);
00070 
00071    /* Look for duplicate bridge technology already using this name, or already registered */
00072    AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) {
00073       if ((!strcasecmp(current->name, technology->name)) || (current == technology)) {
00074          ast_log(LOG_WARNING, "A bridge technology of %s already claims to exist in our world.\n", technology->name);
00075          AST_RWLIST_UNLOCK(&bridge_technologies);
00076          return -1;
00077       }
00078    }
00079 
00080    /* Copy module pointer so reference counting can keep the module from unloading */
00081    technology->mod = module;
00082 
00083    /* Insert our new bridge technology into the list and print out a pretty message */
00084    AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
00085 
00086    AST_RWLIST_UNLOCK(&bridge_technologies);
00087 
00088    if (option_verbose > 1) {
00089       ast_verbose(VERBOSE_PREFIX_2 "Registered bridge technology %s\n", technology->name);
00090    }
00091 
00092    return 0;
00093 }

void ast_bridge_change_state ( struct ast_bridge_channel bridge_channel,
enum ast_bridge_channel_state  new_state 
)

Change the state of a bridged channel.

Parameters:
bridge_channel Channel to change the state on
new_state The new state to place the channel into

Example usage:

This places the channel pointed to by bridge_channel into the state AST_BRIDGE_CHANNEL_STATE_WAIT.

Note:
This API call is only meant to be used in feature hook callbacks to make sure the channel either hangs up or returns to the bridge.

Definition at line 118 of file bridging.c.

References ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), ast_bridge_channel::cond, ast_bridge_channel::lock, ast_bridge_channel::state, and ast_bridge_channel::thread.

Referenced by ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_dtmf_stream(), ast_bridge_handle_trip(), ast_bridge_remove(), attended_abort_transfer(), attended_threeway_transfer(), bridge_channel_dtmf_stream(), bridge_channel_feature(), bridge_channel_join(), bridge_check_dissolve(), bridge_handle_dtmf(), feature_attended_transfer(), feature_blind_transfer(), and feature_hangup().

00119 {
00120    /* Change the state on the bridge channel */
00121    bridge_channel->state = new_state;
00122 
00123    /* Only poke the channel's thread if it is not us */
00124    if (!pthread_equal(pthread_self(), bridge_channel->thread)) {
00125       pthread_kill(bridge_channel->thread, SIGURG);
00126       ast_mutex_lock(&bridge_channel->lock);
00127       ast_cond_signal(&bridge_channel->cond);
00128       ast_mutex_unlock(&bridge_channel->lock);
00129    }
00130 
00131    return;
00132 }

int ast_bridge_check ( int  capabilities  ) 

See if it is possible to create a bridge.

Parameters:
capabilities The capabilities that the bridge will use
Return values:
1 if possible
0 if not possible

Example usage:

This sees if it is possible to create a bridge capable of bridging two channels together.

Definition at line 501 of file bridging.c.

References ast_module_unref(), find_best_technology(), and ast_bridge_technology::mod.

00502 {
00503    struct ast_bridge_technology *bridge_technology = NULL;
00504 
00505    if (!(bridge_technology = find_best_technology(capabilities))) {
00506       return 0;
00507    }
00508 
00509    ast_module_unref(bridge_technology->mod);
00510 
00511    return 1;
00512 }

int ast_bridge_depart ( struct ast_bridge bridge,
struct ast_channel chan 
)

Depart a channel from a bridge.

Parameters:
bridge Bridge to depart from
chan Channel to depart
Return values:
0 on success
-1 on failure

Example usage:

This removes the channel pointed to by the chan pointer from the bridge pointed to by the bridge pointer and gives control to the calling thread. This does not hang up the channel.

Note:
This API call can only be used on channels that were added to the bridge using the ast_bridge_impart API call.

Definition at line 1064 of file bridging.c.

References ao2_lock(), ao2_unlock(), ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DEPART, find_bridge_channel(), ast_bridge_channel::thread, and thread.

Referenced by feature_attended_transfer(), and play_sound_file().

01065 {
01066    struct ast_bridge_channel *bridge_channel = NULL;
01067    pthread_t thread;
01068 
01069    ao2_lock(bridge);
01070 
01071    /* Try to find the channel that we want to depart */
01072    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01073       ao2_unlock(bridge);
01074       return -1;
01075    }
01076 
01077    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
01078    thread = bridge_channel->thread;
01079 
01080    ao2_unlock(bridge);
01081 
01082    pthread_join(thread, NULL);
01083 
01084    return 0;
01085 }

int ast_bridge_destroy ( struct ast_bridge bridge  ) 

Destroy a bridge.

Parameters:
bridge Bridge to destroy
Return values:
0 on success
-1 on failure

Example usage:

This destroys a bridge that was previously created using ast_bridge_new.

Definition at line 514 of file bridging.c.

References ao2_lock(), ao2_ref, ao2_unlock(), ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, ast_debug, AST_LIST_TRAVERSE, bridge_poke(), ast_bridge::channels, ast_bridge_channel::entry, and ast_bridge::stop.

Referenced by ast_bridge_new(), destroy_conference_bridge(), and feature_attended_transfer().

00515 {
00516    struct ast_bridge_channel *bridge_channel = NULL;
00517 
00518    ao2_lock(bridge);
00519 
00520    bridge->stop = 1;
00521 
00522    bridge_poke(bridge);
00523 
00524    ast_debug(1, "Telling all channels in bridge %p to end and leave the party\n", bridge);
00525 
00526    /* Drop every bridged channel, the last one will cause the bridge thread (if it exists) to exit */
00527    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00528       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00529    }
00530 
00531    ao2_unlock(bridge);
00532 
00533    ao2_ref(bridge, -1);
00534 
00535    return 0;
00536 }

int ast_bridge_dtmf_stream ( struct ast_bridge bridge,
const char *  dtmf,
struct ast_channel chan 
)

Play a DTMF stream into a bridge, optionally not to a given channel.

Parameters:
bridge Bridge to play stream into
dtmf DTMF to play
chan Channel to optionally not play to
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_dtmf_stream(bridge, "0123456789", NULL);

This sends the DTMF digits '0123456789' to all channels in the bridge pointed to by the bridge pointer. Optionally a channel may be excluded by passing it's channel pointer using the chan parameter.

Definition at line 1332 of file bridging.c.

References ao2_lock(), ao2_unlock(), ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DTMF, ast_copy_string(), AST_LIST_TRAVERSE, ast_bridge_channel::chan, ast_bridge::channels, ast_bridge_channel::dtmf_stream_q, and ast_bridge_channel::entry.

Referenced by bridge_channel_feature().

01333 {
01334    struct ast_bridge_channel *bridge_channel = NULL;
01335 
01336    ao2_lock(bridge);
01337 
01338    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01339       if (bridge_channel->chan == chan) {
01340          continue;
01341       }
01342       ast_copy_string(bridge_channel->dtmf_stream_q, dtmf, sizeof(bridge_channel->dtmf_stream_q));
01343       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DTMF);
01344    }
01345 
01346    ao2_unlock(bridge);
01347 
01348    return 0;
01349 }

int ast_bridge_features_cleanup ( struct ast_bridge_features features  ) 

Clean up the contents of a bridge features structure.

Parameters:
features Bridge features structure
Return values:
0 on success
-1 on failure

Example usage:

This cleans up the feature structure 'features'.

Note:
This MUST be called after the features structure is done being used or a memory leak may occur.

Definition at line 1320 of file bridging.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_bridge_features_hook::entry, and ast_bridge_features::hooks.

Referenced by confbridge_exec(), destroy_bridge(), and feature_attended_transfer().

01321 {
01322    struct ast_bridge_features_hook *hook = NULL;
01323 
01324    /* This is relatively simple, hooks are kept as a list on the features structure so we just pop them off and free them */
01325    while ((hook = AST_LIST_REMOVE_HEAD(&features->hooks, entry))) {
01326       ast_free(hook);
01327    }
01328 
01329    return 0;
01330 }

int ast_bridge_features_enable ( struct ast_bridge_features features,
enum ast_bridge_builtin_feature  feature,
const char *  dtmf,
void *  config 
)

Enable a built in feature on a bridge features structure.

Parameters:
features Bridge features structure
feature Feature to enable
dtmf Optionally the DTMF stream to trigger the feature, if not specified it will be the default
config Configuration structure unique to the built in type
Return values:
0 on success
-1 on failure

Example usage:

This enables the attended transfer DTMF option using the default DTMF string. An alternate string may be provided using the dtmf parameter. Internally this is simply setting up a hook to a built in feature callback function.

Definition at line 1282 of file bridging.c.

References ast_bridge_features_hook(), ast_debug, and ast_strlen_zero().

Referenced by feature_attended_transfer().

01283 {
01284    /* If no alternate DTMF stream was provided use the default one */
01285    if (ast_strlen_zero(dtmf)) {
01286       dtmf = builtin_features_dtmf[feature];
01287       /* If no DTMF is still available (ie: it has been disabled) then error out now */
01288       if (ast_strlen_zero(dtmf)) {
01289          ast_debug(1, "Failed to enable built in feature %d on %p, no DTMF string is available for it.\n", feature, features);
01290          return -1;
01291       }
01292    }
01293 
01294    if (!builtin_features_handlers[feature]) {
01295       return -1;
01296    }
01297 
01298    /* The rest is basically pretty easy. We create another hook using the built in feature's callback and DTMF, easy as pie. */
01299    return ast_bridge_features_hook(features, dtmf, builtin_features_handlers[feature], config);
01300 }

int ast_bridge_features_hook ( struct ast_bridge_features features,
const char *  dtmf,
ast_bridge_features_hook_callback  callback,
void *  hook_pvt 
)

Attach a custom hook to a bridge features structure.

Parameters:
features Bridge features structure
dtmf DTMF string to be activated upon
callback Function to execute upon activation
hook_pvt Unique data
Return values:
0 on success
-1 on failure

Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);
 ast_bridge_features_hook(&features, "#", pound_callback, NULL);

This makes the bridging core call pound_callback if a channel that has this feature structure inputs the DTMF string '#'. A pointer to useful data may be provided to the hook_pvt parameter.

Note:
It is important that the callback set the bridge channel state back to AST_BRIDGE_CHANNEL_STATE_WAIT or the bridge thread will not service the channel.

Definition at line 1261 of file bridging.c.

References ast_calloc, ast_copy_string(), AST_LIST_INSERT_TAIL, ast_bridge_features_hook::callback, ast_bridge_features_hook::dtmf, ast_bridge_features_hook::entry, ast_bridge_features_hook::hook_pvt, ast_bridge_features::hooks, and ast_bridge_features::usable.

Referenced by ast_bridge_features_enable(), confbridge_exec(), and feature_attended_transfer().

01262 {
01263    struct ast_bridge_features_hook *hook = NULL;
01264 
01265    /* Allocate new memory and setup it's various variables */
01266    if (!(hook = ast_calloc(1, sizeof(*hook)))) {
01267       return -1;
01268    }
01269 
01270    ast_copy_string(hook->dtmf, dtmf, sizeof(hook->dtmf));
01271    hook->callback = callback;
01272    hook->hook_pvt = hook_pvt;
01273 
01274    /* Once done we add it onto the list. Now it will be picked up when DTMF is used */
01275    AST_LIST_INSERT_TAIL(&features->hooks, hook, entry);
01276 
01277    features->usable = 1;
01278 
01279    return 0;
01280 }

int ast_bridge_features_init ( struct ast_bridge_features features  ) 

Initialize bridge features structure.

Parameters:
features Bridge featues structure
Return values:
0 on success
-1 on failure

Example usage:

 struct ast_bridge_features features;
 ast_bridge_features_init(&features);

This initializes the feature structure 'features' to have nothing enabled.

Note:
This MUST be called before enabling features or flags. Failure to do so may result in a crash.

Definition at line 1309 of file bridging.c.

References AST_LIST_HEAD_INIT_NOLOCK, and ast_bridge_features::hooks.

Referenced by confbridge_exec(), and feature_attended_transfer().

01310 {
01311    /* Zero out the structure */
01312    memset(features, 0, sizeof(*features));
01313 
01314    /* Initialize the hooks list, just in case */
01315    AST_LIST_HEAD_INIT_NOLOCK(&features->hooks);
01316 
01317    return 0;
01318 }

int ast_bridge_features_register ( enum ast_bridge_builtin_feature  feature,
ast_bridge_features_hook_callback  callback,
const char *  dtmf 
)

Register a handler for a built in feature.

Parameters:
feature The feature that the handler will be responsible for
callback The callback function that will handle it
dtmf Default DTMF string used to activate the feature
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge_builtin_attended_transfer, "*1");

This registers the function bridge_builtin_attended_transfer as the function responsible for the built in attended transfer feature.

Definition at line 1235 of file bridging.c.

References ast_copy_string(), and ast_strlen_zero().

Referenced by load_module().

01236 {
01237    if (builtin_features_handlers[feature]) {
01238       return -1;
01239    }
01240 
01241    if (!ast_strlen_zero(dtmf)) {
01242       ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
01243    }
01244 
01245    builtin_features_handlers[feature] = callback;
01246 
01247    return 0;
01248 }

int ast_bridge_features_set_flag ( struct ast_bridge_features features,
enum ast_bridge_feature_flags  flag 
)

Set a flag on a bridge features structure.

Parameters:
features Bridge features structure
flag Flag to enable
Return values:
0 on success
-1 on failure

Example usage:

This sets the AST_BRIDGE_FLAG_DISSOLVE feature to be enabled on the features structure 'features'.

Definition at line 1302 of file bridging.c.

References ast_set_flag, ast_bridge_features::feature_flags, and ast_bridge_features::usable.

Referenced by feature_attended_transfer().

01303 {
01304    ast_set_flag(&features->feature_flags, flag);
01305    features->usable = 1;
01306    return 0;
01307 }

int ast_bridge_features_unregister ( enum ast_bridge_builtin_feature  feature  ) 

Unregister a handler for a built in feature.

Parameters:
feature The feature to unregister
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER);

This unregisters the function that is handling the built in attended transfer feature.

Definition at line 1250 of file bridging.c.

01251 {
01252    if (!builtin_features_handlers[feature]) {
01253       return -1;
01254    }
01255 
01256    builtin_features_handlers[feature] = NULL;
01257 
01258    return 0;
01259 }

void ast_bridge_handle_trip ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_channel chan,
int  outfd 
)

Feed notification that a frame is waiting on a channel into the bridging core.

Parameters:
bridge The bridge that the notification should influence
bridge_channel Bridge channel the notification was received on (if known)
chan Channel the notification was received on (if known)
outfd File descriptor that the notification was received on (if known)

Example usage:

 ast_bridge_handle_trip(bridge, NULL, chan, -1);

This tells the bridging core that a frame has been received on the channel pointed to by chan and that it should be read and handled.

Note:
This should only be used by bridging technologies.

Definition at line 276 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, ast_frfree, ast_read(), ast_read_noaudio(), bridge_drop_control_frame(), bridge_handle_dtmf(), ast_bridge_technology::fd, ast_bridge_channel::features, ast_bridge::features, find_bridge_channel(), ast_frame::frametype, ast_bridge_features::mute, ast_bridge_technology::poke, ast_frame::subclass, ast_bridge::technology, and ast_bridge_technology::write.

Referenced by bridge_channel_join_multithreaded(), generic_thread_loop(), and multiplexed_thread_function().

00277 {
00278    /* If no bridge channel has been provided and the actual channel has been provided find it */
00279    if (chan && !bridge_channel) {
00280       bridge_channel = find_bridge_channel(bridge, chan);
00281    }
00282 
00283    /* If a bridge channel with actual channel is present read a frame and handle it */
00284    if (chan && bridge_channel) {
00285       struct ast_frame *frame = (((bridge->features.mute) || (bridge_channel->features && bridge_channel->features->mute)) ? ast_read_noaudio(chan) : ast_read(chan));
00286 
00287       /* This is pretty simple... see if they hung up */
00288       if (!frame || (frame->frametype == AST_FRAME_CONTROL && frame->subclass == AST_CONTROL_HANGUP)) {
00289          /* Signal the thread that is handling the bridged channel that it should be ended */
00290          ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00291       } else if (frame->frametype == AST_FRAME_CONTROL && bridge_drop_control_frame(frame->subclass)) {
00292          ast_debug(1, "Dropping control frame from bridge channel %p\n", bridge_channel);
00293       } else {
00294          if (frame->frametype == AST_FRAME_DTMF_BEGIN) {
00295             frame = bridge_handle_dtmf(bridge, bridge_channel, frame);
00296          }
00297          /* Simply write the frame out to the bridge technology if it still exists */
00298          if (frame) {
00299             bridge->technology->write(bridge, bridge_channel, frame);
00300          }
00301       }
00302 
00303       if (frame) {
00304          ast_frfree(frame);
00305       }
00306       return;
00307    }
00308 
00309    /* If a file descriptor actually tripped pass it off to the bridge technology */
00310    if (outfd > -1 && bridge->technology->fd) {
00311       bridge->technology->fd(bridge, bridge_channel, outfd);
00312       return;
00313    }
00314 
00315    /* If all else fails just poke the bridge */
00316    if (bridge->technology->poke && bridge_channel) {
00317       bridge->technology->poke(bridge, bridge_channel);
00318       return;
00319    }
00320 
00321    return;
00322 }

int ast_bridge_impart ( struct ast_bridge bridge,
struct ast_channel chan,
struct ast_channel swap,
struct ast_bridge_features features 
)

Impart (non-blocking) a channel on a bridge.

Parameters:
bridge Bridge to impart on
chan Channel to impart
swap Channel to swap out if swapping
features Bridge features structure
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_impart(bridge, chan, NULL, NULL);

This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will return immediately and will not wait until the channel is no longer part of the bridge.

If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.

If channel specific features are enabled a pointer to the features structure can be specified in the features parameter.

Definition at line 1030 of file bridging.c.

References ao2_ref, ast_calloc, ast_cond_destroy(), ast_cond_init(), ast_free, ast_mutex_destroy(), ast_mutex_init(), ast_pthread_create, ast_bridge_channel::bridge, bridge_channel_thread(), ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge_channel::features, ast_bridge_channel::lock, ast_bridge_channel::swap, and ast_bridge_channel::thread.

Referenced by bridge_call(), feature_attended_transfer(), feature_blind_transfer(), and play_sound_file().

01031 {
01032    struct ast_bridge_channel *bridge_channel = NULL;
01033 
01034    /* Try to allocate a structure for the bridge channel */
01035    if (!(bridge_channel = ast_calloc(1, sizeof(*bridge_channel)))) {
01036       return -1;
01037    }
01038 
01039    /* Setup various parameters */
01040    bridge_channel->chan = chan;
01041    bridge_channel->swap = swap;
01042    bridge_channel->bridge = bridge;
01043    bridge_channel->features = features;
01044 
01045    /* Initialize our mutex lock and condition */
01046    ast_mutex_init(&bridge_channel->lock);
01047    ast_cond_init(&bridge_channel->cond, NULL);
01048 
01049    /* Bump up the reference count on the bridge, it'll get decremented later */
01050    ao2_ref(bridge, +1);
01051 
01052    /* Actually create the thread that will handle the channel */
01053    if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
01054       ao2_ref(bridge, -1);
01055       ast_cond_destroy(&bridge_channel->cond);
01056       ast_mutex_destroy(&bridge_channel->lock);
01057       ast_free(bridge_channel);
01058       return -1;
01059    }
01060 
01061    return 0;
01062 }

enum ast_bridge_channel_state ast_bridge_join ( struct ast_bridge bridge,
struct ast_channel chan,
struct ast_channel swap,
struct ast_bridge_features features 
)

Join (blocking) a channel to a bridge.

Parameters:
bridge Bridge to join
chan Channel to join
swap Channel to swap out if swapping
features Bridge features structure
Return values:
state that channel exited the bridge with

Example usage:

 ast_bridge_join(bridge, chan, NULL, NULL);

This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will not return until the channel has been removed from the bridge, swapped out for another channel, or has hung up.

If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.

If channel specific features are enabled a pointer to the features structure can be specified in the features parameter.

Definition at line 980 of file bridging.c.

References ao2_ref, ast_cond_destroy(), ast_cond_init(), ast_mutex_destroy(), ast_mutex_init(), ast_bridge_channel::bridge, ast_channel::bridge, bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge::features, and ast_bridge_channel::lock.

Referenced by confbridge_exec(), and feature_attended_transfer().

00981 {
00982    struct ast_bridge_channel bridge_channel = {
00983       .chan = chan,
00984       .swap = swap,
00985       .bridge = bridge,
00986       .features = features,
00987    };
00988    enum ast_bridge_channel_state state;
00989 
00990    /* Initialize various other elements of the bridge channel structure that we can't do above */
00991    ast_mutex_init(&bridge_channel.lock);
00992    ast_cond_init(&bridge_channel.cond, NULL);
00993 
00994    ao2_ref(bridge_channel.bridge, +1);
00995 
00996    state = bridge_channel_join(&bridge_channel);
00997 
00998    ao2_ref(bridge_channel.bridge, -1);
00999 
01000    /* Destroy some elements of the bridge channel structure above */
01001    ast_mutex_destroy(&bridge_channel.lock);
01002    ast_cond_destroy(&bridge_channel.cond);
01003 
01004    return state;
01005 }

int ast_bridge_merge ( struct ast_bridge bridge0,
struct ast_bridge bridge1 
)

Merge two bridges together.

Parameters:
bridge0 First bridge
bridge1 Second bridge
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_merge(bridge0, bridge1);

This merges the bridge pointed to by bridge1 with the bridge pointed to by bridge0. In reality all of the channels in bridge1 are simply moved to bridge0.

Note:
The second bridge specified is not destroyed when this operation is completed.

Definition at line 1106 of file bridging.c.

References ao2_lock(), ao2_ref, ao2_unlock(), AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_FLAG_SMART, ast_cond_signal(), ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_STOP, ast_test_flag, ast_bridge_channel::bridge, bridge_array_add(), bridge_array_remove(), bridge_make_compatible(), ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge::channels, ast_bridge_channel::cond, ast_bridge_channel::entry, ast_bridge::feature_flags, ast_bridge_technology::join, ast_bridge_technology::leave, ast_bridge_channel::lock, ast_bridge_technology::name, ast_bridge::num, smart_bridge_operation(), ast_bridge::technology, ast_bridge_channel::thread, and ast_bridge::thread.

01107 {
01108    struct ast_bridge_channel *bridge_channel = NULL;
01109 
01110    ao2_lock(bridge0);
01111    ao2_lock(bridge1);
01112 
01113    /* If the first bridge currently has 2 channels and is not capable of becoming a multimixing bridge we can not merge */
01114    if ((bridge0->num + bridge1->num) > 2 && (!(bridge0->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) && !ast_test_flag(&bridge0->feature_flags, AST_BRIDGE_FLAG_SMART))) {
01115       ao2_unlock(bridge1);
01116       ao2_unlock(bridge0);
01117       ast_debug(1, "Can't merge bridge %p into bridge %p, multimix is needed and it could not be acquired.\n", bridge1, bridge0);
01118       return -1;
01119    }
01120 
01121    ast_debug(1, "Merging channels from bridge %p into bridge %p\n", bridge1, bridge0);
01122 
01123    /* Perform smart bridge operation on bridge we are merging into so it can change bridge technology if needed */
01124    if (smart_bridge_operation(bridge0, NULL, bridge0->num + bridge1->num)) {
01125       ao2_unlock(bridge1);
01126       ao2_unlock(bridge0);
01127       ast_debug(1, "Can't merge bridge %p into bridge %p, tried to perform smart bridge operation and failed.\n", bridge1, bridge0);
01128       return -1;
01129    }
01130 
01131    /* If a thread is currently executing on bridge1 tell it to stop */
01132    if (bridge1->thread) {
01133       ast_debug(1, "Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0);
01134       bridge1->thread = AST_PTHREADT_STOP;
01135    }
01136 
01137    /* Move channels from bridge1 over to bridge0 */
01138    while ((bridge_channel = AST_LIST_REMOVE_HEAD(&bridge1->channels, entry))) {
01139       /* Tell the technology handling bridge1 that the bridge channel is leaving */
01140       if (bridge1->technology->leave) {
01141          ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01142          if (bridge1->technology->leave(bridge1, bridge_channel)) {
01143             ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01144          }
01145       }
01146 
01147       /* Drop channel count and reference count on the bridge they are leaving */
01148       bridge1->num--;
01149       ao2_ref(bridge1, -1);
01150 
01151       bridge_array_remove(bridge1, bridge_channel->chan);
01152 
01153       /* Now add them into the bridge they are joining, increase channel count, and bump up reference count */
01154       bridge_channel->bridge = bridge0;
01155       AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, entry);
01156       bridge0->num++;
01157       ao2_ref(bridge0, +1);
01158 
01159       bridge_array_add(bridge0, bridge_channel->chan);
01160 
01161       /* Make the channel compatible with the new bridge it is joining or else formats would go amuck */
01162       bridge_make_compatible(bridge0, bridge_channel);
01163 
01164       /* Tell the technology handling bridge0 that the bridge channel is joining */
01165       if (bridge0->technology->join) {
01166          ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01167          if (bridge0->technology->join(bridge0, bridge_channel)) {
01168             ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01169          }
01170       }
01171 
01172       /* Poke the bridge channel, this will cause it to wake up and execute the proper threading model for the new bridge it is in */
01173       pthread_kill(bridge_channel->thread, SIGURG);
01174       ast_mutex_lock(&bridge_channel->lock);
01175       ast_cond_signal(&bridge_channel->cond);
01176       ast_mutex_unlock(&bridge_channel->lock);
01177    }
01178 
01179    ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge1, bridge0);
01180 
01181    ao2_unlock(bridge1);
01182    ao2_unlock(bridge0);
01183 
01184    return 0;
01185 }

struct ast_bridge* ast_bridge_new ( int  capabilities,
int  flags 
) [read]

Create a new bridge.

Parameters:
capabilities The capabilities that we require to be used on the bridge
flags Flags that will alter the behavior of the bridge
Return values:
a pointer to a new bridge on success
NULL on failure

Example usage:

This creates a simple two party bridge that will be destroyed once one of the channels hangs up.

Definition at line 448 of file bridging.c.

References ao2_alloc, ao2_ref, ast_bridge::array, ast_bridge::array_size, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_MULTIMIX, ast_bridge_destroy(), AST_BRIDGE_FLAG_SMART, ast_bridge_new(), ast_calloc, ast_debug, AST_PTHREADT_NULL, ast_set_flag, BRIDGE_ARRAY_START, ast_bridge_technology::create, destroy_bridge(), ast_bridge::feature_flags, find_best_technology(), ast_bridge_technology::name, ast_bridge::technology, and ast_bridge::thread.

Referenced by ast_bridge_new(), feature_attended_transfer(), and join_conference_bridge().

00449 {
00450    struct ast_bridge *bridge = NULL;
00451    struct ast_bridge_technology *bridge_technology = NULL;
00452 
00453    /* If we need to be a smart bridge see if we can move between 1to1 and multimix bridges */
00454    if (flags & AST_BRIDGE_FLAG_SMART) {
00455       struct ast_bridge *other_bridge;
00456 
00457       if (!(other_bridge = ast_bridge_new((capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) ? AST_BRIDGE_CAPABILITY_MULTIMIX : AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) {
00458          return NULL;
00459       }
00460 
00461       ast_bridge_destroy(other_bridge);
00462    }
00463 
00464    /* If capabilities were provided use our helper function to find the "best" bridge technology, otherwise we can
00465     * just look for the most basic capability needed, single 1to1 mixing. */
00466    bridge_technology = (capabilities ? find_best_technology(capabilities) : find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX));
00467 
00468    /* If no bridge technology was found we can't possibly do bridging so fail creation of the bridge */
00469    if (!bridge_technology) {
00470       ast_debug(1, "Failed to find a bridge technology to satisfy capabilities %d\n", capabilities);
00471       return NULL;
00472    }
00473 
00474    /* We have everything we need to create this bridge... so allocate the memory, link things together, and fire her up! */
00475    if (!(bridge = ao2_alloc(sizeof(*bridge), destroy_bridge))) {
00476       return NULL;
00477    }
00478 
00479    bridge->technology = bridge_technology;
00480    bridge->thread = AST_PTHREADT_NULL;
00481 
00482    /* Create an array of pointers for the channels that will be joining us */
00483    bridge->array = ast_calloc(BRIDGE_ARRAY_START, sizeof(struct ast_channel*));
00484    bridge->array_size = BRIDGE_ARRAY_START;
00485 
00486    ast_set_flag(&bridge->feature_flags, flags);
00487 
00488    /* Pass off the bridge to the technology to manipulate if needed */
00489    if (bridge->technology->create) {
00490       ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", bridge->technology->name, bridge);
00491       if (bridge->technology->create(bridge)) {
00492          ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", bridge->technology->name, bridge);
00493          ao2_ref(bridge, -1);
00494          bridge = NULL;
00495       }
00496    }
00497 
00498    return bridge;
00499 }

int ast_bridge_remove ( struct ast_bridge bridge,
struct ast_channel chan 
)

Remove a channel from a bridge.

Parameters:
bridge Bridge that the channel is to be removed from
chan Channel to remove
Return values:
0 on success
-1 on failure

Example usage:

This removes the channel pointed to by the chan pointer from the bridge pointed to by the bridge pointer and requests that it be hung up. Control over the channel will NOT be given to the calling thread.

Note:
This API call can be used on channels that were added to the bridge using both ast_bridge_join and ast_bridge_impart.

Definition at line 1087 of file bridging.c.

References ao2_lock(), ao2_unlock(), ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_HANGUP, and find_bridge_channel().

Referenced by menu_callback().

01088 {
01089    struct ast_bridge_channel *bridge_channel = NULL;
01090 
01091    ao2_lock(bridge);
01092 
01093    /* Try to find the channel that we want to remove */
01094    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01095       ao2_unlock(bridge);
01096       return -1;
01097    }
01098 
01099    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
01100 
01101    ao2_unlock(bridge);
01102 
01103    return 0;
01104 }

int ast_bridge_suspend ( struct ast_bridge bridge,
struct ast_channel chan 
)

Suspend a channel temporarily from a bridge.

Parameters:
bridge Bridge to suspend the channel from
chan Channel to suspend
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_suspend(bridge, chan);

This suspends the channel pointed to by chan from the bridge pointed to by bridge temporarily. Control of the channel is given to the calling thread. This differs from ast_bridge_depart as the channel will not be removed from the bridge.

Note:
This API call can be used on channels that were added to the bridge using both ast_bridge_join and ast_bridge_impart.

Definition at line 1187 of file bridging.c.

References ao2_lock(), ao2_unlock(), bridge_channel_suspend(), and find_bridge_channel().

Referenced by leave_conference_bridge(), post_join_marked(), and post_join_unmarked().

01188 {
01189    struct ast_bridge_channel *bridge_channel;
01190 
01191    ao2_lock(bridge);
01192 
01193    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01194       ao2_unlock(bridge);
01195       return -1;
01196    }
01197 
01198    bridge_channel_suspend(bridge, bridge_channel);
01199 
01200    ao2_unlock(bridge);
01201 
01202    return 0;
01203 }

void ast_bridge_technology_suspend ( struct ast_bridge_technology technology  ) 

Suspend a bridge technology from consideration.

Parameters:
technology The bridge technology to suspend

Example usage:

 ast_bridge_technology_suspend(&simple_bridge_tech);

This suspends the bridge technology simple_bridge_tech from being considered when creating a new bridge. Existing bridges using the bridge technology are not affected.

Definition at line 1223 of file bridging.c.

References ast_bridge_technology::suspended.

01224 {
01225    technology->suspended = 1;
01226    return;
01227 }

int ast_bridge_technology_unregister ( struct ast_bridge_technology technology  ) 

Unregister a bridge technology from use.

Parameters:
technology The bridge technology to unregister
Return values:
0 on success
-1 on failure

Example usage:

 ast_bridge_technology_unregister(&simple_bridge_tech);

This unregisters a bridge technlogy declared as the structure simple_bridge_tech with the bridging core. It will no longer be considered when creating a new bridge.

Definition at line 95 of file bridging.c.

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose, ast_bridge_technology::entry, ast_bridge_technology::name, option_verbose, and VERBOSE_PREFIX_2.

Referenced by unload_module().

00096 {
00097    struct ast_bridge_technology *current = NULL;
00098 
00099    AST_RWLIST_WRLOCK(&bridge_technologies);
00100 
00101    /* Ensure the bridge technology is registered before removing it */
00102    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) {
00103       if (current == technology) {
00104          AST_RWLIST_REMOVE_CURRENT(entry);
00105          if (option_verbose > 1) {
00106             ast_verbose(VERBOSE_PREFIX_2 "Unregistered bridge technology %s\n", technology->name);
00107          }
00108          break;
00109       }
00110    }
00111    AST_RWLIST_TRAVERSE_SAFE_END;
00112 
00113    AST_RWLIST_UNLOCK(&bridge_technologies);
00114 
00115    return current ? 0 : -1;
00116 }

void ast_bridge_technology_unsuspend ( struct ast_bridge_technology technology  ) 

Unsuspend a bridge technology.

Parameters:
technology The bridge technology to unsuspend

Example usage:

 ast_bridge_technology_unsuspend(&simple_bridge_tech);

This makes the bridge technology simple_bridge_tech considered when creating a new bridge again.

Definition at line 1229 of file bridging.c.

References ast_bridge_technology::suspended.

01230 {
01231    technology->suspended = 0;
01232    return;
01233 }

int ast_bridge_unsuspend ( struct ast_bridge bridge,
struct ast_channel chan 
)

Unsuspend a channel from a bridge.

Parameters:
bridge Bridge to unsuspend the channel from
chan Channel to unsuspend
Return values:
0 on success
-1 on failure

Example usage:

This unsuspends the channel pointed to by chan from the bridge pointed to by bridge. The bridge will go back to handling the channel once this function returns.

Note:
You must not mess with the channel once this function returns. Doing so may result in bad things happening.

Definition at line 1205 of file bridging.c.

References ao2_lock(), ao2_unlock(), bridge_channel_unsuspend(), and find_bridge_channel().

Referenced by leave_conference_bridge(), post_join_marked(), and post_join_unmarked().

01206 {
01207    struct ast_bridge_channel *bridge_channel;
01208 
01209    ao2_lock(bridge);
01210 
01211    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01212       ao2_unlock(bridge);
01213       return -1;
01214    }
01215 
01216    bridge_channel_unsuspend(bridge, bridge_channel);
01217 
01218    ao2_unlock(bridge);
01219 
01220    return 0;
01221 }

static void bridge_array_add ( struct ast_bridge bridge,
struct ast_channel chan 
) [static]

Helper function to add a channel to the bridge array.

Note:
This function assumes the bridge is locked.

Definition at line 149 of file bridging.c.

References ast_bridge::array, ast_bridge::array_num, ast_bridge::array_size, ast_debug, ast_log(), ast_realloc, BRIDGE_ARRAY_GROW, bridge_poke(), LOG_ERROR, ast_channel::name, and ast_bridge::waiting.

Referenced by ast_bridge_merge(), bridge_channel_join(), and bridge_channel_unsuspend().

00150 {
00151    /* We have to make sure the bridge thread is not using the bridge array before messing with it */
00152    while (bridge->waiting) {
00153       bridge_poke(bridge);
00154       sched_yield();
00155    }
00156 
00157    bridge->array[bridge->array_num++] = chan;
00158 
00159    ast_debug(1, "Added channel %s(%p) to bridge array on %p, new count is %d\n", chan->name, chan, bridge, (int)bridge->array_num);
00160 
00161    /* If the next addition of a channel will exceed our array size grow it out */
00162    if (bridge->array_num == bridge->array_size) {
00163       struct ast_channel **tmp;
00164       ast_debug(1, "Growing bridge array on %p from %d to %d\n", bridge, (int)bridge->array_size, (int)bridge->array_size + BRIDGE_ARRAY_GROW);
00165       if (!(tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel *)))) {
00166          ast_log(LOG_ERROR, "Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge);
00167          return;
00168       }
00169       bridge->array = tmp;
00170       bridge->array_size += BRIDGE_ARRAY_GROW;
00171    }
00172 
00173    return;
00174 }

static void bridge_array_remove ( struct ast_bridge bridge,
struct ast_channel chan 
) [static]

Helper function to remove a channel from the bridge array.

Note:
This function assumes the bridge is locked.

Definition at line 180 of file bridging.c.

References ast_bridge::array, ast_bridge::array_num, ast_debug, bridge_poke(), and ast_bridge::waiting.

Referenced by ast_bridge_merge(), bridge_channel_join(), and bridge_channel_suspend().

00181 {
00182    int i;
00183 
00184    /* We have to make sure the bridge thread is not using the bridge array before messing with it */
00185    while (bridge->waiting) {
00186       bridge_poke(bridge);
00187       sched_yield();
00188    }
00189 
00190    for (i = 0; i < bridge->array_num; i++) {
00191       if (bridge->array[i] == chan) {
00192          bridge->array[i] = (bridge->array[(bridge->array_num - 1)] != chan ? bridge->array[(bridge->array_num - 1)] : NULL);
00193          bridge->array[(bridge->array_num - 1)] = NULL;
00194          bridge->array_num--;
00195          ast_debug(1, "Removed channel %p from bridge array on %p, new count is %d\n", chan, bridge, (int)bridge->array_num);
00196          break;
00197       }
00198    }
00199 
00200    return;
00201 }

static void bridge_channel_dtmf_stream ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Internal function that plays back DTMF on a bridge channel.

Definition at line 844 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_copy_string(), ast_debug, ast_dtmf_stream(), ast_bridge_channel::chan, and ast_bridge_channel::dtmf_stream_q.

Referenced by bridge_channel_join().

00845 {
00846    char dtmf_q[8] = "";
00847 
00848    ast_copy_string(dtmf_q, bridge_channel->dtmf_stream_q, sizeof(dtmf_q));
00849    bridge_channel->dtmf_stream_q[0] = '\0';
00850 
00851    ast_debug(1, "Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel);
00852    ast_dtmf_stream(bridge_channel->chan, NULL, dtmf_q, 250, 0);
00853 
00854    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00855 
00856    return;
00857 }

static void bridge_channel_feature ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Internal function that executes a feature on a bridge channel.

Definition at line 778 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_dtmf_stream(), ast_clear_flag, ast_debug, AST_FLAG_END_DTMF_ONLY, AST_LIST_TRAVERSE, ast_set_flag, ast_waitfordigit(), ast_bridge_features_hook::callback, ast_bridge_channel::chan, ast_bridge_features_hook::dtmf, ast_bridge_features_hook::entry, ast_bridge::features, ast_bridge_channel::features, ast_bridge_features_hook::hook_pvt, ast_bridge_features::hooks, and MAXIMUM_DTMF_FEATURE_STRING.

Referenced by bridge_channel_join().

00779 {
00780    struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00781    struct ast_bridge_features_hook *hook = NULL;
00782    char dtmf[MAXIMUM_DTMF_FEATURE_STRING] = "";
00783    int look_for_dtmf = 1, dtmf_len = 0;
00784 
00785    /* The channel is now under our control and we don't really want any begin frames to do our DTMF matching so disable 'em at the core level */
00786    ast_set_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00787 
00788    /* Wait for DTMF on the channel and put it into a buffer. If the buffer matches any feature hook execute the hook. */
00789    while (look_for_dtmf) {
00790       int res = ast_waitfordigit(bridge_channel->chan, 3000);
00791 
00792       /* If the above timed out simply exit */
00793       if (!res) {
00794          ast_debug(1, "DTMF feature string collection on bridge channel %p timed out\n", bridge_channel);
00795          break;
00796       } else if (res < 0) {
00797          ast_debug(1, "DTMF feature string collection failed on bridge channel %p for some reason\n", bridge_channel);
00798          break;
00799       }
00800 
00801       /* Add the above DTMF into the DTMF string so we can do our matching */
00802       dtmf[dtmf_len++] = res;
00803 
00804       ast_debug(1, "DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf);
00805 
00806       /* Assume that we do not want to look for DTMF any longer */
00807       look_for_dtmf = 0;
00808 
00809       /* See if a DTMF feature hook matches or can match */
00810       AST_LIST_TRAVERSE(&features->hooks, hook, entry) {
00811          /* If this hook matches just break out now */
00812          if (!strcmp(hook->dtmf, dtmf)) {
00813             ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel);
00814             break;
00815          } else if (!strncmp(hook->dtmf, dtmf, dtmf_len)) {
00816             ast_debug(1, "DTMF feature hook %p can match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel);
00817             look_for_dtmf = 1;
00818          } else {
00819             ast_debug(1, "DTMF feature hook %p does not match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel);
00820          }
00821       }
00822 
00823       /* If we have reached the maximum length of a DTMF feature string bail out */
00824       if (dtmf_len == MAXIMUM_DTMF_FEATURE_STRING) {
00825          break;
00826       }
00827    }
00828 
00829    /* Since we are done bringing DTMF in return to using both begin and end frames */
00830    ast_clear_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00831 
00832    /* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */
00833    if (hook) {
00834       hook->callback(bridge, bridge_channel, hook->hook_pvt);
00835    } else {
00836       ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan);
00837       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00838    }
00839 
00840    return;
00841 }

static enum ast_bridge_channel_state bridge_channel_join ( struct ast_bridge_channel bridge_channel  )  [static]

Join a channel to a bridge and handle anything the bridge may want us to do.

Definition at line 860 of file bridging.c.

References ao2_lock(), ao2_ref, ao2_unlock(), AST_BRIDGE_CAPABILITY_MULTITHREADED, AST_BRIDGE_CAPABILITY_THREAD, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DTMF, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_FEATURE, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_BRIDGE_CHANNEL_STATE_WAIT, AST_BRIDGE_FLAG_SMART, ast_debug, ast_getformatname(), AST_LIST_INSERT_TAIL, AST_LIST_REMOVE, ast_pthread_create, AST_PTHREADT_NULL, ast_set_read_format(), ast_set_write_format(), ast_test_flag, ast_channel::bridge, ast_bridge_channel::bridge, bridge_array_add(), bridge_array_remove(), bridge_channel_dtmf_stream(), bridge_channel_feature(), bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), bridge_channel_suspend(), bridge_channel_unsuspend(), bridge_check_dissolve(), bridge_make_compatible(), bridge_thread(), ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge::channels, ast_bridge_channel::entry, ast_bridge_features_hook::entry, ast_bridge::feature_flags, find_bridge_channel(), ast_bridge_technology::join, ast_bridge_technology::leave, ast_bridge_technology::name, ast_bridge::num, ast_channel::readformat, smart_bridge_operation(), ast_bridge_channel::state, ast_bridge::stop, ast_bridge_channel::swap, ast_bridge::technology, ast_bridge::thread, ast_bridge_channel::thread, and ast_channel::writeformat.

Referenced by ast_bridge_join(), and bridge_channel_thread().

00861 {
00862    int formats[2] = { bridge_channel->chan->readformat, bridge_channel->chan->writeformat };
00863    enum ast_bridge_channel_state state;
00864 
00865    /* Record the thread that will be the owner of us */
00866    bridge_channel->thread = pthread_self();
00867 
00868    ast_debug(1, "Joining bridge channel %p to bridge %p\n", bridge_channel, bridge_channel->bridge);
00869 
00870    ao2_lock(bridge_channel->bridge);
00871 
00872    state = bridge_channel->state;
00873 
00874    /* Add channel into the bridge */
00875    AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry);
00876    bridge_channel->bridge->num++;
00877 
00878    bridge_array_add(bridge_channel->bridge, bridge_channel->chan);
00879 
00880    if (bridge_channel->swap) {
00881       struct ast_bridge_channel *bridge_channel2 = NULL;
00882 
00883       /* If we are performing a swap operation we do not need to execute the smart bridge operation as the actual number of channels involved will not have changed, we just need to tell the other channel to leave */
00884       if ((bridge_channel2 = find_bridge_channel(bridge_channel->bridge, bridge_channel->swap))) {
00885          ast_debug(1, "Swapping bridge channel %p out from bridge %p so bridge channel %p can slip in\n", bridge_channel2, bridge_channel->bridge, bridge_channel);
00886          ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00887       }
00888 
00889       bridge_channel->swap = NULL;
00890    } else if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
00891       /* Perform the smart bridge operation, basically see if we need to move around between technologies */
00892       smart_bridge_operation(bridge_channel->bridge, bridge_channel, bridge_channel->bridge->num);
00893    }
00894 
00895    /* Make the channel compatible with the bridge */
00896    bridge_make_compatible(bridge_channel->bridge, bridge_channel);
00897 
00898    /* Tell the bridge technology we are joining so they set us up */
00899    if (bridge_channel->bridge->technology->join) {
00900       ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00901       if (bridge_channel->bridge->technology->join(bridge_channel->bridge, bridge_channel)) {
00902          ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00903       }
00904    }
00905 
00906    /* Actually execute the respective threading model, and keep our bridge thread alive */
00907    while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00908       /* Update bridge pointer on channel */
00909       bridge_channel->chan->bridge = bridge_channel->bridge;
00910       /* If the technology requires a thread and one is not running, start it up */
00911       if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
00912          bridge_channel->bridge->stop = 0;
00913          ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
00914          ao2_ref(bridge_channel->bridge, +1);
00915          if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) {
00916             ast_debug(1, "Failed to create a bridge thread for bridge %p, giving it another go.\n", bridge_channel->bridge);
00917             ao2_ref(bridge_channel->bridge, -1);
00918             continue;
00919          }
00920       }
00921       /* Execute the threading model */
00922       state = (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTITHREADED ? bridge_channel_join_multithreaded(bridge_channel) : bridge_channel_join_singlethreaded(bridge_channel));
00923       /* Depending on the above state see what we need to do */
00924       if (state == AST_BRIDGE_CHANNEL_STATE_FEATURE) {
00925          bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00926          bridge_channel_feature(bridge_channel->bridge, bridge_channel);
00927          bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00928       } else if (state == AST_BRIDGE_CHANNEL_STATE_DTMF) {
00929          bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00930          bridge_channel_dtmf_stream(bridge_channel->bridge, bridge_channel);
00931          bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00932       }
00933    }
00934 
00935    bridge_channel->chan->bridge = NULL;
00936 
00937    /* See if we need to dissolve the bridge itself if they hung up */
00938    if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_END) {
00939       bridge_check_dissolve(bridge_channel->bridge, bridge_channel);
00940    }
00941 
00942    /* Tell the bridge technology we are leaving so they tear us down */
00943    if (bridge_channel->bridge->technology->leave) {
00944       ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00945       if (bridge_channel->bridge->technology->leave(bridge_channel->bridge, bridge_channel)) {
00946          ast_debug(1, "Bridge technology %s failed to leave %p from bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00947       }
00948    }
00949 
00950    /* Remove channel from the bridge */
00951    bridge_channel->bridge->num--;
00952    AST_LIST_REMOVE(&bridge_channel->bridge->channels, bridge_channel, entry);
00953 
00954    bridge_array_remove(bridge_channel->bridge, bridge_channel->chan);
00955 
00956    /* Perform the smart bridge operation if needed since a channel has left */
00957    if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
00958       smart_bridge_operation(bridge_channel->bridge, NULL, bridge_channel->bridge->num);
00959    }
00960 
00961    ao2_unlock(bridge_channel->bridge);
00962 
00963    /* Restore original formats of the channel as they came in */
00964    if (bridge_channel->chan->readformat != formats[0]) {
00965       ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]);
00966       if (ast_set_read_format(bridge_channel->chan, formats[0])) {
00967          ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]);
00968       }
00969    }
00970    if (bridge_channel->chan->writeformat != formats[1]) {
00971       ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]);
00972       if (ast_set_write_format(bridge_channel->chan, formats[1])) {
00973          ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]);
00974       }
00975    }
00976 
00977    return bridge_channel->state;
00978 }

static enum ast_bridge_channel_state bridge_channel_join_multithreaded ( struct ast_bridge_channel bridge_channel  )  [static]

Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve.

Definition at line 698 of file bridging.c.

References ao2_lock(), ao2_unlock(), ast_bridge_handle_trip(), ast_cond_wait(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_waitfor_nandfds(), ast_bridge_channel::bridge, ast_bridge_channel::chan, chan, ast_bridge_channel::cond, ast_bridge_technology::fd, ast_bridge_channel::fds, ast_bridge_channel::lock, ast_bridge_channel::state, ast_bridge_channel::suspended, and ast_bridge::technology.

Referenced by bridge_channel_join().

00699 {
00700    int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1;
00701    struct ast_channel *chan = NULL;
00702 
00703    /* Add any file descriptors we may want to monitor */
00704    if (bridge_channel->bridge->technology->fd) {
00705       for (i = 0; i < 4; i ++) {
00706          if (bridge_channel->fds[i] >= 0) {
00707             fds[nfds++] = bridge_channel->fds[i];
00708          }
00709       }
00710    }
00711 
00712    ao2_unlock(bridge_channel->bridge);
00713 
00714    /* Wait for data to either come from the channel or us to be signalled */
00715    if (!bridge_channel->suspended) {
00716       ast_debug(1, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00717       chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms);
00718    } else {
00719       ast_mutex_lock(&bridge_channel->lock);
00720       ast_debug(1, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00721       ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
00722       ast_mutex_unlock(&bridge_channel->lock);
00723    }
00724 
00725    ao2_lock(bridge_channel->bridge);
00726 
00727    if (!bridge_channel->suspended) {
00728       ast_bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd);
00729    }
00730 
00731    return bridge_channel->state;
00732 }

static enum ast_bridge_channel_state bridge_channel_join_singlethreaded ( struct ast_bridge_channel bridge_channel  )  [static]

Run in a singlethreaded model. Each joined channel yields itself to the main bridge thread. TODO: Improve.

Definition at line 735 of file bridging.c.

References ao2_lock(), ao2_unlock(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_cond_wait(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_bridge_channel::bridge, ast_bridge_channel::cond, ast_bridge_channel::lock, and ast_bridge_channel::state.

Referenced by bridge_channel_join().

00736 {
00737    ao2_unlock(bridge_channel->bridge);
00738    ast_mutex_lock(&bridge_channel->lock);
00739    if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00740       ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00741       ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
00742    }
00743    ast_mutex_unlock(&bridge_channel->lock);
00744    ao2_lock(bridge_channel->bridge);
00745 
00746    return bridge_channel->state;
00747 }

static void bridge_channel_suspend ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Internal function that suspends a channel from a bridge.

Definition at line 750 of file bridging.c.

References bridge_array_remove(), ast_bridge_channel::chan, ast_bridge_technology::suspend, ast_bridge_channel::suspended, and ast_bridge::technology.

Referenced by ast_bridge_suspend(), and bridge_channel_join().

00751 {
00752    bridge_channel->suspended = 1;
00753 
00754    bridge_array_remove(bridge, bridge_channel->chan);
00755 
00756    if (bridge->technology->suspend) {
00757       bridge->technology->suspend(bridge, bridge_channel);
00758    }
00759 
00760    return;
00761 }

static void* bridge_channel_thread ( void *  data  )  [static]

Thread responsible for imparted bridged channels.

Definition at line 1008 of file bridging.c.

References ao2_ref, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, ast_cond_destroy(), ast_free, ast_hangup(), ast_mutex_destroy(), ast_bridge_channel::bridge, bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::cond, and ast_bridge_channel::lock.

Referenced by ast_bridge_impart().

01009 {
01010    struct ast_bridge_channel *bridge_channel = data;
01011    enum ast_bridge_channel_state state;
01012 
01013    state = bridge_channel_join(bridge_channel);
01014 
01015    ao2_ref(bridge_channel->bridge, -1);
01016 
01017    /* If no other thread is going to take the channel then hang it up, or else we would have to service it until something else came along */
01018    if (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP) {
01019       ast_hangup(bridge_channel->chan);
01020    }
01021 
01022    /* Destroy elements of the bridge channel structure and the bridge channel structure itself */
01023    ast_mutex_destroy(&bridge_channel->lock);
01024    ast_cond_destroy(&bridge_channel->cond);
01025    ast_free(bridge_channel);
01026 
01027    return NULL;
01028 }

static void bridge_channel_unsuspend ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Internal function that unsuspends a channel from a bridge.

Definition at line 764 of file bridging.c.

References bridge_array_add(), ast_bridge_channel::chan, ast_bridge_channel::suspended, ast_bridge::technology, and ast_bridge_technology::unsuspend.

Referenced by ast_bridge_unsuspend(), and bridge_channel_join().

00765 {
00766    bridge_channel->suspended =0;
00767 
00768    bridge_array_add(bridge, bridge_channel->chan);
00769 
00770    if (bridge->technology->unsuspend) {
00771       bridge->technology->unsuspend(bridge, bridge_channel);
00772    }
00773 
00774    return;
00775 }

static void bridge_check_dissolve ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Internal function to see whether a bridge should dissolve, and if so do it.

Definition at line 218 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DEPART, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_BRIDGE_FLAG_DISSOLVE, ast_debug, AST_LIST_TRAVERSE, ast_test_flag, ast_bridge::channels, ast_bridge_channel::entry, ast_bridge_features::feature_flags, ast_bridge::feature_flags, ast_bridge_channel::features, ast_bridge_channel::state, ast_bridge::stop, and ast_bridge_features::usable.

Referenced by bridge_channel_join().

00219 {
00220    struct ast_bridge_channel *bridge_channel2 = NULL;
00221 
00222    if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE) && (!bridge_channel->features || !bridge_channel->features->usable || !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE))) {
00223       return;
00224    }
00225 
00226    ast_debug(1, "Dissolving bridge %p\n", bridge);
00227 
00228    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) {
00229       if (bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_END && bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_DEPART) {
00230          ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00231       }
00232    }
00233 
00234    /* Since all the channels are going away let's go ahead and stop our on thread */
00235    bridge->stop = 1;
00236 
00237    return;
00238 }

static int bridge_drop_control_frame ( int  subclass  )  [static]

Internal function used to determine whether a control frame should be dropped or not.

Definition at line 265 of file bridging.c.

References AST_CONTROL_ANSWER.

Referenced by ast_bridge_handle_trip().

00266 {
00267    switch (subclass) {
00268    case AST_CONTROL_ANSWER:
00269    case -1:
00270       return 1;
00271    default:
00272       return 0;
00273    }
00274 }

static struct ast_frame* bridge_handle_dtmf ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
struct ast_frame frame 
) [static, read]

Internal function to handle DTMF from a channel.

Definition at line 241 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_FEATURE, ast_frfree, AST_LIST_TRAVERSE, ast_bridge_features_hook::dtmf, ast_bridge_features_hook::entry, ast_bridge::features, ast_bridge_channel::features, ast_bridge_features::hooks, ast_frame::subclass, and ast_bridge_features::usable.

Referenced by ast_bridge_handle_trip().

00242 {
00243    struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00244    struct ast_bridge_features_hook *hook = NULL;
00245 
00246    /* If the features structure we grabbed is not usable immediately return the frame */
00247    if (!features->usable) {
00248       return frame;
00249    }
00250 
00251    /* See if this DTMF matches the beginnings of any feature hooks, if so we switch to the feature state to either execute the feature or collect more DTMF */
00252    AST_LIST_TRAVERSE(&features->hooks, hook, entry) {
00253       if (hook->dtmf[0] == frame->subclass) {
00254          ast_frfree(frame);
00255          frame = NULL;
00256          ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_FEATURE);
00257          break;
00258       }
00259    }
00260 
00261    return frame;
00262 }

static int bridge_make_compatible ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 538 of file bridging.c.

References ast_best_codec(), ast_debug, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_set_read_format(), ast_set_write_format(), ast_bridge_channel::chan, ast_bridge_technology::formats, LOG_WARNING, ast_channel::name, ast_bridge_technology::name, option_debug, ast_channel::readformat, ast_bridge::technology, and ast_channel::writeformat.

Referenced by ast_bridge_merge(), bridge_channel_join(), and smart_bridge_operation().

00539 {
00540    int formats[2] = {bridge_channel->chan->readformat, bridge_channel->chan->writeformat};
00541 
00542    /* Are the formats currently in use something ths bridge can handle? */
00543    if (!(bridge->technology->formats & bridge_channel->chan->readformat)) {
00544       int best_format = ast_best_codec(bridge->technology->formats);
00545 
00546       /* Read format is a no go... */
00547       if (option_debug) {
00548          char codec_buf[512];
00549          ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats);
00550          ast_debug(1, "Bridge technology %s wants to read any of formats %s(%d) but channel has %s(%d)\n", bridge->technology->name, codec_buf, bridge->technology->formats, ast_getformatname(formats[0]), formats[0]);
00551       }
00552       /* Switch read format to the best one chosen */
00553       if (ast_set_read_format(bridge_channel->chan, best_format)) {
00554          ast_log(LOG_WARNING, "Failed to set channel %s to read format %s(%d)\n", bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00555          return -1;
00556       }
00557       ast_debug(1, "Bridge %p put channel %s into read format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00558    } else {
00559       ast_debug(1, "Bridge %p is happy that channel %s already has read format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[0]), formats[0]);
00560    }
00561 
00562    if (!(bridge->technology->formats & formats[1])) {
00563       int best_format = ast_best_codec(bridge->technology->formats);
00564 
00565       /* Write format is a no go... */
00566       if (option_debug) {
00567          char codec_buf[512];
00568          ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats);
00569          ast_debug(1, "Bridge technology %s wants to write any of formats %s(%d) but channel has %s(%d)\n", bridge->technology->name, codec_buf, bridge->technology->formats, ast_getformatname(formats[1]), formats[1]);
00570       }
00571       /* Switch write format to the best one chosen */
00572       if (ast_set_write_format(bridge_channel->chan, best_format)) {
00573          ast_log(LOG_WARNING, "Failed to set channel %s to write format %s(%d)\n", bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00574          return -1;
00575       }
00576       ast_debug(1, "Bridge %p put channel %s into write format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00577    } else {
00578       ast_debug(1, "Bridge %p is happy that channel %s already has write format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[1]), formats[1]);
00579    }
00580 
00581    return 0;
00582 }

static void bridge_poke ( struct ast_bridge bridge  )  [static]

Helper function to poke the bridge thread.

Definition at line 135 of file bridging.c.

References AST_PTHREADT_NULL, AST_PTHREADT_STOP, and ast_bridge::thread.

Referenced by ast_bridge_destroy(), bridge_array_add(), bridge_array_remove(), and smart_bridge_operation().

00136 {
00137    /* Poke the thread just in case */
00138    if (bridge->thread != AST_PTHREADT_NULL && bridge->thread != AST_PTHREADT_STOP) {
00139       pthread_kill(bridge->thread, SIGURG);
00140    }
00141 
00142    return;
00143 }

static void* bridge_thread ( void *  data  )  [static]

Bridge thread function.

Definition at line 353 of file bridging.c.

References ao2_lock(), ao2_ref, ao2_unlock(), ast_bridge::array_num, ast_debug, AST_PTHREADT_NULL, generic_thread_loop(), ast_bridge::refresh, ast_bridge::stop, ast_bridge::technology, ast_bridge::thread, and ast_bridge_technology::thread.

Referenced by bridge_channel_join().

00354 {
00355    struct ast_bridge *bridge = data;
00356    int res = 0;
00357 
00358    ao2_lock(bridge);
00359 
00360    ast_debug(1, "Started bridge thread for %p\n", bridge);
00361 
00362    /* Loop around until we are told to stop */
00363    while (!bridge->stop && bridge->array_num && !res) {
00364       /* In case the refresh bit was set simply set it back to off */
00365       bridge->refresh = 0;
00366 
00367       ast_debug(1, "Launching bridge thread function %p for bridge %p\n", (bridge->technology->thread ? bridge->technology->thread : &generic_thread_loop), bridge);
00368 
00369       /* Execute the appropriate thread function. If the technology does not provide one we use the generic one */
00370       res = (bridge->technology->thread ? bridge->technology->thread(bridge) : generic_thread_loop(bridge));
00371    }
00372 
00373    ast_debug(1, "Ending bridge thread for %p\n", bridge);
00374 
00375    /* Indicate the bridge thread is no longer active */
00376    bridge->thread = AST_PTHREADT_NULL;
00377    ao2_unlock(bridge);
00378 
00379    ao2_ref(bridge, -1);
00380 
00381    return NULL;
00382 }

static void destroy_bridge ( void *  obj  )  [static]

Definition at line 420 of file bridging.c.

References ast_bridge::array, ast_bridge_features_cleanup(), ast_debug, ast_free, ast_module_unref(), ast_bridge_technology::destroy, ast_bridge::features, ast_bridge_technology::mod, ast_bridge_technology::name, and ast_bridge::technology.

Referenced by ast_bridge_new().

00421 {
00422    struct ast_bridge *bridge = obj;
00423 
00424    ast_debug(1, "Actually destroying bridge %p, nobody wants it anymore\n", bridge);
00425 
00426    /* Pass off the bridge to the technology to destroy if needed */
00427    if (bridge->technology->destroy) {
00428       ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge);
00429       if (bridge->technology->destroy(bridge)) {
00430          ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->technology->name, bridge);
00431       }
00432    }
00433 
00434    /* We are no longer using the bridge technology so decrement the module reference count on it */
00435    if (bridge->technology->mod) {
00436       ast_module_unref(bridge->technology->mod);
00437    }
00438 
00439    /* Last but not least clean up the features configuration */
00440    ast_bridge_features_cleanup(&bridge->features);
00441 
00442    /* Drop the array of channels */
00443    ast_free(bridge->array);
00444 
00445    return;
00446 }

static struct ast_bridge_technology* find_best_technology ( int  capabilities  )  [static, read]

Helper function used to find the "best" bridge technology given a specified capabilities.

Definition at line 385 of file bridging.c.

References ast_debug, ast_module_ref(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_bridge_technology::capabilities, ast_bridge_technology::entry, ast_bridge_technology::name, ast_bridge_technology::preference, and ast_bridge_technology::suspended.

Referenced by ast_bridge_check(), ast_bridge_new(), and smart_bridge_operation().

00386 {
00387    struct ast_bridge_technology *current = NULL, *best = NULL;
00388 
00389    AST_RWLIST_RDLOCK(&bridge_technologies);
00390    AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) {
00391       ast_debug(1, "Bridge technology %s has capabilities %d and we want %d\n", current->name, current->capabilities, capabilities);
00392       if (current->suspended) {
00393          ast_debug(1, "Bridge technology %s is suspended. Skipping.\n", current->name);
00394          continue;
00395       }
00396       if (!(current->capabilities & capabilities)) {
00397          ast_debug(1, "Bridge technology %s does not have the capabilities we need.\n", current->name);
00398          continue;
00399       }
00400       if (best && best->preference < current->preference) {
00401          ast_debug(1, "Bridge technology %s has preference %d while %s has preference %d. Skipping.\n", current->name, current->preference, best->name, best->preference);
00402          continue;
00403       }
00404       best = current;
00405    }
00406 
00407    if (best) {
00408       /* Increment it's module reference count if present so it does not get unloaded while in use */
00409       if (best->mod) {
00410          ast_module_ref(best->mod);
00411       }
00412       ast_debug(1, "Chose bridge technology %s\n", best->name);
00413    }
00414 
00415    AST_RWLIST_UNLOCK(&bridge_technologies);
00416 
00417    return best;
00418 }

static struct ast_bridge_channel* find_bridge_channel ( struct ast_bridge bridge,
struct ast_channel chan 
) [static, read]

Helper function to find a bridge channel given a channel.

Definition at line 204 of file bridging.c.

References AST_LIST_TRAVERSE, ast_bridge_channel::chan, ast_bridge::channels, and ast_bridge_channel::entry.

Referenced by ast_bridge_depart(), ast_bridge_handle_trip(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), and bridge_channel_join().

00205 {
00206    struct ast_bridge_channel *bridge_channel = NULL;
00207 
00208    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00209       if (bridge_channel->chan == chan) {
00210          break;
00211       }
00212    }
00213 
00214    return bridge_channel;
00215 }

static int generic_thread_loop ( struct ast_bridge bridge  )  [static]

Generic thread loop, TODO: Rethink this/improve it.

Definition at line 325 of file bridging.c.

References ao2_lock(), ao2_unlock(), ast_bridge::array, ast_bridge::array_num, ast_bridge_handle_trip(), ast_waitfor_n(), first, ast_bridge::refresh, ast_bridge::stop, and ast_bridge::waiting.

Referenced by bridge_thread().

00326 {
00327    while (!bridge->stop && !bridge->refresh && bridge->array_num) {
00328       struct ast_channel *winner = NULL;
00329       int to = -1;
00330 
00331       /* Move channels around for priority reasons if we have more than one channel in our array */
00332       if (bridge->array_num > 1) {
00333          struct ast_channel *first = bridge->array[0];
00334          memmove(bridge->array, bridge->array + 1, sizeof(struct ast_channel *) * (bridge->array_num - 1));
00335          bridge->array[(bridge->array_num - 1)] = first;
00336       }
00337 
00338       /* Wait on the channels */
00339       bridge->waiting = 1;
00340       ao2_unlock(bridge);
00341       winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to);
00342       bridge->waiting = 0;
00343       ao2_lock(bridge);
00344 
00345       /* Process whatever they did */
00346       ast_bridge_handle_trip(bridge, NULL, winner, -1);
00347    }
00348 
00349    return 0;
00350 }

static int smart_bridge_operation ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
int  count 
) [static]

Perform the smart bridge operation. Basically sees if a new bridge technology should be used instead of the current one.

Definition at line 585 of file bridging.c.

References AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_CAPABILITY_THREAD, ast_cond_signal(), ast_debug, AST_LIST_TRAVERSE, ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, bridge_make_compatible(), bridge_poke(), ast_bridge::bridge_pvt, ast_bridge_technology::capabilities, ast_bridge::channels, ast_bridge_channel::cond, ast_bridge_technology::create, ast_bridge_channel::entry, find_best_technology(), ast_bridge_technology::join, ast_bridge_channel::lock, ast_bridge_technology::name, ast_bridge::refresh, ast_bridge::stop, ast_bridge::technology, ast_bridge_channel::thread, and ast_bridge::thread.

Referenced by ast_bridge_merge(), and bridge_channel_join().

00586 {
00587    int new_capabilities = 0;
00588    struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology;
00589    struct ast_bridge temp_bridge = {
00590       .technology = bridge->technology,
00591       .bridge_pvt = bridge->bridge_pvt,
00592    };
00593    struct ast_bridge_channel *bridge_channel2 = NULL;
00594 
00595    /* Based on current feature determine whether we want to change bridge technologies or not */
00596    if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
00597       if (count <= 2) {
00598          ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name);
00599          return 0;
00600       }
00601       new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
00602    } else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
00603       if (count > 2) {
00604          ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name);
00605          return 0;
00606       }
00607       new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
00608    }
00609 
00610    if (!new_capabilities) {
00611       ast_debug(1, "Bridge '%p' has no new capabilities, not performing smart bridge operation.\n", bridge);
00612       return 0;
00613    }
00614 
00615    /* Attempt to find a new bridge technology to satisfy the capabilities */
00616    if (!(new_technology = find_best_technology(new_capabilities))) {
00617       ast_debug(1, "Smart bridge operation was unable to find new bridge technology with capabilities %d to satisfy bridge %p\n", new_capabilities, bridge);
00618       return -1;
00619    }
00620 
00621    ast_debug(1, "Performing smart bridge operation on bridge %p, moving from bridge technology %s to %s\n", bridge, old_technology->name, new_technology->name);
00622 
00623    /* If a thread is currently executing for the current technology tell it to stop */
00624    if (bridge->thread != AST_PTHREADT_NULL) {
00625       /* If the new bridge technology also needs a thread simply tell the bridge thread to refresh itself. This has the benefit of not incurring the cost/time of tearing down and bringing up a new thread. */
00626       if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
00627          ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
00628          bridge->refresh = 1;
00629       } else {
00630          ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge);
00631          bridge->stop = 1;
00632       }
00633       bridge_poke(bridge);
00634    }
00635 
00636    /* Since we are soon going to pass this bridge to a new technology we need to NULL out the bridge_pvt pointer but don't worry as it still exists in temp_bridge, ditto for the old technology */
00637    bridge->bridge_pvt = NULL;
00638    bridge->technology = new_technology;
00639 
00640    /* Pass the bridge to the new bridge technology so it can set it up */
00641    if (new_technology->create) {
00642       ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge);
00643       if (new_technology->create(bridge)) {
00644          ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge);
00645       }
00646    }
00647 
00648    /* Move existing channels over to the new technology, while taking them away from the old one */
00649    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) {
00650       /* Skip over channel that initiated the smart bridge operation */
00651       if (bridge_channel == bridge_channel2) {
00652          continue;
00653       }
00654 
00655       /* First we part them from the old technology */
00656       if (old_technology->leave) {
00657          ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p (really %p)\n", old_technology->name, bridge_channel2, &temp_bridge, bridge);
00658          if (old_technology->leave(&temp_bridge, bridge_channel2)) {
00659             ast_debug(1, "Bridge technology %s failed to allow %p (really %p) to leave bridge %p\n", old_technology->name, bridge_channel2, &temp_bridge, bridge);
00660          }
00661       }
00662 
00663       /* Second we make them compatible again with the bridge */
00664       bridge_make_compatible(bridge, bridge_channel2);
00665 
00666       /* Third we join them to the new technology */
00667       if (new_technology->join) {
00668          ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge);
00669          if (new_technology->join(bridge, bridge_channel2)) {
00670             ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge);
00671          }
00672       }
00673 
00674       /* Fourth we tell them to wake up so they become aware that they above has happened */
00675       pthread_kill(bridge_channel2->thread, SIGURG);
00676       ast_mutex_lock(&bridge_channel2->lock);
00677       ast_cond_signal(&bridge_channel2->cond);
00678       ast_mutex_unlock(&bridge_channel2->lock);
00679    }
00680 
00681    /* Now that all the channels have been moved over we need to get rid of all the information the old technology may have left around */
00682    if (old_technology->destroy) {
00683       ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge);
00684       if (old_technology->destroy(&temp_bridge)) {
00685          ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p (really %p)... some memory may have leaked\n", old_technology->name, &temp_bridge, bridge);
00686       }
00687    }
00688 
00689    /* Finally if the old technology has module referencing remove our reference, we are no longer going to use it */
00690    if (old_technology->mod) {
00691       ast_module_unref(old_technology->mod);
00692    }
00693 
00694    return 0;
00695 }


Variable Documentation

char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING] [static]

Default DTMF keys for built in features

Definition at line 54 of file bridging.c.

void* builtin_features_handlers[AST_BRIDGE_BUILTIN_END] [static]

Function handlers for the built in features

Definition at line 57 of file bridging.c.


Generated by  doxygen 1.6.2