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

Go to the source code of this file.
Data Structures | |
| struct | bridge_technologies |
Defines | |
| #define | BRIDGE_ARRAY_GROW 32 |
| #define | BRIDGE_ARRAY_START 128 |
Functions | |
| int | __ast_bridge_technology_register (struct ast_bridge_technology *technology, struct ast_module *module) |
| Register a bridge technology for use. | |
| static void | __fini_bridge_technologies (void) |
| static void | __init_bridge_technologies (void) |
| void | ast_bridge_change_state (struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state) |
| Change the state of a bridged channel. | |
| int | ast_bridge_check (uint32_t capabilities) |
| See if it is possible to create a bridge. | |
| int | ast_bridge_depart (struct ast_bridge *bridge, struct ast_channel *chan) |
| Depart a channel from a bridge. | |
| int | ast_bridge_destroy (struct ast_bridge *bridge) |
| Destroy a bridge. | |
| int | ast_bridge_dtmf_stream (struct ast_bridge *bridge, const char *dtmf, struct ast_channel *chan) |
| Play a DTMF stream into a bridge, optionally not to a given channel. | |
| int | ast_bridge_features_cleanup (struct ast_bridge_features *features) |
| Clean up the contents of a bridge features structure. | |
| int | ast_bridge_features_enable (struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config) |
| Enable a built in feature on a bridge features structure. | |
| int | ast_bridge_features_hook (struct ast_bridge_features *features, const char *dtmf, ast_bridge_features_hook_callback callback, void *hook_pvt, ast_bridge_features_hook_pvt_destructor destructor) |
| Attach a custom hook to a bridge features structure. | |
| int | ast_bridge_features_init (struct ast_bridge_features *features) |
| Initialize bridge features structure. | |
| int | ast_bridge_features_register (enum ast_bridge_builtin_feature feature, ast_bridge_features_hook_callback callback, const char *dtmf) |
| Register a handler for a built in feature. | |
| int | ast_bridge_features_set_flag (struct ast_bridge_features *features, enum ast_bridge_feature_flags flag) |
| Set a flag on a bridge features structure. | |
| int | ast_bridge_features_set_talk_detector (struct ast_bridge_features *features, ast_bridge_talking_indicate_callback talker_cb, ast_bridge_talking_indicate_destructor talker_destructor, void *pvt_data) |
| Set a callback on the features structure to receive talking notifications on. | |
| int | ast_bridge_features_unregister (enum ast_bridge_builtin_feature feature) |
| Unregister a handler for a built in feature. | |
| void | ast_bridge_handle_trip (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd) |
| Feed notification that a frame is waiting on a channel into the bridging core. | |
| int | ast_bridge_impart (struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, int allow_hangup) |
| Impart (non-blocking) a channel on a bridge. | |
| int | ast_bridge_is_video_src (struct ast_bridge *bridge, struct ast_channel *chan) |
| Determine if a channel is a video src for the bridge. | |
| enum ast_bridge_channel_state | ast_bridge_join (struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args) |
| Join (blocking) a channel to a bridge. | |
| int | ast_bridge_merge (struct ast_bridge *bridge0, struct ast_bridge *bridge1) |
| Merge two bridges together. | |
| struct ast_bridge * | ast_bridge_new (uint32_t capabilities, int flags) |
| Create a new bridge. | |
| void | ast_bridge_notify_talking (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int started_talking) |
| Lets the bridging indicate when a bridge channel has stopped or started talking. | |
| int | ast_bridge_number_video_src (struct ast_bridge *bridge) |
| Returns the number of video sources currently active in the bridge. | |
| int | ast_bridge_remove (struct ast_bridge *bridge, struct ast_channel *chan) |
| Remove a channel from a bridge. | |
| void | ast_bridge_remove_video_src (struct ast_bridge *bridge, struct ast_channel *chan) |
| remove a channel as a source of video for the bridge. | |
| void | ast_bridge_set_internal_sample_rate (struct ast_bridge *bridge, unsigned int sample_rate) |
| Adjust the internal mixing sample rate of a bridge used during multimix mode. | |
| void | ast_bridge_set_mixing_interval (struct ast_bridge *bridge, unsigned int mixing_interval) |
| Adjust the internal mixing interval of a bridge used during multimix mode. | |
| void | ast_bridge_set_single_src_video_mode (struct ast_bridge *bridge, struct ast_channel *video_src_chan) |
| Set a bridge to feed a single video source to all participants. | |
| void | ast_bridge_set_talker_src_video_mode (struct ast_bridge *bridge) |
| Set the bridge to pick the strongest talker supporting video as the single source video feed. | |
| int | ast_bridge_suspend (struct ast_bridge *bridge, struct ast_channel *chan) |
| Suspend a channel temporarily from a bridge. | |
| void | ast_bridge_technology_suspend (struct ast_bridge_technology *technology) |
| Suspend a bridge technology from consideration. | |
| int | ast_bridge_technology_unregister (struct ast_bridge_technology *technology) |
| Unregister a bridge technology from use. | |
| void | ast_bridge_technology_unsuspend (struct ast_bridge_technology *technology) |
| Unsuspend a bridge technology. | |
| int | ast_bridge_unsuspend (struct ast_bridge *bridge, struct ast_channel *chan) |
| Unsuspend a channel from a bridge. | |
| void | ast_bridge_update_talker_src_video_mode (struct ast_bridge *bridge, struct ast_channel *chan, int talker_energy, int is_keyframe) |
| Update information about talker energy for talker src video mode. | |
| static void | bridge_array_add (struct ast_bridge *bridge, struct ast_channel *chan) |
| Helper function to add a channel to the bridge array. | |
| static void | bridge_array_remove (struct ast_bridge *bridge, struct ast_channel *chan) |
| Helper function to remove a channel from the bridge array. | |
| static struct ast_bridge_channel * | bridge_channel_alloc (struct ast_bridge *bridge) |
| static void | bridge_channel_destroy (void *obj) |
| static void | bridge_channel_dtmf_stream (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Internal function that plays back DTMF on a bridge channel. | |
| static void | bridge_channel_feature (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Internal function that executes a feature on a bridge channel. | |
| static enum ast_bridge_channel_state | bridge_channel_join (struct ast_bridge_channel *bridge_channel) |
| Join a channel to a bridge and handle anything the bridge may want us to do. | |
| static enum ast_bridge_channel_state | bridge_channel_join_multithreaded (struct ast_bridge_channel *bridge_channel) |
| Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve. | |
| static enum ast_bridge_channel_state | bridge_channel_join_singlethreaded (struct ast_bridge_channel *bridge_channel) |
| Run in a singlethreaded model. Each joined channel yields itself to the main bridge thread. TODO: Improve. | |
| static void | bridge_channel_suspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Internal function that suspends a channel from a bridge. | |
| static void | bridge_channel_talking (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| static void * | bridge_channel_thread (void *data) |
| Thread responsible for imparted bridged channels. | |
| static void | bridge_channel_unsuspend (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Internal function that unsuspends a channel from a bridge. | |
| static void | bridge_check_dissolve (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel) |
| Internal function to see whether a bridge should dissolve, and if so do it. | |
| static int | bridge_drop_control_frame (int subclass) |
| Internal function used to determine whether a control frame should be dropped or not. | |
| static struct ast_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 | cleanup_video_mode (struct ast_bridge *bridge) |
| static void | destroy_bridge (void *obj) |
| static struct ast_bridge_technology * | find_best_technology (uint32_t capabilities) |
| Helper function used to find the "best" bridge technology given a specified capabilities. | |
| static struct ast_bridge_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] |
Definition in file bridging.c.
| #define BRIDGE_ARRAY_GROW 32 |
| #define BRIDGE_ARRAY_START 128 |
| 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 |
ast_bridge_technology_register(&simple_bridge_tech);
This registers a bridge technology declared as the structure simple_bridge_tech with the bridging core and makes it available for use when creating bridges.
Definition at line 62 of file bridging.c.
References ast_log(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), ast_verb, ast_bridge_technology::capabilities, LOG_WARNING, ast_bridge_technology::mod, ast_bridge_technology::name, and ast_bridge_technology::write.
00063 { 00064 struct ast_bridge_technology *current = NULL; 00065 00066 /* Perform a sanity check to make sure the bridge technology conforms to our needed requirements */ 00067 if (ast_strlen_zero(technology->name) || !technology->capabilities || !technology->write) { 00068 ast_log(LOG_WARNING, "Bridge technology %s failed registration sanity check.\n", technology->name); 00069 return -1; 00070 } 00071 00072 AST_RWLIST_WRLOCK(&bridge_technologies); 00073 00074 /* Look for duplicate bridge technology already using this name, or already registered */ 00075 AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) { 00076 if ((!strcasecmp(current->name, technology->name)) || (current == technology)) { 00077 ast_log(LOG_WARNING, "A bridge technology of %s already claims to exist in our world.\n", technology->name); 00078 AST_RWLIST_UNLOCK(&bridge_technologies); 00079 return -1; 00080 } 00081 } 00082 00083 /* Copy module pointer so reference counting can keep the module from unloading */ 00084 technology->mod = module; 00085 00086 /* Insert our new bridge technology into the list and print out a pretty message */ 00087 AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry); 00088 00089 AST_RWLIST_UNLOCK(&bridge_technologies); 00090 00091 ast_verb(2, "Registered bridge technology %s\n", technology->name); 00092 00093 return 0; 00094 }
| static void __fini_bridge_technologies | ( | void | ) | [static] |
| static void __init_bridge_technologies | ( | void | ) | [static] |
| 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 |
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 117 of file bridging.c.
References ao2_lock, ao2_unlock, ast_cond_signal, ast_bridge_channel::cond, ast_bridge_channel::state, and ast_bridge_channel::thread.
Referenced by ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_dtmf_stream(), ast_bridge_handle_trip(), ast_bridge_notify_talking(), ast_bridge_remove(), attended_abort_transfer(), attended_threeway_transfer(), bridge_channel_dtmf_stream(), bridge_channel_feature(), bridge_channel_join(), bridge_channel_talking(), bridge_check_dissolve(), bridge_handle_dtmf(), feature_attended_transfer(), feature_blind_transfer(), and feature_hangup().
00118 { 00119 /* Change the state on the bridge channel */ 00120 bridge_channel->state = new_state; 00121 00122 /* Only poke the channel's thread if it is not us */ 00123 if (!pthread_equal(pthread_self(), bridge_channel->thread)) { 00124 pthread_kill(bridge_channel->thread, SIGURG); 00125 ao2_lock(bridge_channel); 00126 ast_cond_signal(&bridge_channel->cond); 00127 ao2_unlock(bridge_channel); 00128 } 00129 00130 return; 00131 }
| int ast_bridge_check | ( | uint32_t | capabilities | ) |
See if it is possible to create a bridge.
| capabilities | The capabilities that the bridge will use |
| 1 | if possible | |
| 0 | if not possible |
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 516 of file bridging.c.
References ast_module_unref(), find_best_technology(), and ast_bridge_technology::mod.
00517 { 00518 struct ast_bridge_technology *bridge_technology = NULL; 00519 00520 if (!(bridge_technology = find_best_technology(capabilities))) { 00521 return 0; 00522 } 00523 00524 ast_module_unref(bridge_technology->mod); 00525 00526 return 1; 00527 }
| int ast_bridge_depart | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) |
Depart a channel from a bridge.
| bridge | Bridge to depart from | |
| chan | Channel to depart |
| 0 | on success | |
| -1 | on failure |
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 1164 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DEPART, find_bridge_channel(), ast_bridge_channel::thread, and thread.
Referenced by feature_attended_transfer(), and play_sound_helper().
01165 { 01166 struct ast_bridge_channel *bridge_channel = NULL; 01167 pthread_t thread; 01168 01169 ao2_lock(bridge); 01170 01171 /* Try to find the channel that we want to depart */ 01172 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01173 ao2_unlock(bridge); 01174 return -1; 01175 } 01176 01177 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART); 01178 thread = bridge_channel->thread; 01179 01180 ao2_unlock(bridge); 01181 01182 pthread_join(thread, NULL); 01183 01184 return 0; 01185 }
| int ast_bridge_destroy | ( | struct ast_bridge * | bridge | ) |
Destroy a bridge.
| bridge | Bridge to destroy |
| 0 | on success | |
| -1 | on failure |
ast_bridge_destroy(bridge);
This destroys a bridge that was previously created using ast_bridge_new.
Definition at line 529 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, ast_debug, AST_LIST_TRAVERSE, bridge_poke(), and ast_bridge::stop.
Referenced by ast_bridge_new(), destroy_conference_bridge(), and feature_attended_transfer().
00530 { 00531 struct ast_bridge_channel *bridge_channel = NULL; 00532 00533 ao2_lock(bridge); 00534 00535 bridge->stop = 1; 00536 00537 bridge_poke(bridge); 00538 00539 ast_debug(1, "Telling all channels in bridge %p to end and leave the party\n", bridge); 00540 00541 /* Drop every bridged channel, the last one will cause the bridge thread (if it exists) to exit */ 00542 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { 00543 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END); 00544 } 00545 00546 ao2_unlock(bridge); 00547 00548 ao2_ref(bridge, -1); 00549 00550 return 0; 00551 }
| int ast_bridge_dtmf_stream | ( | struct ast_bridge * | bridge, | |
| const char * | dtmf, | |||
| struct ast_channel * | chan | |||
| ) |
Play a DTMF stream into a bridge, optionally not to a given channel.
| bridge | Bridge to play stream into | |
| dtmf | DTMF to play | |
| chan | Channel to optionally not play to |
| 0 | on success | |
| -1 | on failure |
ast_bridge_dtmf_stream(bridge, "0123456789", NULL);
This sends the DTMF digits '0123456789' to all channels in the bridge pointed to by the bridge pointer. Optionally a channel may be excluded by passing it's channel pointer using the chan parameter.
Definition at line 1455 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DTMF, ast_copy_string(), AST_LIST_TRAVERSE, ast_bridge_channel::chan, and ast_bridge_channel::dtmf_stream_q.
Referenced by bridge_channel_feature().
01456 { 01457 struct ast_bridge_channel *bridge_channel = NULL; 01458 01459 ao2_lock(bridge); 01460 01461 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { 01462 if (bridge_channel->chan == chan) { 01463 continue; 01464 } 01465 ast_copy_string(bridge_channel->dtmf_stream_q, dtmf, sizeof(bridge_channel->dtmf_stream_q)); 01466 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DTMF); 01467 } 01468 01469 ao2_unlock(bridge); 01470 01471 return 0; 01472 }
| int ast_bridge_features_cleanup | ( | struct ast_bridge_features * | features | ) |
Clean up the contents of a bridge features structure.
| features | Bridge features structure |
| 0 | on success | |
| -1 | on failure |
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 1436 of file bridging.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_bridge_features_hook::destructor, ast_bridge_features_hook::hook_pvt, ast_bridge_features::talker_destructor_cb, and ast_bridge_features::talker_pvt_data.
Referenced by confbridge_exec(), destroy_bridge(), and feature_attended_transfer().
01437 { 01438 struct ast_bridge_features_hook *hook = NULL; 01439 01440 /* This is relatively simple, hooks are kept as a list on the features structure so we just pop them off and free them */ 01441 while ((hook = AST_LIST_REMOVE_HEAD(&features->hooks, entry))) { 01442 if (hook->destructor) { 01443 hook->destructor(hook->hook_pvt); 01444 } 01445 ast_free(hook); 01446 } 01447 if (features->talker_destructor_cb && features->talker_pvt_data) { 01448 features->talker_destructor_cb(features->talker_pvt_data); 01449 features->talker_pvt_data = NULL; 01450 } 01451 01452 return 0; 01453 }
| int ast_bridge_features_enable | ( | struct ast_bridge_features * | features, | |
| enum ast_bridge_builtin_feature | feature, | |||
| const char * | dtmf, | |||
| void * | config | |||
| ) |
Enable a built in feature on a bridge features structure.
| 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 |
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 1398 of file bridging.c.
References ast_bridge_features_hook(), ast_debug, and ast_strlen_zero().
Referenced by feature_attended_transfer().
01399 { 01400 /* If no alternate DTMF stream was provided use the default one */ 01401 if (ast_strlen_zero(dtmf)) { 01402 dtmf = builtin_features_dtmf[feature]; 01403 /* If no DTMF is still available (ie: it has been disabled) then error out now */ 01404 if (ast_strlen_zero(dtmf)) { 01405 ast_debug(1, "Failed to enable built in feature %d on %p, no DTMF string is available for it.\n", feature, features); 01406 return -1; 01407 } 01408 } 01409 01410 if (!builtin_features_handlers[feature]) { 01411 return -1; 01412 } 01413 01414 /* The rest is basically pretty easy. We create another hook using the built in feature's callback and DTMF, easy as pie. */ 01415 return ast_bridge_features_hook(features, dtmf, builtin_features_handlers[feature], config, NULL); 01416 }
| int ast_bridge_features_hook | ( | struct ast_bridge_features * | features, | |
| const char * | dtmf, | |||
| ast_bridge_features_hook_callback | callback, | |||
| void * | hook_pvt, | |||
| ast_bridge_features_hook_pvt_destructor | destructor | |||
| ) |
Attach a custom hook to a bridge features structure.
| features | Bridge features structure | |
| dtmf | DTMF string to be activated upon | |
| callback | Function to execute upon activation | |
| hook_pvt | Unique data | |
| Optional | destructor callback for hook_pvt data |
| 0 | on success | |
| -1 | on failure |
struct ast_bridge_features features; ast_bridge_features_init(&features); ast_bridge_features_hook(&features, "#", pound_callback, NULL, NULL);
This makes the bridging core call pound_callback if a channel that has this feature structure inputs the DTMF string '#'. A pointer to useful data may be provided to the hook_pvt parameter.
Definition at line 1361 of file bridging.c.
References ast_calloc, ast_copy_string(), AST_LIST_INSERT_TAIL, ast_bridge_features_hook::callback, ast_bridge_features_hook::destructor, ast_bridge_features_hook::dtmf, ast_bridge_features_hook::hook_pvt, and ast_bridge_features::usable.
Referenced by ast_bridge_features_enable(), and feature_attended_transfer().
01366 { 01367 struct ast_bridge_features_hook *hook = NULL; 01368 01369 /* Allocate new memory and setup it's various variables */ 01370 if (!(hook = ast_calloc(1, sizeof(*hook)))) { 01371 return -1; 01372 } 01373 01374 ast_copy_string(hook->dtmf, dtmf, sizeof(hook->dtmf)); 01375 hook->callback = callback; 01376 hook->destructor = destructor; 01377 hook->hook_pvt = hook_pvt; 01378 01379 /* Once done we add it onto the list. Now it will be picked up when DTMF is used */ 01380 AST_LIST_INSERT_TAIL(&features->hooks, hook, entry); 01381 01382 features->usable = 1; 01383 01384 return 0; 01385 }
| int ast_bridge_features_init | ( | struct ast_bridge_features * | features | ) |
Initialize bridge features structure.
| features | Bridge featues structure |
| 0 | on success | |
| -1 | on failure |
struct ast_bridge_features features; ast_bridge_features_init(&features);
This initializes the feature structure 'features' to have nothing enabled.
Definition at line 1425 of file bridging.c.
References AST_LIST_HEAD_INIT_NOLOCK.
Referenced by confbridge_exec(), and feature_attended_transfer().
01426 { 01427 /* Zero out the structure */ 01428 memset(features, 0, sizeof(*features)); 01429 01430 /* Initialize the hooks list, just in case */ 01431 AST_LIST_HEAD_INIT_NOLOCK(&features->hooks); 01432 01433 return 0; 01434 }
| int ast_bridge_features_register | ( | enum ast_bridge_builtin_feature | feature, | |
| ast_bridge_features_hook_callback | callback, | |||
| const char * | dtmf | |||
| ) |
Register a handler for a built in feature.
| 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 |
ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER, bridge_builtin_attended_transfer, "*1");
This registers the function bridge_builtin_attended_transfer as the function responsible for the built in attended transfer feature.
Definition at line 1335 of file bridging.c.
References ast_copy_string(), and ast_strlen_zero().
Referenced by load_module().
01336 { 01337 if (builtin_features_handlers[feature]) { 01338 return -1; 01339 } 01340 01341 if (!ast_strlen_zero(dtmf)) { 01342 ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature])); 01343 } 01344 01345 builtin_features_handlers[feature] = callback; 01346 01347 return 0; 01348 }
| int ast_bridge_features_set_flag | ( | struct ast_bridge_features * | features, | |
| enum ast_bridge_feature_flags | flag | |||
| ) |
Set a flag on a bridge features structure.
| features | Bridge features structure | |
| flag | Flag to enable |
| 0 | on success | |
| -1 | on failure |
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 1418 of file bridging.c.
References ast_set_flag, ast_bridge_features::feature_flags, and ast_bridge_features::usable.
Referenced by feature_attended_transfer().
01419 { 01420 ast_set_flag(&features->feature_flags, flag); 01421 features->usable = 1; 01422 return 0; 01423 }
| int ast_bridge_features_set_talk_detector | ( | struct ast_bridge_features * | features, | |
| ast_bridge_talking_indicate_callback | talker_cb, | |||
| ast_bridge_talking_indicate_destructor | talker_destructor, | |||
| void * | pvt_data | |||
| ) |
Set a callback on the features structure to receive talking notifications on.
| features | Bridge features structure | |
| talker_cb,Callback | function to execute when talking events occur in the bridge core. | |
| pvt_data | Optional unique data that will be passed with the talking events. | |
| Optional | destructor callback for pvt data. |
| 0,success | ||
| -1,failure |
Definition at line 1387 of file bridging.c.
References ast_bridge_features::talker_cb, ast_bridge_features::talker_destructor_cb, and ast_bridge_features::talker_pvt_data.
Referenced by confbridge_exec().
01391 { 01392 features->talker_cb = talker_cb; 01393 features->talker_destructor_cb = talker_destructor; 01394 features->talker_pvt_data = pvt_data; 01395 return 0; 01396 }
| int ast_bridge_features_unregister | ( | enum ast_bridge_builtin_feature | feature | ) |
Unregister a handler for a built in feature.
| feature | The feature to unregister |
| 0 | on success | |
| -1 | on failure |
ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_ATTENDED_TRANSFER);
This unregisters the function that is handling the built in attended transfer feature.
Definition at line 1350 of file bridging.c.
01351 { 01352 if (!builtin_features_handlers[feature]) { 01353 return -1; 01354 } 01355 01356 builtin_features_handlers[feature] = NULL; 01357 01358 return 0; 01359 }
| void ast_bridge_handle_trip | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel, | |||
| struct ast_channel * | chan, | |||
| int | outfd | |||
| ) |
Feed notification that a frame is waiting on a channel into the bridging core.
| 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) |
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 284 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frfree, ast_read(), ast_read_noaudio(), bridge_drop_control_frame(), bridge_handle_dtmf(), ast_bridge_features::dtmf_passthrough, ast_bridge_technology::fd, ast_bridge_channel::features, ast_bridge::features, find_bridge_channel(), ast_frame::frametype, ast_frame_subclass::integer, ast_bridge_features::mute, ast_bridge_technology::poke, ast_frame::subclass, ast_bridge::technology, and ast_bridge_technology::write.
Referenced by bridge_channel_join_multithreaded(), generic_thread_loop(), and multiplexed_thread_function().
00285 { 00286 /* If no bridge channel has been provided and the actual channel has been provided find it */ 00287 if (chan && !bridge_channel) { 00288 bridge_channel = find_bridge_channel(bridge, chan); 00289 } 00290 00291 /* If a bridge channel with actual channel is present read a frame and handle it */ 00292 if (chan && bridge_channel) { 00293 struct ast_frame *frame = (((bridge->features.mute) || (bridge_channel->features && bridge_channel->features->mute)) ? ast_read_noaudio(chan) : ast_read(chan)); 00294 00295 /* This is pretty simple... see if they hung up */ 00296 if (!frame || (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_HANGUP)) { 00297 /* Signal the thread that is handling the bridged channel that it should be ended */ 00298 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END); 00299 } else if (frame->frametype == AST_FRAME_CONTROL && bridge_drop_control_frame(frame->subclass.integer)) { 00300 ast_debug(1, "Dropping control frame from bridge channel %p\n", bridge_channel); 00301 } else if (frame->frametype == AST_FRAME_DTMF_BEGIN || frame->frametype == AST_FRAME_DTMF_END) { 00302 int dtmf_passthrough = bridge_channel->features ? 00303 bridge_channel->features->dtmf_passthrough : 00304 bridge->features.dtmf_passthrough; 00305 00306 if (frame->frametype == AST_FRAME_DTMF_BEGIN) { 00307 frame = bridge_handle_dtmf(bridge, bridge_channel, frame); 00308 } 00309 00310 if (frame && dtmf_passthrough) { 00311 bridge->technology->write(bridge, bridge_channel, frame); 00312 } 00313 } else { 00314 /* Simply write the frame out to the bridge technology if it still exists */ 00315 bridge->technology->write(bridge, bridge_channel, frame); 00316 } 00317 00318 if (frame) { 00319 ast_frfree(frame); 00320 } 00321 return; 00322 } 00323 00324 /* If a file descriptor actually tripped pass it off to the bridge technology */ 00325 if (outfd > -1 && bridge->technology->fd) { 00326 bridge->technology->fd(bridge, bridge_channel, outfd); 00327 return; 00328 } 00329 00330 /* If all else fails just poke the bridge */ 00331 if (bridge->technology->poke && bridge_channel) { 00332 bridge->technology->poke(bridge, bridge_channel); 00333 return; 00334 } 00335 00336 return; 00337 }
| int ast_bridge_impart | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan, | |||
| struct ast_channel * | swap, | |||
| struct ast_bridge_features * | features, | |||
| int | allow_hangup | |||
| ) |
Impart (non-blocking) a channel on a bridge.
| bridge | Bridge to impart on | |
| chan | Channel to impart | |
| swap | Channel to swap out if swapping | |
| features | Bridge features structure | |
| allow_hangup | Indicates if the bridge thread should manage hanging up of the channel or not. |
| 0 | on success | |
| -1 | on failure |
ast_bridge_impart(bridge, chan, NULL, NULL, 0);
This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will return immediately and will not wait until the channel is no longer part of the bridge.
If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.
If channel specific features are enabled a pointer to the features structure can be specified in the features parameter.
Definition at line 1140 of file bridging.c.
References ast_bridge_channel::allow_impart_hangup, ao2_ref, ast_pthread_create, bridge_channel_alloc(), bridge_channel_thread(), ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_channel::swap, and ast_bridge_channel::thread.
Referenced by bridge_call(), feature_attended_transfer(), feature_blind_transfer(), and play_sound_helper().
01141 { 01142 struct ast_bridge_channel *bridge_channel = bridge_channel_alloc(bridge); 01143 /* Try to allocate a structure for the bridge channel */ 01144 if (!(bridge_channel)) { 01145 return -1; 01146 } 01147 01148 /* Setup various parameters */ 01149 bridge_channel->chan = chan; 01150 bridge_channel->swap = swap; 01151 bridge_channel->features = features; 01152 bridge_channel->allow_impart_hangup = allow_hangup; 01153 01154 01155 /* Actually create the thread that will handle the channel */ 01156 if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) { 01157 ao2_ref(bridge_channel, -1); 01158 return -1; 01159 } 01160 01161 return 0; 01162 }
| int ast_bridge_is_video_src | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) |
Determine if a channel is a video src for the bridge.
| 0 | Not a current video source of the bridge. | |
| None | 0, is a video source of the bridge, The number returned represents the priority this video stream has on the bridge where 1 is the highest priority. |
Definition at line 1594 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.
Referenced by handle_video_on_exit(), handle_video_on_join(), softmix_bridge_write(), and softmix_pass_video_top_priority().
01595 { 01596 int res = 0; 01597 01598 ao2_lock(bridge); 01599 switch (bridge->video_mode.mode) { 01600 case AST_BRIDGE_VIDEO_MODE_NONE: 01601 break; 01602 case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC: 01603 if (bridge->video_mode.mode_data.single_src_data.chan_vsrc == chan) { 01604 res = 1; 01605 } 01606 break; 01607 case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: 01608 if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc == chan) { 01609 res = 1; 01610 } else if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) { 01611 res = 2; 01612 } 01613 01614 } 01615 ao2_unlock(bridge); 01616 return res; 01617 }
| enum ast_bridge_channel_state ast_bridge_join | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan, | |||
| struct ast_channel * | swap, | |||
| struct ast_bridge_features * | features, | |||
| struct ast_bridge_tech_optimizations * | tech_args | |||
| ) |
Join (blocking) a channel to a bridge.
| bridge | Bridge to join | |
| chan | Channel to join | |
| swap | Channel to swap out if swapping | |
| features | Bridge features structure | |
| (Optional) | Bridging tech optimization parameters for this channel. |
| state | that channel exited the bridge with |
ast_bridge_join(bridge, chan, NULL, NULL);
This adds a channel pointed to by the chan pointer to the bridge pointed to by the bridge pointer. This function will not return until the channel has been removed from the bridge, swapped out for another channel, or has hung up.
If this channel will be replacing another channel the other channel can be specified in the swap parameter. The other channel will be thrown out of the bridge in an atomic fashion.
If channel specific features are enabled a pointer to the features structure can be specified in the features parameter.
Definition at line 1080 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CHANNEL_STATE_HANGUP, bridge_channel_alloc(), bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::features, ast_bridge_channel::swap, and ast_bridge_channel::tech_args.
Referenced by confbridge_exec(), feature_attended_transfer(), and record_thread().
01085 { 01086 struct ast_bridge_channel *bridge_channel = bridge_channel_alloc(bridge); 01087 enum ast_bridge_channel_state state = AST_BRIDGE_CHANNEL_STATE_HANGUP; 01088 01089 if (!bridge_channel) { 01090 return state; 01091 } 01092 if (tech_args) { 01093 memcpy(&bridge_channel->tech_args, tech_args, sizeof(bridge_channel->tech_args)); 01094 } 01095 01096 /* Initialize various other elements of the bridge channel structure that we can't do above */ 01097 bridge_channel->chan = chan; 01098 bridge_channel->swap = swap; 01099 bridge_channel->features = features; 01100 01101 state = bridge_channel_join(bridge_channel); 01102 01103 /* Cleanup all the data in the bridge channel after it leaves the bridge. */ 01104 ao2_lock(bridge_channel); 01105 bridge_channel->chan = NULL; 01106 bridge_channel->swap = NULL; 01107 bridge_channel->features = NULL; 01108 ao2_unlock(bridge_channel); 01109 01110 ao2_ref(bridge_channel, -1); 01111 01112 return state; 01113 }
| int ast_bridge_merge | ( | struct ast_bridge * | bridge0, | |
| struct ast_bridge * | bridge1 | |||
| ) |
Merge two bridges together.
| bridge0 | First bridge | |
| bridge1 | Second bridge |
| 0 | on success | |
| -1 | on failure |
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 1206 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_FLAG_SMART, ast_cond_signal, ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, AST_PTHREADT_STOP, ast_test_flag, ast_bridge_channel::bridge, bridge_array_add(), bridge_array_remove(), bridge_make_compatible(), ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge::feature_flags, ast_bridge_technology::join, ast_bridge_technology::leave, ast_bridge_technology::name, ast_bridge::num, smart_bridge_operation(), ast_bridge::technology, ast_bridge_channel::thread, and ast_bridge::thread.
01207 { 01208 struct ast_bridge_channel *bridge_channel = NULL; 01209 01210 ao2_lock(bridge0); 01211 ao2_lock(bridge1); 01212 01213 /* If the first bridge currently has 2 channels and is not capable of becoming a multimixing bridge we can not merge */ 01214 if ((bridge0->num + bridge1->num) > 2 && (!(bridge0->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) && !ast_test_flag(&bridge0->feature_flags, AST_BRIDGE_FLAG_SMART))) { 01215 ao2_unlock(bridge1); 01216 ao2_unlock(bridge0); 01217 ast_debug(1, "Can't merge bridge %p into bridge %p, multimix is needed and it could not be acquired.\n", bridge1, bridge0); 01218 return -1; 01219 } 01220 01221 ast_debug(1, "Merging channels from bridge %p into bridge %p\n", bridge1, bridge0); 01222 01223 /* Perform smart bridge operation on bridge we are merging into so it can change bridge technology if needed */ 01224 if (smart_bridge_operation(bridge0, NULL, bridge0->num + bridge1->num)) { 01225 ao2_unlock(bridge1); 01226 ao2_unlock(bridge0); 01227 ast_debug(1, "Can't merge bridge %p into bridge %p, tried to perform smart bridge operation and failed.\n", bridge1, bridge0); 01228 return -1; 01229 } 01230 01231 /* If a thread is currently executing on bridge1 tell it to stop */ 01232 if (bridge1->thread) { 01233 ast_debug(1, "Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0); 01234 bridge1->thread = AST_PTHREADT_STOP; 01235 } 01236 01237 /* Move channels from bridge1 over to bridge0 */ 01238 while ((bridge_channel = AST_LIST_REMOVE_HEAD(&bridge1->channels, entry))) { 01239 /* Tell the technology handling bridge1 that the bridge channel is leaving */ 01240 if (bridge1->technology->leave) { 01241 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->technology->name, bridge_channel, bridge1); 01242 if (bridge1->technology->leave(bridge1, bridge_channel)) { 01243 ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->technology->name, bridge_channel, bridge1); 01244 } 01245 } 01246 01247 /* Drop channel count and reference count on the bridge they are leaving */ 01248 bridge1->num--; 01249 ao2_ref(bridge1, -1); 01250 01251 bridge_array_remove(bridge1, bridge_channel->chan); 01252 01253 /* Now add them into the bridge they are joining, increase channel count, and bump up reference count */ 01254 bridge_channel->bridge = bridge0; 01255 AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, entry); 01256 bridge0->num++; 01257 ao2_ref(bridge0, +1); 01258 01259 bridge_array_add(bridge0, bridge_channel->chan); 01260 01261 /* Make the channel compatible with the new bridge it is joining or else formats would go amuck */ 01262 bridge_make_compatible(bridge0, bridge_channel); 01263 01264 /* Tell the technology handling bridge0 that the bridge channel is joining */ 01265 if (bridge0->technology->join) { 01266 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->technology->name, bridge_channel, bridge0); 01267 if (bridge0->technology->join(bridge0, bridge_channel)) { 01268 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge0->technology->name, bridge_channel, bridge0); 01269 } 01270 } 01271 01272 /* Poke the bridge channel, this will cause it to wake up and execute the proper threading model for the new bridge it is in */ 01273 pthread_kill(bridge_channel->thread, SIGURG); 01274 ao2_lock(bridge_channel); 01275 ast_cond_signal(&bridge_channel->cond); 01276 ao2_unlock(bridge_channel); 01277 } 01278 01279 ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge1, bridge0); 01280 01281 ao2_unlock(bridge1); 01282 ao2_unlock(bridge0); 01283 01284 return 0; 01285 }
| struct ast_bridge* ast_bridge_new | ( | uint32_t | capabilities, | |
| int | flags | |||
| ) | [read] |
Create a new bridge.
| 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 |
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 464 of file bridging.c.
References ao2_alloc, ao2_ref, ast_bridge::array, ast_bridge::array_size, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_MULTIMIX, ast_bridge_destroy(), AST_BRIDGE_FLAG_SMART, ast_bridge_new(), ast_calloc, ast_debug, AST_PTHREADT_NULL, ast_set_flag, BRIDGE_ARRAY_START, ast_bridge_technology::create, destroy_bridge(), ast_bridge::feature_flags, find_best_technology(), ast_bridge_technology::name, ast_bridge::technology, and ast_bridge::thread.
Referenced by ast_bridge_new(), feature_attended_transfer(), and join_conference_bridge().
00465 { 00466 struct ast_bridge *bridge = NULL; 00467 struct ast_bridge_technology *bridge_technology = NULL; 00468 00469 /* If we need to be a smart bridge see if we can move between 1to1 and multimix bridges */ 00470 if (flags & AST_BRIDGE_FLAG_SMART) { 00471 struct ast_bridge *other_bridge; 00472 00473 if (!(other_bridge = ast_bridge_new((capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) ? AST_BRIDGE_CAPABILITY_MULTIMIX : AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) { 00474 return NULL; 00475 } 00476 00477 ast_bridge_destroy(other_bridge); 00478 } 00479 00480 /* If capabilities were provided use our helper function to find the "best" bridge technology, otherwise we can 00481 * just look for the most basic capability needed, single 1to1 mixing. */ 00482 bridge_technology = (capabilities ? find_best_technology(capabilities) : find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX)); 00483 00484 /* If no bridge technology was found we can't possibly do bridging so fail creation of the bridge */ 00485 if (!bridge_technology) { 00486 return NULL; 00487 } 00488 00489 /* We have everything we need to create this bridge... so allocate the memory, link things together, and fire her up! */ 00490 if (!(bridge = ao2_alloc(sizeof(*bridge), destroy_bridge))) { 00491 return NULL; 00492 } 00493 00494 bridge->technology = bridge_technology; 00495 bridge->thread = AST_PTHREADT_NULL; 00496 00497 /* Create an array of pointers for the channels that will be joining us */ 00498 bridge->array = ast_calloc(BRIDGE_ARRAY_START, sizeof(struct ast_channel*)); 00499 bridge->array_size = BRIDGE_ARRAY_START; 00500 00501 ast_set_flag(&bridge->feature_flags, flags); 00502 00503 /* Pass off the bridge to the technology to manipulate if needed */ 00504 if (bridge->technology->create) { 00505 ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", bridge->technology->name, bridge); 00506 if (bridge->technology->create(bridge)) { 00507 ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", bridge->technology->name, bridge); 00508 ao2_ref(bridge, -1); 00509 bridge = NULL; 00510 } 00511 } 00512 00513 return bridge; 00514 }
| void ast_bridge_notify_talking | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel, | |||
| int | started_talking | |||
| ) |
Lets the bridging indicate when a bridge channel has stopped or started talking.
| bridge | The bridge that the channel is a part of. | |
| bridge_channel | The bridge channel that has either started or stopped talking. | |
| started_talking,set | to 1 when this indicates the channel has started talking, set to 0 when this indicates the channel has stopped talking. |
Definition at line 275 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_START_TALKING, and AST_BRIDGE_CHANNEL_STATE_STOP_TALKING.
Referenced by softmix_bridge_write().
00276 { 00277 if (started_talking) { 00278 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_START_TALKING); 00279 } else { 00280 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_STOP_TALKING); 00281 } 00282 }
| int ast_bridge_number_video_src | ( | struct ast_bridge * | bridge | ) |
Returns the number of video sources currently active in the bridge.
Definition at line 1569 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.
Referenced by softmix_bridge_write().
01570 { 01571 int res = 0; 01572 01573 ao2_lock(bridge); 01574 switch (bridge->video_mode.mode) { 01575 case AST_BRIDGE_VIDEO_MODE_NONE: 01576 break; 01577 case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC: 01578 if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) { 01579 res = 1; 01580 } 01581 break; 01582 case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: 01583 if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) { 01584 res++; 01585 } 01586 if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) { 01587 res++; 01588 } 01589 } 01590 ao2_unlock(bridge); 01591 return res; 01592 }
| int ast_bridge_remove | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) |
Remove a channel from a bridge.
| bridge | Bridge that the channel is to be removed from | |
| chan | Channel to remove |
| 0 | on success | |
| -1 | on failure |
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 1187 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_HANGUP, and find_bridge_channel().
Referenced by action_confbridgekick(), action_kick_last(), conf_stop_record(), execute_menu_entry(), handle_cli_confbridge_kick(), and leave_conference_bridge().
01188 { 01189 struct ast_bridge_channel *bridge_channel = NULL; 01190 01191 ao2_lock(bridge); 01192 01193 /* Try to find the channel that we want to remove */ 01194 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01195 ao2_unlock(bridge); 01196 return -1; 01197 } 01198 01199 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP); 01200 01201 ao2_unlock(bridge); 01202 01203 return 0; 01204 }
| void ast_bridge_remove_video_src | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) |
remove a channel as a source of video for the bridge.
Definition at line 1619 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_channel_unref, ast_bridge_video_talker_src_data::average_talking_energy, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.
Referenced by handle_video_on_exit().
01620 { 01621 ao2_lock(bridge); 01622 switch (bridge->video_mode.mode) { 01623 case AST_BRIDGE_VIDEO_MODE_NONE: 01624 break; 01625 case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC: 01626 if (bridge->video_mode.mode_data.single_src_data.chan_vsrc == chan) { 01627 if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) { 01628 ast_channel_unref(bridge->video_mode.mode_data.single_src_data.chan_vsrc); 01629 } 01630 bridge->video_mode.mode_data.single_src_data.chan_vsrc = NULL; 01631 } 01632 break; 01633 case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: 01634 if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc == chan) { 01635 if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) { 01636 ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc); 01637 } 01638 bridge->video_mode.mode_data.talker_src_data.chan_vsrc = NULL; 01639 bridge->video_mode.mode_data.talker_src_data.average_talking_energy = 0; 01640 } 01641 if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc == chan) { 01642 if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) { 01643 ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc); 01644 } 01645 bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc = NULL; 01646 } 01647 } 01648 ao2_unlock(bridge); 01649 }
| void ast_bridge_set_internal_sample_rate | ( | struct ast_bridge * | bridge, | |
| unsigned int | sample_rate | |||
| ) |
Adjust the internal mixing sample rate of a bridge used during multimix mode.
| bridge_channel | Channel to change the sample rate on. | |
| sample | rate, the sample rate to change to. If a value of 0 is passed here, the bridge will be free to pick what ever sample rate it chooses. |
Definition at line 1481 of file bridging.c.
References ao2_lock, ao2_unlock, and ast_bridge::internal_sample_rate.
Referenced by join_conference_bridge().
01482 { 01483 01484 ao2_lock(bridge); 01485 bridge->internal_sample_rate = sample_rate; 01486 ao2_unlock(bridge); 01487 }
| void ast_bridge_set_mixing_interval | ( | struct ast_bridge * | bridge, | |
| unsigned int | mixing_interval | |||
| ) |
Adjust the internal mixing interval of a bridge used during multimix mode.
| bridge_channel | Channel to change the sample rate on. | |
| mixing_interval,the | sample rate to change to. If 0 is set the bridge tech is free to choose any mixing interval it uses by default. |
Definition at line 1474 of file bridging.c.
References ao2_lock, ao2_unlock, and ast_bridge::internal_mixing_interval.
Referenced by join_conference_bridge().
01475 { 01476 ao2_lock(bridge); 01477 bridge->internal_mixing_interval = mixing_interval; 01478 ao2_unlock(bridge); 01479 }
| void ast_bridge_set_single_src_video_mode | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | video_src_chan | |||
| ) |
Set a bridge to feed a single video source to all participants.
Definition at line 1510 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, ast_channel_name(), ast_channel_ref, AST_CONTROL_VIDUPDATE, ast_indicate(), ast_test_suite_event_notify, ast_bridge_video_single_src_data::chan_vsrc, cleanup_video_mode(), ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, and ast_bridge::video_mode.
Referenced by action_confbridgesetsinglevideosrc(), execute_menu_entry(), handle_video_on_exit(), and handle_video_on_join().
01511 { 01512 ao2_lock(bridge); 01513 cleanup_video_mode(bridge); 01514 bridge->video_mode.mode = AST_BRIDGE_VIDEO_MODE_SINGLE_SRC; 01515 bridge->video_mode.mode_data.single_src_data.chan_vsrc = ast_channel_ref(video_src_chan); 01516 ast_test_suite_event_notify("BRIDGE_VIDEO_MODE", "Message: video mode set to single source\r\nVideo Mode: %d\r\nVideo Channel: %s", bridge->video_mode.mode, ast_channel_name(video_src_chan)); 01517 ast_indicate(video_src_chan, AST_CONTROL_VIDUPDATE); 01518 ao2_unlock(bridge); 01519 }
| void ast_bridge_set_talker_src_video_mode | ( | struct ast_bridge * | bridge | ) |
Set the bridge to pick the strongest talker supporting video as the single source video feed.
Definition at line 1521 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_test_suite_event_notify, cleanup_video_mode(), ast_bridge_video_mode::mode, and ast_bridge::video_mode.
Referenced by handle_video_on_exit(), and join_conference_bridge().
01522 { 01523 ao2_lock(bridge); 01524 cleanup_video_mode(bridge); 01525 bridge->video_mode.mode = AST_BRIDGE_VIDEO_MODE_TALKER_SRC; 01526 ast_test_suite_event_notify("BRIDGE_VIDEO_MODE", "Message: video mode set to talker source\r\nVideo Mode: %d", bridge->video_mode.mode); 01527 ao2_unlock(bridge); 01528 }
| int ast_bridge_suspend | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) |
Suspend a channel temporarily from a bridge.
| bridge | Bridge to suspend the channel from | |
| chan | Channel to suspend |
| 0 | on success | |
| -1 | on failure |
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 1287 of file bridging.c.
References ao2_lock, ao2_unlock, bridge_channel_suspend(), and find_bridge_channel().
Referenced by leave_conference_bridge(), post_join_marked(), and post_join_unmarked().
01288 { 01289 struct ast_bridge_channel *bridge_channel; 01290 01291 ao2_lock(bridge); 01292 01293 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01294 ao2_unlock(bridge); 01295 return -1; 01296 } 01297 01298 bridge_channel_suspend(bridge, bridge_channel); 01299 01300 ao2_unlock(bridge); 01301 01302 return 0; 01303 }
| void ast_bridge_technology_suspend | ( | struct ast_bridge_technology * | technology | ) |
Suspend a bridge technology from consideration.
| technology | The bridge technology to suspend |
ast_bridge_technology_suspend(&simple_bridge_tech);
This suspends the bridge technology simple_bridge_tech from being considered when creating a new bridge. Existing bridges using the bridge technology are not affected.
Definition at line 1323 of file bridging.c.
References ast_bridge_technology::suspended.
01324 { 01325 technology->suspended = 1; 01326 return; 01327 }
| int ast_bridge_technology_unregister | ( | struct ast_bridge_technology * | technology | ) |
Unregister a bridge technology from use.
| technology | The bridge technology to unregister |
| 0 | on success | |
| -1 | on failure |
ast_bridge_technology_unregister(&simple_bridge_tech);
This unregisters a bridge technlogy declared as the structure simple_bridge_tech with the bridging core. It will no longer be considered when creating a new bridge.
Definition at line 96 of file bridging.c.
References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and ast_bridge_technology::name.
Referenced by unload_module().
00097 { 00098 struct ast_bridge_technology *current = NULL; 00099 00100 AST_RWLIST_WRLOCK(&bridge_technologies); 00101 00102 /* Ensure the bridge technology is registered before removing it */ 00103 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) { 00104 if (current == technology) { 00105 AST_RWLIST_REMOVE_CURRENT(entry); 00106 ast_verb(2, "Unregistered bridge technology %s\n", technology->name); 00107 break; 00108 } 00109 } 00110 AST_RWLIST_TRAVERSE_SAFE_END; 00111 00112 AST_RWLIST_UNLOCK(&bridge_technologies); 00113 00114 return current ? 0 : -1; 00115 }
| void ast_bridge_technology_unsuspend | ( | struct ast_bridge_technology * | technology | ) |
Unsuspend a bridge technology.
| technology | The bridge technology to unsuspend |
ast_bridge_technology_unsuspend(&simple_bridge_tech);
This makes the bridge technology simple_bridge_tech considered when creating a new bridge again.
Definition at line 1329 of file bridging.c.
References ast_bridge_technology::suspended.
01330 { 01331 technology->suspended = 0; 01332 return; 01333 }
| int ast_bridge_unsuspend | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) |
Unsuspend a channel from a bridge.
| bridge | Bridge to unsuspend the channel from | |
| chan | Channel to unsuspend |
| 0 | on success | |
| -1 | on failure |
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 1305 of file bridging.c.
References ao2_lock, ao2_unlock, bridge_channel_unsuspend(), and find_bridge_channel().
Referenced by leave_conference_bridge(), post_join_marked(), and post_join_unmarked().
01306 { 01307 struct ast_bridge_channel *bridge_channel; 01308 01309 ao2_lock(bridge); 01310 01311 if (!(bridge_channel = find_bridge_channel(bridge, chan))) { 01312 ao2_unlock(bridge); 01313 return -1; 01314 } 01315 01316 bridge_channel_unsuspend(bridge, bridge_channel); 01317 01318 ao2_unlock(bridge); 01319 01320 return 0; 01321 }
| void ast_bridge_update_talker_src_video_mode | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan, | |||
| int | talker_energy, | |||
| int | is_keyframe | |||
| ) |
Update information about talker energy for talker src video mode.
Definition at line 1530 of file bridging.c.
References ao2_lock, ao2_unlock, ast_channel_name(), ast_channel_ref, ast_channel_unref, AST_CONTROL_VIDUPDATE, ast_format_cap_has_type(), AST_FORMAT_TYPE_VIDEO, ast_indicate(), ast_test_suite_event_notify, ast_bridge_video_talker_src_data::average_talking_energy, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_mode::mode_data, ast_channel::nativeformats, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.
Referenced by softmix_bridge_write().
01531 { 01532 struct ast_bridge_video_talker_src_data *data; 01533 /* If the channel doesn't support video, we don't care about it */ 01534 if (!ast_format_cap_has_type(chan->nativeformats, AST_FORMAT_TYPE_VIDEO)) { 01535 return; 01536 } 01537 01538 ao2_lock(bridge); 01539 data = &bridge->video_mode.mode_data.talker_src_data; 01540 01541 if (data->chan_vsrc == chan) { 01542 data->average_talking_energy = talker_energy; 01543 } else if ((data->average_talking_energy < talker_energy) && is_keyframe) { 01544 if (data->chan_old_vsrc) { 01545 ast_channel_unref(data->chan_old_vsrc); 01546 } 01547 if (data->chan_vsrc) { 01548 data->chan_old_vsrc = data->chan_vsrc; 01549 ast_indicate(data->chan_old_vsrc, AST_CONTROL_VIDUPDATE); 01550 } 01551 data->chan_vsrc = ast_channel_ref(chan); 01552 data->average_talking_energy = talker_energy; 01553 ast_test_suite_event_notify("BRIDGE_VIDEO_SRC", "Message: video source updated\r\nVideo Channel: %s", ast_channel_name(data->chan_vsrc)); 01554 ast_indicate(data->chan_vsrc, AST_CONTROL_VIDUPDATE); 01555 } else if ((data->average_talking_energy < talker_energy) && !is_keyframe) { 01556 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 01557 } else if (!data->chan_vsrc && is_keyframe) { 01558 data->chan_vsrc = ast_channel_ref(chan); 01559 data->average_talking_energy = talker_energy; 01560 ast_test_suite_event_notify("BRIDGE_VIDEO_SRC", "Message: video source updated\r\nVideo Channel: %s", ast_channel_name(data->chan_vsrc)); 01561 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 01562 } else if (!data->chan_old_vsrc && is_keyframe) { 01563 data->chan_old_vsrc = ast_channel_ref(chan); 01564 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 01565 } 01566 ao2_unlock(bridge); 01567 }
| static void bridge_array_add | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Helper function to add a channel to the bridge array.
Definition at line 148 of file bridging.c.
References ast_bridge::array, ast_bridge::array_num, ast_bridge::array_size, ast_channel_name(), ast_debug, ast_log(), ast_realloc, BRIDGE_ARRAY_GROW, bridge_poke(), LOG_ERROR, and ast_bridge::waiting.
Referenced by ast_bridge_merge(), bridge_channel_join(), and bridge_channel_unsuspend().
00149 { 00150 /* We have to make sure the bridge thread is not using the bridge array before messing with it */ 00151 while (bridge->waiting) { 00152 bridge_poke(bridge); 00153 sched_yield(); 00154 } 00155 00156 bridge->array[bridge->array_num++] = chan; 00157 00158 ast_debug(1, "Added channel %s(%p) to bridge array on %p, new count is %d\n", ast_channel_name(chan), chan, bridge, (int)bridge->array_num); 00159 00160 /* If the next addition of a channel will exceed our array size grow it out */ 00161 if (bridge->array_num == bridge->array_size) { 00162 struct ast_channel **tmp; 00163 ast_debug(1, "Growing bridge array on %p from %d to %d\n", bridge, (int)bridge->array_size, (int)bridge->array_size + BRIDGE_ARRAY_GROW); 00164 if (!(tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel *)))) { 00165 ast_log(LOG_ERROR, "Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge); 00166 return; 00167 } 00168 bridge->array = tmp; 00169 bridge->array_size += BRIDGE_ARRAY_GROW; 00170 } 00171 00172 return; 00173 }
| static void bridge_array_remove | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Helper function to remove a channel from the bridge array.
Definition at line 179 of file bridging.c.
References ast_bridge::array, ast_bridge::array_num, ast_debug, bridge_poke(), and ast_bridge::waiting.
Referenced by ast_bridge_merge(), bridge_channel_join(), and bridge_channel_suspend().
00180 { 00181 int i; 00182 00183 /* We have to make sure the bridge thread is not using the bridge array before messing with it */ 00184 while (bridge->waiting) { 00185 bridge_poke(bridge); 00186 sched_yield(); 00187 } 00188 00189 for (i = 0; i < bridge->array_num; i++) { 00190 if (bridge->array[i] == chan) { 00191 bridge->array[i] = (bridge->array[(bridge->array_num - 1)] != chan ? bridge->array[(bridge->array_num - 1)] : NULL); 00192 bridge->array[(bridge->array_num - 1)] = NULL; 00193 bridge->array_num--; 00194 ast_debug(1, "Removed channel %p from bridge array on %p, new count is %d\n", chan, bridge, (int)bridge->array_num); 00195 break; 00196 } 00197 } 00198 00199 return; 00200 }
| static struct ast_bridge_channel* bridge_channel_alloc | ( | struct ast_bridge * | bridge | ) | [static, read] |
Definition at line 1066 of file bridging.c.
References ao2_alloc, ao2_ref, ast_cond_init, ast_bridge_channel::bridge, bridge_channel_destroy(), and ast_bridge_channel::cond.
Referenced by ast_bridge_impart(), and ast_bridge_join().
01067 { 01068 struct ast_bridge_channel *bridge_channel = ao2_alloc(sizeof(struct ast_bridge_channel), bridge_channel_destroy); 01069 if (!(bridge_channel)) { 01070 return NULL; 01071 } 01072 ast_cond_init(&bridge_channel->cond, NULL); 01073 if (bridge) { 01074 bridge_channel->bridge = bridge; 01075 ao2_ref(bridge_channel->bridge, +1); 01076 } 01077 return bridge_channel; 01078 }
| static void bridge_channel_destroy | ( | void * | obj | ) | [static] |
Definition at line 1054 of file bridging.c.
References ao2_ref, ast_cond_destroy, ast_bridge_channel::bridge, and ast_bridge_channel::cond.
Referenced by bridge_channel_alloc().
01055 { 01056 struct ast_bridge_channel *bridge_channel = obj; 01057 01058 if (bridge_channel->bridge) { 01059 ao2_ref(bridge_channel->bridge, -1); 01060 bridge_channel->bridge = NULL; 01061 } 01062 /* Destroy elements of the bridge channel structure and the bridge channel structure itself */ 01063 ast_cond_destroy(&bridge_channel->cond); 01064 }
| static void bridge_channel_dtmf_stream | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel | |||
| ) | [static] |
Internal function that plays back DTMF on a bridge channel.
Definition at line 900 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_copy_string(), ast_debug, ast_dtmf_stream(), ast_bridge_channel::chan, and ast_bridge_channel::dtmf_stream_q.
Referenced by bridge_channel_join().
00901 { 00902 char dtmf_q[8] = ""; 00903 00904 ast_copy_string(dtmf_q, bridge_channel->dtmf_stream_q, sizeof(dtmf_q)); 00905 bridge_channel->dtmf_stream_q[0] = '\0'; 00906 00907 ast_debug(1, "Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel); 00908 ast_dtmf_stream(bridge_channel->chan, NULL, dtmf_q, 250, 0); 00909 00910 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT); 00911 00912 return; 00913 }
| static void bridge_channel_feature | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel | |||
| ) | [static] |
Internal function that executes a feature on a bridge channel.
Definition at line 813 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_FEATURE, AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge_dtmf_stream(), ast_check_hangup_locked(), ast_clear_flag, ast_debug, AST_FLAG_END_DTMF_ONLY, AST_LIST_TRAVERSE, ast_set_flag, ast_waitfordigit(), ast_bridge_features_hook::callback, ast_bridge_channel::chan, ast_bridge_features_hook::dtmf, ast_bridge::features, ast_bridge_channel::features, ast_bridge_features_hook::hook_pvt, MAXIMUM_DTMF_FEATURE_STRING, and ast_bridge_channel::state.
Referenced by bridge_channel_join().
00814 { 00815 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features); 00816 struct ast_bridge_features_hook *hook = NULL; 00817 char dtmf[MAXIMUM_DTMF_FEATURE_STRING] = ""; 00818 int look_for_dtmf = 1, dtmf_len = 0; 00819 00820 /* The channel is now under our control and we don't really want any begin frames to do our DTMF matching so disable 'em at the core level */ 00821 ast_set_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY); 00822 00823 /* Wait for DTMF on the channel and put it into a buffer. If the buffer matches any feature hook execute the hook. */ 00824 while (look_for_dtmf) { 00825 int res = ast_waitfordigit(bridge_channel->chan, 3000); 00826 00827 /* If the above timed out simply exit */ 00828 if (!res) { 00829 ast_debug(1, "DTMF feature string collection on bridge channel %p timed out\n", bridge_channel); 00830 break; 00831 } else if (res < 0) { 00832 ast_debug(1, "DTMF feature string collection failed on bridge channel %p for some reason\n", bridge_channel); 00833 break; 00834 } 00835 00836 /* Add the above DTMF into the DTMF string so we can do our matching */ 00837 dtmf[dtmf_len++] = res; 00838 00839 ast_debug(1, "DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf); 00840 00841 /* Assume that we do not want to look for DTMF any longer */ 00842 look_for_dtmf = 0; 00843 00844 /* See if a DTMF feature hook matches or can match */ 00845 AST_LIST_TRAVERSE(&features->hooks, hook, entry) { 00846 /* If this hook matches just break out now */ 00847 if (!strcmp(hook->dtmf, dtmf)) { 00848 ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel); 00849 look_for_dtmf = 0; 00850 break; 00851 } else if (!strncmp(hook->dtmf, dtmf, dtmf_len)) { 00852 ast_debug(1, "DTMF feature hook %p can match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel); 00853 look_for_dtmf = 1; 00854 } else { 00855 ast_debug(1, "DTMF feature hook %p does not match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel); 00856 } 00857 } 00858 00859 /* If we have reached the maximum length of a DTMF feature string bail out */ 00860 if (dtmf_len == MAXIMUM_DTMF_FEATURE_STRING) { 00861 break; 00862 } 00863 } 00864 00865 /* Since we are done bringing DTMF in return to using both begin and end frames */ 00866 ast_clear_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY); 00867 00868 /* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */ 00869 if (hook) { 00870 hook->callback(bridge, bridge_channel, hook->hook_pvt); 00871 /* If we are handing the channel off to an external hook for ownership, 00872 * we are not guaranteed what kind of state it will come back in. If 00873 * the channel hungup, we need to detect that here. */ 00874 if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) { 00875 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END); 00876 } 00877 } else { 00878 ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan); 00879 } 00880 00881 /* if the channel is still in feature state, revert it back to wait state */ 00882 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_FEATURE) { 00883 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT); 00884 } 00885 00886 return; 00887 }
| static enum ast_bridge_channel_state bridge_channel_join | ( | struct ast_bridge_channel * | bridge_channel | ) | [static] |
Join a channel to a bridge and handle anything the bridge may want us to do.
Definition at line 916 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CAPABILITY_MULTITHREADED, AST_BRIDGE_CAPABILITY_THREAD, ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DTMF, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_FEATURE, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_BRIDGE_CHANNEL_STATE_START_TALKING, AST_BRIDGE_CHANNEL_STATE_STOP_TALKING, AST_BRIDGE_CHANNEL_STATE_WAIT, AST_BRIDGE_FLAG_SMART, ast_debug, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_copy(), ast_getformatname(), AST_LIST_INSERT_TAIL, AST_LIST_REMOVE, ast_pthread_create, AST_PTHREADT_NULL, ast_set_read_format(), ast_set_write_format(), ast_test_flag, ast_channel::bridge, ast_bridge_channel::bridge, bridge_array_add(), bridge_array_remove(), bridge_channel_dtmf_stream(), bridge_channel_feature(), bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), bridge_channel_suspend(), bridge_channel_talking(), bridge_channel_unsuspend(), bridge_check_dissolve(), bridge_make_compatible(), bridge_thread(), ast_bridge_technology::capabilities, ast_bridge_channel::chan, ast_bridge::feature_flags, find_bridge_channel(), ast_bridge_technology::join, ast_bridge_technology::leave, ast_bridge_technology::name, ast_bridge::num, ast_channel::readformat, smart_bridge_operation(), ast_bridge_channel::state, ast_bridge::stop, ast_bridge_channel::swap, ast_bridge::technology, ast_bridge::thread, ast_bridge_channel::thread, and ast_channel::writeformat.
Referenced by ast_bridge_join(), and bridge_channel_thread().
00917 { 00918 struct ast_format formats[2]; 00919 enum ast_bridge_channel_state state; 00920 ast_format_copy(&formats[0], &bridge_channel->chan->readformat); 00921 ast_format_copy(&formats[1], &bridge_channel->chan->writeformat); 00922 00923 /* Record the thread that will be the owner of us */ 00924 bridge_channel->thread = pthread_self(); 00925 00926 ast_debug(1, "Joining bridge channel %p to bridge %p\n", bridge_channel, bridge_channel->bridge); 00927 00928 ao2_lock(bridge_channel->bridge); 00929 00930 state = bridge_channel->state; 00931 00932 /* Add channel into the bridge */ 00933 AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry); 00934 bridge_channel->bridge->num++; 00935 00936 bridge_array_add(bridge_channel->bridge, bridge_channel->chan); 00937 00938 if (bridge_channel->swap) { 00939 struct ast_bridge_channel *bridge_channel2 = NULL; 00940 00941 /* If we are performing a swap operation we do not need 00942 * to execute the smart bridge operation as the actual number 00943 * of channels involved will not have changed, we just need to 00944 * tell the other channel to leave */ 00945 if ((bridge_channel2 = find_bridge_channel(bridge_channel->bridge, bridge_channel->swap))) { 00946 ast_debug(1, "Swapping bridge channel %p out from bridge %p so bridge channel %p can slip in\n", bridge_channel2, bridge_channel->bridge, bridge_channel); 00947 ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP); 00948 } 00949 00950 bridge_channel->swap = NULL; 00951 } else if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) { 00952 /* Perform the smart bridge operation, basically see if we need to move around between technologies */ 00953 smart_bridge_operation(bridge_channel->bridge, bridge_channel, bridge_channel->bridge->num); 00954 } 00955 00956 /* Make the channel compatible with the bridge */ 00957 bridge_make_compatible(bridge_channel->bridge, bridge_channel); 00958 00959 /* Tell the bridge technology we are joining so they set us up */ 00960 if (bridge_channel->bridge->technology->join) { 00961 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 00962 if (bridge_channel->bridge->technology->join(bridge_channel->bridge, bridge_channel)) { 00963 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 00964 } 00965 } 00966 00967 /* Actually execute the respective threading model, and keep our bridge thread alive */ 00968 while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) { 00969 /* Update bridge pointer on channel */ 00970 bridge_channel->chan->bridge = bridge_channel->bridge; 00971 /* If the technology requires a thread and one is not running, start it up */ 00972 if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) { 00973 bridge_channel->bridge->stop = 0; 00974 ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge); 00975 ao2_ref(bridge_channel->bridge, +1); 00976 if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) { 00977 ast_debug(1, "Failed to create a bridge thread for bridge %p, giving it another go.\n", bridge_channel->bridge); 00978 ao2_ref(bridge_channel->bridge, -1); 00979 continue; 00980 } 00981 } 00982 /* Execute the threading model */ 00983 state = (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTITHREADED ? bridge_channel_join_multithreaded(bridge_channel) : bridge_channel_join_singlethreaded(bridge_channel)); 00984 /* Depending on the above state see what we need to do */ 00985 switch (state) { 00986 case AST_BRIDGE_CHANNEL_STATE_FEATURE: 00987 bridge_channel_suspend(bridge_channel->bridge, bridge_channel); 00988 ao2_unlock(bridge_channel->bridge); 00989 bridge_channel_feature(bridge_channel->bridge, bridge_channel); 00990 ao2_lock(bridge_channel->bridge); 00991 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel); 00992 break; 00993 case AST_BRIDGE_CHANNEL_STATE_DTMF: 00994 bridge_channel_suspend(bridge_channel->bridge, bridge_channel); 00995 bridge_channel_dtmf_stream(bridge_channel->bridge, bridge_channel); 00996 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel); 00997 break; 00998 case AST_BRIDGE_CHANNEL_STATE_START_TALKING: 00999 case AST_BRIDGE_CHANNEL_STATE_STOP_TALKING: 01000 ao2_unlock(bridge_channel->bridge); 01001 bridge_channel_talking(bridge_channel->bridge, bridge_channel); 01002 ao2_lock(bridge_channel->bridge); 01003 break; 01004 default: 01005 break; 01006 } 01007 } 01008 01009 bridge_channel->chan->bridge = NULL; 01010 01011 /* See if we need to dissolve the bridge itself if they hung up */ 01012 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_END) { 01013 bridge_check_dissolve(bridge_channel->bridge, bridge_channel); 01014 } 01015 01016 /* Tell the bridge technology we are leaving so they tear us down */ 01017 if (bridge_channel->bridge->technology->leave) { 01018 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 01019 if (bridge_channel->bridge->technology->leave(bridge_channel->bridge, bridge_channel)) { 01020 ast_debug(1, "Bridge technology %s failed to leave %p from bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge); 01021 } 01022 } 01023 01024 /* Remove channel from the bridge */ 01025 bridge_channel->bridge->num--; 01026 AST_LIST_REMOVE(&bridge_channel->bridge->channels, bridge_channel, entry); 01027 01028 bridge_array_remove(bridge_channel->bridge, bridge_channel->chan); 01029 01030 /* Perform the smart bridge operation if needed since a channel has left */ 01031 if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) { 01032 smart_bridge_operation(bridge_channel->bridge, NULL, bridge_channel->bridge->num); 01033 } 01034 01035 ao2_unlock(bridge_channel->bridge); 01036 01037 /* Restore original formats of the channel as they came in */ 01038 if (ast_format_cmp(&bridge_channel->chan->readformat, &formats[0]) == AST_FORMAT_CMP_NOT_EQUAL) { 01039 ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(&formats[0]), formats[0].id); 01040 if (ast_set_read_format(bridge_channel->chan, &formats[0])) { 01041 ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(&formats[0]), formats[0].id); 01042 } 01043 } 01044 if (ast_format_cmp(&bridge_channel->chan->writeformat, &formats[1]) == AST_FORMAT_CMP_NOT_EQUAL) { 01045 ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(&formats[1]), formats[1].id); 01046 if (ast_set_write_format(bridge_channel->chan, &formats[1])) { 01047 ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(&formats[1]), formats[1].id); 01048 } 01049 } 01050 01051 return bridge_channel->state; 01052 }
| static enum ast_bridge_channel_state bridge_channel_join_multithreaded | ( | struct ast_bridge_channel * | bridge_channel | ) | [static] |
Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve.
Definition at line 723 of file bridging.c.
References ao2_lock, ao2_object_get_lockaddr(), ao2_unlock, ast_bridge_handle_trip(), ast_cond_wait, ast_debug, ast_waitfor_nandfds(), ast_bridge_channel::bridge, ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge_technology::fd, ast_bridge_channel::fds, ast_bridge_channel::state, ast_bridge_channel::suspended, and ast_bridge::technology.
Referenced by bridge_channel_join().
00724 { 00725 int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1; 00726 struct ast_channel *chan = NULL; 00727 00728 /* Add any file descriptors we may want to monitor */ 00729 if (bridge_channel->bridge->technology->fd) { 00730 for (i = 0; i < 4; i ++) { 00731 if (bridge_channel->fds[i] >= 0) { 00732 fds[nfds++] = bridge_channel->fds[i]; 00733 } 00734 } 00735 } 00736 00737 ao2_unlock(bridge_channel->bridge); 00738 00739 ao2_lock(bridge_channel); 00740 /* Wait for data to either come from the channel or us to be signalled */ 00741 if (!bridge_channel->suspended) { 00742 ao2_unlock(bridge_channel); 00743 ast_debug(10, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); 00744 chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms); 00745 } else { 00746 ast_debug(10, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); 00747 ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel)); 00748 ao2_unlock(bridge_channel); 00749 } 00750 00751 ao2_lock(bridge_channel->bridge); 00752 00753 if (!bridge_channel->suspended) { 00754 ast_bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd); 00755 } 00756 00757 return bridge_channel->state; 00758 }
| static enum ast_bridge_channel_state bridge_channel_join_singlethreaded | ( | struct ast_bridge_channel * | bridge_channel | ) | [static] |
Run in a singlethreaded model. Each joined channel yields itself to the main bridge thread. TODO: Improve.
Definition at line 761 of file bridging.c.
References ao2_lock, ao2_object_get_lockaddr(), ao2_unlock, AST_BRIDGE_CHANNEL_STATE_WAIT, ast_cond_wait, ast_debug, ast_bridge_channel::bridge, ast_bridge_channel::cond, and ast_bridge_channel::state.
Referenced by bridge_channel_join().
00762 { 00763 ao2_unlock(bridge_channel->bridge); 00764 ao2_lock(bridge_channel); 00765 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) { 00766 ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge); 00767 ast_cond_wait(&bridge_channel->cond, ao2_object_get_lockaddr(bridge_channel)); 00768 } 00769 ao2_unlock(bridge_channel); 00770 ao2_lock(bridge_channel->bridge); 00771 00772 return bridge_channel->state; 00773 }
| static void bridge_channel_suspend | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel | |||
| ) | [static] |
Internal function that suspends a channel from a bridge.
Definition at line 776 of file bridging.c.
References ao2_lock, ao2_unlock, bridge_array_remove(), ast_bridge_channel::chan, ast_bridge_technology::suspend, ast_bridge_channel::suspended, and ast_bridge::technology.
Referenced by ast_bridge_suspend(), and bridge_channel_join().
00777 { 00778 ao2_lock(bridge_channel); 00779 bridge_channel->suspended = 1; 00780 bridge_array_remove(bridge, bridge_channel->chan); 00781 ao2_unlock(bridge_channel); 00782 00783 if (bridge->technology->suspend) { 00784 bridge->technology->suspend(bridge, bridge_channel); 00785 } 00786 00787 return; 00788 }
| static void bridge_channel_talking | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel | |||
| ) | [static] |
Definition at line 889 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_WAIT, ast_bridge::features, ast_bridge_channel::features, ast_bridge_features::talker_cb, and ast_bridge_features::talker_pvt_data.
Referenced by bridge_channel_join().
00890 { 00891 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features); 00892 00893 if (features && features->talker_cb) { 00894 features->talker_cb(bridge, bridge_channel, features->talker_pvt_data); 00895 } 00896 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT); 00897 }
| static void* bridge_channel_thread | ( | void * | data | ) | [static] |
Thread responsible for imparted bridged channels.
Definition at line 1116 of file bridging.c.
References ast_bridge_channel::allow_impart_hangup, ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, ast_hangup(), bridge_channel_join(), ast_bridge_channel::chan, ast_bridge_channel::features, and ast_bridge_channel::swap.
Referenced by ast_bridge_impart().
01117 { 01118 struct ast_bridge_channel *bridge_channel = data; 01119 enum ast_bridge_channel_state state; 01120 01121 state = bridge_channel_join(bridge_channel); 01122 01123 /* If no other thread is going to take the channel then hang it up, or else we would have to service it until something else came along */ 01124 if (bridge_channel->allow_impart_hangup && (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP)) { 01125 ast_hangup(bridge_channel->chan); 01126 } 01127 01128 /* cleanup */ 01129 ao2_lock(bridge_channel); 01130 bridge_channel->chan = NULL; 01131 bridge_channel->swap = NULL; 01132 bridge_channel->features = NULL; 01133 ao2_unlock(bridge_channel); 01134 01135 ao2_ref(bridge_channel, -1); 01136 01137 return NULL; 01138 }
| static void bridge_channel_unsuspend | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel | |||
| ) | [static] |
Internal function that unsuspends a channel from a bridge.
Definition at line 791 of file bridging.c.
References ao2_lock, ao2_unlock, ast_cond_signal, bridge_array_add(), ast_bridge_channel::chan, ast_bridge_channel::cond, ast_bridge_channel::suspended, ast_bridge::technology, and ast_bridge_technology::unsuspend.
Referenced by ast_bridge_unsuspend(), and bridge_channel_join().
00792 { 00793 ao2_lock(bridge_channel); 00794 bridge_channel->suspended = 0; 00795 bridge_array_add(bridge, bridge_channel->chan); 00796 ast_cond_signal(&bridge_channel->cond); 00797 ao2_unlock(bridge_channel); 00798 00799 if (bridge->technology->unsuspend) { 00800 bridge->technology->unsuspend(bridge, bridge_channel); 00801 } 00802 00803 00804 00805 return; 00806 }
| static void bridge_check_dissolve | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel | |||
| ) | [static] |
Internal function to see whether a bridge should dissolve, and if so do it.
Definition at line 217 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_DEPART, AST_BRIDGE_CHANNEL_STATE_END, AST_BRIDGE_CHANNEL_STATE_HANGUP, AST_BRIDGE_FLAG_DISSOLVE, ast_debug, AST_LIST_TRAVERSE, ast_test_flag, ast_bridge_features::feature_flags, ast_bridge::feature_flags, ast_bridge_channel::features, ast_bridge_channel::state, ast_bridge::stop, and ast_bridge_features::usable.
Referenced by bridge_channel_join().
00218 { 00219 struct ast_bridge_channel *bridge_channel2 = NULL; 00220 00221 if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE) && (!bridge_channel->features || !bridge_channel->features->usable || !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE))) { 00222 return; 00223 } 00224 00225 ast_debug(1, "Dissolving bridge %p\n", bridge); 00226 00227 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) { 00228 if (bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_END && bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_DEPART) { 00229 ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP); 00230 } 00231 } 00232 00233 /* Since all the channels are going away let's go ahead and stop our on thread */ 00234 bridge->stop = 1; 00235 00236 return; 00237 }
| static int bridge_drop_control_frame | ( | int | subclass | ) | [static] |
Internal function used to determine whether a control frame should be dropped or not.
Definition at line 264 of file bridging.c.
References AST_CONTROL_ANSWER.
Referenced by ast_bridge_handle_trip().
00265 { 00266 switch (subclass) { 00267 case AST_CONTROL_ANSWER: 00268 case -1: 00269 return 1; 00270 default: 00271 return 0; 00272 } 00273 }
| static struct ast_frame* bridge_handle_dtmf | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel, | |||
| struct ast_frame * | frame | |||
| ) | [static, read] |
Internal function to handle DTMF from a channel.
Definition at line 240 of file bridging.c.
References ast_bridge_change_state(), AST_BRIDGE_CHANNEL_STATE_FEATURE, ast_frfree, AST_LIST_TRAVERSE, ast_bridge_features_hook::dtmf, ast_bridge::features, ast_bridge_channel::features, ast_frame_subclass::integer, ast_frame::subclass, and ast_bridge_features::usable.
Referenced by ast_bridge_handle_trip().
00241 { 00242 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features); 00243 struct ast_bridge_features_hook *hook = NULL; 00244 00245 /* If the features structure we grabbed is not usable immediately return the frame */ 00246 if (!features->usable) { 00247 return frame; 00248 } 00249 00250 /* See if this DTMF matches the beginnings of any feature hooks, if so we switch to the feature state to either execute the feature or collect more DTMF */ 00251 AST_LIST_TRAVERSE(&features->hooks, hook, entry) { 00252 if (hook->dtmf[0] == frame->subclass.integer) { 00253 ast_frfree(frame); 00254 frame = NULL; 00255 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_FEATURE); 00256 break; 00257 } 00258 } 00259 00260 return frame; 00261 }
| static int bridge_make_compatible | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel | |||
| ) | [static] |
Definition at line 553 of file bridging.c.
References ast_best_codec(), ast_channel_name(), ast_debug, ast_format_cap_iscompatible(), ast_format_copy(), ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_set_read_format(), ast_set_write_format(), ast_bridge_channel::chan, ast_bridge_technology::format_capabilities, LOG_WARNING, ast_bridge_technology::name, option_debug, ast_channel::readformat, ast_bridge::technology, and ast_channel::writeformat.
Referenced by ast_bridge_merge(), bridge_channel_join(), and smart_bridge_operation().
00554 { 00555 struct ast_format formats[2]; 00556 ast_format_copy(&formats[0], &bridge_channel->chan->readformat); 00557 ast_format_copy(&formats[1], &bridge_channel->chan->writeformat); 00558 00559 /* Are the formats currently in use something ths bridge can handle? */ 00560 if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, &bridge_channel->chan->readformat)) { 00561 struct ast_format best_format; 00562 ast_best_codec(bridge->technology->format_capabilities, &best_format); 00563 00564 /* Read format is a no go... */ 00565 if (option_debug) { 00566 char codec_buf[512]; 00567 ast_debug(1, "Bridge technology %s wants to read any of formats %s but channel has %s\n", bridge->technology->name, 00568 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->format_capabilities), 00569 ast_getformatname(&formats[0])); 00570 } 00571 /* Switch read format to the best one chosen */ 00572 if (ast_set_read_format(bridge_channel->chan, &best_format)) { 00573 ast_log(LOG_WARNING, "Failed to set channel %s to read format %s\n", ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format)); 00574 return -1; 00575 } 00576 ast_debug(1, "Bridge %p put channel %s into read format %s\n", bridge, ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format)); 00577 } else { 00578 ast_debug(1, "Bridge %p is happy that channel %s already has read format %s\n", bridge, ast_channel_name(bridge_channel->chan), ast_getformatname(&formats[0])); 00579 } 00580 00581 if (!ast_format_cap_iscompatible(bridge->technology->format_capabilities, &formats[1])) { 00582 struct ast_format best_format; 00583 ast_best_codec(bridge->technology->format_capabilities, &best_format); 00584 00585 /* Write format is a no go... */ 00586 if (option_debug) { 00587 char codec_buf[512]; 00588 ast_debug(1, "Bridge technology %s wants to write any of formats %s but channel has %s\n", bridge->technology->name, 00589 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->format_capabilities), 00590 ast_getformatname(&formats[1])); 00591 } 00592 /* Switch write format to the best one chosen */ 00593 if (ast_set_write_format(bridge_channel->chan, &best_format)) { 00594 ast_log(LOG_WARNING, "Failed to set channel %s to write format %s\n", ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format)); 00595 return -1; 00596 } 00597 ast_debug(1, "Bridge %p put channel %s into write format %s\n", bridge, ast_channel_name(bridge_channel->chan), ast_getformatname(&best_format)); 00598 } else { 00599 ast_debug(1, "Bridge %p is happy that channel %s already has write format %s\n", bridge, ast_channel_name(bridge_channel->chan), ast_getformatname(&formats[1])); 00600 } 00601 00602 return 0; 00603 }
| static void bridge_poke | ( | struct ast_bridge * | bridge | ) | [static] |
Helper function to poke the bridge thread.
Definition at line 134 of file bridging.c.
References AST_PTHREADT_NULL, AST_PTHREADT_STOP, and ast_bridge::thread.
Referenced by ast_bridge_destroy(), bridge_array_add(), bridge_array_remove(), and smart_bridge_operation().
00135 { 00136 /* Poke the thread just in case */ 00137 if (bridge->thread != AST_PTHREADT_NULL && bridge->thread != AST_PTHREADT_STOP) { 00138 pthread_kill(bridge->thread, SIGURG); 00139 } 00140 00141 return; 00142 }
| static void* bridge_thread | ( | void * | data | ) | [static] |
Bridge thread function.
Definition at line 368 of file bridging.c.
References ao2_lock, ao2_ref, ao2_unlock, ast_bridge::array_num, ast_debug, AST_PTHREADT_NULL, generic_thread_loop(), ast_bridge::refresh, ast_bridge::stop, ast_bridge::technology, ast_bridge::thread, and ast_bridge_technology::thread.
Referenced by bridge_channel_join(), and smart_bridge_operation().
00369 { 00370 struct ast_bridge *bridge = data; 00371 int res = 0; 00372 00373 ao2_lock(bridge); 00374 00375 ast_debug(1, "Started bridge thread for %p\n", bridge); 00376 00377 /* Loop around until we are told to stop */ 00378 while (!bridge->stop && bridge->array_num && !res) { 00379 /* In case the refresh bit was set simply set it back to off */ 00380 bridge->refresh = 0; 00381 00382 ast_debug(1, "Launching bridge thread function %p for bridge %p\n", (bridge->technology->thread ? bridge->technology->thread : &generic_thread_loop), bridge); 00383 00384 /* Execute the appropriate thread function. If the technology does not provide one we use the generic one */ 00385 res = (bridge->technology->thread ? bridge->technology->thread(bridge) : generic_thread_loop(bridge)); 00386 } 00387 00388 ast_debug(1, "Ending bridge thread for %p\n", bridge); 00389 00390 /* Indicate the bridge thread is no longer active */ 00391 bridge->thread = AST_PTHREADT_NULL; 00392 ao2_unlock(bridge); 00393 00394 ao2_ref(bridge, -1); 00395 00396 return NULL; 00397 }
| static void cleanup_video_mode | ( | struct ast_bridge * | bridge | ) | [static] |
Definition at line 1489 of file bridging.c.
References AST_BRIDGE_VIDEO_MODE_NONE, AST_BRIDGE_VIDEO_MODE_SINGLE_SRC, AST_BRIDGE_VIDEO_MODE_TALKER_SRC, ast_channel_unref, ast_bridge_video_talker_src_data::chan_old_vsrc, ast_bridge_video_talker_src_data::chan_vsrc, ast_bridge_video_single_src_data::chan_vsrc, ast_bridge_video_mode::mode, ast_bridge_video_mode::mode_data, ast_bridge_video_mode::single_src_data, ast_bridge_video_mode::talker_src_data, and ast_bridge::video_mode.
Referenced by ast_bridge_set_single_src_video_mode(), ast_bridge_set_talker_src_video_mode(), and destroy_bridge().
01490 { 01491 switch (bridge->video_mode.mode) { 01492 case AST_BRIDGE_VIDEO_MODE_NONE: 01493 break; 01494 case AST_BRIDGE_VIDEO_MODE_SINGLE_SRC: 01495 if (bridge->video_mode.mode_data.single_src_data.chan_vsrc) { 01496 ast_channel_unref(bridge->video_mode.mode_data.single_src_data.chan_vsrc); 01497 } 01498 break; 01499 case AST_BRIDGE_VIDEO_MODE_TALKER_SRC: 01500 if (bridge->video_mode.mode_data.talker_src_data.chan_vsrc) { 01501 ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_vsrc); 01502 } 01503 if (bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc) { 01504 ast_channel_unref(bridge->video_mode.mode_data.talker_src_data.chan_old_vsrc); 01505 } 01506 } 01507 memset(&bridge->video_mode, 0, sizeof(bridge->video_mode)); 01508 }
| static void destroy_bridge | ( | void * | obj | ) | [static] |
Definition at line 434 of file bridging.c.
References ast_bridge::array, ast_bridge_features_cleanup(), ast_debug, ast_free, ast_module_unref(), cleanup_video_mode(), ast_bridge_technology::destroy, ast_bridge::features, ast_bridge_technology::mod, ast_bridge_technology::name, and ast_bridge::technology.
Referenced by ast_bridge_new().
00435 { 00436 struct ast_bridge *bridge = obj; 00437 00438 ast_debug(1, "Actually destroying bridge %p, nobody wants it anymore\n", bridge); 00439 00440 /* Pass off the bridge to the technology to destroy if needed */ 00441 if (bridge->technology->destroy) { 00442 ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge); 00443 if (bridge->technology->destroy(bridge)) { 00444 ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->technology->name, bridge); 00445 } 00446 } 00447 00448 /* We are no longer using the bridge technology so decrement the module reference count on it */ 00449 if (bridge->technology->mod) { 00450 ast_module_unref(bridge->technology->mod); 00451 } 00452 00453 /* Last but not least clean up the features configuration */ 00454 ast_bridge_features_cleanup(&bridge->features); 00455 00456 /* Drop the array of channels */ 00457 ast_free(bridge->array); 00458 00459 cleanup_video_mode(bridge); 00460 00461 return; 00462 }
| static struct ast_bridge_technology* find_best_technology | ( | uint32_t | capabilities | ) | [static, read] |
Helper function used to find the "best" bridge technology given a specified capabilities.
Definition at line 400 of file bridging.c.
References ast_debug, ast_module_ref(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_bridge_technology::capabilities, ast_bridge_technology::name, ast_bridge_technology::preference, and ast_bridge_technology::suspended.
Referenced by ast_bridge_check(), ast_bridge_new(), and smart_bridge_operation().
00401 { 00402 struct ast_bridge_technology *current = NULL, *best = NULL; 00403 00404 AST_RWLIST_RDLOCK(&bridge_technologies); 00405 AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) { 00406 if (current->suspended) { 00407 ast_debug(1, "Bridge technology %s is suspended. Skipping.\n", current->name); 00408 continue; 00409 } 00410 if (!(current->capabilities & capabilities)) { 00411 ast_debug(1, "Bridge technology %s does not have the capabilities we need.\n", current->name); 00412 continue; 00413 } 00414 if (best && best->preference < current->preference) { 00415 ast_debug(1, "Bridge technology %s has preference %d while %s has preference %d. Skipping.\n", current->name, current->preference, best->name, best->preference); 00416 continue; 00417 } 00418 best = current; 00419 } 00420 00421 if (best) { 00422 /* Increment it's module reference count if present so it does not get unloaded while in use */ 00423 if (best->mod) { 00424 ast_module_ref(best->mod); 00425 } 00426 ast_debug(1, "Chose bridge technology %s\n", best->name); 00427 } 00428 00429 AST_RWLIST_UNLOCK(&bridge_technologies); 00430 00431 return best; 00432 }
| static struct ast_bridge_channel* find_bridge_channel | ( | struct ast_bridge * | bridge, | |
| struct ast_channel * | chan | |||
| ) | [static, read] |
Helper function to find a bridge channel given a channel.
Definition at line 203 of file bridging.c.
References AST_LIST_TRAVERSE, and ast_bridge_channel::chan.
Referenced by ast_bridge_depart(), ast_bridge_handle_trip(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), and bridge_channel_join().
00204 { 00205 struct ast_bridge_channel *bridge_channel = NULL; 00206 00207 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) { 00208 if (bridge_channel->chan == chan) { 00209 break; 00210 } 00211 } 00212 00213 return bridge_channel; 00214 }
| static int generic_thread_loop | ( | struct ast_bridge * | bridge | ) | [static] |
Generic thread loop, TODO: Rethink this/improve it.
Definition at line 340 of file bridging.c.
References ao2_lock, ao2_unlock, ast_bridge::array, ast_bridge::array_num, ast_bridge_handle_trip(), ast_waitfor_n(), first, ast_bridge::refresh, ast_bridge::stop, and ast_bridge::waiting.
Referenced by bridge_thread().
00341 { 00342 while (!bridge->stop && !bridge->refresh && bridge->array_num) { 00343 struct ast_channel *winner = NULL; 00344 int to = -1; 00345 00346 /* Move channels around for priority reasons if we have more than one channel in our array */ 00347 if (bridge->array_num > 1) { 00348 struct ast_channel *first = bridge->array[0]; 00349 memmove(bridge->array, bridge->array + 1, sizeof(struct ast_channel *) * (bridge->array_num - 1)); 00350 bridge->array[(bridge->array_num - 1)] = first; 00351 } 00352 00353 /* Wait on the channels */ 00354 bridge->waiting = 1; 00355 ao2_unlock(bridge); 00356 winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to); 00357 bridge->waiting = 0; 00358 ao2_lock(bridge); 00359 00360 /* Process whatever they did */ 00361 ast_bridge_handle_trip(bridge, NULL, winner, -1); 00362 } 00363 00364 return 0; 00365 }
| static int smart_bridge_operation | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel, | |||
| int | count | |||
| ) | [static] |
Perform the smart bridge operation. Basically sees if a new bridge technology should be used instead of the current one.
Definition at line 606 of file bridging.c.
References ao2_lock, ao2_unlock, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_CAPABILITY_THREAD, ast_cond_signal, ast_debug, AST_LIST_TRAVERSE, ast_module_unref(), AST_PTHREADT_NULL, bridge_make_compatible(), bridge_poke(), ast_bridge::bridge_pvt, bridge_thread(), ast_bridge_technology::capabilities, ast_bridge_channel::cond, ast_bridge_technology::create, find_best_technology(), ast_bridge_technology::join, ast_bridge_technology::name, ast_bridge::refresh, ast_bridge::stop, ast_bridge::technology, ast_bridge_channel::thread, and ast_bridge::thread.
Referenced by ast_bridge_merge(), and bridge_channel_join().
00607 { 00608 uint32_t new_capabilities = 0; 00609 struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology; 00610 struct ast_bridge temp_bridge = { 00611 .technology = bridge->technology, 00612 .bridge_pvt = bridge->bridge_pvt, 00613 }; 00614 struct ast_bridge_channel *bridge_channel2 = NULL; 00615 00616 /* Based on current feature determine whether we want to change bridge technologies or not */ 00617 if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) { 00618 if (count <= 2) { 00619 ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name); 00620 return 0; 00621 } 00622 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX; 00623 } else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) { 00624 if (count > 2) { 00625 ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name); 00626 return 0; 00627 } 00628 new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX; 00629 } 00630 00631 if (!new_capabilities) { 00632 ast_debug(1, "Bridge '%p' has no new capabilities, not performing smart bridge operation.\n", bridge); 00633 return 0; 00634 } 00635 00636 /* Attempt to find a new bridge technology to satisfy the capabilities */ 00637 if (!(new_technology = find_best_technology(new_capabilities))) { 00638 return -1; 00639 } 00640 00641 ast_debug(1, "Performing smart bridge operation on bridge %p, moving from bridge technology %s to %s\n", bridge, old_technology->name, new_technology->name); 00642 00643 /* If a thread is currently executing for the current technology tell it to stop */ 00644 if (bridge->thread != AST_PTHREADT_NULL) { 00645 /* If the new bridge technology also needs a thread simply tell the bridge thread to refresh itself. This has the benefit of not incurring the cost/time of tearing down and bringing up a new thread. */ 00646 if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) { 00647 ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge); 00648 bridge->refresh = 1; 00649 bridge_poke(bridge); 00650 } else { 00651 pthread_t bridge_thread = bridge->thread; 00652 ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge); 00653 bridge->stop = 1; 00654 bridge_poke(bridge); 00655 ao2_unlock(bridge); 00656 pthread_join(bridge_thread, NULL); 00657 ao2_lock(bridge); 00658 } 00659 } 00660 00661 /* Since we are soon going to pass this bridge to a new technology we need to NULL out the bridge_pvt pointer but don't worry as it still exists in temp_bridge, ditto for the old technology */ 00662 bridge->bridge_pvt = NULL; 00663 bridge->technology = new_technology; 00664 00665 /* Pass the bridge to the new bridge technology so it can set it up */ 00666 if (new_technology->create) { 00667 ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge); 00668 if (new_technology->create(bridge)) { 00669 ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge); 00670 } 00671 } 00672 00673 /* Move existing channels over to the new technology, while taking them away from the old one */ 00674 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) { 00675 /* Skip over channel that initiated the smart bridge operation */ 00676 if (bridge_channel == bridge_channel2) { 00677 continue; 00678 } 00679 00680 /* First we part them from the old technology */ 00681 if (old_technology->leave) { 00682 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p (really %p)\n", old_technology->name, bridge_channel2, &temp_bridge, bridge); 00683 if (old_technology->leave(&temp_bridge, bridge_channel2)) { 00684 ast_debug(1, "Bridge technology %s failed to allow %p (really %p) to leave bridge %p\n", old_technology->name, bridge_channel2, &temp_bridge, bridge); 00685 } 00686 } 00687 00688 /* Second we make them compatible again with the bridge */ 00689 bridge_make_compatible(bridge, bridge_channel2); 00690 00691 /* Third we join them to the new technology */ 00692 if (new_technology->join) { 00693 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge); 00694 if (new_technology->join(bridge, bridge_channel2)) { 00695 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge); 00696 } 00697 } 00698 00699 /* Fourth we tell them to wake up so they become aware that they above has happened */ 00700 pthread_kill(bridge_channel2->thread, SIGURG); 00701 ao2_lock(bridge_channel2); 00702 ast_cond_signal(&bridge_channel2->cond); 00703 ao2_unlock(bridge_channel2); 00704 } 00705 00706 /* Now that all the channels have been moved over we need to get rid of all the information the old technology may have left around */ 00707 if (old_technology->destroy) { 00708 ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge); 00709 if (old_technology->destroy(&temp_bridge)) { 00710 ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p (really %p)... some memory may have leaked\n", old_technology->name, &temp_bridge, bridge); 00711 } 00712 } 00713 00714 /* Finally if the old technology has module referencing remove our reference, we are no longer going to use it */ 00715 if (old_technology->mod) { 00716 ast_module_unref(old_technology->mod); 00717 } 00718 00719 return 0; 00720 }
char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING] [static] |
Default DTMF keys for built in features
Definition at line 57 of file bridging.c.
void* builtin_features_handlers[AST_BRIDGE_BUILTIN_END] [static] |
Function handlers for the built in features
Definition at line 60 of file bridging.c.
1.5.6