Fri Feb 10 06:35:01 2012

Asterisk developer's documentation


bridging.c File Reference

Channel Bridging API. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_technology.h"
#include "asterisk/app.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/test.h"

Include dependency graph for bridging.c:

Go to the source code of this file.

Data Structures

struct  bridge_technologies

Defines

#define BRIDGE_ARRAY_GROW   32
#define BRIDGE_ARRAY_START   128

Functions

int __ast_bridge_technology_register (struct ast_bridge_technology *technology, struct ast_module *module)
 Register a bridge technology for use.
static void __fini_bridge_technologies (void)
static void __init_bridge_technologies (void)
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 (uint32_t 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, ast_bridge_features_hook_pvt_destructor destructor)
 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_set_talk_detector (struct ast_bridge_features *features, ast_bridge_talking_indicate_callback talker_cb, ast_bridge_talking_indicate_destructor talker_destructor, void *pvt_data)
 Set a callback on the features structure to receive talking notifications on.
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, int allow_hangup)
 Impart (non-blocking) a channel on a bridge.
int ast_bridge_is_video_src (struct ast_bridge *bridge, struct ast_channel *chan)
 Determine if a channel is a video src for the 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, struct ast_bridge_tech_optimizations *tech_args)
 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 (uint32_t capabilities, int flags)
 Create a new bridge.
void ast_bridge_notify_talking (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int started_talking)
 Lets the bridging indicate when a bridge channel has stopped or started talking.
int ast_bridge_number_video_src (struct ast_bridge *bridge)
 Returns the number of video sources currently active in the bridge.
int ast_bridge_remove (struct ast_bridge *bridge, struct ast_channel *chan)
 Remove a channel from a bridge.
void ast_bridge_remove_video_src (struct ast_bridge *bridge, struct ast_channel *chan)
 remove a channel as a source of video for the bridge.
void ast_bridge_set_internal_sample_rate (struct ast_bridge *bridge, unsigned int sample_rate)
 Adjust the internal mixing sample rate of a bridge used during multimix mode.
void ast_bridge_set_mixing_interval (struct ast_bridge *bridge, unsigned int mixing_interval)
 Adjust the internal mixing interval of a bridge used during multimix mode.
void ast_bridge_set_single_src_video_mode (struct ast_bridge *bridge, struct ast_channel *video_src_chan)
 Set a bridge to feed a single video source to all participants.
void ast_bridge_set_talker_src_video_mode (struct ast_bridge *bridge)
 Set the bridge to pick the strongest talker supporting video as the single source video feed.
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.
void ast_bridge_update_talker_src_video_mode (struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyframe)
 Update information about talker energy for talker src video mode.
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 struct ast_bridge_channelbridge_channel_alloc (struct ast_bridge *bridge)
static void bridge_channel_destroy (void *obj)
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_talking (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
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 cleanup_video_mode (struct ast_bridge *bridge)
static void destroy_bridge (void *obj)
static struct
ast_bridge_technology
find_best_technology (uint32_t 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 52 of file bridging.c.

Referenced by bridge_array_add().

#define BRIDGE_ARRAY_START   128

Definition at line 49 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 62 of file bridging.c.

References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), ast_verb, ast_bridge_technology::capabilities, LOG_WARNING, ast_bridge_technology::mod, ast_bridge_technology::name, and ast_bridge_technology::write.

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

static void __fini_bridge_technologies ( void   )  [static]

Definition at line 46 of file bridging.c.

00063 {

static void __init_bridge_technologies ( void   )  [static]

Definition at line 46 of file bridging.c.

00063 {

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

References ao2_lock, ao2_unlock, ast_cond_signal, ast_bridge_channel::cond, 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_notify_talking(), ast_bridge_remove(), attended_abort_transfer(), attended_threeway_transfer(), bridge_channel_dtmf_stream(), bridge_channel_feature(), bridge_channel_join(), bridge_channel_talking(), bridge_check_dissolve(), bridge_handle_dtmf(), feature_attended_transfer(), feature_blind_transfer(), and feature_hangup().

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

int ast_bridge_check ( uint32_t  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 516 of file bridging.c.

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

00517 {
00518    struct ast_bridge_technology *bridge_technology = NULL;
00519 
00520    if (!(bridge_technology = find_best_technology(capabilities))) {
00521       return 0;
00522    }
00523 
00524    ast_module_unref(bridge_technology->mod);
00525 
00526    return 1;
00527 }

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 1164 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_helper().

01165 {
01166    struct ast_bridge_channel *bridge_channel = NULL;
01167    pthread_t thread;
01168 
01169    ao2_lock(bridge);
01170 
01171    /* Try to find the channel that we want to depart */
01172    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01173       ao2_unlock(bridge);
01174       return -1;
01175    }
01176 
01177    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
01178    thread = bridge_channel->thread;
01179 
01180    ao2_unlock(bridge);
01181 
01182    pthread_join(thread, NULL);
01183 
01184    return 0;
01185 }

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

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

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

00530 {
00531    struct ast_bridge_channel *bridge_channel = NULL;
00532 
00533    ao2_lock(bridge);
00534 
00535    bridge->stop = 1;
00536 
00537    bridge_poke(bridge);
00538 
00539    ast_debug(1, "Telling all channels in bridge %p to end and leave the party\n", bridge);
00540 
00541    /* Drop every bridged channel, the last one will cause the bridge thread (if it exists) to exit */
00542    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00543       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00544    }
00545 
00546    ao2_unlock(bridge);
00547 
00548    ao2_ref(bridge, -1);
00549 
00550    return 0;
00551 }

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

01456 {
01457    struct ast_bridge_channel *bridge_channel = NULL;
01458 
01459    ao2_lock(bridge);
01460 
01461    AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01462       if (bridge_channel->chan == chan) {
01463          continue;
01464       }
01465       ast_copy_string(bridge_channel->dtmf_stream_q, dtmf, sizeof(bridge_channel->dtmf_stream_q));
01466       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DTMF);
01467    }
01468 
01469    ao2_unlock(bridge);
01470 
01471    return 0;
01472 }

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

References ast_free, AST_LIST_REMOVE_HEAD, ast_bridge_features_hook::destructor, ast_bridge_features_hook::hook_pvt, ast_bridge_features::talker_destructor_cb, and ast_bridge_features::talker_pvt_data.

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

