2007-03-29 22:34:40 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2009-02-13 23:37:37 +00:00
* Copyright ( C ) 2005 - 2009 , 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
* Michael Jerris < mike @ jerris . com >
2008-10-22 17:51:34 +00:00
* Travis Cross < tc @ traviscross . com >
2007-03-29 22:34:40 +00:00
*
* switch_ivr_originate . c - - IVR Library ( originate )
*
*/
2008-01-27 17:36:53 +00:00
2007-03-29 22:34:40 +00:00
# include <switch.h>
static const switch_state_handler_table_t originate_state_handlers ;
2008-05-05 15:30:55 +00:00
static switch_status_t originate_on_consume_media_transmit ( switch_core_session_t * session )
2008-03-03 18:05:07 +00:00
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2008-05-27 04:30:03 +00:00
2009-08-31 19:09:26 +00:00
/* testing out not using this, we probably don't need it anymore now that we have audio sync */
#if 0
2008-12-26 17:09:09 +00:00
if ( ! switch_channel_test_flag ( channel , CF_PROXY_MODE ) ) {
while ( switch_channel_get_state ( channel ) = = CS_CONSUME_MEDIA & & ! switch_channel_test_flag ( channel , CF_TAGGED ) ) {
2009-01-06 23:26:49 +00:00
if ( ! switch_channel_media_ready ( channel ) ) {
switch_yield ( 10000 ) ;
} else {
switch_ivr_sleep ( session , 10 , SWITCH_FALSE , NULL ) ;
}
2008-12-26 17:09:09 +00:00
}
}
2009-08-31 19:09:26 +00:00
# endif
2008-12-26 17:09:09 +00:00
2008-03-03 18:05:07 +00:00
switch_channel_clear_state_handler ( channel , & originate_state_handlers ) ;
return SWITCH_STATUS_FALSE ;
}
2008-05-05 15:30:55 +00:00
static switch_status_t originate_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
2009-02-03 17:17:31 +00:00
if ( switch_channel_get_state ( channel ) = = CS_ROUTING ) {
/* put the channel in a passive state until it is answered */
switch_channel_set_state ( channel , CS_CONSUME_MEDIA ) ;
}
2008-03-03 18:05:07 +00:00
2007-03-29 22:34:40 +00:00
return SWITCH_STATUS_FALSE ;
}
static const switch_state_handler_table_t originate_state_handlers = {
/*.on_init */ NULL ,
2008-05-05 15:30:55 +00:00
/*.on_routing */ originate_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 */ NULL ,
/*.on_soft_execute */ originate_on_consume_media_transmit ,
/*.on_consume_media */ originate_on_consume_media_transmit
2007-03-29 22:34:40 +00:00
} ;
2009-01-19 17:54:54 +00:00
typedef struct {
switch_core_session_t * peer_session ;
switch_channel_t * peer_channel ;
switch_caller_profile_t * caller_profile ;
uint8_t ring_ready ;
uint8_t early_media ;
uint8_t answered ;
2009-01-20 00:21:58 +00:00
uint32_t per_channel_timelimit_sec ;
uint32_t per_channel_progress_timelimit_sec ;
2009-03-04 04:19:33 +00:00
uint32_t per_channel_delay_start ;
2009-01-19 17:54:54 +00:00
} originate_status_t ;
typedef struct {
switch_core_session_t * session ;
int32_t idx ;
uint32_t hups ;
char file [ 512 ] ;
char key [ 80 ] ;
uint8_t early_ok ;
uint8_t ring_ready ;
2009-02-11 00:22:41 +00:00
uint8_t instant_ringback ;
2009-01-19 17:54:54 +00:00
uint8_t sent_ring ;
uint8_t progress ;
uint8_t return_ring_ready ;
2009-01-19 23:15:59 +00:00
uint8_t monitor_early_media_ring ;
uint8_t monitor_early_media_fail ;
2009-01-20 15:39:32 +00:00
uint8_t gen_ringback ;
uint8_t ignore_early_media ;
uint8_t ignore_ring_ready ;
2009-02-11 14:56:22 +00:00
int monitor_early_media_ring_count ;
int monitor_early_media_ring_total ;
2009-07-14 17:19:14 +00:00
int cancel_timeout ;
2009-01-19 17:54:54 +00:00
} originate_global_t ;
2007-03-29 22:34:40 +00:00
typedef enum {
2008-04-16 21:29:57 +00:00
IDX_TIMEOUT = - 3 ,
2007-03-29 22:34:40 +00:00
IDX_CANCEL = - 2 ,
IDX_NADA = - 1
} abort_t ;
struct key_collect {
char * key ;
char * file ;
switch_core_session_t * session ;
} ;
2008-05-27 04:30:03 +00:00
static void * SWITCH_THREAD_FUNC collect_thread_run ( switch_thread_t * thread , void * obj )
2007-03-29 22:34:40 +00:00
{
struct key_collect * collect = ( struct key_collect * ) obj ;
switch_channel_t * channel = switch_core_session_get_channel ( collect - > session ) ;
2007-09-29 01:06:08 +00:00
char buf [ 10 ] = SWITCH_BLANK_STRING ;
2007-03-29 22:34:40 +00:00
char * p , term ;
2008-10-14 18:03:14 +00:00
if ( collect - > session ) {
if ( switch_core_session_read_lock ( collect - > session ) ! = SWITCH_STATUS_SUCCESS ) {
return NULL ;
}
} else {
return NULL ;
}
2008-12-10 00:48:24 +00:00
switch_ivr_sleep ( collect - > session , 0 , SWITCH_TRUE , NULL ) ;
2008-12-01 16:21:27 +00:00
2007-03-29 22:34:40 +00:00
if ( ! strcasecmp ( collect - > key , " exec " ) ) {
char * data ;
2008-11-13 17:40:25 +00:00
switch_application_interface_t * application_interface ;
2007-03-29 22:34:40 +00:00
char * app_name , * app_data ;
if ( ! ( data = collect - > file ) ) {
goto wbreak ;
}
app_name = data ;
if ( ( app_data = strchr ( app_name , ' ' ) ) ) {
* app_data + + = ' \0 ' ;
}
if ( ( application_interface = switch_loadable_module_get_application_interface ( app_name ) ) = = 0 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( collect - > session ) , SWITCH_LOG_ERROR , " Invalid Application %s \n " , app_name ) ;
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
2008-11-12 19:28:05 +00:00
UNPROTECT_INTERFACE ( application_interface ) ;
2007-03-29 22:34:40 +00:00
goto wbreak ;
}
if ( ! application_interface - > application_function ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( collect - > session ) , SWITCH_LOG_ERROR , " No Function for %s \n " , app_name ) ;
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
goto wbreak ;
}
2007-04-21 01:03:58 +00:00
switch_core_session_exec ( collect - > session , application_interface , app_data ) ;
2008-05-27 04:30:03 +00:00
2009-02-25 03:41:18 +00:00
if ( switch_channel_up ( channel ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_set_flag ( channel , CF_WINNER ) ;
}
goto wbreak ;
}
2009-03-16 01:37:18 +00:00
if ( ! switch_channel_up ( channel ) ) {
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
goto wbreak ;
}
while ( switch_channel_ready ( channel ) ) {
memset ( buf , 0 , sizeof ( buf ) ) ;
if ( collect - > file ) {
switch_input_args_t args = { 0 } ;
args . buf = buf ;
args . buflen = sizeof ( buf ) ;
switch_ivr_play_file ( collect - > session , NULL , collect - > file , & args ) ;
} else {
2008-01-07 16:49:46 +00:00
switch_ivr_collect_digits_count ( collect - > session , buf , sizeof ( buf ) , 1 , SWITCH_BLANK_STRING , & term , 0 , 0 , 0 ) ;
2007-03-29 22:34:40 +00:00
}
for ( p = buf ; * p ; p + + ) {
if ( * collect - > key = = * p ) {
switch_channel_set_flag ( channel , CF_WINNER ) ;
goto wbreak ;
}
}
}
2008-10-14 18:03:14 +00:00
wbreak :
switch_core_session_rwunlock ( collect - > session ) ;
2007-03-29 22:34:40 +00:00
return NULL ;
}
static void launch_collect_thread ( struct key_collect * collect )
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
switch_threadattr_create ( & thd_attr , switch_core_session_get_pool ( collect - > session ) ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
2007-03-30 00:13:31 +00:00
switch_thread_create ( & thread , thd_attr , collect_thread_run , collect , switch_core_session_get_pool ( collect - > session ) ) ;
2007-03-29 22:34:40 +00:00
}
2009-02-03 20:33:24 +00:00
static int check_per_channel_timeouts ( originate_global_t * oglobals ,
originate_status_t * originate_status ,
2008-10-09 00:38:59 +00:00
int max ,
time_t start )
{
int x = 0 , i ;
2009-01-25 21:23:07 +00:00
time_t elapsed = switch_epoch_time_now ( NULL ) - start ;
2008-10-09 00:38:59 +00:00
2009-07-14 17:19:14 +00:00
if ( oglobals - > cancel_timeout > 0 ) {
return 0 ;
}
2008-10-09 00:38:59 +00:00
for ( i = 0 ; i < max ; i + + ) {
2009-03-04 04:19:33 +00:00
if ( originate_status [ i ] . peer_channel & & originate_status [ i ] . per_channel_delay_start & & elapsed > originate_status [ i ] . per_channel_delay_start ) {
switch_channel_clear_flag ( originate_status [ i ] . peer_channel , CF_BLOCK_STATE ) ;
originate_status [ i ] . per_channel_delay_start = 0 ;
}
2009-02-25 03:41:18 +00:00
if ( originate_status [ i ] . peer_channel & & switch_channel_up ( originate_status [ i ] . peer_channel ) ) {
2009-01-20 00:21:58 +00:00
if ( originate_status [ i ] . per_channel_progress_timelimit_sec & & elapsed > originate_status [ i ] . per_channel_progress_timelimit_sec & &
2008-10-09 00:38:59 +00:00
! (
2009-01-19 17:54:54 +00:00
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_RING_READY ) | |
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_ANSWERED ) | |
2009-02-03 20:33:24 +00:00
( ! oglobals - > monitor_early_media_ring & & switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_EARLY_MEDIA ) )
2008-10-09 00:38:59 +00:00
)
) {
2009-01-19 17:54:54 +00:00
switch_channel_hangup ( originate_status [ i ] . peer_channel , SWITCH_CAUSE_PROGRESS_TIMEOUT ) ;
2008-10-09 00:38:59 +00:00
x + + ;
}
2009-01-20 00:21:58 +00:00
if ( originate_status [ i ] . per_channel_timelimit_sec & & elapsed > originate_status [ i ] . per_channel_timelimit_sec ) {
2009-01-19 17:54:54 +00:00
switch_channel_hangup ( originate_status [ i ] . peer_channel , SWITCH_CAUSE_ALLOTTED_TIMEOUT ) ;
2008-10-09 00:38:59 +00:00
x + + ;
}
}
}
return x ;
}
2009-01-19 23:15:59 +00:00
static switch_bool_t monitor_callback ( switch_core_session_t * session , const char * app , const char * data )
{
if ( app ) {
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
if ( ! strcmp ( app , " fail " ) ) {
2009-01-22 23:50:01 +00:00
const char * bd = switch_channel_get_variable ( channel , " monitor_fail_dispo " ) ;
if ( ! bd ) {
bd = " monitor_early_media_fail " ;
}
switch_channel_set_variable ( channel , " originate_disposition " , bd ) ;
2009-01-19 23:15:59 +00:00
switch_channel_hangup ( channel , data ? switch_channel_str2cause ( data ) : SWITCH_CAUSE_USER_BUSY ) ;
} else if ( ! strcmp ( app , " ring " ) ) {
originate_global_t * oglobals = ( originate_global_t * ) switch_channel_get_private ( channel , " _oglobals_ " ) ;
2009-01-22 23:50:01 +00:00
const char * bd = switch_channel_get_variable ( channel , " monitor_ring_dispo " ) ;
if ( ! bd ) {
bd = " monitor_early_media_ring " ;
}
switch_channel_set_variable ( channel , " originate_disposition " , bd ) ;
2009-02-11 00:16:36 +00:00
2009-01-19 23:15:59 +00:00
if ( oglobals ) {
2009-02-11 00:16:36 +00:00
if ( oglobals - > monitor_early_media_ring_total & & + + oglobals - > monitor_early_media_ring_count < oglobals - > monitor_early_media_ring_total ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Ring %d/%d \n " ,
2009-02-11 00:16:36 +00:00
oglobals - > monitor_early_media_ring_count , oglobals - > monitor_early_media_ring_total ) ;
return SWITCH_TRUE ;
}
2009-01-19 23:15:59 +00:00
switch_channel_set_private ( channel , " _oglobals_ " , NULL ) ;
2009-01-19 23:30:41 +00:00
if ( ! oglobals - > progress ) {
oglobals - > progress = 1 ;
}
2009-01-20 15:39:32 +00:00
if ( ! oglobals - > ring_ready & & ! oglobals - > ignore_ring_ready ) {
2009-01-19 23:30:41 +00:00
oglobals - > ring_ready = 1 ;
}
2009-01-20 15:39:32 +00:00
if ( ! oglobals - > ignore_early_media & & ! oglobals - > early_ok ) {
oglobals - > early_ok = 1 ;
}
2009-01-19 23:15:59 +00:00
}
}
}
return SWITCH_FALSE ;
}
2009-01-19 21:11:01 +00:00
static uint8_t check_channel_status ( originate_global_t * oglobals , originate_status_t * originate_status , uint32_t len )
2007-03-29 22:34:40 +00:00
{
uint32_t i ;
2009-01-19 21:11:01 +00:00
uint8_t rval = 0 ;
2009-01-16 16:22:29 +00:00
switch_channel_t * caller_channel = NULL ;
int pindex = - 1 ;
2009-02-11 14:56:22 +00:00
char bug_key [ 256 ] = " " ;
2009-01-19 21:11:01 +00:00
oglobals - > hups = 0 ;
oglobals - > idx = IDX_NADA ;
2009-02-11 14:56:22 +00:00
2009-01-16 16:22:29 +00:00
2009-01-19 17:54:54 +00:00
if ( oglobals - > session ) {
caller_channel = switch_core_session_get_channel ( oglobals - > session ) ;
2009-01-16 16:22:29 +00:00
}
2009-01-19 17:54:54 +00:00
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
for ( i = 0 ; i < len ; i + + ) {
2008-01-05 01:03:08 +00:00
switch_channel_state_t state ;
2009-02-11 00:16:36 +00:00
if ( ! ( originate_status [ i ] . peer_channel & & originate_status [ i ] . peer_session ) ) {
2009-09-14 18:03:25 +00:00
oglobals - > hups + + ;
2007-03-29 22:34:40 +00:00
continue ;
}
2009-01-19 17:54:54 +00:00
if ( switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_RING_READY ) ) {
if ( ! originate_status [ i ] . ring_ready ) {
originate_status [ i ] . ring_ready = 1 ;
}
if ( ! oglobals - > ring_ready ) {
oglobals - > ring_ready = 1 ;
}
2007-03-29 22:34:40 +00:00
}
2009-09-14 18:03:25 +00:00
2009-01-19 17:54:54 +00:00
if ( switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_EARLY_MEDIA ) ) {
if ( ! originate_status [ i ] . early_media ) {
originate_status [ i ] . early_media = 1 ;
if ( oglobals - > early_ok ) {
pindex = i ;
}
2009-01-19 23:15:59 +00:00
if ( oglobals - > monitor_early_media_fail ) {
const char * var = switch_channel_get_variable ( originate_status [ i ] . peer_channel , " monitor_early_media_fail " ) ;
if ( ! switch_strlen_zero ( var ) ) {
char * fail_array [ 128 ] = { 0 } ;
int fail_count = 0 ;
char * fail_data = strdup ( var ) ;
int fx ;
2009-02-11 00:16:36 +00:00
int y = 0 ;
2009-01-19 23:15:59 +00:00
switch_assert ( fail_data ) ;
fail_count = switch_separate_string ( fail_data , ' ! ' , fail_array , ( sizeof ( fail_array ) / sizeof ( fail_array [ 0 ] ) ) ) ;
for ( fx = 0 ; fx < fail_count ; fx + + ) {
char * cause = fail_array [ fx ] ;
int hits = 2 ;
char * p , * q ;
if ( ! ( p = strchr ( cause , ' : ' ) ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_ERROR , " Parse Error \n " ) ;
2009-01-19 23:15:59 +00:00
continue ;
}
* p + + = ' \0 ' ;
if ( ! p ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_ERROR , " Parse Error \n " ) ;
2009-01-19 23:15:59 +00:00
continue ;
}
if ( ! ( hits = atoi ( p ) ) ) {
hits = 2 ;
}
if ( ! ( p = strchr ( p , ' : ' ) ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_ERROR , " Parse Error \n " ) ;
2009-01-19 23:15:59 +00:00
continue ;
}
* p + + = ' \0 ' ;
if ( ! p ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_ERROR , " Parse Error \n " ) ;
2009-01-19 23:15:59 +00:00
continue ;
}
for ( q = p ; q & & * q ; q + + ) {
if ( * q = = ' + ' ) {
* q = ' , ' ;
}
}
2009-02-11 00:16:36 +00:00
switch_snprintf ( bug_key , sizeof ( bug_key ) , " monitor_early_media_fail_%d " , + + y ) ;
2009-01-19 23:15:59 +00:00
switch_ivr_tone_detect_session ( originate_status [ i ] . peer_session ,
2009-02-11 00:16:36 +00:00
bug_key ,
p , " r " , 0 ,
hits ,
" fail " ,
cause , monitor_callback ) ;
2009-01-19 23:15:59 +00:00
}
switch_safe_free ( fail_data ) ;
}
}
if ( oglobals - > monitor_early_media_ring ) {
const char * var = switch_channel_get_variable ( originate_status [ i ] . peer_channel , " monitor_early_media_ring " ) ;
2009-02-11 00:16:36 +00:00
const char * var_total = switch_channel_get_variable ( originate_status [ i ] . peer_channel , " monitor_early_media_ring_total " ) ;
2009-01-19 23:15:59 +00:00
if ( ! switch_strlen_zero ( var ) ) {
char * ring_array [ 128 ] = { 0 } ;
int ring_count = 0 ;
char * ring_data = strdup ( var ) ;
int fx ;
2009-02-11 00:16:36 +00:00
int y = 0 ;
2009-01-19 23:15:59 +00:00
switch_assert ( ring_data ) ;
ring_count = switch_separate_string ( ring_data , ' ! ' , ring_array , ( sizeof ( ring_array ) / sizeof ( ring_array [ 0 ] ) ) ) ;
for ( fx = 0 ; fx < ring_count ; fx + + ) {
int hits = 2 ;
char * p = ring_array [ fx ] , * q ;
2009-01-21 02:18:03 +00:00
if ( ! p ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_ERROR , " Parse Error \n " ) ;
2009-01-21 02:18:03 +00:00
continue ;
}
2009-01-19 23:15:59 +00:00
if ( ! ( hits = atoi ( p ) ) ) {
hits = 2 ;
}
if ( ! ( p = strchr ( p , ' : ' ) ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_ERROR , " Parse Error \n " ) ;
2009-01-19 23:15:59 +00:00
continue ;
}
* p + + = ' \0 ' ;
if ( ! p ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_ERROR , " Parse Error \n " ) ;
2009-01-19 23:15:59 +00:00
continue ;
}
for ( q = p ; q & & * q ; q + + ) {
if ( * q = = ' + ' ) {
* q = ' , ' ;
}
}
switch_channel_set_private ( originate_status [ i ] . peer_channel , " _oglobals_ " , oglobals ) ;
2009-02-11 00:16:36 +00:00
switch_snprintf ( bug_key , sizeof ( bug_key ) , " monitor_early_media_ring_%d " , + + y ) ;
2009-01-19 23:15:59 +00:00
switch_ivr_tone_detect_session ( originate_status [ i ] . peer_session ,
2009-02-11 00:16:36 +00:00
bug_key ,
2009-01-19 23:15:59 +00:00
p , " r " , 0 , hits , " ring " , NULL , monitor_callback ) ;
}
2009-02-11 00:16:36 +00:00
if ( var_total ) {
int tmp = atoi ( var_total ) ;
if ( tmp > 0 & & tmp < 100 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( originate_status [ i ] . peer_session ) , SWITCH_LOG_DEBUG , " %s setting ring total to %d \n " ,
2009-02-11 00:16:36 +00:00
switch_channel_get_name ( originate_status [ i ] . peer_channel ) , tmp ) ;
oglobals - > monitor_early_media_ring_total = tmp ;
}
}
2009-01-19 23:15:59 +00:00
switch_safe_free ( ring_data ) ;
}
}
2009-01-19 17:54:54 +00:00
}
2009-01-20 15:39:32 +00:00
2009-01-19 23:30:41 +00:00
if ( ! oglobals - > monitor_early_media_ring ) {
if ( ! oglobals - > progress ) {
oglobals - > progress = 1 ;
}
2009-02-03 20:33:24 +00:00
2009-01-20 15:39:32 +00:00
if ( ! oglobals - > ring_ready & & ! oglobals - > ignore_ring_ready ) {
2009-01-19 23:30:41 +00:00
oglobals - > ring_ready = 1 ;
}
2009-01-19 17:54:54 +00:00
}
2008-06-23 22:07:22 +00:00
}
2009-01-19 17:54:54 +00:00
if ( switch_core_session_private_event_count ( originate_status [ i ] . peer_session ) ) {
switch_ivr_parse_all_events ( originate_status [ i ] . peer_session ) ;
2008-12-08 17:08:26 +00:00
}
2009-01-19 17:54:54 +00:00
state = switch_channel_get_state ( originate_status [ i ] . peer_channel ) ;
if ( state > = CS_HANGUP | | state = = CS_RESET | | switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_TRANSFER ) | |
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_REDIRECT ) | |
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_BRIDGED ) | |
! switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_ORIGINATING )
2008-05-27 04:30:03 +00:00
) {
2009-01-19 17:54:54 +00:00
( oglobals - > hups ) + + ;
} else if ( ( switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_ANSWERED ) | |
( oglobals - > early_ok & & switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_EARLY_MEDIA ) ) | |
( oglobals - > ring_ready & & oglobals - > return_ring_ready & & len = = 1 & &
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_RING_READY ) )
)
& & ! switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_TAGGED )
) {
2009-01-16 16:22:29 +00:00
2009-01-19 17:54:54 +00:00
if ( ! switch_strlen_zero ( oglobals - > key ) ) {
2007-03-29 22:34:40 +00:00
struct key_collect * collect ;
2009-07-14 17:19:14 +00:00
if ( oglobals - > cancel_timeout < 0 ) {
oglobals - > cancel_timeout = 1 ;
}
2009-01-19 17:54:54 +00:00
if ( ( collect = switch_core_session_alloc ( originate_status [ i ] . peer_session , sizeof ( * collect ) ) ) ) {
switch_channel_set_flag ( originate_status [ i ] . peer_channel , CF_TAGGED ) ;
if ( ! switch_strlen_zero ( oglobals - > key ) ) {
collect - > key = switch_core_session_strdup ( originate_status [ i ] . peer_session , oglobals - > key ) ;
}
if ( ! switch_strlen_zero ( oglobals - > file ) ) {
collect - > file = switch_core_session_strdup ( originate_status [ i ] . peer_session , oglobals - > file ) ;
2007-03-29 22:34:40 +00:00
}
2009-08-31 19:09:26 +00:00
switch_channel_audio_sync ( originate_status [ i ] . peer_channel ) ;
2009-01-19 17:54:54 +00:00
collect - > session = originate_status [ i ] . peer_session ;
2007-03-29 22:34:40 +00:00
launch_collect_thread ( collect ) ;
}
} else {
2009-01-19 17:54:54 +00:00
oglobals - > idx = i ;
2009-01-16 16:22:29 +00:00
pindex = ( uint32_t ) i ;
rval = 0 ;
goto end ;
2007-03-29 22:34:40 +00:00
}
2009-01-19 17:54:54 +00:00
} else if ( switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_WINNER ) ) {
oglobals - > idx = i ;
2009-01-16 16:22:29 +00:00
rval = 0 ;
pindex = ( uint32_t ) i ;
goto end ;
2007-03-29 22:34:40 +00:00
}
}
2009-01-19 17:54:54 +00:00
if ( oglobals - > hups = = len ) {
2009-01-16 16:22:29 +00:00
rval = 0 ;
2007-03-29 22:34:40 +00:00
} else {
2009-01-16 16:22:29 +00:00
rval = 1 ;
}
end :
if ( pindex > - 1 & & caller_channel & & switch_channel_ready ( caller_channel ) & & ! switch_channel_media_ready ( caller_channel ) ) {
const char * var = switch_channel_get_variable ( caller_channel , " inherit_codec " ) ;
if ( switch_true ( var ) ) {
2009-03-27 23:50:34 +00:00
switch_codec_implementation_t impl = { 0 } ;
2009-03-27 18:39:02 +00:00
char tmp [ 128 ] = " " ;
2009-01-16 16:22:29 +00:00
2009-03-27 18:39:02 +00:00
2009-03-27 23:50:34 +00:00
if ( switch_core_session_get_read_impl ( originate_status [ pindex ] . peer_session , & impl ) = = SWITCH_STATUS_SUCCESS ) {
switch_snprintf ( tmp , sizeof ( tmp ) , " %s@%uh@%ui " , impl . iananame , impl . samples_per_second , impl . microseconds_per_packet / 1000 ) ;
switch_channel_set_variable ( caller_channel , " absolute_codec_string " , tmp ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( caller_channel ) , SWITCH_LOG_DEBUG , " Setting codec string on %s to %s \n " , switch_channel_get_name ( caller_channel ) , tmp ) ;
2009-03-27 23:50:34 +00:00
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( originate_status [ pindex ] . peer_channel ) , SWITCH_LOG_WARNING , " Error inheriting codec. Channel %s has no read codec yet. \n " ,
2009-03-27 23:50:34 +00:00
switch_channel_get_name ( originate_status [ pindex ] . peer_channel ) ) ;
}
2009-03-27 18:39:02 +00:00
2009-01-16 16:22:29 +00:00
}
2007-03-29 22:34:40 +00:00
}
2009-01-16 16:22:29 +00:00
return rval ;
2007-03-29 22:34:40 +00:00
}
struct ringback {
switch_buffer_t * audio_buffer ;
teletone_generation_session_t ts ;
switch_file_handle_t fhb ;
switch_file_handle_t * fh ;
2008-12-09 00:32:51 +00:00
int silence ;
2007-03-29 22:34:40 +00:00
uint8_t asis ;
} ;
typedef struct ringback ringback_t ;
2008-05-27 04:30:03 +00:00
static int teletone_handler ( teletone_generation_session_t * ts , teletone_tone_map_t * map )
2007-03-29 22:34:40 +00:00
{
ringback_t * tto = ts - > user_data ;
int wrote ;
if ( ! tto ) {
return - 1 ;
}
wrote = teletone_mux_tones ( ts , map ) ;
switch_buffer_write ( tto - > audio_buffer , ts - > buffer , wrote * 2 ) ;
return 0 ;
}
2008-01-05 01:03:08 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_wait_for_answer ( switch_core_session_t * session , switch_core_session_t * peer_session )
{
2008-07-18 19:29:29 +00:00
switch_channel_t * caller_channel = NULL ;
2008-01-28 07:26:10 +00:00
switch_channel_t * peer_channel = switch_core_session_get_channel ( peer_session ) ;
2008-05-27 04:30:03 +00:00
const char * ringback_data = NULL ;
2008-01-05 01:03:08 +00:00
switch_frame_t write_frame = { 0 } ;
switch_codec_t write_codec = { 0 } ;
2008-01-28 07:26:10 +00:00
switch_codec_t * read_codec = switch_core_session_get_read_codec ( session ) ;
2008-01-05 01:03:08 +00:00
uint8_t pass = 0 ;
ringback_t ringback = { 0 } ;
switch_core_session_message_t * message = NULL ;
switch_frame_t * read_frame = NULL ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
int timelimit = 60 ;
2008-07-21 14:55:49 +00:00
const char * var ;
2008-01-05 01:03:08 +00:00
switch_time_t start = 0 ;
2009-08-26 19:49:35 +00:00
const char * cancel_key = NULL ;
2008-05-27 04:30:03 +00:00
2008-07-21 14:55:49 +00:00
switch_assert ( peer_channel ) ;
2008-07-18 19:29:29 +00:00
if ( session ) {
caller_channel = switch_core_session_get_channel ( session ) ;
}
2008-05-19 19:24:20 +00:00
if ( ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) | | switch_channel_test_flag ( peer_channel , CF_EARLY_MEDIA ) ) ) {
2009-01-03 03:10:11 +00:00
goto end ;
2008-05-19 19:24:20 +00:00
}
2008-02-18 21:34:06 +00:00
switch_zmalloc ( write_frame . data , SWITCH_RECOMMENDED_BUFFER_SIZE ) ;
2008-02-18 21:32:35 +00:00
write_frame . buflen = SWITCH_RECOMMENDED_BUFFER_SIZE ;
2008-01-05 01:03:08 +00:00
2009-05-21 17:55:56 +00:00
if ( caller_channel & & ( var = switch_channel_get_variable ( caller_channel , SWITCH_CALL_TIMEOUT_VARIABLE ) ) ) {
2008-01-05 01:03:08 +00:00
timelimit = atoi ( var ) ;
if ( timelimit < 0 ) {
timelimit = 60 ;
}
}
timelimit * = 1000000 ;
2009-01-25 21:23:07 +00:00
start = switch_micro_time_now ( ) ;
2008-01-05 01:03:08 +00:00
2008-07-18 19:29:29 +00:00
if ( caller_channel ) {
2009-08-26 19:49:35 +00:00
cancel_key = switch_channel_get_variable ( caller_channel , " origination_cancel_key " ) ;
2008-07-18 19:29:29 +00:00
if ( switch_channel_test_flag ( caller_channel , CF_ANSWERED ) ) {
ringback_data = switch_channel_get_variable ( caller_channel , " transfer_ringback " ) ;
}
if ( ! ringback_data ) {
ringback_data = switch_channel_get_variable ( caller_channel , " ringback " ) ;
}
if ( switch_channel_test_flag ( caller_channel , CF_PROXY_MODE ) | | switch_channel_test_flag ( caller_channel , CF_PROXY_MEDIA ) ) {
ringback_data = NULL ;
2008-12-10 00:06:25 +00:00
} else if ( switch_strlen_zero ( ringback_data ) ) {
2008-12-09 00:32:51 +00:00
if ( ( var = switch_channel_get_variable ( caller_channel , SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE ) ) ) {
int sval = atoi ( var ) ;
if ( sval ) {
2008-12-09 18:52:16 +00:00
ringback_data = switch_core_session_sprintf ( session , " silence:%d " , sval ) ;
2008-12-09 00:32:51 +00:00
}
}
2008-07-18 19:29:29 +00:00
}
2008-01-05 01:03:08 +00:00
}
2008-05-27 04:30:03 +00:00
2008-07-18 19:29:29 +00:00
if ( read_codec & & ringback_data ) {
2008-01-05 01:03:08 +00:00
if ( ! ( pass = ( uint8_t ) switch_test_flag ( read_codec , SWITCH_CODEC_FLAG_PASSTHROUGH ) ) ) {
if ( switch_core_codec_init ( & write_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-05-27 04:30:03 +00:00
1 , SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , NULL ,
2008-01-05 01:03:08 +00:00
switch_core_session_get_pool ( session ) ) = = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG ,
2008-01-05 01:03:08 +00:00
" Raw Codec Activation Success L16@%uhz 1 channel %dms \n " ,
2008-10-20 17:48:42 +00:00
read_codec - > implementation - > actual_samples_per_second , read_codec - > implementation - > microseconds_per_packet / 1000 ) ;
2008-05-27 04:30:03 +00:00
2008-01-05 01:03:08 +00:00
write_frame . codec = & write_codec ;
2008-10-20 17:48:42 +00:00
write_frame . datalen = read_codec - > implementation - > decoded_bytes_per_packet ;
2008-01-05 01:03:08 +00:00
write_frame . samples = write_frame . datalen / 2 ;
memset ( write_frame . data , 255 , write_frame . datalen ) ;
if ( ringback_data ) {
char * tmp_data = NULL ;
2008-05-27 04:30:03 +00:00
2008-01-05 01:03:08 +00:00
if ( switch_is_file_path ( ringback_data ) ) {
char * ext ;
2008-05-27 04:30:03 +00:00
2008-01-05 01:03:08 +00:00
if ( strrchr ( ringback_data , ' . ' ) | | strstr ( ringback_data , SWITCH_URL_SEPARATOR ) ) {
switch_core_session_set_read_codec ( session , & write_codec ) ;
} else {
ringback . asis + + ;
write_frame . codec = read_codec ;
ext = read_codec - > implementation - > iananame ;
tmp_data = switch_mprintf ( " %s.%s " , ringback_data , ext ) ;
ringback_data = tmp_data ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Play Ringback File [%s] \n " , ringback_data ) ;
2008-01-05 01:03:08 +00:00
ringback . fhb . channels = read_codec - > implementation - > number_of_channels ;
ringback . fhb . samplerate = read_codec - > implementation - > actual_samples_per_second ;
if ( switch_core_file_open ( & ringback . fhb ,
ringback_data ,
read_codec - > implementation - > number_of_channels ,
read_codec - > implementation - > actual_samples_per_second ,
2008-05-27 04:30:03 +00:00
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Error Playing File \n " ) ;
2008-01-05 01:03:08 +00:00
switch_safe_free ( tmp_data ) ;
goto done ;
}
ringback . fh = & ringback . fhb ;
} else {
2008-12-09 00:32:51 +00:00
if ( ! strncasecmp ( ringback_data , " silence " , 7 ) ) {
const char * p = ringback_data + 7 ;
if ( * p = = ' : ' ) {
p + + ;
if ( p ) {
ringback . silence = atoi ( p ) ;
}
}
if ( ringback . silence < = 0 ) {
ringback . silence = 400 ;
}
} else {
2008-12-09 18:52:16 +00:00
switch_buffer_create_dynamic ( & ringback . audio_buffer , 512 , 1024 , 0 ) ;
switch_buffer_set_loops ( ringback . audio_buffer , - 1 ) ;
2008-12-09 00:32:51 +00:00
teletone_init_session ( & ringback . ts , 0 , teletone_handler , & ringback ) ;
ringback . ts . rate = read_codec - > implementation - > actual_samples_per_second ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Play Ringback Tone [%s] \n " , ringback_data ) ;
2008-12-09 00:32:51 +00:00
if ( teletone_run ( & ringback . ts , ringback_data ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Error Playing Tone \n " ) ;
2008-12-09 00:32:51 +00:00
teletone_destroy_session ( & ringback . ts ) ;
switch_buffer_destroy ( & ringback . audio_buffer ) ;
ringback_data = NULL ;
}
2008-01-05 01:03:08 +00:00
}
}
switch_safe_free ( tmp_data ) ;
}
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Codec Error! \n " ) ;
2008-07-18 19:29:29 +00:00
if ( caller_channel ) {
switch_channel_hangup ( caller_channel , SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE ) ;
}
2008-01-05 01:03:08 +00:00
read_codec = NULL ;
}
}
}
2008-05-27 04:30:03 +00:00
while ( switch_channel_ready ( peer_channel )
& & ! ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) | | switch_channel_test_flag ( peer_channel , CF_EARLY_MEDIA ) ) ) {
2009-01-25 21:23:07 +00:00
int diff = ( int ) ( switch_micro_time_now ( ) - start ) ;
2008-05-27 04:30:03 +00:00
2009-08-26 19:49:35 +00:00
if ( caller_channel & & cancel_key ) {
if ( switch_channel_has_dtmf ( caller_channel ) ) {
switch_dtmf_t dtmf = { 0 , 0 } ;
if ( switch_channel_dequeue_dtmf ( caller_channel , & dtmf ) = = SWITCH_STATUS_SUCCESS ) {
if ( dtmf . digit = = * cancel_key ) {
status = SWITCH_STATUS_FALSE ;
goto done ;
}
}
}
}
2008-01-05 01:03:08 +00:00
if ( diff > timelimit ) {
status = SWITCH_STATUS_TIMEOUT ;
goto done ;
}
2008-09-04 18:29:43 +00:00
2008-01-05 01:03:08 +00:00
if ( switch_core_session_dequeue_message ( peer_session , & message ) = = SWITCH_STATUS_SUCCESS ) {
if ( switch_test_flag ( message , SCSMF_DYNAMIC ) ) {
switch_safe_free ( message ) ;
} else {
message = NULL ;
}
}
2009-01-19 19:32:44 +00:00
2008-09-04 18:29:43 +00:00
if ( switch_channel_media_ready ( caller_channel ) ) {
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
}
} else {
read_frame = NULL ;
}
2009-01-19 19:32:44 +00:00
2008-01-05 01:03:08 +00:00
if ( read_frame & & ! pass ) {
2009-01-19 19:32:44 +00:00
2008-01-05 01:03:08 +00:00
if ( ringback . fh ) {
switch_size_t mlen , olen ;
unsigned int pos = 0 ;
2008-09-04 18:29:43 +00:00
2008-01-05 01:03:08 +00:00
if ( ringback . asis ) {
2008-10-20 17:48:42 +00:00
mlen = write_frame . codec - > implementation - > encoded_bytes_per_packet ;
2008-01-05 01:03:08 +00:00
} else {
2008-10-20 17:48:42 +00:00
mlen = write_frame . codec - > implementation - > samples_per_packet ;
2008-01-05 01:03:08 +00:00
}
olen = mlen ;
2009-01-09 20:34:01 +00:00
//if (ringback.fh->resampler && ringback.fh->resampler->rfactor > 1) {
//olen = (switch_size_t) (olen * ringback.fh->resampler->rfactor);
//}
2008-02-18 21:32:35 +00:00
switch_core_file_read ( ringback . fh , write_frame . data , & olen ) ;
2008-01-05 01:03:08 +00:00
if ( olen = = 0 ) {
olen = mlen ;
ringback . fh - > speed = 0 ;
switch_core_file_seek ( ringback . fh , & pos , 0 , SEEK_SET ) ;
2008-02-18 21:32:35 +00:00
switch_core_file_read ( ringback . fh , write_frame . data , & olen ) ;
2008-01-05 01:03:08 +00:00
if ( olen = = 0 ) {
break ;
}
}
write_frame . datalen = ( uint32_t ) ( ringback . asis ? olen : olen * 2 ) ;
} else if ( ringback . audio_buffer ) {
if ( ( write_frame . datalen = ( uint32_t ) switch_buffer_read_loop ( ringback . audio_buffer ,
write_frame . data ,
2008-10-20 17:48:42 +00:00
write_frame . codec - > implementation - > decoded_bytes_per_packet ) ) < = 0 ) {
2008-01-05 01:03:08 +00:00
break ;
}
2008-12-09 00:32:51 +00:00
} else if ( ringback . silence ) {
write_frame . datalen = write_frame . codec - > implementation - > decoded_bytes_per_packet ;
switch_generate_sln_silence ( ( int16_t * ) write_frame . data , write_frame . datalen / 2 , ringback . silence ) ;
2008-01-05 01:03:08 +00:00
}
2008-12-09 00:32:51 +00:00
if ( ( ringback . fh | | ringback . silence | | ringback . audio_buffer ) & & write_frame . codec & & write_frame . datalen ) {
2008-09-04 18:29:43 +00:00
if ( switch_core_session_write_frame ( session , & write_frame , SWITCH_IO_FLAG_NONE , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
2008-01-05 01:03:08 +00:00
}
} else {
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2008-01-05 01:03:08 +00:00
}
}
2009-01-19 23:15:59 +00:00
done :
2008-05-27 04:30:03 +00:00
2008-01-05 01:03:08 +00:00
if ( ringback . fh ) {
switch_core_file_close ( ringback . fh ) ;
ringback . fh = NULL ;
} else if ( ringback . audio_buffer ) {
teletone_destroy_session ( & ringback . ts ) ;
switch_buffer_destroy ( & ringback . audio_buffer ) ;
}
2009-01-09 20:34:01 +00:00
switch_core_session_reset ( session , SWITCH_TRUE , SWITCH_TRUE ) ;
2008-07-15 17:39:16 +00:00
2009-04-09 17:17:12 +00:00
if ( switch_core_codec_ready ( & write_codec ) ) {
2008-01-05 01:03:08 +00:00
switch_core_codec_destroy ( & write_codec ) ;
}
2008-02-18 21:32:35 +00:00
switch_safe_free ( write_frame . data ) ;
2008-01-05 01:03:08 +00:00
2009-01-03 03:10:11 +00:00
end :
return ( ! caller_channel | | switch_channel_ready ( caller_channel ) ) ? status : SWITCH_STATUS_FALSE ;
2008-01-05 01:03:08 +00:00
}
2009-03-23 16:06:32 +00:00
SWITCH_DECLARE ( void ) switch_process_import ( switch_core_session_t * session , switch_channel_t * peer_channel , const char * varname )
2008-06-04 23:33:29 +00:00
{
const char * import , * val ;
switch_channel_t * caller_channel ;
switch_assert ( session & & peer_channel ) ;
caller_channel = switch_core_session_get_channel ( session ) ;
2009-03-23 16:06:32 +00:00
if ( ( import = switch_channel_get_variable ( caller_channel , varname ) ) ) {
2008-06-04 23:33:29 +00:00
char * mydata = switch_core_session_strdup ( session , import ) ;
int i , argc ;
char * argv [ 64 ] = { 0 } ;
if ( ( argc = switch_separate_string ( mydata , ' , ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) ) {
for ( i = 0 ; i < argc ; i + + ) {
if ( ( val = switch_channel_get_variable ( peer_channel , argv [ i ] ) ) ) {
switch_channel_set_variable ( caller_channel , argv [ i ] , val ) ;
}
}
}
}
}
2009-01-19 17:54:54 +00:00
2007-12-18 17:33:29 +00:00
# define MAX_PEERS 128
2007-03-29 22:34:40 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_originate ( switch_core_session_t * session ,
switch_core_session_t * * bleg ,
switch_call_cause_t * cause ,
2007-11-01 11:28:26 +00:00
const char * bridgeto ,
2007-03-29 22:34:40 +00:00
uint32_t timelimit_sec ,
const switch_state_handler_table_t * table ,
2008-05-27 04:30:03 +00:00
const char * cid_name_override ,
const char * cid_num_override ,
2008-12-05 14:59:24 +00:00
switch_caller_profile_t * caller_profile_override ,
switch_event_t * ovars ,
switch_originate_flag_t flags
)
2007-03-29 22:34:40 +00:00
{
2009-01-19 17:54:54 +00:00
originate_status_t originate_status [ MAX_PEERS ] = { { 0 } } ;
2008-08-11 21:27:20 +00:00
switch_originate_flag_t dftflags = SOF_NONE , myflags = dftflags ;
2007-03-29 22:34:40 +00:00
char * pipe_names [ MAX_PEERS ] = { 0 } ;
char * data = NULL ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
switch_channel_t * caller_channel = NULL ;
char * peer_names [ MAX_PEERS ] = { 0 } ;
2009-01-19 17:54:54 +00:00
switch_core_session_t * new_session = NULL , * peer_session ;
switch_caller_profile_t * new_profile = NULL , * caller_caller_profile ;
2007-03-29 22:34:40 +00:00
char * chan_type = NULL , * chan_data ;
2009-01-19 17:54:54 +00:00
switch_channel_t * peer_channel = NULL ;
2007-03-29 22:34:40 +00:00
ringback_t ringback = { 0 } ;
time_t start ;
switch_frame_t * read_frame = NULL ;
switch_memory_pool_t * pool = NULL ;
int r = 0 , i , and_argc = 0 , or_argc = 0 ;
2009-01-19 17:54:54 +00:00
int32_t sleep_ms = 1000 , try = 0 , retries = 1 ;
2007-03-29 22:34:40 +00:00
switch_codec_t write_codec = { 0 } ;
switch_frame_t write_frame = { 0 } ;
2008-02-08 18:26:11 +00:00
uint8_t pass = 0 ;
2009-01-19 17:54:54 +00:00
char * odata , * var ;
2008-07-03 22:51:09 +00:00
switch_call_cause_t reason = SWITCH_CAUSE_NONE ;
2007-03-29 22:34:40 +00:00
uint8_t to = 0 ;
2007-11-01 11:28:26 +00:00
char * var_val , * vars = NULL ;
2008-10-22 17:51:34 +00:00
int var_block_count = 0 ;
char * e = NULL ;
2007-11-01 11:28:26 +00:00
const char * ringback_data = NULL ;
2007-03-29 22:34:40 +00:00
switch_codec_t * read_codec = NULL ;
switch_core_session_message_t * message = NULL ;
switch_event_t * var_event = NULL ;
uint8_t fail_on_single_reject = 0 ;
2008-10-09 00:38:59 +00:00
char * fail_on_single_reject_var = NULL ;
2007-03-29 22:34:40 +00:00
char * loop_data = NULL ;
2008-06-23 22:07:22 +00:00
uint32_t progress_timelimit_sec = 0 ;
2009-06-18 16:35:41 +00:00
const char * cid_tmp , * lc ;
2009-01-19 17:54:54 +00:00
originate_global_t oglobals = { 0 } ;
2009-04-30 13:53:29 +00:00
int cdr_total = 0 ;
2009-06-18 16:35:41 +00:00
int local_clobber = 0 ;
2009-08-26 19:49:35 +00:00
const char * cancel_key = NULL ;
2009-01-19 17:54:54 +00:00
oglobals . idx = IDX_NADA ;
oglobals . early_ok = 1 ;
oglobals . session = session ;
2007-03-29 22:34:40 +00:00
2008-08-11 16:12:55 +00:00
* bleg = NULL ;
2008-02-18 21:34:06 +00:00
switch_zmalloc ( write_frame . data , SWITCH_RECOMMENDED_BUFFER_SIZE ) ;
2008-02-18 21:32:35 +00:00
write_frame . buflen = SWITCH_RECOMMENDED_BUFFER_SIZE ;
2007-03-29 22:34:40 +00:00
odata = strdup ( bridgeto ) ;
2007-12-17 22:52:32 +00:00
if ( ! odata ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Memory Error! \n " ) ;
2007-12-17 22:52:32 +00:00
status = SWITCH_STATUS_MEMERR ;
goto done ;
}
2007-03-29 22:34:40 +00:00
data = odata ;
/* strip leading spaces */
while ( data & & * data & & * data = = ' ' ) {
data + + ;
}
2008-05-27 04:30:03 +00:00
2008-10-22 17:51:34 +00:00
/* extract channel variables, allowing multiple sets of braces */
while ( * data = = ' { ' ) {
if ( ! var_block_count ) {
e = switch_find_end_paren ( data , ' { ' , ' } ' ) ;
if ( ! e | | ! * e ) {
goto var_extract_error ;
}
2007-12-10 21:55:46 +00:00
vars = data + 1 ;
2008-10-22 17:51:34 +00:00
* e = ' \0 ' ;
data = e + 1 ;
2007-12-10 21:55:46 +00:00
} else {
2008-10-22 21:55:06 +00:00
int j = 0 , k = 0 ;
2008-10-22 17:51:34 +00:00
if ( e ) {
* e = ' , ' ;
}
e = switch_find_end_paren ( data , ' { ' , ' } ' ) ;
if ( ! e | | ! * e ) {
goto var_extract_error ;
}
/* swallow the opening bracket */
2008-10-22 21:55:06 +00:00
while ( ( data + k ) & & * ( data + k ) ) {
j = k ; k + + ;
2008-10-22 17:51:34 +00:00
/* note that this affects vars[] */
2008-10-22 21:55:06 +00:00
data [ j ] = data [ k ] ;
2008-10-22 17:51:34 +00:00
}
* ( - - e ) = ' \0 ' ;
data = e + 1 ;
2007-03-29 22:34:40 +00:00
}
2008-10-22 17:51:34 +00:00
var_block_count + + ;
continue ;
var_extract_error :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Parse Error! \n " ) ;
2008-10-22 17:51:34 +00:00
status = SWITCH_STATUS_GENERR ;
goto done ;
2007-03-29 22:34:40 +00:00
}
/* strip leading spaces (again) */
while ( data & & * data & & * data = = ' ' ) {
data + + ;
}
if ( switch_strlen_zero ( data ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " No origination URL specified! \n " ) ;
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_GENERR ;
goto done ;
}
/* Some channel are created from an originating channel and some aren't so not all outgoing calls have a way to get params
so we will normalize dialstring params and channel variables ( when there is an originator ) into an event that we
will use as a pseudo hash to consult for params as needed .
2009-01-19 23:15:59 +00:00
*/
2008-12-05 14:59:24 +00:00
if ( ovars ) {
var_event = ovars ;
} else {
2009-06-18 19:47:29 +00:00
if ( switch_event_create_plain ( & var_event , SWITCH_EVENT_CHANNEL_DATA ) ! = SWITCH_STATUS_SUCCESS ) {
2008-12-05 14:59:24 +00:00
abort ( ) ;
}
2007-03-29 22:34:40 +00:00
}
2009-05-07 02:05:16 +00:00
if ( vars ) { /* Parse parameters specified from the dialstring */
char * var_array [ 1024 ] = { 0 } ;
int var_count = 0 ;
if ( ( var_count = switch_separate_string ( vars , ' , ' , var_array , ( sizeof ( var_array ) / sizeof ( var_array [ 0 ] ) ) ) ) ) {
int x = 0 ;
for ( x = 0 ; x < var_count ; x + + ) {
char * inner_var_array [ 2 ] = { 0 } ;
int inner_var_count ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " variable string %d = [%s] \n " , x , var_array [ x ] ) ;
2009-05-07 02:05:16 +00:00
if ( ( inner_var_count =
switch_separate_string ( var_array [ x ] , ' = ' , inner_var_array , ( sizeof ( inner_var_array ) / sizeof ( inner_var_array [ 0 ] ) ) ) ) = = 2 ) {
switch_event_del_header ( var_event , inner_var_array [ 0 ] ) ;
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , inner_var_array [ 0 ] , inner_var_array [ 1 ] ) ;
}
}
}
}
2009-01-19 17:54:54 +00:00
if ( oglobals . session ) {
2007-09-29 01:06:08 +00:00
switch_event_header_t * hi ;
2009-04-30 13:53:29 +00:00
const char * cdr_total_var ;
2009-01-19 17:54:54 +00:00
caller_channel = switch_core_session_get_channel ( oglobals . session ) ;
2007-03-29 22:34:40 +00:00
2009-04-30 13:53:29 +00:00
if ( ( cdr_total_var = switch_channel_get_variable ( caller_channel , " failed_xml_cdr_total " ) ) ) {
int tmp = atoi ( cdr_total_var ) ;
if ( tmp > 0 ) {
cdr_total = tmp ;
}
}
2009-05-07 02:05:16 +00:00
/* Copy all the missing applicable channel variables from A-leg into the event */
2007-09-29 01:06:08 +00:00
if ( ( hi = switch_channel_variable_first ( caller_channel ) ) ) {
for ( ; hi ; hi = hi - > next ) {
2007-12-11 00:09:04 +00:00
int ok = 0 ;
2008-05-27 04:30:03 +00:00
if ( ! strcasecmp ( ( char * ) hi - > name , " group_confirm_key " ) ) {
2007-12-11 00:09:04 +00:00
ok = 1 ;
2008-05-27 04:30:03 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " group_confirm_file " ) ) {
2007-12-11 00:09:04 +00:00
ok = 1 ;
2009-07-15 15:24:47 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " group_confirm_cancel_timeout " ) ) {
2009-07-14 17:19:14 +00:00
ok = 1 ;
2008-05-27 04:30:03 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " forked_dial " ) ) {
2008-01-07 21:14:24 +00:00
ok = 1 ;
2008-05-27 04:30:03 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " fail_on_single_reject " ) ) {
2007-12-11 00:09:04 +00:00
ok = 1 ;
2008-05-27 04:30:03 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " ignore_early_media " ) ) {
2007-12-11 00:09:04 +00:00
ok = 1 ;
2009-01-20 15:39:32 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " ignore_ring_ready " ) ) {
ok = 1 ;
2009-01-19 23:15:59 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " monitor_early_media_ring " ) ) {
ok = 1 ;
2009-02-11 00:16:36 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " monitor_early_media_ring_total " ) ) {
ok = 1 ;
2009-01-19 23:15:59 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " monitor_early_media_fail " ) ) {
ok = 1 ;
2008-05-27 04:30:03 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " return_ring_ready " ) ) {
2008-01-05 14:58:26 +00:00
ok = 1 ;
2008-09-23 19:01:22 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " ring_ready " ) ) {
ok = 1 ;
2009-02-11 00:22:41 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " instant_ringback " ) ) {
ok = 1 ;
2008-06-23 22:07:22 +00:00
} else if ( ! strcasecmp ( ( char * ) hi - > name , " progress_timeout " ) ) {
ok = 1 ;
2007-12-11 00:09:04 +00:00
}
2009-05-07 02:05:16 +00:00
if ( ok & & ! switch_event_get_header ( var_event , hi - > name ) ) {
2008-08-16 02:17:09 +00:00
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , ( char * ) hi - > name , ( char * ) hi - > value ) ;
2007-12-11 00:09:04 +00:00
}
2007-09-29 01:06:08 +00:00
}
switch_channel_variable_last ( caller_channel ) ;
}
/*
2009-01-19 23:15:59 +00:00
if ( ( hi = switch_channel_variable_first ( caller_channel ) ) ) {
for ( ; hi ; hi = switch_hash_next ( hi ) ) {
switch_hash_this ( hi , & vvar , NULL , & vval ) ;
if ( vvar & & vval ) {
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , ( void * ) vvar , ( char * ) vval ) ;
}
}
switch_channel_variable_last ( caller_channel ) ;
}
*/
2007-03-29 22:34:40 +00:00
}
if ( caller_channel ) { /* ringback is only useful when there is an originator */
2007-12-20 21:42:00 +00:00
ringback_data = NULL ;
2009-08-26 19:49:35 +00:00
cancel_key = switch_channel_get_variable ( caller_channel , " origination_cancel_key " ) ;
2007-12-20 21:42:00 +00:00
2008-01-05 16:20:39 +00:00
if ( switch_channel_test_flag ( caller_channel , CF_ANSWERED ) ) {
2007-12-20 21:42:00 +00:00
ringback_data = switch_channel_get_variable ( caller_channel , " transfer_ringback " ) ;
2008-05-27 04:30:03 +00:00
}
2007-12-20 21:42:00 +00:00
if ( ! ringback_data ) {
ringback_data = switch_channel_get_variable ( caller_channel , " ringback " ) ;
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
switch_channel_set_variable ( caller_channel , " originate_disposition " , " failure " ) ;
2008-10-08 18:15:00 +00:00
if ( switch_channel_test_flag ( caller_channel , CF_PROXY_MODE ) | | switch_channel_test_flag ( caller_channel , CF_PROXY_MEDIA ) ) {
ringback_data = NULL ;
2008-12-10 00:06:25 +00:00
} else if ( switch_strlen_zero ( ringback_data ) ) {
2008-12-09 00:32:51 +00:00
const char * vvar ;
if ( ( vvar = switch_channel_get_variable ( caller_channel , SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE ) ) ) {
int sval = atoi ( vvar ) ;
if ( sval ) {
2009-01-19 17:54:54 +00:00
ringback_data = switch_core_session_sprintf ( oglobals . session , " silence:%d " , sval ) ;
2008-12-09 00:32:51 +00:00
}
}
2008-10-08 18:15:00 +00:00
}
}
if ( ringback_data ) {
2009-01-19 17:54:54 +00:00
oglobals . early_ok = 0 ;
2007-03-29 22:34:40 +00:00
}
2009-07-14 17:19:14 +00:00
if ( switch_true ( switch_event_get_header ( var_event , " group_confirm_cancel_timeout " ) ) ) {
oglobals . cancel_timeout = - 1 ;
}
2007-03-29 22:34:40 +00:00
if ( ( var = switch_event_get_header ( var_event , " group_confirm_key " ) ) ) {
2009-01-19 17:54:54 +00:00
switch_copy_string ( oglobals . key , var , sizeof ( oglobals . key ) ) ;
2007-03-29 22:34:40 +00:00
if ( ( var = switch_event_get_header ( var_event , " group_confirm_file " ) ) ) {
2009-01-19 17:54:54 +00:00
switch_copy_string ( oglobals . file , var , sizeof ( oglobals . file ) ) ;
2007-03-29 22:34:40 +00:00
}
}
2008-09-02 10:46:44 +00:00
/* When using the AND operator, the fail_on_single_reject flag may be set in order to indicate that a single
2008-10-09 00:38:59 +00:00
rejections should terminate the attempt rather than a timeout , answer , or rejection by all .
If the value is set to ' true ' any fail cause will end the attempt otherwise it can contain a comma ( , ) separated
list of cause names which should be considered fatal
*/
2007-03-29 22:34:40 +00:00
if ( ( var = switch_event_get_header ( var_event , " fail_on_single_reject " ) ) & & switch_true ( var ) ) {
2008-10-09 00:38:59 +00:00
fail_on_single_reject_var = strdup ( var ) ;
2007-03-29 22:34:40 +00:00
fail_on_single_reject = 1 ;
}
2009-01-19 17:54:54 +00:00
if ( ( * oglobals . file ! = ' \0 ' ) & & ( ! strcmp ( oglobals . file , " undef " ) ) ) {
* oglobals . file = ' \0 ' ;
2007-03-29 22:34:40 +00:00
}
if ( ( var_val = switch_event_get_header ( var_event , " ignore_early_media " ) ) & & switch_true ( var_val ) ) {
2009-01-19 17:54:54 +00:00
oglobals . early_ok = 0 ;
2009-01-20 15:39:32 +00:00
oglobals . ignore_early_media = 1 ;
}
if ( ( var_val = switch_event_get_header ( var_event , " ignore_ring_ready " ) ) & & switch_true ( var_val ) ) {
oglobals . ignore_ring_ready = 1 ;
2007-03-29 22:34:40 +00:00
}
2009-01-19 23:15:59 +00:00
if ( ( var_val = switch_event_get_header ( var_event , " monitor_early_media_ring " ) ) ) {
oglobals . early_ok = 0 ;
oglobals . monitor_early_media_ring = 1 ;
}
if ( ( var_val = switch_event_get_header ( var_event , " monitor_early_media_fail " ) ) ) {
oglobals . early_ok = 0 ;
oglobals . monitor_early_media_fail = 1 ;
}
2008-01-05 14:58:26 +00:00
if ( ( var_val = switch_event_get_header ( var_event , " return_ring_ready " ) ) & & switch_true ( var_val ) ) {
2009-01-19 17:54:54 +00:00
oglobals . return_ring_ready = 1 ;
2008-01-05 14:58:26 +00:00
}
2008-09-23 19:01:22 +00:00
if ( ( var_val = switch_event_get_header ( var_event , " ring_ready " ) ) & & switch_true ( var_val ) ) {
2009-01-19 19:32:44 +00:00
oglobals . ring_ready = 1 ;
2008-09-23 19:01:22 +00:00
}
2009-02-11 00:22:41 +00:00
if ( ( var_val = switch_event_get_header ( var_event , " instant_ringback " ) ) & & switch_true ( var_val ) ) {
oglobals . instant_ringback = 1 ;
}
2008-06-23 22:07:22 +00:00
if ( ( var_val = switch_event_get_header ( var_event , " originate_timeout " ) ) ) {
2008-04-15 18:43:12 +00:00
int tmp = atoi ( var_val ) ;
if ( tmp > 0 ) {
timelimit_sec = ( uint32_t ) tmp ;
}
}
2008-06-23 22:07:22 +00:00
if ( ( var_val = switch_event_get_header ( var_event , " progress_timeout " ) ) ) {
int tmp = atoi ( var_val ) ;
if ( tmp > 0 ) {
progress_timelimit_sec = ( uint32_t ) tmp ;
}
}
2007-03-29 22:34:40 +00:00
if ( ( var_val = switch_event_get_header ( var_event , " originate_retries " ) ) & & switch_true ( var_val ) ) {
int32_t tmp ;
tmp = atoi ( var_val ) ;
if ( tmp > 0 & & tmp < 101 ) {
retries = tmp ;
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING ,
2007-03-30 00:13:31 +00:00
" Invalid originate_retries setting of %d ignored, value must be between 1 and 100 \n " , tmp ) ;
2007-03-29 22:34:40 +00:00
}
}
if ( ( var_val = switch_event_get_header ( var_event , " originate_retry_sleep_ms " ) ) & & switch_true ( var_val ) ) {
int32_t tmp ;
tmp = atoi ( var_val ) ;
2008-06-11 16:40:36 +00:00
if ( tmp > = 500 & & tmp < = 60000 ) {
2007-03-29 22:34:40 +00:00
sleep_ms = tmp ;
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING ,
2007-03-30 00:13:31 +00:00
" Invalid originate_retry_sleep_ms setting of %d ignored, value must be between 500 and 60000 \n " , tmp ) ;
2007-03-29 22:34:40 +00:00
}
}
2008-08-11 21:27:20 +00:00
if ( ( cid_tmp = switch_event_get_header ( var_event , " origination_caller_id_name " ) ) ) {
cid_name_override = cid_tmp ;
}
2008-06-23 19:04:17 +00:00
if ( cid_name_override ) {
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " origination_caller_id_name " , cid_name_override ) ;
} else {
2007-03-29 22:34:40 +00:00
cid_name_override = switch_event_get_header ( var_event , " origination_caller_id_name " ) ;
}
2008-08-11 21:27:20 +00:00
if ( ( cid_tmp = switch_event_get_header ( var_event , " origination_caller_id_number " ) ) ) {
cid_num_override = cid_tmp ;
}
2008-06-23 19:04:17 +00:00
if ( cid_num_override ) {
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " origination_caller_id_number " , cid_num_override ) ;
} else {
2007-03-29 22:34:40 +00:00
cid_num_override = switch_event_get_header ( var_event , " origination_caller_id_number " ) ;
}
2008-08-11 21:27:20 +00:00
if ( cid_num_override ) {
dftflags | = SOF_NO_EFFECTIVE_CID_NUM ;
}
if ( cid_name_override ) {
dftflags | = SOF_NO_EFFECTIVE_CID_NAME ;
}
2008-06-23 22:07:22 +00:00
if ( ! progress_timelimit_sec ) {
progress_timelimit_sec = timelimit_sec ;
}
2007-03-29 22:34:40 +00:00
for ( try = 0 ; try < retries ; try + + ) {
switch_safe_free ( loop_data ) ;
2007-10-19 00:21:50 +00:00
loop_data = strdup ( data ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( loop_data ) ;
2007-03-29 22:34:40 +00:00
or_argc = switch_separate_string ( loop_data , ' | ' , pipe_names , ( sizeof ( pipe_names ) / sizeof ( pipe_names [ 0 ] ) ) ) ;
2007-12-20 21:42:00 +00:00
if ( ( flags & SOF_NOBLOCK ) & & or_argc > 1 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " Only calling the first element in the list in this mode. \n " ) ;
2007-12-20 21:42:00 +00:00
or_argc = 1 ;
}
2009-09-18 22:09:47 +00:00
2007-03-29 22:34:40 +00:00
for ( r = 0 ; r < or_argc ; r + + ) {
2008-10-23 01:39:04 +00:00
char * p , * end = NULL ;
2008-06-06 18:24:35 +00:00
const char * var_begin , * var_end ;
2009-01-19 21:11:01 +00:00
oglobals . hups = 0 ;
2008-06-06 18:24:35 +00:00
2008-07-03 22:51:09 +00:00
reason = SWITCH_CAUSE_NONE ;
2007-03-29 22:34:40 +00:00
memset ( peer_names , 0 , sizeof ( peer_names ) ) ;
peer_session = NULL ;
2009-01-19 17:54:54 +00:00
memset ( originate_status , 0 , sizeof ( originate_status ) ) ;
2007-04-16 19:32:08 +00:00
new_profile = NULL ;
new_session = NULL ;
2007-03-29 22:34:40 +00:00
chan_type = NULL ;
chan_data = NULL ;
peer_channel = NULL ;
start = 0 ;
read_frame = NULL ;
pool = NULL ;
pass = 0 ;
var = NULL ;
to = 0 ;
2009-01-19 17:54:54 +00:00
oglobals . sent_ring = 0 ;
oglobals . progress = 0 ;
2008-08-11 21:27:20 +00:00
myflags = dftflags ;
2007-03-29 22:34:40 +00:00
if ( try > 0 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Originate attempt %d/%d in %d ms \n " , try + 1 , retries , sleep_ms ) ;
2008-10-13 21:17:10 +00:00
if ( caller_channel ) {
2009-01-19 17:54:54 +00:00
switch_ivr_sleep ( oglobals . session , sleep_ms , SWITCH_TRUE , NULL ) ;
2009-05-04 14:09:32 +00:00
if ( ! switch_channel_ready ( caller_channel ) ) {
status = SWITCH_STATUS_FALSE ;
goto done ;
}
2008-10-13 21:17:10 +00:00
} else {
switch_yield ( sleep_ms * 1000 ) ;
}
2007-03-29 22:34:40 +00:00
}
2008-06-05 15:24:14 +00:00
p = pipe_names [ r ] ;
while ( p & & * p ) {
if ( * p = = ' [ ' ) {
2008-10-23 01:39:04 +00:00
end = switch_find_end_paren ( p , ' [ ' , ' ] ' ) ;
2008-06-05 15:24:14 +00:00
}
2008-10-24 19:25:07 +00:00
if ( end & & p < end & & * p = = ' , ' ) {
2008-06-05 15:24:14 +00:00
* p = ' | ' ;
}
2007-03-29 22:34:40 +00:00
2008-10-23 01:39:04 +00:00
if ( p = = end ) {
2008-10-24 19:25:07 +00:00
end = NULL ;
2008-06-05 15:24:14 +00:00
}
p + + ;
}
2007-03-30 00:13:31 +00:00
and_argc = switch_separate_string ( pipe_names [ r ] , ' , ' , peer_names , ( sizeof ( peer_names ) / sizeof ( peer_names [ 0 ] ) ) ) ;
2007-03-29 22:34:40 +00:00
2007-12-20 21:42:00 +00:00
if ( ( flags & SOF_NOBLOCK ) & & and_argc > 1 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " Only calling the first element in the list in this mode. \n " ) ;
2007-12-20 21:42:00 +00:00
and_argc = 1 ;
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
for ( i = 0 ; i < and_argc ; i + + ) {
2007-12-10 21:55:46 +00:00
char * vdata ;
2009-03-14 14:30:37 +00:00
const char * current_variable ;
char variable_buffer [ 512 ] = " " ;
2009-03-16 19:53:17 +00:00
end = NULL ;
chan_type = peer_names [ i ] ;
2009-03-14 14:14:51 +00:00
2007-12-10 21:55:46 +00:00
while ( chan_type & & * chan_type & & * chan_type = = ' ' ) {
chan_type + + ;
}
vdata = chan_type ;
2008-10-23 01:39:04 +00:00
end = switch_find_end_paren ( vdata , ' [ ' , ' ] ' ) ;
2008-05-27 04:30:03 +00:00
2008-10-23 01:39:04 +00:00
if ( end ) {
2007-12-10 21:55:46 +00:00
vdata + + ;
2008-10-23 01:39:04 +00:00
* end + + = ' \0 ' ;
chan_type = end ;
2007-12-10 21:55:46 +00:00
} else {
vdata = NULL ;
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
if ( ( chan_data = strchr ( chan_type , ' / ' ) ) ! = 0 ) {
* chan_data = ' \0 ' ;
chan_data + + ;
}
2009-01-19 17:54:54 +00:00
if ( oglobals . session ) {
2007-03-29 22:34:40 +00:00
if ( ! switch_channel_ready ( caller_channel ) ) {
status = SWITCH_STATUS_FALSE ;
goto done ;
}
2007-03-30 00:13:31 +00:00
caller_caller_profile = caller_profile_override ? caller_profile_override : switch_channel_get_caller_profile ( caller_channel ) ;
2009-01-19 17:54:54 +00:00
new_profile = switch_caller_profile_clone ( oglobals . session , caller_caller_profile ) ;
2007-09-29 01:06:08 +00:00
new_profile - > uuid = SWITCH_BLANK_STRING ;
new_profile - > chan_name = SWITCH_BLANK_STRING ;
new_profile - > destination_number = switch_core_strdup ( new_profile - > pool , chan_data ) ;
2007-03-29 22:34:40 +00:00
2007-08-28 21:55:30 +00:00
if ( cid_name_override ) {
2007-09-29 01:06:08 +00:00
new_profile - > caller_id_name = switch_core_strdup ( new_profile - > pool , cid_name_override ) ;
2007-03-29 22:34:40 +00:00
}
2007-08-28 21:55:30 +00:00
if ( cid_num_override ) {
2007-09-29 01:06:08 +00:00
new_profile - > caller_id_number = switch_core_strdup ( new_profile - > pool , cid_num_override ) ;
2007-03-29 22:34:40 +00:00
}
pool = NULL ;
} else {
2007-09-29 01:06:08 +00:00
switch_core_new_memory_pool ( & pool ) ;
2007-03-29 22:34:40 +00:00
if ( caller_profile_override ) {
2007-08-28 21:55:30 +00:00
new_profile = switch_caller_profile_dup ( pool , caller_profile_override ) ;
2007-12-22 01:00:10 +00:00
new_profile - > destination_number = switch_core_strdup ( new_profile - > pool , switch_str_nil ( chan_data ) ) ;
2007-09-29 01:06:08 +00:00
new_profile - > uuid = SWITCH_BLANK_STRING ;
new_profile - > chan_name = SWITCH_BLANK_STRING ;
2007-03-29 22:34:40 +00:00
} else {
2007-08-28 21:55:30 +00:00
if ( ! cid_name_override ) {
cid_name_override = " FreeSWITCH " ;
}
if ( ! cid_num_override ) {
cid_num_override = " 0000000000 " ;
}
2007-04-16 19:32:08 +00:00
new_profile = switch_caller_profile_new ( pool ,
2007-08-28 22:44:02 +00:00
NULL ,
NULL ,
2008-05-27 04:30:03 +00:00
cid_name_override , cid_num_override , NULL , NULL , NULL , NULL , __FILE__ , NULL , chan_data ) ;
2007-03-29 22:34:40 +00:00
}
}
2008-05-27 04:30:03 +00:00
2009-01-19 17:54:54 +00:00
originate_status [ i ] . caller_profile = NULL ;
originate_status [ i ] . peer_channel = NULL ;
originate_status [ i ] . peer_session = NULL ;
2007-04-16 19:32:08 +00:00
new_session = NULL ;
2008-05-27 04:30:03 +00:00
2007-12-20 21:42:00 +00:00
if ( and_argc > 1 | | or_argc > 1 ) {
myflags | = SOF_FORKED_DIAL ;
2008-01-07 21:14:24 +00:00
} else if ( var_event ) {
const char * vvar ;
if ( ( vvar = switch_event_get_header ( var_event , " forked_dial " ) ) & & switch_true ( vvar ) ) {
myflags | = SOF_FORKED_DIAL ;
}
2007-12-20 21:42:00 +00:00
}
2009-03-14 14:30:37 +00:00
/* only valid in [] since it's unique to each channel leg */
2008-06-06 18:24:35 +00:00
2009-03-14 14:30:37 +00:00
if ( vdata & & ( var_begin = switch_stristr ( " origination_uuid= " , vdata ) ) ) {
2008-06-06 18:24:35 +00:00
char tmp [ 512 ] = " " ;
2009-03-14 14:30:37 +00:00
var_begin + = strlen ( " origination_uuid= " ) ;
2008-06-06 18:24:35 +00:00
var_end = strchr ( var_begin , ' | ' ) ;
2009-03-14 14:30:37 +00:00
2008-06-06 18:24:35 +00:00
if ( var_end ) {
strncpy ( tmp , var_begin , var_end - var_begin ) ;
} else {
strncpy ( tmp , var_begin , strlen ( var_begin ) ) ;
}
2009-03-14 14:30:37 +00:00
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " origination_uuid " , tmp ) ;
2008-06-06 18:24:35 +00:00
}
2009-03-14 14:30:37 +00:00
/* The rest are valid in both {} and [] with [] taking precedence */
current_variable = NULL ;
if ( vdata & & ( var_begin = switch_stristr ( " origination_caller_id_number= " , vdata ) ) ) {
var_begin + = strlen ( " origination_caller_id_number= " ) ;
2008-06-06 18:24:35 +00:00
var_end = strchr ( var_begin , ' | ' ) ;
2009-03-14 14:30:37 +00:00
2008-06-06 18:24:35 +00:00
if ( var_end ) {
2009-03-14 14:30:37 +00:00
strncpy ( variable_buffer , var_begin , var_end - var_begin ) ;
2008-06-06 18:24:35 +00:00
} else {
2009-03-14 14:30:37 +00:00
strncpy ( variable_buffer , var_begin , strlen ( var_begin ) ) ;
2008-06-06 18:24:35 +00:00
}
2009-03-14 14:30:37 +00:00
current_variable = variable_buffer ;
}
if ( current_variable | | ( current_variable = switch_event_get_header ( var_event , " origination_caller_id_number " ) ) ) {
new_profile - > caller_id_number = switch_core_strdup ( new_profile - > pool , current_variable ) ;
myflags | = SOF_NO_EFFECTIVE_CID_NUM ;
2008-06-06 18:24:35 +00:00
}
2009-03-14 14:30:37 +00:00
current_variable = NULL ;
if ( vdata & & ( var_begin = switch_stristr ( " origination_caller_id_name= " , vdata ) ) ) {
var_begin + = strlen ( " origination_caller_id_name= " ) ;
2008-11-04 16:46:33 +00:00
var_end = strchr ( var_begin , ' | ' ) ;
2009-03-14 14:30:37 +00:00
2008-11-04 16:46:33 +00:00
if ( var_end ) {
2009-03-14 14:30:37 +00:00
strncpy ( variable_buffer , var_begin , var_end - var_begin ) ;
2008-11-04 16:46:33 +00:00
} else {
2009-03-14 14:30:37 +00:00
strncpy ( variable_buffer , var_begin , strlen ( var_begin ) ) ;
2008-11-04 16:46:33 +00:00
}
2009-03-10 13:16:14 +00:00
2009-03-14 14:30:37 +00:00
current_variable = variable_buffer ;
}
if ( current_variable | | ( current_variable = switch_event_get_header ( var_event , " origination_caller_id_name " ) ) ) {
2009-03-17 16:23:32 +00:00
new_profile - > caller_id_name = switch_core_strdup ( new_profile - > pool , current_variable ) ;
2009-03-14 14:30:37 +00:00
myflags | = SOF_NO_EFFECTIVE_CID_NAME ;
}
current_variable = NULL ;
2009-03-10 13:16:14 +00:00
if ( vdata & & ( var_begin = switch_stristr ( " origination_privacy= " , vdata ) ) ) {
var_begin + = strlen ( " origination_privacy= " ) ;
var_end = strchr ( var_begin , ' | ' ) ;
2009-03-14 14:30:37 +00:00
2009-03-10 13:16:14 +00:00
if ( var_end ) {
2009-03-14 14:30:37 +00:00
strncpy ( variable_buffer , var_begin , var_end - var_begin ) ;
2009-03-10 13:16:14 +00:00
} else {
2009-03-14 14:30:37 +00:00
strncpy ( variable_buffer , var_begin , strlen ( var_begin ) ) ;
2009-03-10 13:16:14 +00:00
}
2009-03-14 14:30:37 +00:00
current_variable = variable_buffer ;
2009-03-14 14:14:51 +00:00
}
2009-03-14 14:30:37 +00:00
if ( current_variable | | ( current_variable = switch_event_get_header ( var_event , " origination_privacy " ) ) ) {
2009-03-10 13:16:14 +00:00
new_profile - > flags = SWITCH_CPF_NONE ;
2009-03-14 14:14:51 +00:00
2009-03-14 14:30:37 +00:00
if ( switch_stristr ( " screen " , current_variable ) ) {
2009-03-10 13:16:14 +00:00
switch_set_flag ( new_profile , SWITCH_CPF_SCREEN ) ;
}
2009-03-14 14:30:37 +00:00
if ( switch_stristr ( " hide_name " , current_variable ) ) {
2009-03-10 13:16:14 +00:00
switch_set_flag ( new_profile , SWITCH_CPF_HIDE_NAME ) ;
}
2009-03-14 14:30:37 +00:00
if ( switch_stristr ( " hide_number " , current_variable ) ) {
2009-03-10 13:16:14 +00:00
switch_set_flag ( new_profile , SWITCH_CPF_HIDE_NUMBER ) ;
}
}
2009-03-14 14:30:37 +00:00
current_variable = NULL ;
switch_event_add_header_string ( var_event , SWITCH_STACK_BOTTOM , " originate_early_media " , oglobals . early_ok ? " true " : " false " ) ;
2009-01-19 17:54:54 +00:00
if ( ( reason = switch_core_session_outgoing_channel ( oglobals . session , var_event , chan_type ,
2008-10-09 00:38:59 +00:00
new_profile , & new_session , & pool , myflags ) ) ! = SWITCH_CAUSE_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Cannot create outgoing channel of type [%s] cause: [%s] \n " ,
2008-10-09 00:38:59 +00:00
chan_type , switch_channel_cause2str ( reason ) ) ;
2007-03-29 22:34:40 +00:00
if ( pool ) {
switch_core_destroy_memory_pool ( & pool ) ;
}
continue ;
}
2009-01-09 20:34:01 +00:00
if ( switch_core_session_read_lock ( new_session ) ! = SWITCH_STATUS_SUCCESS ) {
status = SWITCH_STATUS_FALSE ;
goto done ;
}
2007-03-29 22:34:40 +00:00
pool = NULL ;
2009-01-19 17:54:54 +00:00
originate_status [ i ] . caller_profile = new_profile ;
originate_status [ i ] . peer_session = new_session ;
originate_status [ i ] . peer_channel = switch_core_session_get_channel ( new_session ) ;
switch_channel_set_flag ( originate_status [ i ] . peer_channel , CF_ORIGINATING ) ;
2008-05-27 04:30:03 +00:00
2009-06-18 16:35:41 +00:00
if ( ( lc = switch_event_get_header ( var_event , " local_var_clobber " ) ) ) {
local_clobber = switch_true ( lc ) ;
}
2009-06-18 19:47:29 +00:00
if ( local_clobber ) {
2009-06-18 16:35:41 +00:00
if ( var_event ) {
switch_event_t * event ;
switch_event_header_t * header ;
/* install the vars from the {} params */
for ( header = var_event - > headers ; header ; header = header - > next ) {
switch_channel_set_variable ( originate_status [ i ] . peer_channel , header - > name , header - > value ) ;
}
switch_event_create ( & event , SWITCH_EVENT_CHANNEL_ORIGINATE ) ;
switch_assert ( event ) ;
switch_channel_event_set_data ( originate_status [ i ] . peer_channel , event ) ;
switch_event_fire ( & event ) ;
}
}
2007-12-10 21:55:46 +00:00
if ( vdata ) {
char * var_array [ 1024 ] = { 0 } ;
int var_count = 0 ;
2008-06-05 15:24:14 +00:00
if ( ( var_count = switch_separate_string ( vdata , ' | ' , var_array , ( sizeof ( var_array ) / sizeof ( var_array [ 0 ] ) ) ) ) ) {
2007-12-10 21:55:46 +00:00
int x = 0 ;
for ( x = 0 ; x < var_count ; x + + ) {
2007-12-10 23:49:30 +00:00
char * inner_var_array [ 2 ] = { 0 } ;
2007-12-10 21:55:46 +00:00
int inner_var_count ;
if ( ( inner_var_count =
2008-05-27 04:30:03 +00:00
switch_separate_string ( var_array [ x ] , ' = ' ,
2007-12-10 21:55:46 +00:00
inner_var_array , ( sizeof ( inner_var_array ) / sizeof ( inner_var_array [ 0 ] ) ) ) ) = = 2 ) {
2008-05-27 04:30:03 +00:00
2009-01-19 17:54:54 +00:00
switch_channel_set_variable ( originate_status [ i ] . peer_channel , inner_var_array [ 0 ] , inner_var_array [ 1 ] ) ;
2007-12-10 21:55:46 +00:00
}
}
}
}
2008-05-27 04:30:03 +00:00
2009-06-18 19:47:29 +00:00
if ( ! local_clobber ) {
2009-06-18 16:35:41 +00:00
if ( var_event ) {
switch_event_t * event ;
switch_event_header_t * header ;
/* install the vars from the {} params */
for ( header = var_event - > headers ; header ; header = header - > next ) {
switch_channel_set_variable ( originate_status [ i ] . peer_channel , header - > name , header - > value ) ;
}
switch_event_create ( & event , SWITCH_EVENT_CHANNEL_ORIGINATE ) ;
switch_assert ( event ) ;
switch_channel_event_set_data ( originate_status [ i ] . peer_channel , event ) ;
switch_event_fire ( & event ) ;
2008-04-14 17:30:45 +00:00
}
}
2009-01-19 17:54:54 +00:00
if ( originate_status [ i ] . peer_channel ) {
2008-10-09 00:38:59 +00:00
const char * vvar ;
2009-05-06 15:13:51 +00:00
2009-01-19 17:54:54 +00:00
if ( ( vvar = switch_channel_get_variable ( originate_status [ i ] . peer_channel , " leg_timeout " ) ) ) {
2008-10-09 00:38:59 +00:00
int val = atoi ( vvar ) ;
if ( val > 0 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Setting leg timeout to %d \n " ,
2009-09-07 04:35:35 +00:00
switch_channel_get_name ( originate_status [ i ] . peer_channel ) , val ) ;
2009-01-20 00:21:58 +00:00
originate_status [ i ] . per_channel_timelimit_sec = ( uint32_t ) val ;
2008-10-09 00:38:59 +00:00
}
}
2009-01-19 17:54:54 +00:00
if ( ( vvar = switch_channel_get_variable ( originate_status [ i ] . peer_channel , " leg_progress_timeout " ) ) ) {
2008-10-09 00:38:59 +00:00
int val = atoi ( vvar ) ;
if ( val > 0 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Setting leg progress timeout to %d \n " ,
2009-09-07 04:35:35 +00:00
switch_channel_get_name ( originate_status [ i ] . peer_channel ) , val ) ;
2009-01-20 00:21:58 +00:00
originate_status [ i ] . per_channel_progress_timelimit_sec = ( uint32_t ) val ;
2008-10-09 00:38:59 +00:00
}
}
2009-03-04 04:19:33 +00:00
if ( ( vvar = switch_channel_get_variable ( originate_status [ i ] . peer_channel , " leg_delay_start " ) ) ) {
int val = atoi ( vvar ) ;
if ( val > 0 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Setting leg delay start to %d \n " ,
2009-09-07 04:35:35 +00:00
switch_channel_get_name ( originate_status [ i ] . peer_channel ) , val ) ;
2009-03-04 04:19:33 +00:00
originate_status [ i ] . per_channel_delay_start = ( uint32_t ) val ;
}
}
2008-10-09 00:38:59 +00:00
}
2007-03-29 22:34:40 +00:00
if ( ! table ) {
table = & originate_state_handlers ;
}
if ( table ) {
2009-01-19 17:54:54 +00:00
switch_channel_add_state_handler ( originate_status [ i ] . peer_channel , table ) ;
2007-03-29 22:34:40 +00:00
}
2009-01-19 17:54:54 +00:00
if ( ( flags & SOF_NOBLOCK ) & & originate_status [ i ] . peer_session ) {
2007-12-20 21:42:00 +00:00
status = SWITCH_STATUS_SUCCESS ;
2009-01-19 17:54:54 +00:00
* bleg = originate_status [ i ] . peer_session ;
2007-12-20 21:42:00 +00:00
* cause = SWITCH_CAUSE_SUCCESS ;
goto outer_for ;
}
2008-05-27 04:30:03 +00:00
2009-01-19 17:54:54 +00:00
if ( ! switch_core_session_running ( originate_status [ i ] . peer_session ) ) {
2009-03-04 04:19:33 +00:00
if ( originate_status [ i ] . per_channel_delay_start ) {
switch_channel_set_flag ( originate_status [ i ] . peer_channel , CF_BLOCK_STATE ) ;
}
2009-01-19 17:54:54 +00:00
switch_core_session_thread_launch ( originate_status [ i ] . peer_session ) ;
2007-03-29 22:34:40 +00:00
}
2008-05-27 04:30:03 +00:00
}
2007-03-29 22:34:40 +00:00
2009-01-25 21:23:07 +00:00
switch_epoch_time_now ( & start ) ;
2007-03-29 22:34:40 +00:00
for ( ; ; ) {
uint32_t valid_channels = 0 ;
for ( i = 0 ; i < and_argc ; i + + ) {
int state ;
2008-10-09 00:38:59 +00:00
time_t elapsed ;
2007-03-29 22:34:40 +00:00
2009-01-19 17:54:54 +00:00
if ( ! originate_status [ i ] . peer_channel ) {
2007-03-29 22:34:40 +00:00
continue ;
}
2008-03-25 22:05:52 +00:00
2009-01-19 17:54:54 +00:00
state = switch_channel_get_state ( originate_status [ i ] . peer_channel ) ;
2007-03-29 22:34:40 +00:00
2008-03-25 22:05:52 +00:00
if ( state < CS_HANGUP ) {
valid_channels + + ;
} else {
continue ;
}
2008-05-05 15:30:55 +00:00
if ( state > = CS_ROUTING ) {
2007-03-29 22:34:40 +00:00
goto endfor1 ;
}
if ( caller_channel & & ! switch_channel_ready ( caller_channel ) ) {
goto notready ;
}
2008-10-09 00:38:59 +00:00
2009-01-25 21:23:07 +00:00
elapsed = switch_epoch_time_now ( NULL ) - start ;
2008-10-09 00:38:59 +00:00
if ( elapsed > ( time_t ) timelimit_sec ) {
2007-03-29 22:34:40 +00:00
to + + ;
2009-01-19 17:54:54 +00:00
oglobals . idx = IDX_TIMEOUT ;
2007-03-29 22:34:40 +00:00
goto notready ;
}
2009-01-19 17:54:54 +00:00
if ( ! oglobals . sent_ring & & ! oglobals . progress & & ( progress_timelimit_sec & & elapsed > ( time_t ) progress_timelimit_sec ) ) {
2008-06-23 22:07:22 +00:00
to + + ;
2009-01-19 17:54:54 +00:00
oglobals . idx = IDX_TIMEOUT ;
2008-06-23 22:07:22 +00:00
goto notready ;
}
2008-10-09 00:38:59 +00:00
2009-02-20 19:51:34 +00:00
switch_cond_next ( ) ;
2008-03-25 22:05:52 +00:00
}
2008-05-27 04:30:03 +00:00
2009-02-03 20:33:24 +00:00
check_per_channel_timeouts ( & oglobals , originate_status , and_argc , start ) ;
2008-10-09 00:38:59 +00:00
2007-03-29 22:34:40 +00:00
if ( valid_channels = = 0 ) {
status = SWITCH_STATUS_GENERR ;
goto done ;
}
}
2008-03-25 22:05:52 +00:00
2009-01-19 23:15:59 +00:00
endfor1 :
2007-03-29 22:34:40 +00:00
2008-07-18 19:29:29 +00:00
if ( caller_channel ) {
if ( switch_channel_test_flag ( caller_channel , CF_PROXY_MODE ) | | switch_channel_test_flag ( caller_channel , CF_PROXY_MEDIA ) ) {
ringback_data = NULL ;
}
}
2007-03-29 22:34:40 +00:00
if ( ringback_data & & ! switch_channel_test_flag ( caller_channel , CF_ANSWERED )
& & ! switch_channel_test_flag ( caller_channel , CF_EARLY_MEDIA ) ) {
2008-02-20 03:57:01 +00:00
if ( ( status = switch_channel_pre_answer ( caller_channel ) ) ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( caller_channel ) , SWITCH_LOG_DEBUG , " %s Media Establishment Failed. \n " , switch_channel_get_name ( caller_channel ) ) ;
2008-02-20 03:57:01 +00:00
goto done ;
}
2007-03-29 22:34:40 +00:00
}
2009-01-19 17:54:54 +00:00
if ( oglobals . session & & ( read_codec = switch_core_session_get_read_codec ( oglobals . session ) ) & & ringback_data ) {
2007-03-29 22:34:40 +00:00
if ( ! ( pass = ( uint8_t ) switch_test_flag ( read_codec , SWITCH_CODEC_FLAG_PASSTHROUGH ) ) ) {
if ( switch_core_codec_init ( & write_codec ,
" L16 " ,
NULL ,
2007-10-19 15:31:02 +00:00
read_codec - > implementation - > actual_samples_per_second ,
2008-10-20 17:48:42 +00:00
read_codec - > implementation - > microseconds_per_packet / 1000 ,
2008-05-27 04:30:03 +00:00
1 , SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , NULL ,
2009-01-19 17:54:54 +00:00
switch_core_session_get_pool ( oglobals . session ) ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( oglobals . session ) , SWITCH_LOG_DEBUG ,
2007-03-29 22:34:40 +00:00
" Raw Codec Activation Success L16@%uhz 1 channel %dms \n " ,
2008-05-27 04:30:03 +00:00
read_codec - > implementation - > actual_samples_per_second ,
2008-10-20 17:48:42 +00:00
read_codec - > implementation - > microseconds_per_packet / 1000 ) ;
2007-03-29 22:34:40 +00:00
write_frame . codec = & write_codec ;
2008-10-20 17:48:42 +00:00
write_frame . datalen = read_codec - > implementation - > decoded_bytes_per_packet ;
2007-03-29 22:34:40 +00:00
write_frame . samples = write_frame . datalen / 2 ;
memset ( write_frame . data , 255 , write_frame . datalen ) ;
if ( ringback_data ) {
char * tmp_data = NULL ;
2009-01-20 15:39:32 +00:00
oglobals . gen_ringback = 1 ;
2007-12-06 20:03:27 +00:00
if ( switch_is_file_path ( ringback_data ) ) {
2007-03-29 22:34:40 +00:00
char * ext ;
2008-05-27 04:30:03 +00:00
2007-12-20 21:42:00 +00:00
if ( strrchr ( ringback_data , ' . ' ) | | strstr ( ringback_data , SWITCH_URL_SEPARATOR ) ) {
2009-01-19 17:54:54 +00:00
switch_core_session_set_read_codec ( oglobals . session , & write_codec ) ;
2007-03-29 22:34:40 +00:00
} else {
ringback . asis + + ;
write_frame . codec = read_codec ;
ext = read_codec - > implementation - > iananame ;
tmp_data = switch_mprintf ( " %s.%s " , ringback_data , ext ) ;
ringback_data = tmp_data ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( oglobals . session ) , SWITCH_LOG_DEBUG , " Play Ringback File [%s] \n " , ringback_data ) ;
2007-03-29 22:34:40 +00:00
ringback . fhb . channels = read_codec - > implementation - > number_of_channels ;
2007-10-19 15:31:02 +00:00
ringback . fhb . samplerate = read_codec - > implementation - > actual_samples_per_second ;
2007-03-29 22:34:40 +00:00
if ( switch_core_file_open ( & ringback . fhb ,
ringback_data ,
read_codec - > implementation - > number_of_channels ,
2007-10-19 15:31:02 +00:00
read_codec - > implementation - > actual_samples_per_second ,
2008-05-27 04:30:03 +00:00
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:34:40 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Playing File \n " ) ;
switch_safe_free ( tmp_data ) ;
goto notready ;
}
ringback . fh = & ringback . fhb ;
2008-12-09 00:32:51 +00:00
} else if ( ! strncasecmp ( ringback_data , " silence " , 7 ) ) {
2008-12-11 20:52:04 +00:00
const char * c = ringback_data + 7 ;
if ( * c = = ' : ' ) {
c + + ;
if ( c ) {
ringback . silence = atoi ( c ) ;
2008-12-09 00:32:51 +00:00
}
}
if ( ringback . silence < = 0 ) {
ringback . silence = 400 ;
}
2007-03-29 22:34:40 +00:00
} else {
2008-12-09 18:52:16 +00:00
switch_buffer_create_dynamic ( & ringback . audio_buffer , 512 , 1024 , 0 ) ;
switch_buffer_set_loops ( ringback . audio_buffer , - 1 ) ;
2007-03-29 22:34:40 +00:00
teletone_init_session ( & ringback . ts , 0 , teletone_handler , & ringback ) ;
2007-10-19 15:31:02 +00:00
ringback . ts . rate = read_codec - > implementation - > actual_samples_per_second ;
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Play Ringback Tone [%s] \n " , ringback_data ) ;
2008-09-02 10:46:44 +00:00
/* ringback.ts.debug = 1;
ringback . ts . debug_stream = switch_core_get_console ( ) ;
*/
2007-03-29 22:34:40 +00:00
if ( teletone_run ( & ringback . ts , ringback_data ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error Playing Tone \n " ) ;
teletone_destroy_session ( & ringback . ts ) ;
switch_buffer_destroy ( & ringback . audio_buffer ) ;
ringback_data = NULL ;
}
}
switch_safe_free ( tmp_data ) ;
}
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( caller_channel ) , SWITCH_LOG_ERROR , " Codec Error! \n " ) ;
2007-03-29 22:34:40 +00:00
switch_channel_hangup ( caller_channel , SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE ) ;
read_codec = NULL ;
}
}
}
if ( ringback_data ) {
2009-01-19 17:54:54 +00:00
oglobals . early_ok = 0 ;
2007-03-29 22:34:40 +00:00
}
2009-01-19 17:54:54 +00:00
while ( ( ! caller_channel | | switch_channel_ready ( caller_channel ) ) & & check_channel_status ( & oglobals , originate_status , and_argc ) ) {
2009-01-25 21:23:07 +00:00
time_t elapsed = switch_epoch_time_now ( NULL ) - start ;
2009-01-19 19:32:44 +00:00
if ( caller_channel & & ! oglobals . sent_ring & & oglobals . ring_ready & & ! oglobals . return_ring_ready ) {
2008-01-05 16:20:39 +00:00
switch_channel_ring_ready ( caller_channel ) ;
2009-01-19 17:54:54 +00:00
oglobals . sent_ring = 1 ;
2008-01-05 16:20:39 +00:00
}
2008-09-02 10:46:44 +00:00
/* When the AND operator is being used, and fail_on_single_reject is set, a hangup indicates that the call should fail. */
2008-10-08 20:59:16 +00:00
2009-02-03 20:33:24 +00:00
check_per_channel_timeouts ( & oglobals , originate_status , and_argc , start ) ;
2008-10-09 00:38:59 +00:00
2009-01-19 17:54:54 +00:00
if ( oglobals . session & & switch_core_session_private_event_count ( oglobals . session ) ) {
switch_ivr_parse_all_events ( oglobals . session ) ;
2008-12-08 17:08:26 +00:00
}
2009-01-19 17:54:54 +00:00
if ( ! oglobals . sent_ring & & ! oglobals . progress & & ( progress_timelimit_sec & & elapsed > ( time_t ) progress_timelimit_sec ) ) {
oglobals . idx = IDX_TIMEOUT ;
2007-03-29 22:34:40 +00:00
goto notready ;
}
2009-01-19 17:54:54 +00:00
if ( ( to = ( uint8_t ) ( elapsed > = ( time_t ) timelimit_sec ) ) | | ( fail_on_single_reject & & oglobals . hups ) ) {
2008-10-09 00:38:59 +00:00
int ok = 0 ;
if ( fail_on_single_reject_var & & ! switch_true ( fail_on_single_reject_var ) ) {
ok = 1 ;
for ( i = 0 ; i < and_argc ; i + + ) {
switch_channel_t * pchannel ;
const char * cause_str ;
2009-01-19 17:54:54 +00:00
if ( ! originate_status [ i ] . peer_session ) {
2008-10-09 00:38:59 +00:00
continue ;
}
2009-01-19 17:54:54 +00:00
pchannel = switch_core_session_get_channel ( originate_status [ i ] . peer_session ) ;
2008-10-09 00:38:59 +00:00
2009-02-25 03:41:18 +00:00
if ( switch_channel_down ( pchannel ) ) {
2008-10-10 00:29:45 +00:00
cause_str = switch_channel_cause2str ( switch_channel_get_cause ( pchannel ) ) ;
2008-10-09 00:38:59 +00:00
if ( switch_stristr ( cause_str , fail_on_single_reject_var ) ) {
ok = 0 ;
break ;
}
}
}
}
if ( ! ok ) {
2009-01-19 17:54:54 +00:00
oglobals . idx = IDX_TIMEOUT ;
2008-10-09 00:38:59 +00:00
goto notready ;
}
}
2009-01-19 17:54:54 +00:00
if ( originate_status [ 0 ] . peer_session
& & switch_core_session_dequeue_message ( originate_status [ 0 ] . peer_session , & message ) = = SWITCH_STATUS_SUCCESS ) {
2009-01-19 19:32:44 +00:00
if ( oglobals . session & & ! ringback_data & & or_argc = = 1 & & and_argc = = 1 ) {
/* when there is only 1 channel to call and bridge and no ringback */
2009-01-19 17:54:54 +00:00
switch_core_session_receive_message ( oglobals . session , message ) ;
2007-03-29 22:34:40 +00:00
}
if ( switch_test_flag ( message , SCSMF_DYNAMIC ) ) {
switch_safe_free ( message ) ;
} else {
message = NULL ;
}
}
2008-05-27 04:30:03 +00:00
/* read from the channel while we wait if the audio is up on it */
2009-01-19 17:54:54 +00:00
if ( oglobals . session & &
2008-05-27 04:30:03 +00:00
! switch_channel_test_flag ( caller_channel , CF_PROXY_MODE ) & &
! switch_channel_test_flag ( caller_channel , CF_PROXY_MEDIA ) & &
( ringback_data
| | ( switch_channel_test_flag ( caller_channel , CF_ANSWERED ) | | switch_channel_test_flag ( caller_channel , CF_EARLY_MEDIA ) ) ) ) {
2008-09-04 18:29:43 +00:00
switch_status_t tstatus = SWITCH_STATUS_SUCCESS ;
2008-12-09 18:52:16 +00:00
int silence = 0 ;
2008-05-27 04:30:03 +00:00
2009-08-26 19:49:35 +00:00
if ( caller_channel & & cancel_key ) {
if ( switch_channel_has_dtmf ( caller_channel ) ) {
switch_dtmf_t dtmf = { 0 , 0 } ;
if ( switch_channel_dequeue_dtmf ( caller_channel , & dtmf ) = = SWITCH_STATUS_SUCCESS ) {
if ( dtmf . digit = = * cancel_key ) {
2009-08-27 16:43:55 +00:00
oglobals . idx = IDX_CANCEL ;
2009-08-26 19:49:35 +00:00
goto notready ;
}
}
}
}
2008-09-04 18:29:43 +00:00
if ( switch_channel_media_ready ( caller_channel ) ) {
2009-01-19 17:54:54 +00:00
tstatus = switch_core_session_read_frame ( oglobals . session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2008-09-04 18:29:43 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( tstatus ) ) {
break ;
}
} else {
read_frame = NULL ;
2007-03-29 22:34:40 +00:00
}
2009-01-19 19:32:44 +00:00
2009-02-11 00:22:41 +00:00
if ( ( oglobals . ring_ready | | oglobals . instant_ringback ) & & read_frame & & ! pass ) {
2007-03-29 22:34:40 +00:00
if ( ringback . fh ) {
switch_size_t mlen , olen ;
unsigned int pos = 0 ;
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
if ( ringback . asis ) {
2008-10-20 17:48:42 +00:00
mlen = write_frame . codec - > implementation - > encoded_bytes_per_packet ;
2007-03-29 22:34:40 +00:00
} else {
2008-10-20 17:48:42 +00:00
mlen = write_frame . codec - > implementation - > samples_per_packet ;
2007-03-29 22:34:40 +00:00
}
olen = mlen ;
2009-01-09 20:34:01 +00:00
//if (ringback.fh->resampler && ringback.fh->resampler->rfactor > 1) {
//olen = (switch_size_t) (olen * ringback.fh->resampler->rfactor);
//}
2008-08-11 20:41:18 +00:00
2008-02-18 21:32:35 +00:00
switch_core_file_read ( ringback . fh , write_frame . data , & olen ) ;
2007-03-29 22:34:40 +00:00
if ( olen = = 0 ) {
olen = mlen ;
ringback . fh - > speed = 0 ;
switch_core_file_seek ( ringback . fh , & pos , 0 , SEEK_SET ) ;
2008-02-18 21:32:35 +00:00
switch_core_file_read ( ringback . fh , write_frame . data , & olen ) ;
2007-03-29 22:34:40 +00:00
if ( olen = = 0 ) {
break ;
}
}
write_frame . datalen = ( uint32_t ) ( ringback . asis ? olen : olen * 2 ) ;
} else if ( ringback . audio_buffer ) {
2007-04-04 18:22:59 +00:00
if ( ( write_frame . datalen = ( uint32_t ) switch_buffer_read_loop ( ringback . audio_buffer ,
write_frame . data ,
2008-10-20 17:48:42 +00:00
write_frame . codec - > implementation - > decoded_bytes_per_packet ) ) < = 0 ) {
2007-04-04 18:22:59 +00:00
break ;
2007-03-29 22:34:40 +00:00
}
2008-12-09 00:32:51 +00:00
} else if ( ringback . silence ) {
2008-12-09 18:52:16 +00:00
silence = ringback . silence ;
2007-03-29 22:34:40 +00:00
}
2008-12-09 18:52:16 +00:00
} else {
2009-03-23 01:59:35 +00:00
silence = 600 ;
2008-12-09 18:52:16 +00:00
}
if ( ( ringback . fh | | silence | | ringback . audio_buffer ) & & write_frame . codec & & write_frame . datalen ) {
2008-12-09 20:28:12 +00:00
if ( silence ) {
write_frame . datalen = write_frame . codec - > implementation - > decoded_bytes_per_packet ;
switch_generate_sln_silence ( ( int16_t * ) write_frame . data , write_frame . datalen / 2 , silence ) ;
}
2009-01-19 17:54:54 +00:00
if ( switch_core_session_write_frame ( oglobals . session , & write_frame , SWITCH_IO_FLAG_NONE , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
2008-12-09 18:52:16 +00:00
break ;
2007-03-29 22:34:40 +00:00
}
}
2008-12-09 18:52:16 +00:00
2007-03-29 22:34:40 +00:00
} else {
2009-02-20 19:51:34 +00:00
switch_cond_next ( ) ;
2007-03-29 22:34:40 +00:00
}
2008-10-08 20:59:16 +00:00
2007-03-29 22:34:40 +00:00
}
notready :
if ( caller_channel & & ! switch_channel_ready ( caller_channel ) ) {
2009-01-19 17:54:54 +00:00
oglobals . idx = IDX_CANCEL ;
2007-03-29 22:34:40 +00:00
}
2009-01-19 17:54:54 +00:00
if ( oglobals . session & & ( ringback_data | | ! ( switch_channel_test_flag ( caller_channel , CF_PROXY_MODE ) & &
2008-02-21 17:48:41 +00:00
switch_channel_test_flag ( caller_channel , CF_PROXY_MEDIA ) ) ) ) {
2009-01-19 17:54:54 +00:00
switch_core_session_reset ( oglobals . session , SWITCH_FALSE , SWITCH_TRUE ) ;
2007-03-29 22:34:40 +00:00
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
for ( i = 0 ; i < and_argc ; i + + ) {
2009-01-19 17:54:54 +00:00
if ( ! originate_status [ i ] . peer_channel ) {
2007-03-29 22:34:40 +00:00
continue ;
}
2008-05-27 04:30:03 +00:00
2009-03-04 04:28:06 +00:00
//switch_channel_clear_flag(originate_status[i].peer_channel, CF_BLOCK_STATE);
2009-03-04 04:19:33 +00:00
2009-01-19 17:54:54 +00:00
if ( switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_TRANSFER )
| | switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_REDIRECT )
| | switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_BRIDGED ) | |
switch_channel_get_state ( originate_status [ i ] . peer_channel ) = = CS_RESET | |
! switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_ORIGINATING )
2008-01-05 01:03:08 +00:00
) {
continue ;
}
2009-01-19 17:54:54 +00:00
if ( i ! = oglobals . idx ) {
2008-03-13 01:08:42 +00:00
const char * holding = NULL ;
2008-04-16 21:29:57 +00:00
2009-01-19 17:54:54 +00:00
if ( oglobals . idx = = IDX_TIMEOUT | | to ) {
2008-04-16 21:29:57 +00:00
reason = SWITCH_CAUSE_NO_ANSWER ;
2007-03-29 22:34:40 +00:00
} else {
2009-01-19 17:54:54 +00:00
if ( oglobals . idx = = IDX_CANCEL ) {
2008-04-16 21:29:57 +00:00
reason = SWITCH_CAUSE_ORIGINATOR_CANCEL ;
2007-03-29 22:34:40 +00:00
} else {
2008-04-16 21:29:57 +00:00
if ( and_argc > 1 ) {
reason = SWITCH_CAUSE_LOSE_RACE ;
} else {
reason = SWITCH_CAUSE_NO_ANSWER ;
}
2007-03-29 22:34:40 +00:00
}
}
2009-03-04 04:19:33 +00:00
if ( switch_channel_up ( originate_status [ i ] . peer_channel ) ) {
2008-05-19 21:02:26 +00:00
if ( caller_channel & & i = = 0 ) {
holding = switch_channel_get_variable ( caller_channel , SWITCH_HOLDING_UUID_VARIABLE ) ;
switch_channel_set_variable ( caller_channel , SWITCH_HOLDING_UUID_VARIABLE , NULL ) ;
}
2009-08-27 16:43:55 +00:00
if ( holding & & oglobals . idx ! = IDX_TIMEOUT & & oglobals . idx ! = IDX_CANCEL ) {
2009-01-19 17:54:54 +00:00
switch_ivr_uuid_bridge ( holding , switch_core_session_get_uuid ( originate_status [ i ] . peer_session ) ) ;
2008-05-19 21:02:26 +00:00
} else {
2009-01-19 17:54:54 +00:00
switch_channel_hangup ( originate_status [ i ] . peer_channel , reason ) ;
2008-05-19 21:02:26 +00:00
}
2008-03-13 01:08:42 +00:00
}
2007-03-29 22:34:40 +00:00
}
}
2009-01-19 17:54:54 +00:00
if ( oglobals . idx > IDX_NADA ) {
peer_session = originate_status [ oglobals . idx ] . peer_session ;
peer_channel = originate_status [ oglobals . idx ] . peer_channel ;
2007-03-29 22:34:40 +00:00
} else {
status = SWITCH_STATUS_FALSE ;
2008-06-05 00:23:58 +00:00
if ( caller_channel & & peer_channel ) {
2009-03-23 16:06:32 +00:00
switch_process_import ( oglobals . session , peer_channel , " import " ) ;
2008-06-04 23:33:29 +00:00
}
2008-01-05 01:03:08 +00:00
peer_channel = NULL ;
2007-03-29 22:34:40 +00:00
goto done ;
}
if ( caller_channel ) {
if ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) ) {
2008-02-20 03:57:01 +00:00
status = switch_channel_answer ( caller_channel ) ;
2007-03-29 22:34:40 +00:00
} else if ( switch_channel_test_flag ( peer_channel , CF_EARLY_MEDIA ) ) {
2008-02-20 03:57:01 +00:00
status = switch_channel_pre_answer ( caller_channel ) ;
} else {
status = SWITCH_STATUS_SUCCESS ;
}
if ( status ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_CHANNEL_LOG ( peer_channel ) , SWITCH_LOG_DEBUG , " %s Media Establishment Failed. \n " , switch_channel_get_name ( caller_channel ) ) ;
2008-02-20 03:57:01 +00:00
switch_channel_hangup ( peer_channel , SWITCH_CAUSE_INCOMPATIBLE_DESTINATION ) ;
2007-03-29 22:34:40 +00:00
}
}
2008-05-27 04:30:03 +00:00
if ( switch_channel_test_flag ( peer_channel , CF_ANSWERED ) | |
2009-01-19 17:54:54 +00:00
( oglobals . early_ok & & switch_channel_test_flag ( peer_channel , CF_EARLY_MEDIA ) ) | |
( oglobals . return_ring_ready & & switch_channel_test_flag ( peer_channel , CF_RING_READY ) )
2008-01-05 16:20:39 +00:00
) {
2007-03-29 22:34:40 +00:00
* bleg = peer_session ;
2009-01-19 23:15:59 +00:00
if ( oglobals . monitor_early_media_ring | | oglobals . monitor_early_media_fail ) {
switch_ivr_stop_tone_detect_session ( peer_session ) ;
switch_channel_set_private ( peer_channel , " _oglobals_ " , NULL ) ;
}
2007-03-29 22:34:40 +00:00
status = SWITCH_STATUS_SUCCESS ;
} else {
status = SWITCH_STATUS_FALSE ;
}
done :
2009-09-18 22:09:47 +00:00
2008-07-03 22:51:09 +00:00
* cause = SWITCH_CAUSE_NONE ;
2007-03-29 22:34:40 +00:00
2008-02-21 02:27:27 +00:00
if ( caller_channel & & ! switch_channel_ready ( caller_channel ) ) {
status = SWITCH_STATUS_FALSE ;
}
2007-03-29 22:34:40 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
if ( caller_channel ) {
switch_channel_set_variable ( caller_channel , " originate_disposition " , " call accepted " ) ;
2008-06-05 00:23:58 +00:00
if ( peer_channel ) {
2009-03-23 16:06:32 +00:00
switch_process_import ( oglobals . session , peer_channel , " import " ) ;
2008-06-05 00:23:58 +00:00
}
2007-03-29 22:34:40 +00:00
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( oglobals . session ) , SWITCH_LOG_DEBUG , " Originate Resulted in Success: [%s] \n " , switch_channel_get_name ( peer_channel ) ) ;
2007-03-29 22:34:40 +00:00
* cause = SWITCH_CAUSE_SUCCESS ;
} else {
2008-05-30 18:11:05 +00:00
const char * cdr_var = NULL ;
switch_xml_t cdr ;
char * xml_text ;
char buf [ 128 ] = " " , buf2 [ 128 ] = " " ;
if ( caller_channel ) {
cdr_var = switch_channel_get_variable ( caller_channel , " failed_xml_cdr_prefix " ) ;
}
2007-03-29 22:34:40 +00:00
if ( peer_channel ) {
2008-05-30 18:11:05 +00:00
* cause = switch_channel_get_cause ( peer_channel ) ;
2007-03-29 22:34:40 +00:00
} else {
for ( i = 0 ; i < and_argc ; i + + ) {
2009-01-19 17:54:54 +00:00
if ( ! originate_status [ i ] . peer_channel ) {
2007-03-29 22:34:40 +00:00
continue ;
}
2009-01-19 17:54:54 +00:00
* cause = switch_channel_get_cause ( originate_status [ i ] . peer_channel ) ;
2007-03-29 22:34:40 +00:00
break ;
}
}
2008-05-30 18:11:05 +00:00
if ( cdr_var ) {
for ( i = 0 ; i < and_argc ; i + + ) {
2009-05-11 16:52:01 +00:00
switch_channel_t * channel ;
2009-01-19 17:54:54 +00:00
if ( ! originate_status [ i ] . peer_session ) {
2008-05-30 18:11:05 +00:00
continue ;
}
2009-05-11 16:52:01 +00:00
channel = switch_core_session_get_channel ( originate_status [ i ] . peer_session ) ;
2008-05-30 18:11:05 +00:00
2009-05-12 14:54:34 +00:00
switch_channel_wait_for_state_timeout ( channel , CS_REPORTING , 5000 ) ;
if ( ! switch_channel_test_flag ( channel , CF_TIMESTAMP_SET ) ) {
switch_channel_set_timestamps ( channel ) ;
2009-05-11 16:52:01 +00:00
}
2009-05-12 14:54:34 +00:00
2009-01-19 17:54:54 +00:00
if ( switch_ivr_generate_xml_cdr ( originate_status [ i ] . peer_session , & cdr ) = = SWITCH_STATUS_SUCCESS ) {
2008-05-30 18:11:05 +00:00
if ( ( xml_text = switch_xml_toxml ( cdr , SWITCH_FALSE ) ) ) {
switch_snprintf ( buf , sizeof ( buf ) , " %s_%d " , cdr_var , + + cdr_total ) ;
switch_channel_set_variable ( caller_channel , buf , xml_text ) ;
switch_safe_free ( xml_text ) ;
}
switch_xml_free ( cdr ) ;
cdr = NULL ;
}
}
switch_snprintf ( buf , sizeof ( buf ) , " %s_total " , cdr_var ) ;
switch_snprintf ( buf2 , sizeof ( buf2 ) , " %d " , cdr_total ? cdr_total : 0 ) ;
switch_channel_set_variable ( caller_channel , buf , buf2 ) ;
}
2007-03-29 22:34:40 +00:00
if ( ! * cause ) {
if ( reason ) {
* cause = reason ;
} else if ( caller_channel ) {
* cause = switch_channel_get_cause ( caller_channel ) ;
} else {
* cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
}
2008-07-03 22:51:09 +00:00
if ( * cause = = SWITCH_CAUSE_SUCCESS | | * cause = = SWITCH_CAUSE_NONE ) {
2008-01-05 01:03:08 +00:00
* cause = SWITCH_CAUSE_ORIGINATOR_CANCEL ;
}
2009-01-19 17:54:54 +00:00
if ( oglobals . idx = = IDX_CANCEL ) {
2008-03-25 22:05:52 +00:00
* cause = SWITCH_CAUSE_ORIGINATOR_CANCEL ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( oglobals . session ) , SWITCH_LOG_DEBUG ,
2007-03-30 00:13:31 +00:00
" Originate Cancelled by originator termination Cause: %d [%s] \n " , * cause , switch_channel_cause2str ( * cause ) ) ;
2007-03-29 22:34:40 +00:00
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( oglobals . session ) , SWITCH_LOG_DEBUG ,
2007-03-30 00:13:31 +00:00
" Originate Resulted in Error Cause: %d [%s] \n " , * cause , switch_channel_cause2str ( * cause ) ) ;
2007-03-29 22:34:40 +00:00
}
}
if ( caller_channel ) {
switch_channel_set_variable ( caller_channel , " originate_disposition " , switch_channel_cause2str ( * cause ) ) ;
}
if ( ringback . fh ) {
switch_core_file_close ( ringback . fh ) ;
ringback . fh = NULL ;
2008-01-05 01:03:08 +00:00
} else if ( ringback . audio_buffer ) {
teletone_destroy_session ( & ringback . ts ) ;
switch_buffer_destroy ( & ringback . audio_buffer ) ;
}
2009-01-19 17:54:54 +00:00
if ( oglobals . session ) {
switch_core_session_reset ( oglobals . session , SWITCH_FALSE , SWITCH_TRUE ) ;
2008-07-15 19:14:15 +00:00
}
2008-07-15 17:39:16 +00:00
2009-04-09 17:17:12 +00:00
if ( switch_core_codec_ready ( & write_codec ) ) {
2008-12-09 20:46:26 +00:00
switch_core_codec_destroy ( & write_codec ) ;
2007-03-29 22:34:40 +00:00
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:34:40 +00:00
for ( i = 0 ; i < and_argc ; i + + ) {
2008-11-11 14:26:21 +00:00
switch_channel_state_t state ;
2009-01-19 17:54:54 +00:00
if ( ! originate_status [ i ] . peer_channel ) {
2007-03-29 22:34:40 +00:00
continue ;
}
2008-11-11 14:26:21 +00:00
2008-06-24 22:14:47 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
2009-01-19 17:54:54 +00:00
switch_channel_clear_flag ( originate_status [ i ] . peer_channel , CF_ORIGINATING ) ;
if ( bleg & & * bleg & & * bleg = = originate_status [ i ] . peer_session ) {
2008-06-24 22:14:47 +00:00
continue ;
}
2009-01-19 17:54:54 +00:00
} else if ( ( state = switch_channel_get_state ( originate_status [ i ] . peer_channel ) ) < CS_HANGUP & &
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_ORIGINATING ) ) {
if ( ! ( state = = CS_RESET | | switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_TRANSFER ) | |
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_REDIRECT ) | |
switch_channel_test_flag ( originate_status [ i ] . peer_channel , CF_BRIDGED ) ) ) {
switch_channel_hangup ( originate_status [ i ] . peer_channel , * cause ) ;
2008-11-11 14:26:21 +00:00
}
2007-04-13 22:15:58 +00:00
}
2009-01-19 17:54:54 +00:00
switch_channel_clear_flag ( originate_status [ i ] . peer_channel , CF_ORIGINATING ) ;
2008-06-24 22:14:47 +00:00
2009-01-19 17:54:54 +00:00
switch_core_session_rwunlock ( originate_status [ i ] . peer_session ) ;
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 ( status = = SWITCH_STATUS_SUCCESS ) {
goto outer_for ;
2009-09-18 22:09:47 +00:00
} else {
int ok = 0 ;
if ( fail_on_single_reject_var & & ! switch_true ( fail_on_single_reject_var ) ) {
ok = 1 ;
for ( i = 0 ; i < and_argc ; i + + ) {
switch_channel_t * pchannel ;
const char * cause_str ;
if ( ! originate_status [ i ] . peer_session ) {
continue ;
}
pchannel = switch_core_session_get_channel ( originate_status [ i ] . peer_session ) ;
if ( switch_channel_down ( pchannel ) ) {
cause_str = switch_channel_cause2str ( switch_channel_get_cause ( pchannel ) ) ;
if ( switch_stristr ( cause_str , fail_on_single_reject_var ) ) {
ok = 0 ;
break ;
}
}
}
}
if ( ! ok ) {
goto outer_for ;
}
2007-03-29 22:34:40 +00:00
}
}
}
outer_for :
switch_safe_free ( loop_data ) ;
switch_safe_free ( odata ) ;
2007-04-13 22:15:58 +00:00
if ( bleg & & status ! = SWITCH_STATUS_SUCCESS ) {
* bleg = NULL ;
}
2008-12-01 16:21:27 +00:00
if ( * bleg ) {
2009-03-21 16:47:16 +00:00
if ( session & & caller_channel & & ! switch_channel_get_originatee_caller_profile ( caller_channel ) ) {
2009-03-12 16:47:47 +00:00
switch_caller_profile_t * cloned_profile , * peer_profile = switch_channel_get_caller_profile ( switch_core_session_get_channel ( * bleg ) ) ;
if ( peer_profile ) {
2009-03-21 16:47:16 +00:00
if ( ( cloned_profile = switch_caller_profile_clone ( session , peer_profile ) ) ! = 0 ) {
2009-03-12 16:47:47 +00:00
switch_channel_set_originatee_caller_profile ( caller_channel , cloned_profile ) ;
}
}
}
2008-12-10 00:48:24 +00:00
switch_ivr_sleep ( * bleg , 0 , SWITCH_TRUE , NULL ) ;
2008-12-01 16:21:27 +00:00
}
2009-01-23 14:16:34 +00:00
if ( oglobals . session & & status = = SWITCH_STATUS_SUCCESS ) {
2009-01-19 17:54:54 +00:00
switch_ivr_sleep ( oglobals . session , 0 , SWITCH_TRUE , NULL ) ;
2008-12-01 16:21:27 +00:00
}
2008-05-27 04:30:03 +00:00
2008-12-05 14:59:24 +00:00
if ( var_event & & var_event ! = ovars ) {
2007-10-04 20:30:59 +00:00
switch_event_destroy ( & var_event ) ;
}
2009-09-18 22:09:47 +00:00
2008-02-18 21:32:35 +00:00
switch_safe_free ( write_frame . data ) ;
2009-09-18 22:09:47 +00:00
switch_safe_free ( fail_on_single_reject_var ) ;
2007-10-04 20:30:59 +00:00
2007-03-29 22:34:40 +00:00
return status ;
}
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
*/