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