01437 {
01438    struct ast_bridge_features_hook *hook = NULL;
01439 
01440    /* This is relatively simple, hooks are kept as a list on the features structure so we just pop them off and free them */
01441    while ((hook = AST_LIST_REMOVE_HEAD(&features->hooks, entry))) {
01442       if (hook->destructor) {
01443          hook->destructor(hook->hook_pvt);
01444       }
01445       ast_free(hook);
01446    }
01447    if (features->talker_destructor_cb && features->talker_pvt_data) {
01448       features->talker_destructor_cb(features->talker_pvt_data);
01449       features->talker_pvt_data = NULL;
01450    }
01451 
01452    return 0;
01453 }

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

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

Referenced by feature_attended_transfer().

01399 {
01400    /* If no alternate DTMF stream was provided use the default one */
01401    if (ast_strlen_zero(dtmf)) {
01402       dtmf = builtin_features_dtmf[feature];
01403       /* If no DTMF is still available (ie: it has been disabled) then error out now */
01404       if (ast_strlen_zero(dtmf)) {
01405          ast_debug(1, "Failed to enable built in feature %d on %p, no DTMF string is available for it.\n", feature, features);
01406          return -1;
01407       }
01408    }
01409 
01410    if (!builtin_features_handlers[feature]) {
01411       return -1;
01412    }
01413 
01414    /* The rest is basically pretty easy. We create another hook using the built in feature's callback and DTMF, easy as pie. */
01415    return ast_bridge_features_hook(features, dtmf, builtin_features_handlers[feature], config, NULL);
01416 }

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

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
Optional destructor callback for hook_pvt 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, 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 1361 of file bridging.c.

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

Referenced by ast_bridge_features_enable(), and feature_attended_transfer().

01366 {
01367    struct ast_bridge_features_hook *hook = NULL;
01368 
01369    /* Allocate new memory and setup it's various variables */
01370    if (!(hook = ast_calloc(1, sizeof(*hook)))) {
01371       return -1;
01372    }
01373 
01374    ast_copy_string(hook->dtmf, dtmf, sizeof(hook->dtmf));
01375    hook->callback = callback;
01376    hook->destructor = destructor;
01377    hook->hook_pvt = hook_pvt;
01378 
01379    /* Once done we add it onto the list. Now it will be picked up when DTMF is used */
01380    AST_LIST_INSERT_TAIL(&features->hooks, hook, entry);
01381 
01382    features->usable = 1;
01383 
01384    return 0;
01385 }

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

References AST_LIST_HEAD_INIT_NOLOCK.

Referenced by confbridge_exec(), and feature_attended_transfer().

01426 {
01427    /* Zero out the structure */
01428    memset(features, 0, sizeof(*features));
01429 
01430    /* Initialize the hooks list, just in case */
01431    AST_LIST_HEAD_INIT_NOLOCK(&features->hooks);
01432 
01433    return 0;
01434 }

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

References ast_copy_string(), and ast_strlen_zero().

Referenced by load_module().

01336 {
01337    if (builtin_features_handlers[feature]) {
01338       return -1;
01339    }
01340 
01341    if (!ast_strlen_zero(dtmf)) {
01342       ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
01343    }
01344 
01345    builtin_features_handlers[feature] = callback;
01346 
01347    return 0;
01348 }

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

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

Referenced by feature_attended_transfer().

01419 {
01420    ast_set_flag(&features->feature_flags, flag);
01421    features->usable = 1;
01422    return 0;
01423 }

int ast_bridge_features_set_talk_detector ( struct ast_bridge_features features,
ast_bridge_talking_indicate_callback  talker_cb,
ast_bridge_talking_indicate_destructor  talker_destructor,
void *  pvt_data 
)

Set a callback on the features structure to receive talking notifications on.

Parameters:
features Bridge features structure
talker_cb,Callback function to execute when talking events occur in the bridge core.
pvt_data Optional unique data that will be passed with the talking events.
Optional destructor callback for pvt data.
Return values:
0,success 
-1,failure 

Definition at line 1387 of file bridging.c.

References ast_bridge_features::talker_cb, ast_bridge_features::talker_destructor_cb, and ast_bridge_features::talker_pvt_data.

Referenced by confbridge_exec().

01391 {
01392    features->talker_cb = talker_cb;
01393    features->talker_destructor_cb = talker_destructor;
01394    features->talker_pvt_data = pvt_data;
01395    return 0;
01396 }

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

01351 {
01352    if (!builtin_features_handlers[feature]) {
01353       return -1;
01354    }
01355 
01356    builtin_features_handlers[feature] = NULL;
01357 
01358    return 0;
01359 }

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 284 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_FRAME_DTMF_END, ast_frfree, ast_read(), ast_read_noaudio(), bridge_drop_control_frame(), bridge_handle_dtmf(), ast_bridge_features::dtmf_passthrough, 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().

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

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

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
allow_hangup Indicates if the bridge thread should manage hanging up of the channel or not.
Return values:
0 on success
-1 on failure
Example usage:

 ast_bridge_impart(bridge, chan, NULL, NULL, 0);

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

References ast_bridge_channel::allow_impart_hangup, ao2_ref, ast_pthread_create, bridge_channel_alloc(), bridge_channel_thread(), ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_channel::swap, and ast_bridge_channel::thread.

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

01141 {
01142    struct ast_bridge_channel *bridge_channel = bridge_channel_alloc(bridge);
01143    /* Try to allocate a structure for the bridge channel */
01144    if (!(bridge_channel)) {
01145       return -1;
01146    }
01147 
01148    /* Setup various parameters */
01149    bridge_channel->chan = chan;
01150    bridge_channel->swap = swap;
01151    bridge_channel->features = features;
01152    bridge_channel->allow_impart_hangup = allow_hangup;
01153 
01154 
01155    /* Actually create the thread that will handle the channel */
01156    if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
01157       ao2_ref(bridge_channel, -1);
01158       return -1;
01159    }
01160 
01161    return 0;
01162 }

int ast_bridge_is_video_src ( struct ast_bridge bridge,
struct ast_channel chan 
)

Determine if a channel is a video src for the bridge.

Return values:
0 Not a current video source of the bridge.
None 0, is a video source of the bridge, The number returned represents the priority this video stream has on the bridge where 1 is the highest priority.

Definition at line 1594 of file bridging.c.

References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.

