2007-05-26 04:45:31 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 / 2006 , Anthony Minessale II < anthmct @ yahoo . com >
*
* 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
* Anthony Minessale II < anthmct @ yahoo . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Anthony Minessale II < anthmct @ yahoo . com >
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 >
2007-05-26 04:45:31 +00:00
*
*
2010-01-15 19:56:54 +00:00
* mod_freetdm . c - - FreeTDM Endpoint Module
2007-05-26 04:45:31 +00:00
*
*/
# include <switch.h>
2010-01-15 19:22:49 +00:00
# include "freetdm.h"
2007-05-26 04:45:31 +00:00
2008-02-18 15:43:54 +00:00
# ifndef __FUNCTION__
# define __FUNCTION__ __SWITCH_FUNC__
# endif
2010-01-15 19:56:54 +00:00
# define FREETDM_VAR_PREFIX "freetdm_"
# define FREETDM_VAR_PREFIX_LEN 8
2008-10-06 19:13:32 +00:00
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 ;
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 ) ,
TFLAG_DEAD = ( 1 < < 5 )
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 ;
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 ;
2007-05-31 02:41:50 +00:00
uint32_t wr_error ;
2007-05-26 04:45:31 +00:00
} ;
2010-05-20 15:43:40 +00:00
/* private data attached to FTDM channels (only FXS for now) */
typedef struct chan_pvt {
unsigned int flags ;
} chan_pvt_t ;
2007-05-26 04:45:31 +00:00
typedef struct private_object private_t ;
2010-05-20 15:43:40 +00:00
struct span_config {
ftdm_span_t * span ;
char dialplan [ 80 ] ;
char context [ 80 ] ;
char dial_regex [ 256 ] ;
char fail_dial_regex [ 256 ] ;
char hold_music [ 256 ] ;
char type [ 256 ] ;
analog_option_t analog_options ;
chan_pvt_t pvts [ FTDM_MAX_CHANNELS_SPAN ] ;
} ;
static struct span_config SPAN_CONFIG [ FTDM_MAX_SPANS_INTERFACE ] = { { 0 } } ;
2007-05-26 04:45:31 +00:00
static switch_status_t channel_on_init ( switch_core_session_t * session ) ;
static switch_status_t channel_on_hangup ( switch_core_session_t * session ) ;
2009-04-14 19:03:03 +00:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session ) ;
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_routing ( switch_core_session_t * session ) ;
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session ) ;
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session ) ;
2008-05-15 19:43:58 +00:00
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
2007-05-26 04:45:31 +00:00
switch_caller_profile_t * outbound_profile ,
2008-01-08 23:33:07 +00:00
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
2009-11-23 18:19:35 +00:00
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause ) ;
2008-05-08 20:27:31 +00:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id ) ;
2007-05-26 04:45:31 +00:00
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig ) ;
2010-01-15 19:22:49 +00:00
ftdm_status_t ftdm_channel_from_event ( ftdm_sigmsg_t * sigmsg , switch_core_session_t * * sp ) ;
void dump_chan ( ftdm_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream ) ;
void dump_chan_xml ( ftdm_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream ) ;
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
static switch_core_session_t * ftdm_channel_get_session ( ftdm_channel_t * channel , int32_t id )
2007-06-11 18:15:09 +00:00
{
switch_core_session_t * session = NULL ;
2010-04-21 15:20:05 +00:00
const char * token = ftdm_channel_get_token ( channel , id ) ;
2007-06-11 18:15:09 +00:00
2010-04-21 15:20:05 +00:00
if ( ! zstr ( token ) ) {
if ( ! ( session = switch_core_session_locate ( token ) ) ) {
ftdm_channel_clear_token ( channel , token ) ;
2008-01-10 00:47:04 +00:00
}
2007-06-11 18:15:09 +00:00
}
return session ;
}
2010-01-15 19:22:49 +00:00
static const char * ftdm_channel_get_uuid ( ftdm_channel_t * channel , int32_t id )
2009-09-06 14:43:58 +00:00
{
2010-04-21 15:20:05 +00:00
return ftdm_channel_get_token ( channel , id ) ;
2009-09-06 14:43:58 +00:00
}
2007-06-11 18:15:09 +00:00
2008-05-01 16:41:10 +00:00
static void stop_hold ( switch_core_session_t * session_a , const char * uuid )
2008-01-10 00:47:04 +00:00
{
switch_core_session_t * session ;
2008-05-01 16:41:10 +00:00
switch_channel_t * channel , * channel_a ;
;
2008-01-10 00:47:04 +00:00
if ( ! uuid ) {
return ;
}
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2008-05-01 16:41:10 +00:00
if ( switch_channel_test_flag ( channel , CF_HOLD ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_unhold ( session ) ;
switch_channel_clear_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_clear_flag ( channel_a , CF_HOLD ) ;
} else {
switch_channel_stop_broadcast ( channel ) ;
2008-09-09 19:17:38 +00:00
switch_channel_wait_for_flag ( channel , CF_BROADCAST , SWITCH_FALSE , 2000 , NULL ) ;
2008-05-01 16:41:10 +00:00
}
2008-04-30 15:17:55 +00:00
2008-01-10 00:47:04 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
2010-01-15 19:22:49 +00:00
static void start_hold ( ftdm_channel_t * ftdmchan , switch_core_session_t * session_a , const char * uuid , const char * stream )
2008-01-10 00:47:04 +00:00
{
switch_core_session_t * session ;
2008-05-01 16:41:10 +00:00
switch_channel_t * channel , * channel_a ;
2010-04-21 15:20:05 +00:00
int32_t spanid = 0 ;
2008-01-10 00:47:04 +00:00
if ( ! uuid ) {
return ;
}
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( ftdmchan ) ;
2008-01-10 00:47:04 +00:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
if ( ! strcasecmp ( globals . hold_music , " indicate_hold " ) ) {
stream = " indicate_hold " ;
}
2010-04-21 15:20:05 +00:00
if ( ! strcasecmp ( SPAN_CONFIG [ spanid ] . hold_music , " indicate_hold " ) ) {
2008-05-01 16:41:10 +00:00
stream = " indicate_hold " ;
}
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2010-04-21 15:20:05 +00:00
stream = SPAN_CONFIG [ spanid ] . hold_music ;
2008-05-01 16:41:10 +00:00
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
stream = globals . hold_music ;
}
2008-01-10 00:47:04 +00:00
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) & & ! ( stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ) ) {
2008-04-30 15:17:55 +00:00
stream = globals . hold_music ;
2008-01-10 00:47:04 +00:00
}
2009-10-23 16:03:57 +00:00
if ( ! zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
if ( ! strcasecmp ( stream , " indicate_hold " ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_hold_uuid ( uuid , NULL , 0 ) ;
switch_channel_set_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_set_flag ( channel_a , CF_HOLD ) ;
} else {
switch_ivr_broadcast ( switch_core_session_get_uuid ( session ) , stream , SMF_ECHO_ALEG | SMF_LOOP ) ;
}
2008-01-10 00:47:04 +00:00
}
switch_core_session_rwunlock ( session ) ;
}
}
2010-01-15 19:22:49 +00:00
static void cycle_foreground ( ftdm_channel_t * ftdmchan , int flash , const char * bcast ) {
2007-06-11 18:15:09 +00:00
uint32_t i = 0 ;
switch_core_session_t * session ;
switch_channel_t * channel ;
private_t * tech_pvt ;
2010-04-29 14:52:42 +00:00
uint32_t tokencnt = ftdm_channel_get_token_count ( ftdmchan ) ;
2007-06-11 18:15:09 +00:00
2008-01-10 00:47:04 +00:00
2010-04-21 15:20:05 +00:00
for ( i = 0 ; i < tokencnt ; i + + ) {
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( ftdmchan , i ) ) ) {
2008-01-10 00:47:04 +00:00
const char * buuid ;
2007-06-11 18:15:09 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
2008-01-10 00:47:04 +00:00
buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2010-04-21 15:20:05 +00:00
if ( tokencnt = = 1 & & flash ) {
2007-06-11 18:15:09 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
2007-06-11 18:15:09 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2010-01-15 19:22:49 +00:00
start_hold ( ftdmchan , session , buuid , bcast ) ;
2007-06-11 18:15:09 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
} else if ( i ) {
2010-01-15 19:22:49 +00:00
start_hold ( ftdmchan , session , buuid , bcast ) ;
2007-06-11 18:15:09 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
2007-06-11 18:15:09 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
switch_channel_mark_answered ( channel ) ;
}
}
switch_core_session_rwunlock ( session ) ;
}
}
}
2010-01-15 19:22:49 +00:00
static switch_status_t tech_init ( private_t * tech_pvt , switch_core_session_t * session , ftdm_channel_t * ftdmchan )
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 ;
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 ;
}
2010-01-15 19:22:49 +00:00
if ( FTDM_SUCCESS ! = ftdm_channel_command ( ftdmchan , FTDM_COMMAND_GET_CODEC , & codec ) ) {
2009-09-14 21:19:07 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to retrieve channel codec. \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2007-05-26 04:45:31 +00:00
switch ( codec ) {
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_ULAW :
2007-05-26 04:45:31 +00:00
{
dname = " PCMU " ;
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_ALAW :
2007-05-26 04:45:31 +00:00
{
dname = " PCMA " ;
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CODEC_SLIN :
2007-05-26 04:45:31 +00:00
{
dname = " L16 " ;
}
break ;
2008-01-08 23:33:07 +00:00
default :
2009-09-14 21:19:07 +00:00
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid codec value retrieved from channel, codec value: %d \n " , codec ) ;
return SWITCH_STATUS_GENERR ;
}
2007-05-26 04:45:31 +00:00
}
if ( switch_core_codec_init ( & tech_pvt - > read_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
return SWITCH_STATUS_GENERR ;
} else {
if ( switch_core_codec_init ( & tech_pvt - > write_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
return SWITCH_STATUS_GENERR ;
}
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Set codec %s %dms \n " , dname , interval ) ;
switch_core_session_set_read_codec ( tech_pvt - > session , & tech_pvt - > read_codec ) ;
switch_core_session_set_write_codec ( tech_pvt - > session , & tech_pvt - > write_codec ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_CODEC ) ;
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
2008-10-17 23:00:47 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_init ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt = NULL ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
2008-05-08 20:27:31 +00:00
/* Move channel's state machine to ROUTING */
2008-05-05 15:47:44 +00:00
switch_channel_set_state ( channel , CS_ROUTING ) ;
2007-05-26 04:45:31 +00:00
switch_mutex_lock ( globals . mutex ) ;
globals . calls + + ;
switch_mutex_unlock ( globals . mutex ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_init ( tech_pvt - > ftdmchan ) ;
2008-04-01 00:38:40 +00:00
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 ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2008-06-05 14:09:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL ROUTING \n " , switch_channel_get_name ( channel ) ) ;
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 ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL EXECUTE \n " , switch_channel_get_name ( channel ) ) ;
return SWITCH_STATUS_SUCCESS ;
}
2009-04-14 19:03:03 +00:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session )
{
private_t * tech_pvt = NULL ;
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
static switch_status_t channel_on_hangup ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2010-04-21 15:20:05 +00:00
ftdm_chan_type_t chantype ;
uint32_t tokencnt ;
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 ) ;
2010-02-09 22:01:15 +00:00
if ( ! tech_pvt - > ftdmchan ) {
goto end ;
}
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
chantype = ftdm_channel_get_type ( tech_pvt - > ftdmchan ) ;
switch ( chantype ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXO :
case FTDM_CHAN_TYPE_EM :
case FTDM_CHAN_TYPE_CAS :
2007-05-31 20:15:16 +00:00
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_hangup ( tech_pvt - > ftdmchan ) ;
2007-05-31 20:15:16 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXS :
2007-05-27 14:58:01 +00:00
{
2010-04-21 15:20:05 +00:00
if ( ! ftdm_channel_call_check_busy ( tech_pvt - > ftdmchan ) & & ! ftdm_channel_call_check_done ( tech_pvt - > ftdmchan ) ) {
tokencnt = ftdm_channel_get_token_count ( tech_pvt - > ftdmchan ) ;
if ( tokencnt ) {
2010-01-15 19:22:49 +00:00
cycle_foreground ( tech_pvt - > ftdmchan , 0 , NULL ) ;
2007-06-11 18:15:09 +00:00
} else {
2010-04-21 15:20:05 +00:00
ftdm_channel_call_hangup ( tech_pvt - > ftdmchan ) ;
2007-06-11 18:15:09 +00:00
}
2007-05-27 14:58:01 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_B :
2007-06-13 03:37:55 +00:00
{
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 ;
}
ftdm_channel_call_hangup_with_cause ( tech_pvt - > ftdmchan , hcause ) ;
2007-06-13 03:37:55 +00:00
}
break ;
2007-05-27 14:58:01 +00:00
default :
{
2010-04-21 15:20:05 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Unhandled channel type %d for channel %s \n " , chantype ,
2009-09-22 15:45:41 +00:00
switch_channel_get_name ( channel ) ) ;
2007-05-27 14:58:01 +00:00
}
break ;
2007-05-26 04:45:31 +00:00
}
2010-02-09 22:01:15 +00:00
end :
2007-05-27 14:58:01 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 04:45:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL HANGUP \n " , switch_channel_get_name ( channel ) ) ;
switch_mutex_lock ( globals . mutex ) ;
globals . calls - - ;
if ( globals . calls < 0 ) {
globals . calls = 0 ;
}
switch_mutex_unlock ( globals . mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( sig ) {
case SWITCH_SIG_KILL :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2008-10-17 23:00:47 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-05-26 04:45:31 +00:00
break ;
case SWITCH_SIG_BREAK :
switch_set_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
2008-05-05 15:47:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL EXCHANGE_MEDIA \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
2008-05-05 15:47:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL SOFT_EXECUTE \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-12-22 02:16:03 +00:00
static switch_status_t channel_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2007-05-26 04:45:31 +00:00
{
private_t * tech_pvt = NULL ;
2007-12-22 02:16:03 +00:00
char tmp [ 2 ] = " " ;
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2007-12-22 02:16:03 +00:00
tmp [ 0 ] = dtmf - > digit ;
2010-01-15 19:22:49 +00:00
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_SEND_DTMF , tmp ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-08 20:27:31 +00:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_size_t len ;
ftdm_wait_flag_t wflags = FTDM_READ ;
2007-05-27 05:23:28 +00:00
char dtmf [ 128 ] = " " ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status ;
2008-05-08 20:27:31 +00:00
int total_to ;
2007-05-31 20:15:16 +00:00
int chunk , do_break = 0 ;
2007-05-26 04:45:31 +00:00
2009-02-07 23:14:25 +00:00
2007-05-26 04:45:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2008-01-25 16:42:06 +00:00
2010-02-09 22:01:15 +00:00
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " TFLAG_DEAD is set \n " ) ;
2010-02-09 22:01:15 +00:00
return SWITCH_STATUS_FALSE ;
}
2007-05-26 04:45:31 +00:00
2009-05-26 21:47:48 +00:00
/* Digium Cards sometimes timeout several times in a row here.
Yes , we support digium cards , ain ' t we nice . . . . . . .
6 double length intervals should compensate */
2010-04-21 15:20:05 +00:00
chunk = ftdm_channel_get_io_interval ( tech_pvt - > ftdmchan ) * 2 ;
2009-05-26 21:47:48 +00:00
total_to = chunk * 6 ;
2007-05-31 20:15:16 +00:00
2007-05-31 02:41:50 +00:00
top :
2007-05-31 20:15:16 +00:00
2008-05-08 20:27:31 +00:00
if ( switch_channel_test_flag ( channel , CF_SUSPEND ) ) {
do_break = 1 ;
}
2007-05-31 20:15:16 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BREAK ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
do_break = 1 ;
}
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) | | do_break ) {
2010-04-21 15:20:05 +00:00
switch_yield ( ftdm_channel_get_io_interval ( tech_pvt - > ftdmchan ) * 1000 ) ;
tech_pvt - > cng_frame . datalen = ftdm_channel_get_io_packet_len ( tech_pvt - > ftdmchan ) ;
2007-05-27 18:14:49 +00:00
tech_pvt - > cng_frame . samples = tech_pvt - > cng_frame . datalen ;
2008-10-17 23:00:47 +00:00
tech_pvt - > cng_frame . flags = SFF_CNG ;
* frame = & tech_pvt - > cng_frame ;
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_get_codec ( tech_pvt - > ftdmchan ) = = FTDM_CODEC_SLIN ) {
2007-05-27 18:14:49 +00:00
tech_pvt - > cng_frame . samples / = 2 ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-27 14:58:01 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " TFLAG_IO is not set \n " ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2010-01-15 19:22:49 +00:00
wflags = FTDM_READ ;
status = ftdm_channel_wait ( tech_pvt - > ftdmchan , & wflags , chunk ) ;
2007-11-17 01:39:28 +00:00
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_FAIL ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_WARNING , " failed to wait for I/O \n " ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2007-05-31 02:41:50 +00:00
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_TIMEOUT ) {
2008-05-08 20:27:31 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2007-05-31 02:41:50 +00:00
total_to - = chunk ;
if ( total_to < = 0 ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_WARNING , " Too many timeouts while waiting for I/O \n " ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-31 02:41:50 +00:00
}
}
goto top ;
2007-05-26 04:45:31 +00:00
}
2010-01-15 19:22:49 +00:00
if ( ! ( wflags & FTDM_READ ) ) {
2010-06-03 23:09:34 +00:00
goto top ;
2007-05-26 04:45:31 +00:00
}
len = tech_pvt - > read_frame . buflen ;
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_read ( tech_pvt - > ftdmchan , tech_pvt - > read_frame . data , & len ) ! = FTDM_SUCCESS ) {
2010-06-02 18:48:37 +00:00
ftdm_log ( FTDM_LOG_WARNING , " failed to read from device \n " ) ;
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
* frame = & tech_pvt - > read_frame ;
2009-03-06 18:17:15 +00:00
tech_pvt - > read_frame . datalen = ( uint32_t ) len ;
2007-05-26 04:45:31 +00:00
tech_pvt - > read_frame . samples = tech_pvt - > read_frame . datalen ;
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_get_codec ( tech_pvt - > ftdmchan ) = = FTDM_CODEC_SLIN ) {
2007-05-26 04:45:31 +00:00
tech_pvt - > read_frame . samples / = 2 ;
}
2010-02-25 23:36:18 +00:00
while ( ftdm_channel_dequeue_dtmf ( tech_pvt - > ftdmchan , dtmf , sizeof ( dtmf ) ) ) {
2007-12-22 02:16:03 +00:00
switch_dtmf_t _dtmf = { 0 , SWITCH_DEFAULT_DTMF_DURATION } ;
2008-01-12 06:11:48 +00:00
char * p ;
for ( p = dtmf ; p & & * p ; p + + ) {
if ( is_dtmf ( * p ) ) {
_dtmf . digit = * p ;
2010-06-03 21:27:43 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Queuing DTMF [%c] in channel %s \n " , * p , switch_channel_get_name ( channel ) ) ;
2008-01-12 06:11:48 +00:00
switch_channel_queue_dtmf ( channel , & _dtmf ) ;
}
}
2007-05-26 04:45:31 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-17 01:39:28 +00:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 04:45:31 +00:00
}
2008-05-08 20:27:31 +00:00
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_size_t len ;
2008-10-03 18:15:04 +00:00
unsigned char data [ SWITCH_RECOMMENDED_BUFFER_SIZE ] = { 0 } ;
2010-01-15 19:22:49 +00:00
ftdm_wait_flag_t wflags = FTDM_WRITE ;
ftdm_status_t status ;
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 ) ;
2010-02-09 22:01:15 +00:00
if ( ! tech_pvt - > ftdmchan ) {
return SWITCH_STATUS_FALSE ;
}
2007-05-26 04:45:31 +00:00
2008-10-17 23:00:47 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
return SWITCH_STATUS_FALSE ;
}
2007-05-27 18:14:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2007-05-31 02:41:50 +00:00
2008-10-03 18:15:04 +00:00
if ( switch_test_flag ( frame , SFF_CNG ) ) {
frame - > data = data ;
frame - > buflen = sizeof ( data ) ;
2008-10-20 18:10:37 +00:00
if ( ( frame - > datalen = tech_pvt - > write_codec . implementation - > encoded_bytes_per_packet ) > frame - > buflen ) {
2008-10-03 18:15:04 +00:00
goto fail ;
}
memset ( data , 255 , frame - > datalen ) ;
}
2010-01-15 19:22:49 +00:00
wflags = FTDM_WRITE ;
2010-04-21 15:20:05 +00:00
status = ftdm_channel_wait ( tech_pvt - > ftdmchan , & wflags , ftdm_channel_get_io_interval ( tech_pvt - > ftdmchan ) * 10 ) ;
2009-07-24 16:01:33 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ( wflags & FTDM_WRITE ) ) {
2010-02-25 23:36:18 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Dropping frame! (write not ready) \n " ) ;
return SWITCH_STATUS_SUCCESS ;
2009-07-24 16:01:33 +00:00
}
2007-05-26 04:45:31 +00:00
len = frame - > datalen ;
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_write ( tech_pvt - > ftdmchan , frame - > data , frame - > buflen , & len ) ! = FTDM_SUCCESS ) {
2007-05-31 02:41:50 +00:00
if ( + + tech_pvt - > wr_error > 10 ) {
2010-03-12 19:25:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " too many I/O write errors! \n " ) ;
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 {
tech_pvt - > wr_error = 0 ;
2007-05-26 04:45:31 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-17 01:39:28 +00:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 04:45:31 +00:00
}
2009-08-19 21:47:56 +00:00
static switch_status_t channel_receive_message_cas ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
2010-04-21 15:20:05 +00:00
uint32_t phy_id ;
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-04-21 15:20:05 +00:00
phy_id = ftdm_channel_get_ph_id ( tech_pvt - > ftdmchan ) ;
ftdm_log ( FTDM_LOG_DEBUG , " Got Freeswitch message in R2 channel %d [%d] \n " , phy_id , msg - > message_id ) ;
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2009-08-19 21:47:56 +00:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_RINGING :
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_PROGRESS ) ;
2009-08-19 21:47:56 +00:00
}
break ;
case SWITCH_MESSAGE_INDICATE_PROGRESS :
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA ) ;
2009-08-19 21:47:56 +00:00
}
break ;
case SWITCH_MESSAGE_INDICATE_ANSWER :
{
2010-04-21 15:20:05 +00:00
ftdm_channel_call_answer ( tech_pvt - > ftdmchan ) ;
2009-08-19 21:47:56 +00:00
}
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2008-08-22 16:55:01 +00:00
2007-05-31 20:15:16 +00:00
static switch_status_t channel_receive_message_b ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
2007-06-13 03:37:55 +00:00
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-01-13 17:53:22 +00:00
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_call_check_hangup ( tech_pvt - > ftdmchan ) ) {
return SWITCH_STATUS_SUCCESS ;
}
if ( switch_channel_test_flag ( channel , CF_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-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_PROGRESS ) ;
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 ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
2007-05-31 20:15:16 +00:00
}
static switch_status_t channel_receive_message_fxo ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-04-21 15:20:05 +00:00
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2007-05-31 20:15:16 +00:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-04-21 15:20:05 +00:00
ftdm_channel_call_answer ( tech_pvt - > ftdmchan ) ;
2007-05-31 20:15:16 +00:00
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_receive_message_fxs ( switch_core_session_t * session , switch_core_session_message_t * msg )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-05-17 23:03:32 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-04-21 15:20:05 +00:00
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2010-02-09 22:01:15 +00:00
2007-05-26 04:45:31 +00:00
switch ( msg - > message_id ) {
2007-05-31 20:15:16 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
2007-05-26 04:45:31 +00:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-04-21 15:20:05 +00:00
ftdm_channel_call_answer ( tech_pvt - > ftdmchan ) ;
switch_channel_mark_answered ( channel ) ;
2007-05-26 04:45:31 +00:00
break ;
case SWITCH_MESSAGE_INDICATE_RINGING :
2010-04-21 15:20:05 +00:00
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) & &
! switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) & &
! switch_channel_test_flag ( channel , CF_RING_READY )
) {
ftdm_channel_call_indicate ( tech_pvt - > ftdmchan , FTDM_CHANNEL_INDICATE_RING ) ;
2008-09-26 17:29:48 +00:00
switch_channel_mark_ring_ready ( channel ) ;
2008-09-26 17:09:10 +00:00
}
2007-05-26 04:45:31 +00:00
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-31 20:15:16 +00:00
static switch_status_t channel_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
private_t * tech_pvt ;
2008-02-26 16:55:54 +00:00
switch_status_t status ;
2009-09-14 14:26:31 +00:00
switch_channel_t * channel ;
const char * var ;
2010-02-09 22:01:15 +00:00
ftdm_channel_t * ftdmchan = NULL ;
2009-09-14 14:26:31 +00:00
2007-05-31 20:15:16 +00:00
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2009-09-14 14:26:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
if ( ! ( ftdmchan = tech_pvt - > ftdmchan ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
if ( ! tech_pvt - > ftdmchan ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
2010-04-21 15:20:05 +00:00
return SWITCH_STATUS_FALSE ;
2010-02-09 22:01:15 +00:00
}
2009-09-14 14:26:31 +00:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
if ( ! switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
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
}
}
}
break ;
2009-10-22 14:55:15 +00:00
case SWITCH_MESSAGE_INDICATE_UUID_CHANGE :
{
2010-01-15 19:22:49 +00:00
ftdm_channel_replace_token ( tech_pvt - > ftdmchan , msg - > string_array_arg [ 0 ] , msg - > string_array_arg [ 1 ] ) ;
2009-10-22 14:55:15 +00:00
}
break ;
2009-09-14 14:26:31 +00:00
default :
break ;
}
2010-04-21 15:20:05 +00:00
switch ( ftdm_channel_get_type ( tech_pvt - > ftdmchan ) ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXS :
case FTDM_CHAN_TYPE_EM :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_fxs ( session , msg ) ;
2008-02-26 22:30:54 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXO :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_fxo ( session , msg ) ;
2008-02-26 22:30:54 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_B :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_b ( session , msg ) ;
2009-08-19 21:47:56 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_CAS :
2009-08-19 21:47:56 +00:00
status = channel_receive_message_cas ( session , msg ) ;
break ;
2007-05-31 20:15:16 +00:00
default :
2008-02-26 16:55:54 +00:00
status = SWITCH_STATUS_FALSE ;
2008-02-26 22:30:54 +00:00
break ;
2007-05-31 20:15:16 +00:00
}
2008-02-26 16:55:54 +00:00
return status ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
switch_state_handler_table_t freetdm_state_handlers = {
2007-05-26 04:45:31 +00:00
/*.on_init */ channel_on_init ,
2008-05-05 15:47:44 +00:00
/*.on_routing */ channel_on_routing ,
2007-05-26 04:45:31 +00:00
/*.on_execute */ channel_on_execute ,
/*.on_hangup */ channel_on_hangup ,
2008-05-05 15:47:44 +00:00
/*.on_exchange_media */ channel_on_exchange_media ,
2009-04-14 19:03:03 +00:00
/*.on_soft_execute */ channel_on_soft_execute ,
/*.on_consume_media */ NULL ,
/*.on_hibernate */ NULL ,
/*.on_reset */ NULL ,
/*.on_park*/ NULL ,
/*.on_reporting*/ NULL ,
/*.on_destroy*/ channel_on_destroy
2007-05-26 04:45:31 +00:00
} ;
2010-01-15 19:22:49 +00:00
switch_io_routines_t freetdm_io_routines = {
2007-05-26 04:45:31 +00:00
/*.outgoing_channel */ channel_outgoing_channel ,
/*.read_frame */ channel_read_frame ,
/*.write_frame */ channel_write_frame ,
/*.kill_channel */ channel_kill_channel ,
/*.send_dtmf */ channel_send_dtmf ,
/*.receive_message*/ channel_receive_message
} ;
/* 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
{
2007-05-31 03:04:26 +00:00
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 ;
2010-01-15 19:22:49 +00:00
ftdm_channel_t * ftdmchan = NULL ;
2007-05-31 03:04:26 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
char name [ 128 ] ;
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 ;
2008-02-29 00:21:04 +00:00
2007-05-31 03:04:26 +00:00
if ( ! outbound_profile ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing caller profile \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( outbound_profile - > destination_number ) ) {
2008-01-07 16:50:20 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-01-25 15:05:37 +00:00
2008-10-06 20:02:55 +00:00
data = switch_core_strdup ( outbound_profile - > pool , outbound_profile - > destination_number ) ;
2008-10-06 15:57:11 +00:00
2010-03-10 20:06:31 +00:00
if ( ! zstr ( outbound_profile - > destination_number ) ) {
dest_num = switch_sanitize_number ( switch_core_strdup ( outbound_profile - > pool , outbound_profile - > destination_number ) ) ;
}
if ( ! zstr ( outbound_profile - > caller_id_number ) ) {
callerid_num = switch_sanitize_number ( switch_core_strdup ( outbound_profile - > pool , outbound_profile - > caller_id_number ) ) ;
}
2010-02-09 22:01:15 +00:00
2010-03-10 20:06:31 +00:00
if ( ! zstr ( callerid_num ) & & ! strcmp ( callerid_num , " 0000000000 " ) ) {
callerid_num = NULL ;
}
2008-10-09 01:18:40 +00:00
if ( ( argc = switch_separate_string ( data , ' / ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) < 2 ) {
2008-10-06 20:02:55 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-10-06 15:57:11 +00:00
2008-10-06 20:02:55 +00:00
if ( switch_is_number ( argv [ 0 ] ) ) {
span_id = atoi ( argv [ 0 ] ) ;
} else {
span_name = argv [ 0 ] ;
}
if ( * argv [ 1 ] = = ' A ' ) {
2010-01-15 19:22:49 +00:00
direction = FTDM_BOTTOM_UP ;
2008-10-06 20:02:55 +00:00
} else if ( * argv [ 1 ] = = ' a ' ) {
2010-01-15 19:22:49 +00:00
direction = FTDM_TOP_DOWN ;
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 ;
}
2008-03-01 00:48:36 +00:00
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_SCREEN ) ) {
caller_data . screen = 1 ;
}
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_HIDE_NUMBER ) ) {
caller_data . pres = 1 ;
}
2009-10-23 16:03:57 +00:00
if ( ! zstr ( dest ) ) {
2010-02-01 21:40:01 +00:00
ftdm_set_string ( caller_data . dnis . digits , dest ) ;
2008-03-01 00:48:36 +00:00
}
2009-01-12 17:46:30 +00:00
2010-01-15 19:22:49 +00:00
if ( ( var = switch_event_get_header ( var_event , " freetdm_outbound_ton " ) ) | | ( var = switch_core_get_variable ( " freetdm_outbound_ton " ) ) ) {
2009-01-12 17:46:30 +00:00
if ( ! strcasecmp ( var , " national " ) ) {
2010-02-01 21:40:01 +00:00
caller_data . dnis . type = FTDM_TON_NATIONAL ;
2009-03-02 22:05:11 +00:00
} else if ( ! strcasecmp ( var , " international " ) ) {
2010-02-01 21:40:01 +00:00
caller_data . dnis . type = FTDM_TON_INTERNATIONAL ;
2009-03-02 22:05:11 +00:00
} else if ( ! strcasecmp ( var , " local " ) ) {
2010-02-01 21:40:01 +00:00
caller_data . dnis . type = FTDM_TON_SUBSCRIBER_NUMBER ;
2009-03-02 22:05:11 +00:00
} else if ( ! strcasecmp ( var , " unknown " ) ) {
2010-02-01 21:40:01 +00:00
caller_data . dnis . type = FTDM_TON_UNKNOWN ;
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
if ( ( var = switch_event_get_header ( var_event , " freetdm_custom_call_data " ) ) | | ( var = switch_core_get_variable ( " freetdm_custom_call_data " ) ) ) {
ftdm_set_string ( caller_data . raw_data , var ) ;
caller_data . raw_data_len = strlen ( var ) ;
}
2009-01-12 18:05:22 +00:00
2010-02-01 21:40:01 +00:00
caller_data . dnis . plan = outbound_profile - > destination_number_numplan ;
2008-03-01 00:48:36 +00:00
2010-03-10 20:06:31 +00:00
/* blindly copy data from outbound_profile. They will be overwritten
* by calling ftdm_caller_data if needed after */
caller_data . cid_num . type = outbound_profile - > caller_ton ;
caller_data . cid_num . plan = outbound_profile - > caller_numplan ;
caller_data . rdnis . type = outbound_profile - > rdnis_ton ;
caller_data . rdnis . plan = outbound_profile - > rdnis_numplan ;
2008-01-25 15:05:37 +00:00
2010-01-15 19:22:49 +00:00
ftdm_set_string ( caller_data . cid_name , outbound_profile - > caller_id_name ) ;
2010-03-10 20:06:31 +00:00
ftdm_set_string ( caller_data . cid_num . digits , switch_str_nil ( outbound_profile - > caller_id_number ) ) ;
2010-01-04 15:26:23 +00:00
if ( group_id > = 0 ) {
2010-01-15 19:22:49 +00:00
status = ftdm_channel_open_by_group ( group_id , direction , & caller_data , & ftdmchan ) ;
2010-01-04 15:26:23 +00:00
} else if ( chan_id ) {
2010-01-15 19:22:49 +00:00
status = ftdm_channel_open ( span_id , chan_id , & ftdmchan ) ;
2007-05-31 20:15:16 +00:00
} else {
2010-01-15 19:22:49 +00:00
status = ftdm_channel_open_by_span ( span_id , direction , & caller_data , & ftdmchan ) ;
2007-05-31 20:15:16 +00:00
}
2007-06-11 18:15:09 +00:00
2010-01-15 19:22:49 +00:00
if ( status ! = FTDM_SUCCESS ) {
2010-02-09 22:01:15 +00:00
if ( caller_data . hangup_cause = = SWITCH_CAUSE_NONE ) {
caller_data . hangup_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION ;
}
return caller_data . hangup_cause ;
2007-05-31 03:04:26 +00:00
}
2010-01-15 19:22:49 +00:00
if ( ( var = switch_event_get_header ( var_event , " 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 ( ftdmchan , FTDM_COMMAND_SET_PRE_BUFFER_SIZE , & tmp ) ;
2009-09-14 14:26:31 +00:00
}
}
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_vars ( ftdmchan ) ;
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 ) ) {
2010-01-15 19:22:49 +00:00
ftdm_channel_add_var ( ftdmchan , v , h - > value ) ;
2008-10-06 19:13:32 +00:00
}
}
}
2010-01-15 19:22:49 +00:00
if ( ( * new_session = switch_core_session_request ( freetdm_endpoint_interface , SWITCH_CALL_DIRECTION_OUTBOUND , pool ) ) ! = 0 ) {
2007-05-26 04:45:31 +00:00
private_t * tech_pvt ;
switch_caller_profile_t * caller_profile ;
2009-01-12 18:05:22 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( * new_session ) ;
2007-05-26 04:45:31 +00:00
switch_core_session_add_stream ( * new_session , NULL ) ;
if ( ( tech_pvt = ( private_t * ) switch_core_session_alloc ( * new_session , sizeof ( private_t ) ) ) ! = 0 ) {
2010-01-15 19:22:49 +00:00
tech_init ( tech_pvt , * new_session , ftdmchan ) ;
2007-05-26 04:45:31 +00:00
} else {
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
}
2010-04-21 15:20:05 +00:00
snprintf ( name , sizeof ( name ) , " FreeTDM/%u:%u/%s " , ftdm_channel_get_span_id ( ftdmchan ) , ftdm_channel_get_id ( ftdmchan ) , dest ) ;
2008-04-01 21:49:35 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Connect outbound channel %s \n " , name ) ;
2007-05-31 03:04:26 +00:00
switch_channel_set_name ( channel , name ) ;
2010-04-21 15:20:05 +00:00
switch_channel_set_variable ( channel , " freetdm_span_name " , ftdm_channel_get_span_name ( ftdmchan ) ) ;
switch_channel_set_variable_printf ( channel , " freetdm_span_number " , " %d " , ftdm_channel_get_span_id ( ftdmchan ) ) ;
switch_channel_set_variable_printf ( channel , " freetdm_chan_number " , " %d " , ftdm_channel_get_id ( ftdmchan ) ) ;
2010-03-10 20:06:31 +00:00
ftdm_channel_set_caller_data ( ftdmchan , & caller_data ) ;
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 03:04:26 +00:00
switch_channel_set_caller_profile ( channel , caller_profile ) ;
tech_pvt - > caller_profile = caller_profile ;
2008-04-01 21:49:35 +00:00
2007-05-31 03:04:26 +00:00
2007-05-26 04:45:31 +00:00
switch_channel_set_flag ( channel , CF_OUTBOUND ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_add_token ( ftdmchan , switch_core_session_get_uuid ( * new_session ) , ftdm_channel_get_token_count ( ftdmchan ) ) ! = FTDM_SUCCESS ) {
2007-05-31 20:15:16 +00:00
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2010-04-23 20:28:01 +00:00
goto fail ;
2007-05-31 20:15:16 +00:00
}
2007-06-11 18:15:09 +00:00
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_call_place ( ftdmchan ) ! = FTDM_SUCCESS ) {
2007-06-11 18:15:09 +00:00
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
switch_core_session_destroy ( new_session ) ;
2010-04-23 20:28:01 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto fail ;
2007-06-11 18:15:09 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_channel_init ( ftdmchan ) ;
2008-10-31 14:30:45 +00:00
2007-05-26 04:45:31 +00:00
return SWITCH_CAUSE_SUCCESS ;
}
2010-04-23 20:28:01 +00:00
fail :
2007-06-14 04:44:44 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdmchan ) {
2010-04-23 20:28:01 +00:00
ftdm_channel_call_hangup_with_cause ( ftdmchan , FTDM_CAUSE_SWITCH_CONGESTION ) ;
2007-05-31 03:04:26 +00:00
}
2007-06-14 04:44:44 +00:00
2007-05-31 03:04:26 +00:00
return cause ;
2007-05-26 04:45:31 +00:00
}
2010-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-04-21 15:20:05 +00:00
uint32_t spanid , chanid ;
2007-05-27 14:58:01 +00:00
char name [ 128 ] ;
2010-05-21 15:10:15 +00:00
ftdm_caller_data_t * channel_caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2007-06-05 16:57:32 +00:00
2007-05-27 14:58:01 +00:00
* sp = NULL ;
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2010-06-01 15:51:27 +00:00
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
2007-05-27 14:58:01 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ( session = switch_core_session_request ( freetdm_endpoint_interface , SWITCH_CALL_DIRECTION_INBOUND , 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
}
switch_core_session_add_stream ( session , NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_alloc ( session , sizeof ( private_t ) ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
if ( tech_init ( tech_pvt , session , sigmsg - > channel ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Initilization Error! \n " ) ;
switch_core_session_destroy ( & session ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-27 14:58:01 +00:00
}
2010-04-21 15:20:05 +00:00
channel_caller_data - > collected [ 0 ] = ' \0 ' ;
2007-06-05 16:57:32 +00:00
2010-04-21 15:20:05 +00:00
if ( zstr ( channel_caller_data - > cid_name ) ) {
switch_set_string ( channel_caller_data - > cid_name , ftdm_channel_get_name ( sigmsg - > channel ) ) ;
2007-06-05 16:57:32 +00:00
}
2010-04-21 15:20:05 +00:00
if ( zstr ( channel_caller_data - > cid_num . digits ) ) {
if ( ! zstr ( channel_caller_data - > ani . digits ) ) {
switch_set_string ( channel_caller_data - > cid_num . digits , channel_caller_data - > ani . digits ) ;
2007-06-05 16:57:32 +00:00
} else {
2010-04-21 15:20:05 +00:00
switch_set_string ( channel_caller_data - > cid_num . digits , ftdm_channel_get_number ( sigmsg - > channel ) ) ;
2007-06-05 16:57:32 +00:00
}
}
2007-11-17 01:39:28 +00:00
2007-05-27 14:58:01 +00:00
tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
2010-01-15 19:56:54 +00:00
" FreeTDM " ,
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ spanid ] . dialplan ,
channel_caller_data - > cid_name ,
channel_caller_data - > cid_num . digits ,
2007-05-27 14:58:01 +00:00
NULL ,
2010-04-21 15:20:05 +00:00
channel_caller_data - > ani . digits ,
channel_caller_data - > aniII ,
channel_caller_data - > rdnis . digits ,
( char * ) modname ,
SPAN_CONFIG [ spanid ] . context ,
channel_caller_data - > dnis . digits ) ;
2008-03-01 00:48:36 +00:00
2007-05-27 14:58:01 +00:00
assert ( tech_pvt - > caller_profile ! = NULL ) ;
2008-03-01 00:48:36 +00:00
2010-04-21 15:20:05 +00:00
if ( channel_caller_data - > screen = = 1 | | channel_caller_data - > screen = = 3 ) {
2008-03-01 00:48:36 +00:00
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_SCREEN ) ;
}
2010-04-21 15:20:05 +00:00
tech_pvt - > caller_profile - > caller_ton = channel_caller_data - > cid_num . type ;
tech_pvt - > caller_profile - > caller_numplan = channel_caller_data - > cid_num . plan ;
tech_pvt - > caller_profile - > ani_ton = channel_caller_data - > ani . type ;
tech_pvt - > caller_profile - > ani_numplan = channel_caller_data - > ani . plan ;
tech_pvt - > caller_profile - > destination_number_ton = channel_caller_data - > dnis . type ;
tech_pvt - > caller_profile - > destination_number_numplan = channel_caller_data - > dnis . plan ;
tech_pvt - > caller_profile - > rdnis_ton = channel_caller_data - > rdnis . type ;
tech_pvt - > caller_profile - > rdnis_numplan = channel_caller_data - > rdnis . plan ;
2010-04-06 17:39:03 +00:00
2010-04-21 15:20:05 +00:00
if ( channel_caller_data - > pres ) {
2008-03-01 00:48:36 +00:00
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER ) ;
}
2010-04-21 15:20:05 +00:00
snprintf ( name , sizeof ( name ) , " FreeTDM/%u:%u/%s " , spanid , chanid , tech_pvt - > caller_profile - > destination_number ) ;
2008-04-01 21:49:35 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Connect inbound channel %s \n " , name ) ;
2007-05-27 14:58:01 +00:00
switch_channel_set_name ( channel , name ) ;
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
2009-03-12 15:27:29 +00:00
2010-04-21 15:20:05 +00:00
switch_channel_set_variable ( channel , " freetdm_span_name " , ftdm_channel_get_span_name ( sigmsg - > channel ) ) ;
switch_channel_set_variable_printf ( channel , " freetdm_span_number " , " %d " , spanid ) ;
switch_channel_set_variable_printf ( channel , " freetdm_chan_number " , " %d " , chanid ) ;
2010-05-21 15:10:15 +00:00
if ( channel_caller_data - > raw_data_len ) {
switch_channel_set_variable_printf ( channel , " freetdm_custom_call_data " , " %s " , channel_caller_data - > raw_data ) ;
}
2007-05-27 14:58:01 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
if ( switch_core_session_thread_launch ( session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error spawning thread \n " ) ;
switch_core_session_destroy ( & session ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-27 14:58:01 +00:00
}
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_add_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) , 0 ) ! = FTDM_SUCCESS ) {
2008-05-21 16:49:22 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error adding token \n " ) ;
2007-05-27 18:14:49 +00:00
switch_core_session_destroy ( & session ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2007-05-27 18:14:49 +00:00
}
2007-05-27 14:58:01 +00:00
* sp = session ;
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-27 14:58:01 +00:00
}
2010-03-10 20:06:31 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_common_signal )
{
switch_event_t * event = NULL ;
2010-04-21 15:20:05 +00:00
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE ;
uint32_t chanid , spanid ;
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2010-03-10 20:06:31 +00:00
switch ( sigmsg - > event_id ) {
case FTDM_SIGEVENT_ALARM_CLEAR :
case FTDM_SIGEVENT_ALARM_TRAP :
{
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_get_alarms ( sigmsg - > channel , & alarmbits ) ! = FTDM_SUCCESS ) {
2010-03-10 20:06:31 +00:00
ftdm_log ( FTDM_LOG_ERROR , " failed to retrieve alarms \n " ) ;
return FTDM_FAIL ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_TRAP ) ! = SWITCH_STATUS_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " failed to create alarms events \n " ) ;
return FTDM_FAIL ;
}
if ( sigmsg - > event_id = = FTDM_SIGEVENT_ALARM_CLEAR ) {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_NOTICE , " Alarm cleared on channel %d:%d \n " , spanid , chanid ) ;
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " condition " , " ftdm-alarm-clear " ) ;
} else {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_NOTICE , " Alarm raised on channel %d:%d \n " , spanid , chanid ) ;
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " condition " , " ftdm-alarm-trap " ) ;
}
}
break ;
default :
return FTDM_SUCCESS ;
break ;
}
2010-04-21 15:20:05 +00:00
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
2010-04-21 15:20:05 +00:00
if ( alarmbits & FTDM_ALARM_RED ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " red " ) ;
2010-03-10 20:06:31 +00:00
}
2010-04-21 15:20:05 +00:00
if ( alarmbits & FTDM_ALARM_YELLOW ) {
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " yellow " ) ;
}
2010-04-21 15:20:05 +00:00
if ( alarmbits & FTDM_ALARM_RAI ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " rai " ) ;
2010-03-10 20:06:31 +00:00
}
2010-04-21 15:20:05 +00:00
if ( alarmbits & FTDM_ALARM_BLUE ) {
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " blue " ) ;
}
2010-04-21 15:20:05 +00:00
if ( alarmbits & FTDM_ALARM_AIS ) {
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " ais " ) ;
}
2010-04-21 15:20:05 +00:00
if ( alarmbits & FTDM_ALARM_GENERAL ) {
2010-03-10 20:06:31 +00:00
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " general " ) ;
}
switch_event_fire ( & event ) ;
return FTDM_BREAK ;
}
2007-05-27 18:14:49 +00:00
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_fxo_signal )
2007-05-26 04:45:31 +00:00
{
2007-05-31 20:15:16 +00:00
switch_core_session_t * session = NULL ;
2007-06-01 00:31:50 +00:00
switch_channel_t * channel = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status ;
2010-04-21 15:20:05 +00:00
uint32_t spanid ;
uint32_t chanid ;
ftdm_caller_data_t * callerdata ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
2010-05-21 15:10:15 +00:00
callerdata = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2007-05-31 20:15:16 +00:00
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got FXO sig %d:%d [%s] \n " , spanid , chanid , ftdm_signal_event2str ( sigmsg - > event_id ) ) ;
2007-05-31 20:15:16 +00:00
switch ( sigmsg - > event_id ) {
2007-11-17 01:39:28 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS_MEDIA :
2007-11-17 01:39:28 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-11-17 01:39:28 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_pre_answered ( channel ) ;
2009-09-01 00:49:10 +00:00
switch_core_session_rwunlock ( session ) ;
2007-11-17 01:39:28 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
2007-11-17 01:39:28 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , 0 ) ;
2007-11-17 01:39:28 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-04-21 15:20:05 +00:00
switch_channel_hangup ( channel , callerdata - > hangup_cause ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-11-17 01:39:28 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2007-06-01 00:31:50 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-06-01 00:31:50 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2007-05-31 20:15:16 +00:00
{
2010-01-15 19:22:49 +00:00
status = ftdm_channel_from_event ( sigmsg , & session ) ;
if ( status ! = FTDM_SUCCESS ) {
2010-04-21 15:20:05 +00:00
ftdm_channel_call_hangup ( sigmsg - > channel ) ;
2007-05-31 20:15:16 +00:00
}
}
break ;
2008-01-08 23:33:07 +00:00
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
sigmsg - > event_id , spanid , chanid ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-05-31 20:15:16 +00:00
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_fxs_signal )
2007-05-26 04:45:31 +00:00
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status = FTDM_SUCCESS ;
2010-04-21 15:20:05 +00:00
uint32_t chanid , spanid , tokencount ;
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
tokencount = ftdm_channel_get_token_count ( sigmsg - > channel ) ;
2007-05-27 14:58:01 +00:00
2010-05-20 15:43:40 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got FXS sig [%s] \n " , ftdm_signal_event2str ( sigmsg - > event_id ) ) ;
2007-05-26 04:45:31 +00:00
2007-05-27 14:58:01 +00:00
switch ( sigmsg - > event_id ) {
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2007-05-31 20:15:16 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-05-31 20:15:16 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS :
2008-09-11 17:55:27 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2008-09-11 17:55:27 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2007-05-27 14:58:01 +00:00
{
2010-01-15 19:22:49 +00:00
status = ftdm_channel_from_event ( sigmsg , & session ) ;
if ( status ! = FTDM_SUCCESS ) {
2010-04-21 15:20:05 +00:00
ftdm_channel_call_indicate ( sigmsg - > channel , FTDM_CHANNEL_INDICATE_BUSY ) ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
2007-05-27 14:58:01 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2008-01-10 00:47:04 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING ;
2010-04-21 15:20:05 +00:00
if ( tokencount ) {
2010-05-17 23:03:32 +00:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2008-01-10 00:47:04 +00:00
switch_core_session_t * session_a , * session_b , * session_t = NULL ;
switch_channel_t * channel_a = NULL , * channel_b = NULL ;
2010-05-17 23:03:32 +00:00
int digits = ! zstr ( caller_data - > collected ) ;
2008-01-10 00:47:04 +00:00
const char * br_a_uuid = NULL , * br_b_uuid = NULL ;
private_t * tech_pvt = NULL ;
2010-04-21 15:20:05 +00:00
if ( ( session_a = switch_core_session_locate ( ftdm_channel_get_token ( sigmsg - > channel , 0 ) ) ) ) {
2008-01-10 00:47:04 +00:00
channel_a = switch_core_session_get_channel ( session_a ) ;
br_a_uuid = switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ;
tech_pvt = switch_core_session_get_private ( session_a ) ;
2008-05-01 16:41:10 +00:00
stop_hold ( session_a , switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-10 00:47:04 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
2010-04-21 15:20:05 +00:00
if ( ( session_b = switch_core_session_locate ( ftdm_channel_get_token ( sigmsg - > channel , 1 ) ) ) ) {
2008-01-10 00:47:04 +00:00
channel_b = switch_core_session_get_channel ( session_b ) ;
br_b_uuid = switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ;
tech_pvt = switch_core_session_get_private ( session_b ) ;
2008-05-01 16:41:10 +00:00
stop_hold ( session_a , switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-10 00:47:04 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
if ( channel_a & & channel_b & & ! switch_channel_test_flag ( channel_a , CF_OUTBOUND ) & & ! switch_channel_test_flag ( channel_b , CF_OUTBOUND ) ) {
cause = SWITCH_CAUSE_ATTENDED_TRANSFER ;
if ( br_a_uuid & & br_b_uuid ) {
switch_ivr_uuid_bridge ( br_a_uuid , br_b_uuid ) ;
} else if ( br_a_uuid & & digits ) {
session_t = switch_core_session_locate ( br_a_uuid ) ;
} else if ( br_b_uuid & & digits ) {
session_t = switch_core_session_locate ( br_b_uuid ) ;
}
}
if ( session_t ) {
2010-05-17 23:03:32 +00:00
switch_ivr_session_transfer ( session_t , caller_data - > collected , NULL , NULL ) ;
2008-01-10 00:47:04 +00:00
switch_core_session_rwunlock ( session_t ) ;
}
if ( session_a ) {
switch_core_session_rwunlock ( session_a ) ;
}
if ( session_b ) {
switch_core_session_rwunlock ( session_b ) ;
}
}
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-05-27 18:14:49 +00:00
channel = switch_core_session_get_channel ( session ) ;
2008-01-10 00:47:04 +00:00
switch_channel_hangup ( channel , cause ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-05-27 18:14:49 +00:00
switch_core_session_rwunlock ( session ) ;
2007-05-27 14:58:01 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , NULL ) ;
2008-01-10 00:47:04 +00:00
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
break ;
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_ADD_CALL :
2008-01-10 00:47:04 +00:00
{
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_FLASH :
2007-05-27 18:14:49 +00:00
{
2010-05-20 15:43:40 +00:00
chan_pvt_t * chanpvt = ftdm_channel_get_private ( sigmsg - > channel ) ;
if ( ! chanpvt ) {
ftdm_log ( FTDM_LOG_ERROR , " %d:%d has no private data, can't handle FXS features! (this is a bug) \n " ,
chanid , spanid ) ;
break ;
}
2010-04-21 15:20:05 +00:00
if ( ftdm_channel_call_check_hold ( sigmsg - > channel ) & & tokencount = = 1 ) {
2008-05-01 16:41:10 +00:00
switch_core_session_t * session ;
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2008-05-01 16:41:10 +00:00
const char * buuid ;
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2010-04-21 15:20:05 +00:00
ftdm_channel_call_unhold ( sigmsg - > channel ) ;
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
switch_core_session_rwunlock ( session ) ;
}
2010-04-21 15:20:05 +00:00
} else if ( tokencount = = 2 & & ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_3WAY ) ) {
2010-05-20 15:43:40 +00:00
if ( switch_test_flag ( chanpvt , ANALOG_OPTION_3WAY ) ) {
switch_clear_flag ( chanpvt , ANALOG_OPTION_3WAY ) ;
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 1 ) ) ) {
2008-01-10 00:47:04 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2008-01-10 00:47:04 +00:00
switch_core_session_rwunlock ( session ) ;
}
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
} else {
char * cmd ;
2010-05-20 15:43:40 +00:00
cmd = switch_mprintf ( " three_way::%s " , ftdm_channel_get_token ( sigmsg - > channel , 0 ) ) ;
switch_set_flag ( chanpvt , ANALOG_OPTION_3WAY ) ;
2008-01-10 00:47:04 +00:00
cycle_foreground ( sigmsg - > channel , 1 , cmd ) ;
free ( cmd ) ;
}
2008-01-25 16:42:06 +00:00
} else if ( ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_CALL_SWAP )
| | ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_3WAY )
) {
2008-01-10 00:47:04 +00:00
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
2010-04-21 15:20:05 +00:00
if ( tokencount = = 1 ) {
ftdm_channel_call_hold ( sigmsg - > channel ) ;
2008-01-10 00:47:04 +00:00
}
}
2007-05-27 18:14:49 +00:00
}
break ;
2007-11-24 18:04:14 +00:00
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_COLLECTED_DIGIT :
2007-11-24 18:04:14 +00:00
{
2010-05-17 23:03:32 +00:00
int span_id = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2007-11-24 18:04:14 +00:00
char * dtmf = sigmsg - > raw_data ;
2010-05-17 23:03:32 +00:00
char * regex = SPAN_CONFIG [ span_id ] . dial_regex ;
char * fail_regex = SPAN_CONFIG [ span_id ] . fail_dial_regex ;
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2007-11-24 18:04:14 +00:00
2009-10-23 16:03:57 +00:00
if ( zstr ( regex ) ) {
2007-11-24 18:04:14 +00:00
regex = NULL ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( fail_regex ) ) {
2007-11-24 18:04:14 +00:00
fail_regex = NULL ;
}
2008-02-18 16:15:24 +00:00
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got DTMF sig [%s] \n " , dtmf ) ;
2010-05-17 23:03:32 +00:00
switch_set_string ( caller_data - > collected , dtmf ) ;
2008-01-10 00:47:04 +00:00
2009-10-23 16:03:57 +00:00
if ( ( regex | | fail_regex ) & & ! zstr ( dtmf ) ) {
2007-11-24 18:04:14 +00:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
match = switch_regex_perform ( dtmf , fail_regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_SUCCESS : FTDM_BREAK ;
2007-11-24 18:04:14 +00:00
switch_regex_safe_free ( re ) ;
2010-05-17 23:03:32 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " DTMF [%s] vs fail regex %s %s \n " , dtmf , fail_regex , match ? " matched " : " did not match " ) ;
2007-11-24 18:04:14 +00:00
}
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_SUCCESS & & regex ) {
2007-11-24 18:04:14 +00:00
match = switch_regex_perform ( dtmf , regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_BREAK : FTDM_SUCCESS ;
2010-05-17 23:03:32 +00:00
switch_regex_safe_free ( re ) ;
ftdm_log ( FTDM_LOG_DEBUG , " DTMF [%s] vs dial regex %s %s \n " , dtmf , regex , match ? " matched " : " did not match " ) ;
2007-11-24 18:04:14 +00:00
}
2010-05-17 23:03:32 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " returning %s to COLLECT event with DTMF %s \n " , status = = FTDM_SUCCESS ? " success " : " break " , dtmf ) ;
2007-11-24 18:04:14 +00:00
}
}
break ;
2008-01-08 23:33:07 +00:00
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
sigmsg - > event_id , spanid , chanid ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
2007-05-27 14:58:01 +00:00
return status ;
2007-05-26 04:45:31 +00:00
}
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_r2_signal )
2009-08-19 21:47:56 +00:00
{
2010-04-21 15:20:05 +00:00
uint32_t phyid , chanid , spanid ;
2009-08-19 21:47:56 +00:00
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status = FTDM_SUCCESS ;
2010-05-21 15:10:15 +00:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2010-04-21 15:20:05 +00:00
phyid = ftdm_channel_get_ph_id ( sigmsg - > channel ) ;
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2009-08-19 21:47:56 +00:00
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Got R2 channel sig [%s] in channel %d \n " , ftdm_signal_event2str ( sigmsg - > event_id ) , phyid ) ;
2009-08-19 21:47:56 +00:00
2010-03-10 20:06:31 +00:00
if ( on_common_signal ( sigmsg ) = = FTDM_BREAK ) {
return FTDM_SUCCESS ;
}
2009-08-19 21:47:56 +00:00
switch ( sigmsg - > event_id ) {
/* on_call_disconnect from the R2 side */
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
2009-08-19 21:47:56 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-04-21 15:20:05 +00:00
switch_channel_hangup ( channel , caller_data - > hangup_cause ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2009-08-19 21:47:56 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
/* on_call_offered from the R2 side */
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2009-08-19 21:47:56 +00:00
{
2010-01-15 19:22:49 +00:00
status = ftdm_channel_from_event ( sigmsg , & session ) ;
2009-08-19 21:47:56 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
case FTDM_SIGEVENT_COLLECTED_DIGIT :
2009-08-19 21:47:56 +00:00
{
2010-05-17 23:03:32 +00:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
int span_id = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
char * regex = SPAN_CONFIG [ span_id ] . dial_regex ;
char * fail_regex = SPAN_CONFIG [ span_id ] . fail_dial_regex ;
2009-08-19 21:47:56 +00:00
2009-10-23 16:03:57 +00:00
if ( zstr ( regex ) ) {
2009-08-19 21:47:56 +00:00
regex = NULL ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( fail_regex ) ) {
2009-08-19 21:47:56 +00:00
fail_regex = NULL ;
}
2010-05-17 23:03:32 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " R2 DNIS so far [%s] \n " , caller_data - > dnis . digits ) ;
2009-08-19 21:47:56 +00:00
2010-05-17 23:03:32 +00:00
if ( ( regex | | fail_regex ) & & ! zstr ( caller_data - > dnis . digits ) ) {
2009-08-19 21:47:56 +00:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
2010-05-17 23:03:32 +00:00
match = switch_regex_perform ( caller_data - > dnis . digits , fail_regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_SUCCESS : FTDM_BREAK ;
2009-08-19 21:47:56 +00:00
switch_regex_safe_free ( re ) ;
}
2010-01-15 19:22:49 +00:00
if ( status = = FTDM_SUCCESS & & regex ) {
2010-05-17 23:03:32 +00:00
match = switch_regex_perform ( caller_data - > dnis . digits , regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
2010-01-15 19:22:49 +00:00
status = match ? FTDM_BREAK : FTDM_SUCCESS ;
2009-08-19 21:47:56 +00:00
}
switch_regex_safe_free ( re ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS :
2009-08-19 21:47:56 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2009-08-19 21:47:56 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
ftdm_tone_type_t tt = FTDM_TONE_DTMF ;
2009-08-19 21:47:56 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_command ( sigmsg - > channel , FTDM_COMMAND_ENABLE_DTMF_DETECT , & tt ) ! = FTDM_SUCCESS ) {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Failed to enable DTMF detection in R2 channel %d:%d \n " , spanid , chanid ) ;
2009-08-19 21:47:56 +00:00
}
switch_core_session_rwunlock ( session ) ;
}
}
break ;
default :
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled event %d from R2 for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
sigmsg - > event_id , spanid , chanid ) ;
2009-08-19 21:47:56 +00:00
}
break ;
}
return status ;
}
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_clear_channel_signal )
2007-06-13 03:37:55 +00:00
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2010-04-21 15:20:05 +00:00
ftdm_caller_data_t * caller_data ;
uint32_t spanid , chanid ;
2007-06-13 03:37:55 +00:00
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " got clear channel sig [%s] \n " , ftdm_signal_event2str ( sigmsg - > event_id ) ) ;
2007-06-13 03:37:55 +00:00
2010-05-21 15:10:15 +00:00
caller_data = ftdm_channel_get_caller_data ( sigmsg - > channel ) ;
2010-04-21 15:20:05 +00:00
chanid = ftdm_channel_get_id ( sigmsg - > channel ) ;
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
2010-03-10 20:06:31 +00:00
if ( on_common_signal ( sigmsg ) = = FTDM_BREAK ) {
return FTDM_SUCCESS ;
}
2007-06-13 03:37:55 +00:00
switch ( sigmsg - > event_id ) {
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_START :
2007-06-13 03:37:55 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_tone_type_t tt = FTDM_TONE_DTMF ;
2009-09-06 14:07:06 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_command ( sigmsg - > channel , FTDM_COMMAND_ENABLE_DTMF_DETECT , & tt ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " TONE ERROR \n " ) ;
2008-01-28 21:45:48 +00:00
}
2010-01-15 19:22:49 +00:00
return ftdm_channel_from_event ( sigmsg , & session ) ;
2007-06-13 03:37:55 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_STOP :
case FTDM_SIGEVENT_RESTART :
2009-09-06 14:07:06 +00:00
{
2010-02-09 22:01:15 +00:00
private_t * tech_pvt = NULL ;
2010-01-15 19:22:49 +00:00
while ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-02-09 22:01:15 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-06-13 03:37:55 +00:00
channel = switch_core_session_get_channel ( session ) ;
2010-04-21 15:20:05 +00:00
switch_channel_hangup ( channel , caller_data - > hangup_cause ) ;
2010-01-15 19:22:49 +00:00
ftdm_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-06-13 03:37:55 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_UP :
2007-06-13 03:37:55 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
ftdm_tone_type_t tt = FTDM_TONE_DTMF ;
2007-06-13 03:37:55 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-01-15 19:22:49 +00:00
if ( ftdm_channel_command ( sigmsg - > channel , FTDM_COMMAND_ENABLE_DTMF_DETECT , & tt ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " TONE ERROR \n " ) ;
2008-02-04 20:40:23 +00:00
}
2007-06-13 03:37:55 +00:00
switch_core_session_rwunlock ( session ) ;
2009-09-06 14:07:06 +00:00
} else {
2010-01-15 19:22:49 +00:00
const char * uuid = ftdm_channel_get_uuid ( sigmsg - > channel , 0 ) ;
2009-09-06 14:43:58 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
2010-04-21 15:20:05 +00:00
spanid , chanid , ( uuid ) ? uuid : " N/A " ) ;
2007-06-13 03:37:55 +00:00
}
}
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS_MEDIA :
2007-06-16 04:39:15 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-06-16 04:39:15 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_pre_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
2009-09-06 14:07:06 +00:00
} else {
2010-01-15 19:22:49 +00:00
const char * uuid = ftdm_channel_get_uuid ( sigmsg - > channel , 0 ) ;
2009-09-06 14:43:58 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
2010-04-21 15:20:05 +00:00
spanid , chanid , ( uuid ) ? uuid : " N/A " ) ;
2007-06-16 04:39:15 +00:00
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_SIGEVENT_PROGRESS :
2007-06-16 04:39:15 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ( session = ftdm_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2007-06-16 04:39:15 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
2009-09-06 14:07:06 +00:00
} else {
2010-01-15 19:22:49 +00:00
const char * uuid = ftdm_channel_get_uuid ( sigmsg - > channel , 0 ) ;
2009-09-06 14:43:58 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
2010-04-21 15:20:05 +00:00
spanid , chanid , ( uuid ) ? uuid : " N/A " ) ;
2007-06-16 04:39:15 +00:00
}
}
2010-04-23 21:34:57 +00:00
break ;
case FTDM_SIGEVENT_SIGSTATUS_CHANGED :
{
2010-04-27 21:21:57 +00:00
ftdm_signaling_status_t * sigstatus = ( ftdm_signaling_status_t * ) ( sigmsg - > raw_data ) ;
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-04-28 17:49:45 +00:00
spanid , chanid , ftdm_signaling_status2str ( * sigstatus ) ) ;
2010-04-23 21:34:57 +00:00
}
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-04-14 15:00:17 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_ss7_signal )
{
2010-04-21 15:20:05 +00:00
uint32_t spanid , chanid ;
2010-04-14 15:00:17 +00:00
if ( on_common_signal ( sigmsg ) = = FTDM_BREAK ) {
return FTDM_SUCCESS ;
}
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
chanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
ftdm_log ( FTDM_LOG_DEBUG , " got ss7 sig %d:%d [%s] \n " , spanid , chanid , ftdm_signal_event2str ( sigmsg - > event_id ) ) ;
2010-04-14 15:00:17 +00:00
return FTDM_SUCCESS ;
}
2010-01-15 20:35:11 +00:00
static FIO_SIGNAL_CB_FUNCTION ( on_analog_signal )
2007-05-27 14:58:01 +00:00
{
2010-04-21 15:20:05 +00:00
uint32_t spanid , chanid ;
ftdm_chan_type_t type ;
2008-01-08 23:33:07 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-09-06 14:07:06 +00:00
2010-04-21 15:20:05 +00:00
spanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
chanid = ftdm_channel_get_span_id ( sigmsg - > channel ) ;
type = ftdm_channel_get_type ( sigmsg - > channel ) ;
2010-03-10 20:06:31 +00:00
if ( on_common_signal ( sigmsg ) = = FTDM_BREAK ) {
return FTDM_SUCCESS ;
}
2010-04-21 15:20:05 +00:00
switch ( type ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXO :
case FTDM_CHAN_TYPE_EM :
2007-05-27 14:58:01 +00:00
{
2007-11-24 18:04:14 +00:00
status = on_fxo_signal ( sigmsg ) ;
2007-05-27 14:58:01 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHAN_TYPE_FXS :
2007-05-27 14:58:01 +00:00
{
2007-11-24 18:04:14 +00:00
status = on_fxs_signal ( sigmsg ) ;
2007-05-27 14:58:01 +00:00
}
break ;
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled analog channel type %d for channel %d:%d \n " ,
2010-04-21 15:20:05 +00:00
type , spanid , chanid ) ;
2007-05-27 14:58:01 +00:00
}
break ;
}
2007-06-01 15:40:12 +00:00
2007-11-24 18:04:14 +00:00
return status ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
static void ftdm_logger ( const char * file , const char * func , int line , int level , const char * fmt , . . . )
2007-05-26 04:45:31 +00:00
{
char * data = NULL ;
va_list ap ;
va_start ( ap , fmt ) ;
if ( switch_vasprintf ( & data , fmt , ap ) ! = - 1 ) {
2008-11-03 20:46:43 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , ( char * ) func , line , NULL , level , " %s " , data ) ;
2007-05-26 04:45:31 +00:00
free ( data ) ;
}
va_end ( ap ) ;
}
2008-01-25 16:42:06 +00:00
static uint32_t enable_analog_option ( const char * str , uint32_t current_options )
{
if ( ! strcasecmp ( str , " 3-way " ) ) {
current_options | = ANALOG_OPTION_3WAY ;
current_options & = ~ ANALOG_OPTION_CALL_SWAP ;
} else if ( ! strcasecmp ( str , " call-swap " ) ) {
current_options | = ANALOG_OPTION_CALL_SWAP ;
current_options & = ~ ANALOG_OPTION_3WAY ;
}
return current_options ;
}
2010-04-14 21:59:39 +00:00
/* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list
* last 2 args are for limited aka dumb recursivity
* */
static int add_config_list_nodes ( switch_xml_t swnode , ftdm_conf_node_t * rootnode ,
const char * list_name , const char * list_element_name ,
const char * sub_list_name , const char * sub_list_element_name )
{
char * var , * val ;
switch_xml_t list ;
switch_xml_t element ;
switch_xml_t param ;
ftdm_conf_node_t * n_list ;
ftdm_conf_node_t * n_element ;
list = switch_xml_child ( swnode , list_name ) ;
if ( ! list ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " no list %s found \n " , list_name ) ;
return - 1 ;
}
if ( ( FTDM_SUCCESS ! = ftdm_conf_node_create ( list_name , & n_list , rootnode ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to create %s node \n " , list_name ) ;
return - 1 ;
}
for ( element = switch_xml_child ( list , list_element_name ) ; element ; element = element - > next ) {
char * element_name = ( char * ) switch_xml_attr ( element , " name " ) ;
if ( ! element_name ) {
continue ;
}
if ( ( FTDM_SUCCESS ! = ftdm_conf_node_create ( list_element_name , & n_element , n_list ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to create %s node for %s \n " , list_element_name , element_name ) ;
return - 1 ;
}
ftdm_conf_node_add_param ( n_element , " name " , element_name ) ;
for ( param = switch_xml_child ( element , " param " ) ; param ; param = param - > next ) {
var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
ftdm_conf_node_add_param ( n_element , var , val ) ;
}
if ( sub_list_name & & sub_list_element_name ) {
if ( add_config_list_nodes ( element , n_element , sub_list_name , sub_list_element_name , NULL , NULL ) ) {
return - 1 ;
}
}
}
return 0 ;
}
2010-04-14 15:00:17 +00:00
static ftdm_conf_node_t * get_ss7_config_node ( switch_xml_t cfg , const char * confname )
{
2010-04-14 21:59:39 +00:00
switch_xml_t signode , ss7configs , isup ;
ftdm_conf_node_t * rootnode ;
/* try to find the conf in the hash first */
rootnode = switch_core_hash_find ( globals . ss7_configs , confname ) ;
if ( rootnode ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " ss7 config %s was found in the hash already \n " , confname ) ;
return rootnode ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " not found %s config in hash, searching in xml ... \n " , confname ) ;
signode = switch_xml_child ( cfg , " signaling_configs " ) ;
if ( ! signode ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " not found 'signaling_configs' XML config section \n " ) ;
return NULL ;
}
ss7configs = switch_xml_child ( signode , " sngss7_configs " ) ;
if ( ! ss7configs ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " not found 'sngss7_configs' XML config section \n " ) ;
return NULL ;
}
/* search the isup config */
for ( isup = switch_xml_child ( ss7configs , " sng_isup " ) ; isup ; isup = isup - > next ) {
char * name = ( char * ) switch_xml_attr ( isup , " name " ) ;
if ( ! name ) {
continue ;
}
if ( ! strcasecmp ( name , confname ) ) {
break ;
}
}
if ( ! isup ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " not found '%s' sng_isup XML config section \n " , confname ) ;
return NULL ;
}
/* found our XML chunk, create the root node */
if ( ( FTDM_SUCCESS ! = ftdm_conf_node_create ( " sng_isup " , & rootnode , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to create root node for sng_isup config %s \n " , confname ) ;
return NULL ;
}
/* add mtp linksets */
if ( add_config_list_nodes ( isup , rootnode , " mtp_linksets " , " mtp_linkset " , " mtp_links " , " mtp_link " ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process mtp_linksets for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
/* add mtp routes */
if ( add_config_list_nodes ( isup , rootnode , " mtp_routes " , " mtp_route " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process mtp_routes for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
/* add isup interfaces */
if ( add_config_list_nodes ( isup , rootnode , " isup_interfaces " , " isup_interface " , NULL , NULL ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " failed to process isup_interfaces for sng_isup config %s \n " , confname ) ;
ftdm_conf_node_destroy ( rootnode ) ;
return NULL ;
}
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
}
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 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * boost_spans [ FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN ] ;
ftdm_span_t * boost_span = NULL ;
2009-11-24 18:15:55 +00:00
unsigned boosti = 0 ;
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 ;
unsigned int chancount = 0 ;
2007-05-26 04:45:31 +00:00
2009-11-24 18:15:55 +00:00
memset ( boost_spans , 0 , sizeof ( boost_spans ) ) ;
2007-05-26 04:45:31 +00:00
memset ( & globals , 0 , sizeof ( globals ) ) ;
switch_mutex_init ( & globals . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " open of %s failed \n " , cf ) ;
return SWITCH_STATUS_TERM ;
}
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " debug " ) ) {
globals . debug = atoi ( val ) ;
2008-01-10 00:47:04 +00:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
switch_set_string ( globals . hold_music , val ) ;
2008-01-25 16:42:06 +00:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
globals . analog_options = enable_analog_option ( val , globals . analog_options ) ;
2007-05-26 04:45:31 +00:00
}
}
}
2010-04-14 15:00:17 +00:00
switch_core_hash_init ( & globals . ss7_configs , module_pool ) ;
2010-06-06 17:07:30 +00:00
if ( ( spans = switch_xml_child ( cfg , " sangoma_ss7_spans " ) ) ) {
2010-04-14 15:00:17 +00:00
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
ftdm_status_t zstatus = FTDM_FAIL ;
2010-04-14 22:36:22 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
ftdm_conf_parameter_t spanparameters [ 30 ] ;
2010-04-14 15:00:17 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
char * configname = ( char * ) switch_xml_attr ( myspan , " config " ) ;
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 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " ss7 span missing required attribute 'id' or 'name', skipping ... \n " ) ;
continue ;
}
if ( ! configname ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_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 ) {
ftdm_log ( FTDM_LOG_ERROR , " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
continue ;
}
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2010-04-14 15:00:17 +00:00
}
ss7confnode = get_ss7_config_node ( cfg , configname ) ;
2010-04-14 21:59:39 +00:00
if ( ! ss7confnode ) {
ftdm_log ( FTDM_LOG_ERROR , " Error finding ss7config '%s' for FreeTDM span id: %s \n " , configname , switch_str_nil ( id ) ) ;
2010-04-14 15:00:17 +00:00
continue ;
}
2010-04-14 21:59:39 +00:00
2010-04-14 22:36:22 +00:00
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
2010-06-06 17:07:30 +00:00
paramindex = 0 ;
spanparameters [ paramindex ] . var = " confnode " ;
spanparameters [ paramindex ] . ptr = ss7confnode ;
paramindex + + ;
2010-04-14 22:36:22 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( sizeof ( spanparameters ) / sizeof ( spanparameters [ 0 ] ) = = paramindex ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Too many parameters for ss7 span, ignoring any parameter after %s \n " , var ) ;
break ;
}
if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
2010-04-14 21:59:39 +00:00
}
}
2010-04-14 22:36:22 +00:00
2010-06-06 17:07:30 +00:00
if ( ftdm_configure_span_signaling ( span ,
" sangoma_ss7 " ,
on_ss7_signal ,
spanparameters ) ! = FTDM_SUCCESS ) {
2010-04-14 22:36:22 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error configuring ss7 FreeTDM span %d \n " , span_id ) ;
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . context , context , sizeof ( SPAN_CONFIG [ span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " Sangoma (SS7) " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2010-04-14 15:00:17 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Configured ss7 FreeTDM span %d with config node %s \n " , span_id , configname ) ;
2010-05-31 10:27:03 +00:00
ftdm_span_start ( span ) ;
2010-04-14 15:00:17 +00:00
}
}
2007-05-26 04:45:31 +00:00
if ( ( spans = switch_xml_child ( cfg , " analog_spans " ) ) ) {
2007-05-27 05:23:28 +00:00
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
2008-09-26 15:36:34 +00:00
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2010-01-15 19:22:49 +00:00
ftdm_status_t zstatus = FTDM_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2007-05-26 04:45:31 +00:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
2008-10-06 19:21:27 +00:00
char * hotline = NULL ;
2007-11-24 18:04:14 +00:00
char * dial_regex = NULL ;
2008-01-10 00:47:04 +00:00
char * hold_music = NULL ;
2007-11-24 18:04:14 +00:00
char * fail_dial_regex = NULL ;
2009-01-13 22:45:09 +00:00
const char * enable_callerid = " true " ;
2010-05-25 16:48:10 +00:00
int callwaiting = 1 ;
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 ;
2008-09-26 15:36:34 +00:00
2007-05-27 05:23:28 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
2007-05-26 04:45:31 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2010-05-25 16:48:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " analog_spans var = %s \n " , var ) ;
2007-05-26 04:45:31 +00:00
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
2007-05-26 04:45:31 +00:00
digit_timeout = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
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 ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
2008-01-10 00:47:04 +00:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
hold_music = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " max_digits " ) | | ! strcasecmp ( var , " max-digits " ) ) {
2008-09-08 23:01:44 +00:00
max_digits = val ;
2008-10-06 19:21:27 +00:00
} else if ( ! strcasecmp ( var , " hotline " ) ) {
hotline = val ;
2010-05-25 16:48:10 +00:00
} else if ( ! strcasecmp ( var , " callwaiting " ) ) {
callwaiting = switch_true ( val ) ? 1 : 0 ;
2008-01-25 16:42:06 +00:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
2007-05-26 04:45:31 +00:00
}
}
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2007-05-26 04:45:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
2008-08-29 20:41:17 +00:00
continue ;
2007-05-26 04:45:31 +00:00
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 15:36:34 +00:00
if ( name ) {
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2008-09-26 15:36:34 +00:00
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find ( span_id , & span ) ;
2008-09-26 15:36:34 +00:00
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
2008-09-26 15:36:34 +00:00
}
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2007-05-26 04:45:31 +00:00
continue ;
}
2008-09-26 15:36:34 +00:00
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2008-09-26 15:36:34 +00:00
}
2007-05-26 04:45:31 +00:00
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " analog " , on_analog_signal ,
2008-08-29 15:58:59 +00:00
" tonemap " , tonegroup ,
" digit_timeout " , & to ,
2008-08-29 20:41:17 +00:00
" max_dialstr " , & max ,
2010-05-25 16:48:10 +00:00
" hotline " , hotline ? hotline : " " ,
2008-09-29 15:51:00 +00:00
" enable_callerid " , enable_callerid ,
2010-05-25 16:48:10 +00:00
" callwaiting " , & callwaiting ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2010-05-20 15:43:40 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error configuring FreeTDM analog span %s \n " , ftdm_span_get_name ( span ) ) ;
2007-05-26 04:45:31 +00:00
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_set_string ( SPAN_CONFIG [ span_id ] . context , context ) ;
switch_set_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan ) ;
SPAN_CONFIG [ span_id ] . analog_options = analog_options | globals . analog_options ;
2008-01-25 16:42:06 +00:00
2010-05-20 15:43:40 +00:00
chancount = ftdm_span_get_chan_count ( span ) ;
for ( i = 1 ; i < = chancount ; i + + ) {
fchan = ftdm_span_get_channel ( span , i ) ;
ftdm_channel_set_private ( fchan , & SPAN_CONFIG [ span_id ] . pvts [ i ] ) ;
}
2007-11-24 18:04:14 +00:00
if ( dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . dial_regex , dial_regex ) ;
2007-11-24 18:04:14 +00:00
}
if ( fail_dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . fail_dial_regex , fail_dial_regex ) ;
2007-11-24 18:04:14 +00:00
}
2007-05-26 04:45:31 +00:00
2008-01-10 00:47:04 +00:00
if ( hold_music ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . hold_music , hold_music ) ;
2008-01-10 00:47:04 +00:00
}
2010-04-21 15:20:05 +00:00
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " analog " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_span_start ( span ) ;
2007-05-26 04:45:31 +00:00
}
}
2008-09-17 02:21:28 +00:00
if ( ( spans = switch_xml_child ( cfg , " analog_em_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2010-01-15 19:22:49 +00:00
ftdm_status_t zstatus = FTDM_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2008-09-17 02:21:28 +00:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
char * dial_regex = NULL ;
char * hold_music = NULL ;
char * fail_dial_regex = NULL ;
uint32_t span_id = 0 , to = 0 , max = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2008-09-17 02:21:28 +00:00
analog_option_t analog_options = ANALOG_OPTION_NONE ;
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
digit_timeout = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
hold_music = val ;
} else if ( ! strcasecmp ( var , " max_digits " ) | | ! strcasecmp ( var , " max-digits " ) ) {
max_digits = val ;
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
}
}
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2008-09-17 02:21:28 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 17:09:10 +00:00
if ( name ) {
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2008-09-26 17:09:10 +00:00
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find ( span_id , & span ) ;
2008-09-26 17:09:10 +00:00
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
2008-09-26 17:09:10 +00:00
}
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2008-09-17 02:21:28 +00:00
continue ;
}
2008-09-26 17:09:10 +00:00
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2008-09-26 17:09:10 +00:00
}
2008-09-17 02:21:28 +00:00
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " analog_em " , on_analog_signal ,
2008-09-17 02:21:28 +00:00
" tonemap " , tonegroup ,
" digit_timeout " , & to ,
" max_dialstr " , & max ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error starting FreeTDM span %d \n " , span_id ) ;
2008-09-17 02:21:28 +00:00
continue ;
}
2010-04-21 15:20:05 +00:00
SPAN_CONFIG [ span_id ] . span = span ;
switch_set_string ( SPAN_CONFIG [ span_id ] . context , context ) ;
switch_set_string ( SPAN_CONFIG [ span_id ] . dialplan , dialplan ) ;
SPAN_CONFIG [ span_id ] . analog_options = analog_options | globals . analog_options ;
2008-09-17 02:21:28 +00:00
if ( dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . dial_regex , dial_regex ) ;
2008-09-17 02:21:28 +00:00
}
if ( fail_dial_regex ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . fail_dial_regex , fail_dial_regex ) ;
2008-09-17 02:21:28 +00:00
}
if ( hold_music ) {
2010-04-21 15:20:05 +00:00
switch_set_string ( SPAN_CONFIG [ span_id ] . hold_music , hold_music ) ;
2008-09-17 02:21:28 +00:00
}
2010-04-21 15:20:05 +00:00
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " analog_em " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_span_start ( span ) ;
2008-09-17 02:21:28 +00:00
}
}
2007-06-13 03:37:55 +00:00
if ( ( spans = switch_xml_child ( cfg , " pri_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * 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 " ;
2008-08-29 15:58:59 +00:00
//Q921NetUser_t mode = Q931_TE;
//Q931Dialect_t dialect = Q931_Dialect_National;
char * mode = NULL ;
char * dialect = NULL ;
2007-06-13 03:37:55 +00:00
uint32_t span_id = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2009-01-13 22:45:09 +00:00
const char * tonegroup = NULL ;
2008-10-12 22:07:45 +00:00
char * digit_timeout = NULL ;
2009-03-19 23:06:04 +00:00
const char * opts = " none " ;
2008-10-12 22:07:45 +00:00
uint32_t to = 0 ;
2008-10-03 21:57:57 +00:00
int q921loglevel = - 1 ;
int q931loglevel = - 1 ;
2010-03-10 20:06:31 +00:00
2009-01-06 01:07:09 +00:00
// quick debug
2009-01-30 11:37:11 +00:00
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ID: '%s', Name:'%s'\n",id,name);
2008-10-03 21:57:57 +00:00
2007-06-13 03:37:55 +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 " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
} else if ( ! strcasecmp ( var , " mode " ) ) {
2008-08-29 15:58:59 +00:00
mode = val ;
2007-06-13 03:37:55 +00:00
} else if ( ! strcasecmp ( var , " dialect " ) ) {
2008-08-29 15:58:59 +00:00
dialect = val ;
2008-10-03 21:57:57 +00:00
} else if ( ! strcasecmp ( var , " q921loglevel " ) ) {
if ( ( q921loglevel = switch_log_str2level ( val ) ) = = SWITCH_LOG_INVALID ) {
q921loglevel = - 1 ;
}
} else if ( ! strcasecmp ( var , " q931loglevel " ) ) {
if ( ( q931loglevel = switch_log_str2level ( val ) ) = = SWITCH_LOG_INVALID ) {
q931loglevel = - 1 ;
}
2007-06-13 03:37:55 +00:00
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
2009-03-19 23:06:04 +00:00
} else if ( ! strcasecmp ( var , " opts " ) ) {
opts = val ;
2007-06-13 03:37:55 +00:00
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2008-10-12 22:07:45 +00:00
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
digit_timeout = val ;
}
2007-06-13 03:37:55 +00:00
}
2008-10-03 21:57:57 +00:00
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2007-06-13 03:37:55 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
2008-02-29 00:21:04 +00:00
continue ;
2007-06-13 03:37:55 +00:00
}
2008-10-24 20:41:52 +00:00
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
}
2007-06-13 03:37:55 +00:00
}
2008-09-26 17:09:10 +00:00
2008-10-12 22:07:45 +00:00
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2007-06-13 03:37:55 +00:00
continue ;
}
2009-01-30 11:37:11 +00:00
2010-04-21 15:20:05 +00:00
if ( ! span_id ) {
span_id = ftdm_span_get_id ( span ) ;
}
2009-01-30 11:37:11 +00:00
2008-09-26 17:09:10 +00:00
if ( ! tonegroup ) {
tonegroup = " us " ;
}
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " isdn " , on_clear_channel_signal ,
2008-10-12 22:07:45 +00:00
" mode " , mode ,
2008-08-29 20:41:17 +00:00
" dialect " , dialect ,
2008-10-12 22:07:45 +00:00
" digit_timeout " , & to ,
2008-10-07 15:27:51 +00:00
" opts " , opts ,
2009-12-14 17:47:41 +00:00
" tonemap " , tonegroup ,
2008-10-03 21:57:57 +00:00
" q921loglevel " , q921loglevel ,
" q931loglevel " , q931loglevel ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " Error starting FreeTDM span %d mode: %s dialect: %s error: %s \n " , span_id ,
mode , dialect , ftdm_span_get_last_error ( span ) ) ;
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
}
}
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 * 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-02-07 23:14:25 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * o_node = " cpe " ;
const char * o_switch = " dms100 " ;
const char * o_dp = " unknown " ;
const char * o_l1 = " ulaw " ;
2009-03-19 20:15:39 +00:00
const char * o_debug = " none " ;
const char * opts = " none " ;
2009-02-07 23:14:25 +00:00
uint32_t span_id = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2009-03-19 20:15:39 +00:00
2009-02-07 23:14:25 +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 " ) ;
if ( ! strcasecmp ( var , " node " ) ) {
o_node = val ;
} else if ( ! strcasecmp ( var , " switch " ) ) {
o_switch = val ;
} else if ( ! strcasecmp ( var , " dp " ) ) {
o_dp = val ;
} else if ( ! strcasecmp ( var , " l1 " ) ) {
o_l1 = val ;
} else if ( ! strcasecmp ( var , " debug " ) ) {
o_debug = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
2009-03-19 20:15:39 +00:00
} else if ( ! strcasecmp ( var , " opts " ) ) {
opts = val ;
2009-02-07 23:14:25 +00:00
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
}
}
if ( ! id & & ! name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( name ) {
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2009-02-07 23:14:25 +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 ) ;
2009-02-07 23:14:25 +00:00
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
2009-02-07 23:14:25 +00:00
}
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2009-02-07 23:14:25 +00:00
continue ;
}
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2009-02-07 23:14:25 +00:00
}
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " libpri " , on_clear_channel_signal ,
2009-02-07 23:14:25 +00:00
" node " , o_node ,
" switch " , o_switch ,
" dp " , o_dp ,
" l1 " , o_l1 ,
" debug " , o_debug ,
" opts " , opts ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error starting FreeTDM span %d node: %s switch: %s dp: %s l1: %s debug: %s error: %s \n " ,
2009-02-07 23:14:25 +00:00
span_id , switch_str_nil ( o_node ) , switch_str_nil ( o_switch ) , switch_str_nil ( o_dp ) , switch_str_nil ( o_l1 ) , switch_str_nil ( o_debug ) ,
2010-04-21 15:20:05 +00:00
ftdm_span_get_last_error ( span ) ) ;
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
}
}
2008-02-29 00:21:04 +00:00
if ( ( spans = switch_xml_child ( cfg , " boost_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 " ) ;
2009-11-17 18:47:23 +00:00
char * sigmod = ( char * ) switch_xml_attr ( myspan , " sigmod " ) ;
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 " ;
2008-02-29 00:21:04 +00:00
uint32_t span_id = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
ftdm_conf_parameter_t spanparameters [ 30 ] ;
2009-11-17 18:47:23 +00:00
unsigned paramindex = 0 ;
if ( ! id & & ! name ) {
2010-01-15 19:22:49 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " boost span requires an id or name as attribute: <span id=ftid|name=ftname> \n " ) ;
2009-11-17 18:47:23 +00:00
continue ;
}
memset ( spanparameters , 0 , sizeof ( spanparameters ) ) ;
if ( sigmod ) {
spanparameters [ paramindex ] . var = " sigmod " ;
spanparameters [ paramindex ] . val = sigmod ;
paramindex + + ;
}
2008-02-29 00:21:04 +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 " ) ;
2009-11-17 18:47:23 +00:00
if ( sizeof ( spanparameters ) / sizeof ( spanparameters [ 0 ] ) = = paramindex ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Too many parameters for boost span, ignoring any parameter after %s \n " , var ) ;
break ;
}
2010-04-14 22:36:22 +00:00
if ( ! strcasecmp ( var , " context " ) ) {
2008-02-29 00:21:04 +00:00
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2009-11-17 18:47:23 +00:00
} else {
spanparameters [ paramindex ] . var = var ;
spanparameters [ paramindex ] . val = val ;
paramindex + + ;
}
2008-02-29 00:21:04 +00:00
}
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 ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2008-02-29 00:21:04 +00:00
continue ;
}
2008-09-26 17:09:10 +00:00
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2008-09-26 17:09:10 +00:00
}
2008-02-29 00:21:04 +00:00
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span_signaling ( span , " sangoma_boost " , on_clear_channel_signal , spanparameters ) ! = FTDM_SUCCESS ) {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error starting FreeTDM span %d error: %s \n " , span_id , ftdm_span_get_last_error ( span ) ) ;
2008-02-29 00:21:04 +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 ) ) ;
2008-02-29 00:21:04 +00:00
2010-04-21 15:20:05 +00:00
switch_copy_string ( SPAN_CONFIG [ span_id ] . type , " Sangoma (boost) " , sizeof ( SPAN_CONFIG [ span_id ] . type ) ) ;
2009-11-24 18:15:55 +00:00
boost_spans [ boosti + + ] = span ;
2008-02-29 00:21:04 +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 * 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-08-19 21:47:56 +00:00
/* strings */
const char * variant = " itu " ;
const char * category = " national_subscriber " ;
const char * logdir = " /usr/local/freeswitch/log/ " ; /* FIXME: get PREFIX variable */
const char * logging = " notice,warning,error " ;
const char * advanced_protocol_file = " " ;
/* booleans */
int call_files = 0 ;
int get_ani_first = - 1 ;
int immediate_accept = - 1 ;
int double_answer = - 1 ;
int skip_category = - 1 ;
int forced_release = - 1 ;
int charge_calls = - 1 ;
/* integers */
int mfback_timeout = - 1 ;
int metering_pulse_timeout = - 1 ;
int allow_collect_calls = - 1 ;
int max_ani = 10 ;
int max_dnis = 4 ;
/* 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
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 */
if ( ! strcasecmp ( var , " variant " ) ) {
variant = val ;
} else if ( ! strcasecmp ( var , " category " ) ) {
category = val ;
} else if ( ! strcasecmp ( var , " logdir " ) ) {
logdir = val ;
} else if ( ! strcasecmp ( var , " logging " ) ) {
logging = val ;
} else if ( ! strcasecmp ( var , " advanced_protocol_file " ) ) {
advanced_protocol_file = val ;
/* booleans */
} else if ( ! strcasecmp ( var , " allow_collect_calls " ) ) {
allow_collect_calls = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " immediate_accept " ) ) {
immediate_accept = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " double_answer " ) ) {
double_answer = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " skip_category " ) ) {
skip_category = switch_true ( var ) ;
} else if ( ! strcasecmp ( var , " forced_release " ) ) {
forced_release = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " charge_calls " ) ) {
charge_calls = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " get_ani_first " ) ) {
get_ani_first = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " call_files " ) ) {
call_files = switch_true ( val ) ;
/* integers */
} else if ( ! strcasecmp ( var , " mfback_timeout " ) ) {
mfback_timeout = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " metering_pulse_timeout " ) ) {
metering_pulse_timeout = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " max_ani " ) ) {
max_ani = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " max_dnis " ) ) {
max_dnis = atoi ( val ) ;
/* common non r2 stuff */
} 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 ;
}
}
if ( ! id & & ! name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( name ) {
2010-01-15 19:22:49 +00:00
zstatus = ftdm_span_find_by_name ( name , & span ) ;
2009-08-19 21:47:56 +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 ) ;
2009-08-19 21:47:56 +00:00
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
zstatus = ftdm_span_find_by_name ( id , & span ) ;
2009-08-19 21:47:56 +00:00
}
}
2010-01-15 19:22:49 +00:00
if ( zstatus ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error finding FreeTDM span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2009-08-19 21:47:56 +00:00
continue ;
}
if ( ! span_id ) {
2010-04-21 15:20:05 +00:00
span_id = ftdm_span_get_id ( span ) ;
2009-08-19 21:47:56 +00:00
}
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " r2 " , on_r2_signal ,
2009-08-19 21:47:56 +00:00
" variant " , variant ,
" max_ani " , max_ani ,
" max_dnis " , max_dnis ,
" category " , category ,
" logdir " , logdir ,
" logging " , logging ,
" advanced_protocol_file " , advanced_protocol_file ,
" allow_collect_calls " , allow_collect_calls ,
" immediate_accept " , immediate_accept ,
" double_answer " , double_answer ,
" skip_category " , skip_category ,
" forced_release " , forced_release ,
" charge_calls " , charge_calls ,
" get_ani_first " , get_ani_first ,
" call_files " , call_files ,
" mfback_timeout " , mfback_timeout ,
" metering_pulse_timeout " , metering_pulse_timeout ,
2010-04-21 15:20:05 +00:00
FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error configuring R2 FreeTDM span %d, error: %s \n " ,
2010-04-21 15:20:05 +00:00
span_id , 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 ) ) ;
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 ) {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error starting R2 FreeTDM span %d, error: %s \n " , span_id , ftdm_span_get_last_error ( span ) ) ;
2009-08-19 21:47:56 +00:00
continue ;
}
}
}
2007-05-26 04:45:31 +00:00
2009-11-24 18:15:55 +00:00
/* start all boost spans now that we're done configuring. Unfortunately at this point boost modules have the limitation
* of needing all spans to be configured before starting them */
for ( ; i < boosti ; i + + ) {
boost_span = boost_spans [ i ] ;
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_DEBUG , " Starting boost span %d \n " , ftdm_span_get_id ( boost_span ) ) ;
2010-01-15 19:22:49 +00:00
if ( ftdm_span_start ( boost_span ) = = FTDM_FAIL ) {
2010-04-21 15:20:05 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error starting boost FreeTDM span %d, error: %s \n " ,
ftdm_span_get_id ( boost_span ) , ftdm_span_get_last_error ( boost_span ) ) ;
2009-11-24 18:15:55 +00:00
continue ;
}
}
2007-05-26 04:45:31 +00:00
switch_xml_free ( xml ) ;
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 ;
float txgain , rxgain ;
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
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 ) ;
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 "
" 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 "
" cause: %s \n \n " ,
2010-04-21 15:20:05 +00:00
span_id ,
chan_id ,
phspan_id ,
phchan_id ,
alarmflag ? " alarmed " : " ok " ,
ftdm_signaling_status2str ( sigstatus ) ,
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 ) ) ;
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 "
" <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 " ,
ftdm_signaling_status2str ( sigstatus ) ,
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
}
2010-05-25 22:21:34 +00:00
# define FT_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix] || gains <txgain> <rxgain> <span_id> [<chan_id>] || dtmf on|off <span_id> [<chan_id>]"
2010-01-15 19:22:49 +00:00
SWITCH_STANDARD_API ( ft_function )
2008-04-01 17:29:57 +00:00
{
char * mycmd = NULL , * argv [ 10 ] = { 0 } ;
int argc = 0 ;
2009-10-23 16:03:57 +00:00
if ( ! zstr ( cmd ) & & ( mycmd = strdup ( cmd ) ) ) {
2008-04-01 17:29:57 +00:00
argc = switch_separate_string ( mycmd , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
}
if ( ! argc ) {
2010-01-15 19:22:49 +00:00
stream - > write_function ( stream , " %s " , FT_SYNTAX ) ;
2008-04-01 17:29:57 +00:00
goto end ;
}
if ( ! strcasecmp ( argv [ 0 ] , " dump " ) ) {
if ( argc < 2 ) {
2010-05-28 16:44:37 +00:00
stream - > write_function ( stream , " -ERR Usage: ftdm dump <span_id> [<chan_id>] \n " ) ;
2008-04-01 17:29:57 +00:00
goto end ;
} else {
2009-03-11 02:04:18 +00:00
uint32_t chan_id = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span ;
2009-07-31 19:16:47 +00:00
char * as = NULL ;
2009-03-11 02:04:18 +00:00
2010-01-15 19:22:49 +00:00
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
2009-03-11 02:04:18 +00:00
2008-04-01 17:29:57 +00:00
if ( argc > 2 ) {
2009-07-31 19:16:47 +00:00
if ( argv [ 3 ] & & ! strcasecmp ( argv [ 2 ] , " as " ) ) {
as = argv [ 3 ] ;
} else {
chan_id = atoi ( argv [ 2 ] ) ;
}
2008-04-01 17:29:57 +00:00
}
2009-07-31 19:16:47 +00:00
if ( argv [ 4 ] & & ! strcasecmp ( argv [ 3 ] , " as " ) ) {
as = argv [ 4 ] ;
}
2009-10-23 16:03:57 +00:00
if ( ! zstr ( as ) & & ! strcasecmp ( as , " xml " ) ) {
2009-07-31 19:16:47 +00:00
stream - > write_function ( stream , " <channels> \n " ) ;
if ( ! span ) {
stream - > write_function ( stream , " <error>invalid span</error> \n " ) ;
} else {
if ( chan_id ) {
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
stream - > write_function ( stream , " <error>invalid channel</error> \n " ) ;
} else {
dump_chan_xml ( span , chan_id , stream ) ;
}
2009-02-05 02:37:04 +00:00
} else {
2009-07-31 19:16:47 +00:00
uint32_t j ;
2010-04-21 15:20:05 +00:00
uint32_t ccount = ftdm_span_get_chan_count ( span ) ;
for ( j = 1 ; j < = ccount ; j + + ) {
2009-07-31 19:16:47 +00:00
dump_chan_xml ( span , j , stream ) ;
}
2009-02-05 02:37:04 +00:00
}
2009-07-31 19:16:47 +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 {
2009-07-31 19:16:47 +00:00
if ( chan_id ) {
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
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
} else {
dump_chan ( span , chan_id , stream ) ;
}
} else {
uint32_t j ;
2010-04-21 15:20:05 +00:00
uint32_t ccount = ftdm_span_get_chan_count ( span ) ;
2009-07-31 19:16:47 +00:00
stream - > write_function ( stream , " +OK \n " ) ;
2010-04-21 15:20:05 +00:00
for ( j = 1 ; j < = ccount ; j + + ) {
2009-07-31 19:16:47 +00:00
dump_chan ( span , j , stream ) ;
}
2008-04-01 17:29:57 +00:00
}
}
}
}
} else if ( ! strcasecmp ( argv [ 0 ] , " list " ) ) {
int j ;
2010-01-15 19:22:49 +00:00
for ( j = 0 ; j < FTDM_MAX_SPANS_INTERFACE ; j + + ) {
2008-04-01 17:29:57 +00:00
if ( SPAN_CONFIG [ j ] . span ) {
2010-04-28 18:35:10 +00:00
ftdm_channel_t * fchan ;
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE ;
2009-01-13 22:45:09 +00:00
const char * flags = " none " ;
2010-01-15 19:22:49 +00:00
ftdm_signaling_status_t sigstatus ;
2008-04-01 17:29:57 +00:00
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 " ;
}
2010-04-28 18:35:10 +00:00
fchan = ftdm_span_get_channel ( SPAN_CONFIG [ j ] . span , 1 ) ;
if ( fchan ) {
ftdm_channel_get_alarms ( fchan , & alarmbits ) ;
}
2009-11-25 22:53:23 +00:00
2010-01-15 19:22:49 +00:00
if ( ( FTDM_SUCCESS = = ftdm_span_get_sig_status ( SPAN_CONFIG [ j ] . span , & sigstatus ) ) ) {
2009-11-25 22:53:23 +00:00
stream - > write_function ( stream ,
" +OK \n "
" span: %u (%s) \n "
2010-04-27 18:32:36 +00:00
" type: %s \n "
2010-04-28 18:35:10 +00:00
" physical_status: %s \n "
2009-11-25 22:53:23 +00:00
" 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 ,
2010-04-21 15:20:05 +00:00
ftdm_span_get_name ( SPAN_CONFIG [ j ] . span ) ,
2009-11-25 22:53:23 +00:00
SPAN_CONFIG [ j ] . type ,
2010-04-28 18:35:10 +00:00
alarmbits ? " alarmed " : " ok " ,
2010-01-15 19:22:49 +00:00
ftdm_signaling_status2str ( sigstatus ) ,
2010-04-21 15:20:05 +00:00
ftdm_span_get_chan_count ( SPAN_CONFIG [ j ] . span ) ,
2009-11-25 22:53:23 +00:00
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 "
2010-04-28 18:35:10 +00:00
" physical_status: %s \n "
2009-11-25 22:53:23 +00:00
" 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 ,
2010-04-21 15:20:05 +00:00
ftdm_span_get_name ( SPAN_CONFIG [ j ] . span ) ,
2009-11-25 22:53:23 +00:00
SPAN_CONFIG [ j ] . type ,
2010-04-28 18:35:10 +00:00
alarmbits ? " alarmed " : " ok " ,
2010-04-21 15:20:05 +00:00
ftdm_span_get_chan_count ( SPAN_CONFIG [ j ] . span ) ,
2009-11-25 22:53:23 +00:00
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
}
}
2009-03-11 02:04:18 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " stop " ) | | ! strcasecmp ( argv [ 0 ] , " start " ) ) {
char * span_name = argv [ 1 ] ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
ftdm_status_t status ;
2009-01-06 01:07:09 +00:00
2009-03-11 02:04:18 +00:00
if ( span_name ) {
2010-01-15 19:22:49 +00:00
ftdm_span_find_by_name ( span_name , & span ) ;
2009-03-11 02:04:18 +00:00
}
2009-01-06 01:07:09 +00:00
2009-03-11 02:04:18 +00:00
if ( ! span ) {
stream - > write_function ( stream , " -ERR no span \n " ) ;
goto end ;
}
if ( ! strcasecmp ( argv [ 0 ] , " stop " ) ) {
2010-01-15 19:22:49 +00:00
status = ftdm_span_stop ( span ) ;
2009-03-11 02:04:18 +00:00
} else {
2010-01-15 19:22:49 +00:00
status = ftdm_span_start ( span ) ;
2009-03-11 02:04:18 +00:00
}
2010-01-15 19:22:49 +00:00
stream - > write_function ( stream , status = = FTDM_SUCCESS ? " +OK \n " : " -ERR failure \n " ) ;
2009-03-11 02:04:18 +00:00
goto end ;
2009-01-06 01:07:09 +00:00
2009-03-11 02:04:18 +00:00
/*Q931ToPcap enhancement*/
2009-01-30 11:37:11 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " q931_pcap " ) ) {
int32_t span_id = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span ;
2009-01-30 22:27:23 +00:00
const char * pcapfn = NULL ;
2009-01-30 11:37:11 +00:00
char * tmp_path = NULL ;
if ( argc < 3 ) {
2010-05-28 16:44:37 +00:00
stream - > write_function ( stream , " -ERR Usage: ftdm q931_pcap <span_id> on|off [pcapfilename without suffix] \n " ) ;
2009-01-30 11:37:11 +00:00
goto end ;
}
span_id = atoi ( argv [ 1 ] ) ;
if ( ! ( span_id & & ( span = SPAN_CONFIG [ span_id ] . span ) ) ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
/*Look for a given file name or use default file name*/
if ( argc > 3 ) {
if ( argv [ 3 ] ) {
pcapfn = argv [ 3 ] ;
}
}
else {
pcapfn = " q931 " ;
}
/*Add log directory path to file name*/
tmp_path = switch_mprintf ( " %s%s%s.pcap " , SWITCH_GLOBAL_dirs . log_dir , SWITCH_PATH_SEPARATOR , pcapfn ) ;
if ( ! strcasecmp ( argv [ 2 ] , " on " ) ) {
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " isdn " , on_clear_channel_signal , " q931topcap " , 1 , " pcapfilename " , tmp_path , FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_WARNING , " Error couldn't (re-)enable Q931-To-Pcap! \n " ) ;
2009-01-30 11:37:11 +00:00
goto end ;
} else {
stream - > write_function ( stream , " +OK \n " ) ;
}
} else if ( ! strcasecmp ( argv [ 2 ] , " off " ) ) {
2010-04-28 22:16:22 +00:00
if ( ftdm_configure_span ( span , " isdn " , on_clear_channel_signal , " q931topcap " , 0 , FTDM_TAG_END ) ! = FTDM_SUCCESS ) {
2010-01-15 19:22:49 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error couldn't enable Q931-To-Pcap! \n " ) ;
2009-01-30 11:37:11 +00:00
goto end ;
} else {
stream - > write_function ( stream , " +OK \n " ) ;
}
} else {
2010-01-15 19:22:49 +00:00
stream - > write_function ( stream , " -ERR Usage: ft q931_pcap <span_id> on|off [pcapfilename without suffix] \n " ) ;
2009-01-30 11:37:11 +00:00
goto end ;
}
2010-05-25 22:21:34 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " dtmf " ) ) {
unsigned i = 0 ;
uint32_t chan_id = 0 ;
unsigned schan_count = 0 ;
ftdm_span_t * span = NULL ;
ftdm_command_t fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT ;
ftdm_channel_t * fchan ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: dtmf on|off <span_id> [<chan_id>] \n " ) ;
goto end ;
}
if ( switch_true ( argv [ 1 ] ) ) {
fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT ;
} else {
fcmd = FTDM_COMMAND_DISABLE_DTMF_DETECT ;
}
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
schan_count = ftdm_span_get_chan_count ( span ) ;
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > schan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
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 ) ;
}
}
stream - > write_function ( stream , " +OK DTMF detection was %s \n " , fcmd = = FTDM_COMMAND_ENABLE_DTMF_DETECT ? " enabled " : " disabled " ) ;
2010-05-28 16:44:37 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " trace " ) ) {
char tracepath [ 255 ] ;
2010-05-28 22:43:45 +00:00
unsigned i = 0 ;
2010-05-28 16:44:37 +00:00
uint32_t chan_id = 0 ;
2010-05-28 22:43:45 +00:00
uint32_t chan_count = 0 ;
2010-05-28 16:44:37 +00:00
ftdm_span_t * span = NULL ;
ftdm_channel_t * chan = NULL ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: ftdm trace <path> <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
chan_count = ftdm_span_get_chan_count ( span ) ;
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
if ( chan_id ) {
chan = ftdm_span_get_channel ( span , chan_id ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-in-c%d " , argv [ 1 ] , chan_id ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_TRACE_INPUT , tracepath ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-out-c%d " , argv [ 1 ] , 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-c%d " , argv [ 1 ] , i ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_TRACE_INPUT , tracepath ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-out-c%d " , argv [ 1 ] , i ) ;
ftdm_channel_command ( chan , FTDM_COMMAND_TRACE_OUTPUT , tracepath ) ;
}
}
stream - > write_function ( stream , " +OK trace enabled with prefix path %s \n " , argv [ 1 ] ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " notrace " ) ) {
uint32_t i = 0 ;
uint32_t chan_id = 0 ;
2010-05-28 22:43:45 +00:00
uint32_t chan_count = 0 ;
2010-05-28 16:44:37 +00:00
ftdm_channel_t * fchan = NULL ;
ftdm_span_t * span = NULL ;
if ( argc < 2 ) {
stream - > write_function ( stream , " -ERR Usage: oz notrace <span_id> [<chan_id>] \n " ) ;
goto end ;
}
ftdm_span_find_by_name ( argv [ 1 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
chan_count = ftdm_span_get_chan_count ( span ) ;
if ( argc > 2 ) {
chan_id = atoi ( argv [ 2 ] ) ;
if ( chan_id > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
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 ) ;
ftdm_channel_command ( fchan , FTDM_COMMAND_TRACE_END_ALL , NULL ) ;
}
}
stream - > write_function ( stream , " +OK trace disabled \n " ) ;
2010-01-06 20:58:21 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " gains " ) ) {
2010-01-15 21:43:41 +00:00
unsigned int i = 0 ;
2010-01-06 20:58:21 +00:00
float txgain = 0.0 ;
float rxgain = 0.0 ;
uint32_t chan_id = 0 ;
2010-04-21 15:20:05 +00:00
uint32_t ccount = 0 ;
ftdm_channel_t * chan ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2010-01-06 20:58:21 +00:00
if ( argc < 4 ) {
2010-01-15 19:22:49 +00:00
stream - > write_function ( stream , " -ERR Usage: ft gains <txgain> <rxgain> <span_id> [<chan_id>] \n " ) ;
2010-01-06 20:58:21 +00:00
goto end ;
}
2010-01-15 19:22:49 +00:00
ftdm_span_find_by_name ( argv [ 3 ] , & span ) ;
2010-01-06 20:58:21 +00:00
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 4 ) {
chan_id = atoi ( argv [ 4 ] ) ;
2010-04-21 15:20:05 +00:00
if ( chan_id > ftdm_span_get_chan_count ( span ) ) {
2010-01-06 20:58:21 +00:00
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
i = sscanf ( argv [ 1 ] , " %f " , & rxgain ) ;
i + = sscanf ( argv [ 2 ] , " %f " , & txgain ) ;
if ( i ! = 2 ) {
stream - > write_function ( stream , " -ERR invalid gains \n " ) ;
goto end ;
}
2010-04-21 15:20:05 +00:00
2010-01-06 20:58:21 +00:00
if ( chan_id ) {
2010-04-21 15:20:05 +00:00
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 ) ;
2010-01-06 20:58:21 +00:00
} else {
2010-04-21 15:20:05 +00:00
ccount = ftdm_span_get_chan_count ( span ) ;
for ( i = 1 ; i < ccount ; i + + ) {
chan = ftdm_span_get_channel ( span , i ) ;
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
}
}
stream - > write_function ( stream , " +OK gains set to Rx %f and Tx %f \n " , rxgain , txgain ) ;
2008-04-01 17:29:57 +00:00
} else {
2010-04-13 19:17:32 +00:00
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-04-21 15:20:05 +00:00
free ( rply ) ;
2009-02-09 19:13:02 +00:00
} else {
2010-01-15 19:22:49 +00:00
stream - > write_function ( stream , " -ERR Usage: %s \n " , FT_SYNTAX ) ;
2009-02-09 19:13:02 +00:00
}
2008-04-01 17:29:57 +00:00
}
2009-01-30 11:37:11 +00:00
/*Q931ToPcap enhancement done*/
2008-04-01 17:29:57 +00:00
end :
switch_safe_free ( mycmd ) ;
return SWITCH_STATUS_SUCCESS ;
}
2010-05-26 15:17:47 +00:00
SWITCH_STANDARD_APP ( enable_dtmf_function )
{
private_t * tech_pvt ;
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_ENABLE_DTMF_DETECT , NULL ) ;
ftdm_log ( FTDM_LOG_INFO , " DTMF detection enabled in channel %d:%d \n " , ftdm_channel_get_id ( tech_pvt - > ftdmchan ) , ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ) ;
}
2010-05-25 22:21:34 +00:00
SWITCH_STANDARD_APP ( disable_dtmf_function )
{
private_t * tech_pvt ;
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_DISABLE_DTMF_DETECT , NULL ) ;
ftdm_log ( FTDM_LOG_INFO , " DTMF detection Disabled in channel %d:%d \n " , ftdm_channel_get_id ( tech_pvt - > ftdmchan ) , ftdm_channel_get_span_id ( tech_pvt - > ftdmchan ) ) ;
}
2008-04-01 17:29:57 +00:00
2008-07-30 15:05:07 +00:00
SWITCH_STANDARD_APP ( disable_ec_function )
{
private_t * tech_pvt ;
int x = 0 ;
2010-01-15 19:22:49 +00:00
if ( ! switch_core_session_check_interface ( session , freetdm_endpoint_interface ) ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " This application is only for FreeTDM channels. \n " ) ;
2008-07-30 15:05:07 +00:00
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-09 22:01:15 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
2010-01-15 19:22:49 +00:00
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_DISABLE_ECHOCANCEL , & x ) ;
ftdm_channel_command ( tech_pvt - > ftdmchan , FTDM_COMMAND_DISABLE_ECHOTRAIN , & x ) ;
ftdm_log ( FTDM_LOG_INFO , " Echo Canceller Disabled \n " ) ;
2008-07-30 15:05:07 +00:00
}
2010-01-15 19:22:49 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_freetdm_load )
2007-05-26 04:45:31 +00:00
{
2008-04-01 17:29:57 +00:00
switch_api_interface_t * commands_api_interface ;
2008-07-30 15:05:07 +00:00
switch_application_interface_t * app_interface ;
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
ftdm_cpu_monitor_disable ( ) ;
2007-05-26 04:45:31 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdm_global_init ( ) ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error loading FreeTDM \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_TERM ;
}
2010-01-15 19:22:49 +00:00
if ( ftdm_global_configuration ( ) ! = FTDM_SUCCESS ) {
2010-01-15 19:56:54 +00:00
ftdm_log ( FTDM_LOG_ERROR , " Error configuring FreeTDM \n " ) ;
2009-11-18 17:13:33 +00:00
return SWITCH_STATUS_TERM ;
}
2007-05-26 04:45:31 +00:00
if ( load_config ( ) ! = SWITCH_STATUS_SUCCESS ) {
2010-01-15 19:22:49 +00:00
ftdm_global_destroy ( ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_TERM ;
}
2007-07-03 20:38:43 +00:00
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
2010-01-15 19:22:49 +00:00
freetdm_endpoint_interface = switch_loadable_module_create_interface ( * module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
freetdm_endpoint_interface - > interface_name = " freetdm " ;
freetdm_endpoint_interface - > io_routines = & freetdm_io_routines ;
freetdm_endpoint_interface - > state_handler = & freetdm_state_handlers ;
2008-04-01 17:29:57 +00:00
2010-01-15 22:09:36 +00:00
SWITCH_ADD_API ( commands_api_interface , " ftdm " , " FreeTDM commands " , ft_function , FT_SYNTAX ) ;
2007-05-26 04:45:31 +00:00
2008-07-30 15:05:07 +00:00
SWITCH_ADD_APP ( app_interface , " disable_ec " , " Disable Echo Canceller " , " Disable Echo Canceller " , disable_ec_function , " " , SAF_NONE ) ;
2010-05-25 22:21:34 +00:00
SWITCH_ADD_APP ( app_interface , " disable_dtmf " , " Disable DTMF Detection " , " Disable DTMF Detection " , disable_dtmf_function , " " , SAF_NONE ) ;
2010-05-26 15:17:47 +00:00
SWITCH_ADD_APP ( app_interface , " enable_dtmf " , " Enable DTMF Detection " , " Enable DTMF Detection " , enable_dtmf_function , " " , SAF_NONE ) ;
2008-07-30 15:05:07 +00:00
2007-05-26 04:45:31 +00:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
2010-01-15 19:22:49 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_freetdm_shutdown )
2007-11-24 18:04:14 +00:00
{
2010-04-14 22:15:22 +00:00
switch_hash_index_t * hi ;
const void * var ;
void * val ;
/* destroy ss7 configs */
for ( hi = switch_hash_first ( NULL , globals . ss7_configs ) ; hi ; hi = switch_hash_next ( hi ) ) {
switch_hash_this ( hi , & var , NULL , & val ) ;
ftdm_conf_node_destroy ( val ) ;
}
2010-01-15 19:22:49 +00:00
ftdm_global_destroy ( ) ;
2009-02-07 23:14:25 +00:00
// this breaks pika but they are MIA so *shrug*
//return SWITCH_STATUS_NOUNLOAD;
return SWITCH_STATUS_SUCCESS ;
2007-11-24 18:04:14 +00:00
}
2007-05-26 04:45:31 +00:00
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2009-09-14 22:06:20 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2007-05-26 04:45:31 +00:00
*/