2007-05-26 04:45:31 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 / 2006 , Anthony Minessale II < anthmct @ yahoo . com >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthmct @ yahoo . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Anthony Minessale II < anthmct @ yahoo . com >
2009-08-19 21:47:56 +00:00
* Moises Silva < moy @ sangoma . com >
2007-05-26 04:45:31 +00:00
*
*
* mod_openzap . c - - OPENZAP Endpoint Module
*
*/
# include <switch.h>
# include "openzap.h"
2008-02-18 15:43:54 +00:00
# ifndef __FUNCTION__
# define __FUNCTION__ __SWITCH_FUNC__
# endif
2008-10-06 19:13:32 +00:00
# define OPENZAP_VAR_PREFIX "openzap_"
# define OPENZAP_VAR_PREFIX_LEN 8
2007-07-03 20:38:43 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_openzap_load ) ;
2007-11-24 18:04:14 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_openzap_shutdown ) ;
SWITCH_MODULE_DEFINITION ( mod_openzap , mod_openzap_load , mod_openzap_shutdown , NULL ) ;
2007-07-03 20:38:43 +00:00
2007-10-29 18:10:25 +00:00
switch_endpoint_interface_t * openzap_endpoint_interface ;
2007-05-26 04:45:31 +00:00
static switch_memory_pool_t * module_pool = NULL ;
2008-01-25 16:42:06 +00:00
typedef enum {
ANALOG_OPTION_NONE = 0 ,
ANALOG_OPTION_3WAY = ( 1 < < 0 ) ,
ANALOG_OPTION_CALL_SWAP = ( 1 < < 1 )
} analog_option_t ;
2007-05-26 04:45:31 +00:00
struct span_config {
zap_span_t * span ;
char dialplan [ 80 ] ;
char context [ 80 ] ;
2007-11-24 18:04:14 +00:00
char dial_regex [ 256 ] ;
char fail_dial_regex [ 256 ] ;
2008-01-10 00:47:04 +00:00
char hold_music [ 256 ] ;
2008-04-01 17:29:57 +00:00
char type [ 256 ] ;
2008-01-25 16:42:06 +00:00
analog_option_t analog_options ;
2007-05-26 04:45:31 +00:00
} ;
2008-01-08 23:33:07 +00:00
static struct span_config SPAN_CONFIG [ ZAP_MAX_SPANS_INTERFACE ] = { { 0 } } ;
2007-05-26 04:45:31 +00:00
typedef enum {
TFLAG_IO = ( 1 < < 0 ) ,
2007-05-31 03:04:26 +00:00
TFLAG_DTMF = ( 1 < < 1 ) ,
TFLAG_CODEC = ( 1 < < 2 ) ,
TFLAG_BREAK = ( 1 < < 3 ) ,
2008-10-17 23:00:47 +00:00
TFLAG_HOLD = ( 1 < < 4 ) ,
TFLAG_DEAD = ( 1 < < 5 )
2007-05-26 04:45:31 +00:00
} TFLAGS ;
static struct {
int debug ;
char * dialplan ;
char * codec_string ;
char * codec_order [ SWITCH_MAX_CODECS ] ;
int codec_order_last ;
char * codec_rates_string ;
char * codec_rates [ SWITCH_MAX_CODECS ] ;
int codec_rates_last ;
unsigned int flags ;
int fd ;
int calls ;
2008-01-10 00:47:04 +00:00
char hold_music [ 256 ] ;
2007-05-26 04:45:31 +00:00
switch_mutex_t * mutex ;
2008-01-25 16:42:06 +00:00
analog_option_t analog_options ;
2007-05-26 04:45:31 +00: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 18:14:49 +00:00
switch_frame_t cng_frame ;
unsigned char cng_databuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
2007-05-26 04:45:31 +00:00
switch_core_session_t * session ;
switch_caller_profile_t * caller_profile ;
unsigned int codec ;
unsigned int codecs ;
unsigned short samprate ;
switch_mutex_t * mutex ;
switch_mutex_t * flag_mutex ;
zap_channel_t * zchan ;
2007-05-31 02:41:50 +00:00
uint32_t wr_error ;
2007-05-26 04:45:31 +00: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 19:03:03 +00:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session ) ;
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_routing ( switch_core_session_t * session ) ;
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session ) ;
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session ) ;
2008-05-15 19:43:58 +00:00
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
2007-05-26 04:45:31 +00:00
switch_caller_profile_t * outbound_profile ,
2008-01-08 23:33:07 +00:00
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
2009-11-20 02:17:21 +00:00
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause ) ;
2008-05-08 20:27:31 +00:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id ) ;
2007-05-26 04:45:31 +00:00
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig ) ;
2009-01-13 22:45:09 +00: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 19:16:47 +00:00
void dump_chan_xml ( zap_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream ) ;
2007-05-26 04:45:31 +00:00
2007-06-11 18:15:09 +00: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 16:03:57 +00:00
if ( ! zstr ( channel - > tokens [ id ] ) ) {
2008-01-10 00:47:04 +00:00
if ( ! ( session = switch_core_session_locate ( channel - > tokens [ id ] ) ) ) {
zap_channel_clear_token ( channel , channel - > tokens [ id ] ) ;
}
2007-06-11 18:15:09 +00:00
}
return session ;
}
2009-09-06 14:43:58 +00: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 16:03:57 +00:00
if ( ! zstr ( channel - > tokens [ id ] ) ) {
2009-09-06 14:43:58 +00:00
return channel - > tokens [ id ] ;
}
return NULL ;
}
2007-06-11 18:15:09 +00:00
2008-05-01 16:41:10 +00:00
static void stop_hold ( switch_core_session_t * session_a , const char * uuid )
2008-01-10 00:47:04 +00:00
{
switch_core_session_t * session ;
2008-05-01 16:41:10 +00:00
switch_channel_t * channel , * channel_a ;
;
2008-01-10 00:47:04 +00:00
if ( ! uuid ) {
return ;
}
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2008-05-01 16:41:10 +00:00
if ( switch_channel_test_flag ( channel , CF_HOLD ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_unhold ( session ) ;
switch_channel_clear_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_clear_flag ( channel_a , CF_HOLD ) ;
} else {
switch_channel_stop_broadcast ( channel ) ;
2008-09-09 19:17:38 +00:00
switch_channel_wait_for_flag ( channel , CF_BROADCAST , SWITCH_FALSE , 2000 , NULL ) ;
2008-05-01 16:41:10 +00:00
}
2008-04-30 15:17:55 +00:00
2008-01-10 00:47:04 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
2008-05-01 16:41:10 +00:00
static void start_hold ( zap_channel_t * zchan , switch_core_session_t * session_a , const char * uuid , const char * stream )
2008-01-10 00:47:04 +00:00
{
switch_core_session_t * session ;
2008-05-01 16:41:10 +00:00
switch_channel_t * channel , * channel_a ;
2008-01-10 00:47:04 +00:00
if ( ! uuid ) {
return ;
}
2008-05-01 16:41:10 +00:00
2008-01-10 00:47:04 +00:00
if ( ( session = switch_core_session_locate ( uuid ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
if ( ! strcasecmp ( globals . hold_music , " indicate_hold " ) ) {
stream = " indicate_hold " ;
}
if ( ! strcasecmp ( SPAN_CONFIG [ zchan - > span - > span_id ] . hold_music , " indicate_hold " ) ) {
stream = " indicate_hold " ;
}
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
stream = SPAN_CONFIG [ zchan - > span - > span_id ] . hold_music ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
stream = globals . hold_music ;
}
2008-01-10 00:47:04 +00:00
2009-10-23 16:03:57 +00:00
if ( zstr ( stream ) & & ! ( stream = switch_channel_get_variable ( channel , SWITCH_HOLD_MUSIC_VARIABLE ) ) ) {
2008-04-30 15:17:55 +00:00
stream = globals . hold_music ;
2008-01-10 00:47:04 +00:00
}
2009-10-23 16:03:57 +00:00
if ( ! zstr ( stream ) ) {
2008-05-01 16:41:10 +00:00
if ( ! strcasecmp ( stream , " indicate_hold " ) ) {
channel_a = switch_core_session_get_channel ( session_a ) ;
switch_ivr_hold_uuid ( uuid , NULL , 0 ) ;
switch_channel_set_flag ( channel_a , CF_SUSPEND ) ;
switch_channel_set_flag ( channel_a , CF_HOLD ) ;
} else {
switch_ivr_broadcast ( switch_core_session_get_uuid ( session ) , stream , SMF_ECHO_ALEG | SMF_LOOP ) ;
}
2008-01-10 00:47:04 +00:00
}
switch_core_session_rwunlock ( session ) ;
}
}
static void cycle_foreground ( zap_channel_t * zchan , int flash , const char * bcast ) {
2007-06-11 18:15:09 +00:00
uint32_t i = 0 ;
switch_core_session_t * session ;
switch_channel_t * channel ;
private_t * tech_pvt ;
2008-01-10 00:47:04 +00:00
2007-06-11 18:15:09 +00:00
for ( i = 0 ; i < zchan - > token_count ; i + + ) {
if ( ( session = zap_channel_get_session ( zchan , i ) ) ) {
2008-01-10 00:47:04 +00:00
const char * buuid ;
2007-06-11 18:15:09 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
channel = switch_core_session_get_channel ( session ) ;
2008-01-10 00:47:04 +00:00
buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ;
2007-06-11 18:15:09 +00:00
if ( zchan - > token_count = = 1 & & flash ) {
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
2007-06-11 18:15:09 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2008-05-01 16:41:10 +00:00
start_hold ( zchan , session , buuid , bcast ) ;
2007-06-11 18:15:09 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
} else if ( i ) {
2008-05-01 16:41:10 +00:00
start_hold ( zchan , session , buuid , bcast ) ;
2007-06-11 18:15:09 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
} else {
2008-05-01 16:41:10 +00:00
stop_hold ( session , buuid ) ;
2007-06-11 18:15:09 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
if ( ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
switch_channel_mark_answered ( channel ) ;
}
}
switch_core_session_rwunlock ( session ) ;
}
}
}
2007-05-26 04:45:31 +00:00
static switch_status_t tech_init ( private_t * tech_pvt , switch_core_session_t * session , zap_channel_t * zchan )
{
2009-01-13 22:45:09 +00:00
const char * dname = NULL ;
2007-05-26 04:45:31 +00:00
uint32_t interval = 0 , srate = 8000 ;
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 18:14:49 +00:00
tech_pvt - > cng_frame . data = tech_pvt - > cng_databuf ;
tech_pvt - > cng_frame . buflen = sizeof ( tech_pvt - > cng_databuf ) ;
2007-11-08 00:50:28 +00:00
tech_pvt - > cng_frame . flags = SFF_CNG ;
2008-01-10 00:47:04 +00:00
tech_pvt - > cng_frame . codec = & tech_pvt - > read_codec ;
2007-05-27 18:14:49 +00:00
memset ( tech_pvt - > cng_frame . data , 255 , tech_pvt - > cng_frame . buflen ) ;
2007-05-26 04:45:31 +00:00
switch_mutex_init ( & tech_pvt - > mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( session ) ) ;
switch_core_session_set_private ( session , tech_pvt ) ;
tech_pvt - > session = session ;
2009-09-14 21:19:07 +00: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 04:45:31 +00: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 23:33:07 +00:00
default :
2009-09-14 21:19:07 +00:00
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid codec value retrieved from channel, codec value: %d \n " , codec ) ;
return SWITCH_STATUS_GENERR ;
}
2007-05-26 04:45:31 +00:00
}
if ( switch_core_codec_init ( & tech_pvt - > read_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
return SWITCH_STATUS_GENERR ;
} else {
if ( switch_core_codec_init ( & tech_pvt - > write_codec ,
dname ,
NULL ,
srate ,
interval ,
1 ,
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE ,
NULL , switch_core_session_get_pool ( tech_pvt - > session ) ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Can't load codec? \n " ) ;
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
return SWITCH_STATUS_GENERR ;
}
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Set codec %s %dms \n " , dname , interval ) ;
switch_core_session_set_read_codec ( tech_pvt - > session , & tech_pvt - > read_codec ) ;
switch_core_session_set_write_codec ( tech_pvt - > session , & tech_pvt - > write_codec ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_CODEC ) ;
tech_pvt - > read_frame . codec = & tech_pvt - > read_codec ;
2008-10-17 23:00:47 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_init ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt = NULL ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2008-05-08 20:27:31 +00:00
/* Move channel's state machine to ROUTING */
2008-05-05 15:47:44 +00:00
switch_channel_set_state ( channel , CS_ROUTING ) ;
2007-05-26 04:45:31 +00:00
switch_mutex_lock ( globals . mutex ) ;
globals . calls + + ;
switch_mutex_unlock ( globals . mutex ) ;
2008-04-01 00:38:40 +00:00
zap_channel_init ( tech_pvt - > zchan ) ;
2008-10-03 21:03:21 +00:00
//switch_channel_set_flag(channel, CF_ACCEPT_CNG);
2008-10-03 18:15:04 +00:00
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_routing ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2008-06-05 14:09:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL ROUTING \n " , switch_channel_get_name ( channel ) ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_on_execute ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL EXECUTE \n " , switch_channel_get_name ( channel ) ) ;
return SWITCH_STATUS_SUCCESS ;
}
2009-04-14 19:03:03 +00:00
static switch_status_t channel_on_destroy ( switch_core_session_t * session )
{
private_t * tech_pvt = NULL ;
if ( ( tech_pvt = switch_core_session_get_private ( session ) ) ) {
if ( tech_pvt - > read_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > read_codec ) ;
}
if ( tech_pvt - > write_codec . implementation ) {
switch_core_codec_destroy ( & tech_pvt - > write_codec ) ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
static switch_status_t channel_on_hangup ( switch_core_session_t * session )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-06-11 18:15:09 +00:00
zap_channel_clear_token ( tech_pvt - > zchan , switch_core_session_get_uuid ( session ) ) ;
2007-05-26 04:45:31 +00:00
2007-05-27 14:58:01 +00:00
switch ( tech_pvt - > zchan - > type ) {
case ZAP_CHAN_TYPE_FXO :
2008-09-17 02:21:28 +00:00
case ZAP_CHAN_TYPE_EM :
2009-08-19 21:47:56 +00:00
case ZAP_CHAN_TYPE_CAS :
2007-05-31 20:15:16 +00:00
{
2007-11-17 01:39:28 +00:00
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_HANGUP ) ;
2007-05-31 20:15:16 +00:00
}
break ;
2007-05-27 14:58:01 +00:00
case ZAP_CHAN_TYPE_FXS :
{
2007-11-17 01:39:28 +00:00
if ( tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_BUSY & & tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_DOWN ) {
2007-06-11 18:15:09 +00:00
if ( tech_pvt - > zchan - > token_count ) {
2008-01-10 00:47:04 +00:00
cycle_foreground ( tech_pvt - > zchan , 0 , NULL ) ;
2007-06-11 18:15:09 +00:00
} else {
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_HANGUP ) ;
}
2007-05-27 14:58:01 +00:00
}
}
break ;
2007-06-13 03:37:55 +00:00
case ZAP_CHAN_TYPE_B :
{
2007-06-16 15:52:49 +00:00
if ( tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_DOWN & & tech_pvt - > zchan - > state ! = ZAP_CHANNEL_STATE_TERMINATING ) {
2008-09-24 21:26:44 +00:00
tech_pvt - > zchan - > caller_data . hangup_cause = switch_channel_get_cause_q850 ( channel ) ;
2008-08-11 16:09:39 +00:00
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 ;
}
2007-06-13 03:37:55 +00:00
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_HANGUP ) ;
}
}
break ;
2007-05-27 14:58:01 +00:00
default :
{
2009-09-22 15:45:41 +00: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 14:58:01 +00:00
}
break ;
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2007-05-26 04:45:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL HANGUP \n " , switch_channel_get_name ( channel ) ) ;
switch_mutex_lock ( globals . mutex ) ;
globals . calls - - ;
if ( globals . calls < 0 ) {
globals . calls = 0 ;
}
switch_mutex_unlock ( globals . mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t channel_kill_channel ( switch_core_session_t * session , int sig )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( sig ) {
case SWITCH_SIG_KILL :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
2008-10-17 23:00:47 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_DEAD ) ;
2007-05-26 04:45:31 +00:00
break ;
case SWITCH_SIG_BREAK :
switch_set_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_exchange_media ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
2008-05-05 15:47:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL EXCHANGE_MEDIA \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-05 15:47:44 +00:00
static switch_status_t channel_on_soft_execute ( switch_core_session_t * session )
2007-05-26 04:45:31 +00:00
{
2008-05-05 15:47:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL SOFT_EXECUTE \n " ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-12-22 02:16:03 +00:00
static switch_status_t channel_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2007-05-26 04:45:31 +00:00
{
private_t * tech_pvt = NULL ;
2007-12-22 02:16:03 +00:00
char tmp [ 2 ] = " " ;
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2007-12-22 02:16:03 +00:00
tmp [ 0 ] = dtmf - > digit ;
zap_channel_command ( tech_pvt - > zchan , ZAP_COMMAND_SEND_DTMF , tmp ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2008-05-08 20:27:31 +00:00
static switch_status_t channel_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
2008-01-10 01:15:04 +00:00
zap_size_t len ;
2007-05-26 04:45:31 +00:00
zap_wait_flag_t wflags = ZAP_READ ;
2007-05-27 05:23:28 +00:00
char dtmf [ 128 ] = " " ;
2007-05-26 04:45:31 +00:00
zap_status_t status ;
2008-05-08 20:27:31 +00:00
int total_to ;
2007-05-31 20:15:16 +00:00
int chunk , do_break = 0 ;
2007-05-26 04:45:31 +00:00
2009-02-07 23:14:25 +00:00
2007-05-26 04:45:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
2008-01-25 16:42:06 +00:00
2007-05-26 04:45:31 +00:00
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
assert ( tech_pvt - > zchan ! = NULL ) ;
2009-05-26 21:47:48 +00:00
/* Digium Cards sometimes timeout several times in a row here.
Yes , we support digium cards , ain ' t we nice . . . . . . .
6 double length intervals should compensate */
2007-05-31 02:41:50 +00:00
chunk = tech_pvt - > zchan - > effective_interval * 2 ;
2009-05-26 21:47:48 +00:00
total_to = chunk * 6 ;
2007-05-31 20:15:16 +00:00
2008-10-17 23:00:47 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
return SWITCH_STATUS_FALSE ;
}
2007-05-31 02:41:50 +00:00
top :
2007-05-31 20:15:16 +00:00
2008-05-08 20:27:31 +00:00
if ( switch_channel_test_flag ( channel , CF_SUSPEND ) ) {
do_break = 1 ;
}
2007-05-31 20:15:16 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_BREAK ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
do_break = 1 ;
}
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) | | do_break ) {
2007-05-27 18:14:49 +00: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 23:00:47 +00:00
tech_pvt - > cng_frame . flags = SFF_CNG ;
* frame = & tech_pvt - > cng_frame ;
2007-05-27 18:14:49 +00:00
if ( tech_pvt - > zchan - > effective_codec = = ZAP_CODEC_SLIN ) {
tech_pvt - > cng_frame . samples / = 2 ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-27 14:58:01 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2007-11-17 01:39:28 +00:00
wflags = ZAP_READ ;
2007-05-31 02:41:50 +00:00
status = zap_channel_wait ( tech_pvt - > zchan , & wflags , chunk ) ;
2007-11-17 01:39:28 +00:00
2007-05-26 04:45:31 +00:00
if ( status = = ZAP_FAIL ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2007-05-31 02:41:50 +00:00
2007-05-26 04:45:31 +00:00
if ( status = = ZAP_TIMEOUT ) {
2008-05-08 20:27:31 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
2007-05-31 02:41:50 +00:00
total_to - = chunk ;
if ( total_to < = 0 ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-31 02:41:50 +00:00
}
}
2007-05-31 20:15:16 +00:00
2007-05-31 02:41:50 +00:00
goto top ;
2007-05-26 04:45:31 +00:00
}
if ( ! ( wflags & ZAP_READ ) ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
len = tech_pvt - > read_frame . buflen ;
if ( zap_channel_read ( tech_pvt - > zchan , tech_pvt - > read_frame . data , & len ) ! = ZAP_SUCCESS ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
* frame = & tech_pvt - > read_frame ;
2009-03-06 18:17:15 +00:00
tech_pvt - > read_frame . datalen = ( uint32_t ) len ;
2007-05-26 04:45:31 +00:00
tech_pvt - > read_frame . samples = tech_pvt - > read_frame . datalen ;
if ( tech_pvt - > zchan - > effective_codec = = ZAP_CODEC_SLIN ) {
tech_pvt - > read_frame . samples / = 2 ;
}
if ( zap_channel_dequeue_dtmf ( tech_pvt - > zchan , dtmf , sizeof ( dtmf ) ) ) {
2007-12-22 02:16:03 +00:00
switch_dtmf_t _dtmf = { 0 , SWITCH_DEFAULT_DTMF_DURATION } ;
2008-01-12 06:11:48 +00:00
char * p ;
for ( p = dtmf ; p & & * p ; p + + ) {
if ( is_dtmf ( * p ) ) {
_dtmf . digit = * p ;
zap_log ( ZAP_LOG_DEBUG , " queue DTMF [%c] \n " , * p ) ;
switch_channel_queue_dtmf ( channel , & _dtmf ) ;
}
}
2007-05-26 04:45:31 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-17 01:39:28 +00:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 04:45:31 +00:00
}
2008-05-08 20:27:31 +00:00
static switch_status_t channel_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
2007-05-26 04:45:31 +00:00
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
zap_size_t len ;
2008-10-03 18:15:04 +00:00
unsigned char data [ SWITCH_RECOMMENDED_BUFFER_SIZE ] = { 0 } ;
2009-07-24 16:01:33 +00:00
zap_wait_flag_t wflags = ZAP_WRITE ;
zap_status_t status ;
2007-05-26 04:45:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
assert ( tech_pvt - > zchan ! = NULL ) ;
2008-10-17 23:00:47 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_DEAD ) ) {
return SWITCH_STATUS_FALSE ;
}
2007-05-27 18:14:49 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HOLD ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2007-05-26 04:45:31 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-26 04:45:31 +00:00
}
2007-05-31 02:41:50 +00:00
2008-10-03 18:15:04 +00:00
if ( switch_test_flag ( frame , SFF_CNG ) ) {
frame - > data = data ;
frame - > buflen = sizeof ( data ) ;
2008-10-20 18:10:37 +00:00
if ( ( frame - > datalen = tech_pvt - > write_codec . implementation - > encoded_bytes_per_packet ) > frame - > buflen ) {
2008-10-03 18:15:04 +00:00
goto fail ;
}
memset ( data , 255 , frame - > datalen ) ;
}
2009-07-24 16:01:33 +00:00
wflags = ZAP_WRITE ;
status = zap_channel_wait ( tech_pvt - > zchan , & wflags , tech_pvt - > zchan - > effective_interval * 4 ) ;
if ( ! ( wflags & ZAP_WRITE ) ) {
goto fail ;
}
2007-05-26 04:45:31 +00:00
len = frame - > datalen ;
2007-06-01 00:31:50 +00:00
if ( zap_channel_write ( tech_pvt - > zchan , frame - > data , frame - > buflen , & len ) ! = ZAP_SUCCESS ) {
2007-05-31 02:41:50 +00:00
if ( + + tech_pvt - > wr_error > 10 ) {
2007-11-17 01:39:28 +00:00
goto fail ;
2007-05-31 02:41:50 +00:00
}
2007-05-31 20:15:16 +00:00
} else {
tech_pvt - > wr_error = 0 ;
2007-05-26 04:45:31 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2007-11-17 01:39:28 +00:00
fail :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
return SWITCH_STATUS_GENERR ;
2007-05-26 04:45:31 +00:00
}
2009-08-19 21:47:56 +00:00
static switch_status_t channel_receive_message_cas ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
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 :
{
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
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 :
{
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
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 :
{
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
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 16:55:01 +00:00
2007-05-31 20:15:16 +00:00
static switch_status_t channel_receive_message_b ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
2007-06-13 03:37:55 +00:00
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( msg - > message_id ) {
2007-06-16 04:39:15 +00:00
case SWITCH_MESSAGE_INDICATE_RINGING :
2007-06-16 13:46:32 +00:00
{
2008-03-19 20:45:57 +00:00
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
} else {
2008-08-22 16:55:01 +00:00
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
2007-06-16 13:46:32 +00:00
}
2007-06-16 04:39:15 +00:00
}
2007-06-16 13:46:32 +00:00
break ;
2007-06-13 03:37:55 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
2007-06-16 13:46:32 +00:00
{
2008-03-19 20:45:57 +00:00
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_PROGRESS ) ;
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_MEDIA ) ;
} else {
2008-09-07 17:39:36 +00: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 ) {
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS ) ;
}
2008-08-22 16:55:01 +00:00
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_PROGRESS_MEDIA ) ;
2007-06-16 13:46:32 +00:00
}
2007-06-16 04:39:15 +00:00
}
2007-06-16 13:46:32 +00:00
break ;
2007-06-13 03:37:55 +00:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2007-06-16 13:46:32 +00:00
{
2008-03-19 20:45:57 +00:00
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
zap_set_flag_locked ( tech_pvt - > zchan , ZAP_CHANNEL_ANSWERED ) ;
} else {
2008-09-07 17:39:36 +00: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 ) {
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 ) ;
}
2008-08-22 16:55:01 +00:00
zap_set_state_locked_wait ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_UP ) ;
2007-06-16 13:46:32 +00:00
}
2007-06-13 03:37:55 +00:00
}
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
2007-05-31 20:15:16 +00:00
}
static switch_status_t channel_receive_message_fxo ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
2008-03-19 20:45:57 +00:00
if ( switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
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 20:15:16 +00: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 04:45:31 +00:00
{
switch_channel_t * channel ;
private_t * tech_pvt ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
switch ( msg - > message_id ) {
2007-05-31 20:15:16 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
2007-05-26 04:45:31 +00:00
case SWITCH_MESSAGE_INDICATE_ANSWER :
2008-09-26 17:29:48 +00:00
if ( ! switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
2008-03-19 20:45:57 +00: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 20:15:16 +00:00
zap_set_state_locked ( tech_pvt - > zchan , ZAP_CHANNEL_STATE_UP ) ;
2008-09-26 17:29:48 +00:00
switch_channel_mark_answered ( channel ) ;
2007-05-31 20:15:16 +00:00
}
2007-05-26 04:45:31 +00:00
break ;
case SWITCH_MESSAGE_INDICATE_RINGING :
2008-09-26 17:29:48 +00:00
if ( ! switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
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 17:09:10 +00:00
}
2007-05-26 04:45:31 +00:00
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
2007-05-31 20:15:16 +00:00
static switch_status_t channel_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
private_t * tech_pvt ;
2008-02-26 16:55:54 +00:00
switch_status_t status ;
2009-09-14 14:26:31 +00:00
switch_channel_t * channel ;
const char * var ;
2007-05-31 20:15:16 +00:00
tech_pvt = ( private_t * ) switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
2009-09-14 14:26:31 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch ( msg - > message_id ) {
case SWITCH_MESSAGE_INDICATE_PROGRESS :
case SWITCH_MESSAGE_INDICATE_ANSWER :
if ( ! switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
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 14:55:15 +00: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 14:26:31 +00:00
default :
break ;
}
2007-05-31 20:15:16 +00:00
switch ( tech_pvt - > zchan - > type ) {
case ZAP_CHAN_TYPE_FXS :
2008-09-17 02:21:28 +00:00
case ZAP_CHAN_TYPE_EM :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_fxs ( session , msg ) ;
2008-02-26 22:30:54 +00:00
break ;
2007-05-31 20:15:16 +00:00
case ZAP_CHAN_TYPE_FXO :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_fxo ( session , msg ) ;
2008-02-26 22:30:54 +00:00
break ;
2007-05-31 20:15:16 +00:00
case ZAP_CHAN_TYPE_B :
2008-02-26 16:55:54 +00:00
status = channel_receive_message_b ( session , msg ) ;
2009-08-19 21:47:56 +00:00
break ;
case ZAP_CHAN_TYPE_CAS :
status = channel_receive_message_cas ( session , msg ) ;
break ;
2007-05-31 20:15:16 +00:00
default :
2008-02-26 16:55:54 +00:00
status = SWITCH_STATUS_FALSE ;
2008-02-26 22:30:54 +00:00
break ;
2007-05-31 20:15:16 +00:00
}
2008-02-26 16:55:54 +00:00
return status ;
2007-05-31 20:15:16 +00:00
}
2007-10-29 18:10:25 +00:00
switch_state_handler_table_t openzap_state_handlers = {
2007-05-26 04:45:31 +00:00
/*.on_init */ channel_on_init ,
2008-05-05 15:47:44 +00:00
/*.on_routing */ channel_on_routing ,
2007-05-26 04:45:31 +00:00
/*.on_execute */ channel_on_execute ,
/*.on_hangup */ channel_on_hangup ,
2008-05-05 15:47:44 +00:00
/*.on_exchange_media */ channel_on_exchange_media ,
2009-04-14 19:03:03 +00:00
/*.on_soft_execute */ channel_on_soft_execute ,
/*.on_consume_media */ NULL ,
/*.on_hibernate */ NULL ,
/*.on_reset */ NULL ,
/*.on_park*/ NULL ,
/*.on_reporting*/ NULL ,
/*.on_destroy*/ channel_on_destroy
2007-05-26 04:45:31 +00:00
} ;
2007-10-29 18:10:25 +00:00
switch_io_routines_t openzap_io_routines = {
2007-05-26 04:45:31 +00:00
/*.outgoing_channel */ channel_outgoing_channel ,
/*.read_frame */ channel_read_frame ,
/*.write_frame */ channel_write_frame ,
/*.kill_channel */ channel_kill_channel ,
/*.send_dtmf */ channel_send_dtmf ,
/*.receive_message*/ channel_receive_message
} ;
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel ' s pool !
*/
2008-05-15 19:43:58 +00:00
static switch_call_cause_t channel_outgoing_channel ( switch_core_session_t * session , switch_event_t * var_event ,
2007-05-26 04:45:31 +00:00
switch_caller_profile_t * outbound_profile ,
2008-01-08 23:33:07 +00:00
switch_core_session_t * * new_session , switch_memory_pool_t * * pool ,
2009-11-20 02:17:21 +00:00
switch_originate_flag_t flags , switch_call_cause_t * cancel_cause )
2007-05-26 04:45:31 +00:00
{
2007-05-31 03:04:26 +00:00
2009-01-13 22:45:09 +00:00
const char * dest = NULL ;
char * data = NULL ;
2009-03-01 23:38:33 +00:00
int span_id = - 1 , chan_id = 0 ;
2007-05-31 03:04:26 +00:00
zap_channel_t * zchan = NULL ;
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
char name [ 128 ] ;
2007-05-31 20:15:16 +00:00
zap_status_t status ;
2008-01-25 15:05:37 +00:00
int direction = ZAP_TOP_DOWN ;
2008-02-29 00:21:04 +00:00
zap_caller_data_t caller_data = { { 0 } } ;
2008-10-06 15:57:11 +00:00
char * span_name = NULL ;
2008-10-06 19:13:32 +00:00
switch_event_header_t * h ;
2008-10-06 20:02:55 +00:00
char * argv [ 3 ] ;
int argc = 0 ;
2009-01-12 17:46:30 +00:00
const char * var ;
2009-01-12 17:50:26 +00:00
2008-02-29 00:21:04 +00:00
2007-05-31 03:04:26 +00:00
if ( ! outbound_profile ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing caller profile \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( outbound_profile - > destination_number ) ) {
2008-01-07 16:50:20 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-01-25 15:05:37 +00:00
2008-10-06 20:02:55 +00:00
data = switch_core_strdup ( outbound_profile - > pool , outbound_profile - > destination_number ) ;
2008-10-06 15:57:11 +00:00
2008-10-09 01:18:40 +00:00
if ( ( argc = switch_separate_string ( data , ' / ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) < 2 ) {
2008-10-06 20:02:55 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid dial string \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-10-06 15:57:11 +00:00
2008-10-06 20:02:55 +00:00
if ( switch_is_number ( argv [ 0 ] ) ) {
span_id = atoi ( argv [ 0 ] ) ;
} else {
span_name = argv [ 0 ] ;
}
if ( * argv [ 1 ] = = ' A ' ) {
direction = ZAP_BOTTOM_UP ;
} else if ( * argv [ 1 ] = = ' a ' ) {
direction = ZAP_TOP_DOWN ;
} else {
chan_id = atoi ( argv [ 1 ] ) ;
2007-05-31 03:04:26 +00:00
}
2008-02-02 16:48:20 +00:00
2008-10-09 01:18:40 +00:00
if ( ! ( dest = argv [ 2 ] ) ) {
dest = " " ;
}
2008-10-06 20:02:55 +00:00
2009-03-01 23:38:33 +00:00
if ( span_id = = 0 & & chan_id ! = 0 ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Span 0 is used to pick the first available span, selecting a channel is not supported (and doesn't make sense) \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2009-10-23 16:03:57 +00:00
if ( span_id = = - 1 & & ! zstr ( span_name ) ) {
2008-10-06 15:57:11 +00: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 23:38:33 +00:00
if ( span_id = = - 1 ) {
2007-05-31 03:04:26 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Missing span \n " ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
2008-01-25 15:05:37 +00:00
if ( chan_id < 0 ) {
direction = ZAP_BOTTOM_UP ;
chan_id = 0 ;
}
2008-03-01 00:48:36 +00:00
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_SCREEN ) ) {
caller_data . screen = 1 ;
}
if ( switch_test_flag ( outbound_profile , SWITCH_CPF_HIDE_NUMBER ) ) {
caller_data . pres = 1 ;
}
2009-10-23 16:03:57 +00:00
if ( ! zstr ( dest ) ) {
2008-03-01 00:48:36 +00:00
zap_set_string ( caller_data . ani . digits , dest ) ;
}
2009-01-12 17:46:30 +00:00
2009-01-12 18:05:22 +00:00
if ( ( var = switch_event_get_header ( var_event , " openzap_outbound_ton " ) ) | | ( var = switch_core_get_variable ( " openzap_outbound_ton " ) ) ) {
2009-01-12 17:46:30 +00:00
if ( ! strcasecmp ( var , " national " ) ) {
2009-04-08 21:58:51 +00:00
caller_data . ani . type = ZAP_TON_NATIONAL ;
2009-03-02 22:05:11 +00:00
} else if ( ! strcasecmp ( var , " international " ) ) {
2009-04-08 21:58:51 +00:00
caller_data . ani . type = ZAP_TON_INTERNATIONAL ;
2009-03-02 22:05:11 +00:00
} else if ( ! strcasecmp ( var , " local " ) ) {
2009-04-08 21:58:51 +00:00
caller_data . ani . type = ZAP_TON_SUBSCRIBER_NUMBER ;
2009-03-02 22:05:11 +00:00
} else if ( ! strcasecmp ( var , " unknown " ) ) {
2009-04-08 21:58:51 +00:00
caller_data . ani . type = ZAP_TON_UNKNOWN ;
2009-01-12 17:46:30 +00:00
}
} else {
caller_data . ani . type = outbound_profile - > destination_number_ton ;
}
2009-01-12 18:05:22 +00:00
2009-01-12 17:46:30 +00:00
caller_data . ani . plan = outbound_profile - > destination_number_numplan ;
2008-03-01 00:48:36 +00:00
2009-01-12 18:05:22 +00:00
2008-03-01 00:48:36 +00:00
#if 0
2009-10-23 16:03:57 +00:00
if ( ! zstr ( outbound_profile - > rdnis ) ) {
2008-03-01 00:48:36 +00:00
zap_set_string ( caller_data . rdnis . digits , outbound_profile - > rdnis ) ;
}
# endif
2008-01-25 15:05:37 +00:00
2008-02-29 00:21:04 +00:00
zap_set_string ( caller_data . cid_name , outbound_profile - > caller_id_name ) ;
2008-03-01 00:48:36 +00:00
zap_set_string ( caller_data . cid_num . digits , outbound_profile - > caller_id_number ) ;
2008-02-29 00:21:04 +00:00
2007-05-31 20:15:16 +00:00
if ( chan_id ) {
2008-01-25 15:05:37 +00:00
status = zap_channel_open ( span_id , chan_id , & zchan ) ;
2007-05-31 20:15:16 +00:00
} else {
2008-02-29 00:21:04 +00:00
status = zap_channel_open_any ( span_id , direction , & caller_data , & zchan ) ;
2007-05-31 20:15:16 +00:00
}
2007-06-11 18:15:09 +00:00
2007-05-31 20:15:16 +00:00
if ( status ! = ZAP_SUCCESS ) {
2007-05-31 03:04:26 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " No channels available \n " ) ;
2009-02-24 20:50:10 +00:00
return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION ;
2007-05-31 03:04:26 +00:00
}
2009-09-14 14:26:31 +00: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 19:13:32 +00: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 16:03:57 +00:00
if ( ! zstr ( v ) ) {
2008-10-06 19:13:32 +00:00
zap_channel_add_var ( zchan , v , h - > value ) ;
}
}
}
2009-02-24 05:05:25 +00:00
if ( ( * new_session = switch_core_session_request ( openzap_endpoint_interface , SWITCH_CALL_DIRECTION_OUTBOUND , pool ) ) ! = 0 ) {
2007-05-26 04:45:31 +00:00
private_t * tech_pvt ;
switch_caller_profile_t * caller_profile ;
2009-01-12 18:05:22 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( * new_session ) ;
2007-05-26 04:45:31 +00:00
switch_core_session_add_stream ( * new_session , NULL ) ;
if ( ( tech_pvt = ( private_t * ) switch_core_session_alloc ( * new_session , sizeof ( private_t ) ) ) ! = 0 ) {
2007-05-31 03:04:26 +00:00
tech_init ( tech_pvt , * new_session , zchan ) ;
2007-05-26 04:45:31 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Hey where is my memory pool? \n " ) ;
switch_core_session_destroy ( new_session ) ;
2007-05-31 03:04:26 +00:00
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto fail ;
2007-05-26 04:45:31 +00:00
}
2008-04-01 21:49:35 +00: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-31 03:04:26 +00:00
switch_channel_set_name ( channel , name ) ;
2009-03-12 15:27:29 +00: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 ) ;
2008-02-29 00:21:04 +00:00
zchan - > caller_data = caller_data ;
2007-05-31 03:04:26 +00:00
caller_profile = switch_caller_profile_clone ( * new_session , outbound_profile ) ;
switch_channel_set_caller_profile ( channel , caller_profile ) ;
tech_pvt - > caller_profile = caller_profile ;
2008-04-01 21:49:35 +00:00
2007-05-31 03:04:26 +00:00
2007-05-26 04:45:31 +00:00
switch_channel_set_flag ( channel , CF_OUTBOUND ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
2007-06-11 18:15:09 +00:00
if ( zap_channel_add_token ( zchan , switch_core_session_get_uuid ( * new_session ) , zchan - > token_count ) ! = ZAP_SUCCESS ) {
2007-05-31 20:15:16 +00:00
switch_core_session_destroy ( new_session ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto fail ;
}
2007-06-11 18:15:09 +00: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 14:30:45 +00:00
zap_channel_init ( zchan ) ;
2007-05-26 04:45:31 +00:00
return SWITCH_CAUSE_SUCCESS ;
}
2007-05-31 03:04:26 +00:00
fail :
2007-06-14 04:44:44 +00:00
2007-05-31 03:04:26 +00:00
if ( zchan ) {
zap_channel_done ( zchan ) ;
}
2007-06-14 04:44:44 +00:00
2007-05-31 03:04:26 +00:00
return cause ;
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00: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 16:57:32 +00:00
2007-05-27 14:58:01 +00:00
* sp = NULL ;
2009-02-24 05:05:25 +00:00
if ( ! ( session = switch_core_session_request ( openzap_endpoint_interface , SWITCH_CALL_DIRECTION_INBOUND , NULL ) ) ) {
2008-05-21 16:49:22 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Initilization Error! \n " ) ;
2007-05-27 14:58:01 +00: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 16:57:32 +00:00
2008-01-10 00:47:04 +00:00
* sigmsg - > channel - > caller_data . collected = ' \0 ' ;
2009-10-23 16:03:57 +00:00
if ( zstr ( sigmsg - > channel - > caller_data . cid_name ) ) {
2007-06-05 16:57:32 +00:00
switch_set_string ( sigmsg - > channel - > caller_data . cid_name , sigmsg - > channel - > chan_name ) ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( sigmsg - > channel - > caller_data . cid_num . digits ) ) {
if ( ! zstr ( sigmsg - > channel - > caller_data . ani . digits ) ) {
2008-03-01 00:48:36 +00:00
switch_set_string ( sigmsg - > channel - > caller_data . cid_num . digits , sigmsg - > channel - > caller_data . ani . digits ) ;
2007-06-05 16:57:32 +00:00
} else {
2008-03-01 00:48:36 +00:00
switch_set_string ( sigmsg - > channel - > caller_data . cid_num . digits , sigmsg - > channel - > chan_number ) ;
2007-06-05 16:57:32 +00:00
}
}
2007-11-17 01:39:28 +00:00
2007-05-27 14:58:01 +00:00
tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
" OpenZAP " ,
2007-05-31 20:15:16 +00:00
SPAN_CONFIG [ sigmsg - > channel - > span_id ] . dialplan ,
2007-06-05 16:57:32 +00:00
sigmsg - > channel - > caller_data . cid_name ,
2008-03-01 00:48:36 +00:00
sigmsg - > channel - > caller_data . cid_num . digits ,
2007-05-27 14:58:01 +00:00
NULL ,
2008-03-01 00:48:36 +00:00
sigmsg - > channel - > caller_data . ani . digits ,
2007-06-05 16:57:32 +00:00
sigmsg - > channel - > caller_data . aniII ,
2008-03-01 00:48:36 +00:00
sigmsg - > channel - > caller_data . rdnis . digits ,
2007-05-27 14:58:01 +00:00
( char * ) modname ,
2007-05-31 20:15:16 +00:00
SPAN_CONFIG [ sigmsg - > channel - > span_id ] . context ,
2008-03-01 00:48:36 +00:00
sigmsg - > channel - > caller_data . dnis . digits ) ;
2007-05-27 14:58:01 +00:00
assert ( tech_pvt - > caller_profile ! = NULL ) ;
2008-03-01 00:48:36 +00:00
if ( sigmsg - > channel - > caller_data . screen = = 1 | | sigmsg - > channel - > caller_data . screen = = 3 ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_SCREEN ) ;
}
if ( sigmsg - > channel - > caller_data . pres ) {
switch_set_flag ( tech_pvt - > caller_profile , SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER ) ;
}
2008-04-01 21:49:35 +00: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 14:58:01 +00:00
switch_channel_set_name ( channel , name ) ;
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
2009-03-12 15:27:29 +00:00
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 ) ;
2007-05-27 14:58:01 +00:00
switch_channel_set_state ( channel , CS_INIT ) ;
if ( switch_core_session_thread_launch ( session ) ! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error spawning thread \n " ) ;
switch_core_session_destroy ( & session ) ;
return ZAP_FAIL ;
}
2007-06-11 18:15:09 +00:00
if ( zap_channel_add_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) , 0 ) ! = ZAP_SUCCESS ) {
2008-05-21 16:49:22 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error adding token \n " ) ;
2007-05-27 18:14:49 +00:00
switch_core_session_destroy ( & session ) ;
return ZAP_FAIL ;
}
2007-05-27 14:58:01 +00:00
* sp = session ;
return ZAP_SUCCESS ;
}
2007-05-27 18:14:49 +00:00
2007-05-26 04:45:31 +00:00
static ZIO_SIGNAL_CB_FUNCTION ( on_fxo_signal )
{
2007-05-31 20:15:16 +00:00
switch_core_session_t * session = NULL ;
2007-06-01 00:31:50 +00:00
switch_channel_t * channel = NULL ;
2007-05-31 20:15:16 +00:00
zap_status_t status ;
2007-11-17 01:39:28 +00: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 20:15:16 +00:00
switch ( sigmsg - > event_id ) {
2007-11-17 01:39:28 +00: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-09-01 00:49:10 +00:00
switch_core_session_rwunlock ( session ) ;
2007-11-17 01:39:28 +00:00
}
}
break ;
case ZAP_SIGEVENT_STOP :
{
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
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 23:33:07 +00:00
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-11-17 01:39:28 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2007-06-01 00:31:50 +00: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 ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2007-05-31 20:15:16 +00: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 23:33:07 +00:00
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
sigmsg - > event_id , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-05-31 20:15:16 +00:00
}
2007-05-26 04:45:31 +00:00
return ZAP_SUCCESS ;
}
2007-05-27 14:58:01 +00:00
2007-05-26 04:45:31 +00:00
static ZIO_SIGNAL_CB_FUNCTION ( on_fxs_signal )
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2007-06-01 15:40:12 +00:00
zap_status_t status = ZAP_SUCCESS ;
2007-05-27 14:58:01 +00:00
2007-06-16 13:46:32 +00:00
zap_log ( ZAP_LOG_DEBUG , " got FXS sig [%s] \n " , zap_signal_event2str ( sigmsg - > event_id ) ) ;
2007-05-26 04:45:31 +00:00
2007-05-27 14:58:01 +00:00
switch ( sigmsg - > event_id ) {
2007-05-31 20:15:16 +00: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 ) ;
switch_core_session_rwunlock ( session ) ;
}
}
break ;
2008-09-11 17:55:27 +00: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 14:58:01 +00:00
case ZAP_SIGEVENT_START :
{
2008-01-25 16:42:06 +00:00
zap_clear_flag_locked ( sigmsg - > channel , ZAP_CHANNEL_HOLD ) ;
2007-05-27 14:58:01 +00: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 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
break ;
case ZAP_SIGEVENT_STOP :
{
2008-01-10 00:47:04 +00: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 16:03:57 +00:00
int digits = ! zstr ( sigmsg - > channel - > caller_data . collected ) ;
2008-01-10 00:47:04 +00:00
const char * br_a_uuid = NULL , * br_b_uuid = NULL ;
private_t * tech_pvt = NULL ;
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 16:41:10 +00:00
stop_hold ( session_a , switch_channel_get_variable ( channel_a , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-10 00:47:04 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
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 16:41:10 +00:00
stop_hold ( session_a , switch_channel_get_variable ( channel_b , SWITCH_SIGNAL_BOND_VARIABLE ) ) ;
2008-01-10 00:47:04 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_HOLD ) ;
}
if ( channel_a & & channel_b & & ! switch_channel_test_flag ( channel_a , CF_OUTBOUND ) & & ! switch_channel_test_flag ( channel_b , CF_OUTBOUND ) ) {
cause = SWITCH_CAUSE_ATTENDED_TRANSFER ;
if ( br_a_uuid & & br_b_uuid ) {
switch_ivr_uuid_bridge ( br_a_uuid , br_b_uuid ) ;
} else if ( br_a_uuid & & digits ) {
session_t = switch_core_session_locate ( br_a_uuid ) ;
} else if ( br_b_uuid & & digits ) {
session_t = switch_core_session_locate ( br_b_uuid ) ;
}
}
if ( session_t ) {
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 18:14:49 +00:00
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2008-01-10 00:47:04 +00:00
switch_channel_hangup ( channel , cause ) ;
2008-01-08 23:33:07 +00:00
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-05-27 18:14:49 +00:00
switch_core_session_rwunlock ( session ) ;
2007-05-27 14:58:01 +00:00
}
2008-01-10 00:47:04 +00:00
zap_channel_clear_token ( sigmsg - > channel , NULL ) ;
2007-05-26 04:45:31 +00:00
}
2007-05-27 14:58:01 +00:00
break ;
2007-05-26 04:45:31 +00:00
2008-01-10 00:47:04 +00:00
case ZAP_SIGEVENT_ADD_CALL :
{
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
}
break ;
2007-05-27 18:14:49 +00:00
case ZAP_SIGEVENT_FLASH :
{
2008-05-01 16:41:10 +00: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-10 00:47:04 +00: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 16:42:06 +00:00
} else if ( ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_CALL_SWAP )
| | ( SPAN_CONFIG [ sigmsg - > span_id ] . analog_options & ANALOG_OPTION_3WAY )
) {
2008-01-10 00:47:04 +00:00
cycle_foreground ( sigmsg - > channel , 1 , NULL ) ;
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 18:14:49 +00:00
}
break ;
2007-11-24 18:04:14 +00: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 16:03:57 +00:00
if ( zstr ( regex ) ) {
2007-11-24 18:04:14 +00:00
regex = NULL ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( fail_regex ) ) {
2007-11-24 18:04:14 +00:00
fail_regex = NULL ;
}
2008-02-18 16:15:24 +00:00
zap_log ( ZAP_LOG_DEBUG , " got DTMF sig [%s] \n " , dtmf ) ;
2008-01-10 00:47:04 +00:00
switch_set_string ( sigmsg - > channel - > caller_data . collected , dtmf ) ;
2009-10-23 16:03:57 +00:00
if ( ( regex | | fail_regex ) & & ! zstr ( dtmf ) ) {
2007-11-24 18:04:14 +00:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
match = switch_regex_perform ( dtmf , fail_regex , & re , ovector , sizeof ( ovector ) / sizeof ( ovector [ 0 ] ) ) ;
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 23:33:07 +00:00
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
sigmsg - > event_id , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
2007-05-27 14:58:01 +00:00
return status ;
2007-05-26 04:45:31 +00:00
}
2009-08-19 21:47:56 +00: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 ) ;
switch ( sigmsg - > event_id ) {
/* on_call_disconnect from the R2 side */
case ZAP_SIGEVENT_STOP :
{
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
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 16:03:57 +00:00
if ( zstr ( regex ) ) {
2009-08-19 21:47:56 +00:00
regex = NULL ;
}
2009-10-23 16:03:57 +00:00
if ( zstr ( fail_regex ) ) {
2009-08-19 21:47:56 +00:00
fail_regex = NULL ;
}
zap_log ( ZAP_LOG_DEBUG , " R2 DNIS so far [%s] \n " , sigmsg - > channel - > caller_data . dnis . digits ) ;
2009-10-23 16:03:57 +00:00
if ( ( regex | | fail_regex ) & & ! zstr ( sigmsg - > channel - > caller_data . dnis . digits ) ) {
2009-08-19 21:47:56 +00:00
switch_regex_t * re = NULL ;
int ovector [ 30 ] ;
int match = 0 ;
if ( fail_regex ) {
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 ) ) ) {
zap_tone_type_t tt = ZAP_TONE_DTMF ;
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
if ( zap_channel_command ( sigmsg - > channel , ZAP_COMMAND_ENABLE_DTMF_DETECT , & tt ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " Failed to enable DTMF detection in R2 channel %d:%d \n " , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
}
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-03-01 00:48:36 +00:00
static ZIO_SIGNAL_CB_FUNCTION ( on_clear_channel_signal )
2007-06-13 03:37:55 +00:00
{
switch_core_session_t * session = NULL ;
switch_channel_t * channel = NULL ;
2008-03-01 00:48:36 +00:00
zap_log ( ZAP_LOG_DEBUG , " got clear channel sig [%s] \n " , zap_signal_event2str ( sigmsg - > event_id ) ) ;
2007-06-13 03:37:55 +00:00
switch ( sigmsg - > event_id ) {
case ZAP_SIGEVENT_START :
{
2008-01-28 21:45:48 +00:00
zap_tone_type_t tt = ZAP_TONE_DTMF ;
2009-09-06 14:07:06 +00:00
2008-01-28 21:45:48 +00:00
if ( zap_channel_command ( sigmsg - > channel , ZAP_COMMAND_ENABLE_DTMF_DETECT , & tt ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " TONE ERROR \n " ) ;
}
2007-06-13 03:37:55 +00:00
return zap_channel_from_event ( sigmsg , & session ) ;
}
break ;
case ZAP_SIGEVENT_STOP :
2008-05-26 01:51:11 +00:00
case ZAP_SIGEVENT_RESTART :
2009-09-06 14:07:06 +00:00
{
2007-06-13 03:37:55 +00:00
while ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
channel = switch_core_session_get_channel ( session ) ;
2007-06-16 15:52:49 +00:00
switch_channel_hangup ( channel , sigmsg - > channel - > caller_data . hangup_cause ) ;
2008-01-08 23:33:07 +00:00
zap_channel_clear_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) ) ;
2007-06-13 03:37:55 +00:00
switch_core_session_rwunlock ( session ) ;
}
}
break ;
case ZAP_SIGEVENT_UP :
{
if ( ( session = zap_channel_get_session ( sigmsg - > channel , 0 ) ) ) {
2008-02-04 20:40:23 +00:00
zap_tone_type_t tt = ZAP_TONE_DTMF ;
2007-06-13 03:37:55 +00:00
channel = switch_core_session_get_channel ( session ) ;
switch_channel_mark_answered ( channel ) ;
2008-02-04 20:40:23 +00:00
if ( zap_channel_command ( sigmsg - > channel , ZAP_COMMAND_ENABLE_DTMF_DETECT , & tt ) ! = ZAP_SUCCESS ) {
zap_log ( ZAP_LOG_ERROR , " TONE ERROR \n " ) ;
}
2007-06-13 03:37:55 +00:00
switch_core_session_rwunlock ( session ) ;
2009-09-06 14:07:06 +00:00
} else {
2009-09-06 14:43:58 +00: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-13 03:37:55 +00:00
}
}
2007-06-16 04:39:15 +00: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 14:07:06 +00:00
} else {
2009-09-06 14:43:58 +00: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 04:39:15 +00: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 14:07:06 +00:00
} else {
2009-09-06 14:43:58 +00: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 04:39:15 +00:00
}
}
2007-06-13 03:37:55 +00:00
break ;
2008-01-08 23:33:07 +00:00
default :
{
2009-09-22 16:21:32 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled msg type %d for channel %d:%d \n " ,
2009-09-22 15:45:41 +00:00
sigmsg - > event_id , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2008-01-08 23:33:07 +00:00
}
break ;
2007-06-13 03:37:55 +00:00
}
return ZAP_SUCCESS ;
}
static ZIO_SIGNAL_CB_FUNCTION ( on_analog_signal )
2007-05-27 14:58:01 +00:00
{
2008-01-08 23:33:07 +00:00
switch_status_t status = SWITCH_STATUS_FALSE ;
2009-09-06 14:07:06 +00:00
2007-05-27 14:58:01 +00:00
switch ( sigmsg - > channel - > type ) {
case ZAP_CHAN_TYPE_FXO :
2008-09-17 02:21:28 +00:00
case ZAP_CHAN_TYPE_EM :
2007-05-27 14:58:01 +00:00
{
2007-11-24 18:04:14 +00:00
status = on_fxo_signal ( sigmsg ) ;
2007-05-27 14:58:01 +00:00
}
break ;
case ZAP_CHAN_TYPE_FXS :
{
2007-11-24 18:04:14 +00:00
status = on_fxs_signal ( sigmsg ) ;
2007-05-27 14:58:01 +00:00
}
break ;
default :
{
2009-09-22 15:45:41 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Unhandled analog channel type %d for channel %d:%d \n " ,
sigmsg - > channel - > type , sigmsg - > channel - > span_id , sigmsg - > channel - > chan_id ) ;
2007-05-27 14:58:01 +00:00
}
break ;
}
2007-06-01 15:40:12 +00:00
2007-11-24 18:04:14 +00:00
return status ;
2007-05-27 14:58:01 +00:00
}
2007-05-26 04:45:31 +00:00
2008-02-18 17:41:41 +00:00
static void zap_logger ( const char * file , const char * func , int line , int level , const char * fmt , . . . )
2007-05-26 04:45:31 +00:00
{
char * data = NULL ;
va_list ap ;
va_start ( ap , fmt ) ;
if ( switch_vasprintf ( & data , fmt , ap ) ! = - 1 ) {
2008-11-03 20:46:43 +00:00
switch_log_printf ( SWITCH_CHANNEL_ID_LOG , file , ( char * ) func , line , NULL , level , " %s " , data ) ;
2007-05-26 04:45:31 +00:00
free ( data ) ;
}
va_end ( ap ) ;
}
2008-01-25 16:42:06 +00:00
static uint32_t enable_analog_option ( const char * str , uint32_t current_options )
{
if ( ! strcasecmp ( str , " 3-way " ) ) {
current_options | = ANALOG_OPTION_3WAY ;
current_options & = ~ ANALOG_OPTION_CALL_SWAP ;
} else if ( ! strcasecmp ( str , " call-swap " ) ) {
current_options | = ANALOG_OPTION_CALL_SWAP ;
current_options & = ~ ANALOG_OPTION_3WAY ;
}
return current_options ;
}
2007-05-26 04:45:31 +00:00
static switch_status_t load_config ( void )
{
2009-01-13 22:45:09 +00:00
const char * cf = " openzap.conf " ;
2007-05-27 05:23:28 +00:00
switch_xml_t cfg , xml , settings , param , spans , myspan ;
2007-05-26 04:45:31 +00:00
memset ( & globals , 0 , sizeof ( globals ) ) ;
switch_mutex_init ( & globals . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " open of %s failed \n " , cf ) ;
return SWITCH_STATUS_TERM ;
}
if ( ( settings = switch_xml_child ( cfg , " settings " ) ) ) {
for ( param = switch_xml_child ( settings , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " debug " ) ) {
globals . debug = atoi ( val ) ;
2008-01-10 00:47:04 +00:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
switch_set_string ( globals . hold_music , val ) ;
2008-01-25 16:42:06 +00:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
globals . analog_options = enable_analog_option ( val , globals . analog_options ) ;
2007-05-26 04:45:31 +00:00
}
}
}
if ( ( spans = switch_xml_child ( cfg , " analog_spans " ) ) ) {
2007-05-27 05:23:28 +00:00
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
2008-09-26 15:36:34 +00:00
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
2008-09-26 17:09:10 +00:00
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2007-05-26 04:45:31 +00:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
2008-10-06 19:21:27 +00:00
char * hotline = NULL ;
2007-11-24 18:04:14 +00:00
char * dial_regex = NULL ;
2008-01-10 00:47:04 +00:00
char * hold_music = NULL ;
2007-11-24 18:04:14 +00:00
char * fail_dial_regex = NULL ;
2009-01-13 22:45:09 +00:00
const char * enable_callerid = " true " ;
2008-09-29 15:51:00 +00:00
2007-05-26 04:45:31 +00:00
uint32_t span_id = 0 , to = 0 , max = 0 ;
zap_span_t * span = NULL ;
2008-01-25 16:42:06 +00:00
analog_option_t analog_options = ANALOG_OPTION_NONE ;
2008-09-26 15:36:34 +00:00
2007-05-27 05:23:28 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
2007-05-26 04:45:31 +00:00
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
2007-05-26 04:45:31 +00:00
digit_timeout = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " dial-regex " ) ) {
dial_regex = val ;
2008-09-29 15:51:00 +00:00
} else if ( ! strcasecmp ( var , " enable-callerid " ) ) {
enable_callerid = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " fail-dial-regex " ) ) {
fail_dial_regex = val ;
2008-01-10 00:47:04 +00:00
} else if ( ! strcasecmp ( var , " hold-music " ) ) {
hold_music = val ;
2007-11-24 18:04:14 +00:00
} else if ( ! strcasecmp ( var , " max_digits " ) | | ! strcasecmp ( var , " max-digits " ) ) {
2008-09-08 23:01:44 +00:00
max_digits = val ;
2008-10-06 19:21:27 +00:00
} else if ( ! strcasecmp ( var , " hotline " ) ) {
hotline = val ;
2008-01-25 16:42:06 +00:00
} else if ( ! strcasecmp ( var , " enable-analog-option " ) ) {
analog_options = enable_analog_option ( val , analog_options ) ;
2007-05-26 04:45:31 +00:00
}
}
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2007-05-26 04:45:31 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
2008-08-29 20:41:17 +00:00
continue ;
2007-05-26 04:45:31 +00:00
}
2008-09-26 15:36:34 +00:00
2007-05-26 04:45:31 +00:00
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 15:36:34 +00:00
if ( name ) {
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 20:52:45 +00: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 04:45:31 +00:00
continue ;
}
2008-09-26 15:36:34 +00:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2007-05-26 04:45:31 +00:00
2008-08-29 15:58:59 +00:00
if ( zap_configure_span ( " analog " , span , on_analog_signal ,
" tonemap " , tonegroup ,
" digit_timeout " , & to ,
2008-08-29 20:41:17 +00:00
" max_dialstr " , & max ,
2008-10-06 19:21:27 +00:00
" hotline " , hotline ,
2008-09-29 15:51:00 +00:00
" enable_callerid " , enable_callerid ,
2008-08-29 20:41:17 +00:00
TAG_END ) ! = ZAP_SUCCESS ) {
2007-05-31 02:41:50 +00:00
zap_log ( ZAP_LOG_ERROR , " Error starting OpenZAP span %d \n " , span_id ) ;
2007-05-26 04:45:31 +00:00
continue ;
}
SPAN_CONFIG [ span - > span_id ] . span = span ;
2007-11-24 18:04:14 +00:00
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . context , context ) ;
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . dialplan , dialplan ) ;
2008-01-25 16:42:06 +00:00
SPAN_CONFIG [ span - > span_id ] . analog_options = analog_options | globals . analog_options ;
2007-11-24 18:04:14 +00: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 04:45:31 +00:00
2008-01-10 00:47:04 +00:00
if ( hold_music ) {
switch_set_string ( SPAN_CONFIG [ span - > span_id ] . hold_music , hold_music ) ;
}
2008-04-01 17:29:57 +00:00
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " analog " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
2008-08-29 15:58:59 +00:00
zap_span_start ( span ) ;
2007-05-26 04:45:31 +00:00
}
}
2008-09-17 02:21:28 +00:00
if ( ( spans = switch_xml_child ( cfg , " analog_em_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
const char * tonegroup = NULL ;
2008-09-17 02:21:28 +00:00
char * digit_timeout = NULL ;
char * max_digits = NULL ;
char * dial_regex = NULL ;
char * hold_music = NULL ;
char * fail_dial_regex = NULL ;
uint32_t span_id = 0 , to = 0 , max = 0 ;
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 17:09:10 +00:00
if ( ! id & & ! name ) {
2008-09-17 02:21:28 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
if ( max_digits ) {
max = atoi ( max_digits ) ;
}
2008-09-26 17:09:10 +00:00
if ( name ) {
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 20:52:45 +00: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-17 02:21:28 +00:00
continue ;
}
2008-09-26 17:09:10 +00:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2008-09-17 02:21:28 +00: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-13 03:37:55 +00:00
if ( ( spans = switch_xml_child ( cfg , " pri_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
2008-08-29 15:58:59 +00:00
//Q921NetUser_t mode = Q931_TE;
//Q931Dialect_t dialect = Q931_Dialect_National;
char * mode = NULL ;
char * dialect = NULL ;
2007-06-13 03:37:55 +00:00
uint32_t span_id = 0 ;
zap_span_t * span = NULL ;
2009-01-13 22:45:09 +00:00
const char * tonegroup = NULL ;
2008-10-12 22:07:45 +00:00
char * digit_timeout = NULL ;
2009-03-19 23:06:04 +00:00
const char * opts = " none " ;
2008-10-12 22:07:45 +00:00
uint32_t to = 0 ;
2008-10-03 21:57:57 +00:00
int q921loglevel = - 1 ;
int q931loglevel = - 1 ;
2009-01-06 01:07:09 +00:00
// quick debug
2009-01-30 11:37:11 +00:00
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ID: '%s', Name:'%s'\n",id,name);
2008-10-03 21:57:57 +00:00
2007-06-13 03:37:55 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " tonegroup " ) ) {
tonegroup = val ;
} else if ( ! strcasecmp ( var , " mode " ) ) {
2008-08-29 15:58:59 +00:00
mode = val ;
2007-06-13 03:37:55 +00:00
} else if ( ! strcasecmp ( var , " dialect " ) ) {
2008-08-29 15:58:59 +00:00
dialect = val ;
2008-10-03 21:57:57 +00:00
} else if ( ! strcasecmp ( var , " q921loglevel " ) ) {
if ( ( q921loglevel = switch_log_str2level ( val ) ) = = SWITCH_LOG_INVALID ) {
q921loglevel = - 1 ;
}
} else if ( ! strcasecmp ( var , " q931loglevel " ) ) {
if ( ( q931loglevel = switch_log_str2level ( val ) ) = = SWITCH_LOG_INVALID ) {
q931loglevel = - 1 ;
}
2007-06-13 03:37:55 +00:00
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
2009-03-19 23:06:04 +00:00
} else if ( ! strcasecmp ( var , " opts " ) ) {
opts = val ;
2007-06-13 03:37:55 +00:00
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
2008-10-12 22:07:45 +00:00
} else if ( ! strcasecmp ( var , " digit_timeout " ) | | ! strcasecmp ( var , " digit-timeout " ) ) {
digit_timeout = val ;
}
2007-06-13 03:37:55 +00:00
}
2008-10-03 21:57:57 +00:00
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2007-06-13 03:37:55 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
2008-02-29 00:21:04 +00:00
continue ;
2007-06-13 03:37:55 +00:00
}
2008-10-24 20:41:52 +00:00
2008-09-26 17:09:10 +00:00
if ( name ) {
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-13 03:37:55 +00:00
}
2008-09-26 17:09:10 +00:00
2008-10-12 22:07:45 +00:00
if ( digit_timeout ) {
to = atoi ( digit_timeout ) ;
}
2008-09-26 17:09:10 +00:00
if ( zstatus ! = ZAP_SUCCESS ) {
2008-10-24 20:52:45 +00: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-13 03:37:55 +00:00
continue ;
}
2009-01-30 11:37:11 +00:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2008-09-26 17:09:10 +00:00
if ( ! tonegroup ) {
tonegroup = " us " ;
}
2008-08-29 15:58:59 +00:00
if ( zap_configure_span ( " isdn " , span , on_clear_channel_signal ,
2008-10-12 22:07:45 +00:00
" mode " , mode ,
2008-08-29 20:41:17 +00:00
" dialect " , dialect ,
2008-10-12 22:07:45 +00:00
" digit_timeout " , & to ,
2008-10-07 15:27:51 +00:00
" opts " , opts ,
2008-10-03 21:57:57 +00:00
" q921loglevel " , q921loglevel ,
" q931loglevel " , q931loglevel ,
2008-08-29 20:41:17 +00:00
TAG_END ) ! = ZAP_SUCCESS ) {
2009-01-09 22:11:04 +00: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-13 03:37:55 +00: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 17:29:57 +00:00
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " isdn " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
2007-06-13 03:37:55 +00:00
2008-08-29 15:58:59 +00:00
zap_span_start ( span ) ;
2007-06-13 03:37:55 +00:00
}
}
2009-02-07 23:14:25 +00:00
if ( ( spans = switch_xml_child ( cfg , " libpri_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
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 20:15:39 +00:00
const char * o_debug = " none " ;
const char * opts = " none " ;
2009-02-07 23:14:25 +00:00
uint32_t span_id = 0 ;
zap_span_t * span = NULL ;
2009-03-19 20:15:39 +00:00
2009-02-07 23:14:25 +00:00
for ( param = switch_xml_child ( myspan , " param " ) ; param ; param = param - > next ) {
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( ! strcasecmp ( var , " node " ) ) {
o_node = val ;
} else if ( ! strcasecmp ( var , " switch " ) ) {
o_switch = val ;
} else if ( ! strcasecmp ( var , " dp " ) ) {
o_dp = val ;
} else if ( ! strcasecmp ( var , " l1 " ) ) {
o_l1 = val ;
} else if ( ! strcasecmp ( var , " debug " ) ) {
o_debug = val ;
} else if ( ! strcasecmp ( var , " context " ) ) {
context = val ;
2009-03-19 20:15:39 +00:00
} else if ( ! strcasecmp ( var , " opts " ) ) {
opts = val ;
2009-02-07 23:14:25 +00:00
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
}
}
if ( ! id & & ! name ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param 'id' \n " ) ;
continue ;
}
if ( name ) {
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-29 00:21:04 +00:00
if ( ( spans = switch_xml_child ( cfg , " boost_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
2008-09-26 17:09:10 +00:00
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
zap_status_t zstatus = ZAP_FAIL ;
2009-01-13 22:45:09 +00:00
const char * context = " default " ;
const char * dialplan = " XML " ;
2008-02-29 00:21:04 +00:00
uint32_t span_id = 0 ;
zap_span_t * span = NULL ;
2009-01-13 22:45:09 +00:00
const char * tonegroup = NULL ;
2008-02-29 00:21:04 +00: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 ;
} else if ( ! strcasecmp ( var , " dialplan " ) ) {
dialplan = val ;
}
}
2008-09-26 17:09:10 +00:00
if ( ! id & & ! name ) {
2008-02-29 00:21:04 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " span missing required param \n " ) ;
continue ;
}
if ( ! tonegroup ) {
tonegroup = " us " ;
}
2008-09-26 17:09:10 +00: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 20:52:45 +00: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-29 00:21:04 +00:00
continue ;
}
2008-09-26 17:09:10 +00:00
if ( ! span_id ) {
span_id = span - > span_id ;
}
2008-02-29 00:21:04 +00:00
2009-09-02 17:28:56 +00:00
if ( zap_configure_span ( " sangoma_boost " , span , on_clear_channel_signal ,
2008-08-29 15:58:59 +00:00
" local_ip " , local_ip ,
" local_port " , & local_port ,
" remote_ip " , remote_ip ,
2008-08-29 20:41:17 +00:00
" remote_port " , & remote_port ,
TAG_END ) ! = ZAP_SUCCESS ) {
2008-02-29 00:21:04 +00: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 15:58:59 +00:00
zap_span_start ( span ) ;
2009-09-02 17:28:56 +00:00
switch_copy_string ( SPAN_CONFIG [ span - > span_id ] . type , " Sangoma (boost) " , sizeof ( SPAN_CONFIG [ span - > span_id ] . type ) ) ;
2008-02-29 00:21:04 +00:00
}
}
2009-08-19 21:47:56 +00:00
if ( ( spans = switch_xml_child ( cfg , " r2_spans " ) ) ) {
for ( myspan = switch_xml_child ( spans , " span " ) ; myspan ; myspan = myspan - > next ) {
char * id = ( char * ) switch_xml_attr ( myspan , " id " ) ;
char * name = ( char * ) switch_xml_attr ( myspan , " name " ) ;
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-29 00:21:04 +00:00
2009-08-19 21:47:56 +00: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 04:45:31 +00:00
switch_xml_free ( xml ) ;
return SWITCH_STATUS_SUCCESS ;
}
2008-04-01 17:29:57 +00:00
void dump_chan ( zap_span_t * span , uint32_t chan_id , switch_stream_handle_t * stream )
{
2009-02-04 23:11:41 +00:00
if ( chan_id > span - > chan_count ) {
return ;
}
2008-04-01 17:29:57 +00:00
stream - > write_function ( stream ,
" span_id: %u \n "
" chan_id: %u \n "
" physical_span_id: %u \n "
" physical_chan_id: %u \n "
" type: %s \n "
" state: %s \n "
" last_state: %s \n "
" 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 15:25:02 +00: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 ) ,
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 17:29:57 +00:00
) ;
}
2009-07-31 19:16:47 +00: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 "
" <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 ) ,
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 )
) ;
}
2009-03-18 18:09:01 +00:00
# define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix]"
2008-04-01 17:29:57 +00:00
SWITCH_STANDARD_API ( oz_function )
{
char * mycmd = NULL , * argv [ 10 ] = { 0 } ;
int argc = 0 ;
2009-10-23 16:03:57 +00:00
if ( ! zstr ( cmd ) & & ( mycmd = strdup ( cmd ) ) ) {
2008-04-01 17:29:57 +00:00
argc = switch_separate_string ( mycmd , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
}
if ( ! argc ) {
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-11 02:04:18 +00:00
uint32_t chan_id = 0 ;
2008-04-01 17:29:57 +00:00
zap_span_t * span ;
2009-07-31 19:16:47 +00:00
char * as = NULL ;
2009-03-11 02:04:18 +00:00
zap_span_find_by_name ( argv [ 1 ] , & span ) ;
2008-04-01 17:29:57 +00:00
if ( argc > 2 ) {
2009-07-31 19:16:47 +00:00
if ( argv [ 3 ] & & ! strcasecmp ( argv [ 2 ] , " as " ) ) {
as = argv [ 3 ] ;
} else {
chan_id = atoi ( argv [ 2 ] ) ;
}
2008-04-01 17:29:57 +00:00
}
2009-07-31 19:16:47 +00:00
if ( argv [ 4 ] & & ! strcasecmp ( argv [ 3 ] , " as " ) ) {
as = argv [ 4 ] ;
}
2009-10-23 16:03:57 +00:00
if ( ! zstr ( as ) & & ! strcasecmp ( as , " xml " ) ) {
2009-07-31 19:16:47 +00:00
stream - > write_function ( stream , " <channels> \n " ) ;
if ( ! span ) {
stream - > write_function ( stream , " <error>invalid span</error> \n " ) ;
} else {
if ( chan_id ) {
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-05 02:37:04 +00:00
} else {
2009-07-31 19:16:47 +00:00
uint32_t j ;
for ( j = 1 ; j < = span - > chan_count ; j + + ) {
dump_chan_xml ( span , j , stream ) ;
}
2009-02-05 02:37:04 +00:00
}
2009-07-31 19:16:47 +00:00
}
stream - > write_function ( stream , " </channels> \n " ) ;
} else {
if ( ! span ) {
stream - > write_function ( stream , " -ERR invalid span \n " ) ;
2008-04-01 17:29:57 +00:00
} else {
2009-07-31 19:16:47 +00:00
if ( chan_id ) {
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 17:29:57 +00: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 22:45:09 +00:00
const char * flags = " none " ;
2008-04-01 17:29:57 +00:00
if ( SPAN_CONFIG [ j ] . analog_options & ANALOG_OPTION_3WAY ) {
flags = " 3way " ;
} else if ( SPAN_CONFIG [ j ] . analog_options & ANALOG_OPTION_CALL_SWAP ) {
flags = " call swap " ;
}
stream - > write_function ( stream ,
" +OK \n "
2008-10-24 19:53:56 +00:00
" span: %u (%s) \n "
2008-04-01 17:29:57 +00: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 19:53:56 +00:00
SPAN_CONFIG [ j ] . span - > name ,
2008-04-01 17:29:57 +00: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-11 02:04:18 +00: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-06 01:07:09 +00:00
2009-03-11 02:04:18 +00:00
if ( span_name ) {
zap_span_find_by_name ( span_name , & span ) ;
}
2009-01-06 01:07:09 +00:00
2009-03-11 02:04:18 +00:00
if ( ! span ) {
stream - > write_function ( stream , " -ERR no span \n " ) ;
goto end ;
}
if ( ! strcasecmp ( argv [ 0 ] , " stop " ) ) {
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-06 01:07:09 +00:00
2009-03-11 02:04:18 +00:00
/*Q931ToPcap enhancement*/
2009-01-30 11:37:11 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " q931_pcap " ) ) {
int32_t span_id = 0 ;
zap_span_t * span ;
2009-01-30 22:27:23 +00:00
const char * pcapfn = NULL ;
2009-01-30 11:37:11 +00:00
char * tmp_path = NULL ;
if ( argc < 3 ) {
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 14:07:55 +00:00
stream - > write_function ( stream , " -ERR Usage: oz q931_pcap <span_id> on|off [pcapfilename without suffix] \n " ) ;
2009-01-30 11:37:11 +00:00
goto end ;
}
2008-04-01 17:29:57 +00:00
} else {
2009-02-09 19:13:02 +00: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 17:29:57 +00:00
}
2009-01-30 11:37:11 +00:00
/*Q931ToPcap enhancement done*/
2008-04-01 17:29:57 +00:00
end :
switch_safe_free ( mycmd ) ;
return SWITCH_STATUS_SUCCESS ;
}
2008-07-30 15:05:07 +00: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 ) ;
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 14:27:59 +00:00
zap_log ( ZAP_LOG_INFO , " Echo Canceller Disabled \n " ) ;
2008-07-30 15:05:07 +00:00
}
2007-07-03 20:38:43 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_openzap_load )
2007-05-26 04:45:31 +00:00
{
2008-04-01 17:29:57 +00:00
switch_api_interface_t * commands_api_interface ;
2008-07-30 15:05:07 +00:00
switch_application_interface_t * app_interface ;
2008-04-01 17:29:57 +00:00
2007-07-03 20:38:43 +00:00
module_pool = pool ;
2007-05-26 04:45:31 +00:00
zap_global_set_logger ( zap_logger ) ;
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 20:38:43 +00:00
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
2007-10-29 18:10:25 +00: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 17:29:57 +00:00
SWITCH_ADD_API ( commands_api_interface , " oz " , " OpenZAP commands " , oz_function , OZ_SYNTAX ) ;
2007-05-26 04:45:31 +00:00
2008-07-30 15:05:07 +00:00
SWITCH_ADD_APP ( app_interface , " disable_ec " , " Disable Echo Canceller " , " Disable Echo Canceller " , disable_ec_function , " " , SAF_NONE ) ;
2007-05-26 04:45:31 +00:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
2007-11-24 18:04:14 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_openzap_shutdown )
{
zap_global_destroy ( ) ;
2009-02-07 23:14:25 +00:00
// this breaks pika but they are MIA so *shrug*
//return SWITCH_STATUS_NOUNLOAD;
return SWITCH_STATUS_SUCCESS ;
2007-11-24 18:04:14 +00:00
}
2007-05-26 04:45:31 +00:00
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2009-09-14 22:06:20 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2007-05-26 04:45:31 +00:00
*/