Referenced by handle_video_on_exit(), handle_video_on_join(), softmix_bridge_write(), and softmix_pass_video_top_priority().

01595 {
01596    int res = 0;
01597 
01598    ao2_lock(bridge);
01599    switch (bridge->video_mode.mode) {
01600    case AST_BRIDGE_VIDEO_MODE_NONE:
01601       break;
01602    case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
01603       if (bridge->video_mode.mode_data.single_src_data.chan_vsrc == chan) {
01604          res = 1;
01605       }
01606       break;
01607    case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
01608       if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc == chan) {
01609          res = 1;
01610       } else if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
01611          res = 2;
01612       }
01613 
01614    }
01615    ao2_unlock(bridge);
01616    return res;
01617 }

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,
struct ast_bridge_tech_optimizations tech_args 
)

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
(Optional) Bridging tech optimization parameters for this channel.
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 1080 of file bridging.c.

References ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CHANNEL_STATE_HANGUP, bridge_channel_alloc(), bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_channel::swap, and ast_bridge_channel::tech_args.

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

01085 {
01086    struct ast_bridge_channel *bridge_channel = bridge_channel_alloc(bridge);
01087    enum ast_bridge_channel_state state = AST_BRIDGE_CHANNEL_STATE_HANGUP;
01088 
01089    if (!bridge_channel) {
01090       return state;
01091    }
01092    if (tech_args) {
01093       memcpy(&bridge_channel->tech_args, tech_args, sizeof(bridge_channel->tech_args));
01094    }
01095 
01096    /* Initialize various other elements of the bridge channel structure that we can't do above */
01097    bridge_channel->chan = chan;
01098    bridge_channel->swap = swap;
01099    bridge_channel->features = features;
01100 
01101    state = bridge_channel_join(bridge_channel);
01102 
01103    /* Cleanup all the data in the bridge channel after it leaves the bridge. */
01104    ao2_lock(bridge_channel);
01105    bridge_channel->chan = NULL;
01106    bridge_channel->swap = NULL;
01107    bridge_channel->features = NULL;
01108    ao2_unlock(bridge_channel);
01109 
01110    ao2_ref(bridge_channel, -1);
01111 
01112    return state;
01113 }

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 1206 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_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_technology::name, ast_bridge::num, smart_bridge_operation(), ast_bridge::technology, ast_bridge_channel::thread, and ast_bridge::thread.

01207 {
01208    struct ast_bridge_channel *bridge_channel = NULL;
01209 
01210    ao2_lock(bridge0);
01211    ao2_lock(bridge1);
01212 
01213    /* If the first bridge currently has 2 channels and is not capable of becoming a multimixing bridge we can not merge */
01214    if ((bridge0->num + bridge1->num) > 2 && (!(bridge0->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) && !ast_test_flag(&bridge0->feature_flags, AST_BRIDGE_FLAG_SMART))) {
01215       ao2_unlock(bridge1);
01216       ao2_unlock(bridge0);
01217       ast_debug(1, "Can't merge bridge %p into bridge %p, multimix is needed and it could not be acquired.\n", bridge1, bridge0);
01218       return -1;
01219    }
01220 
01221    ast_debug(1, "Merging channels from bridge %p into bridge %p\n", bridge1, bridge0);
01222 
01223    /* Perform smart bridge operation on bridge we are merging into so it can change bridge technology if needed */
01224    if (smart_bridge_operation(bridge0, NULL, bridge0->num + bridge1->num)) {
01225       ao2_unlock(bridge1);
01226       ao2_unlock(bridge0);
01227       ast_debug(1, "Can't merge bridge %p into bridge %p, tried to perform smart bridge operation and failed.\n", bridge1, bridge0);
01228       return -1;
01229    }
01230 
01231    /* If a thread is currently executing on bridge1 tell it to stop */
01232    if (bridge1->thread) {
01233       ast_debug(1, "Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0);
01234       bridge1->thread = AST_PTHREADT_STOP;
01235    }
01236 
01237    /* Move channels from bridge1 over to bridge0 */
01238    while ((bridge_channel = AST_LIST_REMOVE_HEAD(&bridge1->channels, entry))) {
01239       /* Tell the technology handling bridge1 that the bridge channel is leaving */
01240       if (bridge1->technology->leave) {
01241          ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01242          if (bridge1->technology->leave(bridge1, bridge_channel)) {
01243             ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01244          }
01245       }
01246 
01247       /* Drop channel count and reference count on the bridge they are leaving */
01248       bridge1->num--;
01249       ao2_ref(bridge1, -1);
01250 
01251       bridge_array_remove(bridge1, bridge_channel->chan);
01252 
01253       /* Now add them into the bridge they are joining, increase channel count, and bump up reference count */
01254       bridge_channel->bridge = bridge0;
01255       AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, entry);
01256       bridge0->num++;
01257       ao2_ref(bridge0, +1);
01258 
01259       bridge_array_add(bridge0, bridge_channel->chan);
01260 
01261       /* Make the channel compatible with the new bridge it is joining or else formats would go amuck */
01262       bridge_make_compatible(bridge0, bridge_channel);
01263 
01264       /* Tell the technology handling bridge0 that the bridge channel is joining */
01265       if (bridge0->technology->join) {
01266          ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01267          if (bridge0->technology->join(bridge0, bridge_channel)) {
01268             ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01269          }
01270       }
01271 
01272       /* Poke the bridge channel, this will cause it to wake up and execute the proper threading model for the new bridge it is in */
01273       pthread_kill(bridge_channel->thread, SIGURG);
01274       ao2_lock(bridge_channel);
01275       ast_cond_signal(&bridge_channel->cond);
01276       ao2_unlock(bridge_channel);
01277    }
01278 
01279    ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge1, bridge0);
01280 
01281    ao2_unlock(bridge1);
01282    ao2_unlock(bridge0);
01283 
01284    return 0;
01285 }

struct ast_bridge* ast_bridge_new ( uint32_t  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 464 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().

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

void ast_bridge_notify_talking ( struct ast_bridge bridge,
struct ast_bridge_channel bridge_channel,
int  started_talking 
)

Lets the bridging indicate when a bridge channel has stopped or started talking.

Note:
All DSP functionality on the bridge has been pushed down to the lowest possible layer, which in this case is the specific bridging technology being used. Since it is necessary for the knowledge of which channels are talking to make its way up to the application, this function has been created to allow the bridging technology to communicate that information with the bridging core.
Parameters:
bridge The bridge that the channel is a part of.
bridge_channel The bridge channel that has either started or stopped talking.
started_talking,set to 1 when this indicates the channel has started talking, set to 0 when this indicates the channel has stopped talking.

Definition at line 275 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_START_TALKING, and AST_BRIDGE_CHANNEL_STATE_STOP_TALKING.

Referenced by softmix_bridge_write().

00276 {
00277    if (started_talking) {
00278       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_START_TALKING);
00279    } else {
00280       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_STOP_TALKING);
00281    }
00282 }

