mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
More trivial bridge code cleanup.
* Breaking long lines * Word wrapping comment blocks. * Removing redundant initializers. * Debug message wording. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@380108 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -100,11 +100,13 @@ static int multiplexed_bridge_create(struct ast_bridge *bridge)
|
|||||||
ao2_lock(multiplexed_threads);
|
ao2_lock(multiplexed_threads);
|
||||||
|
|
||||||
/* Try to find an existing thread to handle our additional channels */
|
/* Try to find an existing thread to handle our additional channels */
|
||||||
if (!(multiplexed_thread = ao2_callback(multiplexed_threads, 0, find_multiplexed_thread, NULL))) {
|
multiplexed_thread = ao2_callback(multiplexed_threads, 0, find_multiplexed_thread, NULL);
|
||||||
|
if (!multiplexed_thread) {
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
/* If we failed we will have to create a new one from scratch */
|
/* If we failed we will have to create a new one from scratch */
|
||||||
if (!(multiplexed_thread = ao2_alloc(sizeof(*multiplexed_thread), destroy_multiplexed_thread))) {
|
multiplexed_thread = ao2_alloc(sizeof(*multiplexed_thread), destroy_multiplexed_thread);
|
||||||
|
if (!multiplexed_thread) {
|
||||||
ast_debug(1, "Failed to find or create a new multiplexed thread for bridge '%p'\n", bridge);
|
ast_debug(1, "Failed to find or create a new multiplexed thread for bridge '%p'\n", bridge);
|
||||||
ao2_unlock(multiplexed_threads);
|
ao2_unlock(multiplexed_threads);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -207,11 +209,14 @@ static void *multiplexed_thread_function(void *data)
|
|||||||
ast_debug(1, "Starting actual thread for multiplexed thread '%p'\n", multiplexed_thread);
|
ast_debug(1, "Starting actual thread for multiplexed thread '%p'\n", multiplexed_thread);
|
||||||
|
|
||||||
while (multiplexed_thread->thread != AST_PTHREADT_STOP) {
|
while (multiplexed_thread->thread != AST_PTHREADT_STOP) {
|
||||||
struct ast_channel *winner = NULL, *first = multiplexed_thread->chans[0];
|
struct ast_channel *winner;
|
||||||
int to = -1, outfd = -1;
|
struct ast_channel *first = multiplexed_thread->chans[0];
|
||||||
|
int to = -1;
|
||||||
|
int outfd = -1;
|
||||||
|
|
||||||
/* Move channels around so not just the first one gets priority */
|
/* Move channels around so not just the first one gets priority */
|
||||||
memmove(multiplexed_thread->chans, multiplexed_thread->chans + 1, sizeof(struct ast_channel *) * (multiplexed_thread->service_count - 1));
|
memmove(multiplexed_thread->chans, multiplexed_thread->chans + 1,
|
||||||
|
sizeof(struct ast_channel *) * (multiplexed_thread->service_count - 1));
|
||||||
multiplexed_thread->chans[multiplexed_thread->service_count - 1] = first;
|
multiplexed_thread->chans[multiplexed_thread->service_count - 1] = first;
|
||||||
|
|
||||||
multiplexed_thread->waiting = 1;
|
multiplexed_thread->waiting = 1;
|
||||||
@@ -233,8 +238,9 @@ static void *multiplexed_thread_function(void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (winner && ast_channel_internal_bridge(winner)) {
|
if (winner && ast_channel_internal_bridge(winner)) {
|
||||||
struct ast_bridge *bridge = ast_channel_internal_bridge(winner);
|
struct ast_bridge *bridge;
|
||||||
int stop = 0;
|
int stop = 0;
|
||||||
|
|
||||||
ao2_unlock(multiplexed_thread);
|
ao2_unlock(multiplexed_thread);
|
||||||
while ((bridge = ast_channel_internal_bridge(winner)) && ao2_trylock(bridge)) {
|
while ((bridge = ast_channel_internal_bridge(winner)) && ao2_trylock(bridge)) {
|
||||||
sched_yield();
|
sched_yield();
|
||||||
@@ -310,7 +316,8 @@ static void multiplexed_add_or_remove(struct multiplexed_thread *multiplexed_thr
|
|||||||
/*! \brief Join function which actually adds the channel into the array to be monitored */
|
/*! \brief Join function which actually adds the channel into the array to be monitored */
|
||||||
static int multiplexed_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
static int multiplexed_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
||||||
{
|
{
|
||||||
struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan, *c1 = AST_LIST_LAST(&bridge->channels)->chan;
|
struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
|
||||||
|
struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
|
||||||
struct multiplexed_thread *multiplexed_thread = bridge->bridge_pvt;
|
struct multiplexed_thread *multiplexed_thread = bridge->bridge_pvt;
|
||||||
|
|
||||||
ast_debug(1, "Adding channel '%s' to multiplexed thread '%p' for monitoring\n", ast_channel_name(bridge_channel->chan), multiplexed_thread);
|
ast_debug(1, "Adding channel '%s' to multiplexed thread '%p' for monitoring\n", ast_channel_name(bridge_channel->chan), multiplexed_thread);
|
||||||
|
@@ -47,7 +47,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
|
|
||||||
static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
||||||
{
|
{
|
||||||
struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan, *c1 = AST_LIST_LAST(&bridge->channels)->chan;
|
struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
|
||||||
|
struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
|
||||||
|
|
||||||
/* If this is the first channel we can't make it compatible... unless we make it compatible with itself O.o */
|
/* If this is the first channel we can't make it compatible... unless we make it compatible with itself O.o */
|
||||||
if (AST_LIST_FIRST(&bridge->channels) == AST_LIST_LAST(&bridge->channels)) {
|
if (AST_LIST_FIRST(&bridge->channels) == AST_LIST_LAST(&bridge->channels)) {
|
||||||
|
@@ -284,7 +284,8 @@ static void softmix_process_write_audio(struct softmix_translate_helper *trans_h
|
|||||||
|
|
||||||
static void softmix_translate_helper_cleanup(struct softmix_translate_helper *trans_helper)
|
static void softmix_translate_helper_cleanup(struct softmix_translate_helper *trans_helper)
|
||||||
{
|
{
|
||||||
struct softmix_translate_helper_entry *entry = NULL;
|
struct softmix_translate_helper_entry *entry;
|
||||||
|
|
||||||
AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
|
AST_LIST_TRAVERSE(&trans_helper->entries, entry, entry) {
|
||||||
if (entry->out_frame) {
|
if (entry->out_frame) {
|
||||||
ast_frfree(entry->out_frame);
|
ast_frfree(entry->out_frame);
|
||||||
@@ -328,8 +329,10 @@ static int softmix_bridge_create(struct ast_bridge *bridge)
|
|||||||
/*! \brief Function called when a bridge is destroyed */
|
/*! \brief Function called when a bridge is destroyed */
|
||||||
static int softmix_bridge_destroy(struct ast_bridge *bridge)
|
static int softmix_bridge_destroy(struct ast_bridge *bridge)
|
||||||
{
|
{
|
||||||
struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
|
struct softmix_bridge_data *softmix_data;
|
||||||
if (!bridge->bridge_pvt) {
|
|
||||||
|
softmix_data = bridge->bridge_pvt;
|
||||||
|
if (!softmix_data) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ao2_ref(softmix_data, -1);
|
ao2_ref(softmix_data, -1);
|
||||||
@@ -382,7 +385,7 @@ static void set_softmix_bridge_data(int rate, int interval, struct ast_bridge_ch
|
|||||||
/*! \brief Function called when a channel is joined into the bridge */
|
/*! \brief Function called when a channel is joined into the bridge */
|
||||||
static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
||||||
{
|
{
|
||||||
struct softmix_channel *sc = NULL;
|
struct softmix_channel *sc;
|
||||||
struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
|
struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
|
||||||
|
|
||||||
/* Create a new softmix_channel structure and allocate various things on it */
|
/* Create a new softmix_channel structure and allocate various things on it */
|
||||||
@@ -718,7 +721,7 @@ static int softmix_mixing_array_init(struct softmix_mixing_array *mixing_array,
|
|||||||
memset(mixing_array, 0, sizeof(*mixing_array));
|
memset(mixing_array, 0, sizeof(*mixing_array));
|
||||||
mixing_array->max_num_entries = starting_num_entries;
|
mixing_array->max_num_entries = starting_num_entries;
|
||||||
if (!(mixing_array->buffers = ast_calloc(mixing_array->max_num_entries, sizeof(int16_t *)))) {
|
if (!(mixing_array->buffers = ast_calloc(mixing_array->max_num_entries, sizeof(int16_t *)))) {
|
||||||
ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure. \n");
|
ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -735,7 +738,7 @@ static int softmix_mixing_array_grow(struct softmix_mixing_array *mixing_array,
|
|||||||
/* give it some room to grow since memory is cheap but allocations can be expensive */
|
/* give it some room to grow since memory is cheap but allocations can be expensive */
|
||||||
mixing_array->max_num_entries = num_entries;
|
mixing_array->max_num_entries = num_entries;
|
||||||
if (!(tmp = ast_realloc(mixing_array->buffers, (mixing_array->max_num_entries * sizeof(int16_t *))))) {
|
if (!(tmp = ast_realloc(mixing_array->buffers, (mixing_array->max_num_entries * sizeof(int16_t *))))) {
|
||||||
ast_log(LOG_NOTICE, "Failed to re-allocate softmix mixing structure. \n");
|
ast_log(LOG_NOTICE, "Failed to re-allocate softmix mixing structure.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mixing_array->buffers = tmp;
|
mixing_array->buffers = tmp;
|
||||||
@@ -747,7 +750,7 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
|
|||||||
{
|
{
|
||||||
struct softmix_stats stats = { { 0 }, };
|
struct softmix_stats stats = { { 0 }, };
|
||||||
struct softmix_mixing_array mixing_array;
|
struct softmix_mixing_array mixing_array;
|
||||||
struct softmix_bridge_data *softmix_data = bridge->bridge_pvt;
|
struct softmix_bridge_data *softmix_data;
|
||||||
struct ast_timer *timer;
|
struct ast_timer *timer;
|
||||||
struct softmix_translate_helper trans_helper;
|
struct softmix_translate_helper trans_helper;
|
||||||
int16_t buf[MAX_DATALEN];
|
int16_t buf[MAX_DATALEN];
|
||||||
@@ -757,7 +760,8 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
|
|||||||
int i, x;
|
int i, x;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
if (!(softmix_data = bridge->bridge_pvt)) {
|
softmix_data = bridge->bridge_pvt;
|
||||||
|
if (!softmix_data) {
|
||||||
goto softmix_cleanup;
|
goto softmix_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,12 +773,11 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
|
|||||||
|
|
||||||
/* Give the mixing array room to grow, memory is cheap but allocations are expensive. */
|
/* Give the mixing array room to grow, memory is cheap but allocations are expensive. */
|
||||||
if (softmix_mixing_array_init(&mixing_array, bridge->num + 10)) {
|
if (softmix_mixing_array_init(&mixing_array, bridge->num + 10)) {
|
||||||
ast_log(LOG_NOTICE, "Failed to allocate softmix mixing structure. \n");
|
|
||||||
goto softmix_cleanup;
|
goto softmix_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!bridge->stop && !bridge->refresh && bridge->array_num) {
|
while (!bridge->stop && !bridge->refresh && bridge->array_num) {
|
||||||
struct ast_bridge_channel *bridge_channel = NULL;
|
struct ast_bridge_channel *bridge_channel;
|
||||||
int timeout = -1;
|
int timeout = -1;
|
||||||
enum ast_format_id cur_slin_id = ast_format_slin_by_rate(softmix_data->internal_rate);
|
enum ast_format_id cur_slin_id = ast_format_slin_by_rate(softmix_data->internal_rate);
|
||||||
unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
|
unsigned int softmix_samples = SOFTMIX_SAMPLES(softmix_data->internal_rate, softmix_data->internal_mixing_interval);
|
||||||
@@ -790,7 +793,8 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Grow the mixing array buffer as participants are added. */
|
/* Grow the mixing array buffer as participants are added. */
|
||||||
if (mixing_array.max_num_entries < bridge->num && softmix_mixing_array_grow(&mixing_array, bridge->num + 5)) {
|
if (mixing_array.max_num_entries < bridge->num
|
||||||
|
&& softmix_mixing_array_grow(&mixing_array, bridge->num + 5)) {
|
||||||
goto softmix_cleanup;
|
goto softmix_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,7 +891,7 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
|
|||||||
/* Wait for the timing source to tell us to wake up and get things done */
|
/* Wait for the timing source to tell us to wake up and get things done */
|
||||||
ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
|
ast_waitfor_n_fd(&timingfd, 1, &timeout, NULL);
|
||||||
if (ast_timer_ack(timer, 1) < 0) {
|
if (ast_timer_ack(timer, 1) < 0) {
|
||||||
ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge\n");
|
ast_log(LOG_ERROR, "Failed to acknowledge timer in softmix bridge.\n");
|
||||||
ao2_lock(bridge);
|
ao2_lock(bridge);
|
||||||
goto softmix_cleanup;
|
goto softmix_cleanup;
|
||||||
}
|
}
|
||||||
|
122
main/bridging.c
122
main/bridging.c
@@ -138,7 +138,11 @@ void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast
|
|||||||
ao2_unlock(bridge_channel);
|
ao2_unlock(bridge_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Helper function to poke the bridge thread */
|
/*!
|
||||||
|
* \brief Helper function to poke the bridge thread
|
||||||
|
*
|
||||||
|
* \note This function assumes the bridge is locked.
|
||||||
|
*/
|
||||||
static void bridge_poke(struct ast_bridge *bridge)
|
static void bridge_poke(struct ast_bridge *bridge)
|
||||||
{
|
{
|
||||||
/* Poke the thread just in case */
|
/* Poke the thread just in case */
|
||||||
@@ -167,7 +171,8 @@ static void bridge_stop(struct ast_bridge *bridge)
|
|||||||
ao2_lock(bridge);
|
ao2_lock(bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Helper function to add a channel to the bridge array
|
/*!
|
||||||
|
* \brief Helper function to add a channel to the bridge array
|
||||||
*
|
*
|
||||||
* \note This function assumes the bridge is locked.
|
* \note This function assumes the bridge is locked.
|
||||||
*/
|
*/
|
||||||
@@ -181,17 +186,21 @@ static void bridge_array_add(struct ast_bridge *bridge, struct ast_channel *chan
|
|||||||
|
|
||||||
bridge->array[bridge->array_num++] = chan;
|
bridge->array[bridge->array_num++] = chan;
|
||||||
|
|
||||||
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);
|
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);
|
||||||
|
|
||||||
/* If the next addition of a channel will exceed our array size grow it out */
|
/* If the next addition of a channel will exceed our array size grow it out */
|
||||||
if (bridge->array_num == bridge->array_size) {
|
if (bridge->array_num == bridge->array_size) {
|
||||||
struct ast_channel **tmp;
|
struct ast_channel **new_array;
|
||||||
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);
|
|
||||||
if (!(tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel *)))) {
|
ast_debug(1, "Growing bridge array on %p from %d to %d\n",
|
||||||
ast_log(LOG_ERROR, "Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge);
|
bridge, (int) bridge->array_size, (int) bridge->array_size + BRIDGE_ARRAY_GROW);
|
||||||
|
new_array = ast_realloc(bridge->array,
|
||||||
|
(bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(*bridge->array));
|
||||||
|
if (!new_array) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bridge->array = tmp;
|
bridge->array = new_array;
|
||||||
bridge->array_size += BRIDGE_ARRAY_GROW;
|
bridge->array_size += BRIDGE_ARRAY_GROW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -268,7 +277,10 @@ static void bridge_force_out_all(struct ast_bridge *bridge)
|
|||||||
/*! \brief Internal function to see whether a bridge should dissolve, and if so do it */
|
/*! \brief Internal function to see whether a bridge should dissolve, and if so do it */
|
||||||
static void bridge_check_dissolve(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
static void bridge_check_dissolve(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
|
||||||
{
|
{
|
||||||
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))) {
|
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))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +355,8 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel
|
|||||||
/* Signal the thread that is handling the bridged channel that it should be ended */
|
/* Signal the thread that is handling the bridged channel that it should be ended */
|
||||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||||
} else if (frame->frametype == AST_FRAME_CONTROL && bridge_drop_control_frame(frame->subclass.integer)) {
|
} else if (frame->frametype == AST_FRAME_CONTROL && bridge_drop_control_frame(frame->subclass.integer)) {
|
||||||
ast_debug(1, "Dropping control frame from bridge channel %p\n", bridge_channel);
|
ast_debug(1, "Dropping control frame %d from bridge channel %p\n",
|
||||||
|
frame->subclass.integer, bridge_channel);
|
||||||
} else if (frame->frametype == AST_FRAME_DTMF_BEGIN || frame->frametype == AST_FRAME_DTMF_END) {
|
} else if (frame->frametype == AST_FRAME_DTMF_BEGIN || frame->frametype == AST_FRAME_DTMF_END) {
|
||||||
int dtmf_passthrough = bridge_channel->features ?
|
int dtmf_passthrough = bridge_channel->features ?
|
||||||
bridge_channel->features->dtmf_passthrough :
|
bridge_channel->features->dtmf_passthrough :
|
||||||
@@ -384,7 +397,7 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel
|
|||||||
static int generic_thread_loop(struct ast_bridge *bridge)
|
static int generic_thread_loop(struct ast_bridge *bridge)
|
||||||
{
|
{
|
||||||
while (!bridge->stop && !bridge->refresh && bridge->array_num) {
|
while (!bridge->stop && !bridge->refresh && bridge->array_num) {
|
||||||
struct ast_channel *winner = NULL;
|
struct ast_channel *winner;
|
||||||
int to = -1;
|
int to = -1;
|
||||||
|
|
||||||
/* Move channels around for priority reasons if we have more than one channel in our array */
|
/* Move channels around for priority reasons if we have more than one channel in our array */
|
||||||
@@ -397,7 +410,7 @@ static int generic_thread_loop(struct ast_bridge *bridge)
|
|||||||
/* Wait on the channels */
|
/* Wait on the channels */
|
||||||
bridge->waiting = 1;
|
bridge->waiting = 1;
|
||||||
ao2_unlock(bridge);
|
ao2_unlock(bridge);
|
||||||
winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to);
|
winner = ast_waitfor_n(bridge->array, (int) bridge->array_num, &to);
|
||||||
bridge->waiting = 0;
|
bridge->waiting = 0;
|
||||||
ao2_lock(bridge);
|
ao2_lock(bridge);
|
||||||
|
|
||||||
@@ -431,7 +444,10 @@ static void *bridge_thread(void *data)
|
|||||||
bridge->technology->thread ? bridge->technology->thread : generic_thread_loop,
|
bridge->technology->thread ? bridge->technology->thread : generic_thread_loop,
|
||||||
bridge);
|
bridge);
|
||||||
|
|
||||||
/* Execute the appropriate thread function. If the technology does not provide one we use the generic one */
|
/*
|
||||||
|
* Execute the appropriate thread function. If the technology
|
||||||
|
* does not provide one we use the generic one.
|
||||||
|
*/
|
||||||
res = bridge->technology->thread
|
res = bridge->technology->thread
|
||||||
? bridge->technology->thread(bridge)
|
? bridge->technology->thread(bridge)
|
||||||
: generic_thread_loop(bridge);
|
: generic_thread_loop(bridge);
|
||||||
@@ -494,7 +510,8 @@ static void destroy_bridge(void *obj)
|
|||||||
if (bridge->technology->destroy) {
|
if (bridge->technology->destroy) {
|
||||||
ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge);
|
ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge);
|
||||||
if (bridge->technology->destroy(bridge)) {
|
if (bridge->technology->destroy(bridge)) {
|
||||||
ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->technology->name, bridge);
|
ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... some memory may have leaked\n",
|
||||||
|
bridge->technology->name, bridge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,8 +529,8 @@ static void destroy_bridge(void *obj)
|
|||||||
|
|
||||||
struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags)
|
struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags)
|
||||||
{
|
{
|
||||||
struct ast_bridge *bridge = NULL;
|
struct ast_bridge *bridge;
|
||||||
struct ast_bridge_technology *bridge_technology = NULL;
|
struct ast_bridge_technology *bridge_technology;
|
||||||
|
|
||||||
/* If we need to be a smart bridge see if we can move between 1to1 and multimix bridges */
|
/* If we need to be a smart bridge see if we can move between 1to1 and multimix bridges */
|
||||||
if (flags & AST_BRIDGE_FLAG_SMART) {
|
if (flags & AST_BRIDGE_FLAG_SMART) {
|
||||||
@@ -526,8 +543,11 @@ struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags)
|
|||||||
ast_bridge_destroy(other_bridge);
|
ast_bridge_destroy(other_bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If capabilities were provided use our helper function to find the "best" bridge technology, otherwise we can
|
/*
|
||||||
* just look for the most basic capability needed, single 1to1 mixing. */
|
* If capabilities were provided use our helper function to find
|
||||||
|
* the "best" bridge technology, otherwise we can just look for
|
||||||
|
* the most basic capability needed, single 1to1 mixing.
|
||||||
|
*/
|
||||||
bridge_technology = capabilities
|
bridge_technology = capabilities
|
||||||
? find_best_technology(capabilities)
|
? find_best_technology(capabilities)
|
||||||
: find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX);
|
: find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX);
|
||||||
@@ -557,7 +577,7 @@ struct ast_bridge *ast_bridge_new(uint32_t capabilities, int flags)
|
|||||||
if (bridge->technology->create(bridge)) {
|
if (bridge->technology->create(bridge)) {
|
||||||
ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", bridge->technology->name, bridge);
|
ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", bridge->technology->name, bridge);
|
||||||
ao2_ref(bridge, -1);
|
ao2_ref(bridge, -1);
|
||||||
bridge = NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,23 +677,26 @@ static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_c
|
|||||||
static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int count)
|
static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int count)
|
||||||
{
|
{
|
||||||
uint32_t new_capabilities = 0;
|
uint32_t new_capabilities = 0;
|
||||||
struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology;
|
struct ast_bridge_technology *new_technology;
|
||||||
|
struct ast_bridge_technology *old_technology = bridge->technology;
|
||||||
struct ast_bridge temp_bridge = {
|
struct ast_bridge temp_bridge = {
|
||||||
.technology = bridge->technology,
|
.technology = bridge->technology,
|
||||||
.bridge_pvt = bridge->bridge_pvt,
|
.bridge_pvt = bridge->bridge_pvt,
|
||||||
};
|
};
|
||||||
struct ast_bridge_channel *bridge_channel2 = NULL;
|
struct ast_bridge_channel *bridge_channel2;
|
||||||
|
|
||||||
/* Based on current feature determine whether we want to change bridge technologies or not */
|
/* Based on current feature determine whether we want to change bridge technologies or not */
|
||||||
if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
|
if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
|
||||||
if (count <= 2) {
|
if (count <= 2) {
|
||||||
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);
|
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);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
|
new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
|
||||||
} else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
|
} else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
|
||||||
if (count > 2) {
|
if (count > 2) {
|
||||||
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);
|
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);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
|
new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
|
||||||
@@ -689,11 +712,17 @@ static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_c
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
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);
|
||||||
|
|
||||||
/* If a thread is currently executing for the current technology tell it to stop */
|
/* If a thread is currently executing for the current technology tell it to stop */
|
||||||
if (bridge->thread != AST_PTHREADT_NULL) {
|
if (bridge->thread != AST_PTHREADT_NULL) {
|
||||||
/* 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. */
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
|
if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
|
||||||
ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
|
ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
|
||||||
bridge->refresh = 1;
|
bridge->refresh = 1;
|
||||||
@@ -704,15 +733,22 @@ static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 */
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
bridge->bridge_pvt = NULL;
|
bridge->bridge_pvt = NULL;
|
||||||
bridge->technology = new_technology;
|
bridge->technology = new_technology;
|
||||||
|
|
||||||
/* Pass the bridge to the new bridge technology so it can set it up */
|
/* Pass the bridge to the new bridge technology so it can set it up */
|
||||||
if (new_technology->create) {
|
if (new_technology->create) {
|
||||||
ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge);
|
ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n",
|
||||||
|
new_technology->name, bridge);
|
||||||
if (new_technology->create(bridge)) {
|
if (new_technology->create(bridge)) {
|
||||||
ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge);
|
ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n",
|
||||||
|
new_technology->name, bridge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,9 +761,11 @@ static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_c
|
|||||||
|
|
||||||
/* First we part them from the old technology */
|
/* First we part them from the old technology */
|
||||||
if (old_technology->leave) {
|
if (old_technology->leave) {
|
||||||
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);
|
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);
|
||||||
if (old_technology->leave(&temp_bridge, bridge_channel2)) {
|
if (old_technology->leave(&temp_bridge, bridge_channel2)) {
|
||||||
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);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,9 +774,11 @@ static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_c
|
|||||||
|
|
||||||
/* Third we join them to the new technology */
|
/* Third we join them to the new technology */
|
||||||
if (new_technology->join) {
|
if (new_technology->join) {
|
||||||
ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge);
|
ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n",
|
||||||
|
new_technology->name, bridge_channel2, bridge);
|
||||||
if (new_technology->join(bridge, bridge_channel2)) {
|
if (new_technology->join(bridge, bridge_channel2)) {
|
||||||
ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge);
|
ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n",
|
||||||
|
new_technology->name, bridge_channel2, bridge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,9 +791,11 @@ static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_c
|
|||||||
|
|
||||||
/* 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 */
|
/* 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 */
|
||||||
if (old_technology->destroy) {
|
if (old_technology->destroy) {
|
||||||
ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge);
|
ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n",
|
||||||
|
old_technology->name, &temp_bridge, bridge);
|
||||||
if (old_technology->destroy(&temp_bridge)) {
|
if (old_technology->destroy(&temp_bridge)) {
|
||||||
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);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,9 +949,12 @@ static void bridge_channel_feature(struct ast_bridge *bridge, struct ast_bridge_
|
|||||||
/* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */
|
/* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */
|
||||||
if (hook) {
|
if (hook) {
|
||||||
hook->callback(bridge, bridge_channel, hook->hook_pvt);
|
hook->callback(bridge, bridge_channel, hook->hook_pvt);
|
||||||
/* If we are handing the channel off to an external hook for ownership,
|
/*
|
||||||
* we are not guaranteed what kind of state it will come back in. If
|
* If we are handing the channel off to an external hook for
|
||||||
* the channel hungup, we need to detect that here. */
|
* ownership, we are not guaranteed what kind of state it will
|
||||||
|
* come back in. If the channel hungup, we need to detect that
|
||||||
|
* here if the hook did not already change the state.
|
||||||
|
*/
|
||||||
if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
|
if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
|
||||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||||
}
|
}
|
||||||
@@ -1000,7 +1045,8 @@ static enum ast_bridge_channel_state bridge_channel_join(struct ast_bridge_chann
|
|||||||
/* Update bridge pointer on channel */
|
/* Update bridge pointer on channel */
|
||||||
ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
|
ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
|
||||||
/* If the technology requires a thread and one is not running, start it up */
|
/* If the technology requires a thread and one is not running, start it up */
|
||||||
if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
|
if (bridge_channel->bridge->thread == AST_PTHREADT_NULL
|
||||||
|
&& (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
|
||||||
bridge_channel->bridge->stop = 0;
|
bridge_channel->bridge->stop = 0;
|
||||||
ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
|
ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
|
||||||
ao2_ref(bridge_channel->bridge, +1);
|
ao2_ref(bridge_channel->bridge, +1);
|
||||||
|
Reference in New Issue
Block a user