Wed Aug 7 17:15:52 2019

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"

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 (enum ast_bridge_capability 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 (enum ast_bridge_capability 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 (enum ast_bridge_capability 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 55 of file bridging.c.

Referenced by bridge_array_add().

#define BRIDGE_ARRAY_START   128

Definition at line 52 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
mod 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 63 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, LOG_WARNING, ast_bridge_technology::mod, ast_bridge_technology::name, option_verbose, VERBOSE_PREFIX_2, and ast_bridge_technology::write.

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

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 122 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().

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

int ast_bridge_check ( enum ast_bridge_capability  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 502 of file bridging.c.

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

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

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:

 ast_bridge_depart(bridge, chan);

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 1077 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().

01078 {
01079    struct ast_bridge_channel *bridge_channel = NULL;
01080    pthread_t thread;
01081 
01082    ao2_lock(bridge);
01083 
01084    /* Try to find the channel that we want to depart */
01085    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01086       ao2_unlock(bridge);
01087       return -1;
01088    }
01089 
01090    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
01091    thread = bridge_channel->thread;
01092 
01093    ao2_unlock(bridge);
01094 
01095    pthread_join(thread, NULL);
01096 
01097    return 0;
01098 }

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 515 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, AST_PTHREADT_NULL, bridge_poke(), ast_bridge::stop, thread, and ast_bridge::thread.

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

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

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 1345 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, and ast_bridge_channel::dtmf_stream_q.

Referenced by bridge_channel_feature().

01346 {
01347    struct ast_bridge_channel *bridge_channel = NULL;
01348 
01349    ao2_lock(bridge);
01350 
01351    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01352       if (bridge_channel->chan == chan) {
01353          continue;
01354       }
01355       ast_copy_string(bridge_channel->dtmf_stream_q, dtmf, sizeof(bridge_channel->dtmf_stream_q));
01356       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DTMF);
01357    }
01358 
01359    ao2_unlock(bridge);
01360 
01361    return 0;
01362 }

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 1333 of file bridging.c.

References ast_free, and AST_LIST_REMOVE_HEAD.

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

01334 {
01335    struct ast_bridge_features_hook *hook = NULL;
01336 
01337    /* This is relatively simple, hooks are kept as a list on the features structure so we just pop them off and free them */
01338    while ((hook = AST_LIST_REMOVE_HEAD(&features->hooks, entry))) {
01339       ast_free(hook);
01340    }
01341 
01342    return 0;
01343 }

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 1295 of file bridging.c.

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

Referenced by feature_attended_transfer().

01296 {
01297    /* If no alternate DTMF stream was provided use the default one */
01298    if (ast_strlen_zero(dtmf)) {
01299       dtmf = builtin_features_dtmf[feature];
01300       /* If no DTMF is still available (ie: it has been disabled) then error out now */
01301       if (ast_strlen_zero(dtmf)) {
01302          ast_debug(1, "Failed to enable built in feature %u on %p, no DTMF string is available for it.\n", feature, features);
01303          return -1;
01304       }
01305    }
01306 
01307    if (!builtin_features_handlers[feature]) {
01308       return -1;
01309    }
01310 
01311    /* The rest is basically pretty easy. We create another hook using the built in feature's callback and DTMF, easy as pie. */
01312    return ast_bridge_features_hook(features, dtmf, builtin_features_handlers[feature], config);
01313 }

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 1274 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::hook_pvt, and ast_bridge_features::usable.

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

01275 {
01276    struct ast_bridge_features_hook *hook = NULL;
01277 
01278    /* Allocate new memory and setup it's various variables */
01279    if (!(hook = ast_calloc(1, sizeof(*hook)))) {
01280       return -1;
01281    }
01282 
01283    ast_copy_string(hook->dtmf, dtmf, sizeof(hook->dtmf));
01284    hook->callback = callback;
01285    hook->hook_pvt = hook_pvt;
01286 
01287    /* Once done we add it onto the list. Now it will be picked up when DTMF is used */
01288    AST_LIST_INSERT_TAIL(&features->hooks, hook, entry);
01289 
01290    features->usable = 1;
01291 
01292    return 0;
01293 }

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 1322 of file bridging.c.

References AST_LIST_HEAD_INIT_NOLOCK.

Referenced by confbridge_exec(), and feature_attended_transfer().

01323 {
01324    /* Zero out the structure */
01325    memset(features, 0, sizeof(*features));
01326 
01327    /* Initialize the hooks list, just in case */
01328    AST_LIST_HEAD_INIT_NOLOCK(&features->hooks);
01329 
01330    return 0;
01331 }

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 1248 of file bridging.c.

References ast_copy_string(), and ast_strlen_zero().

Referenced by load_module().

01249 {
01250    if (builtin_features_handlers[feature]) {
01251       return -1;
01252    }
01253 
01254    if (!ast_strlen_zero(dtmf)) {
01255       ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
01256    }
01257 
01258    builtin_features_handlers[feature] = callback;
01259 
01260    return 0;
01261 }

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 1315 of file bridging.c.

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

Referenced by feature_attended_transfer().

01316 {
01317    ast_set_flag(&features->feature_flags, flag);
01318    features->usable = 1;
01319    return 0;
01320 }

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 1263 of file bridging.c.

01264 {
01265    if (!builtin_features_handlers[feature]) {
01266       return -1;
01267    }
01268 
01269    builtin_features_handlers[feature] = NULL;
01270 
01271    return 0;
01272 }

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 277 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_frame_subclass::integer, 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().

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

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 1043 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().

01044 {
01045    struct ast_bridge_channel *bridge_channel = NULL;
01046 
01047    /* Try to allocate a structure for the bridge channel */
01048    if (!(bridge_channel = ast_calloc(1, sizeof(*bridge_channel)))) {
01049       return -1;
01050    }
01051 
01052    /* Setup various parameters */
01053    bridge_channel->chan = chan;
01054    bridge_channel->swap = swap;
01055    bridge_channel->bridge = bridge;
01056    bridge_channel->features = features;
01057 
01058    /* Initialize our mutex lock and condition */
01059    ast_mutex_init(&bridge_channel->lock);
01060    ast_cond_init(&bridge_channel->cond, NULL);
01061 
01062    /* Bump up the reference count on the bridge, it'll get decremented later */
01063    ao2_ref(bridge, +1);
01064 
01065    /* Actually create the thread that will handle the channel */
01066    if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
01067       ao2_ref(bridge, -1);
01068       ast_cond_destroy(&bridge_channel->cond);
01069       ast_mutex_destroy(&bridge_channel->lock);
01070       ast_free(bridge_channel);
01071       return -1;
01072    }
01073 
01074    return 0;
01075 }

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 993 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().