int ast_bridge_number_video_src ( struct ast_bridge bridge  ) 

Returns the number of video sources currently active in the bridge.

Definition at line 1569 of file bridging.c.

References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.

Referenced by softmix_bridge_write().

01570 {
01571    int res = 0;
01572 
01573    ao2_lock(bridge);
01574    switch (bridge->video_mode.mode) {
01575    case AST_BRIDGE_VIDEO_MODE_NONE:
01576       break;
01577    case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
01578       if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) {
01579          res = 1;
01580       }
01581       break;
01582    case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
01583       if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) {
01584          res++;
01585       }
01586       if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
01587          res++;
01588       }
01589    }
01590    ao2_unlock(bridge);
01591    return res;
01592 }

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

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

Referenced by action_confbridgekick(), action_kick_last(), conf_stop_record(), execute_menu_entry(), handle_cli_confbridge_kick(), and leave_conference_bridge().

01188 {
01189    struct ast_bridge_channel *bridge_channel = NULL;
01190 
01191    ao2_lock(bridge);
01192 
01193    /* Try to find the channel that we want to remove */
01194    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01195       ao2_unlock(bridge);
01196       return -1;
01197    }
01198 
01199    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
01200 
01201    ao2_unlock(bridge);
01202 
01203    return 0;
01204 }

void ast_bridge_remove_video_src ( struct ast_bridge bridge,
struct ast_channel chan 
)

remove a channel as a source of video for the bridge.

Definition at line 1619 of file bridging.c.

References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_channel_unref, ast_bridge_video_talker_src_data::average_talking_energy, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.

Referenced by handle_video_on_exit().

01620 {
01621    ao2_lock(bridge);
01622    switch (bridge->video_mode.mode) {
01623    case AST_BRIDGE_VIDEO_MODE_NONE:
01624       break;
01625    case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC:
01626       if (bridge->video_mode.mode_data.single_src_data.chan_vsrc == chan) {
01627          if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) {
01628             ast_channel_unref(bridge->video_mode.mode_data.single_src_data.chan_vsrc);
01629          }
01630          bridge->video_mode.mode_data.single_src_data.chan_vsrc = NULL;
01631       }
01632       break;
01633    case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
01634       if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc == chan) {
01635          if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) {
01636             ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc);
01637          }
01638          bridge->video_mode.mode_data.talker_src_data.chan_vsrc = NULL;
01639          bridge->video_mode.mode_data.talker_src_data.average_talking_energy = 0;
01640       }
01641       if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) {
01642          if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) {
01643             ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc);
01644          }
01645          bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc = NULL;
01646       }
01647    }
01648    ao2_unlock(bridge);
01649 }

void ast_bridge_set_internal_sample_rate ( struct ast_bridge bridge,
unsigned int  sample_rate 
)

Adjust the internal mixing sample rate of a bridge used during multimix mode.

Parameters:
bridge_channel Channel to change the sample rate on.
sample rate, the sample rate to change to. If a value of 0 is passed here, the bridge will be free to pick what ever sample rate it chooses.

Definition at line 1481 of file bridging.c.

References ao2_lock, ao2_unlock, and ast_bridge::internal_sample_rate.

Referenced by join_conference_bridge().

01482 {
01483 
01484    ao2_lock(bridge);
01485    bridge->internal_sample_rate = sample_rate;
01486    ao2_unlock(bridge);
01487 }

void ast_bridge_set_mixing_interval ( struct ast_bridge bridge,
unsigned int  mixing_interval 
)

Adjust the internal mixing interval of a bridge used during multimix mode.

Parameters:
bridge_channel Channel to change the sample rate on.
mixing_interval,the sample rate to change to. If 0 is set the bridge tech is free to choose any mixing interval it uses by default.

Definition at line 1474 of file bridging.c.

References ao2_lock, ao2_unlock, and ast_bridge::internal_mixing_interval.

Referenced by join_conference_bridge().

01475 {
01476    ao2_lock(bridge);
01477    bridge->internal_mixing_interval = mixing_interval;
01478    ao2_unlock(bridge);
01479 }

void ast_bridge_set_single_src_video_mode ( struct ast_bridge bridge,
struct ast_channel video_src_chan 
)

Set a bridge to feed a single video source to all participants.

Definition at line 1510 of file bridging.c.

References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, ast_channel_name(), ast_channel_ref, AST_CONTROL_VIDUPDATE, ast_indicate(), ast_test_suite_event_notify, ast_bridge_video_single_src_data::chan_vsrc, cleanup_video_mode(), ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, and ast_bridge::video_mode.

Referenced by action_confbridgesetsinglevideosrc(), execute_menu_entry(), handle_video_on_exit(), and handle_video_on_join().

01511 {
01512    ao2_lock(bridge);
01513    cleanup_video_mode(bridge);
01514    bridge->video_mode.mode = AST_BRIDGE_VIDEO_MODE_SINGLE_SRC;
01515    bridge->video_mode.mode_data.single_src_data.chan_vsrc = ast_channel_ref(video_src_chan);
01516    ast_test_suite_event_notify("BRIDGE_VIDEO_MODE", "Message: video mode set to single source\r\nVideo Mode: %d\r\nVideo Channel: %s", bridge->video_mode.mode, ast_channel_name(video_src_chan));
01517    ast_indicate(video_src_chan, AST_CONTROL_VIDUPDATE);
01518    ao2_unlock(bridge);
01519 }

void ast_bridge_set_talker_src_video_mode ( struct ast_bridge bridge  ) 

Set the bridge to pick the strongest talker supporting video as the single source video feed.

Definition at line 1521 of file bridging.c.

References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_test_suite_event_notify, cleanup_video_mode(), ast_bridge_video_mode::mode, and ast_bridge::video_mode.

Referenced by handle_video_on_exit(), and join_conference_bridge().

