2007-03-29 22:34:40 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2009-02-04 21:20:54 +00:00
* Copyright ( C ) 2005 / 2006 , 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>
2008-11-03 16:38:32 +00:00
# define DEFAULT_LEAD_FRAMES 50
2007-03-29 22:34:40 +00:00
static const switch_state_handler_table_t audio_bridge_peer_state_handlers ;
/* 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 ) ;
switch_status_t status ;
switch_frame_t * read_frame ;
2008-05-27 04:30:03 +00:00
vh - > up = 1 ;
while ( switch_channel_ready ( 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-05-27 04:30:03 +00:00
2008-02-01 21:22:27 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
}
2008-05-27 04:30:03 +00:00
2008-05-08 19:19:47 +00:00
switch_core_session_write_video_frame ( vh - > session_b , read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2008-05-27 04:30:03 +00:00
2008-02-01 21:22:27 +00:00
}
vh - > up = 0 ;
return NULL ;
}
static void launch_video ( struct vid_helper * vh )
{
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_detach_set ( thd_attr , 1 ) ;
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 ) ) ;
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
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 ;
2008-11-03 16:38:32 +00:00
uint32_t skip_frames ;
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 ;
switch_core_session_message_t * message , msg = { 0 } ;
void * user_data ;
switch_channel_t * chan_a , * chan_b ;
switch_frame_t * read_frame ;
switch_core_session_t * session_a , * session_b ;
2008-02-05 21:09:52 +00:00
uint32_t loop_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 } ;
int16_t silence_data [ SWITCH_RECOMMENDED_BUFFER_SIZE / 2 ] = { 0 } ;
2008-09-18 21:50:18 +00:00
const char * silence_var , * var ;
int silence_val = 0 , bypass_media_after_bridge = 0 ;
2008-02-05 21:09:52 +00:00
# ifdef SWITCH_VIDEO_IN_THREADS
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
}
2008-09-18 21:50:18 +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 ) ;
ans_a = switch_channel_test_flag ( chan_a , CF_ANSWERED ) ;
if ( ( originator = switch_channel_test_flag ( chan_a , CF_ORIGINATOR ) ) ) {
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 ) ;
2008-05-27 04:30:03 +00:00
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 ) ) {
2008-11-21 00:09:11 +00:00
if ( ! ( switch_channel_test_flag ( chan_b , CF_TRANSFER ) | | switch_channel_test_flag ( chan_b , CF_REDIRECT )
| | 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 ;
}
2008-09-18 21:50:18 +00:00
if ( ( var = switch_channel_get_variable ( chan_a , SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE ) ) & & switch_true ( var ) ) {
bypass_media_after_bridge = 1 ;
switch_channel_set_variable ( chan_a , SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE , NULL ) ;
}
2008-09-12 16:38:43 +00:00
if ( ( silence_var = switch_channel_get_variable ( chan_a , " bridge_generate_comfort_noise " ) ) ) {
switch_codec_t * read_codec = NULL ;
if ( ! ( read_codec = switch_core_session_get_read_codec ( session_a ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Channel has no media! \n " ) ;
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 " ,
NULL ,
read_codec - > implementation - > actual_samples_per_second ,
2008-10-20 17:48:42 +00:00
read_codec - > implementation - > microseconds_per_packet / 1000 ,
2008-09-12 16:38:43 +00:00
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL ,
switch_core_session_get_pool ( session_a ) ) ! = SWITCH_STATUS_SUCCESS ) {
silence_val = 0 ;
} else {
2008-09-12 16:43:29 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Setup generated silence from %s to %s at %d \n " , switch_channel_get_name ( chan_a ) , 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 ) ;
2008-10-20 17:48:42 +00:00
silence_frame . datalen = read_codec - > implementation - > decoded_bytes_per_packet ;
2008-09-12 16:38:43 +00:00
silence_frame . samples = silence_frame . datalen / sizeof ( int16_t ) ;
}
}
}
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-14 23:50:38 +00:00
loop_count + + ;
2007-05-09 19:44:15 +00:00
2008-05-20 15:40:27 +00:00
if ( ! switch_channel_test_flag ( chan_b , CF_BRIDGED ) ) {
goto end_of_bridge_loop ;
}
2007-08-30 15:38:21 +00:00
if ( ! switch_channel_ready ( chan_a ) ) {
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-03-30 22:13:19 +00:00
}
2007-04-16 19:32:08 +00:00
if ( ( b_state = switch_channel_get_state ( chan_b ) ) > = CS_HANGUP ) {
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2007-03-29 22:34:40 +00:00
}
2008-11-25 17:53:35 +00:00
if ( switch_channel_test_flag ( chan_a , CF_TRANSFER ) ) {
2008-10-11 16:37:15 +00:00
data - > clean_exit = 1 ;
}
2008-11-25 17:53:35 +00:00
if ( data - > clean_exit | | switch_channel_test_flag ( chan_b , CF_TRANSFER ) ) {
2007-03-29 22:34:40 +00:00
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-29 22:34:40 +00:00
}
2008-11-03 16:38:32 +00:00
if ( loop_count > DEFAULT_LEAD_FRAMES & & switch_core_session_private_event_count ( session_a ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_set_flag ( chan_b , CF_SUSPEND ) ;
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
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 ;
launch_video ( & vh ) ;
}
2008-02-05 21:09:52 +00:00
# endif
2008-02-01 21:22:27 +00:00
2008-11-03 16:38:32 +00:00
if ( loop_count > DEFAULT_LEAD_FRAMES & & bypass_media_after_bridge ) {
2008-09-18 21:50:18 +00:00
switch_ivr_nomedia ( switch_core_session_get_uuid ( session_a ) , SMF_REBRIDGE ) ;
bypass_media_after_bridge = 0 ;
}
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 ) {
2007-12-22 00:32:20 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s ended call via DTMF \n " , switch_channel_get_name ( chan_a ) ) ;
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 ) ;
}
2007-03-29 22:34:40 +00:00
}
}
if ( switch_core_session_dequeue_event ( session_a , & event ) = = SWITCH_STATUS_SUCCESS ) {
if ( input_callback ) {
status = input_callback ( session_a , event , SWITCH_INPUT_TYPE_EVENT , user_data , 0 ) ;
}
2008-10-02 17:10:05 +00:00
if ( event - > event_id ! = SWITCH_EVENT_COMMAND | | switch_core_session_receive_event ( session_b , & event ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
switch_event_destroy ( & event ) ;
}
}
if ( switch_core_session_dequeue_message ( session_b , & message ) = = SWITCH_STATUS_SUCCESS ) {
switch_core_session_receive_message ( session_a , message ) ;
if ( switch_test_flag ( message , SCSMF_DYNAMIC ) ) {
switch_safe_free ( message ) ;
} else {
message = NULL ;
}
}
if ( ! ans_a & & originator ) {
if ( ! ans_b & & switch_channel_test_flag ( chan_b , CF_ANSWERED ) ) {
2008-02-20 03:57:01 +00:00
if ( switch_channel_answer ( chan_a ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Media Establishment Failed. \n " , switch_channel_get_name ( chan_a ) ) ;
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2008-02-20 03:57:01 +00:00
}
2007-03-29 22:34:40 +00:00
ans_a + + ;
} else if ( ! pre_b & & switch_channel_test_flag ( chan_b , CF_EARLY_MEDIA ) ) {
2008-02-20 03:57:01 +00:00
if ( switch_channel_pre_answer ( chan_a ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s Media Establishment Failed. \n " , switch_channel_get_name ( chan_a ) ) ;
2008-03-13 01:08:42 +00:00
goto end_of_bridge_loop ;
2008-02-20 03:57:01 +00:00
}
2007-03-29 22:34:40 +00:00
pre_b + + ;
}
if ( ! pre_b ) {
switch_yield ( 10000 ) ;
continue ;
}
}
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 ) ) {
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
}
2008-09-12 16:38:43 +00:00
2008-11-03 16:38:32 +00:00
if ( data - > skip_frames ) {
data - > skip_frames - - ;
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 ) {
2008-08-15 21:49:43 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" %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 {
2008-08-15 21:49:43 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , 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
}
}
2008-09-12 16:38:43 +00:00
end_of_bridge_loop :
if ( silence_val ) {
switch_core_codec_destroy ( & silence_codec ) ;
}
2008-03-13 01:08:42 +00:00
2008-02-05 21:09:52 +00:00
# ifdef SWITCH_VIDEO_IN_THREADS
2008-05-27 04:30:03 +00:00
if ( vh . up ) {
vh . up = - 1 ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Ending video thread. \n " ) ;
while ( vh . up ) {
switch_yield ( 100000 ) ;
}
}
2008-02-05 21:09:52 +00:00
# endif
2008-02-01 21:22:27 +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
2008-03-13 01:08:42 +00:00
if ( ! switch_strlen_zero ( hook_var ) ) {
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 ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " \n Post-Bridge Command %s(%s): \n %s \n " , cmd , arg , switch_str_nil ( ( char * ) stream . data ) ) ;
switch_safe_free ( stream . data ) ;
}
2008-05-27 04:30:03 +00:00
if ( switch_channel_get_state ( chan_b ) > = CS_HANGUP ) {
2007-09-07 00:49:08 +00:00
if ( originator & & switch_channel_ready ( chan_a ) & & ! switch_channel_test_flag ( chan_a , CF_ANSWERED ) ) {
switch_channel_hangup ( chan_a , switch_channel_get_cause ( chan_b ) ) ;
}
}
2007-04-13 22:15:58 +00:00
msg . string_arg = data - > b_uuid ;
2007-03-29 22:34:40 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE ;
msg . from = __FILE__ ;
switch_core_session_receive_message ( session_a , & msg ) ;
2008-05-27 04:30:03 +00:00
2008-05-20 15:40:27 +00:00
if ( ! inner_bridge & & switch_channel_get_state ( chan_a ) < CS_HANGUP ) {
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 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " memory error! \n " ) ;
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-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 ) ;
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " BRIDGE THREAD DONE [%s] \n " , switch_channel_get_name ( chan_a ) ) ;
2008-05-20 15:40:27 +00:00
if ( ! inner_bridge ) {
switch_channel_clear_flag ( chan_a , CF_BRIDGED ) ;
}
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 ;
}
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 ;
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 ) ;
2008-11-25 17:53:35 +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 ) ;
2008-11-21 19:52:18 +00:00
} else {
2008-11-25 17:53:35 +00:00
if ( ! switch_channel_test_flag ( channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( channel , CF_REDIRECT ) & & bd & & ! bd - > clean_exit
& & state ! = CS_PARK & & state ! = CS_ROUTING & & ! switch_channel_test_flag ( channel , CF_INNER_BRIDGE ) ) {
2008-11-21 19:52:18 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
2008-11-25 17:53:35 +00:00
}
2007-12-27 22:24:30 +00:00
}
2008-11-25 17:53:35 +00:00
2007-03-29 22:34:40 +00:00
2008-07-09 16:03:03 +00:00
if ( switch_true ( switch_channel_get_variable ( channel , SWITCH_COPY_XML_CDR_VARIABLE ) ) ) {
switch_xml_t cdr ;
char * xml_text ;
if ( switch_ivr_generate_xml_cdr ( session , & cdr ) = = SWITCH_STATUS_SUCCESS ) {
if ( ( xml_text = switch_xml_toxml ( cdr , SWITCH_FALSE ) ) ) {
switch_channel_set_variable_partner ( channel , " b_leg_cdr " , xml_text ) ;
switch_safe_free ( xml_text ) ;
}
switch_xml_free ( cdr ) ;
}
}
2008-11-21 18:00:15 +00:00
if ( switch_channel_get_state ( channel ) = = CS_EXCHANGE_MEDIA ) {
2008-11-21 00:09:11 +00:00
switch_channel_set_state ( channel , CS_RESET ) ;
}
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
2008-05-12 13:46:07 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , 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
2007-12-08 00:14:21 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , 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
2007-12-08 00:14:21 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , 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
2008-11-21 00:09:11 +00:00
if ( switch_channel_test_flag ( channel , CF_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
2008-11-21 00:09:11 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , 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
2008-11-21 00:09:11 +00:00
if ( ! switch_channel_test_flag ( channel , CF_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
2008-11-21 00:09:11 +00:00
switch_channel_clear_flag ( channel , CF_ORIGINATOR ) ;
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 ;
uint8_t ready_a , ready_b ;
2008-08-19 19:24:00 +00:00
switch_channel_state_t state ;
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 ) ;
2007-12-08 00:14:21 +00:00
switch_channel_wait_for_state ( channel , other_channel , CS_RESET ) ;
2008-03-13 01:08:42 +00:00
if ( switch_ivr_wait_for_answer ( session , other_session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_core_session_rwunlock ( other_session ) ;
switch_channel_hangup ( channel , SWITCH_CAUSE_ORIGINATOR_CANCEL ) ;
return SWITCH_STATUS_FALSE ;
}
2007-12-08 00:14:21 +00:00
if ( switch_channel_get_state ( other_channel ) = = CS_RESET ) {
2008-05-05 15:30:55 +00:00
switch_channel_set_state ( other_channel , CS_SOFT_EXECUTE ) ;
2007-03-29 22:34:40 +00:00
}
2007-12-08 00:14:21 +00:00
2008-05-05 15:30:55 +00:00
switch_channel_wait_for_state ( channel , other_channel , CS_SOFT_EXECUTE ) ;
2008-03-13 01:08:42 +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
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 ) ;
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_FALSE ;
}
/* 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 ) ;
}
2008-01-10 00:57:06 +00:00
2007-03-29 22:34:40 +00:00
switch_ivr_multi_threaded_bridge ( session , other_session , NULL , NULL , NULL ) ;
2008-11-25 17:53:35 +00:00
2008-08-19 19:24:00 +00:00
state = switch_channel_get_state ( channel ) ;
2008-11-25 17:53:35 +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 ) ;
}
return SWITCH_STATUS_FALSE ;
}
static switch_status_t signal_bridge_on_hibernate ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
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
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 ) ) ;
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 ;
2008-05-27 04:30:03 +00:00
if ( switch_channel_test_flag ( channel , CF_ORIGINATOR ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_clear_flag ( channel , CF_ORIGINATOR ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_UNBRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
}
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2008-01-28 07:26:10 +00:00
switch_channel_t * other_channel = switch_core_session_get_channel ( other_session ) ;
2008-09-19 19:58:01 +00:00
const char * sbv = switch_channel_get_variable ( other_channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ;
if ( ! switch_strlen_zero ( sbv ) & & ! strcmp ( sbv , switch_core_session_get_uuid ( session ) ) ) {
switch_channel_set_variable ( other_channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
2007-03-29 22:34:40 +00:00
2008-09-19 19:58:01 +00:00
switch_channel_set_variable ( channel , SWITCH_BRIDGE_VARIABLE , NULL ) ;
switch_channel_set_variable ( other_channel , SWITCH_BRIDGE_VARIABLE , NULL ) ;
2007-03-29 22:34:40 +00:00
2008-09-19 19:58:01 +00:00
if ( switch_channel_get_state ( other_channel ) < CS_HANGUP ) {
switch_channel_hangup ( other_channel , switch_channel_get_cause ( channel ) ) ;
}
2008-03-04 00:52:54 +00:00
}
2008-09-19 19:58:01 +00:00
switch_channel_set_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
2007-12-19 23:24:55 +00:00
2007-03-29 22:34:40 +00:00
switch_core_session_rwunlock ( other_session ) ;
}
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
} ;
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 ;
2008-04-18 15:39:49 +00:00
if ( switch_channel_get_state ( peer_channel ) > = CS_HANGUP ) {
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( caller_channel , switch_channel_get_cause ( peer_channel ) ) ;
return SWITCH_STATUS_FALSE ;
}
if ( ! switch_channel_ready ( caller_channel ) ) {
switch_channel_hangup ( peer_channel , SWITCH_CAUSE_ORIGINATOR_CANCEL ) ;
return SWITCH_STATUS_FALSE ;
}
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 ) ) ;
2008-11-19 20:12:20 +00:00
switch_channel_set_flag ( caller_channel , CF_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 ) ;
/* 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 ) ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_BRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( caller_channel , event ) ;
switch_event_fire ( & event ) ;
}
2008-09-19 19:58:01 +00:00
2007-03-29 22:34:40 +00:00
switch_channel_set_state_flag ( caller_channel , CF_TRANSFER ) ;
switch_channel_set_state_flag ( peer_channel , CF_TRANSFER ) ;
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 ) ;
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 ) ;
}
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_SUCCESS ;
}
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 ) ;
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
switch_channel_set_flag ( caller_channel , CF_ORIGINATOR ) ;
2007-12-27 22:24:30 +00:00
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 ) ) {
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-03-29 22:34:40 +00:00
switch_core_session_message_t msg = { 0 } ;
2007-11-01 11:28:26 +00:00
const char * app , * data ;
2007-03-29 22:34:40 +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
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_BRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( caller_channel , event ) ;
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 ) ) ;
2008-09-04 18:29:43 +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 ) ;
2008-11-21 00:09:11 +00:00
if ( w_state < CS_HANGUP & & w_state ! = CS_ROUTING & & w_state ! = CS_PARK & &
! 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 ) ;
}
}
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
}
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 ;
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 ;
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 " ) ) ) {
2008-11-03 19:56:16 +00:00
switch_event_t * execute_event ;
2008-11-03 16:38:32 +00:00
2008-04-14 17:12:42 +00:00
data = switch_channel_get_variable ( caller_channel , " bridge_pre_execute_aleg_data " ) ;
2008-11-03 19:56:16 +00:00
if ( switch_event_create ( & execute_event , SWITCH_EVENT_COMMAND ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " call-command " , " execute " ) ;
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " execute-app-name " , app ) ;
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " execute-app-arg " , data ) ;
switch_event_add_header ( execute_event , SWITCH_STACK_BOTTOM , " lead-frames " , " %d " , 5 ) ;
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " event-lock " , " true " ) ;
switch_core_session_queue_private_event ( session , & execute_event ) ;
2008-11-03 16:38:32 +00:00
a_leg - > skip_frames = DEFAULT_LEAD_FRAMES ;
}
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 " ) ) ) {
2008-11-03 19:56:16 +00:00
switch_event_t * execute_event ;
2008-04-14 17:12:42 +00:00
data = switch_channel_get_variable ( caller_channel , " bridge_pre_execute_bleg_data " ) ;
2008-11-03 19:56:16 +00:00
if ( switch_event_create ( & execute_event , SWITCH_EVENT_COMMAND ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " call-command " , " execute " ) ;
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " execute-app-name " , app ) ;
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " execute-app-arg " , data ) ;
switch_event_add_header ( execute_event , SWITCH_STACK_BOTTOM , " lead-frames " , " %d " , 5 ) ;
switch_event_add_header_string ( execute_event , SWITCH_STACK_BOTTOM , " event-lock " , " true " ) ;
switch_core_session_queue_private_event ( peer_session , & execute_event ) ;
2008-11-03 16:38:32 +00:00
b_leg - > skip_frames = DEFAULT_LEAD_FRAMES ;
}
2008-04-14 17:12:42 +00:00
}
2008-09-09 16:31:53 +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 ) ;
2008-10-10 22:59:32 +00:00
2007-03-29 22:34:40 +00:00
switch_channel_clear_flag ( caller_channel , CF_ORIGINATOR ) ;
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 ) {
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
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 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Bridge Failed %s->%s \n " ,
switch_channel_get_name ( caller_channel ) , switch_channel_get_name ( peer_channel )
) ;
switch_channel_hangup ( peer_channel , SWITCH_CAUSE_NO_ANSWER ) ;
}
done :
2008-02-20 03:57:01 +00:00
if ( br & & switch_event_create ( & event , SWITCH_EVENT_CHANNEL_UNBRIDGE ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( caller_channel , event ) ;
switch_event_fire ( & event ) ;
}
2007-12-27 22:24:30 +00:00
state = switch_channel_get_state ( caller_channel ) ;
2008-11-21 00:09:11 +00:00
if ( ! switch_channel_test_flag ( caller_channel , CF_TRANSFER ) & & ! switch_channel_test_flag ( caller_channel , CF_REDIRECT )
& & ! a_leg - > clean_exit & & ! inner_bridge ) {
2008-08-13 21:46:06 +00:00
if ( ( state ! = CS_EXECUTE & & state ! = CS_SOFT_EXECUTE & & state ! = CS_PARK & & state ! = CS_ROUTING ) | |
2008-11-07 14:10:02 +00:00
( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) & & state < CS_HANGUP ) ) {
2008-11-21 19:52:18 +00:00
if ( switch_true ( switch_channel_get_variable ( caller_channel , SWITCH_PARK_AFTER_BRIDGE_VARIABLE ) ) ) {
2008-11-07 14:10:02 +00:00
switch_ivr_park_session ( session ) ;
2008-11-21 19:52:18 +00:00
} else if ( switch_true ( switch_channel_get_variable ( caller_channel , SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE ) ) ) {
switch_channel_hangup ( caller_channel , switch_channel_get_cause ( peer_channel ) ) ;
2008-11-07 14:10:02 +00:00
}
2007-12-07 16:14:09 +00:00
}
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 ) ) {
2008-11-25 17:53:35 +00:00
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-21 00:09:11 +00:00
}
2008-11-25 17:53:35 +00:00
2007-03-29 22:34:40 +00:00
return status ;
}
2008-09-19 19:58:01 +00:00
static void cleanup_proxy_mode ( switch_core_session_t * session )
{
switch_core_session_t * sbsession ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) ) {
const char * sbv = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2008-09-19 20:59:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Restore media to %s \n " , switch_channel_get_name ( channel ) ) ;
2008-09-19 19:58:01 +00:00
switch_ivr_media ( switch_core_session_get_uuid ( session ) , SMF_IMMEDIATE ) ;
if ( ! switch_strlen_zero ( sbv ) & & ( sbsession = switch_core_session_locate ( sbv ) ) ) {
switch_channel_t * sbchannel = switch_core_session_get_channel ( sbsession ) ;
switch_channel_hangup ( sbchannel , SWITCH_CAUSE_ATTENDED_TRANSFER ) ;
switch_core_session_rwunlock ( sbsession ) ;
}
}
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 ;
2007-12-08 00:14:21 +00:00
switch_caller_profile_t * cp , * originator_cp , * originatee_cp ;
2008-07-24 16:31:47 +00:00
char * p ;
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 ) ;
2008-03-13 01:08:42 +00:00
if ( switch_channel_get_state ( originator_channel ) > = CS_HANGUP ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s is hungup refusing to bridge. \n " , switch_channel_get_name ( originatee_channel ) ) ;
switch_core_session_rwunlock ( originator_session ) ;
switch_core_session_rwunlock ( originatee_session ) ;
return SWITCH_STATUS_FALSE ;
}
2008-01-05 01:03:08 +00:00
if ( ! switch_channel_test_flag ( originator_channel , CF_ANSWERED ) ) {
if ( switch_channel_test_flag ( originatee_channel , CF_ANSWERED ) ) {
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 ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " reversing order of channels so this will work! \n " ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , 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 ;
}
}
2008-09-19 19:58:01 +00:00
cleanup_proxy_mode ( originator_session ) ;
cleanup_proxy_mode ( originatee_session ) ;
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 ) ;
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
2008-09-19 19:58:01 +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
cp = switch_caller_profile_clone ( originatee_session , originatee_cp ) ;
cp - > destination_number = switch_core_strdup ( cp - > pool , originator_cp - > caller_id_number ) ;
cp - > caller_id_number = switch_core_strdup ( cp - > pool , originator_cp - > caller_id_number ) ;
cp - > caller_id_name = switch_core_strdup ( cp - > pool , originator_cp - > caller_id_name ) ;
2008-07-24 16:31:47 +00:00
cp - > rdnis = switch_core_strdup ( cp - > pool , originatee_cp - > destination_number ) ;
if ( ( p = strchr ( cp - > rdnis , ' @ ' ) ) ) {
* p = ' \0 ' ;
}
2007-12-08 00:14:21 +00:00
switch_channel_set_caller_profile ( originatee_channel , cp ) ;
switch_channel_set_originator_caller_profile ( originatee_channel , switch_caller_profile_clone ( originatee_session , originator_cp ) ) ;
2008-05-27 04:30:03 +00:00
2007-12-08 00:14:21 +00:00
cp = switch_caller_profile_clone ( originator_session , originator_cp ) ;
cp - > destination_number = switch_core_strdup ( cp - > pool , originatee_cp - > caller_id_number ) ;
cp - > caller_id_number = switch_core_strdup ( cp - > pool , originatee_cp - > caller_id_number ) ;
cp - > caller_id_name = switch_core_strdup ( cp - > pool , originatee_cp - > caller_id_name ) ;
2008-07-24 16:31:47 +00:00
cp - > rdnis = switch_core_strdup ( cp - > pool , originator_cp - > destination_number ) ;
if ( ( p = strchr ( cp - > rdnis , ' @ ' ) ) ) {
* p = ' \0 ' ;
}
2007-12-08 00:14:21 +00:00
switch_channel_set_caller_profile ( originator_channel , cp ) ;
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
2007-03-29 22:34:40 +00:00
/* change the states and let the chips fall where they may */
2008-11-21 00:09:11 +00:00
switch_channel_clear_state_handler ( originator_channel , NULL ) ;
switch_channel_clear_state_handler ( originatee_channel , NULL ) ;
switch_channel_set_state_flag ( originator_channel , CF_ORIGINATOR ) ;
switch_channel_clear_flag ( originatee_channel , CF_ORIGINATOR ) ;
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 ) ;
2007-07-03 02:10:35 +00:00
status = SWITCH_STATUS_SUCCESS ;
2007-03-29 22:34:40 +00:00
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 {
switch_core_session_rwunlock ( originator_session ) ;
2008-03-13 01:08:42 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " originatee uuid %s is not present \n " , originatee_uuid ) ;
2007-03-29 22:34:40 +00:00
}
} else {
2008-03-13 01:08:42 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , 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 ;
if ( ( brto = switch_channel_get_variable ( rchannel , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
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 ;
2007-12-08 00:14:21 +00:00
const char * buuid ;
2008-05-24 17:28:04 +00:00
char brto [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] = " " ;
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 {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " no uuid bridged to %s \n " , uuid ) ;
return ;
}
}
2007-12-08 00:14:21 +00:00
if ( switch_strlen_zero ( uuid ) | | ! ( rsession = switch_core_session_locate ( uuid ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " no uuid %s \n " , uuid ) ;
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 ) ;
2007-12-20 02:55:36 +00:00
switch_channel_pre_answer ( channel ) ;
2007-12-08 00:14:21 +00:00
2007-12-20 02:55:36 +00:00
if ( ( buuid = switch_channel_get_variable ( rchannel , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
2008-11-11 15:25:45 +00:00
if ( ( bsession = switch_core_session_locate ( buuid ) ) ) {
bchannel = switch_core_session_get_channel ( bsession ) ;
}
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
2008-12-31 01:08:51 +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 ) ;
if ( bchannel ) {
switch_channel_set_state_flag ( bchannel , CF_TRANSFER ) ;
switch_channel_set_state ( bchannel , CS_PARK ) ;
}
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
2008-05-27 20:19:19 +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
*/