2012-09-11 15:12:31 +00:00
/*
2007-05-26 04:45:31 +00:00
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2012-04-18 16:51:48 +00:00
* Copyright ( C ) 2005 - 2012 , Anthony Minessale II < anthm @ freeswitch . org >
2007-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 ) :
2012-09-11 15:12:31 +00:00
*
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-24 20:43:23 +00:00
* James Zhang < jzhang @ sangoma . com >
2012-05-07 19:35:13 +00:00
* Gideon Sadan < gsadan @ 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
2011-09-12 22:12:12 +00:00
//#define CUDATEL_DEBUG
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_"
2012-09-11 15:12:31 +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
2012-05-18 06:35:25 +00:00
# define get_ss7_config_node(_cfg, _confname) _get_ss7_config_node(cfg, confname, "ISUP")
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 ] ;
2012-09-11 15:12:31 +00:00
char type [ 256 ] ;
2010-05-20 15:43:40 +00:00
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 ,
2012-09-11 15:12:31 +00:00
switch_core_session_t * * new_session ,
2008-01-08 23:33:07 +00:00
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 ) ;
2012-09-13 04:00:26 +00:00
#if 0
2012-07-25 22:57:32 +00:00
void ctdm_init ( switch_loadable_module_interface_t * module_interface ) ;
2012-09-13 04:00:26 +00:00
# endif
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 ;
}
2012-09-11 15:12:31 +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 ;
}
2012-09-11 15:12:31 +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 ) ;
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 ) ;
2012-05-29 18:10:15 +00:00
buuid = switch_channel_get_partner_uuid ( channel ) ;
2008-01-10 00:47:04 +00:00
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
2012-09-11 15:12: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 ;
2012-09-11 15:12: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 ;
2012-09-11 15:12:31 +00:00
2009-04-14 19:03:03 +00:00
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
2012-09-11 15:12:31 +00:00
2009-04-14 19:03:03 +00:00
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
2013-01-17 15:03:40 +00:00
switch_core_session_unset_read_codec ( session ) ;
switch_core_session_unset_write_codec ( session ) ;
2009-04-14 19:03:03 +00:00
}
return SWITCH_STATUS_SUCCESS ;
}
2012-07-11 15:21:49 +00:00
# ifdef CUDATEL_DEBUG
struct cudatel_trace_priv {
const char * name ;
int span_id ;
int chan_id ;
} ;
static void cudatel_trace ( const int tid , const void * addr , const char * symbol , void * priv )
{
struct cudatel_trace_priv * data = priv ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " [%d:%d][tid:%d] %s -> %s \n " ,
data - > span_id , data - > chan_id , tid , data - > name , symbol ) ;
}
# endif
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 ;
2011-09-12 22:12:12 +00:00
const char * name = NULL ;
2011-09-15 17:50:42 +00:00
int span_id = 0 ;
int chan_id = 0 ;
2011-10-07 13:38:48 +00:00
uint32_t t = 0 ;
2010-04-21 15:20:05 +00:00
uint32_t tokencnt ;
2011-09-15 23:32:08 +00:00
char * uuid = NULL ;
const char * token = NULL ;
uint8_t uuid_found = 0 ;
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-09-12 19:21:23 +00:00
/* ignore any further I/O requests, we're hanging up already! */
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2012-09-11 15:12:31 +00:00
2011-09-12 22:12:12 +00:00
name = switch_channel_get_name ( channel ) ;
2011-09-15 17:50:42 +00:00
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 ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " [%d:%d] %s CHANNEL HANGUP ENTER \n " , span_id , chan_id , name ) ;
2011-09-12 22:12:12 +00:00
2011-09-15 23:32:08 +00:00
/* First verify this call has a device attached */
2010-02-09 22:01:15 +00:00
if ( ! tech_pvt - > ftdmchan ) {
2011-09-15 17:50:42 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s does not have any ftdmchan attached \n " , name ) ;
2010-02-09 22:01:15 +00:00
goto end ;
2011-09-12 22:12:12 +00:00
}
2012-09-11 15:12:31 +00:00
/* Now verify the device is still attached to this call :-)
2011-09-15 23:32:08 +00:00
* 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 + + ) {
2011-09-16 20:53:49 +00:00
token = ftdm_channel_get_token ( tech_pvt - > ftdmchan , t ) ;
2011-09-16 19:52:14 +00:00
if ( ! zstr ( token ) & & ! strcasecmp ( uuid , token ) ) {
2011-09-15 23:32:08 +00:00
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 ;
}
2011-09-12 22:12:12 +00:00
# ifdef CUDATEL_DEBUG
{
2012-07-11 15:21:49 +00:00
struct cudatel_trace_priv trace_data ;
trace_data . name = name ;
trace_data . span_id = span_id ;
trace_data . chan_id = chan_id ;
ftdm_backtrace_walk ( & cudatel_trace , & trace_data ) ;
2011-09-12 22:12:12 +00:00
}
# endif
2007-06-11 18:15:09 +00:00
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
2011-09-12 19:21:23 +00:00
chantype = ftdm_channel_get_type ( tech_pvt - > ftdmchan ) ;
2010-04-21 15:20:05 +00:00
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
{
2012-03-19 13:20:44 +00:00
tokencnt = ftdm_channel_get_token_count ( tech_pvt - > ftdmchan ) ;
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 ) ) {
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 ;
2012-09-11 15:12:31 +00:00
default :
2007-05-27 14:58:01 +00:00
{
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-26 04:45:31 +00:00
switch_mutex_lock ( globals . mutex ) ;
globals . calls - - ;
if ( globals . calls < 0 ) {
globals . calls = 0 ;
}
switch_mutex_unlock ( globals . mutex ) ;
2011-09-15 17:50:42 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " [%d:%d] %s CHANNEL HANGUP EXIT \n " , span_id , chan_id , name ) ;
2007-05-26 04:45:31 +00:00
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 ;
2012-09-11 15:12:31 +00:00
}
2010-02-09 22:01:15 +00:00
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 ) ;
2012-09-11 15:12:31 +00:00
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 ;
2011-09-12 19:21:23 +00:00
const char * name = NULL ;
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 ) ;
2012-09-11 15:12:31 +00:00
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2011-09-12 19:21:23 +00:00
name = switch_channel_get_name ( channel ) ;
2011-06-07 21:35:49 +00:00
if ( ! tech_pvt - > ftdmchan ) {
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " no ftdmchan set in channel %s! \n " , name ) ;
2011-06-07 21:35:49 +00:00
return SWITCH_STATUS_FALSE ;
2012-09-11 15:12:31 +00:00
}
2011-06-07 21:35:49 +00:00
span_id = ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ;
chan_id = ftdm_channel_get_id ( tech_pvt - > ftdmchan ) ;
2011-09-12 19:21:23 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " TFLAG_DEAD is set in channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
return SWITCH_STATUS_FALSE ;
2012-09-11 15:12:31 +00:00
}
2011-06-07 21:35:49 +00:00
2012-09-11 15:12:31 +00:00
/* Digium Cards sometimes timeout several times in a row here.
2009-05-26 21:47:48 +00:00
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 ;
}
2012-09-11 15:12:31 +00:00
2007-05-27 14:58:01 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " TFLAG_IO is not set in channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2012-09-11 15:12:31 +00:00
wflags = FTDM_READ ;
2010-01-15 19:22:49 +00:00
status = ftdm_channel_wait ( tech_pvt - > ftdmchan , & wflags , chunk ) ;
2012-09-11 15:12:31 +00:00
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_FAIL ) {
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to read from channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2012-09-11 15:12:31 +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 ) {
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Too many timeouts while waiting I/O in channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
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-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Failed to read from channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2011-06-07 21:35:49 +00:00
if ( + + tech_pvt - > read_error > FTDM_MAX_READ_WRITE_ERRORS ) {
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " too many I/O read errors on channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2011-06-07 21:35:49 +00:00
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 ) ) ) {
2011-08-31 18:44:48 +00:00
switch_dtmf_t _dtmf = { 0 , switch_core_default_dtmf_duration ( 0 ) } ;
2008-01-12 06:11:48 +00:00
char * p ;
for ( p = dtmf ; p & & * p ; p + + ) {
if ( is_dtmf ( * p ) ) {
_dtmf . digit = * p ;
2011-09-12 19:21:23 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Queuing DTMF [%c] in channel %s device %d:%d \n " , * p , name , span_id , chan_id ) ;
2008-01-12 06:11:48 +00:00
switch_channel_queue_dtmf ( channel , & _dtmf ) ;
}
}
2007-05-26 04:45:31 +00:00
}
2011-09-12 19:21:23 +00:00
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
2011-09-12 19:21:23 +00:00
fail :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " clearing IO in channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2007-11-17 01:39:28 +00:00
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 } ;
2011-09-12 19:21:23 +00:00
const char * name = " (none) " ;
2010-01-15 19:22:49 +00:00
ftdm_wait_flag_t wflags = FTDM_WRITE ;
2011-09-12 19:21:23 +00:00
uint32_t span_id = 0 , chan_id = 0 ;
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 ) ;
2011-09-12 19:21:23 +00:00
name = switch_channel_get_name ( channel ) ;
if ( ! tech_pvt - > ftdmchan ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " no ftdmchan set in channel %s! \n " , name ) ;
return SWITCH_STATUS_FALSE ;
2012-09-11 15:12:31 +00:00
}
2011-09-12 19:21:23 +00:00
span_id = ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ;
chan_id = ftdm_channel_get_id ( tech_pvt - > ftdmchan ) ;
2012-09-11 15:12:31 +00:00
2008-10-17 23:00:47 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " TFLAG_DEAD is set in channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2008-10-17 23:00:47 +00:00
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 ) ) {
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " TFLAG_IO is not set in channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
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
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 ) ;
}
2012-09-11 15:12:31 +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 ) ;
2012-09-11 15:12:31 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ( wflags & FTDM_WRITE ) ) {
2012-08-08 15:30:03 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Dropping frame! (write not ready) in channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2010-02-25 23:36:18 +00:00
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-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Failed to write to channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2011-06-07 21:35:49 +00:00
if ( + + tech_pvt - > write_error > FTDM_MAX_READ_WRITE_ERRORS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG ,
2011-09-12 19:21:23 +00:00
SWITCH_LOG_ERROR , " Too many I/O write errors on channel %s device %d:%d! \n " , name , 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 :
2011-09-12 19:21:23 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Error writing to channel %s device %d:%d! \n " , name , span_id , chan_id ) ;
2007-11-17 01:39:28 +00:00
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 ) ;
2012-09-11 15:12:31 +00:00
2009-08-19 21:47:56 +00:00
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2012-09-11 15:12:31 +00:00
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2012-09-11 15:12:31 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-04-21 15:20:05 +00:00
2012-09-11 15:12:31 +00:00
phy_id = ftdm_channel_get_ph_id ( tech_pvt - > ftdmchan ) ;
2010-04-21 15:20:05 +00:00
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 ) ;
2012-09-11 15:12:31 +00:00
2007-06-13 03:37:55 +00:00
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 ) ;
2012-09-11 15:12: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 ) ;
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 ;
}
2012-09-11 15:12:31 +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 ) ;
2012-09-11 15:12:31 +00:00
2007-05-26 04:45:31 +00:00
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 ;
}
2012-09-11 15:12:31 +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 :
2012-09-11 15:12:31 +00:00
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) & &
2010-04-21 15:20:05 +00:00
! 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 ) ) {
2012-09-11 15:12:31 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
2010-02-09 22:01:15 +00:00
}
if ( ! ( ftdmchan = tech_pvt - > ftdmchan ) ) {
2012-09-11 15:12:31 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-02-09 22:01:15 +00:00
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 ) ;
2012-09-12 23:01:19 +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 ) ;
2012-09-12 23:01:19 +00:00
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 ,
2012-09-11 15:12:31 +00:00
/*.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 )
{
2012-09-12 23:01:19 +00:00
const char * variable = NULL ;
if ( var_event ) {
if ( ( variable = switch_event_get_header ( var_event , variable_name ) ) ) {
return variable ;
}
}
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 ;
2010-11-26 00:19:32 +00:00
}
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 ] ;
2012-09-11 15:12:31 +00:00
snprintf ( spanresource , sizeof ( spanresource ) , " span_%s_%s " , ftdm_channel_get_span_name ( fchan ) ,
2011-01-10 21:49:58 +00:00
caller_data - > dnis . digits ) ;
2012-09-11 15:12:31 +00:00
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 ,
2011-01-10 21:49:58 +00:00
spanresource , SPAN_CONFIG [ span_id ] . limit_calls , SPAN_CONFIG [ span_id ] . limit_seconds ) ;
2012-09-11 15:12:31 +00:00
if ( switch_limit_incr ( " hash " , hdata - > new_session , FREETDM_LIMIT_REALM , spanresource ,
2011-01-10 21:49:58 +00:00
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 ) ) ;
2012-11-05 20:12:38 +00:00
if ( callerid_num & & * callerid_num = = ' + ' ) {
callerid_num + + ;
}
2010-03-10 20:06:31 +00:00
}
2010-02-09 22:01:15 +00:00
2012-09-17 19:30:37 +00:00
if ( ! zstr ( callerid_num ) & & ! strcmp ( callerid_num , SWITCH_DEFAULT_CLID_NUMBER ) ) {
2010-03-10 20:06:31 +00:00
callerid_num = NULL ;
}
2012-09-11 15:12:31 +00:00
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
}
2012-09-11 15:12:31 +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 ] ;
2012-09-11 15:12:31 +00:00
}
2008-10-06 20:02:55 +00:00
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 ) ;
}
2012-09-11 15:12:31 +00:00
2010-06-29 20:29:37 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-CallerNumber " ) ;
if ( sipvar ) {
2012-11-05 20:12:38 +00:00
if ( * sipvar = = ' + ' ) {
sipvar + + ;
}
2010-06-29 20:29:37 +00:00
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 ) ;
}
2012-09-11 15:12:31 +00:00
2010-06-29 20:29:37 +00:00
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-09-12 23:01:19 +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-24 20:43:23 +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 ) ;
2012-02-16 20:14:06 +00:00
}
2012-02-24 20:43:23 +00:00
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
}
2012-09-11 15:12:31 +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 ) ;
}
2012-09-11 15:12:31 +00:00
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 ) ;
}
2012-09-11 15:12:31 +00:00
2011-05-17 21:13:38 +00:00
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-24 20:43:23 +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 ) ;
}
2012-05-30 17:10:04 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-IAM-FWD-IND-HEX " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_iam_fwd_ind_hex " , sipvar ) ;
}
2012-09-12 23:01:19 +00:00
ss7: add ss7_iam_nature_connection_hex to support Nature of Connection
Indicator in IAM message.
- ss7_iam_nature_connection_hex is the channel variable to carry
HEX value from/to IAM message
- X-FreeTDM-IAM-NATURE-CONN-HEX is the x-header string to carry
HEX value from/to sip invite message
- This IE is 8 bit hex, which turns into 2 chars
- Only Satellite indicator, Continuity check indicator, and Echo
control device indicator are supported. Spare value are not taken.
Spare value is always set to all zero.
- example:
To set 00010101 (bit H-A), set X-FreeTDM-IAM-NATURE-CONN-HEX string
value to 15 in the sip invite message to NSG.
When NSG send out sip invite, if the incoming IAM message comes with
Nature of Connection IE, NSG will put X-FreeTDM-IAM-NATURE-CONN-HEX
in the invite x-header. For example, if the IE value is 00001010 in
the IAM, NSG will send X-FreeTDM-IAM-NATURE-CONN-HEX with value string
of "0A".
- Two characters are madatory. "0A" must be specified rather than "A". If
invalid format or characters are found, this x-header will be ommited.
- Valid characters include 0-9, A-F, and a-f
2012-06-27 16:31:35 +00:00
sipvar = switch_channel_get_variable ( channel , " sip_h_X-FreeTDM-IAM-NATURE-CONN-HEX " ) ;
if ( sipvar ) {
ftdm_usrmsg_add_var ( & usrmsg , " ss7_iam_nature_connection_hex " , 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
}
2012-09-11 15:12:31 +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
2012-09-17 15:14:27 +00:00
if ( ( var = channel_get_variable ( session , var_event , " freetdm_outbound_npi " ) ) ) {
ftdm_set_npi ( var , & caller_data . dnis . plan ) ;
} else {
caller_data . dnis . plan = outbound_profile - > destination_number_numplan ;
}
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 ) ;
}
2012-09-11 15:12:31 +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 ) ;
2012-11-05 20:12:38 +00:00
ftdm_set_string ( caller_data . cid_num . digits , switch_str_nil ( callerid_num ) ) ;
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 ) ;
}
2012-09-11 15:12:31 +00:00
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 ;
2012-09-11 15:12:31 +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-24 20:43:23 +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-24 20:43:23 +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-09-12 23:01:19 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Session %s is network-bridged with %s \n " ,
2012-01-27 04:51:21 +00:00
my_uuid , network_peer_uuid ) ;
2012-01-26 16:19:41 +00:00
2012-09-12 23:01:19 +00:00
snprintf ( sigbridge_peer , sizeof ( sigbridge_peer ) , " %u:%u " ,
2012-01-27 04:51:21 +00:00
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-24 20:43:23 +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
2012-09-12 23:01:19 +00:00
& & ( var = channel_get_variable ( session , var_event , FREETDM_VAR_PREFIX " native_sigbridge " ) )
2012-02-24 20:43:23 +00:00
& & 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 ) ;
2012-09-12 23:01:19 +00:00
snprintf ( sigbridge_peer , sizeof ( sigbridge_peer ) , " %u:%u " ,
2012-02-24 20:43:23 +00:00
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 ) ;
}
2012-09-11 15:12:31 +00:00
2007-06-11 18:15:09 +00:00
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
switch_core_session_destroy ( new_session ) ;
2012-09-11 15:12:31 +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
}
2011-01-10 21:49:58 +00:00
goto fail ;
2007-06-11 18:15:09 +00:00
}
2012-01-27 04:51:21 +00:00
if ( our_chan & & peer_chan ) {
2012-09-12 23:01:19 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO ,
" Bridging native signaling of channel %s to channel %s \n " ,
2012-01-27 04:51:21 +00:00
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-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 ) ;
2012-09-11 15:12:31 +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 ) ;
2012-09-11 15:12:31 +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
}
2012-09-11 15:12:31 +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 ) ;
2012-09-11 15:12:31 +00:00
2007-05-27 14:58:01 +00:00
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 ' ;
2012-09-11 15:12:31 +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 ) ;
}
2012-09-11 15:12:31 +00:00
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 ) ) ;
2012-09-11 15:12:31 +00:00
switch_channel_set_variable_printf ( channel , " freetdm_span_number " , " %d " , spanid ) ;
2010-04-21 15:20:05 +00:00
switch_channel_set_variable_printf ( channel , " freetdm_chan_number " , " %d " , chanid ) ;
2012-09-11 15:12:31 +00:00
switch_channel_set_variable_printf ( channel , " freetdm_bearer_capability " , " %d " , channel_caller_data - > bearer_capability ) ;
2010-08-10 22:51:06 +00:00
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 ) ) ;
2012-09-11 15:12:31 +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-09-11 15:12:31 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-SpanNumber " , " %d " , spanid ) ;
2012-09-12 23:01:19 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-TransUUID " , " %s " , switch_core_session_get_uuid ( session ) ) ;
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-SpanNumber " , " %d " , spanid ) ;
2010-06-17 22:11:22 +00:00
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 ) ;
2012-09-11 15:12:31 +00:00
2010-06-29 20:29:37 +00:00
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 ) ) ;
2012-09-11 15:12:31 +00:00
ss7: add ss7_iam_nature_connection_hex to support Nature of Connection
Indicator in IAM message.
- ss7_iam_nature_connection_hex is the channel variable to carry
HEX value from/to IAM message
- X-FreeTDM-IAM-NATURE-CONN-HEX is the x-header string to carry
HEX value from/to sip invite message
- This IE is 8 bit hex, which turns into 2 chars
- Only Satellite indicator, Continuity check indicator, and Echo
control device indicator are supported. Spare value are not taken.
Spare value is always set to all zero.
- example:
To set 00010101 (bit H-A), set X-FreeTDM-IAM-NATURE-CONN-HEX string
value to 15 in the sip invite message to NSG.
When NSG send out sip invite, if the incoming IAM message comes with
Nature of Connection IE, NSG will put X-FreeTDM-IAM-NATURE-CONN-HEX
in the invite x-header. For example, if the IE value is 00001010 in
the IAM, NSG will send X-FreeTDM-IAM-NATURE-CONN-HEX with value string
of "0A".
- Two characters are madatory. "0A" must be specified rather than "A". If
invalid format or characters are found, this x-header will be ommited.
- Valid characters include 0-9, A-F, and a-f
2012-06-27 16:31:35 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_iam_nature_connection_hex " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-IAM-NATURE-CONN-HEX " , " %s " , var_value ) ;
}
2012-09-12 23:01:19 +00:00
ss7: adding ss7_iam_fwd_ind_hex as x-header and channel variables in hex format.
Read the forward call indicator IE and print it into channel variable
ss7_iam_fwd_ind_hex. If this variable exists, put it in the x-header.
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 and set to 0.
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.
2012-06-22 21:05:15 +00:00
var_value = ftdm_sigmsg_get_var ( sigmsg , " ss7_iam_fwd_ind_hex " ) ;
if ( ! ftdm_strlen_zero ( var_value ) ) {
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-IAM-FWD-IND-HEX " , " %s " , var_value ) ;
}
2012-09-12 23:01:19 +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
}
2012-09-12 23:01:19 +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 ) ;
}
2012-09-12 23:01:19 +00:00
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-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-09-30 17:09:13 +00:00
switch_channel_set_variable_printf ( channel , " sip_h_X-FreeTDM-CallReference " , " %d " , channel_caller_data - > call_reference ) ;
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-24 20:43:23 +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 ) ;
}
2012-09-12 23:01:19 +00:00
2012-02-24 20:43:23 +00:00
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 ) ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +00:00
switch_event_t * event = NULL ;
2011-05-26 15:38:24 +00:00
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 ) {
2012-09-11 15:12:31 +00:00
case FTDM_SIGEVENT_SMS :
2012-05-07 19:35:13 +00:00
{
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
ftdm_sms_data_t * sms = ( ftdm_sms_data_t * ) caller_data - > priv ;
ftdm_log ( FTDM_LOG_INFO , " FTDM_SIGEVENT_SMS from %s: %s " , sms - > from , sms - > body ) ;
if ( switch_event_create ( & event , SWITCH_EVENT_TRAP ) ! = SWITCH_STATUS_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " failed to create SMS event \n " ) ;
return FTDM_FAIL ;
}
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " from " , sms - > from ) ;
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " body " , sms - > body ) ;
alarmbits = 0 ;
}
//return FTDM_BREAK;
break ;
2010-03-10 20:06:31 +00:00
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 ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " condition " , " ftdm-alarm-clear " ) ;
} else {
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 ;
}
2012-09-11 15:12:31 +00:00
break ;
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 ;
2012-09-11 15:12:31 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2011-05-26 15:38:24 +00:00
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 ;
2013-06-26 04:16:11 +00:00
ftdm_status_t status = FTDM_SUCCESS ;
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
2012-09-12 23:01:19 +00:00
switch ( sigmsg - > event_id ) {
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-20 00:02:30 +00:00
case FTDM_SIGEVENT_COLLECTED_DIGIT : /* Analog E&M */
2013-06-26 04:16:11 +00:00
{
int span_id = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
char * dtmf = sigmsg - > ev_data . collected . digits ;
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 ) ;
if ( zstr ( regex ) ) {
regex = NULL ;
}
if ( zstr ( fail_regex ) ) {
fail_regex = NULL ;
}
ftdm_log ( FTDM_LOG_DEBUG , " got DTMF sig [%s] \n " , dtmf ) ;
switch_set_string ( caller_data - > collected , dtmf ) ;
if ( ( regex | | fail_regex ) & & ! zstr ( dtmf ) ) {
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 ] ) ) ;
status = match ? FTDM_SUCCESS : FTDM_BREAK ;
switch_regex_safe_free ( re ) ;
ftdm_log ( FTDM_LOG_DEBUG , " DTMF [%s] vs fail regex %s %s \n " , dtmf , fail_regex , match ? " matched " : " did not match " ) ;
}
if ( status = = FTDM_SUCCESS & & regex ) {
match = switch_regex_perform ( dtmf , regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
status = match ? FTDM_BREAK : FTDM_SUCCESS ;
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 " ) ;
}
ftdm_log ( FTDM_LOG_DEBUG , " returning %s to COLLECT event with DTMF %s \n " , status = = FTDM_SUCCESS ? " success " : " break " , dtmf ) ;
}
}
2012-09-11 15:12:31 +00:00
break ;
2013-10-06 23:08:45 +00:00
case FTDM_SIGEVENT_SIGSTATUS_CHANGED :
/* span signaling status changed ... nothing to do here .. */
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-31 20:15:16 +00:00
}
2013-06-26 04:16:11 +00:00
return status ;
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
2012-09-12 23:01:19 +00:00
switch ( sigmsg - > event_id ) {
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ) ;
2012-05-29 18:10:15 +00:00
br_a_uuid = switch_channel_get_partner_uuid ( channel_a ) ;
2008-01-10 00:47:04 +00:00
tech_pvt = switch_core_session_get_private ( session_a ) ;
2012-05-29 18:10:15 +00:00
stop_hold ( session_a , switch_channel_get_partner_uuid ( channel_a ) ) ;
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 ) ;
2012-05-29 18:10:15 +00:00
br_b_uuid = switch_channel_get_partner_uuid ( channel_b ) ;
2008-01-10 00:47:04 +00:00
tech_pvt = switch_core_session_get_private ( session_b ) ;
2012-05-29 18:10:15 +00:00
stop_hold ( session_a , switch_channel_get_partner_uuid ( channel_b ) ) ;
2008-01-10 00:47:04 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
2012-09-11 15:12:31 +00:00
if ( channel_a & & channel_b & & switch_channel_direction ( channel_a ) = = SWITCH_CALL_DIRECTION_INBOUND & &
2010-12-16 02:59:33 +00:00
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 ) ;
}
}
2012-09-11 15:12:31 +00:00
2008-01-10 00:47:04 +00:00
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 ) ;
}
}
2012-09-11 15:12:31 +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 ) ;
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
break ;
2012-09-11 15:12:31 +00:00
case FTDM_SIGEVENT_ADD_CALL :
2008-01-10 00:47:04 +00:00
{
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
}
break ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +00:00
2008-05-01 16:41:10 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
2012-05-29 18:10:15 +00:00
buuid = switch_channel_get_partner_uuid ( channel ) ;
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 )
2012-09-11 15:12:31 +00:00
) {
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 ;
2012-09-11 15:12:31 +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 ) ;
2012-09-11 15:12:31 +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 ) ;
2012-09-11 15:12:31 +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 ;
}
2012-09-11 15:12:31 +00:00
switch ( sigmsg - > event_id ) {
case FTDM_SIGEVENT_STOP : /* on_call_disconnect from the R2 side */
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2012-09-11 15:12:31 +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 ) ;
2009-08-19 21:47:56 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2012-09-11 15:12:31 +00:00
case FTDM_SIGEVENT_START : /* on_call_offered from the R2 side */
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 ;
2012-09-11 15:12:31 +00:00
case FTDM_SIGEVENT_COLLECTED_DIGIT : /* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +00:00
case FTDM_SIGEVENT_PROGRESS_MEDIA :
2010-12-08 16:57:24 +00:00
{
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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +00:00
case FTDM_SIGEVENT_SIGSTATUS_CHANGED :
2010-11-23 16:55:59 +00:00
{
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 ;
2012-09-11 15:12:31 +00:00
case FTDM_SIGEVENT_PROCEED :
case FTDM_SIGEVENT_INDICATION_COMPLETED :
break ;
default :
2009-08-19 21:47:56 +00:00
{
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 ;
}
2012-09-11 15:12:31 +00:00
switch ( sigmsg - > event_id ) {
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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +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
}
}
2012-09-11 15:15:33 +00:00
break ;
2012-09-11 15:12:31 +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
}
}
2012-09-11 15:12:31 +00:00
break ;
2010-04-23 21:34:57 +00:00
case FTDM_SIGEVENT_SIGSTATUS_CHANGED :
2012-09-11 15:12:31 +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 ;
2012-09-11 15:12:31 +00:00
default :
2007-05-27 14:58:01 +00:00
{
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
{
2012-09-11 15:12:31 +00:00
char * data = NULL ;
va_list ap ;
va_start ( ap , fmt ) ;
2007-05-26 04:45:31 +00:00
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
}
2012-09-11 15:12:31 +00:00
if ( data ) {
free ( data ) ;
}
2007-05-26 04:45:31 +00:00
2012-09-11 15:12:31 +00:00
va_end ( ap ) ;
2007-05-26 04:45:31 +00:00
}
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 ;
}
2012-09-11 15:12:31 +00:00
2008-01-25 16:42:06 +00:00
return current_options ;
}
2012-08-15 20:11:13 +00:00
# define LOAD_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
}
2012-09-11 15:12:31 +00:00
/*
2012-09-12 23:01:19 +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 .
2012-09-11 15:12:31 +00:00
*/
static int add_config_list_nodes ( switch_xml_t swnode , ftdm_conf_node_t * rootnode ,
const char * list_name , const char * list_element_name ,
2010-04-14 21:59:39 +00:00
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 ;
}
2012-09-12 23:01:19 +00:00
/*
* Create ftdm_conf_node_t tree based on a fixed pattern XML configuration list .
* Last arg is to specify if we have any sublist for e . g . :
*
2012-06-12 13:13:01 +00:00
* < list_name >
* < list_element_name >
* < param name = " xxx " value = " xxx " / >
* < sub - list >
* < param name = " xxx " value = " xxx " / >
* < / sub - list >
* < / list_element_name >
2012-09-12 23:01:19 +00:00
* < / list_name >
*/
static int add_config_nodes ( switch_xml_t swnode , ftdm_conf_node_t * rootnode ,
2012-06-12 13:13:01 +00:00
const char * list_name , const char * list_element_name , const char * sub_list_name )
{
char * var , * val ;
switch_xml_t list ;
switch_xml_t sub_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 we have single node list */
if ( sub_list_name ) {
sub_list = switch_xml_child ( element , sub_list_name ) ;
if ( ! sub_list ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " no sub_list %s found \n " , sub_list_name ) ;
return - 1 ;
}
for ( param = switch_xml_child ( sub_list , " 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 ) ;
}
}
}
return 0 ;
}
2012-06-12 23:15:14 +00:00
static ftdm_conf_node_t * _get_ss7_config_node ( switch_xml_t cfg , const char * confname , const char * operating_mode )
2010-04-14 15:00:17 +00:00
{
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 ;
2012-05-18 06:35:25 +00:00
int is_isup = 0x00 ;
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 ;
}
2012-06-11 17:23:37 +00:00
/* sng_isup and ss7config xml childs are treated the same way. sng_isup was used initially, but does not make sense
* for configurations that do not have an ISUP layer , sng_isup is kept for backward compatibility */
/* search the ss7config */
for ( isup = switch_xml_child ( ss7configs , " sngss7_config " ) ; isup ; isup = isup - > next ) {
2010-04-14 21:59:39 +00:00
char * name = ( char * ) switch_xml_attr ( isup , " name " ) ;
if ( ! name ) {
continue ;
}
if ( ! strcasecmp ( name , confname ) ) {
break ;
}
}
2012-09-12 23:01:19 +00:00
2010-04-14 21:59:39 +00:00
if ( ! isup ) {
2012-06-11 17:23:37 +00:00
/* 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' ss7config or sng_isup XML config section \n " , confname ) ;
return NULL ;
}
2010-04-14 21:59:39 +00:00
}
/* 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 ;
}
2012-05-18 06:35:25 +00:00
/* operating mode , M2UA or ISUP */
2012-09-12 23:01:19 +00:00
if ( operating_mode & & ( ' \0 ' ! = operating_mode [ 0 ] ) ) {
if ( ! strcasecmp ( operating_mode , " ISUP " ) ) {
2012-05-18 06:35:25 +00:00
is_isup = 0x01 ;
}
2012-09-12 23:01:19 +00:00
else if ( ! strcasecmp ( operating_mode , " M2UA_SG " ) ) {
2012-05-18 06:35:25 +00:00
is_isup = 0x00 ;
} else {
2012-06-12 23:15:14 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid operating Mode[%s] \n " , operating_mode ) ;
2012-05-18 06:35:25 +00:00
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
} else {
2012-06-12 23:15:14 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Operating mode not specified, default to ISUP \n " ) ;
2012-05-18 06:35:25 +00:00
is_isup = 0x01 ;
}
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 ;
}
2012-09-12 23:01:19 +00:00
if ( is_isup ) {
2012-05-18 06:35:25 +00:00
/* 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-11-26 20:59:24 +00:00
2012-06-12 13:13:01 +00:00
/* add mtp linksets */
if ( add_config_list_nodes ( isup , rootnode , " mtp_linksets " , " mtp_linkset " , NULL , NULL ) ) {
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 ;
}
2010-04-14 21:59:39 +00:00
2012-06-12 13:13:01 +00:00
/* add mtp routes */
if ( add_config_list_nodes ( isup , rootnode , " mtp_routes " , " mtp_route " , " linksets " , " linkset " ) ) {
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 ;
}
2010-04-14 21:59:39 +00:00
2012-05-18 06:35:25 +00:00
/* 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-04-14 21:59:39 +00:00
2012-05-18 06:35:25 +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 ;
}
2012-06-18 12:11:05 +00:00
} else {
2012-05-18 06:35:25 +00:00
/* add sctp links */
2012-06-18 12:11:05 +00:00
if ( add_config_nodes ( isup , rootnode , " sng_sctp_interfaces " , " sng_sctp_interface " , " sng_source_addresses " ) ) {
2012-05-18 06:35:25 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process sng_sctp_interface for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
if ( add_config_list_nodes ( isup , rootnode , " sng_nif_interfaces " , " sng_nif_interface " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process sng_nif_interfaces for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
if ( add_config_list_nodes ( isup , rootnode , " sng_m2ua_interfaces " , " sng_m2ua_interface " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process sng_m2ua_interfaces for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
2012-06-12 13:13:01 +00:00
if ( add_config_nodes ( isup , rootnode , " sng_m2ua_peer_interfaces " , " sng_m2ua_peer_interface " , " sng_destination_addresses " ) ) {
2012-05-18 06:35:25 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process sng_m2ua_peer_interfaces for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
2012-06-12 13:13:01 +00:00
if ( add_config_nodes ( isup , rootnode , " sng_m2ua_cluster_interfaces " , " sng_m2ua_cluster_interface " , " sng_m2ua_peers " ) ) {
2012-05-18 06:35:25 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process sng_m2ua_cluster_interfaces for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
2010-11-26 20:59:24 +00:00
}
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
}
2012-05-07 19:10:25 +00:00
static void parse_gsm_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 " ;
2011-12-26 01:49:10 +00:00
ftdm_conf_parameter_t spanparameters [ FTDM_MAX_SIG_PARAMETERS ] ;
2012-05-07 19:10:25 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " GSM span missing required attribute 'id' or 'name', skipping ... \n " ) ;
2012-05-07 19:10:25 +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 ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2012-05-07 19:10:25 +00:00
continue ;
}
2012-09-11 15:12:31 +00:00
2012-05-07 19:10:25 +00:00
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 ) ;
}
}
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 ( ftdm_array_len ( spanparameters ) - 1 = = paramindex ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " Too many parameters for GSM span, ignoring any parameter after %s \n " , var ) ;
2012-05-07 19:10:25 +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 + + ;
}
}
2012-09-11 15:12:31 +00:00
if ( ftdm_configure_span_signaling ( span ,
" gsm " ,
2012-05-07 19:10:25 +00:00
on_clear_channel_signal ,
spanparameters ) ! = FTDM_SUCCESS ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " Error configuring Sangoma GSM FreeTDM span %d \n " , span_id ) ;
2012-05-07 19:10:25 +00:00
continue ;
}
2012-09-12 23:01:19 +00:00
2012-05-07 19:10:25 +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 , " GSM " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2012-09-12 23:01:19 +00:00
2012-05-07 19:10:25 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Configured GSM FreeTDM span %d \n " , span_id ) ;
ftdm_span_start ( span ) ;
}
}
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 " ;
2011-12-26 01:49:10 +00:00
ftdm_conf_parameter_t spanparameters [ FTDM_MAX_SIG_PARAMETERS ] ;
2010-09-09 21:22:10 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
}
2012-09-11 15:12:31 +00:00
2010-09-09 21:22:10 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-09-11 15:12:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR ,
2011-05-19 20:17:46 +00:00
" 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 ;
2012-09-11 15:12:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" Unrestricted digital codec is %s at %dhz for span %d \n " ,
2011-05-19 20:17:46 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 {
2012-08-15 20:11:13 +00:00
LOAD_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 + + ;
}
}
2012-09-11 15:12:31 +00:00
if ( ftdm_configure_span_signaling ( span ,
" sangoma_isdn " ,
2010-09-09 21:22:10 +00:00
on_clear_channel_signal ,
spanparameters ) ! = FTDM_SUCCESS ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " Error configuring Sangoma ISDN FreeTDM span %d \n " , span_id ) ;
2010-09-09 21:22:10 +00:00
continue ;
}
2012-09-12 23:01:19 +00:00
2010-09-09 21:22:10 +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 (ISDN) " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2012-09-12 23:01:19 +00:00
2010-09-09 21:22:10 +00:00
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 ) ;
2012-09-12 23:01:19 +00:00
2007-05-26 04:45:31 +00:00
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 ;
}
2012-09-11 15:12:31 +00:00
2007-05-26 04:45:31 +00:00
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
}
}
}
2012-09-11 15:12:31 +00:00
if ( ( spans = switch_xml_child ( cfg , " sangoma_pri_spans " ) ) ) {
2010-09-09 21:22:10 +00:00
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
}
2012-05-07 19:10:25 +00:00
if ( ( spans = switch_xml_child ( cfg , " gsm_spans " ) ) ) {
parse_gsm_spans ( cfg , spans ) ;
}
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 " ;
2011-12-26 01:49:10 +00:00
ftdm_conf_parameter_t spanparameters [ FTDM_MAX_SIG_PARAMETERS ] ;
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 " ) ;
2012-06-12 23:15:14 +00:00
char * operating_mode = ( char * ) switch_xml_attr ( myspan , " operating_mode " ) ;
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " ss7 span missing required attribute 'id' or 'name', skipping ... \n " ) ;
2010-04-14 21:59:39 +00:00
continue ;
}
if ( ! configname ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
}
2012-09-11 15:12:31 +00:00
2010-04-14 15:00:17 +00:00
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
}
2012-06-12 23:15:14 +00:00
ss7confnode = _get_ss7_config_node ( cfg , configname , operating_mode ) ;
2010-04-14 21:59:39 +00:00
if ( ! ss7confnode ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
2012-09-12 23:01:19 +00:00
if ( operating_mode ) {
2012-06-12 23:15:14 +00:00
spanparameters [ paramindex ] . var = " operating-mode " ;
spanparameters [ paramindex ] . val = operating_mode ;
2012-05-18 06:35:25 +00:00
paramindex + + ;
}
2012-09-12 23:01:19 +00:00
2010-06-06 17:07:30 +00:00
spanparameters [ paramindex ] . var = " confnode " ;
spanparameters [ paramindex ] . ptr = ss7confnode ;
paramindex + + ;
2012-09-12 23:01:19 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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
2012-09-11 15:12:31 +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 ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " Error configuring ss7 FreeTDM span %d \n " , span_id ) ;
2010-04-14 22:36:22 +00:00
continue ;
}
2012-09-12 23:01:19 +00:00
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
2012-09-12 23:01:19 +00:00
2010-04-21 15:20:05 +00:00
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 ) ) ;
2012-09-12 23:01:19 +00:00
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 ) ;
2012-09-12 23:01:19 +00:00
if ( FTDM_SUCCESS ! = ftdm_span_start ( span ) ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " Error Starting ss7 FreeTDM span %d \n " , span_id ) ;
2012-08-15 18:26:09 +00:00
continue ;
}
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 " ;
2011-08-07 01:29:46 +00:00
const char * polarity_callerid = " false " ;
2010-12-21 20:11:22 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
}
2012-09-11 15:12:31 +00:00
2010-08-31 17:59:13 +00:00
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 ;
2012-09-11 15:12:31 +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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 {
2012-08-15 20:11:13 +00:00
LOAD_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 ) ;
2011-08-07 01:29:46 +00:00
} else if ( ! strcasecmp ( var , " polarity-callerid " ) ) {
polarity_callerid = 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
}
}
2012-09-11 15:12:31 +00:00
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " span missing required param 'id' \n " ) ;
2008-08-29 20:41:17 +00:00
continue ;
2007-05-26 04:45:31 +00:00
}
2012-09-11 15:12:31 +00:00
2007-05-26 04:45:31 +00:00
if ( ! tonegroup ) {
tonegroup = " us " ;
}
2012-09-11 15:12:31 +00:00
2007-05-26 04:45:31 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
}
2012-09-11 15:12:31 +00:00
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
2012-09-11 15:12:31 +00:00
if ( ftdm_configure_span ( span , " analog " , on_analog_signal ,
" tonemap " , tonegroup ,
2008-08-29 15:58:59 +00:00
" 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 ,
2011-08-07 01:29:46 +00:00
" polarity_callerid " , polarity_callerid ,
2010-12-21 20:11:22 +00:00
" 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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
2012-09-11 15:12:31 +00:00
2010-09-10 18:09:06 +00:00
chaniter = ftdm_span_get_chan_iterator ( span , NULL ) ;
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 ) ;
2012-09-11 15:12:31 +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 ;
2012-12-19 03:50:49 +00:00
char * dial_timeout = NULL ;
2008-09-17 02:21:28 +00:00
char * max_digits = NULL ;
char * dial_regex = NULL ;
char * hold_music = NULL ;
char * fail_dial_regex = NULL ;
2012-12-19 03:50:49 +00:00
char str_false [ ] = " false " ;
2013-06-26 03:41:30 +00:00
char str_empty [ ] = " " ;
2012-12-19 03:50:49 +00:00
char * answer_supervision = str_false ;
2013-08-21 21:54:00 +00:00
char * immediate_ringback = str_false ;
2013-06-26 03:41:30 +00:00
char * ringback_file = str_empty ;
2012-12-19 03:50:49 +00:00
uint32_t span_id = 0 , to = 0 , max = 0 , dial_timeout_int = 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 ;
2012-12-19 03:50:49 +00:00
} else if ( ! strcasecmp ( var , " dial-timeout " ) ) {
dial_timeout = val ;
2008-09-17 02:21:28 +00:00
} 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 ;
2012-12-19 03:50:49 +00:00
} else if ( ! strcasecmp ( var , " answer-supervision " ) ) {
answer_supervision = val ;
2013-08-21 21:54:00 +00:00
} else if ( ! strcasecmp ( var , " immediate-ringback " ) ) {
immediate_ringback = val ;
2013-06-26 03:41:30 +00:00
} else if ( ! strcasecmp ( var , " ringback-file " ) ) {
ringback_file = val ;
2008-09-17 02:21:28 +00:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
}
}
2012-09-11 15:12:31 +00:00
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2012-08-15 20:11:13 +00:00
LOAD_ERROR ( " span missing required param 'id' \n " ) ;
2008-09-17 02:21:28 +00:00
continue ;
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
2012-09-11 15:12:31 +00:00
2008-09-17 02:21:28 +00:00
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
2012-12-19 03:50:49 +00:00
if ( dial_timeout ) {
dial_timeout_int = atoi ( dial_timeout ) ;
}
2008-09-17 02:21:28 +00:00
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
}
2012-09-11 15:12:31 +00:00
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
2012-09-11 15:12:31 +00:00
if ( ftdm_configure_span ( span , " analog_em " , on_analog_signal ,
" tonemap " , tonegroup ,
2012-12-19 03:50:49 +00:00
" answer_supervision " , answer_supervision ,
2013-08-21 21:54:00 +00:00
" immediate_ringback " , immediate_ringback ,
2013-06-26 03:41:30 +00:00
" ringback_file " , ringback_file ,
2008-09-17 02:21:28 +00:00
" digit_timeout " , & to ,
2012-12-19 03:50:49 +00:00
" dial_timeout " , & dial_timeout_int ,
2008-09-17 02:21:28 +00:00
" max_dialstr " , & max ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
2012-09-11 15:12:31 +00:00
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 " ) ;
2011-12-26 01:49:10 +00:00
ftdm_conf_parameter_t spanparameters [ FTDM_MAX_SIG_PARAMETERS ] ;
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ;
2011-12-26 01:49:10 +00:00
ftdm_conf_parameter_t spanparameters [ FTDM_MAX_SIG_PARAMETERS ] ;
2010-07-30 23:46:05 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
ftdm_span_t * span = NULL ;
int span_id = 0 ;
if ( ! name ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 + + ;
}
}
2012-09-11 15:12:31 +00:00
2010-07-30 23:46:05 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
if ( zstatus ! = FTDM_SUCCESS ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 " ) ;
2011-12-26 01:49:10 +00:00
ftdm_conf_parameter_t spanparameters [ FTDM_MAX_SIG_PARAMETERS ] ;
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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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
2011-12-26 01:49:10 +00:00
ftdm_conf_parameter_t spanparameters [ FTDM_MAX_SIG_PARAMETERS ] ;
2010-11-27 00:10:33 +00:00
unsigned paramindex = 0 ;
2009-08-19 21:47:56 +00:00
2010-12-03 11:13:11 +00:00
if ( ! name ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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 ) {
2012-08-15 20:11:13 +00:00
LOAD_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-08-04 14:09:28 +00:00
typedef struct ftdm_cli_entry ftdm_cli_entry_t ;
typedef switch_status_t ( * ftdm_cli_function_t ) ( ftdm_cli_entry_t * cli , const char * cmd , switch_core_session_t * session ,
switch_stream_handle_t * stream , int argc , char * argv [ ] ) ;
# define FTDM_CLI_DECLARE(name) static switch_status_t name(ftdm_cli_entry_t *cli, const char *cmd, \
switch_core_session_t * session , switch_stream_handle_t * stream , \
int argc , char * argv [ ] )
static void print_usage ( switch_stream_handle_t * stream , ftdm_cli_entry_t * cli ) ;
2011-07-29 23:33:42 +00:00
2011-09-12 19:21:23 +00:00
typedef struct cmd_ioread_data {
int num_times ;
uint32_t interval ;
ftdm_span_t * span ;
ftdm_channel_t * fchan ;
switch_memory_pool_t * pool ;
int already_open ;
} cmd_ioread_data_t ;
static void * SWITCH_THREAD_FUNC ioread_thread ( switch_thread_t * thread , void * obj )
{
ftdm_wait_flag_t wflags = FTDM_READ ;
ftdm_status_t status = FTDM_FAIL ;
unsigned char iobuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
cmd_ioread_data_t * data = obj ;
int span_id = ftdm_span_get_id ( data - > span ) ;
int chan_id = ftdm_channel_get_id ( data - > fchan ) ;
2011-09-12 19:48:28 +00:00
ftdm_size_t len = ftdm_channel_get_io_packet_len ( data - > fchan ) ;
ftdm_size_t origlen = len ;
2011-09-12 19:21:23 +00:00
unsigned int pbuf [ 5 ] ;
2012-09-11 15:12:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" Started ioread thread (times = %d, interval = %ums, len = % " FTDM_SIZE_FMT " , span = %d, chan = %d \n " ,
2011-09-12 19:21:23 +00:00
data - > num_times , data - > interval , len , span_id , chan_id ) ;
while ( ftdm_running ( ) & & data - > num_times > 0 ) {
data - > num_times - - ;
2012-09-11 15:12:31 +00:00
wflags = FTDM_READ ;
2011-09-12 19:21:23 +00:00
status = ftdm_channel_wait ( data - > fchan , & wflags , ( data - > interval * 10 ) ) ;
2012-09-11 15:12:31 +00:00
2011-09-12 19:21:23 +00:00
if ( status = = FTDM_FAIL ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to wait for IO in device %d:%d! \n " , span_id , chan_id ) ;
continue ;
}
2012-09-11 15:12:31 +00:00
2011-09-12 19:21:23 +00:00
if ( status = = FTDM_TIMEOUT ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Timed out while waiting I/O in device %d:%d! \n " , span_id , chan_id ) ;
continue ;
}
len = origlen ;
if ( ftdm_channel_read ( data - > fchan , iobuf , & len ) ! = FTDM_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Failed to read from device %d:%d! \n " , span_id , chan_id ) ;
continue ;
}
pbuf [ 0 ] = iobuf [ 0 ] ;
pbuf [ 1 ] = iobuf [ 1 ] ;
pbuf [ 2 ] = iobuf [ 2 ] ;
pbuf [ 3 ] = iobuf [ 3 ] ;
pbuf [ 4 ] = iobuf [ 4 ] ;
2012-09-11 15:12:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Read 0x%1X 0x%1X 0x%1X 0x%1X 0x%1X \n " ,
2011-09-12 19:21:23 +00:00
pbuf [ 0 ] , pbuf [ 1 ] , pbuf [ 2 ] , pbuf [ 3 ] , pbuf [ 4 ] ) ;
}
if ( ! data - > already_open ) {
ftdm_channel_close ( & data - > fchan ) ;
}
switch_core_destroy_memory_pool ( & data - > pool ) ;
2012-09-11 15:12:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" Done ioread thread (times = %d, interval = %ums, len = % " FTDM_SIZE_FMT " , span = %d, chan = %d \n " ,
2011-09-12 19:21:23 +00:00
data - > num_times , data - > interval , origlen , span_id , chan_id ) ;
return NULL ;
}
FTDM_CLI_DECLARE ( ftdm_cmd_ioread )
2008-04-01 17:29:57 +00:00
{
2011-09-12 19:21:23 +00:00
char * span_name = NULL ;
int channo = 0 ;
ftdm_status_t status = FTDM_SUCCESS ;
switch_threadattr_t * attr = NULL ;
switch_thread_t * thread = NULL ;
cmd_ioread_data_t * thdata ;
cmd_ioread_data_t data ;
memset ( & data , 0 , sizeof ( data ) ) ;
data . num_times = 1 ;
if ( argc < 3 ) {
print_usage ( stream , cli ) ;
goto end ;
}
span_name = argv [ 1 ] ;
ftdm_span_find_by_name ( span_name , & data . span ) ;
if ( ! data . span ) {
stream - > write_function ( stream , " -ERR span %s not found \n " , span_name ) ;
goto end ;
}
channo = atoi ( argv [ 2 ] ) ;
status = ftdm_channel_open ( ftdm_span_get_id ( data . span ) , channo , & data . fchan ) ;
if ( ! data . fchan | | ( status ! = FTDM_SUCCESS & & status ! = FTDM_EBUSY ) ) {
stream - > write_function ( stream , " -ERR Failed to open channel %d in span %s \n " , channo , span_name ) ;
goto end ;
}
if ( status = = FTDM_EBUSY ) {
data . already_open = 1 ;
}
if ( argc > 3 ) {
data . num_times = atoi ( argv [ 3 ] ) ;
if ( data . num_times < 1 ) {
data . num_times = 1 ;
}
}
if ( argc > 4 ) {
data . interval = atoi ( argv [ 4 ] ) ;
}
if ( data . interval < = 0 | | data . interval > 10000 ) {
data . interval = ftdm_channel_get_io_interval ( data . fchan ) ;
}
switch_core_new_memory_pool ( & data . pool ) ;
thdata = switch_core_alloc ( data . pool , sizeof ( data ) ) ;
memcpy ( thdata , & data , sizeof ( * thdata ) ) ;
switch_threadattr_create ( & attr , data . pool ) ;
switch_threadattr_detach_set ( attr , 1 ) ;
switch_threadattr_stacksize_set ( attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , attr , ioread_thread , thdata , data . pool ) ;
end :
2011-07-29 23:33:42 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-04-01 17:29:57 +00:00
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_list )
2011-07-29 23:33:42 +00:00
{
int j ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
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 ) ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( ( FTDM_SUCCESS = = ftdm_span_get_sig_status ( SPAN_CONFIG [ j ] . span , & sigstatus ) ) ) {
stream - > write_function ( stream ,
" +OK \n "
" span: %u (%s) \n "
2012-09-11 15:12:31 +00:00
" type: %s \n "
2011-07-29 23:33:42 +00:00
" 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-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_start_stop )
2011-07-29 23:33:42 +00:00
{
char * span_name = argv [ 1 ] ;
ftdm_span_t * span = NULL ;
ftdm_status_t status ;
2011-08-04 14:09:28 +00:00
if ( argc < 2 ) {
print_usage ( stream , cli ) ;
goto end ;
2011-07-29 23:33:42 +00:00
}
2011-08-04 14:09:28 +00:00
ftdm_span_find_by_name ( span_name , & span ) ;
2011-07-29 23:33:42 +00:00
if ( ! span ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR span %s not found \n " , span_name ) ;
2008-04-01 17:29:57 +00:00
goto end ;
}
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( ! strcasecmp ( argv [ 0 ] , " stop " ) ) {
status = ftdm_span_stop ( span ) ;
} else {
status = ftdm_span_start ( span ) ;
}
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
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-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_reset )
2011-07-29 23:33:42 +00:00
{
uint32_t chan_id = 0 ;
uint32_t ccount = 0 ;
ftdm_channel_t * chan ;
ftdm_span_t * span = NULL ;
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 2 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
if ( ! span ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR span %s not found \n " , argv [ 1 ] ) ;
2011-07-29 23:33:42 +00:00
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 ) ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid channel %d \n " , chan_id ) ;
2010-12-16 19:01:06 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( chan_id ) {
chan = ftdm_span_get_channel ( span , chan_id ) ;
if ( ! chan ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR Could not find channel %d \n " , chan_id ) ;
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-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_dump )
2011-07-29 23:33:42 +00:00
{
ftdm_iterator_t * chaniter = NULL ;
ftdm_iterator_t * curr = NULL ;
uint32_t chan_id = 0 ;
ftdm_span_t * span ;
char * as = NULL ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 2 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
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 ) {
2012-09-11 15:12:31 +00:00
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2011-07-29 23:33:42 +00:00
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 ) {
2012-09-11 15:12:31 +00:00
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2011-07-29 23:33:42 +00:00
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
2012-01-30 19:15:51 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_alarms )
{
2012-09-12 23:01:19 +00:00
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE ;
uint32_t chan_id = 0 ;
ftdm_span_t * span ;
if ( argc < 3 ) {
print_usage ( stream , cli ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
chan_id = atoi ( argv [ 2 ] ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
} else if ( chan_id ) {
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
} else {
ftdm_channel_t * chan = ftdm_span_get_channel ( span , chan_id ) ;
if ( ! chan ) {
stream - > write_function ( stream , " -ERR channel not configured \n " ) ;
} else {
ftdm_channel_get_alarms ( chan , & alarmbits ) ;
if ( ! strlen ( ftdm_channel_get_last_error ( chan ) ) ) {
stream - > write_function ( stream , " +OK No alarms \n " ) ;
} else {
stream - > write_function ( stream , " -ERR %s on %s:%d \n " , ftdm_channel_get_last_error ( chan ) , argv [ 1 ] , chan ) ;
}
}
}
}
2012-01-30 19:15:51 +00:00
end :
2012-09-12 23:01:19 +00:00
return SWITCH_STATUS_SUCCESS ;
2012-01-30 19:15:51 +00:00
}
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_sigstatus )
2011-07-29 23:33:42 +00:00
{
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 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( ! strcasecmp ( argv [ 1 ] , " get " ) & & argc < 3 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( ! strcasecmp ( argv [ 1 ] , " set " ) & & argc ! = 5 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
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 ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid span %s \n " , argv [ 2 ] ) ;
2011-07-29 23:33:42 +00:00
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 ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid 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 ) ) ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " Channel %d signaling status: %s \n " , chan_id , ftdm_signaling_status2str ( sigstatus ) ) ;
2011-07-29 23:33:42 +00:00
} else {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to get channel signaling status \n " ) ;
2011-07-29 23:33:42 +00:00
}
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 {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to read span signaling status: %s \n " , ftdm_span_get_last_error ( span ) ) ;
2011-07-29 23:33:42 +00:00
}
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 ;
}
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_trace )
2011-07-29 23:33:42 +00:00
{
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 ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 3 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
goto end ;
2012-09-11 15:12:31 +00:00
}
2011-07-29 23:33:42 +00:00
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to find span %s \n " , argv [ 2 ] ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
chan_count = ftdm_span_get_chan_count ( span ) ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > chan_count ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
2010-05-28 16:44:37 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
span_id = ftdm_span_get_id ( span ) ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
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 ;
}
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_notrace )
2011-07-29 23:33:42 +00:00
{
uint32_t i = 0 ;
uint32_t chan_id = 0 ;
uint32_t chan_count = 0 ;
ftdm_channel_t * fchan = NULL ;
ftdm_span_t * span = NULL ;
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 2 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
goto end ;
2012-09-11 15:12:31 +00:00
}
2011-07-29 23:33:42 +00:00
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
if ( ! span ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to find span %s \n " , argv [ 1 ] ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
chan_count = ftdm_span_get_chan_count ( span ) ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( argc > 2 ) {
chan_id = atoi ( argv [ 2 ] ) ;
if ( chan_id > chan_count ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
2010-05-28 16:44:37 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
2011-08-04 14:09:28 +00:00
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 " ) ;
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
end :
return SWITCH_STATUS_SUCCESS ;
}
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_gains )
2011-07-29 23:33:42 +00:00
{
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 ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 4 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
goto end ;
2012-09-11 15:12:31 +00:00
}
2011-07-29 23:33:42 +00:00
ftdm_span_find_by_name ( argv [ 3 ] , & span ) ;
if ( ! span ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to find span %s \n " , argv [ 3 ] ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( argc > 4 ) {
chan_id = atoi ( argv [ 4 ] ) ;
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
2010-01-06 20:58:21 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
2012-09-11 15:12:31 +00:00
i = sscanf ( argv [ 1 ] , " %f " , & rxgain ) ;
2011-07-29 23:33:42 +00:00
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 ;
}
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_dtmf )
2011-07-29 23:33:42 +00:00
{
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 ;
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 3 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
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 ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to find span %s \n " , argv [ 2 ] ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
schan_count = ftdm_span_get_chan_count ( span ) ;
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > schan_count ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid channel \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 ;
}
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_queuesize )
2011-07-29 23:33:42 +00:00
{
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 ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
if ( argc < 4 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-29 23:33:42 +00:00
goto end ;
2012-09-11 15:12:31 +00:00
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
ftdm_span_find_by_name ( argv [ 3 ] , & span ) ;
if ( ! span ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to find span %s \n " , argv [ 3 ] ) ;
2011-07-29 23:33:42 +00:00
goto end ;
}
2011-08-04 14:09:28 +00:00
2011-07-29 23:33:42 +00:00
if ( argc > 4 ) {
chan_id = atoi ( argv [ 4 ] ) ;
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
2011-03-21 18:25:20 +00:00
goto end ;
}
2011-07-29 23:33:42 +00:00
}
2011-08-04 14:09:28 +00:00
2012-09-11 15:12:31 +00:00
i = sscanf ( argv [ 1 ] , " %u " , & rxsize ) ;
2011-07-29 23:33:42 +00:00
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 ;
2012-09-11 15:12:31 +00:00
2011-07-30 21:39:29 +00:00
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 ) ;
2012-09-11 15:12:31 +00:00
stream - > write_function ( stream , " -- IO statistics for channel %d:%d -- \n " ,
2011-07-30 21:39:29 +00:00
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 ) ;
}
}
2011-08-04 14:09:28 +00:00
FTDM_CLI_DECLARE ( ftdm_cmd_iostats )
2011-07-30 21:39:29 +00:00
{
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 ) {
2011-08-04 14:09:28 +00:00
print_usage ( stream , cli ) ;
2011-07-30 21:39:29 +00:00
goto end ;
}
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR failed to find span %s \n " , argv [ 2 ] ) ;
2011-07-30 21:39:29 +00:00
goto end ;
}
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2011-08-04 14:09:28 +00:00
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
2011-07-30 21:39:29 +00:00
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 ;
}
2013-03-08 20:15:07 +00:00
SWITCH_STANDARD_API ( ftdm_api_exec_usage )
{
char * mycmd = NULL , * argv [ 10 ] = { 0 } ;
int argc = 0 ;
uint32_t chan_id = 0 ;
ftdm_channel_t * chan = NULL ;
ftdm_span_t * span = NULL ;
uint32_t tokencnt = 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 ) {
stream - > write_function ( stream , " -ERR invalid args \n " ) ;
goto end ;
}
if ( argc < 2 ) {
stream - > write_function ( stream , " -ERR invalid args \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 0 ] , & span ) ;
chan_id = atoi ( argv [ 1 ] ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( chan_id < = 0 ) {
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
goto end ;
}
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
goto end ;
}
chan = ftdm_span_get_channel ( span , chan_id ) ;
if ( ! chan ) {
stream - > write_function ( stream , " -ERR channel not configured \n " ) ;
goto end ;
}
tokencnt = ftdm_channel_get_token_count ( chan ) ;
stream - > write_function ( stream , " %d " , tokencnt ) ;
end :
switch_safe_free ( mycmd ) ;
return SWITCH_STATUS_SUCCESS ;
}
2011-08-04 14:09:28 +00:00
struct ftdm_cli_entry {
2011-07-29 23:33:42 +00:00
const char * name ;
const char * args ;
const char * complete ;
2013-03-08 20:15:07 +00:00
const char * desc ;
2011-07-29 23:33:42 +00:00
ftdm_cli_function_t execute ;
2013-03-08 20:15:07 +00:00
switch_api_function_t execute_api ;
2011-08-04 14:09:28 +00:00
} ;
2011-03-25 20:48:57 +00:00
2011-07-29 23:33:42 +00:00
static ftdm_cli_entry_t ftdm_cli_options [ ] =
{
2013-03-08 20:15:07 +00:00
{ " list " , " " , " " , NULL , ftdm_cmd_list , NULL } ,
{ " start " , " <span_id|span_name> " , " " , NULL , ftdm_cmd_start_stop , NULL } ,
{ " stop " , " <span_id|span_name> " , " " , NULL , ftdm_cmd_start_stop , NULL } ,
{ " reset " , " <span_id|span_name> [<chan_id>] " , " " , NULL , ftdm_cmd_reset , NULL } ,
{ " alarms " , " <span_id> <chan_id> " , " " , NULL , ftdm_cmd_alarms , NULL } ,
{ " dump " , " <span_id|span_name> [<chan_id>] " , " " , NULL , ftdm_cmd_dump , NULL } ,
{ " sigstatus " , " get|set <span_id|span_name> [<chan_id>] [<sigstatus>] " , " ::[set:get " , NULL , ftdm_cmd_sigstatus , NULL } ,
{ " trace " , " <path> <span_id|span_name> [<chan_id>] " , " " , NULL , ftdm_cmd_trace , NULL } ,
{ " notrace " , " <span_id|span_name> [<chan_id>] " , " " , NULL , ftdm_cmd_notrace , NULL } ,
{ " gains " , " <rxgain> <txgain> <span_id|span_name> [<chan_id>] " , " " , NULL , ftdm_cmd_gains , NULL } ,
{ " dtmf " , " on|off <span_id|span_name> [<chan_id>] " , " ::[on:off " , NULL , ftdm_cmd_dtmf , NULL } ,
{ " queuesize " , " <rxsize> <txsize> <span_id|span_name> [<chan_id>] " , " " , NULL , ftdm_cmd_queuesize , NULL } ,
{ " iostats " , " enable|disable|flush|print <span_id|span_name> <chan_id> " , " ::[enable:disable:flush:print " , NULL , ftdm_cmd_iostats , NULL } ,
{ " ioread " , " <span_id|span_name> <chan_id> [num_times] [interval] " , " " , NULL , ftdm_cmd_ioread , NULL } ,
/* Stand-alone commands (not part of the generic ftdm API */
{ " ftdm_usage " , " <span_id|span_name> <chan_id> " , " " , " Return channel call count " , NULL , ftdm_api_exec_usage } ,
2011-07-29 23:33:42 +00:00
/* Fake handlers as they are handled within freetdm library,
* we should provide a way inside freetdm to query for completions from signaling modules */
2013-03-08 20:15:07 +00:00
{ " core state " , " [!]<state_name> " , " " , NULL , NULL , NULL } ,
{ " core flag " , " [!]<flag-int-value|flag-name> [<span_id|span_name>] [<chan_id>] " , " " , NULL , NULL , NULL } ,
{ " core spanflag " , " [!]<flag-int-value|flag-name> [<span_id|span_name>] " , " " , NULL , NULL , NULL } ,
{ " core calls " , " " , " " , NULL , NULL , NULL } ,
2011-07-29 23:33:42 +00:00
} ;
2011-08-04 14:09:28 +00:00
static void print_usage ( switch_stream_handle_t * stream , ftdm_cli_entry_t * cli )
{
stream - > write_function ( stream , " -ERR Usage: ftdm %s %s \n " , cli - > name , cli - > args ) ;
}
2011-07-29 23:33:42 +00:00
static void print_full_usage ( switch_stream_handle_t * stream )
{
int i = 0 ;
ftdm_cli_entry_t * entry = NULL ;
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
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 ] ;
2013-03-08 20:15:07 +00:00
if ( entry - > execute_api ) {
continue ;
}
2011-07-29 23:33:42 +00:00
stream - > write_function ( stream , " ftdm %s %s \n " , entry - > name , entry - > args ) ;
}
stream - > write_function ( stream , " -------------------------------------------------------------------------------- \n " ) ;
}
2013-03-08 20:15:07 +00:00
SWITCH_STANDARD_API ( ftdm_api_exec )
2011-07-29 23:33:42 +00:00
{
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 ) {
2011-08-04 14:09:28 +00:00
entry - > execute ( entry , cmd , session , stream , argc , argv ) ;
2011-07-29 23:33:42 +00:00
break ;
}
}
2012-09-11 15:12:31 +00:00
2011-07-29 23:33:42 +00:00
/* 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 ;
2012-09-11 15:12:31 +00:00
2010-05-26 15:17:47 +00:00
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
return ;
}
2012-09-11 15:12:31 +00:00
2010-05-26 15:17:47 +00:00
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 ;
}
2012-09-11 15:12:31 +00:00
2010-05-26 15:17:47 +00:00
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 ;
2012-09-11 15:12:31 +00:00
2010-05-25 22:21:34 +00:00
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
return ;
}
2012-09-11 15:12:31 +00:00
2010-05-25 22:21:34 +00:00
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 ;
}
2012-09-11 15:12:31 +00:00
2010-05-25 22:21:34 +00:00
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 ;
}
2012-09-11 15:12:31 +00:00
2008-07-30 15:05:07 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2012-09-11 15:12:31 +00:00
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 ) {
2012-04-02 21:20:35 +00:00
ftdm_global_destroy ( ) ;
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 ) {
2012-04-02 21:20:35 +00:00
ftdm_global_destroy ( ) ;
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 ;
}
2012-09-11 15:12:31 +00:00
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 ;
2012-09-11 15:12:31 +00:00
2013-03-08 20:15:07 +00:00
SWITCH_ADD_API ( commands_api_interface , " ftdm " , " FreeTDM commands " , ftdm_api_exec , " <cmd> <args> " ) ;
2011-07-29 23:33:42 +00:00
for ( i = 0 ; i < ftdm_array_len ( ftdm_cli_options ) ; i + + ) {
char complete_cli [ 512 ] ;
entry = & ftdm_cli_options [ i ] ;
2013-03-08 20:15:07 +00:00
if ( entry - > execute_api ) {
/* This is a stand-alone API */
SWITCH_ADD_API ( commands_api_interface , entry - > name , entry - > desc , ftdm_api_exec_usage , entry - > args ) ;
snprintf ( complete_cli , sizeof ( complete_cli ) , " add %s %s " , entry - > name , entry - > complete ) ;
switch_console_set_complete ( complete_cli ) ;
} else {
snprintf ( complete_cli , sizeof ( complete_cli ) , " add ftdm %s %s " , entry - > name , entry - > complete ) ;
switch_console_set_complete ( complete_cli ) ;
}
2011-07-29 23:33:42 +00:00
}
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 ) ;
2012-09-13 04:00:26 +00:00
#if 0
2012-07-25 22:57:32 +00:00
ctdm_init ( * module_interface ) ;
2012-09-13 04:00:26 +00:00
# endif
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
{
2012-09-11 15:12:31 +00:00
switch_hash_index_t * hi ;
2010-04-14 22:15:22 +00:00
const void * var ;
void * val ;
/* destroy ss7 configs */
for ( hi = switch_hash_first ( NULL , globals . ss7_configs ) ; hi ; hi = switch_hash_next ( hi ) ) {
2012-09-11 15:12:31 +00:00
switch_hash_this ( hi , & var , NULL , & val ) ;
2010-04-14 22:15:22 +00:00
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 :
2013-06-25 16:50:17 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 noet :
2007-05-26 04:45:31 +00:00
*/