01522 {
01523    ao2_lock(bridge);
01524    cleanup_video_mode(bridge);
01525    bridge->video_mode.mode = AST_BRIDGE_VIDEO_MODE_TALKER_SRC;
01526    ast_test_suite_event_notify("BRIDGE_VIDEO_MODE", "Message: video mode set to talker source\r\nVideo Mode: %d", bridge->video_mode.mode);
01527    ao2_unlock(bridge);
01528 }

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:

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

01288 {
01289    struct ast_bridge_channel *bridge_channel;
01290 
01291    ao2_lock(bridge);
01292 
01293    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01294       ao2_unlock(bridge);
01295       return -1;
01296    }
01297 
01298    bridge_channel_suspend(bridge, bridge_channel);
01299 
01300    ao2_unlock(bridge);
01301 
01302    return 0;
01303 }

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

References ast_bridge_technology::suspended.

01324 {
01325    technology->suspended = 1;
01326    return;
01327 }

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 96 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_verb, and ast_bridge_technology::name.

Referenced by unload_module().

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

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

References ast_bridge_technology::suspended.

01330 {
01331    technology->suspended = 0;
01332    return;
01333 }

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

01306 {
01307    struct ast_bridge_channel *bridge_channel;
01308 
01309    ao2_lock(bridge);
01310 
01311    if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01312       ao2_unlock(bridge);
01313       return -1;
01314    }
01315 
01316    bridge_channel_unsuspend(bridge, bridge_channel);
01317 
01318    ao2_unlock(bridge);
01319 
01320    return 0;
01321 }

void ast_bridge_update_talker_src_video_mode ( struct ast_bridge bridge,
struct ast_channel chan,
int  talker_energy,
int  is_keyframe 
)

Update information about talker energy for talker src video mode.

Definition at line 1530 of file bridging.c.

References ao2_lock, ao2_unlock, ast_channel_name(), ast_channel_ref, ast_channel_unref, AST_CONTROL_VIDUPDATE, ast_format_cap_has_type(), AST_FORMAT_TYPE_VIDEO, ast_indicate(), ast_test_suite_event_notify, ast_bridge_video_talker_src_data::average_talking_energy, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_mode::mode_data, ast_channel::nativeformats, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.

Referenced by softmix_bridge_write().

01531 {
01532    struct ast_bridge_video_talker_src_data *data;
01533    /* If the channel doesn't support video, we don't care about it */
01534    if (!ast_format_cap_has_type(chan->nativeformats, AST_FORMAT_TYPE_VIDEO)) {
01535       return;
01536    }
01537 
01538    ao2_lock(bridge);
01539    data = &bridge->video_mode.mode_data.talker_src_data;
01540 
01541    if (data->chan_vsrc == chan) {
01542       data->average_talking_energy = talker_energy;
01543    } else if ((data->average_talking_energy < talker_energy) && is_keyframe) {
01544       if (data->chan_old_vsrc) {
01545          ast_channel_unref(data->chan_old_vsrc);
01546       }
01547       if (data->chan_vsrc) {
01548          data->chan_old_vsrc = data->chan_vsrc;
01549          ast_indicate(data->chan_old_vsrc, AST_CONTROL_VIDUPDATE);
01550       }
01551       data->chan_vsrc = ast_channel_ref(chan);
01552       data->average_talking_energy = talker_energy;
01553       ast_test_suite_event_notify("BRIDGE_VIDEO_SRC", "Message: video source updated\r\nVideo Channel: %s", ast_channel_name(data->chan_vsrc));
01554       ast_indicate(data->chan_vsrc, AST_CONTROL_VIDUPDATE);
01555    } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) {
01556       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
01557    } else if (!data->chan_vsrc && is_keyframe) {
01558       data->chan_vsrc = ast_channel_ref(chan);
01559       data->average_talking_energy = talker_energy;
01560       ast_test_suite_event_notify("BRIDGE_VIDEO_SRC", "Message: video source updated\r\nVideo Channel: %s", ast_channel_name(data->chan_vsrc));
01561       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
01562    } else if (!data->chan_old_vsrc && is_keyframe) {
01563       data->chan_old_vsrc = ast_channel_ref(chan);
01564       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
01565    }
01566    ao2_unlock(bridge);
01567 }

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

References ast_bridge::array, ast_bridge::array_num, ast_bridge::array_size, ast_channel_name(), 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().

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

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

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

static struct ast_bridge_channel* bridge_channel_alloc ( struct ast_bridge bridge  )  [static, read]

Definition at line 1066 of file bridging.c.

References ao2_alloc, ao2_ref, ast_cond_init, ast_bridge_channel::bridge, bridge_channel_destroy(), and ast_bridge_channel::cond.

Referenced by ast_bridge_impart(), and ast_bridge_join().

01067 {
01068    struct ast_bridge_channel *bridge_channel = ao2_alloc(sizeof(struct ast_bridge_channel), bridge_channel_destroy);
01069    if (!(bridge_channel)) {
01070       return NULL;
01071    }
01072    ast_cond_init(&bridge_channel->cond, NULL);
01073    if (bridge) {
01074       bridge_channel->bridge = bridge;
01075       ao2_ref(bridge_channel->bridge, +1);
01076    }
01077    return bridge_channel;
01078 }

static void bridge_channel_destroy ( void *  obj  )  [static]

Definition at line 1054 of file bridging.c.

References ao2_ref, ast_cond_destroy, ast_bridge_channel::bridge, and ast_bridge_channel::cond.

Referenced by bridge_channel_alloc().

01055 {
01056    struct ast_bridge_channel *bridge_channel = obj;
01057 
01058    if (bridge_channel->bridge) {
01059       ao2_ref(bridge_channel->bridge, -1);
01060       bridge_channel->bridge = NULL;
01061    }
01062    /* Destroy elements of the bridge channel structure and the bridge channel structure itself */
01063    ast_cond_destroy(&bridge_channel->cond);
01064 }

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

00901 {
00902    char dtmf_q[8] = "";
00903 
00904    ast_copy_string(dtmf_q, bridge_channel->dtmf_stream_q, sizeof(dtmf_q));
00905    bridge_channel->dtmf_stream_q[0] = '\0';
00906 
00907    ast_debug(1, "Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel);
00908    ast_dtmf_stream(bridge_channel->chan, NULL, dtmf_q, 250, 0);
00909 
00910    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00911 
00912    return;
00913 }

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.

Note:
Neither the bridge nor the bridge_channel locks should be held when entering this function.

Definition at line 813 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_FEATURE, AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_dtmf_stream(), ast_check_hangup_locked(), 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, MAXIMUM_DTMF_FEATURE_STRING, and ast_bridge_channel::state.

Referenced by bridge_channel_join().

00814 {
00815    struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00816    struct ast_bridge_features_hook *hook = NULL;
00817    char dtmf[MAXIMUM_DTMF_FEATURE_STRING] = "";
00818    int look_for_dtmf = 1, dtmf_len = 0;
00819 
00820    /* 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 */
00821    ast_set_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00822 
00823    /* Wait for DTMF on the channel and put it into a buffer. If the buffer matches any feature hook execute the hook. */
00824    while (look_for_dtmf) {
00825       int res = ast_waitfordigit(bridge_channel->chan, 3000);
00826 
00827       /* If the above timed out simply exit */
00828       if (!res) {
00829          ast_debug(1, "DTMF feature string collection on bridge channel %p timed out\n", bridge_channel);
00830          break;
00831       } else if (res < 0) {
00832          ast_debug(1, "DTMF feature string collection failed on bridge channel %p for some reason\n", bridge_channel);
00833          break;
00834       }
00835 
00836       /* Add the above DTMF into the DTMF string so we can do our matching */
00837       dtmf[dtmf_len++] = res;
00838 
00839       ast_debug(1, "DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf);
00840 
00841       /* Assume that we do not want to look for DTMF any longer */
00842       look_for_dtmf = 0;
00843 
00844       /* See if a DTMF feature hook matches or can match */
00845       AST_LIST_TRAVERSE(&features->hooks, hook, entry) {
00846          /* If this hook matches just break out now */
00847          if (!strcmp(hook->dtmf, dtmf)) {
00848             ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel);
00849             look_for_dtmf = 0;
00850             break;
00851          } else if (!strncmp(hook->dtmf, dtmf, dtmf_len)) {
00852             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);
00853             look_for_dtmf = 1;
00854          } else {
00855             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);
00856          }
00857       }
00858 
00859       /* If we have reached the maximum length of a DTMF feature string bail out */
00860       if (dtmf_len == MAXIMUM_DTMF_FEATURE_STRING) {
00861          break;
00862       }
00863    }
00864 
00865    /* Since we are done bringing DTMF in return to using both begin and end frames */
00866    ast_clear_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00867 
00868    /* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */
00869    if (hook) {
00870       hook->callback(bridge, bridge_channel, hook->hook_pvt);
00871       /* If we are handing the channel off to an external hook for ownership,
00872        * we are not guaranteed what kind of state it will come back in.  If
00873        * the channel hungup, we need to detect that here. */
00874       if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
00875          ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00876       }
00877    } else {
00878       ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan);
00879    }
00880 
00881    /* if the channel is still in feature state, revert it back to wait state */
00882    if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_FEATURE) {
00883       ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00884    }
00885 
00886    return;
00887 }

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 916 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_START_TALKING, AST_BRIDGE_CHANNEL_STATE_STOP_TALKING, AST_BRIDGE_CHANNEL_STATE_WAIT, AST_BRIDGE_FLAG_SMART, ast_debug, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_copy(), 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_talking(), 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().

00917 {
00918    struct ast_format formats[2];
00919    enum ast_bridge_channel_state state;
00920    ast_format_copy(&formats[0], &bridge_channel->chan->readformat);
00921    ast_format_copy(&formats[1], &bridge_channel->chan->writeformat);
00922 
00923    /* Record the thread that will be the owner of us */
00924    bridge_channel->thread = pthread_self();
00925 
00926    ast_debug(1, "Joining bridge channel %p to bridge %p\n", bridge_channel, bridge_channel->bridge);
00927 
00928    ao2_lock(bridge_channel->bridge);
00929 
00930    state = bridge_channel->state;
00931 
00932    /* Add channel into the bridge */
00933    AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry);
00934    bridge_channel->bridge->num++;
00935 
00936    bridge_array_add(bridge_channel->bridge, bridge_channel->chan);
00937 
00938    if (bridge_channel->swap) {
00939       struct ast_bridge_channel *bridge_channel2 = NULL;
00940 
00941       /* If we are performing a swap operation we do not need
00942        * to execute the smart bridge operation as the actual number
00943        * of channels involved will not have changed, we just need to
00944        * tell the other channel to leave */
00945       if ((bridge_channel2 = find_bridge_channel(bridge_channel->bridge, bridge_channel->swap))) {
00946          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);
00947          ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00948       }
00949 
00950       bridge_channel->swap = NULL;
00951    } else if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
00952       /* Perform the smart bridge operation, basically see if we need to move around between technologies */
00953       smart_bridge_operation(bridge_channel->bridge, bridge_channel, bridge_channel->bridge->num);
00954    }
00955 
00956    /* Make the channel compatible with the bridge */
00957    bridge_make_compatible(bridge_channel->bridge, bridge_channel);
00958 
00959    /* Tell the bridge technology we are joining so they set us up */
00960    if (bridge_channel->bridge->technology->join) {
00961       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);
00962       if (bridge_channel->bridge->technology->join(bridge_channel->bridge, bridge_channel)) {
00963          ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00964       }
00965    }
00966 
00967    /* Actually execute the respective threading model, and keep our bridge thread alive */
00968    while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00969       /* Update bridge pointer on channel */
00970       bridge_channel->chan->bridge = bridge_channel->bridge;
00971       /* If the technology requires a thread and one is not running, start it up */
00972       if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
00973          bridge_channel->bridge->stop = 0;
00974          ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
00975          ao2_ref(bridge_channel->bridge, +1);
00976          if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) {
00977             ast_debug(1, "Failed to create a bridge thread for bridge %p, giving it another go.\n", bridge_channel->bridge);
00978             ao2_ref(bridge_channel->bridge, -1);
00979             continue;
00980          }
00981       }
00982       /* Execute the threading model */
00983       state = (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTITHREADED ? bridge_channel_join_multithreaded(bridge_channel) : bridge_channel_join_singlethreaded(bridge_channel));
00984       /* Depending on the above state see what we need to do */
00985       switch (state) {
00986       case AST_BRIDGE_CHANNEL_STATE_FEATURE:
00987          bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00988          ao2_unlock(bridge_channel->bridge);
00989          bridge_channel_feature(bridge_channel->bridge, bridge_channel);
00990          ao2_lock(bridge_channel->bridge);
00991          bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00992          break;
00993       case AST_BRIDGE_CHANNEL_STATE_DTMF:
00994          bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00995          bridge_channel_dtmf_stream(bridge_channel->bridge, bridge_channel);
00996          bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00997          break;
00998       case AST_BRIDGE_CHANNEL_STATE_START_TALKING:
00999       case AST_BRIDGE_CHANNEL_STATE_STOP_TALKING:
01000          ao2_unlock(bridge_channel->bridge);
01001          bridge_channel_talking(bridge_channel->bridge, bridge_channel);
01002          ao2_lock(bridge_channel->bridge);
01003          break;
01004       default:
01005          break;
01006       }
01007    }
01008 
01009    bridge_channel->chan->bridge = NULL;
01010 
01011    /* See if we need to dissolve the bridge itself if they hung up */
01012    if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_END) {
01013       bridge_check_dissolve(bridge_channel->bridge, bridge_channel);
01014    }
01015 
01016    /* Tell the bridge technology we are leaving so they tear us down */
01017    if (bridge_channel->bridge->technology->leave) {
01018       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);
01019       if (bridge_channel->bridge->technology->leave(bridge_channel->bridge, bridge_channel)) {
01020          ast_debug(1, "Bridge technology %s failed to leave %p from bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
01021       }
01022    }
01023 
01024    /* Remove channel from the bridge */
01025    bridge_channel->bridge->num--;
01026    AST_LIST_REMOVE(&bridge_channel->bridge->channels, bridge_channel, entry);
01027 
01028    bridge_array_remove(bridge_channel->bridge, bridge_channel->chan);
01029 
01030    /* Perform the smart bridge operation if needed since a channel has left */
01031    if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
01032       smart_bridge_operation(bridge_channel->bridge, NULL, bridge_channel->bridge->num);
01033    }
01034 
01035    ao2_unlock(bridge_channel->bridge);
01036 
01037    /* Restore original formats of the channel as they came in */
01038    if (ast_format_cmp(&bridge_channel->chan->readformat, &formats[0]) == AST_FORMAT_CMP_NOT_EQUAL) {
01039       ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(&formats[0]), formats[0].id);
01040       if (ast_set_read_format(bridge_channel->chan, &formats[0])) {
01041          ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(&formats[0]), formats[0].id);
01042       }
01043    }
01044    if (ast_format_cmp(&bridge_channel->chan->writeformat, &formats[1]) == AST_FORMAT_CMP_NOT_EQUAL) {
01045       ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(&formats[1]), formats[1].id);
01046       if (ast_set_write_format(bridge_channel->chan, &formats[1])) {
01047          ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(&formats[1]), formats[1].id);
01048       }
01049    }
01050 
01051    return bridge_channel->state;
01052 }

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

