Channel Bridging API. More...
#include "asterisk.h"
#include <signal.h>
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_technology.h"
#include "asterisk/app.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
struct | bridge_technologies |
Defines | |
#define | BRIDGE_ARRAY_GROW 32 |
#define | BRIDGE_ARRAY_START 128 |
Functions | |
int | __ast_bridge_technology_register (struct ast_bridge_technology *technology, struct ast_module *module) |
Register a bridge technology for use. | |
void | ast_bridge_change_state (struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state) |
Change the state of a bridged channel. | |
int | ast_bridge_check (enum ast_bridge_capability capabilities) |
See if it is possible to create a bridge. | |
int | ast_bridge_depart (struct ast_bridge *bridge, struct ast_channel *chan) |
Depart a channel from a bridge. | |
int | ast_bridge_destroy (struct ast_bridge *bridge) |
Destroy a bridge. | |
int | ast_bridge_dtmf_stream (struct ast_bridge *bridge, const char *dtmf, struct ast_channel *chan) |
Play a DTMF stream into a bridge, optionally not to a given channel. | |
int | ast_bridge_features_cleanup (struct ast_bridge_features *features) |
Clean up the contents of a bridge features structure. | |
int | ast_bridge_features_enable (struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config) |
Enable a built in feature on a bridge features structure. | |
int | ast_bridge_features_hook (struct ast_bridge_features *features, const char *dtmf, ast_bridge_features_hook_callback callback, void *hook_pvt) |
Attach a custom hook to a bridge features structure. | |
int | ast_bridge_features_init (struct ast_bridge_features *features) |
Initialize bridge features structure. | |
int | ast_bridge_features_register (enum ast_bridge_builtin_feature feature, ast_bridge_features_hook_callback callback, const char *dtmf) |
Register a handler for a built in feature. | |
int | ast_bridge_features_set_flag (struct ast_bridge_features *features, enum ast_bridge_feature_flags flag) |
Set a flag on a bridge features structure. | |
int | ast_bridge_features_unregister (enum ast_bridge_builtin_feature feature) |
Unregister a handler for a built in feature. | |
void | ast_bridge_handle_trip (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd) |
Feed notification that a frame is waiting on a channel into the bridging core. | |
int | ast_bridge_impart (struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features) |
Impart (non-blocking) a channel on a bridge. | |
enum ast_bridge_channel_state | ast_bridge_join (struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features) |
Join (blocking) a channel to a bridge. | |
int | ast_bridge_merge (struct ast_bridge *bridge0, struct ast_bridge *bridge1) |
Merge two bridges together. | |
struct ast_bridge * | ast_bridge_new (enum ast_bridge_capability capabilities, int flags) |
Create a new bridge. | |
int | ast_bridge_remove (struct ast_bridge *bridge, struct ast_channel *chan) |
Remove a channel from a bridge. | |
int | ast_bridge_suspend (struct ast_bridge *bridge, struct ast_channel *chan) |
Suspend a channel temporarily from a bridge. | |
void | ast_bridge_technology_suspend (struct ast_bridge_technology *technology) |
Suspend a bridge technology from consideration. | |
int | ast_bridge_technology_unregister (struct ast_bridge_technology *technology) |
Unregister a bridge technology from use. | |
void | ast_bridge_technology_unsuspend (struct ast_bridge_technology *technology) |
Unsuspend a bridge technology. | |
int | ast_bridge_unsuspend (struct ast_bridge *bridge, struct ast_channel *chan) |
Unsuspend a channel from a bridge. | |
static void | bridge_array_add (struct ast_bridge *bridge, struct ast_channel *chan) |
Helper function to add a channel to the bridge array. | |
static void | bridge_array_remove (struct ast_bridge *bridge, struct ast_channel *chan) |
Helper function to remove a channel from the bridge array. | |
static void | bridge_channel_dtmf_stream (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
Internal function that plays back DTMF on a bridge channel. | |
static void | bridge_channel_feature (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
Internal function that executes a feature on a bridge channel. | |
static enum ast_bridge_channel_state | bridge_channel_join (struct ast_bridge_channel *bridge_channel) |
Join a channel to a bridge and handle anything the bridge may want us to do. | |
static enum ast_bridge_channel_state | bridge_channel_join_multithreaded (struct ast_bridge_channel *bridge_channel) |
Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve. | |
static enum ast_bridge_channel_state | bridge_channel_join_singlethreaded (struct ast_bridge_channel *bridge_channel) |
Run in a singlethreaded model. Each joined channel yields itself to the main bridge thread. TODO: Improve. | |
static void | bridge_channel_suspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
Internal function that suspends a channel from a bridge. | |
static void * | bridge_channel_thread (void *data) |
Thread responsible for imparted bridged channels. | |
static void | bridge_channel_unsuspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
Internal function that unsuspends a channel from a bridge. | |
static void | bridge_check_dissolve (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
Internal function to see whether a bridge should dissolve, and if so do it. | |
static int | bridge_drop_control_frame (int subclass) |
Internal function used to determine whether a control frame should be dropped or not. | |
static struct ast_frame * | bridge_handle_dtmf (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) |
Internal function to handle DTMF from a channel. | |
static int | bridge_make_compatible (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
static void | bridge_poke (struct ast_bridge *bridge) |
Helper function to poke the bridge thread. | |
static void * | bridge_thread (void *data) |
Bridge thread function. | |
static void | destroy_bridge (void *obj) |
static struct ast_bridge_technology * | find_best_technology (enum ast_bridge_capability capabilities) |
Helper function used to find the "best" bridge technology given a specified capabilities. | |
static struct ast_bridge_channel * | find_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] |
Channel Bridging API.
Definition in file bridging.c.
#define BRIDGE_ARRAY_GROW 32 |
Definition at line 55 of file bridging.c.
Referenced by bridge_array_add().
#define BRIDGE_ARRAY_START 128 |
Definition at line 52 of file bridging.c.
Referenced by ast_bridge_new().
int __ast_bridge_technology_register | ( | struct ast_bridge_technology * | technology, | |
struct ast_module * | mod | |||
) |
Register a bridge technology for use.
technology | The bridge technology to register | |
mod | The module that is registering the bridge technology |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_technology_register(&simple_bridge_tech);
This registers a bridge technology declared as the structure simple_bridge_tech with the bridging core and makes it available for use when creating bridges.
Definition at line 63 of file bridging.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), ast_verbose, ast_bridge_technology::capabilities, LOG_WARNING, ast_bridge_technology::mod, ast_bridge_technology::name, option_verbose, VERBOSE_PREFIX_2, and ast_bridge_technology::write.
00064 { 00065 struct ast_bridge_technology *current = NULL; 00066 00067 /* Perform a sanity check to make sure the bridge technology conforms to our needed requirements */ 00068 if (ast_strlen_zero(technology->name) || !technology->capabilities || !technology->write) { 00069 ast_log(LOG_WARNING, "Bridge technology %s failed registration sanity check.\n", technology->name); 00070 return -1; 00071 } 00072 00073 AST_RWLIST_WRLOCK(&bridge_technologies); 00074 00075 /* Look for duplicate bridge technology already using this name, or already registered */ 00076 AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) { 00077 if ((!strcasecmp(current->name, technology->name)) || (current == technology)) { 00078 ast_log(LOG_WARNING, "A bridge technology of %s already claims to exist in our world.\n", technology->name); 00079 AST_RWLIST_UNLOCK(&bridge_technologies); 00080 return -1; 00081 } 00082 } 00083 00084 /* Copy module pointer so reference counting can keep the module from unloading */ 00085 technology->mod = module; 00086 00087 /* Insert our new bridge technology into the list and print out a pretty message */ 00088 AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry); 00089 00090 AST_RWLIST_UNLOCK(&bridge_technologies); 00091 00092 if (option_verbose > 1) { 00093 ast_verbose(VERBOSE_PREFIX_2 "Registered bridge technology %s\n", technology->name); 00094 } 00095 00096 return 0; 00097 }
void ast_bridge_change_state | ( | struct ast_bridge_channel * | bridge_channel, | |
enum ast_bridge_channel_state | new_state | |||
) |
Change the state of a bridged channel.
bridge_channel | Channel to change the state on | |
new_state | The new state to place the channel into |
Example usage:
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
This places the channel pointed to by bridge_channel into the state AST_BRIDGE_CHANNEL_STATE_WAIT.
Definition at line 122 of file bridging.c.
References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_bridge_channel::cond, ast_bridge_channel::lock, ast_bridge_channel::state, and ast_bridge_channel::thread.
Referenced by ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_dtmf_stream(), ast_bridge_handle_trip(), ast_bridge_remove(), attended_abort_transfer(), attended_threeway_transfer(), bridge_channel_dtmf_stream(), bridge_channel_feature(), bridge_channel_join(), bridge_check_dissolve(), bridge_handle_dtmf(), feature_attended_transfer(), feature_blind_transfer(), and feature_hangup().
00123 { 00124 /* Change the state on the bridge channel */ 00125 bridge_channel->state = new_state; 00126 00127 /* Only poke the channel's thread if it is not us */ 00128 if (!pthread_equal(pthread_self(), bridge_channel->thread)) { 00129 pthread_kill(bridge_channel->thread, SIGURG); 00130 ast_mutex_lock(&bridge_channel->lock); 00131 ast_cond_signal(&bridge_channel->cond); 00132 ast_mutex_unlock(&bridge_channel->lock); 00133 } 00134 00135 return; 00136 }
int ast_bridge_check | ( | enum ast_bridge_capability | capabilities | ) |
See if it is possible to create a bridge.
capabilities | The capabilities that the bridge will use |
1 | if possible | |
0 | if not possible |
Example usage:
int possible = ast_bridge_check(AST_BRIDGE_CAPABILITY_1TO1MIX);
This sees if it is possible to create a bridge capable of bridging two channels together.
Definition at line 502 of file bridging.c.
References ast_module_unref(), find_best_technology(), and ast_bridge_technology::mod.
00503 { 00504 struct ast_bridge_technology *bridge_technology = NULL; 00505 00506 if (!(bridge_technology = find_best_technology(capabilities))) { 00507 return 0; 00508 } 00509 00510 ast_module_unref(bridge_technology->mod); 00511 00512 return 1; 00513 }
int ast_bridge_depart | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan | |||
) |
Depart a channel from a bridge.
bridge | Bridge to depart from | |
chan | Channel to depart |
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.
Definition at line 1077 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DEPART, find_bridge_channel(), ast_bridge_channel::thread, and thread.
Referenced by feature_attended_transfer(), and play_sound_file().
01078 { 01079 struct ast_bridge_channel *bridge_channel = NULL; 01080 pthread_t thread; 01081 01082 ao2_lock(bridge); 01083 01084 /* Try to find the channel that we want to depart */ 01085 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01086 ao2_unlock(bridge); 01087 return -1; 01088 } 01089 01090 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART); 01091 thread = bridge_channel->thread; 01092 01093 ao2_unlock(bridge); 01094 01095 pthread_join(thread, NULL); 01096 01097 return 0; 01098 }
int ast_bridge_destroy | ( | struct ast_bridge * | bridge | ) |
Destroy a bridge.
bridge | Bridge to destroy |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_destroy(bridge);
This destroys a bridge that was previously created using ast_bridge_new.
Definition at line 515 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, ast_debug, AST_LIST_TRAVERSE, AST_PTHREADT_NULL, bridge_poke(), ast_bridge::stop, thread, and ast_bridge::thread.
Referenced by ast_bridge_new(), destroy_conference_bridge(), and feature_attended_transfer().
00516 { 00517 struct ast_bridge_channel *bridge_channel = NULL; 00518 00519 ao2_lock(bridge); 00520 00521 if (bridge->thread != AST_PTHREADT_NULL) { 00522 pthread_t thread = bridge->thread; 00523 bridge->stop = 1; 00524 bridge_poke(bridge); 00525 ao2_unlock(bridge); 00526 pthread_join(thread, NULL); 00527 ao2_lock(bridge); 00528 } 00529 00530 ast_debug(1, "Telling all channels in bridge %p to end and leave the party\n", bridge); 00531 00532 /* Drop every bridged channel, the last one will cause the bridge thread (if it exists) to exit */ 00533 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { 00534 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END); 00535 } 00536 00537 ao2_unlock(bridge); 00538 00539 ao2_ref(bridge, -1); 00540 00541 return 0; 00542 }
int ast_bridge_dtmf_stream | ( | struct ast_bridge * | bridge, | |
const char * | dtmf, | |||
struct ast_channel * | chan | |||
) |
Play a DTMF stream into a bridge, optionally not to a given channel.
bridge | Bridge to play stream into | |
dtmf | DTMF to play | |
chan | Channel to optionally not play to |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_dtmf_stream(bridge, "0123456789", NULL);
This sends the DTMF digits '0123456789' to all channels in the bridge pointed to by the bridge pointer. Optionally a channel may be excluded by passing it's channel pointer using the chan parameter.
Definition at line 1345 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DTMF, ast_copy_string(), AST_LIST_TRAVERSE, ast_bridge_channel::chan, and ast_bridge_channel::dtmf_stream_q.
Referenced by bridge_channel_feature().
01346 { 01347 struct ast_bridge_channel *bridge_channel = NULL; 01348 01349 ao2_lock(bridge); 01350 01351 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { 01352 if (bridge_channel->chan == chan) { 01353 continue; 01354 } 01355 ast_copy_string(bridge_channel->dtmf_stream_q, dtmf, sizeof(bridge_channel->dtmf_stream_q)); 01356 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DTMF); 01357 } 01358 01359 ao2_unlock(bridge); 01360 01361 return 0; 01362 }
int ast_bridge_features_cleanup | ( | struct ast_bridge_features * | features | ) |
Clean up the contents of a bridge features structure.
features | Bridge features structure |
0 | on success | |
-1 | on failure |
Example usage:
struct ast_bridge_features features; ast_bridge_features_init(&features); ast_bridge_features_cleanup(&features);
This cleans up the feature structure 'features'.
Definition at line 1333 of file bridging.c.
References ast_free, and AST_LIST_REMOVE_HEAD.
Referenced by confbridge_exec(), destroy_bridge(), and feature_attended_transfer().
01334 { 01335 struct ast_bridge_features_hook *hook = NULL; 01336 01337 /* This is relatively simple, hooks are kept as a list on the features structure so we just pop them off and free them */ 01338 while ((hook = AST_LIST_REMOVE_HEAD(&features->hooks, entry))) { 01339 ast_free(hook); 01340 } 01341 01342 return 0; 01343 }
int ast_bridge_features_enable | ( | struct ast_bridge_features * | features, | |
enum ast_bridge_builtin_feature | feature, | |||
const char * | dtmf, | |||
void * | config | |||
) |
Enable a built in feature on a bridge features structure.
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 |
0 | on success | |
-1 | on failure |
Example usage:
struct ast_bridge_features features; ast_bridge_features_init(&features); ast_bridge_features_enable(&features, AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, NULL);
This enables the attended transfer DTMF option using the default DTMF string. An alternate string may be provided using the dtmf parameter. Internally this is simply setting up a hook to a built in feature callback function.
Definition at line 1295 of file bridging.c.
References ast_bridge_features_hook(), ast_debug, and ast_strlen_zero().
Referenced by feature_attended_transfer().
01296 { 01297 /* If no alternate DTMF stream was provided use the default one */ 01298 if (ast_strlen_zero(dtmf)) { 01299 dtmf = builtin_features_dtmf[feature]; 01300 /* If no DTMF is still available (ie: it has been disabled) then error out now */ 01301 if (ast_strlen_zero(dtmf)) { 01302 ast_debug(1, "Failed to enable built in feature %u on %p, no DTMF string is available for it.\n", feature, features); 01303 return -1; 01304 } 01305 } 01306 01307 if (!builtin_features_handlers[feature]) { 01308 return -1; 01309 } 01310 01311 /* The rest is basically pretty easy. We create another hook using the built in feature's callback and DTMF, easy as pie. */ 01312 return ast_bridge_features_hook(features, dtmf, builtin_features_handlers[feature], config); 01313 }
int ast_bridge_features_hook | ( | struct ast_bridge_features * | features, | |
const char * | dtmf, | |||
ast_bridge_features_hook_callback | callback, | |||
void * | hook_pvt | |||
) |
Attach a custom hook to a bridge features structure.
features | Bridge features structure | |
dtmf | DTMF string to be activated upon | |
callback | Function to execute upon activation | |
hook_pvt | Unique data |
0 | on success | |
-1 | on failure |
Example usage:
struct ast_bridge_features features; ast_bridge_features_init(&features); ast_bridge_features_hook(&features, "#", pound_callback, NULL);
This makes the bridging core call pound_callback if a channel that has this feature structure inputs the DTMF string '#'. A pointer to useful data may be provided to the hook_pvt parameter.
Definition at line 1274 of file bridging.c.
References ast_calloc, ast_copy_string(), AST_LIST_INSERT_TAIL, ast_bridge_features_hook::callback, ast_bridge_features_hook::dtmf, ast_bridge_features_hook::hook_pvt, and ast_bridge_features::usable.
Referenced by ast_bridge_features_enable(), confbridge_exec(), and feature_attended_transfer().
01275 { 01276 struct ast_bridge_features_hook *hook = NULL; 01277 01278 /* Allocate new memory and setup it's various variables */ 01279 if (!(hook = ast_calloc(1, sizeof(*hook)))) { 01280 return -1; 01281 } 01282 01283 ast_copy_string(hook->dtmf, dtmf, sizeof(hook->dtmf)); 01284 hook->callback = callback; 01285 hook->hook_pvt = hook_pvt; 01286 01287 /* Once done we add it onto the list. Now it will be picked up when DTMF is used */ 01288 AST_LIST_INSERT_TAIL(&features->hooks, hook, entry); 01289 01290 features->usable = 1; 01291 01292 return 0; 01293 }
int ast_bridge_features_init | ( | struct ast_bridge_features * | features | ) |
Initialize bridge features structure.
features | Bridge featues structure |
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.
Definition at line 1322 of file bridging.c.
References AST_LIST_HEAD_INIT_NOLOCK.
Referenced by confbridge_exec(), and feature_attended_transfer().
01323 { 01324 /* Zero out the structure */ 01325 memset(features, 0, sizeof(*features)); 01326 01327 /* Initialize the hooks list, just in case */ 01328 AST_LIST_HEAD_INIT_NOLOCK(&features->hooks); 01329 01330 return 0; 01331 }
int ast_bridge_features_register | ( | enum ast_bridge_builtin_feature | feature, | |
ast_bridge_features_hook_callback | callback, | |||
const char * | dtmf | |||
) |
Register a handler for a built in feature.
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 |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge_builtin_attended_transfer, "*1");
This registers the function bridge_builtin_attended_transfer as the function responsible for the built in attended transfer feature.
Definition at line 1248 of file bridging.c.
References ast_copy_string(), and ast_strlen_zero().
Referenced by load_module().
01249 { 01250 if (builtin_features_handlers[feature]) { 01251 return -1; 01252 } 01253 01254 if (!ast_strlen_zero(dtmf)) { 01255 ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature])); 01256 } 01257 01258 builtin_features_handlers[feature] = callback; 01259 01260 return 0; 01261 }
int ast_bridge_features_set_flag | ( | struct ast_bridge_features * | features, | |
enum ast_bridge_feature_flags | flag | |||
) |
Set a flag on a bridge features structure.
features | Bridge features structure | |
flag | Flag to enable |
0 | on success | |
-1 | on failure |
Example usage:
struct ast_bridge_features features; ast_bridge_features_init(&features); ast_bridge_features_set_flag(&features, AST_BRIDGE_FLAG_DISSOLVE);
This sets the AST_BRIDGE_FLAG_DISSOLVE feature to be enabled on the features structure 'features'.
Definition at line 1315 of file bridging.c.
References ast_set_flag, ast_bridge_features::feature_flags, and ast_bridge_features::usable.
Referenced by feature_attended_transfer().
01316 { 01317 ast_set_flag(&features->feature_flags, flag); 01318 features->usable = 1; 01319 return 0; 01320 }
int ast_bridge_features_unregister | ( | enum ast_bridge_builtin_feature | feature | ) |
Unregister a handler for a built in feature.
feature | The feature to unregister |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER);
This unregisters the function that is handling the built in attended transfer feature.
Definition at line 1263 of file bridging.c.
01264 { 01265 if (!builtin_features_handlers[feature]) { 01266 return -1; 01267 } 01268 01269 builtin_features_handlers[feature] = NULL; 01270 01271 return 0; 01272 }
void ast_bridge_handle_trip | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel, | |||
struct ast_channel * | chan, | |||
int | outfd | |||
) |
Feed notification that a frame is waiting on a channel into the bridging core.
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.
Definition at line 277 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, ast_frfree, ast_read(), ast_read_noaudio(), bridge_drop_control_frame(), bridge_handle_dtmf(), ast_bridge_technology::fd, ast_bridge_channel::features, ast_bridge::features, find_bridge_channel(), ast_frame::frametype, ast_frame_subclass::integer, ast_bridge_features::mute, ast_bridge_technology::poke, ast_frame::subclass, ast_bridge::technology, and ast_bridge_technology::write.
Referenced by bridge_channel_join_multithreaded(), generic_thread_loop(), and multiplexed_thread_function().
00278 { 00279 /* If no bridge channel has been provided and the actual channel has been provided find it */ 00280 if (chan && !bridge_channel) { 00281 bridge_channel = find_bridge_channel(bridge, chan); 00282 } 00283 00284 /* If a bridge channel with actual channel is present read a frame and handle it */ 00285 if (chan && bridge_channel) { 00286 struct ast_frame *frame = (((bridge->features.mute) || (bridge_channel->features && bridge_channel->features->mute)) ? ast_read_noaudio(chan) : ast_read(chan)); 00287 00288 /* This is pretty simple... see if they hung up */ 00289 if (!frame || (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_HANGUP)) { 00290 /* Signal the thread that is handling the bridged channel that it should be ended */ 00291 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END); 00292 } else if (frame->frametype == AST_FRAME_CONTROL && bridge_drop_control_frame(frame->subclass.integer)) { 00293 ast_debug(1, "Dropping control frame from bridge channel %p\n", bridge_channel); 00294 } else { 00295 if (frame->frametype == AST_FRAME_DTMF_BEGIN) { 00296 frame = bridge_handle_dtmf(bridge, bridge_channel, frame); 00297 } 00298 /* Simply write the frame out to the bridge technology if it still exists */ 00299 if (frame) { 00300 bridge->technology->write(bridge, bridge_channel, frame); 00301 } 00302 } 00303 00304 if (frame) { 00305 ast_frfree(frame); 00306 } 00307 return; 00308 } 00309 00310 /* If a file descriptor actually tripped pass it off to the bridge technology */ 00311 if (outfd > -1 && bridge->technology->fd) { 00312 bridge->technology->fd(bridge, bridge_channel, outfd); 00313 return; 00314 } 00315 00316 /* If all else fails just poke the bridge */ 00317 if (bridge->technology->poke && bridge_channel) { 00318 bridge->technology->poke(bridge, bridge_channel); 00319 return; 00320 } 00321 00322 return; 00323 }
int ast_bridge_impart | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan, | |||
struct ast_channel * | swap, | |||
struct ast_bridge_features * | features | |||
) |
Impart (non-blocking) a channel on a bridge.
bridge | Bridge to impart on | |
chan | Channel to impart | |
swap | Channel to swap out if swapping | |
features | Bridge features structure |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_impart(bridge, chan, NULL, NULL);
This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will return immediately and will not wait until the channel is no longer part of the bridge.
If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.
If channel specific features are enabled a pointer to the features structure can be specified in the features parameter.
Definition at line 1043 of file bridging.c.
References ao2_ref, ast_calloc, ast_cond_destroy, ast_cond_init, ast_free, ast_mutex_destroy, ast_mutex_init, ast_pthread_create, ast_bridge_channel::bridge, bridge_channel_thread(), ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge_channel::features, ast_bridge_channel::lock, ast_bridge_channel::swap, and ast_bridge_channel::thread.
Referenced by bridge_call(), feature_attended_transfer(), feature_blind_transfer(), and play_sound_file().
01044 { 01045 struct ast_bridge_channel *bridge_channel = NULL; 01046 01047 /* Try to allocate a structure for the bridge channel */ 01048 if (!(bridge_channel = ast_calloc(1, sizeof(*bridge_channel)))) { 01049 return -1; 01050 } 01051 01052 /* Setup various parameters */ 01053 bridge_channel->chan = chan; 01054 bridge_channel->swap = swap; 01055 bridge_channel->bridge = bridge; 01056 bridge_channel->features = features; 01057 01058 /* Initialize our mutex lock and condition */ 01059 ast_mutex_init(&bridge_channel->lock); 01060 ast_cond_init(&bridge_channel->cond, NULL); 01061 01062 /* Bump up the reference count on the bridge, it'll get decremented later */ 01063 ao2_ref(bridge, +1); 01064 01065 /* Actually create the thread that will handle the channel */ 01066 if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) { 01067 ao2_ref(bridge, -1); 01068 ast_cond_destroy(&bridge_channel->cond); 01069 ast_mutex_destroy(&bridge_channel->lock); 01070 ast_free(bridge_channel); 01071 return -1; 01072 } 01073 01074 return 0; 01075 }
enum ast_bridge_channel_state ast_bridge_join | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan, | |||
struct ast_channel * | swap, | |||
struct ast_bridge_features * | features | |||
) |
Join (blocking) a channel to a bridge.
bridge | Bridge to join | |
chan | Channel to join | |
swap | Channel to swap out if swapping | |
features | Bridge features structure |
state | that channel exited the bridge with |
Example usage:
ast_bridge_join(bridge, chan, NULL, NULL);
This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will not return until the channel has been removed from the bridge, swapped out for another channel, or has hung up.
If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.
If channel specific features are enabled a pointer to the features structure can be specified in the features parameter.
Definition at line 993 of file bridging.c.
References ao2_ref, ast_cond_destroy, ast_cond_init, ast_mutex_destroy, ast_mutex_init, ast_bridge_channel::bridge, ast_channel::bridge, bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge::features, and ast_bridge_channel::lock.
Referenced by confbridge_exec(), and feature_attended_transfer().
00994 { 00995 struct ast_bridge_channel bridge_channel = { 00996 .chan = chan, 00997 .swap = swap, 00998 .bridge = bridge, 00999 .features = features, 01000 }; 01001 enum ast_bridge_channel_state state; 01002 01003 /* Initialize various other elements of the bridge channel structure that we can't do above */ 01004 ast_mutex_init(&bridge_channel.lock); 01005 ast_cond_init(&bridge_channel.cond, NULL); 01006 01007 ao2_ref(bridge_channel.bridge, +1); 01008 01009 state = bridge_channel_join(&bridge_channel); 01010 01011 ao2_ref(bridge_channel.bridge, -1); 01012 01013 /* Destroy some elements of the bridge channel structure above */ 01014 ast_mutex_destroy(&bridge_channel.lock); 01015 ast_cond_destroy(&bridge_channel.cond); 01016 01017 return state; 01018 }
int ast_bridge_merge | ( | struct ast_bridge * | bridge0, | |
struct ast_bridge * | bridge1 | |||
) |
Merge two bridges together.
bridge0 | First bridge | |
bridge1 | Second bridge |
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.
Definition at line 1119 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_FLAG_SMART, ast_cond_signal, ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_STOP, ast_test_flag, ast_bridge_channel::bridge, bridge_array_add(), bridge_array_remove(), bridge_make_compatible(), ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge::feature_flags, ast_bridge_technology::join, ast_bridge_technology::leave, ast_bridge_channel::lock, ast_bridge_technology::name, ast_bridge::num, smart_bridge_operation(), ast_bridge::technology, ast_bridge_channel::thread, and ast_bridge::thread.
01120 { 01121 struct ast_bridge_channel *bridge_channel = NULL; 01122 01123 ao2_lock(bridge0); 01124 ao2_lock(bridge1); 01125 01126 /* If the first bridge currently has 2 channels and is not capable of becoming a multimixing bridge we can not merge */ 01127 if ((bridge0->num + bridge1->num) > 2 && (!(bridge0->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) && !ast_test_flag(&bridge0->feature_flags, AST_BRIDGE_FLAG_SMART))) { 01128 ao2_unlock(bridge1); 01129 ao2_unlock(bridge0); 01130 ast_debug(1, "Can't merge bridge %p into bridge %p, multimix is needed and it could not be acquired.\n", bridge1, bridge0); 01131 return -1; 01132 } 01133 01134 ast_debug(1, "Merging channels from bridge %p into bridge %p\n", bridge1, bridge0); 01135 01136 /* Perform smart bridge operation on bridge we are merging into so it can change bridge technology if needed */ 01137 if (smart_bridge_operation(bridge0, NULL, bridge0->num + bridge1->num)) { 01138 ao2_unlock(bridge1); 01139 ao2_unlock(bridge0); 01140 ast_debug(1, "Can't merge bridge %p into bridge %p, tried to perform smart bridge operation and failed.\n", bridge1, bridge0); 01141 return -1; 01142 } 01143 01144 /* If a thread is currently executing on bridge1 tell it to stop */ 01145 if (bridge1->thread) { 01146 ast_debug(1, "Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0); 01147 bridge1->thread = AST_PTHREADT_STOP; 01148 } 01149 01150 /* Move channels from bridge1 over to bridge0 */ 01151 while ((bridge_channel = AST_LIST_REMOVE_HEAD(&bridge1->channels, entry))) { 01152 /* Tell the technology handling bridge1 that the bridge channel is leaving */ 01153 if (bridge1->technology->leave) { 01154 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->technology->name, bridge_channel, bridge1); 01155 if (bridge1->technology->leave(bridge1, bridge_channel)) { 01156 ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->technology->name, bridge_channel, bridge1); 01157 } 01158 } 01159 01160 /* Drop channel count and reference count on the bridge they are leaving */ 01161 bridge1->num--; 01162 ao2_ref(bridge1, -1); 01163 01164 bridge_array_remove(bridge1, bridge_channel->chan); 01165 01166 /* Now add them into the bridge they are joining, increase channel count, and bump up reference count */ 01167 bridge_channel->bridge = bridge0; 01168 AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, entry); 01169 bridge0->num++; 01170 ao2_ref(bridge0, +1); 01171 01172 bridge_array_add(bridge0, bridge_channel->chan); 01173 01174 /* Make the channel compatible with the new bridge it is joining or else formats would go amuck */ 01175 bridge_make_compatible(bridge0, bridge_channel); 01176 01177 /* Tell the technology handling bridge0 that the bridge channel is joining */ 01178 if (bridge0->technology->join) { 01179 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->technology->name, bridge_channel, bridge0); 01180 if (bridge0->technology->join(bridge0, bridge_channel)) { 01181 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge0->technology->name, bridge_channel, bridge0); 01182 } 01183 } 01184 01185 /* Poke the bridge channel, this will cause it to wake up and execute the proper threading model for the new bridge it is in */ 01186 pthread_kill(bridge_channel->thread, SIGURG); 01187 ast_mutex_lock(&bridge_channel->lock); 01188 ast_cond_signal(&bridge_channel->cond); 01189 ast_mutex_unlock(&bridge_channel->lock); 01190 } 01191 01192 ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge1, bridge0); 01193 01194 ao2_unlock(bridge1); 01195 ao2_unlock(bridge0); 01196 01197 return 0; 01198 }
struct ast_bridge* ast_bridge_new | ( | enum ast_bridge_capability | capabilities, | |
int | flags | |||
) | [read] |
Create a new bridge.
capabilities | The capabilities that we require to be used on the bridge | |
flags | Flags that will alter the behavior of the bridge |
a | pointer to a new bridge on success | |
NULL | on failure |
Example usage:
struct ast_bridge *bridge; bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE);
This creates a simple two party bridge that will be destroyed once one of the channels hangs up.
Definition at line 449 of file bridging.c.
References ao2_alloc, ao2_ref, ast_bridge::array, ast_bridge::array_size, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_MULTIMIX, ast_bridge_destroy(), AST_BRIDGE_FLAG_SMART, ast_bridge_new(), ast_calloc, ast_debug, AST_PTHREADT_NULL, ast_set_flag, BRIDGE_ARRAY_START, ast_bridge_technology::create, destroy_bridge(), ast_bridge::feature_flags, find_best_technology(), ast_bridge_technology::name, ast_bridge::technology, and ast_bridge::thread.
Referenced by ast_bridge_new(), feature_attended_transfer(), and join_conference_bridge().
00450 { 00451 struct ast_bridge *bridge = NULL; 00452 struct ast_bridge_technology *bridge_technology = NULL; 00453 00454 /* If we need to be a smart bridge see if we can move between 1to1 and multimix bridges */ 00455 if (flags & AST_BRIDGE_FLAG_SMART) { 00456 struct ast_bridge *other_bridge; 00457 00458 if (!(other_bridge = ast_bridge_new((capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) ? AST_BRIDGE_CAPABILITY_MULTIMIX : AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) { 00459 return NULL; 00460 } 00461 00462 ast_bridge_destroy(other_bridge); 00463 } 00464 00465 /* If capabilities were provided use our helper function to find the "best" bridge technology, otherwise we can 00466 * just look for the most basic capability needed, single 1to1 mixing. */ 00467 bridge_technology = (capabilities ? find_best_technology(capabilities) : find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX)); 00468 00469 /* If no bridge technology was found we can't possibly do bridging so fail creation of the bridge */ 00470 if (!bridge_technology) { 00471 ast_debug(1, "Failed to find a bridge technology to satisfy capabilities %u\n", capabilities); 00472 return NULL; 00473 } 00474 00475 /* We have everything we need to create this bridge... so allocate the memory, link things together, and fire her up! */ 00476 if (!(bridge = ao2_alloc(sizeof(*bridge), destroy_bridge))) { 00477 return NULL; 00478 } 00479 00480 bridge->technology = bridge_technology; 00481 bridge->thread = AST_PTHREADT_NULL; 00482 00483 /* Create an array of pointers for the channels that will be joining us */ 00484 bridge->array = ast_calloc(BRIDGE_ARRAY_START, sizeof(struct ast_channel*)); 00485 bridge->array_size = BRIDGE_ARRAY_START; 00486 00487 ast_set_flag(&bridge->feature_flags, flags); 00488 00489 /* Pass off the bridge to the technology to manipulate if needed */ 00490 if (bridge->technology->create) { 00491 ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", bridge->technology->name, bridge); 00492 if (bridge->technology->create(bridge)) { 00493 ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", bridge->technology->name, bridge); 00494 ao2_ref(bridge, -1); 00495 bridge = NULL; 00496 } 00497 } 00498 00499 return bridge; 00500 }
int ast_bridge_remove | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan | |||
) |
Remove a channel from a bridge.
bridge | Bridge that the channel is to be removed from | |
chan | Channel to remove |
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.
Definition at line 1100 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_HANGUP, and find_bridge_channel().
Referenced by menu_callback().
01101 { 01102 struct ast_bridge_channel *bridge_channel = NULL; 01103 01104 ao2_lock(bridge); 01105 01106 /* Try to find the channel that we want to remove */ 01107 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01108 ao2_unlock(bridge); 01109 return -1; 01110 } 01111 01112 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP); 01113 01114 ao2_unlock(bridge); 01115 01116 return 0; 01117 }
int ast_bridge_suspend | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan | |||
) |
Suspend a channel temporarily from a bridge.
bridge | Bridge to suspend the channel from | |
chan | Channel to suspend |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_suspend(bridge, chan);
This suspends the channel pointed to by chan from the bridge pointed to by bridge temporarily. Control of the channel is given to the calling thread. This differs from ast_bridge_depart as the channel will not be removed from the bridge.
Definition at line 1200 of file bridging.c.
References ao2_lock, ao2_unlock, bridge_channel_suspend(), and find_bridge_channel().
Referenced by leave_conference_bridge(), post_join_marked(), and post_join_unmarked().
01201 { 01202 struct ast_bridge_channel *bridge_channel; 01203 01204 ao2_lock(bridge); 01205 01206 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01207 ao2_unlock(bridge); 01208 return -1; 01209 } 01210 01211 bridge_channel_suspend(bridge, bridge_channel); 01212 01213 ao2_unlock(bridge); 01214 01215 return 0; 01216 }
void ast_bridge_technology_suspend | ( | struct ast_bridge_technology * | technology | ) |
Suspend a bridge technology from consideration.
technology | The bridge technology to suspend |
Example usage:
ast_bridge_technology_suspend(&simple_bridge_tech);
This suspends the bridge technology simple_bridge_tech from being considered when creating a new bridge. Existing bridges using the bridge technology are not affected.
Definition at line 1236 of file bridging.c.
References ast_bridge_technology::suspended.
01237 { 01238 technology->suspended = 1; 01239 return; 01240 }
int ast_bridge_technology_unregister | ( | struct ast_bridge_technology * | technology | ) |
Unregister a bridge technology from use.
technology | The bridge technology to unregister |
0 | on success | |
-1 | on failure |
Example usage:
ast_bridge_technology_unregister(&simple_bridge_tech);
This unregisters a bridge technlogy declared as the structure simple_bridge_tech with the bridging core. It will no longer be considered when creating a new bridge.
Definition at line 99 of file bridging.c.
References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose, ast_bridge_technology::name, option_verbose, and VERBOSE_PREFIX_2.
Referenced by unload_module().
00100 { 00101 struct ast_bridge_technology *current = NULL; 00102 00103 AST_RWLIST_WRLOCK(&bridge_technologies); 00104 00105 /* Ensure the bridge technology is registered before removing it */ 00106 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) { 00107 if (current == technology) { 00108 AST_RWLIST_REMOVE_CURRENT(entry); 00109 if (option_verbose > 1) { 00110 ast_verbose(VERBOSE_PREFIX_2 "Unregistered bridge technology %s\n", technology->name); 00111 } 00112 break; 00113 } 00114 } 00115 AST_RWLIST_TRAVERSE_SAFE_END; 00116 00117 AST_RWLIST_UNLOCK(&bridge_technologies); 00118 00119 return current ? 0 : -1; 00120 }
void ast_bridge_technology_unsuspend | ( | struct ast_bridge_technology * | technology | ) |
Unsuspend a bridge technology.
technology | The bridge technology to unsuspend |
Example usage:
ast_bridge_technology_unsuspend(&simple_bridge_tech);
This makes the bridge technology simple_bridge_tech considered when creating a new bridge again.
Definition at line 1242 of file bridging.c.
References ast_bridge_technology::suspended.
01243 { 01244 technology->suspended = 0; 01245 return; 01246 }
int ast_bridge_unsuspend | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan | |||
) |
Unsuspend a channel from a bridge.
bridge | Bridge to unsuspend the channel from | |
chan | Channel to unsuspend |
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.
Definition at line 1218 of file bridging.c.
References ao2_lock, ao2_unlock, bridge_channel_unsuspend(), and find_bridge_channel().
Referenced by leave_conference_bridge(), post_join_marked(), and post_join_unmarked().
01219 { 01220 struct ast_bridge_channel *bridge_channel; 01221 01222 ao2_lock(bridge); 01223 01224 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01225 ao2_unlock(bridge); 01226 return -1; 01227 } 01228 01229 bridge_channel_unsuspend(bridge, bridge_channel); 01230 01231 ao2_unlock(bridge); 01232 01233 return 0; 01234 }
static void bridge_array_add | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan | |||
) | [static] |
Helper function to add a channel to the bridge array.
Definition at line 153 of file bridging.c.
References ast_bridge::array, ast_bridge::array_num, ast_bridge::array_size, ast_debug, ast_log(), ast_realloc, BRIDGE_ARRAY_GROW, bridge_poke(), LOG_ERROR, and ast_bridge::waiting.
Referenced by ast_bridge_merge(), bridge_channel_join(), and bridge_channel_unsuspend().
00154 { 00155 /* We have to make sure the bridge thread is not using the bridge array before messing with it */ 00156 while (bridge->waiting) { 00157 bridge_poke(bridge); 00158 sched_yield(); 00159 } 00160 00161 bridge->array[bridge->array_num++] = chan; 00162 00163 ast_debug(1, "Added channel %s(%p) to bridge array on %p, new count is %d\n", chan->name, chan, bridge, (int)bridge->array_num); 00164 00165 /* If the next addition of a channel will exceed our array size grow it out */ 00166 if (bridge->array_num == bridge->array_size) { 00167 struct ast_channel **tmp; 00168 ast_debug(1, "Growing bridge array on %p from %d to %d\n", bridge, (int)bridge->array_size, (int)bridge->array_size + BRIDGE_ARRAY_GROW); 00169 if (!(tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel *)))) { 00170 ast_log(LOG_ERROR, "Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge); 00171 return; 00172 } 00173 bridge->array = tmp; 00174 bridge->array_size += BRIDGE_ARRAY_GROW; 00175 } 00176 00177 return; 00178 }
static void bridge_array_remove | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan | |||
) | [static] |
Helper function to remove a channel from the bridge array.
Definition at line 184 of file bridging.c.
References ast_bridge::array, ast_bridge::array_num, ast_debug, bridge_poke(), and ast_bridge::waiting.
Referenced by ast_bridge_merge(), bridge_channel_join(), and bridge_channel_suspend().
00185 { 00186 int i; 00187 00188 /* We have to make sure the bridge thread is not using the bridge array before messing with it */ 00189 while (bridge->waiting) { 00190 bridge_poke(bridge); 00191 sched_yield(); 00192 } 00193 00194 for (i = 0; i < bridge->array_num; i++) { 00195 if (bridge->array[i] == chan) { 00196 bridge->array[i] = (bridge->array[(bridge->array_num - 1)] != chan ? bridge->array[(bridge->array_num - 1)] : NULL); 00197 bridge->array[(bridge->array_num - 1)] = NULL; 00198 bridge->array_num--; 00199 ast_debug(1, "Removed channel %p from bridge array on %p, new count is %d\n", chan, bridge, (int)bridge->array_num); 00200 break; 00201 } 00202 } 00203 00204 return; 00205 }
static void bridge_channel_dtmf_stream | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel | |||
) | [static] |
Internal function that plays back DTMF on a bridge channel.
Definition at line 857 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_copy_string(), ast_debug, ast_dtmf_stream(), ast_bridge_channel::chan, and ast_bridge_channel::dtmf_stream_q.
Referenced by bridge_channel_join().
00858 { 00859 char dtmf_q[8] = ""; 00860 00861 ast_copy_string(dtmf_q, bridge_channel->dtmf_stream_q, sizeof(dtmf_q)); 00862 bridge_channel->dtmf_stream_q[0] = '\0'; 00863 00864 ast_debug(1, "Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel); 00865 ast_dtmf_stream(bridge_channel->chan, NULL, dtmf_q, 250, 0); 00866 00867 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT); 00868 00869 return; 00870 }
static void bridge_channel_feature | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel | |||
) | [static] |
Internal function that executes a feature on a bridge channel.
Definition at line 791 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_dtmf_stream(), ast_clear_flag, ast_debug, AST_FLAG_END_DTMF_ONLY, AST_LIST_TRAVERSE, ast_set_flag, ast_waitfordigit(), ast_bridge_features_hook::callback, ast_bridge_channel::chan, ast_bridge_features_hook::dtmf, ast_bridge::features, ast_bridge_channel::features, ast_bridge_features_hook::hook_pvt, and MAXIMUM_DTMF_FEATURE_STRING.
Referenced by bridge_channel_join().
00792 { 00793 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features); 00794 struct ast_bridge_features_hook *hook = NULL; 00795 char dtmf[MAXIMUM_DTMF_FEATURE_STRING] = ""; 00796 int look_for_dtmf = 1, dtmf_len = 0; 00797 00798 /* The channel is now under our control and we don't really want any begin frames to do our DTMF matching so disable 'em at the core level */ 00799 ast_set_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY); 00800 00801 /* Wait for DTMF on the channel and put it into a buffer. If the buffer matches any feature hook execute the hook. */ 00802 while (look_for_dtmf) { 00803 int res = ast_waitfordigit(bridge_channel->chan, 3000); 00804 00805 /* If the above timed out simply exit */ 00806 if (!res) { 00807 ast_debug(1, "DTMF feature string collection on bridge channel %p timed out\n", bridge_channel); 00808 break; 00809 } else if (res < 0) { 00810 ast_debug(1, "DTMF feature string collection failed on bridge channel %p for some reason\n", bridge_channel); 00811 break; 00812 } 00813 00814 /* Add the above DTMF into the DTMF string so we can do our matching */ 00815 dtmf[dtmf_len++] = res; 00816 00817 ast_debug(1, "DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf); 00818 00819 /* Assume that we do not want to look for DTMF any longer */ 00820 look_for_dtmf = 0; 00821 00822 /* See if a DTMF feature hook matches or can match */ 00823 AST_LIST_TRAVERSE(&features->hooks, hook, entry) { 00824 /* If this hook matches just break out now */ 00825 if (!strcmp(hook->dtmf, dtmf)) { 00826 ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel); 00827 break; 00828 } else if (!strncmp(hook->dtmf, dtmf, dtmf_len)) { 00829 ast_debug(1, "DTMF feature hook %p can match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel); 00830 look_for_dtmf = 1; 00831 } else { 00832 ast_debug(1, "DTMF feature hook %p does not match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel); 00833 } 00834 } 00835 00836 /* If we have reached the maximum length of a DTMF feature string bail out */ 00837 if (dtmf_len == MAXIMUM_DTMF_FEATURE_STRING) { 00838 break; 00839 } 00840 } 00841 00842 /* Since we are done bringing DTMF in return to using both begin and end frames */ 00843 ast_clear_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY); 00844 00845 /* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */ 00846 if (hook) { 00847 hook->callback(bridge, bridge_channel, hook->hook_pvt); 00848 } else { 00849 ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan); 00850 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT); 00851 } 00852 00853 return; 00854 }
static enum ast_bridge_channel_state bridge_channel_join | ( | struct ast_bridge_channel * | bridge_channel | ) | [static] |
Join a channel to a bridge and handle anything the bridge may want us to do.
Definition at line 873 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CAPABILITY_MULTITHREADED, AST_BRIDGE_CAPABILITY_THREAD, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DTMF, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_FEATURE, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_BRIDGE_CHANNEL_STATE_WAIT, AST_BRIDGE_FLAG_SMART, ast_debug, ast_getformatname(), AST_LIST_INSERT_TAIL, AST_LIST_REMOVE, ast_pthread_create, AST_PTHREADT_NULL, ast_set_read_format(), ast_set_write_format(), ast_test_flag, ast_channel::bridge, ast_bridge_channel::bridge, bridge_array_add(), bridge_array_remove(), bridge_channel_dtmf_stream(), bridge_channel_feature(), bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), bridge_channel_suspend(), bridge_channel_unsuspend(), bridge_check_dissolve(), bridge_make_compatible(), bridge_thread(), ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge::feature_flags, find_bridge_channel(), ast_bridge_technology::join, ast_bridge_technology::leave, ast_bridge_technology::name, ast_bridge::num, ast_channel::readformat, smart_bridge_operation(), ast_bridge_channel::state, ast_bridge::stop, ast_bridge_channel::swap, ast_bridge::technology, ast_bridge::thread, ast_bridge_channel::thread, and ast_channel::writeformat.
Referenced by ast_bridge_join(), and bridge_channel_thread().
00874 { 00875 int formats[2] = { bridge_channel->chan->readformat, bridge_channel->chan->writeformat }; 00876 enum ast_bridge_channel_state state; 00877 00878 /* Record the thread that will be the owner of us */ 00879 bridge_channel->thread = pthread_self(); 00880 00881 ast_debug(1, "Joining bridge channel %p to bridge %p\n", bridge_channel, bridge_channel->bridge); 00882 00883 ao2_lock(bridge_channel->bridge); 00884 00885 state = bridge_channel->state; 00886 00887 /* Add channel into the bridge */ 00888 AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry); 00889 bridge_channel->bridge->num++; 00890 00891 bridge_array_add(bridge_channel->bridge, bridge_channel->chan); 00892 00893 if (bridge_channel->swap) { 00894 struct ast_bridge_channel *bridge_channel2 = NULL; 00895 00896 /* If we are performing a swap operation we do not need to execute the smart bridge operation as the actual number of channels involved will not have changed, we just need to tell the other channel to leave */ 00897 if ((bridge_channel2 = find_bridge_channel(bridge_channel->bridge, bridge_channel->swap))) { 00898 ast_debug(1, "Swapping bridge channel %p out from bridge %p so bridge channel %p can slip in\n", bridge_channel2, bridge_channel->bridge, bridge_channel); 00899 ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP); 00900 } 00901 00902 bridge_channel->swap = NULL; 00903 } else if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) { 00904 /* Perform the smart bridge operation, basically see if we need to move around between technologies */ 00905 smart_bridge_operation(bridge_channel->bridge, bridge_channel, bridge_channel->bridge->num); 00906 } 00907 00908 /* Make the channel compatible with the bridge */ 00909 bridge_make_compatible(bridge_channel->bridge, bridge_channel); 00910 00911 /* Tell the bridge technology we are joining so they set us up */ 00912 if (bridge_channel->bridge->technology->join) { 00913 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 00914 if (bridge_channel->bridge->technology->join(bridge_channel->bridge, bridge_channel)) { 00915 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 00916 } 00917 } 00918 00919 /* Actually execute the respective threading model, and keep our bridge thread alive */ 00920 while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) { 00921 /* Update bridge pointer on channel */ 00922 bridge_channel->chan->bridge = bridge_channel->bridge; 00923 /* If the technology requires a thread and one is not running, start it up */ 00924 if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) { 00925 bridge_channel->bridge->stop = 0; 00926 ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge); 00927 ao2_ref(bridge_channel->bridge, +1); 00928 if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) { 00929 ast_debug(1, "Failed to create a bridge thread for bridge %p, giving it another go.\n", bridge_channel->bridge); 00930 ao2_ref(bridge_channel->bridge, -1); 00931 continue; 00932 } 00933 } 00934 /* Execute the threading model */ 00935 state = (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTITHREADED ? bridge_channel_join_multithreaded(bridge_channel) : bridge_channel_join_singlethreaded(bridge_channel)); 00936 /* Depending on the above state see what we need to do */ 00937 if (state == AST_BRIDGE_CHANNEL_STATE_FEATURE) { 00938 bridge_channel_suspend(bridge_channel->bridge, bridge_channel); 00939 bridge_channel_feature(bridge_channel->bridge, bridge_channel); 00940 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel); 00941 } else if (state == AST_BRIDGE_CHANNEL_STATE_DTMF) { 00942 bridge_channel_suspend(bridge_channel->bridge, bridge_channel); 00943 bridge_channel_dtmf_stream(bridge_channel->bridge, bridge_channel); 00944 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel); 00945 } 00946 } 00947 00948 bridge_channel->chan->bridge = NULL; 00949 00950 /* See if we need to dissolve the bridge itself if they hung up */ 00951 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_END) { 00952 bridge_check_dissolve(bridge_channel->bridge, bridge_channel); 00953 } 00954 00955 /* Tell the bridge technology we are leaving so they tear us down */ 00956 if (bridge_channel->bridge->technology->leave) { 00957 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 00958 if (bridge_channel->bridge->technology->leave(bridge_channel->bridge, bridge_channel)) { 00959 ast_debug(1, "Bridge technology %s failed to leave %p from bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 00960 } 00961 } 00962 00963 /* Remove channel from the bridge */ 00964 bridge_channel->bridge->num--; 00965 AST_LIST_REMOVE(&bridge_channel->bridge->channels, bridge_channel, entry); 00966 00967 bridge_array_remove(bridge_channel->bridge, bridge_channel->chan); 00968 00969 /* Perform the smart bridge operation if needed since a channel has left */ 00970 if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) { 00971 smart_bridge_operation(bridge_channel->bridge, NULL, bridge_channel->bridge->num); 00972 } 00973 00974 ao2_unlock(bridge_channel->bridge); 00975 00976 /* Restore original formats of the channel as they came in */ 00977 if (bridge_channel->chan->readformat != formats[0]) { 00978 ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]); 00979 if (ast_set_read_format(bridge_channel->chan, formats[0])) { 00980 ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]); 00981 } 00982 } 00983 if (bridge_channel->chan->writeformat != formats[1]) { 00984 ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]); 00985 if (ast_set_write_format(bridge_channel->chan, formats[1])) { 00986 ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]); 00987 } 00988 } 00989 00990 return bridge_channel->state; 00991 }
static enum ast_bridge_channel_state bridge_channel_join_multithreaded | ( | struct ast_bridge_channel * | bridge_channel | ) | [static] |
Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve.
Definition at line 711 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge_handle_trip(), ast_cond_wait, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_waitfor_nandfds(), ast_bridge_channel::bridge, ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge_technology::fd, ast_bridge_channel::fds, ast_bridge_channel::lock, ast_bridge_channel::state, ast_bridge_channel::suspended, and ast_bridge::technology.
Referenced by bridge_channel_join().
00712 { 00713 int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1; 00714 struct ast_channel *chan = NULL; 00715 00716 /* Add any file descriptors we may want to monitor */ 00717 if (bridge_channel->bridge->technology->fd) { 00718 for (i = 0; i < 4; i ++) { 00719 if (bridge_channel->fds[i] >= 0) { 00720 fds[nfds++] = bridge_channel->fds[i]; 00721 } 00722 } 00723 } 00724 00725 ao2_unlock(bridge_channel->bridge); 00726 00727 /* Wait for data to either come from the channel or us to be signalled */ 00728 if (!bridge_channel->suspended) { 00729 ast_debug(1, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); 00730 chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms); 00731 } else { 00732 ast_mutex_lock(&bridge_channel->lock); 00733 ast_debug(1, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); 00734 ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock); 00735 ast_mutex_unlock(&bridge_channel->lock); 00736 } 00737 00738 ao2_lock(bridge_channel->bridge); 00739 00740 if (!bridge_channel->suspended) { 00741 ast_bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd); 00742 } 00743 00744 return bridge_channel->state; 00745 }
static enum ast_bridge_channel_state bridge_channel_join_singlethreaded | ( | struct ast_bridge_channel * | bridge_channel | ) | [static] |
Run in a singlethreaded model. Each joined channel yields itself to the main bridge thread. TODO: Improve.
Definition at line 748 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_CHANNEL_STATE_WAIT, ast_cond_wait, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_bridge_channel::bridge, ast_bridge_channel::cond, ast_bridge_channel::lock, and ast_bridge_channel::state.
Referenced by bridge_channel_join().
00749 { 00750 ao2_unlock(bridge_channel->bridge); 00751 ast_mutex_lock(&bridge_channel->lock); 00752 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) { 00753 ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); 00754 ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock); 00755 } 00756 ast_mutex_unlock(&bridge_channel->lock); 00757 ao2_lock(bridge_channel->bridge); 00758 00759 return bridge_channel->state; 00760 }
static void bridge_channel_suspend | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel | |||
) | [static] |
Internal function that suspends a channel from a bridge.
Definition at line 763 of file bridging.c.
References bridge_array_remove(), ast_bridge_channel::chan, ast_bridge_technology::suspend, ast_bridge_channel::suspended, and ast_bridge::technology.
Referenced by ast_bridge_suspend(), and bridge_channel_join().
00764 { 00765 bridge_channel->suspended = 1; 00766 00767 bridge_array_remove(bridge, bridge_channel->chan); 00768 00769 if (bridge->technology->suspend) { 00770 bridge->technology->suspend(bridge, bridge_channel); 00771 } 00772 00773 return; 00774 }
static void* bridge_channel_thread | ( | void * | data | ) | [static] |
Thread responsible for imparted bridged channels.
Definition at line 1021 of file bridging.c.
References ao2_ref, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, ast_cond_destroy, ast_free, ast_hangup(), ast_mutex_destroy, ast_bridge_channel::bridge, bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::cond, and ast_bridge_channel::lock.
Referenced by ast_bridge_impart().
01022 { 01023 struct ast_bridge_channel *bridge_channel = data; 01024 enum ast_bridge_channel_state state; 01025 01026 state = bridge_channel_join(bridge_channel); 01027 01028 ao2_ref(bridge_channel->bridge, -1); 01029 01030 /* If no other thread is going to take the channel then hang it up, or else we would have to service it until something else came along */ 01031 if (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP) { 01032 ast_hangup(bridge_channel->chan); 01033 } 01034 01035 /* Destroy elements of the bridge channel structure and the bridge channel structure itself */ 01036 ast_mutex_destroy(&bridge_channel->lock); 01037 ast_cond_destroy(&bridge_channel->cond); 01038 ast_free(bridge_channel); 01039 01040 return NULL; 01041 }
static void bridge_channel_unsuspend | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel | |||
) | [static] |
Internal function that unsuspends a channel from a bridge.
Definition at line 777 of file bridging.c.
References bridge_array_add(), ast_bridge_channel::chan, ast_bridge_channel::suspended, ast_bridge::technology, and ast_bridge_technology::unsuspend.
Referenced by ast_bridge_unsuspend(), and bridge_channel_join().
00778 { 00779 bridge_channel->suspended =0; 00780 00781 bridge_array_add(bridge, bridge_channel->chan); 00782 00783 if (bridge->technology->unsuspend) { 00784 bridge->technology->unsuspend(bridge, bridge_channel); 00785 } 00786 00787 return; 00788 }
static void bridge_check_dissolve | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel | |||
) | [static] |
Internal function to see whether a bridge should dissolve, and if so do it.
Definition at line 222 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DEPART, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_BRIDGE_FLAG_DISSOLVE, ast_debug, AST_LIST_TRAVERSE, ast_test_flag, ast_bridge_features::feature_flags, ast_bridge::feature_flags, ast_bridge_channel::features, ast_bridge_channel::state, and ast_bridge_features::usable.
Referenced by bridge_channel_join().
00223 { 00224 struct ast_bridge_channel *bridge_channel2 = NULL; 00225 00226 if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE) && (!bridge_channel->features || !bridge_channel->features->usable || !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE))) { 00227 return; 00228 } 00229 00230 ast_debug(1, "Dissolving bridge %p\n", bridge); 00231 00232 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) { 00233 if (bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_END && bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_DEPART) { 00234 ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP); 00235 } 00236 } 00237 00238 return; 00239 }
static int bridge_drop_control_frame | ( | int | subclass | ) | [static] |
Internal function used to determine whether a control frame should be dropped or not.
Definition at line 266 of file bridging.c.
References AST_CONTROL_ANSWER.
Referenced by ast_bridge_handle_trip().
00267 { 00268 switch (subclass) { 00269 case AST_CONTROL_ANSWER: 00270 case -1: 00271 return 1; 00272 default: 00273 return 0; 00274 } 00275 }
static struct ast_frame* bridge_handle_dtmf | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel, | |||
struct ast_frame * | frame | |||
) | [static, read] |
Internal function to handle DTMF from a channel.
Definition at line 242 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_FEATURE, ast_frfree, AST_LIST_TRAVERSE, ast_bridge_features_hook::dtmf, ast_bridge::features, ast_bridge_channel::features, ast_frame_subclass::integer, ast_frame::subclass, and ast_bridge_features::usable.
Referenced by ast_bridge_handle_trip().
00243 { 00244 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features); 00245 struct ast_bridge_features_hook *hook = NULL; 00246 00247 /* If the features structure we grabbed is not usable immediately return the frame */ 00248 if (!features->usable) { 00249 return frame; 00250 } 00251 00252 /* See if this DTMF matches the beginnings of any feature hooks, if so we switch to the feature state to either execute the feature or collect more DTMF */ 00253 AST_LIST_TRAVERSE(&features->hooks, hook, entry) { 00254 if (hook->dtmf[0] == frame->subclass.integer) { 00255 ast_frfree(frame); 00256 frame = NULL; 00257 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_FEATURE); 00258 break; 00259 } 00260 } 00261 00262 return frame; 00263 }
static int bridge_make_compatible | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel | |||
) | [static] |
Definition at line 544 of file bridging.c.
References ast_best_codec(), ast_debug, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_set_read_format(), ast_set_write_format(), ast_bridge_channel::chan, ast_bridge_technology::formats, LOG_WARNING, ast_bridge_technology::name, option_debug, ast_channel::readformat, ast_bridge::technology, and ast_channel::writeformat.
Referenced by ast_bridge_merge(), bridge_channel_join(), and smart_bridge_operation().
00545 { 00546 format_t formats[2] = {bridge_channel->chan->readformat, bridge_channel->chan->writeformat}; 00547 00548 /* Are the formats currently in use something ths bridge can handle? */ 00549 if (!(bridge->technology->formats & bridge_channel->chan->readformat)) { 00550 format_t best_format = ast_best_codec(bridge->technology->formats); 00551 00552 /* Read format is a no go... */ 00553 if (option_debug) { 00554 char codec_buf[512]; 00555 ast_debug(1, "Bridge technology %s wants to read any of formats %s but channel has %s\n", bridge->technology->name, 00556 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats), 00557 ast_getformatname(formats[0])); 00558 } 00559 /* Switch read format to the best one chosen */ 00560 if (ast_set_read_format(bridge_channel->chan, best_format)) { 00561 ast_log(LOG_WARNING, "Failed to set channel %s to read format %s\n", bridge_channel->chan->name, ast_getformatname(best_format)); 00562 return -1; 00563 } 00564 ast_debug(1, "Bridge %p put channel %s into read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format)); 00565 } else { 00566 ast_debug(1, "Bridge %p is happy that channel %s already has read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[0])); 00567 } 00568 00569 if (!(bridge->technology->formats & formats[1])) { 00570 int best_format = ast_best_codec(bridge->technology->formats); 00571 00572 /* Write format is a no go... */ 00573 if (option_debug) { 00574 char codec_buf[512]; 00575 ast_debug(1, "Bridge technology %s wants to write any of formats %s but channel has %s\n", bridge->technology->name, 00576 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats), 00577 ast_getformatname(formats[1])); 00578 } 00579 /* Switch write format to the best one chosen */ 00580 if (ast_set_write_format(bridge_channel->chan, best_format)) { 00581 ast_log(LOG_WARNING, "Failed to set channel %s to write format %s\n", bridge_channel->chan->name, ast_getformatname(best_format)); 00582 return -1; 00583 } 00584 ast_debug(1, "Bridge %p put channel %s into write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format)); 00585 } else { 00586 ast_debug(1, "Bridge %p is happy that channel %s already has write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[1])); 00587 } 00588 00589 return 0; 00590 }
static void bridge_poke | ( | struct ast_bridge * | bridge | ) | [static] |
Helper function to poke the bridge thread.
Definition at line 139 of file bridging.c.
References AST_PTHREADT_NULL, AST_PTHREADT_STOP, and ast_bridge::thread.
Referenced by ast_bridge_destroy(), bridge_array_add(), bridge_array_remove(), and smart_bridge_operation().
00140 { 00141 /* Poke the thread just in case */ 00142 if (bridge->thread != AST_PTHREADT_NULL && bridge->thread != AST_PTHREADT_STOP) { 00143 pthread_kill(bridge->thread, SIGURG); 00144 } 00145 00146 return; 00147 }
static void* bridge_thread | ( | void * | data | ) | [static] |
Bridge thread function.
Definition at line 354 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, ast_bridge::array_num, ast_debug, AST_PTHREADT_NULL, generic_thread_loop(), ast_bridge::refresh, ast_bridge::stop, ast_bridge::technology, ast_bridge::thread, and ast_bridge_technology::thread.
Referenced by bridge_channel_join(), and smart_bridge_operation().
00355 { 00356 struct ast_bridge *bridge = data; 00357 int res = 0; 00358 00359 ao2_lock(bridge); 00360 00361 ast_debug(1, "Started bridge thread for %p\n", bridge); 00362 00363 /* Loop around until we are told to stop */ 00364 while (!bridge->stop && bridge->array_num && !res) { 00365 /* In case the refresh bit was set simply set it back to off */ 00366 bridge->refresh = 0; 00367 00368 ast_debug(1, "Launching bridge thread function %p for bridge %p\n", (bridge->technology->thread ? bridge->technology->thread : &generic_thread_loop), bridge); 00369 00370 /* Execute the appropriate thread function. If the technology does not provide one we use the generic one */ 00371 res = (bridge->technology->thread ? bridge->technology->thread(bridge) : generic_thread_loop(bridge)); 00372 } 00373 00374 ast_debug(1, "Ending bridge thread for %p\n", bridge); 00375 00376 /* Indicate the bridge thread is no longer active */ 00377 bridge->thread = AST_PTHREADT_NULL; 00378 ao2_unlock(bridge); 00379 00380 ao2_ref(bridge, -1); 00381 00382 return NULL; 00383 }
static void destroy_bridge | ( | void * | obj | ) | [static] |
Definition at line 421 of file bridging.c.
References ast_bridge::array, ast_bridge_features_cleanup(), ast_debug, ast_free, ast_module_unref(), ast_bridge_technology::destroy, ast_bridge::features, ast_bridge_technology::mod, ast_bridge_technology::name, and ast_bridge::technology.
Referenced by ast_bridge_new().
00422 { 00423 struct ast_bridge *bridge = obj; 00424 00425 ast_debug(1, "Actually destroying bridge %p, nobody wants it anymore\n", bridge); 00426 00427 /* Pass off the bridge to the technology to destroy if needed */ 00428 if (bridge->technology->destroy) { 00429 ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge); 00430 if (bridge->technology->destroy(bridge)) { 00431 ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->technology->name, bridge); 00432 } 00433 } 00434 00435 /* We are no longer using the bridge technology so decrement the module reference count on it */ 00436 if (bridge->technology->mod) { 00437 ast_module_unref(bridge->technology->mod); 00438 } 00439 00440 /* Last but not least clean up the features configuration */ 00441 ast_bridge_features_cleanup(&bridge->features); 00442 00443 /* Drop the array of channels */ 00444 ast_free(bridge->array); 00445 00446 return; 00447 }
static struct ast_bridge_technology* find_best_technology | ( | enum ast_bridge_capability | capabilities | ) | [static, read] |
Helper function used to find the "best" bridge technology given a specified capabilities.
Definition at line 386 of file bridging.c.
References ast_debug, ast_module_ref(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_bridge_technology::capabilities, ast_bridge_technology::name, ast_bridge_technology::preference, and ast_bridge_technology::suspended.
Referenced by ast_bridge_check(), ast_bridge_new(), and smart_bridge_operation().
00387 { 00388 struct ast_bridge_technology *current = NULL, *best = NULL; 00389 00390 AST_RWLIST_RDLOCK(&bridge_technologies); 00391 AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) { 00392 ast_debug(1, "Bridge technology %s has capabilities %d and we want %u\n", current->name, current->capabilities, capabilities); 00393 if (current->suspended) { 00394 ast_debug(1, "Bridge technology %s is suspended. Skipping.\n", current->name); 00395 continue; 00396 } 00397 if (!(current->capabilities & capabilities)) { 00398 ast_debug(1, "Bridge technology %s does not have the capabilities we need.\n", current->name); 00399 continue; 00400 } 00401 if (best && best->preference < current->preference) { 00402 ast_debug(1, "Bridge technology %s has preference %u while %s has preference %u. Skipping.\n", current->name, current->preference, best->name, best->preference); 00403 continue; 00404 } 00405 best = current; 00406 } 00407 00408 if (best) { 00409 /* Increment it's module reference count if present so it does not get unloaded while in use */ 00410 if (best->mod) { 00411 ast_module_ref(best->mod); 00412 } 00413 ast_debug(1, "Chose bridge technology %s\n", best->name); 00414 } 00415 00416 AST_RWLIST_UNLOCK(&bridge_technologies); 00417 00418 return best; 00419 }
static struct ast_bridge_channel* find_bridge_channel | ( | struct ast_bridge * | bridge, | |
struct ast_channel * | chan | |||
) | [static, read] |
Helper function to find a bridge channel given a channel.
Definition at line 208 of file bridging.c.
References AST_LIST_TRAVERSE, and ast_bridge_channel::chan.
Referenced by ast_bridge_depart(), ast_bridge_handle_trip(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), and bridge_channel_join().
00209 { 00210 struct ast_bridge_channel *bridge_channel = NULL; 00211 00212 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { 00213 if (bridge_channel->chan == chan) { 00214 break; 00215 } 00216 } 00217 00218 return bridge_channel; 00219 }
static int generic_thread_loop | ( | struct ast_bridge * | bridge | ) | [static] |
Generic thread loop, TODO: Rethink this/improve it.
Definition at line 326 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge::array, ast_bridge::array_num, ast_bridge_handle_trip(), ast_waitfor_n(), first, ast_bridge::refresh, ast_bridge::stop, and ast_bridge::waiting.
Referenced by bridge_thread().
00327 { 00328 while (!bridge->stop && !bridge->refresh && bridge->array_num) { 00329 struct ast_channel *winner = NULL; 00330 int to = -1; 00331 00332 /* Move channels around for priority reasons if we have more than one channel in our array */ 00333 if (bridge->array_num > 1) { 00334 struct ast_channel *first = bridge->array[0]; 00335 memmove(bridge->array, bridge->array + 1, sizeof(struct ast_channel *) * (bridge->array_num - 1)); 00336 bridge->array[(bridge->array_num - 1)] = first; 00337 } 00338 00339 /* Wait on the channels */ 00340 bridge->waiting = 1; 00341 ao2_unlock(bridge); 00342 winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to); 00343 bridge->waiting = 0; 00344 ao2_lock(bridge); 00345 00346 /* Process whatever they did */ 00347 ast_bridge_handle_trip(bridge, NULL, winner, -1); 00348 } 00349 00350 return 0; 00351 }
static int smart_bridge_operation | ( | struct ast_bridge * | bridge, | |
struct ast_bridge_channel * | bridge_channel, | |||
int | count | |||
) | [static] |
Perform the smart bridge operation. Basically sees if a new bridge technology should be used instead of the current one.
Definition at line 593 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_CAPABILITY_THREAD, ast_cond_signal, ast_debug, AST_LIST_TRAVERSE, ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, bridge_make_compatible(), bridge_poke(), ast_bridge::bridge_pvt, bridge_thread(), ast_bridge_technology::capabilities, ast_bridge_channel::cond, ast_bridge_technology::create, find_best_technology(), ast_bridge_technology::join, ast_bridge_channel::lock, ast_bridge_technology::name, ast_bridge::refresh, ast_bridge::stop, ast_bridge::technology, ast_bridge_channel::thread, and ast_bridge::thread.
Referenced by ast_bridge_merge(), and bridge_channel_join().
00594 { 00595 enum ast_bridge_capability new_capabilities = 0; 00596 struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology; 00597 struct ast_bridge temp_bridge = { 00598 .technology = bridge->technology, 00599 .bridge_pvt = bridge->bridge_pvt, 00600 }; 00601 struct ast_bridge_channel *bridge_channel2 = NULL; 00602 00603 /* Based on current feature determine whether we want to change bridge technologies or not */ 00604 if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) { 00605 if (count <= 2) { 00606 ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name); 00607 return 0; 00608 } 00609 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX; 00610 } else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) { 00611 if (count > 2) { 00612 ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name); 00613 return 0; 00614 } 00615 new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX; 00616 } 00617 00618 if (!new_capabilities) { 00619 ast_debug(1, "Bridge '%p' has no new capabilities, not performing smart bridge operation.\n", bridge); 00620 return 0; 00621 } 00622 00623 /* Attempt to find a new bridge technology to satisfy the capabilities */ 00624 if (!(new_technology = find_best_technology(new_capabilities))) { 00625 ast_debug(1, "Smart bridge operation was unable to find new bridge technology with capabilities %u to satisfy bridge %p\n", new_capabilities, bridge); 00626 return -1; 00627 } 00628 00629 ast_debug(1, "Performing smart bridge operation on bridge %p, moving from bridge technology %s to %s\n", bridge, old_technology->name, new_technology->name); 00630 00631 /* If a thread is currently executing for the current technology tell it to stop */ 00632 if (bridge->thread != AST_PTHREADT_NULL) { 00633 /* If the new bridge technology also needs a thread simply tell the bridge thread to refresh itself. This has the benefit of not incurring the cost/time of tearing down and bringing up a new thread. */ 00634 if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) { 00635 ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge); 00636 bridge->refresh = 1; 00637 bridge_poke(bridge); 00638 } else { 00639 pthread_t bridge_thread = bridge->thread; 00640 ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge); 00641 bridge->stop = 1; 00642 bridge_poke(bridge); 00643 ao2_unlock(bridge); 00644 pthread_join(bridge_thread, NULL); 00645 ao2_lock(bridge); 00646 } 00647 } 00648 00649 /* Since we are soon going to pass this bridge to a new technology we need to NULL out the bridge_pvt pointer but don't worry as it still exists in temp_bridge, ditto for the old technology */ 00650 bridge->bridge_pvt = NULL; 00651 bridge->technology = new_technology; 00652 00653 /* Pass the bridge to the new bridge technology so it can set it up */ 00654 if (new_technology->create) { 00655 ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge); 00656 if (new_technology->create(bridge)) { 00657 ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge); 00658 } 00659 } 00660 00661 /* Move existing channels over to the new technology, while taking them away from the old one */ 00662 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) { 00663 /* Skip over channel that initiated the smart bridge operation */ 00664 if (bridge_channel == bridge_channel2) { 00665 continue; 00666 } 00667 00668 /* First we part them from the old technology */ 00669 if (old_technology->leave) { 00670 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p (really %p)\n", old_technology->name, bridge_channel2, &temp_bridge, bridge); 00671 if (old_technology->leave(&temp_bridge, bridge_channel2)) { 00672 ast_debug(1, "Bridge technology %s failed to allow %p (really %p) to leave bridge %p\n", old_technology->name, bridge_channel2, &temp_bridge, bridge); 00673 } 00674 } 00675 00676 /* Second we make them compatible again with the bridge */ 00677 bridge_make_compatible(bridge, bridge_channel2); 00678 00679 /* Third we join them to the new technology */ 00680 if (new_technology->join) { 00681 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge); 00682 if (new_technology->join(bridge, bridge_channel2)) { 00683 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge); 00684 } 00685 } 00686 00687 /* Fourth we tell them to wake up so they become aware that they above has happened */ 00688 pthread_kill(bridge_channel2->thread, SIGURG); 00689 ast_mutex_lock(&bridge_channel2->lock); 00690 ast_cond_signal(&bridge_channel2->cond); 00691 ast_mutex_unlock(&bridge_channel2->lock); 00692 } 00693 00694 /* Now that all the channels have been moved over we need to get rid of all the information the old technology may have left around */ 00695 if (old_technology->destroy) { 00696 ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge); 00697 if (old_technology->destroy(&temp_bridge)) { 00698 ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p (really %p)... some memory may have leaked\n", old_technology->name, &temp_bridge, bridge); 00699 } 00700 } 00701 00702 /* Finally if the old technology has module referencing remove our reference, we are no longer going to use it */ 00703 if (old_technology->mod) { 00704 ast_module_unref(old_technology->mod); 00705 } 00706 00707 return 0; 00708 }
char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING] [static] |
Default DTMF keys for built in features
Definition at line 58 of file bridging.c.
void* builtin_features_handlers[AST_BRIDGE_BUILTIN_END] [static] |
Function handlers for the built in features
Definition at line 61 of file bridging.c.