2006-01-26 18:00:27 +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 >
2006-01-26 18:00:27 +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 >
2006-01-26 18:00:27 +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 >
2006-10-28 04:40:59 +00:00
* Paul D . Tinsley < pdt at jackhammer . org >
2006-11-13 16:29:16 +00:00
* Neal Horman < neal at wanlink dot com >
2006-11-29 20:07:13 +00:00
* Matt Klein < mklein @ nmedia . net >
2007-02-03 04:09:43 +00:00
* Michael Jerris < mike @ jerris . com >
2008-01-16 22:13:36 +00:00
* Ken Rice < krice at suspicious dot org >
2006-01-26 18:00:27 +00:00
*
2006-12-04 05:41:03 +00:00
* switch_ivr . c - - IVR Library
2006-01-26 18:00:27 +00:00
*
*/
2008-01-27 17:36:53 +00:00
2006-01-26 18:00:27 +00:00
# include <switch.h>
# include <switch_ivr.h>
2007-10-04 15:09:44 +00:00
# include "stfu.h"
2006-10-25 04:28:49 +00:00
2009-02-05 19:53:13 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_sound_test ( switch_core_session_t * session )
{
switch_codec_implementation_t imp = { 0 } ;
switch_codec_t codec = { 0 } ;
int16_t peak = 0 ;
int16_t * data ;
switch_frame_t * read_frame = NULL ;
2009-02-06 23:49:22 +00:00
uint32_t i ;
2009-02-05 19:53:13 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
int64_t global_total = 0 , global_sum = 0 , period_sum = 0 ;
int period_total = 0 ;
int period_avg = 0 , global_avg = 0 ;
int avg = 0 ;
int period_len ;
switch_core_session_get_read_impl ( session , & imp ) ;
period_len = imp . actual_samples_per_second / imp . samples_per_packet ;
if ( switch_core_codec_init ( & codec ,
" L16 " ,
NULL ,
imp . samples_per_second ,
imp . microseconds_per_packet / 1000 ,
imp . number_of_channels ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , NULL ,
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_ERROR , " Codec Error L16@%uhz %u channels %dms \n " ,
2009-02-05 19:53:13 +00:00
imp . samples_per_second , imp . number_of_channels , imp . microseconds_per_packet / 1000 ) ;
return SWITCH_STATUS_FALSE ;
}
while ( switch_channel_ready ( channel ) ) {
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
}
if ( switch_test_flag ( read_frame , SFF_CNG ) | | ! read_frame - > samples ) {
continue ;
}
data = ( int16_t * ) read_frame - > data ;
peak = 0 ;
avg = 0 ;
for ( i = 0 ; i < read_frame - > samples ; i + + ) {
2009-02-06 23:49:22 +00:00
const int16_t s = ( int16_t ) abs ( data [ i ] ) ;
2009-02-05 19:53:13 +00:00
if ( s > peak ) {
peak = s ;
}
avg + = s ;
}
avg / = read_frame - > samples ;
period_sum + = peak ;
global_sum + = peak ;
global_total + + ;
period_total + + ;
2009-02-06 23:49:22 +00:00
period_avg = ( int ) ( period_sum / period_total ) ;
2009-02-05 19:53:13 +00:00
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_CONSOLE ,
2009-02-05 19:53:13 +00:00
" \n packet_avg=%d packet_peak=%d period_avg=%d global_avg=%d \n \n " , avg , peak , period_avg , global_avg ) ;
if ( period_total > = period_len ) {
2009-02-06 23:49:22 +00:00
global_avg = ( int ) ( global_sum / global_total ) ;
2009-02-05 19:53:13 +00:00
period_total = 0 ;
period_sum = 0 ;
}
}
switch_core_codec_destroy ( & codec ) ;
return SWITCH_STATUS_SUCCESS ;
}
2008-12-10 00:48:24 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_sleep ( switch_core_session_t * session , uint32_t ms , switch_bool_t sync , switch_input_args_t * args )
2006-07-13 13:20:20 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2006-07-13 13:20:20 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2009-01-25 21:23:07 +00:00
switch_time_t start = switch_micro_time_now ( ) , now , done = switch_micro_time_now ( ) + ( ms * 1000 ) ;
2008-10-03 18:14:11 +00:00
switch_frame_t * read_frame , cng_frame = { 0 } ;
2006-07-13 13:20:20 +00:00
int32_t left , elapsed ;
2008-10-03 18:14:11 +00:00
char data [ 2 ] = " " ;
2008-12-09 00:32:51 +00:00
switch_frame_t write_frame = { 0 } ;
unsigned char * abuf = NULL ;
switch_codec_implementation_t imp = { 0 } ;
switch_codec_t codec = { 0 } ;
int sval = 0 ;
const char * var ;
2009-01-06 22:39:48 +00:00
2009-02-03 20:33:24 +00:00
/*
2009-01-19 16:00:11 +00:00
if ( ! switch_channel_test_flag ( channel , CF_OUTBOUND ) & & ! switch_channel_test_flag ( channel , CF_PROXY_MODE ) & &
! switch_channel_media_ready ( channel ) & & ! switch_channel_test_flag ( channel , CF_SERVICE ) ) {
2009-01-06 22:39:48 +00:00
if ( ( status = switch_channel_pre_answer ( channel ) ) ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Cannot establish media. \n " ) ;
2009-01-06 22:39:48 +00:00
return SWITCH_STATUS_FALSE ;
}
}
2009-02-03 20:33:24 +00:00
*/
2009-01-06 22:39:48 +00:00
2009-01-19 16:00:11 +00:00
if ( ! switch_channel_media_ready ( channel ) ) {
switch_yield ( ms * 1000 ) ;
return SWITCH_STATUS_SUCCESS ;
}
if ( ms > 100 & & ( var = switch_channel_get_variable ( channel , SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE ) ) & & ( sval = atoi ( var ) ) ) {
2008-12-09 00:32:51 +00:00
switch_core_session_get_read_impl ( session , & imp ) ;
2009-01-06 21:07:58 +00:00
2008-12-09 00:32:51 +00:00
if ( switch_core_codec_init ( & codec ,
" L16 " ,
NULL ,
imp . samples_per_second ,
imp . microseconds_per_packet / 1000 ,
imp . number_of_channels ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , NULL ,
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_ERROR , " Codec Error L16@%uhz %u channels %dms \n " ,
2008-12-09 00:32:51 +00:00
imp . samples_per_second , imp . number_of_channels , imp . microseconds_per_packet / 1000 ) ;
return SWITCH_STATUS_FALSE ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Codec Activated L16@%uhz %u channels %dms \n " ,
2008-12-09 00:32:51 +00:00
imp . samples_per_second , imp . number_of_channels , imp . microseconds_per_packet / 1000 ) ;
write_frame . codec = & codec ;
switch_zmalloc ( abuf , SWITCH_RECOMMENDED_BUFFER_SIZE ) ;
write_frame . data = abuf ;
write_frame . buflen = SWITCH_RECOMMENDED_BUFFER_SIZE ;
write_frame . datalen = imp . decoded_bytes_per_packet ;
write_frame . samples = write_frame . datalen / sizeof ( int16_t ) ;
2008-12-10 00:48:24 +00:00
2008-12-09 00:32:51 +00:00
}
2009-01-06 23:26:49 +00:00
if ( ! write_frame . datalen ) {
sval = 0 ;
}
2008-10-03 18:14:11 +00:00
cng_frame . data = data ;
cng_frame . datalen = 2 ;
cng_frame . buflen = 2 ;
2008-11-26 18:56:37 +00:00
switch_set_flag ( ( & cng_frame ) , SFF_CNG ) ;
2007-03-29 22:31:56 +00:00
2009-01-19 16:00:11 +00:00
if ( sync ) {
2008-12-01 16:21:27 +00:00
switch_channel_audio_sync ( channel ) ;
}
if ( ! ms ) {
return SWITCH_STATUS_SUCCESS ;
}
2008-11-27 04:02:57 +00:00
2007-03-29 22:31:56 +00:00
for ( ; ; ) {
2009-01-25 21:23:07 +00:00
now = switch_micro_time_now ( ) ;
2007-03-29 22:31:56 +00:00
elapsed = ( int32_t ) ( ( now - start ) / 1000 ) ;
2006-07-13 13:20:20 +00:00
left = ms - elapsed ;
if ( ! switch_channel_ready ( channel ) ) {
status = SWITCH_STATUS_FALSE ;
break ;
}
2008-07-08 19:26:44 +00:00
if ( switch_channel_test_flag ( channel , CF_BREAK ) ) {
switch_channel_clear_flag ( channel , CF_BREAK ) ;
status = SWITCH_STATUS_BREAK ;
break ;
}
2006-07-13 13:20:20 +00:00
if ( now > done | | left < = 0 ) {
break ;
}
2008-07-08 17:27:02 +00:00
2009-10-12 22:23:55 +00:00
switch_ivr_parse_all_events ( session ) ;
2008-07-08 23:13:02 +00:00
2008-07-08 17:27:02 +00:00
if ( args & & ( args - > input_callback | | args - > buf | | args - > buflen ) ) {
switch_dtmf_t dtmf ;
/*
dtmf handler function you can hook up to be executed when a digit is dialed during playback
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop .
*/
if ( switch_channel_has_dtmf ( channel ) ) {
if ( ! args - > input_callback & & ! args - > buf ) {
status = SWITCH_STATUS_BREAK ;
break ;
}
switch_channel_dequeue_dtmf ( channel , & dtmf ) ;
if ( args - > input_callback ) {
status = args - > input_callback ( session , ( void * ) & dtmf , SWITCH_INPUT_TYPE_DTMF , args - > buf , args - > buflen ) ;
} else {
switch_copy_string ( ( char * ) args - > buf , ( void * ) & dtmf , args - > buflen ) ;
status = SWITCH_STATUS_BREAK ;
}
}
2008-07-08 23:13:02 +00:00
2008-07-08 17:27:02 +00:00
if ( args - > input_callback ) {
switch_event_t * event = NULL ;
2009-02-21 23:19:58 +00:00
if ( switch_core_session_dequeue_event ( session , & event , SWITCH_FALSE ) = = SWITCH_STATUS_SUCCESS ) {
2008-07-08 17:27:02 +00:00
status = args - > input_callback ( session , event , SWITCH_INPUT_TYPE_EVENT , args - > buf , args - > buflen ) ;
switch_event_destroy ( & event ) ;
}
}
if ( status ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
}
2006-07-13 13:20:20 +00:00
2009-01-06 22:39:48 +00:00
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
2006-07-13 13:20:20 +00:00
}
2008-10-03 18:14:11 +00:00
2009-01-06 23:26:49 +00:00
if ( sval & & write_frame . datalen ) {
2008-12-09 00:32:51 +00:00
switch_generate_sln_silence ( ( int16_t * ) write_frame . data , write_frame . samples , sval ) ;
switch_core_session_write_frame ( session , & write_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
} else {
switch_core_session_write_frame ( session , & cng_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
}
}
2009-01-06 22:39:48 +00:00
2008-12-09 00:32:51 +00:00
if ( write_frame . codec ) {
switch_core_codec_destroy ( & codec ) ;
2006-07-13 13:20:20 +00:00
}
2007-03-29 22:31:56 +00:00
2008-12-09 00:32:51 +00:00
switch_safe_free ( abuf ) ;
2006-07-13 13:20:20 +00:00
return status ;
}
2006-01-26 18:00:27 +00:00
2007-04-09 18:38:47 +00:00
static void * SWITCH_THREAD_FUNC unicast_thread_run ( switch_thread_t * thread , void * obj )
{
switch_unicast_conninfo_t * conninfo = ( switch_unicast_conninfo_t * ) obj ;
2007-04-10 21:18:33 +00:00
switch_size_t len ;
2007-04-09 18:38:47 +00:00
switch_channel_t * channel ;
if ( ! conninfo ) {
return NULL ;
}
channel = switch_core_session_get_channel ( conninfo - > session ) ;
2008-05-27 04:30:03 +00:00
while ( switch_test_flag ( conninfo , SUF_READY ) & & switch_test_flag ( conninfo , SUF_THREAD_RUNNING ) ) {
2007-04-09 18:38:47 +00:00
len = conninfo - > write_frame . buflen ;
if ( switch_socket_recv ( conninfo - > socket , conninfo - > write_frame . data , & len ) ! = SWITCH_STATUS_SUCCESS | | len = = 0 ) {
break ;
}
2008-05-27 04:30:03 +00:00
conninfo - > write_frame . datalen = ( uint32_t ) len ;
2007-04-09 18:38:47 +00:00
conninfo - > write_frame . samples = conninfo - > write_frame . datalen / 2 ;
2008-05-08 19:19:47 +00:00
switch_core_session_write_frame ( conninfo - > session , & conninfo - > write_frame , SWITCH_IO_FLAG_NONE , conninfo - > stream_id ) ;
2007-04-09 18:38:47 +00:00
}
2008-05-27 04:30:03 +00:00
2007-04-09 18:38:47 +00:00
switch_clear_flag_locked ( conninfo , SUF_READY ) ;
switch_clear_flag_locked ( conninfo , SUF_THREAD_RUNNING ) ;
return NULL ;
}
static void unicast_thread_launch ( switch_unicast_conninfo_t * conninfo )
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
switch_threadattr_create ( & thd_attr , switch_core_session_get_pool ( conninfo - > session ) ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_set_flag_locked ( conninfo , SUF_THREAD_RUNNING ) ;
switch_thread_create ( & thread , thd_attr , unicast_thread_run , conninfo , switch_core_session_get_pool ( conninfo - > session ) ) ;
}
SWITCH_DECLARE ( switch_status_t ) switch_ivr_deactivate_unicast ( switch_core_session_t * session )
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-04-09 18:38:47 +00:00
switch_unicast_conninfo_t * conninfo ;
int sanity = 0 ;
2007-12-11 04:21:54 +00:00
if ( ! switch_channel_test_flag ( channel , CF_UNICAST ) ) {
2008-05-27 04:30:03 +00:00
return SWITCH_STATUS_FALSE ;
2007-12-11 04:21:54 +00:00
}
if ( ( conninfo = switch_channel_get_private ( channel , " unicast " ) ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Shutting down unicast connection \n " ) ;
2007-12-11 04:21:54 +00:00
switch_clear_flag_locked ( conninfo , SUF_READY ) ;
switch_socket_shutdown ( conninfo - > socket , SWITCH_SHUTDOWN_READWRITE ) ;
2008-05-27 04:30:03 +00:00
while ( switch_test_flag ( conninfo , SUF_THREAD_RUNNING ) ) {
2007-12-11 04:21:54 +00:00
switch_yield ( 10000 ) ;
if ( + + sanity > = 10000 ) {
break ;
2007-04-13 16:24:02 +00:00
}
2007-04-09 18:38:47 +00:00
}
2009-04-09 17:17:12 +00:00
if ( switch_core_codec_ready ( & conninfo - > read_codec ) ) {
2007-12-11 04:21:54 +00:00
switch_core_codec_destroy ( & conninfo - > read_codec ) ;
}
switch_socket_close ( conninfo - > socket ) ;
2007-04-09 18:38:47 +00:00
}
2007-12-11 04:21:54 +00:00
switch_channel_clear_flag ( channel , CF_UNICAST ) ;
return SWITCH_STATUS_SUCCESS ;
2007-04-09 18:38:47 +00:00
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_activate_unicast ( switch_core_session_t * session ,
2007-04-09 18:38:47 +00:00
char * local_ip ,
2007-04-10 17:34:53 +00:00
switch_port_t local_port ,
2008-05-27 04:30:03 +00:00
char * remote_ip , switch_port_t remote_port , char * transport , char * flags )
2007-04-09 18:38:47 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_unicast_conninfo_t * conninfo = switch_core_session_alloc ( session , sizeof ( * conninfo ) ) ;
2007-04-09 18:38:47 +00:00
switch_codec_t * read_codec ;
2007-12-11 19:23:57 +00:00
switch_assert ( conninfo ! = NULL ) ;
2007-04-09 18:38:47 +00:00
conninfo - > local_ip = switch_core_session_strdup ( session , local_ip ) ;
conninfo - > local_port = local_port ;
conninfo - > remote_ip = switch_core_session_strdup ( session , remote_ip ) ;
conninfo - > remote_port = remote_port ;
conninfo - > session = session ;
2008-05-27 04:30:03 +00:00
2007-04-09 18:38:47 +00:00
if ( ! strcasecmp ( transport , " udp " ) ) {
conninfo - > type = AF_INET ;
conninfo - > transport = SOCK_DGRAM ;
} else if ( ! strcasecmp ( transport , " tcp " ) ) {
conninfo - > type = AF_INET ;
conninfo - > transport = SOCK_STREAM ;
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Invalid transport %s \n " , transport ) ;
2007-04-09 18:38:47 +00:00
goto fail ;
}
2007-04-13 16:24:02 +00:00
if ( flags ) {
if ( strstr ( flags , " native " ) ) {
switch_set_flag ( conninfo , SUF_NATIVE ) ;
}
}
2007-04-09 18:38:47 +00:00
switch_mutex_init ( & conninfo - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
2008-05-27 04:30:03 +00:00
2007-04-09 18:38:47 +00:00
read_codec = switch_core_session_get_read_codec ( session ) ;
2008-05-27 04:30:03 +00:00
2007-04-13 16:24:02 +00:00
if ( ! switch_test_flag ( conninfo , SUF_NATIVE ) ) {
if ( switch_core_codec_init ( & conninfo - > read_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 ,
2007-04-13 16:24:02 +00:00
1 , SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , 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 ,
2007-04-13 16:24:02 +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 ) ;
2007-04-13 16:24:02 +00:00
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Raw Codec Activation Failed 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 ) ;
2007-04-13 16:24:02 +00:00
goto fail ;
}
2007-04-09 18:38:47 +00:00
}
conninfo - > write_frame . data = conninfo - > write_frame_data ;
conninfo - > write_frame . buflen = sizeof ( conninfo - > write_frame_data ) ;
2007-04-13 16:24:02 +00:00
conninfo - > write_frame . codec = switch_test_flag ( conninfo , SUF_NATIVE ) ? read_codec : & conninfo - > read_codec ;
2007-04-09 18:38:47 +00:00
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " connect %s:%d->%s:%d \n " ,
2007-04-09 18:38:47 +00:00
conninfo - > local_ip , conninfo - > local_port , conninfo - > remote_ip , conninfo - > remote_port ) ;
if ( switch_sockaddr_info_get ( & conninfo - > local_addr ,
2008-05-27 04:30:03 +00:00
conninfo - > local_ip , SWITCH_UNSPEC , conninfo - > local_port , 0 ,
2007-04-09 18:38:47 +00:00
switch_core_session_get_pool ( session ) ) ! = SWITCH_STATUS_SUCCESS ) {
goto fail ;
}
2008-05-27 04:30:03 +00:00
if ( switch_sockaddr_info_get ( & conninfo - > remote_addr ,
2007-04-09 18:38:47 +00:00
conninfo - > remote_ip , SWITCH_UNSPEC , conninfo - > remote_port , 0 ,
switch_core_session_get_pool ( session ) ) ! = SWITCH_STATUS_SUCCESS ) {
goto fail ;
}
2008-05-27 04:30:03 +00:00
2007-04-09 18:38:47 +00:00
if ( switch_socket_create ( & conninfo - > socket , AF_INET , SOCK_DGRAM , 0 , switch_core_session_get_pool ( session ) ) = = SWITCH_STATUS_SUCCESS ) {
if ( switch_socket_bind ( conninfo - > socket , conninfo - > local_addr ) ! = SWITCH_STATUS_SUCCESS ) {
goto fail ;
}
} else {
goto fail ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_INFO , " Created unicast connection %s:%d->%s:%d \n " ,
2007-04-09 18:38:47 +00:00
conninfo - > local_ip , conninfo - > local_port , conninfo - > remote_ip , conninfo - > remote_port ) ;
switch_channel_set_private ( channel , " unicast " , conninfo ) ;
switch_channel_set_flag ( channel , CF_UNICAST ) ;
switch_set_flag_locked ( conninfo , SUF_READY ) ;
return SWITCH_STATUS_SUCCESS ;
2008-05-27 04:30:03 +00:00
fail :
2007-04-09 18:38:47 +00:00
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_CRIT , " Failure creating unicast connection %s:%d->%s:%d \n " ,
2007-04-09 18:38:47 +00:00
conninfo - > local_ip , conninfo - > local_port , conninfo - > remote_ip , conninfo - > remote_port ) ;
2008-05-27 04:30:03 +00:00
return SWITCH_STATUS_FALSE ;
2007-04-09 18:38:47 +00:00
}
2007-01-06 17:06:18 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_parse_event ( switch_core_session_t * session , switch_event_t * event )
2006-09-07 03:58:01 +00:00
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
char * cmd = switch_event_get_header ( event , " call-command " ) ;
unsigned long cmd_hash ;
2007-09-29 01:06:08 +00:00
switch_ssize_t hlen = - 1 ;
2007-03-09 20:44:13 +00:00
unsigned long CMD_EXECUTE = switch_hashfunc_default ( " execute " , & hlen ) ;
unsigned long CMD_HANGUP = switch_hashfunc_default ( " hangup " , & hlen ) ;
unsigned long CMD_NOMEDIA = switch_hashfunc_default ( " nomedia " , & hlen ) ;
2007-04-09 18:38:47 +00:00
unsigned long CMD_UNICAST = switch_hashfunc_default ( " unicast " , & hlen ) ;
2007-05-09 19:44:15 +00:00
char * lead_frames = switch_event_get_header ( event , " lead-frames " ) ;
2007-06-25 21:25:33 +00:00
char * event_lock = switch_event_get_header ( event , " event-lock " ) ;
2009-12-10 01:29:02 +00:00
char * event_lock_pri = switch_event_get_header ( event , " event-lock-pri " ) ;
2007-06-25 21:25:33 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-12-10 21:53:23 +00:00
int el = 0 , elp = 0 ;
2007-06-25 21:25:33 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( cmd ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Invalid Command! \n " ) ;
2007-05-14 20:38:18 +00:00
return SWITCH_STATUS_FALSE ;
2007-03-29 22:31:56 +00:00
}
2007-01-06 17:06:18 +00:00
2007-03-09 20:44:13 +00:00
cmd_hash = switch_hashfunc_default ( cmd , & hlen ) ;
2006-09-07 03:58:01 +00:00
2009-08-26 17:42:36 +00:00
switch_channel_set_flag_recursive ( channel , CF_EVENT_PARSE ) ;
2007-03-29 22:31:56 +00:00
2007-06-25 21:25:33 +00:00
if ( switch_true ( event_lock ) ) {
2009-08-26 17:42:36 +00:00
switch_channel_set_flag_recursive ( channel , CF_EVENT_LOCK ) ;
2009-12-10 21:53:23 +00:00
el = 1 ;
2007-06-25 21:25:33 +00:00
}
2009-12-10 01:29:02 +00:00
if ( switch_true ( event_lock_pri ) ) {
switch_channel_set_flag_recursive ( channel , CF_EVENT_LOCK_PRI ) ;
2009-12-10 21:53:23 +00:00
elp = 1 ;
2009-12-10 01:29:02 +00:00
}
2007-05-09 19:44:15 +00:00
if ( lead_frames ) {
switch_frame_t * read_frame ;
int frame_count = atoi ( lead_frames ) ;
2008-05-19 14:30:39 +00:00
int max_frames = frame_count * 2 ;
2008-05-27 04:30:03 +00:00
while ( frame_count > 0 & & - - max_frames > 0 ) {
2008-05-08 19:19:47 +00:00
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2007-05-09 19:44:15 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
2007-06-25 21:25:33 +00:00
goto done ;
2007-05-09 19:44:15 +00:00
}
if ( ! switch_test_flag ( read_frame , SFF_CNG ) ) {
frame_count - - ;
}
}
}
2007-03-29 22:31:56 +00:00
if ( cmd_hash = = CMD_EXECUTE ) {
char * app_name = switch_event_get_header ( event , " execute-app-name " ) ;
char * app_arg = switch_event_get_header ( event , " execute-app-arg " ) ;
2009-12-15 18:45:29 +00:00
char * content_type = switch_event_get_header ( event , " content-type " ) ;
2007-03-30 22:13:19 +00:00
char * loop_h = switch_event_get_header ( event , " loops " ) ;
2008-03-12 00:11:33 +00:00
char * hold_bleg = switch_event_get_header ( event , " hold-bleg " ) ;
2007-04-09 18:38:47 +00:00
int loops = 1 ;
2007-06-25 21:25:33 +00:00
2009-12-15 18:45:29 +00:00
if ( zstr ( app_arg ) & & ! zstr ( content_type ) & & ! strcasecmp ( content_type , " text/plain " ) ) {
app_arg = switch_event_get_body ( event ) ;
}
2007-03-30 22:13:19 +00:00
if ( loop_h ) {
loops = atoi ( loop_h ) ;
}
2007-11-02 18:34:26 +00:00
2007-06-25 21:25:33 +00:00
if ( app_name ) {
2009-12-11 21:51:10 +00:00
int x ;
const char * b_uuid = NULL ;
switch_core_session_t * b_session = NULL ;
switch_channel_clear_flag ( channel , CF_STOP_BROADCAST ) ;
switch_channel_set_flag ( channel , CF_BROADCAST ) ;
if ( hold_bleg & & switch_true ( hold_bleg ) ) {
if ( ( b_uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
const char * stream ;
b_uuid = switch_core_session_strdup ( session , b_uuid ) ;
if ( ! ( stream = switch_channel_get_variable_partner ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ) ) {
stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ;
2007-03-30 22:13:19 +00:00
}
2008-03-13 01:08:42 +00:00
2009-12-11 21:51:10 +00:00
if ( stream & & switch_is_moh ( stream ) ) {
2008-03-12 00:11:33 +00:00
if ( ( b_session = switch_core_session_locate ( b_uuid ) ) ) {
switch_channel_t * b_channel = switch_core_session_get_channel ( b_session ) ;
2009-12-11 21:51:10 +00:00
switch_ivr_broadcast ( b_uuid , stream , SMF_ECHO_ALEG | SMF_LOOP ) ;
switch_channel_wait_for_flag ( b_channel , CF_BROADCAST , SWITCH_TRUE , 5000 , NULL ) ;
2008-03-12 00:11:33 +00:00
switch_core_session_rwunlock ( b_session ) ;
}
2009-12-11 21:51:10 +00:00
} else {
b_uuid = NULL ;
2008-03-12 00:11:33 +00:00
}
2009-12-11 21:51:10 +00:00
}
}
for ( x = 0 ; x < loops | | loops < 0 ; x + + ) {
switch_time_t b4 , aftr ;
2008-03-13 01:08:42 +00:00
2009-12-11 21:51:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " %s Command Execute %s(%s) \n " ,
switch_channel_get_name ( channel ) , app_name , switch_str_nil ( app_arg ) ) ;
b4 = switch_micro_time_now ( ) ;
if ( switch_core_session_execute_application ( session , app_name , app_arg ) ! = SWITCH_STATUS_SUCCESS ) {
goto done ;
}
aftr = switch_micro_time_now ( ) ;
if ( ! switch_channel_ready ( channel ) | | switch_channel_test_flag ( channel , CF_STOP_BROADCAST ) | | aftr - b4 < 500000 ) {
break ;
}
}
if ( b_uuid ) {
if ( ( b_session = switch_core_session_locate ( b_uuid ) ) ) {
switch_channel_t * b_channel = switch_core_session_get_channel ( b_session ) ;
switch_channel_stop_broadcast ( b_channel ) ;
switch_channel_wait_for_flag ( b_channel , CF_BROADCAST , SWITCH_FALSE , 5000 , NULL ) ;
switch_core_session_rwunlock ( b_session ) ;
2007-03-29 22:31:56 +00:00
}
}
2009-12-11 21:51:10 +00:00
switch_channel_clear_flag ( channel , CF_BROADCAST ) ;
2007-03-29 22:31:56 +00:00
}
2007-04-09 18:38:47 +00:00
} else if ( cmd_hash = = CMD_UNICAST ) {
2007-10-31 21:44:49 +00:00
char * local_ip = switch_event_get_header ( event , " local-ip " ) ;
char * local_port = switch_event_get_header ( event , " local-port " ) ;
char * remote_ip = switch_event_get_header ( event , " remote-ip " ) ;
char * remote_port = switch_event_get_header ( event , " remote-port " ) ;
2007-04-09 18:38:47 +00:00
char * transport = switch_event_get_header ( event , " transport " ) ;
2007-04-13 16:24:02 +00:00
char * flags = switch_event_get_header ( event , " flags " ) ;
2007-04-09 18:38:47 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( local_ip ) ) {
2007-04-09 18:38:47 +00:00
local_ip = " 127.0.0.1 " ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( remote_ip ) ) {
2007-04-09 18:38:47 +00:00
remote_ip = " 127.0.0.1 " ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( local_port ) ) {
2007-04-09 18:38:47 +00:00
local_port = " 8025 " ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( remote_port ) ) {
2007-04-09 18:38:47 +00:00
remote_port = " 8026 " ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( transport ) ) {
2007-04-09 18:38:47 +00:00
transport = " udp " ;
}
2008-05-27 04:30:03 +00:00
switch_ivr_activate_unicast ( session , local_ip , ( switch_port_t ) atoi ( local_port ) , remote_ip , ( switch_port_t ) atoi ( remote_port ) , transport , flags ) ;
2007-04-09 18:38:47 +00:00
2007-03-29 22:31:56 +00:00
} else if ( cmd_hash = = CMD_HANGUP ) {
char * cause_name = switch_event_get_header ( event , " hangup-cause " ) ;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING ;
if ( cause_name ) {
cause = switch_channel_str2cause ( cause_name ) ;
}
switch_channel_hangup ( channel , cause ) ;
} else if ( cmd_hash = = CMD_NOMEDIA ) {
char * uuid = switch_event_get_header ( event , " nomedia-uuid " ) ;
switch_ivr_nomedia ( uuid , SMF_REBRIDGE ) ;
}
2007-06-25 21:25:33 +00:00
status = SWITCH_STATUS_SUCCESS ;
2007-05-14 20:38:18 +00:00
2008-05-27 04:30:03 +00:00
done :
2009-12-10 21:53:23 +00:00
2009-08-26 17:42:36 +00:00
switch_channel_clear_flag_recursive ( channel , CF_EVENT_PARSE ) ;
2009-12-10 21:53:23 +00:00
if ( el ) {
switch_channel_clear_flag_recursive ( channel , CF_EVENT_LOCK ) ;
}
if ( elp ) {
switch_channel_clear_flag_recursive ( channel , CF_EVENT_LOCK_PRI ) ;
}
2007-06-25 21:25:33 +00:00
return status ;
2006-09-07 03:58:01 +00:00
}
2008-03-25 00:24:23 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_parse_next_event ( switch_core_session_t * session )
2007-05-14 23:50:38 +00:00
{
switch_event_t * event ;
2008-03-25 00:24:23 +00:00
if ( switch_core_session_dequeue_private_event ( session , & event ) = = SWITCH_STATUS_SUCCESS ) {
2007-05-14 23:50:38 +00:00
switch_ivr_parse_event ( session , event ) ;
switch_event_fire ( & event ) ;
2008-03-25 00:24:23 +00:00
return SWITCH_STATUS_SUCCESS ;
2007-05-14 23:50:38 +00:00
}
2008-03-25 00:24:23 +00:00
return SWITCH_STATUS_FALSE ;
}
2009-10-12 22:23:55 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_parse_all_messages ( switch_core_session_t * session )
{
switch_core_session_message_t * message ;
int i = 0 ;
while ( switch_core_session_dequeue_message ( session , & message ) = = SWITCH_STATUS_SUCCESS ) {
i + + ;
switch_core_session_receive_message ( session , message ) ;
message = NULL ;
}
return i ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE ;
}
2008-03-25 00:24:23 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_parse_all_events ( switch_core_session_t * session )
{
2009-10-12 23:27:01 +00:00
int x = 0 ;
2008-03-25 00:24:23 +00:00
2009-10-12 22:23:55 +00:00
switch_ivr_parse_all_messages ( session ) ;
2009-10-12 23:27:01 +00:00
while ( switch_ivr_parse_next_event ( session ) = = SWITCH_STATUS_SUCCESS ) x + + ;
if ( x ) {
switch_ivr_sleep ( session , 0 , SWITCH_TRUE , NULL ) ;
}
2008-12-17 21:50:34 +00:00
2007-05-14 23:50:38 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-02-16 21:32:49 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_park ( switch_core_session_t * session , switch_input_args_t * args )
2006-09-07 03:58:01 +00:00
{
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2009-05-14 13:48:11 +00:00
switch_frame_t * read_frame = NULL ;
2006-11-30 21:28:32 +00:00
int stream_id = 0 ;
2006-09-07 03:58:01 +00:00
switch_event_t * event ;
2007-04-09 18:38:47 +00:00
switch_unicast_conninfo_t * conninfo = NULL ;
2009-05-13 16:34:39 +00:00
uint32_t rate = 0 ;
uint32_t bpf = 0 ;
2008-11-13 23:25:38 +00:00
const char * to ;
int timeout = 0 ;
time_t expires = 0 ;
2009-02-10 19:09:06 +00:00
switch_codec_implementation_t read_impl = { 0 } ;
2009-05-13 16:34:39 +00:00
2009-04-30 22:45:46 +00:00
2008-04-14 14:05:22 +00:00
if ( switch_channel_test_flag ( channel , CF_CONTROLLED ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Cannot park channels that are under control already. \n " ) ;
2008-04-14 14:05:22 +00:00
return SWITCH_STATUS_FALSE ;
}
2009-04-30 22:45:46 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) | | switch_channel_get_state ( channel ) = = CS_RESET ) {
2008-09-19 19:58:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2008-11-13 23:25:38 +00:00
if ( ( to = switch_channel_get_variable ( channel , " park_timeout " ) ) ) {
if ( ( timeout = atoi ( to ) ) < 0 ) {
timeout = 0 ;
} else {
2009-01-25 21:23:07 +00:00
expires = switch_epoch_time_now ( NULL ) + timeout ;
2008-11-13 23:25:38 +00:00
}
2009-04-30 22:45:46 +00:00
switch_channel_set_variable ( channel , " park_timeout " , NULL ) ;
2009-10-07 04:30:19 +00:00
switch_channel_set_variable ( channel , SWITCH_PARK_AFTER_BRIDGE_VARIABLE , NULL ) ;
2008-11-13 23:25:38 +00:00
}
2007-10-31 23:19:30 +00:00
switch_channel_set_flag ( channel , CF_CONTROLLED ) ;
2009-04-30 22:45:46 +00:00
switch_channel_set_flag ( channel , CF_PARK ) ;
2006-09-07 03:58:01 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_PARK ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2009-05-13 16:34:39 +00:00
while ( switch_channel_ready ( channel ) & & switch_channel_test_flag ( channel , CF_CONTROLLED ) & & switch_channel_test_flag ( channel , CF_PARK ) ) {
if ( ! rate & & switch_channel_media_ready ( channel ) ) {
switch_core_session_get_read_impl ( session , & read_impl ) ;
rate = read_impl . actual_samples_per_second ;
bpf = read_impl . decoded_bytes_per_packet ;
}
if ( rate ) {
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , stream_id ) ;
} else {
switch_yield ( 20000 ) ;
status = SWITCH_STATUS_SUCCESS ;
}
2008-05-27 04:30:03 +00:00
2009-05-13 16:34:39 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
} else {
2009-01-25 21:23:07 +00:00
if ( expires & & switch_epoch_time_now ( NULL ) > = expires ) {
2010-01-21 02:51:04 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
2008-11-13 23:25:38 +00:00
break ;
}
2007-04-09 18:38:47 +00:00
if ( switch_channel_test_flag ( channel , CF_UNICAST ) ) {
2009-05-13 16:34:39 +00:00
if ( ! switch_channel_media_ready ( channel ) ) {
if ( switch_channel_pre_answer ( channel ) ! = SWITCH_STATUS_SUCCESS ) {
return SWITCH_STATUS_FALSE ;
}
}
2007-04-09 18:38:47 +00:00
if ( ! conninfo ) {
if ( ! ( conninfo = switch_channel_get_private ( channel , " unicast " ) ) ) {
switch_channel_clear_flag ( channel , CF_UNICAST ) ;
}
2008-05-27 04:30:03 +00:00
2007-04-09 18:38:47 +00:00
if ( conninfo ) {
unicast_thread_launch ( conninfo ) ;
}
}
2008-05-27 04:30:03 +00:00
2007-04-09 18:38:47 +00:00
if ( conninfo ) {
2007-04-13 16:24:02 +00:00
switch_size_t len = 0 ;
2007-04-09 18:38:47 +00:00
uint32_t flags = 0 ;
switch_byte_t decoded [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
uint32_t dlen = sizeof ( decoded ) ;
2007-12-18 17:50:39 +00:00
switch_status_t tstatus ;
2007-04-09 18:38:47 +00:00
switch_byte_t * sendbuf = NULL ;
uint32_t sendlen = 0 ;
2009-05-14 14:58:58 +00:00
switch_assert ( read_frame ) ;
2007-04-09 18:38:47 +00:00
if ( switch_test_flag ( read_frame , SFF_CNG ) ) {
2008-05-24 02:39:23 +00:00
sendlen = bpf ;
2008-05-21 22:26:30 +00:00
switch_assert ( sendlen < = SWITCH_RECOMMENDED_BUFFER_SIZE ) ;
2007-04-09 18:38:47 +00:00
memset ( decoded , 255 , sendlen ) ;
sendbuf = decoded ;
2007-12-18 18:31:38 +00:00
tstatus = SWITCH_STATUS_SUCCESS ;
2007-04-09 18:38:47 +00:00
} else {
2007-04-13 16:24:02 +00:00
if ( switch_test_flag ( conninfo , SUF_NATIVE ) ) {
2007-12-18 17:50:39 +00:00
tstatus = SWITCH_STATUS_NOOP ;
2007-04-13 16:24:02 +00:00
} else {
2009-02-10 19:09:06 +00:00
switch_codec_t * read_codec = switch_core_session_get_read_codec ( session ) ;
2008-05-27 04:30:03 +00:00
tstatus = switch_core_codec_decode ( read_codec ,
& conninfo - > read_codec ,
read_frame - > data ,
read_frame - > datalen ,
2009-02-10 19:09:06 +00:00
read_impl . actual_samples_per_second , decoded , & dlen , & rate , & flags ) ;
2007-04-13 16:24:02 +00:00
}
2007-12-18 17:50:39 +00:00
switch ( tstatus ) {
2007-04-09 18:38:47 +00:00
case SWITCH_STATUS_NOOP :
case SWITCH_STATUS_BREAK :
sendbuf = read_frame - > data ;
sendlen = read_frame - > datalen ;
2007-12-18 17:50:39 +00:00
tstatus = SWITCH_STATUS_SUCCESS ;
2007-04-09 18:38:47 +00:00
break ;
case SWITCH_STATUS_SUCCESS :
sendbuf = decoded ;
sendlen = dlen ;
2007-12-18 17:50:39 +00:00
tstatus = SWITCH_STATUS_SUCCESS ;
2007-04-09 18:38:47 +00:00
break ;
default :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Codec Error \n " ) ;
2007-04-09 18:38:47 +00:00
switch_ivr_deactivate_unicast ( session ) ;
break ;
}
}
2007-12-18 17:50:39 +00:00
if ( tstatus = = SWITCH_STATUS_SUCCESS ) {
2007-04-09 18:38:47 +00:00
len = sendlen ;
2008-05-27 04:30:03 +00:00
if ( switch_socket_sendto ( conninfo - > socket , conninfo - > remote_addr , 0 , ( void * ) sendbuf , & len ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-09 18:38:47 +00:00
switch_ivr_deactivate_unicast ( session ) ;
}
}
}
}
2008-05-27 04:30:03 +00:00
2009-10-12 22:23:55 +00:00
switch_ivr_parse_all_events ( session ) ;
2007-01-06 17:06:18 +00:00
if ( switch_channel_has_dtmf ( channel ) ) {
2008-05-27 04:30:03 +00:00
switch_dtmf_t dtmf = { 0 } ;
2007-12-22 00:32:20 +00:00
switch_channel_dequeue_dtmf ( channel , & dtmf ) ;
2007-02-16 21:32:49 +00:00
if ( args & & args - > input_callback ) {
2007-12-22 00:32:20 +00:00
if ( ( status = args - > input_callback ( session , ( void * ) & dtmf , SWITCH_INPUT_TYPE_DTMF , args - > buf , args - > buflen ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-02-16 21:32:49 +00:00
break ;
}
}
2007-03-29 22:31:56 +00:00
}
2007-01-06 17:06:18 +00:00
2009-02-21 23:19:58 +00:00
if ( switch_core_session_dequeue_event ( session , & event , SWITCH_FALSE ) = = SWITCH_STATUS_SUCCESS ) {
2007-02-16 21:32:49 +00:00
if ( args & & args - > input_callback ) {
2007-03-30 00:13:31 +00:00
if ( ( status = args - > input_callback ( session , event , SWITCH_INPUT_TYPE_EVENT , args - > buf , args - > buflen ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-02-16 21:32:49 +00:00
break ;
}
} else {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2007-03-29 22:31:56 +00:00
}
}
2006-09-07 03:58:01 +00:00
}
2008-05-24 02:39:23 +00:00
2006-09-07 03:58:01 +00:00
switch_channel_clear_flag ( channel , CF_CONTROLLED ) ;
2009-04-30 22:45:46 +00:00
switch_channel_clear_flag ( channel , CF_PARK ) ;
2006-09-07 03:58:01 +00:00
if ( switch_event_create ( & event , SWITCH_EVENT_CHANNEL_UNPARK ) = = SWITCH_STATUS_SUCCESS ) {
switch_channel_event_set_data ( channel , event ) ;
switch_event_fire ( & event ) ;
}
2007-04-09 18:38:47 +00:00
if ( switch_channel_test_flag ( channel , CF_UNICAST ) ) {
switch_ivr_deactivate_unicast ( session ) ;
}
2006-09-07 03:58:01 +00:00
return status ;
}
2009-09-25 19:07:20 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_collect_digits_callback ( switch_core_session_t * session , switch_input_args_t * args , uint32_t digit_timeout , uint32_t abs_timeout )
2006-01-27 21:33:45 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2006-04-29 23:43:28 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2009-09-25 19:07:20 +00:00
switch_time_t abs_started = 0 , digit_started = 0 ;
uint32_t abs_elapsed = 0 , digit_elapsed = 0 ;
2006-11-09 05:39:04 +00:00
2008-05-16 17:55:12 +00:00
if ( ! args | | ! args - > input_callback ) {
2006-01-27 21:33:45 +00:00
return SWITCH_STATUS_GENERR ;
}
2009-09-25 19:07:20 +00:00
if ( abs_timeout ) {
abs_started = switch_micro_time_now ( ) ;
}
if ( digit_timeout ) {
digit_started = switch_micro_time_now ( ) ;
2006-11-09 05:39:04 +00:00
}
2007-03-29 22:31:56 +00:00
while ( switch_channel_ready ( channel ) ) {
2008-04-04 21:43:20 +00:00
switch_frame_t * read_frame = NULL ;
2006-07-12 18:39:19 +00:00
switch_event_t * event ;
2008-05-27 04:30:03 +00:00
switch_dtmf_t dtmf = { 0 } ;
2006-01-27 21:33:45 +00:00
2008-04-03 21:27:16 +00:00
if ( switch_channel_test_flag ( channel , CF_BREAK ) ) {
switch_channel_clear_flag ( channel , CF_BREAK ) ;
status = SWITCH_STATUS_BREAK ;
break ;
}
2009-09-25 19:07:20 +00:00
if ( abs_timeout ) {
abs_elapsed = ( uint32_t ) ( ( switch_micro_time_now ( ) - abs_started ) / 1000 ) ;
if ( abs_elapsed > = abs_timeout ) {
status = SWITCH_STATUS_TIMEOUT ;
break ;
}
}
if ( digit_timeout ) {
digit_elapsed = ( uint32_t ) ( ( switch_micro_time_now ( ) - digit_started ) / 1000 ) ;
if ( digit_elapsed > = digit_timeout ) {
status = SWITCH_STATUS_TIMEOUT ;
2006-11-09 05:39:04 +00:00
break ;
}
}
2006-09-07 03:58:01 +00:00
2009-10-12 22:23:55 +00:00
switch_ivr_parse_all_events ( session ) ;
2006-09-07 03:58:01 +00:00
2006-01-27 21:33:45 +00:00
if ( switch_channel_has_dtmf ( channel ) ) {
2007-12-22 00:32:20 +00:00
switch_channel_dequeue_dtmf ( channel , & dtmf ) ;
2008-05-27 04:30:03 +00:00
status = args - > input_callback ( session , ( void * ) & dtmf , SWITCH_INPUT_TYPE_DTMF , args - > buf , args - > buflen ) ;
2009-09-25 19:07:20 +00:00
if ( digit_timeout ) {
digit_started = switch_micro_time_now ( ) ;
}
2006-07-12 18:39:19 +00:00
}
2009-02-21 23:19:58 +00:00
if ( switch_core_session_dequeue_event ( session , & event , SWITCH_FALSE ) = = SWITCH_STATUS_SUCCESS ) {
2007-03-29 22:31:56 +00:00
status = args - > input_callback ( session , event , SWITCH_INPUT_TYPE_EVENT , args - > buf , args - > buflen ) ;
2006-07-12 18:39:19 +00:00
switch_event_destroy ( & event ) ;
2006-01-27 21:33:45 +00:00
}
if ( status ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
2006-06-09 22:59:13 +00:00
if ( switch_channel_test_flag ( channel , CF_SERVICE ) ) {
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2006-06-09 22:59:13 +00:00
} else {
2008-05-08 19:19:47 +00:00
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2006-06-09 22:59:13 +00:00
}
2006-04-28 19:46:57 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
2006-01-27 21:33:45 +00:00
break ;
}
2008-04-04 21:18:16 +00:00
2008-04-04 21:43:20 +00:00
if ( read_frame & & args & & ( args - > read_frame_callback ) ) {
2008-04-04 21:18:16 +00:00
if ( args - > read_frame_callback ( session , read_frame , args - > user_data ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
}
2006-01-27 21:33:45 +00:00
}
return status ;
}
2006-04-29 23:43:28 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_collect_digits_count ( switch_core_session_t * session ,
2006-06-09 22:59:13 +00:00
char * buf ,
2007-10-12 20:14:41 +00:00
switch_size_t buflen ,
2008-05-27 04:30:03 +00:00
switch_size_t maxdigits ,
const char * terminators , char * terminator ,
uint32_t first_timeout , uint32_t digit_timeout , uint32_t abs_timeout )
2006-01-27 21:33:45 +00:00
{
2007-10-12 20:14:41 +00:00
switch_size_t i = 0 , x = strlen ( buf ) ;
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2006-12-04 05:41:03 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2008-01-07 16:49:46 +00:00
switch_time_t started = 0 , digit_started = 0 ;
uint32_t abs_elapsed = 0 , digit_elapsed = 0 ;
uint32_t eff_timeout = 0 ;
2008-12-09 00:32:51 +00:00
switch_frame_t write_frame = { 0 } ;
unsigned char * abuf = NULL ;
switch_codec_implementation_t imp = { 0 } ;
switch_codec_t codec = { 0 } ;
int sval = 0 ;
const char * var ;
if ( ( var = switch_channel_get_variable ( channel , SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE ) ) & & ( sval = atoi ( var ) ) ) {
switch_core_session_get_read_impl ( session , & imp ) ;
if ( switch_core_codec_init ( & codec ,
" L16 " ,
NULL ,
imp . samples_per_second ,
imp . microseconds_per_packet / 1000 ,
imp . number_of_channels ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , NULL ,
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_ERROR , " Codec Error L16@%uhz %u channels %dms \n " ,
2008-12-09 00:32:51 +00:00
imp . samples_per_second , imp . number_of_channels , imp . microseconds_per_packet / 1000 ) ;
return SWITCH_STATUS_FALSE ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Codec Activated L16@%uhz %u channels %dms \n " ,
2008-12-09 00:32:51 +00:00
imp . samples_per_second , imp . number_of_channels , imp . microseconds_per_packet / 1000 ) ;
write_frame . codec = & codec ;
switch_zmalloc ( abuf , SWITCH_RECOMMENDED_BUFFER_SIZE ) ;
write_frame . data = abuf ;
write_frame . buflen = SWITCH_RECOMMENDED_BUFFER_SIZE ;
write_frame . datalen = imp . decoded_bytes_per_packet ;
write_frame . samples = write_frame . datalen / sizeof ( int16_t ) ;
}
2006-03-01 00:58:32 +00:00
2008-12-09 00:32:51 +00:00
if ( terminator ! = NULL ) {
2006-12-04 05:41:03 +00:00
* terminator = ' \0 ' ;
2008-12-09 00:32:51 +00:00
}
2006-01-30 16:11:21 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( terminators ) ) {
2007-03-29 22:31:56 +00:00
for ( i = 0 ; i < x ; i + + ) {
2006-12-04 05:41:03 +00:00
if ( strchr ( terminators , buf [ i ] ) & & terminator ! = NULL ) {
2006-03-01 00:58:32 +00:00
* terminator = buf [ i ] ;
2008-03-12 16:40:01 +00:00
buf [ i ] = ' \0 ' ;
2006-03-01 00:58:32 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-01-30 16:11:21 +00:00
}
}
2008-01-07 16:49:46 +00:00
if ( abs_timeout ) {
2009-01-25 21:23:07 +00:00
started = switch_micro_time_now ( ) ;
2008-01-07 16:49:46 +00:00
}
if ( digit_timeout & & first_timeout ) {
eff_timeout = first_timeout ;
} else if ( digit_timeout & & ! first_timeout ) {
first_timeout = eff_timeout = digit_timeout ;
} else if ( first_timeout ) {
digit_timeout = eff_timeout = first_timeout ;
2006-03-01 00:58:32 +00:00
}
2008-05-27 04:30:03 +00:00
2008-01-07 16:49:46 +00:00
if ( eff_timeout ) {
2009-01-25 21:23:07 +00:00
digit_started = switch_micro_time_now ( ) ;
2008-01-07 16:49:46 +00:00
}
2007-03-29 22:31:56 +00:00
while ( switch_channel_ready ( channel ) ) {
2006-04-29 06:05:03 +00:00
switch_frame_t * read_frame ;
2008-05-27 04:30:03 +00:00
2008-01-07 16:49:46 +00:00
if ( abs_timeout ) {
2009-01-25 21:23:07 +00:00
abs_elapsed = ( uint32_t ) ( ( switch_micro_time_now ( ) - started ) / 1000 ) ;
2008-01-07 16:49:46 +00:00
if ( abs_elapsed > = abs_timeout ) {
2009-08-17 23:03:49 +00:00
status = SWITCH_STATUS_TIMEOUT ;
2006-03-01 00:58:32 +00:00
break ;
}
}
2007-03-29 22:31:56 +00:00
2009-10-12 22:23:55 +00:00
switch_ivr_parse_all_events ( session ) ;
2007-03-29 22:31:56 +00:00
2009-03-05 16:53:31 +00:00
2008-01-07 16:49:46 +00:00
if ( eff_timeout ) {
2009-01-25 21:23:07 +00:00
digit_elapsed = ( uint32_t ) ( ( switch_micro_time_now ( ) - digit_started ) / 1000 ) ;
2009-03-05 16:53:31 +00:00
2008-01-07 16:49:46 +00:00
if ( digit_elapsed > = eff_timeout ) {
2008-08-05 21:50:48 +00:00
status = SWITCH_STATUS_TIMEOUT ;
2008-01-07 16:49:46 +00:00
break ;
}
}
2006-01-27 21:33:45 +00:00
if ( switch_channel_has_dtmf ( channel ) ) {
2008-05-27 04:30:03 +00:00
switch_dtmf_t dtmf = { 0 } ;
2007-12-22 00:51:26 +00:00
switch_size_t y ;
2009-03-05 16:53:31 +00:00
2008-01-07 16:49:46 +00:00
if ( eff_timeout ) {
eff_timeout = digit_timeout ;
2009-01-25 21:23:07 +00:00
digit_started = switch_micro_time_now ( ) ;
2008-01-07 16:49:46 +00:00
}
2008-03-04 18:55:16 +00:00
for ( y = 0 ; y < = maxdigits ; y + + ) {
2007-12-22 00:32:20 +00:00
if ( switch_channel_dequeue_dtmf ( channel , & dtmf ) ! = SWITCH_STATUS_SUCCESS ) {
break ;
}
2006-01-27 21:33:45 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( terminators ) & & strchr ( terminators , dtmf . digit ) & & terminator ! = NULL ) {
2007-12-22 00:32:20 +00:00
* terminator = dtmf . digit ;
2006-01-27 21:33:45 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-27 04:30:03 +00:00
2007-12-22 00:32:20 +00:00
buf [ x + + ] = dtmf . digit ;
2006-01-27 21:33:45 +00:00
buf [ x ] = ' \0 ' ;
2009-03-05 16:53:31 +00:00
2006-01-27 21:33:45 +00:00
if ( x > = buflen | | x > = maxdigits ) {
return SWITCH_STATUS_SUCCESS ;
}
}
}
2006-06-09 22:59:13 +00:00
if ( switch_channel_test_flag ( channel , CF_SERVICE ) ) {
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2006-06-09 22:59:13 +00:00
} else {
2008-05-08 19:19:47 +00:00
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2006-04-28 19:46:57 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
2006-03-01 00:58:32 +00:00
break ;
}
2008-12-09 00:32:51 +00:00
if ( write_frame . data ) {
switch_generate_sln_silence ( ( int16_t * ) write_frame . data , write_frame . samples , sval ) ;
switch_core_session_write_frame ( session , & write_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
}
2006-01-27 21:33:45 +00:00
}
}
2008-12-09 00:32:51 +00:00
if ( write_frame . codec ) {
switch_core_codec_destroy ( & codec ) ;
}
switch_safe_free ( abuf ) ;
2006-01-27 21:33:45 +00:00
return status ;
}
2008-05-01 16:41:46 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_hold ( switch_core_session_t * session , const char * message , switch_bool_t moh )
2006-01-27 01:46:14 +00:00
{
2007-03-29 22:31:56 +00:00
switch_core_session_message_t msg = { 0 } ;
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2008-03-10 16:19:55 +00:00
const char * stream ;
const char * other_uuid ;
2006-03-01 22:55:28 +00:00
2007-03-29 22:31:56 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_HOLD ;
2008-03-11 03:45:16 +00:00
msg . string_arg = message ;
2007-03-29 22:31:56 +00:00
msg . from = __FILE__ ;
2006-01-27 01:46:14 +00:00
2007-03-29 22:31:56 +00:00
switch_channel_set_flag ( channel , CF_HOLD ) ;
switch_channel_set_flag ( channel , CF_SUSPEND ) ;
switch_core_session_receive_message ( session , & msg ) ;
2008-05-27 04:30:03 +00:00
2008-05-01 16:41:46 +00:00
if ( moh & & ( stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ) ) {
2008-03-10 16:19:55 +00:00
if ( ( other_uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
switch_ivr_broadcast ( other_uuid , stream , SMF_ECHO_ALEG | SMF_LOOP ) ;
}
}
2008-05-27 04:30:03 +00:00
2008-03-10 16:19:55 +00:00
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-01-27 01:46:14 +00:00
2008-05-01 16:41:46 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_hold_uuid ( const char * uuid , const char * message , switch_bool_t moh )
2007-03-29 22:31:56 +00:00
{
switch_core_session_t * session ;
2006-01-27 01:46:14 +00:00
2007-03-29 22:31:56 +00:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
2008-05-01 16:41:46 +00:00
switch_ivr_hold ( session , message , moh ) ;
2007-03-29 22:31:56 +00:00
switch_core_session_rwunlock ( session ) ;
2006-01-27 01:46:14 +00:00
}
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-01-27 01:46:14 +00:00
2007-03-29 22:31:56 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_unhold ( switch_core_session_t * session )
{
switch_core_session_message_t msg = { 0 } ;
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2008-03-10 16:19:55 +00:00
const char * other_uuid ;
switch_core_session_t * b_session ;
2006-07-25 22:37:52 +00:00
2007-03-29 22:31:56 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_UNHOLD ;
msg . from = __FILE__ ;
2006-07-25 22:37:52 +00:00
2007-03-29 22:31:56 +00:00
switch_channel_clear_flag ( channel , CF_HOLD ) ;
switch_channel_clear_flag ( channel , CF_SUSPEND ) ;
2006-07-25 22:37:52 +00:00
2007-03-29 22:31:56 +00:00
switch_core_session_receive_message ( session , & msg ) ;
2006-07-25 22:37:52 +00:00
2008-03-10 16:19:55 +00:00
if ( ( other_uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ) & & ( b_session = switch_core_session_locate ( other_uuid ) ) ) {
switch_channel_t * b_channel = switch_core_session_get_channel ( b_session ) ;
switch_channel_stop_broadcast ( b_channel ) ;
2008-09-09 16:31:53 +00:00
switch_channel_wait_for_flag ( b_channel , CF_BROADCAST , SWITCH_FALSE , 5000 , NULL ) ;
2008-03-10 16:19:55 +00:00
switch_core_session_rwunlock ( b_session ) ;
}
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-11-29 17:10:40 +00:00
2007-11-01 11:28:26 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_unhold_uuid ( const char * uuid )
2007-03-29 22:31:56 +00:00
{
switch_core_session_t * session ;
2006-01-27 01:46:14 +00:00
2007-03-29 22:31:56 +00:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
switch_ivr_unhold ( session ) ;
switch_core_session_rwunlock ( session ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
2006-09-07 03:58:01 +00:00
2007-11-01 11:28:26 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_media ( const char * uuid , switch_media_flag_t flags )
2007-03-29 22:31:56 +00:00
{
2007-11-01 11:28:26 +00:00
const char * other_uuid = NULL ;
2007-03-29 22:31:56 +00:00
switch_channel_t * channel , * other_channel = NULL ;
switch_core_session_t * session , * other_session ;
switch_core_session_message_t msg = { 0 } ;
switch_status_t status = SWITCH_STATUS_GENERR ;
uint8_t swap = 0 ;
2008-03-24 20:58:44 +00:00
switch_frame_t * read_frame = NULL ;
2008-05-27 04:30:03 +00:00
2007-03-29 22:31:56 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_MEDIA ;
msg . from = __FILE__ ;
2006-01-27 01:46:14 +00:00
2007-03-29 22:31:56 +00:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2008-01-28 07:26:10 +00:00
2009-10-07 04:30:19 +00:00
if ( ( flags & SMF_REBRIDGE ) & & ! switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
2007-03-29 22:31:56 +00:00
swap = 1 ;
}
2006-07-12 18:39:19 +00:00
2008-02-21 17:48:41 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) ) {
2007-03-29 22:31:56 +00:00
status = SWITCH_STATUS_SUCCESS ;
switch_core_session_receive_message ( session , & msg ) ;
2008-09-19 20:59:23 +00:00
if ( ( flags & SMF_IMMEDIATE ) ) {
switch_channel_wait_for_flag ( channel , CF_REQ_MEDIA , SWITCH_FALSE , 250 , NULL ) ;
switch_yield ( 250000 ) ;
} else {
2010-01-22 00:51:32 +00:00
switch_status_t st ;
2008-09-19 19:58:01 +00:00
switch_channel_wait_for_flag ( channel , CF_REQ_MEDIA , SWITCH_FALSE , 10000 , NULL ) ;
2010-01-22 00:51:32 +00:00
switch_channel_wait_for_flag ( channel , CF_MEDIA_ACK , SWITCH_TRUE , 10000 , NULL ) ;
switch_channel_wait_for_flag ( channel , CF_MEDIA_SET , SWITCH_TRUE , 10000 , NULL ) ;
st = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2008-09-19 19:58:01 +00:00
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:31:56 +00:00
if ( ( flags & SMF_REBRIDGE )
& & ( other_uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( other_uuid ) ) ) {
other_channel = switch_core_session_get_channel ( other_session ) ;
2007-12-11 19:23:57 +00:00
switch_assert ( other_channel ! = NULL ) ;
2007-03-29 22:31:56 +00:00
switch_core_session_receive_message ( other_session , & msg ) ;
2008-09-09 16:31:53 +00:00
switch_channel_wait_for_flag ( other_channel , CF_REQ_MEDIA , SWITCH_FALSE , 10000 , NULL ) ;
2010-01-23 06:53:30 +00:00
switch_channel_wait_for_flag ( other_channel , CF_MEDIA_ACK , SWITCH_TRUE , 10000 , NULL ) ;
switch_channel_wait_for_flag ( other_channel , CF_MEDIA_SET , SWITCH_TRUE , 10000 , NULL ) ;
2008-05-08 19:19:47 +00:00
switch_core_session_read_frame ( other_session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2007-03-29 22:31:56 +00:00
switch_channel_clear_state_handler ( other_channel , NULL ) ;
switch_core_session_rwunlock ( other_session ) ;
}
if ( other_channel ) {
switch_channel_clear_state_handler ( channel , NULL ) ;
2006-01-27 01:46:14 +00:00
}
}
2008-05-27 04:30:03 +00:00
2007-03-29 22:31:56 +00:00
switch_core_session_rwunlock ( session ) ;
if ( other_channel ) {
if ( swap ) {
switch_ivr_uuid_bridge ( other_uuid , uuid ) ;
2006-12-22 21:10:20 +00:00
} else {
2007-03-29 22:31:56 +00:00
switch_ivr_uuid_bridge ( uuid , other_uuid ) ;
2007-03-11 03:07:58 +00:00
}
2008-09-09 16:31:53 +00:00
switch_channel_wait_for_flag ( channel , CF_BRIDGED , SWITCH_TRUE , 1000 , NULL ) ;
switch_channel_wait_for_flag ( other_channel , CF_BRIDGED , SWITCH_TRUE , 1000 , NULL ) ;
2006-03-01 04:47:34 +00:00
}
2006-01-27 01:46:14 +00:00
}
return status ;
}
2006-01-26 18:00:27 +00:00
2007-11-01 11:28:26 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_nomedia ( const char * uuid , switch_media_flag_t flags )
2006-09-09 03:39:28 +00:00
{
2007-11-01 11:28:26 +00:00
const char * other_uuid ;
2007-03-29 22:31:56 +00:00
switch_channel_t * channel , * other_channel = NULL ;
switch_core_session_t * session , * other_session = NULL ;
switch_core_session_message_t msg = { 0 } ;
switch_status_t status = SWITCH_STATUS_GENERR ;
uint8_t swap = 0 ;
2008-05-27 04:30:03 +00:00
2007-03-29 22:31:56 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_NOMEDIA ;
msg . from = __FILE__ ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
status = SWITCH_STATUS_SUCCESS ;
channel = switch_core_session_get_channel ( session ) ;
2009-10-07 04:30:19 +00:00
if ( ( flags & SMF_REBRIDGE ) & & ! switch_channel_test_flag ( channel , CF_BRIDGE_ORIGINATOR ) ) {
2007-03-29 22:31:56 +00:00
swap = 1 ;
}
2010-01-28 18:21:27 +00:00
switch_channel_set_flag ( channel , CF_REDIRECT ) ;
switch_channel_set_flag ( channel , CF_RESET ) ;
2008-02-21 17:48:41 +00:00
if ( ( flags & SMF_FORCE ) | | ! switch_channel_test_flag ( channel , CF_PROXY_MODE ) ) {
2007-03-29 22:31:56 +00:00
if ( ( flags & SMF_REBRIDGE ) & & ( other_uuid = switch_channel_get_variable ( channel , SWITCH_BRIDGE_VARIABLE ) ) & &
( other_session = switch_core_session_locate ( other_uuid ) ) ) {
other_channel = switch_core_session_get_channel ( other_session ) ;
2010-01-28 18:21:27 +00:00
2010-01-28 17:46:57 +00:00
switch_channel_set_flag ( other_channel , CF_RESET ) ;
2010-01-23 06:53:30 +00:00
switch_channel_set_flag ( other_channel , CF_REDIRECT ) ;
switch_channel_set_state ( other_channel , CS_PARK ) ;
2010-01-28 18:21:27 +00:00
switch_channel_wait_for_state ( other_channel , channel , CS_PARK ) ;
2007-03-29 22:31:56 +00:00
switch_core_session_receive_message ( other_session , & msg ) ;
2010-01-28 18:46:47 +00:00
switch_channel_wait_for_flag ( other_channel , CF_REQ_MEDIA , SWITCH_FALSE , 10000 , NULL ) ;
switch_channel_wait_for_flag ( other_channel , CF_MEDIA_ACK , SWITCH_TRUE , 10000 , NULL ) ;
switch_channel_wait_for_flag ( other_channel , CF_MEDIA_SET , SWITCH_TRUE , 10000 , NULL ) ;
2007-03-29 22:31:56 +00:00
}
2010-01-28 18:21:27 +00:00
switch_core_session_receive_message ( session , & msg ) ;
2007-05-14 23:50:38 +00:00
2010-01-28 18:21:27 +00:00
if ( ! switch_core_session_in_thread ( session ) ) {
switch_channel_set_state ( channel , CS_PARK ) ;
switch_channel_wait_for_state ( channel , channel , CS_PARK ) ;
2010-01-28 18:46:47 +00:00
switch_channel_wait_for_flag ( channel , CF_REQ_MEDIA , SWITCH_FALSE , 10000 , NULL ) ;
switch_channel_wait_for_flag ( channel , CF_MEDIA_ACK , SWITCH_TRUE , 10000 , NULL ) ;
switch_channel_wait_for_flag ( channel , CF_MEDIA_SET , SWITCH_TRUE , 10000 , NULL ) ;
2010-01-23 18:35:05 +00:00
}
2010-01-23 06:53:30 +00:00
if ( other_channel ) {
2007-03-29 22:31:56 +00:00
if ( swap ) {
switch_ivr_signal_bridge ( other_session , session ) ;
} else {
switch_ivr_signal_bridge ( session , other_session ) ;
}
2010-01-28 18:21:27 +00:00
2010-01-23 06:53:30 +00:00
switch_channel_wait_for_state ( other_channel , channel , CS_HIBERNATE ) ;
2010-01-28 18:21:27 +00:00
if ( ! switch_core_session_in_thread ( session ) ) {
switch_channel_wait_for_state ( channel , other_channel , CS_HIBERNATE ) ;
2010-01-23 18:35:05 +00:00
}
2007-03-29 22:31:56 +00:00
switch_core_session_rwunlock ( other_session ) ;
2006-09-09 03:39:28 +00:00
}
}
2007-03-29 22:31:56 +00:00
switch_core_session_rwunlock ( session ) ;
2006-09-09 03:39:28 +00:00
}
2007-03-20 20:37:52 +00:00
2007-03-29 22:31:56 +00:00
return status ;
2006-09-09 03:39:28 +00:00
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_session_transfer ( switch_core_session_t * session , const char * extension , const char * dialplan ,
const char * context )
2006-09-09 03:39:28 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-29 22:31:56 +00:00
switch_caller_profile_t * profile , * new_profile ;
switch_core_session_message_t msg = { 0 } ;
switch_core_session_t * other_session ;
switch_channel_t * other_channel = NULL ;
2007-11-01 11:28:26 +00:00
const char * uuid = NULL ;
2008-04-14 15:55:37 +00:00
const char * max_forwards ;
const char * forwardvar = switch_channel_get_variable ( channel , SWITCH_MAX_FORWARDS_VARIABLE ) ;
int forwardval = 70 ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( forwardvar ) ) {
2008-05-27 04:30:03 +00:00
forwardval = atoi ( forwardvar ) - 1 ;
2008-04-14 15:55:37 +00:00
}
if ( forwardval < = 0 ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR ) ;
return SWITCH_STATUS_FALSE ;
}
max_forwards = switch_core_session_sprintf ( session , " %d " , forwardval ) ;
switch_channel_set_variable ( channel , SWITCH_MAX_FORWARDS_VARIABLE , max_forwards ) ;
2006-09-09 03:39:28 +00:00
2009-01-09 20:34:01 +00:00
switch_core_session_reset ( session , SWITCH_TRUE , SWITCH_TRUE ) ;
2008-01-05 01:03:08 +00:00
switch_channel_clear_flag ( channel , CF_ORIGINATING ) ;
2007-03-29 22:31:56 +00:00
/* clear all state handlers */
switch_channel_clear_state_handler ( channel , NULL ) ;
2006-09-09 03:39:28 +00:00
2007-12-05 22:35:37 +00:00
if ( ( profile = switch_channel_get_caller_profile ( channel ) ) ) {
2008-11-19 20:42:28 +00:00
const char * var ;
2009-10-23 16:03:42 +00:00
if ( zstr ( dialplan ) ) {
2007-12-05 22:35:37 +00:00
dialplan = profile - > dialplan ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( dialplan ) & & ! strcasecmp ( dialplan , " inline " ) ) {
2009-10-09 00:52:25 +00:00
dialplan = NULL ;
}
2007-12-05 22:35:37 +00:00
}
2008-05-27 04:30:03 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( context ) ) {
2007-12-05 22:35:37 +00:00
context = profile - > context ;
}
2007-09-29 01:06:08 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( dialplan ) ) {
2007-12-05 22:35:37 +00:00
dialplan = " XML " ;
}
2008-05-27 04:30:03 +00:00
2009-10-23 16:03:42 +00:00
if ( zstr ( context ) ) {
2007-12-05 22:35:37 +00:00
context = " default " ;
}
2009-10-23 16:03:42 +00:00
if ( zstr ( extension ) ) {
2007-12-05 22:35:37 +00:00
extension = " service " ;
}
2008-05-27 04:30:03 +00:00
2008-11-19 20:42:28 +00:00
if ( ( var = switch_channel_get_variable ( channel , " force_transfer_dialplan " ) ) ) {
dialplan = var ;
}
if ( ( var = switch_channel_get_variable ( channel , " force_transfer_context " ) ) ) {
context = var ;
}
2007-03-29 22:31:56 +00:00
new_profile = switch_caller_profile_clone ( session , profile ) ;
2007-06-12 21:00:26 +00:00
2008-01-16 22:13:36 +00:00
new_profile - > dialplan = switch_core_strdup ( new_profile - > pool , dialplan ) ;
new_profile - > context = switch_core_strdup ( new_profile - > pool , context ) ;
new_profile - > destination_number = switch_core_strdup ( new_profile - > pool , extension ) ;
new_profile - > rdnis = switch_core_strdup ( new_profile - > pool , profile - > destination_number ) ;
2006-09-09 03:39:28 +00:00
2007-03-29 22:31:56 +00:00
switch_channel_set_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE , NULL ) ;
2007-09-21 18:49:14 +00:00
/* If HANGUP_AFTER_BRIDGE is set to 'true', SWITCH_SIGNAL_BRIDGE_VARIABLE
* will not have a value , so we need to check SWITCH_BRIDGE_VARIABLE */
uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) ;
2007-09-29 01:06:08 +00:00
2008-02-15 23:16:01 +00:00
if ( ! uuid ) {
2007-09-21 18:49:14 +00:00
uuid = switch_channel_get_variable ( channel , SWITCH_BRIDGE_VARIABLE ) ;
}
2008-05-27 04:30:03 +00:00
2007-09-21 18:49:14 +00:00
if ( uuid & & ( other_session = switch_core_session_locate ( uuid ) ) ) {
2007-10-01 14:57:15 +00:00
other_channel = switch_core_session_get_channel ( other_session ) ;
2007-03-29 22:31:56 +00:00
switch_channel_set_variable ( other_channel , SWITCH_SIGNAL_BOND_VARIABLE , NULL ) ;
switch_core_session_rwunlock ( other_session ) ;
}
2006-09-09 03:39:28 +00:00
2007-03-29 22:31:56 +00:00
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
other_channel = switch_core_session_get_channel ( other_session ) ;
2006-09-09 03:39:28 +00:00
2007-03-29 22:31:56 +00:00
switch_channel_set_variable ( channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
switch_channel_set_variable ( other_channel , SWITCH_SIGNAL_BRIDGE_VARIABLE , NULL ) ;
2008-05-27 04:30:03 +00:00
2007-03-29 22:31:56 +00:00
switch_channel_set_variable ( channel , SWITCH_BRIDGE_VARIABLE , NULL ) ;
switch_channel_set_variable ( other_channel , SWITCH_BRIDGE_VARIABLE , NULL ) ;
2007-09-21 18:49:14 +00:00
/* If we are transferring the CALLER out of the bridge, we do not want to hang up on them */
switch_channel_set_variable ( channel , SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE , " false " ) ;
2006-09-09 03:39:28 +00:00
2007-03-29 22:31:56 +00:00
switch_channel_hangup ( other_channel , SWITCH_CAUSE_BLIND_TRANSFER ) ;
switch_ivr_media ( uuid , SMF_NONE ) ;
2006-09-09 03:39:28 +00:00
2007-03-29 22:31:56 +00:00
switch_core_session_rwunlock ( other_session ) ;
}
switch_channel_set_caller_profile ( channel , new_profile ) ;
switch_channel_set_flag ( channel , CF_TRANSFER ) ;
2007-06-25 21:25:33 +00:00
2008-05-05 15:30:55 +00:00
switch_channel_set_state ( channel , CS_ROUTING ) ;
2008-05-27 04:30:03 +00:00
2007-03-29 22:31:56 +00:00
msg . message_id = SWITCH_MESSAGE_INDICATE_TRANSFER ;
msg . from = __FILE__ ;
switch_core_session_receive_message ( session , & msg ) ;
2006-09-09 03:39:28 +00:00
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_NOTICE , " Transfer %s to %s[%s@%s] \n " , switch_channel_get_name ( channel ) , dialplan , extension ,
2007-03-30 00:15:25 +00:00
context ) ;
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
2006-09-09 03:39:28 +00:00
}
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_FALSE ;
2006-09-09 03:39:28 +00:00
}
2007-03-30 00:13:31 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_transfer_variable ( switch_core_session_t * sessa , switch_core_session_t * sessb , char * var )
2006-10-05 14:24:25 +00:00
{
switch_channel_t * chana = switch_core_session_get_channel ( sessa ) ;
switch_channel_t * chanb = switch_core_session_get_channel ( sessb ) ;
2007-11-01 11:28:26 +00:00
const char * val = NULL ;
2007-02-13 01:22:17 +00:00
uint8_t prefix = 0 ;
2006-10-05 14:24:25 +00:00
2007-02-13 01:22:17 +00:00
if ( var & & * var = = ' ~ ' ) {
var + + ;
prefix = 1 ;
}
if ( var & & ! prefix ) {
2006-10-05 14:24:25 +00:00
if ( ( val = switch_channel_get_variable ( chana , var ) ) ) {
switch_channel_set_variable ( chanb , var , val ) ;
}
} else {
2007-09-29 01:06:08 +00:00
switch_event_header_t * hi ;
2007-09-24 19:34:25 +00:00
if ( ( hi = switch_channel_variable_first ( chana ) ) ) {
2007-09-29 01:06:08 +00:00
for ( ; hi ; hi = hi - > next ) {
char * vvar = hi - > name ;
char * vval = hi - > value ;
2007-04-28 21:48:03 +00:00
if ( vvar & & vval & & ( ! prefix | | ( var & & ! strncmp ( ( char * ) vvar , var , strlen ( var ) ) ) ) ) {
switch_channel_set_variable ( chanb , ( char * ) vvar , ( char * ) vval ) ;
}
2006-10-05 14:24:25 +00:00
}
2007-04-28 21:48:03 +00:00
switch_channel_variable_last ( chana ) ;
2006-10-05 14:24:25 +00:00
}
}
2006-04-28 19:46:57 +00:00
2006-10-05 14:24:25 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-11-12 00:32:18 +00:00
2006-12-04 05:41:03 +00:00
/******************************************************************************************************/
2006-11-13 16:29:16 +00:00
struct switch_ivr_digit_stream_parser {
int pool_auto_created ;
switch_memory_pool_t * pool ;
switch_hash_t * hash ;
switch_size_t maxlen ;
2009-02-24 18:36:45 +00:00
switch_size_t buflen ;
2006-12-04 05:41:03 +00:00
switch_size_t minlen ;
2006-12-10 22:22:28 +00:00
char terminator ;
2006-12-04 05:41:03 +00:00
unsigned int digit_timeout_ms ;
2006-12-10 22:22:28 +00:00
} ;
struct switch_ivr_digit_stream {
char * digits ;
2006-12-04 05:41:03 +00:00
switch_time_t last_digit_time ;
2006-11-13 16:29:16 +00:00
} ;
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_parser_new ( switch_memory_pool_t * pool , switch_ivr_digit_stream_parser_t * * parser )
2007-03-29 22:31:56 +00:00
{
switch_status_t status = SWITCH_STATUS_FALSE ;
2006-11-13 16:29:16 +00:00
2007-03-29 22:31:56 +00:00
if ( parser ! = NULL ) {
2006-11-13 16:29:16 +00:00
int pool_auto_created = 0 ;
2008-09-02 10:39:39 +00:00
/* if the caller didn't provide a pool, make one */
2006-11-13 16:29:16 +00:00
if ( pool = = NULL ) {
switch_core_new_memory_pool ( & pool ) ;
2006-12-04 05:41:03 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " created a memory pool \n " ) ;
2006-11-13 16:29:16 +00:00
if ( pool ! = NULL ) {
pool_auto_created = 1 ;
}
}
2008-09-02 10:39:39 +00:00
/* if we have a pool, make a parser object */
2006-11-13 16:29:16 +00:00
if ( pool ! = NULL ) {
2007-03-30 00:13:31 +00:00
* parser = ( switch_ivr_digit_stream_parser_t * ) switch_core_alloc ( pool , sizeof ( switch_ivr_digit_stream_parser_t ) ) ;
2006-11-13 16:29:16 +00:00
}
2008-09-02 10:39:39 +00:00
/* if we have parser object, initialize it for the caller */
2008-01-28 08:47:55 +00:00
if ( pool & & * parser ! = NULL ) {
2007-03-29 22:31:56 +00:00
memset ( * parser , 0 , sizeof ( switch_ivr_digit_stream_parser_t ) ) ;
2006-11-13 16:29:16 +00:00
( * parser ) - > pool_auto_created = pool_auto_created ;
( * parser ) - > pool = pool ;
2006-12-04 05:41:03 +00:00
( * parser ) - > digit_timeout_ms = 1000 ;
2007-03-29 22:31:56 +00:00
switch_core_hash_init ( & ( * parser ) - > hash , ( * parser ) - > pool ) ;
2006-11-13 16:29:16 +00:00
status = SWITCH_STATUS_SUCCESS ;
} else {
status = SWITCH_STATUS_MEMERR ;
2008-09-02 10:39:39 +00:00
/* if we can't create a parser object,clean up the pool if we created it */
2006-11-13 16:29:16 +00:00
if ( pool ! = NULL & & pool_auto_created ) {
switch_core_destroy_memory_pool ( & pool ) ;
}
}
}
2007-03-29 22:31:56 +00:00
return status ;
2006-11-12 00:32:18 +00:00
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_parser_destroy ( switch_ivr_digit_stream_parser_t * parser )
2006-11-12 00:32:18 +00:00
{
2007-03-29 22:31:56 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
if ( parser ! = NULL ) {
if ( parser - > hash ! = NULL ) {
2007-09-29 01:06:08 +00:00
switch_core_hash_destroy ( & parser - > hash ) ;
2007-03-29 22:31:56 +00:00
parser - > hash = NULL ;
}
2008-09-02 10:39:39 +00:00
/* free the memory pool if we created it */
2007-03-29 22:31:56 +00:00
if ( parser - > pool_auto_created & & parser - > pool ! = NULL ) {
status = switch_core_destroy_memory_pool ( & parser - > pool ) ;
2006-11-12 20:34:04 +00:00
}
2006-11-12 00:32:18 +00:00
}
2007-03-29 22:31:56 +00:00
return status ;
2006-11-12 00:32:18 +00:00
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_new ( switch_ivr_digit_stream_parser_t * parser , switch_ivr_digit_stream_t * * stream )
2006-11-12 00:32:18 +00:00
{
2007-03-29 22:31:56 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2008-10-06 23:05:55 +00:00
/* if we have a parser object memory pool and a stream object pointer that is null */
2009-02-24 18:36:45 +00:00
if ( parser & & stream & & * stream = = NULL ) {
* stream = ( switch_ivr_digit_stream_t * ) malloc ( sizeof ( * * stream ) ) ;
switch_assert ( * stream ) ;
memset ( * stream , 0 , sizeof ( * * stream ) ) ;
switch_zmalloc ( ( * stream ) - > digits , parser - > buflen + 1 ) ;
status = SWITCH_STATUS_SUCCESS ;
2006-11-12 00:32:18 +00:00
}
2007-03-29 22:31:56 +00:00
return status ;
2006-11-12 00:32:18 +00:00
}
2009-02-24 18:36:45 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_destroy ( switch_ivr_digit_stream_t * * stream )
2006-11-12 00:32:18 +00:00
{
2006-12-04 05:41:03 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2006-11-12 00:32:18 +00:00
2009-02-24 18:36:45 +00:00
if ( * stream ) {
switch_safe_free ( ( * stream ) - > digits ) ;
free ( * stream ) ;
* stream = NULL ;
2007-03-29 22:31:56 +00:00
status = SWITCH_STATUS_SUCCESS ;
2006-11-12 00:32:18 +00:00
}
2006-12-04 05:41:03 +00:00
return status ;
2006-11-12 00:32:18 +00:00
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_parser_set_event ( switch_ivr_digit_stream_parser_t * parser , char * digits , void * data )
2006-11-12 20:34:04 +00:00
{
2006-12-04 05:41:03 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2007-02-13 17:15:42 +00:00
2007-03-29 22:31:56 +00:00
if ( parser ! = NULL & & digits ! = NULL & & * digits & & parser - > hash ! = NULL ) {
2006-11-12 20:34:04 +00:00
2007-09-29 01:06:08 +00:00
status = switch_core_hash_insert ( parser - > hash , digits , data ) ;
2007-03-29 22:31:56 +00:00
if ( status = = SWITCH_STATUS_SUCCESS ) {
switch_size_t len = strlen ( digits ) ;
2006-11-12 20:34:04 +00:00
2008-09-02 10:39:39 +00:00
/* if we don't have a terminator, then we have to try and
* figure out when a digit set is completed , therefore we
* keep track of the min and max digit lengths
*/
2009-02-24 18:36:45 +00:00
if ( len > parser - > buflen ) {
parser - > buflen = len ;
}
2007-03-29 22:31:56 +00:00
if ( parser - > terminator = = ' \0 ' ) {
if ( len > parser - > maxlen ) {
parser - > maxlen = len ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " max len %u \n " , ( uint32_t ) parser - > maxlen ) ;
2007-02-15 21:59:59 +00:00
}
2007-03-29 22:31:56 +00:00
if ( parser - > minlen = = 0 | | len < parser - > minlen ) {
parser - > minlen = len ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " min len %u \n " , ( uint32_t ) parser - > minlen ) ;
2007-02-15 21:59:59 +00:00
}
2007-03-29 22:31:56 +00:00
} else {
2008-09-02 10:39:39 +00:00
/* since we have a terminator, reset min and max */
2007-03-29 22:31:56 +00:00
parser - > minlen = 0 ;
parser - > maxlen = 0 ;
2007-02-13 17:15:42 +00:00
}
2006-11-12 20:34:04 +00:00
}
}
2007-03-29 22:31:56 +00:00
if ( status ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " unable to add hash for '%s' \n " , digits ) ;
}
2006-11-12 20:34:04 +00:00
return status ;
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_parser_del_event ( switch_ivr_digit_stream_parser_t * parser , char * digits )
2006-11-12 00:32:18 +00:00
{
2007-03-29 22:31:56 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2006-11-12 00:32:18 +00:00
2007-03-29 22:31:56 +00:00
if ( parser ! = NULL & & digits ! = NULL & & * digits ) {
status = switch_core_hash_delete ( parser - > hash , digits ) ;
2006-12-04 05:41:03 +00:00
}
2007-03-29 22:31:56 +00:00
if ( status ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " unable to del hash for '%s' \n " , digits ) ;
2006-11-12 00:32:18 +00:00
}
2007-03-29 22:31:56 +00:00
return status ;
}
2006-11-12 00:32:18 +00:00
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( void * ) switch_ivr_digit_stream_parser_feed ( switch_ivr_digit_stream_parser_t * parser , switch_ivr_digit_stream_t * stream , char digit )
2007-03-29 22:31:56 +00:00
{
void * result = NULL ;
2009-02-24 19:58:45 +00:00
switch_size_t len ;
2006-11-12 00:32:18 +00:00
2009-02-24 18:36:45 +00:00
switch_assert ( parser ) ;
switch_assert ( stream ) ;
switch_assert ( stream - > digits ) ;
2006-12-23 16:40:37 +00:00
2009-02-24 19:58:45 +00:00
len = strlen ( stream - > digits ) ;
2009-02-24 18:36:45 +00:00
/* handle new digit arrivals */
if ( digit ) {
/* if it's not a terminator digit, add it to the collected digits */
if ( digit ! = parser - > terminator ) {
/* if collected digits length >= the max length of the keys
* in the hash table , then left shift the digit string
*/
if ( len > 0 & & parser - > maxlen ! = 0 & & len > = parser - > maxlen ) {
char * src = stream - > digits + 1 ;
char * dst = stream - > digits ;
2006-11-12 00:32:18 +00:00
2009-02-24 18:36:45 +00:00
while ( * src ) {
* ( dst + + ) = * ( src + + ) ;
2006-11-12 00:32:18 +00:00
}
2009-02-24 18:36:45 +00:00
* dst = digit ;
} else {
* ( stream - > digits + ( len + + ) ) = digit ;
* ( stream - > digits + len ) = ' \0 ' ;
stream - > last_digit_time = switch_micro_time_now ( ) / 1000 ;
2006-11-12 00:32:18 +00:00
}
}
2009-02-24 18:36:45 +00:00
}
/* don't allow collected digit string testing if there are varying sized keys until timeout */
if ( parser - > maxlen - parser - > minlen > 0 & & ( switch_micro_time_now ( ) / 1000 ) - stream - > last_digit_time < parser - > digit_timeout_ms ) {
len = 0 ;
}
/* if we have digits to test */
if ( len ) {
result = switch_core_hash_find ( parser - > hash , stream - > digits ) ;
/* if we matched the digit string, or this digit is the terminator
* reset the collected digits for next digit string
*/
if ( result ! = NULL | | parser - > terminator = = digit ) {
* stream - > digits = ' \0 ' ;
2006-11-12 00:32:18 +00:00
}
2006-12-04 05:41:03 +00:00
}
2009-02-24 18:36:45 +00:00
2006-12-04 05:41:03 +00:00
2007-03-29 22:31:56 +00:00
return result ;
2006-11-12 00:32:18 +00:00
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_reset ( switch_ivr_digit_stream_t * stream )
2006-12-04 05:41:03 +00:00
{
2007-03-29 22:31:56 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-02-24 18:36:45 +00:00
switch_assert ( stream ) ;
switch_assert ( stream - > digits ) ;
2006-12-04 05:41:03 +00:00
2009-02-24 18:36:45 +00:00
* stream - > digits = ' \0 ' ;
stream - > last_digit_time = 0 ;
status = SWITCH_STATUS_SUCCESS ;
2006-12-04 05:41:03 +00:00
2007-03-29 22:31:56 +00:00
return status ;
2006-12-04 05:41:03 +00:00
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_digit_stream_parser_set_terminator ( switch_ivr_digit_stream_parser_t * parser , char digit )
2006-12-04 05:41:03 +00:00
{
switch_status_t status = SWITCH_STATUS_FALSE ;
2007-03-29 22:31:56 +00:00
if ( parser ! = NULL ) {
parser - > terminator = digit ;
2008-09-02 10:39:39 +00:00
/* since we have a terminator, reset min and max */
2007-03-29 22:31:56 +00:00
parser - > minlen = 0 ;
parser - > maxlen = 0 ;
status = SWITCH_STATUS_SUCCESS ;
2006-12-04 05:41:03 +00:00
}
return status ;
}
2007-10-02 19:58:06 +00:00
SWITCH_DECLARE ( int ) switch_ivr_set_xml_profile_data ( switch_xml_t xml , switch_caller_profile_t * caller_profile , int off )
2006-11-13 16:29:16 +00:00
{
2007-03-29 22:31:56 +00:00
switch_xml_t param ;
2006-12-04 05:41:03 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " username " , off + + ) ) ) {
return - 1 ;
2006-12-04 05:41:03 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > username ) ;
2006-12-04 05:41:03 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " dialplan " , off + + ) ) ) {
return - 1 ;
2006-12-04 05:41:03 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > dialplan ) ;
2006-12-04 05:41:03 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " caller_id_name " , off + + ) ) ) {
return - 1 ;
2006-12-04 05:41:03 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > caller_id_name ) ;
2006-12-04 05:41:03 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " ani " , off + + ) ) ) {
return - 1 ;
2006-11-13 16:29:16 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > ani ) ;
2006-11-13 16:29:16 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " aniii " , off + + ) ) ) {
return - 1 ;
2006-11-13 16:29:16 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > aniii ) ;
2006-11-13 16:29:16 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " caller_id_number " , off + + ) ) ) {
return - 1 ;
2007-02-09 22:55:48 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > caller_id_number ) ;
2007-02-09 22:55:48 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " network_addr " , off + + ) ) ) {
return - 1 ;
2007-02-09 22:55:48 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > network_addr ) ;
2007-02-09 22:55:48 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " rdnis " , off + + ) ) ) {
return - 1 ;
2006-12-20 21:25:14 +00:00
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > rdnis ) ;
2006-12-20 21:25:14 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " destination_number " , off + + ) ) ) {
return - 1 ;
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > destination_number ) ;
2007-02-14 15:19:01 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " uuid " , off + + ) ) ) {
2007-02-14 15:19:01 +00:00
return - 1 ;
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > uuid ) ;
2007-02-14 15:19:01 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " source " , off + + ) ) ) {
2007-02-14 15:19:01 +00:00
return - 1 ;
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > source ) ;
2007-02-14 15:19:01 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " context " , off + + ) ) ) {
2007-02-14 15:19:01 +00:00
return - 1 ;
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > context ) ;
2007-02-14 15:19:01 +00:00
2007-03-29 22:31:56 +00:00
if ( ! ( param = switch_xml_add_child_d ( xml , " chan_name " , off + + ) ) ) {
return - 1 ;
}
2009-03-20 20:41:30 +00:00
switch_xml_set_txt_d ( param , caller_profile - > chan_name ) ;
2007-02-14 15:19:01 +00:00
2007-10-02 16:38:15 +00:00
return off ;
2007-02-14 15:19:01 +00:00
}
2007-10-02 19:58:06 +00:00
SWITCH_DECLARE ( int ) switch_ivr_set_xml_chan_vars ( switch_xml_t xml , switch_channel_t * channel , int off )
{
switch_xml_t variable ;
2007-12-11 04:21:54 +00:00
switch_event_header_t * hi = switch_channel_variable_first ( channel ) ;
2007-10-02 19:58:06 +00:00
2008-05-27 04:30:03 +00:00
if ( ! hi )
return off ;
2007-12-11 04:21:54 +00:00
for ( ; hi ; hi = hi - > next ) {
2009-10-23 16:03:42 +00:00
if ( ! zstr ( hi - > name ) & & ! zstr ( hi - > value ) & & ( ( variable = switch_xml_add_child_d ( xml , hi - > name , off + + ) ) ) ) {
2007-12-11 04:21:54 +00:00
char * data ;
switch_size_t dlen = strlen ( hi - > value ) * 3 ;
2008-05-27 04:30:03 +00:00
2007-12-11 04:21:54 +00:00
if ( ( data = malloc ( dlen ) ) ) {
memset ( data , 0 , dlen ) ;
switch_url_encode ( hi - > value , data , dlen ) ;
switch_xml_set_txt_d ( variable , data ) ;
free ( data ) ;
2007-10-02 19:58:06 +00:00
}
}
}
2007-12-11 04:21:54 +00:00
switch_channel_variable_last ( channel ) ;
2007-10-02 19:58:06 +00:00
return off ;
}
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_generate_xml_cdr ( switch_core_session_t * session , switch_xml_t * xml_cdr )
2007-02-14 15:19:01 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-02-14 15:19:01 +00:00
switch_caller_profile_t * caller_profile ;
2008-05-27 04:30:03 +00:00
switch_xml_t variables , cdr , x_main_cp , x_caller_profile , x_caller_extension , x_times , time_tag ,
2007-10-02 16:38:15 +00:00
x_application , x_callflow , x_inner_extension , x_apps , x_o ;
2007-04-21 01:03:58 +00:00
switch_app_log_t * app_log ;
2007-02-14 15:19:01 +00:00
char tmp [ 512 ] ;
int cdr_off = 0 , v_off = 0 ;
if ( ! ( cdr = switch_xml_new ( " cdr " ) ) ) {
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-02-14 15:19:01 +00:00
if ( ! ( variables = switch_xml_add_child_d ( cdr , " variables " , cdr_off + + ) ) ) {
goto error ;
}
2007-03-29 22:31:56 +00:00
2007-04-21 01:03:58 +00:00
if ( ( app_log = switch_core_session_get_app_log ( session ) ) ) {
int app_off = 0 ;
switch_app_log_t * ap ;
2008-05-27 04:30:03 +00:00
2007-04-21 01:03:58 +00:00
if ( ! ( x_apps = switch_xml_add_child_d ( cdr , " app_log " , cdr_off + + ) ) ) {
goto error ;
}
2008-05-27 04:30:03 +00:00
for ( ap = app_log ; ap ; ap = ap - > next ) {
2007-04-21 01:03:58 +00:00
if ( ! ( x_application = switch_xml_add_child_d ( x_apps , " application " , app_off + + ) ) ) {
goto error ;
}
2008-05-27 04:30:03 +00:00
2007-04-21 01:03:58 +00:00
switch_xml_set_attr_d ( x_application , " app_name " , ap - > app ) ;
switch_xml_set_attr_d ( x_application , " app_data " , ap - > arg ) ;
}
}
2007-10-02 19:58:06 +00:00
switch_ivr_set_xml_chan_vars ( variables , channel , v_off ) ;
2008-05-27 04:30:03 +00:00
2007-02-14 15:19:01 +00:00
caller_profile = switch_channel_get_caller_profile ( channel ) ;
2007-03-29 22:31:56 +00:00
2007-02-14 15:19:01 +00:00
while ( caller_profile ) {
int cf_off = 0 ;
2007-10-02 16:38:15 +00:00
int cp_off = 0 ;
2007-03-29 22:31:56 +00:00
2007-02-14 15:19:01 +00:00
if ( ! ( x_callflow = switch_xml_add_child_d ( cdr , " callflow " , cdr_off + + ) ) ) {
goto error ;
}
2008-02-26 23:29:58 +00:00
2009-10-23 16:03:42 +00:00
if ( ! zstr ( caller_profile - > dialplan ) ) {
2008-02-26 23:29:58 +00:00
switch_xml_set_attr_d ( x_callflow , " dialplan " , caller_profile - > dialplan ) ;
}
2009-10-23 16:03:42 +00:00
if ( ! zstr ( caller_profile - > profile_index ) ) {
2008-02-26 23:29:58 +00:00
switch_xml_set_attr_d ( x_callflow , " profile_index " , caller_profile - > profile_index ) ;
}
2007-03-29 22:31:56 +00:00
2007-02-14 15:19:01 +00:00
if ( caller_profile - > caller_extension ) {
switch_caller_application_t * ap ;
2007-02-15 19:58:25 +00:00
int app_off = 0 ;
2007-02-14 15:19:01 +00:00
if ( ! ( x_caller_extension = switch_xml_add_child_d ( x_callflow , " extension " , cf_off + + ) ) ) {
goto error ;
}
2008-05-27 04:30:03 +00:00
2007-02-14 15:19:01 +00:00
switch_xml_set_attr_d ( x_caller_extension , " name " , caller_profile - > caller_extension - > extension_name ) ;
switch_xml_set_attr_d ( x_caller_extension , " number " , caller_profile - > caller_extension - > extension_number ) ;
if ( caller_profile - > caller_extension - > current_application ) {
2007-03-30 00:13:31 +00:00
switch_xml_set_attr_d ( x_caller_extension , " current_app " , caller_profile - > caller_extension - > current_application - > application_name ) ;
2007-02-14 15:19:01 +00:00
}
2007-03-29 22:31:56 +00:00
for ( ap = caller_profile - > caller_extension - > applications ; ap ; ap = ap - > next ) {
2007-02-15 19:58:25 +00:00
if ( ! ( x_application = switch_xml_add_child_d ( x_caller_extension , " application " , app_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-02-15 20:02:52 +00:00
if ( ap = = caller_profile - > caller_extension - > current_application ) {
switch_xml_set_attr_d ( x_application , " last_executed " , " true " ) ;
}
2007-02-14 15:19:01 +00:00
switch_xml_set_attr_d ( x_application , " app_name " , ap - > application_name ) ;
switch_xml_set_attr_d ( x_application , " app_data " , ap - > application_data ) ;
}
2007-04-21 01:03:58 +00:00
if ( caller_profile - > caller_extension - > children ) {
switch_caller_profile_t * cp = NULL ;
int i_off = 0 ;
for ( cp = caller_profile - > caller_extension - > children ; cp ; cp = cp - > next ) {
2007-12-17 23:19:10 +00:00
app_off = 0 ;
2008-05-27 04:30:03 +00:00
2007-04-21 01:03:58 +00:00
if ( ! cp - > caller_extension ) {
continue ;
}
if ( ! ( x_inner_extension = switch_xml_add_child_d ( x_caller_extension , " sub_extensions " , i_off + + ) ) ) {
goto error ;
2008-05-27 04:30:03 +00:00
}
2007-04-21 01:03:58 +00:00
if ( ! ( x_caller_extension = switch_xml_add_child_d ( x_inner_extension , " extension " , cf_off + + ) ) ) {
goto error ;
}
switch_xml_set_attr_d ( x_caller_extension , " name " , cp - > caller_extension - > extension_name ) ;
switch_xml_set_attr_d ( x_caller_extension , " number " , cp - > caller_extension - > extension_number ) ;
switch_xml_set_attr_d ( x_caller_extension , " dialplan " , cp - > dialplan ) ;
if ( cp - > caller_extension - > current_application ) {
switch_xml_set_attr_d ( x_caller_extension , " current_app " , cp - > caller_extension - > current_application - > application_name ) ;
}
2008-05-27 04:30:03 +00:00
2007-04-21 01:03:58 +00:00
for ( ap = cp - > caller_extension - > applications ; ap ; ap = ap - > next ) {
if ( ! ( x_application = switch_xml_add_child_d ( x_caller_extension , " application " , app_off + + ) ) ) {
goto error ;
}
if ( ap = = cp - > caller_extension - > current_application ) {
switch_xml_set_attr_d ( x_application , " last_executed " , " true " ) ;
}
switch_xml_set_attr_d ( x_application , " app_name " , ap - > application_name ) ;
switch_xml_set_attr_d ( x_application , " app_data " , ap - > application_data ) ;
}
}
}
2007-02-14 15:19:01 +00:00
}
2007-03-29 22:31:56 +00:00
2007-10-02 16:38:15 +00:00
if ( ! ( x_main_cp = switch_xml_add_child_d ( x_callflow , " caller_profile " , cf_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-10-02 16:38:15 +00:00
2007-10-02 19:58:06 +00:00
cp_off + = switch_ivr_set_xml_profile_data ( x_main_cp , caller_profile , 0 ) ;
2007-02-14 15:19:01 +00:00
if ( caller_profile - > originator_caller_profile ) {
2007-10-02 16:38:15 +00:00
switch_caller_profile_t * cp = NULL ;
int off = 0 ;
if ( ! ( x_o = switch_xml_add_child_d ( x_main_cp , " originator " , cp_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-10-02 16:38:15 +00:00
for ( cp = caller_profile - > originator_caller_profile ; cp ; cp = cp - > next ) {
if ( ! ( x_caller_profile = switch_xml_add_child_d ( x_o , " originator_caller_profile " , off + + ) ) ) {
goto error ;
}
2007-10-02 19:58:06 +00:00
switch_ivr_set_xml_profile_data ( x_caller_profile , cp , 0 ) ;
2007-10-02 16:38:15 +00:00
}
2007-02-14 15:19:01 +00:00
}
if ( caller_profile - > originatee_caller_profile ) {
2007-10-02 16:38:15 +00:00
switch_caller_profile_t * cp = NULL ;
int off = 0 ;
if ( ! ( x_o = switch_xml_add_child_d ( x_main_cp , " originatee " , cp_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-10-02 16:38:15 +00:00
for ( cp = caller_profile - > originatee_caller_profile ; cp ; cp = cp - > next ) {
if ( ! ( x_caller_profile = switch_xml_add_child_d ( x_o , " originatee_caller_profile " , off + + ) ) ) {
goto error ;
}
2008-10-30 15:18:07 +00:00
switch_ivr_set_xml_profile_data ( x_caller_profile , cp , 0 ) ;
2007-10-02 16:38:15 +00:00
}
2007-02-14 15:19:01 +00:00
}
if ( caller_profile - > times ) {
2007-02-15 19:20:14 +00:00
int t_off = 0 ;
if ( ! ( x_times = switch_xml_add_child_d ( x_callflow , " times " , cf_off + + ) ) ) {
goto error ;
}
if ( ! ( time_tag = switch_xml_add_child_d ( x_times , " created_time " , t_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > created ) ;
2007-02-15 19:20:14 +00:00
switch_xml_set_txt_d ( time_tag , tmp ) ;
2007-02-14 15:19:01 +00:00
2007-12-20 17:27:11 +00:00
if ( ! ( time_tag = switch_xml_add_child_d ( x_times , " profile_created_time " , t_off + + ) ) ) {
goto error ;
}
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > profile_created ) ;
switch_xml_set_txt_d ( time_tag , tmp ) ;
2008-05-24 01:43:12 +00:00
if ( ! ( time_tag = switch_xml_add_child_d ( x_times , " progress_time " , t_off + + ) ) ) {
goto error ;
}
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > progress ) ;
switch_xml_set_txt_d ( time_tag , tmp ) ;
if ( ! ( time_tag = switch_xml_add_child_d ( x_times , " progress_media_time " , t_off + + ) ) ) {
goto error ;
}
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > progress_media ) ;
switch_xml_set_txt_d ( time_tag , tmp ) ;
2007-02-15 19:20:14 +00:00
if ( ! ( time_tag = switch_xml_add_child_d ( x_times , " answered_time " , t_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > answered ) ;
2007-02-15 19:20:14 +00:00
switch_xml_set_txt_d ( time_tag , tmp ) ;
2007-02-14 15:19:01 +00:00
2007-02-15 19:20:14 +00:00
if ( ! ( time_tag = switch_xml_add_child_d ( x_times , " hangup_time " , t_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > hungup ) ;
2007-02-15 19:20:14 +00:00
switch_xml_set_txt_d ( time_tag , tmp ) ;
2007-02-14 15:19:01 +00:00
2007-02-15 19:20:14 +00:00
if ( ! ( time_tag = switch_xml_add_child_d ( x_times , " transfer_time " , t_off + + ) ) ) {
2007-02-14 15:19:01 +00:00
goto error ;
}
2007-12-12 21:53:32 +00:00
switch_snprintf ( tmp , sizeof ( tmp ) , " % " SWITCH_TIME_T_FMT , caller_profile - > times - > transferred ) ;
2007-02-15 19:20:14 +00:00
switch_xml_set_txt_d ( time_tag , tmp ) ;
2007-02-14 15:19:01 +00:00
}
caller_profile = caller_profile - > next ;
}
* xml_cdr = cdr ;
2007-03-29 22:31:56 +00:00
return SWITCH_STATUS_SUCCESS ;
error :
2007-02-14 15:19:01 +00:00
if ( cdr ) {
switch_xml_free ( cdr ) ;
}
2007-03-29 22:31:56 +00:00
2007-02-14 15:19:01 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-12-13 22:17:20 +00:00
SWITCH_DECLARE ( void ) switch_ivr_park_session ( switch_core_session_t * session )
{
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_channel_set_state ( channel , CS_PARK ) ;
2008-10-27 17:14:55 +00:00
switch_channel_set_flag ( channel , CF_TRANSFER ) ;
2007-12-13 22:17:20 +00:00
}
2007-10-04 15:09:44 +00:00
SWITCH_DECLARE ( void ) switch_ivr_delay_echo ( switch_core_session_t * session , uint32_t delay_ms )
{
stfu_instance_t * jb ;
int qlen = 0 ;
stfu_frame_t * jb_frame ;
switch_frame_t * read_frame , write_frame = { 0 } ;
switch_status_t status ;
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-10-04 15:09:44 +00:00
uint32_t interval , samples ;
uint32_t ts = 0 ;
2009-02-10 19:09:06 +00:00
switch_codec_implementation_t read_impl = { 0 } ;
switch_core_session_get_read_impl ( session , & read_impl ) ;
2007-10-04 15:09:44 +00:00
2007-10-05 00:05:41 +00:00
if ( delay_ms < 1 | | delay_ms > 10000 ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Invalid delay [%d] must be between 1 and 10000 \n " , delay_ms ) ;
2007-10-04 15:09:44 +00:00
return ;
}
2009-02-10 19:09:06 +00:00
interval = read_impl . microseconds_per_packet / 1000 ;
samples = switch_samples_per_packet ( read_impl . samples_per_second , interval ) ;
2007-10-04 15:09:44 +00:00
qlen = delay_ms / ( interval ) ;
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " Setting delay to %dms (%d frames) \n " , delay_ms , qlen ) ;
2007-10-04 15:09:44 +00:00
jb = stfu_n_init ( qlen ) ;
2009-02-10 19:09:06 +00:00
write_frame . codec = switch_core_session_get_read_codec ( session ) ;
2007-10-04 15:09:44 +00:00
2008-05-27 04:30:03 +00:00
while ( switch_channel_ready ( channel ) ) {
2008-05-08 19:19:47 +00:00
status = switch_core_session_read_frame ( session , & read_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2007-10-04 15:09:44 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
}
2010-01-08 00:45:09 +00:00
stfu_n_eat ( jb , ts , read_frame - > payload , read_frame - > data , read_frame - > datalen ) ;
2007-10-04 15:09:44 +00:00
ts + = interval ;
if ( ( jb_frame = stfu_n_read_a_frame ( jb ) ) ) {
write_frame . data = jb_frame - > data ;
2008-05-27 04:30:03 +00:00
write_frame . datalen = ( uint32_t ) jb_frame - > dlen ;
2008-05-08 19:19:47 +00:00
status = switch_core_session_write_frame ( session , & write_frame , SWITCH_IO_FLAG_NONE , 0 ) ;
2007-10-04 15:09:44 +00:00
if ( ! SWITCH_READ_ACCEPTABLE ( status ) ) {
break ;
}
}
}
stfu_n_destroy ( & jb ) ;
}
2007-02-14 15:19:01 +00:00
2008-05-27 04:30:03 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_say ( switch_core_session_t * session , const char * tosay , const char * module_name , const char * say_type ,
const char * say_method , switch_input_args_t * args )
2008-05-09 22:16:08 +00:00
{
switch_say_interface_t * si ;
2009-06-23 13:40:07 +00:00
switch_channel_t * channel ;
2009-07-21 17:56:12 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
const char * save_path = NULL , * chan_lang = NULL , * lang = NULL , * lname = NULL , * sound_path = NULL ;
switch_event_t * hint_data ;
switch_xml_t cfg , xml = NULL , language , macros ;
2009-06-23 13:40:07 +00:00
switch_assert ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
switch_assert ( channel ) ;
lang = switch_channel_get_variable ( channel , " language " ) ;
if ( ! lang ) {
chan_lang = switch_channel_get_variable ( channel , " default_language " ) ;
if ( ! chan_lang ) {
chan_lang = " en " ;
}
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_DEBUG , " No language specified - Using [%s] \n " , chan_lang ) ;
2009-06-23 13:40:07 +00:00
} else {
chan_lang = lang ;
}
2009-07-21 17:56:12 +00:00
switch_event_create ( & hint_data , SWITCH_EVENT_REQUEST_PARAMS ) ;
switch_assert ( hint_data ) ;
switch_event_add_header_string ( hint_data , SWITCH_STACK_BOTTOM , " macro_name " , " say_app " ) ;
switch_event_add_header_string ( hint_data , SWITCH_STACK_BOTTOM , " lang " , chan_lang ) ;
switch_channel_event_set_data ( channel , hint_data ) ;
if ( switch_xml_locate ( " phrases " , NULL , NULL , NULL , & xml , & cfg , hint_data , SWITCH_TRUE ) ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Open of phrases failed. \n " ) ;
2009-07-21 17:56:12 +00:00
goto done ;
}
if ( ! ( macros = switch_xml_child ( cfg , " macros " ) ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Can't find macros tag. \n " ) ;
2009-07-21 17:56:12 +00:00
goto done ;
}
if ( ! ( language = switch_xml_child ( macros , " language " ) ) ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Can't find language tag. \n " ) ;
2009-07-21 17:56:12 +00:00
goto done ;
}
while ( language ) {
if ( ( lname = ( char * ) switch_xml_attr ( language , " name " ) ) & & ! strcasecmp ( lname , chan_lang ) ) {
const char * tmp ;
if ( ( tmp = switch_xml_attr ( language , " module " ) ) ) {
module_name = tmp ;
}
break ;
}
language = language - > next ;
}
if ( ! language ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Can't find language %s. \n " , chan_lang ) ;
2009-07-21 17:56:12 +00:00
goto done ;
}
if ( ! ( sound_path = ( char * ) switch_xml_attr ( language , " sound-path " ) ) ) {
sound_path = ( char * ) switch_xml_attr ( language , " sound_path " ) ;
}
2009-06-23 13:40:07 +00:00
save_path = switch_channel_get_variable ( channel , " sound_prefix " ) ;
2009-07-21 17:56:12 +00:00
if ( sound_path ) {
switch_channel_set_variable ( channel , " sound_prefix " , sound_path ) ;
}
2008-05-09 22:16:08 +00:00
if ( ( si = switch_loadable_module_get_say_interface ( module_name ) ) ) {
2008-09-02 10:39:39 +00:00
/* should go back and proto all the say mods to const.... */
2008-05-27 04:30:03 +00:00
status = si - > say_function ( session , ( char * ) tosay , switch_ivr_get_say_type_by_name ( say_type ) , switch_ivr_get_say_method_by_name ( say_method ) , args ) ;
2008-05-09 22:16:08 +00:00
} else {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " Invalid SAY Interface [%s]! \n " , module_name ) ;
2008-05-09 22:16:08 +00:00
status = SWITCH_STATUS_FALSE ;
}
2009-07-21 17:56:12 +00:00
done :
if ( hint_data ) {
switch_event_destroy ( & hint_data ) ;
}
if ( save_path ) {
switch_channel_set_variable ( channel , " sound_prefix " , save_path ) ;
}
if ( xml ) {
switch_xml_free ( xml ) ;
}
2009-06-23 13:40:07 +00:00
2008-05-09 22:16:08 +00:00
return status ;
}
2007-02-14 15:19:01 +00:00
2009-09-08 19:05:32 +00:00
static const char * get_prefixed_str ( char * buffer , size_t buffer_size , const char * prefix , size_t prefix_size , const char * str )
{
size_t str_len ;
2009-09-09 15:07:51 +00:00
if ( ! buffer ) {
2009-09-08 19:05:32 +00:00
/*
if buffer is null then it just returns the str without the prefix appended , otherwise buffer contains the prefix followed by the original string
*/
return str ;
}
str_len = strlen ( str ) ;
memcpy ( buffer , prefix , prefix_size ) ;
if ( str_len + prefix_size + 1 > buffer_size ) {
memcpy ( buffer + prefix_size , str , buffer_size - prefix_size - 1 ) ;
buffer [ buffer_size - prefix_size - 1 ] = ' \0 ' ;
} else {
memcpy ( buffer + prefix_size , str , str_len + 1 ) ;
}
return buffer ;
}
2008-05-24 17:28:04 +00:00
2008-07-16 17:44:54 +00:00
SWITCH_DECLARE ( switch_status_t ) switch_ivr_set_user ( switch_core_session_t * session , const char * data )
{
2008-12-23 17:36:50 +00:00
switch_xml_t x_domain , xml = NULL , x_user , x_param , x_params , x_group = NULL ;
2009-05-18 17:11:47 +00:00
char * user , * number_alias , * domain ;
2008-07-16 17:44:54 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-09-08 19:05:32 +00:00
char * prefix_buffer = NULL , * prefix ;
size_t buffer_size = 0 ;
size_t prefix_size = 0 ;
2009-10-23 16:03:42 +00:00
if ( zstr ( data ) ) {
2008-07-16 17:44:54 +00:00
goto error ;
}
user = switch_core_session_strdup ( session , data ) ;
2009-09-08 19:05:32 +00:00
if ( ( prefix = strchr ( user , ' ' ) ) ) {
* prefix + + = 0 ;
}
2008-07-16 17:44:54 +00:00
if ( ! ( domain = strchr ( user , ' @ ' ) ) ) {
goto error ;
}
* domain + + = ' \0 ' ;
2008-12-23 17:36:50 +00:00
if ( switch_xml_locate_user ( " id " , user , domain , NULL , & xml , & x_domain , & x_user , & x_group , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_WARNING , " can't find user [%s@%s] \n " , user , domain ) ;
2008-07-16 17:44:54 +00:00
goto done ;
}
status = SWITCH_STATUS_SUCCESS ;
2009-10-23 16:03:42 +00:00
if ( ! zstr ( prefix ) ) {
2009-09-08 19:05:32 +00:00
prefix_size = strlen ( prefix ) ;
buffer_size = 1024 + prefix_size + 1 ;
prefix_buffer = switch_core_session_alloc ( session , buffer_size ) ;
}
2009-05-18 17:11:47 +00:00
if ( ( number_alias = ( char * ) switch_xml_attr ( x_user , " number-alias " ) ) ) {
2009-09-08 19:05:32 +00:00
switch_channel_set_variable ( channel , get_prefixed_str ( prefix_buffer , buffer_size , prefix , prefix_size , " number_alias " ) , number_alias ) ;
2008-07-16 17:44:54 +00:00
}
2008-09-02 16:38:45 +00:00
if ( ( x_params = switch_xml_child ( x_domain , " variables " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " variable " ) ; x_param ; x_param = x_param - > next ) {
2008-12-23 17:36:50 +00:00
const char * var = switch_xml_attr ( x_param , " name " ) ;
const char * val = switch_xml_attr ( x_param , " value " ) ;
if ( var & & val ) {
2009-09-08 19:05:32 +00:00
switch_channel_set_variable ( channel , get_prefixed_str ( prefix_buffer , buffer_size , prefix , prefix_size , var ) , val ) ;
2008-12-23 17:36:50 +00:00
}
}
}
if ( x_group & & ( x_params = switch_xml_child ( x_group , " variables " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " variable " ) ; x_param ; x_param = x_param - > next ) {
2008-09-02 16:38:45 +00:00
const char * var = switch_xml_attr ( x_param , " name " ) ;
const char * val = switch_xml_attr ( x_param , " value " ) ;
if ( var & & val ) {
2009-09-08 19:05:32 +00:00
switch_channel_set_variable ( channel , get_prefixed_str ( prefix_buffer , buffer_size , prefix , prefix_size , var ) , val ) ;
2008-09-02 16:38:45 +00:00
}
}
}
2008-07-16 17:44:54 +00:00
if ( ( x_params = switch_xml_child ( x_user , " variables " ) ) ) {
for ( x_param = switch_xml_child ( x_params , " variable " ) ; x_param ; x_param = x_param - > next ) {
const char * var = switch_xml_attr ( x_param , " name " ) ;
const char * val = switch_xml_attr ( x_param , " value " ) ;
if ( var & & val ) {
2009-09-08 19:05:32 +00:00
switch_channel_set_variable ( channel , get_prefixed_str ( prefix_buffer , buffer_size , prefix , prefix_size , var ) , val ) ;
2008-07-16 17:44:54 +00:00
}
}
}
2009-09-08 19:05:32 +00:00
switch_channel_set_variable ( channel , get_prefixed_str ( prefix_buffer , buffer_size , prefix , prefix_size , " user_name " ) , user ) ;
switch_channel_set_variable ( channel , get_prefixed_str ( prefix_buffer , buffer_size , prefix , prefix_size , " domain_name " ) , domain ) ;
2008-07-16 17:44:54 +00:00
goto done ;
error :
2009-08-13 20:35:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_SESSION_LOG ( session ) , SWITCH_LOG_ERROR , " No user@domain specified. \n " ) ;
2008-07-16 17:44:54 +00:00
done :
if ( xml ) {
switch_xml_free ( xml ) ;
}
return status ;
}
2009-10-08 18:09:06 +00:00
SWITCH_DECLARE ( switch_bool_t ) switch_ivr_uuid_exists ( const char * uuid )
{
switch_bool_t exists = SWITCH_FALSE ;
switch_core_session_t * psession = NULL ;
if ( ( psession = switch_core_session_locate ( uuid ) ) ) {
switch_core_session_rwunlock ( psession ) ;
exists = 1 ;
}
return exists ;
}
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +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 :
2006-11-27 22:30:48 +00:00
*/