2007-03-29 22:34:40 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2012-04-18 16:51:48 +00:00
* Copyright ( C ) 2005 - 2012 , Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
2009-02-04 21:20:54 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-03-29 22:34:40 +00:00
*
* switch_ivr_bridge . c - - IVR Library
*
*/
2008-01-27 17:36:53 +00:00
2007-03-29 22:34:40 +00:00
# include <switch.h>
2010-01-23 18:35:05 +00:00
# define DEFAULT_LEAD_FRAMES 10
2007-03-29 22:34:40 +00:00
static const switch_state_handler_table_t audio_bridge_peer_state_handlers ;
2010-01-22 00:51:32 +00:00
static void cleanup_proxy_mode_a ( switch_core_session_t * session ) ;
static void cleanup_proxy_mode_b ( switch_core_session_t * session ) ;
2007-03-29 22:34:40 +00:00
/* Bridge Related Stuff*/
/*********************************************************************************/
2008-02-01 21:22:27 +00:00
2008-02-05 21:09:52 +00:00
# ifdef SWITCH_VIDEO_IN_THREADS
2008-02-01 21:22:27 +00:00
struct vid_helper {
switch_core_session_t * session_a ;
switch_core_session_t * session_b ;
int up ;
} ;
static void * SWITCH_THREAD_FUNC video_bridge_thread ( switch_thread_t * thread , void * obj )
{
struct vid_helper * vh = obj ;
switch_channel_t * channel = switch_core_session_get_channel ( vh - > session_a ) ;
2009-11-19 18:22:05 +00:00
switch_channel_t * b_channel = switch_core_session_get_channel ( vh - > session_b ) ;
2008-02-01 21:22:27 +00:00
switch_status_t status ;
switch_frame_t * read_frame ;
2008-05-27 04:30:03 +00:00
vh - > up = 1 ;
2009-11-19 18:22:05 +00:00
while ( switch_channel_ready ( channel ) & & switch_channel_ready ( b_channel ) & & vh - > up = = 1 ) {
2008-05-08 19:19:47 +00:00
status = switch_core_session_read_video_frame ( vh - > session_a , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2008-02-01 21:22:27 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
}
2008-05-27 04:30:03 +00:00
2009-11-18 19:22:45 +00:00
if ( ! switch_test_flag ( read_frame , SFF_CNG ) ) {
if ( switch_core_session_write_video_frame ( vh - > session_b , read_frame , SWITCH_IO_FLAG_NONE , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
}
2008-05-27 04:30:03 +00:00
2008-02-01 21:22:27 +00:00
}
2009-11-18 19:22:45 +00:00
2010-02-06 03:38:24 +00:00
switch_core_session_kill_channel ( vh - > session_b , SWITCH_SIG_BREAK ) ;
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( vh - > session_a ) , SWITCH_LOG_DEBUG , " %s video thread ended. \n " , switch_channel_get_name ( channel ) ) ;
2009-11-19 18:22:05 +00:00
2008-02-01 21:22:27 +00:00
vh - > up = 0 ;
return NULL ;
}
2009-11-18 19:22:45 +00:00
static switch_thread_t * launch_video ( struct vid_helper * vh )
2008-02-01 21:22:27 +00:00
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
2008-05-27 04:30:03 +00:00
switch_threadattr_create ( & thd_attr , switch_core_session_get_pool ( vh - > session_a ) ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , thd_attr , video_bridge_thread , vh , switch_core_session_get_pool ( vh - > session_a ) ) ;
2009-11-18 19:22:45 +00:00
return thread ;
2008-02-01 21:22:27 +00:00
}
2008-02-05 21:09:52 +00:00
# endif
2008-02-01 21:22:27 +00:00
2009-10-07 22:35:21 +00:00
2010-02-06 03:38:24 +00:00
static void send_display ( switch_core_session_t * session , switch_core_session_t * peer_session )
{
2009-10-07 22:35:21 +00:00
2009-10-13 20:35:13 +00:00
switch_core_session_message_t * msg ;
2009-10-07 22:35:21 +00:00
switch_caller_profile_t * caller_profile ;
switch_channel_t * caller_channel ;
2009-10-19 19:58:23 +00:00
const char * name , * number , * p ;
2009-10-07 22:35:21 +00:00
caller_channel = switch_core_session_get_channel ( session ) ;
caller_profile = switch_channel_get_caller_profile ( caller_channel ) ;
2010-07-08 06:22:38 +00:00
2010-12-16 15:45:43 +00:00
if ( switch_channel_direction ( caller_channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND & & ! switch_channel_test_flag ( caller_channel , CF_DIALPLAN ) ) {
2009-10-07 22:35:21 +00:00
name = caller_profile - > callee_id_name ;
number = caller_profile - > callee_id_number ;
2010-02-06 03:38:24 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( name ) ) {
2009-10-07 22:35:21 +00:00
name = caller_profile - > destination_number ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( number ) ) {
2009-10-07 22:35:21 +00:00
number = caller_profile - > destination_number ;
}
} else {
name = caller_profile - > caller_id_name ;
number = caller_profile - > caller_id_number ;
2010-02-06 03:38:24 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( name ) ) {
2009-10-07 22:35:21 +00:00
name = caller_profile - > destination_number ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( number ) ) {
2009-10-07 22:35:21 +00:00
number = caller_profile - > destination_number ;
}
}
2009-10-19 19:58:23 +00:00
if ( ( p = strrchr ( number , ' / ' ) ) ) {
2010-02-06 03:38:24 +00:00
number = p + 1 ;
2009-10-19 19:58:23 +00:00
}
if ( ( p = strrchr ( name , ' / ' ) ) ) {
2010-02-06 03:38:24 +00:00
name = p + 1 ;
2009-10-19 19:58:23 +00:00
}
2009-10-13 20:35:13 +00:00
msg = switch_core_session_alloc ( peer_session , sizeof ( * msg ) ) ;
MESSAGE_STAMP_FFL ( msg ) ;
msg - > message_id = SWITCH_MESSAGE_INDICATE_DISPLAY ;
msg - > string_array_arg [ 0 ] = switch_core_session_strdup ( peer_session , name ) ;
msg - > string_array_arg [ 1 ] = switch_core_session_strdup ( peer_session , number ) ;
msg - > from = __FILE__ ;
switch_core_session_queue_message ( peer_session , msg ) ;
2009-10-07 22:35:21 +00:00
}
SWITCH_DECLARE ( void ) switch_ivr_bridge_display ( switch_core_session_t * session , switch_core_session_t * peer_session )
{
send_display ( session , peer_session ) ;
send_display ( peer_session , session ) ;
}
2007-04-13 22:15:58 +00:00
struct switch_ivr_bridge_data {
switch_core_session_t * session ;
2007-05-03 19:16:54 +00:00
char b_uuid [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
2007-04-13 22:15:58 +00:00
int stream_id ;
switch_input_callback_function_t input_callback ;
void * session_data ;
2008-10-11 16:37:15 +00:00
int clean_exit ;
2007-03-29 22:34:40 +00:00
} ;
2007-04-13 22:15:58 +00:00
typedef struct switch_ivr_bridge_data switch_ivr_bridge_data_t ;
2008-05-27 04:30:03 +00:00
static void * audio_bridge_thread ( switch_thread_t * thread , void * obj )
2007-03-29 22:34:40 +00:00
{
2007-04-13 22:15:58 +00:00
switch_ivr_bridge_data_t * data = obj ;
2007-03-29 22:34:40 +00:00
int stream_id = 0 , pre_b = 0 , ans_a = 0 , ans_b = 0 , originator = 0 ;
switch_input_callback_function_t input_callback ;
2009-10-13 20:59:50 +00:00
switch_core_session_message_t msg = { 0 } ;
2007-03-29 22:34:40 +00:00
void * user_data ;
switch_channel_t * chan_a , * chan_b ;
switch_frame_t * read_frame ;
switch_core_session_t * session_a , * session_b ;
2010-11-29 19:00:19 +00:00
uint32_t read_frame_count = 0 ;
2007-11-01 11:28:26 +00:00
const char * app_name = NULL , * app_arg = NULL ;
2008-03-13 01:08:42 +00:00
const char * hook_var = NULL ;
2008-05-27 04:30:03 +00:00
int inner_bridge = 0 ;
2008-09-12 16:38:43 +00:00
switch_codec_t silence_codec = { 0 } ;
switch_frame_t silence_frame = { 0 } ;
2010-02-06 03:38:24 +00:00
int16_t silence_data [ SWITCH_RECOMMENDED_BUFFER_SIZE / 2 ] = { 0 } ;
2009-11-09 23:49:35 +00:00
const char * silence_var ;
2008-09-18 21:50:18 +00:00
int silence_val = 0 , bypass_media_after_bridge = 0 ;
2009-10-02 21:23:52 +00:00
const char * bridge_answer_timeout = NULL ;
2009-10-14 19:26:10 +00:00
int answer_timeout , sent_update = 0 ;
2009-10-02 21:23:52 +00:00
time_t answer_limit = 0 ;
2010-11-29 19:00:19 +00:00
const char * exec_app = NULL ;
const char * exec_data = NULL ;
2010-02-06 03:38:24 +00:00
2008-02-05 21:09:52 +00:00
# ifdef SWITCH_VIDEO_IN_THREADS
2009-11-18 19:22:45 +00:00
switch_thread_t * vid_thread = NULL ;
2008-05-27 04:30:03 +00:00
struct vid_helper vh = { 0 } ;
2008-02-05 21:09:52 +00:00
uint32_t vid_launch = 0 ;
# endif
2008-10-11 16:37:15 +00:00
data - > clean_exit = 0 ;
2007-03-29 22:34:40 +00:00
2007-04-13 22:15:58 +00:00
session_a = data - > session ;
if ( ! ( session_b = switch_core_session_locate ( data - > b_uuid ) ) ) {
return NULL ;
2007-03-29 22:34:40 +00:00
}
2010-02-06 03:38:24 +00:00
2007-04-13 22:15:58 +00:00
input_callback = data - > input_callback ;
user_data = data - > session_data ;
stream_id = data - > stream_id ;
2007-03-29 22:34:40 +00:00
chan_a = switch_core_session_get_channel ( session_a ) ;
chan_b = switch_core_session_get_channel ( session_b ) ;
2011-04-28 18:46:39 +00:00
switch_channel_set_bridge_time ( chan_a ) ;
2010-11-29 19:00:19 +00:00
if ( ( exec_app = switch_channel_get_variable ( chan_a , " bridge_pre_execute_app " ) ) ) {
exec_data = switch_channel_get_variable ( chan_a , " bridge_pre_execute_data " ) ;
}
2009-11-09 23:49:35 +00:00
bypass_media_after_bridge = switch_channel_test_flag ( chan_a , CF_BYPASS_MEDIA_AFTER_BRIDGE ) ;
switch_channel_clear_flag ( chan_a , CF_BYPASS_MEDIA_AFTER_BRIDGE ) ;
2007-03-29 22:34:40 +00:00
ans_a = switch_channel_test_flag ( chan_a , CF_ANSWERED ) ;
2009-10-14 19:26:10 +00:00
2009-10-07 04:30:19 +00:00
if ( ( originator = switch_channel_test_flag ( chan_a , CF_BRIDGE_ORIGINATOR ) ) ) {
2007-03-29 22:34:40 +00:00
pre_b = switch_channel_test_flag ( chan_a , CF_EARLY_MEDIA ) ;
ans_b = switch_channel_test_flag ( chan_b , CF_ANSWERED ) ;
}
2008-05-20 15:40:27 +00:00
inner_bridge = switch_channel_test_flag ( chan_a , CF_INNER_BRIDGE ) ;
2010-11-29 19:00:19 +00:00
2009-10-02 21:23:52 +00:00
if ( ! switch_channel_test_flag ( chan_a , CF_ANSWERED ) & & ( bridge_answer_timeout = switch_channel_get_variable ( chan_a , " bridge_answer_timeout " ) ) ) {
if ( ( answer_timeout = atoi ( bridge_answer_timeout ) ) < 0 ) {
answer_timeout = 0 ;
} else {
answer_limit = switch_epoch_time_now ( NULL ) + answer_timeout ;
}
}
2010-02-06 03:38:24 +00:00
2012-05-11 03:34:37 +00:00
switch_channel_clear_flag ( chan_a , CF_INTERCEPT ) ;
switch_channel_clear_flag ( chan_a , CF_INTERCEPTED ) ;
2008-05-20 15:40:27 +00:00
switch_channel_set_flag ( chan_a , CF_BRIDGED ) ;
2008-09-09 16:31:53 +00:00
switch_channel_wait_for_flag ( chan_b , CF_BRIDGED , SWITCH_TRUE , 10000 , chan_a ) ;
if ( ! switch_channel_test_flag ( chan_b , CF_BRIDGED ) ) {
2010-02-06 03:38:24 +00:00
if ( ! ( switch_channel_test_flag ( chan_b , CF_TRANSFER ) | | switch_channel_test_flag ( chan_b , CF_REDIRECT )
2008-11-21 00:09:11 +00:00
| | switch_channel_get_state ( chan_b ) = = CS_RESET ) ) {
2008-09-25 14:25:59 +00:00
switch_channel_hangup ( chan_b , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2008-09-09 16:31:53 +00:00
goto end_of_bridge_loop ;
}
2009-11-09 23:49:35 +00:00
if ( bypass_media_after_bridge ) {
2009-10-22 16:09:46 +00:00
if ( switch_stristr ( " loopback " , switch_channel_get_name ( chan_a ) ) | | switch_stristr ( " loopback " , switch_channel_get_name ( chan_b ) ) ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_WARNING , " Cannot bypass media while bridged to a loopback address. \n " ) ;
2009-11-09 23:49:35 +00:00
bypass_media_after_bridge = 0 ;
2009-10-22 16:09:46 +00:00
}
2008-09-18 21:50:18 +00:00
}
2010-02-06 03:38:24 +00:00
if ( ( silence_var = switch_channel_get_variable ( chan_a , " bridge_generate_comfort_noise " ) ) ) {
switch_codec_implementation_t read_impl = { 0 } ;
2009-02-10 19:09:06 +00:00
switch_core_session_get_read_impl ( session_a , & read_impl ) ;
2009-10-13 20:35:13 +00:00
2009-02-10 19:09:06 +00:00
if ( ! switch_channel_media_ready ( chan_a ) ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_ERROR , " Channel has no media! \n " ) ;
2008-09-12 16:38:43 +00:00
goto end_of_bridge_loop ;
}
if ( switch_true ( silence_var ) ) {
silence_val = 1400 ;
} else {
if ( ( silence_val = atoi ( silence_var ) ) < 0 ) {
silence_val = 0 ;
}
}
2008-05-20 15:40:27 +00:00
2008-09-12 16:38:43 +00:00
if ( silence_val ) {
if ( switch_core_codec_init ( & silence_codec ,
" L16 " ,
2010-02-06 03:38:24 +00:00
NULL ,
read_impl . actual_samples_per_second ,
2009-02-10 19:09:06 +00:00
read_impl . microseconds_per_packet / 1000 ,
2008-09-12 16:38:43 +00:00
1 ,
2010-02-06 03:38:24 +00:00
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( session_a ) ) ! = SWITCH_STATUS_SUCCESS ) {
2008-09-12 16:38:43 +00:00
silence_val = 0 ;
} else {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " Setup generated silence from %s to %s at %d \n " , switch_channel_get_name ( chan_a ) ,
2010-02-06 03:38:24 +00:00
switch_channel_get_name ( chan_b ) , silence_val ) ;
2008-09-12 16:38:43 +00:00
silence_frame . codec = & silence_codec ;
silence_frame . data = silence_data ;
silence_frame . buflen = sizeof ( silence_data ) ;
2009-02-10 19:09:06 +00:00
silence_frame . datalen = read_impl . decoded_bytes_per_packet ;
2008-09-12 16:38:43 +00:00
silence_frame . samples = silence_frame . datalen / sizeof ( int16_t ) ;
}
}
}
2010-02-06 03:38:24 +00:00
2007-03-30 22:13:19 +00:00
for ( ; ; ) {
switch_channel_state_t b_state ;
2007-03-29 22:34:40 +00:00
switch_status_t status ;
switch_event_t * event ;
2007-05-09 19:44:15 +00:00
2010-06-03 02:57:16 +00:00
if ( switch_channel_test_flag ( chan_a , CF_TRANSFER ) ) {
data - > clean_exit = 1 ;
2008-05-20 15:40:27 +00:00
}
2010-06-03 02:57:16 +00:00
if ( data - > clean_exit | | switch_channel_test_flag ( chan_b , CF_TRANSFER ) ) {
switch_channel_clear_flag ( chan_a , CF_HOLD ) ;
switch_channel_clear_flag ( chan_a , CF_SUSPEND ) ;
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-03-30 22:13:19 +00:00
}
2010-06-03 02:57:16 +00:00
if ( ! switch_channel_test_flag ( chan_b , CF_BRIDGED ) ) {
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-03-29 22:34:40 +00:00
}
2010-06-03 02:57:16 +00:00
if ( ! switch_channel_ready ( chan_a ) ) {
goto end_of_bridge_loop ;
2008-10-11 16:37:15 +00:00
}
2011-11-18 19:17:56 +00:00
if ( ( b_state = switch_channel_down_nosig ( chan_b ) ) ) {
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-03-29 22:34:40 +00:00
}
2010-06-03 02:57:16 +00:00
2010-11-29 19:00:19 +00:00
if ( read_frame_count > DEFAULT_LEAD_FRAMES & & switch_channel_media_ack ( chan_a ) & & switch_core_session_private_event_count ( session_a ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_set_flag ( chan_b , CF_SUSPEND ) ;
2011-01-05 16:42:33 +00:00
msg . numeric_arg = 42 ;
2007-05-09 19:44:15 +00:00
msg . string_arg = data - > b_uuid ;
msg . message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE ;
msg . from = __FILE__ ;
switch_core_session_receive_message ( session_a , & msg ) ;
2008-03-25 00:24:23 +00:00
switch_ivr_parse_next_event ( session_a ) ;
2007-05-09 19:44:15 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_BRIDGE ;
switch_core_session_receive_message ( session_a , & msg ) ;
2007-03-29 22:34:40 +00:00
switch_channel_clear_flag ( chan_b , CF_SUSPEND ) ;
2008-03-19 22:52:16 +00:00
switch_core_session_kill_channel ( session_b , SWITCH_SIG_BREAK ) ;
2007-03-29 22:34:40 +00:00
}
2008-03-19 22:52:16 +00:00
2009-10-13 21:52:47 +00:00
switch_ivr_parse_all_messages ( session_a ) ;
2008-05-20 15:40:27 +00:00
if ( ! inner_bridge & & ( switch_channel_test_flag ( chan_a , CF_SUSPEND ) | | switch_channel_test_flag ( chan_b , CF_SUSPEND ) ) ) {
2008-05-08 20:54:19 +00:00
status = switch_core_session_read_frame ( session_a , & read_frame , SWITCH_IO_FLAG_NONE , stream_id ) ;
2008-05-27 04:30:03 +00:00
2008-03-19 22:52:16 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
goto end_of_bridge_loop ;
}
2007-05-14 20:38:18 +00:00
continue ;
}
2008-02-05 21:09:52 +00:00
# ifdef SWITCH_VIDEO_IN_THREADS
2008-05-27 04:30:03 +00:00
if ( switch_channel_test_flag ( chan_a , CF_VIDEO ) & & switch_channel_test_flag ( chan_b , CF_VIDEO ) & & ! vid_launch ) {
vid_launch + + ;
vh . session_a = session_a ;
vh . session_b = session_b ;
2009-11-18 19:22:45 +00:00
vid_thread = launch_video ( & vh ) ;
2008-05-27 04:30:03 +00:00
}
2008-02-05 21:09:52 +00:00
# endif
2008-02-01 21:22:27 +00:00
2010-11-29 19:00:19 +00:00
if ( read_frame_count > DEFAULT_LEAD_FRAMES & & switch_channel_media_ack ( chan_a ) ) {
if ( exec_app ) {
2010-11-29 19:02:48 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " %s Bridge execute app %s(%s) \n " ,
2010-11-29 19:00:19 +00:00
switch_channel_get_name ( chan_a ) , exec_app , exec_data ) ;
2010-11-30 17:01:54 +00:00
switch_core_session_execute_application_async ( session_a , exec_app , exec_data ) ;
2010-11-29 19:00:19 +00:00
exec_app = exec_data = NULL ;
}
2011-04-04 16:55:05 +00:00
if ( ( bypass_media_after_bridge | | switch_channel_test_flag ( chan_b , CF_BYPASS_MEDIA_AFTER_BRIDGE ) ) & & switch_channel_test_flag ( chan_a , CF_ANSWERED )
2010-11-29 19:00:19 +00:00
& & switch_channel_test_flag ( chan_b , CF_ANSWERED ) ) {
switch_ivr_nomedia ( switch_core_session_get_uuid ( session_a ) , SMF_REBRIDGE ) ;
bypass_media_after_bridge = 0 ;
2011-04-04 16:55:05 +00:00
switch_channel_clear_flag ( chan_b , CF_BYPASS_MEDIA_AFTER_BRIDGE ) ;
2010-11-29 19:00:19 +00:00
goto end_of_bridge_loop ;
}
2008-09-18 21:50:18 +00:00
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:34:40 +00:00
/* if 1 channel has DTMF pass it to the other */
2007-12-22 00:32:20 +00:00
while ( switch_channel_has_dtmf ( chan_a ) ) {
switch_dtmf_t dtmf = { 0 , 0 } ;
if ( switch_channel_dequeue_dtmf ( chan_a , & dtmf ) = = SWITCH_STATUS_SUCCESS ) {
2008-03-13 01:08:42 +00:00
int send_dtmf = 1 ;
2008-03-19 17:56:27 +00:00
2007-12-22 00:32:20 +00:00
if ( input_callback ) {
2008-05-27 04:30:03 +00:00
switch_status_t cb_status = input_callback ( session_a , ( void * ) & dtmf , SWITCH_INPUT_TYPE_DTMF , user_data , 0 ) ;
2008-03-13 01:08:42 +00:00
if ( cb_status = = SWITCH_STATUS_IGNORE ) {
send_dtmf = 0 ;
2008-04-09 18:15:15 +00:00
} else if ( cb_status ! = SWITCH_STATUS_SUCCESS ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " %s ended call via DTMF \n " , switch_channel_get_name ( chan_a ) ) ;
2007-12-22 00:32:20 +00:00
switch_core_session_kill_channel ( session_b , SWITCH_SIG_BREAK ) ;
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-12-22 00:32:20 +00:00
}
2007-03-29 22:34:40 +00:00
}
2008-05-27 04:30:03 +00:00
2008-03-13 01:08:42 +00:00
if ( send_dtmf ) {
switch_core_session_send_dtmf ( session_b , & dtmf ) ;
2011-03-10 02:06:27 +00:00
switch_core_session_kill_channel ( session_b , SWITCH_SIG_BREAK ) ;
2008-03-13 01:08:42 +00:00
}
2007-03-29 22:34:40 +00:00
}
}
2009-02-21 23:19:58 +00:00
if ( switch_core_session_dequeue_event ( session_a , & event , SWITCH_FALSE ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
if ( input_callback ) {
status = input_callback ( session_a , event , SWITCH_INPUT_TYPE_EVENT , user_data , 0 ) ;
}
2010-08-18 19:58:14 +00:00
if ( ( event - > event_id ! = SWITCH_EVENT_COMMAND & & event - > event_id ! = SWITCH_EVENT_MESSAGE )
| | switch_core_session_receive_event ( session_b , & event ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
switch_event_destroy ( & event ) ;
}
}
2009-10-02 21:23:52 +00:00
if ( ! ans_a & & answer_limit & & switch_epoch_time_now ( NULL ) > answer_limit ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " Answer timeout hit on %s. \n " , switch_channel_get_name ( chan_a ) ) ;
2009-10-02 21:23:52 +00:00
switch_channel_hangup ( chan_a , SWITCH_CAUSE_ALLOTTED_TIMEOUT ) ;
}
2010-02-23 17:00:17 +00:00
if ( ! ans_a ) {
if ( originator ) {
if ( ! ans_b & & switch_channel_test_flag ( chan_b , CF_ANSWERED ) ) {
switch_channel_pass_callee_id ( chan_b , chan_a ) ;
if ( switch_channel_answer ( chan_a ) ! = SWITCH_STATUS_SUCCESS ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " %s Media Establishment Failed. \n " , switch_channel_get_name ( chan_a ) ) ;
2010-02-23 17:00:17 +00:00
goto end_of_bridge_loop ;
}
ans_a = 1 ;
} else if ( ! pre_b & & switch_channel_test_flag ( chan_b , CF_EARLY_MEDIA ) ) {
if ( switch_channel_pre_answer ( chan_a ) ! = SWITCH_STATUS_SUCCESS ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " %s Media Establishment Failed. \n " , switch_channel_get_name ( chan_a ) ) ;
2010-02-23 17:00:17 +00:00
goto end_of_bridge_loop ;
}
pre_b = 1 ;
2008-02-20 03:57:01 +00:00
}
2010-02-23 17:00:17 +00:00
if ( ! pre_b ) {
switch_yield ( 10000 ) ;
continue ;
2008-02-20 03:57:01 +00:00
}
2010-02-23 17:00:17 +00:00
} else {
ans_a = switch_channel_test_flag ( chan_b , CF_ANSWERED ) ;
2007-03-29 22:34:40 +00:00
}
}
2009-03-13 22:01:39 +00:00
2009-03-16 00:28:18 +00:00
if ( ans_a ! = ans_b ) {
2009-03-13 22:01:39 +00:00
switch_channel_t * un = ans_a ? chan_b : chan_a ;
2010-12-01 19:07:37 +00:00
switch_channel_t * a = un = = chan_b ? chan_a : chan_b ;
2010-02-06 03:38:24 +00:00
2010-12-16 02:59:23 +00:00
if ( switch_channel_direction ( un ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
if ( switch_channel_direction ( a ) = = SWITCH_CALL_DIRECTION_OUTBOUND | | ( un = = chan_a & & ! originator ) ) {
2010-12-02 03:20:59 +00:00
switch_channel_pass_callee_id ( a , un ) ;
}
2009-04-06 18:34:31 +00:00
if ( switch_channel_answer ( un ) ! = SWITCH_STATUS_SUCCESS ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " %s Media Establishment Failed. \n " , switch_channel_get_name ( un ) ) ;
2009-04-06 18:34:31 +00:00
goto end_of_bridge_loop ;
}
2009-10-19 19:58:23 +00:00
2010-12-01 19:07:37 +00:00
if ( ans_a ) {
ans_b = 1 ;
} else {
ans_a = 1 ;
}
}
2009-03-13 22:01:39 +00:00
}
2010-02-06 03:38:24 +00:00
2011-08-05 14:31:21 +00:00
if ( originator & & ! ans_b ) ans_b = switch_channel_test_flag ( chan_b , CF_ANSWERED ) ;
2009-10-14 19:26:10 +00:00
if ( originator & & ! sent_update & & ans_a & & ans_b & & switch_channel_media_ack ( chan_a ) & & switch_channel_media_ack ( chan_b ) ) {
switch_ivr_bridge_display ( session_a , session_b ) ;
sent_update = 1 ;
2009-10-13 20:03:18 +00:00
}
2008-02-05 21:09:52 +00:00
# ifndef SWITCH_VIDEO_IN_THREADS
if ( switch_channel_test_flag ( chan_a , CF_VIDEO ) & & switch_channel_test_flag ( chan_b , CF_VIDEO ) ) {
/* read video from 1 channel and write it to the other */
2008-05-08 19:19:47 +00:00
status = switch_core_session_read_video_frame ( session_a , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2008-05-27 04:30:03 +00:00
2008-02-05 21:09:52 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2008-02-05 21:09:52 +00:00
}
2008-05-27 04:30:03 +00:00
2008-05-08 19:19:47 +00:00
switch_core_session_write_video_frame ( session_b , read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2008-02-05 21:09:52 +00:00
}
# endif
2007-03-29 22:34:40 +00:00
/* read audio from 1 channel and write it to the other */
2008-05-08 19:19:47 +00:00
status = switch_core_session_read_frame ( session_a , & read_frame , SWITCH_IO_FLAG_NONE , stream_id ) ;
2007-03-29 22:34:40 +00:00
if ( SWITCH_READ_ACCEPTABLE ( status ) ) {
2010-11-29 19:00:19 +00:00
read_frame_count + + ;
2007-12-06 22:26:37 +00:00
if ( switch_test_flag ( read_frame , SFF_CNG ) ) {
2008-09-12 16:38:43 +00:00
if ( silence_val ) {
switch_generate_sln_silence ( ( int16_t * ) silence_frame . data , silence_frame . samples , silence_val ) ;
read_frame = & silence_frame ;
2008-09-23 21:39:09 +00:00
} else if ( ! switch_channel_test_flag ( chan_b , CF_ACCEPT_CNG ) ) {
2008-09-12 16:38:43 +00:00
continue ;
}
2007-12-06 22:26:37 +00:00
}
2010-02-06 03:38:24 +00:00
2010-10-07 23:30:07 +00:00
if ( switch_channel_test_flag ( chan_a , CF_BRIDGE_NOWRITE ) ) {
continue ;
}
2007-03-29 22:34:40 +00:00
if ( status ! = SWITCH_STATUS_BREAK & & ! switch_channel_test_flag ( chan_a , CF_HOLD ) ) {
2008-05-08 19:19:47 +00:00
if ( switch_core_session_write_frame ( session_b , read_frame , SWITCH_IO_FLAG_NONE , stream_id ) ! = SWITCH_STATUS_SUCCESS ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG ,
2008-08-15 21:49:43 +00:00
" %s ending bridge by request from write function \n " , switch_channel_get_name ( chan_b ) ) ;
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-03-29 22:34:40 +00:00
}
}
} else {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " %s ending bridge by request from read function \n " , switch_channel_get_name ( chan_a ) ) ;
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-03-29 22:34:40 +00:00
}
}
2010-02-06 03:38:24 +00:00
end_of_bridge_loop :
2008-09-12 16:38:43 +00:00
2009-11-19 18:22:05 +00:00
# ifdef SWITCH_VIDEO_IN_THREADS
if ( vid_thread ) {
vh . up = - 1 ;
switch_channel_set_flag ( chan_a , CF_NOT_READY ) ;
switch_channel_set_flag ( chan_b , CF_NOT_READY ) ;
switch_core_session_kill_channel ( session_a , SWITCH_SIG_BREAK ) ;
switch_core_session_kill_channel ( session_b , SWITCH_SIG_BREAK ) ;
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " Ending video thread. \n " ) ;
2009-11-19 18:22:05 +00:00
}
# endif
2008-09-12 16:38:43 +00:00
if ( silence_val ) {
switch_core_codec_destroy ( & silence_codec ) ;
}
2008-03-13 01:08:42 +00:00
2008-05-20 15:40:27 +00:00
if ( ! inner_bridge ) {
2008-03-13 01:08:42 +00:00
hook_var = switch_channel_get_variable ( chan_a , SWITCH_API_BRIDGE_END_VARIABLE ) ;
}
2008-02-01 21:22:27 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( hook_var ) ) {
2008-03-13 01:08:42 +00:00
switch_stream_handle_t stream = { 0 } ;
char * cmd = switch_core_session_strdup ( session_a , hook_var ) ;
char * arg = NULL ;
if ( ( arg = strchr ( cmd , ' ' ) ) ) {
* arg + + = ' \0 ' ;
}
SWITCH_STANDARD_STREAM ( stream ) ;
switch_api_execute ( cmd , arg , NULL , & stream ) ;
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " \n Post-Bridge Command %s(%s): \n %s \n " , cmd , arg , switch_str_nil ( ( char * ) stream . data ) ) ;
2008-03-13 01:08:42 +00:00
switch_safe_free ( stream . data ) ;
}
2008-05-27 04:30:03 +00:00
2011-11-18 19:17:56 +00:00
if ( ! inner_bridge & & switch_channel_up_nosig ( chan_a ) ) {
2007-07-26 00:51:32 +00:00
if ( ( app_name = switch_channel_get_variable ( chan_a , SWITCH_EXEC_AFTER_BRIDGE_APP_VARIABLE ) ) ) {
switch_caller_extension_t * extension = NULL ;
if ( ( extension = switch_caller_extension_new ( session_a , app_name , app_name ) ) = = 0 ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_CRIT , " memory error! \n " ) ;
2007-07-26 00:51:32 +00:00
goto end ;
}
app_arg = switch_channel_get_variable ( chan_a , SWITCH_EXEC_AFTER_BRIDGE_ARG_VARIABLE ) ;
2007-07-26 00:49:02 +00:00
2007-07-26 00:51:32 +00:00
switch_caller_extension_add_application ( session_a , extension , ( char * ) app_name , app_arg ) ;
switch_channel_set_caller_extension ( chan_a , extension ) ;
2007-07-26 00:49:02 +00:00
2007-07-26 00:51:32 +00:00
if ( switch_channel_get_state ( chan_a ) = = CS_EXECUTE ) {
switch_channel_set_flag ( chan_a , CF_RESET ) ;
} else {
switch_channel_set_state ( chan_a , CS_EXECUTE ) ;
}
2007-07-26 00:49:02 +00:00
}
}
2008-05-27 04:30:03 +00:00
end :
2007-07-26 00:49:02 +00:00
2009-11-18 19:22:45 +00:00
# ifdef SWITCH_VIDEO_IN_THREADS
if ( vid_thread ) {
switch_status_t st ;
2009-11-19 18:22:05 +00:00
if ( vh . up ) {
switch_core_session_kill_channel ( session_a , SWITCH_SIG_BREAK ) ;
switch_core_session_kill_channel ( session_b , SWITCH_SIG_BREAK ) ;
}
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " Ending video thread. \n " ) ;
2009-11-18 19:22:45 +00:00
switch_thread_join ( & st , vid_thread ) ;
2009-11-19 18:22:05 +00:00
switch_channel_clear_flag ( chan_a , CF_NOT_READY ) ;
switch_channel_clear_flag ( chan_b , CF_NOT_READY ) ;
2009-11-18 19:22:45 +00:00
}
# endif
2009-01-09 20:34:01 +00:00
switch_core_session_reset ( session_a , SWITCH_TRUE , SWITCH_TRUE ) ;
2007-03-29 22:34:40 +00:00
switch_channel_set_variable ( chan_a , SWITCH_BRIDGE_VARIABLE , NULL ) ;
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session_a ) , SWITCH_LOG_DEBUG , " BRIDGE THREAD DONE [%s] \n " , switch_channel_get_name ( chan_a ) ) ;
2009-07-31 19:09:50 +00:00
switch_channel_clear_flag ( chan_a , CF_BRIDGED ) ;
2009-12-10 22:57:56 +00:00
2009-12-14 16:38:44 +00:00
if ( switch_channel_test_flag ( chan_a , CF_LEG_HOLDING ) & & switch_channel_ready ( chan_b ) ) {
2009-12-10 22:57:56 +00:00
const char * ext = switch_channel_get_variable ( chan_a , " hold_hangup_xfer_exten " ) ;
switch_channel_stop_broadcast ( chan_b ) ;
2010-02-06 03:38:24 +00:00
2009-12-10 22:57:56 +00:00
if ( zstr ( ext ) ) {
switch_call_cause_t cause = switch_channel_get_cause ( chan_b ) ;
if ( cause = = SWITCH_CAUSE_NONE ) {
cause = SWITCH_CAUSE_NORMAL_CLEARING ;
}
switch_channel_hangup ( chan_b , cause ) ;
} else {
switch_channel_set_variable ( chan_b , SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE , ext ) ;
}
switch_channel_clear_flag ( chan_a , CF_LEG_HOLDING ) ;
}
2011-11-06 14:53:00 +00:00
if ( switch_channel_test_flag ( chan_a , CF_INTERCEPTED ) ) {
switch_channel_set_flag ( chan_b , CF_INTERCEPT ) ;
}
2008-10-10 22:59:32 +00:00
switch_core_session_kill_channel ( session_b , SWITCH_SIG_BREAK ) ;
2007-03-29 22:34:40 +00:00
switch_core_session_rwunlock ( session_b ) ;
return NULL ;
}
2009-03-20 20:40:30 +00:00
static void transfer_after_bridge ( switch_core_session_t * session , const char * where )
{
int argc ;
char * argv [ 4 ] = { 0 } ;
char * mydata ;
2009-10-07 04:30:19 +00:00
switch_channel_set_variable ( switch_core_session_get_channel ( session ) , SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE , NULL ) ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( where ) & & ( mydata = switch_core_session_strdup ( session , where ) ) ) {
2009-03-20 20:40:30 +00:00
if ( ( argc = switch_separate_string ( mydata , ' : ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) > = 1 ) {
switch_ivr_session_transfer ( session , argv [ 0 ] , argv [ 1 ] , argv [ 2 ] ) ;
} else {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " No extension specified. \n " ) ;
2009-03-20 20:40:30 +00:00
}
}
}
2008-05-05 15:30:55 +00:00
static switch_status_t audio_bridge_on_exchange_media ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_ivr_bridge_data_t * bd = switch_channel_get_private ( channel , " _bridge_ " ) ;
2007-12-27 22:24:30 +00:00
switch_channel_state_t state ;
2009-03-20 20:40:30 +00:00
const char * var ;
2007-03-29 22:34:40 +00:00
2008-01-28 07:26:10 +00:00
if ( bd ) {
2007-03-29 22:34:40 +00:00
switch_channel_set_private ( channel , " _bridge_ " , NULL ) ;
2007-05-03 19:16:54 +00:00
if ( bd - > session = = session & & * bd - > b_uuid ) {
audio_bridge_thread ( NULL , ( void * ) bd ) ;
2009-01-09 20:34:01 +00:00
switch_core_session_reset ( session , SWITCH_TRUE , SWITCH_TRUE ) ;
2007-05-03 19:16:54 +00:00
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2007-03-29 22:34:40 +00:00
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
switch_channel_clear_state_handler ( channel , & audio_bridge_peer_state_handlers ) ;
2007-12-27 22:24:30 +00:00
state = switch_channel_get_state ( channel ) ;
2010-02-06 03:38:24 +00:00
2008-11-11 15:03:09 +00:00
if ( state < CS_HANGUP & & switch_true ( switch_channel_get_variable ( channel , SWITCH_PARK_AFTER_BRIDGE_VARIABLE ) ) ) {
switch_ivr_park_session ( session ) ;
2009-03-20 20:40:30 +00:00
} else if ( state < CS_HANGUP & & ( var = switch_channel_get_variable ( channel , SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE ) ) ) {
transfer_after_bridge ( session , var ) ;
2008-11-21 19:52:18 +00:00
} else {
2010-02-06 03:38:24 +00:00
if ( ! switch_channel_test_flag ( channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( channel , CF_REDIRECT ) & &
! switch_channel_test_flag ( channel , CF_XFER_ZOMBIE ) & & bd & & ! bd - > clean_exit
2010-02-11 19:52:36 +00:00
& & state ! = CS_PARK & & state ! = CS_ROUTING & & state = = CS_EXCHANGE_MEDIA & & ! switch_channel_test_flag ( channel , CF_INNER_BRIDGE ) ) {
2012-04-30 23:25:59 +00:00
if ( switch_channel_test_flag ( channel , CF_INTERCEPTED ) ) {
2012-05-01 00:37:59 +00:00
switch_channel_clear_flag ( channel , CF_INTERCEPT ) ;
switch_channel_clear_flag ( channel , CF_INTERCEPTED ) ;
2012-04-30 23:25:59 +00:00
return SWITCH_STATUS_FALSE ;
} else {
2012-04-30 23:13:32 +00:00
if ( switch_channel_test_flag ( channel , CF_INTERCEPT ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_PICKED_OFF ) ;
2011-11-28 19:38:00 +00:00
} else {
2012-04-30 23:13:32 +00:00
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_ORIGINATOR_CANCEL ) ;
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
}
2011-11-28 19:38:00 +00:00
}
2011-11-06 14:53:00 +00:00
}
2008-07-09 16:03:03 +00:00
}
}
2010-02-06 03:38:24 +00:00
2008-11-21 18:00:15 +00:00
if ( switch_channel_get_state ( channel ) = = CS_EXCHANGE_MEDIA ) {
2009-12-11 21:51:10 +00:00
switch_channel_set_variable ( channel , " park_timeout " , " 3 " ) ;
switch_channel_set_state ( channel , CS_PARK ) ;
2008-11-21 00:09:11 +00:00
}
2008-07-09 16:03:03 +00:00
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-05-05 15:30:55 +00:00
static switch_status_t audio_bridge_on_routing ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-29 22:34:40 +00:00
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s CUSTOM ROUTING \n " , switch_channel_get_name ( channel ) ) ;
2007-03-29 22:34:40 +00:00
/* put the channel in a passive state so we can loop audio to it */
2008-05-05 15:30:55 +00:00
switch_channel_set_state ( channel , CS_CONSUME_MEDIA ) ;
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-05-05 15:30:55 +00:00
static switch_status_t audio_bridge_on_consume_media ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-29 22:34:40 +00:00
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s CUSTOM HOLD \n " , switch_channel_get_name ( channel ) ) ;
2007-03-29 22:34:40 +00:00
/* put the channel in a passive state so we can loop audio to it */
return SWITCH_STATUS_FALSE ;
}
static const switch_state_handler_table_t audio_bridge_peer_state_handlers = {
/*.on_init */ NULL ,
2008-05-05 15:30:55 +00:00
/*.on_routing */ audio_bridge_on_routing ,
2007-03-29 22:34:40 +00:00
/*.on_execute */ NULL ,
/*.on_hangup */ NULL ,
2008-05-05 15:30:55 +00:00
/*.on_exchange_media */ audio_bridge_on_exchange_media ,
/*.on_soft_execute */ NULL ,
/*.on_consume_media */ audio_bridge_on_consume_media ,
2007-03-29 22:34:40 +00:00
} ;
2009-01-30 22:48:44 +00:00
static switch_status_t uuid_bridge_on_reset ( switch_core_session_t * session ) ;
static switch_status_t uuid_bridge_on_hibernate ( switch_core_session_t * session ) ;
static switch_status_t uuid_bridge_on_soft_execute ( switch_core_session_t * session ) ;
static const switch_state_handler_table_t uuid_bridge_state_handlers = {
/*.on_init */ NULL ,
/*.on_routing */ NULL ,
/*.on_execute */ NULL ,
/*.on_hangup */ NULL ,
/*.on_exchange_media */ NULL ,
/*.on_soft_execute */ uuid_bridge_on_soft_execute ,
/*.on_consume_media */ uuid_bridge_on_hibernate ,
/*.on_hibernate */ uuid_bridge_on_hibernate ,
/*.on_reset */ uuid_bridge_on_reset
} ;
2007-07-03 02:10:35 +00:00
static switch_status_t uuid_bridge_on_reset ( switch_core_session_t * session )
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-07-03 02:10:35 +00:00
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s CUSTOM RESET \n " , switch_channel_get_name ( channel ) ) ;
2007-07-03 02:10:35 +00:00
2008-11-17 20:13:12 +00:00
switch_channel_clear_flag ( channel , CF_ORIGINATING ) ;
2007-10-25 18:36:40 +00:00
2010-01-22 00:51:32 +00:00
cleanup_proxy_mode_b ( session ) ;
2009-10-07 04:30:19 +00:00
if ( switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
2008-05-05 15:30:55 +00:00
switch_channel_set_state ( channel , CS_SOFT_EXECUTE ) ;
2008-01-10 00:57:06 +00:00
}
2007-07-03 02:10:35 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-29 22:34:40 +00:00
2008-11-21 00:09:11 +00:00
static switch_status_t uuid_bridge_on_hibernate ( switch_core_session_t * session )
{
switch_channel_set_state ( switch_core_session_get_channel ( session ) , CS_RESET ) ;
return SWITCH_STATUS_FALSE ;
}
2008-05-05 15:30:55 +00:00
static switch_status_t uuid_bridge_on_soft_execute ( switch_core_session_t * session )
2007-03-29 22:34:40 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-29 22:34:40 +00:00
switch_core_session_t * other_session ;
2007-11-01 11:28:26 +00:00
const char * other_uuid = NULL ;
2007-03-29 22:34:40 +00:00
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s CUSTOM SOFT_EXECUTE \n " , switch_channel_get_name ( channel ) ) ;
2009-01-30 22:48:44 +00:00
switch_channel_clear_state_handler ( channel , & uuid_bridge_state_handlers ) ;
2007-03-29 22:34:40 +00:00
2009-10-07 04:30:19 +00:00
if ( ! switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
2007-12-08 00:14:21 +00:00
return SWITCH_STATUS_SUCCESS ;
2007-03-29 22:34:40 +00:00
}
2008-05-27 04:30:03 +00:00
if ( ( other_uuid = switch_channel_get_variable ( channel , SWITCH_UUID_BRIDGE ) ) & & ( other_session = switch_core_session_locate ( other_uuid ) ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_t * other_channel = switch_core_session_get_channel ( other_session ) ;
switch_event_t * event ;
2009-02-11 14:52:39 +00:00
int ready_a , ready_b ;
2011-12-07 21:13:59 +00:00
switch_channel_state_t state , running_state ;
int max = 1000 , loops = max ;
2008-05-27 04:30:03 +00:00
2007-07-03 02:10:35 +00:00
switch_channel_set_variable ( channel , SWITCH_UUID_BRIDGE , NULL ) ;
2011-12-07 21:13:59 +00:00
for ( ; ; ) {
state = switch_channel_get_state ( other_channel ) ;
running_state = switch_channel_get_running_state ( other_channel ) ;
2012-04-02 21:03:37 +00:00
if ( switch_channel_down_nosig ( other_channel ) | | switch_channel_down ( channel ) ) {
2012-01-11 18:05:16 +00:00
break ;
}
if ( state < CS_HANGUP & & state = = running_state ) {
2011-12-07 21:13:59 +00:00
if ( - - loops < 1 ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
switch_channel_hangup ( other_channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
if ( running_state = = CS_RESET ) {
switch_channel_set_state ( other_channel , CS_SOFT_EXECUTE ) ;
}
2007-12-08 00:14:21 +00:00
2011-12-07 21:13:59 +00:00
if ( running_state = = CS_SOFT_EXECUTE ) {
2007-12-08 00:14:21 +00:00
2011-12-07 21:13:59 +00:00
if ( switch_channel_test_flag ( other_channel , CF_BRIDGE_ORIGINATOR ) ) {
goto done ;
} else {
break ;
}
}
} else {
loops = max ;
}
2012-01-11 18:05:16 +00:00
2011-12-07 21:13:59 +00:00
switch_yield ( 20000 ) ;
2007-03-29 22:34:40 +00:00
}
2007-12-08 00:14:21 +00:00
2009-01-09 20:34:01 +00:00
switch_core_session_reset ( session , SWITCH_TRUE , SWITCH_TRUE ) ;
2008-10-29 15:57:57 +00:00
2010-02-04 23:52:03 +00:00
if ( switch_ivr_wait_for_answer ( session , other_session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_core_session_rwunlock ( other_session ) ;
2010-03-18 19:15:52 +00:00
if ( switch_true ( switch_channel_get_variable ( channel , " uuid_bridge_continue_on_cancel " ) ) ) {
switch_channel_set_state ( channel , CS_EXECUTE ) ;
2012-04-27 16:37:21 +00:00
} else if ( ! switch_channel_test_flag ( channel , CF_TRANSFER ) ) {
2010-03-18 19:15:52 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_ORIGINATOR_CANCEL ) ;
}
2011-12-07 21:13:59 +00:00
goto done ;
2010-02-04 23:52:03 +00:00
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
ready_a = switch_channel_ready ( channel ) ;
ready_b = switch_channel_ready ( other_channel ) ;
if ( ! ready_a | | ! ready_b ) {
if ( ! ready_a ) {
switch_channel_hangup ( other_channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
if ( ! ready_b ) {
2008-07-24 16:31:47 +00:00
const char * cid = switch_channel_get_variable ( other_channel , " rdnis " ) ;
if ( ready_a & & cid ) {
switch_ivr_session_transfer ( session , cid , NULL , NULL ) ;
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2007-03-29 22:34:40 +00:00
}
2007-07-03 02:10:35 +00:00
switch_core_session_rwunlock ( other_session ) ;
2011-12-07 21:13:59 +00:00
goto done ;
2007-03-29 22:34:40 +00:00
}
/* fire events that will change the data table from "show channels" */
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_EXECUTE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application " , " uuid_bridge " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application-Data " , switch_core_session_get_uuid ( other_session ) ) ;
2007-03-29 22:34:40 +00:00
switch_event_fire ( & event ) ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_EXECUTE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( other_channel , event ) ;
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application " , " uuid_bridge " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application-Data " , switch_core_session_get_uuid ( session ) ) ;
2007-03-29 22:34:40 +00:00
switch_event_fire ( & event ) ;
}
2010-01-22 02:59:01 +00:00
2007-03-29 22:34:40 +00:00
switch_ivr_multi_threaded_bridge ( session , other_session , NULL , NULL , NULL ) ;
2010-02-06 03:38:24 +00:00
2008-08-19 19:24:00 +00:00
state = switch_channel_get_state ( channel ) ;
2010-02-06 03:38:24 +00:00
if ( ! switch_channel_test_flag ( channel , CF_TRANSFER ) & &
! switch_channel_test_flag ( channel , CF_REDIRECT ) & & state < CS_HANGUP & & state ! = CS_ROUTING & & state ! = CS_PARK ) {
2008-08-14 16:29:26 +00:00
switch_channel_set_state ( channel , CS_EXECUTE ) ;
}
2007-07-03 02:10:35 +00:00
switch_core_session_rwunlock ( other_session ) ;
2007-03-29 22:34:40 +00:00
} else {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2011-12-07 21:13:59 +00:00
done :
2007-03-29 22:34:40 +00:00
2011-12-07 21:13:59 +00:00
switch_channel_clear_flag_recursive ( channel , CF_BRIDGE_ORIGINATOR ) ;
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_FALSE ;
}
2010-01-28 17:10:23 +00:00
static switch_status_t sb_on_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf , switch_dtmf_direction_t direction )
{
switch_channel_t * channel = NULL ;
char * key ;
channel = switch_core_session_get_channel ( session ) ;
switch_assert ( channel ! = NULL ) ;
2010-02-06 03:38:24 +00:00
2010-01-28 17:10:23 +00:00
if ( ( key = ( char * ) switch_channel_get_private ( channel , " __bridge_term_key " ) ) & & dtmf - > digit = = * key ) {
const char * uuid ;
switch_core_session_t * other_session ;
if ( switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
switch_channel_set_state ( channel , CS_EXECUTE ) ;
} else {
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ) & & ( other_session = switch_core_session_locate ( uuid ) ) ) {
switch_channel_t * other_channel = switch_core_session_get_channel ( other_session ) ;
switch_channel_set_state ( other_channel , CS_EXECUTE ) ;
switch_core_session_rwunlock ( other_session ) ;
} else {
return SWITCH_STATUS_SUCCESS ;
}
}
2010-02-06 03:38:24 +00:00
2010-01-28 17:10:23 +00:00
return SWITCH_STATUS_FALSE ;
}
2010-02-06 03:38:24 +00:00
2010-01-28 17:10:23 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2010-02-02 16:20:12 +00:00
static switch_status_t hanguphook ( switch_core_session_t * session )
{
switch_core_session_message_t msg = { 0 } ;
switch_channel_t * channel = NULL ;
2010-10-07 23:30:07 +00:00
switch_event_t * event ;
2010-02-02 16:20:12 +00:00
2010-02-06 03:38:24 +00:00
channel = switch_core_session_get_channel ( session ) ;
2011-04-22 21:43:29 +00:00
2010-02-02 16:20:12 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE ;
msg . from = __FILE__ ;
msg . string_arg = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ;
2010-02-06 03:38:24 +00:00
2010-10-18 19:47:26 +00:00
if ( switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
switch_channel_clear_flag_recursive ( channel , CF_BRIDGE_ORIGINATOR ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_UNBRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
2010-10-07 23:30:07 +00:00
}
}
2010-10-18 19:47:26 +00:00
2010-10-07 23:30:07 +00:00
2010-02-02 16:20:12 +00:00
switch_core_session_receive_message ( session , & msg ) ;
switch_core_event_hook_remove_state_change ( session , hanguphook ) ;
return SWITCH_STATUS_SUCCESS ;
}
2010-01-28 17:10:23 +00:00
2007-03-29 22:34:40 +00:00
static switch_status_t signal_bridge_on_hibernate ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
2010-01-28 17:10:23 +00:00
const char * key ;
2010-02-02 16:20:12 +00:00
switch_core_session_message_t msg = { 0 } ;
2010-07-06 21:01:26 +00:00
switch_event_t * event = NULL ;
2011-09-02 14:34:40 +00:00
switch_ivr_dmachine_t * dmachine [ 2 ] = { 0 } ;
2007-03-29 22:34:40 +00:00
channel = switch_core_session_get_channel ( session ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( channel ! = NULL ) ;
2007-03-29 22:34:40 +00:00
2010-02-02 16:20:12 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_BRIDGE ;
msg . from = __FILE__ ;
msg . string_arg = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ;
switch_core_event_hook_add_state_change ( session , hanguphook ) ;
switch_core_session_receive_message ( session , & msg ) ;
2010-01-28 17:10:23 +00:00
if ( ( key = switch_channel_get_variable ( channel , " bridge_terminate_key " ) ) ) {
switch_channel_set_private ( channel , " __bridge_term_key " , switch_core_session_strdup ( session , key ) ) ;
switch_core_event_hook_add_recv_dtmf ( session , sb_on_dtmf ) ;
}
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( channel , SWITCH_BRIDGE_VARIABLE , switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ) ;
2010-08-20 18:28:17 +00:00
switch_channel_set_variable ( channel , SWITCH_LAST_BRIDGE_VARIABLE , switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ) ;
2007-03-29 22:34:40 +00:00
2010-07-06 21:01:26 +00:00
if ( switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_BRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
2012-05-10 17:15:25 +00:00
switch_core_session_t * other_session ;
2011-08-04 04:43:41 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-A-Unique-ID " , switch_core_session_get_uuid ( session ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-B-Unique-ID " , msg . string_arg ) ;
2010-07-06 21:01:26 +00:00
switch_channel_event_set_data ( channel , event ) ;
2012-05-10 17:15:25 +00:00
if ( ( other_session = switch_core_session_locate ( msg . string_arg ) ) ) {
switch_channel_t * other_channel = switch_core_session_get_channel ( other_session ) ;
switch_event_add_presence_data_cols ( other_channel , event , " Bridge-B-PD- " ) ;
switch_core_session_rwunlock ( other_session ) ;
}
2010-07-06 21:01:26 +00:00
switch_event_fire ( & event ) ;
}
}
2011-09-02 14:34:40 +00:00
if ( ( dmachine [ 0 ] = switch_core_session_get_dmachine ( session , DIGIT_TARGET_SELF ) ) | |
( dmachine [ 1 ] = switch_core_session_get_dmachine ( session , DIGIT_TARGET_PEER ) ) ) {
2010-10-07 23:30:07 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
" %s not hibernating due to active digit parser, semi-hibernation engaged. \n " , switch_channel_get_name ( channel ) ) ;
while ( switch_channel_ready ( channel ) & & switch_channel_get_state ( channel ) = = CS_HIBERNATE ) {
if ( ! switch_channel_test_flag ( channel , CF_BROADCAST ) ) {
2011-09-02 14:34:40 +00:00
if ( dmachine [ 0 ] ) {
switch_ivr_dmachine_ping ( dmachine [ 0 ] , NULL ) ;
}
if ( dmachine [ 1 ] ) {
switch_ivr_dmachine_ping ( dmachine [ 1 ] , NULL ) ;
}
2010-10-07 23:30:07 +00:00
}
switch_yield ( 20000 ) ;
2012-04-18 19:49:00 +00:00
switch_ivr_parse_all_messages ( session ) ;
2010-10-07 23:30:07 +00:00
}
}
2011-09-02 14:34:40 +00:00
2010-10-07 23:30:07 +00:00
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t signal_bridge_on_hangup ( switch_core_session_t * session )
{
2007-11-01 11:28:26 +00:00
const char * uuid ;
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-29 22:34:40 +00:00
switch_core_session_t * other_session ;
switch_event_t * event ;
2009-03-20 01:23:38 +00:00
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ) ) {
switch_channel_set_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
}
2010-01-28 17:10:23 +00:00
if ( switch_channel_get_private ( channel , " __bridge_term_key " ) ) {
switch_core_event_hook_remove_recv_dtmf ( session , sb_on_dtmf ) ;
switch_channel_set_private ( channel , " __bridge_term_key " , NULL ) ;
}
2009-03-20 01:23:38 +00:00
switch_channel_set_variable ( channel , SWITCH_BRIDGE_VARIABLE , NULL ) ;
if ( uuid & & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2010-02-06 03:38:24 +00:00
switch_channel_t * other_channel = switch_core_session_get_channel ( other_session ) ;
const char * sbv = switch_channel_get_variable ( other_channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ;
2009-10-22 16:34:58 +00:00
const char * var ;
2009-03-20 01:23:38 +00:00
2010-02-06 03:38:24 +00:00
if ( ! zstr ( sbv ) & & ! strcmp ( sbv , switch_core_session_get_uuid ( session ) ) ) {
switch_channel_set_variable ( other_channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
switch_channel_set_variable ( other_channel , SWITCH_BRIDGE_VARIABLE , NULL ) ;
2011-08-04 06:04:21 +00:00
switch_channel_set_variable ( other_channel , " call_uuid " , switch_core_session_get_uuid ( other_session ) ) ;
2009-03-20 01:23:38 +00:00
2011-11-18 19:17:56 +00:00
if ( switch_channel_up_nosig ( other_channel ) ) {
2010-01-23 18:35:05 +00:00
2009-10-22 16:34:58 +00:00
if ( switch_true ( switch_channel_get_variable ( other_channel , SWITCH_PARK_AFTER_BRIDGE_VARIABLE ) ) ) {
switch_ivr_park_session ( other_session ) ;
} else if ( ( var = switch_channel_get_variable ( other_channel , SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE ) ) ) {
transfer_after_bridge ( other_session , var ) ;
}
2010-01-23 18:35:05 +00:00
if ( switch_channel_test_flag ( other_channel , CF_BRIDGE_ORIGINATOR ) ) {
if ( switch_channel_test_flag ( channel , CF_ANSWERED ) & &
switch_true ( switch_channel_get_variable ( other_channel , SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE ) ) ) {
2011-11-06 14:53:00 +00:00
if ( switch_channel_test_flag ( channel , CF_INTERCEPTED ) ) {
switch_channel_set_flag ( other_channel , CF_INTERCEPT ) ;
}
2010-02-06 03:38:24 +00:00
switch_channel_hangup ( other_channel , switch_channel_get_cause ( channel ) ) ;
2010-01-23 18:35:05 +00:00
} else {
switch_channel_set_state ( other_channel , CS_EXECUTE ) ;
}
2009-10-22 16:34:58 +00:00
} else {
2010-01-23 18:35:05 +00:00
switch_channel_hangup ( other_channel , switch_channel_get_cause ( channel ) ) ;
2009-10-22 16:34:58 +00:00
}
2010-02-06 03:38:24 +00:00
}
}
2010-03-04 15:58:59 +00:00
2012-05-10 17:15:25 +00:00
if ( switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
switch_channel_clear_flag_recursive ( channel , CF_BRIDGE_ORIGINATOR ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_UNBRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-A-Unique-ID " , switch_core_session_get_uuid ( session ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-B-Unique-ID " , uuid ) ;
switch_event_add_presence_data_cols ( other_channel , event , " Bridge-B-PD- " ) ;
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
}
2010-02-06 03:38:24 +00:00
2012-05-10 17:15:25 +00:00
switch_core_session_rwunlock ( other_session ) ;
} else {
if ( switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
switch_channel_clear_flag_recursive ( channel , CF_BRIDGE_ORIGINATOR ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_UNBRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-A-Unique-ID " , switch_core_session_get_uuid ( session ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-B-Unique-ID " , uuid ) ;
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2007-03-29 22:34:40 +00:00
}
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static const switch_state_handler_table_t signal_bridge_state_handlers = {
/*.on_init */ NULL ,
2008-05-05 15:30:55 +00:00
/*.on_routing */ NULL ,
2007-03-29 22:34:40 +00:00
/*.on_execute */ NULL ,
/*.on_hangup */ signal_bridge_on_hangup ,
2008-05-05 15:30:55 +00:00
/*.on_exchange_media */ NULL ,
/*.on_soft_execute */ NULL ,
/*.on_consume_media */ NULL ,
2007-03-29 22:34:40 +00:00
/*.on_hibernate */ signal_bridge_on_hibernate
} ;
2010-10-01 22:26:03 +00:00
static void check_bridge_export ( switch_channel_t * channel , switch_channel_t * peer_channel )
{
switch_channel_process_export ( peer_channel , channel , NULL , SWITCH_BRIDGE_EXPORT_VARS_VARIABLE ) ;
switch_channel_process_export ( channel , peer_channel , NULL , SWITCH_BRIDGE_EXPORT_VARS_VARIABLE ) ;
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_signal_bridge ( switch_core_session_t * session , switch_core_session_t * peer_session )
2007-03-29 22:34:40 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * caller_channel = switch_core_session_get_channel ( session ) ;
switch_channel_t * peer_channel = switch_core_session_get_channel ( peer_session ) ;
2007-03-29 22:34:40 +00:00
switch_event_t * event ;
2011-11-18 19:17:56 +00:00
if ( switch_channel_down_nosig ( peer_channel ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( caller_channel , switch_channel_get_cause ( peer_channel ) ) ;
return SWITCH_STATUS_FALSE ;
}
2011-11-18 19:17:56 +00:00
if ( ! switch_channel_up_nosig ( caller_channel ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( peer_channel , SWITCH_CAUSE_ORIGINATOR_CANCEL ) ;
return SWITCH_STATUS_FALSE ;
}
2010-10-01 22:26:03 +00:00
check_bridge_export ( caller_channel , peer_channel ) ;
2009-11-03 16:50:16 +00:00
switch_channel_set_flag_recursive ( caller_channel , CF_SIGNAL_BRIDGE_TTL ) ;
switch_channel_set_flag_recursive ( peer_channel , CF_SIGNAL_BRIDGE_TTL ) ;
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( caller_channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , switch_core_session_get_uuid ( peer_session ) ) ;
2007-03-29 22:34:40 +00:00
switch_channel_set_variable ( peer_channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , switch_core_session_get_uuid ( session ) ) ;
2011-08-04 06:04:21 +00:00
switch_channel_set_variable ( peer_channel , " call_uuid " , switch_core_session_get_uuid ( session ) ) ;
2007-03-29 22:34:40 +00:00
2009-11-02 23:58:30 +00:00
switch_channel_set_flag_recursive ( caller_channel , CF_BRIDGE_ORIGINATOR ) ;
switch_channel_clear_flag ( peer_channel , CF_BRIDGE_ORIGINATOR ) ;
2007-03-29 22:34:40 +00:00
switch_channel_clear_state_handler ( caller_channel , NULL ) ;
switch_channel_clear_state_handler ( peer_channel , NULL ) ;
switch_channel_add_state_handler ( caller_channel , & signal_bridge_state_handlers ) ;
switch_channel_add_state_handler ( peer_channel , & signal_bridge_state_handlers ) ;
2010-08-20 18:28:17 +00:00
switch_channel_set_variable ( caller_channel , " signal_bridge " , " true " ) ;
switch_channel_set_variable ( peer_channel , " signal_bridge " , " true " ) ;
2007-03-29 22:34:40 +00:00
/* fire events that will change the data table from "show channels" */
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_EXECUTE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( caller_channel , event ) ;
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application " , " signal_bridge " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application-Data " , switch_core_session_get_uuid ( peer_session ) ) ;
2007-03-29 22:34:40 +00:00
switch_event_fire ( & event ) ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_EXECUTE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( peer_channel , event ) ;
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application " , " signal_bridge " ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Application-Data " , switch_core_session_get_uuid ( session ) ) ;
2007-03-29 22:34:40 +00:00
switch_event_fire ( & event ) ;
}
2011-04-28 18:46:39 +00:00
switch_channel_set_bridge_time ( caller_channel ) ;
switch_channel_set_bridge_time ( peer_channel ) ;
2010-07-06 21:01:26 +00:00
2010-01-21 00:12:24 +00:00
switch_channel_set_state_flag ( caller_channel , CF_RESET ) ;
switch_channel_set_state_flag ( peer_channel , CF_RESET ) ;
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
switch_channel_set_state ( caller_channel , CS_HIBERNATE ) ;
switch_channel_set_state ( peer_channel , CS_HIBERNATE ) ;
2010-01-21 00:12:24 +00:00
2010-02-06 03:38:24 +00:00
#if 0
2008-09-19 19:58:01 +00:00
if ( switch_channel_test_flag ( caller_channel , CF_BRIDGED ) ) {
switch_channel_set_flag ( caller_channel , CF_TRANSFER ) ;
switch_channel_set_flag ( peer_channel , CF_TRANSFER ) ;
}
2010-01-21 00:12:24 +00:00
# endif
2007-03-29 22:34:40 +00:00
2009-10-19 19:58:23 +00:00
switch_ivr_bridge_display ( session , peer_session ) ;
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2011-12-07 23:42:52 +00:00
static void abort_call ( switch_channel_t * caller_channel , switch_channel_t * peer_channel )
{
switch_call_cause_t cause = switch_channel_get_cause ( caller_channel ) ;
if ( ! cause ) {
cause = SWITCH_CAUSE_ORIGINATOR_CANCEL ;
}
switch_channel_hangup ( peer_channel , cause ) ;
}
2007-03-29 22:34:40 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_multi_threaded_bridge ( switch_core_session_t * session ,
switch_core_session_t * peer_session ,
2007-03-30 00:15:25 +00:00
switch_input_callback_function_t input_callback , void * session_data ,
void * peer_session_data )
2007-03-29 22:34:40 +00:00
{
2008-01-28 07:26:10 +00:00
switch_ivr_bridge_data_t * a_leg = switch_core_session_alloc ( session , sizeof ( * a_leg ) ) ;
switch_ivr_bridge_data_t * b_leg = switch_core_session_alloc ( peer_session , sizeof ( * b_leg ) ) ;
switch_channel_t * caller_channel = switch_core_session_get_channel ( session ) ;
switch_channel_t * peer_channel = switch_core_session_get_channel ( peer_session ) ;
2007-03-29 22:34:40 +00:00
int stream_id = 0 ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2007-12-27 22:24:30 +00:00
switch_channel_state_t state ;
2008-02-20 03:57:01 +00:00
switch_event_t * event ;
int br = 0 ;
2008-05-20 15:40:27 +00:00
int inner_bridge = switch_channel_test_flag ( caller_channel , CF_INNER_BRIDGE ) ;
2009-03-20 20:40:30 +00:00
const char * var ;
2009-04-16 22:13:55 +00:00
switch_call_cause_t cause ;
2010-07-14 17:40:08 +00:00
switch_core_session_message_t msg = { 0 } ;
2008-05-27 04:30:03 +00:00
2009-09-30 23:50:51 +00:00
if ( switch_channel_test_flag ( caller_channel , CF_PROXY_MODE ) ) {
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Call has no media... Redirecting to signal bridge. \n " ) ;
return switch_ivr_signal_bridge ( session , peer_session ) ;
}
2010-02-06 03:38:24 +00:00
2010-10-01 22:26:03 +00:00
check_bridge_export ( caller_channel , peer_channel ) ;
2009-11-03 16:50:16 +00:00
switch_channel_set_flag_recursive ( caller_channel , CF_MEDIA_BRIDGE_TTL ) ;
switch_channel_set_flag_recursive ( peer_channel , CF_MEDIA_BRIDGE_TTL ) ;
2009-11-02 23:58:30 +00:00
switch_channel_set_flag_recursive ( caller_channel , CF_BRIDGE_ORIGINATOR ) ;
switch_channel_clear_flag ( peer_channel , CF_BRIDGE_ORIGINATOR ) ;
2007-12-27 22:24:30 +00:00
2012-03-26 15:53:34 +00:00
switch_channel_audio_sync ( caller_channel ) ;
switch_channel_audio_sync ( peer_channel ) ;
2007-04-13 22:15:58 +00:00
b_leg - > session = peer_session ;
2007-05-03 19:16:54 +00:00
switch_copy_string ( b_leg - > b_uuid , switch_core_session_get_uuid ( session ) , sizeof ( b_leg - > b_uuid ) ) ;
2007-04-13 22:15:58 +00:00
b_leg - > stream_id = stream_id ;
b_leg - > input_callback = input_callback ;
2007-06-12 21:00:26 +00:00
b_leg - > session_data = peer_session_data ;
2008-10-11 16:37:15 +00:00
b_leg - > clean_exit = 0 ;
2007-04-13 22:15:58 +00:00
a_leg - > session = session ;
2007-05-03 19:16:54 +00:00
switch_copy_string ( a_leg - > b_uuid , switch_core_session_get_uuid ( peer_session ) , sizeof ( a_leg - > b_uuid ) ) ;
2007-06-12 21:00:26 +00:00
a_leg - > stream_id = stream_id ;
a_leg - > input_callback = input_callback ;
a_leg - > session_data = session_data ;
2008-10-11 16:37:15 +00:00
a_leg - > clean_exit = 0 ;
2007-03-29 22:34:40 +00:00
switch_channel_add_state_handler ( peer_channel , & audio_bridge_peer_state_handlers ) ;
if ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) & & ! switch_channel_test_flag ( caller_channel , CF_ANSWERED ) ) {
2009-10-21 18:48:28 +00:00
switch_channel_pass_callee_id ( peer_channel , caller_channel ) ;
2007-03-29 22:34:40 +00:00
switch_channel_answer ( caller_channel ) ;
}
2008-01-05 01:03:08 +00:00
if ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) | | switch_channel_test_flag ( peer_channel , CF_EARLY_MEDIA ) | |
switch_channel_test_flag ( peer_channel , CF_RING_READY ) ) {
2007-11-01 11:28:26 +00:00
const char * app , * data ;
2011-01-05 22:25:07 +00:00
2011-12-07 23:42:52 +00:00
if ( ! switch_channel_ready ( caller_channel ) ) {
abort_call ( caller_channel , peer_channel ) ;
goto done ;
2011-11-28 19:38:00 +00:00
}
2008-05-05 15:30:55 +00:00
switch_channel_set_state ( peer_channel , CS_CONSUME_MEDIA ) ;
2007-03-29 22:34:40 +00:00
2011-08-04 06:04:21 +00:00
switch_channel_set_variable ( peer_channel , " call_uuid " , switch_core_session_get_uuid ( session ) ) ;
2011-11-28 19:38:00 +00:00
2007-03-29 22:34:40 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_BRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
2011-08-04 04:43:41 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-A-Unique-ID " , switch_core_session_get_uuid ( session ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-B-Unique-ID " , switch_core_session_get_uuid ( peer_session ) ) ;
2007-03-29 22:34:40 +00:00
switch_channel_event_set_data ( caller_channel , event ) ;
2012-05-10 17:15:25 +00:00
switch_event_add_presence_data_cols ( peer_channel , event , " Bridge-B-PD- " ) ;
2007-03-29 22:34:40 +00:00
switch_event_fire ( & event ) ;
2008-02-20 03:57:01 +00:00
br = 1 ;
2007-03-29 22:34:40 +00:00
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
if ( switch_core_session_read_lock ( peer_session ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_channel_set_variable ( caller_channel , SWITCH_BRIDGE_VARIABLE , switch_core_session_get_uuid ( peer_session ) ) ;
2007-03-29 22:34:40 +00:00
switch_channel_set_variable ( peer_channel , SWITCH_BRIDGE_VARIABLE , switch_core_session_get_uuid ( session ) ) ;
2010-08-20 18:28:17 +00:00
switch_channel_set_variable ( caller_channel , SWITCH_LAST_BRIDGE_VARIABLE , switch_core_session_get_uuid ( peer_session ) ) ;
switch_channel_set_variable ( peer_channel , SWITCH_LAST_BRIDGE_VARIABLE , switch_core_session_get_uuid ( session ) ) ;
2007-03-29 22:34:40 +00:00
2011-12-07 23:42:52 +00:00
if ( ! switch_channel_ready ( caller_channel ) ) {
abort_call ( caller_channel , peer_channel ) ;
2012-02-23 03:48:03 +00:00
switch_core_session_rwunlock ( peer_session ) ;
2011-12-07 23:42:52 +00:00
goto done ;
}
2010-02-06 03:38:24 +00:00
if ( ! switch_channel_media_ready ( caller_channel ) | |
2009-01-03 03:10:11 +00:00
( ! switch_channel_test_flag ( peer_channel , CF_ANSWERED ) & & ! switch_channel_test_flag ( peer_channel , CF_EARLY_MEDIA ) ) ) {
if ( ( status = switch_ivr_wait_for_answer ( session , peer_session ) ) ! = SWITCH_STATUS_SUCCESS | | ! switch_channel_ready ( caller_channel ) ) {
2008-01-05 01:03:08 +00:00
switch_channel_state_t w_state = switch_channel_get_state ( caller_channel ) ;
switch_channel_hangup ( peer_channel , SWITCH_CAUSE_ALLOTTED_TIMEOUT ) ;
2010-02-06 03:38:24 +00:00
if ( w_state < CS_HANGUP & & w_state ! = CS_ROUTING & & w_state ! = CS_PARK & &
2008-11-21 00:09:11 +00:00
! switch_channel_test_flag ( caller_channel , CF_REDIRECT ) & & ! switch_channel_test_flag ( caller_channel , CF_TRANSFER ) & &
2008-01-05 01:03:08 +00:00
w_state ! = CS_EXECUTE ) {
const char * ext = switch_channel_get_variable ( peer_channel , " original_destination_number " ) ;
if ( ! ext ) {
ext = switch_channel_get_variable ( peer_channel , " destination_number " ) ;
}
if ( ext ) {
switch_ivr_session_transfer ( session , ext , NULL , NULL ) ;
} else {
switch_channel_hangup ( caller_channel , SWITCH_CAUSE_ALLOTTED_TIMEOUT ) ;
}
}
2011-12-07 23:42:52 +00:00
abort_call ( caller_channel , peer_channel ) ;
2008-01-05 01:03:08 +00:00
switch_core_session_rwunlock ( peer_session ) ;
goto done ;
}
2009-01-03 03:10:11 +00:00
2008-01-05 16:20:39 +00:00
if ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) & & ! switch_channel_test_flag ( caller_channel , CF_ANSWERED ) ) {
switch_channel_answer ( caller_channel ) ;
}
2008-01-05 01:03:08 +00:00
}
2011-01-05 16:42:33 +00:00
switch_channel_wait_for_flag ( peer_channel , CF_BROADCAST , SWITCH_FALSE , 10000 , caller_channel ) ;
switch_ivr_parse_all_events ( peer_session ) ;
switch_ivr_parse_all_events ( session ) ;
2007-03-29 22:34:40 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_BRIDGE ;
msg . from = __FILE__ ;
2007-04-13 22:15:58 +00:00
msg . string_arg = switch_core_session_strdup ( peer_session , switch_core_session_get_uuid ( session ) ) ;
2007-03-29 22:34:40 +00:00
2007-04-13 22:15:58 +00:00
if ( switch_core_session_receive_message ( peer_session , & msg ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_FALSE ;
2011-12-07 23:42:52 +00:00
abort_call ( caller_channel , peer_channel ) ;
2007-03-29 22:34:40 +00:00
switch_core_session_rwunlock ( peer_session ) ;
goto done ;
}
2007-04-13 22:15:58 +00:00
msg . string_arg = switch_core_session_strdup ( session , switch_core_session_get_uuid ( peer_session ) ) ;
if ( switch_core_session_receive_message ( session , & msg ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_FALSE ;
2011-12-07 23:42:52 +00:00
abort_call ( caller_channel , peer_channel ) ;
2007-03-29 22:34:40 +00:00
switch_core_session_rwunlock ( peer_session ) ;
goto done ;
}
2007-12-06 15:46:54 +00:00
switch_channel_set_variable ( caller_channel , SWITCH_BRIDGE_CHANNEL_VARIABLE , switch_channel_get_name ( peer_channel ) ) ;
switch_channel_set_variable ( caller_channel , SWITCH_BRIDGE_UUID_VARIABLE , switch_core_session_get_uuid ( peer_session ) ) ;
2007-12-07 17:26:15 +00:00
switch_channel_set_variable ( caller_channel , SWITCH_SIGNAL_BOND_VARIABLE , switch_core_session_get_uuid ( peer_session ) ) ;
2007-12-06 15:46:54 +00:00
switch_channel_set_variable ( peer_channel , SWITCH_BRIDGE_CHANNEL_VARIABLE , switch_channel_get_name ( caller_channel ) ) ;
switch_channel_set_variable ( peer_channel , SWITCH_BRIDGE_UUID_VARIABLE , switch_core_session_get_uuid ( session ) ) ;
2007-12-07 17:26:15 +00:00
switch_channel_set_variable ( peer_channel , SWITCH_SIGNAL_BOND_VARIABLE , switch_core_session_get_uuid ( session ) ) ;
2008-05-27 04:30:03 +00:00
2008-04-14 17:12:42 +00:00
if ( ( app = switch_channel_get_variable ( caller_channel , " bridge_pre_execute_aleg_app " ) ) ) {
2010-11-29 19:00:19 +00:00
switch_channel_set_variable ( caller_channel , " bridge_pre_execute_app " , app ) ;
if ( ( data = switch_channel_get_variable ( caller_channel , " bridge_pre_execute_aleg_data " ) ) ) {
switch_channel_set_variable ( caller_channel , " bridge_pre_execute_data " , data ) ;
2008-11-03 16:38:32 +00:00
}
2008-04-14 17:12:42 +00:00
}
2008-05-27 04:30:03 +00:00
2008-04-14 17:12:42 +00:00
if ( ( app = switch_channel_get_variable ( caller_channel , " bridge_pre_execute_bleg_app " ) ) ) {
2010-11-29 19:00:19 +00:00
switch_channel_set_variable ( peer_channel , " bridge_pre_execute_app " , app ) ;
if ( ( data = switch_channel_get_variable ( caller_channel , " bridge_pre_execute_bleg_data " ) ) ) {
switch_channel_set_variable ( peer_channel , " bridge_pre_execute_data " , data ) ;
2008-11-03 16:38:32 +00:00
}
2010-11-29 19:00:19 +00:00
2008-04-14 17:12:42 +00:00
}
2010-11-29 19:00:19 +00:00
2007-04-13 22:15:58 +00:00
switch_channel_set_private ( peer_channel , " _bridge_ " , b_leg ) ;
2008-05-05 15:30:55 +00:00
switch_channel_set_state ( peer_channel , CS_EXCHANGE_MEDIA ) ;
2007-04-13 22:15:58 +00:00
audio_bridge_thread ( NULL , ( void * ) a_leg ) ;
2010-02-06 03:38:24 +00:00
2009-11-02 23:58:30 +00:00
switch_channel_clear_flag_recursive ( caller_channel , CF_BRIDGE_ORIGINATOR ) ;
2010-02-06 03:38:24 +00:00
2009-11-24 18:18:09 +00:00
switch_channel_stop_broadcast ( peer_channel ) ;
2010-02-06 03:38:24 +00:00
2008-05-27 04:30:03 +00:00
2008-05-05 15:30:55 +00:00
while ( switch_channel_get_state ( peer_channel ) = = CS_EXCHANGE_MEDIA ) {
2012-04-18 19:49:00 +00:00
switch_ivr_parse_all_messages ( session ) ;
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2007-03-29 22:34:40 +00:00
}
2009-07-31 19:09:50 +00:00
if ( inner_bridge ) {
if ( switch_channel_ready ( caller_channel ) ) {
switch_channel_set_flag ( caller_channel , CF_BRIDGED ) ;
}
if ( switch_channel_ready ( peer_channel ) ) {
switch_channel_set_flag ( peer_channel , CF_BRIDGED ) ;
}
}
2010-02-06 03:38:24 +00:00
2009-04-16 22:13:55 +00:00
if ( ( cause = switch_channel_get_cause ( caller_channel ) ) ) {
switch_channel_set_variable ( peer_channel , SWITCH_BRIDGE_HANGUP_CAUSE_VARIABLE , switch_channel_cause2str ( cause ) ) ;
}
if ( ( cause = switch_channel_get_cause ( peer_channel ) ) ) {
switch_channel_set_variable ( caller_channel , SWITCH_BRIDGE_HANGUP_CAUSE_VARIABLE , switch_channel_cause2str ( cause ) ) ;
}
2010-03-04 15:58:59 +00:00
2012-05-08 12:43:01 +00:00
if ( switch_channel_down_nosig ( peer_channel ) ) {
switch_bool_t copy_xml_cdr = switch_true ( switch_channel_get_variable ( peer_channel , SWITCH_COPY_XML_CDR_VARIABLE ) ) ;
switch_bool_t copy_json_cdr = switch_true ( switch_channel_get_variable ( peer_channel , SWITCH_COPY_JSON_CDR_VARIABLE ) ) ;
2010-02-06 03:38:24 +00:00
2012-05-08 12:43:01 +00:00
if ( copy_xml_cdr | | copy_json_cdr ) {
char * cdr_text = NULL ;
2009-04-28 14:13:05 +00:00
2012-05-08 12:43:01 +00:00
switch_channel_wait_for_state ( peer_channel , caller_channel , CS_DESTROY ) ;
if ( copy_xml_cdr ) {
switch_xml_t cdr = NULL ;
if ( switch_ivr_generate_xml_cdr ( peer_session , & cdr ) = = SWITCH_STATUS_SUCCESS ) {
cdr_text = switch_xml_toxml ( cdr , SWITCH_FALSE ) ;
switch_xml_free ( cdr ) ;
}
}
if ( copy_json_cdr ) {
cJSON * cdr = NULL ;
if ( switch_ivr_generate_json_cdr ( peer_session , & cdr , SWITCH_TRUE ) = = SWITCH_STATUS_SUCCESS ) {
cdr_text = cJSON_PrintUnformatted ( cdr ) ;
cJSON_Delete ( cdr ) ;
}
}
if ( cdr_text ) {
switch_channel_set_variable ( caller_channel , " b_leg_cdr " , cdr_text ) ;
switch_channel_set_variable_name_printf ( caller_channel , cdr_text , " b_leg_cdr_%s " , switch_core_session_get_uuid ( peer_session ) ) ;
switch_safe_free ( cdr_text ) ;
2009-04-28 14:13:05 +00:00
}
}
2012-05-08 12:43:01 +00:00
2009-04-28 14:13:05 +00:00
}
2012-05-08 12:43:01 +00:00
2007-03-29 22:34:40 +00:00
switch_core_session_rwunlock ( peer_session ) ;
} else {
status = SWITCH_STATUS_FALSE ;
}
} else {
status = SWITCH_STATUS_FALSE ;
}
if ( status ! = SWITCH_STATUS_SUCCESS ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " Bridge Failed %s->%s \n " ,
2007-03-29 22:34:40 +00:00
switch_channel_get_name ( caller_channel ) , switch_channel_get_name ( peer_channel )
) ;
switch_channel_hangup ( peer_channel , SWITCH_CAUSE_NO_ANSWER ) ;
}
done :
2011-08-04 06:04:21 +00:00
switch_channel_set_variable ( peer_channel , " call_uuid " , switch_core_session_get_uuid ( peer_session ) ) ;
2008-02-20 03:57:01 +00:00
if ( br & & switch_event_create ( & event , SWITCH_EVENT_CHANNEL_UNBRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
2011-08-04 22:20:02 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-A-Unique-ID " , switch_core_session_get_uuid ( session ) ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " Bridge-B-Unique-ID " , switch_core_session_get_uuid ( peer_session ) ) ;
2008-02-20 03:57:01 +00:00
switch_channel_event_set_data ( caller_channel , event ) ;
2012-05-10 17:15:25 +00:00
switch_event_add_presence_data_cols ( peer_channel , event , " Bridge-B-PD- " ) ;
2008-02-20 03:57:01 +00:00
switch_event_fire ( & event ) ;
}
2010-07-14 17:40:08 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE ;
msg . from = __FILE__ ;
msg . string_arg = switch_core_session_strdup ( peer_session , switch_core_session_get_uuid ( session ) ) ;
switch_core_session_receive_message ( peer_session , & msg ) ;
msg . string_arg = switch_core_session_strdup ( session , switch_core_session_get_uuid ( peer_session ) ) ;
switch_core_session_receive_message ( session , & msg ) ;
2007-12-27 22:24:30 +00:00
state = switch_channel_get_state ( caller_channel ) ;
2010-01-21 00:12:24 +00:00
2010-02-06 03:38:24 +00:00
if ( ! switch_channel_test_flag ( caller_channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( caller_channel , CF_REDIRECT ) & &
! switch_channel_test_flag ( caller_channel , CF_XFER_ZOMBIE ) & & ! a_leg - > clean_exit & & ! inner_bridge ) {
if ( ( state ! = CS_EXECUTE & & state ! = CS_SOFT_EXECUTE & & state ! = CS_PARK & & state ! = CS_ROUTING ) | |
( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) & & state < CS_HANGUP ) ) {
if ( switch_true ( switch_channel_get_variable ( caller_channel , SWITCH_PARK_AFTER_BRIDGE_VARIABLE ) ) ) {
switch_ivr_park_session ( session ) ;
} else if ( ( var = switch_channel_get_variable ( caller_channel , SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE ) ) ) {
transfer_after_bridge ( session , var ) ;
} else if ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) & &
switch_true ( switch_channel_get_variable ( caller_channel , SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE ) ) ) {
2010-01-21 02:51:04 +00:00
switch_call_cause_t cause = switch_channel_get_cause ( peer_channel ) ;
if ( cause = = SWITCH_CAUSE_NONE ) {
cause = SWITCH_CAUSE_NORMAL_CLEARING ;
}
2011-11-06 14:53:00 +00:00
if ( switch_channel_test_flag ( peer_channel , CF_INTERCEPTED ) ) {
switch_channel_set_flag ( peer_channel , CF_INTERCEPT ) ;
}
2010-02-06 03:38:24 +00:00
switch_channel_hangup ( caller_channel , cause ) ;
}
}
}
2007-03-29 22:34:40 +00:00
2008-11-21 00:09:11 +00:00
if ( switch_channel_test_flag ( caller_channel , CF_REDIRECT ) ) {
2010-01-23 06:53:30 +00:00
if ( switch_channel_test_flag ( caller_channel , CF_RESET ) ) {
switch_channel_clear_flag ( caller_channel , CF_RESET ) ;
} else {
state = switch_channel_get_state ( caller_channel ) ;
if ( ! ( state = = CS_RESET | | state = = CS_PARK | | state = = CS_ROUTING ) ) {
switch_channel_set_state ( caller_channel , CS_RESET ) ;
}
2008-11-25 17:53:35 +00:00
}
2008-11-21 00:09:11 +00:00
}
2010-02-06 03:38:24 +00:00
2007-03-29 22:34:40 +00:00
return status ;
}
2010-01-22 00:51:32 +00:00
static void cleanup_proxy_mode_b ( switch_core_session_t * session )
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) ) {
switch_ivr_media ( switch_core_session_get_uuid ( session ) , SMF_NONE ) ;
}
}
static void cleanup_proxy_mode_a ( switch_core_session_t * session )
2008-09-19 19:58:01 +00:00
{
switch_core_session_t * sbsession ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2012-05-08 16:51:46 +00:00
int done = 0 ;
2008-09-19 19:58:01 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) ) {
2012-05-08 16:51:46 +00:00
if ( switch_core_session_get_partner ( session , & sbsession ) = = SWITCH_STATUS_SUCCESS ) {
2008-09-19 19:58:01 +00:00
switch_channel_t * sbchannel = switch_core_session_get_channel ( sbsession ) ;
2012-05-08 16:51:46 +00:00
if ( switch_channel_test_flag ( sbchannel , CF_PROXY_MODE ) ) {
/* Clear this now, otherwise will cause the one we're interested in to hang up too...*/
switch_channel_set_variable ( sbchannel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
switch_channel_hangup ( sbchannel , SWITCH_CAUSE_ATTENDED_TRANSFER ) ;
} else {
done = 1 ;
}
2008-09-19 19:58:01 +00:00
switch_core_session_rwunlock ( sbsession ) ;
}
}
2012-05-08 16:51:46 +00:00
if ( done ) return ;
2008-09-19 19:58:01 +00:00
switch_channel_set_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
switch_channel_set_variable ( channel , SWITCH_BRIDGE_VARIABLE , NULL ) ;
switch_channel_set_variable ( channel , SWITCH_BRIDGE_UUID_VARIABLE , NULL ) ;
}
2007-11-01 11:28:26 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_uuid_bridge ( const char * originator_uuid , const char * originatee_uuid )
2007-03-29 22:34:40 +00:00
{
2008-01-05 01:03:08 +00:00
switch_core_session_t * originator_session , * originatee_session , * swap_session ;
switch_channel_t * originator_channel , * originatee_channel , * swap_channel ;
2007-03-29 22:34:40 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-10-07 22:35:21 +00:00
switch_caller_profile_t * originator_cp , * originatee_cp ;
2008-11-21 00:09:11 +00:00
switch_channel_state_t state ;
2007-03-29 22:34:40 +00:00
if ( ( originator_session = switch_core_session_locate ( originator_uuid ) ) ) {
if ( ( originatee_session = switch_core_session_locate ( originatee_uuid ) ) ) {
originator_channel = switch_core_session_get_channel ( originator_session ) ;
originatee_channel = switch_core_session_get_channel ( originatee_session ) ;
2011-08-04 04:43:41 +00:00
if ( switch_channel_direction ( originatee_channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND & & ! switch_channel_test_flag ( originatee_channel , CF_DIALPLAN ) ) {
switch_channel_flip_cid ( originatee_channel ) ;
switch_channel_set_flag ( originatee_channel , CF_DIALPLAN ) ;
}
if ( switch_channel_direction ( originator_channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND & & ! switch_channel_test_flag ( originator_channel , CF_DIALPLAN ) ) {
switch_channel_flip_cid ( originator_channel ) ;
switch_channel_set_flag ( originator_channel , CF_DIALPLAN ) ;
}
2011-11-18 19:17:56 +00:00
if ( switch_channel_down_nosig ( originator_channel ) ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originator_session ) , SWITCH_LOG_DEBUG , " %s is hungup refusing to bridge. \n " , switch_channel_get_name ( originatee_channel ) ) ;
2008-03-13 01:08:42 +00:00
switch_core_session_rwunlock ( originator_session ) ;
switch_core_session_rwunlock ( originatee_session ) ;
return SWITCH_STATUS_FALSE ;
}
2011-02-24 16:17:33 +00:00
if ( ! switch_channel_media_up ( originator_channel ) ) {
if ( switch_channel_media_up ( originatee_channel ) ) {
2008-01-05 01:03:08 +00:00
swap_session = originator_session ;
originator_session = originatee_session ;
originatee_session = swap_session ;
2008-05-27 04:30:03 +00:00
2008-01-05 01:03:08 +00:00
swap_channel = originator_channel ;
originator_channel = originatee_channel ;
originatee_channel = swap_channel ;
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originatee_session ) , SWITCH_LOG_WARNING , " reversing order of channels so this will work! \n " ) ;
2008-01-05 01:03:08 +00:00
} else {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originator_session ) , SWITCH_LOG_CRIT , " Neither channel is answered, cannot bridge them. \n " ) ;
2008-03-06 19:51:11 +00:00
switch_core_session_rwunlock ( originator_session ) ;
switch_core_session_rwunlock ( originatee_session ) ;
2008-01-05 01:03:08 +00:00
return SWITCH_STATUS_FALSE ;
}
}
2010-01-22 00:51:32 +00:00
cleanup_proxy_mode_a ( originator_session ) ;
cleanup_proxy_mode_a ( originatee_session ) ;
2010-02-06 03:38:24 +00:00
2007-03-29 22:34:40 +00:00
/* override transmit state for originator_channel to bridge to originatee_channel
* install pointer to originatee_session into originator_channel
2008-05-05 15:30:55 +00:00
* set CF_TRANSFER on both channels and change state to CS_SOFT_EXECUTE to
2008-10-06 23:05:55 +00:00
* interrupt anything they are already doing .
2007-03-29 22:34:40 +00:00
* originatee_session will fall asleep and originator_session will bridge to it
*/
2008-05-27 04:30:03 +00:00
2008-11-21 00:09:11 +00:00
switch_channel_set_flag ( originator_channel , CF_REDIRECT ) ;
switch_channel_set_flag ( originatee_channel , CF_REDIRECT ) ;
2010-02-06 03:38:24 +00:00
2008-05-27 04:30:03 +00:00
2008-11-21 00:09:11 +00:00
switch_channel_set_variable ( originator_channel , SWITCH_UUID_BRIDGE , switch_core_session_get_uuid ( originatee_session ) ) ;
2007-12-06 15:46:54 +00:00
switch_channel_set_variable ( originator_channel , SWITCH_BRIDGE_CHANNEL_VARIABLE , switch_channel_get_name ( originatee_channel ) ) ;
switch_channel_set_variable ( originator_channel , SWITCH_BRIDGE_UUID_VARIABLE , switch_core_session_get_uuid ( originatee_session ) ) ;
2007-12-07 17:26:15 +00:00
switch_channel_set_variable ( originator_channel , SWITCH_SIGNAL_BOND_VARIABLE , switch_core_session_get_uuid ( originatee_session ) ) ;
2007-12-06 15:46:54 +00:00
switch_channel_set_variable ( originatee_channel , SWITCH_BRIDGE_CHANNEL_VARIABLE , switch_channel_get_name ( originator_channel ) ) ;
switch_channel_set_variable ( originatee_channel , SWITCH_BRIDGE_UUID_VARIABLE , switch_core_session_get_uuid ( originator_session ) ) ;
2007-12-07 17:26:15 +00:00
switch_channel_set_variable ( originatee_channel , SWITCH_SIGNAL_BOND_VARIABLE , switch_core_session_get_uuid ( originator_session ) ) ;
2007-12-06 15:46:54 +00:00
2010-02-06 03:38:24 +00:00
2007-12-08 00:14:21 +00:00
originator_cp = switch_channel_get_caller_profile ( originator_channel ) ;
originatee_cp = switch_channel_get_caller_profile ( originatee_channel ) ;
2008-05-27 04:30:03 +00:00
2008-01-05 01:03:08 +00:00
switch_channel_set_variable ( originatee_channel , " original_destination_number " , originatee_cp - > destination_number ) ;
switch_channel_set_variable ( originatee_channel , " original_caller_id_name " , originatee_cp - > caller_id_name ) ;
switch_channel_set_variable ( originatee_channel , " original_caller_id_number " , originatee_cp - > caller_id_number ) ;
switch_channel_set_variable ( originator_channel , " original_destination_number " , originator_cp - > destination_number ) ;
switch_channel_set_variable ( originator_channel , " original_caller_id_name " , originator_cp - > caller_id_name ) ;
switch_channel_set_variable ( originator_channel , " original_caller_id_number " , originator_cp - > caller_id_number ) ;
2007-12-08 00:14:21 +00:00
2008-05-27 04:30:03 +00:00
2009-10-07 22:35:21 +00:00
switch_channel_set_originator_caller_profile ( originatee_channel , switch_caller_profile_clone ( originatee_session , originator_cp ) ) ;
2007-12-08 00:14:21 +00:00
switch_channel_set_originatee_caller_profile ( originator_channel , switch_caller_profile_clone ( originator_session , originatee_cp ) ) ;
2008-01-10 00:45:28 +00:00
switch_channel_stop_broadcast ( originator_channel ) ;
switch_channel_stop_broadcast ( originatee_channel ) ;
2007-10-25 18:36:40 +00:00
switch_channel_set_flag ( originator_channel , CF_TRANSFER ) ;
switch_channel_set_flag ( originatee_channel , CF_TRANSFER ) ;
2008-01-05 01:03:08 +00:00
2008-11-21 00:09:11 +00:00
2008-01-05 01:03:08 +00:00
switch_channel_clear_flag ( originator_channel , CF_ORIGINATING ) ;
switch_channel_clear_flag ( originatee_channel , CF_ORIGINATING ) ;
2008-05-27 04:30:03 +00:00
2011-10-11 20:13:23 +00:00
originator_cp - > transfer_source = switch_core_sprintf ( originator_cp - > pool ,
" %ld:%s:uuid_br:%s " , ( long ) switch_epoch_time_now ( NULL ) , originator_cp - > uuid_str ,
switch_core_session_get_uuid ( originatee_session ) ) ;
switch_channel_add_variable_var_check ( originator_channel , SWITCH_TRANSFER_HISTORY_VARIABLE ,
originator_cp - > transfer_source , SWITCH_FALSE , SWITCH_STACK_PUSH ) ;
2011-12-08 23:33:31 +00:00
switch_channel_set_variable ( originator_channel , SWITCH_TRANSFER_SOURCE_VARIABLE , originator_cp - > transfer_source ) ;
2011-10-11 20:13:23 +00:00
2011-12-08 23:33:31 +00:00
2011-10-11 20:13:23 +00:00
originatee_cp - > transfer_source = switch_core_sprintf ( originatee_cp - > pool ,
" %ld:%s:uuid_br:%s " , ( long ) switch_epoch_time_now ( NULL ) , originatee_cp - > uuid_str ,
switch_core_session_get_uuid ( originator_session ) ) ;
switch_channel_add_variable_var_check ( originatee_channel , SWITCH_TRANSFER_HISTORY_VARIABLE ,
originatee_cp - > transfer_source , SWITCH_FALSE , SWITCH_STACK_PUSH ) ;
2011-12-08 23:33:31 +00:00
switch_channel_set_variable ( originatee_channel , SWITCH_TRANSFER_SOURCE_VARIABLE , originatee_cp - > transfer_source ) ;
2011-10-11 20:13:23 +00:00
2007-03-29 22:34:40 +00:00
/* change the states and let the chips fall where they may */
2009-10-07 04:30:19 +00:00
2010-07-01 14:33:44 +00:00
//switch_channel_set_variable(originator_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
//switch_channel_set_variable(originatee_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, NULL);
2008-11-21 00:09:11 +00:00
switch_channel_clear_state_handler ( originator_channel , NULL ) ;
switch_channel_clear_state_handler ( originatee_channel , NULL ) ;
2011-12-07 21:13:59 +00:00
switch_channel_clear_flag_recursive ( originator_channel , CF_BRIDGE_ORIGINATOR ) ;
2009-11-02 23:58:30 +00:00
switch_channel_clear_flag_recursive ( originatee_channel , CF_BRIDGE_ORIGINATOR ) ;
2011-12-07 21:13:59 +00:00
switch_channel_set_state_flag ( originator_channel , CF_BRIDGE_ORIGINATOR ) ;
switch_channel_clear_state_flag ( originatee_channel , CF_BRIDGE_ORIGINATOR ) ;
2008-11-21 00:09:11 +00:00
switch_channel_add_state_handler ( originator_channel , & uuid_bridge_state_handlers ) ;
switch_channel_add_state_handler ( originatee_channel , & uuid_bridge_state_handlers ) ;
2007-07-03 02:10:35 +00:00
2008-11-21 00:09:11 +00:00
state = switch_channel_get_state ( originator_channel ) ;
switch_channel_set_state ( originator_channel , state = = CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE ) ;
state = switch_channel_get_state ( originatee_channel ) ;
switch_channel_set_state ( originatee_channel , state = = CS_HIBERNATE ? CS_CONSUME_MEDIA : CS_HIBERNATE ) ;
2010-02-06 03:38:24 +00:00
2007-07-03 02:10:35 +00:00
status = SWITCH_STATUS_SUCCESS ;
2007-03-29 22:34:40 +00:00
2009-10-07 22:35:21 +00:00
switch_ivr_bridge_display ( originator_session , originatee_session ) ;
2007-05-15 02:21:53 +00:00
/* release the read locks we have on the channels */
switch_core_session_rwunlock ( originator_session ) ;
switch_core_session_rwunlock ( originatee_session ) ;
2007-03-29 22:34:40 +00:00
} else {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originator_session ) , SWITCH_LOG_DEBUG , " originatee uuid %s is not present \n " , originatee_uuid ) ;
2007-03-29 22:34:40 +00:00
switch_core_session_rwunlock ( originator_session ) ;
}
} else {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originator_session ) , SWITCH_LOG_DEBUG , " originator uuid %s is not present \n " , originator_uuid ) ;
2007-03-29 22:34:40 +00:00
}
return status ;
}
2007-12-08 00:14:21 +00:00
2008-05-24 17:28:04 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_find_bridged_uuid ( const char * uuid , char * b_uuid , switch_size_t blen )
{
switch_core_session_t * rsession ;
switch_status_t status = SWITCH_STATUS_FALSE ;
switch_assert ( uuid ) ;
2008-05-27 04:30:03 +00:00
2008-05-24 17:28:04 +00:00
if ( ( rsession = switch_core_session_locate ( uuid ) ) ) {
switch_channel_t * rchannel = switch_core_session_get_channel ( rsession ) ;
const char * brto ;
2012-05-01 00:37:59 +00:00
if ( ( brto = switch_channel_get_variable ( rchannel , " orignate_signal_bond " ) ) | |
2012-05-29 18:10:15 +00:00
( brto = switch_channel_get_partner_uuid ( rchannel ) ) ) {
2008-05-24 17:28:04 +00:00
switch_copy_string ( b_uuid , brto , blen ) ;
status = SWITCH_STATUS_SUCCESS ;
}
switch_core_session_rwunlock ( rsession ) ;
}
2008-05-27 04:30:03 +00:00
2008-05-24 17:28:04 +00:00
return status ;
}
SWITCH_DECLARE ( void ) switch_ivr_intercept_session ( switch_core_session_t * session , const char * uuid , switch_bool_t bleg )
2007-12-08 00:14:21 +00:00
{
2007-12-20 02:55:36 +00:00
switch_core_session_t * rsession , * bsession = NULL ;
2008-05-27 20:19:19 +00:00
switch_channel_t * channel , * rchannel , * bchannel = NULL ;
2010-05-05 16:15:09 +00:00
const char * buuid , * var ;
2008-05-24 17:28:04 +00:00
char brto [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] = " " ;
2010-05-05 16:15:09 +00:00
2008-05-24 17:28:04 +00:00
if ( bleg ) {
if ( switch_ivr_find_bridged_uuid ( uuid , brto , sizeof ( brto ) ) = = SWITCH_STATUS_SUCCESS ) {
2008-05-24 18:49:02 +00:00
uuid = switch_core_session_strdup ( session , brto ) ;
2008-05-24 17:28:04 +00:00
} else {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " no uuid bridged to %s \n " , uuid ) ;
2008-05-24 17:28:04 +00:00
return ;
}
}
2007-12-08 00:14:21 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( uuid ) | | ! ( rsession = switch_core_session_locate ( uuid ) ) ) {
2012-04-10 21:17:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " no uuid %s \n " , uuid ) ;
2007-12-08 00:14:21 +00:00
return ;
}
2008-05-27 04:30:03 +00:00
channel = switch_core_session_get_channel ( session ) ;
2007-12-08 00:14:21 +00:00
rchannel = switch_core_session_get_channel ( rsession ) ;
2012-05-29 18:10:15 +00:00
buuid = switch_channel_get_partner_uuid ( rchannel ) ;
2010-05-05 16:15:09 +00:00
if ( ( var = switch_channel_get_variable ( channel , " intercept_unbridged_only " ) ) & & switch_true ( var ) ) {
if ( ( switch_channel_test_flag ( rchannel , CF_BRIDGED ) ) ) {
switch_core_session_rwunlock ( rsession ) ;
return ;
}
}
2007-12-08 00:14:21 +00:00
2010-11-15 19:51:27 +00:00
if ( ( var = switch_channel_get_variable ( channel , " intercept_unanswered_only " ) ) & & switch_true ( var ) ) {
if ( ( switch_channel_test_flag ( rchannel , CF_ANSWERED ) ) ) {
switch_core_session_rwunlock ( rsession ) ;
return ;
}
}
2010-12-02 03:20:59 +00:00
switch_channel_answer ( channel ) ;
2007-12-08 00:14:21 +00:00
2010-05-05 16:15:09 +00:00
if ( ! zstr ( buuid ) ) {
2008-11-11 15:25:45 +00:00
if ( ( bsession = switch_core_session_locate ( buuid ) ) ) {
bchannel = switch_core_session_get_channel ( bsession ) ;
2011-10-31 13:06:15 +00:00
switch_channel_set_flag ( bchannel , CF_INTERCEPT ) ;
2008-11-11 15:25:45 +00:00
}
2007-12-20 02:55:36 +00:00
}
if ( ! switch_channel_test_flag ( rchannel , CF_ANSWERED ) ) {
switch_channel_answer ( rchannel ) ;
2008-05-27 04:30:03 +00:00
}
2008-05-27 20:19:19 +00:00
2011-04-15 19:22:45 +00:00
switch_channel_mark_hold ( rchannel , SWITCH_FALSE ) ;
2010-02-06 03:38:24 +00:00
switch_channel_set_state_flag ( rchannel , CF_TRANSFER ) ;
2008-05-27 20:19:19 +00:00
switch_channel_set_state ( rchannel , CS_PARK ) ;
2010-02-06 03:38:24 +00:00
2008-05-27 20:19:19 +00:00
if ( bchannel ) {
switch_channel_set_state_flag ( bchannel , CF_TRANSFER ) ;
switch_channel_set_state ( bchannel , CS_PARK ) ;
}
2011-11-03 15:29:43 +00:00
switch_channel_set_flag ( rchannel , CF_INTERCEPTED ) ;
2008-05-27 20:19:19 +00:00
switch_ivr_uuid_bridge ( switch_core_session_get_uuid ( session ) , uuid ) ;
switch_core_session_rwunlock ( rsession ) ;
2007-12-08 00:14:21 +00:00
2007-12-20 02:55:36 +00:00
if ( bsession ) {
switch_channel_hangup ( bchannel , SWITCH_CAUSE_PICKED_OFF ) ;
switch_core_session_rwunlock ( bsession ) ;
2007-12-08 00:14:21 +00:00
}
2007-12-20 02:55:36 +00:00
2010-02-06 03:38:24 +00:00
2007-12-08 00:14:21 +00:00
}
2008-01-27 05:02:52 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2008-01-27 05:02:52 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2008-07-03 19:12:26 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2008-01-27 05:02:52 +00:00
*/