00994 {
00995    struct ast_bridge_channel bridge_channel = {
00996       .chan = chan,
00997       .swap = swap,
00998       .bridge = bridge,
00999       .features = features,
01000    };
01001    enum ast_bridge_channel_state state;
01002 
01003    /* Initialize various other elements of the bridge channel structure that we can't do above */
01004    ast_mutex_init(&bridge_channel.lock);
01005    ast_cond_init(&bridge_channel.cond, NULL);
01006 
01007    ao2_ref(bridge_channel.bridge, +1);
01008 
01009    state = bridge_channel_join(&bridge_channel);
01010 
01011    ao2_ref(bridge_channel.bridge, -1);
01012 
01013    /* Destroy some elements of the bridge channel structure above */
01014    ast_mutex_destroy(&bridge_channel.lock);
01015    ast_cond_destroy(&bridge_channel.cond);
01016 
01017    return state;
01018 }

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 1119 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_channel::cond, 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.

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

struct ast_bridge* ast_bridge_new ( enum ast_bridge_capability  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 449 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().

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

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:

 ast_bridge_remove(bridge, chan);

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 1100 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().

01101 {
01102    struct ast_bridge_channel *bridge_channel = NULL;
01103 
01104    ao2_lock(bridge);
01105 
01106    /* Try to find the channel that we want to remove */
01107    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01108       ao2_unlock(bridge);
01109       return -1;
01110    }
01111 
01112    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
01113 
01114    ao2_unlock(bridge);
01115 
01116    return 0;
01117 }

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 1200 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().

