2006-02-22 17:16:47 +00:00
/*
2006-01-03 22:13:59 +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
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* 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 >
*
*
2006-01-13 14:23:34 +00:00
* mod_wanpipe . c - - WANPIPE PRI Channel Module
2006-01-03 22:13:59 +00:00
*
*/
2006-02-22 16:47:07 +00:00
2006-01-03 22:13:59 +00:00
# include <switch.h>
# include <libsangoma.h>
# include <sangoma_pri.h>
2006-02-22 16:47:07 +00:00
# include <libteletone.h>
2007-03-02 19:12:26 +00:00
# include <ss7boost_client.h>
2006-12-04 20:51:16 +00:00
# ifndef INVALID_HANDLE_VALUE
# define INVALID_HANDLE_VALUE -1
# endif
2006-03-17 14:47:41 +00:00
//#define DOTRACE
2007-10-09 19:04:35 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_wanpipe_shutdown ) ;
2007-06-13 17:48:49 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_wanpipe_load ) ;
2007-09-29 01:06:08 +00:00
SWITCH_MODULE_DEFINITION ( mod_wanpipe , mod_wanpipe_load , mod_wanpipe_shutdown , NULL ) ;
2007-06-13 17:48:49 +00:00
2006-01-03 22:13:59 +00:00
# define STRLEN 15
2007-10-29 18:10:06 +00:00
switch_endpoint_interface_t * wanpipe_endpoint_interface ;
2006-04-29 06:58:08 +00:00
static switch_memory_pool_t * module_pool = NULL ;
2006-01-03 22:13:59 +00:00
typedef enum {
PFLAG_ANSWER = ( 1 < < 0 ) ,
PFLAG_HANGUP = ( 1 < < 1 ) ,
} PFLAGS ;
typedef enum {
PPFLAG_RING = ( 1 < < 0 ) ,
} PPFLAGS ;
typedef enum {
TFLAG_MEDIA = ( 1 < < 0 ) ,
TFLAG_INBOUND = ( 1 < < 1 ) ,
TFLAG_OUTBOUND = ( 1 < < 2 ) ,
TFLAG_INCOMING = ( 1 < < 3 ) ,
TFLAG_PARSE_INCOMING = ( 1 < < 4 ) ,
TFLAG_ACTIVATE = ( 1 < < 5 ) ,
TFLAG_DTMF = ( 1 < < 6 ) ,
TFLAG_DESTROY = ( 1 < < 7 ) ,
TFLAG_ABORT = ( 1 < < 8 ) ,
TFLAG_SWITCH = ( 1 < < 9 ) ,
2006-03-26 17:42:06 +00:00
TFLAG_NOSIG = ( 1 < < 10 ) ,
2007-03-02 19:12:26 +00:00
TFLAG_BYE = ( 1 < < 11 ) ,
2007-04-17 01:15:06 +00:00
TFLAG_CODEC = ( 1 < < 12 ) ,
TFLAG_HANGUP = ( 1 < < 13 )
2006-01-03 22:13:59 +00:00
} TFLAGS ;
2006-02-24 19:11:49 +00:00
2007-02-09 20:03:07 +00:00
# define DEFAULT_SAMPLES_PER_FRAME 160
2007-03-02 19:12:26 +00:00
# define MAX_SPANS 128
struct channel_map {
char map [ SANGOMA_MAX_CHAN_PER_SPAN ] [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
2007-04-16 23:49:58 +00:00
switch_mutex_t * mutex ;
2007-03-02 19:12:26 +00:00
} ;
2007-04-09 19:27:59 +00:00
unsigned int txseq = 0 ;
unsigned int rxseq = 0 ;
2007-03-02 19:12:26 +00:00
# define SETUP_LEN CORE_MAX_CHAN_PER_SPAN*CORE_MAX_SPANS+1
struct ss7boost_handle {
char * local_ip ;
char * remote_ip ;
int local_port ;
int remote_port ;
ss7boost_client_connection_t mcon ;
switch_mutex_t * mutex ;
struct channel_map span_chanmap [ MAX_SPANS ] ;
char setup_array [ SETUP_LEN ] [ SWITCH_UUID_FORMATTED_LENGTH + 1 ] ;
uint32_t setup_index ;
} ;
typedef struct ss7boost_handle ss7boost_handle_t ;
2007-04-09 19:27:59 +00:00
static int isup_exec_command ( ss7boost_handle_t * ss7boost_handle , int span , int chan , int id , int cmd , int cause ) ;
2006-01-03 22:13:59 +00:00
static struct {
int debug ;
int panic ;
2007-02-09 20:03:07 +00:00
uint32_t samples_per_frame ;
2006-02-22 18:32:15 +00:00
int dtmf_on ;
int dtmf_off ;
2007-06-15 02:58:11 +00:00
int suppress_dtmf_tone ;
int ignore_dtmf_tone ;
2006-02-24 16:47:22 +00:00
int configured_spans ;
2007-03-02 19:12:26 +00:00
int configured_boost_spans ;
2006-02-12 20:38:24 +00:00
char * dialplan ;
2007-08-08 14:37:19 +00:00
char * context ;
2006-09-24 15:25:36 +00:00
switch_hash_t * call_hash ;
switch_mutex_t * hash_mutex ;
2007-02-09 01:34:01 +00:00
switch_mutex_t * channel_mutex ;
2007-03-02 19:12:26 +00:00
ss7boost_handle_t * ss7boost_handle ;
2007-03-22 21:50:59 +00:00
uint32_t fxo_index ;
uint32_t fxs_index ;
2006-02-12 20:38:24 +00:00
} globals ;
struct wanpipe_pri_span {
2006-01-03 22:13:59 +00:00
int span ;
int dchan ;
2006-02-12 20:38:24 +00:00
unsigned int bchans ;
2006-01-03 22:13:59 +00:00
int node ;
int pswitch ;
char * dialplan ;
2006-02-12 20:38:24 +00:00
unsigned int l1 ;
unsigned int dp ;
struct sangoma_pri spri ;
} ;
2006-01-03 22:13:59 +00:00
2006-09-24 15:25:36 +00:00
struct wpsock {
2006-12-04 20:51:16 +00:00
sng_fd_t fd ;
2006-09-24 15:25:36 +00:00
char * name ;
} ;
typedef struct wpsock wpsock_t ;
2007-03-22 21:50:59 +00:00
typedef enum {
ANALOG_TYPE_UNKNOWN ,
ANALOG_TYPE_PHONE_FXS ,
ANLOG_TYPE_LINE_FXO
} analog_type_t ;
typedef enum {
ANALOG_STATE_DOWN ,
ANALOG_STATE_ONHOOK ,
ANALOG_STATE_OFFHOOK ,
ANALOG_STATE_RING
} analog_state_t ;
struct analog_channel {
analog_type_t a_type ;
analog_state_t state ;
wpsock_t * sock ;
int chan ;
int span ;
char * device ;
char * user ;
char * domain ;
char * cid_name ;
char * cid_num ;
} ;
typedef struct analog_channel analog_channel_t ;
# define MAX_ANALOG_CHANNELS 128
static struct analog_channel * FXS_ANALOG_CHANNELS [ MAX_ANALOG_CHANNELS ] ;
static struct analog_channel * FXO_ANALOG_CHANNELS [ MAX_ANALOG_CHANNELS ] ;
2006-02-12 20:38:24 +00:00
static struct wanpipe_pri_span * SPANS [ MAX_SPANS ] ;
2006-01-03 22:13:59 +00:00
struct private_object {
2006-01-20 15:05:05 +00:00
unsigned int flags ; /* FLAGS */
2006-04-29 06:58:08 +00:00
switch_frame_t read_frame ; /* Frame for Writing */
switch_core_session_t * session ;
switch_codec_t read_codec ;
switch_codec_t write_codec ;
2007-03-09 23:51:52 +00:00
unsigned char databuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
unsigned char auxbuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
2006-01-03 22:13:59 +00:00
struct sangoma_pri * spri ;
sangoma_api_hdr_t hdrframe ;
2006-04-29 06:58:08 +00:00
switch_caller_profile_t * caller_profile ;
2006-09-24 15:25:36 +00:00
wpsock_t * wpsock ;
2006-01-03 22:13:59 +00:00
int callno ;
2006-02-22 18:32:15 +00:00
int span ;
2006-01-03 22:13:59 +00:00
int cause ;
2006-02-10 22:26:00 +00:00
q931_call * call ;
2006-02-22 18:32:15 +00:00
teletone_dtmf_detect_state_t dtmf_detect ;
2006-02-22 16:47:07 +00:00
teletone_generation_session_t tone_session ;
2006-04-29 06:58:08 +00:00
switch_buffer_t * dtmf_buffer ;
2006-03-17 14:47:41 +00:00
unsigned int skip_read_frames ;
unsigned int skip_write_frames ;
2006-06-23 16:59:47 +00:00
switch_mutex_t * flag_mutex ;
2007-02-09 20:03:07 +00:00
int frame_size ;
2007-03-02 19:12:26 +00:00
ss7boost_handle_t * ss7boost_handle ;
int boost_chan_number ;
int boost_span_number ;
int boost_trunk_group ;
uint32_t setup_index ;
uint32_t boost_pres ;
2006-03-17 14:47:41 +00:00
# ifdef DOTRACE
int fd ;
int fd2 ;
# endif
2006-01-03 22:13:59 +00:00
} ;
2007-02-09 01:34:01 +00:00
typedef struct private_object private_object_t ;
2006-01-03 22:13:59 +00:00
2007-03-22 21:50:59 +00:00
2007-04-19 15:34:30 +00:00
static void wp_logger ( char * file , const char * func , int line , int level , char * fmt , . . . )
{
va_list ap ;
char * data = NULL ;
int ret ;
va_start ( ap , fmt ) ;
if ( ( ret = switch_vasprintf ( & data , fmt , ap ) ) ! = - 1 ) {
2007-06-20 11:02:45 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , func , line , NULL , level , " %s " , data ) ;
2007-04-19 15:34:30 +00:00
}
va_end ( ap ) ;
}
2007-04-09 19:27:59 +00:00
static int local_sangoma_tdm_read_event ( sng_fd_t fd , wp_tdm_api_rx_hdr_t * rx_event )
2007-03-22 21:50:59 +00:00
{
wanpipe_tdm_api_t tdm_api [ 1 ] ;
2007-04-09 19:27:59 +00:00
2007-03-22 21:50:59 +00:00
# if defined(WIN32)
2007-04-09 19:27:59 +00:00
rx_event = & last_tdm_api_event_buffer ;
2007-03-22 21:50:59 +00:00
# else
2007-04-09 19:27:59 +00:00
int err ;
2007-03-22 21:50:59 +00:00
2007-04-09 19:27:59 +00:00
tdm_api - > wp_tdm_cmd . cmd = SIOC_WP_TDM_READ_EVENT ;
2007-03-22 21:50:59 +00:00
2007-04-09 19:27:59 +00:00
if ( ( err = sangoma_tdm_cmd_exec ( fd , tdm_api ) ) ) {
return err ;
}
2007-03-22 21:50:59 +00:00
2007-04-09 19:27:59 +00:00
rx_event = & tdm_api - > wp_tdm_cmd . event ;
2007-03-22 21:50:59 +00:00
# endif
return 0 ;
}
2007-04-09 19:27:59 +00:00
static int analog_set_state ( analog_channel_t * alc , analog_state_t state )
2007-03-22 21:50:59 +00:00
{
alc - > state = state ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Changing State to %d \n " , state ) ;
}
2007-04-09 19:27:59 +00:00
static void analog_check_state ( analog_channel_t * alc )
2007-03-22 21:50:59 +00:00
{
wanpipe_tdm_api_t tdm_api ;
2007-04-09 19:27:59 +00:00
switch ( alc - > state ) {
2007-03-22 21:50:59 +00:00
case ANALOG_STATE_DOWN :
sangoma_tdm_enable_rxhook_events ( alc - > sock - > fd , & tdm_api ) ;
analog_set_state ( alc , ANALOG_STATE_ONHOOK ) ;
break ;
default :
break ;
}
}
2007-04-09 19:27:59 +00:00
static void analog_parse_event ( analog_channel_t * alc )
2007-03-22 21:50:59 +00:00
{
wp_tdm_api_rx_hdr_t rx_event ;
int err = local_sangoma_tdm_read_event ( alc - > sock - > fd , & rx_event ) ;
2007-04-09 19:27:59 +00:00
2007-03-22 21:50:59 +00:00
if ( err < 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error reading event! \n " ) ;
return ;
}
switch ( rx_event . wp_tdm_api_event_type ) {
case WP_TDM_EVENT_RXHOOK :
printf ( " hook \n " ) ;
break ;
}
}
2007-04-09 19:27:59 +00:00
static void * SWITCH_THREAD_FUNC fxs_thread_run ( switch_thread_t * thread , void * obj )
2007-03-22 21:50:59 +00:00
{
2007-04-09 19:27:59 +00:00
for ( ; ; ) {
2007-03-22 21:50:59 +00:00
int i = 0 , sel_on = - 1 ;
fd_set oob ;
FD_ZERO ( & oob ) ;
2007-04-09 19:27:59 +00:00
for ( i = 0 ; i < globals . fxs_index ; i + + ) {
2007-04-09 22:26:03 +00:00
int fd ;
2007-03-22 21:50:59 +00:00
assert ( FXS_ANALOG_CHANNELS [ i ] ) ;
assert ( FXS_ANALOG_CHANNELS [ i ] - > sock ) ;
fd = FXS_ANALOG_CHANNELS [ i ] - > sock - > fd ;
2007-04-09 19:27:59 +00:00
2007-03-22 21:50:59 +00:00
analog_check_state ( FXS_ANALOG_CHANNELS [ i ] ) ;
FD_SET ( fd , & oob ) ;
if ( fd > sel_on ) {
sel_on = fd ;
}
}
if ( sel_on > - 1 ) {
if ( select ( + + sel_on , NULL , NULL , & oob , NULL ) ) {
2007-04-09 19:27:59 +00:00
for ( i = 0 ; i < globals . fxs_index ; i + + ) {
2007-03-22 21:50:59 +00:00
int fd = FXS_ANALOG_CHANNELS [ i ] - > sock - > fd ;
if ( FD_ISSET ( fd , & oob ) ) {
analog_parse_event ( FXS_ANALOG_CHANNELS [ i ] ) ;
}
}
}
}
}
}
2007-04-16 20:26:21 +00:00
static wpsock_t * wp_open ( int span , int chan )
2006-09-24 15:25:36 +00:00
{
2006-12-04 20:51:16 +00:00
sng_fd_t fd ;
2006-09-24 15:25:36 +00:00
wpsock_t * sock ;
char name [ 25 ] ;
2007-04-09 19:27:59 +00:00
2006-09-24 15:25:36 +00:00
snprintf ( name , sizeof ( name ) , " s%dc%d " , span , chan ) ;
switch_mutex_lock ( globals . hash_mutex ) ;
if ( ( sock = switch_core_hash_find ( globals . call_hash , name ) ) ) {
fd = sock - > fd ;
} else {
2006-12-04 20:51:16 +00:00
if ( ( fd = sangoma_open_tdmapi_span_chan ( span , chan ) ) ! = INVALID_HANDLE_VALUE ) {
2006-09-24 15:25:36 +00:00
if ( ( sock = malloc ( sizeof ( * sock ) ) ) ) {
memset ( sock , 0 , sizeof ( * sock ) ) ;
sock - > fd = fd ;
sock - > name = strdup ( name ) ;
switch_core_hash_insert ( globals . call_hash , sock - > name , sock ) ;
}
}
}
switch_mutex_unlock ( globals . hash_mutex ) ;
2007-03-22 21:50:59 +00:00
return sock ;
2006-09-24 15:25:36 +00:00
}
static int wp_restart ( int span , int chan )
{
wpsock_t * sock ;
2006-12-04 20:51:16 +00:00
sng_fd_t fd ;
2006-09-24 15:25:36 +00:00
char name [ 25 ] ;
2007-04-09 19:27:59 +00:00
2006-09-24 15:25:36 +00:00
snprintf ( name , sizeof ( name ) , " s%dc%d " , span , chan ) ;
switch_mutex_lock ( globals . hash_mutex ) ;
if ( ( sock = switch_core_hash_find ( globals . call_hash , name ) ) ) {
switch_core_hash_delete ( globals . call_hash , sock - > name ) ;
fd = sock - > fd ;
} else {
fd = sangoma_open_tdmapi_span_chan ( span , chan ) ;
}
switch_mutex_unlock ( globals . hash_mutex ) ;
2006-12-04 20:51:16 +00:00
if ( fd ! = INVALID_HANDLE_VALUE ) {
sangoma_socket_close ( & fd ) ;
2006-09-24 15:25:36 +00:00
return 0 ;
}
2007-04-09 19:27:59 +00:00
2006-09-24 15:25:36 +00:00
return - 1 ;
}
2006-01-03 22:13:59 +00:00
static void set_global_dialplan ( char * dialplan )
{
if ( globals . dialplan ) {
free ( globals . dialplan ) ;
globals . dialplan = NULL ;
}
2006-01-20 15:05:05 +00:00
2006-01-03 22:13:59 +00:00
globals . dialplan = strdup ( dialplan ) ;
}
2007-08-08 14:37:19 +00:00
static void set_global_context ( char * context )
{
if ( globals . context ) {
free ( globals . context ) ;
globals . context = NULL ;
}
globals . context = strdup ( context ) ;
}
2006-01-03 22:13:59 +00:00
static int str2node ( char * node )
{
if ( ! strcasecmp ( node , " cpe " ) )
return PRI_CPE ;
if ( ! strcasecmp ( node , " network " ) )
return PRI_NETWORK ;
return - 1 ;
}
static int str2switch ( char * swtype )
{
2007-02-09 21:32:12 +00:00
if ( ! strcasecmp ( swtype , " ni1 " ) )
return PRI_SWITCH_NI1 ;
2006-01-03 22:13:59 +00:00
if ( ! strcasecmp ( swtype , " ni2 " ) )
return PRI_SWITCH_NI2 ;
if ( ! strcasecmp ( swtype , " dms100 " ) )
return PRI_SWITCH_DMS100 ;
if ( ! strcasecmp ( swtype , " lucent5e " ) )
return PRI_SWITCH_LUCENT5E ;
if ( ! strcasecmp ( swtype , " att4ess " ) )
return PRI_SWITCH_ATT4ESS ;
if ( ! strcasecmp ( swtype , " euroisdn " ) )
return PRI_SWITCH_EUROISDN_E1 ;
if ( ! strcasecmp ( swtype , " gr303eoc " ) )
return PRI_SWITCH_GR303_EOC ;
if ( ! strcasecmp ( swtype , " gr303tmc " ) )
return PRI_SWITCH_GR303_TMC ;
return - 1 ;
}
2006-02-12 20:38:24 +00:00
static int str2l1 ( char * l1 )
{
if ( ! strcasecmp ( l1 , " alaw " ) )
return PRI_LAYER_1_ALAW ;
return PRI_LAYER_1_ULAW ;
}
static int str2dp ( char * dp )
{
if ( ! strcasecmp ( dp , " international " ) )
return PRI_INTERNATIONAL_ISDN ;
if ( ! strcasecmp ( dp , " national " ) )
return PRI_NATIONAL_ISDN ;
if ( ! strcasecmp ( dp , " local " ) )
return PRI_LOCAL_ISDN ;
if ( ! strcasecmp ( dp , " private " ) )
2007-04-09 19:27:59 +00:00
return PRI_PRIVATE ;
2006-02-12 20:38:24 +00:00
if ( ! strcasecmp ( dp , " unknown " ) )
return PRI_UNKNOWN ;
return PRI_UNKNOWN ;
}
2006-03-30 23:02:50 +00:00
2006-01-03 22:13:59 +00:00
static void set_global_dialplan ( char * dialplan ) ;
2007-08-08 14:37:19 +00:00
static void set_global_context ( char * context ) ;
2006-01-03 22:13:59 +00:00
static int str2node ( char * node ) ;
static int str2switch ( char * swtype ) ;
2006-05-01 04:29:44 +00:00
static switch_status_t wanpipe_on_init ( switch_core_session_t * session ) ;
static switch_status_t wanpipe_on_hangup ( switch_core_session_t * session ) ;
2008-05-05 15:30:55 +00:00
static switch_status_t wanpipe_on_exchange_media ( switch_core_session_t * session ) ;
static switch_status_t wanpipe_on_soft_execute ( switch_core_session_t * session ) ;
2007-04-09 19:27:59 +00:00
static switch_call_cause_t wanpipe_outgoing_channel ( switch_core_session_t * session , switch_caller_profile_t * outbound_profile ,
2007-12-20 21:42:00 +00:00
switch_core_session_t * * new_session , switch_memory_pool_t * * pool , switch_originate_flag_t flags ) ;
2007-04-09 19:27:59 +00:00
static switch_status_t wanpipe_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout ,
switch_io_flag_t flags , int stream_id ) ;
static switch_status_t wanpipe_write_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout ,
switch_io_flag_t flags , int stream_id ) ;
static int on_info ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent ) ;
static int on_hangup ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent ) ;
2008-05-05 15:30:55 +00:00
static int on_routing ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent ) ;
2006-01-03 22:13:59 +00:00
static int check_flags ( struct sangoma_pri * spri ) ;
2007-04-09 19:27:59 +00:00
static int on_restart ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent ) ;
static int on_anything ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent ) ;
static void * SWITCH_THREAD_FUNC pri_thread_run ( switch_thread_t * thread , void * obj ) ;
2006-05-01 04:29:44 +00:00
static switch_status_t config_wanpipe ( int reload ) ;
2006-01-03 22:13:59 +00:00
2007-04-09 19:27:59 +00:00
static switch_status_t wanpipe_codec_init ( private_object_t * tech_pvt )
2006-01-03 22:13:59 +00:00
{
2006-02-10 22:26:00 +00:00
int err = 0 ;
2007-04-09 19:27:59 +00:00
wanpipe_tdm_api_t tdm_api = { { 0 } } ;
2006-02-10 22:26:00 +00:00
unsigned int rate = 8000 ;
2007-03-02 19:12:26 +00:00
switch_channel_t * channel = NULL ;
2007-02-09 20:03:07 +00:00
2007-03-02 19:12:26 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_CODEC ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2006-01-03 22:13:59 +00:00
2007-03-02 19:12:26 +00:00
channel = switch_core_session_get_channel ( tech_pvt - > session ) ;
assert ( channel ! = NULL ) ;
2006-01-20 15:05:05 +00:00
2006-09-24 15:25:36 +00:00
err = sangoma_tdm_set_codec ( tech_pvt - > wpsock - > fd , & tdm_api , WP_SLINEAR ) ;
2007-04-09 19:27:59 +00:00
2007-02-09 20:03:07 +00:00
sangoma_tdm_set_usr_period ( tech_pvt - > wpsock - > fd , & tdm_api , globals . samples_per_frame / 8 ) ;
tech_pvt - > frame_size = sangoma_tdm_get_usr_mtu_mru ( tech_pvt - > wpsock - > fd , & tdm_api ) ;
2006-02-10 22:26:00 +00:00
if ( switch_core_codec_init
2007-04-09 19:27:59 +00:00
( & tech_pvt - > read_codec , " L16 " , NULL , rate , globals . samples_per_frame / 8 , 1 , SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , NULL ,
switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s Cannot set read codec \n " , switch_channel_get_name ( channel ) ) ;
2006-04-22 03:05:25 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
2006-02-10 22:26:00 +00:00
return SWITCH_STATUS_FALSE ;
}
if ( switch_core_codec_init
2007-04-09 19:27:59 +00:00
( & tech_pvt - > write_codec , " L16 " , NULL , rate , globals . samples_per_frame / 8 , 1 , SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE , NULL ,
switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " %s Cannot set read codec \n " , switch_channel_get_name ( channel ) ) ;
2006-04-22 03:05:25 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
2006-02-10 22:26:00 +00:00
return SWITCH_STATUS_FALSE ;
}
tech_pvt - > read_frame . rate = rate ;
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
2007-03-02 19:12:26 +00:00
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 ) ;
2006-01-20 15:05:05 +00:00
2007-04-09 19:27:59 +00:00
# ifdef DOTRACE
tech_pvt - > fd = open ( " /tmp/wp-in.raw " , O_WRONLY | O_TRUNC | O_CREAT ) ;
tech_pvt - > fd2 = open ( " /tmp/wp-out.raw " , O_WRONLY | O_TRUNC | O_CREAT ) ;
2006-03-17 14:47:41 +00:00
# endif
2006-02-22 18:32:15 +00:00
/* Setup artificial DTMF stuff */
memset ( & tech_pvt - > tone_session , 0 , sizeof ( tech_pvt - > tone_session ) ) ;
2006-02-22 16:47:07 +00:00
teletone_init_session ( & tech_pvt - > tone_session , 1024 , NULL , NULL ) ;
2007-04-09 19:27:59 +00:00
2006-02-22 18:32:15 +00:00
if ( globals . debug ) {
2006-02-22 16:47:07 +00:00
tech_pvt - > tone_session . debug = globals . debug ;
tech_pvt - > tone_session . debug_stream = stdout ;
}
2007-04-09 19:27:59 +00:00
2006-02-22 16:47:07 +00:00
tech_pvt - > tone_session . rate = rate ;
2006-02-22 18:32:15 +00:00
tech_pvt - > tone_session . duration = globals . dtmf_on * ( tech_pvt - > tone_session . rate / 1000 ) ;
tech_pvt - > tone_session . wait = globals . dtmf_off * ( tech_pvt - > tone_session . rate / 1000 ) ;
2007-06-15 02:58:11 +00:00
if ( ! globals . ignore_dtmf_tone ) {
teletone_dtmf_detect_init ( & tech_pvt - > dtmf_detect , rate ) ;
}
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Audio init %s \n " , switch_channel_get_name ( channel ) ) ;
2006-02-22 18:32:15 +00:00
2007-03-02 19:12:26 +00:00
switch_set_flag ( tech_pvt , TFLAG_CODEC ) ;
return SWITCH_STATUS_SUCCESS ;
}
/*
State methods they get called when the state changes to the specific state
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it .
*/
static switch_status_t wanpipe_on_init ( switch_core_session_t * session )
{
private_object_t * tech_pvt ;
switch_channel_t * channel = NULL ;
switch_status_t status ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
tech_pvt - > read_frame . data = tech_pvt - > databuf ;
2007-04-09 19:27:59 +00:00
if ( tech_pvt - > ss7boost_handle ) {
2007-03-02 19:12:26 +00:00
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
ss7boost_client_event_t event ;
event . calling_number_presentation = tech_pvt - > boost_pres ;
event . trunk_group = tech_pvt - > boost_trunk_group ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_mutex_lock ( tech_pvt - > ss7boost_handle - > mutex ) ;
tech_pvt - > setup_index = + + tech_pvt - > ss7boost_handle - > setup_index ;
if ( tech_pvt - > ss7boost_handle - > setup_index = = SETUP_LEN - 1 ) {
tech_pvt - > ss7boost_handle - > setup_index = 0 ;
}
switch_mutex_unlock ( tech_pvt - > ss7boost_handle - > mutex ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_copy_string ( tech_pvt - > ss7boost_handle - > setup_array [ tech_pvt - > setup_index ] ,
2007-04-09 19:27:59 +00:00
switch_core_session_get_uuid ( session ) ,
sizeof ( tech_pvt - > ss7boost_handle - > setup_array [ tech_pvt - > setup_index ] ) ) ;
ss7boost_client_call_init ( & event , tech_pvt - > caller_profile - > caller_id_number , tech_pvt - > caller_profile - > destination_number , tech_pvt - > setup_index ) ;
2007-03-02 19:12:26 +00:00
if ( ss7boost_client_connection_write ( & tech_pvt - > ss7boost_handle - > mcon , & event ) < = 0 ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Critical System Error: Failed to tx on ISUP socket [%s] \n " , strerror ( errno ) ) ;
2007-03-02 19:12:26 +00:00
}
2007-04-09 19:27:59 +00:00
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Call Called Event TG=%d \n " , tech_pvt - > boost_trunk_group ) ;
2007-03-02 19:12:26 +00:00
goto done ;
}
2007-04-09 19:27:59 +00:00
}
2007-03-02 19:12:26 +00:00
if ( ( status = wanpipe_codec_init ( tech_pvt ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return status ;
}
2007-04-09 19:27:59 +00:00
2006-03-18 04:04:59 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_NOSIG ) ) {
2007-02-09 01:34:01 +00:00
switch_channel_mark_answered ( channel ) ;
2006-03-18 04:04:59 +00:00
}
2007-04-09 19:27:59 +00:00
done :
2006-02-22 16:47:07 +00:00
2006-01-03 22:13:59 +00:00
/* Move Channel's State Machine to RING */
2008-05-05 15:30:55 +00:00
switch_channel_set_state ( channel , CS_ROUTING ) ;
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:30:55 +00:00
static switch_status_t wanpipe_on_routing ( switch_core_session_t * session )
2006-01-03 22:13:59 +00:00
{
2006-04-29 06:58:08 +00:00
switch_channel_t * channel = NULL ;
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt = NULL ;
2006-01-03 22:13:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " WANPIPE RING \n " ) ;
2006-01-03 22:13:59 +00:00
2007-04-09 19:27:59 +00:00
2006-02-10 22:26:00 +00:00
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-05-01 04:29:44 +00:00
static switch_status_t wanpipe_on_hangup ( switch_core_session_t * session )
2006-01-03 22:13:59 +00:00
{
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-04-29 06:58:08 +00:00
switch_channel_t * channel = NULL ;
2006-03-17 14:47:41 +00:00
struct channel_map * chanmap = NULL ;
2006-02-10 22:26:00 +00:00
2007-04-09 19:27:59 +00:00
2006-01-03 22:13:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-02-10 22:26:00 +00:00
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " WANPIPE HANGUP \n " ) ;
2006-02-10 22:26:00 +00:00
2007-03-02 19:12:26 +00:00
if ( tech_pvt - > ss7boost_handle ) {
switch_mutex_lock ( tech_pvt - > ss7boost_handle - > mutex ) ;
* tech_pvt - > ss7boost_handle - > span_chanmap [ tech_pvt - > boost_span_number ] . map [ tech_pvt - > boost_chan_number ] = ' \0 ' ;
switch_mutex_unlock ( tech_pvt - > ss7boost_handle - > mutex ) ;
if ( ! switch_test_flag ( tech_pvt , TFLAG_BYE ) ) {
isup_exec_command ( tech_pvt - > ss7boost_handle ,
2007-04-09 19:27:59 +00:00
tech_pvt - > boost_span_number ,
tech_pvt - > boost_chan_number ,
- 1 ,
SIGBOOST_EVENT_CALL_STOPPED ,
SIGBOOST_RELEASE_CAUSE_NORMAL ) ;
2007-03-02 19:12:26 +00:00
}
} else if ( tech_pvt - > spri ) {
chanmap = tech_pvt - > spri - > private_info ;
2007-04-17 01:15:06 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_HANGUP ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_HANGUP ) ;
switch_mutex_lock ( chanmap - > mutex ) ;
pri_hangup ( tech_pvt - > spri - > pri , tech_pvt - > call , switch_channel_get_cause ( channel ) ) ;
pri_destroycall ( tech_pvt - > spri - > pri , tech_pvt - > call ) ;
switch_mutex_unlock ( chanmap - > mutex ) ;
}
2006-02-10 22:26:00 +00:00
2007-02-09 20:03:07 +00:00
switch_mutex_lock ( globals . channel_mutex ) ;
2007-02-10 00:28:50 +00:00
* chanmap - > map [ tech_pvt - > callno ] = ' \0 ' ;
2007-02-09 20:03:07 +00:00
switch_mutex_unlock ( globals . channel_mutex ) ;
2007-04-09 19:27:59 +00:00
2006-02-10 22:26:00 +00:00
}
2007-03-02 19:12:26 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
2006-02-22 16:47:07 +00:00
teletone_destroy_session ( & tech_pvt - > tone_session ) ;
2006-09-08 18:57:24 +00:00
switch_buffer_destroy ( & tech_pvt - > dtmf_buffer ) ;
2007-04-09 19:27:59 +00:00
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:30:55 +00:00
static switch_status_t wanpipe_on_exchange_media ( switch_core_session_t * session )
2006-01-03 22:13:59 +00:00
{
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " WANPIPE LOOPBACK \n " ) ;
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:30:55 +00:00
static switch_status_t wanpipe_on_soft_execute ( switch_core_session_t * session )
2006-01-03 22:13:59 +00:00
{
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-04-29 06:58:08 +00:00
switch_channel_t * channel ;
2006-03-18 04:04:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " WANPIPE TRANSMIT \n " ) ;
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-05-01 04:29:44 +00:00
static switch_status_t wanpipe_answer_channel ( switch_core_session_t * session )
2006-01-03 22:13:59 +00:00
{
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-04-29 06:58:08 +00:00
switch_channel_t * channel = NULL ;
2006-01-20 15:05:05 +00:00
2006-01-03 22:13:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-03-02 19:12:26 +00:00
if ( tech_pvt - > spri ) {
2007-04-16 23:49:58 +00:00
struct channel_map * chanmap = tech_pvt - > spri - > private_info ;
2007-03-02 19:12:26 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_INBOUND ) ) {
2007-04-16 23:49:58 +00:00
switch_mutex_lock ( chanmap - > mutex ) ;
2007-03-02 19:12:26 +00:00
pri_answer ( tech_pvt - > spri - > pri , tech_pvt - > call , 0 , 1 ) ;
2007-04-16 23:49:58 +00:00
switch_mutex_unlock ( chanmap - > mutex ) ;
2007-03-02 19:12:26 +00:00
}
} else if ( tech_pvt - > ss7boost_handle ) {
2007-04-09 19:27:59 +00:00
isup_exec_command ( tech_pvt - > ss7boost_handle ,
tech_pvt - > boost_span_number ,
tech_pvt - > boost_chan_number ,
- 1 ,
SIGBOOST_EVENT_CALL_ANSWERED ,
0 ) ;
2006-02-10 22:26:00 +00:00
}
2007-03-02 19:12:26 +00:00
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-04-09 19:27:59 +00:00
static switch_status_t wanpipe_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout ,
switch_io_flag_t flags , int stream_id )
2006-01-03 22:13:59 +00:00
{
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-04-29 06:58:08 +00:00
switch_channel_t * channel = NULL ;
2006-03-30 23:02:50 +00:00
uint8_t * bp ;
2006-12-04 20:51:16 +00:00
uint32_t bytes = 0 ;
2007-02-09 20:03:07 +00:00
int bread = 0 ;
2006-02-22 18:32:15 +00:00
char digit_str [ 80 ] ;
2006-01-03 22:13:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-01-20 15:05:05 +00:00
2006-09-24 15:25:36 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BYE ) | | tech_pvt - > wpsock - > fd < 0 ) {
2006-02-10 22:26:00 +00:00
return SWITCH_STATUS_GENERR ;
}
2006-01-03 22:13:59 +00:00
bp = tech_pvt - > databuf ;
* frame = NULL ;
memset ( tech_pvt - > databuf , 0 , sizeof ( tech_pvt - > databuf ) ) ;
2007-02-09 20:03:07 +00:00
while ( bytes < globals . samples_per_frame * 2 ) {
2006-09-24 15:25:36 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BYE ) | | tech_pvt - > wpsock - > fd < 0 ) {
2006-03-26 17:42:06 +00:00
return SWITCH_STATUS_GENERR ;
}
2006-04-20 23:57:04 +00:00
2006-09-24 15:25:36 +00:00
if ( sangoma_socket_waitfor ( tech_pvt - > wpsock - > fd , 1000 , POLLIN | POLLERR | POLLHUP ) < = 0 ) {
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_GENERR ;
}
2007-02-09 20:03:07 +00:00
if ( ( bread = sangoma_readmsg_socket ( tech_pvt - > wpsock - > fd ,
2007-04-09 19:27:59 +00:00
& tech_pvt - > hdrframe ,
sizeof ( tech_pvt - > hdrframe ) , bp , sizeof ( tech_pvt - > databuf ) - bytes , 0 ) ) < 0 ) {
2006-01-03 22:13:59 +00:00
if ( errno = = EBUSY ) {
continue ;
} else {
return SWITCH_STATUS_GENERR ;
}
2006-03-17 14:47:41 +00:00
2006-01-03 22:13:59 +00:00
}
2007-02-09 20:03:07 +00:00
bytes + = bread ;
2006-01-03 22:13:59 +00:00
bp + = bytes ;
}
2006-03-26 17:42:06 +00:00
2006-09-24 15:25:36 +00:00
if ( ! bytes | | switch_test_flag ( tech_pvt , TFLAG_BYE ) | | tech_pvt - > wpsock - > fd < 0 ) {
2006-03-26 17:42:06 +00:00
return SWITCH_STATUS_GENERR ;
}
2006-02-10 22:26:00 +00:00
tech_pvt - > read_frame . datalen = bytes ;
2006-02-22 18:32:15 +00:00
tech_pvt - > read_frame . samples = bytes / 2 ;
2007-04-09 19:27:59 +00:00
2007-06-15 02:58:11 +00:00
if ( ! globals . ignore_dtmf_tone ) {
teletone_dtmf_detect ( & tech_pvt - > dtmf_detect , tech_pvt - > read_frame . data , tech_pvt - > read_frame . samples ) ;
teletone_dtmf_get ( & tech_pvt - > dtmf_detect , digit_str , sizeof ( digit_str ) ) ;
2008-02-15 23:23:59 +00:00
if ( digit_str [ 0 ] ) {
2007-12-22 00:32:20 +00:00
char * p = digit_str ;
switch_dtmf_t dtmf = { 0 , globals . dtmf_on } ;
while ( p & & * p ) {
dtmf . digit = * p ;
switch_channel_queue_dtmf ( channel , & dtmf ) ;
p + + ;
}
2007-06-15 02:58:11 +00:00
if ( globals . debug ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " DTMF DETECTED: [%s] \n " , digit_str ) ;
}
if ( globals . suppress_dtmf_tone ) {
tech_pvt - > skip_read_frames = 20 ;
}
2006-02-23 22:41:08 +00:00
}
2006-01-20 15:05:05 +00:00
2007-06-15 02:58:11 +00:00
if ( tech_pvt - > skip_read_frames > 0 ) {
memset ( tech_pvt - > read_frame . data , 0 , tech_pvt - > read_frame . datalen ) ;
tech_pvt - > skip_read_frames - - ;
}
2006-03-17 14:47:41 +00:00
}
2007-04-09 19:27:59 +00:00
# ifdef DOTRACE
2006-03-17 14:47:41 +00:00
write ( tech_pvt - > fd2 , tech_pvt - > read_frame . data , ( int ) tech_pvt - > read_frame . datalen ) ;
# endif
//printf("read %d\n", tech_pvt->read_frame.datalen);
2006-02-10 22:26:00 +00:00
* frame = & tech_pvt - > read_frame ;
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-04-09 19:27:59 +00:00
static switch_status_t wanpipe_write_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout ,
switch_io_flag_t flags , int stream_id )
2006-01-03 22:13:59 +00:00
{
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2007-02-12 21:08:57 +00:00
uint32_t dtmf_blen ;
void * data = frame - > data ;
int result = 0 ;
2006-01-03 22:13:59 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2006-09-24 15:25:36 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BYE ) | | tech_pvt - > wpsock - > fd < 0 ) {
2006-03-26 17:42:06 +00:00
return SWITCH_STATUS_GENERR ;
}
2007-02-12 21:08:57 +00:00
if ( tech_pvt - > dtmf_buffer & & ( dtmf_blen = switch_buffer_inuse ( tech_pvt - > dtmf_buffer ) ) ) {
uint32_t len = dtmf_blen > frame - > datalen ? frame - > datalen : dtmf_blen ;
2007-04-09 19:27:59 +00:00
switch_buffer_read ( tech_pvt - > dtmf_buffer , tech_pvt - > auxbuf , len ) ;
2007-02-12 21:08:57 +00:00
if ( len < frame - > datalen ) {
2007-03-13 20:34:27 +00:00
uint8_t * data = frame - > data ;
memcpy ( data + len , tech_pvt - > auxbuf + len , frame - > datalen - len ) ;
2007-02-12 21:08:57 +00:00
}
2007-04-09 19:27:59 +00:00
data = tech_pvt - > auxbuf ;
}
2006-03-17 14:47:41 +00:00
if ( tech_pvt - > skip_write_frames ) {
tech_pvt - > skip_write_frames - - ;
return SWITCH_STATUS_SUCCESS ;
}
2007-04-09 19:27:59 +00:00
2007-02-12 21:08:57 +00:00
# ifdef DOTRACE
write ( tech_pvt - > fd , data , frame - > datalen ) ;
2006-03-17 14:47:41 +00:00
# endif
2006-03-18 04:04:59 +00:00
2007-03-30 00:13:31 +00:00
result = sangoma_sendmsg_socket ( tech_pvt - > wpsock - > fd , & tech_pvt - > hdrframe , sizeof ( tech_pvt - > hdrframe ) , data , frame - > datalen , 0 ) ;
2007-04-09 19:27:59 +00:00
2007-02-12 21:08:57 +00:00
if ( result < 0 & & errno ! = EBUSY ) {
return SWITCH_STATUS_GENERR ;
}
return SWITCH_STATUS_SUCCESS ;
2006-01-03 22:13:59 +00:00
}
2007-12-22 00:32:20 +00:00
static switch_status_t wanpipe_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2006-02-22 16:47:07 +00:00
{
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-04-29 06:58:08 +00:00
switch_channel_t * channel = NULL ;
2006-05-01 04:29:44 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2006-02-22 16:47:07 +00:00
int wrote = 0 ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-04-14 17:16:31 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BYE ) | | tech_pvt - > wpsock - > fd < 0 ) {
return SWITCH_STATUS_GENERR ;
}
2006-02-22 16:47:07 +00:00
if ( ! tech_pvt - > dtmf_buffer ) {
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Allocate DTMF Buffer.... " ) ;
2006-09-08 18:57:24 +00:00
if ( switch_buffer_create_dynamic ( & tech_pvt - > dtmf_buffer , 1024 , 3192 , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG_CLEAN , SWITCH_LOG_ERROR , " Failed to allocate DTMF Buffer! \n " ) ;
2006-02-22 16:47:07 +00:00
return SWITCH_STATUS_FALSE ;
} else {
2006-04-11 21:13:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG_CLEAN , SWITCH_LOG_DEBUG , " SUCCESS! \n " ) ;
2006-02-22 16:47:07 +00:00
}
}
2007-12-22 00:32:20 +00:00
tech_pvt - > tone_session . duration = dtmf . duration * ( tech_pvt - > tone_session . rate / 1000 ) ;
if ( ( wrote = teletone_mux_tones ( & tech_pvt - > tone_session , & tech_pvt - > tone_session . TONES [ ( int ) dtmf - > digit ] ) ) ) {
switch_buffer_write ( tech_pvt - > dtmf_buffer , tech_pvt - > tone_session . buffer , wrote * 2 ) ;
2006-02-22 16:47:07 +00:00
}
2007-12-22 00:32:20 +00:00
2006-03-17 14:47:41 +00:00
tech_pvt - > skip_read_frames = 200 ;
2007-04-09 19:27:59 +00:00
2006-02-22 16:47:07 +00:00
return status ;
}
2006-05-01 04:29:44 +00:00
static switch_status_t wanpipe_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
2006-02-22 16:47:07 +00:00
{
2007-02-09 01:34:01 +00:00
switch_channel_t * channel ;
private_object_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-04-09 19:27:59 +00:00
2007-02-09 01:34:01 +00:00
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-04-14 17:16:31 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BYE ) | | tech_pvt - > wpsock - > fd < 0 ) {
return SWITCH_STATUS_GENERR ;
}
2007-02-09 01:34:01 +00:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_NOMEDIA :
break ;
case SWITCH_MESSAGE_INDICATE_MEDIA :
break ;
case SWITCH_MESSAGE_INDICATE_HOLD :
break ;
case SWITCH_MESSAGE_INDICATE_UNHOLD :
break ;
case SWITCH_MESSAGE_INDICATE_BRIDGE :
break ;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE :
break ;
case SWITCH_MESSAGE_INDICATE_REDIRECT :
break ;
2007-04-16 16:53:30 +00:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
wanpipe_answer_channel ( session ) ;
break ;
2007-02-09 01:34:01 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
break ;
case SWITCH_MESSAGE_INDICATE_RINGING :
break ;
2007-03-13 20:34:27 +00:00
default :
break ;
2007-02-09 01:34:01 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2006-02-22 16:47:07 +00:00
}
2006-05-01 04:29:44 +00:00
static switch_status_t wanpipe_kill_channel ( switch_core_session_t * session , int sig )
2006-02-22 16:47:07 +00:00
{
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-04-29 06:58:08 +00:00
switch_channel_t * channel = NULL ;
2006-02-22 16:47:07 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-04-09 19:27:59 +00:00
switch ( sig ) {
2006-12-21 16:46:11 +00:00
case SWITCH_SIG_KILL :
2007-03-02 19:12:26 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_MEDIA ) ;
2006-12-21 16:46:11 +00:00
break ;
default :
break ;
}
2006-02-22 16:47:07 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-10-29 18:10:06 +00:00
switch_io_routines_t wanpipe_io_routines = {
2006-01-20 15:05:05 +00:00
/*.outgoing_channel */ wanpipe_outgoing_channel ,
2006-02-10 22:26:00 +00:00
/*.read_frame */ wanpipe_read_frame ,
2006-02-22 16:47:07 +00:00
/*.write_frame */ wanpipe_write_frame ,
/*.kill_channel */ wanpipe_kill_channel ,
/*.waitfor_read */ NULL ,
/*.waitfor_read */ NULL ,
2007-04-09 19:27:59 +00:00
/*.send_dtmf*/ wanpipe_send_dtmf ,
/*.receive_message*/ wanpipe_receive_message
2006-01-03 22:13:59 +00:00
} ;
2007-10-29 18:10:06 +00:00
switch_state_handler_table_t wanpipe_state_handlers = {
2006-01-20 15:05:05 +00:00
/*.on_init */ wanpipe_on_init ,
2008-05-05 15:30:55 +00:00
/*.on_routing */ wanpipe_on_routing ,
2006-01-20 15:05:05 +00:00
/*.on_execute */ NULL ,
/*.on_hangup */ wanpipe_on_hangup ,
2008-05-05 15:30:55 +00:00
/*.on_exchange_media */ wanpipe_on_exchange_media ,
/*.on_soft_execute */ wanpipe_on_soft_execute
2006-01-03 22:13:59 +00:00
} ;
2007-04-09 19:27:59 +00:00
static switch_call_cause_t wanpipe_outgoing_channel ( switch_core_session_t * session , switch_caller_profile_t * outbound_profile ,
2007-12-20 21:42:00 +00:00
switch_core_session_t * * new_session , switch_memory_pool_t * * pool , switch_originate_flag_t flags )
2006-03-30 23:02:50 +00:00
{
char * bchan = NULL ;
char name [ 128 ] = " " ;
2007-03-13 20:34:27 +00:00
char * protocol = NULL ;
2007-03-02 19:12:26 +00:00
char * dest ;
int ready = 0 , is_pri = 0 , is_boost = 0 , is_raw = 0 ;
2007-04-16 19:32:08 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
private_object_t * tech_pvt ;
switch_channel_t * channel ;
switch_caller_profile_t * caller_profile = NULL ;
int callno = 0 ;
struct sangoma_pri * spri ;
int span = 0 , autospan = 0 , autochan = 0 ;
char * num , * p ;
struct channel_map * chanmap = NULL ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
if ( ! outbound_profile ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Doh! no caller profile \n " ) ;
2007-03-13 20:34:27 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
2006-03-30 23:02:50 +00:00
}
2007-03-13 20:34:27 +00:00
protocol = strdup ( outbound_profile - > destination_number ) ;
2007-04-16 19:32:08 +00:00
assert ( protocol ! = NULL ) ;
2007-03-02 19:12:26 +00:00
if ( ! ( dest = strchr ( protocol , ' / ' ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error No protocol specified! \n " ) ;
2007-03-13 20:34:27 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
2007-03-02 19:12:26 +00:00
}
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
* dest + + = ' \0 ' ;
if ( ! strcasecmp ( protocol , " raw " ) ) {
bchan = dest ;
is_raw = ready = 1 ;
} else if ( ! strcasecmp ( protocol , " pri " ) ) {
if ( ( is_pri = globals . configured_spans ) ) {
ready = is_pri ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error No PRI Spans Configured. \n " ) ;
}
} else if ( ! strcasecmp ( protocol , " ss7boost " ) ) {
if ( ( is_boost = globals . configured_boost_spans ) ) {
ready = is_boost ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error No SS7BOOST Spans Configured. \n " ) ;
2006-03-30 23:02:50 +00:00
}
2007-03-02 19:12:26 +00:00
}
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
if ( ! ready ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot Continue! \n " ) ;
2007-03-13 20:34:27 +00:00
cause = SWITCH_CAUSE_NETWORK_OUT_OF_ORDER ;
goto error ;
2006-03-30 23:02:50 +00:00
}
2007-03-02 19:12:26 +00:00
outbound_profile - > destination_number = dest ;
2006-03-30 23:02:50 +00:00
2007-10-29 19:15:26 +00:00
if ( ! ( * new_session = switch_core_session_request ( wanpipe_endpoint_interface , pool ) ) ) {
2007-04-16 19:32:08 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
}
2006-03-30 23:02:50 +00:00
2007-04-16 19:32:08 +00:00
switch_core_session_add_stream ( * new_session , NULL ) ;
if ( ( tech_pvt = ( private_object_t * ) switch_core_session_alloc ( * new_session , sizeof ( private_object_t ) ) ) ) {
memset ( tech_pvt , 0 , sizeof ( * tech_pvt ) ) ;
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( * new_session ) ) ;
channel = switch_core_session_get_channel ( * new_session ) ;
switch_core_session_set_private ( * new_session , tech_pvt ) ;
tech_pvt - > session = * new_session ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Memory Error! \n " ) ;
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
}
2007-03-02 19:12:26 +00:00
2007-04-16 19:32:08 +00:00
caller_profile = switch_caller_profile_clone ( * new_session , outbound_profile ) ;
if ( is_pri ) {
num = caller_profile - > destination_number ;
if ( ( p = strchr ( num , ' / ' ) ) ) {
* p + + = ' \0 ' ;
if ( * num = = ' a ' ) {
span = 1 ;
autospan = 1 ;
} else if ( * num = = ' A ' ) {
span = MAX_SPANS - 1 ;
autospan = - 1 ;
} else {
if ( num & & * num > 47 & & * num < 58 ) {
span = atoi ( num ) ;
} else {
2007-08-06 17:04:08 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Syntax \n " ) ;
2007-04-16 19:32:08 +00:00
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
}
}
num = p ;
2007-03-02 19:12:26 +00:00
if ( ( p = strchr ( num , ' / ' ) ) ) {
* p + + = ' \0 ' ;
if ( * num = = ' a ' ) {
2007-04-16 19:32:08 +00:00
autochan = 1 ;
2007-03-13 20:34:27 +00:00
} else if ( * num = = ' A ' ) {
2007-04-16 19:32:08 +00:00
autochan = - 1 ;
} else if ( num & & * num > 47 & & * num < 58 ) {
callno = atoi ( num ) ;
2007-03-02 19:12:26 +00:00
} else {
2007-08-06 17:04:08 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Syntax \n " ) ;
2007-03-02 19:12:26 +00:00
switch_core_session_destroy ( new_session ) ;
2007-03-13 20:34:27 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
2006-03-30 23:02:50 +00:00
}
2007-04-16 19:32:08 +00:00
caller_profile - > destination_number = p ;
} else {
2007-08-06 17:04:08 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Syntax \n " ) ;
2007-04-16 19:32:08 +00:00
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
2006-03-30 23:02:50 +00:00
}
2007-03-02 19:12:26 +00:00
}
2007-04-16 19:32:08 +00:00
}
2006-03-30 23:02:50 +00:00
2007-04-16 19:32:08 +00:00
tech_pvt - > caller_profile = caller_profile ;
2006-03-30 23:02:50 +00:00
2007-04-16 19:32:08 +00:00
if ( is_raw ) {
int chan , span ;
2006-09-24 15:25:36 +00:00
2008-02-15 23:23:59 +00:00
if ( sangoma_span_chan_fromif ( bchan , & span , & chan ) ) {
2007-04-16 20:26:21 +00:00
if ( ! ( tech_pvt - > wpsock = wp_open ( span , chan ) ) ) {
2007-04-16 19:32:08 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't open fd for s%dc%d! [%s] \n " , span , chan , strerror ( errno ) ) ;
2007-03-02 19:12:26 +00:00
switch_core_session_destroy ( new_session ) ;
2007-04-16 19:32:08 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2007-03-13 20:34:27 +00:00
goto error ;
2007-03-02 19:12:26 +00:00
}
2007-04-16 19:32:08 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_NOSIG ) ;
snprintf ( name , sizeof ( name ) , " wanpipe/%s/nosig " , bchan ) ;
switch_channel_set_name ( channel , name ) ;
switch_channel_set_caller_profile ( channel , caller_profile ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid address \n " ) ;
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL ;
goto error ;
}
} else if ( is_pri ) {
switch_mutex_lock ( globals . channel_mutex ) ;
callno = 0 ;
while ( ! callno ) {
if ( autospan > 0 & & span = = MAX_SPANS - 1 ) {
break ;
}
2007-02-09 20:03:07 +00:00
2007-04-16 19:32:08 +00:00
if ( autospan < 0 & & span = = 0 ) {
break ;
}
2007-02-09 20:03:07 +00:00
2007-04-16 19:32:08 +00:00
if ( SPANS [ span ] & & ( spri = & SPANS [ span ] - > spri ) & & switch_test_flag ( spri , SANGOMA_PRI_READY ) ) {
chanmap = spri - > private_info ;
2007-04-09 19:27:59 +00:00
2007-04-16 19:32:08 +00:00
if ( autochan > 0 ) {
for ( callno = 1 ; callno < SANGOMA_MAX_CHAN_PER_SPAN ; callno + + ) {
if ( ( SPANS [ span ] - > bchans & ( 1 < < callno ) ) & & ! * chanmap - > map [ callno ] ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Choosing channel s%dc%d \n " , span , callno ) ;
goto done ;
2007-03-02 19:12:26 +00:00
}
2007-04-16 19:32:08 +00:00
}
callno = 0 ;
} else if ( autochan < 0 ) {
for ( callno = SANGOMA_MAX_CHAN_PER_SPAN ; callno > 0 ; callno - - ) {
if ( ( SPANS [ span ] - > bchans & ( 1 < < callno ) ) & & ! * chanmap - > map [ callno ] ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Choosing channel s%dc%d \n " , span , callno ) ;
goto done ;
2006-03-30 23:02:50 +00:00
}
2007-02-09 20:03:07 +00:00
}
2007-04-16 19:32:08 +00:00
callno = 0 ;
2006-03-30 23:02:50 +00:00
}
2007-03-02 19:12:26 +00:00
}
2007-04-16 19:32:08 +00:00
if ( autospan > 0 ) {
span + + ;
} else if ( autospan < 0 ) {
span - - ;
2007-03-02 19:12:26 +00:00
}
2007-04-16 19:32:08 +00:00
}
done :
switch_mutex_unlock ( globals . channel_mutex ) ;
if ( ! spri | | callno = = 0 | | callno = = ( SANGOMA_MAX_CHAN_PER_SPAN ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " No Free Channels! \n " ) ;
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_SWITCH_CONGESTION ;
goto error ;
}
2007-04-09 19:27:59 +00:00
2007-04-16 19:32:08 +00:00
tech_pvt - > callno = callno ;
2007-04-09 19:27:59 +00:00
2007-04-16 23:49:58 +00:00
if ( spri ) {
struct channel_map * chanmap = spri - > private_info ;
switch_mutex_lock ( chanmap - > mutex ) ;
if ( tech_pvt - > call = pri_new_call ( spri - > pri ) ) {
struct pri_sr * sr ;
2007-04-09 19:27:59 +00:00
2007-04-16 23:49:58 +00:00
snprintf ( name , sizeof ( name ) , " wanpipe/pri/s%dc%d/%s " , spri - > span , callno , caller_profile - > destination_number ) ;
switch_channel_set_name ( channel , name ) ;
switch_channel_set_caller_profile ( channel , caller_profile ) ;
sr = pri_sr_new ( ) ;
pri_sr_set_channel ( sr , callno , 0 , 0 ) ;
pri_sr_set_bearer ( sr , 0 , SPANS [ span ] - > l1 ) ;
pri_sr_set_called ( sr , caller_profile - > destination_number , SPANS [ span ] - > dp , 1 ) ;
pri_sr_set_caller ( sr ,
caller_profile - > caller_id_number ,
caller_profile - > caller_id_name ,
SPANS [ span ] - > dp ,
PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN ) ;
pri_sr_set_redirecting ( sr ,
caller_profile - > caller_id_number ,
SPANS [ span ] - > dp ,
PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN ,
PRI_REDIR_UNCONDITIONAL ) ;
2007-04-09 19:27:59 +00:00
2007-04-16 23:49:58 +00:00
if ( pri_setup ( spri - > pri , tech_pvt - > call , sr ) ) {
switch_core_session_destroy ( new_session ) ;
pri_sr_free ( sr ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
switch_mutex_unlock ( chanmap - > mutex ) ;
goto error ;
}
if ( ! ( tech_pvt - > wpsock = wp_open ( spri - > span , callno ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't open fd! \n " ) ;
switch_core_session_destroy ( new_session ) ;
pri_sr_free ( sr ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
switch_mutex_unlock ( chanmap - > mutex ) ;
goto error ;
}
2007-04-16 19:32:08 +00:00
pri_sr_free ( sr ) ;
2007-04-16 23:49:58 +00:00
switch_copy_string ( chanmap - > map [ callno ] ,
switch_core_session_get_uuid ( * new_session ) ,
sizeof ( chanmap - > map [ callno ] ) ) ;
tech_pvt - > spri = spri ;
2007-03-02 19:12:26 +00:00
}
2007-04-16 23:49:58 +00:00
switch_mutex_unlock ( chanmap - > mutex ) ;
2007-04-16 19:32:08 +00:00
}
} else if ( is_boost ) {
char * p ;
if ( ( p = strchr ( caller_profile - > destination_number , ' / ' ) ) ) {
char * grp = caller_profile - > destination_number ;
* p = ' \0 ' ;
caller_profile - > destination_number = p + 1 ;
tech_pvt - > boost_trunk_group = atoi ( grp + 1 ) - 1 ;
if ( tech_pvt - > boost_trunk_group < 0 ) {
tech_pvt - > boost_trunk_group = 0 ;
}
}
sprintf ( name , " wanpipe/ss7boost/%s " , caller_profile - > destination_number ) ;
switch_channel_set_name ( channel , name ) ;
tech_pvt - > ss7boost_handle = globals . ss7boost_handle ;
2007-03-02 19:12:26 +00:00
2007-04-16 19:32:08 +00:00
if ( session & & switch_core_session_compare ( session , * new_session ) ) {
private_object_t * otech_pvt = switch_core_session_get_private ( session ) ;
tech_pvt - > boost_pres = otech_pvt - > boost_pres ;
2006-03-30 23:02:50 +00:00
}
}
2007-04-16 19:32:08 +00:00
tech_pvt - > caller_profile = caller_profile ;
switch_channel_set_flag ( channel , CF_OUTBOUND ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_OUTBOUND ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
cause = SWITCH_CAUSE_SUCCESS ;
2007-04-09 19:27:59 +00:00
error :
2007-03-13 20:34:27 +00:00
switch_safe_free ( protocol ) ;
return cause ;
2006-03-30 23:02:50 +00:00
}
2006-12-04 22:25:31 +00:00
# ifdef WIN32
static void s_pri_error ( char * s )
# else
2006-02-24 19:11:49 +00:00
static void s_pri_error ( struct pri * pri , char * s )
2006-12-04 22:25:31 +00:00
# endif
2006-02-24 19:11:49 +00:00
{
2006-03-24 16:40:31 +00:00
if ( globals . debug ) {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , s ) ;
2006-03-24 16:40:31 +00:00
}
2006-02-24 19:11:49 +00:00
}
2006-12-04 22:25:31 +00:00
# ifdef WIN32
static void s_pri_message ( char * s )
{
s_pri_error ( s ) ;
}
# else
2006-02-24 19:11:49 +00:00
static void s_pri_message ( struct pri * pri , char * s )
{
s_pri_error ( pri , s ) ;
}
2006-12-04 22:25:31 +00:00
# endif
2006-02-24 19:11:49 +00:00
2007-06-13 17:48:49 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_wanpipe_load )
2006-01-20 15:05:05 +00:00
{
2006-05-01 04:29:44 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2006-01-03 22:13:59 +00:00
2007-04-19 15:34:30 +00:00
sangoma_set_logger ( wp_logger ) ;
2006-02-12 20:38:24 +00:00
memset ( SPANS , 0 , sizeof ( SPANS ) ) ;
2006-01-03 22:13:59 +00:00
2006-03-24 16:40:31 +00:00
pri_set_error ( s_pri_error ) ;
pri_set_message ( s_pri_message ) ;
2007-10-09 19:04:35 +00:00
module_pool = pool ;
2006-01-20 15:05:05 +00:00
2006-09-24 15:25:36 +00:00
memset ( & globals , 0 , sizeof ( globals ) ) ;
switch_core_hash_init ( & globals . call_hash , module_pool ) ;
switch_mutex_init ( & globals . hash_mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
2007-02-09 01:34:01 +00:00
switch_mutex_init ( & globals . channel_mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
2006-09-24 15:25:36 +00:00
2006-02-12 20:38:24 +00:00
/* start the pri's */
2006-03-30 23:02:50 +00:00
if ( ( status = config_wanpipe ( 0 ) ) ! = SWITCH_STATUS_SUCCESS ) {
2006-02-24 19:11:49 +00:00
return status ;
}
2006-01-03 22:13:59 +00:00
/* connect my internal structure to the blank pointer passed to me */
2007-10-09 19:04:35 +00:00
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
wanpipe_endpoint_interface = switch_loadable_module_create_interface ( * module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
wanpipe_endpoint_interface - > interface_name = " wanpipe " ;
wanpipe_endpoint_interface - > io_routines = & wanpipe_io_routines ;
wanpipe_endpoint_interface - > state_handler = & wanpipe_state_handlers ;
2006-01-03 22:13:59 +00:00
/* indicate that the module should continue to be loaded */
2006-02-24 19:11:49 +00:00
return status ;
2006-01-03 22:13:59 +00:00
}
2007-09-29 01:06:08 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_wanpipe_shutdown )
{
switch_core_hash_destroy ( & globals . call_hash ) ;
return SWITCH_STATUS_SUCCESS ;
}
2006-02-10 22:26:00 +00:00
/*event Handlers */
2006-01-03 22:13:59 +00:00
2007-04-09 19:27:59 +00:00
static int on_info ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-01-03 22:13:59 +00:00
{
2006-12-04 20:51:16 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " number is: %s \n " , pevent - > ring . callednum ) ;
if ( strlen ( pevent - > ring . callednum ) > 3 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " final number is: %s \n " , pevent - > ring . callednum ) ;
pri_answer ( spri - > pri , pevent - > ring . call , 0 , 1 ) ;
2006-01-03 22:13:59 +00:00
}
return 0 ;
}
2007-04-09 19:27:59 +00:00
static int on_hangup ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-01-03 22:13:59 +00:00
{
struct channel_map * chanmap ;
2006-04-29 06:58:08 +00:00
switch_core_session_t * session ;
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-01-03 22:13:59 +00:00
2006-02-26 04:52:34 +00:00
chanmap = spri - > private_info ;
2007-02-09 01:34:01 +00:00
if ( ( session = switch_core_session_locate ( chanmap - > map [ pevent - > hangup . channel ] ) ) ) {
2006-04-29 06:58:08 +00:00
switch_channel_t * channel = NULL ;
2006-01-03 22:13:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-04-16 20:20:24 +00:00
if ( switch_channel_get_state ( channel ) < CS_HANGUP ) {
2007-04-17 01:26:13 +00:00
2007-04-16 20:20:24 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-04-17 01:26:13 +00:00
chanmap = tech_pvt - > spri - > private_info ;
2007-04-16 20:20:24 +00:00
if ( ! tech_pvt - > call ) {
tech_pvt - > call = pevent - > hangup . call ;
}
2007-02-09 20:03:07 +00:00
2007-04-16 20:20:24 +00:00
tech_pvt - > cause = pevent - > hangup . cause ;
2007-04-17 01:15:06 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_HANGUP ) ;
2007-04-16 20:20:24 +00:00
switch_channel_hangup ( channel , tech_pvt - > cause ) ;
2007-04-17 01:26:13 +00:00
switch_mutex_lock ( chanmap - > mutex ) ;
pri_destroycall ( tech_pvt - > spri - > pri , tech_pvt - > call ) ;
switch_mutex_unlock ( chanmap - > mutex ) ;
2007-04-17 01:21:34 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Hanging up channel s%dc%d \n " , spri - > span , pevent - > hangup . channel ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Duplicate Hang up on channel s%dc%d \n " , spri - > span , pevent - > hangup . channel ) ;
2007-04-16 20:20:24 +00:00
}
2007-02-09 01:34:01 +00:00
switch_core_session_rwunlock ( session ) ;
2007-04-17 01:21:34 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Hanging up nonexistant channel s%dc%d \n " , spri - > span , pevent - > hangup . channel ) ;
2006-01-03 22:13:59 +00:00
}
2006-01-20 15:05:05 +00:00
2007-04-17 01:21:34 +00:00
2006-01-03 22:13:59 +00:00
return 0 ;
}
2007-04-09 19:27:59 +00:00
static int on_answer ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-02-10 22:26:00 +00:00
{
2006-04-29 06:58:08 +00:00
switch_core_session_t * session ;
switch_channel_t * channel ;
2006-02-10 22:26:00 +00:00
struct channel_map * chanmap ;
2006-03-17 14:47:41 +00:00
2006-02-26 04:52:34 +00:00
chanmap = spri - > private_info ;
2006-02-10 22:26:00 +00:00
2007-02-09 01:34:01 +00:00
if ( ( session = switch_core_session_locate ( chanmap - > map [ pevent - > answer . channel ] ) ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Answer on channel s%dc%d \n " , spri - > span , pevent - > answer . channel ) ;
2006-02-10 22:26:00 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-02-09 01:34:01 +00:00
switch_channel_mark_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
2006-02-10 22:26:00 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Answer on channel s%dc%d but it's not in use? \n " , spri - > span , pevent - > answer . channel ) ;
2006-02-10 22:26:00 +00:00
}
2007-04-09 19:27:59 +00:00
2006-02-10 22:26:00 +00:00
return 0 ;
}
2006-02-22 02:50:33 +00:00
2007-04-09 19:27:59 +00:00
static int on_proceed ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-02-22 02:50:33 +00:00
{
2006-04-29 06:58:08 +00:00
switch_core_session_t * session ;
switch_channel_t * channel ;
2006-02-22 02:50:33 +00:00
struct channel_map * chanmap ;
2006-02-26 04:52:34 +00:00
chanmap = spri - > private_info ;
2006-02-22 02:50:33 +00:00
2007-02-09 01:34:01 +00:00
if ( ( session = switch_core_session_locate ( chanmap - > map [ pevent - > proceeding . channel ] ) ) ) {
switch_core_session_message_t * msg ;
2006-02-22 02:50:33 +00:00
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Proceeding on channel s%dc%d \n " , spri - > span , pevent - > proceeding . channel ) ;
2007-04-09 19:27:59 +00:00
2006-02-22 02:50:33 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-04-09 19:27:59 +00:00
2007-04-16 16:53:30 +00:00
switch_core_session_pass_indication ( session , SWITCH_MESSAGE_INDICATE_PROGRESS ) ;
switch_channel_mark_pre_answered ( channel ) ;
2007-04-09 19:27:59 +00:00
2007-02-09 01:34:01 +00:00
switch_core_session_rwunlock ( session ) ;
2006-02-22 02:50:33 +00:00
} else {
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Proceeding on channel s%dc%d but it's not in use? \n " ,
spri - > span , pevent - > proceeding . channel ) ;
2006-02-22 02:50:33 +00:00
}
return 0 ;
}
2007-02-09 01:34:01 +00:00
2008-05-05 15:30:55 +00:00
static int on_routinging ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-02-10 22:26:00 +00:00
{
2006-04-29 06:58:08 +00:00
switch_core_session_t * session ;
switch_channel_t * channel ;
2006-02-10 22:26:00 +00:00
struct channel_map * chanmap ;
2007-03-13 20:34:27 +00:00
2006-02-10 22:26:00 +00:00
2006-02-26 04:52:34 +00:00
chanmap = spri - > private_info ;
2006-02-10 22:26:00 +00:00
2007-02-09 01:34:01 +00:00
if ( ( session = switch_core_session_locate ( chanmap - > map [ pevent - > ringing . channel ] ) ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " -- Ringing on channel s%dc%d \n " , spri - > span , pevent - > ringing . channel ) ;
2006-02-10 22:26:00 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-04-16 16:53:30 +00:00
switch_core_session_pass_indication ( session , SWITCH_MESSAGE_INDICATE_RINGING ) ;
2007-02-13 15:47:15 +00:00
switch_channel_mark_ring_ready ( channel ) ;
2007-02-09 01:34:01 +00:00
switch_core_session_rwunlock ( session ) ;
2006-02-10 22:26:00 +00:00
} else {
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " -- Ringing on channel s%dc%d %s but it's not in use? \n " , spri - > span , pevent - > ringing . channel , chanmap - > map [ pevent - > ringing . channel ] ) ;
2006-02-10 22:26:00 +00:00
}
return 0 ;
}
2007-02-09 01:34:01 +00:00
2006-02-10 22:26:00 +00:00
2008-05-05 15:30:55 +00:00
static int on_routing ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-01-03 22:13:59 +00:00
{
char name [ 128 ] ;
2007-04-16 20:51:19 +00:00
switch_core_session_t * session = NULL ;
2006-04-29 06:58:08 +00:00
switch_channel_t * channel ;
2006-01-03 22:13:59 +00:00
struct channel_map * chanmap ;
2007-02-09 01:34:01 +00:00
int ret = 0 ;
2007-04-09 19:27:59 +00:00
2007-02-09 01:34:01 +00:00
switch_mutex_lock ( globals . channel_mutex ) ;
2006-01-03 22:13:59 +00:00
2006-02-26 04:52:34 +00:00
chanmap = spri - > private_info ;
2007-04-16 20:51:19 +00:00
if ( ( session = switch_core_session_locate ( chanmap - > map [ pevent - > ring . channel ] ) ) ) {
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " --Duplicate Ring on channel s%dc%d (ignored) \n " ,
spri - > span , pevent - > ring . channel ) ;
2007-02-09 01:34:01 +00:00
switch_core_session_rwunlock ( session ) ;
ret = 0 ;
goto done ;
2006-01-03 22:13:59 +00:00
}
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Ring on channel s%dc%d (from %s to %s) \n " , spri - > span , pevent - > ring . channel ,
pevent - > ring . callingnum , pevent - > ring . callednum ) ;
2006-01-03 22:13:59 +00:00
2007-04-16 23:49:58 +00:00
switch_mutex_unlock ( chanmap - > mutex ) ;
2006-12-04 20:51:16 +00:00
pri_proceeding ( spri - > pri , pevent - > ring . call , pevent - > ring . channel , 0 ) ;
pri_acknowledge ( spri - > pri , pevent - > ring . call , pevent - > ring . channel , 0 ) ;
2007-04-16 23:49:58 +00:00
switch_mutex_unlock ( chanmap - > mutex ) ;
2006-02-10 22:26:00 +00:00
2007-10-29 19:15:26 +00:00
if ( ( session = switch_core_session_request ( wanpipe_endpoint_interface , NULL ) ) ) {
2007-02-09 01:34:01 +00:00
private_object_t * tech_pvt ;
2006-12-04 20:51:16 +00:00
char ani2str [ 4 ] = " " ;
2006-01-03 22:13:59 +00:00
//wanpipe_tdm_api_t tdm_api;
2006-01-09 18:40:56 +00:00
switch_core_session_add_stream ( session , NULL ) ;
2007-02-09 01:34:01 +00:00
if ( ( tech_pvt = ( private_object_t * ) switch_core_session_alloc ( session , sizeof ( private_object_t ) ) ) ) {
2006-01-03 22:13:59 +00:00
memset ( tech_pvt , 0 , sizeof ( * tech_pvt ) ) ;
2006-06-23 16:59:47 +00:00
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
2006-01-03 22:13:59 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_core_session_set_private ( session , tech_pvt ) ;
2007-03-02 19:12:26 +00:00
sprintf ( name , " wanpipe/pri/s%dc%d " , spri - > span , pevent - > ring . channel ) ;
2006-02-10 22:26:00 +00:00
switch_channel_set_name ( channel , name ) ;
2007-03-02 19:12:26 +00:00
tech_pvt - > session = session ;
2006-01-03 22:13:59 +00:00
} else {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Hey where is my memory pool? \n " ) ;
2006-01-03 22:13:59 +00:00
switch_core_session_destroy ( & session ) ;
2007-02-09 01:34:01 +00:00
ret = 0 ;
goto done ;
2006-01-03 22:13:59 +00:00
}
2006-01-20 15:05:05 +00:00
2006-12-04 20:51:16 +00:00
if ( pevent - > ring . ani2 > = 0 ) {
snprintf ( ani2str , 5 , " %.2d " , pevent - > ring . ani2 ) ;
2006-01-03 22:13:59 +00:00
}
2006-03-01 22:55:28 +00:00
if ( ( tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
2007-04-09 19:27:59 +00:00
NULL ,
globals . dialplan ,
" FreeSWITCH " ,
pevent - > ring . callingnum ,
2006-12-04 20:51:16 +00:00
# ifdef WIN32
NULL ,
# else
pevent - > ring . callingani ,
# endif
switch_strlen_zero ( ani2str ) ? NULL : ani2str ,
2007-04-09 19:27:59 +00:00
NULL ,
NULL ,
( char * ) modname ,
2007-08-08 14:37:19 +00:00
globals . context ,
2007-04-09 19:27:59 +00:00
pevent - > ring . callednum ) ) ) {
2006-01-03 22:13:59 +00:00
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
}
2006-06-23 16:59:47 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_INBOUND ) ;
2006-01-03 22:13:59 +00:00
tech_pvt - > spri = spri ;
tech_pvt - > cause = - 1 ;
2006-02-10 22:26:00 +00:00
if ( ! tech_pvt - > call ) {
2006-12-04 20:51:16 +00:00
tech_pvt - > call = pevent - > ring . call ;
2006-02-10 22:26:00 +00:00
}
2007-04-09 19:27:59 +00:00
2006-12-04 20:51:16 +00:00
tech_pvt - > callno = pevent - > ring . channel ;
2006-02-22 18:32:15 +00:00
tech_pvt - > span = spri - > span ;
2006-01-03 22:13:59 +00:00
2007-04-16 20:26:21 +00:00
if ( ! ( tech_pvt - > wpsock = wp_open ( spri - > span , pevent - > ring . channel ) ) ) {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't open fd! \n " ) ;
2006-01-03 22:13:59 +00:00
}
2007-03-30 00:13:31 +00:00
switch_copy_string ( chanmap - > map [ pevent - > ring . channel ] , switch_core_session_get_uuid ( session ) , sizeof ( chanmap - > map [ pevent - > ring . channel ] ) ) ;
2007-04-09 19:27:59 +00:00
2006-01-03 22:13:59 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
2007-05-11 00:27:55 +00:00
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 ) ;
ret = 0 ;
goto done ;
}
2006-01-03 22:13:59 +00:00
} else {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot Create new Inbound Channel! \n " ) ;
2006-01-03 22:13:59 +00:00
}
2007-04-09 19:27:59 +00:00
done :
2007-02-09 01:34:01 +00:00
switch_mutex_unlock ( globals . channel_mutex ) ;
2007-04-09 19:27:59 +00:00
2007-02-09 01:34:01 +00:00
return ret ;
2006-01-03 22:13:59 +00:00
}
static int check_flags ( struct sangoma_pri * spri )
{
2006-01-20 15:05:05 +00:00
2006-01-03 22:13:59 +00:00
return 0 ;
}
2007-04-09 19:27:59 +00:00
static int on_restart ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-01-03 22:13:59 +00:00
{
2006-04-29 06:58:08 +00:00
switch_core_session_t * session ;
2006-02-10 22:26:00 +00:00
struct channel_map * chanmap ;
2006-01-03 22:13:59 +00:00
2006-03-21 00:20:24 +00:00
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " -- Restarting s%dc%d \n " , spri - > span , pevent - > restart . channel ) ;
2006-01-03 22:13:59 +00:00
2006-12-04 20:51:16 +00:00
if ( pevent - > restart . channel < 1 ) {
2006-03-21 00:20:24 +00:00
return 0 ;
}
2006-02-26 04:52:34 +00:00
chanmap = spri - > private_info ;
2007-04-09 19:27:59 +00:00
2007-02-09 01:34:01 +00:00
if ( ( session = switch_core_session_locate ( chanmap - > map [ pevent - > restart . channel ] ) ) ) {
2006-04-29 06:58:08 +00:00
switch_channel_t * channel ;
2006-02-10 22:26:00 +00:00
channel = switch_core_session_get_channel ( session ) ;
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Hanging Up channel %s \n " , switch_channel_get_name ( channel ) ) ;
2006-04-22 03:05:25 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
2007-02-09 01:34:01 +00:00
switch_core_session_rwunlock ( session ) ;
2006-02-10 22:26:00 +00:00
}
2007-04-09 19:27:59 +00:00
2006-12-04 20:51:16 +00:00
wp_restart ( spri - > span , pevent - > restart . channel ) ;
2006-09-24 15:25:36 +00:00
2006-01-03 22:13:59 +00:00
return 0 ;
}
2007-04-09 19:27:59 +00:00
static int on_dchan_up ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-03-24 14:47:53 +00:00
{
if ( ! switch_test_flag ( spri , SANGOMA_PRI_READY ) ) {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Span %d D-Chan UP! \n " , spri - > span ) ;
2006-03-24 14:47:53 +00:00
switch_set_flag ( spri , SANGOMA_PRI_READY ) ;
}
return 0 ;
}
2007-04-09 19:27:59 +00:00
static int on_dchan_down ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-03-24 14:47:53 +00:00
{
if ( switch_test_flag ( spri , SANGOMA_PRI_READY ) ) {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Span %d D-Chan DOWN! \n " , spri - > span ) ;
2006-03-24 14:47:53 +00:00
switch_clear_flag ( spri , SANGOMA_PRI_READY ) ;
}
2007-04-09 19:27:59 +00:00
2006-03-24 14:47:53 +00:00
return 0 ;
}
2007-04-09 19:27:59 +00:00
static int on_anything ( struct sangoma_pri * spri , sangoma_pri_event_t event_type , pri_event * pevent )
2006-01-03 22:13:59 +00:00
{
2006-03-24 14:47:53 +00:00
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Caught Event span %d %u (%s) \n " , spri - > span , event_type ,
sangoma_pri_event_str ( event_type ) ) ;
2006-01-03 22:13:59 +00:00
return 0 ;
}
2007-04-09 19:27:59 +00:00
static void * SWITCH_THREAD_FUNC pri_thread_run ( switch_thread_t * thread , void * obj )
2006-01-03 22:13:59 +00:00
{
struct sangoma_pri * spri = obj ;
2007-03-13 20:34:27 +00:00
struct channel_map chanmap ;
memset ( & chanmap , 0 , sizeof ( chanmap ) ) ;
2006-02-22 15:20:46 +00:00
2006-04-29 06:58:08 +00:00
switch_event_t * s_event ;
2007-04-16 23:49:58 +00:00
switch_mutex_init ( & chanmap . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
2006-01-03 22:13:59 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_ANY , on_anything ) ;
2008-05-05 15:30:55 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_RING , on_routing ) ;
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_RINGING , on_routinging ) ;
2006-03-23 19:22:06 +00:00
//SANGOMA_MAP_PRI_EVENT((*spri), SANGOMA_PRI_EVENT_SETUP_ACK, on_proceed);
2006-02-22 02:50:33 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_PROCEEDING , on_proceed ) ;
2006-02-10 22:26:00 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_ANSWER , on_answer ) ;
2006-03-24 14:47:53 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_DCHAN_UP , on_dchan_up ) ;
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_DCHAN_DOWN , on_dchan_down ) ;
2006-01-03 22:13:59 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_HANGUP_REQ , on_hangup ) ;
2006-02-22 02:50:33 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_HANGUP , on_hangup ) ;
2006-01-03 22:13:59 +00:00
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_INFO_RECEIVED , on_info ) ;
SANGOMA_MAP_PRI_EVENT ( ( * spri ) , SANGOMA_PRI_EVENT_RESTART , on_restart ) ;
spri - > on_loop = check_flags ;
2006-02-26 04:52:34 +00:00
spri - > private_info = & chanmap ;
2006-02-14 16:42:26 +00:00
if ( switch_event_create ( & s_event , SWITCH_EVENT_PUBLISH ) = = SWITCH_STATUS_SUCCESS ) {
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " service " , " _pri._tcp " ) ;
switch_event_fire ( & s_event ) ;
}
2006-01-03 22:13:59 +00:00
sangoma_run_pri ( spri ) ;
2006-01-20 15:05:05 +00:00
2006-01-03 22:13:59 +00:00
free ( spri ) ;
return NULL ;
}
2006-02-12 20:38:24 +00:00
static void pri_thread_launch ( struct sangoma_pri * spri )
{
2006-04-29 06:58:08 +00:00
switch_thread_t * thread ;
2006-02-12 20:38:24 +00:00
switch_threadattr_t * thd_attr = NULL ;
2007-04-09 19:27:59 +00:00
2006-02-12 20:38:24 +00:00
switch_threadattr_create ( & thd_attr , module_pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
2006-04-26 17:18:33 +00:00
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
2006-02-12 20:38:24 +00:00
switch_thread_create ( & thread , thd_attr , pri_thread_run , spri , module_pool ) ;
}
2006-01-03 22:13:59 +00:00
2007-03-02 19:12:26 +00:00
2007-04-09 19:27:59 +00:00
static int isup_exec_command ( ss7boost_handle_t * ss7boost_handle , int span , int chan , int id , int cmd , int cause )
2007-03-02 19:12:26 +00:00
{
ss7boost_client_event_t oevent ;
int r = 0 ;
switch_mutex_lock ( ss7boost_handle - > mutex ) ;
ss7boost_client_event_init ( & oevent , cmd , chan , span ) ;
oevent . release_cause = cause ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
if ( id > = 0 ) {
oevent . call_setup_id = id ;
}
2007-04-09 19:27:59 +00:00
if ( ss7boost_client_connection_write ( & ss7boost_handle - > mcon , & oevent ) < = 0 ) {
2007-03-02 19:12:26 +00:00
r = - 1 ;
}
switch_mutex_unlock ( ss7boost_handle - > mutex ) ;
return r ;
}
2007-03-13 20:34:27 +00:00
# ifdef USE_WAITFOR_SOCKET
2007-03-02 19:12:26 +00:00
static int waitfor_socket ( int fd , int timeout , int flags )
{
2007-04-09 19:27:59 +00:00
struct pollfd pfds [ 1 ] ;
int res ;
memset ( & pfds [ 0 ] , 0 , sizeof ( pfds [ 0 ] ) ) ;
pfds [ 0 ] . fd = fd ;
pfds [ 0 ] . events = flags ;
res = poll ( pfds , 1 , timeout ) ;
if ( res > 0 ) {
2008-02-15 23:23:59 +00:00
if ( pfds [ 0 ] . revents & POLLIN ) {
2007-04-09 19:27:59 +00:00
res = 1 ;
} else if ( ( pfds [ 0 ] . revents & POLLERR ) ) {
res = - 1 ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " System Error: Poll Event Error no event! \n " ) ;
res = - 1 ;
}
}
return res ;
2007-03-02 19:12:26 +00:00
}
2007-03-13 20:34:27 +00:00
# endif
2007-03-02 19:12:26 +00:00
static void validate_number ( unsigned char * s )
{
unsigned char * p ;
for ( p = s ; * p ; p + + ) {
if ( * p < 48 | | * p > 57 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Encountered a non-numeric character [%c]! \n " , * p ) ;
* p = ' \0 ' ;
break ;
}
}
}
2007-04-09 19:27:59 +00:00
static void handle_call_stop ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
char * uuid = ss7boost_handle - > span_chanmap [ event - > span ] . map [ event - > chan ] ;
if ( * uuid ) {
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
private_object_t * tech_pvt ;
switch_channel_t * channel ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
switch_channel_hangup ( channel , event - > release_cause ) ;
switch_core_session_rwunlock ( session ) ;
}
* uuid = ' \0 ' ;
2007-04-09 19:27:59 +00:00
}
2007-03-02 19:12:26 +00:00
2007-04-09 19:27:59 +00:00
isup_exec_command ( ss7boost_handle ,
event - > span ,
event - > chan ,
- 1 ,
SIGBOOST_EVENT_CALL_STOPPED_ACK ,
0 ) ;
2007-03-02 19:12:26 +00:00
}
2007-04-09 19:27:59 +00:00
static void handle_call_start ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
char name [ 128 ] ;
if ( * ss7boost_handle - > span_chanmap [ event - > span ] . map [ event - > chan ] ) {
2007-04-09 19:27:59 +00:00
isup_exec_command ( ss7boost_handle ,
event - > span ,
event - > chan ,
- 1 ,
SIGBOOST_EVENT_CALL_START_NACK ,
SIGBOOST_RELEASE_CAUSE_BUSY ) ;
2007-03-02 19:12:26 +00:00
return ;
}
2007-04-09 19:27:59 +00:00
2007-10-29 19:15:26 +00:00
if ( ( session = switch_core_session_request ( wanpipe_endpoint_interface , NULL ) ) ) {
2007-03-02 19:12:26 +00:00
private_object_t * tech_pvt ;
switch_core_session_add_stream ( session , NULL ) ;
if ( ( tech_pvt = ( private_object_t * ) switch_core_session_alloc ( session , sizeof ( private_object_t ) ) ) ) {
memset ( tech_pvt , 0 , sizeof ( * tech_pvt ) ) ;
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
channel = switch_core_session_get_channel ( session ) ;
switch_core_session_set_private ( session , tech_pvt ) ;
2007-04-09 19:27:59 +00:00
sprintf ( name , " wanpipe/ss7boost/s%dc%d " , event - > span + 1 , event - > chan + 1 ) ;
2007-03-02 19:12:26 +00:00
switch_channel_set_name ( channel , name ) ;
tech_pvt - > session = session ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Hey where is my memory pool? \n " ) ;
goto fail ;
}
if ( ( tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
2007-04-09 19:27:59 +00:00
NULL ,
globals . dialplan ,
" FreeSWITCH(boost) " ,
( char * ) event - > calling_number_digits ,
2007-03-02 19:12:26 +00:00
# ifdef WIN32
NULL ,
# else
2007-04-09 19:27:59 +00:00
( char * ) event - > calling_number_digits ,
2007-03-02 19:12:26 +00:00
# endif
2007-04-09 19:27:59 +00:00
NULL ,
NULL ,
NULL ,
( char * ) modname ,
NULL ,
( char * ) event - > called_number_digits ) ) ) {
2007-03-02 19:12:26 +00:00
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
}
switch_set_flag_locked ( tech_pvt , TFLAG_INBOUND ) ;
tech_pvt - > cause = - 1 ;
tech_pvt - > ss7boost_handle = ss7boost_handle ;
tech_pvt - > boost_span_number = event - > span ;
tech_pvt - > boost_chan_number = event - > chan ;
tech_pvt - > boost_pres = event - > calling_number_presentation ;
2007-04-09 19:27:59 +00:00
2007-04-16 20:26:21 +00:00
if ( ! ( tech_pvt - > wpsock = wp_open ( event - > span + 1 , event - > chan + 1 ) ) ) {
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't open channel %d:%d \n " , event - > span + 1 , event - > chan + 1 ) ;
2007-03-02 19:12:26 +00:00
goto fail ;
}
2007-04-09 19:27:59 +00:00
switch_copy_string ( ss7boost_handle - > span_chanmap [ event - > span ] . map [ event - > chan ] , switch_core_session_get_uuid ( session ) ,
sizeof ( ss7boost_handle - > span_chanmap [ event - > span ] . map [ event - > chan ] ) ) ;
2007-03-02 19:12:26 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
2007-04-09 19:27:59 +00:00
isup_exec_command ( ss7boost_handle ,
event - > span ,
event - > chan ,
- 1 ,
SIGBOOST_EVENT_CALL_START_ACK ,
0 ) ;
2007-03-02 19:12:26 +00:00
switch_core_session_thread_launch ( session ) ;
return ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot Create new Inbound Channel! \n " ) ;
}
2007-04-09 19:27:59 +00:00
fail :
2007-03-02 19:12:26 +00:00
if ( session ) {
switch_core_session_destroy ( & session ) ;
}
2007-04-09 19:27:59 +00:00
isup_exec_command ( ss7boost_handle ,
event - > span ,
event - > chan ,
- 1 ,
SIGBOOST_EVENT_CALL_STOPPED ,
SIGBOOST_RELEASE_CAUSE_BUSY ) ;
2007-03-02 19:12:26 +00:00
}
2007-04-09 19:27:59 +00:00
static void handle_heartbeat ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Heartbeat! \n " ) ;
2007-04-09 19:27:59 +00:00
isup_exec_command ( ss7boost_handle ,
event - > span ,
event - > chan ,
- 1 ,
SIGBOOST_EVENT_HEARTBEAT ,
0 ) ;
2007-03-02 19:12:26 +00:00
}
2007-04-09 19:27:59 +00:00
static void handle_call_start_ack ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
char * uuid = ss7boost_handle - > setup_array [ event - > call_setup_id ] ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
if ( * uuid ) {
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
private_object_t * tech_pvt ;
switch_channel_t * channel ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
tech_pvt - > ss7boost_handle = ss7boost_handle ;
tech_pvt - > boost_span_number = event - > span ;
tech_pvt - > boost_chan_number = event - > chan ;
2007-04-09 19:27:59 +00:00
switch_copy_string ( ss7boost_handle - > span_chanmap [ event - > span ] . map [ event - > chan ] , switch_core_session_get_uuid ( session ) ,
sizeof ( ss7boost_handle - > span_chanmap [ event - > span ] . map [ event - > chan ] ) ) ;
2007-03-02 19:12:26 +00:00
if ( ! tech_pvt - > wpsock ) {
2007-04-16 20:26:21 +00:00
if ( ! ( tech_pvt - > wpsock = wp_open ( tech_pvt - > boost_span_number + 1 , tech_pvt - > boost_chan_number + 1 ) ) ) {
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't open fd for s%dc%d! [%s] \n " ,
tech_pvt - > boost_span_number + 1 , tech_pvt - > boost_chan_number + 1 , strerror ( errno ) ) ;
2007-03-02 19:12:26 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return ;
}
if ( wanpipe_codec_init ( tech_pvt ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return ;
}
}
switch_channel_mark_pre_answered ( channel ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_core_session_rwunlock ( session ) ;
}
* uuid = ' \0 ' ;
}
}
2007-04-09 19:27:59 +00:00
static void handle_call_start_nack_ack ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
// WTF IS THIS! ?
}
2007-04-09 19:27:59 +00:00
static void handle_call_answer ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
char * uuid = ss7boost_handle - > span_chanmap [ event - > span ] . map [ event - > chan ] ;
if ( * uuid ) {
switch_core_session_t * session ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
private_object_t * tech_pvt ;
switch_channel_t * channel ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
if ( ! tech_pvt - > wpsock ) {
2007-04-16 20:26:21 +00:00
if ( ! ( tech_pvt - > wpsock = wp_open ( tech_pvt - > boost_span_number + 1 , tech_pvt - > boost_chan_number + 1 ) ) ) {
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't open fd for s%dc%d! [%s] \n " ,
tech_pvt - > boost_span_number + 1 , tech_pvt - > boost_chan_number + 1 , strerror ( errno ) ) ;
2007-03-02 19:12:26 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return ;
}
if ( wanpipe_codec_init ( tech_pvt ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return ;
}
}
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_channel_mark_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Session %s missing! \n " , uuid ) ;
* uuid = ' \0 ' ;
}
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " No UUID? \n " ) ;
}
}
2007-04-09 19:27:59 +00:00
static void handle_call_stop_ack ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
// TODO anything here?
}
2007-04-09 19:27:59 +00:00
static void handle_call_start_nack ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
char * uuid = ss7boost_handle - > setup_array [ event - > call_setup_id ] ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
if ( * uuid ) {
switch_core_session_t * session ;
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
private_object_t * tech_pvt ;
switch_channel_t * channel ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
tech_pvt - > ss7boost_handle = ss7boost_handle ;
tech_pvt - > boost_span_number = event - > span ;
tech_pvt - > boost_chan_number = event - > chan ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_channel_hangup ( channel , event - > release_cause ) ;
2007-04-09 19:27:59 +00:00
isup_exec_command ( ss7boost_handle ,
event - > span ,
event - > chan ,
event - > call_setup_id ,
SIGBOOST_EVENT_CALL_START_NACK_ACK ,
0 ) ;
2007-03-02 19:12:26 +00:00
switch_core_session_rwunlock ( session ) ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Session %s missing! \n " , uuid ) ;
}
* uuid = ' \0 ' ;
}
}
2007-04-09 19:27:59 +00:00
static int parse_ss7_event ( ss7boost_handle_t * ss7boost_handle , ss7boost_client_event_t * event )
2007-03-02 19:12:26 +00:00
{
int ret = 0 ;
switch_mutex_lock ( ss7boost_handle - > mutex ) ;
2007-04-09 19:27:59 +00:00
validate_number ( ( unsigned char * ) event - > called_number_digits ) ;
validate_number ( ( unsigned char * ) event - > calling_number_digits ) ;
2007-03-02 19:12:26 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG ,
" \n RX EVENT \n "
" =================================== \n "
" rType: %s (%0x HEX) \n "
" rSpan: [%d] \n "
" rChan: [%d] \n "
" rCalledNum: %s \n "
" rCallingNum: %s \n "
" rCause: %s \n "
" rInterface : [w%dg%d] \n "
" rEvent ID : [%d] \n "
" rSetup ID: [%d] \n "
" rSeq: [%d] \n "
" =================================== \n "
" \n " ,
ss7boost_client_event_id_name ( event - > event_id ) ,
event - > event_id ,
2007-04-09 19:27:59 +00:00
event - > span + 1 ,
event - > chan + 1 ,
2007-03-02 19:12:26 +00:00
( event - > called_number_digits_count ? ( char * ) event - > called_number_digits : " N/A " ) ,
( event - > calling_number_digits_count ? ( char * ) event - > calling_number_digits : " N/A " ) ,
2007-04-09 19:27:59 +00:00
switch_channel_cause2str ( event - > release_cause ) ,
event - > span + 1 ,
event - > chan + 1 ,
event - > event_id ,
event - > call_setup_id ,
event - > seqno
) ;
2007-03-02 19:12:26 +00:00
2007-04-09 19:27:59 +00:00
switch ( event - > event_id ) {
2007-03-02 19:12:26 +00:00
case SIGBOOST_EVENT_CALL_START :
handle_call_start ( ss7boost_handle , event ) ;
break ;
case SIGBOOST_EVENT_CALL_STOPPED :
handle_call_stop ( ss7boost_handle , event ) ;
break ;
case SIGBOOST_EVENT_CALL_START_ACK :
handle_call_start_ack ( ss7boost_handle , event ) ;
break ;
case SIGBOOST_EVENT_CALL_START_NACK :
handle_call_start_nack ( ss7boost_handle , event ) ;
break ;
case SIGBOOST_EVENT_CALL_ANSWERED :
handle_call_answer ( ss7boost_handle , event ) ;
break ;
case SIGBOOST_EVENT_HEARTBEAT :
handle_heartbeat ( ss7boost_handle , event ) ;
break ;
case SIGBOOST_EVENT_CALL_START_NACK_ACK :
handle_call_start_nack_ack ( ss7boost_handle , event ) ;
break ;
case SIGBOOST_EVENT_CALL_STOPPED_ACK :
handle_call_stop_ack ( ss7boost_handle , event ) ;
break ;
default :
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Warning no handler implemented for [%s] \n " ,
2007-03-30 00:15:25 +00:00
ss7boost_client_event_id_name ( event - > event_id ) ) ;
2007-03-02 19:12:26 +00:00
break ;
}
switch_mutex_unlock ( ss7boost_handle - > mutex ) ;
return ret ;
}
2007-04-09 19:27:59 +00:00
static void * SWITCH_THREAD_FUNC boost_thread_run ( switch_thread_t * thread , void * obj )
2007-03-02 19:12:26 +00:00
{
ss7boost_handle_t * ss7boost_handle = ( ss7boost_handle_t * ) obj ;
ss7boost_client_event_t * event ;
if ( ss7boost_client_connection_open ( & ss7boost_handle - > mcon ,
2007-04-09 19:27:59 +00:00
ss7boost_handle - > local_ip ,
ss7boost_handle - > local_port ,
ss7boost_handle - > remote_ip ,
ss7boost_handle - > remote_port ,
module_pool ) ! = SWITCH_STATUS_SUCCESS ) {
2007-03-02 19:12:26 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " FATAL ERROR CREATING CLIENT CONNECTION \n " ) ;
return NULL ;
}
2007-04-09 19:27:59 +00:00
isup_exec_command ( ss7boost_handle ,
0 ,
0 ,
- 1 ,
SIGBOOST_EVENT_SYSTEM_RESTART ,
0 ) ;
2007-03-02 19:12:26 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Monitor Thread Started \n " ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_mutex_lock ( globals . hash_mutex ) ;
globals . configured_boost_spans + + ;
switch_mutex_unlock ( globals . hash_mutex ) ;
globals . ss7boost_handle = ss7boost_handle ;
2007-04-09 19:27:59 +00:00
for ( ; ; ) {
2007-03-02 19:12:26 +00:00
if ( ss7boost_client_connection_read ( & ss7boost_handle - > mcon , & event ) = = SWITCH_STATUS_SUCCESS ) {
2007-04-09 19:27:59 +00:00
struct timeval current ;
struct timeval difftime ;
gettimeofday ( & current , NULL ) ;
timersub ( & current , & event - > tv , & difftime ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Socket Event [%s] T=%d:%d \n " ,
ss7boost_client_event_id_name ( event - > event_id ) ,
( int ) difftime . tv_sec , ( int ) difftime . tv_usec ) ;
parse_ss7_event ( ss7boost_handle , event ) ;
2007-03-02 19:12:26 +00:00
} else {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error: Reading from Boost Socket! %s \n " , strerror ( errno ) ) ;
2007-03-02 19:12:26 +00:00
break ;
}
}
2007-03-13 20:34:27 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Close udp socket \n " ) ;
2007-03-02 19:12:26 +00:00
ss7boost_client_connection_close ( & ss7boost_handle - > mcon ) ;
2007-04-09 19:27:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Monitor Thread Ended \n " ) ;
2007-03-02 19:12:26 +00:00
return NULL ;
}
2007-04-09 19:27:59 +00:00
static void launch_ss7boost_handle ( ss7boost_handle_t * ss7boost_handle )
2007-03-02 19:12:26 +00:00
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
switch_threadattr_create ( & thd_attr , module_pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , thd_attr , boost_thread_run , ss7boost_handle , module_pool ) ;
}
2006-05-01 04:29:44 +00:00
static switch_status_t config_wanpipe ( int reload )
2006-01-03 22:13:59 +00:00
{
2006-01-13 14:23:34 +00:00
char * cf = " wanpipe.conf " ;
2007-02-07 23:43:04 +00:00
int current_span = 0 , min_span = 0 , max_span = 0 ;
2007-03-22 21:50:59 +00:00
switch_xml_t cfg , xml , settings , param , pri_spans , ss7boost_handles , span , analog_channels , channel ;
2006-01-03 22:13:59 +00:00
2007-02-09 20:03:07 +00:00
globals . samples_per_frame = DEFAULT_SAMPLES_PER_FRAME ;
2006-02-22 18:32:15 +00:00
globals . dtmf_on = 150 ;
globals . dtmf_off = 50 ;
2006-01-03 22:13:59 +00:00
2006-02-12 20:38:24 +00:00
2006-09-24 15:25:36 +00:00
2006-05-10 15:47:54 +00:00
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " open of %s failed \n " , cf ) ;
2006-01-03 22:13:59 +00:00
return SWITCH_STATUS_TERM ;
}
2006-05-10 03:23:05 +00:00
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
2006-05-17 00:58:21 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2006-05-10 03:23:05 +00:00
2006-01-03 22:13:59 +00:00
if ( ! strcmp ( var , " debug " ) ) {
globals . debug = atoi ( val ) ;
2007-02-09 20:03:07 +00:00
} else if ( ! strcmp ( var , " ms-per-frame " ) ) {
globals . samples_per_frame = atoi ( val ) * 8 ;
2006-05-16 17:08:21 +00:00
} else if ( ! strcmp ( var , " dtmf-on " ) ) {
2006-02-22 18:32:15 +00:00
globals . dtmf_on = atoi ( val ) ;
2006-05-16 17:08:21 +00:00
} else if ( ! strcmp ( var , " dtmf-off " ) ) {
2006-02-22 18:32:15 +00:00
globals . dtmf_off = atoi ( val ) ;
2007-03-02 19:12:26 +00:00
} else if ( ! strcmp ( var , " dialplan " ) ) {
set_global_dialplan ( val ) ;
2007-08-08 14:37:19 +00:00
} else if ( ! strcmp ( var , " context " ) ) {
set_global_context ( val ) ;
2007-06-15 02:58:11 +00:00
} else if ( ! strcmp ( var , " suppress-dtmf-tone " ) ) {
globals . suppress_dtmf_tone = switch_true ( val ) ;
} else if ( ! strcmp ( var , " ignore-dtmf-tone " ) ) {
globals . ignore_dtmf_tone = switch_true ( val ) ;
2006-02-12 20:38:24 +00:00
}
2006-05-10 03:23:05 +00:00
}
}
2007-03-02 19:12:26 +00:00
ss7boost_handles = switch_xml_child ( cfg , " ss7boost_handles " ) ;
for ( span = switch_xml_child ( ss7boost_handles , " handle " ) ; span ; span = span - > next ) {
char * local_ip = NULL , * remote_ip = NULL ;
int local_port = 0 , remote_port = 0 ;
ss7boost_handle_t * ss7boost_handle ;
for ( param = switch_xml_child ( span , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2007-04-09 19:27:59 +00:00
2007-03-02 19:12:26 +00:00
if ( ! strcasecmp ( var , " local-ip " ) ) {
local_ip = val ;
} else if ( ! strcasecmp ( var , " local-port " ) ) {
local_port = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " remote-ip " ) ) {
remote_ip = val ;
} else if ( ! strcasecmp ( var , " remote-port " ) ) {
remote_port = atoi ( val ) ;
}
}
if ( ! ( local_ip & & local_port & & remote_ip & & remote_port ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Config, skipping... \n " ) ;
continue ;
}
assert ( ss7boost_handle = malloc ( sizeof ( * ss7boost_handle ) ) ) ;
memset ( ss7boost_handle , 0 , sizeof ( * ss7boost_handle ) ) ;
ss7boost_handle - > local_ip = switch_core_strdup ( module_pool , local_ip ) ;
ss7boost_handle - > local_port = local_port ;
ss7boost_handle - > remote_ip = switch_core_strdup ( module_pool , remote_ip ) ;
ss7boost_handle - > remote_port = remote_port ;
switch_mutex_init ( & ss7boost_handle - > mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
launch_ss7boost_handle ( ss7boost_handle ) ;
break ;
}
2007-03-22 21:50:59 +00:00
analog_channels = switch_xml_child ( cfg , " analog_channels " ) ;
2007-04-09 19:27:59 +00:00
for ( channel = switch_xml_child ( analog_channels , " channel " ) ; channel ; channel = channel - > next ) {
2007-03-22 21:50:59 +00:00
char * c_type = ( char * ) switch_xml_attr ( channel , " type " ) ;
char * c_dev = ( char * ) switch_xml_attr ( channel , " device " ) ;
char * user = NULL ;
char * domain = NULL ;
char * cid_name = NULL , * cid_num = NULL ;
analog_channel_t * alc ;
analog_type_t a_type = ANALOG_TYPE_UNKNOWN ;
wpsock_t * sock ;
int chan , span ;
2007-04-09 19:27:59 +00:00
2007-03-22 21:50:59 +00:00
if ( ! c_type ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing required attribute 'type' \n " ) ;
continue ;
}
if ( ! strcasecmp ( c_type , " phone " ) | | ! strcasecmp ( c_type , " fxs " ) ) {
a_type = ANALOG_TYPE_PHONE_FXS ;
} else if ( ! strcasecmp ( c_type , " line " ) | | ! strcasecmp ( c_type , " fxo " ) ) {
a_type = ANLOG_TYPE_LINE_FXO ;
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid type '%s' \n " , c_type ) ;
continue ;
}
if ( ! c_dev ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing required attribute 'device' \n " ) ;
continue ;
}
2008-02-15 23:23:59 +00:00
if ( ! sangoma_span_chan_fromif ( c_dev , & span , & chan ) ) {
2007-03-22 21:50:59 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid device name '%s' \n " , c_dev ) ;
continue ;
}
2007-04-09 19:27:59 +00:00
2007-04-16 20:26:21 +00:00
if ( ! ( sock = wp_open ( span , chan ) ) ) {
2007-03-30 00:13:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot open device '%s' (%s) \n " , c_dev , strerror ( errno ) ) ;
2007-03-22 21:50:59 +00:00
continue ;
}
for ( param = switch_xml_child ( channel , " param " ) ; param ; param = param - > next ) {
2007-04-09 19:27:59 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2007-03-22 21:50:59 +00:00
if ( ! strcasecmp ( var , " user " ) ) {
user = var ;
} else if ( ! strcasecmp ( var , " domain " ) ) {
domain = val ;
} else if ( ! strcasecmp ( var , " caller-id-name " ) ) {
cid_name = val ;
} else if ( ! strcasecmp ( var , " caller-id-number " ) ) {
cid_num = val ;
}
}
assert ( ( alc = malloc ( sizeof ( * alc ) ) ) ) ;
memset ( alc , 0 , sizeof ( * alc ) ) ;
if ( user ) {
alc - > user = strdup ( user ) ;
}
if ( domain ) {
alc - > domain = strdup ( domain ) ;
}
if ( cid_name ) {
alc - > cid_name = strdup ( cid_name ) ;
}
if ( cid_num ) {
alc - > cid_name = strdup ( cid_num ) ;
}
2007-04-09 19:27:59 +00:00
2007-03-22 21:50:59 +00:00
alc - > a_type = a_type ;
alc - > sock = sock ;
alc - > chan = chan ;
alc - > span = span ;
if ( a_type = = ANALOG_TYPE_PHONE_FXS ) {
FXS_ANALOG_CHANNELS [ globals . fxs_index + + ] = alc ;
} else {
FXO_ANALOG_CHANNELS [ globals . fxo_index + + ] = alc ;
}
}
if ( globals . fxs_index ) {
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
2007-04-09 19:27:59 +00:00
2007-03-22 21:50:59 +00:00
switch_threadattr_create ( & thd_attr , module_pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , thd_attr , fxs_thread_run , NULL , module_pool ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Starting FXS Thread! \n " ) ;
}
2007-03-02 19:12:26 +00:00
pri_spans = switch_xml_child ( cfg , " pri_spans " ) ;
for ( span = switch_xml_child ( pri_spans , " span " ) ; span ; span = span - > next ) {
2007-02-09 01:34:01 +00:00
char * id = ( char * ) switch_xml_attr ( span , " id " ) ;
2007-02-07 23:43:04 +00:00
int32_t i = 0 ;
2006-05-10 03:23:05 +00:00
2007-02-07 23:43:04 +00:00
current_span = 0 ;
2007-04-09 19:27:59 +00:00
2007-02-07 23:43:04 +00:00
if ( id ) {
char * p ;
2007-04-09 19:27:59 +00:00
2007-02-07 23:43:04 +00:00
min_span = atoi ( id ) ;
if ( ( p = strchr ( id , ' - ' ) ) ) {
p + + ;
max_span = atoi ( p ) ;
2006-02-12 20:38:24 +00:00
} else {
2007-02-07 23:43:04 +00:00
max_span = min_span ;
}
if ( min_span < 1 | | max_span < min_span ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid Span Config! [%s] \n " , id ) ;
continue ;
}
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Missing SPAN ID! \n " ) ;
continue ;
}
2007-04-09 19:27:59 +00:00
2007-02-07 23:43:04 +00:00
for ( i = min_span ; i < = max_span ; i + + ) {
current_span = i ;
2007-04-09 19:27:59 +00:00
2007-02-07 23:43:04 +00:00
if ( current_span < = 0 | | current_span > MAX_SPANS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid SPAN %d! \n " , current_span ) ;
current_span = 0 ;
continue ;
}
2007-04-09 19:27:59 +00:00
2007-02-07 23:43:04 +00:00
if ( ! SPANS [ current_span ] ) {
if ( ! ( SPANS [ current_span ] = switch_core_alloc ( module_pool , sizeof ( * SPANS [ current_span ] ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " MEMORY ERROR \n " ) ;
break ;
2006-02-12 20:38:24 +00:00
}
2007-02-07 23:43:04 +00:00
SPANS [ current_span ] - > span = current_span ;
}
2007-04-09 19:27:59 +00:00
2007-02-07 23:43:04 +00:00
for ( param = switch_xml_child ( span , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
2007-04-09 19:27:59 +00:00
2006-02-12 20:38:24 +00:00
if ( ! strcmp ( var , " dchan " ) ) {
SPANS [ current_span ] - > dchan = atoi ( val ) ;
} else if ( ! strcmp ( var , " bchan " ) ) {
char from [ 128 ] ;
char * to ;
switch_copy_string ( from , val , sizeof ( from ) ) ;
if ( ( to = strchr ( from , ' - ' ) ) ) {
int fromi , toi , x = 0 ;
* to + + = ' \0 ' ;
fromi = atoi ( from ) ;
toi = atoi ( to ) ;
if ( fromi > 0 & & toi > 0 & & fromi < toi & & fromi < MAX_SPANS & & toi < MAX_SPANS ) {
2007-04-09 19:27:59 +00:00
for ( x = fromi ; x < = toi ; x + + ) {
2006-02-12 20:38:24 +00:00
SPANS [ current_span ] - > bchans | = ( 1 < < x ) ;
}
} else {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid bchan range! \n " ) ;
2006-02-12 20:38:24 +00:00
}
} else {
int i = atoi ( val ) ;
if ( i > 0 & & i < 31 ) {
SPANS [ current_span ] - > bchans | = ( 1 < < i ) ;
} else {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid bchan! \n " ) ;
2006-02-12 20:38:24 +00:00
}
}
} else if ( ! strcmp ( var , " node " ) ) {
SPANS [ current_span ] - > node = str2node ( val ) ;
} else if ( ! strcmp ( var , " switch " ) ) {
SPANS [ current_span ] - > pswitch = str2switch ( val ) ;
} else if ( ! strcmp ( var , " dp " ) ) {
SPANS [ current_span ] - > dp = str2dp ( val ) ;
} else if ( ! strcmp ( var , " l1 " ) ) {
SPANS [ current_span ] - > l1 = str2l1 ( val ) ;
}
2006-01-20 15:05:05 +00:00
}
2006-01-03 22:13:59 +00:00
}
}
2006-05-10 03:23:05 +00:00
switch_xml_free ( xml ) ;
2006-01-03 22:13:59 +00:00
if ( ! globals . dialplan ) {
2007-03-02 19:12:26 +00:00
set_global_dialplan ( " XML " ) ;
2006-01-03 22:13:59 +00:00
}
2006-02-24 16:47:22 +00:00
globals . configured_spans = 0 ;
2007-04-09 19:27:59 +00:00
for ( current_span = 1 ; current_span < MAX_SPANS ; current_span + + ) {
2006-02-12 20:38:24 +00:00
if ( SPANS [ current_span ] ) {
2006-02-21 19:36:51 +00:00
2006-02-12 20:38:24 +00:00
if ( ! SPANS [ current_span ] - > l1 ) {
SPANS [ current_span ] - > l1 = PRI_LAYER_1_ULAW ;
}
2006-02-21 19:36:51 +00:00
if ( sangoma_init_pri ( & SPANS [ current_span ] - > spri ,
2007-04-09 19:27:59 +00:00
current_span ,
SPANS [ current_span ] - > dchan ,
SPANS [ current_span ] - > pswitch ,
SPANS [ current_span ] - > node ,
globals . debug ) ) {
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cannot launch span %d \n " , current_span ) ;
2006-02-21 19:36:51 +00:00
continue ;
}
2006-04-16 06:05:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Launch span %d \n " , current_span ) ;
2006-02-12 20:38:24 +00:00
pri_thread_launch ( & SPANS [ current_span ] - > spri ) ;
2007-03-02 19:12:26 +00:00
switch_mutex_lock ( globals . hash_mutex ) ;
2006-02-24 16:47:22 +00:00
globals . configured_spans + + ;
2007-03-02 19:12:26 +00:00
switch_mutex_unlock ( globals . hash_mutex ) ;
2006-02-12 20:38:24 +00:00
}
}
2006-01-20 15:05:05 +00:00
2006-03-30 23:02:50 +00:00
return SWITCH_STATUS_SUCCESS ;
2006-01-03 22:13:59 +00:00
}
2007-04-09 19:27:59 +00:00
2008-01-27 05:02:52 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2008-01-27 05:02:52 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 expandtab :
*/