References ao2_lock, ao2_object_get_lockaddr(), ao2_unlock, ast_bridge_handle_trip(), ast_cond_wait, ast_debug, 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::state, ast_bridge_channel::suspended, and ast_bridge::technology.

Referenced by bridge_channel_join().

00724 {
00725    int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1;
00726    struct ast_channel *chan = NULL;
00727 
00728    /* Add any file descriptors we may want to monitor */
00729    if (bridge_channel->bridge->technology->fd) {
00730       for (i = 0; i < 4; i ++) {
00731          if (bridge_channel->fds[i] >= 0) {
00732             fds[nfds++] = bridge_channel->fds[i];
00733          }
00734       }
00735    }
00736 
00737    ao2_unlock(bridge_channel->bridge);
00738 
00739    ao2_lock(bridge_channel);
00740    /* Wait for data to either come from the channel or us to be signalled */
00741    if (!bridge_channel->suspended) {
00742       ao2_unlock(bridge_channel);
00743       ast_debug(10, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00744       chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms);
00745    } else {
00746       ast_debug(10, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00747       ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel));
00748       ao2_unlock(bridge_channel);
00749    }
00750 
00751    ao2_lock(bridge_channel->bridge);
00752 
00753    if (!bridge_channel->suspended) {
00754       ast_bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd);
00755    }
00756 
00757    return bridge_channel->state;
00758 }

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

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

Referenced by bridge_channel_join().

00762 {
00763    ao2_unlock(bridge_channel->bridge);
00764    ao2_lock(bridge_channel);
00765    if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00766       ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00767       ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel));
00768    }
00769    ao2_unlock(bridge_channel);
00770    ao2_lock(bridge_channel->bridge);
00771 
00772    return bridge_channel->state;
00773 }

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

References ao2_lock, ao2_unlock, 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().

00777 {
00778    ao2_lock(bridge_channel);
00779    bridge_channel->suspended = 1;
00780    bridge_array_remove(bridge, bridge_channel->chan);
00781    ao2_unlock(bridge_channel);
00782 
00783    if (bridge->technology->suspend) {
00784       bridge->technology->suspend(bridge, bridge_channel);
00785    }
00786 
00787    return;
00788 }

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

Definition at line 889 of file bridging.c.

References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge::features, ast_bridge_channel::features, ast_bridge_features::talker_cb, and ast_bridge_features::talker_pvt_data.

Referenced by bridge_channel_join().

00890 {
00891    struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00892 
00893    if (features && features->talker_cb) {
00894       features->talker_cb(bridge, bridge_channel, features->talker_pvt_data);
00895    }
00896    ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00897 }

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

Thread responsible for imparted bridged channels.

Definition at line 1116 of file bridging.c.

References ast_bridge_channel::allow_impart_hangup, ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, ast_hangup(), bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::features, and ast_bridge_channel::swap.

Referenced by ast_bridge_impart().

01117 {
01118    struct ast_bridge_channel *bridge_channel = data;
01119    enum ast_bridge_channel_state state;
01120 
01121    state = bridge_channel_join(bridge_channel);
01122 
01123    /* 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 */
01124    if (bridge_channel->allow_impart_hangup && (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP)) {
01125       ast_hangup(bridge_channel->chan);
01126    }
01127 
01128    /* cleanup */
01129    ao2_lock(bridge_channel);
01130    bridge_channel->chan = NULL;
01131    bridge_channel->swap = NULL;
01132    bridge_channel->features = NULL;
01133    ao2_unlock(bridge_channel);
01134 
01135    ao2_ref(bridge_channel, -1);
01136 
01137    return NULL;
01138 }

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