01201 {
01202    struct ast_bridge_channel *bridge_channel;
01203 
01204    ao2_lock(bridge);
01205 
01206    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01207       ao2_unlock(bridge);
01208       return -1;
01209    }
01210 
01211    bridge_channel_suspend(bridge, bridge_channel);
01212 
01213    ao2_unlock(bridge);
01214 
01215    return 0;
01216 }

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 1236 of file bridging.c.

References ast_bridge_technology::suspended.

01237 {
01238    technology->suspended = 1;
01239    return;
01240 }

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 99 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::name, option_verbose, and VERBOSE_PREFIX_2.

Referenced by unload_module().

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

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 1242 of file bridging.c.

References ast_bridge_technology::suspended.

01243 {
01244    technology->suspended = 0;
01245    return;
01246 }

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:

 ast_bridge_unsuspend(bridge, chan);

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 1218 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().

01219 {
01220    struct ast_bridge_channel *bridge_channel;
01221 
01222    ao2_lock(bridge);
01223 
01224    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01225       ao2_unlock(bridge);
01226       return -1;
01227    }
01228 
01229    bridge_channel_unsuspend(bridge, bridge_channel);
01230 
01231    ao2_unlock(bridge);
01232 
01233    return 0;
01234 }

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 153 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, and ast_bridge::waiting.

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

00154 {
00155    /* We have to make sure the bridge thread is not using the bridge array before messing with it */
00156    while (bridge->waiting) {
00157       bridge_poke(bridge);
00158       sched_yield();
00159    }
00160 
00161    bridge->array[bridge->array_num++] = chan;
00162 
00163    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);
00164 
00165    /* If the next addition of a channel will exceed our array size grow it out */
00166    if (bridge->array_num == bridge->array_size) {
00167       struct ast_channel **tmp;
00168       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);
00169       if (!(tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel *)))) {
00170          ast_log(LOG_ERROR, "Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge);
00171          return;
00172       }
00173       bridge->array = tmp;
00174       bridge->array_size += BRIDGE_ARRAY_GROW;
00175    }
00176 
00177    return;
00178 }

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 184 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().

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

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 857 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().

00858 {
00859    char dtmf_q[8] = "";
00860 
00861    ast_copy_string(dtmf_q, bridge_channel->dtmf_stream_q, sizeof(dtmf_q));
00862    bridge_channel->dtmf_stream_q[0] = '\0';
00863 
00864    ast_debug(1, "Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel);
00865    ast_dtmf_stream(bridge_channel->chan, NULL, dtmf_q, 250, 0);
00866 
00867    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00868 
00869    return;
00870 }

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 791 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, ast_bridge_channel::features, ast_bridge_features_hook::hook_pvt, and MAXIMUM_DTMF_FEATURE_STRING.

Referenced by bridge_channel_join().

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

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 873 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::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().

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

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 711 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, 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().

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

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 748 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().

00749 {
00750    ao2_unlock(bridge_channel->bridge);
00751    ast_mutex_lock(&bridge_channel->lock);
00752    if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00753       ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00754       ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
00755    }
00756    ast_mutex_unlock(&bridge_channel->lock);
00757    ao2_lock(bridge_channel->bridge);
00758 
00759    return bridge_channel->state;
00760 }

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 763 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().

00764 {
00765    bridge_channel->suspended = 1;
00766 
00767    bridge_array_remove(bridge, bridge_channel->chan);
00768 
00769    if (bridge->technology->suspend) {
00770       bridge->technology->suspend(bridge, bridge_channel);
00771    }
00772 
00773    return;
00774 }

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

Thread responsible for imparted bridged channels.

Definition at line 1021 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().

