improve bridge code
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1251 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
a8e506e6f1
commit
ba6b7651b2
|
@ -253,6 +253,13 @@ SWITCH_DECLARE(switch_status) switch_channel_pre_answer(switch_channel *channel)
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel *channel, const switch_state_handler_table *state_handler);
|
SWITCH_DECLARE(int) switch_channel_add_state_handler(switch_channel *channel, const switch_state_handler_table *state_handler);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief clear a state handler table from a given channel
|
||||||
|
\param channel channel from which to clear the state handler table
|
||||||
|
\param state_handler table of state handler functions
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel *channel, const switch_state_handler_table *state_handler);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Retrieve an state handler tablefrom a given channel at given index level
|
\brief Retrieve an state handler tablefrom a given channel at given index level
|
||||||
\param channel channel from which to retrieve the state handler table
|
\param channel channel from which to retrieve the state handler table
|
||||||
|
|
|
@ -324,6 +324,7 @@ CF_EARLY_MEDIA = (1 << 2) - Channel is ready for audio before answer
|
||||||
CF_ORIGINATOR = (1 << 3) - Channel is an originator
|
CF_ORIGINATOR = (1 << 3) - Channel is an originator
|
||||||
CF_TRANSFER = (1 << 4) - Channel is being transfered
|
CF_TRANSFER = (1 << 4) - Channel is being transfered
|
||||||
CF_ACCEPT_CNG = (1 << 5) - Channel will accept CNG frames
|
CF_ACCEPT_CNG = (1 << 5) - Channel will accept CNG frames
|
||||||
|
CF_LOCK_THREAD = (1 << 6) - Prevent the channel thread from exiting while this flag is set
|
||||||
</pre>
|
</pre>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -333,7 +334,8 @@ typedef enum {
|
||||||
CF_EARLY_MEDIA = (1 << 2),
|
CF_EARLY_MEDIA = (1 << 2),
|
||||||
CF_ORIGINATOR = (1 << 3),
|
CF_ORIGINATOR = (1 << 3),
|
||||||
CF_TRANSFER = (1 << 4),
|
CF_TRANSFER = (1 << 4),
|
||||||
CF_ACCEPT_CNG = (1 << 5)
|
CF_ACCEPT_CNG = (1 << 5),
|
||||||
|
CF_LOCK_THREAD = (1 << 6)
|
||||||
} switch_channel_flag;
|
} switch_channel_flag;
|
||||||
|
|
||||||
|
|
||||||
|
@ -357,11 +359,14 @@ typedef enum {
|
||||||
\brief Signals to send to channels
|
\brief Signals to send to channels
|
||||||
<pre>
|
<pre>
|
||||||
SWITCH_SIG_KILL - Kill the channel
|
SWITCH_SIG_KILL - Kill the channel
|
||||||
|
SWITCH_SIG_XFER - Stop the current io but leave it viable
|
||||||
</pre>
|
</pre>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SWITCH_SIG_KILL
|
SWITCH_SIG_NONE,
|
||||||
|
SWITCH_SIG_KILL,
|
||||||
|
SWITCH_SIG_XFER
|
||||||
} switch_signal;
|
} switch_signal;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -645,6 +645,26 @@ SWITCH_DECLARE(const switch_state_handler_table *) switch_channel_get_state_hand
|
||||||
return channel->state_handlers[index];
|
return channel->state_handlers[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(void) switch_channel_clear_state_handler(switch_channel *channel, const switch_state_handler_table *state_handler)
|
||||||
|
{
|
||||||
|
int index, i = 0;
|
||||||
|
const switch_state_handler_table *new_handlers[SWITCH_MAX_STATE_HANDLERS] = {0};
|
||||||
|
|
||||||
|
assert(channel != NULL);
|
||||||
|
|
||||||
|
|
||||||
|
for (index = 0; index < channel->state_handler_index; index++) {
|
||||||
|
if (channel->state_handlers[index] != state_handler) {
|
||||||
|
new_handlers[i++] = channel->state_handlers[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(channel->state_handlers, 0, sizeof(channel->state_handlers));
|
||||||
|
for (index = 0; index < i; index++) {
|
||||||
|
channel->state_handlers[index] = new_handlers[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel *channel,
|
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel *channel,
|
||||||
switch_caller_extension *caller_extension)
|
switch_caller_extension *caller_extension)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2197,6 +2197,13 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread *thread
|
||||||
|
|
||||||
switch_core_hash_insert(runtime.session_table, session->uuid_str, session);
|
switch_core_hash_insert(runtime.session_table, session->uuid_str, session);
|
||||||
switch_core_session_run(session);
|
switch_core_session_run(session);
|
||||||
|
|
||||||
|
if (switch_channel_test_flag(session->channel, CF_LOCK_THREAD)) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %u (%s) Locked\n", session->id, switch_channel_get_name(session->channel));
|
||||||
|
while(switch_channel_test_flag(session->channel, CF_LOCK_THREAD)) {
|
||||||
|
switch_yield(10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
switch_core_hash_delete(runtime.session_table, session->uuid_str);
|
switch_core_hash_delete(runtime.session_table, session->uuid_str);
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Session %u (%s) Ended\n", session->id, switch_channel_get_name(session->channel));
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Session %u (%s) Ended\n", session->id, switch_channel_get_name(session->channel));
|
||||||
switch_core_session_destroy(&session);
|
switch_core_session_destroy(&session);
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include <switch_ivr.h>
|
#include <switch_ivr.h>
|
||||||
|
|
||||||
|
static const switch_state_handler_table audio_bridge_peer_state_handlers;
|
||||||
|
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_callback(switch_core_session *session,
|
SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_callback(switch_core_session *session,
|
||||||
switch_dtmf_callback_function dtmf_callback,
|
switch_dtmf_callback_function dtmf_callback,
|
||||||
|
@ -779,15 +781,18 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj)
|
||||||
|
|
||||||
data->running = 0;
|
data->running = 0;
|
||||||
|
|
||||||
if (his_thread->running > 0 && switch_channel_test_flag(chan_a, CF_ORIGINATOR)) {
|
if (switch_channel_test_flag(chan_a, CF_ORIGINATOR)) {
|
||||||
if (!switch_channel_test_flag(chan_b, CF_TRANSFER)) {
|
if (switch_channel_test_flag(chan_b, CF_TRANSFER)) {
|
||||||
|
if (switch_channel_get_state(chan_b) < CS_HANGUP) {
|
||||||
|
switch_channel_set_state(chan_b, CS_RING);
|
||||||
|
/* TBD we need to teach all the endpoints to honor this still */
|
||||||
|
switch_core_session_kill_channel(session_b, SWITCH_SIG_XFER);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
switch_core_session_kill_channel(session_b, SWITCH_SIG_KILL);
|
switch_core_session_kill_channel(session_b, SWITCH_SIG_KILL);
|
||||||
switch_channel_hangup(chan_b, SWITCH_CAUSE_NORMAL_CLEARING);
|
switch_channel_hangup(chan_b, SWITCH_CAUSE_NORMAL_CLEARING);
|
||||||
}
|
}
|
||||||
switch_channel_clear_flag(chan_a, CF_ORIGINATOR);
|
switch_channel_clear_flag(chan_a, CF_ORIGINATOR);
|
||||||
} else if (!switch_channel_test_flag(chan_a, CF_ORIGINATOR) && !switch_channel_test_flag(chan_a, CF_TRANSFER)) {
|
|
||||||
switch_core_session_kill_channel(session_a, SWITCH_SIG_KILL);
|
|
||||||
switch_channel_hangup(chan_a, SWITCH_CAUSE_NORMAL_CLEARING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (his_thread->running > 0) {
|
while (his_thread->running > 0) {
|
||||||
|
@ -799,10 +804,26 @@ static void *audio_bridge_thread(switch_thread *thread, void *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
data->running = 0;
|
data->running = 0;
|
||||||
switch_sleep(1000000);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static switch_status audio_bridge_on_transmit(switch_core_session *session)
|
||||||
|
{
|
||||||
|
switch_channel *channel = NULL;
|
||||||
|
void *arg;
|
||||||
|
|
||||||
|
channel = switch_core_session_get_channel(session);
|
||||||
|
assert(channel != NULL);
|
||||||
|
|
||||||
|
arg = switch_channel_get_private(channel);
|
||||||
|
audio_bridge_thread(NULL, (void *) arg);
|
||||||
|
switch_channel_set_private(channel, NULL);
|
||||||
|
switch_channel_clear_state_handler(channel, &audio_bridge_peer_state_handlers);
|
||||||
|
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static switch_status audio_bridge_on_ring(switch_core_session *session)
|
static switch_status audio_bridge_on_ring(switch_core_session *session)
|
||||||
{
|
{
|
||||||
switch_channel *channel = NULL;
|
switch_channel *channel = NULL;
|
||||||
|
@ -814,7 +835,7 @@ static switch_status audio_bridge_on_ring(switch_core_session *session)
|
||||||
|
|
||||||
/* put the channel in a passive state so we can loop audio to it */
|
/* put the channel in a passive state so we can loop audio to it */
|
||||||
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
|
||||||
switch_channel_set_state(channel, CS_TRANSMIT);
|
//switch_channel_set_state(channel, CS_TRANSMIT);
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -828,7 +849,7 @@ static const switch_state_handler_table audio_bridge_peer_state_handlers = {
|
||||||
/*.on_execute */ NULL,
|
/*.on_execute */ NULL,
|
||||||
/*.on_hangup */ NULL,
|
/*.on_hangup */ NULL,
|
||||||
/*.on_loopback */ NULL,
|
/*.on_loopback */ NULL,
|
||||||
/*.on_transmit */ NULL
|
/*.on_transmit */ audio_bridge_on_transmit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -876,12 +897,10 @@ SWITCH_DECLARE(switch_status) switch_ivr_multi_threaded_bridge(switch_core_sessi
|
||||||
this_audio_thread.objs[5] = &other_audio_thread;
|
this_audio_thread.objs[5] = &other_audio_thread;
|
||||||
this_audio_thread.running = 2;
|
this_audio_thread.running = 2;
|
||||||
|
|
||||||
|
|
||||||
switch_channel_set_private(caller_channel, peer_session);
|
|
||||||
switch_channel_set_private(peer_channel, session);
|
|
||||||
switch_channel_add_state_handler(peer_channel, &audio_bridge_peer_state_handlers);
|
switch_channel_add_state_handler(peer_channel, &audio_bridge_peer_state_handlers);
|
||||||
|
|
||||||
if (switch_core_session_runing(peer_session)) {
|
if (switch_core_session_runing(peer_session)) {
|
||||||
switch_channel_set_state(peer_channel, CS_TRANSMIT);
|
switch_channel_set_state(peer_channel, CS_RING);
|
||||||
} else {
|
} else {
|
||||||
switch_core_session_thread_launch(peer_session);
|
switch_core_session_thread_launch(peer_session);
|
||||||
}
|
}
|
||||||
|
@ -890,7 +909,7 @@ SWITCH_DECLARE(switch_status) switch_ivr_multi_threaded_bridge(switch_core_sessi
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int state = switch_channel_get_state(peer_channel);
|
int state = switch_channel_get_state(peer_channel);
|
||||||
if (state > CS_RING) {
|
if (state >= CS_RING) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -952,14 +971,16 @@ SWITCH_DECLARE(switch_status) switch_ivr_multi_threaded_bridge(switch_core_sessi
|
||||||
msg.pointer_arg = peer_session;
|
msg.pointer_arg = peer_session;
|
||||||
switch_core_session_receive_message(session, &msg);
|
switch_core_session_receive_message(session, &msg);
|
||||||
|
|
||||||
|
switch_channel_set_flag(peer_channel, CF_LOCK_THREAD);
|
||||||
switch_core_session_launch_thread(peer_session, audio_bridge_thread, (void *) &other_audio_thread);
|
switch_channel_set_private(peer_channel, &other_audio_thread);
|
||||||
|
switch_channel_set_state(peer_channel, CS_TRANSMIT);
|
||||||
audio_bridge_thread(NULL, (void *) &this_audio_thread);
|
audio_bridge_thread(NULL, (void *) &this_audio_thread);
|
||||||
|
|
||||||
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
|
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) {
|
||||||
switch_channel_event_set_data(caller_channel, event);
|
switch_channel_event_set_data(caller_channel, event);
|
||||||
switch_event_fire(&event);
|
switch_event_fire(&event);
|
||||||
}
|
}
|
||||||
|
switch_channel_clear_flag(peer_channel, CF_LOCK_THREAD);
|
||||||
}
|
}
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue