2007-05-26 00:45:31 -04:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
2011-01-05 11:08:55 -05:00
* Copyright ( C ) 2005 - 2011 , Anthony Minessale II < anthm @ freeswitch . org >
2007-05-26 00:45:31 -04:00
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
2011-01-05 11:08:55 -05:00
* Anthony Minessale II < anthm @ freeswitch . org >
2007-05-26 00:45:31 -04:00
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
2011-01-05 11:08:55 -05:00
* Anthony Minessale II < anthm @ freeswitch . org >
2009-08-19 17:47:56 -04:00
* Moises Silva < moy @ sangoma . com >
2007-05-26 00:45:31 -04:00
*
*
* mod_openzap . c - - OPENZAP Endpoint Module
*
*/
# include <switch.h>
# include "openzap.h"
2008-02-18 10:43:54 -05:00
# ifndef __FUNCTION__
# define __FUNCTION__ __SWITCH_FUNC__
# endif
2008-10-06 15:13:32 -04:00
# define OPENZAP_VAR_PREFIX "openzap_"
# define OPENZAP_VAR_PREFIX_LEN 8
2007-07-03 16:38:43 -04:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_openzap_load ) ;
2007-11-24 13:04:14 -05:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_openzap_shutdown ) ;
SWITCH_MODULE_DEFINITION ( mod_openzap , mod_openzap_load , mod_openzap_shutdown , NULL ) ;
2007-07-03 16:38:43 -04:00
2007-10-29 14:10:25 -04:00
switch_endpoint_interface_t * openzap_endpoint_interface ;
2007-05-26 00:45:31 -04:00
static switch_memory_pool_t * module_pool = NULL ;
2008-01-25 11:42:06 -05:00
typedef enum {
ANALOG_OPTION_NONE = 0 ,
ANALOG_OPTION_3WAY = ( 1 < < 0 ) ,
ANALOG_OPTION_CALL_SWAP = ( 1 < < 1 )
} analog_option_t ;
2007-05-26 00:45:31 -04:00
struct span_config {
zap_span_t * span ;
char dialplan [ 80 ] ;
char context [ 80 ] ;
2007-11-24 13:04:14 -05:00
char dial_regex [ 256 ] ;
char fail_dial_regex [ 256 ] ;
2008-01-09 19:47:04 -05:00
char hold_music [ 256 ] ;
2010-02-26 15:57:59 -05:00
char type [ 256 ] ;
2008-01-25 11:42:06 -05:00
analog_option_t analog_options ;
2007-05-26 00:45:31 -04:00
} ;
2008-01-08 18:33:07 -05:00
static struct span_config SPAN_CONFIG [ ZAP_MAX_SPANS_INTERFACE ] = { { 0 } } ;
2007-05-26 00:45:31 -04:00
typedef enum {
TFLAG_IO = ( 1 < < 0 ) ,
2007-05-30 23:04:26 -04:00
TFLAG_DTMF = ( 1 < < 1 ) ,
TFLAG_CODEC = ( 1 < < 2 ) ,
TFLAG_BREAK = ( 1 < < 3 ) ,
2008-10-17 19:00:47 -04:00
TFLAG_HOLD = ( 1 < < 4 ) ,
TFLAG_DEAD = ( 1 < < 5 )
2007-05-26 00:45:31 -04:00
} TFLAGS ;
static struct {
int debug ;
char * dialplan ;
char * codec_string ;
char * codec_order [ SWITCH_MAX_CODECS ] ;
int codec_order_last ;
char * codec_rates_string ;
char * codec_rates [ SWITCH_MAX_CODECS ] ;
int codec_rates_last ;
unsigned int flags ;
int fd ;
int calls ;
2008-01-09 19:47:04 -05:00
char hold_music [ 256 ] ;
2007-05-26 00:45:31 -04:00
switch_mutex_t * mutex ;
2008-01-25 11:42:06 -05:00
analog_option_t analog_options ;
2007-05-26 00:45:31 -04:00
} globals ;
struct private_object {
unsigned int flags ;
switch_codec_t read_codec ;
switch_codec_t write_codec ;
switch_frame_t read_frame ;
unsigned char databuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
2007-05-27 14:14:49 -04:00
switch_frame_t cng_frame ;
unsigned char cng_databuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
2007-05-26 00:45:31 -04:00
switch_core_session_t * session ;
switch_caller_profile_t * caller_profile ;
unsigned int codec ;
unsigned int codecs ;
unsigned short samprate ;
switch_mutex_t * mutex ;
switch_mutex_t * flag_mutex ;
zap_channel_t * zchan ;
2007-05-30 22:41:50 -04:00
uint32_t wr_error ;
2007-05-26 00:45:31 -04:00
} ;
typedef struct private_object private_t ;
static switch_status_t channel_on_init ( switch_core_session_t * session ) ;
static switch_status_t channel_on_hangup ( switch_core_session_t * session ) ;
2009-04-14 15:03:03 -04:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session ) ;
2008-05-05 11:47:44 -04:00
static switch_status_t channel_on_routing ( switch_core_session_t * session ) ;
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session ) ;
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session ) ;
2008-05-15 15:43:58 -04:00
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
2007-05-26 00:45:31 -04:00
switch_caller_profile_t * outbound_profile ,
2008-01-08 18:33:07 -05:00
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
2009-11-19 21:17:21 -05:00
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause ) ;
2008-05-08 16:27:31 -04:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id ) ;
2007-05-26 00:45:31 -04:00
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig ) ;
2009-01-13 17:45:09 -05:00
zap_status_t zap_channel_from_event ( zap_sigmsg_t * sigmsg , switch_core_session_t * * sp ) ;
void dump_chan ( zap_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream ) ;
2009-07-31 15:16:47 -04:00
void dump_chan_xml ( zap_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream ) ;
2007-05-26 00:45:31 -04:00
2010-02-26 15:57:59 -05:00
static void zap_set_npi ( const char * npi_string , uint8_t * target )
{
2011-02-01 17:35:53 -05:00
if ( switch_is_number ( npi_string ) ) {
* target = ( uint8_t ) atoi ( npi_string ) ;
} else if ( ! strcasecmp ( npi_string , " isdn " ) | | ! strcasecmp ( npi_string , " e164 " ) ) {
2010-02-26 15:57:59 -05:00
* target = ZAP_NPI_ISDN ;
} else if ( ! strcasecmp ( npi_string , " data " ) ) {
* target = ZAP_NPI_DATA ;
} else if ( ! strcasecmp ( npi_string , " telex " ) ) {
* target = ZAP_NPI_TELEX ;
} else if ( ! strcasecmp ( npi_string , " national " ) ) {
* target = ZAP_NPI_NATIONAL ;
} else if ( ! strcasecmp ( npi_string , " private " ) ) {
* target = ZAP_NPI_PRIVATE ;
} else if ( ! strcasecmp ( npi_string , " reserved " ) ) {
* target = ZAP_NPI_RESERVED ;
} else if ( ! strcasecmp ( npi_string , " unknown " ) ) {
* target = ZAP_NPI_UNKNOWN ;
} else {
zap_log ( ZAP_LOG_WARNING , " Invalid NPI value (%s) \n " , npi_string ) ;
* target = ZAP_NPI_UNKNOWN ;
}
}
static void zap_set_ton ( const char * ton_string , uint8_t * target )
{
2011-02-01 17:35:53 -05:00
if ( switch_is_number ( ton_string ) ) {
* target = ( uint8_t ) atoi ( ton_string ) ;
} else if ( ! strcasecmp ( ton_string , " national " ) ) {
2010-02-26 15:57:59 -05:00
* target = ZAP_TON_NATIONAL ;
} else if ( ! strcasecmp ( ton_string , " international " ) ) {
* target = ZAP_TON_INTERNATIONAL ;
} else if ( ! strcasecmp ( ton_string , " local " ) ) {
* target = ZAP_TON_SUBSCRIBER_NUMBER ;
} else if ( ! strcasecmp ( ton_string , " unknown " ) ) {
* target = ZAP_TON_UNKNOWN ;
} else {
zap_log ( ZAP_LOG_WARNING , " Invalid TON value (%s) \n " , ton_string ) ;
* target = ZAP_TON_UNKNOWN ;
}
}
2007-05-26 00:45:31 -04:00
2007-06-11 14:15:09 -04:00
static switch_core_session_t * zap_channel_get_session ( zap_channel_t * channel , int32_t id )
{
switch_core_session_t * session = NULL ;
if ( id > ZAP_MAX_TOKENS ) {
return NULL ;
}
2009-10-23 12:03:57 -04:00
if ( ! zstr ( channel - > tokens [ id ] ) ) {
2008-01-09 19:47:04 -05:00
if ( ! ( session = switch_core_session_locate ( channel - > tokens [ id ] ) ) ) {
zap_channel_clear_token ( channel , channel - > tokens [ id ] ) ;
}
2007-06-11 14:15:09 -04:00
}
return session ;
}
2009-09-06 10:43:58 -04:00
static const char * zap_channel_get_uuid ( zap_channel_t * channel , int32_t id )
{
if ( id > ZAP_MAX_TOKENS ) {
return NULL ;
}
2009-10-23 12:03:57 -04:00
if ( ! zstr ( channel - > tokens [ id ] ) ) {
2009-09-06 10:43:58 -04:00
return channel - > tokens [ id ] ;
}
return NULL ;
}
2007-06-11 14:15:09 -04:00
2008-05-01 12:41:10 -04:00
static void stop_hold ( switch_core_session_t * session_a , const char * uuid )
2008-01-09 19:47:04 -05:00
{
switch_core_session_t * session ;
2008-05-01 12:41:10 -04:00
switch_channel_t * channel , * channel_a ;
;
2008-01-09 19:47:04 -05:00
if ( ! uuid ) {
return ;
}
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2008-05-01 12:41:10 -04:00
if ( switch_channel_test_flag ( channel , CF_HOLD ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_unhold ( session ) ;
switch_channel_clear_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_clear_flag ( channel_a , CF_HOLD ) ;
} else {
switch_channel_stop_broadcast ( channel ) ;
2008-09-09 15:17:38 -04:00
switch_channel_wait_for_flag ( channel , CF_BROADCAST , SWITCH_FALSE , 2000 , NULL ) ;
2008-05-01 12:41:10 -04:00
}
2008-04-30 11:17:55 -04:00
2008-01-09 19:47:04 -05:00
switch_core_session_rwunlock ( session ) ;
}
}
2008-05-01 12:41:10 -04:00
static void start_hold ( zap_channel_t * zchan , switch_core_session_t * session_a , const char * uuid , const char * stream )
2008-01-09 19:47:04 -05:00
{
switch_core_session_t * session ;
2008-05-01 12:41:10 -04:00
switch_channel_t * channel , * channel_a ;
2008-01-09 19:47:04 -05:00
if ( ! uuid ) {
return ;
}
2008-05-01 12:41:10 -04:00
2008-01-09 19:47:04 -05:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2009-10-23 12:03:57 -04:00
if ( zstr ( stream ) ) {
2008-05-01 12:41:10 -04:00
if ( ! strcasecmp ( globals . hold_music , " indicate_hold " ) ) {
stream = " indicate_hold " ;
}
if ( ! strcasecmp ( SPAN_CONFIG [ zchan - > span - > span_id ] . hold_music , " indicate_hold " ) ) {
stream = " indicate_hold " ;
}
}
2009-10-23 12:03:57 -04:00
if ( zstr ( stream ) ) {
2008-05-01 12:41:10 -04:00
stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ;
}
2009-10-23 12:03:57 -04:00
if ( zstr ( stream ) ) {
2008-05-01 12:41:10 -04:00
stream = SPAN_CONFIG [ zchan - > span - > span_id ] . hold_music ;
}
2009-10-23 12:03:57 -04:00
if ( zstr ( stream ) ) {
2008-05-01 12:41:10 -04:00
stream = globals . hold_music ;
}
2008-01-09 19:47:04 -05:00
2009-10-23 12:03:57 -04:00
if ( zstr ( stream ) & & ! ( stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ) ) {
2008-04-30 11:17:55 -04:00
stream = globals . hold_music ;
2008-01-09 19:47:04 -05:00
}
2009-10-23 12:03:57 -04:00
if ( ! zstr ( stream ) ) {
2008-05-01 12:41:10 -04:00
if ( ! strcasecmp ( stream , " indicate_hold " ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_hold_uuid ( uuid , NULL , 0 ) ;
switch_channel_set_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_set_flag ( channel_a , CF_HOLD ) ;
} else {
switch_ivr_broadcast ( switch_core_session_get_uuid ( session ) , stream , SMF_ECHO_ALEG | SMF_LOOP ) ;
}
2008-01-09 19:47:04 -05:00
}
switch_core_session_rwunlock ( session ) ;
}
}
static void cycle_foreground ( zap_channel_t * zchan , int flash , const char * bcast ) {
2007-06-11 14:15:09 -04:00
uint32_t i = 0 ;
switch_core_session_t * session ;
switch_channel_t * channel ;
private_t * tech_pvt ;
2008-01-09 19:47:04 -05:00
2007-06-11 14:15:09 -04:00
for ( i = 0 ; i < zchan - > token_count ; i + + ) {
if ( ( session = zap_channel_get_session ( zchan , i ) ) ) {
2008-01-09 19:47:04 -05:00
const char * buuid ;
2007-06-11 14:15:09 -04:00
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
2008-01-09 19:47:04 -05:00
buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2007-06-11 14:15:09 -04:00
if ( zchan - > token_count = = 1 & & flash ) {
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2008-05-01 12:41:10 -04:00
stop_hold ( session , buuid ) ;
2007-06-11 14:15:09 -04:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2008-05-01 12:41:10 -04:00
start_hold ( zchan , session , buuid , bcast ) ;
2007-06-11 14:15:09 -04:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
} else if ( i ) {
2008-05-01 12:41:10 -04:00
start_hold ( zchan , session , buuid , bcast ) ;
2007-06-11 14:15:09 -04:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2008-05-01 12:41:10 -04:00
stop_hold ( session , buuid ) ;
2007-06-11 14:15:09 -04:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
switch_channel_mark_answered ( channel ) ;
}
}
switch_core_session_rwunlock ( session ) ;
}
}
}
2007-05-26 00:45:31 -04:00
static switch_status_t tech_init ( private_t * tech_pvt , switch_core_session_t * session , zap_channel_t * zchan )
{
2009-01-13 17:45:09 -05:00
const char * dname = NULL ;
2007-05-26 00:45:31 -04:00
uint32_t interval = 0 , srate = 8000 ;
zap_codec_t codec ;
tech_pvt - > zchan = zchan ;
tech_pvt - > read_frame . data = tech_pvt - > databuf ;
tech_pvt - > read_frame . buflen = sizeof ( tech_pvt - > databuf ) ;
2007-05-27 14:14:49 -04:00
tech_pvt - > cng_frame . data = tech_pvt - > cng_databuf ;
tech_pvt - > cng_frame . buflen = sizeof ( tech_pvt - > cng_databuf ) ;
2007-11-07 19:50:28 -05:00
tech_pvt - > cng_frame . flags = SFF_CNG ;
2008-01-09 19:47:04 -05:00
tech_pvt - > cng_frame . codec = & tech_pvt - > read_codec ;
2007-05-27 14:14:49 -04:00
memset ( tech_pvt - > cng_frame . data , 255 , tech_pvt - > cng_frame . buflen ) ;
2007-05-26 00:45:31 -04:00
switch_mutex_init ( & tech_pvt - > mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
switch_core_session_set_private ( session , tech_pvt ) ;
tech_pvt - > session = session ;
2009-09-14 17:19:07 -04:00
if ( ZAP_SUCCESS ! = zap_channel_command ( zchan , ZAP_COMMAND_GET_INTERVAL , & interval ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to retrieve channel interval. \n " ) ;
return SWITCH_STATUS_GENERR ;
}
if ( ZAP_SUCCESS ! = zap_channel_command ( zchan , ZAP_COMMAND_GET_CODEC , & codec ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Failed to retrieve channel codec. \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2007-05-26 00:45:31 -04:00
switch ( codec ) {
case ZAP_CODEC_ULAW :
{
dname = " PCMU " ;
}
break ;
case ZAP_CODEC_ALAW :
{
dname = " PCMA " ;
}
break ;
case ZAP_CODEC_SLIN :
{
dname = " L16 " ;
}
break ;
2008-01-08 18:33:07 -05:00
default :
2009-09-14 17:19:07 -04:00
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid codec value retrieved from channel, codec value: %d \n " , codec ) ;
return SWITCH_STATUS_GENERR ;
}
2007-05-26 00:45:31 -04:00
}
if ( switch_core_codec_init ( & tech_pvt - > read_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
return SWITCH_STATUS_GENERR ;
} else {
if ( switch_core_codec_init ( & tech_pvt - > write_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
return SWITCH_STATUS_GENERR ;
}
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Set codec %s %dms \n " , dname , interval ) ;
switch_core_session_set_read_codec ( tech_pvt - > session , & tech_pvt - > read_codec ) ;
switch_core_session_set_write_codec ( tech_pvt - > session , & tech_pvt - > write_codec ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_CODEC ) ;
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
2008-10-17 19:00:47 -04:00
switch_set_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 00:45:31 -04:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_init ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt = NULL ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 00:45:31 -04:00
2008-05-08 16:27:31 -04:00
/* Move channel's state machine to ROUTING */
2008-05-05 11:47:44 -04:00
switch_channel_set_state ( channel , CS_ROUTING ) ;
2007-05-26 00:45:31 -04:00
switch_mutex_lock ( globals . mutex ) ;
globals . calls + + ;
switch_mutex_unlock ( globals . mutex ) ;
2008-03-31 20:38:40 -04:00
zap_channel_init ( tech_pvt - > zchan ) ;
2008-10-03 17:03:21 -04:00
//switch_channel_set_flag(channel, CF_ACCEPT_CNG);
2008-10-03 14:15:04 -04:00
2007-05-26 00:45:31 -04:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 11:47:44 -04:00
static switch_status_t channel_on_routing ( switch_core_session_t * session )
2007-05-26 00:45:31 -04:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2008-06-05 10:09:53 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL ROUTING \n " , switch_channel_get_name ( channel ) ) ;
2007-05-26 00:45:31 -04:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_execute ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL EXECUTE \n " , switch_channel_get_name ( channel ) ) ;
return SWITCH_STATUS_SUCCESS ;
}
2009-04-14 15:03:03 -04:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session )
{
private_t * tech_pvt = NULL ;
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 00:45:31 -04:00
static switch_status_t channel_on_hangup ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-01-29 17:15:05 -05:00
if ( ! tech_pvt - > zchan ) {
goto end ;
}
2007-06-11 14:15:09 -04:00
zap_channel_clear_token ( tech_pvt - > zchan , switch_core_session_get_uuid ( session ) ) ;
2007-05-26 00:45:31 -04:00
2007-05-27 10:58:01 -04:00
switch ( tech_pvt - > zchan - > type ) {
case ZAP_CHAN_TYPE_FXO :
2008-09-16 22:21:28 -04:00
case ZAP_CHAN_TYPE_EM :
2009-08-19 17:47:56 -04:00
case ZAP_CHAN_TYPE_CAS :
2007-05-31 16:15:16 -04:00
{
2007-11-16 20:39:28 -05:00
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_HANGUP ) ;
2007-05-31 16:15:16 -04:00
}
break ;
2007-05-27 10:58:01 -04:00
case ZAP_CHAN_TYPE_FXS :
{
2007-11-16 20:39:28 -05:00
if ( tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_BUSY & & tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_DOWN ) {
2007-06-11 14:15:09 -04:00
if ( tech_pvt - > zchan - > token_count ) {
2008-01-09 19:47:04 -05:00
cycle_foreground ( tech_pvt - > zchan , 0 , NULL ) ;
2007-06-11 14:15:09 -04:00
} else {
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_HANGUP ) ;
}
2007-05-27 10:58:01 -04:00
}
}
break ;
2007-06-12 23:37:55 -04:00
case ZAP_CHAN_TYPE_B :
{
2009-12-03 14:06:27 -05:00
if ( tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_DOWN ) {
if ( tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_TERMINATING ) {
tech_pvt - > zchan - > caller_data . hangup_cause = switch_channel_get_cause_q850 ( channel ) ;
if ( tech_pvt - > zchan - > caller_data . hangup_cause < 1 | | tech_pvt - > zchan - > caller_data . hangup_cause > 127 ) {
tech_pvt - > zchan - > caller_data . hangup_cause = ZAP_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-08-11 12:09:39 -04:00
}
2007-06-12 23:37:55 -04:00
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_HANGUP ) ;
}
}
break ;
2007-05-27 10:58:01 -04:00
default :
{
2009-09-22 11:45:41 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Unhandled channel type %d for channel %s \n " , tech_pvt - > zchan - > type ,
switch_channel_get_name ( channel ) ) ;
2007-05-27 10:58:01 -04:00
}
break ;
2007-05-26 00:45:31 -04:00
}
2010-01-29 17:15:05 -05:00
end :
2007-05-27 10:58:01 -04:00
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 00:45:31 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL HANGUP \n " , switch_channel_get_name ( channel ) ) ;
switch_mutex_lock ( globals . mutex ) ;
globals . calls - - ;
if ( globals . calls < 0 ) {
globals . calls = 0 ;
}
switch_mutex_unlock ( globals . mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( sig ) {
case SWITCH_SIG_KILL :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2008-10-17 19:00:47 -04:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-05-26 00:45:31 -04:00
break ;
case SWITCH_SIG_BREAK :
switch_set_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 11:47:44 -04:00
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session )
2007-05-26 00:45:31 -04:00
{
2008-05-05 11:47:44 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL EXCHANGE_MEDIA \n " ) ;
2007-05-26 00:45:31 -04:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 11:47:44 -04:00
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session )
2007-05-26 00:45:31 -04:00
{
2008-05-05 11:47:44 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL SOFT_EXECUTE \n " ) ;
2007-05-26 00:45:31 -04:00
return SWITCH_STATUS_SUCCESS ;
}
2007-12-21 21:16:03 -05:00
static switch_status_t channel_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2007-05-26 00:45:31 -04:00
{
private_t * tech_pvt = NULL ;
2007-12-21 21:16:03 -05:00
char tmp [ 2 ] = " " ;
2007-05-26 00:45:31 -04:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2007-12-21 21:16:03 -05:00
tmp [ 0 ] = dtmf - > digit ;
zap_channel_command ( tech_pvt - > zchan , ZAP_COMMAND_SEND_DTMF , tmp ) ;
2007-05-26 00:45:31 -04:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-08 16:27:31 -04:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 00:45:31 -04:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2008-01-09 20:15:04 -05:00
zap_size_t len ;
2007-05-26 00:45:31 -04:00
zap_wait_flag_t wflags = ZAP_READ ;
2007-05-27 01:23:28 -04:00
char dtmf [ 128 ] = " " ;
2007-05-26 00:45:31 -04:00
zap_status_t status ;
2008-05-08 16:27:31 -04:00
int total_to ;
2007-05-31 16:15:16 -04:00
int chunk , do_break = 0 ;
2007-05-26 00:45:31 -04:00
2009-02-07 18:14:25 -05:00
2007-05-26 00:45:31 -04:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2008-01-25 11:42:06 -05:00
2010-02-01 18:26:34 -05:00
2007-05-26 00:45:31 -04:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
return SWITCH_STATUS_FALSE ;
}
2007-05-26 00:45:31 -04:00
2009-05-26 17:47:48 -04:00
/* Digium Cards sometimes timeout several times in a row here.
Yes , we support digium cards , ain ' t we nice . . . . . . .
6 double length intervals should compensate */
2007-05-30 22:41:50 -04:00
chunk = tech_pvt - > zchan - > effective_interval * 2 ;
2009-05-26 17:47:48 -04:00
total_to = chunk * 6 ;
2007-05-31 16:15:16 -04:00
2007-05-30 22:41:50 -04:00
top :
2007-05-31 16:15:16 -04:00
2008-05-08 16:27:31 -04:00
if ( switch_channel_test_flag ( channel , CF_SUSPEND ) ) {
do_break = 1 ;
}
2007-05-31 16:15:16 -04:00
if ( switch_test_flag ( tech_pvt , TFLAG_BREAK ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
do_break = 1 ;
}
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) | | do_break ) {
2007-05-27 14:14:49 -04:00
switch_yield ( tech_pvt - > zchan - > effective_interval * 1000 ) ;
tech_pvt - > cng_frame . datalen = tech_pvt - > zchan - > packet_len ;
tech_pvt - > cng_frame . samples = tech_pvt - > cng_frame . datalen ;
2008-10-17 19:00:47 -04:00
tech_pvt - > cng_frame . flags = SFF_CNG ;
* frame = & tech_pvt - > cng_frame ;
2007-05-27 14:14:49 -04:00
if ( tech_pvt - > zchan - > effective_codec = = ZAP_CODEC_SLIN ) {
tech_pvt - > cng_frame . samples / = 2 ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-27 10:58:01 -04:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2007-11-16 20:39:28 -05:00
goto fail ;
2007-05-26 00:45:31 -04:00
}
2007-11-16 20:39:28 -05:00
wflags = ZAP_READ ;
2007-05-30 22:41:50 -04:00
status = zap_channel_wait ( tech_pvt - > zchan , & wflags , chunk ) ;
2007-11-16 20:39:28 -05:00
2007-05-26 00:45:31 -04:00
if ( status = = ZAP_FAIL ) {
2007-11-16 20:39:28 -05:00
goto fail ;
2007-05-26 00:45:31 -04:00
}
2007-05-30 22:41:50 -04:00
2007-05-26 00:45:31 -04:00
if ( status = = ZAP_TIMEOUT ) {
2008-05-08 16:27:31 -04:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2007-05-30 22:41:50 -04:00
total_to - = chunk ;
if ( total_to < = 0 ) {
2007-11-16 20:39:28 -05:00
goto fail ;
2007-05-30 22:41:50 -04:00
}
}
2007-05-31 16:15:16 -04:00
2007-05-30 22:41:50 -04:00
goto top ;
2007-05-26 00:45:31 -04:00
}
if ( ! ( wflags & ZAP_READ ) ) {
2007-11-16 20:39:28 -05:00
goto fail ;
2007-05-26 00:45:31 -04:00
}
len = tech_pvt - > read_frame . buflen ;
if ( zap_channel_read ( tech_pvt - > zchan , tech_pvt - > read_frame . data , & len ) ! = ZAP_SUCCESS ) {
2007-11-16 20:39:28 -05:00
goto fail ;
2007-05-26 00:45:31 -04:00
}
* frame = & tech_pvt - > read_frame ;
2009-03-06 13:17:15 -05:00
tech_pvt - > read_frame . datalen = ( uint32_t ) len ;
2007-05-26 00:45:31 -04:00
tech_pvt - > read_frame . samples = tech_pvt - > read_frame . datalen ;
if ( tech_pvt - > zchan - > effective_codec = = ZAP_CODEC_SLIN ) {
tech_pvt - > read_frame . samples / = 2 ;
}
2010-02-18 13:55:03 -05:00
while ( zap_channel_dequeue_dtmf ( tech_pvt - > zchan , dtmf , sizeof ( dtmf ) ) ) {
2007-12-21 21:16:03 -05:00
switch_dtmf_t _dtmf = { 0 , SWITCH_DEFAULT_DTMF_DURATION } ;
2008-01-12 01:11:48 -05:00
char * p ;
for ( p = dtmf ; p & & * p ; p + + ) {
if ( is_dtmf ( * p ) ) {
_dtmf . digit = * p ;
zap_log ( ZAP_LOG_DEBUG , " queue DTMF [%c] \n " , * p ) ;
switch_channel_queue_dtmf ( channel , & _dtmf ) ;
}
}
2007-05-26 00:45:31 -04:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-16 20:39:28 -05:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 00:45:31 -04:00
}
2008-05-08 16:27:31 -04:00
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 00:45:31 -04:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
zap_size_t len ;
2008-10-03 14:15:04 -04:00
unsigned char data [ SWITCH_RECOMMENDED_BUFFER_SIZE ] = { 0 } ;
2009-07-24 12:01:33 -04:00
zap_wait_flag_t wflags = ZAP_WRITE ;
zap_status_t status ;
2007-05-26 00:45:31 -04:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-01 10:36:32 -05:00
if ( ! tech_pvt - > zchan ) {
return SWITCH_STATUS_FALSE ;
}
2007-05-26 00:45:31 -04:00
2008-10-17 19:00:47 -04:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
return SWITCH_STATUS_FALSE ;
}
2007-05-27 14:14:49 -04:00
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 00:45:31 -04:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2007-11-16 20:39:28 -05:00
goto fail ;
2007-05-26 00:45:31 -04:00
}
2007-05-30 22:41:50 -04:00
2008-10-03 14:15:04 -04:00
if ( switch_test_flag ( frame , SFF_CNG ) ) {
frame - > data = data ;
frame - > buflen = sizeof ( data ) ;
2008-10-20 14:10:37 -04:00
if ( ( frame - > datalen = tech_pvt - > write_codec . implementation - > encoded_bytes_per_packet ) > frame - > buflen ) {
2008-10-03 14:15:04 -04:00
goto fail ;
}
memset ( data , 255 , frame - > datalen ) ;
}
2009-07-24 12:01:33 -04:00
wflags = ZAP_WRITE ;
2010-02-18 13:55:03 -05:00
status = zap_channel_wait ( tech_pvt - > zchan , & wflags , tech_pvt - > zchan - > effective_interval * 10 ) ;
2009-07-24 12:01:33 -04:00
if ( ! ( wflags & ZAP_WRITE ) ) {
2010-02-18 13:55:03 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Dropping frame! (write not ready) \n " ) ;
return SWITCH_STATUS_SUCCESS ;
2009-07-24 12:01:33 -04:00
}
2007-05-26 00:45:31 -04:00
len = frame - > datalen ;
2007-05-31 20:31:50 -04:00
if ( zap_channel_write ( tech_pvt - > zchan , frame - > data , frame - > buflen , & len ) ! = ZAP_SUCCESS ) {
2007-05-30 22:41:50 -04:00
if ( + + tech_pvt - > wr_error > 10 ) {
2007-11-16 20:39:28 -05:00
goto fail ;
2007-05-30 22:41:50 -04:00
}
2007-05-31 16:15:16 -04:00
} else {
tech_pvt - > wr_error = 0 ;
2007-05-26 00:45:31 -04:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-16 20:39:28 -05:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 00:45:31 -04:00
}
2009-08-19 17:47:56 -04:00
static switch_status_t channel_receive_message_cas ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2009-08-19 17:47:56 -04:00
zap_log ( ZAP_LOG_DEBUG , " Got Freeswitch message in R2 channel %d [%d] \n " , tech_pvt - > zchan - > physical_chan_id ,
msg - > message_id ) ;
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_RINGING :
{
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2009-08-19 17:47:56 -04:00
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
} else {
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
}
}
break ;
case SWITCH_MESSAGE_INDICATE_PROGRESS :
{
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2009-08-19 17:47:56 -04:00
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_MEDIA ) ;
} else {
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS_MEDIA ) ;
}
}
break ;
case SWITCH_MESSAGE_INDICATE_ANSWER :
{
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2009-08-19 17:47:56 -04:00
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_ANSWERED ) ;
} else {
/* lets make the ozmod_r2 module life easier by moving thru each
* state waiting for completion , clumsy , but does the job
*/
if ( tech_pvt - > zchan - > state < ZAP_CHANNEL_STATE_PROGRESS ) {
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
}
if ( tech_pvt - > zchan - > state < ZAP_CHANNEL_STATE_PROGRESS_MEDIA ) {
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS_MEDIA ) ;
}
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_UP ) ;
}
}
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2008-08-22 12:55:01 -04:00
2007-05-31 16:15:16 -04:00
static switch_status_t channel_receive_message_b ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
2007-06-12 23:37:55 -04:00
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-01 10:36:32 -05:00
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-01-08 16:02:50 -05:00
if ( tech_pvt - > zchan - > state = = ZAP_CHANNEL_STATE_TERMINATING ) {
zap_mutex_unlock ( tech_pvt - > zchan - > mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-06-12 23:37:55 -04:00
switch ( msg - > message_id ) {
2007-06-16 00:39:15 -04:00
case SWITCH_MESSAGE_INDICATE_RINGING :
2007-06-16 09:46:32 -04:00
{
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-01-08 16:02:50 -05:00
zap_set_flag ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
2008-03-19 16:45:57 -04:00
} else {
2010-01-08 16:02:50 -05:00
zap_set_state_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
2007-06-16 09:46:32 -04:00
}
2007-06-16 00:39:15 -04:00
}
2007-06-16 09:46:32 -04:00
break ;
2007-06-12 23:37:55 -04:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
2007-06-16 09:46:32 -04:00
{
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-01-08 16:02:50 -05:00
zap_set_flag ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
zap_set_flag ( tech_pvt - > zchan , ZAP_CHANNEL_MEDIA ) ;
2008-03-19 16:45:57 -04:00
} else {
2008-09-07 13:39:36 -04:00
/* Don't skip messages in the ISDN call setup
* TODO : make the isdn stack smart enough to handle that itself
* until then , this is here for safety . . .
*/
if ( tech_pvt - > zchan - > state < ZAP_CHANNEL_STATE_PROGRESS ) {
2010-01-08 16:02:50 -05:00
zap_set_state_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
2008-09-07 13:39:36 -04:00
}
2010-01-08 16:02:50 -05:00
zap_set_state_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS_MEDIA ) ;
2007-06-16 09:46:32 -04:00
}
2007-06-16 00:39:15 -04:00
}
2007-06-16 09:46:32 -04:00
break ;
2007-06-12 23:37:55 -04:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2007-06-16 09:46:32 -04:00
{
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2010-01-08 16:02:50 -05:00
zap_set_flag ( tech_pvt - > zchan , ZAP_CHANNEL_ANSWERED ) ;
2008-03-19 16:45:57 -04:00
} else {
2008-09-07 13:39:36 -04:00
/* Don't skip messages in the ISDN call setup
* TODO : make the isdn stack smart enough to handle that itself
* until then , this is here for safety . . .
*/
if ( tech_pvt - > zchan - > state < ZAP_CHANNEL_STATE_PROGRESS ) {
2010-01-08 16:02:50 -05:00
zap_set_state_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
2008-09-07 13:39:36 -04:00
}
if ( tech_pvt - > zchan - > state < ZAP_CHANNEL_STATE_PROGRESS_MEDIA ) {
2010-01-08 16:02:50 -05:00
zap_set_state_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS_MEDIA ) ;
2008-09-07 13:39:36 -04:00
}
2010-01-08 16:02:50 -05:00
zap_set_state_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_UP ) ;
2007-06-16 09:46:32 -04:00
}
2007-06-12 23:37:55 -04:00
}
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
2007-05-31 16:15:16 -04:00
}
static switch_status_t channel_receive_message_fxo ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2007-05-31 16:15:16 -04:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_OUTBOUND ) {
2008-03-19 16:45:57 -04:00
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_ANSWERED ) ;
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_MEDIA ) ;
} else {
2007-05-31 16:15:16 -04:00
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_UP ) ;
}
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_receive_message_fxs ( switch_core_session_t * session , switch_core_session_message_t * msg )
2007-05-26 00:45:31 -04:00
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2007-05-26 00:45:31 -04:00
switch ( msg - > message_id ) {
2007-05-31 16:15:16 -04:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
2007-05-26 00:45:31 -04:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2008-03-19 16:45:57 -04:00
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_ANSWERED ) ;
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_MEDIA ) ;
2007-05-31 16:15:16 -04:00
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_UP ) ;
2008-09-26 13:29:48 -04:00
switch_channel_mark_answered ( channel ) ;
2007-05-31 16:15:16 -04:00
}
2007-05-26 00:45:31 -04:00
break ;
case SWITCH_MESSAGE_INDICATE_RINGING :
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2008-09-26 13:29:48 -04:00
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) & &
! switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) & &
! switch_channel_test_flag ( channel , CF_RING_READY )
) {
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_RING ) ;
switch_channel_mark_ring_ready ( channel ) ;
}
2008-09-26 13:09:10 -04:00
}
2007-05-26 00:45:31 -04:00
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-31 16:15:16 -04:00
static switch_status_t channel_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
private_t * tech_pvt ;
2008-02-26 11:55:54 -05:00
switch_status_t status ;
2009-09-14 10:26:31 -04:00
switch_channel_t * channel ;
const char * var ;
2010-02-01 13:16:13 -05:00
zap_channel_t * zchan = NULL ;
2009-09-14 10:26:31 -04:00
2007-05-31 16:15:16 -04:00
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2009-09-14 10:26:31 -04:00
channel = switch_core_session_get_channel ( session ) ;
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
2010-02-01 13:16:13 -05:00
if ( ! ( zchan = tech_pvt - > zchan ) ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
return SWITCH_STATUS_FALSE ;
}
zap_mutex_lock ( zchan - > mutex ) ;
if ( ! tech_pvt - > zchan ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_LOSE_RACE ) ;
status = SWITCH_STATUS_FALSE ;
goto end ;
}
2009-09-14 10:26:31 -04:00
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
2010-12-15 21:59:33 -05:00
if ( switch_channel_direction ( channel ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2009-09-14 10:26:31 -04:00
if ( ( var = switch_channel_get_variable ( channel , " openzap_pre_buffer_size " ) ) ) {
int tmp = atoi ( var ) ;
if ( tmp > - 1 ) {
zap_channel_command ( tech_pvt - > zchan , ZAP_COMMAND_SET_PRE_BUFFER_SIZE , & tmp ) ;
}
}
}
break ;
2009-10-22 10:55:15 -04:00
case SWITCH_MESSAGE_INDICATE_UUID_CHANGE :
{
zap_channel_replace_token ( tech_pvt - > zchan , msg - > string_array_arg [ 0 ] , msg - > string_array_arg [ 1 ] ) ;
}
break ;
2009-09-14 10:26:31 -04:00
default :
break ;
}
2007-05-31 16:15:16 -04:00
switch ( tech_pvt - > zchan - > type ) {
case ZAP_CHAN_TYPE_FXS :
2008-09-16 22:21:28 -04:00
case ZAP_CHAN_TYPE_EM :
2008-02-26 11:55:54 -05:00
status = channel_receive_message_fxs ( session , msg ) ;
2008-02-26 17:30:54 -05:00
break ;
2007-05-31 16:15:16 -04:00
case ZAP_CHAN_TYPE_FXO :
2008-02-26 11:55:54 -05:00
status = channel_receive_message_fxo ( session , msg ) ;
2008-02-26 17:30:54 -05:00
break ;
2007-05-31 16:15:16 -04:00
case ZAP_CHAN_TYPE_B :
2008-02-26 11:55:54 -05:00
status = channel_receive_message_b ( session , msg ) ;
2009-08-19 17:47:56 -04:00
break ;
case ZAP_CHAN_TYPE_CAS :
status = channel_receive_message_cas ( session , msg ) ;
break ;
2007-05-31 16:15:16 -04:00
default :
2008-02-26 11:55:54 -05:00
status = SWITCH_STATUS_FALSE ;
2008-02-26 17:30:54 -05:00
break ;
2007-05-31 16:15:16 -04:00
}
2008-02-26 11:55:54 -05:00
2010-02-01 13:16:13 -05:00
end :
zap_mutex_unlock ( zchan - > mutex ) ;
2008-02-26 11:55:54 -05:00
return status ;
2007-05-31 16:15:16 -04:00
}
2007-10-29 14:10:25 -04:00
switch_state_handler_table_t openzap_state_handlers = {
2007-05-26 00:45:31 -04:00
/*.on_init */ channel_on_init ,
2008-05-05 11:47:44 -04:00
/*.on_routing */ channel_on_routing ,
2007-05-26 00:45:31 -04:00
/*.on_execute */ channel_on_execute ,
/*.on_hangup */ channel_on_hangup ,
2008-05-05 11:47:44 -04:00
/*.on_exchange_media */ channel_on_exchange_media ,
2009-04-14 15:03:03 -04:00
/*.on_soft_execute */ channel_on_soft_execute ,
/*.on_consume_media */ NULL ,
/*.on_hibernate */ NULL ,
/*.on_reset */ NULL ,
/*.on_park*/ NULL ,
/*.on_reporting*/ NULL ,
/*.on_destroy*/ channel_on_destroy
2007-05-26 00:45:31 -04:00
} ;
2007-10-29 14:10:25 -04:00
switch_io_routines_t openzap_io_routines = {
2007-05-26 00:45:31 -04:00
/*.outgoing_channel */ channel_outgoing_channel ,
/*.read_frame */ channel_read_frame ,
/*.write_frame */ channel_write_frame ,
/*.kill_channel */ channel_kill_channel ,
/*.send_dtmf */ channel_send_dtmf ,
/*.receive_message*/ channel_receive_message
} ;
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel ' s pool !
*/
2008-05-15 15:43:58 -04:00
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
2007-05-26 00:45:31 -04:00
switch_caller_profile_t * outbound_profile ,
2008-01-08 18:33:07 -05:00
switch_core_session_t * * new_session , switch_memory_pool_t * * pool ,
2009-11-19 21:17:21 -05:00
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause )
2007-05-26 00:45:31 -04:00
{
2007-05-30 23:04:26 -04:00
2009-01-13 17:45:09 -05:00
const char * dest = NULL ;
char * data = NULL ;
2009-03-01 18:38:33 -05:00
int span_id = - 1 , chan_id = 0 ;
2007-05-30 23:04:26 -04:00
zap_channel_t * zchan = NULL ;
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
char name [ 128 ] ;
2007-05-31 16:15:16 -04:00
zap_status_t status ;
2008-01-25 10:05:37 -05:00
int direction = ZAP_TOP_DOWN ;
2008-02-28 19:21:04 -05:00
zap_caller_data_t caller_data = { { 0 } } ;
2008-10-06 11:57:11 -04:00
char * span_name = NULL ;
2008-10-06 15:13:32 -04:00
switch_event_header_t * h ;
2008-10-06 16:02:55 -04:00
char * argv [ 3 ] ;
int argc = 0 ;
2009-01-12 12:46:30 -05:00
const char * var ;
2010-03-01 18:23:51 -05:00
const char * dest_num = NULL , * callerid_num = NULL ;
2009-01-12 12:50:26 -05:00
2007-05-30 23:04:26 -04:00
if ( ! outbound_profile ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing caller profile \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2009-10-23 12:03:57 -04:00
if ( zstr ( outbound_profile - > destination_number ) ) {
2008-01-07 11:50:20 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-01-25 10:05:37 -05:00
2008-10-06 16:02:55 -04:00
data = switch_core_strdup ( outbound_profile - > pool , outbound_profile - > destination_number ) ;
2008-10-06 11:57:11 -04:00
2010-03-01 18:23:51 -05:00
if ( ! zstr ( outbound_profile - > destination_number ) ) {
2010-03-01 19:15:52 -05:00
dest_num = switch_sanitize_number ( switch_core_strdup ( outbound_profile - > pool , outbound_profile - > destination_number ) ) ;
2010-03-01 18:23:51 -05:00
}
if ( ! zstr ( outbound_profile - > caller_id_number ) ) {
2010-03-01 19:15:52 -05:00
callerid_num = switch_sanitize_number ( switch_core_strdup ( outbound_profile - > pool , outbound_profile - > caller_id_number ) ) ;
2010-03-01 18:23:51 -05:00
}
2010-01-25 12:24:52 -05:00
2010-03-01 18:23:51 -05:00
if ( ! zstr ( callerid_num ) & & ! strcmp ( callerid_num , " 0000000000 " ) ) {
callerid_num = NULL ;
}
2008-10-08 21:18:40 -04:00
if ( ( argc = switch_separate_string ( data , ' / ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) < 2 ) {
2008-10-06 16:02:55 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-10-06 11:57:11 -04:00
2008-10-06 16:02:55 -04:00
if ( switch_is_number ( argv [ 0 ] ) ) {
span_id = atoi ( argv [ 0 ] ) ;
} else {
span_name = argv [ 0 ] ;
}
if ( * argv [ 1 ] = = ' A ' ) {
direction = ZAP_BOTTOM_UP ;
} else if ( * argv [ 1 ] = = ' a ' ) {
direction = ZAP_TOP_DOWN ;
} else {
chan_id = atoi ( argv [ 1 ] ) ;
2007-05-30 23:04:26 -04:00
}
2008-02-02 11:48:20 -05:00
2008-10-08 21:18:40 -04:00
if ( ! ( dest = argv [ 2 ] ) ) {
dest = " " ;
}
2008-10-06 16:02:55 -04:00
2009-03-01 18:38:33 -05:00
if ( span_id = = 0 & & chan_id ! = 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Span 0 is used to pick the first available span, selecting a channel is not supported (and doesn't make sense) \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2009-10-23 12:03:57 -04:00
if ( span_id = = - 1 & & ! zstr ( span_name ) ) {
2008-10-06 11:57:11 -04:00
zap_span_t * span ;
zap_status_t zstatus = zap_span_find_by_name ( span_name , & span ) ;
if ( zstatus = = ZAP_SUCCESS & & span ) {
span_id = span - > span_id ;
}
}
2009-03-01 18:38:33 -05:00
if ( span_id = = - 1 ) {
2007-05-30 23:04:26 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing span \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-01-25 10:05:37 -05:00
if ( chan_id < 0 ) {
direction = ZAP_BOTTOM_UP ;
chan_id = 0 ;
}
2008-02-29 19:48:36 -05:00
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_SCREEN ) ) {
caller_data . screen = 1 ;
}
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_HIDE_NUMBER ) ) {
caller_data . pres = 1 ;
}
2009-10-23 12:03:57 -04:00
if ( ! zstr ( dest ) ) {
2008-02-29 19:48:36 -05:00
zap_set_string ( caller_data . ani . digits , dest ) ;
}
2009-01-12 12:46:30 -05:00
2011-02-02 17:05:51 -05:00
if ( ( var = switch_event_get_header ( var_event , " openzap_outbound_ton " ) ) ) {
2011-02-01 17:35:53 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Setting TON to: %s \n " , var ) ;
zap_set_ton ( var , & caller_data . ani . type ) ;
2009-01-12 12:46:30 -05:00
} else {
caller_data . ani . type = outbound_profile - > destination_number_ton ;
}
2010-02-26 15:57:59 -05:00
2011-02-02 17:05:51 -05:00
if ( ( var = switch_event_get_header ( var_event , " openzap_custom_call_data " ) ) ) {
2010-05-20 16:08:22 -04:00
zap_set_string ( ( char * ) caller_data . raw_data , var ) ;
caller_data . raw_data_len = strlen ( var ) ;
}
2011-02-01 17:35:53 -05:00
2011-02-02 17:05:51 -05:00
if ( ( var = switch_event_get_header ( var_event , " openzap_outbound_npi " ) ) ) {
2011-02-01 17:35:53 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Setting NPI to: %s \n " , var ) ;
zap_set_npi ( var , & caller_data . ani . plan ) ;
} else {
caller_data . ani . plan = outbound_profile - > destination_number_numplan ;
}
2010-02-26 15:57:59 -05:00
/* blindly copy data from outbound_profile. They will be overwritten
* by calling zap_caller_data if needed after */
caller_data . cid_num . type = outbound_profile - > caller_ton ;
caller_data . cid_num . plan = outbound_profile - > caller_numplan ;
2009-01-12 13:05:22 -05:00
2010-02-26 15:57:59 -05:00
caller_data . rdnis . type = outbound_profile - > rdnis_ton ;
caller_data . rdnis . plan = outbound_profile - > rdnis_numplan ;
2008-02-29 19:48:36 -05:00
#if 0
2009-10-23 12:03:57 -04:00
if ( ! zstr ( outbound_profile - > rdnis ) ) {
2008-02-29 19:48:36 -05:00
zap_set_string ( caller_data . rdnis . digits , outbound_profile - > rdnis ) ;
}
# endif
2008-01-25 10:05:37 -05:00
2008-02-28 19:21:04 -05:00
zap_set_string ( caller_data . cid_name , outbound_profile - > caller_id_name ) ;
2010-03-01 18:23:51 -05:00
zap_set_string ( caller_data . cid_num . digits , switch_str_nil ( callerid_num ) ) ;
2008-02-28 19:21:04 -05:00
2007-05-31 16:15:16 -04:00
if ( chan_id ) {
2008-01-25 10:05:37 -05:00
status = zap_channel_open ( span_id , chan_id , & zchan ) ;
2007-05-31 16:15:16 -04:00
} else {
2008-02-28 19:21:04 -05:00
status = zap_channel_open_any ( span_id , direction , & caller_data , & zchan ) ;
2007-05-31 16:15:16 -04:00
}
2007-06-11 14:15:09 -04:00
2007-05-31 16:15:16 -04:00
if ( status ! = ZAP_SUCCESS ) {
2010-01-21 00:35:53 -05:00
if ( caller_data . hangup_cause = = SWITCH_CAUSE_NONE ) {
caller_data . hangup_cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION ;
}
return caller_data . hangup_cause ;
2007-05-30 23:04:26 -04:00
}
2009-09-14 10:26:31 -04:00
if ( ( var = switch_event_get_header ( var_event , " openzap_pre_buffer_size " ) ) ) {
int tmp = atoi ( var ) ;
if ( tmp > - 1 ) {
zap_channel_command ( zchan , ZAP_COMMAND_SET_PRE_BUFFER_SIZE , & tmp ) ;
}
}
2008-10-06 15:13:32 -04:00
zap_channel_clear_vars ( zchan ) ;
for ( h = var_event - > headers ; h ; h = h - > next ) {
if ( ! strncasecmp ( h - > name , OPENZAP_VAR_PREFIX , OPENZAP_VAR_PREFIX_LEN ) ) {
char * v = h - > name + OPENZAP_VAR_PREFIX_LEN ;
2009-10-23 12:03:57 -04:00
if ( ! zstr ( v ) ) {
2008-10-06 15:13:32 -04:00
zap_channel_add_var ( zchan , v , h - > value ) ;
}
}
}
2010-08-26 13:20:14 -04:00
if ( ( * new_session = switch_core_session_request ( openzap_endpoint_interface , SWITCH_CALL_DIRECTION_OUTBOUND , flags , pool ) ) ! = 0 ) {
2007-05-26 00:45:31 -04:00
private_t * tech_pvt ;
switch_caller_profile_t * caller_profile ;
2009-01-12 13:05:22 -05:00
switch_channel_t * channel = switch_core_session_get_channel ( * new_session ) ;
2007-05-26 00:45:31 -04:00
switch_core_session_add_stream ( * new_session , NULL ) ;
if ( ( tech_pvt = ( private_t * ) switch_core_session_alloc ( * new_session , sizeof ( private_t ) ) ) ! = 0 ) {
2007-05-30 23:04:26 -04:00
tech_init ( tech_pvt , * new_session , zchan ) ;
2007-05-26 00:45:31 -04:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Hey where is my memory pool? \n " ) ;
switch_core_session_destroy ( new_session ) ;
2007-05-30 23:04:26 -04:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto fail ;
2007-05-26 00:45:31 -04:00
}
2008-04-01 17:49:35 -04:00
snprintf ( name , sizeof ( name ) , " OpenZAP/%u:%u/%s " , zchan - > span_id , zchan - > chan_id , dest ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Connect outbound channel %s \n " , name ) ;
2007-05-30 23:04:26 -04:00
switch_channel_set_name ( channel , name ) ;
2009-03-12 11:27:29 -04:00
switch_channel_set_variable ( channel , " openzap_span_name " , zchan - > span - > name ) ;
switch_channel_set_variable_printf ( channel , " openzap_span_number " , " %d " , zchan - > span_id ) ;
switch_channel_set_variable_printf ( channel , " openzap_chan_number " , " %d " , zchan - > chan_id ) ;
2010-02-26 17:54:59 -05:00
zap_channel_set_caller_data ( zchan , & caller_data ) ;
2007-05-30 23:04:26 -04:00
caller_profile = switch_caller_profile_clone ( * new_session , outbound_profile ) ;
2010-03-01 18:23:51 -05:00
caller_profile - > destination_number = switch_core_strdup ( caller_profile - > pool , switch_str_nil ( dest_num ) ) ;
caller_profile - > caller_id_number = switch_core_strdup ( caller_profile - > pool , switch_str_nil ( callerid_num ) ) ;
2007-05-30 23:04:26 -04:00
switch_channel_set_caller_profile ( channel , caller_profile ) ;
tech_pvt - > caller_profile = caller_profile ;
2008-04-01 17:49:35 -04:00
2007-05-30 23:04:26 -04:00
2007-05-26 00:45:31 -04:00
switch_channel_set_state ( channel , CS_INIT ) ;
2007-06-11 14:15:09 -04:00
if ( zap_channel_add_token ( zchan , switch_core_session_get_uuid ( * new_session ) , zchan - > token_count ) ! = ZAP_SUCCESS ) {
2007-05-31 16:15:16 -04:00
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto fail ;
}
2007-06-11 14:15:09 -04:00
if ( zap_channel_outgoing_call ( zchan ) ! = ZAP_SUCCESS ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto fail ;
}
2008-10-31 10:30:45 -04:00
zap_channel_init ( zchan ) ;
2007-05-26 00:45:31 -04:00
return SWITCH_CAUSE_SUCCESS ;
}
2007-05-30 23:04:26 -04:00
fail :
2007-06-14 00:44:44 -04:00
2007-05-30 23:04:26 -04:00
if ( zchan ) {
zap_channel_done ( zchan ) ;
}
2007-06-14 00:44:44 -04:00
2007-05-30 23:04:26 -04:00
return cause ;
2007-05-26 00:45:31 -04:00
}
2007-05-27 10:58:01 -04:00
zap_status_t zap_channel_from_event ( zap_sigmsg_t * sigmsg , switch_core_session_t * * sp )
{
switch_core_session_t * session = NULL ;
private_t * tech_pvt = NULL ;
switch_channel_t * channel = NULL ;
char name [ 128 ] ;
2007-06-05 12:57:32 -04:00
2007-05-27 10:58:01 -04:00
* sp = NULL ;
2010-08-26 13:20:14 -04:00
if ( ! ( session = switch_core_session_request ( openzap_endpoint_interface , SWITCH_CALL_DIRECTION_INBOUND , SOF_NONE , NULL ) ) ) {
2008-05-21 12:49:22 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Initilization Error! \n " ) ;
2007-05-27 10:58:01 -04:00
return ZAP_FAIL ;
}
switch_core_session_add_stream ( session , NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_alloc ( session , sizeof ( private_t ) ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
if ( tech_init ( tech_pvt , session , sigmsg - > channel ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Initilization Error! \n " ) ;
switch_core_session_destroy ( & session ) ;
return ZAP_FAIL ;
}
2007-06-05 12:57:32 -04:00
2008-01-09 19:47:04 -05:00
* sigmsg - > channel - > caller_data . collected = ' \0 ' ;
2009-10-23 12:03:57 -04:00
if ( zstr ( sigmsg - > channel - > caller_data . cid_name ) ) {
2007-06-05 12:57:32 -04:00
switch_set_string ( sigmsg - > channel - > caller_data . cid_name , sigmsg - > channel - > chan_name ) ;
}
2009-10-23 12:03:57 -04:00
if ( zstr ( sigmsg - > channel - > caller_data . cid_num . digits ) ) {
if ( ! zstr ( sigmsg - > channel - > caller_data . ani . digits ) ) {
2008-02-29 19:48:36 -05:00
switch_set_string ( sigmsg - > channel - > caller_data . cid_num . digits , sigmsg - > channel - > caller_data . ani . digits ) ;
2007-06-05 12:57:32 -04:00
} else {
2008-02-29 19:48:36 -05:00
switch_set_string ( sigmsg - > channel - > caller_data . cid_num . digits , sigmsg - > channel - > chan_number ) ;
2007-06-05 12:57:32 -04:00
}
}
2007-11-16 20:39:28 -05:00
2007-05-27 10:58:01 -04:00
tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
" OpenZAP " ,
2007-05-31 16:15:16 -04:00
SPAN_CONFIG [ sigmsg - > channel - > span_id ] . dialplan ,
2007-06-05 12:57:32 -04:00
sigmsg - > channel - > caller_data . cid_name ,
2008-02-29 19:48:36 -05:00
sigmsg - > channel - > caller_data . cid_num . digits ,
2007-05-27 10:58:01 -04:00
NULL ,
2008-02-29 19:48:36 -05:00
sigmsg - > channel - > caller_data . ani . digits ,
2007-06-05 12:57:32 -04:00
sigmsg - > channel - > caller_data . aniII ,
2008-02-29 19:48:36 -05:00
sigmsg - > channel - > caller_data . rdnis . digits ,
2007-05-27 10:58:01 -04:00
( char * ) modname ,
2007-05-31 16:15:16 -04:00
SPAN_CONFIG [ sigmsg - > channel - > span_id ] . context ,
2008-02-29 19:48:36 -05:00
sigmsg - > channel - > caller_data . dnis . digits ) ;
2007-05-27 10:58:01 -04:00
assert ( tech_pvt - > caller_profile ! = NULL ) ;
2008-02-29 19:48:36 -05:00
if ( sigmsg - > channel - > caller_data . screen = = 1 | | sigmsg - > channel - > caller_data . screen = = 3 ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_SCREEN ) ;
}
2010-03-17 18:35:29 -04:00
tech_pvt - > caller_profile - > caller_ton = sigmsg - > channel - > caller_data . cid_num . type ;
tech_pvt - > caller_profile - > caller_numplan = sigmsg - > channel - > caller_data . cid_num . plan ;
tech_pvt - > caller_profile - > ani_ton = sigmsg - > channel - > caller_data . ani . type ;
tech_pvt - > caller_profile - > ani_numplan = sigmsg - > channel - > caller_data . ani . plan ;
tech_pvt - > caller_profile - > destination_number_ton = sigmsg - > channel - > caller_data . dnis . type ;
tech_pvt - > caller_profile - > destination_number_numplan = sigmsg - > channel - > caller_data . dnis . plan ;
tech_pvt - > caller_profile - > rdnis_ton = sigmsg - > channel - > caller_data . rdnis . type ;
tech_pvt - > caller_profile - > rdnis_numplan = sigmsg - > channel - > caller_data . rdnis . plan ;
2008-02-29 19:48:36 -05:00
if ( sigmsg - > channel - > caller_data . pres ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER ) ;
}
2008-04-01 17:49:35 -04:00
snprintf ( name , sizeof ( name ) , " OpenZAP/%u:%u/%s " , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id , tech_pvt - > caller_profile - > destination_number ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Connect inbound channel %s \n " , name ) ;
2007-05-27 10:58:01 -04:00
switch_channel_set_name ( channel , name ) ;
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
2009-03-12 11:27:29 -04:00
switch_channel_set_variable ( channel , " openzap_span_name " , sigmsg - > channel - > span - > name ) ;
switch_channel_set_variable_printf ( channel , " openzap_span_number " , " %d " , sigmsg - > channel - > span_id ) ;
switch_channel_set_variable_printf ( channel , " openzap_chan_number " , " %d " , sigmsg - > channel - > chan_id ) ;
2010-05-20 17:37:57 -04:00
if ( sigmsg - > channel - > caller_data . raw_data_len ) {
switch_channel_set_variable_printf ( channel , " openzap_custom_call_data " , " %s " , sigmsg - > channel - > caller_data . raw_data ) ;
2010-05-20 16:08:22 -04:00
}
2007-05-27 10:58:01 -04:00
switch_channel_set_state ( channel , CS_INIT ) ;
if ( switch_core_session_thread_launch ( session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error spawning thread \n " ) ;
switch_core_session_destroy ( & session ) ;
return ZAP_FAIL ;
}
2007-06-11 14:15:09 -04:00
if ( zap_channel_add_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) , 0 ) ! = ZAP_SUCCESS ) {
2008-05-21 12:49:22 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error adding token \n " ) ;
2007-05-27 14:14:49 -04:00
switch_core_session_destroy ( & session ) ;
return ZAP_FAIL ;
}
2007-05-27 10:58:01 -04:00
* sp = session ;
return ZAP_SUCCESS ;
}
2010-03-05 16:59:00 -05:00
static ZIO_SIGNAL_CB_FUNCTION ( on_common_signal )
{
switch_event_t * event = NULL ;
switch ( sigmsg - > event_id ) {
case ZAP_SIGEVENT_ALARM_CLEAR :
case ZAP_SIGEVENT_ALARM_TRAP :
{
if ( zap_channel_get_alarms ( sigmsg - > channel ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " failed to retrieve alarms \n " ) ;
return ZAP_FAIL ;
}
if ( switch_event_create ( & event , SWITCH_EVENT_TRAP ) ! = SWITCH_STATUS_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " failed to create alarms events \n " ) ;
return ZAP_FAIL ;
}
if ( sigmsg - > event_id = = ZAP_SIGEVENT_ALARM_CLEAR ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " condition " , " zap-alarm-clear " ) ;
} else {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " condition " , " zap-alarm-trap " ) ;
}
}
break ;
default :
return ZAP_SUCCESS ;
break ;
}
2010-03-05 18:01:23 -05:00
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " span-name " , " %s " , sigmsg - > channel - > span - > name ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " span-number " , " %d " , sigmsg - > channel - > span_id ) ;
switch_event_add_header ( event , SWITCH_STACK_BOTTOM , " chan-number " , " %d " , sigmsg - > channel - > chan_id ) ;
2010-03-05 16:59:00 -05:00
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_RECOVER ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " recover " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_LOOPBACK ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " loopback " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_YELLOW ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " yellow " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_RED ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " red " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_BLUE ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " blue " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_NOTOPEN ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " notopen " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_AIS ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " ais " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_RAI ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " rai " ) ;
}
if ( zap_test_alarm_flag ( sigmsg - > channel , ZAP_ALARM_GENERAL ) ) {
switch_event_add_header_string ( event , SWITCH_STACK_BOTTOM , " alarm " , " general " ) ;
}
switch_event_fire ( & event ) ;
return ZAP_BREAK ;
}
2007-05-27 14:14:49 -04:00
2010-06-27 19:31:26 -04:00
static void zap_enable_channel_dtmf ( zap_channel_t * zchan , switch_channel_t * channel )
{
if ( channel ) {
const char * var ;
if ( ( var = switch_channel_get_variable ( channel , " openzap_disable_dtmf " ) ) ) {
if ( switch_true ( var ) ) {
zap_channel_command ( zchan , ZAP_COMMAND_DISABLE_DTMF_DETECT , NULL ) ;
zap_log ( ZAP_LOG_INFO , " DTMF detection disabled in channel %d:%d \n " , zchan - > span_id , zchan - > chan_id ) ;
return ;
}
}
/* the variable is not present or has negative value then proceed to enable DTMF */
}
if ( zap_channel_command ( zchan , ZAP_COMMAND_ENABLE_DTMF_DETECT , NULL ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Failed to enable DTMF detection in channel %d:%d \n " , zchan - > span_id , zchan - > chan_id ) ;
}
}
2007-05-26 00:45:31 -04:00
static ZIO_SIGNAL_CB_FUNCTION ( on_fxo_signal )
{
2007-05-31 16:15:16 -04:00
switch_core_session_t * session = NULL ;
2007-05-31 20:31:50 -04:00
switch_channel_t * channel = NULL ;
2007-05-31 16:15:16 -04:00
zap_status_t status ;
2007-11-16 20:39:28 -05:00
zap_log ( ZAP_LOG_DEBUG , " got FXO sig %d:%d [%s] \n " , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id , zap_signal_event2str ( sigmsg - > event_id ) ) ;
2007-05-31 16:15:16 -04:00
switch ( sigmsg - > event_id ) {
2007-11-16 20:39:28 -05:00
case ZAP_SIGEVENT_PROGRESS_MEDIA :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_pre_answered ( channel ) ;
2009-08-31 20:49:10 -04:00
switch_core_session_rwunlock ( session ) ;
2007-11-16 20:39:28 -05:00
}
}
break ;
case ZAP_SIGEVENT_STOP :
{
2010-01-29 17:15:05 -05:00
private_t * tech_pvt = NULL ;
2007-11-16 20:39:28 -05:00
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-01-29 17:15:05 -05:00
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-01 18:26:34 -05:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-11-16 20:39:28 -05:00
zap_channel_clear_token ( sigmsg - > channel , 0 ) ;
channel = switch_core_session_get_channel ( session ) ;
switch_channel_hangup ( channel , sigmsg - > channel - > caller_data . hangup_cause ) ;
2008-01-08 18:33:07 -05:00
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-11-16 20:39:28 -05:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2007-05-31 20:31:50 -04:00
case ZAP_SIGEVENT_UP :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-27 19:31:26 -04:00
zap_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2007-05-31 20:31:50 -04:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2007-05-31 16:15:16 -04:00
case ZAP_SIGEVENT_START :
{
status = zap_channel_from_event ( sigmsg , & session ) ;
if ( status ! = ZAP_SUCCESS ) {
zap_set_state_locked ( sigmsg - > channel , ZAP_CHANNEL_STATE_DOWN ) ;
}
}
break ;
2008-01-08 18:33:07 -05:00
default :
{
2009-09-22 11:45:41 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
sigmsg - > event_id , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2008-01-08 18:33:07 -05:00
}
break ;
2007-05-31 16:15:16 -04:00
}
2007-05-26 00:45:31 -04:00
return ZAP_SUCCESS ;
}
2007-05-27 10:58:01 -04:00
2007-05-26 00:45:31 -04:00
static ZIO_SIGNAL_CB_FUNCTION ( on_fxs_signal )
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2007-06-01 11:40:12 -04:00
zap_status_t status = ZAP_SUCCESS ;
2007-05-27 10:58:01 -04:00
2007-06-16 09:46:32 -04:00
zap_log ( ZAP_LOG_DEBUG , " got FXS sig [%s] \n " , zap_signal_event2str ( sigmsg - > event_id ) ) ;
2007-05-26 00:45:31 -04:00
2007-05-27 10:58:01 -04:00
switch ( sigmsg - > event_id ) {
2007-05-31 16:15:16 -04:00
case ZAP_SIGEVENT_UP :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-27 19:31:26 -04:00
zap_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2007-05-31 16:15:16 -04:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2008-09-11 13:55:27 -04:00
case ZAP_SIGEVENT_PROGRESS :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2007-05-27 10:58:01 -04:00
case ZAP_SIGEVENT_START :
{
2008-01-25 11:42:06 -05:00
zap_clear_flag_locked ( sigmsg - > channel , ZAP_CHANNEL_HOLD ) ;
2007-05-27 10:58:01 -04:00
status = zap_channel_from_event ( sigmsg , & session ) ;
if ( status ! = ZAP_SUCCESS ) {
zap_set_state_locked ( sigmsg - > channel , ZAP_CHANNEL_STATE_BUSY ) ;
}
2007-05-26 00:45:31 -04:00
}
2007-05-27 10:58:01 -04:00
break ;
case ZAP_SIGEVENT_STOP :
{
2010-01-29 17:15:05 -05:00
private_t * tech_pvt = NULL ;
2008-01-09 19:47:04 -05:00
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING ;
if ( sigmsg - > channel - > token_count ) {
switch_core_session_t * session_a , * session_b , * session_t = NULL ;
switch_channel_t * channel_a = NULL , * channel_b = NULL ;
2009-10-23 12:03:57 -04:00
int digits = ! zstr ( sigmsg - > channel - > caller_data . collected ) ;
2008-01-09 19:47:04 -05:00
const char * br_a_uuid = NULL , * br_b_uuid = NULL ;
private_t * tech_pvt = NULL ;
if ( ( session_a = switch_core_session_locate ( sigmsg - > channel - > tokens [ 0 ] ) ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
br_a_uuid = switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ;
tech_pvt = switch_core_session_get_private ( session_a ) ;
2008-05-01 12:41:10 -04:00
stop_hold ( session_a , switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-09 19:47:04 -05:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
if ( ( session_b = switch_core_session_locate ( sigmsg - > channel - > tokens [ 1 ] ) ) ) {
channel_b = switch_core_session_get_channel ( session_b ) ;
br_b_uuid = switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ;
tech_pvt = switch_core_session_get_private ( session_b ) ;
2008-05-01 12:41:10 -04:00
stop_hold ( session_a , switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-09 19:47:04 -05:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
2010-12-15 21:59:33 -05:00
if ( channel_a & & channel_b & & switch_channel_direction ( channel_a ) = = SWITCH_CALL_DIRECTION_INBOUND & &
switch_channel_direction ( channel_b ) = = SWITCH_CALL_DIRECTION_INBOUND ) {
2008-01-09 19:47:04 -05:00
cause = SWITCH_CAUSE_ATTENDED_TRANSFER ;
if ( br_a_uuid & & br_b_uuid ) {
switch_ivr_uuid_bridge ( br_a_uuid , br_b_uuid ) ;
} else if ( br_a_uuid & & digits ) {
session_t = switch_core_session_locate ( br_a_uuid ) ;
} else if ( br_b_uuid & & digits ) {
session_t = switch_core_session_locate ( br_b_uuid ) ;
}
}
if ( session_t ) {
switch_ivr_session_transfer ( session_t , sigmsg - > channel - > caller_data . collected , NULL , NULL ) ;
switch_core_session_rwunlock ( session_t ) ;
}
if ( session_a ) {
switch_core_session_rwunlock ( session_a ) ;
}
if ( session_b ) {
switch_core_session_rwunlock ( session_b ) ;
}
}
2007-05-27 14:14:49 -04:00
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-01-29 17:15:05 -05:00
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-01 18:26:34 -05:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-05-27 14:14:49 -04:00
channel = switch_core_session_get_channel ( session ) ;
2008-01-09 19:47:04 -05:00
switch_channel_hangup ( channel , cause ) ;
2008-01-08 18:33:07 -05:00
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-05-27 14:14:49 -04:00
switch_core_session_rwunlock ( session ) ;
2007-05-27 10:58:01 -04:00
}
2008-01-09 19:47:04 -05:00
zap_channel_clear_token ( sigmsg - > channel , NULL ) ;
2007-05-26 00:45:31 -04:00
}
2007-05-27 10:58:01 -04:00
break ;
2007-05-26 00:45:31 -04:00
2008-01-09 19:47:04 -05:00
case ZAP_SIGEVENT_ADD_CALL :
{
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
}
break ;
2007-05-27 14:14:49 -04:00
case ZAP_SIGEVENT_FLASH :
{
2008-05-01 12:41:10 -04:00
if ( zap_test_flag ( sigmsg - > channel , ZAP_CHANNEL_HOLD ) & & sigmsg - > channel - > token_count = = 1 ) {
switch_core_session_t * session ;
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
const char * buuid ;
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
zap_set_state_locked ( sigmsg - > channel , ZAP_CHANNEL_STATE_UP ) ;
stop_hold ( session , buuid ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
switch_core_session_rwunlock ( session ) ;
}
} else if ( sigmsg - > channel - > token_count = = 2 & & ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_3WAY ) ) {
2008-01-09 19:47:04 -05:00
if ( zap_test_flag ( sigmsg - > channel , ZAP_CHANNEL_3WAY ) ) {
zap_clear_flag ( sigmsg - > channel , ZAP_CHANNEL_3WAY ) ;
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 1 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
switch_core_session_rwunlock ( session ) ;
}
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
} else {
char * cmd ;
cmd = switch_mprintf ( " three_way::%s " , sigmsg - > channel - > tokens [ 0 ] ) ;
zap_set_flag ( sigmsg - > channel , ZAP_CHANNEL_3WAY ) ;
cycle_foreground ( sigmsg - > channel , 1 , cmd ) ;
free ( cmd ) ;
}
2008-01-25 11:42:06 -05:00
} else if ( ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_CALL_SWAP )
| | ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_3WAY )
) {
2008-01-09 19:47:04 -05:00
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
if ( sigmsg - > channel - > token_count = = 1 ) {
zap_set_flag_locked ( sigmsg - > channel , ZAP_CHANNEL_HOLD ) ;
zap_set_state_locked ( sigmsg - > channel , ZAP_CHANNEL_STATE_DIALTONE ) ;
}
}
2007-05-27 14:14:49 -04:00
}
break ;
2007-11-24 13:04:14 -05:00
case ZAP_SIGEVENT_COLLECTED_DIGIT :
{
char * dtmf = sigmsg - > raw_data ;
char * regex = SPAN_CONFIG [ sigmsg - > channel - > span - > span_id ] . dial_regex ;
char * fail_regex = SPAN_CONFIG [ sigmsg - > channel - > span - > span_id ] . fail_dial_regex ;
2009-10-23 12:03:57 -04:00
if ( zstr ( regex ) ) {
2007-11-24 13:04:14 -05:00
regex = NULL ;
}
2009-10-23 12:03:57 -04:00
if ( zstr ( fail_regex ) ) {
2007-11-24 13:04:14 -05:00
fail_regex = NULL ;
}
2008-02-18 11:15:24 -05:00
zap_log ( ZAP_LOG_DEBUG , " got DTMF sig [%s] \n " , dtmf ) ;
2008-01-09 19:47:04 -05:00
switch_set_string ( sigmsg - > channel - > caller_data . collected , dtmf ) ;
2009-10-23 12:03:57 -04:00
if ( ( regex | | fail_regex ) & & ! zstr ( dtmf ) ) {
2007-11-24 13:04:14 -05:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
match = switch_regex_perform ( dtmf , fail_regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
status = match ? ZAP_SUCCESS : ZAP_BREAK ;
switch_regex_safe_free ( re ) ;
}
if ( status = = ZAP_SUCCESS & & regex ) {
match = switch_regex_perform ( dtmf , regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
status = match ? ZAP_BREAK : ZAP_SUCCESS ;
}
switch_regex_safe_free ( re ) ;
}
}
break ;
2008-01-08 18:33:07 -05:00
default :
{
2009-09-22 11:45:41 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
sigmsg - > event_id , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2008-01-08 18:33:07 -05:00
}
break ;
2007-05-27 10:58:01 -04:00
}
2007-05-26 00:45:31 -04:00
2007-05-27 10:58:01 -04:00
return status ;
2007-05-26 00:45:31 -04:00
}
2009-08-19 17:47:56 -04:00
static ZIO_SIGNAL_CB_FUNCTION ( on_r2_signal )
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
zap_status_t status = ZAP_SUCCESS ;
zap_log ( ZAP_LOG_DEBUG , " Got R2 channel sig [%s] in channel %d \n " , zap_signal_event2str ( sigmsg - > event_id ) , sigmsg - > channel - > physical_chan_id ) ;
2010-03-05 16:59:00 -05:00
if ( on_common_signal ( sigmsg ) = = ZAP_BREAK ) {
return ZAP_SUCCESS ;
}
2009-08-19 17:47:56 -04:00
switch ( sigmsg - > event_id ) {
/* on_call_disconnect from the R2 side */
case ZAP_SIGEVENT_STOP :
{
2010-01-29 17:15:05 -05:00
private_t * tech_pvt = NULL ;
2009-08-19 17:47:56 -04:00
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-01-29 17:15:05 -05:00
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-01 18:26:34 -05:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2009-08-19 17:47:56 -04:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_hangup ( channel , sigmsg - > channel - > caller_data . hangup_cause ) ;
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
/* on_call_offered from the R2 side */
case ZAP_SIGEVENT_START :
{
status = zap_channel_from_event ( sigmsg , & session ) ;
}
break ;
/* on DNIS received from the R2 forward side, return status == ZAP_BREAK to stop requesting DNIS */
case ZAP_SIGEVENT_COLLECTED_DIGIT :
{
char * regex = SPAN_CONFIG [ sigmsg - > channel - > span - > span_id ] . dial_regex ;
char * fail_regex = SPAN_CONFIG [ sigmsg - > channel - > span - > span_id ] . fail_dial_regex ;
2009-10-23 12:03:57 -04:00
if ( zstr ( regex ) ) {
2009-08-19 17:47:56 -04:00
regex = NULL ;
}
2009-10-23 12:03:57 -04:00
if ( zstr ( fail_regex ) ) {
2009-08-19 17:47:56 -04:00
fail_regex = NULL ;
}
zap_log ( ZAP_LOG_DEBUG , " R2 DNIS so far [%s] \n " , sigmsg - > channel - > caller_data . dnis . digits ) ;
2009-10-23 12:03:57 -04:00
if ( ( regex | | fail_regex ) & & ! zstr ( sigmsg - > channel - > caller_data . dnis . digits ) ) {
2009-08-19 17:47:56 -04:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
match = switch_regex_perform ( sigmsg - > channel - > caller_data . dnis . digits , fail_regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
status = match ? ZAP_SUCCESS : ZAP_BREAK ;
switch_regex_safe_free ( re ) ;
}
if ( status = = ZAP_SUCCESS & & regex ) {
match = switch_regex_perform ( sigmsg - > channel - > caller_data . dnis . digits , regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
status = match ? ZAP_BREAK : ZAP_SUCCESS ;
}
switch_regex_safe_free ( re ) ;
}
}
break ;
case ZAP_SIGEVENT_PROGRESS :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
case ZAP_SIGEVENT_UP :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-27 19:31:26 -04:00
zap_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2009-08-19 17:47:56 -04:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
default :
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled event %d from R2 for channel %d:%d \n " ,
sigmsg - > event_id , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
}
break ;
}
return status ;
}
2008-02-29 19:48:36 -05:00
static ZIO_SIGNAL_CB_FUNCTION ( on_clear_channel_signal )
2007-06-12 23:37:55 -04:00
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2008-02-29 19:48:36 -05:00
zap_log ( ZAP_LOG_DEBUG , " got clear channel sig [%s] \n " , zap_signal_event2str ( sigmsg - > event_id ) ) ;
2007-06-12 23:37:55 -04:00
2010-03-05 15:14:44 -05:00
if ( on_common_signal ( sigmsg ) = = ZAP_BREAK ) {
return ZAP_SUCCESS ;
}
2007-06-12 23:37:55 -04:00
switch ( sigmsg - > event_id ) {
case ZAP_SIGEVENT_START :
{
2010-06-27 19:31:26 -04:00
zap_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2007-06-12 23:37:55 -04:00
return zap_channel_from_event ( sigmsg , & session ) ;
}
break ;
case ZAP_SIGEVENT_STOP :
2008-05-25 21:51:11 -04:00
case ZAP_SIGEVENT_RESTART :
2009-09-06 10:07:06 -04:00
{
2010-01-29 17:15:05 -05:00
private_t * tech_pvt = NULL ;
2007-06-12 23:37:55 -04:00
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2010-01-29 17:15:05 -05:00
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-01 18:26:34 -05:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-06-12 23:37:55 -04:00
channel = switch_core_session_get_channel ( session ) ;
2007-06-16 11:52:49 -04:00
switch_channel_hangup ( channel , sigmsg - > channel - > caller_data . hangup_cause ) ;
2008-01-08 18:33:07 -05:00
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-06-12 23:37:55 -04:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
case ZAP_SIGEVENT_UP :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2010-06-27 19:31:26 -04:00
zap_enable_channel_dtmf ( sigmsg - > channel , channel ) ;
2007-06-12 23:37:55 -04:00
switch_core_session_rwunlock ( session ) ;
2009-09-06 10:07:06 -04:00
} else {
2009-09-06 10:43:58 -04:00
const char * uuid = zap_channel_get_uuid ( sigmsg - > channel , 0 ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id , ( uuid ) ? uuid : " N/A " ) ;
2007-06-12 23:37:55 -04:00
}
}
2007-06-16 00:39:15 -04:00
case ZAP_SIGEVENT_PROGRESS_MEDIA :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_pre_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
2009-09-06 10:07:06 -04:00
} else {
2009-09-06 10:43:58 -04:00
const char * uuid = zap_channel_get_uuid ( sigmsg - > channel , 0 ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id , ( uuid ) ? uuid : " N/A " ) ;
2007-06-16 00:39:15 -04:00
}
}
break ;
case ZAP_SIGEVENT_PROGRESS :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
2009-09-06 10:07:06 -04:00
} else {
2009-09-06 10:43:58 -04:00
const char * uuid = zap_channel_get_uuid ( sigmsg - > channel , 0 ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Session for channel %d:%d not found [UUID: %s] \n " ,
sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id , ( uuid ) ? uuid : " N/A " ) ;
2007-06-16 00:39:15 -04:00
}
}
2007-06-12 23:37:55 -04:00
break ;
2008-01-08 18:33:07 -05:00
default :
{
2009-09-22 12:21:32 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
2009-09-22 11:45:41 -04:00
sigmsg - > event_id , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2008-01-08 18:33:07 -05:00
}
break ;
2007-06-12 23:37:55 -04:00
}
return ZAP_SUCCESS ;
}
static ZIO_SIGNAL_CB_FUNCTION ( on_analog_signal )
2007-05-27 10:58:01 -04:00
{
2008-01-08 18:33:07 -05:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-09-06 10:07:06 -04:00
2010-03-05 16:59:00 -05:00
if ( on_common_signal ( sigmsg ) = = ZAP_BREAK ) {
return ZAP_SUCCESS ;
}
2007-05-27 10:58:01 -04:00
switch ( sigmsg - > channel - > type ) {
case ZAP_CHAN_TYPE_FXO :
2008-09-16 22:21:28 -04:00
case ZAP_CHAN_TYPE_EM :
2007-05-27 10:58:01 -04:00
{
2007-11-24 13:04:14 -05:00
status = on_fxo_signal ( sigmsg ) ;
2007-05-27 10:58:01 -04:00
}
break ;
case ZAP_CHAN_TYPE_FXS :
{
2007-11-24 13:04:14 -05:00
status = on_fxs_signal ( sigmsg ) ;
2007-05-27 10:58:01 -04:00
}
break ;
default :
{
2009-09-22 11:45:41 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled analog channel type %d for channel %d:%d \n " ,
sigmsg - > channel - > type , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2007-05-27 10:58:01 -04:00
}
break ;
}
2007-06-01 11:40:12 -04:00
2007-11-24 13:04:14 -05:00
return status ;
2007-05-27 10:58:01 -04:00
}
2007-05-26 00:45:31 -04:00
2008-02-18 12:41:41 -05:00
static void zap_logger ( const char * file , const char * func , int line , int level , const char * fmt , . . . )
2007-05-26 00:45:31 -04:00
{
char * data = NULL ;
va_list ap ;
va_start ( ap , fmt ) ;
if ( switch_vasprintf ( & data , fmt , ap ) ! = - 1 ) {
2008-11-03 15:46:43 -05:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , ( char * ) func , line , NULL , level , " %s " , data ) ;
2007-05-26 00:45:31 -04:00
free ( data ) ;
}
va_end ( ap ) ;
}
2008-01-25 11:42:06 -05:00
static uint32_t enable_analog_option ( const char * str , uint32_t current_options )
{
if ( ! strcasecmp ( str , " 3-way " ) ) {
current_options | = ANALOG_OPTION_3WAY ;
current_options & = ~ ANALOG_OPTION_CALL_SWAP ;
} else if ( ! strcasecmp ( str , " call-swap " ) ) {
current_options | = ANALOG_OPTION_CALL_SWAP ;
current_options & = ~ ANALOG_OPTION_3WAY ;
}
return current_options ;
}
2007-05-26 00:45:31 -04:00
static switch_status_t load_config ( void )
{
2009-01-13 17:45:09 -05:00
const char * cf = " openzap.conf " ;
2007-05-27 01:23:28 -04:00
switch_xml_t cfg , xml , settings , param , spans , myspan ;
2007-05-26 00:45:31 -04:00
memset ( & globals , 0 , sizeof ( globals ) ) ;
switch_mutex_init ( & globals . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " open of %s failed \n " , cf ) ;
return SWITCH_STATUS_TERM ;
}
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " debug " ) ) {
globals . debug = atoi ( val ) ;
2008-01-09 19:47:04 -05:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
switch_set_string ( globals . hold_music , val ) ;
2008-01-25 11:42:06 -05:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
globals . analog_options = enable_analog_option ( val , globals . analog_options ) ;
2007-05-26 00:45:31 -04:00
}
}
}
if ( ( spans = switch_xml_child ( cfg , " analog_spans " ) ) ) {
2007-05-27 01:23:28 -04:00
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 13:09:10 -04:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
2008-09-26 11:36:34 -04:00
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2008-09-26 13:09:10 -04:00
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 17:45:09 -05:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2007-05-26 00:45:31 -04:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
2008-10-06 15:21:27 -04:00
char * hotline = NULL ;
2007-11-24 13:04:14 -05:00
char * dial_regex = NULL ;
2008-01-09 19:47:04 -05:00
char * hold_music = NULL ;
2007-11-24 13:04:14 -05:00
char * fail_dial_regex = NULL ;
2009-01-13 17:45:09 -05:00
const char * enable_callerid = " true " ;
2010-05-25 16:49:54 -04:00
int callwaiting = 1 ;
2008-09-29 11:51:00 -04:00
2007-05-26 00:45:31 -04:00
uint32_t span_id = 0 , to = 0 , max = 0 ;
zap_span_t * span = NULL ;
2008-01-25 11:42:06 -05:00
analog_option_t analog_options = ANALOG_OPTION_NONE ;
2008-09-26 11:36:34 -04:00
2007-05-27 01:23:28 -04:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
2007-05-26 00:45:31 -04:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
2007-11-24 13:04:14 -05:00
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
2007-05-26 00:45:31 -04:00
digit_timeout = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2007-11-24 13:04:14 -05:00
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
2008-09-29 11:51:00 -04:00
} else if ( ! strcasecmp ( var , " enable-callerid " ) ) {
enable_callerid = val ;
2007-11-24 13:04:14 -05:00
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
2008-01-09 19:47:04 -05:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
hold_music = val ;
2007-11-24 13:04:14 -05:00
} else if ( ! strcasecmp ( var , " max_digits " ) | | ! strcasecmp ( var , " max-digits " ) ) {
2008-09-08 19:01:44 -04:00
max_digits = val ;
2008-10-06 15:21:27 -04:00
} else if ( ! strcasecmp ( var , " hotline " ) ) {
hotline = val ;
2010-05-25 16:49:54 -04:00
} else if ( ! strcasecmp ( var , " callwaiting " ) ) {
2010-06-08 14:35:15 -04:00
callwaiting = switch_true ( val ) ? 1 : 0 ;
2008-01-25 11:42:06 -05:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
2007-05-26 00:45:31 -04:00
}
}
2008-09-26 13:09:10 -04:00
if ( ! id & & ! name ) {
2007-05-26 00:45:31 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
2008-08-29 16:41:17 -04:00
continue ;
2007-05-26 00:45:31 -04:00
}
2008-09-26 11:36:34 -04:00
2007-05-26 00:45:31 -04:00
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 11:36:34 -04:00
if ( name ) {
zstatus = zap_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = zap_span_find ( span_id , & span ) ;
}
if ( zstatus ! = ZAP_SUCCESS ) {
zstatus = zap_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = ZAP_SUCCESS ) {
2008-10-24 16:52:45 -04:00
zap_log ( ZAP_LOG_ERROR , " Error finding OpenZAP span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2007-05-26 00:45:31 -04:00
continue ;
}
2008-09-26 11:36:34 -04:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2007-05-26 00:45:31 -04:00
2008-08-29 11:58:59 -04:00
if ( zap_configure_span ( " analog " , span , on_analog_signal ,
" tonemap " , tonegroup ,
" digit_timeout " , & to ,
2008-08-29 16:41:17 -04:00
" max_dialstr " , & max ,
2010-05-25 16:49:54 -04:00
" hotline " , hotline ? hotline : " " ,
2008-09-29 11:51:00 -04:00
" enable_callerid " , enable_callerid ,
2010-05-25 16:49:54 -04:00
" callwaiting " , & callwaiting ,
2008-08-29 16:41:17 -04:00
TAG_END ) ! = ZAP_SUCCESS ) {
2007-05-30 22:41:50 -04:00
zap_log ( ZAP_LOG_ERROR , " Error starting OpenZAP span %d \n " , span_id ) ;
2007-05-26 00:45:31 -04:00
continue ;
}
SPAN_CONFIG [ span - > span_id ] . span = span ;
2007-11-24 13:04:14 -05:00
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . context , context ) ;
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . dialplan , dialplan ) ;
2008-01-25 11:42:06 -05:00
SPAN_CONFIG [ span - > span_id ] . analog_options = analog_options | globals . analog_options ;
2007-11-24 13:04:14 -05:00
if ( dial_regex ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . dial_regex , dial_regex ) ;
}
if ( fail_dial_regex ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . fail_dial_regex , fail_dial_regex ) ;
}
2007-05-26 00:45:31 -04:00
2008-01-09 19:47:04 -05:00
if ( hold_music ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . hold_music , hold_music ) ;
}
2008-04-01 13:29:57 -04:00
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " analog " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
2008-08-29 11:58:59 -04:00
zap_span_start ( span ) ;
2007-05-26 00:45:31 -04:00
}
}
2008-09-16 22:21:28 -04:00
if ( ( spans = switch_xml_child ( cfg , " analog_em_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 13:09:10 -04:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 17:45:09 -05:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2008-09-16 22:21:28 -04:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
char * dial_regex = NULL ;
char * hold_music = NULL ;
char * fail_dial_regex = NULL ;
uint32_t span_id = 0 , to = 0 , max = 0 ;
zap_span_t * span = NULL ;
analog_option_t analog_options = ANALOG_OPTION_NONE ;
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
digit_timeout = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
hold_music = val ;
} else if ( ! strcasecmp ( var , " max_digits " ) | | ! strcasecmp ( var , " max-digits " ) ) {
max_digits = val ;
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
}
}
2008-09-26 13:09:10 -04:00
if ( ! id & & ! name ) {
2008-09-16 22:21:28 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 13:09:10 -04:00
if ( name ) {
zstatus = zap_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = zap_span_find ( span_id , & span ) ;
}
if ( zstatus ! = ZAP_SUCCESS ) {
zstatus = zap_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = ZAP_SUCCESS ) {
2008-10-24 16:52:45 -04:00
zap_log ( ZAP_LOG_ERROR , " Error finding OpenZAP span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2008-09-16 22:21:28 -04:00
continue ;
}
2008-09-26 13:09:10 -04:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2008-09-16 22:21:28 -04:00
if ( zap_configure_span ( " analog_em " , span , on_analog_signal ,
" tonemap " , tonegroup ,
" digit_timeout " , & to ,
" max_dialstr " , & max ,
TAG_END ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Error starting OpenZAP span %d \n " , span_id ) ;
continue ;
}
SPAN_CONFIG [ span - > span_id ] . span = span ;
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . context , context ) ;
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . dialplan , dialplan ) ;
SPAN_CONFIG [ span - > span_id ] . analog_options = analog_options | globals . analog_options ;
if ( dial_regex ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . dial_regex , dial_regex ) ;
}
if ( fail_dial_regex ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . fail_dial_regex , fail_dial_regex ) ;
}
if ( hold_music ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . hold_music , hold_music ) ;
}
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " analog_em " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
zap_span_start ( span ) ;
}
}
2007-06-12 23:37:55 -04:00
if ( ( spans = switch_xml_child ( cfg , " pri_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 13:09:10 -04:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 17:45:09 -05:00
const char * context = " default " ;
const char * dialplan = " XML " ;
2008-08-29 11:58:59 -04:00
//Q921NetUser_t mode = Q931_TE;
//Q931Dialect_t dialect = Q931_Dialect_National;
char * mode = NULL ;
char * dialect = NULL ;
2007-06-12 23:37:55 -04:00
uint32_t span_id = 0 ;
zap_span_t * span = NULL ;
2009-01-13 17:45:09 -05:00
const char * tonegroup = NULL ;
2008-10-12 18:07:45 -04:00
char * digit_timeout = NULL ;
2009-03-19 19:06:04 -04:00
const char * opts = " none " ;
2008-10-12 18:07:45 -04:00
uint32_t to = 0 ;
2008-10-03 17:57:57 -04:00
int q921loglevel = - 1 ;
int q931loglevel = - 1 ;
2010-02-26 15:57:59 -05:00
2009-01-05 20:07:09 -05:00
// quick debug
2009-01-30 06:37:11 -05:00
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ID: '%s', Name:'%s'\n",id,name);
2008-10-03 17:57:57 -04:00
2007-06-12 23:37:55 -04:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
} else if ( ! strcasecmp ( var , " mode " ) ) {
2008-08-29 11:58:59 -04:00
mode = val ;
2007-06-12 23:37:55 -04:00
} else if ( ! strcasecmp ( var , " dialect " ) ) {
2008-08-29 11:58:59 -04:00
dialect = val ;
2008-10-03 17:57:57 -04:00
} else if ( ! strcasecmp ( var , " q921loglevel " ) ) {
if ( ( q921loglevel = switch_log_str2level ( val ) ) = = SWITCH_LOG_INVALID ) {
q921loglevel = - 1 ;
}
} else if ( ! strcasecmp ( var , " q931loglevel " ) ) {
if ( ( q931loglevel = switch_log_str2level ( val ) ) = = SWITCH_LOG_INVALID ) {
q931loglevel = - 1 ;
}
2007-06-12 23:37:55 -04:00
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
2009-03-19 19:06:04 -04:00
} else if ( ! strcasecmp ( var , " opts " ) ) {
opts = val ;
2007-06-12 23:37:55 -04:00
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2008-10-12 18:07:45 -04:00
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
digit_timeout = val ;
}
2007-06-12 23:37:55 -04:00
}
2008-10-03 17:57:57 -04:00
2008-09-26 13:09:10 -04:00
if ( ! id & & ! name ) {
2007-06-12 23:37:55 -04:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
2008-02-28 19:21:04 -05:00
continue ;
2007-06-12 23:37:55 -04:00
}
2008-10-24 16:41:52 -04:00
2008-09-26 13:09:10 -04:00
if ( name ) {
zstatus = zap_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = zap_span_find ( span_id , & span ) ;
}
if ( zstatus ! = ZAP_SUCCESS ) {
zstatus = zap_span_find_by_name ( id , & span ) ;
}
2007-06-12 23:37:55 -04:00
}
2008-09-26 13:09:10 -04:00
2008-10-12 18:07:45 -04:00
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
2008-09-26 13:09:10 -04:00
if ( zstatus ! = ZAP_SUCCESS ) {
2008-10-24 16:52:45 -04:00
zap_log ( ZAP_LOG_ERROR , " Error finding OpenZAP span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2007-06-12 23:37:55 -04:00
continue ;
}
2009-01-30 06:37:11 -05:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2008-09-26 13:09:10 -04:00
if ( ! tonegroup ) {
tonegroup = " us " ;
}
2008-08-29 11:58:59 -04:00
if ( zap_configure_span ( " isdn " , span , on_clear_channel_signal ,
2008-10-12 18:07:45 -04:00
" mode " , mode ,
2008-08-29 16:41:17 -04:00
" dialect " , dialect ,
2008-10-12 18:07:45 -04:00
" digit_timeout " , & to ,
2008-10-07 11:27:51 -04:00
" opts " , opts ,
2009-12-03 23:53:04 -05:00
" tonemap " , tonegroup ,
2008-10-03 17:57:57 -04:00
" q921loglevel " , q921loglevel ,
" q931loglevel " , q931loglevel ,
2008-08-29 16:41:17 -04:00
TAG_END ) ! = ZAP_SUCCESS ) {
2009-01-09 17:11:04 -05:00
zap_log ( ZAP_LOG_ERROR , " Error starting OpenZAP span %d mode: %s dialect: %s error: %s \n " , span_id , mode , dialect , span - > last_error ) ;
2007-06-12 23:37:55 -04:00
continue ;
}
SPAN_CONFIG [ span - > span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . context , context , sizeof ( SPAN_CONFIG [ span - > span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span - > span_id ] . dialplan ) ) ;
2008-04-01 13:29:57 -04:00
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " isdn " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
2007-06-12 23:37:55 -04:00
2008-08-29 11:58:59 -04:00
zap_span_start ( span ) ;
2007-06-12 23:37:55 -04:00
}
}
2009-02-07 18:14:25 -05:00
if ( ( spans = switch_xml_child ( cfg , " libpri_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * o_node = " cpe " ;
const char * o_switch = " dms100 " ;
const char * o_dp = " unknown " ;
const char * o_l1 = " ulaw " ;
2009-03-19 16:15:39 -04:00
const char * o_debug = " none " ;
const char * opts = " none " ;
2009-02-07 18:14:25 -05:00
uint32_t span_id = 0 ;
zap_span_t * span = NULL ;
2009-03-19 16:15:39 -04:00
2009-02-07 18:14:25 -05:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " node " ) ) {
o_node = val ;
} else if ( ! strcasecmp ( var , " switch " ) ) {
o_switch = val ;
} else if ( ! strcasecmp ( var , " dp " ) ) {
o_dp = val ;
} else if ( ! strcasecmp ( var , " l1 " ) ) {
o_l1 = val ;
} else if ( ! strcasecmp ( var , " debug " ) ) {
o_debug = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
2009-03-19 16:15:39 -04:00
} else if ( ! strcasecmp ( var , " opts " ) ) {
opts = val ;
2009-02-07 18:14:25 -05:00
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
}
}
if ( ! id & & ! name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( name ) {
zstatus = zap_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = zap_span_find ( span_id , & span ) ;
}
if ( zstatus ! = ZAP_SUCCESS ) {
zstatus = zap_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Error finding OpenZAP span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
continue ;
}
if ( ! span_id ) {
span_id = span - > span_id ;
}
if ( zap_configure_span ( " libpri " , span , on_clear_channel_signal ,
" node " , o_node ,
" switch " , o_switch ,
" dp " , o_dp ,
" l1 " , o_l1 ,
" debug " , o_debug ,
" opts " , opts ,
TAG_END ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Error starting OpenZAP span %d node: %s switch: %s dp: %s l1: %s debug: %s error: %s \n " ,
span_id , switch_str_nil ( o_node ) , switch_str_nil ( o_switch ) , switch_str_nil ( o_dp ) , switch_str_nil ( o_l1 ) , switch_str_nil ( o_debug ) ,
span - > last_error ) ;
continue ;
}
SPAN_CONFIG [ span - > span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . context , context , sizeof ( SPAN_CONFIG [ span - > span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span - > span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " isdn " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
zap_span_start ( span ) ;
}
}
2008-02-28 19:21:04 -05:00
if ( ( spans = switch_xml_child ( cfg , " boost_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 13:09:10 -04:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 17:45:09 -05:00
const char * context = " default " ;
const char * dialplan = " XML " ;
2010-02-26 17:54:59 -05:00
const char * outbound_called_ton = " national " ;
const char * outbound_called_npi = " isdn " ;
const char * outbound_calling_ton = " national " ;
const char * outbound_calling_npi = " isdn " ;
const char * outbound_rdnis_ton = " national " ;
const char * outbound_rdnis_npi = " isdn " ;
2008-02-28 19:21:04 -05:00
uint32_t span_id = 0 ;
zap_span_t * span = NULL ;
2009-01-13 17:45:09 -05:00
const char * tonegroup = NULL ;
2008-02-28 19:21:04 -05:00
char * local_ip = NULL ;
int local_port = 0 ;
char * remote_ip = NULL ;
int remote_port = 0 ;
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
} else if ( ! strcasecmp ( var , " 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 ) ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
2010-02-26 15:57:59 -05:00
} else if ( ! strcasecmp ( var , " outbound-called-ton " ) ) {
outbound_called_ton = val ;
} else if ( ! strcasecmp ( var , " outbound-called-npi " ) ) {
outbound_called_npi = val ;
} else if ( ! strcasecmp ( var , " outbound-calling-ton " ) ) {
outbound_calling_ton = val ;
} else if ( ! strcasecmp ( var , " outbound-calling-npi " ) ) {
outbound_calling_npi = val ;
} else if ( ! strcasecmp ( var , " outbound-rdnis-ton " ) ) {
outbound_rdnis_ton = val ;
} else if ( ! strcasecmp ( var , " outbound-rdnis-npi " ) ) {
outbound_rdnis_npi = val ;
2008-02-28 19:21:04 -05:00
}
}
2008-09-26 13:09:10 -04:00
if ( ! id & & ! name ) {
2008-02-28 19:21:04 -05:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param \n " ) ;
continue ;
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
2008-09-26 13:09:10 -04:00
if ( name ) {
zstatus = zap_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = zap_span_find ( span_id , & span ) ;
}
if ( zstatus ! = ZAP_SUCCESS ) {
zstatus = zap_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = ZAP_SUCCESS ) {
2008-10-24 16:52:45 -04:00
zap_log ( ZAP_LOG_ERROR , " Error finding OpenZAP span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
2008-02-28 19:21:04 -05:00
continue ;
}
2008-09-26 13:09:10 -04:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2008-02-28 19:21:04 -05:00
2010-02-26 15:57:59 -05:00
zap_set_npi ( outbound_called_npi , & span - > default_caller_data . ani . plan ) ;
zap_set_npi ( outbound_calling_npi , & span - > default_caller_data . cid_num . plan ) ;
zap_set_npi ( outbound_rdnis_npi , & span - > default_caller_data . rdnis . plan ) ;
zap_set_ton ( outbound_called_ton , & span - > default_caller_data . ani . type ) ;
zap_set_ton ( outbound_calling_ton , & span - > default_caller_data . cid_num . type ) ;
zap_set_ton ( outbound_rdnis_ton , & span - > default_caller_data . rdnis . type ) ;
2009-09-02 13:28:56 -04:00
if ( zap_configure_span ( " sangoma_boost " , span , on_clear_channel_signal ,
2008-08-29 11:58:59 -04:00
" local_ip " , local_ip ,
" local_port " , & local_port ,
" remote_ip " , remote_ip ,
2008-08-29 16:41:17 -04:00
" remote_port " , & remote_port ,
TAG_END ) ! = ZAP_SUCCESS ) {
2008-02-28 19:21:04 -05:00
zap_log ( ZAP_LOG_ERROR , " Error starting OpenZAP span %d error: %s \n " , span_id , span - > last_error ) ;
continue ;
}
SPAN_CONFIG [ span - > span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . context , context , sizeof ( SPAN_CONFIG [ span - > span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span - > span_id ] . dialplan ) ) ;
2008-08-29 11:58:59 -04:00
zap_span_start ( span ) ;
2009-09-02 13:28:56 -04:00
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " Sangoma (boost) " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
2008-02-28 19:21:04 -05:00
}
}
2009-08-19 17:47:56 -04:00
if ( ( spans = switch_xml_child ( cfg , " r2_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
/* strings */
const char * variant = " itu " ;
const char * category = " national_subscriber " ;
const char * logdir = " /usr/local/freeswitch/log/ " ; /* FIXME: get PREFIX variable */
const char * logging = " notice,warning,error " ;
const char * advanced_protocol_file = " " ;
/* booleans */
int call_files = 0 ;
int get_ani_first = - 1 ;
int immediate_accept = - 1 ;
int double_answer = - 1 ;
int skip_category = - 1 ;
int forced_release = - 1 ;
int charge_calls = - 1 ;
/* integers */
int mfback_timeout = - 1 ;
int metering_pulse_timeout = - 1 ;
int allow_collect_calls = - 1 ;
int max_ani = 10 ;
int max_dnis = 4 ;
/* common non r2 stuff */
const char * context = " default " ;
const char * dialplan = " XML " ;
char * dial_regex = NULL ;
char * fail_dial_regex = NULL ;
uint32_t span_id = 0 ;
zap_span_t * span = NULL ;
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
/* string parameters */
if ( ! strcasecmp ( var , " variant " ) ) {
variant = val ;
} else if ( ! strcasecmp ( var , " category " ) ) {
category = val ;
} else if ( ! strcasecmp ( var , " logdir " ) ) {
logdir = val ;
} else if ( ! strcasecmp ( var , " logging " ) ) {
logging = val ;
} else if ( ! strcasecmp ( var , " advanced_protocol_file " ) ) {
advanced_protocol_file = val ;
/* booleans */
} else if ( ! strcasecmp ( var , " allow_collect_calls " ) ) {
allow_collect_calls = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " immediate_accept " ) ) {
immediate_accept = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " double_answer " ) ) {
double_answer = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " skip_category " ) ) {
skip_category = switch_true ( var ) ;
} else if ( ! strcasecmp ( var , " forced_release " ) ) {
forced_release = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " charge_calls " ) ) {
charge_calls = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " get_ani_first " ) ) {
get_ani_first = switch_true ( val ) ;
} else if ( ! strcasecmp ( var , " call_files " ) ) {
call_files = switch_true ( val ) ;
/* integers */
} else if ( ! strcasecmp ( var , " mfback_timeout " ) ) {
mfback_timeout = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " metering_pulse_timeout " ) ) {
metering_pulse_timeout = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " max_ani " ) ) {
max_ani = atoi ( val ) ;
} else if ( ! strcasecmp ( var , " max_dnis " ) ) {
max_dnis = atoi ( val ) ;
/* common non r2 stuff */
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
}
}
if ( ! id & & ! name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( name ) {
zstatus = zap_span_find_by_name ( name , & span ) ;
} else {
if ( switch_is_number ( id ) ) {
span_id = atoi ( id ) ;
zstatus = zap_span_find ( span_id , & span ) ;
}
if ( zstatus ! = ZAP_SUCCESS ) {
zstatus = zap_span_find_by_name ( id , & span ) ;
}
}
if ( zstatus ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Error finding OpenZAP span id:%s name:%s \n " , switch_str_nil ( id ) , switch_str_nil ( name ) ) ;
continue ;
}
if ( ! span_id ) {
span_id = span - > span_id ;
}
if ( zap_configure_span ( " r2 " , span , on_r2_signal ,
" variant " , variant ,
" max_ani " , max_ani ,
" max_dnis " , max_dnis ,
" category " , category ,
" logdir " , logdir ,
" logging " , logging ,
" advanced_protocol_file " , advanced_protocol_file ,
" allow_collect_calls " , allow_collect_calls ,
" immediate_accept " , immediate_accept ,
" double_answer " , double_answer ,
" skip_category " , skip_category ,
" forced_release " , forced_release ,
" charge_calls " , charge_calls ,
" get_ani_first " , get_ani_first ,
" call_files " , call_files ,
" mfback_timeout " , mfback_timeout ,
" metering_pulse_timeout " , metering_pulse_timeout ,
TAG_END ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Error configuring R2 OpenZAP span %d, error: %s \n " ,
span_id , span - > last_error ) ;
continue ;
}
if ( dial_regex ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . dial_regex , dial_regex ) ;
}
if ( fail_dial_regex ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . fail_dial_regex , fail_dial_regex ) ;
}
2008-02-28 19:21:04 -05:00
2009-08-19 17:47:56 -04:00
SPAN_CONFIG [ span - > span_id ] . span = span ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . context , context , sizeof ( SPAN_CONFIG [ span - > span_id ] . context ) ) ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . dialplan , dialplan , sizeof ( SPAN_CONFIG [ span - > span_id ] . dialplan ) ) ;
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " r2 " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
if ( zap_span_start ( span ) = = ZAP_FAIL ) {
zap_log ( ZAP_LOG_ERROR , " Error starting R2 OpenZAP span %d, error: %s \n " , span_id , span - > last_error ) ;
continue ;
}
}
}
2007-05-26 00:45:31 -04:00
switch_xml_free ( xml ) ;
return SWITCH_STATUS_SUCCESS ;
}
2008-04-01 13:29:57 -04:00
void dump_chan ( zap_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream )
{
2009-02-04 18:11:41 -05:00
if ( chan_id > span - > chan_count ) {
return ;
}
2008-04-01 13:29:57 -04:00
stream - > write_function ( stream ,
" span_id: %u \n "
" chan_id: %u \n "
" physical_span_id: %u \n "
" physical_chan_id: %u \n "
" type: %s \n "
" state: %s \n "
" last_state: %s \n "
2010-03-12 17:47:50 -05:00
" txgain: %3.2f \n "
" rxgain: %3.2f \n "
2008-04-01 13:29:57 -04:00
" cid_date: %s \n "
" cid_name: %s \n "
" cid_num: %s \n "
" ani: %s \n "
" aniII: %s \n "
" dnis: %s \n "
" rdnis: %s \n "
" cause: %s \n \n " ,
2008-09-10 11:25:02 -04:00
span - > channels [ chan_id ] - > span_id ,
span - > channels [ chan_id ] - > chan_id ,
span - > channels [ chan_id ] - > physical_span_id ,
span - > channels [ chan_id ] - > physical_chan_id ,
zap_chan_type2str ( span - > channels [ chan_id ] - > type ) ,
zap_channel_state2str ( span - > channels [ chan_id ] - > state ) ,
zap_channel_state2str ( span - > channels [ chan_id ] - > last_state ) ,
2010-03-12 17:47:50 -05:00
span - > channels [ chan_id ] - > txgain ,
span - > channels [ chan_id ] - > rxgain ,
2008-09-10 11:25:02 -04:00
span - > channels [ chan_id ] - > caller_data . cid_date ,
span - > channels [ chan_id ] - > caller_data . cid_name ,
span - > channels [ chan_id ] - > caller_data . cid_num . digits ,
span - > channels [ chan_id ] - > caller_data . ani . digits ,
span - > channels [ chan_id ] - > caller_data . aniII ,
span - > channels [ chan_id ] - > caller_data . dnis . digits ,
span - > channels [ chan_id ] - > caller_data . rdnis . digits ,
switch_channel_cause2str ( span - > channels [ chan_id ] - > caller_data . hangup_cause )
2008-04-01 13:29:57 -04:00
) ;
}
2009-07-31 15:16:47 -04:00
void dump_chan_xml ( zap_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream )
{
if ( chan_id > span - > chan_count ) {
return ;
}
stream - > write_function ( stream ,
" <channel> \n "
" <span-id>%u</span-id> \n "
" <chan-id>%u</chan-id>> \n "
" <physical-span-id>%u</physical-span-id> \n "
" <physical-chan-id>%u</physical-chan-id> \n "
" <type>%s</type> \n "
" <state>%s</state> \n "
" <last-state>%s</last-state> \n "
2010-03-12 17:47:50 -05:00
" <txgain>%3.2f</txgain> \n "
" <rxgain>%3.2f</rxgain> \n "
2009-07-31 15:16:47 -04:00
" <cid-date>%s</cid-date> \n "
" <cid-name>%s</cid-name> \n "
" <cid-num>%s</cid-num> \n "
" <ani>%s</ani> \n "
" <aniII>%s</aniII> \n "
" <dnis>%s</dnis> \n "
" <rdnis>%s</rdnis> \n "
" <cause>%s</cause> \n "
" </channel> \n " ,
span - > channels [ chan_id ] - > span_id ,
span - > channels [ chan_id ] - > chan_id ,
span - > channels [ chan_id ] - > physical_span_id ,
span - > channels [ chan_id ] - > physical_chan_id ,
zap_chan_type2str ( span - > channels [ chan_id ] - > type ) ,
zap_channel_state2str ( span - > channels [ chan_id ] - > state ) ,
zap_channel_state2str ( span - > channels [ chan_id ] - > last_state ) ,
2010-03-12 17:47:50 -05:00
span - > channels [ chan_id ] - > txgain ,
span - > channels [ chan_id ] - > rxgain ,
2009-07-31 15:16:47 -04:00
span - > channels [ chan_id ] - > caller_data . cid_date ,
span - > channels [ chan_id ] - > caller_data . cid_name ,
span - > channels [ chan_id ] - > caller_data . cid_num . digits ,
span - > channels [ chan_id ] - > caller_data . ani . digits ,
span - > channels [ chan_id ] - > caller_data . aniII ,
span - > channels [ chan_id ] - > caller_data . dnis . digits ,
span - > channels [ chan_id ] - > caller_data . rdnis . digits ,
switch_channel_cause2str ( span - > channels [ chan_id ] - > caller_data . hangup_cause )
) ;
}
2010-05-25 17:41:49 -04:00
# define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix] || gains <txgain> <rxgain> <span_id> [<chan_id>] || dtmf on|off <span_id> [<chan_id>]"
2008-04-01 13:29:57 -04:00
SWITCH_STANDARD_API ( oz_function )
{
char * mycmd = NULL , * argv [ 10 ] = { 0 } ;
int argc = 0 ;
2009-10-23 12:03:57 -04:00
if ( ! zstr ( cmd ) & & ( mycmd = strdup ( cmd ) ) ) {
2008-04-01 13:29:57 -04:00
argc = switch_separate_string ( mycmd , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
}
if ( ! argc ) {
stream - > write_function ( stream , " %s " , OZ_SYNTAX ) ;
goto end ;
}
if ( ! strcasecmp ( argv [ 0 ] , " dump " ) ) {
if ( argc < 2 ) {
stream - > write_function ( stream , " -ERR Usage: oz dump <span_id> [<chan_id>] \n " ) ;
goto end ;
} else {
2009-03-10 22:04:18 -04:00
uint32_t chan_id = 0 ;
2008-04-01 13:29:57 -04:00
zap_span_t * span ;
2009-07-31 15:16:47 -04:00
char * as = NULL ;
2009-03-10 22:04:18 -04:00
zap_span_find_by_name ( argv [ 1 ] , & span ) ;
2008-04-01 13:29:57 -04:00
if ( argc > 2 ) {
2009-07-31 15:16:47 -04:00
if ( argv [ 3 ] & & ! strcasecmp ( argv [ 2 ] , " as " ) ) {
as = argv [ 3 ] ;
} else {
chan_id = atoi ( argv [ 2 ] ) ;
}
2008-04-01 13:29:57 -04:00
}
2009-07-31 15:16:47 -04:00
if ( argv [ 4 ] & & ! strcasecmp ( argv [ 3 ] , " as " ) ) {
as = argv [ 4 ] ;
}
2009-10-23 12:03:57 -04:00
if ( ! zstr ( as ) & & ! strcasecmp ( as , " xml " ) ) {
2009-07-31 15:16:47 -04:00
stream - > write_function ( stream , " <channels> \n " ) ;
if ( ! span ) {
stream - > write_function ( stream , " <error>invalid span</error> \n " ) ;
} else {
if ( chan_id ) {
if ( chan_id > span - > chan_count ) {
stream - > write_function ( stream , " <error>invalid channel</error> \n " ) ;
} else {
dump_chan_xml ( span , chan_id , stream ) ;
}
2009-02-04 21:37:04 -05:00
} else {
2009-07-31 15:16:47 -04:00
uint32_t j ;
for ( j = 1 ; j < = span - > chan_count ; j + + ) {
dump_chan_xml ( span , j , stream ) ;
}
2009-02-04 21:37:04 -05:00
}
2009-07-31 15:16:47 -04:00
}
stream - > write_function ( stream , " </channels> \n " ) ;
} else {
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
2008-04-01 13:29:57 -04:00
} else {
2009-07-31 15:16:47 -04:00
if ( chan_id ) {
if ( chan_id > span - > chan_count ) {
stream - > write_function ( stream , " -ERR invalid channel \n " ) ;
} else {
dump_chan ( span , chan_id , stream ) ;
}
} else {
uint32_t j ;
stream - > write_function ( stream , " +OK \n " ) ;
for ( j = 1 ; j < = span - > chan_count ; j + + ) {
dump_chan ( span , j , stream ) ;
}
2008-04-01 13:29:57 -04:00
}
}
}
}
} else if ( ! strcasecmp ( argv [ 0 ] , " list " ) ) {
int j ;
for ( j = 0 ; j < ZAP_MAX_SPANS_INTERFACE ; j + + ) {
if ( SPAN_CONFIG [ j ] . span ) {
2009-01-13 17:45:09 -05:00
const char * flags = " none " ;
2008-04-01 13:29:57 -04:00
if ( SPAN_CONFIG [ j ] . analog_options & ANALOG_OPTION_3WAY ) {
flags = " 3way " ;
} else if ( SPAN_CONFIG [ j ] . analog_options & ANALOG_OPTION_CALL_SWAP ) {
flags = " call swap " ;
}
stream - > write_function ( stream ,
" +OK \n "
2008-10-24 15:53:56 -04:00
" span: %u (%s) \n "
2008-04-01 13:29:57 -04:00
" type: %s \n "
" chan_count: %u \n "
" dialplan: %s \n "
" context: %s \n "
" dial_regex: %s \n "
" fail_dial_regex: %s \n "
" hold_music: %s \n "
" analog_options %s \n " ,
j ,
2008-10-24 15:53:56 -04:00
SPAN_CONFIG [ j ] . span - > name ,
2008-04-01 13:29:57 -04:00
SPAN_CONFIG [ j ] . type ,
SPAN_CONFIG [ j ] . span - > chan_count ,
SPAN_CONFIG [ j ] . dialplan ,
SPAN_CONFIG [ j ] . context ,
SPAN_CONFIG [ j ] . dial_regex ,
SPAN_CONFIG [ j ] . fail_dial_regex ,
SPAN_CONFIG [ j ] . hold_music ,
flags
) ;
}
}
2009-03-10 22:04:18 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " stop " ) | | ! strcasecmp ( argv [ 0 ] , " start " ) ) {
char * span_name = argv [ 1 ] ;
zap_span_t * span = NULL ;
zap_status_t status ;
2009-01-05 20:07:09 -05:00
2009-03-10 22:04:18 -04:00
if ( span_name ) {
zap_span_find_by_name ( span_name , & span ) ;
}
2009-01-05 20:07:09 -05:00
2009-03-10 22:04:18 -04:00
if ( ! span ) {
stream - > write_function ( stream , " -ERR no span \n " ) ;
goto end ;
}
if ( ! strcasecmp ( argv [ 0 ] , " stop " ) ) {
status = zap_span_stop ( span ) ;
} else {
status = zap_span_start ( span ) ;
}
stream - > write_function ( stream , status = = ZAP_SUCCESS ? " +OK \n " : " -ERR failure \n " ) ;
goto end ;
2009-01-05 20:07:09 -05:00
2009-03-10 22:04:18 -04:00
/*Q931ToPcap enhancement*/
2009-01-30 06:37:11 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " q931_pcap " ) ) {
int32_t span_id = 0 ;
zap_span_t * span ;
2009-01-30 17:27:23 -05:00
const char * pcapfn = NULL ;
2009-01-30 06:37:11 -05:00
char * tmp_path = NULL ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: oz q931_pcap <span_id> on|off [pcapfilename without suffix] \n " ) ;
goto end ;
}
span_id = atoi ( argv [ 1 ] ) ;
if ( ! ( span_id & & ( span = SPAN_CONFIG [ span_id ] . span ) ) ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
/*Look for a given file name or use default file name*/
if ( argc > 3 ) {
if ( argv [ 3 ] ) {
pcapfn = argv [ 3 ] ;
}
}
else {
pcapfn = " q931 " ;
}
/*Add log directory path to file name*/
tmp_path = switch_mprintf ( " %s%s%s.pcap " , SWITCH_GLOBAL_dirs . log_dir , SWITCH_PATH_SEPARATOR , pcapfn ) ;
if ( ! strcasecmp ( argv [ 2 ] , " on " ) ) {
if ( zap_configure_span ( " isdn " , span , on_clear_channel_signal , " q931topcap " , 1 , " pcapfilename " , tmp_path , TAG_END ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_WARNING , " Error couldn't (re-)enable Q931-To-Pcap! \n " ) ;
goto end ;
} else {
stream - > write_function ( stream , " +OK \n " ) ;
}
} else if ( ! strcasecmp ( argv [ 2 ] , " off " ) ) {
if ( zap_configure_span ( " isdn " , span , on_clear_channel_signal , " q931topcap " , 0 , TAG_END ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Error couldn't enable Q931-To-Pcap! \n " ) ;
goto end ;
} else {
stream - > write_function ( stream , " +OK \n " ) ;
}
} else {
2009-07-17 10:07:55 -04:00
stream - > write_function ( stream , " -ERR Usage: oz q931_pcap <span_id> on|off [pcapfilename without suffix] \n " ) ;
2009-01-30 06:37:11 -05:00
goto end ;
}
2010-03-12 16:52:41 -05:00
} else if ( ! strcasecmp ( argv [ 0 ] , " gains " ) ) {
int i = 0 ;
float txgain = 0.0 ;
float rxgain = 0.0 ;
uint32_t chan_id = 0 ;
zap_span_t * span = NULL ;
if ( argc < 4 ) {
stream - > write_function ( stream , " -ERR Usage: oz gains <txgain> <rxgain> <span_id> [<chan_id>] \n " ) ;
goto end ;
}
zap_span_find_by_name ( argv [ 3 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 4 ) {
chan_id = atoi ( argv [ 4 ] ) ;
if ( chan_id > span - > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
i = sscanf ( argv [ 1 ] , " %f " , & rxgain ) ;
i + = sscanf ( argv [ 2 ] , " %f " , & txgain ) ;
if ( i ! = 2 ) {
stream - > write_function ( stream , " -ERR invalid gains \n " ) ;
goto end ;
}
if ( chan_id ) {
zap_channel_command ( span - > channels [ chan_id ] , ZAP_COMMAND_SET_RX_GAIN , & rxgain ) ;
zap_channel_command ( span - > channels [ chan_id ] , ZAP_COMMAND_SET_TX_GAIN , & txgain ) ;
} else {
2010-04-13 16:23:54 -04:00
for ( i = 1 ; i < = ( int ) span - > chan_count ; i + + ) {
2010-03-12 16:52:41 -05:00
zap_channel_command ( span - > channels [ i ] , ZAP_COMMAND_SET_RX_GAIN , & rxgain ) ;
zap_channel_command ( span - > channels [ i ] , ZAP_COMMAND_SET_TX_GAIN , & txgain ) ;
}
}
stream - > write_function ( stream , " +OK gains set to Rx %f and Tx %f \n " , rxgain , txgain ) ;
2010-05-25 17:41:49 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " dtmf " ) ) {
int i = 0 ;
uint32_t chan_id = 0 ;
zap_span_t * span = NULL ;
zap_command_t zapcmd = ZAP_COMMAND_ENABLE_DTMF_DETECT ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: dtmf on|off <span_id> [<chan_id>] \n " ) ;
goto end ;
}
if ( switch_true ( argv [ 1 ] ) ) {
zapcmd = ZAP_COMMAND_ENABLE_DTMF_DETECT ;
} else {
zapcmd = ZAP_COMMAND_DISABLE_DTMF_DETECT ;
}
zap_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > span - > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
if ( chan_id ) {
zap_channel_command ( span - > channels [ chan_id ] , zapcmd , NULL ) ;
} else {
for ( i = 1 ; i < = ( int ) span - > chan_count ; i + + ) {
zap_channel_command ( span - > channels [ i ] , zapcmd , NULL ) ;
}
}
stream - > write_function ( stream , " +OK DTMF detection was %s \n " , zapcmd = = ZAP_COMMAND_ENABLE_DTMF_DETECT ? " enabled " : " disabled " ) ;
2010-04-13 12:23:31 -04:00
} else if ( ! strcasecmp ( argv [ 0 ] , " trace " ) ) {
char tracepath [ 255 ] ;
int i = 0 ;
uint32_t chan_id = 0 ;
zap_span_t * span = NULL ;
if ( argc < 3 ) {
stream - > write_function ( stream , " -ERR Usage: oz trace <path> <span_id> [<chan_id>] \n " ) ;
goto end ;
}
zap_span_find_by_name ( argv [ 2 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 3 ) {
chan_id = atoi ( argv [ 3 ] ) ;
if ( chan_id > span - > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
if ( chan_id ) {
snprintf ( tracepath , sizeof ( tracepath ) , " %s-in-c%d " , argv [ 1 ] , chan_id ) ;
zap_channel_command ( span - > channels [ chan_id ] , ZAP_COMMAND_TRACE_INPUT , tracepath ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-out-c%d " , argv [ 1 ] , chan_id ) ;
zap_channel_command ( span - > channels [ chan_id ] , ZAP_COMMAND_TRACE_OUTPUT , tracepath ) ;
} else {
2010-04-13 16:23:54 -04:00
for ( i = 1 ; i < = ( int ) span - > chan_count ; i + + ) {
2010-04-13 12:23:31 -04:00
snprintf ( tracepath , sizeof ( tracepath ) , " %s-in-c%d " , argv [ 1 ] , i ) ;
zap_channel_command ( span - > channels [ i ] , ZAP_COMMAND_TRACE_INPUT , tracepath ) ;
snprintf ( tracepath , sizeof ( tracepath ) , " %s-out-c%d " , argv [ 1 ] , i ) ;
zap_channel_command ( span - > channels [ i ] , ZAP_COMMAND_TRACE_OUTPUT , tracepath ) ;
}
}
stream - > write_function ( stream , " +OK trace enabled with prefix path %s \n " , argv [ 1 ] ) ;
} else if ( ! strcasecmp ( argv [ 0 ] , " notrace " ) ) {
uint32_t i = 0 ;
uint32_t chan_id = 0 ;
zap_span_t * span = NULL ;
if ( argc < 2 ) {
stream - > write_function ( stream , " -ERR Usage: oz notrace <span_id> [<chan_id>] \n " ) ;
goto end ;
}
zap_span_find_by_name ( argv [ 1 ] , & span ) ;
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
goto end ;
}
if ( argc > 2 ) {
chan_id = atoi ( argv [ 2 ] ) ;
if ( chan_id > span - > chan_count ) {
stream - > write_function ( stream , " -ERR invalid chan \n " ) ;
goto end ;
}
}
if ( chan_id ) {
zap_channel_command ( span - > channels [ chan_id ] , ZAP_COMMAND_TRACE_END_ALL , NULL ) ;
} else {
2010-04-13 16:23:54 -04:00
for ( i = 1 ; i < = ( int ) span - > chan_count ; i + + ) {
2010-04-13 12:23:31 -04:00
zap_channel_command ( span - > channels [ i ] , ZAP_COMMAND_TRACE_END_ALL , NULL ) ;
}
}
stream - > write_function ( stream , " +OK trace disabled \n " ) ;
2008-04-01 13:29:57 -04:00
} else {
2009-02-09 14:13:02 -05:00
char * rply = zap_api_execute ( cmd , NULL ) ;
if ( rply ) {
stream - > write_function ( stream , " %s " , rply ) ;
free ( rply ) ;
} else {
stream - > write_function ( stream , " -ERR Usage: %s \n " , OZ_SYNTAX ) ;
}
2008-04-01 13:29:57 -04:00
}
2009-01-30 06:37:11 -05:00
/*Q931ToPcap enhancement done*/
2008-04-01 13:29:57 -04:00
end :
switch_safe_free ( mycmd ) ;
return SWITCH_STATUS_SUCCESS ;
}
2008-07-30 11:05:07 -04:00
SWITCH_STANDARD_APP ( disable_ec_function )
{
private_t * tech_pvt ;
int x = 0 ;
if ( ! switch_core_session_check_interface ( session , openzap_endpoint_interface ) ) {
zap_log ( ZAP_LOG_ERROR , " This application is only for OpenZAP channels. \n " ) ;
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
2010-02-01 10:36:32 -05:00
2010-02-01 18:26:34 -05:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
2010-02-01 10:36:32 -05:00
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
2008-07-30 11:05:07 -04:00
zap_channel_command ( tech_pvt - > zchan , ZAP_COMMAND_DISABLE_ECHOCANCEL , & x ) ;
zap_channel_command ( tech_pvt - > zchan , ZAP_COMMAND_DISABLE_ECHOTRAIN , & x ) ;
2009-07-20 10:27:59 -04:00
zap_log ( ZAP_LOG_INFO , " Echo Canceller Disabled \n " ) ;
2008-07-30 11:05:07 -04:00
}
2010-05-25 17:41:49 -04:00
SWITCH_STANDARD_APP ( disable_dtmf_function )
{
private_t * tech_pvt ;
if ( ! switch_core_session_check_interface ( session , openzap_endpoint_interface ) ) {
zap_log ( ZAP_LOG_ERROR , " This application is only for OpenZAP channels. \n " ) ;
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
zap_channel_command ( tech_pvt - > zchan , ZAP_COMMAND_DISABLE_DTMF_DETECT , NULL ) ;
zap_log ( ZAP_LOG_INFO , " DTMF detection Disabled in channel %d:%d \n " , tech_pvt - > zchan - > span_id , tech_pvt - > zchan - > chan_id ) ;
}
2010-05-26 11:10:13 -04:00
SWITCH_STANDARD_APP ( enable_dtmf_function )
{
private_t * tech_pvt ;
if ( ! switch_core_session_check_interface ( session , openzap_endpoint_interface ) ) {
zap_log ( ZAP_LOG_ERROR , " This application is only for OpenZAP channels. \n " ) ;
return ;
}
tech_pvt = switch_core_session_get_private ( session ) ;
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
switch_channel_hangup ( switch_core_session_get_channel ( session ) , SWITCH_CAUSE_LOSE_RACE ) ;
return ;
}
zap_channel_command ( tech_pvt - > zchan , ZAP_COMMAND_ENABLE_DTMF_DETECT , NULL ) ;
zap_log ( ZAP_LOG_INFO , " DTMF detection Enabled in channel %d:%d \n " , tech_pvt - > zchan - > span_id , tech_pvt - > zchan - > chan_id ) ;
}
2008-07-30 11:05:07 -04:00
2007-07-03 16:38:43 -04:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_openzap_load )
2007-05-26 00:45:31 -04:00
{
2008-04-01 13:29:57 -04:00
switch_api_interface_t * commands_api_interface ;
2008-07-30 11:05:07 -04:00
switch_application_interface_t * app_interface ;
2008-04-01 13:29:57 -04:00
2007-07-03 16:38:43 -04:00
module_pool = pool ;
2007-05-26 00:45:31 -04:00
zap_global_set_logger ( zap_logger ) ;
2010-03-12 15:08:30 -05:00
zap_cpu_monitor_disable ( ) ;
2007-05-26 00:45:31 -04:00
if ( zap_global_init ( ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Error loading OpenZAP \n " ) ;
return SWITCH_STATUS_TERM ;
}
if ( load_config ( ) ! = SWITCH_STATUS_SUCCESS ) {
zap_global_destroy ( ) ;
return SWITCH_STATUS_TERM ;
}
2007-07-03 16:38:43 -04:00
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
2007-10-29 14:10:25 -04:00
openzap_endpoint_interface = switch_loadable_module_create_interface ( * module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
openzap_endpoint_interface - > interface_name = " openzap " ;
openzap_endpoint_interface - > io_routines = & openzap_io_routines ;
openzap_endpoint_interface - > state_handler = & openzap_state_handlers ;
2008-04-01 13:29:57 -04:00
SWITCH_ADD_API ( commands_api_interface , " oz " , " OpenZAP commands " , oz_function , OZ_SYNTAX ) ;
2007-05-26 00:45:31 -04:00
2008-07-30 11:05:07 -04:00
SWITCH_ADD_APP ( app_interface , " disable_ec " , " Disable Echo Canceller " , " Disable Echo Canceller " , disable_ec_function , " " , SAF_NONE ) ;
2010-05-25 17:41:49 -04:00
SWITCH_ADD_APP ( app_interface , " disable_dtmf " , " Disable DTMF Detection " , " Disable DTMF Detection " , disable_dtmf_function , " " , SAF_NONE ) ;
2010-05-26 11:10:13 -04:00
SWITCH_ADD_APP ( app_interface , " enable_dtmf " , " Enable DTMF Detection " , " Enable DTMF Detection " , enable_dtmf_function , " " , SAF_NONE ) ;
2008-07-30 11:05:07 -04:00
2007-05-26 00:45:31 -04:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
2007-11-24 13:04:14 -05:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_openzap_shutdown )
{
zap_global_destroy ( ) ;
2009-02-07 18:14:25 -05:00
// this breaks pika but they are MIA so *shrug*
//return SWITCH_STATUS_NOUNLOAD;
return SWITCH_STATUS_SUCCESS ;
2007-11-24 13:04:14 -05:00
}
2007-05-26 00:45:31 -04:00
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2009-09-14 18:06:20 -04:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2007-05-26 00:45:31 -04:00
*/