01022 {
01023    struct ast_bridge_channel *bridge_channel = data;
01024    enum ast_bridge_channel_state state;
01025 
01026    state = bridge_channel_join(bridge_channel);
01027 
01028    ao2_ref(bridge_channel->bridge, -1);
01029 
01030    /* 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 */
01031    if (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP) {
01032       ast_hangup(bridge_channel->chan);
01033    }
01034 
01035    /* Destroy elements of the bridge channel structure and the bridge channel structure itself */
01036    ast_mutex_destroy(&bridge_channel->lock);
01037    ast_cond_destroy(&bridge_channel->cond);
01038    ast_free(bridge_channel);
01039 
01040    return NULL;
01041 }

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 777 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().

00778 {
00779    bridge_channel->suspended =0;
00780 
00781    bridge_array_add(bridge, bridge_channel->chan);
00782 
00783    if (bridge->technology->unsuspend) {
00784       bridge->technology->unsuspend(bridge, bridge_channel);
00785    }
00786 
00787    return;
00788 }

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 222 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_features::feature_flags, ast_bridge::feature_flags, ast_bridge_channel::features, ast_bridge_channel::state, and ast_bridge_features::usable.

Referenced by bridge_channel_join().

00223 {
00224    struct ast_bridge_channel *bridge_channel2 = NULL;
00225 
00226    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))) {
00227       return;
00228    }
00229 
00230    ast_debug(1, "Dissolving bridge %p\n", bridge);
00231 
00232    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) {
00233       if (bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_END && bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_DEPART) {
00234          ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00235       }
00236    }
00237 
00238    return;
00239 }

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 266 of file bridging.c.

References AST_CONTROL_ANSWER.

Referenced by ast_bridge_handle_trip().

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

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 242 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, ast_bridge_channel::features, ast_frame_subclass::integer, ast_frame::subclass, and ast_bridge_features::usable.

Referenced by ast_bridge_handle_trip().

00243 {
00244    struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00245    struct ast_bridge_features_hook *hook = NULL;
00246 
00247    /* If the features structure we grabbed is not usable immediately return the frame */
00248    if (!features->usable) {
00249       return frame;
00250    }
00251 
00252    /* 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 */
00253    AST_LIST_TRAVERSE(&features->hooks, hook, entry) {
00254       if (hook->dtmf[0] == frame->subclass.integer) {
00255          ast_frfree(frame);
00256          frame = NULL;
00257          ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_FEATURE);
00258          break;
00259       }
00260    }
00261 
00262    return frame;
00263 }

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

Definition at line 544 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_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().

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

static void bridge_poke ( struct ast_bridge bridge  )  [static]

Helper function to poke the bridge thread.

Definition at line 139 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().

00140 {
00141    /* Poke the thread just in case */
00142    if (bridge->thread != AST_PTHREADT_NULL && bridge->thread != AST_PTHREADT_STOP) {
00143       pthread_kill(bridge->thread, SIGURG);
00144    }
00145 
00146    return;
00147 }

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

Bridge thread function.

Definition at line 354 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(), and smart_bridge_operation().

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

static void destroy_bridge ( void *  obj  )  [static]

Definition at line 421 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().

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

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

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

Definition at line 386 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::name, ast_bridge_technology::preference, and ast_bridge_technology::suspended.

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

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

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 208 of file bridging.c.

References AST_LIST_TRAVERSE, and ast_bridge_channel::chan.

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

00209 {
00210    struct ast_bridge_channel *bridge_channel = NULL;
00211 
00212    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00213       if (bridge_channel->chan == chan) {
00214          break;
00215       }
00216    }
00217 
00218    return bridge_channel;
00219 }

static int generic_thread_loop ( struct ast_bridge bridge  )  [static]

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

Definition at line 326 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().

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

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 593 of file bridging.c.

References ao2_lock, ao2_unlock, 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, bridge_thread(), ast_bridge_technology::capabilities, ast_bridge_channel::cond, ast_bridge_technology::create, 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().