References ao2_lock, ao2_unlock, ast_cond_signal, bridge_array_add(), ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge_channel::suspended, ast_bridge::technology, and ast_bridge_technology::unsuspend.

Referenced by ast_bridge_unsuspend(), and bridge_channel_join().

00792 {
00793    ao2_lock(bridge_channel);
00794    bridge_channel->suspended = 0;
00795    bridge_array_add(bridge, bridge_channel->chan);
00796    ast_cond_signal(&bridge_channel->cond);
00797    ao2_unlock(bridge_channel);
00798 
00799    if (bridge->technology->unsuspend) {
00800       bridge->technology->unsuspend(bridge, bridge_channel);
00801    }
00802 
00803 
00804 
00805    return;
00806 }

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 217 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, ast_bridge::stop, and ast_bridge_features::usable.

Referenced by bridge_channel_join().

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

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

References AST_CONTROL_ANSWER.

Referenced by ast_bridge_handle_trip().

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

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

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

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

Definition at line 553 of file bridging.c.

References ast_best_codec(), ast_channel_name(), ast_debug, ast_format_cap_iscompatible(), ast_format_copy(), ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_set_read_format(), ast_set_write_format(), ast_bridge_channel::chan, ast_bridge_technology::format_capabilities, 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().

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

static void bridge_poke ( struct ast_bridge bridge  )  [static]

Helper function to poke the bridge thread.

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

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

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

Bridge thread function.

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

00369 {
00370    struct ast_bridge *bridge = data;
00371    int res = 0;
00372 
00373    ao2_lock(bridge);
00374 
00375    ast_debug(1, "Started bridge thread for %p\n", bridge);
00376 
00377    /* Loop around until we are told to stop */
00378    while (!bridge->stop && bridge->array_num && !res) {
00379       /* In case the refresh bit was set simply set it back to off */
00380       bridge->refresh = 0;
00381 
00382       ast_debug(1, "Launching bridge thread function %p for bridge %p\n", (bridge->technology->thread ? bridge->technology->thread : &generic_thread_loop), bridge);
00383 
00384       /* Execute the appropriate thread function. If the technology does not provide one we use the generic one */
00385       res = (bridge->technology->thread ? bridge->technology->thread(bridge) : generic_thread_loop(bridge));
00386    }
00387 
00388    ast_debug(1, "Ending bridge thread for %p\n", bridge);
00389 
00390    /* Indicate the bridge thread is no longer active */
00391    bridge->thread = AST_PTHREADT_NULL;
00392    ao2_unlock(bridge);
00393 
00394    ao2_ref(bridge, -1);
00395 
00396    return NULL;
00397 }

static void cleanup_video_mode ( struct ast_bridge bridge  )  [static]

static void destroy_bridge ( void *  obj  )  [static]

Definition at line 434 of file bridging.c.

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

Referenced by ast_bridge_new().

00435 {
00436    struct ast_bridge *bridge = obj;
00437 
00438    ast_debug(1, "Actually destroying bridge %p, nobody wants it anymore\n", bridge);
00439 
00440    /* Pass off the bridge to the technology to destroy if needed */
00441    if (bridge->technology->destroy) {
00442       ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge);
00443       if (bridge->technology->destroy(bridge)) {
00444          ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->technology->name, bridge);
00445       }
00446    }
00447 
00448    /* We are no longer using the bridge technology so decrement the module reference count on it */
00449    if (bridge->technology->mod) {
00450       ast_module_unref(bridge->technology->mod);
00451    }
00452 
00453    /* Last but not least clean up the features configuration */
00454    ast_bridge_features_cleanup(&bridge->features);
00455 
00456    /* Drop the array of channels */
00457    ast_free(bridge->array);
00458 
00459    cleanup_video_mode(bridge);
00460 
00461    return;
00462 }

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

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

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

00401 {
00402    struct ast_bridge_technology *current = NULL, *best = NULL;
00403 
00404    AST_RWLIST_RDLOCK(&bridge_technologies);
00405    AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) {
00406       if (current->suspended) {
00407          ast_debug(1, "Bridge technology %s is suspended. Skipping.\n", current->name);
00408          continue;
00409       }
00410       if (!(current->capabilities & capabilities)) {
00411          ast_debug(1, "Bridge technology %s does not have the capabilities we need.\n", current->name);
00412          continue;
00413       }
00414       if (best && best->preference < current->preference) {
00415          ast_debug(1, "Bridge technology %s has preference %d while %s has preference %d. Skipping.\n", current->name, current->preference, best->name, best->preference);
00416          continue;
00417       }
00418       best = current;
00419    }
00420 
00421    if (best) {
00422       /* Increment it's module reference count if present so it does not get unloaded while in use */
00423       if (best->mod) {
00424          ast_module_ref(best->mod);
00425       }
00426       ast_debug(1, "Chose bridge technology %s\n", best->name);
00427    }
00428 
00429    AST_RWLIST_UNLOCK(&bridge_technologies);
00430 
00431    return best;
00432 }

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

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

static int generic_thread_loop ( struct ast_bridge bridge  )  [static]

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

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

00341 {
00342    while (!bridge->stop && !bridge->refresh && bridge->array_num) {
00343       struct ast_channel *winner = NULL;
00344       int to = -1;
00345 
00346       /* Move channels around for priority reasons if we have more than one channel in our array */
00347       if (bridge->array_num > 1) {
00348          struct ast_channel *first = bridge->array[0];
00349          memmove(bridge->array, bridge->array + 1, sizeof(struct ast_channel *) * (bridge->array_num - 1));
00350          bridge->array[(bridge->array_num - 1)] = first;
00351       }
00352 
00353       /* Wait on the channels */
00354       bridge->waiting = 1;
00355       ao2_unlock(bridge);
00356       winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to);
00357       bridge->waiting = 0;
00358       ao2_lock(bridge);
00359 
00360       /* Process whatever they did */
00361       ast_bridge_handle_trip(bridge, NULL, winner, -1);
00362    }
00363 
00364    return 0;
00365 }

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 606 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_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_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().

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


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

void* builtin_features_handlers[AST_BRIDGE_BUILTIN_END] [static]

Function handlers for the built in features

Definition at line 60 of file bridging.c.


Generated on Fri Feb 10 06:35:01 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6