2007-05-26 04:45:31 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2011-01-05 16:08:55 +00:00
* Copyright ( C ) 2005 - 2011 , Anthony Minessale II < anthm @ freeswitch . org >
2007-05-26 04:45:31 +00:00
*
* Version : MPL 1.1
*
2010-04-21 15:20:05 +00:00
* The contents of this file are subject to the Mozilla Public License Version
2007-05-26 04:45:31 +00:00
* 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
2010-04-21 15:20:05 +00:00
* http : //www.mozilla.org/MPL/
2007-05-26 04:45:31 +00:00
*
* 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
2011-01-05 16:08:55 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-05-26 04:45:31 +00:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
2011-01-05 16:08:55 +00:00
* Anthony Minessale II < anthm @ freeswitch . org >
2009-08-19 21:47:56 +00:00
* Moises Silva < moy @ sangoma . com >
2010-04-27 18:32:36 +00:00
* David Yat Sin < dyatsin @ sangoma . com >
2012-02-16 21:49:51 +00:00
* James Zhang < jzhang @ sangoma . com >
2007-05-26 04:45:31 +00:00
*
*
2010-01-15 19:56:54 +00:00
* mod_freetdm . c - - FreeTDM Endpoint Module
2007-05-26 04:45:31 +00:00
*
*/
# include <switch.h>
2010-01-15 19:22:49 +00:00
# include "freetdm.h"
2007-05-26 04:45:31 +00:00
2008-02-18 15:43:54 +00:00
# ifndef __FUNCTION__
# define __FUNCTION__ __SWITCH_FUNC__
# endif
2010-07-28 15:35:39 +00:00
# define FREETDM_LIMIT_REALM "__freetdm"
2010-01-15 19:56:54 +00:00
# define FREETDM_VAR_PREFIX "freetdm_"
2010-09-01 18:42:34 +00:00
# define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1)
2008-10-06 19:13:32 +00:00
2011-06-07 21:35:49 +00:00
/* How many consecutive IO errors before giving up */
# define FTDM_MAX_READ_WRITE_ERRORS 10
2010-01-15 19:22:49 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_freetdm_load ) ;
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_freetdm_shutdown ) ;
SWITCH_MODULE_DEFINITION ( mod_freetdm , mod_freetdm_load , mod_freetdm_shutdown , NULL ) ;
2007-07-03 20:38:43 +00:00
2010-01-15 19:22:49 +00:00
switch_endpoint_interface_t * freetdm_endpoint_interface ;
2007-05-26 04:45:31 +00:00
static switch_memory_pool_t * module_pool = NULL ;
2008-01-25 16:42:06 +00:00
typedef enum {
ANALOG_OPTION_NONE = 0 ,
ANALOG_OPTION_3WAY = ( 1 < < 0 ) ,
ANALOG_OPTION_CALL_SWAP = ( 1 < < 1 )
} analog_option_t ;
2010-07-28 15:35:39 +00:00
typedef enum {
FTDM_LIMIT_RESET_ON_TIMEOUT = 0 ,
FTDM_LIMIT_RESET_ON_ANSWER = 1
} limit_reset_event_t ;
2007-05-26 04:45:31 +00:00
typedef enum {
TFLAG_IO = ( 1 < < 0 ) ,
2007-05-31 03:04:26 +00:00
TFLAG_DTMF = ( 1 < < 1 ) ,
TFLAG_CODEC = ( 1 < < 2 ) ,
TFLAG_BREAK = ( 1 < < 3 ) ,
2008-10-17 23:00:47 +00:00
TFLAG_HOLD = ( 1 < < 4 ) ,
2011-05-26 15:38:24 +00:00
TFLAG_DEAD = ( 1 < < 5 ) ,
TFLAG_TRANSFER = ( 1 < < 6 ) ,
2007-05-26 04:45:31 +00:00
} TFLAGS ;
static struct {
int debug ;
char * dialplan ;
char * codec_string ;
char * codec_order [ SWITCH_MAX_CODECS ] ;
int codec_order_last ;
char * codec_rates_string ;
char * codec_rates [ SWITCH_MAX_CODECS ] ;
int codec_rates_last ;
unsigned int flags ;
int fd ;
int calls ;
2008-01-10 00:47:04 +00:00
char hold_music [ 256 ] ;
2007-05-26 04:45:31 +00:00
switch_mutex_t * mutex ;
2008-01-25 16:42:06 +00:00
analog_option_t analog_options ;
2010-04-14 15:00:17 +00:00
switch_hash_t * ss7_configs ;
2010-06-17 22:11:22 +00:00
int sip_headers ;
2011-06-01 19:24:09 +00:00
uint8_t crash_on_assert ;
uint8_t fail_on_error ;
uint8_t config_error ;
2007-05-26 04:45:31 +00:00
} globals ;
2010-05-20 15:43:40 +00:00
/* private data attached to each fs session */
2007-05-26 04:45:31 +00:00
struct private_object {
unsigned int flags ;
switch_codec_t read_codec ;
switch_codec_t write_codec ;
switch_frame_t read_frame ;
unsigned char databuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
2007-05-27 18:14:49 +00:00
switch_frame_t cng_frame ;
unsigned char cng_databuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
2007-05-26 04:45:31 +00:00
switch_core_session_t * session ;
switch_caller_profile_t * caller_profile ;
unsigned int codec ;
unsigned int codecs ;
unsigned short samprate ;
switch_mutex_t * mutex ;
switch_mutex_t * flag_mutex ;
2010-01-15 19:22:49 +00:00
ftdm_channel_t * ftdmchan ;
2011-06-07 21:35:49 +00:00
uint32_t write_error ;
uint32_t read_error ;
2012-01-26 16:19:41 +00:00
char network_peer_uuid [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
2007-05-26 04:45:31 +00:00
} ;
2010-05-20 15:43:40 +00:00
/* private data attached to FTDM channels (only FXS for now) */
typedef struct chan_pvt {
unsigned int flags ;
} chan_pvt_t ;
2007-05-26 04:45:31 +00:00
typedef struct private_object private_t ;
2010-05-20 15:43:40 +00:00
struct span_config {
ftdm_span_t * span ;
char dialplan [ 80 ] ;
char context [ 80 ] ;
char dial_regex [ 256 ] ;
char fail_dial_regex [ 256 ] ;
char hold_music [ 256 ] ;
char type [ 256 ] ;
analog_option_t analog_options ;
2010-07-28 15:35:39 +00:00
const char * limit_backend ;
int limit_calls ;
int limit_seconds ;
limit_reset_event_t limit_reset_event ;
2011-05-19 20:17:46 +00:00
/* digital codec and digital sampling rate are used to configure the codec
* when bearer capability is set to unrestricted digital */
const char * digital_codec ;
int digital_sampling_rate ;
2010-05-20 15:43:40 +00:00
chan_pvt_t pvts [ FTDM_MAX_CHANNELS_SPAN ] ;
} ;
static struct span_config SPAN_CONFIG [ FTDM_MAX_SPANS_INTERFACE ] = { { 0 } } ;
2007-05-26 04:45:31 +00:00
static switch_status_t channel_on_init ( switch_core_session_t * session ) ;
static switch_status_t channel_on_hangup ( switch_core_session_t * session ) ;
2009-04-14 19:03:03 +00:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session ) ;
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_routing ( switch_core_session_t * session ) ;
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session ) ;
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session ) ;
2008-05-15 19:43:58 +00:00
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
2007-05-26 04:45:31 +00:00
switch_caller_profile_t * outbound_profile ,
2008-01-08 23:33:07 +00:00
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
2009-11-23 18:19:35 +00:00
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause ) ;
2008-05-08 20:27:31 +00:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id ) ;
2007-05-26 04:45:31 +00:00
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig ) ;
2010-11-26 00:19:32 +00:00
static const char * channel_get_variable ( switch_core_session_t * session , switch_event_t * var_event , const char * variable_name ) ;
2010-01-15 19:22:49 +00:00
ftdm_status_t ftdm_channel_from_event ( ftdm_sigmsg_t * sigmsg , switch_core_session_t * * sp ) ;
void dump_chan ( ftdm_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream ) ;
void dump_chan_xml ( ftdm_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream ) ;
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
static switch_core_session_t * ftdm_channel_get_session ( ftdm_channel_t * channel , int32_t id )
2007-06-11 18:15:09 +00:00
{
switch_core_session_t * session = NULL ;
2010-04-21 15:20:05 +00:00
const char * token = ftdm_channel_get_token ( channel , id ) ;
2007-06-11 18:15:09 +00:00
2010-04-21 15:20:05 +00:00
if ( ! zstr ( token ) ) {
if ( ! ( session = switch_core_session_locate ( token ) ) ) {
ftdm_channel_clear_token ( channel , token ) ;
2008-01-10 00:47:04 +00:00
}
2007-06-11 18:15:09 +00:00
}
return session ;
}
2010-01-15 19:22:49 +00:00
static const char * ftdm_channel_get_uuid ( ftdm_channel_t * channel , int32_t id )
2009-09-06 14:43:58 +00:00
{
2010-04-21 15:20:05 +00:00
return ftdm_channel_get_token ( channel , id ) ;
2009-09-06 14:43:58 +00:00
}
2007-06-11 18:15:09 +00:00
2008-05-01 16:41:10 +00:00
static void stop_hold ( switch_core_session_t * session_a , const char * uuid )
2008-01-10 00:47:04 +00:00
{
switch_core_session_t * session ;
2008-05-01 16:41:10 +00:00
switch_channel_t * channel , * channel_a ;
;
2008-01-10 00:47:04 +00:00
if ( ! uuid ) {
return ;
}
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2008-05-01 16:41:10 +00:00
if ( switch_channel_test_flag ( channel , CF_HOLD ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_unhold ( session ) ;
switch_channel_clear_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_clear_flag ( channel_a , CF_HOLD ) ;
} else {
switch_channel_stop_broadcast ( channel ) ;
2008-09-09 19:17:38 +00:00
switch_channel_wait_for_flag ( channel , CF_BROADCAST , SWITCH_FALSE , 2000 , NULL ) ;
2008-05-01 16:41:10 +00:00
}
2008-04-30 15:17:55 +00:00
2008-01-10 00:47:04 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
2010-01-15 19:22:49 +00:00
static void start_hold ( ftdm_channel_t * ftdmchan , switch_core_session_t * session_a , const char * uuid , const char * stream )
2008-01-10 00:47:04 +00:00
{
switch_core_session_t * session ;
2008-05-01 16:41:10 +00:00
switch_channel_t * channel , * channel_a ;
2010-04-21 15:20:05 +00:00
int32_t spanid = 0 ;
2008-01-10 00:47:04 +00:00
if ( ! uuid ) {
return ;
}
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( ftdmchan ) ;
2008-01-10 00:47:04 +00:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
if ( ! strcasecmp ( globals . hold_music , " indicate_hold " ) ) {
stream = " indicate_hold " ;
}
2010-04-21 15:20:05 +00:00
if ( ! strcasecmp ( SPAN_CONFIG [ spanid ] . hold_music , " indicate_hold " ) ) {
2008-05-01 16:41:10 +00:00
stream = " indicate_hold " ;
}
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2010-04-21 15:20:05 +00:00
stream = SPAN_CONFIG [ spanid ] . hold_music ;
2008-05-01 16:41:10 +00:00
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
stream = globals . hold_music ;
}
2008-01-10 00:47:04 +00:00
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) & & ! ( stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ) ) {
2008-04-30 15:17:55 +00:00
stream = globals . hold_music ;
2008-01-10 00:47:04 +00:00
}
2009-10-23 16:03:57 +00:00
if ( ! zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
if ( ! strcasecmp ( stream , " indicate_hold " ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_hold_uuid ( uuid , NULL , 0 ) ;
switch_channel_set_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_set_flag ( channel_a , CF_HOLD ) ;
} else {
switch_ivr_broadcast ( switch_core_session_get_uuid ( session ) , stream , SMF_ECHO_ALEG | SMF_LOOP ) ;
}
2008-01-10 00:47:04 +00:00
}
switch_core_session_rwunlock ( session ) ;
}
}
2010-01-15 19:22:49 +00:00
static void cycle_foreground ( ftdm_channel_t * ftdmchan , int flash , const char * bcast ) {
2007-06-11 18:15:09 +00:00
uint32_t i = 0 ;
switch_core_session_t * session ;
switch_channel_t * channel ;
private_t * tech_pvt ;
2010-04-29 14:52:42 +00:00
uint32_t tokencnt = ftdm_channel_get_token_count ( ftdmchan ) ;
2007-06-11 18:15:09 +00:00
2008-01-10 00:47:04 +00:00
2010-04-21 15:20:05 +00:00
for ( i = 0 ; i < tokencnt ; i + + ) {
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( ftdmchan , i ) ) ) {
2008-01-10 00:47:04 +00:00
const char * buuid ;
2007-06-11 18:15:09 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
2008-01-10 00:47:04 +00:00
buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2010-04-21 15:20:05 +00:00
if ( tokencnt = = 1 & & flash ) {
2007-06-11 18:15:09 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
2007-06-11 18:15:09 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2010-01-15 19:22:49 +00:00
start_hold ( ftdmchan , session , buuid , bcast ) ;
2007-06-11 18:15:09 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
} else if ( i ) {
2010-01-15 19:22:49 +00:00
start_hold ( ftdmchan , session , buuid , bcast ) ;
2007-06-11 18:15:09 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
2007-06-11 18:15:09 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
switch_channel_mark_answered ( channel ) ;
}
}
switch_core_session_rwunlock ( session ) ;
}
}
}
2011-05-11 03:35:20 +00:00
static switch_status_t tech_init ( private_t * tech_pvt , switch_core_session_t * session , ftdm_channel_t * ftdmchan , ftdm_caller_data_t * caller_data )
2007-05-26 04:45:31 +00:00
{
2009-01-13 22:45:09 +00:00
const char * dname = NULL ;
2007-05-26 04:45:31 +00:00
uint32_t interval = 0 , srate = 8000 ;
2011-05-19 20:17:46 +00:00
uint32_t span_id ;
2010-01-15 19:22:49 +00:00
ftdm_codec_t codec ;
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
tech_pvt - > ftdmchan = ftdmchan ;
2007-05-26 04:45:31 +00:00
tech_pvt - > read_frame . data = tech_pvt - > databuf ;
tech_pvt - > read_frame . buflen = sizeof ( tech_pvt - > databuf ) ;
2007-05-27 18:14:49 +00:00
tech_pvt - > cng_frame . data = tech_pvt - > cng_databuf ;
tech_pvt - > cng_frame . buflen = sizeof ( tech_pvt - > cng_databuf ) ;
2007-11-08 00:50:28 +00:00
tech_pvt - > cng_frame . flags = SFF_CNG ;
2008-01-10 00:47:04 +00:00
tech_pvt - > cng_frame . codec = & tech_pvt - > read_codec ;
2007-05-27 18:14:49 +00:00
memset ( tech_pvt - > cng_frame . data , 255 , tech_pvt - > cng_frame . buflen ) ;
2007-05-26 04:45:31 +00:00
switch_mutex_init ( & tech_pvt - > mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
switch_core_session_set_private ( session , tech_pvt ) ;
tech_pvt - > session = session ;
2010-01-15 19:22:49 +00:00
if ( FTDM_SUCCESS ! = ftdm_channel_command ( ftdmchan , FTDM_COMMAND_GET_INTERVAL , & interval ) ) {
2009-09-14 21:19:07 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to retrieve channel interval. \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2011-05-19 20:17:46 +00:00
span_id = ftdm_channel_get_span_id ( ftdmchan ) ;
if ( caller_data - > bearer_capability = = FTDM_BEARER_CAP_UNRESTRICTED
& & SPAN_CONFIG [ span_id ] . digital_codec ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Initializing digital call with codec %s at %dhz. \n " ,
SPAN_CONFIG [ span_id ] . digital_codec , SPAN_CONFIG [ span_id ] . digital_sampling_rate ) ;
dname = SPAN_CONFIG [ span_id ] . digital_codec ;
srate = SPAN_CONFIG [ span_id ] . digital_sampling_rate ;
2011-05-11 03:35:20 +00:00
goto init_codecs ;
}
2010-01-15 19:22:49 +00:00
if ( FTDM_SUCCESS ! = ftdm_channel_command ( ftdmchan , FTDM_COMMAND_GET_CODEC , & codec ) ) {
2009-09-14 21:19:07 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to retrieve channel codec. \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2007-05-26 04:45:31 +00:00
switch ( codec ) {
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_ULAW :
2007-05-26 04:45:31 +00:00
{
dname = " PCMU " ;
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_ALAW :
2007-05-26 04:45:31 +00:00
{
dname = " PCMA " ;
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_SLIN :
2007-05-26 04:45:31 +00:00
{
dname = " L16 " ;
}
break ;
2008-01-08 23:33:07 +00:00
default :
2009-09-14 21:19:07 +00:00
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid codec value retrieved from channel, codec value: %d \n " , codec ) ;
return SWITCH_STATUS_GENERR ;
}
2007-05-26 04:45:31 +00:00
}
2011-05-11 03:35:20 +00:00
init_codecs :
2007-05-26 04:45:31 +00:00
if ( switch_core_codec_init ( & tech_pvt - > read_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
return SWITCH_STATUS_GENERR ;
} else {
if ( switch_core_codec_init ( & tech_pvt - > write_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
return SWITCH_STATUS_GENERR ;
}
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Set codec %s %dms \n " , dname , interval ) ;
switch_core_session_set_read_codec ( tech_pvt - > session , & tech_pvt - > read_codec ) ;
switch_core_session_set_write_codec ( tech_pvt - > session , & tech_pvt - > write_codec ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_CODEC ) ;
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
2008-10-17 23:00:47 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_init ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt = NULL ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
2008-05-08 20:27:31 +00:00
/* Move channel's state machine to ROUTING */
2008-05-05 15:47:44 +00:00
switch_channel_set_state ( channel , CS_ROUTING ) ;
2007-05-26 04:45:31 +00:00
switch_mutex_lock ( globals . mutex ) ;
globals . calls + + ;
switch_mutex_unlock ( globals . mutex ) ;
2008-10-03 21:03:21 +00:00
//switch_channel_set_flag(channel, CF_ACCEPT_CNG);
2008-10-03 18:15:04 +00:00
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_routing ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
2010-12-29 18:38:43 +00:00
switch_assert ( channel ! = NULL ) ;
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
2010-12-29 18:38:43 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2007-05-26 04:45:31 +00:00
2010-12-29 18:38:43 +00:00
switch_assert ( tech_pvt - > ftdmchan ! = NULL ) ;
2007-05-26 04:45:31 +00:00
2010-11-25 01:04:43 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL ROUTING \n " , switch_channel_get_name ( channel ) ) ;
2010-12-09 18:20:05 +00:00
2010-12-29 18:38:43 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_PROCEED ) ;
}
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_execute ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
2010-12-29 18:38:43 +00:00
switch_assert ( channel ! = NULL ) ;
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
2010-12-29 18:38:43 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2007-05-26 04:45:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL EXECUTE \n " , switch_channel_get_name ( channel ) ) ;
return SWITCH_STATUS_SUCCESS ;
}
2009-04-14 19:03:03 +00:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session )
{
private_t * tech_pvt = NULL ;
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
static switch_status_t channel_on_hangup ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2010-04-21 15:20:05 +00:00
ftdm_chan_type_t chantype ;
uint32_t tokencnt ;
2011-12-16 01:39:38 +00:00
char * uuid = NULL ;
uint8_t uuid_found = 0 ;
uint32_t t = 0 ;
const char * token = NULL ;
int span_id = 0 ;
int chan_id = 0 ;
const char * name = NULL ;
2007-05-26 04:45:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2011-12-16 01:39:38 +00:00
/* ignore any further I/O requests, we're hanging up already! */
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2010-02-09 22:01:15 +00:00
if ( ! tech_pvt - > ftdmchan ) {
goto end ;
}
2007-06-11 18:15:09 +00:00
2011-12-16 01:39:38 +00:00
name = switch_channel_get_name ( channel ) ;
span_id = tech_pvt - > ftdmchan ? ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) : 0 ;
chan_id = tech_pvt - > ftdmchan ? ftdm_channel_get_id ( tech_pvt - > ftdmchan ) : 0 ;
/* Now verify the device is still attached to this call :-)
* Sometimes the FS core takes too long ( more than 3 seconds ) in calling
* channel_on_hangup ( ) and the FreeTDM core decides to take the brute
* force approach and hangup and detach themselves from the call . Later
* when FS finally comes around , we might end up hanging up the device
* attached to another call , this verification avoids that . */
uuid = switch_core_session_get_uuid ( session ) ;
tokencnt = ftdm_channel_get_token_count ( tech_pvt - > ftdmchan ) ;
for ( t = 0 ; t < tokencnt ; t + + ) {
token = ftdm_channel_get_token ( tech_pvt - > ftdmchan , t ) ;
if ( ! zstr ( token ) & & ! strcasecmp ( uuid , token ) ) {
uuid_found = 1 ;
break ;
}
}
if ( ! uuid_found ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Device [%d:%d] is no longer attached to %s. Nothing to do. \n " , span_id , chan_id , name ) ;
goto end ;
}
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( tech_pvt - > ftdmchan , switch_core_session_get_uuid ( session ) ) ;
2010-04-21 15:20:05 +00:00
chantype = ftdm_channel_get_type ( tech_pvt - > ftdmchan ) ;
switch ( chantype ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXO :
case FTDM_CHAN_TYPE_EM :
2007-05-31 20:15:16 +00:00
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_hangup ( tech_pvt - > ftdmchan ) ;
2007-05-31 20:15:16 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXS :
2007-05-27 14:58:01 +00:00
{
2010-04-21 15:20:05 +00:00
if ( ! ftdm_channel_call_check_busy ( tech_pvt - > ftdmchan ) & & ! ftdm_channel_call_check_done ( tech_pvt - > ftdmchan ) ) {
tokencnt = ftdm_channel_get_token_count ( tech_pvt - > ftdmchan ) ;
if ( tokencnt ) {
2010-01-15 19:22:49 +00:00
cycle_foreground ( tech_pvt - > ftdmchan , 0 , NULL ) ;
2007-06-11 18:15:09 +00:00
} else {
2010-04-21 15:20:05 +00:00
ftdm_channel_call_hangup ( tech_pvt - > ftdmchan ) ;
2007-06-11 18:15:09 +00:00
}
2007-05-27 14:58:01 +00:00
}
}
break ;
2011-03-01 17:10:18 +00:00
case FTDM_CHAN_TYPE_CAS :
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_B :
2007-06-13 03:37:55 +00:00
{
2012-01-30 23:02:26 +00:00
const char * var = NULL ;
2010-04-21 15:20:05 +00:00
ftdm_call_cause_t hcause = switch_channel_get_cause_q850 ( channel ) ;
if ( hcause < 1 | | hcause > 127 ) {
hcause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2012-01-30 23:02:26 +00:00
var = switch_channel_get_variable ( channel , " ss7_rel_loc " ) ;
if ( var ) {
ftdm_usrmsg_t usrmsg ;
memset ( & usrmsg , 0 , sizeof ( ftdm_usrmsg_t ) ) ;
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rel_loc " , var ) ;
ftdm_channel_call_hangup_with_cause_ex ( tech_pvt - > ftdmchan , hcause , & usrmsg ) ;
} else {
ftdm_channel_call_hangup_with_cause ( tech_pvt - > ftdmchan , hcause ) ;
2012-01-26 21:39:43 +00:00
}
2007-06-13 03:37:55 +00:00
}
break ;
2007-05-27 14:58:01 +00:00
default :
{
2011-03-01 17:10:18 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Unhandled channel type %d for channel %s \n " , chantype , switch_channel_get_name ( channel ) ) ;
2007-05-27 14:58:01 +00:00
}
break ;
2007-05-26 04:45:31 +00:00
}
2010-02-09 22:01:15 +00:00
end :
2007-05-27 14:58:01 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 04:45:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL HANGUP \n " , switch_channel_get_name ( channel ) ) ;
switch_mutex_lock ( globals . mutex ) ;
globals . calls - - ;
if ( globals . calls < 0 ) {
globals . calls = 0 ;
}
switch_mutex_unlock ( globals . mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( sig ) {
case SWITCH_SIG_KILL :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2008-10-17 23:00:47 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-05-26 04:45:31 +00:00
break ;
case SWITCH_SIG_BREAK :
switch_set_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
2008-05-05 15:47:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL EXCHANGE_MEDIA \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
2008-05-05 15:47:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL SOFT_EXECUTE \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-12-22 02:16:03 +00:00
static switch_status_t channel_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2007-05-26 04:45:31 +00:00
{
private_t * tech_pvt = NULL ;
2007-12-22 02:16:03 +00:00
char tmp [ 2 ] = " " ;
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2007-12-22 02:16:03 +00:00
tmp [ 0 ] = dtmf - > digit ;
2010-01-15 19:22:49 +00:00
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_SEND_DTMF , tmp ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-08 20:27:31 +00:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_size_t len ;
ftdm_wait_flag_t wflags = FTDM_READ ;
2007-05-27 05:23:28 +00:00
char dtmf [ 128 ] = " " ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status ;
2008-05-08 20:27:31 +00:00
int total_to ;
2007-05-31 20:15:16 +00:00
int chunk , do_break = 0 ;
2011-06-07 21:35:49 +00:00
uint32_t span_id , chan_id ;
2009-02-07 23:14:25 +00:00
2007-05-26 04:45:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2008-01-25 16:42:06 +00:00
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " TFLAG_DEAD is set \n " ) ;
2010-02-09 22:01:15 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-05-26 04:45:31 +00:00
2011-06-07 21:35:49 +00:00
if ( ! tech_pvt - > ftdmchan ) {
return SWITCH_STATUS_FALSE ;
}
span_id = ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ;
chan_id = ftdm_channel_get_id ( tech_pvt - > ftdmchan ) ;
2009-05-26 21:47:48 +00:00
/* Digium Cards sometimes timeout several times in a row here.
Yes , we support digium cards , ain ' t we nice . . . . . . .
6 double length intervals should compensate */
2010-04-21 15:20:05 +00:00
chunk = ftdm_channel_get_io_interval ( tech_pvt - > ftdmchan ) * 2 ;
2009-05-26 21:47:48 +00:00
total_to = chunk * 6 ;
2007-05-31 20:15:16 +00:00
2007-05-31 02:41:50 +00:00
top :
2007-05-31 20:15:16 +00:00
2008-05-08 20:27:31 +00:00
if ( switch_channel_test_flag ( channel , CF_SUSPEND ) ) {
do_break = 1 ;
}
2007-05-31 20:15:16 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BREAK ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
do_break = 1 ;
}
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) | | do_break ) {
2010-04-21 15:20:05 +00:00
switch_yield ( ftdm_channel_get_io_interval ( tech_pvt - > ftdmchan ) * 1000 ) ;
tech_pvt - > cng_frame . datalen = ftdm_channel_get_io_packet_len ( tech_pvt - > ftdmchan ) ;
2007-05-27 18:14:49 +00:00
tech_pvt - > cng_frame . samples = tech_pvt - > cng_frame . datalen ;
2008-10-17 23:00:47 +00:00
tech_pvt - > cng_frame . flags = SFF_CNG ;
* frame = & tech_pvt - > cng_frame ;
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_get_codec ( tech_pvt - > ftdmchan ) = = FTDM_CODEC_SLIN ) {
2007-05-27 18:14:49 +00:00
tech_pvt - > cng_frame . samples / = 2 ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-27 14:58:01 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " TFLAG_IO is not set \n " ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2010-01-15 19:22:49 +00:00
wflags = FTDM_READ ;
status = ftdm_channel_wait ( tech_pvt - > ftdmchan , & wflags , chunk ) ;
2007-11-17 01:39:28 +00:00
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_FAIL ) {
2010-11-06 21:14:31 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Failed to wait for I/O \n " ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2007-05-31 02:41:50 +00:00
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_TIMEOUT ) {
2008-05-08 20:27:31 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2007-05-31 02:41:50 +00:00
total_to - = chunk ;
if ( total_to < = 0 ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_WARNING , " Too many timeouts while waiting for I/O \n " ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-31 02:41:50 +00:00
}
}
goto top ;
2007-05-26 04:45:31 +00:00
}
2010-01-15 19:22:49 +00:00
if ( ! ( wflags & FTDM_READ ) ) {
2010-06-03 23:09:34 +00:00
goto top ;
2007-05-26 04:45:31 +00:00
}
len = tech_pvt - > read_frame . buflen ;
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_read ( tech_pvt - > ftdmchan , tech_pvt - > read_frame . data , & len ) ! = FTDM_SUCCESS ) {
2011-06-07 21:35:49 +00:00
ftdm_log ( FTDM_LOG_WARNING , " failed to read from device %d:%d \n " , span_id , chan_id ) ;
if ( + + tech_pvt - > read_error > FTDM_MAX_READ_WRITE_ERRORS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " too many I/O read errors on device %d:%d! \n " , span_id , chan_id ) ;
goto fail ;
}
} else {
tech_pvt - > read_error = 0 ;
2007-05-26 04:45:31 +00:00
}
* frame = & tech_pvt - > read_frame ;
2009-03-06 18:17:15 +00:00
tech_pvt - > read_frame . datalen = ( uint32_t ) len ;
2007-05-26 04:45:31 +00:00
tech_pvt - > read_frame . samples = tech_pvt - > read_frame . datalen ;
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_get_codec ( tech_pvt - > ftdmchan ) = = FTDM_CODEC_SLIN ) {
2007-05-26 04:45:31 +00:00
tech_pvt - > read_frame . samples / = 2 ;
}
2010-02-25 23:36:18 +00:00
while ( ftdm_channel_dequeue_dtmf ( tech_pvt - > ftdmchan , dtmf , sizeof ( dtmf ) ) ) {
2007-12-22 02:16:03 +00:00
switch_dtmf_t _dtmf = { 0 , SWITCH_DEFAULT_DTMF_DURATION } ;
2008-01-12 06:11:48 +00:00
char * p ;
for ( p = dtmf ; p & & * p ; p + + ) {
if ( is_dtmf ( * p ) ) {
_dtmf . digit = * p ;
2010-06-03 21:27:43 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Queuing DTMF [%c] in channel %s \n " , * p , switch_channel_get_name ( channel ) ) ;
2008-01-12 06:11:48 +00:00
switch_channel_queue_dtmf ( channel , & _dtmf ) ;
}
}
2007-05-26 04:45:31 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-17 01:39:28 +00:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 04:45:31 +00:00
}
2008-05-08 20:27:31 +00:00
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_size_t len ;
2008-10-03 18:15:04 +00:00
unsigned char data [ SWITCH_RECOMMENDED_BUFFER_SIZE ] = { 0 } ;
2010-01-15 19:22:49 +00:00
ftdm_wait_flag_t wflags = FTDM_WRITE ;
2011-06-07 21:35:49 +00:00
uint32_t span_id , chan_id ;
2009-07-24 16:01:33 +00:00
2007-05-26 04:45:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2008-10-17 23:00:47 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
return SWITCH_STATUS_FALSE ;
}
2007-05-27 18:14:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2011-06-07 21:35:49 +00:00
if ( ! tech_pvt - > ftdmchan ) {
return SWITCH_STATUS_FALSE ;
}
span_id = ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ;
chan_id = ftdm_channel_get_id ( tech_pvt - > ftdmchan ) ;
2007-05-31 02:41:50 +00:00
2008-10-03 18:15:04 +00:00
if ( switch_test_flag ( frame , SFF_CNG ) ) {
frame - > data = data ;
frame - > buflen = sizeof ( data ) ;
2008-10-20 18:10:37 +00:00
if ( ( frame - > datalen = tech_pvt - > write_codec . implementation - > encoded_bytes_per_packet ) > frame - > buflen ) {
2008-10-03 18:15:04 +00:00
goto fail ;
}
memset ( data , 255 , frame - > datalen ) ;
}
2010-01-15 19:22:49 +00:00
wflags = FTDM_WRITE ;
2011-04-23 02:49:41 +00:00
ftdm_channel_wait ( tech_pvt - > ftdmchan , & wflags , ftdm_channel_get_io_interval ( tech_pvt - > ftdmchan ) * 10 ) ;
2009-07-24 16:01:33 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ( wflags & FTDM_WRITE ) ) {
2010-02-25 23:36:18 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Dropping frame! (write not ready) \n " ) ;
return SWITCH_STATUS_SUCCESS ;
2009-07-24 16:01:33 +00:00
}
2007-05-26 04:45:31 +00:00
len = frame - > datalen ;
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_write ( tech_pvt - > ftdmchan , frame - > data , frame - > buflen , & len ) ! = FTDM_SUCCESS ) {
2011-06-07 21:35:49 +00:00
ftdm_log ( FTDM_LOG_WARNING , " failed to write to device %d:%d \n " , span_id , chan_id ) ;
if ( + + tech_pvt - > write_error > FTDM_MAX_READ_WRITE_ERRORS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG ,
SWITCH_LOG_ERROR , " too many I/O write errors on device %d:%d! \n " , span_id , chan_id ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-31 02:41:50 +00:00
}
2007-05-31 20:15:16 +00:00
} else {
2011-06-07 21:35:49 +00:00
tech_pvt - > write_error = 0 ;
2007-05-26 04:45:31 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-17 01:39:28 +00:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 04:45:31 +00:00
}
2009-08-19 21:47:56 +00:00
static switch_status_t channel_receive_message_cas ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
2010-04-21 15:20:05 +00:00
uint32_t phy_id ;
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-04-21 15:20:05 +00:00
phy_id = ftdm_channel_get_ph_id ( tech_pvt - > ftdmchan ) ;
ftdm_log ( FTDM_LOG_DEBUG , " Got Freeswitch message in R2 channel %d [%d] \n " , phy_id , msg - > message_id ) ;
2010-12-16 02:59:33 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-04-21 15:20:05 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2009-08-19 21:47:56 +00:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_RINGING :
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_PROGRESS ) ;
2009-08-19 21:47:56 +00:00
}
break ;
case SWITCH_MESSAGE_INDICATE_PROGRESS :
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA ) ;
2009-08-19 21:47:56 +00:00
}
break ;
case SWITCH_MESSAGE_INDICATE_ANSWER :
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_answer ( tech_pvt - > ftdmchan ) ;
2009-08-19 21:47:56 +00:00
}
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2008-08-22 16:55:01 +00:00
2007-05-31 20:15:16 +00:00
static switch_status_t channel_receive_message_b ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
2007-06-13 03:37:55 +00:00
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-01-13 17:53:22 +00:00
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-11-30 21:42:58 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-02-09 22:01:15 +00:00
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_call_check_hangup ( tech_pvt - > ftdmchan ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2010-12-16 02:59:33 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-01-13 17:53:22 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-06-13 03:37:55 +00:00
switch ( msg - > message_id ) {
2007-06-16 04:39:15 +00:00
case SWITCH_MESSAGE_INDICATE_RINGING :
2007-06-16 13:46:32 +00:00
{
2010-11-25 01:04:43 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_RINGING ) ;
2007-06-16 04:39:15 +00:00
}
2007-06-16 13:46:32 +00:00
break ;
2007-06-13 03:37:55 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
2007-06-16 13:46:32 +00:00
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA ) ;
2007-06-16 04:39:15 +00:00
}
2007-06-16 13:46:32 +00:00
break ;
2007-06-13 03:37:55 +00:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2007-06-16 13:46:32 +00:00
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_answer ( tech_pvt - > ftdmchan ) ;
2007-06-13 03:37:55 +00:00
}
break ;
2011-05-26 15:38:24 +00:00
case SWITCH_MESSAGE_INDICATE_REDIRECT :
case SWITCH_MESSAGE_INDICATE_DEFLECT :
{
ftdm_usrmsg_t usrmsg ;
const char * val = NULL ;
memset ( & usrmsg , 0 , sizeof ( usrmsg ) ) ;
if ( ( val = switch_channel_get_variable ( channel , " freetdm_transfer_data " ) ) ) {
ftdm_usrmsg_add_var ( & usrmsg , " transfer_data " , val ) ;
}
switch_set_flag ( tech_pvt , TFLAG_TRANSFER ) ;
if ( ftdm_channel_call_transfer_ex ( tech_pvt - > ftdmchan , msg - > string_arg , & usrmsg ) ! = FTDM_SUCCESS ) {
switch_clear_flag ( tech_pvt , TFLAG_TRANSFER ) ;
}
while ( switch_test_flag ( tech_pvt , TFLAG_TRANSFER ) ) {
switch_yield ( 100000 ) ;
}
}
2007-06-13 03:37:55 +00:00
default :
break ;
}
2011-05-26 15:38:24 +00:00
2007-06-13 03:37:55 +00:00
return SWITCH_STATUS_SUCCESS ;
2007-05-31 20:15:16 +00:00
}
static switch_status_t channel_receive_message_fxo ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-11-30 21:42:58 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-02-09 22:01:15 +00:00
2010-12-16 02:59:33 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-04-21 15:20:05 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-05-31 20:15:16 +00:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-04-21 15:20:05 +00:00
ftdm_channel_call_answer ( tech_pvt - > ftdmchan ) ;
2007-05-31 20:15:16 +00:00
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_receive_message_fxs ( switch_core_session_t * session , switch_core_session_message_t * msg )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-05-17 23:03:32 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-04-21 15:20:05 +00:00
2010-12-16 02:59:33 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-04-21 15:20:05 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2010-02-09 22:01:15 +00:00
2007-05-26 04:45:31 +00:00
switch ( msg - > message_id ) {
2007-05-31 20:15:16 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
2007-05-26 04:45:31 +00:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-04-21 15:20:05 +00:00
ftdm_channel_call_answer ( tech_pvt - > ftdmchan ) ;
switch_channel_mark_answered ( channel ) ;
2007-05-26 04:45:31 +00:00
break ;
case SWITCH_MESSAGE_INDICATE_RINGING :
2010-04-21 15:20:05 +00:00
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) & &
! switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) & &
! switch_channel_test_flag ( channel , CF_RING_READY )
) {
2010-11-25 01:04:43 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_RINGING ) ;
2008-09-26 17:29:48 +00:00
switch_channel_mark_ring_ready ( channel ) ;
2008-09-26 17:09:10 +00:00
}
2007-05-26 04:45:31 +00:00
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-31 20:15:16 +00:00
static switch_status_t channel_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
private_t * tech_pvt ;
2008-02-26 16:55:54 +00:00
switch_status_t status ;
2009-09-14 14:26:31 +00:00
switch_channel_t * channel ;
const char * var ;
2010-02-09 22:01:15 +00:00
ftdm_channel_t * ftdmchan = NULL ;
2009-09-14 14:26:31 +00:00
2007-05-31 20:15:16 +00:00
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2009-09-14 14:26:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
if ( ! ( ftdmchan = tech_pvt - > ftdmchan ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
if ( ! tech_pvt - > ftdmchan ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
2010-04-21 15:20:05 +00:00
return SWITCH_STATUS_FALSE ;
2010-02-09 22:01:15 +00:00
}
2009-09-14 14:26:31 +00:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-12-16 02:59:33 +00:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2010-01-15 19:22:49 +00:00
if ( ( var = switch_channel_get_variable ( channel , " freetdm_pre_buffer_size " ) ) ) {
2009-09-14 14:26:31 +00:00
int tmp = atoi ( var ) ;
if ( tmp > - 1 ) {
2010-01-15 19:22:49 +00:00
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_SET_PRE_BUFFER_SIZE , & tmp ) ;
2009-09-14 14:26:31 +00:00
}
}
2010-06-23 19:52:11 +00:00
if ( ( var = switch_channel_get_variable ( channel , " freetdm_disable_dtmf " ) ) ) {
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_DISABLE_DTMF_DETECT , NULL ) ;
}
2009-09-14 14:26:31 +00:00
}
break ;
2009-10-22 14:55:15 +00:00
case SWITCH_MESSAGE_INDICATE_UUID_CHANGE :
{
2010-01-15 19:22:49 +00:00
ftdm_channel_replace_token ( tech_pvt - > ftdmchan , msg - > string_array_arg [ 0 ] , msg - > string_array_arg [ 1 ] ) ;
2009-10-22 14:55:15 +00:00
}
break ;
2009-09-14 14:26:31 +00:00
default :
break ;
}
2010-04-21 15:20:05 +00:00
switch ( ftdm_channel_get_type ( tech_pvt - > ftdmchan ) ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXS :
case FTDM_CHAN_TYPE_EM :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_fxs ( session , msg ) ;
2008-02-26 22:30:54 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXO :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_fxo ( session , msg ) ;
2008-02-26 22:30:54 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_B :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_b ( session , msg ) ;
2009-08-19 21:47:56 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_CAS :
2009-08-19 21:47:56 +00:00
status = channel_receive_message_cas ( session , msg ) ;
break ;
2007-05-31 20:15:16 +00:00
default :
2008-02-26 16:55:54 +00:00
status = SWITCH_STATUS_FALSE ;
2008-02-26 22:30:54 +00:00
break ;
2007-05-31 20:15:16 +00:00
}
2008-02-26 16:55:54 +00:00
return status ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
switch_state_handler_table_t freetdm_state_handlers = {
2007-05-26 04:45:31 +00:00
/*.on_init */ channel_on_init ,
2008-05-05 15:47:44 +00:00
/*.on_routing */ channel_on_routing ,
2007-05-26 04:45:31 +00:00
/*.on_execute */ channel_on_execute ,
/*.on_hangup */ channel_on_hangup ,
2008-05-05 15:47:44 +00:00
/*.on_exchange_media */ channel_on_exchange_media ,
2009-04-14 19:03:03 +00:00
/*.on_soft_execute */ channel_on_soft_execute ,
/*.on_consume_media */ NULL ,
/*.on_hibernate */ NULL ,
/*.on_reset */ NULL ,
/*.on_park*/ NULL ,
/*.on_reporting*/ NULL ,
/*.on_destroy*/ channel_on_destroy
2007-05-26 04:45:31 +00:00
} ;
2010-01-15 19:22:49 +00:00
switch_io_routines_t freetdm_io_routines = {
2007-05-26 04:45:31 +00:00
/*.outgoing_channel */ channel_outgoing_channel ,
/*.read_frame */ channel_read_frame ,
/*.write_frame */ channel_write_frame ,
/*.kill_channel */ channel_kill_channel ,
/*.send_dtmf */ channel_send_dtmf ,
/*.receive_message*/ channel_receive_message
} ;
2010-11-26 00:19:32 +00:00
static const char * channel_get_variable ( switch_core_session_t * session , switch_event_t * var_event , const char * variable_name )
{
const char * variable = NULL ;
if ( var_event ) {
if ( ( variable = switch_event_get_header ( var_event , variable_name ) ) ) {
return variable ;
}
}
2011-02-11 15:55:11 +00:00
2010-11-26 00:19:32 +00:00
if ( session ) {
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
if ( ( variable = switch_channel_get_variable ( channel , variable_name ) ) ) {
return variable ;
}
}
return NULL ;
}
2011-01-10 21:49:58 +00:00
typedef struct {
switch_event_t * var_event ;
switch_core_session_t * new_session ;
private_t * tech_pvt ;
switch_caller_profile_t * caller_profile ;
} hunt_data_t ;
static ftdm_status_t on_channel_found ( ftdm_channel_t * fchan , ftdm_caller_data_t * caller_data )
{
uint32_t span_id , chan_id ;
const char * var ;
char * sess_uuid ;
char name [ 128 ] ;
ftdm_status_t status ;
hunt_data_t * hdata = caller_data - > priv ;
switch_channel_t * channel = switch_core_session_get_channel ( hdata - > new_session ) ;
if ( ( var = switch_event_get_header ( hdata - > var_event , " freetdm_pre_buffer_size " ) ) ) {
int tmp = atoi ( var ) ;
if ( tmp > - 1 ) {
ftdm_channel_command ( fchan , FTDM_COMMAND_SET_PRE_BUFFER_SIZE , & tmp ) ;
}
}
span_id = ftdm_channel_get_span_id ( fchan ) ;
chan_id = ftdm_channel_get_id ( fchan ) ;
2011-05-11 03:35:20 +00:00
tech_init ( hdata - > tech_pvt , hdata - > new_session , fchan , caller_data ) ;
2011-01-10 21:49:58 +00:00
snprintf ( name , sizeof ( name ) , " FreeTDM/%u:%u/%s " , span_id , chan_id , caller_data - > dnis . digits ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Connect outbound channel %s \n " , name ) ;
switch_channel_set_name ( channel , name ) ;
switch_channel_set_variable ( channel , " freetdm_span_name " , ftdm_channel_get_span_name ( fchan ) ) ;
switch_channel_set_variable_printf ( channel , " freetdm_span_number " , " %d " , span_id ) ;
switch_channel_set_variable_printf ( channel , " freetdm_chan_number " , " %d " , chan_id ) ;
2011-01-11 19:53:14 +00:00
switch_channel_set_caller_profile ( channel , hdata - > caller_profile ) ;
hdata - > tech_pvt - > caller_profile = hdata - > caller_profile ;
2011-01-10 21:49:58 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
sess_uuid = switch_core_session_get_uuid ( hdata - > new_session ) ;
status = ftdm_channel_add_token ( fchan , sess_uuid , ftdm_channel_get_token_count ( fchan ) ) ;
switch_assert ( status = = FTDM_SUCCESS ) ;
if ( SPAN_CONFIG [ span_id ] . limit_calls ) {
char spanresource [ 512 ] ;
snprintf ( spanresource , sizeof ( spanresource ) , " span_%s_%s " , ftdm_channel_get_span_name ( fchan ) ,
caller_data - > dnis . digits ) ;
ftdm_log ( FTDM_LOG_DEBUG , " Adding rate limit resource on channel %d:%d (%s/%s/%d/%d) \n " ,
span_id , chan_id , FREETDM_LIMIT_REALM ,
spanresource , SPAN_CONFIG [ span_id ] . limit_calls , SPAN_CONFIG [ span_id ] . limit_seconds ) ;
if ( switch_limit_incr ( " hash " , hdata - > new_session , FREETDM_LIMIT_REALM , spanresource ,
SPAN_CONFIG [ span_id ] . limit_calls , SPAN_CONFIG [ span_id ] . limit_seconds ) ! = SWITCH_STATUS_SUCCESS ) {
return FTDM_BREAK ;
}
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Attached session %s to channel %d:%d \n " , sess_uuid , span_id , chan_id ) ;
return FTDM_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel ' s pool !
*/
2008-05-15 19:43:58 +00:00
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
2007-05-26 04:45:31 +00:00
switch_caller_profile_t * outbound_profile ,
2008-01-08 23:33:07 +00:00
switch_core_session_t * * new_session , switch_memory_pool_t * * pool ,
2009-11-23 18:19:35 +00:00
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause )
2007-05-26 04:45:31 +00:00
{
2011-01-10 21:49:58 +00:00
hunt_data_t hunt_data ;
2009-01-13 22:45:09 +00:00
const char * dest = NULL ;
char * data = NULL ;
2010-04-21 15:20:05 +00:00
int span_id = - 1 , group_id = - 1 , chan_id = 0 ;
2007-05-31 03:04:26 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status ;
int direction = FTDM_TOP_DOWN ;
ftdm_caller_data_t caller_data = { { 0 } } ;
2008-10-06 15:57:11 +00:00
char * span_name = NULL ;
2008-10-06 19:13:32 +00:00
switch_event_header_t * h ;
2008-10-06 20:02:55 +00:00
char * argv [ 3 ] ;
int argc = 0 ;
2009-01-12 17:46:30 +00:00
const char * var ;
2010-03-10 20:06:31 +00:00
const char * dest_num = NULL , * callerid_num = NULL ;
2012-01-26 16:19:41 +00:00
const char * network_peer_uuid = NULL ;
2012-01-27 04:51:21 +00:00
char sigbridge_peer [ 255 ] ;
switch_channel_t * peer_chan = NULL ;
switch_channel_t * our_chan = NULL ;
2011-01-10 21:49:58 +00:00
ftdm_hunting_scheme_t hunting ;
2011-02-25 14:58:15 +00:00
ftdm_usrmsg_t usrmsg ;
2011-02-18 18:01:57 +00:00
2011-02-25 14:58:15 +00:00
memset ( & usrmsg , 0 , sizeof ( ftdm_usrmsg_t ) ) ;
2012-01-27 11:34:36 +00:00
memset ( sigbridge_peer , 0 , sizeof ( sigbridge_peer ) ) ;
2008-02-29 00:21:04 +00:00
2007-05-31 03:04:26 +00:00
if ( ! outbound_profile ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing caller profile \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( outbound_profile - > destination_number ) ) {
2008-01-07 16:50:20 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-01-25 15:05:37 +00:00
2008-10-06 20:02:55 +00:00
data = switch_core_strdup ( outbound_profile - > pool , outbound_profile - > destination_number ) ;
2008-10-06 15:57:11 +00:00
2010-03-10 20:06:31 +00:00
if ( ! zstr ( outbound_profile - > destination_number ) ) {
dest_num = switch_sanitize_number ( switch_core_strdup ( outbound_profile - > pool , outbound_profile - > destination_number ) ) ;
}
if ( ! zstr ( outbound_profile - > caller_id_number ) ) {
callerid_num = switch_sanitize_number ( switch_core_strdup ( outbound_profile - > pool , outbound_profile - > caller_id_number ) ) ;
}
2010-02-09 22:01:15 +00:00
2010-03-10 20:06:31 +00:00
if ( ! zstr ( callerid_num ) & & ! strcmp ( callerid_num , " 0000000000 " ) ) {
callerid_num = NULL ;
}
2008-10-09 01:18:40 +00:00
if ( ( argc = switch_separate_string ( data , ' / ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) < 2 ) {
2008-10-06 20:02:55 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
2011-01-10 21:49:58 +00:00
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2008-10-06 20:02:55 +00:00
}
2008-10-06 15:57:11 +00:00
2008-10-06 20:02:55 +00:00
if ( switch_is_number ( argv [ 0 ] ) ) {
span_id = atoi ( argv [ 0 ] ) ;
} else {
span_name = argv [ 0 ] ;
}
if ( * argv [ 1 ] = = ' A ' ) {
2010-01-15 19:22:49 +00:00
direction = FTDM_BOTTOM_UP ;
2008-10-06 20:02:55 +00:00
} else if ( * argv [ 1 ] = = ' a ' ) {
2010-01-15 19:22:49 +00:00
direction = FTDM_TOP_DOWN ;
2010-12-18 01:04:30 +00:00
} else if ( * argv [ 1 ] = = ' r ' ) {
direction = FTDM_RR_DOWN ;
} else if ( * argv [ 1 ] = = ' R ' ) {
direction = FTDM_RR_UP ;
2008-10-06 20:02:55 +00:00
} else {
chan_id = atoi ( argv [ 1 ] ) ;
2007-05-31 03:04:26 +00:00
}
2008-02-02 16:48:20 +00:00
2008-10-09 01:18:40 +00:00
if ( ! ( dest = argv [ 2 ] ) ) {
dest = " " ;
}
2008-10-06 20:02:55 +00:00
2009-03-01 23:38:33 +00:00
if ( span_id = = 0 & & chan_id ! = 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Span 0 is used to pick the first available span, selecting a channel is not supported (and doesn't make sense) \n " ) ;
2010-01-04 15:26:23 +00:00
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2009-03-01 23:38:33 +00:00
}
2009-10-23 16:03:57 +00:00
if ( span_id = = - 1 & & ! zstr ( span_name ) ) {
2010-01-15 19:22:49 +00:00
ftdm_span_t * span ;
ftdm_status_t zstatus = ftdm_span_find_by_name ( span_name , & span ) ;
if ( zstatus = = FTDM_SUCCESS & & span ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2008-10-06 15:57:11 +00:00
}
}
2009-03-01 23:38:33 +00:00
if ( span_id = = - 1 ) {
2010-01-04 15:26:23 +00:00
//Look for a group
2010-01-15 19:22:49 +00:00
ftdm_group_t * group ;
ftdm_status_t zstatus = ftdm_group_find_by_name ( span_name , & group ) ;
if ( zstatus = = FTDM_SUCCESS & & group ) {
2010-04-21 15:20:05 +00:00
group_id = ftdm_group_get_id ( group ) ;
2010-01-04 15:26:23 +00:00
} else {
2010-01-15 19:22:49 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing ftdm span or group: %s \n " , span_name ) ;
2010-01-04 15:26:23 +00:00
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2007-05-31 03:04:26 +00:00
}
2008-01-25 15:05:37 +00:00
2010-01-04 15:26:23 +00:00
if ( group_id < 0 & & chan_id < 0 ) {
2010-01-15 19:22:49 +00:00
direction = FTDM_BOTTOM_UP ;
2008-01-25 15:05:37 +00:00
chan_id = 0 ;
}
2010-06-29 20:29:37 +00:00
2012-03-30 20:50:00 +00:00
if ( session & & globals . sip_headers & & ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
2010-06-29 20:29:37 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
const char * sipvar ;
2012-01-26 16:19:41 +00:00
network_peer_uuid = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-TransUUID " ) ;
2010-06-29 20:29:37 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-CallerName " ) ;
if ( sipvar ) {
ftdm_set_string ( caller_data . cid_name , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-CallerNumber " ) ;
if ( sipvar ) {
ftdm_set_string ( caller_data . cid_num . digits , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-ANI " ) ;
if ( sipvar ) {
ftdm_set_string ( caller_data . ani . digits , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-ANI-TON " ) ;
if ( sipvar ) {
2010-07-19 13:38:56 +00:00
caller_data . ani . type = ( uint8_t ) atoi ( sipvar ) ;
2010-06-29 20:29:37 +00:00
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-ANI-Plan " ) ;
if ( sipvar ) {
2010-07-19 13:38:56 +00:00
caller_data . ani . plan = ( uint8_t ) atoi ( sipvar ) ;
2010-06-29 20:29:37 +00:00
}
2011-04-06 21:25:29 +00:00
/* Used by ftmod_sangoma_ss7 only */
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-ANI-NADI " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_clg_nadi " , sipvar ) ;
}
2010-06-30 15:14:19 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-ANI2 " ) ;
2010-06-29 20:29:37 +00:00
if ( sipvar ) {
ftdm_set_string ( caller_data . aniII , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-DNIS " ) ;
if ( sipvar ) {
ftdm_set_string ( caller_data . dnis . digits , sipvar ) ;
}
2011-10-12 21:44:52 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-LOC " ) ;
if ( sipvar ) {
ftdm_set_string ( caller_data . loc . digits , sipvar ) ;
}
2012-05-17 21:56:50 +00:00
2012-05-18 13:57:51 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-Access-Transport-URLENC " ) ;
2012-05-17 21:56:50 +00:00
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_access_transport_urlenc " , sipvar ) ;
}
2011-10-12 21:44:52 +00:00
2012-02-16 20:14:06 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-LOC-Screen " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_loc_screen_ind " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-LOC-Presentation " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_loc_pres_ind " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-LOC-NADI " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_loc_nadi " , sipvar ) ;
}
2010-06-29 20:29:37 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-DNIS-TON " ) ;
if ( sipvar ) {
2010-07-19 13:38:56 +00:00
caller_data . dnis . type = ( uint8_t ) atoi ( sipvar ) ;
2010-06-29 20:29:37 +00:00
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-DNIS-Plan " ) ;
if ( sipvar ) {
2010-07-19 13:38:56 +00:00
caller_data . dnis . plan = ( uint8_t ) atoi ( sipvar ) ;
2010-06-29 20:29:37 +00:00
}
2011-04-06 21:25:29 +00:00
/* Used by ftmod_sangoma_ss7 only */
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-DNIS-NADI " ) ;
if ( sipvar ) {
2011-12-05 21:58:26 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " ss7_cld_nadi " , sipvar ) ;
2011-04-06 21:25:29 +00:00
}
2010-06-29 20:29:37 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDNIS " ) ;
if ( sipvar ) {
ftdm_set_string ( caller_data . rdnis . digits , sipvar ) ;
2011-05-06 21:52:41 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdnis_digits " , sipvar ) ;
2010-06-29 20:29:37 +00:00
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDNIS-Plan " ) ;
if ( sipvar ) {
2011-04-26 17:21:49 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdnis_plan " , sipvar ) ;
2010-06-29 20:29:37 +00:00
}
2011-04-06 21:25:29 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDNIS-NADI " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdnis_nadi " , sipvar ) ;
}
2011-04-26 15:04:44 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDNIS-Screen " ) ;
if ( sipvar ) {
2011-04-26 17:21:49 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdnis_screen_ind " , sipvar ) ;
2011-04-26 15:04:44 +00:00
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDNIS-Presentation " ) ;
if ( sipvar ) {
2011-04-26 17:21:49 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdnis_pres_ind " , sipvar ) ;
2011-04-26 15:04:44 +00:00
}
2011-05-06 21:52:41 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-GN " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_gn_digits " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-GN-NumQual " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_gn_numqual " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-GN-NADI " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_gn_nadi " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-GN-Screen " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_gn_screen_ind " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-GN-Presentation " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_gn_pres_ind " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-GN-Plan " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_gn_npi " , sipvar ) ;
}
2011-04-26 15:04:44 +00:00
2011-05-06 21:52:41 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-GN-NumInComp " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_gn_num_inc_ind " , sipvar ) ;
}
2010-06-29 20:29:37 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-Screen " ) ;
if ( sipvar ) {
2011-04-26 19:13:00 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " ss7_screen_ind " , sipvar ) ;
2010-06-29 20:29:37 +00:00
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-Presentation " ) ;
if ( sipvar ) {
2011-04-26 19:13:00 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " ss7_pres_ind " , sipvar ) ;
2010-06-29 20:29:37 +00:00
}
2011-04-06 21:25:29 +00:00
2011-05-10 15:38:23 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-CPC " ) ;
if ( sipvar ) {
2011-05-17 21:13:38 +00:00
ftdm_set_calling_party_category ( sipvar , ( uint8_t * ) & caller_data . cpc ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-IAM " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_iam " , sipvar ) ;
2011-05-10 15:38:23 +00:00
}
2011-12-06 20:38:05 +00:00
/* redirection information */
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDINF-Indicator " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdinfo_indicator " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDINF-OrigReason " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdinfo_orig " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDINF-Count " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdinfo_count " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-RDINF-Reason " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_rdinfo_reason " , sipvar ) ;
}
2012-02-16 20:14:06 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-OCN " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_ocn " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-OCN-NADI " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_ocn_nadi " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-OCN-Plan " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_ocn_plan " , sipvar ) ;
}
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-OCN-Presentation " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_ocn_pres " , sipvar ) ;
}
2010-06-29 20:29:37 +00:00
}
2010-08-10 22:51:06 +00:00
2008-03-01 00:48:36 +00:00
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_SCREEN ) ) {
2011-01-05 15:39:25 +00:00
caller_data . screen = FTDM_SCREENING_VERIFIED_PASSED ;
2008-03-01 00:48:36 +00:00
}
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_HIDE_NUMBER ) ) {
2011-01-05 15:39:25 +00:00
caller_data . pres = FTDM_PRES_RESTRICTED ;
2008-03-01 00:48:36 +00:00
}
2012-01-26 23:00:34 +00:00
if ( ( var = channel_get_variable ( session , var_event , " freetdm_iam_fwd_ind_isdn_access_ind " ) ) ) {
ftdm_usrmsg_add_var ( & usrmsg , " iam_fwd_ind_isdn_access_ind " , var ) ;
}
2010-11-26 00:19:32 +00:00
if ( ( var = channel_get_variable ( session , var_event , " freetdm_bearer_capability " ) ) ) {
caller_data . bearer_capability = ( uint8_t ) atoi ( var ) ;
2008-03-01 00:48:36 +00:00
}
2009-01-12 17:46:30 +00:00
2010-11-26 00:19:32 +00:00
if ( ( var = channel_get_variable ( session , var_event , " freetdm_bearer_layer1 " ) ) ) {
2011-04-26 19:13:00 +00:00
caller_data . bearer_layer1 = ( uint8_t ) atoi ( var ) ;
2010-11-26 00:19:32 +00:00
}
if ( ( var = channel_get_variable ( session , var_event , " freetdm_screening_ind " ) ) ) {
2011-04-26 19:13:00 +00:00
ftdm_set_screening_ind ( var , & caller_data . screen ) ;
2010-11-26 00:19:32 +00:00
}
if ( ( var = channel_get_variable ( session , var_event , " freetdm_presentation_ind " ) ) ) {
2011-04-26 19:13:00 +00:00
ftdm_set_presentation_ind ( var , & caller_data . pres ) ;
2010-11-26 00:19:32 +00:00
}
if ( ( var = channel_get_variable ( session , var_event , " freetdm_outbound_ton " ) ) ) {
2011-04-26 19:13:00 +00:00
ftdm_set_ton ( var , & caller_data . dnis . type ) ;
2009-01-12 17:46:30 +00:00
} else {
2010-02-01 21:40:01 +00:00
caller_data . dnis . type = outbound_profile - > destination_number_ton ;
2009-01-12 17:46:30 +00:00
}
2010-05-21 15:10:15 +00:00
2010-12-18 00:26:43 +00:00
if ( ( var = channel_get_variable ( session , var_event , " freetdm_calling_party_category " ) ) ) {
ftdm_set_calling_party_category ( var , ( uint8_t * ) & caller_data . cpc ) ;
}
ss7: adding iam_fwd_ind_HEX channel variable to set forward indicator
IE's heximal value.
- add <action application="export" data="freetdm_iam_fwd_ind_HEX=2301"/>
to dialplan with expected hex value. If the outgoing ftdm channel's
forward indicator needs to be changed, "export" needs to be put in the
incoming channel's dialplan to set this variable value accordingly.
- this implementation takes bits of A, CB, D, E, F, HG, I from the hex
value. Bits of KJ, L, P-M are not taken from the hex.
- How to calculate hex value with wanted bits:
. the hex value is H-A-P-I, H is the highest bit to A, and next is P-I.
I is the lowest bit in the whole field, and H is the highest bit in
the whole field. Refer to Q.763 chapter 3.23.
. use a text pad to fill in the bits with 0 and 1. eventually fill all
the 16 bits
. copy the binary value into a calculator and convert it to hex
2012-05-28 20:53:45 +00:00
if ( ( var = channel_get_variable ( session , var_event , " iam_fwd_ind_HEX " ) ) ) {
ftdm_usrmsg_add_var ( & usrmsg , " iam_fwd_ind_HEX " , var ) ;
}
2009-01-12 18:05:22 +00:00
2010-11-26 00:19:32 +00:00
if ( ! zstr ( dest ) ) {
ftdm_set_string ( caller_data . dnis . digits , dest ) ;
}
2010-02-01 21:40:01 +00:00
caller_data . dnis . plan = outbound_profile - > destination_number_numplan ;
2008-03-01 00:48:36 +00:00
2010-03-10 20:06:31 +00:00
/* blindly copy data from outbound_profile. They will be overwritten
* by calling ftdm_caller_data if needed after */
caller_data . cid_num . type = outbound_profile - > caller_ton ;
caller_data . cid_num . plan = outbound_profile - > caller_numplan ;
caller_data . rdnis . type = outbound_profile - > rdnis_ton ;
caller_data . rdnis . plan = outbound_profile - > rdnis_numplan ;
2008-01-25 15:05:37 +00:00
2010-01-15 19:22:49 +00:00
ftdm_set_string ( caller_data . cid_name , outbound_profile - > caller_id_name ) ;
2010-03-10 20:06:31 +00:00
ftdm_set_string ( caller_data . cid_num . digits , switch_str_nil ( outbound_profile - > caller_id_number ) ) ;
2010-01-04 15:26:23 +00:00
2011-01-10 21:49:58 +00:00
memset ( & hunting , 0 , sizeof ( hunting ) ) ;
2010-01-04 15:26:23 +00:00
if ( group_id > = 0 ) {
2011-01-10 21:49:58 +00:00
hunting . mode = FTDM_HUNT_GROUP ;
hunting . mode_data . group . group_id = group_id ;
hunting . mode_data . group . direction = direction ;
2010-01-04 15:26:23 +00:00
} else if ( chan_id ) {
2011-01-10 21:49:58 +00:00
hunting . mode = FTDM_HUNT_CHAN ;
hunting . mode_data . chan . span_id = span_id ;
hunting . mode_data . chan . chan_id = chan_id ;
2007-05-31 20:15:16 +00:00
} else {
2011-01-10 21:49:58 +00:00
hunting . mode = FTDM_HUNT_SPAN ;
hunting . mode_data . span . span_id = span_id ;
hunting . mode_data . span . direction = direction ;
2009-09-14 14:26:31 +00:00
}
2008-10-06 19:13:32 +00:00
for ( h = var_event - > headers ; h ; h = h - > next ) {
2010-01-15 19:56:54 +00:00
if ( ! strncasecmp ( h - > name , FREETDM_VAR_PREFIX , FREETDM_VAR_PREFIX_LEN ) ) {
char * v = h - > name + FREETDM_VAR_PREFIX_LEN ;
2009-10-23 16:03:57 +00:00
if ( ! zstr ( v ) ) {
2011-05-17 21:13:38 +00:00
if ( ! strcasecmp ( v , " ss7_iam " ) ) {
/* Do not print the value of ss7_iam as it is very long */
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Adding outbound freetdm variable %s to channel %d:%d \n " , v , span_id , chan_id ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Adding outbound freetdm variable %s=%s to channel %d:%d \n " , v , h - > value , span_id , chan_id ) ;
}
2011-02-25 14:58:15 +00:00
ftdm_usrmsg_add_var ( & usrmsg , v , h - > value ) ;
2008-10-06 19:13:32 +00:00
}
}
}
2011-01-10 21:49:58 +00:00
2010-08-26 17:20:14 +00:00
if ( ( * new_session = switch_core_session_request ( freetdm_endpoint_interface , SWITCH_CALL_DIRECTION_OUTBOUND , flags , pool ) ) ! = 0 ) {
2007-05-26 04:45:31 +00:00
private_t * tech_pvt ;
switch_caller_profile_t * caller_profile ;
2009-01-12 18:05:22 +00:00
2007-05-26 04:45:31 +00:00
switch_core_session_add_stream ( * new_session , NULL ) ;
2011-01-10 21:49:58 +00:00
if ( ! ( tech_pvt = ( private_t * ) switch_core_session_alloc ( * new_session , sizeof ( private_t ) ) ) ) {
2007-05-26 04:45:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Hey where is my memory pool? \n " ) ;
switch_core_session_destroy ( new_session ) ;
2007-05-31 03:04:26 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto fail ;
2007-05-26 04:45:31 +00:00
}
2012-01-27 04:51:21 +00:00
our_chan = switch_core_session_get_channel ( * new_session ) ;
2012-02-16 20:15:22 +00:00
/* Figure out if there is a native bridge requested through SIP x headers */
2012-01-26 16:19:41 +00:00
if ( network_peer_uuid ) {
switch_core_session_t * network_peer = switch_core_session_locate ( network_peer_uuid ) ;
if ( network_peer ) {
2012-01-27 04:51:21 +00:00
const char * my_uuid = switch_core_session_get_uuid ( * new_session ) ;
private_t * peer_private = switch_core_session_get_private ( network_peer ) ;
2012-02-16 20:15:22 +00:00
peer_chan = switch_core_session_get_channel ( network_peer ) ;
2012-01-27 04:51:21 +00:00
switch_set_string ( tech_pvt - > network_peer_uuid , network_peer_uuid ) ;
switch_set_string ( peer_private - > network_peer_uuid , my_uuid ) ;
2012-01-26 16:19:41 +00:00
2012-01-27 04:51:21 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Session %s is network-bridged with %s \n " ,
my_uuid , network_peer_uuid ) ;
2012-01-26 16:19:41 +00:00
2012-01-27 04:51:21 +00:00
snprintf ( sigbridge_peer , sizeof ( sigbridge_peer ) , " %u:%u " ,
ftdm_channel_get_span_id ( peer_private - > ftdmchan ) , ftdm_channel_get_id ( peer_private - > ftdmchan ) ) ;
switch_core_session_rwunlock ( network_peer ) ;
2012-01-26 16:19:41 +00:00
}
2012-02-16 20:15:22 +00:00
/* Figure out if there is a native bridge requested through dial plan variable and the originating channel is also freetdm (not going through SIP) */
} else if ( session
& & ( var = channel_get_variable ( session , var_event , FREETDM_VAR_PREFIX " native_sigbridge " ) )
& & switch_true ( var )
& & switch_core_session_compare ( * new_session , session ) ) {
private_t * peer_pvt = switch_core_session_get_private ( session ) ;
peer_chan = switch_core_session_get_channel ( session ) ;
snprintf ( sigbridge_peer , sizeof ( sigbridge_peer ) , " %u:%u " ,
ftdm_channel_get_span_id ( peer_pvt - > ftdmchan ) , ftdm_channel_get_id ( peer_pvt - > ftdmchan ) ) ;
2012-01-26 16:19:41 +00:00
}
2007-05-31 03:04:26 +00:00
caller_profile = switch_caller_profile_clone ( * new_session , outbound_profile ) ;
2010-03-10 20:06:31 +00:00
caller_profile - > destination_number = switch_core_strdup ( caller_profile - > pool , switch_str_nil ( dest_num ) ) ;
caller_profile - > caller_id_number = switch_core_strdup ( caller_profile - > pool , switch_str_nil ( callerid_num ) ) ;
2007-05-31 20:15:16 +00:00
2011-01-10 21:49:58 +00:00
hunting . result_cb = on_channel_found ;
hunt_data . var_event = var_event ;
hunt_data . new_session = * new_session ;
hunt_data . caller_profile = caller_profile ;
hunt_data . tech_pvt = tech_pvt ;
caller_data . priv = & hunt_data ;
2007-06-11 18:15:09 +00:00
2012-01-27 11:34:36 +00:00
if ( session & & ! zstr ( sigbridge_peer ) ) {
2012-01-27 04:51:21 +00:00
peer_chan = switch_core_session_get_channel ( session ) ;
2012-01-26 21:50:38 +00:00
ftdm_usrmsg_add_var ( & usrmsg , " sigbridge_peer " , sigbridge_peer ) ;
}
2011-02-25 14:58:15 +00:00
if ( ( status = ftdm_call_place_ex ( & caller_data , & hunting , & usrmsg ) ) ! = FTDM_SUCCESS ) {
2007-06-11 18:15:09 +00:00
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
switch_core_session_destroy ( new_session ) ;
2011-01-10 21:49:58 +00:00
if ( status = = FTDM_BREAK | | status = = FTDM_EBUSY ) {
2010-06-16 15:39:42 +00:00
cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION ;
} else {
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2010-06-16 15:19:19 +00:00
}
2012-01-27 04:51:21 +00:00
goto fail ;
}
if ( our_chan & & peer_chan ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO ,
" Bridging native signaling of channel %s to channel %s \n " ,
switch_channel_get_name ( peer_chan ) , switch_channel_get_name ( our_chan ) ) ;
2007-06-11 18:15:09 +00:00
}
2007-05-26 04:45:31 +00:00
return SWITCH_CAUSE_SUCCESS ;
}
2010-04-23 20:28:01 +00:00
fail :
2007-06-14 04:44:44 +00:00
2007-05-31 03:04:26 +00:00
return cause ;
2007-05-26 04:45:31 +00:00
}
2010-12-03 22:52:10 +00:00
static void ftdm_enable_channel_dtmf ( ftdm_channel_t * fchan , switch_channel_t * channel )
{
if ( channel ) {
const char * var ;
if ( ( var = switch_channel_get_variable ( channel , " freetdm_disable_dtmf " ) ) ) {
if ( switch_true ( var ) ) {
ftdm_channel_command ( fchan , FTDM_COMMAND_DISABLE_DTMF_DETECT , NULL ) ;
ftdm_log ( FTDM_LOG_INFO , " DTMF detection disabled in channel %d:%d \n " , ftdm_channel_get_span_id ( fchan ) , ftdm_channel_get_id ( fchan ) ) ;
return ;
}
}
/* the variable is not present or has a negative value then proceed to enable DTMF ... */
}
if ( ftdm_channel_command ( fchan , FTDM_COMMAND_ENABLE_DTMF_DETECT , NULL ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " Failed to enable DTMF detection in channel %d:%d \n " , ftdm_channel_get_span_id ( fchan ) , ftdm_channel_get_id ( fchan ) ) ;
}
}
2010-01-15 19:22:49 +00:00
ftdm_status_t ftdm_channel_from_event ( ftdm_sigmsg_t * sigmsg , switch_core_session_t * * sp )
2007-05-27 14:58:01 +00:00
{
switch_core_session_t * session = NULL ;
private_t * tech_pvt = NULL ;
switch_channel_t * channel = NULL ;
2010-09-01 18:42:34 +00:00
ftdm_iterator_t * iter = NULL ;
2010-09-10 18:01:52 +00:00
ftdm_iterator_t * curr = NULL ;
2010-09-01 18:42:34 +00:00
const char * var_name = NULL ;
const char * var_value = NULL ;
2010-04-21 15:20:05 +00:00
uint32_t spanid , chanid ;
2007-05-27 14:58:01 +00:00
char name [ 128 ] ;
2010-05-21 15:10:15 +00:00
ftdm_caller_data_t * channel_caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2007-06-05 16:57:32 +00:00
2007-05-27 14:58:01 +00:00
* sp = NULL ;
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2010-06-01 15:51:27 +00:00
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
2007-05-27 14:58:01 +00:00
2010-08-26 17:20:14 +00:00
if ( ! ( session = switch_core_session_request ( freetdm_endpoint_interface , SWITCH_CALL_DIRECTION_INBOUND , SOF_NONE , NULL ) ) ) {
2008-05-21 16:49:22 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Initilization Error! \n " ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-27 14:58:01 +00:00
}
2010-12-03 22:52:10 +00:00
/* I guess we always want DTMF detection */
ftdm_enable_channel_dtmf ( sigmsg - > channel , NULL ) ;
2007-05-27 14:58:01 +00:00
switch_core_session_add_stream ( session , NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_alloc ( session , sizeof ( private_t ) ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
2011-05-11 03:35:20 +00:00
if ( tech_init ( tech_pvt , session , sigmsg - > channel , channel_caller_data ) ! = SWITCH_STATUS_SUCCESS ) {
2007-05-27 14:58:01 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Initilization Error! \n " ) ;
switch_core_session_destroy ( & session ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-27 14:58:01 +00:00
}
2010-04-21 15:20:05 +00:00
channel_caller_data - > collected [ 0 ] = ' \0 ' ;
2007-06-05 16:57:32 +00:00
2010-04-21 15:20:05 +00:00
if ( zstr ( channel_caller_data - > cid_name ) ) {
switch_set_string ( channel_caller_data - > cid_name , ftdm_channel_get_name ( sigmsg - > channel ) ) ;
2007-06-05 16:57:32 +00:00
}
2010-04-21 15:20:05 +00:00
if ( zstr ( channel_caller_data - > cid_num . digits ) ) {
if ( ! zstr ( channel_caller_data - > ani . digits ) ) {
switch_set_string ( channel_caller_data - > cid_num . digits , channel_caller_data - > ani . digits ) ;
2007-06-05 16:57:32 +00:00
} else {
2010-04-21 15:20:05 +00:00
switch_set_string ( channel_caller_data - > cid_num . digits , ftdm_channel_get_number ( sigmsg - > channel ) ) ;
2007-06-05 16:57:32 +00:00
}
}
2007-11-17 01:39:28 +00:00
2007-05-27 14:58:01 +00:00
tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
2010-01-15 19:56:54 +00:00
" FreeTDM " ,
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ spanid ] . dialplan ,
channel_caller_data - > cid_name ,
channel_caller_data - > cid_num . digits ,
2007-05-27 14:58:01 +00:00
NULL ,
2010-04-21 15:20:05 +00:00
channel_caller_data - > ani . digits ,
channel_caller_data - > aniII ,
channel_caller_data - > rdnis . digits ,
( char * ) modname ,
SPAN_CONFIG [ spanid ] . context ,
channel_caller_data - > dnis . digits ) ;
2008-03-01 00:48:36 +00:00
2007-05-27 14:58:01 +00:00
assert ( tech_pvt - > caller_profile ! = NULL ) ;
2008-03-01 00:48:36 +00:00
2010-04-21 15:20:05 +00:00
if ( channel_caller_data - > screen = = 1 | | channel_caller_data - > screen = = 3 ) {
2008-03-01 00:48:36 +00:00
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_SCREEN ) ;
}
2010-04-21 15:20:05 +00:00
tech_pvt - > caller_profile - > caller_ton = channel_caller_data - > cid_num . type ;
tech_pvt - > caller_profile - > caller_numplan = channel_caller_data - > cid_num . plan ;
tech_pvt - > caller_profile - > ani_ton = channel_caller_data - > ani . type ;
tech_pvt - > caller_profile - > ani_numplan = channel_caller_data - > ani . plan ;
tech_pvt - > caller_profile - > destination_number_ton = channel_caller_data - > dnis . type ;
tech_pvt - > caller_profile - > destination_number_numplan = channel_caller_data - > dnis . plan ;
tech_pvt - > caller_profile - > rdnis_ton = channel_caller_data - > rdnis . type ;
tech_pvt - > caller_profile - > rdnis_numplan = channel_caller_data - > rdnis . plan ;
2010-04-06 17:39:03 +00:00
2010-04-21 15:20:05 +00:00
if ( channel_caller_data - > pres ) {
2008-03-01 00:48:36 +00:00
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER ) ;
}
2010-04-21 15:20:05 +00:00
snprintf ( name , sizeof ( name ) , " FreeTDM/%u:%u/%s " , spanid , chanid , tech_pvt - > caller_profile - > destination_number ) ;
2008-04-01 21:49:35 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Connect inbound channel %s \n " , name ) ;
2007-05-27 14:58:01 +00:00
switch_channel_set_name ( channel , name ) ;
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
2009-03-12 15:27:29 +00:00
2010-04-21 15:20:05 +00:00
switch_channel_set_variable ( channel , " freetdm_span_name " , ftdm_channel_get_span_name ( sigmsg - > channel ) ) ;
switch_channel_set_variable_printf ( channel , " freetdm_span_number " , " %d " , spanid ) ;
switch_channel_set_variable_printf ( channel , " freetdm_chan_number " , " %d " , chanid ) ;
2010-08-10 22:51:06 +00:00
switch_channel_set_variable_printf ( channel , " freetdm_bearer_capability " , " %d " , channel_caller_data - > bearer_capability ) ;
switch_channel_set_variable_printf ( channel , " freetdm_bearer_layer1 " , " %d " , channel_caller_data - > bearer_layer1 ) ;
2011-05-10 19:56:30 +00:00
switch_channel_set_variable_printf ( channel , " freetdm_calling_party_category " , ftdm_calling_party_category2str ( channel_caller_data - > cpc ) ) ;
2011-02-18 18:01:57 +00:00
switch_channel_set_variable_printf ( channel , " screening_ind " , ftdm_screening2str ( channel_caller_data - > screen ) ) ;
switch_channel_set_variable_printf ( channel , " presentation_ind " , ftdm_presentation2str ( channel_caller_data - > pres ) ) ;
2010-12-09 18:20:05 +00:00
2011-05-10 19:56:30 +00:00
2010-06-17 22:11:22 +00:00
if ( globals . sip_headers ) {
switch_channel_set_variable ( channel , " sip_h_X-FreeTDM-SpanName " , ftdm_channel_get_span_name ( sigmsg - > channel ) ) ;
2012-01-26 16:19:41 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-TransUUID " , " %s " , switch_core_session_get_uuid ( session ) ) ;
2010-06-17 22:11:22 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-SpanNumber " , " %d " , spanid ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-ChanNumber " , " %d " , chanid ) ;
2010-06-29 20:29:37 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-CallerName " , " %s " , channel_caller_data - > cid_name ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-CallerNumber " , " %s " , channel_caller_data - > cid_num . digits ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-ANI " , " %s " , channel_caller_data - > ani . digits ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-ANI-TON " , " %d " , channel_caller_data - > ani . type ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-ANI-Plan " , " %d " , channel_caller_data - > ani . plan ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-ANI2 " , " %s " , channel_caller_data - > aniII ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-DNIS " , " %s " , channel_caller_data - > dnis . digits ) ;
2011-02-02 16:35:38 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-DNIS-TON " , " %d " , channel_caller_data - > dnis . type ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-DNIS-Plan " , " %d " , channel_caller_data - > dnis . plan ) ;
2010-06-29 20:29:37 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDNIS " , " %s " , channel_caller_data - > rdnis . digits ) ;
2011-04-26 18:52:53 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDNIS-NADI " , " %d " , channel_caller_data - > rdnis . type ) ;
2010-06-29 20:29:37 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDNIS-Plan " , " %d " , channel_caller_data - > rdnis . plan ) ;
2011-05-17 21:13:38 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-CPC " , " %s " , ftdm_calling_party_category2str ( channel_caller_data - > cpc ) ) ;
2011-12-06 20:38:05 +00:00
2012-05-17 21:56:50 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_access_transport_urlenc " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2012-05-18 13:57:51 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-Access-Transport-URLENC " , " %s " , var_value ) ;
2012-05-17 21:56:50 +00:00
}
2011-12-06 20:38:05 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_rdinfo_indicator " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDINF-Indicator " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_rdinfo_orig " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDINF-OrigReason " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_rdinfo_count " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDINF-Count " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_rdinfo_reason " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDINF-Reason " , " %s " , var_value ) ;
}
2011-10-24 17:21:15 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_clg_nadi " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 17:53:32 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-NADI " , " %s " , var_value ) ;
2011-12-05 21:58:26 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-ANI-NADI " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_cld_nadi " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-DNIS-NADI " , " %s " , var_value ) ;
2011-10-24 17:21:15 +00:00
}
2011-10-12 21:44:52 +00:00
2011-04-26 18:52:53 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_rdnis_screen_ind " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-14 21:42:23 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDNIS-Screen " , " %s " , var_value ) ;
2011-04-26 18:52:53 +00:00
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_rdnis_pres_ind " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-17 20:43:40 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-RDNIS-Presentation " , " %s " , var_value ) ;
2011-04-26 18:52:53 +00:00
}
2011-05-06 21:52:41 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_gn_digits " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 22:32:02 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-GN " , " %s " , var_value ) ;
2011-05-06 21:52:41 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_gn_numqual " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 22:32:02 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-GN-NumQual " , " %s " , var_value ) ;
2011-05-06 21:52:41 +00:00
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_gn_nadi " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 22:32:02 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-GN-NADI " , " %s " , var_value ) ;
2011-05-06 21:52:41 +00:00
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_gn_screen_ind " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 22:32:02 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-GN-Screen " , " %s " , var_value ) ;
2011-05-06 21:52:41 +00:00
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_gn_pres_ind " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 22:32:02 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-GN-Presentation " , " %s " , var_value ) ;
2011-05-06 21:52:41 +00:00
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_gn_npi " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 22:32:02 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-GN-Plan " , " %s " , var_value ) ;
2011-05-06 21:52:41 +00:00
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_gn_num_inc_ind " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-11-07 22:32:02 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-GN-NumInComp " , " %s " , var_value ) ;
2011-05-06 21:52:41 +00:00
}
} /* End - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_digits"); */
2011-05-17 21:13:38 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_iam " ) ;
2011-05-10 15:38:23 +00:00
if ( ! ftdm_strlen_zero ( var_value ) ) {
2011-05-17 21:13:38 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-IAM " , " %s " , var_value ) ;
2011-05-10 15:38:23 +00:00
}
2011-08-26 21:49:34 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_cic " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-CIC " , " %s " , var_value ) ;
}
2010-06-29 20:29:37 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-Screen " , " %d " , channel_caller_data - > screen ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-Presentation " , " %d " , channel_caller_data - > pres ) ;
2011-11-07 21:37:11 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_callref " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-CallReference " , " %s " , var_value ) ;
}
2011-09-30 17:09:13 +00:00
2011-09-30 14:25:21 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_opc " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-OPC " , " %s " , var_value ) ;
}
2011-10-12 21:44:52 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_loc_digits " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-LOC " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_loc_screen_ind " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-LOC-Screen " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_loc_pres_ind " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-LOC-Presentation " , " %s " , var_value ) ;
}
2011-11-15 23:26:13 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_loc_nadi " ) ;
2011-10-12 21:44:52 +00:00
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-LOC-NADI " , " %s " , var_value ) ;
}
2012-02-16 20:14:06 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_ocn " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-OCN " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_ocn_nadi " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-OCN-NADI " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_ocn_plan " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-OCN-Plan " , " %s " , var_value ) ;
}
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_ocn_pres " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-OCN-Presentation " , " %s " , var_value ) ;
}
2010-06-17 22:11:22 +00:00
}
2011-02-28 17:47:27 +00:00
2010-12-09 18:20:05 +00:00
/* Add any call variable to the dial plan */
2011-02-25 14:58:15 +00:00
iter = ftdm_sigmsg_get_var_iterator ( sigmsg , iter ) ;
2010-12-09 18:20:05 +00:00
for ( curr = iter ; curr ; curr = ftdm_iterator_next ( curr ) ) {
2011-02-25 14:58:15 +00:00
ftdm_get_current_var ( curr , & var_name , & var_value ) ;
2010-12-09 18:20:05 +00:00
snprintf ( name , sizeof ( name ) , FREETDM_VAR_PREFIX " %s " , var_name ) ;
switch_channel_set_variable_printf ( channel , name , " %s " , var_value ) ;
2011-05-17 21:13:38 +00:00
if ( ! strcasecmp ( var_name , " ss7_iam " ) ) {
/* Do not print freetdm_ss7_iam as it is a very long variable */
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Call Variable: %s is present \n " , name ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Call Variable: %s = %s \n " , name , var_value ) ;
}
2010-09-01 18:42:34 +00:00
}
2010-09-10 18:01:52 +00:00
ftdm_iterator_free ( iter ) ;
2010-12-09 18:20:05 +00:00
2007-05-27 14:58:01 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
if ( switch_core_session_thread_launch ( session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error spawning thread \n " ) ;
switch_core_session_destroy ( & session ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-27 14:58:01 +00:00
}
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_add_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) , 0 ) ! = FTDM_SUCCESS ) {
2008-05-21 16:49:22 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error adding token \n " ) ;
2007-05-27 18:14:49 +00:00
switch_core_session_destroy ( & session ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-27 18:14:49 +00:00
}
2007-05-27 14:58:01 +00:00
* sp = session ;
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-27 14:58:01 +00:00
}
2010-03-10 20:06:31 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_common_signal )
{
2010-04-21 15:20:05 +00:00
uint32_t chanid , spanid ;
2011-05-26 15:38:24 +00:00
switch_event_t * event = NULL ;
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE ;
2010-04-21 15:20:05 +00:00
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2011-05-26 15:38:24 +00:00
2010-03-10 20:06:31 +00:00
switch ( sigmsg - > event_id ) {
case FTDM_SIGEVENT_ALARM_CLEAR :
case FTDM_SIGEVENT_ALARM_TRAP :
{
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_get_alarms ( sigmsg - > channel , & alarmbits ) ! = FTDM_SUCCESS ) {
2010-03-10 20:06:31 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failed to retrieve alarms \n " ) ;
return FTDM_FAIL ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_TRAP ) ! = SWITCH_STATUS_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " failed to create alarms events \n " ) ;
return FTDM_FAIL ;
}
if ( sigmsg - > event_id = = FTDM_SIGEVENT_ALARM_CLEAR ) {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_NOTICE , " Alarm cleared on channel %d:%d \n " , spanid , chanid ) ;
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " condition " , " ftdm-alarm-clear " ) ;
} else {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_NOTICE , " Alarm raised on channel %d:%d \n " , spanid , chanid ) ;
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " condition " , " ftdm-alarm-trap " ) ;
}
}
break ;
2010-07-28 15:35:39 +00:00
case FTDM_SIGEVENT_UP :
{
/* clear any rate limit resource for this span */
char spanresource [ 512 ] ;
if ( SPAN_CONFIG [ spanid ] . limit_reset_event = = FTDM_LIMIT_RESET_ON_ANSWER & & SPAN_CONFIG [ spanid ] . limit_calls ) {
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
snprintf ( spanresource , sizeof ( spanresource ) , " span_%s_%s " , ftdm_channel_get_span_name ( sigmsg - > channel ) , caller_data - > dnis . digits ) ;
ftdm_log ( FTDM_LOG_DEBUG , " Clearing rate limit resource on channel %d:%d (%s/%s) \n " , spanid , chanid , FREETDM_LIMIT_REALM , spanresource ) ;
switch_limit_interval_reset ( " hash " , FREETDM_LIMIT_REALM , spanresource ) ;
}
return FTDM_SUCCESS ;
}
2011-05-26 15:38:24 +00:00
case FTDM_SIGEVENT_TRANSFER_COMPLETED :
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
2010-12-31 18:44:20 +00:00
2011-05-26 15:38:24 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_TRANSFER ) ;
switch_channel_set_variable ( channel , " freetdm_transfer_response " , ftdm_transfer_response2str ( sigmsg - > ev_data . transfer_completed . response ) ) ;
switch_core_session_rwunlock ( session ) ;
}
return FTDM_SUCCESS ;
}
break ;
case FTDM_SIGEVENT_RELEASED :
2010-12-31 18:44:20 +00:00
case FTDM_SIGEVENT_INDICATION_COMPLETED :
2011-01-10 21:49:58 +00:00
case FTDM_SIGEVENT_DIALING :
2011-05-26 15:38:24 +00:00
{
2010-12-31 18:44:20 +00:00
/* Swallow these events */
return FTDM_BREAK ;
2011-05-26 15:38:24 +00:00
}
break ;
case FTDM_SIGEVENT_STOP :
case FTDM_SIGEVENT_RESTART :
{
switch_core_session_t * session = NULL ;
private_t * tech_pvt = NULL ;
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
tech_pvt = switch_core_session_get_private ( session ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_TRANSFER ) ;
switch_core_session_rwunlock ( session ) ;
return FTDM_SUCCESS ;
}
}
2010-12-31 18:44:20 +00:00
break ;
2010-03-10 20:06:31 +00:00
default :
return FTDM_SUCCESS ;
break ;
}
2011-06-07 13:54:50 +00:00
if ( event ) {
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " span-name " , " %s " , ftdm_channel_get_span_name ( sigmsg - > channel ) ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " span-number " , " %d " , ftdm_channel_get_span_id ( sigmsg - > channel ) ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " chan-number " , " %d " , ftdm_channel_get_id ( sigmsg - > channel ) ) ;
2010-03-10 20:06:31 +00:00
2011-06-07 13:54:50 +00:00
if ( alarmbits & FTDM_ALARM_RED ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " red " ) ;
}
if ( alarmbits & FTDM_ALARM_YELLOW ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " yellow " ) ;
}
if ( alarmbits & FTDM_ALARM_RAI ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " rai " ) ;
}
if ( alarmbits & FTDM_ALARM_BLUE ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " blue " ) ;
}
if ( alarmbits & FTDM_ALARM_AIS ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " ais " ) ;
}
if ( alarmbits & FTDM_ALARM_GENERAL ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " general " ) ;
}
switch_event_fire ( & event ) ;
2010-03-10 20:06:31 +00:00
}
return FTDM_BREAK ;
}
2007-05-27 18:14:49 +00:00
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_fxo_signal )
2007-05-26 04:45:31 +00:00
{
2007-05-31 20:15:16 +00:00
switch_core_session_t * session = NULL ;
2007-06-01 00:31:50 +00:00
switch_channel_t * channel = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status ;
2010-04-21 15:20:05 +00:00
uint32_t spanid ;
uint32_t chanid ;
2010-12-09 18:20:05 +00:00
ftdm_caller_data_t * caller_data ;
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
2010-12-09 18:20:05 +00:00
caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2007-05-31 20:15:16 +00:00
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got FXO sig %d:%d [%s] \n " , spanid , chanid , ftdm_signal_event2str ( sigmsg - > event_id ) ) ;
2007-05-31 20:15:16 +00:00
switch ( sigmsg - > event_id ) {
2007-11-17 01:39:28 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS_MEDIA :
2007-11-17 01:39:28 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-11-17 01:39:28 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_pre_answered ( channel ) ;
2009-09-01 00:49:10 +00:00
switch_core_session_rwunlock ( session ) ;
2007-11-17 01:39:28 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
2007-11-17 01:39:28 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , 0 ) ;
2007-11-17 01:39:28 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-12-09 18:20:05 +00:00
switch_channel_hangup ( channel , caller_data - > hangup_cause ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-11-17 01:39:28 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2007-06-01 00:31:50 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-06-01 00:31:50 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-23 19:52:11 +00:00
ftdm_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2007-06-01 00:31:50 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2007-05-31 20:15:16 +00:00
{
2010-01-15 19:22:49 +00:00
status = ftdm_channel_from_event ( sigmsg , & session ) ;
if ( status ! = FTDM_SUCCESS ) {
2010-04-21 15:20:05 +00:00
ftdm_channel_call_hangup ( sigmsg - > channel ) ;
2007-05-31 20:15:16 +00:00
}
}
break ;
2010-12-20 21:15:41 +00:00
case FTDM_SIGEVENT_SIGSTATUS_CHANGED : { /* twiddle */ } break ;
2010-12-09 18:20:05 +00:00
2008-01-08 23:33:07 +00:00
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
sigmsg - > event_id , spanid , chanid ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_fxs_signal )
2007-05-26 04:45:31 +00:00
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status = FTDM_SUCCESS ;
2010-04-21 15:20:05 +00:00
uint32_t chanid , spanid , tokencount ;
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
tokencount = ftdm_channel_get_token_count ( sigmsg - > channel ) ;
2007-05-27 14:58:01 +00:00
2010-05-20 15:43:40 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got FXS sig [%s] \n " , ftdm_signal_event2str ( sigmsg - > event_id ) ) ;
2007-05-26 04:45:31 +00:00
2007-05-27 14:58:01 +00:00
switch ( sigmsg - > event_id ) {
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2007-05-31 20:15:16 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-05-31 20:15:16 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-23 19:52:11 +00:00
ftdm_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2007-05-31 20:15:16 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS :
2008-09-11 17:55:27 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2008-09-11 17:55:27 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2007-05-27 14:58:01 +00:00
{
2010-01-15 19:22:49 +00:00
status = ftdm_channel_from_event ( sigmsg , & session ) ;
if ( status ! = FTDM_SUCCESS ) {
2010-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( sigmsg - > channel , FTDM_CHANNEL_INDICATE_BUSY ) ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
break ;
2010-12-09 18:20:05 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
2007-05-27 14:58:01 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2008-01-10 00:47:04 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING ;
2010-04-21 15:20:05 +00:00
if ( tokencount ) {
2010-05-17 23:03:32 +00:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2008-01-10 00:47:04 +00:00
switch_core_session_t * session_a , * session_b , * session_t = NULL ;
switch_channel_t * channel_a = NULL , * channel_b = NULL ;
2010-05-17 23:03:32 +00:00
int digits = ! zstr ( caller_data - > collected ) ;
2008-01-10 00:47:04 +00:00
const char * br_a_uuid = NULL , * br_b_uuid = NULL ;
private_t * tech_pvt = NULL ;
2010-04-21 15:20:05 +00:00
if ( ( session_a = switch_core_session_locate ( ftdm_channel_get_token ( sigmsg - > channel , 0 ) ) ) ) {
2008-01-10 00:47:04 +00:00
channel_a = switch_core_session_get_channel ( session_a ) ;
br_a_uuid = switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ;
tech_pvt = switch_core_session_get_private ( session_a ) ;
2008-05-01 16:41:10 +00:00
stop_hold ( session_a , switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-10 00:47:04 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
2010-04-21 15:20:05 +00:00
if ( ( session_b = switch_core_session_locate ( ftdm_channel_get_token ( sigmsg - > channel , 1 ) ) ) ) {
2008-01-10 00:47:04 +00:00
channel_b = switch_core_session_get_channel ( session_b ) ;
br_b_uuid = switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ;
tech_pvt = switch_core_session_get_private ( session_b ) ;
2008-05-01 16:41:10 +00:00
stop_hold ( session_a , switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-10 00:47:04 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
2010-12-16 02:59:33 +00:00
if ( channel_a & & channel_b & & switch_channel_direction ( channel_a ) = = SWITCH_CALL_DIRECTION_INBOUND & &
switch_channel_direction ( channel_b ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2008-01-10 00:47:04 +00:00
cause = SWITCH_CAUSE_ATTENDED_TRANSFER ;
if ( br_a_uuid & & br_b_uuid ) {
switch_ivr_uuid_bridge ( br_a_uuid , br_b_uuid ) ;
} else if ( br_a_uuid & & digits ) {
session_t = switch_core_session_locate ( br_a_uuid ) ;
} else if ( br_b_uuid & & digits ) {
session_t = switch_core_session_locate ( br_b_uuid ) ;
}
}
if ( session_t ) {
2010-05-17 23:03:32 +00:00
switch_ivr_session_transfer ( session_t , caller_data - > collected , NULL , NULL ) ;
2008-01-10 00:47:04 +00:00
switch_core_session_rwunlock ( session_t ) ;
}
if ( session_a ) {
switch_core_session_rwunlock ( session_a ) ;
}
if ( session_b ) {
switch_core_session_rwunlock ( session_b ) ;
}
}
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-05-27 18:14:49 +00:00
channel = switch_core_session_get_channel ( session ) ;
2008-01-10 00:47:04 +00:00
switch_channel_hangup ( channel , cause ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-05-27 18:14:49 +00:00
switch_core_session_rwunlock ( session ) ;
2007-05-27 14:58:01 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , NULL ) ;
2008-01-10 00:47:04 +00:00
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
break ;
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_ADD_CALL :
2008-01-10 00:47:04 +00:00
{
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_FLASH :
2007-05-27 18:14:49 +00:00
{
2010-05-20 15:43:40 +00:00
chan_pvt_t * chanpvt = ftdm_channel_get_private ( sigmsg - > channel ) ;
if ( ! chanpvt ) {
ftdm_log ( FTDM_LOG_ERROR , " %d:%d has no private data, can't handle FXS features! (this is a bug) \n " ,
chanid , spanid ) ;
break ;
}
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_call_check_hold ( sigmsg - > channel ) & & tokencount = = 1 ) {
2008-05-01 16:41:10 +00:00
switch_core_session_t * session ;
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2008-05-01 16:41:10 +00:00
const char * buuid ;
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2010-04-21 15:20:05 +00:00
ftdm_channel_call_unhold ( sigmsg - > channel ) ;
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
switch_core_session_rwunlock ( session ) ;
}
2010-04-21 15:20:05 +00:00
} else if ( tokencount = = 2 & & ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_3WAY ) ) {
2010-05-20 15:43:40 +00:00
if ( switch_test_flag ( chanpvt , ANALOG_OPTION_3WAY ) ) {
switch_clear_flag ( chanpvt , ANALOG_OPTION_3WAY ) ;
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 1 ) ) ) {
2008-01-10 00:47:04 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2008-01-10 00:47:04 +00:00
switch_core_session_rwunlock ( session ) ;
}
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
} else {
char * cmd ;
2010-05-20 15:43:40 +00:00
cmd = switch_mprintf ( " three_way::%s " , ftdm_channel_get_token ( sigmsg - > channel , 0 ) ) ;
switch_set_flag ( chanpvt , ANALOG_OPTION_3WAY ) ;
2008-01-10 00:47:04 +00:00
cycle_foreground ( sigmsg - > channel , 1 , cmd ) ;
free ( cmd ) ;
}
2008-01-25 16:42:06 +00:00
} else if ( ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_CALL_SWAP )
| | ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_3WAY )
) {
2008-01-10 00:47:04 +00:00
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
2010-04-21 15:20:05 +00:00
if ( tokencount = = 1 ) {
ftdm_channel_call_hold ( sigmsg - > channel ) ;
2008-01-10 00:47:04 +00:00
}
}
2007-05-27 18:14:49 +00:00
}
break ;
2007-11-24 18:04:14 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_COLLECTED_DIGIT :
2007-11-24 18:04:14 +00:00
{
2010-05-17 23:03:32 +00:00
int span_id = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2010-12-20 19:06:54 +00:00
char * dtmf = sigmsg - > ev_data . collected . digits ;
2010-05-17 23:03:32 +00:00
char * regex = SPAN_CONFIG [ span_id ] . dial_regex ;
char * fail_regex = SPAN_CONFIG [ span_id ] . fail_dial_regex ;
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2007-11-24 18:04:14 +00:00
2009-10-23 16:03:57 +00:00
if ( zstr ( regex ) ) {
2007-11-24 18:04:14 +00:00
regex = NULL ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( fail_regex ) ) {
2007-11-24 18:04:14 +00:00
fail_regex = NULL ;
}
2008-02-18 16:15:24 +00:00
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got DTMF sig [%s] \n " , dtmf ) ;
2010-05-17 23:03:32 +00:00
switch_set_string ( caller_data - > collected , dtmf ) ;
2008-01-10 00:47:04 +00:00
2009-10-23 16:03:57 +00:00
if ( ( regex | | fail_regex ) & & ! zstr ( dtmf ) ) {
2007-11-24 18:04:14 +00:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
match = switch_regex_perform ( dtmf , fail_regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_SUCCESS : FTDM_BREAK ;
2007-11-24 18:04:14 +00:00
switch_regex_safe_free ( re ) ;
2010-05-17 23:03:32 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " DTMF [%s] vs fail regex %s %s \n " , dtmf , fail_regex , match ? " matched " : " did not match " ) ;
2007-11-24 18:04:14 +00:00
}
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_SUCCESS & & regex ) {
2007-11-24 18:04:14 +00:00
match = switch_regex_perform ( dtmf , regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_BREAK : FTDM_SUCCESS ;
2010-05-17 23:03:32 +00:00
switch_regex_safe_free ( re ) ;
ftdm_log ( FTDM_LOG_DEBUG , " DTMF [%s] vs dial regex %s %s \n " , dtmf , regex , match ? " matched " : " did not match " ) ;
2007-11-24 18:04:14 +00:00
}
2010-05-17 23:03:32 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " returning %s to COLLECT event with DTMF %s \n " , status = = FTDM_SUCCESS ? " success " : " break " , dtmf ) ;
2007-11-24 18:04:14 +00:00
}
}
break ;
2008-01-08 23:33:07 +00:00
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
sigmsg - > event_id , spanid , chanid ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
2007-05-27 14:58:01 +00:00
return status ;
2007-05-26 04:45:31 +00:00
}
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_r2_signal )
2009-08-19 21:47:56 +00:00
{
2010-04-21 15:20:05 +00:00
uint32_t phyid , chanid , spanid ;
2009-08-19 21:47:56 +00:00
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status = FTDM_SUCCESS ;
2010-05-21 15:10:15 +00:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2010-04-21 15:20:05 +00:00
phyid = ftdm_channel_get_ph_id ( sigmsg - > channel ) ;
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2009-08-19 21:47:56 +00:00
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Got R2 channel sig [%s] in channel %d \n " , ftdm_signal_event2str ( sigmsg - > event_id ) , phyid ) ;
2009-08-19 21:47:56 +00:00
2010-03-10 20:06:31 +00:00
if ( on_common_signal ( sigmsg ) = = FTDM_BREAK ) {
return FTDM_SUCCESS ;
}
2009-08-19 21:47:56 +00:00
switch ( sigmsg - > event_id ) {
/* on_call_disconnect from the R2 side */
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
2009-08-19 21:47:56 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-04-21 15:20:05 +00:00
switch_channel_hangup ( channel , caller_data - > hangup_cause ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2009-08-19 21:47:56 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
/* on_call_offered from the R2 side */
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2009-08-19 21:47:56 +00:00
{
2010-01-15 19:22:49 +00:00
status = ftdm_channel_from_event ( sigmsg , & session ) ;
2009-08-19 21:47:56 +00:00
}
break ;
2010-11-23 16:43:52 +00:00
2010-01-15 19:22:49 +00:00
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
case FTDM_SIGEVENT_COLLECTED_DIGIT :
2009-08-19 21:47:56 +00:00
{
2010-05-17 23:03:32 +00:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
int span_id = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
char * regex = SPAN_CONFIG [ span_id ] . dial_regex ;
char * fail_regex = SPAN_CONFIG [ span_id ] . fail_dial_regex ;
2009-08-19 21:47:56 +00:00
2009-10-23 16:03:57 +00:00
if ( zstr ( regex ) ) {
2009-08-19 21:47:56 +00:00
regex = NULL ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( fail_regex ) ) {
2009-08-19 21:47:56 +00:00
fail_regex = NULL ;
}
2010-05-17 23:03:32 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " R2 DNIS so far [%s] \n " , caller_data - > dnis . digits ) ;
2009-08-19 21:47:56 +00:00
2010-05-17 23:03:32 +00:00
if ( ( regex | | fail_regex ) & & ! zstr ( caller_data - > dnis . digits ) ) {
2009-08-19 21:47:56 +00:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
2010-05-17 23:03:32 +00:00
match = switch_regex_perform ( caller_data - > dnis . digits , fail_regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_SUCCESS : FTDM_BREAK ;
2009-08-19 21:47:56 +00:00
switch_regex_safe_free ( re ) ;
}
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_SUCCESS & & regex ) {
2010-05-17 23:03:32 +00:00
match = switch_regex_perform ( caller_data - > dnis . digits , regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_BREAK : FTDM_SUCCESS ;
2009-08-19 21:47:56 +00:00
}
switch_regex_safe_free ( re ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS :
2009-08-19 21:47:56 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-12-08 16:57:24 +00:00
case FTDM_SIGEVENT_PROGRESS_MEDIA :
{
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_pre_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2009-08-19 21:47:56 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-23 19:52:11 +00:00
ftdm_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2009-08-19 21:47:56 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-11-23 16:55:59 +00:00
case FTDM_SIGEVENT_SIGSTATUS_CHANGED :
{
2010-12-19 20:09:50 +00:00
ftdm_signaling_status_t sigstatus = sigmsg - > ev_data . sigstatus . status ;
2010-11-23 16:55:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " %d:%d signalling changed to: %s \n " ,
spanid , chanid , ftdm_signaling_status2str ( sigstatus ) ) ;
}
break ;
2010-12-03 22:52:10 +00:00
case FTDM_SIGEVENT_PROCEED : { } break ;
2010-12-29 18:38:43 +00:00
case FTDM_SIGEVENT_INDICATION_COMPLETED : { } break ;
2010-12-03 22:52:10 +00:00
2009-08-19 21:47:56 +00:00
default :
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled event %d from R2 for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
sigmsg - > event_id , spanid , chanid ) ;
2009-08-19 21:47:56 +00:00
}
break ;
}
return status ;
}
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_clear_channel_signal )
2007-06-13 03:37:55 +00:00
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2010-04-21 15:20:05 +00:00
ftdm_caller_data_t * caller_data ;
uint32_t spanid , chanid ;
2007-06-13 03:37:55 +00:00
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got clear channel sig [%s] \n " , ftdm_signal_event2str ( sigmsg - > event_id ) ) ;
2007-06-13 03:37:55 +00:00
2010-05-21 15:10:15 +00:00
caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2010-04-21 15:20:05 +00:00
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2010-03-10 20:06:31 +00:00
if ( on_common_signal ( sigmsg ) = = FTDM_BREAK ) {
return FTDM_SUCCESS ;
}
2007-06-13 03:37:55 +00:00
switch ( sigmsg - > event_id ) {
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2007-06-13 03:37:55 +00:00
{
2010-01-15 19:22:49 +00:00
return ftdm_channel_from_event ( sigmsg , & session ) ;
2007-06-13 03:37:55 +00:00
}
break ;
2010-11-23 16:43:52 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
case FTDM_SIGEVENT_RESTART :
2009-09-06 14:07:06 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-06-13 03:37:55 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-04-21 15:20:05 +00:00
switch_channel_hangup ( channel , caller_data - > hangup_cause ) ;
2007-06-13 03:37:55 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2007-06-13 03:37:55 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-06-13 03:37:55 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-23 19:52:11 +00:00
ftdm_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2007-06-13 03:37:55 +00:00
switch_core_session_rwunlock ( session ) ;
2009-09-06 14:07:06 +00:00
} else {
2010-01-15 19:22:49 +00:00
const char * uuid = ftdm_channel_get_uuid ( sigmsg - > channel , 0 ) ;
2009-09-06 14:43:58 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
2010-04-21 15:20:05 +00:00
spanid , chanid , ( uuid ) ? uuid : " N/A " ) ;
2007-06-13 03:37:55 +00:00
}
}
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS_MEDIA :
2007-06-16 04:39:15 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-06-16 04:39:15 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_pre_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
2009-09-06 14:07:06 +00:00
} else {
2010-01-15 19:22:49 +00:00
const char * uuid = ftdm_channel_get_uuid ( sigmsg - > channel , 0 ) ;
2009-09-06 14:43:58 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
2010-04-21 15:20:05 +00:00
spanid , chanid , ( uuid ) ? uuid : " N/A " ) ;
2007-06-16 04:39:15 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS :
2010-12-15 16:45:50 +00:00
case FTDM_SIGEVENT_RINGING :
2007-06-16 04:39:15 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-06-16 04:39:15 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
2009-09-06 14:07:06 +00:00
} else {
2010-01-15 19:22:49 +00:00
const char * uuid = ftdm_channel_get_uuid ( sigmsg - > channel , 0 ) ;
2009-09-06 14:43:58 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
2010-04-21 15:20:05 +00:00
spanid , chanid , ( uuid ) ? uuid : " N/A " ) ;
2007-06-16 04:39:15 +00:00
}
}
2010-11-25 01:04:43 +00:00
break ;
2010-04-23 21:34:57 +00:00
case FTDM_SIGEVENT_SIGSTATUS_CHANGED :
2010-08-31 23:05:37 +00:00
{
2010-12-20 19:06:54 +00:00
ftdm_signaling_status_t sigstatus = sigmsg - > ev_data . sigstatus . status ;
2010-04-27 22:20:25 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " %d:%d signalling changed to :%s \n " ,
2010-08-31 23:05:37 +00:00
spanid , chanid , ftdm_signaling_status2str ( sigstatus ) ) ;
2010-04-23 21:34:57 +00:00
}
break ;
2010-11-25 01:04:43 +00:00
case FTDM_SIGEVENT_PROCEED :
2010-12-09 18:20:05 +00:00
case FTDM_SIGEVENT_FACILITY :
2011-05-26 15:38:24 +00:00
case FTDM_SIGEVENT_TRANSFER_COMPLETED :
2010-11-25 01:04:43 +00:00
/* FS does not have handlers for these messages, so ignore them for now */
break ;
2008-01-08 23:33:07 +00:00
default :
{
2009-09-22 16:21:32 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
sigmsg - > event_id , spanid , chanid ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-06-13 03:37:55 +00:00
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-06-13 03:37:55 +00:00
}
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_analog_signal )
2007-05-27 14:58:01 +00:00
{
2010-04-21 15:20:05 +00:00
uint32_t spanid , chanid ;
ftdm_chan_type_t type ;
2008-01-08 23:33:07 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-09-06 14:07:06 +00:00
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
chanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
type = ftdm_channel_get_type ( sigmsg - > channel ) ;
2010-03-10 20:06:31 +00:00
if ( on_common_signal ( sigmsg ) = = FTDM_BREAK ) {
return FTDM_SUCCESS ;
}
2010-04-21 15:20:05 +00:00
switch ( type ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXO :
case FTDM_CHAN_TYPE_EM :
2007-05-27 14:58:01 +00:00
{
2007-11-24 18:04:14 +00:00
status = on_fxo_signal ( sigmsg ) ;
2007-05-27 14:58:01 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXS :
2007-05-27 14:58:01 +00:00
{
2007-11-24 18:04:14 +00:00
status = on_fxs_signal ( sigmsg ) ;
2007-05-27 14:58:01 +00:00
}
break ;
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled analog channel type %d for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
type , spanid , chanid ) ;
2007-05-27 14:58:01 +00:00
}
break ;
}
2007-06-01 15:40:12 +00:00
2007-11-24 18:04:14 +00:00
return status ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
static void ftdm_logger ( const char * file , const char * func , int line , int level , const char * fmt , . . . )
2007-05-26 04:45:31 +00:00
{
char * data = NULL ;
va_list ap ;
va_start ( ap , fmt ) ;
if ( switch_vasprintf ( & data , fmt , ap ) ! = - 1 ) {
2008-11-03 20:46:43 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , ( char * ) func , line , NULL , level , " %s " , data ) ;
2007-05-26 04:45:31 +00:00
}
2010-09-08 23:41:34 +00:00
if ( data ) free ( data ) ;
2007-05-26 04:45:31 +00:00
va_end ( ap ) ;
}
2008-01-25 16:42:06 +00:00
static uint32_t enable_analog_option ( const char * str , uint32_t current_options )
{
if ( ! strcasecmp ( str , " 3-way " ) ) {
current_options | = ANALOG_OPTION_3WAY ;
current_options & = ~ ANALOG_OPTION_CALL_SWAP ;
} else if ( ! strcasecmp ( str , " call-swap " ) ) {
current_options | = ANALOG_OPTION_CALL_SWAP ;
current_options & = ~ ANALOG_OPTION_3WAY ;
}
return current_options ;
}
2011-06-14 13:47:46 +00:00
# define CONFIG_ERROR(...) { \
2011-06-01 19:24:09 +00:00
ftdm_log ( FTDM_LOG_ERROR , __VA_ARGS__ ) ; \
globals . config_error = 1 ; \
2011-06-14 13:47:46 +00:00
}
2010-04-14 21:59:39 +00:00
/* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list
* last 2 args are for limited aka dumb recursivity
* */
static int add_config_list_nodes ( switch_xml_t swnode , ftdm_conf_node_t * rootnode ,
const char * list_name , const char * list_element_name ,
const char * sub_list_name , const char * sub_list_element_name )
{
char * var , * val ;
switch_xml_t list ;
switch_xml_t element ;
switch_xml_t param ;
ftdm_conf_node_t * n_list ;
ftdm_conf_node_t * n_element ;
list = switch_xml_child ( swnode , list_name ) ;
if ( ! list ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " no list %s found \n " , list_name ) ;
return - 1 ;
}
if ( ( FTDM_SUCCESS ! = ftdm_conf_node_create ( list_name , & n_list , rootnode ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to create %s node \n " , list_name ) ;
return - 1 ;
}
for ( element = switch_xml_child ( list , list_element_name ) ; element ; element = element - > next ) {
char * element_name = ( char * ) switch_xml_attr ( element , " name " ) ;
if ( ! element_name ) {
continue ;
}
if ( ( FTDM_SUCCESS ! = ftdm_conf_node_create ( list_element_name , & n_element , n_list ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to create %s node for %s \n " , list_element_name , element_name ) ;
return - 1 ;
}
ftdm_conf_node_add_param ( n_element , " name " , element_name ) ;
for ( param = switch_xml_child ( element , " param " ) ; param ; param = param - > next ) {
var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
ftdm_conf_node_add_param ( n_element , var , val ) ;
}
if ( sub_list_name & & sub_list_element_name ) {
if ( add_config_list_nodes ( element , n_element , sub_list_name , sub_list_element_name , NULL , NULL ) ) {
return - 1 ;
}
}
}
return 0 ;
}
2010-04-14 15:00:17 +00:00
static ftdm_conf_node_t * get_ss7_config_node ( switch_xml_t cfg , const char * confname )
{
2010-11-26 20:59:24 +00:00
switch_xml_t signode , ss7configs , isup , gen , param ;
ftdm_conf_node_t * rootnode , * list ;
char * var , * val ;
2010-04-14 21:59:39 +00:00
/* try to find the conf in the hash first */
rootnode = switch_core_hash_find ( globals . ss7_configs , confname ) ;
if ( rootnode ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " ss7 config %s was found in the hash already \n " , confname ) ;
return rootnode ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " not found %s config in hash, searching in xml ... \n " , confname ) ;
signode = switch_xml_child ( cfg , " signaling_configs " ) ;
if ( ! signode ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " not found 'signaling_configs' XML config section \n " ) ;
return NULL ;
}
ss7configs = switch_xml_child ( signode , " sngss7_configs " ) ;
if ( ! ss7configs ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " not found 'sngss7_configs' XML config section \n " ) ;
return NULL ;
}
/* search the isup config */
for ( isup = switch_xml_child ( ss7configs , " sng_isup " ) ; isup ; isup = isup - > next ) {
char * name = ( char * ) switch_xml_attr ( isup , " name " ) ;
if ( ! name ) {
continue ;
}
if ( ! strcasecmp ( name , confname ) ) {
break ;
}
}
if ( ! isup ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " not found '%s' sng_isup XML config section \n " , confname ) ;
return NULL ;
}
/* found our XML chunk, create the root node */
if ( ( FTDM_SUCCESS ! = ftdm_conf_node_create ( " sng_isup " , & rootnode , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to create root node for sng_isup config %s \n " , confname ) ;
return NULL ;
}
2010-11-26 20:59:24 +00:00
/* add sng_gen */
gen = switch_xml_child ( isup , " sng_gen " ) ;
if ( gen = = NULL ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process sng_gen for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
if ( ( FTDM_SUCCESS ! = ftdm_conf_node_create ( " sng_gen " , & list , rootnode ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to create %s node for %s \n " , " sng_gen " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
for ( param = switch_xml_child ( gen , " param " ) ; param ; param = param - > next ) {
var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
ftdm_conf_node_add_param ( list , var , val ) ;
}
/* add relay channels */
if ( add_config_list_nodes ( isup , rootnode , " sng_relay " , " relay_channel " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process sng_relay for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
/* add mtp1 links */
if ( add_config_list_nodes ( isup , rootnode , " mtp1_links " , " mtp1_link " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process mtp1_links for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
/* add mtp2 links */
if ( add_config_list_nodes ( isup , rootnode , " mtp2_links " , " mtp2_link " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process mtp2_links for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
/* add mtp3 links */
if ( add_config_list_nodes ( isup , rootnode , " mtp3_links " , " mtp3_link " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process mtp3_links for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
2010-04-14 21:59:39 +00:00
/* add mtp linksets */
2010-11-26 20:59:24 +00:00
if ( add_config_list_nodes ( isup , rootnode , " mtp_linksets " , " mtp_linkset " , NULL , NULL ) ) {
2010-04-14 21:59:39 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process mtp_linksets for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
/* add mtp routes */
2011-01-21 17:04:33 +00:00
if ( add_config_list_nodes ( isup , rootnode , " mtp_routes " , " mtp_route " , " linksets " , " linkset " ) ) {
2010-04-14 21:59:39 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process mtp_routes for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
/* add isup interfaces */
if ( add_config_list_nodes ( isup , rootnode , " isup_interfaces " , " isup_interface " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process isup_interfaces for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
2010-11-26 20:59:24 +00:00
/* add cc spans */
if ( add_config_list_nodes ( isup , rootnode , " cc_spans " , " cc_span " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process cc_spans for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
2010-04-14 21:59:39 +00:00
switch_core_hash_insert ( globals . ss7_configs , confname , rootnode ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Added SS7 node configuration %s \n " , confname ) ;
return rootnode ;
2010-04-14 15:00:17 +00:00
}
2010-06-30 19:11:34 +00:00
static int add_profile_parameters ( switch_xml_t cfg , const char * profname , ftdm_conf_parameter_t * parameters , int len )
{
switch_xml_t profnode , profile , param ;
int paramindex = 0 ;
profnode = switch_xml_child ( cfg , " config_profiles " ) ;
if ( ! profnode ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " cannot find profile '%s', there is no 'config_profiles' XML section \n " , profname ) ;
2010-06-30 19:11:34 +00:00
return 0 ;
}
/* search the profile */
for ( profile = switch_xml_child ( profnode , " profile " ) ; profile ; profile = profile - > next ) {
char * name = ( char * ) switch_xml_attr ( profile , " name " ) ;
if ( ! name ) {
continue ;
}
if ( ! strcasecmp ( name , profname ) ) {
break ;
}
}
if ( ! profile ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " failed to find profile '%s' \n " , profname ) ;
2010-06-30 19:11:34 +00:00
return 0 ;
}
for ( param = switch_xml_child ( profile , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! var | | ! val ) {
continue ;
}
parameters [ paramindex ] . var = var ;
parameters [ paramindex ] . val = val ;
paramindex + + ;
}
return paramindex ;
}
2010-09-09 21:22:10 +00:00
static void parse_bri_pri_spans ( switch_xml_t cfg , switch_xml_t spans )
{
switch_xml_t myspan , param ;
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
ftdm_status_t zstatus = FTDM_FAIL ;
const char * context = " default " ;
const char * dialplan = " XML " ;
ftdm_conf_parameter_t spanparameters [ 30 ] ;
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
char * configname = ( char * ) switch_xml_attr ( myspan , " cfgprofile " ) ;
ftdm_span_t * span = NULL ;
uint32_t span_id = 0 ;
unsigned paramindex = 0 ;
if ( ! name & & ! id ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " sangoma isdn span missing required attribute 'id' or 'name', skipping ... \n " ) ;
2010-09-09 21:22:10 +00:00
continue ;
}
if ( name ) {
zstatus = ftdm_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = ftdm_span_find ( span_id , & span ) ;
}
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2010-09-09 21:22:10 +00:00
continue ;
}
if ( ! span_id ) {
span_id = ftdm_span_get_id ( span ) ;
}
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
paramindex = 0 ;
if ( configname ) {
paramindex = add_profile_parameters ( cfg , configname , spanparameters , ftdm_array_len ( spanparameters ) ) ;
if ( paramindex ) {
ftdm_log ( FTDM_LOG_DEBUG , " Added %d parameters from profile %s for span %d \n " , paramindex , configname , span_id ) ;
}
}
/* some defaults first */
SPAN_CONFIG [ span_id ] . limit_backend = " hash " ;
SPAN_CONFIG [ span_id ] . limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT ;
2011-05-19 20:17:46 +00:00
SPAN_CONFIG [ span_id ] . digital_sampling_rate = 8000 ;
2010-09-09 21:22:10 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2010-11-12 10:36:29 +00:00
if ( ftdm_array_len ( spanparameters ) - 1 = = paramindex ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Too many parameters for ss7 span, ignoring any parameter after %s \n " , var ) ;
2010-09-09 21:22:10 +00:00
break ;
}
if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2011-05-19 20:17:46 +00:00
} else if ( ! strcasecmp ( var , " unrestricted-digital-codec " ) ) {
//switch_core_strdup(pool, val);
const switch_codec_implementation_t * codec = NULL ;
int num_codecs ;
num_codecs = switch_loadable_module_get_codecs_sorted ( & codec , 1 , & val , 1 ) ;
if ( num_codecs ! = 1 | | ! codec ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR ,
" Failed finding codec %s for unrestricted digital calls \n " , val ) ;
} else {
SPAN_CONFIG [ span_id ] . digital_codec = switch_core_strdup ( module_pool , codec - > iananame ) ;
SPAN_CONFIG [ span_id ] . digital_sampling_rate = codec - > samples_per_second ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" Unrestricted digital codec is %s at %dhz for span %d \n " ,
SPAN_CONFIG [ span_id ] . digital_codec , SPAN_CONFIG [ span_id ] . digital_sampling_rate , span_id ) ;
}
2010-09-09 21:22:10 +00:00
} else if ( ! strcasecmp ( var , " call_limit_backend " ) ) {
SPAN_CONFIG [ span_id ] . limit_backend = val ;
ftdm_log ( FTDM_LOG_DEBUG , " Using limit backend %s for span %d \n " , SPAN_CONFIG [ span_id ] . limit_backend , span_id ) ;
} else if ( ! strcasecmp ( var , " call_limit_rate " ) ) {
int calls ;
int seconds ;
if ( sscanf ( val , " %d/%d " , & calls , & seconds ) ! = 2 ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Invalid %s parameter, format example: 3/1 for 3 calls per second \n " , var ) ;
2010-09-09 21:22:10 +00:00
} else {
if ( calls < 1 | | seconds < 1 ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Invalid %s parameter value, minimum call limit must be 1 per second \n " , var ) ;
2010-09-09 21:22:10 +00:00
} else {
SPAN_CONFIG [ span_id ] . limit_calls = calls ;
SPAN_CONFIG [ span_id ] . limit_seconds = seconds ;
}
}
} else if ( ! strcasecmp ( var , " call_limit_reset_event " ) ) {
if ( ! strcasecmp ( val , " answer " ) ) {
SPAN_CONFIG [ span_id ] . limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER ;
} else {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Invalid %s parameter value, only accepted event is 'answer' \n " , var ) ;
2010-09-09 21:22:10 +00:00
}
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
}
}
if ( ftdm_configure_span_signaling ( span ,
" sangoma_isdn " ,
on_clear_channel_signal ,
spanparameters ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error configuring Sangoma ISDN FreeTDM span %d \n " , span_id ) ;
2010-09-09 21:22:10 +00:00
continue ;
}
SPAN_CONFIG [ span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . context , context , sizeof ( SPAN_CONFIG [ span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " Sangoma (ISDN) " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
ftdm_log ( FTDM_LOG_DEBUG , " Configured Sangoma ISDN FreeTDM span %d \n " , span_id ) ;
ftdm_span_start ( span ) ;
}
}
2007-05-26 04:45:31 +00:00
static switch_status_t load_config ( void )
{
2010-01-15 19:22:49 +00:00
const char * cf = " freetdm.conf " ;
2007-05-27 05:23:28 +00:00
switch_xml_t cfg , xml , settings , param , spans , myspan ;
2010-04-14 15:00:17 +00:00
ftdm_conf_node_t * ss7confnode = NULL ;
2009-11-26 16:01:55 +00:00
unsigned int i = 0 ;
2010-05-20 15:43:40 +00:00
ftdm_channel_t * fchan = NULL ;
2010-09-10 18:01:52 +00:00
ftdm_iterator_t * chaniter = NULL ;
ftdm_iterator_t * curr = NULL ;
2007-05-26 04:45:31 +00:00
memset ( & globals , 0 , sizeof ( globals ) ) ;
switch_mutex_init ( & globals . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " open of %s failed \n " , cf ) ;
return SWITCH_STATUS_TERM ;
}
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " debug " ) ) {
globals . debug = atoi ( val ) ;
2008-01-10 00:47:04 +00:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
switch_set_string ( globals . hold_music , val ) ;
2010-08-31 17:48:48 +00:00
} else if ( ! strcasecmp ( var , " crash-on-assert " ) ) {
2011-06-14 13:47:46 +00:00
globals . crash_on_assert = ( uint8_t ) switch_true ( val ) ;
2011-06-01 19:24:09 +00:00
} else if ( ! strcasecmp ( var , " fail-on-error " ) ) {
2011-06-14 13:47:46 +00:00
globals . fail_on_error = ( uint8_t ) switch_true ( val ) ;
2010-06-17 22:11:22 +00:00
} else if ( ! strcasecmp ( var , " sip-headers " ) ) {
globals . sip_headers = switch_true ( val ) ;
2008-01-25 16:42:06 +00:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
globals . analog_options = enable_analog_option ( val , globals . analog_options ) ;
2007-05-26 04:45:31 +00:00
}
}
}
2010-09-09 21:22:10 +00:00
if ( ( spans = switch_xml_child ( cfg , " sangoma_pri_spans " ) ) ) {
parse_bri_pri_spans ( cfg , spans ) ;
}
2010-06-30 19:11:34 +00:00
2010-09-09 21:22:10 +00:00
if ( ( spans = switch_xml_child ( cfg , " sangoma_bri_spans " ) ) ) {
parse_bri_pri_spans ( cfg , spans ) ;
2010-06-30 19:11:34 +00:00
}
2010-04-14 15:00:17 +00:00
switch_core_hash_init ( & globals . ss7_configs , module_pool ) ;
2010-06-06 17:07:30 +00:00
if ( ( spans = switch_xml_child ( cfg , " sangoma_ss7_spans " ) ) ) {
2010-04-14 15:00:17 +00:00
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
ftdm_status_t zstatus = FTDM_FAIL ;
2010-04-14 22:36:22 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
ftdm_conf_parameter_t spanparameters [ 30 ] ;
2010-04-14 15:00:17 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2011-02-15 16:58:16 +00:00
char * configname = ( char * ) switch_xml_attr ( myspan , " cfgprofile " ) ;
2010-04-14 15:00:17 +00:00
ftdm_span_t * span = NULL ;
uint32_t span_id = 0 ;
2010-04-14 22:36:22 +00:00
unsigned paramindex = 0 ;
2010-04-14 21:59:39 +00:00
if ( ! name & & ! id ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " ss7 span missing required attribute 'id' or 'name', skipping ... \n " ) ;
2010-04-14 21:59:39 +00:00
continue ;
}
if ( ! configname ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " ss7 span missing required attribute, skipping ... \n " ) ;
2010-04-14 15:00:17 +00:00
continue ;
}
if ( name ) {
zstatus = ftdm_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = ftdm_span_find ( span_id , & span ) ;
}
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2010-04-14 15:00:17 +00:00
continue ;
}
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2010-04-14 15:00:17 +00:00
}
ss7confnode = get_ss7_config_node ( cfg , configname ) ;
2010-04-14 21:59:39 +00:00
if ( ! ss7confnode ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding ss7config '%s' for FreeTDM span id: %s \n " , configname , switch_str_nil ( id ) ) ;
2010-04-14 15:00:17 +00:00
continue ;
}
2010-04-14 21:59:39 +00:00
2010-04-14 22:36:22 +00:00
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
2010-06-06 17:07:30 +00:00
paramindex = 0 ;
spanparameters [ paramindex ] . var = " confnode " ;
spanparameters [ paramindex ] . ptr = ss7confnode ;
paramindex + + ;
2010-04-14 22:36:22 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2010-11-12 10:36:29 +00:00
if ( ftdm_array_len ( spanparameters ) - 1 = = paramindex ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Too many parameters for ss7 span, ignoring any parameter after %s \n " , var ) ;
2010-04-14 22:36:22 +00:00
break ;
}
if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
2010-04-14 21:59:39 +00:00
}
}
2010-04-14 22:36:22 +00:00
2010-06-06 17:07:30 +00:00
if ( ftdm_configure_span_signaling ( span ,
" sangoma_ss7 " ,
2010-06-08 18:13:54 +00:00
on_clear_channel_signal ,
2010-06-06 17:07:30 +00:00
spanparameters ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error configuring ss7 FreeTDM span %d \n " , span_id ) ;
2010-04-14 22:36:22 +00:00
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . context , context , sizeof ( SPAN_CONFIG [ span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " Sangoma (SS7) " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2010-04-14 15:00:17 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Configured ss7 FreeTDM span %d with config node %s \n " , span_id , configname ) ;
2010-05-31 10:27:03 +00:00
ftdm_span_start ( span ) ;
2010-04-14 15:00:17 +00:00
}
}
2007-05-26 04:45:31 +00:00
if ( ( spans = switch_xml_child ( cfg , " analog_spans " ) ) ) {
2007-05-27 05:23:28 +00:00
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
2008-09-26 15:36:34 +00:00
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2010-01-15 19:22:49 +00:00
ftdm_status_t zstatus = FTDM_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2007-05-26 04:45:31 +00:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
2008-10-06 19:21:27 +00:00
char * hotline = NULL ;
2007-11-24 18:04:14 +00:00
char * dial_regex = NULL ;
2008-01-10 00:47:04 +00:00
char * hold_music = NULL ;
2007-11-24 18:04:14 +00:00
char * fail_dial_regex = NULL ;
2009-01-13 22:45:09 +00:00
const char * enable_callerid = " true " ;
2010-12-21 20:11:22 +00:00
const char * answer_polarity = " false " ;
const char * hangup_polarity = " false " ;
int polarity_delay = 600 ;
2010-05-25 16:48:10 +00:00
int callwaiting = 1 ;
2011-02-25 15:35:25 +00:00
int dialtone_timeout = 5000 ;
2008-09-29 15:51:00 +00:00
2007-05-26 04:45:31 +00:00
uint32_t span_id = 0 , to = 0 , max = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2008-01-25 16:42:06 +00:00
analog_option_t analog_options = ANALOG_OPTION_NONE ;
2010-08-31 17:59:13 +00:00
if ( name ) {
zstatus = ftdm_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = ftdm_span_find ( span_id , & span ) ;
}
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2010-08-31 17:59:13 +00:00
continue ;
}
if ( ! span_id ) {
span_id = ftdm_span_get_id ( span ) ;
}
/* some defaults first */
SPAN_CONFIG [ span_id ] . limit_backend = " hash " ;
SPAN_CONFIG [ span_id ] . limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT ;
2008-09-26 15:36:34 +00:00
2007-05-27 05:23:28 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
2007-05-26 04:45:31 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2010-05-25 16:48:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " analog_spans var = %s \n " , var ) ;
2007-05-26 04:45:31 +00:00
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
2007-05-26 04:45:31 +00:00
digit_timeout = val ;
2011-02-25 15:35:25 +00:00
} else if ( ! strcasecmp ( var , " wait-dialtone-timeout " ) ) {
dialtone_timeout = atoi ( val ) ;
2007-05-26 04:45:31 +00:00
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2010-08-31 17:59:13 +00:00
} else if ( ! strcasecmp ( var , " call_limit_backend " ) ) {
SPAN_CONFIG [ span_id ] . limit_backend = val ;
ftdm_log ( FTDM_LOG_DEBUG , " Using limit backend %s for span %d \n " , SPAN_CONFIG [ span_id ] . limit_backend , span_id ) ;
} else if ( ! strcasecmp ( var , " call_limit_rate " ) ) {
int calls ;
int seconds ;
if ( sscanf ( val , " %d/%d " , & calls , & seconds ) ! = 2 ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Invalid %s parameter, format example: 3/1 for 3 calls per second \n " , var ) ;
2010-08-31 17:59:13 +00:00
} else {
if ( calls < 1 | | seconds < 1 ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Invalid %s parameter value, minimum call limit must be 1 per second \n " , var ) ;
2010-08-31 17:59:13 +00:00
} else {
SPAN_CONFIG [ span_id ] . limit_calls = calls ;
SPAN_CONFIG [ span_id ] . limit_seconds = seconds ;
}
}
} else if ( ! strcasecmp ( var , " call_limit_reset_event " ) ) {
if ( ! strcasecmp ( val , " answer " ) ) {
SPAN_CONFIG [ span_id ] . limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER ;
} else {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Invalid %s parameter value, only accepted event is 'answer' \n " , var ) ;
2010-08-31 17:59:13 +00:00
}
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
2008-09-29 15:51:00 +00:00
} else if ( ! strcasecmp ( var , " enable-callerid " ) ) {
enable_callerid = val ;
2010-12-21 20:11:22 +00:00
} else if ( ! strcasecmp ( var , " answer-polarity-reverse " ) ) {
answer_polarity = val ;
} else if ( ! strcasecmp ( var , " hangup-polarity-reverse " ) ) {
hangup_polarity = val ;
} else if ( ! strcasecmp ( var , " polarity-delay " ) ) {
polarity_delay = atoi ( val ) ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
2008-01-10 00:47:04 +00:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
hold_music = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " max_digits " ) | | ! strcasecmp ( var , " max-digits " ) ) {
2008-09-08 23:01:44 +00:00
max_digits = val ;
2008-10-06 19:21:27 +00:00
} else if ( ! strcasecmp ( var , " hotline " ) ) {
hotline = val ;
2010-05-25 16:48:10 +00:00
} else if ( ! strcasecmp ( var , " callwaiting " ) ) {
callwaiting = switch_true ( val ) ? 1 : 0 ;
2008-01-25 16:42:06 +00:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
2007-05-26 04:45:31 +00:00
}
}
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " span missing required param 'id' \n " ) ;
2008-08-29 20:41:17 +00:00
continue ;
2007-05-26 04:45:31 +00:00
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 15:36:34 +00:00
if ( name ) {
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2008-09-26 15:36:34 +00:00
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find ( span_id , & span ) ;
2008-09-26 15:36:34 +00:00
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
2008-09-26 15:36:34 +00:00
}
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2007-05-26 04:45:31 +00:00
continue ;
}
2008-09-26 15:36:34 +00:00
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2008-09-26 15:36:34 +00:00
}
2007-05-26 04:45:31 +00:00
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " analog " , on_analog_signal ,
2008-08-29 15:58:59 +00:00
" tonemap " , tonegroup ,
" digit_timeout " , & to ,
2008-08-29 20:41:17 +00:00
" max_dialstr " , & max ,
2010-05-25 16:48:10 +00:00
" hotline " , hotline ? hotline : " " ,
2008-09-29 15:51:00 +00:00
" enable_callerid " , enable_callerid ,
2010-12-21 20:11:22 +00:00
" answer_polarity_reverse " , answer_polarity ,
" hangup_polarity_reverse " , hangup_polarity ,
" polarity_delay " , & polarity_delay ,
2010-05-25 16:48:10 +00:00
" callwaiting " , & callwaiting ,
2011-02-25 15:35:25 +00:00
" wait_dialtone_timeout " , & dialtone_timeout ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error configuring FreeTDM analog span %s \n " , ftdm_span_get_name ( span ) ) ;
2007-05-26 04:45:31 +00:00
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_set_string ( SPAN_CONFIG [ span_id ] . context , context ) ;
switch_set_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan ) ;
SPAN_CONFIG [ span_id ] . analog_options = analog_options | globals . analog_options ;
2008-01-25 16:42:06 +00:00
2010-09-10 18:09:06 +00:00
chaniter = ftdm_span_get_chan_iterator ( span , NULL ) ;
curr = chaniter ;
for ( curr = chaniter ; curr ; curr = ftdm_iterator_next ( curr ) ) {
2010-09-10 18:01:52 +00:00
fchan = ftdm_iterator_current ( curr ) ;
2010-05-20 15:43:40 +00:00
ftdm_channel_set_private ( fchan , & SPAN_CONFIG [ span_id ] . pvts [ i ] ) ;
}
2010-09-10 18:01:52 +00:00
ftdm_iterator_free ( chaniter ) ;
2010-05-20 15:43:40 +00:00
2007-11-24 18:04:14 +00:00
if ( dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . dial_regex , dial_regex ) ;
2007-11-24 18:04:14 +00:00
}
if ( fail_dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . fail_dial_regex , fail_dial_regex ) ;
2007-11-24 18:04:14 +00:00
}
2007-05-26 04:45:31 +00:00
2008-01-10 00:47:04 +00:00
if ( hold_music ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . hold_music , hold_music ) ;
2008-01-10 00:47:04 +00:00
}
2010-04-21 15:20:05 +00:00
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " analog " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_span_start ( span ) ;
2007-05-26 04:45:31 +00:00
}
}
2008-09-17 02:21:28 +00:00
if ( ( spans = switch_xml_child ( cfg , " analog_em_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2010-01-15 19:22:49 +00:00
ftdm_status_t zstatus = FTDM_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2008-09-17 02:21:28 +00:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
char * dial_regex = NULL ;
char * hold_music = NULL ;
char * fail_dial_regex = NULL ;
uint32_t span_id = 0 , to = 0 , max = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2008-09-17 02:21:28 +00:00
analog_option_t analog_options = ANALOG_OPTION_NONE ;
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
digit_timeout = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
hold_music = val ;
} else if ( ! strcasecmp ( var , " max_digits " ) | | ! strcasecmp ( var , " max-digits " ) ) {
max_digits = val ;
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
}
}
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " span missing required param 'id' \n " ) ;
2008-09-17 02:21:28 +00:00
continue ;
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 17:09:10 +00:00
if ( name ) {
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2008-09-26 17:09:10 +00:00
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find ( span_id , & span ) ;
2008-09-26 17:09:10 +00:00
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
2008-09-26 17:09:10 +00:00
}
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2008-09-17 02:21:28 +00:00
continue ;
}
2008-09-26 17:09:10 +00:00
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2008-09-26 17:09:10 +00:00
}
2008-09-17 02:21:28 +00:00
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " analog_em " , on_analog_signal ,
2008-09-17 02:21:28 +00:00
" tonemap " , tonegroup ,
" digit_timeout " , & to ,
" max_dialstr " , & max ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error starting FreeTDM span %d \n " , span_id ) ;
2008-09-17 02:21:28 +00:00
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_set_string ( SPAN_CONFIG [ span_id ] . context , context ) ;
switch_set_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan ) ;
SPAN_CONFIG [ span_id ] . analog_options = analog_options | globals . analog_options ;
2008-09-17 02:21:28 +00:00
if ( dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . dial_regex , dial_regex ) ;
2008-09-17 02:21:28 +00:00
}
if ( fail_dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . fail_dial_regex , fail_dial_regex ) ;
2008-09-17 02:21:28 +00:00
}
if ( hold_music ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . hold_music , hold_music ) ;
2008-09-17 02:21:28 +00:00
}
2010-04-21 15:20:05 +00:00
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " analog_em " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_span_start ( span ) ;
2008-09-17 02:21:28 +00:00
}
}
2007-06-13 03:37:55 +00:00
if ( ( spans = switch_xml_child ( cfg , " pri_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2010-11-14 14:44:50 +00:00
ftdm_conf_parameter_t spanparameters [ 10 ] ;
2010-01-15 19:22:49 +00:00
ftdm_status_t zstatus = FTDM_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
2010-11-14 14:44:50 +00:00
unsigned paramindex = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2010-11-14 14:44:50 +00:00
uint32_t span_id = 0 ;
2008-10-03 21:57:57 +00:00
2010-11-14 14:44:50 +00:00
if ( ! name ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " span missing required attribute 'name' \n " ) ;
2010-11-14 14:44:50 +00:00
continue ;
}
2010-11-15 11:33:58 +00:00
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
2007-06-13 03:37:55 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2010-11-15 11:33:58 +00:00
if ( ftdm_array_len ( spanparameters ) - 1 = = paramindex ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Too many parameters for pri span '%s', ignoring everything after '%s' \n " , name , var ) ;
2010-11-14 14:44:50 +00:00
break ;
}
2010-11-15 11:33:58 +00:00
if ( ftdm_strlen_zero ( var ) | | ftdm_strlen_zero ( val ) ) {
ftdm_log ( FTDM_LOG_WARNING , " Skipping parameter with empty name or value \n " ) ;
continue ;
}
2010-11-14 14:44:50 +00:00
if ( ! strcasecmp ( var , " context " ) ) {
2007-06-13 03:37:55 +00:00
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2010-11-14 14:44:50 +00:00
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
2008-09-26 17:09:10 +00:00
}
2007-06-13 03:37:55 +00:00
}
2008-09-26 17:09:10 +00:00
2010-11-14 14:44:50 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span %s \n " , name ) ;
2007-06-13 03:37:55 +00:00
continue ;
}
2009-01-30 11:37:11 +00:00
2010-11-14 14:44:50 +00:00
span_id = ftdm_span_get_id ( span ) ;
if ( ftdm_configure_span_signaling ( span , " isdn " , on_clear_channel_signal , spanparameters ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error configuring FreeTDM span %s \n " , name ) ;
2007-06-13 03:37:55 +00:00
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . context , context , sizeof ( SPAN_CONFIG [ span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " isdn " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2007-06-13 03:37:55 +00:00
2010-01-15 19:22:49 +00:00
ftdm_span_start ( span ) ;
2007-06-13 03:37:55 +00:00
}
}
2010-07-30 23:46:05 +00:00
if ( ( spans = switch_xml_child ( cfg , " pritap_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
ftdm_status_t zstatus = FTDM_FAIL ;
unsigned paramindex = 0 ;
ftdm_conf_parameter_t spanparameters [ 10 ] ;
const char * context = " default " ;
const char * dialplan = " XML " ;
ftdm_span_t * span = NULL ;
int span_id = 0 ;
if ( ! name ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " span missing required attribute 'name' \n " ) ;
2010-07-30 23:46:05 +00:00
continue ;
}
2010-11-15 11:33:58 +00:00
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
2010-07-30 23:46:05 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2010-11-15 11:33:58 +00:00
if ( ftdm_array_len ( spanparameters ) - 1 = = paramindex ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Too many parameters for pritap span '%s', ignoring everything after '%s' \n " , name , var ) ;
2010-11-15 11:33:58 +00:00
break ;
}
2010-07-30 23:46:05 +00:00
if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
}
}
zstatus = ftdm_span_find_by_name ( name , & span ) ;
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span %s \n " , name ) ;
2010-07-30 23:46:05 +00:00
continue ;
}
span_id = ftdm_span_get_id ( span ) ;
if ( ftdm_configure_span_signaling ( span , " pritap " , on_clear_channel_signal , spanparameters ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error configuring FreeTDM span %s \n " , name ) ;
2010-07-30 23:46:05 +00:00
continue ;
}
SPAN_CONFIG [ span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . context , context , sizeof ( SPAN_CONFIG [ span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " isdn " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
ftdm_span_start ( span ) ;
}
}
2009-02-07 23:14:25 +00:00
if ( ( spans = switch_xml_child ( cfg , " libpri_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2010-11-07 16:00:54 +00:00
ftdm_conf_parameter_t spanparameters [ 10 ] ;
2010-01-15 19:22:49 +00:00
ftdm_status_t zstatus = FTDM_FAIL ;
2010-11-07 16:00:54 +00:00
const char * context = " default " ;
2009-02-07 23:14:25 +00:00
const char * dialplan = " XML " ;
2010-11-07 16:00:54 +00:00
unsigned paramindex = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2010-11-07 16:00:54 +00:00
uint32_t span_id = 0 ;
2009-03-19 20:15:39 +00:00
2010-11-07 16:00:54 +00:00
if ( ! name ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " span missing required attribute 'name' \n " ) ;
2010-11-07 16:00:54 +00:00
continue ;
}
2010-11-15 11:33:58 +00:00
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
2009-02-07 23:14:25 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2010-11-12 10:36:29 +00:00
if ( ftdm_array_len ( spanparameters ) - 1 = = paramindex ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Too many parameters for libpri span, ignoring everything after '%s' \n " , var ) ;
2010-11-11 22:53:19 +00:00
break ;
}
2010-11-15 11:33:58 +00:00
if ( ftdm_strlen_zero ( var ) | | ftdm_strlen_zero ( val ) ) {
ftdm_log ( FTDM_LOG_WARNING , " Skipping parameter with empty name or value \n " ) ;
continue ;
}
2010-11-07 16:00:54 +00:00
if ( ! strcasecmp ( var , " context " ) ) {
2009-02-07 23:14:25 +00:00
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2010-11-07 16:00:54 +00:00
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
2009-02-07 23:14:25 +00:00
}
}
2010-11-07 16:00:54 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM span %s \n " , name ) ;
2009-02-07 23:14:25 +00:00
continue ;
}
2010-11-07 16:00:54 +00:00
span_id = ftdm_span_get_id ( span ) ;
if ( ftdm_configure_span_signaling ( span , " libpri " , on_clear_channel_signal , spanparameters ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error configuring FreeTDM span %s \n " , name ) ;
2009-02-07 23:14:25 +00:00
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . context , context , sizeof ( SPAN_CONFIG [ span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " isdn " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2009-02-07 23:14:25 +00:00
2010-01-15 19:22:49 +00:00
ftdm_span_start ( span ) ;
2009-02-07 23:14:25 +00:00
}
}
2009-08-19 21:47:56 +00:00
if ( ( spans = switch_xml_child ( cfg , " r2_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2010-12-03 11:13:11 +00:00
char * configname = ( char * ) switch_xml_attr ( myspan , " cfgprofile " ) ;
2010-01-15 19:22:49 +00:00
ftdm_status_t zstatus = FTDM_FAIL ;
2009-08-19 21:47:56 +00:00
/* common non r2 stuff */
const char * context = " default " ;
const char * dialplan = " XML " ;
char * dial_regex = NULL ;
char * fail_dial_regex = NULL ;
uint32_t span_id = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2009-08-19 21:47:56 +00:00
2010-11-27 00:10:33 +00:00
ftdm_conf_parameter_t spanparameters [ 30 ] ;
unsigned paramindex = 0 ;
2009-08-19 21:47:56 +00:00
2010-12-03 11:13:11 +00:00
if ( ! name ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " 'name' attribute required for R2 spans! \n " ) ;
2010-12-03 11:13:11 +00:00
continue ;
}
2010-11-27 00:10:33 +00:00
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
2010-12-03 11:13:11 +00:00
if ( configname ) {
paramindex = add_profile_parameters ( cfg , configname , spanparameters , ftdm_array_len ( spanparameters ) ) ;
if ( paramindex ) {
ftdm_log ( FTDM_LOG_DEBUG , " Added %d parameters from profile %s for span %d \n " , paramindex , configname , span_id ) ;
}
}
2009-08-19 21:47:56 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
/* string parameters */
2010-11-27 00:10:33 +00:00
if ( ! strcasecmp ( var , " context " ) ) {
2009-08-19 21:47:56 +00:00
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
2010-11-27 00:10:33 +00:00
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
2009-08-19 21:47:56 +00:00
}
}
2010-12-03 11:13:11 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error finding FreeTDM R2 Span '%s' \n " , name ) ;
2009-08-19 21:47:56 +00:00
continue ;
}
2010-12-03 11:13:11 +00:00
span_id = ftdm_span_get_id ( span ) ;
2009-08-19 21:47:56 +00:00
2010-11-27 00:10:33 +00:00
if ( ftdm_configure_span_signaling ( span , " r2 " , on_r2_signal , spanparameters ) ! = FTDM_SUCCESS ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error configuring FreeTDM R2 span %s, error: %s \n " , name , ftdm_span_get_last_error ( span ) ) ;
2009-08-19 21:47:56 +00:00
continue ;
}
if ( dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . dial_regex , dial_regex ) ;
2009-08-19 21:47:56 +00:00
}
if ( fail_dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . fail_dial_regex , fail_dial_regex ) ;
2009-08-19 21:47:56 +00:00
}
2008-02-29 00:21:04 +00:00
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . context , context , sizeof ( SPAN_CONFIG [ span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span_id ] . dialplan ) ) ;
2010-12-03 11:13:11 +00:00
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " R2 " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2009-08-19 21:47:56 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdm_span_start ( span ) = = FTDM_FAIL ) {
2011-06-01 19:24:09 +00:00
CONFIG_ERROR ( " Error starting FreeTDM R2 span %s, error: %s \n " , name , ftdm_span_get_last_error ( span ) ) ;
2009-08-19 21:47:56 +00:00
continue ;
}
}
}
2007-05-26 04:45:31 +00:00
2010-08-31 17:48:48 +00:00
if ( globals . crash_on_assert ) {
ftdm_log ( FTDM_LOG_WARNING , " Crash on assert enabled \n " ) ;
ftdm_global_set_crash_policy ( FTDM_CRASH_ON_ASSERT ) ;
}
2009-11-24 18:15:55 +00:00
2007-05-26 04:45:31 +00:00
switch_xml_free ( xml ) ;
2011-06-01 19:24:09 +00:00
if ( globals . fail_on_error & & globals . config_error ) {
ftdm_log ( FTDM_LOG_ERROR , " Refusing to load module with errors \n " ) ;
return SWITCH_STATUS_TERM ;
}
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2010-01-15 19:22:49 +00:00
void dump_chan ( ftdm_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream )
2008-04-01 17:29:57 +00:00
{
2010-04-21 15:20:05 +00:00
uint32_t span_id ;
uint32_t phspan_id , phchan_id ;
const char * chan_type ;
const char * state ;
const char * last_state ;
2010-09-23 13:30:08 +00:00
const char * uuid = NULL ;
char sessionid [ 255 ] ;
2010-04-21 15:20:05 +00:00
float txgain , rxgain ;
2010-09-23 13:30:08 +00:00
switch_core_session_t * session = NULL ;
2010-04-21 15:20:05 +00:00
ftdm_alarm_flag_t alarmflag ;
ftdm_caller_data_t * caller_data ;
ftdm_channel_t * ftdmchan ;
2010-04-27 22:20:25 +00:00
ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN ;
2010-04-21 15:20:05 +00:00
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2009-02-04 23:11:41 +00:00
return ;
}
2010-04-21 15:20:05 +00:00
2010-09-23 13:30:08 +00:00
strcpy ( sessionid , " (none) " ) ;
2010-04-21 15:20:05 +00:00
ftdmchan = ftdm_span_get_channel ( span , chan_id ) ;
span_id = ftdm_span_get_id ( span ) ;
phspan_id = ftdm_channel_get_ph_span_id ( ftdmchan ) ;
phchan_id = ftdm_channel_get_ph_id ( ftdmchan ) ;
chan_type = ftdm_chan_type2str ( ftdm_channel_get_type ( ftdmchan ) ) ;
state = ftdm_channel_get_state_str ( ftdmchan ) ;
last_state = ftdm_channel_get_last_state_str ( ftdmchan ) ;
ftdm_channel_command ( ftdmchan , FTDM_COMMAND_GET_RX_GAIN , & rxgain ) ;
ftdm_channel_command ( ftdmchan , FTDM_COMMAND_GET_TX_GAIN , & txgain ) ;
caller_data = ftdm_channel_get_caller_data ( ftdmchan ) ;
ftdm_channel_get_sig_status ( ftdmchan , & sigstatus ) ;
ftdm_channel_get_alarms ( ftdmchan , & alarmflag ) ;
2010-09-23 13:30:08 +00:00
uuid = ftdm_channel_get_uuid ( ftdmchan , 0 ) ;
if ( ! zstr ( uuid ) ) {
if ( ! ( session = switch_core_session_locate ( uuid ) ) ) {
snprintf ( sessionid , sizeof ( sessionid ) , " %s (dead) " , uuid ) ;
} else {
snprintf ( sessionid , sizeof ( sessionid ) , " %s " , uuid ) ;
switch_core_session_rwunlock ( session ) ;
}
}
2008-04-01 17:29:57 +00:00
stream - > write_function ( stream ,
" span_id: %u \n "
" chan_id: %u \n "
" physical_span_id: %u \n "
" physical_chan_id: %u \n "
2010-04-27 18:32:36 +00:00
" physical_status: %s \n "
2011-05-06 02:04:43 +00:00
" physical_status_red: %d \n "
" physical_status_yellow: %d \n "
" physical_status_rai: %d \n "
" physical_status_blue: %d \n "
" physical_status_ais: %d \n "
" physical_status_general: %d \n "
2010-04-27 18:32:36 +00:00
" signaling_status: %s \n "
2008-04-01 17:29:57 +00:00
" type: %s \n "
" state: %s \n "
" last_state: %s \n "
2010-04-05 22:13:13 +00:00
" txgain: %3.2f \n "
" rxgain: %3.2f \n "
2008-04-01 17:29:57 +00:00
" cid_date: %s \n "
" cid_name: %s \n "
" cid_num: %s \n "
" ani: %s \n "
" aniII: %s \n "
" dnis: %s \n "
" rdnis: %s \n "
2010-09-23 13:30:08 +00:00
" cause: %s \n "
" session: %s \n \n " ,
2010-04-21 15:20:05 +00:00
span_id ,
chan_id ,
phspan_id ,
phchan_id ,
alarmflag ? " alarmed " : " ok " ,
2011-05-04 16:51:49 +00:00
( alarmflag & FTDM_ALARM_RED ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_YELLOW ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_RAI ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_BLUE ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_AIS ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_GENERAL ) ? 1 : 0 ,
ftdm_signaling_status2str ( sigstatus ) ,
2010-04-21 15:20:05 +00:00
chan_type ,
state ,
last_state ,
txgain ,
rxgain ,
caller_data - > cid_date ,
caller_data - > cid_name ,
caller_data - > cid_num . digits ,
caller_data - > ani . digits ,
caller_data - > aniII ,
caller_data - > dnis . digits ,
caller_data - > rdnis . digits ,
2010-09-23 13:30:08 +00:00
switch_channel_cause2str ( caller_data - > hangup_cause ) ,
sessionid ) ;
2008-04-01 17:29:57 +00:00
}
2010-01-15 19:22:49 +00:00
void dump_chan_xml ( ftdm_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream )
2009-07-31 19:16:47 +00:00
{
2010-04-21 15:20:05 +00:00
uint32_t span_id ;
uint32_t phspan_id , phchan_id ;
const char * chan_type ;
const char * state ;
const char * last_state ;
float txgain , rxgain ;
ftdm_caller_data_t * caller_data ;
ftdm_channel_t * ftdmchan ;
ftdm_alarm_flag_t alarmflag ;
2010-04-27 22:20:25 +00:00
ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN ;
2010-04-21 15:20:05 +00:00
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2009-07-31 19:16:47 +00:00
return ;
}
2010-04-21 15:20:05 +00:00
ftdmchan = ftdm_span_get_channel ( span , chan_id ) ;
span_id = ftdm_span_get_id ( span ) ;
phspan_id = ftdm_channel_get_ph_span_id ( ftdmchan ) ;
phchan_id = ftdm_channel_get_ph_id ( ftdmchan ) ;
chan_type = ftdm_chan_type2str ( ftdm_channel_get_type ( ftdmchan ) ) ;
state = ftdm_channel_get_state_str ( ftdmchan ) ;
last_state = ftdm_channel_get_last_state_str ( ftdmchan ) ;
ftdm_channel_command ( ftdmchan , FTDM_COMMAND_GET_RX_GAIN , & rxgain ) ;
ftdm_channel_command ( ftdmchan , FTDM_COMMAND_GET_TX_GAIN , & txgain ) ;
caller_data = ftdm_channel_get_caller_data ( ftdmchan ) ;
ftdm_channel_get_sig_status ( ftdmchan , & sigstatus ) ;
ftdm_channel_get_alarms ( ftdmchan , & alarmflag ) ;
2009-07-31 19:16:47 +00:00
stream - > write_function ( stream ,
" <channel> \n "
" <span-id>%u</span-id> \n "
" <chan-id>%u</chan-id>> \n "
" <physical-span-id>%u</physical-span-id> \n "
" <physical-chan-id>%u</physical-chan-id> \n "
2010-04-27 18:32:36 +00:00
" <physical-status>%s</physical-status> \n "
2011-05-04 16:51:49 +00:00
" <physical-status-red>%d</physical-status-red> \n "
" <physical-status-yellow>%d</physical-status-yellow> \n "
" <physical-status-rai>%d</physical-status-rai> \n "
" <physical-status-blue>%d</physical-status-blue> \n "
" <physical-status-ais>%d</physical-status-ais> \n "
" <physical-status-general>%d</physical-status-general> \n "
2010-04-27 18:32:36 +00:00
" <signaling-status>%s</signaling-status> \n "
2009-07-31 19:16:47 +00:00
" <type>%s</type> \n "
" <state>%s</state> \n "
" <last-state>%s</last-state> \n "
2010-04-05 22:13:13 +00:00
" <txgain>%3.2f</txgain> \n "
" <rxgain>%3.2f</rxgain> \n "
2009-07-31 19:16:47 +00:00
" <cid-date>%s</cid-date> \n "
" <cid-name>%s</cid-name> \n "
" <cid-num>%s</cid-num> \n "
" <ani>%s</ani> \n "
" <aniII>%s</aniII> \n "
" <dnis>%s</dnis> \n "
" <rdnis>%s</rdnis> \n "
" <cause>%s</cause> \n "
" </channel> \n " ,
2010-04-21 15:20:05 +00:00
span_id ,
chan_id ,
phspan_id ,
phchan_id ,
alarmflag ? " alarmed " : " ok " ,
2011-05-04 16:51:49 +00:00
( alarmflag & FTDM_ALARM_RED ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_YELLOW ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_RAI ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_BLUE ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_AIS ) ? 1 : 0 ,
( alarmflag & FTDM_ALARM_GENERAL ) ? 1 : 0 ,
ftdm_signaling_status2str ( sigstatus ) ,
2010-04-21 15:20:05 +00:00
chan_type ,
state ,
last_state ,
txgain ,
rxgain ,
caller_data - > cid_date ,
caller_data - > cid_name ,
caller_data - > cid_num . digits ,
caller_data - > ani . digits ,
caller_data - > aniII ,
caller_data - > dnis . digits ,
caller_data - > rdnis . digits ,
switch_channel_cause2str ( caller_data - > hangup_cause ) ) ;
2009-07-31 19:16:47 +00:00
}
2011-07-29 23:33:42 +00:00
static switch_status_t ftdm_cmd_voice_detect ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
2008-04-01 17:29:57 +00:00
{
2011-07-29 23:33:42 +00:00
stream - > write_function ( stream , " IMPLEMENT ME! \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
2008-04-01 17:29:57 +00:00
2011-07-29 23:33:42 +00:00
static switch_status_t ftdm_cmd_list ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
int j ;
for ( j = 0 ; j < FTDM_MAX_SPANS_INTERFACE ; j + + ) {
ftdm_channel_t * fchan ;
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE ;
const char * flags = " none " ;
ftdm_signaling_status_t sigstatus ;
if ( ! SPAN_CONFIG [ j ] . span ) {
continue ;
}
if ( SPAN_CONFIG [ j ] . analog_options & ANALOG_OPTION_3WAY ) {
flags = " 3way " ;
} else if ( SPAN_CONFIG [ j ] . analog_options & ANALOG_OPTION_CALL_SWAP ) {
flags = " call swap " ;
}
fchan = ftdm_span_get_channel ( SPAN_CONFIG [ j ] . span , 1 ) ;
ftdm_channel_get_alarms ( fchan , & alarmbits ) ;
if ( ( FTDM_SUCCESS = = ftdm_span_get_sig_status ( SPAN_CONFIG [ j ] . span , & sigstatus ) ) ) {
stream - > write_function ( stream ,
" +OK \n "
" span: %u (%s) \n "
" type: %s \n "
" physical_status: %s \n "
" signaling_status: %s \n "
" chan_count: %u \n "
" dialplan: %s \n "
" context: %s \n "
" dial_regex: %s \n "
" fail_dial_regex: %s \n "
" hold_music: %s \n "
" analog_options: %s \n " ,
j ,
ftdm_span_get_name ( SPAN_CONFIG [ j ] . span ) ,
SPAN_CONFIG [ j ] . type ,
alarmbits ? " alarmed " : " ok " ,
ftdm_signaling_status2str ( sigstatus ) ,
ftdm_span_get_chan_count ( SPAN_CONFIG [ j ] . span ) ,
SPAN_CONFIG [ j ] . dialplan ,
SPAN_CONFIG [ j ] . context ,
SPAN_CONFIG [ j ] . dial_regex ,
SPAN_CONFIG [ j ] . fail_dial_regex ,
SPAN_CONFIG [ j ] . hold_music ,
flags
) ;
} else {
stream - > write_function ( stream ,
" +OK \n "
" span: %u (%s) \n "
" type: %s \n "
" physical_status: %s \n "
" chan_count: %u \n "
" dialplan: %s \n "
" context: %s \n "
" dial_regex: %s \n "
" fail_dial_regex: %s \n "
" hold_music: %s \n "
" analog_options: %s \n " ,
j ,
ftdm_span_get_name ( SPAN_CONFIG [ j ] . span ) ,
SPAN_CONFIG [ j ] . type ,
alarmbits ? " alarmed " : " ok " ,
ftdm_span_get_chan_count ( SPAN_CONFIG [ j ] . span ) ,
SPAN_CONFIG [ j ] . dialplan ,
SPAN_CONFIG [ j ] . context ,
SPAN_CONFIG [ j ] . dial_regex ,
SPAN_CONFIG [ j ] . fail_dial_regex ,
SPAN_CONFIG [ j ] . hold_music ,
flags ) ;
}
2008-04-01 17:29:57 +00:00
}
2011-07-29 23:33:42 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-04-01 17:29:57 +00:00
2011-07-29 23:33:42 +00:00
static switch_status_t ftdm_cmd_start_stop ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
char * span_name = argv [ 1 ] ;
ftdm_span_t * span = NULL ;
ftdm_status_t status ;
if ( span_name ) {
ftdm_span_find_by_name ( span_name , & span ) ;
}
if ( ! span ) {
stream - > write_function ( stream , " -ERR no span \n " ) ;
2008-04-01 17:29:57 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
if ( ! strcasecmp ( argv [ 0 ] , " stop " ) ) {
status = ftdm_span_stop ( span ) ;
} else {
status = ftdm_span_start ( span ) ;
}
stream - > write_function ( stream , status = = FTDM_SUCCESS ? " +OK \n " : " -ERR failure \n " ) ;
end :
return SWITCH_STATUS_SUCCESS ;
}
2008-04-01 17:29:57 +00:00
2011-07-29 23:33:42 +00:00
static switch_status_t ftdm_cmd_reset ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
uint32_t chan_id = 0 ;
uint32_t ccount = 0 ;
ftdm_channel_t * chan ;
ftdm_span_t * span = NULL ;
if ( argc < 2 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm reset <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
2010-12-16 19:01:06 +00:00
2011-07-29 23:33:42 +00:00
if ( argc > 2 ) {
chan_id = atoi ( argv [ 2 ] ) ;
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
2010-12-16 19:01:06 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
if ( chan_id ) {
chan = ftdm_span_get_channel ( span , chan_id ) ;
if ( ! chan ) {
stream - > write_function ( stream , " -ERR Could not find chan \n " ) ;
2010-12-16 19:01:06 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
stream - > write_function ( stream , " Resetting channel %s:%s \n " , argv [ 1 ] , argv [ 2 ] ) ;
ftdm_channel_reset ( chan ) ;
} else {
uint32_t i = 0 ;
ccount = ftdm_span_get_chan_count ( span ) ;
for ( i = 1 ; i < ccount ; i + + ) {
chan = ftdm_span_get_channel ( span , i ) ;
stream - > write_function ( stream , " Resetting channel %s:%d \n " , argv [ 1 ] , i ) ;
ftdm_channel_reset ( chan ) ;
2010-12-16 19:01:06 +00:00
}
2011-07-29 23:33:42 +00:00
}
2010-12-16 19:01:06 +00:00
2011-07-29 23:33:42 +00:00
end :
2010-12-16 19:01:06 +00:00
2011-07-29 23:33:42 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2010-12-16 19:01:06 +00:00
2011-07-29 23:33:42 +00:00
static switch_status_t ftdm_cmd_dump ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
ftdm_iterator_t * chaniter = NULL ;
ftdm_iterator_t * curr = NULL ;
uint32_t chan_id = 0 ;
ftdm_span_t * span ;
char * as = NULL ;
if ( argc < 2 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm dump <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
if ( argc > 2 ) {
if ( argv [ 3 ] & & ! strcasecmp ( argv [ 2 ] , " as " ) ) {
as = argv [ 3 ] ;
} else {
chan_id = atoi ( argv [ 2 ] ) ;
2010-12-16 19:01:06 +00:00
}
2011-07-29 23:33:42 +00:00
}
if ( argv [ 4 ] & & ! strcasecmp ( argv [ 3 ] , " as " ) ) {
as = argv [ 4 ] ;
}
2010-12-16 19:01:06 +00:00
2011-07-29 23:33:42 +00:00
if ( ! zstr ( as ) & & ! strcasecmp ( as , " xml " ) ) {
stream - > write_function ( stream , " <channels> \n " ) ;
if ( ! span ) {
stream - > write_function ( stream , " <error>invalid span</error> \n " ) ;
} else {
if ( chan_id ) {
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " <error>invalid channel</error> \n " ) ;
2010-12-16 19:01:06 +00:00
} else {
2011-07-29 23:33:42 +00:00
dump_chan_xml ( span , chan_id , stream ) ;
2010-12-16 19:01:06 +00:00
}
} else {
2011-07-29 23:33:42 +00:00
chaniter = ftdm_span_get_chan_iterator ( span , NULL ) ;
for ( curr = chaniter ; curr ; curr = ftdm_iterator_next ( curr ) ) {
dump_chan_xml ( span , ftdm_channel_get_id ( ftdm_iterator_current ( curr ) ) , stream ) ;
2010-12-16 19:01:06 +00:00
}
2011-07-29 23:33:42 +00:00
ftdm_iterator_free ( chaniter ) ;
2010-12-16 19:01:06 +00:00
}
}
2011-07-29 23:33:42 +00:00
stream - > write_function ( stream , " </channels> \n " ) ;
} else {
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
2008-04-01 17:29:57 +00:00
} else {
2011-07-29 23:33:42 +00:00
if ( chan_id ) {
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
2009-07-31 19:16:47 +00:00
} else {
2011-07-29 23:33:42 +00:00
char * dbgstr = NULL ;
ftdm_channel_t * fchan = ftdm_span_get_channel ( span , chan_id ) ;
dump_chan ( span , chan_id , stream ) ;
dbgstr = ftdm_channel_get_history_str ( fchan ) ;
stream - > write_function ( stream , " %s \n " , dbgstr ) ;
ftdm_free ( dbgstr ) ;
2009-07-31 19:16:47 +00:00
}
} else {
2011-07-29 23:33:42 +00:00
stream - > write_function ( stream , " +OK \n " ) ;
chaniter = ftdm_span_get_chan_iterator ( span , NULL ) ;
for ( curr = chaniter ; curr ; curr = ftdm_iterator_next ( curr ) ) {
dump_chan ( span , ftdm_channel_get_id ( ftdm_iterator_current ( curr ) ) , stream ) ;
2009-11-25 22:53:23 +00:00
}
2011-07-29 23:33:42 +00:00
ftdm_iterator_free ( chaniter ) ;
2008-04-01 17:29:57 +00:00
}
}
2011-07-29 23:33:42 +00:00
}
2009-01-06 01:07:09 +00:00
2011-07-29 23:33:42 +00:00
end :
return SWITCH_STATUS_SUCCESS ;
}
2009-01-06 01:07:09 +00:00
2011-07-29 23:33:42 +00:00
static switch_status_t ftdm_cmd_sigstatus ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
ftdm_span_t * span = NULL ;
ftdm_signaling_status_t sigstatus ;
2009-01-06 01:07:09 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm sigstatus get|set [<span_id>] [<chan_id>] [<sigstatus>] \n " ) ;
goto end ;
}
if ( ! strcasecmp ( argv [ 1 ] , " get " ) & & argc < 3 ) {
stream - > write_function ( stream , " -ERR sigstatus get usage: get <span_id> \n " ) ;
goto end ;
}
if ( ! strcasecmp ( argv [ 1 ] , " set " ) & & argc ! = 5 ) {
stream - > write_function ( stream , " -ERR sigstatus set usage: set <span_id> <chan_id>|all <sigstatus> \n " ) ;
goto end ;
}
2009-01-30 11:37:11 +00:00
2011-07-29 23:33:42 +00:00
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
2009-01-30 11:37:11 +00:00
2011-07-29 23:33:42 +00:00
if ( ! strcasecmp ( argv [ 1 ] , " get " ) ) {
if ( argc = = 4 ) {
uint32_t chan_id = atol ( argv [ 3 ] ) ;
ftdm_channel_t * fchan = ftdm_span_get_channel ( span , chan_id ) ;
if ( ! fchan ) {
stream - > write_function ( stream , " -ERR failed to get channel id '%d' \n " , chan_id ) ;
2009-01-30 11:37:11 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
if ( ( FTDM_SUCCESS = = ftdm_channel_get_sig_status ( fchan , & sigstatus ) ) ) {
stream - > write_function ( stream , " channel %d signaling status: %s \n " , chan_id , ftdm_signaling_status2str ( sigstatus ) ) ;
} else {
stream - > write_function ( stream , " -ERR failed to get channel sigstatus \n " ) ;
}
2010-05-25 22:21:34 +00:00
goto end ;
} else {
2011-07-29 23:33:42 +00:00
if ( ( FTDM_SUCCESS = = ftdm_span_get_sig_status ( span , & sigstatus ) ) ) {
stream - > write_function ( stream , " signaling_status: %s \n " , ftdm_signaling_status2str ( sigstatus ) ) ;
} else {
stream - > write_function ( stream , " -ERR failed to read span status: %s \n " , ftdm_span_get_last_error ( span ) ) ;
}
2010-05-25 22:21:34 +00:00
}
2011-07-29 23:33:42 +00:00
goto end ;
}
if ( ! strcasecmp ( argv [ 1 ] , " set " ) ) {
sigstatus = ftdm_str2ftdm_signaling_status ( argv [ 4 ] ) ;
2010-05-25 22:21:34 +00:00
2011-07-29 23:33:42 +00:00
if ( ! strcasecmp ( argv [ 3 ] , " all " ) ) {
if ( ( FTDM_SUCCESS = = ftdm_span_set_sig_status ( span , sigstatus ) ) ) {
stream - > write_function ( stream , " Signaling status of all channels from span %s set to %s \n " ,
ftdm_span_get_name ( span ) , ftdm_signaling_status2str ( sigstatus ) ) ;
} else {
stream - > write_function ( stream , " -ERR failed to set span sigstatus to '%s' \n " , ftdm_signaling_status2str ( sigstatus ) ) ;
}
2010-05-25 22:21:34 +00:00
goto end ;
2011-07-29 23:33:42 +00:00
} else {
uint32_t chan_id = atol ( argv [ 3 ] ) ;
ftdm_channel_t * fchan = ftdm_span_get_channel ( span , chan_id ) ;
if ( ! fchan ) {
stream - > write_function ( stream , " -ERR failed to get channel id '%d' \n " , chan_id ) ;
2010-05-25 22:21:34 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
if ( ( FTDM_SUCCESS = = ftdm_channel_set_sig_status ( fchan , sigstatus ) ) ) {
stream - > write_function ( stream , " Signaling status of channel %d set to %s \n " , chan_id ,
ftdm_signaling_status2str ( sigstatus ) ) ;
} else {
stream - > write_function ( stream , " -ERR failed to set span sigstatus to '%s' \n " , ftdm_signaling_status2str ( sigstatus ) ) ;
2010-05-25 22:21:34 +00:00
}
2011-07-29 23:33:42 +00:00
goto end ;
2010-05-25 22:21:34 +00:00
}
2011-07-29 23:33:42 +00:00
}
2010-05-25 22:21:34 +00:00
2011-07-29 23:33:42 +00:00
end :
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t ftdm_cmd_trace ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
char tracepath [ 255 ] ;
unsigned i = 0 ;
uint32_t chan_id = 0 ;
uint32_t span_id = 0 ;
uint32_t chan_count = 0 ;
ftdm_span_t * span = NULL ;
ftdm_channel_t * chan = NULL ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm trace <path> <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
chan_count = ftdm_span_get_chan_count ( span ) ;
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
2010-05-28 16:44:37 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
span_id = ftdm_span_get_id ( span ) ;
if ( chan_id ) {
chan = ftdm_span_get_channel ( span , chan_id ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-in-s%dc%d " , argv [ 1 ] , span_id , chan_id ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_TRACE_INPUT , tracepath ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-out-s%dc%d " , argv [ 1 ] , span_id , chan_id ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_TRACE_OUTPUT , tracepath ) ;
} else {
for ( i = 1 ; i < = chan_count ; i + + ) {
chan = ftdm_span_get_channel ( span , i ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-in-s%dc%d " , argv [ 1 ] , span_id , i ) ;
2010-05-28 16:44:37 +00:00
ftdm_channel_command ( chan , FTDM_COMMAND_TRACE_INPUT , tracepath ) ;
2011-07-29 23:33:42 +00:00
snprintf ( tracepath , sizeof ( tracepath ) , " %s-out-s%dc%d " , argv [ 1 ] , span_id , i ) ;
2010-05-28 16:44:37 +00:00
ftdm_channel_command ( chan , FTDM_COMMAND_TRACE_OUTPUT , tracepath ) ;
}
2011-07-29 23:33:42 +00:00
}
stream - > write_function ( stream , " +OK trace enabled with prefix path %s \n " , argv [ 1 ] ) ;
end :
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t ftdm_cmd_notrace ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
uint32_t i = 0 ;
uint32_t chan_id = 0 ;
uint32_t chan_count = 0 ;
ftdm_channel_t * fchan = NULL ;
ftdm_span_t * span = NULL ;
if ( argc < 2 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm notrace <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
chan_count = ftdm_span_get_chan_count ( span ) ;
if ( argc > 2 ) {
chan_id = atoi ( argv [ 2 ] ) ;
if ( chan_id > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
2010-05-28 16:44:37 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
if ( chan_id ) {
fchan = ftdm_span_get_channel ( span , chan_id ) ;
ftdm_channel_command ( fchan , FTDM_COMMAND_TRACE_END_ALL , NULL ) ;
} else {
for ( i = 1 ; i < = chan_count ; i + + ) {
fchan = ftdm_span_get_channel ( span , i ) ;
2010-05-28 16:44:37 +00:00
ftdm_channel_command ( fchan , FTDM_COMMAND_TRACE_END_ALL , NULL ) ;
2010-01-06 20:58:21 +00:00
}
2011-07-29 23:33:42 +00:00
}
stream - > write_function ( stream , " +OK trace disabled \n " ) ;
end :
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t ftdm_cmd_gains ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
unsigned int i = 0 ;
float txgain = 0.0 ;
float rxgain = 0.0 ;
uint32_t chan_id = 0 ;
uint32_t ccount = 0 ;
ftdm_channel_t * chan ;
ftdm_span_t * span = NULL ;
if ( argc < 4 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm gains <rxgain> <txgain> <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 3 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 4 ) {
chan_id = atoi ( argv [ 4 ] ) ;
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
2010-01-06 20:58:21 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
i = sscanf ( argv [ 1 ] , " %f " , & rxgain ) ;
i + = sscanf ( argv [ 2 ] , " %f " , & txgain ) ;
if ( i ! = 2 ) {
stream - > write_function ( stream , " -ERR invalid gains \n " ) ;
goto end ;
}
2010-04-21 15:20:05 +00:00
2011-07-29 23:33:42 +00:00
if ( chan_id ) {
chan = ftdm_span_get_channel ( span , chan_id ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_SET_RX_GAIN , & rxgain ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_SET_TX_GAIN , & txgain ) ;
} else {
ccount = ftdm_span_get_chan_count ( span ) ;
for ( i = 1 ; i < ccount ; i + + ) {
chan = ftdm_span_get_channel ( span , i ) ;
2010-04-21 15:20:05 +00:00
ftdm_channel_command ( chan , FTDM_COMMAND_SET_RX_GAIN , & rxgain ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_SET_TX_GAIN , & txgain ) ;
2010-01-06 20:58:21 +00:00
}
2011-07-29 23:33:42 +00:00
}
stream - > write_function ( stream , " +OK gains set to Rx %f and Tx %f \n " , rxgain , txgain ) ;
end :
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t ftdm_cmd_dtmf ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
unsigned i = 0 ;
uint32_t chan_id = 0 ;
unsigned schan_count = 0 ;
ftdm_span_t * span = NULL ;
ftdm_command_t fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT ;
ftdm_channel_t * fchan ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: dtmf on|off <span_id> [<chan_id>] \n " ) ;
goto end ;
}
if ( switch_true ( argv [ 1 ] ) ) {
fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT ;
} else {
fcmd = FTDM_COMMAND_DISABLE_DTMF_DETECT ;
}
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
schan_count = ftdm_span_get_chan_count ( span ) ;
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > schan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
2011-03-21 18:25:20 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
if ( chan_id ) {
fchan = ftdm_span_get_channel ( span , chan_id ) ;
ftdm_channel_command ( fchan , fcmd , NULL ) ;
} else {
for ( i = 1 ; i < = schan_count ; i + + ) {
fchan = ftdm_span_get_channel ( span , i ) ;
ftdm_channel_command ( fchan , fcmd , NULL ) ;
2011-03-21 18:25:20 +00:00
}
2011-07-29 23:33:42 +00:00
}
stream - > write_function ( stream , " +OK DTMF detection was %s \n " , fcmd = = FTDM_COMMAND_ENABLE_DTMF_DETECT ? " enabled " : " disabled " ) ;
end :
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t ftdm_cmd_queuesize ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
unsigned int i = 0 ;
uint32_t rxsize = 10 ;
uint32_t txsize = 10 ;
uint32_t chan_id = 0 ;
uint32_t ccount = 0 ;
ftdm_channel_t * chan ;
ftdm_span_t * span = NULL ;
if ( argc < 4 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm queuesize <rxsize> <txsize> <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 3 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 4 ) {
chan_id = atoi ( argv [ 4 ] ) ;
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
2011-03-21 18:25:20 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
i = sscanf ( argv [ 1 ] , " %u " , & rxsize ) ;
i + = sscanf ( argv [ 2 ] , " %u " , & txsize ) ;
if ( i ! = 2 ) {
stream - > write_function ( stream , " -ERR invalid queue sizes provided \n " ) ;
goto end ;
}
2011-03-21 18:25:20 +00:00
2011-07-29 23:33:42 +00:00
if ( chan_id ) {
chan = ftdm_span_get_channel ( span , chan_id ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_SET_RX_QUEUE_SIZE , & rxsize ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_SET_TX_QUEUE_SIZE , & txsize ) ;
} else {
ccount = ftdm_span_get_chan_count ( span ) ;
for ( i = 1 ; i < ccount ; i + + ) {
chan = ftdm_span_get_channel ( span , i ) ;
2011-03-21 18:25:20 +00:00
ftdm_channel_command ( chan , FTDM_COMMAND_SET_RX_QUEUE_SIZE , & rxsize ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_SET_TX_QUEUE_SIZE , & txsize ) ;
2010-12-14 16:23:47 +00:00
}
2011-07-29 23:33:42 +00:00
}
stream - > write_function ( stream , " +OK queue sizes set to Rx %d and Tx %d \n " , rxsize , txsize ) ;
end :
return SWITCH_STATUS_SUCCESS ;
}
2011-03-25 20:48:57 +00:00
2011-07-30 21:39:29 +00:00
static void exec_io_command ( const char * cmd , switch_stream_handle_t * stream , ftdm_channel_t * fchan )
{
int enable = 0 ;
ftdm_channel_iostats_t stats ;
if ( ! strcasecmp ( " enable " , cmd ) ) {
enable = 1 ;
ftdm_channel_command ( fchan , FTDM_COMMAND_SWITCH_IOSTATS , & enable ) ;
} else if ( ! strcasecmp ( " disable " , cmd ) ) {
enable = 0 ;
ftdm_channel_command ( fchan , FTDM_COMMAND_SWITCH_IOSTATS , & enable ) ;
} else if ( ! strcasecmp ( " flush " , cmd ) ) {
ftdm_channel_command ( fchan , FTDM_COMMAND_FLUSH_IOSTATS , NULL ) ;
} else {
ftdm_channel_command ( fchan , FTDM_COMMAND_GET_IOSTATS , & stats ) ;
stream - > write_function ( stream , " -- IO statistics for channel %d:%d -- \n " ,
ftdm_channel_get_span_id ( fchan ) , ftdm_channel_get_id ( fchan ) ) ;
stream - > write_function ( stream , " Rx errors: %u \n " , stats . rx . errors ) ;
stream - > write_function ( stream , " Rx queue size: %u \n " , stats . rx . queue_size ) ;
stream - > write_function ( stream , " Rx queue len: %u \n " , stats . rx . queue_len ) ;
stream - > write_function ( stream , " Rx count: %lu \n " , stats . rx . packets ) ;
stream - > write_function ( stream , " Tx errors: %u \n " , stats . tx . errors ) ;
2011-08-03 17:05:02 +00:00
stream - > write_function ( stream , " Tx queue size: %u \n " , stats . tx . queue_size ) ;
2011-07-30 21:39:29 +00:00
stream - > write_function ( stream , " Tx queue len: %u \n " , stats . tx . queue_len ) ;
stream - > write_function ( stream , " Tx count: %lu \n " , stats . tx . packets ) ;
stream - > write_function ( stream , " Tx idle: %u \n " , stats . tx . idle_packets ) ;
}
}
static switch_status_t ftdm_cmd_iostats ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] )
{
uint32_t chan_id = 0 ;
ftdm_channel_t * chan ;
ftdm_iterator_t * iter = NULL ;
ftdm_iterator_t * curr = NULL ;
ftdm_span_t * span = NULL ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm iostats enable|disable|flush|print <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
chan = ftdm_span_get_channel ( span , chan_id ) ;
exec_io_command ( argv [ 1 ] , stream , chan ) ;
} else {
iter = ftdm_span_get_chan_iterator ( span , NULL ) ;
for ( curr = iter ; curr ; curr = ftdm_iterator_next ( curr ) ) {
chan = ftdm_iterator_current ( curr ) ;
exec_io_command ( argv [ 1 ] , stream , chan ) ;
}
ftdm_iterator_free ( iter ) ;
}
stream - > write_function ( stream , " +OK \n " ) ;
end :
return SWITCH_STATUS_SUCCESS ;
}
2011-07-29 23:33:42 +00:00
typedef switch_status_t ( * ftdm_cli_function_t ) ( const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] ) ;
typedef struct ftdm_cli_entry {
const char * name ;
const char * args ;
const char * complete ;
ftdm_cli_function_t execute ;
} ftdm_cli_entry_t ;
2011-03-25 20:48:57 +00:00
2011-07-29 23:33:42 +00:00
static ftdm_cli_entry_t ftdm_cli_options [ ] =
{
{ " list " , " " , " " , ftdm_cmd_list } ,
{ " start " , " <span_id|span_name> " , " " , ftdm_cmd_start_stop } ,
{ " stop " , " <span_id|span_name> " , " " , ftdm_cmd_start_stop } ,
{ " reset " , " <span_id|span_name> [<chan_id>] " , " " , ftdm_cmd_reset } ,
{ " dump " , " <span_id|span_name> [<chan_id>] " , " " , ftdm_cmd_dump } ,
{ " sigstatus " , " get|set <span_id|span_name> [<chan_id>] [<sigstatus>] " , " ::[set:get " , ftdm_cmd_sigstatus } ,
{ " trace " , " <path> <span_id|span_name> [<chan_id>] " , " " , ftdm_cmd_trace } ,
{ " notrace " , " <span_id|span_name> [<chan_id>] " , " " , ftdm_cmd_notrace } ,
{ " gains " , " <rxgain> <txgain> <span_id|span_name> [<chan_id>] " , " " , ftdm_cmd_gains } ,
{ " dtmf " , " on|off <span_id|span_name> [<chan_id>] " , " ::[on:off " , ftdm_cmd_dtmf } ,
{ " queuesize " , " <rxsize> <txsize> <span_id|span_name> [<chan_id>] " , " " , ftdm_cmd_queuesize } ,
2011-07-30 21:39:29 +00:00
{ " iostats " , " enable|disable|flush|print <span_id|span_name> <chan_id> " , " ::[enable:disable:flush:print " , ftdm_cmd_iostats } ,
2011-07-29 23:33:42 +00:00
{ " voice_detect " , " [on|off] <span_id|span_name> [<chan_id>] " , " ::[on:off " , ftdm_cmd_voice_detect } ,
/* Fake handlers as they are handled within freetdm library,
* we should provide a way inside freetdm to query for completions from signaling modules */
{ " core state " , " [!]<state_name> " , " " , NULL } ,
{ " core flag " , " [!]<flag_value> " , " " , NULL } ,
{ " core calls " , " " , " " , NULL } ,
} ;
static void print_full_usage ( switch_stream_handle_t * stream )
{
int i = 0 ;
ftdm_cli_entry_t * entry = NULL ;
stream - > write_function ( stream , " USAGE: \n " ) ;
stream - > write_function ( stream , " -------------------------------------------------------------------------------- \n " ) ;
for ( i = 0 ; i < ftdm_array_len ( ftdm_cli_options ) ; i + + ) {
entry = & ftdm_cli_options [ i ] ;
stream - > write_function ( stream , " ftdm %s %s \n " , entry - > name , entry - > args ) ;
}
stream - > write_function ( stream , " -------------------------------------------------------------------------------- \n " ) ;
}
SWITCH_STANDARD_API ( ft_function )
{
char * mycmd = NULL , * argv [ 10 ] = { 0 } ;
int argc = 0 ;
int i = 0 ;
ftdm_cli_entry_t * entry = NULL ;
if ( ! zstr ( cmd ) & & ( mycmd = strdup ( cmd ) ) ) {
argc = switch_separate_string ( mycmd , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
}
if ( ! argc ) {
print_full_usage ( stream ) ;
goto end ;
}
2010-04-13 19:17:32 +00:00
2011-07-29 23:33:42 +00:00
for ( i = 0 ; i < ftdm_array_len ( ftdm_cli_options ) ; i + + ) {
entry = & ftdm_cli_options [ i ] ;
if ( ! strcasecmp ( argv [ 0 ] , entry - > name ) & & entry - > execute ) {
entry - > execute ( cmd , session , stream , argc , argv ) ;
break ;
}
}
/* if the command was not found in the main CLI entries, try to execute it as a FreeTDM API */
if ( i = = ftdm_array_len ( ftdm_cli_options ) ) {
2010-04-26 20:55:44 +00:00
char * rply = ftdm_api_execute ( cmd ) ;
2009-02-09 19:13:02 +00:00
if ( rply ) {
stream - > write_function ( stream , " %s " , rply ) ;
2010-09-22 18:59:06 +00:00
ftdm_free ( rply ) ;
2009-02-09 19:13:02 +00:00
} else {
2011-07-29 23:33:42 +00:00
print_full_usage ( stream ) ;
2009-02-09 19:13:02 +00:00
}
2008-04-01 17:29:57 +00:00
}
2011-07-29 23:33:42 +00:00
end :
2008-04-01 17:29:57 +00:00
switch_safe_free ( mycmd ) ;
return SWITCH_STATUS_SUCCESS ;
}
2010-05-26 15:17:47 +00:00
SWITCH_STANDARD_APP ( enable_dtmf_function )
{
private_t * tech_pvt ;
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_ENABLE_DTMF_DETECT , NULL ) ;
ftdm_log ( FTDM_LOG_INFO , " DTMF detection enabled in channel %d:%d \n " , ftdm_channel_get_id ( tech_pvt - > ftdmchan ) , ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ) ;
}
2010-05-25 22:21:34 +00:00
SWITCH_STANDARD_APP ( disable_dtmf_function )
{
private_t * tech_pvt ;
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_DISABLE_DTMF_DETECT , NULL ) ;
ftdm_log ( FTDM_LOG_INFO , " DTMF detection Disabled in channel %d:%d \n " , ftdm_channel_get_id ( tech_pvt - > ftdmchan ) , ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ) ;
}
2008-04-01 17:29:57 +00:00
2008-07-30 15:05:07 +00:00
SWITCH_STANDARD_APP ( disable_ec_function )
{
private_t * tech_pvt ;
int x = 0 ;
2010-01-15 19:22:49 +00:00
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
2008-07-30 15:05:07 +00:00
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
2010-01-15 19:22:49 +00:00
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_DISABLE_ECHOCANCEL , & x ) ;
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_DISABLE_ECHOTRAIN , & x ) ;
ftdm_log ( FTDM_LOG_INFO , " Echo Canceller Disabled \n " ) ;
2008-07-30 15:05:07 +00:00
}
2010-01-15 19:22:49 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_freetdm_load )
2007-05-26 04:45:31 +00:00
{
2011-07-29 23:33:42 +00:00
int i = 0 ;
ftdm_cli_entry_t * entry = NULL ;
switch_api_interface_t * commands_api_interface = NULL ;
switch_application_interface_t * app_interface = NULL ;
2008-04-01 17:29:57 +00:00
2007-07-03 20:38:43 +00:00
module_pool = pool ;
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
ftdm_global_set_logger ( ftdm_logger ) ;
2010-04-05 21:49:43 +00:00
2010-09-21 17:56:11 +00:00
ftdm_global_set_mod_directory ( SWITCH_GLOBAL_dirs . mod_dir ) ;
ftdm_global_set_config_directory ( SWITCH_GLOBAL_dirs . conf_dir ) ;
2010-01-15 19:22:49 +00:00
if ( ftdm_global_init ( ) ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error loading FreeTDM \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_TERM ;
}
2010-01-15 19:22:49 +00:00
if ( ftdm_global_configuration ( ) ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error configuring FreeTDM \n " ) ;
2009-11-18 17:13:33 +00:00
return SWITCH_STATUS_TERM ;
}
2007-05-26 04:45:31 +00:00
if ( load_config ( ) ! = SWITCH_STATUS_SUCCESS ) {
2010-01-15 19:22:49 +00:00
ftdm_global_destroy ( ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_TERM ;
}
2007-07-03 20:38:43 +00:00
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
2010-01-15 19:22:49 +00:00
freetdm_endpoint_interface = switch_loadable_module_create_interface ( * module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
freetdm_endpoint_interface - > interface_name = " freetdm " ;
freetdm_endpoint_interface - > io_routines = & freetdm_io_routines ;
freetdm_endpoint_interface - > state_handler = & freetdm_state_handlers ;
2008-04-01 17:29:57 +00:00
2011-07-29 23:33:42 +00:00
SWITCH_ADD_API ( commands_api_interface , " ftdm " , " FreeTDM commands " , ft_function , " <cmd> <args> " ) ;
for ( i = 0 ; i < ftdm_array_len ( ftdm_cli_options ) ; i + + ) {
char complete_cli [ 512 ] ;
entry = & ftdm_cli_options [ i ] ;
snprintf ( complete_cli , sizeof ( complete_cli ) , " add ftdm %s %s " , entry - > name , entry - > complete ) ;
switch_console_set_complete ( complete_cli ) ;
}
2007-05-26 04:45:31 +00:00
2008-07-30 15:05:07 +00:00
SWITCH_ADD_APP ( app_interface , " disable_ec " , " Disable Echo Canceller " , " Disable Echo Canceller " , disable_ec_function , " " , SAF_NONE ) ;
2010-05-25 22:21:34 +00:00
SWITCH_ADD_APP ( app_interface , " disable_dtmf " , " Disable DTMF Detection " , " Disable DTMF Detection " , disable_dtmf_function , " " , SAF_NONE ) ;
2010-05-26 15:17:47 +00:00
SWITCH_ADD_APP ( app_interface , " enable_dtmf " , " Enable DTMF Detection " , " Enable DTMF Detection " , enable_dtmf_function , " " , SAF_NONE ) ;
2008-07-30 15:05:07 +00:00
2007-05-26 04:45:31 +00:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
2010-01-15 19:22:49 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_freetdm_shutdown )
2007-11-24 18:04:14 +00:00
{
2010-04-14 22:15:22 +00:00
switch_hash_index_t * hi ;
const void * var ;
void * val ;
/* destroy ss7 configs */
for ( hi = switch_hash_first ( NULL , globals . ss7_configs ) ; hi ; hi = switch_hash_next ( hi ) ) {
switch_hash_this ( hi , & var , NULL , & val ) ;
ftdm_conf_node_destroy ( val ) ;
}
2010-01-15 19:22:49 +00:00
ftdm_global_destroy ( ) ;
2009-02-07 23:14:25 +00:00
// this breaks pika but they are MIA so *shrug*
//return SWITCH_STATUS_NOUNLOAD;
return SWITCH_STATUS_SUCCESS ;
2007-11-24 18:04:14 +00:00
}
2007-05-26 04:45:31 +00:00
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2009-09-14 22:06:20 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2007-05-26 04:45:31 +00:00
*/