00594 {
00595    enum ast_bridge_capability new_capabilities = 0;
00596    struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology;
00597    struct ast_bridge temp_bridge = {
00598       .technology = bridge->technology,
00599       .bridge_pvt = bridge->bridge_pvt,
00600    };
00601    struct ast_bridge_channel *bridge_channel2 = NULL;
00602 
00603    /* Based on current feature determine whether we want to change bridge technologies or not */
00604    if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
00605       if (count <= 2) {
00606          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);
00607          return 0;
00608       }
00609       new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
00610    } else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
00611       if (count > 2) {
00612          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);
00613          return 0;
00614       }
00615       new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
00616    }
00617 
00618    if (!new_capabilities) {
00619       ast_debug(1, "Bridge '%p' has no new capabilities, not performing smart bridge operation.\n", bridge);
00620       return 0;
00621    }
00622 
00623    /* Attempt to find a new bridge technology to satisfy the capabilities */
00624    if (!(new_technology = find_best_technology(new_capabilities))) {
00625       ast_debug(1, "Smart bridge operation was unable to find new bridge technology with capabilities %u to satisfy bridge %p\n", new_capabilities, bridge);
00626       return -1;
00627    }
00628 
00629    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);
00630 
00631    /* If a thread is currently executing for the current technology tell it to stop */
00632    if (bridge->thread != AST_PTHREADT_NULL) {
00633       /* 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. */
00634       if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
00635          ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
00636          bridge->refresh = 1;
00637          bridge_poke(bridge);
00638       } else {
00639          pthread_t bridge_thread = bridge->thread;
00640          ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge);
00641          bridge->stop = 1;
00642          bridge_poke(bridge);
00643          ao2_unlock(bridge);
00644          pthread_join(bridge_thread, NULL);
00645          ao2_lock(bridge);
00646       }
00647    }
00648 
00649    /* 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 */
00650    bridge->bridge_pvt = NULL;
00651    bridge->technology = new_technology;
00652 
00653    /* Pass the bridge to the new bridge technology so it can set it up */
00654    if (new_technology->create) {
00655       ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge);
00656       if (new_technology->create(bridge)) {
00657          ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge);
00658       }
00659    }
00660 
00661    /* Move existing channels over to the new technology, while taking them away from the old one */
00662    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) {
00663       /* Skip over channel that initiated the smart bridge operation */
00664       if (bridge_channel == bridge_channel2) {
00665          continue;
00666       }
00667 
00668       /* First we part them from the old technology */
00669       if (old_technology->leave) {
00670          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);
00671          if (old_technology->leave(&temp_bridge, bridge_channel2)) {
00672             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);
00673          }
00674       }
00675 
00676       /* Second we make them compatible again with the bridge */
00677       bridge_make_compatible(bridge, bridge_channel2);
00678 
00679       /* Third we join them to the new technology */
00680       if (new_technology->join) {
00681          ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge);
00682          if (new_technology->join(bridge, bridge_channel2)) {
00683             ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge);
00684          }
00685       }
00686 
00687       /* Fourth we tell them to wake up so they become aware that they above has happened */
00688       pthread_kill(bridge_channel2->thread, SIGURG);
00689       ast_mutex_lock(&bridge_channel2->lock);
00690       ast_cond_signal(&bridge_channel2->cond);
00691       ast_mutex_unlock(&bridge_channel2->lock);
00692    }
00693 
00694    /* 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 */
00695    if (old_technology->destroy) {
00696       ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge);
00697       if (old_technology->destroy(&temp_bridge)) {
00698          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);
00699       }
00700    }
00701 
00702    /* Finally if the old technology has module referencing remove our reference, we are no longer going to use it */
00703    if (old_technology->mod) {
00704       ast_module_unref(old_technology->mod);
00705    }
00706 
00707    return 0;
00708 }


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 58 of file bridging.c.

void* builtin_features_handlers[AST_BRIDGE_BUILTIN_END] [static]

Function handlers for the built in features

Definition at line 61 of file bridging.c.


Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1