52 #define BRIDGE_ARRAY_START 128
55 #define BRIDGE_ARRAY_GROW 32
77 if ((!strcasecmp(current->
name, technology->
name)) || (current == technology)) {
78 ast_log(
LOG_WARNING,
"A bridge technology of %s already claims to exist in our world.\n", technology->
name);
85 technology->
mod = module;
107 if (current == technology) {
119 return current ? 0 : -1;
125 bridge_channel->
state = new_state;
128 if (!pthread_equal(pthread_self(), bridge_channel->
thread)) {
129 pthread_kill(bridge_channel->
thread, SIGURG);
143 pthread_kill(bridge->
thread, SIGURG);
163 ast_debug(1,
"Added channel %s(%p) to bridge array on %p, new count is %d\n", chan->
name, chan, bridge, (
int)bridge->
array_num);
170 ast_log(
LOG_ERROR,
"Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge);
194 for (i = 0; i < bridge->
array_num; i++) {
195 if (bridge->
array[i] == chan) {
199 ast_debug(1,
"Removed channel %p from bridge array on %p, new count is %d\n", chan, bridge, (
int)bridge->
array_num);
213 if (bridge_channel->
chan == chan) {
218 return bridge_channel;
230 ast_debug(1,
"Dissolving bridge %p\n", bridge);
280 if (chan && !bridge_channel) {
285 if (chan && bridge_channel) {
293 ast_debug(1,
"Dropping control frame from bridge channel %p\n", bridge_channel);
361 ast_debug(1,
"Started bridge thread for %p\n", bridge);
374 ast_debug(1,
"Ending bridge thread for %p\n", bridge);
392 ast_debug(1,
"Bridge technology %s has capabilities %d and we want %u\n", current->
name, current->
capabilities, capabilities);
394 ast_debug(1,
"Bridge technology %s is suspended. Skipping.\n", current->
name);
398 ast_debug(1,
"Bridge technology %s does not have the capabilities we need.\n", current->
name);
401 if (best && best->preference < current->
preference) {
402 ast_debug(1,
"Bridge technology %s has preference %u while %s has preference %u. Skipping.\n", current->
name, current->
preference, best->name, best->preference);
413 ast_debug(1,
"Chose bridge technology %s\n", best->name);
425 ast_debug(1,
"Actually destroying bridge %p, nobody wants it anymore\n", bridge);
429 ast_debug(1,
"Giving bridge technology %s the bridge structure %p to destroy\n", bridge->
technology->
name, bridge);
431 ast_debug(1,
"Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->
technology->
name, bridge);
470 if (!bridge_technology) {
471 ast_debug(1,
"Failed to find a bridge technology to satisfy capabilities %u\n", capabilities);
491 ast_debug(1,
"Giving bridge technology %s the bridge structure %p to setup\n", bridge->
technology->
name, bridge);
526 pthread_join(thread, NULL);
530 ast_debug(1,
"Telling all channels in bridge %p to end and leave the party\n", bridge);
555 ast_debug(1,
"Bridge technology %s wants to read any of formats %s but channel has %s\n", bridge->
technology->
name,
575 ast_debug(1,
"Bridge technology %s wants to write any of formats %s but channel has %s\n", bridge->
technology->
name,
606 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);
612 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);
618 if (!new_capabilities) {
619 ast_debug(1,
"Bridge '%p' has no new capabilities, not performing smart bridge operation.\n", bridge);
625 ast_debug(1,
"Smart bridge operation was unable to find new bridge technology with capabilities %u to satisfy bridge %p\n", new_capabilities, bridge);
629 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);
635 ast_debug(1,
"Telling current bridge thread for bridge %p to refresh\n", bridge);
640 ast_debug(1,
"Telling current bridge thread for bridge %p to stop\n", bridge);
644 pthread_join(bridge_thread, NULL);
654 if (new_technology->
create) {
655 ast_debug(1,
"Giving bridge technology %s the bridge structure %p to setup\n", new_technology->
name, bridge);
656 if (new_technology->
create(bridge)) {
657 ast_debug(1,
"Bridge technology %s failed to setup bridge structure %p\n", new_technology->
name, bridge);
664 if (bridge_channel == bridge_channel2) {
669 if (old_technology->leave) {
670 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);
671 if (old_technology->leave(&temp_bridge, bridge_channel2)) {
672 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);
680 if (new_technology->
join) {
681 ast_debug(1,
"Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->
name, bridge_channel2, bridge);
682 if (new_technology->
join(bridge, bridge_channel2)) {
683 ast_debug(1,
"Bridge technology %s failed to join %p to bridge %p\n", new_technology->
name, bridge_channel2, bridge);
688 pthread_kill(bridge_channel2->
thread, SIGURG);
695 if (old_technology->destroy) {
696 ast_debug(1,
"Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge);
697 if (old_technology->destroy(&temp_bridge)) {
698 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);
703 if (old_technology->mod) {
713 int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1;
718 for (i = 0; i < 4; i ++) {
719 if (bridge_channel->
fds[i] >= 0) {
720 fds[nfds++] = bridge_channel->
fds[i];
729 ast_debug(1,
"Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->
bridge);
733 ast_debug(1,
"Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->
bridge);
744 return bridge_channel->
state;
753 ast_debug(1,
"Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->
bridge);
759 return bridge_channel->
state;
796 int look_for_dtmf = 1, dtmf_len = 0;
802 while (look_for_dtmf) {
807 ast_debug(1,
"DTMF feature string collection on bridge channel %p timed out\n", bridge_channel);
809 }
else if (res < 0) {
810 ast_debug(1,
"DTMF feature string collection failed on bridge channel %p for some reason\n", bridge_channel);
815 dtmf[dtmf_len++] = res;
817 ast_debug(1,
"DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf);
825 if (!strcmp(hook->
dtmf, dtmf)) {
826 ast_debug(1,
"DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel);
828 }
else if (!strncmp(hook->
dtmf, dtmf, dtmf_len)) {
829 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);
832 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);
864 ast_debug(1,
"Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel);
879 bridge_channel->
thread = pthread_self();
881 ast_debug(1,
"Joining bridge channel %p to bridge %p\n", bridge_channel, bridge_channel->
bridge);
885 state = bridge_channel->
state;
893 if (bridge_channel->
swap) {
898 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);
902 bridge_channel->
swap = NULL;
926 ast_debug(1,
"Starting a bridge thread for bridge %p\n", bridge_channel->
bridge);
929 ast_debug(1,
"Failed to create a bridge thread for bridge %p, giving it another go.\n", bridge_channel->
bridge);
980 ast_debug(1,
"Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel,
ast_getformatname(formats[0]), formats[0]);
986 ast_debug(1,
"Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel,
ast_getformatname(formats[1]), formats[1]);
990 return bridge_channel->
state;
1048 if (!(bridge_channel =
ast_calloc(1,
sizeof(*bridge_channel)))) {
1091 thread = bridge_channel->
thread;
1095 pthread_join(thread, NULL);
1130 ast_debug(1,
"Can't merge bridge %p into bridge %p, multimix is needed and it could not be acquired.\n", bridge1, bridge0);
1134 ast_debug(1,
"Merging channels from bridge %p into bridge %p\n", bridge1, bridge0);
1140 ast_debug(1,
"Can't merge bridge %p into bridge %p, tried to perform smart bridge operation and failed.\n", bridge1, bridge0);
1146 ast_debug(1,
"Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0);
1154 ast_debug(1,
"Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->
technology->
name, bridge_channel, bridge1);
1156 ast_debug(1,
"Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->
technology->
name, bridge_channel, bridge1);
1167 bridge_channel->
bridge = bridge0;
1179 ast_debug(1,
"Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->
technology->
name, bridge_channel, bridge0);
1181 ast_debug(1,
"Bridge technology %s failed to join %p to bridge %p\n", bridge0->
technology->
name, bridge_channel, bridge0);
1186 pthread_kill(bridge_channel->
thread, SIGURG);
1192 ast_debug(1,
"Merged channels from bridge %p into bridge %p\n", bridge1, bridge0);
1250 if (builtin_features_handlers[feature]) {
1255 ast_copy_string(builtin_features_dtmf[feature], dtmf,
sizeof(builtin_features_dtmf[feature]));
1258 builtin_features_handlers[feature] = callback;
1265 if (!builtin_features_handlers[feature]) {
1269 builtin_features_handlers[feature] = NULL;
1279 if (!(hook =
ast_calloc(1,
sizeof(*hook)))) {
1299 dtmf = builtin_features_dtmf[feature];
1302 ast_debug(1,
"Failed to enable built in feature %u on %p, no DTMF string is available for it.\n", feature, features);
1307 if (!builtin_features_handlers[feature]) {
1325 memset(features, 0,
sizeof(*features));
1352 if (bridge_channel->
chan == chan) {
int(* ast_bridge_features_hook_callback)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Features hook callback type.
static void bridge_channel_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Internal function that unsuspends a channel from a bridge.
ast_bridge_capability
Capabilities for a bridge technology.
struct ast_channel * ast_waitfor_n(struct ast_channel **chan, int n, int *ms)
Waits for input on a group of channels Wait for input on an array of channels for a given # of millis...
static void destroy_bridge(void *obj)
union ast_frame_subclass subclass
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
enum sip_cc_notify_state state
Main Channel structure associated with a channel.
static int generic_thread_loop(struct ast_bridge *bridge)
Generic thread loop, TODO: Rethink this/improve it.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
struct ast_flags feature_flags
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.
struct ast_bridge_features * features
static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
static const char config[]
void ast_module_unref(struct ast_module *)
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
int ast_bridge_check(enum ast_bridge_capability capabilities)
See if it is possible to create a bridge.
enum ast_bridge_channel_state ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
Join (blocking) a channel to a bridge.
Structure that contains features information.
#define ast_test_flag(p, flag)
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
void ast_bridge_technology_suspend(struct ast_bridge_technology *technology)
Suspend a bridge technology from consideration.
#define ast_set_flag(p, flag)
static struct aji_capabilities * capabilities
void ast_verbose(const char *fmt,...)
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
void(* suspend)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
struct ast_bridge * ast_bridge_new(enum ast_bridge_capability capabilities, int flags)
Create a new bridge.
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_depart(struct ast_bridge *bridge, struct ast_channel *chan)
Depart a channel from a bridge.
static void * bridge_channel_thread(void *data)
Thread responsible for imparted bridged channels.
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
#define ast_cond_wait(cond, mutex)
#define ast_cond_init(cond, attr)
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
int ast_bridge_destroy(struct ast_bridge *bridge)
Destroy a bridge.
static int bridge_drop_control_frame(int subclass)
Internal function used to determine whether a control frame should be dropped or not.
#define ast_mutex_lock(a)
int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
Unregister a handler for a built in feature.
int(* poke)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
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 ...
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define ast_cond_signal(cond)
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
void(* unsuspend)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
struct ast_bridge * bridge
static void * bridge_thread(void *data)
Bridge thread function.
struct ast_bridge_features features
char dtmf[MAXIMUM_DTMF_FEATURE_STRING]
int __ast_bridge_technology_register(struct ast_bridge_technology *technology, struct ast_module *mod)
Register a bridge technology for use.
static void bridge_array_add(struct ast_bridge *bridge, struct ast_channel *chan)
Helper function to add a channel to the bridge array.
int ast_bridge_features_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_features_hook_callback callback, void *hook_pvt)
Attach a custom hook to a bridge features structure.
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of "format" is ...
struct ast_bridge_technology * technology
struct ast_flags feature_flags
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
int(* join)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
int(* create)(struct ast_bridge *bridge)
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of "format" is be...
#define ast_debug(level,...)
Log a DEBUG message.
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.
void ast_bridge_technology_unsuspend(struct ast_bridge_technology *technology)
Unsuspend a bridge technology.
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
Impart (non-blocking) a channel on a bridge.
General Asterisk PBX channel definitions.
int ast_bridge_merge(struct ast_bridge *bridge0, struct ast_bridge *bridge1)
Merge two bridges together.
#define AST_PTHREADT_NULL
static force_inline int attribute_pure ast_strlen_zero(const char *s)
static void bridge_poke(struct ast_bridge *bridge)
Helper function to poke the bridge thread.
#define BRIDGE_ARRAY_START
enum ast_bridge_preference preference
#define AST_RWLIST_TRAVERSE
int(* thread)(struct ast_bridge *bridge)
#define ao2_ref(o, delta)
#define AST_RWLIST_REMOVE_CURRENT
static struct ast_bridge_technology * find_best_technology(enum ast_bridge_capability capabilities)
Helper function used to find the "best" bridge technology given a specified capabilities.
A set of macros to manage forward-linked lists.
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.
int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
Suspend a channel temporarily from a bridge.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define MAXIMUM_DTMF_FEATURE_STRING
Maximum length of a DTMF feature string.
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...
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
Unregister a bridge technology from use.
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.
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
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.
static void bridge_channel_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Internal function that suspends a channel from a bridge.
Structure that contains information about a bridge.
char * ast_getformatname(format_t format)
Get the name of a format.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
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.
int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
Remove a channel from a bridge.
struct ast_channel ** array
const ast_string_field name
struct sla_ringing_trunk * first
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
#define ast_cond_destroy(cond)
int(* destroy)(struct ast_bridge *bridge)
#define ao2_alloc(data_size, destructor_fn)
struct ast_bridge * bridge
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define ast_pthread_create(a, b, c, d)
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.
struct ast_channel * swap
#define ast_clear_flag(p, flag)
enum ast_bridge_write_result(* write)(struct ast_bridge *bridge, struct ast_bridge_channel *bridged_channel, struct ast_frame *frame)
Support for logging to various files, console and syslog Configuration in file logger.conf.
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.
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
static void * builtin_features_handlers[AST_BRIDGE_BUILTIN_END]
int(* fd)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int fd)
#define AST_RWLIST_INSERT_TAIL
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
static void bridge_array_remove(struct ast_bridge *bridge, struct ast_channel *chan)
Helper function to remove a channel from the bridge array.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
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...
ast_bridge_feature_flags
Flags used for bridge features.
ast_bridge_features_hook_callback callback
Structure that is the essence of a bridge technology.
#define ast_realloc(a, b)
#define AST_PTHREADT_STOP
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Data structure associated with a single frame of data.
Options provided by main asterisk program.
ast_bridge_channel_state
State information about a bridged channel.
Structure that is the essence of a features hook.
enum ast_frame_type frametype
#define ast_mutex_init(pmutex)
#define BRIDGE_ARRAY_GROW
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send DTMF to a channel.
#define ast_mutex_destroy(a)
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.
static char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING]
int(* leave)(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
Asterisk module definitions.
enum ast_bridge_channel_state state
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.
struct ast_frame * ast_read_noaudio(struct ast_channel *chan)
Reads a frame, returning AST_FRAME_NULL frame if audio.
int ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
#define AST_RWLIST_TRAVERSE_SAFE_END
int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan)
Unsuspend a channel from a bridge.
ast_bridge_builtin_feature
Built in features.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
#define ast_mutex_unlock(a)
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.
struct ast_module * ast_module_ref(struct ast_module *)