2008-09-17 16:33:43 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 / 2008 , 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 >
* Steve Underwood 0.0 .1 < steveu @ coppice . org >
*
*
* mod_unicall . c - - UniCall endpoint module
*
*/
/* This is a work in progress. Unfinished. Non-functional */
# include <switch.h>
# include <unicall.h>
SWITCH_MODULE_LOAD_FUNCTION ( mod_unicall_load ) ;
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_unicall_shutdown ) ;
//SWITCH_MODULE_RUNTIME_FUNCTION(mod_unicall_runtime);
SWITCH_MODULE_DEFINITION ( mod_unicall , mod_unicall_load , mod_unicall_shutdown , NULL ) ; //mod_unicall_runtime);
# define MAX_SPANS 128
switch_endpoint_interface_t * unicall_endpoint_interface ;
static switch_memory_pool_t * module_pool = NULL ;
static volatile int running = 1 ;
typedef struct
{
int span ;
const char * id ;
const char * protocol_class ;
const char * protocol_variant ;
int protocol_end ;
int outgoing_ok ;
char * dialplan ;
int fd ;
uc_t * uc ;
} span_data_t ;
span_data_t * span_data [ MAX_SPANS ] ;
typedef enum {
TFLAG_IO = ( 1 < < 0 ) ,
TFLAG_INBOUND = ( 1 < < 1 ) ,
TFLAG_OUTBOUND = ( 1 < < 2 ) ,
TFLAG_DTMF = ( 1 < < 3 ) ,
TFLAG_VOICE = ( 1 < < 4 ) ,
TFLAG_HANGUP = ( 1 < < 5 ) ,
TFLAG_LINEAR = ( 1 < < 6 ) ,
TFLAG_CODEC = ( 1 < < 7 ) ,
TFLAG_BREAK = ( 1 < < 8 )
} TFLAGS ;
typedef enum {
GFLAG_MY_CODEC_PREFS = ( 1 < < 0 )
} GFLAGS ;
static struct
{
int debug ;
/*! Requested frame duration, in ms */
uint32_t frame_duration ;
int dtmf_on ;
int dtmf_off ;
int suppress_dtmf_tone ;
int ignore_dtmf_tone ;
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 calls ;
int configured_spans ;
switch_hash_t * call_hash ;
switch_mutex_t * mutex ;
switch_mutex_t * hash_mutex ;
switch_mutex_t * channel_mutex ;
} globals ;
typedef struct
{
unsigned int flags ;
switch_codec_t read_codec ;
switch_codec_t write_codec ;
switch_frame_t read_frame ;
uint8_t databuf [ SWITCH_RECOMMENDED_BUFFER_SIZE ] ;
switch_core_session_t * session ;
switch_caller_profile_t * caller_profile ;
switch_mutex_t * mutex ;
switch_mutex_t * flag_mutex ;
//switch_thread_cond_t *cond;
uc_t * uc ;
} private_t ;
SWITCH_DECLARE_GLOBAL_STRING_FUNC ( set_global_dialplan , globals . dialplan ) ;
static switch_status_t unicall_on_init ( switch_core_session_t * session ) ;
static switch_status_t unicall_on_routing ( switch_core_session_t * session ) ;
static switch_status_t unicall_on_execute ( switch_core_session_t * session ) ;
static switch_status_t unicall_on_hangup ( switch_core_session_t * session ) ;
static switch_status_t unicall_on_exchange_media ( switch_core_session_t * session ) ;
static switch_status_t unicall_on_soft_execute ( switch_core_session_t * session ) ;
static switch_call_cause_t unicall_outgoing_channel ( switch_core_session_t * session ,
switch_event_t * var_event ,
switch_caller_profile_t * outbound_profile ,
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
switch_originate_flag_t flags ) ;
static switch_status_t unicall_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t unicall_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t unicall_kill_channel ( switch_core_session_t * session , int sig ) ;
static switch_status_t unicall_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf ) ;
static switch_status_t unicall_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg ) ;
static switch_status_t unicall_receive_event ( switch_core_session_t * session , switch_event_t * event ) ;
#if 0
static switch_call_cause_t unicall_incoming_channel ( 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 ] ;
* sp = NULL ;
if ( ! ( session = switch_core_session_request ( openzap_endpoint_interface , NULL ) ) )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Initilization Error! \n " ) ;
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 ;
}
* sigmsg - > channel - > caller_data . collected = ' \0 ' ;
if ( switch_strlen_zero ( sigmsg - > channel - > caller_data . cid_name ) )
{
switch_set_string ( sigmsg - > channel - > caller_data . cid_name , sigmsg - > channel - > chan_name ) ;
}
if ( switch_strlen_zero ( sigmsg - > channel - > caller_data . cid_num . digits ) )
{
if ( ! switch_strlen_zero ( sigmsg - > channel - > caller_data . ani . digits ) )
{
switch_set_string ( sigmsg - > channel - > caller_data . cid_num . digits , sigmsg - > channel - > caller_data . ani . digits ) ;
}
else
{
switch_set_string ( sigmsg - > channel - > caller_data . cid_num . digits , sigmsg - > channel - > chan_number ) ;
}
}
tech_pvt - > caller_profile = switch_caller_profile_new ( switch_core_session_get_pool ( session ) ,
" UniCall " ,
SPAN_CONFIG [ sigmsg - > channel - > span_id ] . dialplan ,
sigmsg - > channel - > caller_data . cid_name ,
sigmsg - > channel - > caller_data . cid_num . digits ,
NULL ,
sigmsg - > channel - > caller_data . ani . digits ,
sigmsg - > channel - > caller_data . aniII ,
sigmsg - > channel - > caller_data . rdnis . digits ,
( char * ) modname ,
SPAN_CONFIG [ sigmsg - > channel - > span_id ] . context ,
sigmsg - > channel - > caller_data . dnis . digits ) ;
assert ( tech_pvt - > caller_profile ! = NULL ) ;
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 ) ;
}
snprintf ( name , sizeof ( name ) , " UNICALL/%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 ) ;
switch_channel_set_name ( channel , name ) ;
switch_channel_set_caller_profile ( channel , tech_pvt - > caller_profile ) ;
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 ;
}
if ( zap_channel_add_token ( sigmsg - > channel , switch_core_session_get_uuid ( session ) , 0 ) ! = ZAP_SUCCESS )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error adding token \n " ) ;
switch_core_session_destroy ( & session ) ;
return ZAP_FAIL ;
}
* sp = session ;
return ZAP_SUCCESS ;
}
# endif
static void on_devicefail ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_devicefail \n " ) ;
}
static void on_protocolfail ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_protocolfail \n " ) ;
}
static void on_sigchanstatus ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_sigchanstatus \n " ) ;
}
static void on_detected ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//struct channel_map *chanmap;
//char name[128];
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_detected \n " ) ;
switch_mutex_lock ( globals . channel_mutex ) ;
//chanmap = spri->private_info;
#if 0
if ( ( session = switch_core_session_locate ( chanmap - > map [ e - > offered . channel ] ) ) )
{
switch_log_printf ( SWITCH_CHANNEL_LOG ,
SWITCH_LOG_NOTICE ,
" --Duplicate detected on channel s%dc%d (ignored) \n " ,
spri - > span ,
e - > offered . channel ) ;
switch_core_session_rwunlock ( session ) ;
switch_mutex_unlock ( globals . channel_mutex ) ;
return ;
}
switch_log_printf ( SWITCH_CHANNEL_LOG ,
SWITCH_LOG_NOTICE ,
" -- Detected on channel s%dc%d (from %s to %s) \n " ,
spri - > span ,
e - > offered . channel ,
e - > offered . parms . originating_number ,
e - > offered . parms . destination_number ) ;
switch_mutex_unlock ( chanmap - > mutex ) ;
//pri_proceeding(spri->pri, e->offered.call, e->offered.channel, 0);
//pri_acknowledge(spri->pri, e->offered.call, e->offered.channel, 0);
switch_mutex_unlock ( chanmap - > mutex ) ;
if ( ( session = unicall_incoming_channel ( sigmsg , & session ) ) )
{
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot create new inbound channel! \n " ) ;
}
# endif
switch_mutex_unlock ( globals . channel_mutex ) ;
}
static void on_offered ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//struct channel_map *chanmap;
//char name[128];
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_offered \n " ) ;
}
static void on_requestmoreinfo ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_requestmoreinfo \n " ) ;
}
static void on_accepted ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_accepted \n " ) ;
}
static void on_callinfo ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_callinfo \n " ) ;
}
static void on_facility ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_facility \n " ) ;
}
static void on_dialednumber ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_dialednumber \n " ) ;
}
static void on_dialtone ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_dialtone \n " ) ;
}
static void on_dialing ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_dialing \n " ) ;
}
static void on_sendmoreinfo ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_sendmoreinfo \n " ) ;
}
static void on_proceeding ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
//struct channel_map *chanmap;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_proceeding \n " ) ;
#if 0
chanmap = spri - > private_info ;
if ( ( session = switch_core_session_locate ( chanmap - > map [ e - > proceeding . channel ] ) ) )
{
switch_core_session_message_t * msg ;
switch_log_printf ( SWITCH_CHANNEL_LOG ,
SWITCH_LOG_NOTICE ,
" -- Proceeding on channel s%dc%d \n " ,
spri - > span ,
e - > proceeding . channel ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_core_session_pass_indication ( session , SWITCH_MESSAGE_INDICATE_PROGRESS ) ;
switch_channel_mark_pre_answered ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG ,
SWITCH_LOG_NOTICE ,
" -- Proceeding on channel s%dc%d but it's not in use? \n " ,
spri - > span ,
e - > proceeding . channel ) ;
}
# endif
}
static void on_alerting ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
//struct channel_map *chanmap;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_alerting \n " ) ;
#if 0
chanmap = spri - > private_info ;
if ( ( session = switch_core_session_locate ( chanmap - > map [ e - > alerting . channel ] ) ) )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " -- Ringing on channel s%dc%d \n " , spri - > span , e - > alerting . channel ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_core_session_pass_indication ( session , SWITCH_MESSAGE_INDICATE_RINGING ) ;
switch_channel_mark_ring_ready ( channel ) ;
switch_core_session_rwunlock ( session ) ;
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " -- Ringing on channel s%dc%d %s but it's not in use? \n " , spri - > span , e - > alerting . channel , chanmap - > map [ e - > alerting . channel ] ) ;
}
# endif
}
static void on_connected ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_connected \n " ) ;
}
static void on_answered ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_answered \n " ) ;
}
static void on_fardisconnected ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_fardisconnected \n " ) ;
}
static void on_dropcall ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_dropcall \n " ) ;
}
static void on_releasecall ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_releasecall \n " ) ;
}
static void on_farblocked ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_farblocked \n " ) ;
}
static void on_farunblocked ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_farunblocked \n " ) ;
}
static void on_localblocked ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_localblocked \n " ) ;
}
static void on_localunblocked ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
//switch_channel_t *channel;
//private_t *tech_pvt;
//tech_pvt = switch_core_session_get_private(session);
//assert(tech_pvt != NULL);
//channel = switch_core_session_get_channel(session);
//assert(channel != NULL);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_localunblocked \n " ) ;
}
static void on_alarm ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_alarm \n " ) ;
}
static void on_resetlinedev ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_resetlinedev \n " ) ;
}
static void on_l2frame ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_l2frame \n " ) ;
}
static void on_l2bufferfull ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_l2bufferfull \n " ) ;
}
static void on_l2nobuffer ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_l2nobuffer \n " ) ;
}
static void on_usrinfo ( uc_t * uc , switch_core_session_t * session , uc_event_t * e )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " on_usrinfo \n " ) ;
}
static void handle_uc_event ( uc_t * uc , void * user_data , uc_event_t * e )
{
switch_core_session_t * session ;
session = ( switch_core_session_t * ) user_data ;
assert ( session ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " event %d \n " , e - > e ) ;
switch ( e - > e )
{
case UC_EVENT_DEVICEFAIL :
on_devicefail ( uc , session , e ) ;
break ;
case UC_EVENT_PROTOCOLFAIL :
on_protocolfail ( uc , session , e ) ;
break ;
case UC_EVENT_SIGCHANSTATUS :
on_sigchanstatus ( uc , session , e ) ;
break ;
case UC_EVENT_DETECTED :
on_detected ( uc , session , e ) ;
break ;
case UC_EVENT_OFFERED :
on_offered ( uc , session , e ) ;
break ;
case UC_EVENT_REQUESTMOREINFO :
on_requestmoreinfo ( uc , session , e ) ;
break ;
case UC_EVENT_ACCEPTED :
on_accepted ( uc , session , e ) ;
break ;
case UC_EVENT_CALLINFO :
on_callinfo ( uc , session , e ) ;
break ;
case UC_EVENT_FACILITY :
on_facility ( uc , session , e ) ;
break ;
case UC_EVENT_DIALEDNUMBER :
on_dialednumber ( uc , session , e ) ;
break ;
case UC_EVENT_DIALTONE :
on_dialtone ( uc , session , e ) ;
break ;
case UC_EVENT_DIALING :
on_dialing ( uc , session , e ) ;
break ;
case UC_EVENT_SENDMOREINFO :
on_sendmoreinfo ( uc , session , e ) ;
break ;
case UC_EVENT_PROCEEDING :
on_proceeding ( uc , session , e ) ;
break ;
case UC_EVENT_ALERTING :
on_alerting ( uc , session , e ) ;
break ;
case UC_EVENT_CONNECTED :
on_connected ( uc , session , e ) ;
break ;
case UC_EVENT_ANSWERED :
on_answered ( uc , session , e ) ;
break ;
case UC_EVENT_FARDISCONNECTED :
on_fardisconnected ( uc , session , e ) ;
break ;
case UC_EVENT_DROPCALL :
on_dropcall ( uc , session , e ) ;
break ;
case UC_EVENT_RELEASECALL :
on_releasecall ( uc , session , e ) ;
break ;
case UC_EVENT_FARBLOCKED :
on_farblocked ( uc , session , e ) ;
break ;
case UC_EVENT_FARUNBLOCKED :
on_farunblocked ( uc , session , e ) ;
break ;
case UC_EVENT_LOCALBLOCKED :
on_localblocked ( uc , session , e ) ;
break ;
case UC_EVENT_LOCALUNBLOCKED :
on_localunblocked ( uc , session , e ) ;
break ;
case UC_EVENT_ALARM :
on_alarm ( uc , session , e ) ;
break ;
case UC_EVENT_RESETLINEDEV :
on_resetlinedev ( uc , session , e ) ;
break ;
case UC_EVENT_L2FRAME :
on_l2frame ( uc , session , e ) ;
break ;
case UC_EVENT_L2BUFFERFULL :
on_l2bufferfull ( uc , session , e ) ;
break ;
case UC_EVENT_L2NOBUFFER :
on_l2nobuffer ( uc , session , e ) ;
break ;
case UC_EVENT_USRINFO :
on_usrinfo ( uc , session , e ) ;
break ;
default :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unknown unicall event %d \n " , e - > e ) ;
break ;
}
}
static void tech_init ( private_t * tech_pvt , switch_core_session_t * session )
{
tech_pvt - > read_frame . data = tech_pvt - > databuf ;
tech_pvt - > read_frame . buflen = sizeof ( tech_pvt - > databuf ) ;
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 ;
}
/*
State methods they get called when the state changes to the specific state
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it .
*/
static switch_status_t unicall_on_init ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_on_init(%p) \n " , ( void * ) session ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_IO ) ;
/* Move channel's state machine to ROUTING. This means the call is trying
to get from the initial start where the call because , to the point
where a destination has been identified . If the channel is simply
left in the initial state , nothing will happen . */
switch_channel_set_state ( channel , CS_ROUTING ) ;
switch_mutex_lock ( globals . mutex ) ;
globals . calls + + ;
switch_mutex_unlock ( globals . mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_on_routing ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
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_CRIT , " unicall_on_routing(%p) \n " , ( void * ) session ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL ROUTING \n " , switch_channel_get_name ( channel ) ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_on_execute ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
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_CRIT , " unicall_on_execute(%p) \n " , ( void * ) session ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL EXECUTE \n " , switch_channel_get_name ( channel ) ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_on_hangup ( switch_core_session_t * session )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
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_CRIT , " unicall_on_hangup(%p) \n " , ( void * ) session ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_VOICE ) ;
//switch_thread_cond_signal(tech_pvt->cond);
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_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s CHANNEL HANGUP \n " , switch_channel_get_name ( channel ) ) ;
//if ((ret = uc_call_control(uc, UC_OP_DROPCALL, crn, (void *) switch_channel_get_cause(channel))))
// ???;
switch_mutex_lock ( globals . mutex ) ;
if ( - - globals . calls < 0 )
globals . calls = 0 ;
switch_mutex_unlock ( globals . mutex ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_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_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_kill_channel(%p, %d) \n " , ( void * ) session , sig ) ;
switch ( sig )
{
case SWITCH_SIG_KILL :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_kill_channel(%p, %d) SIG_KILL \n " , ( void * ) session , sig ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_VOICE ) ;
switch_channel_hangup ( channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
//switch_thread_cond_signal(tech_pvt->cond);
break ;
case SWITCH_SIG_BREAK :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_kill_channel(%p, %d) SIG_BREAK \n " , ( void * ) session , sig ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_BREAK ) ;
break ;
default :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_kill_channel(%p, %d) DEFAULT \n " , ( void * ) session , sig ) ;
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_on_exchange_media ( switch_core_session_t * session )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_on_exchange_media(%p) \n " , ( void * ) session ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL LOOPBACK \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_on_soft_execute ( switch_core_session_t * session )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_on_soft_execute(%p) \n " , ( void * ) session ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " CHANNEL TRANSMIT \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
{
private_t * tech_pvt = switch_core_session_get_private ( session ) ;
switch_assert ( tech_pvt ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_send_dtmf(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , switch_io_flag_t flags , int stream_id )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
//switch_time_t started = switch_time_now();
//unsigned int elapsed;
switch_byte_t * data ;
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_CRIT , " unicall_read_frame(%p) \n " , ( void * ) session ) ;
tech_pvt - > read_frame . flags = SFF_NONE ;
* frame = NULL ;
while ( switch_test_flag ( tech_pvt , TFLAG_IO ) )
{
if ( switch_test_flag ( tech_pvt , TFLAG_BREAK ) )
{
switch_clear_flag ( tech_pvt , TFLAG_BREAK ) ;
data = ( switch_byte_t * ) tech_pvt - > read_frame . data ;
data [ 0 ] = 65 ;
data [ 1 ] = 0 ;
tech_pvt - > read_frame . datalen = 2 ;
tech_pvt - > read_frame . flags = SFF_CNG ;
* frame = & tech_pvt - > read_frame ;
return SWITCH_STATUS_SUCCESS ;
}
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) )
return SWITCH_STATUS_FALSE ;
if ( switch_test_flag ( tech_pvt , TFLAG_IO ) & & switch_test_flag ( tech_pvt , TFLAG_VOICE ) )
{
switch_clear_flag_locked ( tech_pvt , TFLAG_VOICE ) ;
if ( ! tech_pvt - > read_frame . datalen )
continue ;
* frame = & tech_pvt - > read_frame ;
# if defined(BIGENDIAN)
if ( switch_test_flag ( tech_pvt , TFLAG_LINEAR ) )
switch_swap_linear ( ( * frame ) - > data , ( int ) ( * frame ) - > datalen / 2 ) ;
# endif
return SWITCH_STATUS_SUCCESS ;
}
2008-11-14 23:31:21 +00:00
switch_cond_next ( ) ;
2008-09-17 16:33:43 +00:00
}
return SWITCH_STATUS_FALSE ;
}
static switch_status_t unicall_write_frame ( switch_core_session_t * session , switch_frame_t * frame , switch_io_flag_t flags , int stream_id )
{
switch_channel_t * channel = NULL ;
private_t * tech_pvt = NULL ;
//switch_frame_t *pframe;
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_CRIT , " unicall_write_frame(%p) \n " , ( void * ) session ) ;
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) )
return SWITCH_STATUS_FALSE ;
# if defined(BIGENDIAN)
if ( switch_test_flag ( tech_pvt , TFLAG_LINEAR ) )
switch_swap_linear ( frame - > data , ( int ) frame - > datalen / sizeof ( int16_t ) ) ;
# endif
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t redirect_audio ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " redirect_audio(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t transmit_text ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " transmit_text(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t answer ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " answer(%p) \n " , ( void * ) session ) ;
//if ((ret = uc_call_control(uc, UC_OP_ANSWERCALL, crn, NULL)))
// ???;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t progress ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " progress(%p) \n " , ( void * ) session ) ;
//if ((ret = uc_call_control(uc, UC_OP_ACCEPTCALL, crn, NULL)))
// ???;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t bridge ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " bridge(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unbridge ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unbridge(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t transfer ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " transfer(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t ringing ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " ringing(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t media ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " media(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t nomedia ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " nomedia(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t hold ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " hold(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unhold ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unhold(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t redirect ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " redirect(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t respond ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " respond(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t broadcast ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " broadcast(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t media_redirect ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " media_redirect(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t deflect ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " deflect(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t video_refresh_req ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " video_refresh_req(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t display ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch_channel_t * channel ;
private_t * tech_pvt ;
uc_t * uc ;
channel = switch_core_session_get_channel ( session ) ;
assert ( channel ! = NULL ) ;
tech_pvt = switch_core_session_get_private ( session ) ;
assert ( tech_pvt ! = NULL ) ;
uc = tech_pvt - > uc ;
assert ( uc ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " display(%p) \n " , ( void * ) session ) ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t unicall_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
{
switch ( msg - > message_id )
{
case SWITCH_MESSAGE_REDIRECT_AUDIO :
return redirect_audio ( session , msg ) ;
case SWITCH_MESSAGE_TRANSMIT_TEXT :
return transmit_text ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_ANSWER :
return answer ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_PROGRESS :
return progress ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_BRIDGE :
return bridge ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_UNBRIDGE :
return unbridge ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_TRANSFER :
return transfer ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_RINGING :
return ringing ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_MEDIA :
return media ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_NOMEDIA :
return nomedia ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_HOLD :
return hold ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_UNHOLD :
return unhold ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_REDIRECT :
return redirect ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_RESPOND :
return respond ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_BROADCAST :
return broadcast ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT :
return media_redirect ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_DEFLECT :
return deflect ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ :
return video_refresh_req ( session , msg ) ;
case SWITCH_MESSAGE_INDICATE_DISPLAY :
return display ( session , msg ) ;
default :
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_receive_message(%p) %d \n " , ( void * ) session , msg - > message_id ) ;
break ;
}
return SWITCH_STATUS_SUCCESS ;
}
/* 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 !
*/
static switch_call_cause_t unicall_outgoing_channel ( switch_core_session_t * session ,
switch_event_t * var_event ,
switch_caller_profile_t * outbound_profile ,
switch_core_session_t * * new_session ,
switch_memory_pool_t * * pool ,
switch_originate_flag_t flags )
{
private_t * tech_pvt ;
switch_channel_t * channel ;
switch_caller_profile_t * caller_profile ;
uc_t * uc ;
uc_makecall_t makecall ;
uc_callparms_t * callparms ;
int screen ;
int hide ;
char name [ 128 ] ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_outgoing_channel(%p) \n " , ( void * ) session ) ;
if ( ( * new_session = switch_core_session_request ( unicall_endpoint_interface , pool ) ) = = NULL )
{
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
switch_core_session_add_stream ( * new_session , NULL ) ;
if ( ( tech_pvt = ( private_t * ) switch_core_session_alloc ( * new_session , sizeof ( private_t ) ) ) = = NULL )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Hey where is my memory pool? \n " ) ;
switch_core_session_destroy ( new_session ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
channel = switch_core_session_get_channel ( * new_session ) ;
tech_init ( tech_pvt , * new_session ) ;
if ( outbound_profile = = NULL )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Doh! no caller profile \n " ) ;
switch_core_session_destroy ( new_session ) ;
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
}
snprintf ( name , sizeof ( name ) , " UNICALL/%s " , outbound_profile - > destination_number ) ;
switch_channel_set_name ( channel , name ) ;
caller_profile = switch_caller_profile_clone ( * new_session , outbound_profile ) ;
switch_channel_set_caller_profile ( channel , caller_profile ) ;
tech_pvt - > caller_profile = caller_profile ;
uc = tech_pvt - > uc ;
if ( ( callparms = uc_new_callparms ( NULL ) ) = = NULL )
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
//uc_callparm_bear_cap_transfer_cap(callparms, cap);
//uc_callparm_bear_cap_transfer_mode(callparms, mode);
//uc_callparm_bear_cap_transfer_rate(callparms, rate);
//uc_callparm_userinfo_layer1_protocol(callparms, prot);
//uc_callparm_user_rate(callparms, rate);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " destination '%s' \n " , outbound_profile - > destination_number ) ;
uc_callparm_destination_number ( callparms , outbound_profile - > destination_number ) ;
uc_callparm_destination_ton ( callparms , outbound_profile - > destination_number_ton ) ;
uc_callparm_destination_npi ( callparms , outbound_profile - > destination_number_numplan ) ;
//uc_callparm_destination_sub_addr_number(callparms, num);
//uc_callparm_destination_sub_addr_ton(callparms, ton);
//uc_callparm_destination_sub_addr_npi(callparms, npi);
//uc_callparm_redirecting_cause(callparms, cause);
//uc_callparm_redirecting_presentation(callparms, pres);
uc_callparm_redirecting_number ( callparms , outbound_profile - > rdnis ) ;
uc_callparm_redirecting_ton ( callparms , outbound_profile - > rdnis_ton ) ;
uc_callparm_redirecting_npi ( callparms , outbound_profile - > rdnis_numplan ) ;
//uc_callparm_redirecting_subaddr(callparms, num);
//uc_callparm_redirecting_subaddr_ton(callparms, ton);
//uc_callparm_redirecting_subaddr_npi(callparms, npi);
//uc_callparm_original_called_number(callparms, num);
//uc_callparm_original_called_number_ton(callparms, ton);
//uc_callparm_original_called_number_npi(callparms, npi);
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " caller id name '%s' \n " , outbound_profile - > caller_id_name ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " caller id number '%s' \n " , outbound_profile - > caller_id_number ) ;
uc_callparm_originating_name ( callparms , outbound_profile - > caller_id_name ) ;
uc_callparm_originating_number ( callparms , outbound_profile - > caller_id_number ) ;
screen = switch_test_flag ( outbound_profile , SWITCH_CPF_SCREEN ) ;
hide = switch_test_flag ( outbound_profile , SWITCH_CPF_HIDE_NUMBER ) ;
if ( ! screen & & ! hide )
uc_callparm_originating_presentation ( callparms , UC_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED ) ;
else if ( ! screen & & hide )
uc_callparm_originating_presentation ( callparms , UC_PRES_PROHIB_USER_NUMBER_NOT_SCREENED ) ;
else if ( screen & & ! hide )
uc_callparm_originating_presentation ( callparms , UC_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN ) ;
else
uc_callparm_originating_presentation ( callparms , UC_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN ) ;
uc_callparm_originating_ton ( callparms , outbound_profile - > caller_ton ) ;
uc_callparm_originating_npi ( callparms , outbound_profile - > caller_numplan ) ;
//uc_callparm_originating_sub_addr_ton(callparms, ton);
//uc_callparm_originating_sub_addr_npi(callparms, npi);
//uc_callparm_originating_sub_addr_number(callparms, num);
uc_callparm_calling_party_category ( callparms , UC_CALLER_CATEGORY_NATIONAL_SUBSCRIBER_CALL ) ;
makecall . callparms = callparms ;
makecall . crn = 0 ;
#if 0
if ( ( ret = uc_call_control ( uc , UC_OP_MAKECALL , 0 , ( void * ) & makecall ) ) )
? ? ? ? ;
# endif
free ( callparms ) ;
switch_channel_set_flag ( channel , CF_OUTBOUND ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_OUTBOUND ) ;
switch_channel_set_state ( channel , CS_INIT ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_outgoing_channel(%p) SUCCESS \n " , ( void * ) session ) ;
return SWITCH_CAUSE_SUCCESS ;
}
static switch_status_t unicall_receive_event ( switch_core_session_t * session , switch_event_t * event )
{
struct private_object * tech_pvt = switch_core_session_get_private ( session ) ;
char * body = switch_event_get_body ( event ) ;
switch_assert ( tech_pvt ! = NULL ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " unicall_receive_event(%p) \n " , ( void * ) session ) ;
if ( body = = NULL )
body = " " ;
return SWITCH_STATUS_SUCCESS ;
}
static void * SWITCH_THREAD_FUNC unicall_thread_run ( switch_thread_t * thread , void * obj )
{
fd_set read ;
fd_set write ;
fd_set oob ;
int fd ;
int i ;
int sel_on ;
int ret ;
switch_event_t * s_event ;
uc_t * uc = ( uc_t * ) obj ;
#if 0
switch_mutex_init ( & chanmap . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
# endif
if ( switch_event_create ( & s_event , SWITCH_EVENT_PUBLISH ) = = SWITCH_STATUS_SUCCESS )
{
switch_event_add_header ( s_event , SWITCH_STACK_BOTTOM , " service " , " _uc._tcp " ) ;
switch_event_fire ( & s_event ) ;
}
for ( i = 0 ; i < MAX_SPANS ; i + + )
{
if ( span_data [ i ] )
{
if ( ( ret = uc_call_control ( span_data [ i ] - > uc , UC_OP_UNBLOCK , 0 , ( void * ) ( intptr_t ) - 1 ) ) < 0 )
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Unblock failed - %s \n " , uc_ret_to_str ( ret ) ) ;
/*endif*/
}
}
FD_ZERO ( & read ) ;
FD_ZERO ( & write ) ;
FD_ZERO ( & oob ) ;
for ( ; ; )
{
i = 0 ;
sel_on = - 1 ;
for ( i = 0 ; i < MAX_SPANS ; i + + )
{
if ( span_data [ i ] )
{
fd = span_data [ i ] - > fd ;
FD_SET ( fd , & read ) ;
//FD_SET(fd, &write);
//FD_SET(fd, &oob);
if ( fd > sel_on )
sel_on = fd ;
}
}
if ( sel_on > - 1 )
{
if ( select ( + + sel_on , & read , NULL , NULL , NULL ) )
{
for ( i = 0 ; i < MAX_SPANS ; i + + )
{
if ( span_data [ i ] )
{
fd = span_data [ i ] - > fd ;
if ( FD_ISSET ( fd , & read ) )
{
uc_check_event ( span_data [ i ] - > uc ) ;
uc_schedule_run ( span_data [ i ] - > uc ) ;
}
}
}
}
}
}
uc_delete ( uc ) ;
return NULL ;
}
static void unicall_thread_launch ( uc_t * uc )
{
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
switch_threadattr_create ( & thd_attr , module_pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , thd_attr , unicall_thread_run , uc , module_pool ) ;
}
switch_state_handler_table_t unicall_state_handlers =
{
/*.on_init */ unicall_on_init ,
/*.on_routing */ unicall_on_routing ,
/*.on_execute */ unicall_on_execute ,
/*.on_hangup */ unicall_on_hangup ,
/*.on_exchange_media */ unicall_on_exchange_media ,
/*.on_soft_execute */ unicall_on_soft_execute
} ;
switch_io_routines_t unicall_io_routines =
{
/*.outgoing_channel */ unicall_outgoing_channel ,
/*.read_frame */ unicall_read_frame ,
/*.write_frame */ unicall_write_frame ,
/*.kill_channel */ unicall_kill_channel ,
/*.send_dtmf */ unicall_send_dtmf ,
/*.receive_message */ unicall_receive_message ,
/*.receive_event */ unicall_receive_event
} ;
static switch_status_t config_unicall ( int reload )
{
const char * cf = " unicall.conf " ;
switch_xml_t cfg ;
switch_xml_t xml ;
switch_xml_t settings ;
switch_xml_t param ;
switch_xml_t spans ;
switch_xml_t span ;
int current_span = 0 ;
int min_span = 0 ;
int max_span = 0 ;
int i ;
char * id ;
span_data_t * sp ;
if ( ! ( xml = switch_xml_open_cfg ( cf , & cfg , NULL ) ) )
{
2008-10-11 06:19:56 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Opening of %s failed \n " , cf ) ;
2008-09-17 16:33:43 +00:00
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 ( ! strcmp ( var , " debug " ) )
{
globals . debug = atoi ( val ) ;
}
else if ( ! strcmp ( var , " ms-per-frame " ) )
{
globals . frame_duration = atoi ( val ) ;
}
else if ( ! strcmp ( var , " dtmf-on " ) )
{
globals . dtmf_on = atoi ( val ) ;
}
else if ( ! strcmp ( var , " dtmf-off " ) )
{
globals . dtmf_off = atoi ( val ) ;
}
else if ( ! strcmp ( var , " dialplan " ) )
{
set_global_dialplan ( val ) ;
}
else if ( ! strcmp ( var , " suppress-dtmf-tone " ) )
{
globals . suppress_dtmf_tone = switch_true ( val ) ;
}
else if ( ! strcmp ( var , " ignore-dtmf-tone " ) )
{
globals . ignore_dtmf_tone = switch_true ( val ) ;
}
}
}
spans = switch_xml_child ( cfg , " spans " ) ;
id = NULL ;
for ( span = switch_xml_child ( spans , " span " ) ; span ; span = span - > next )
{
id = ( char * ) switch_xml_attr ( span , " id " ) ;
current_span = 0 ;
if ( id )
{
char * p ;
min_span = atoi ( id ) ;
if ( ( p = strchr ( id , ' - ' ) ) )
{
p + + ;
max_span = atoi ( p ) ;
}
else
{
max_span = min_span ;
}
if ( min_span < 1 | | max_span < min_span )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid Span Config! [%s] \n " , id ) ;
continue ;
}
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Missing SPAN ID! \n " ) ;
continue ;
}
for ( i = min_span ; i < = max_span ; i + + )
{
current_span = i ;
if ( current_span < = 0 | | current_span > MAX_SPANS )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Invalid SPAN %d! \n " , current_span ) ;
current_span = 0 ;
continue ;
}
if ( span_data [ current_span ] = = NULL )
{
if ( ( span_data [ current_span ] = switch_core_alloc ( module_pool , sizeof ( * span_data [ current_span ] ) ) ) = = NULL )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " MEMORY ERROR \n " ) ;
break ;
}
sp = span_data [ current_span ] ;
memset ( sp , 0 , sizeof ( * sp ) ) ;
sp - > span = current_span ;
sp - > protocol_class = NULL ;
sp - > protocol_variant = NULL ;
sp - > protocol_end = UC_MODE_CPE ;
sp - > outgoing_ok = TRUE ;
}
sp = span_data [ current_span ] ;
sp - > id = strdup ( id ) ;
for ( param = switch_xml_child ( span , " param " ) ; param ; param = param - > next )
{
char * var = ( char * ) switch_xml_attr_soft ( param , " name " ) ;
char * val = ( char * ) switch_xml_attr_soft ( param , " value " ) ;
if ( strcmp ( var , " protocol-class " ) = = 0 )
{
sp - > protocol_class = strdup ( val ) ;
}
else if ( strcmp ( var , " protocol-variant " ) = = 0 )
{
sp - > protocol_variant = strdup ( val ) ;
}
else if ( strcmp ( var , " protocol-end " ) = = 0 )
{
if ( strcasecmp ( val , " co " ) = = 0 )
sp - > protocol_end = UC_MODE_CO ;
else if ( strcasecmp ( val , " cpe " ) = = 0 )
sp - > protocol_end = UC_MODE_CPE ;
else if ( strcasecmp ( val , " peer " ) = = 0 )
sp - > protocol_end = UC_MODE_PEER ;
}
else if ( strcmp ( var , " outgoing-allowed " ) = = 0 )
{
sp - > outgoing_ok = switch_true ( var ) ;
}
else if ( strcmp ( var , " dialplan " ) = = 0 )
{
sp - > dialplan = strdup ( val ) ;
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " UNKNOWN PARAMETER %s \n " , var ) ;
}
}
}
}
switch_xml_free ( xml ) ;
if ( globals . dialplan = = NULL )
set_global_dialplan ( " XML " ) ;
globals . configured_spans = 0 ;
for ( current_span = 1 ; current_span < MAX_SPANS ; current_span + + )
{
if ( span_data [ current_span ] )
{
sp = span_data [ current_span ] ;
if ( ( sp - > uc = uc_create ( sp - > id ,
sp - > protocol_class ,
sp - > protocol_variant ,
sp - > protocol_end ,
sp - > outgoing_ok ) ) = = NULL )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cannot launch span %d \n " , current_span ) ;
return SWITCH_STATUS_FALSE ;
}
uc_get_device_handle ( sp - > uc , 0 , & sp - > fd ) ;
uc_set_signaling_callback ( sp - > uc , handle_uc_event , ( void * ) ( intptr_t ) current_span ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Launched span %d \n " , current_span ) ;
unicall_thread_launch ( sp - > uc ) ;
switch_mutex_lock ( globals . hash_mutex ) ;
globals . configured_spans + + ;
switch_mutex_unlock ( globals . hash_mutex ) ;
}
}
return SWITCH_STATUS_SUCCESS ;
}
SWITCH_MODULE_LOAD_FUNCTION ( mod_unicall_load )
{
switch_status_t status = SWITCH_STATUS_SUCCESS ;
memset ( span_data , 0 , sizeof ( span_data ) ) ;
module_pool = pool ;
memset ( & globals , 0 , sizeof ( globals ) ) ;
switch_core_hash_init ( & globals . call_hash , module_pool ) ;
switch_mutex_init ( & globals . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
switch_mutex_init ( & globals . hash_mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
switch_mutex_init ( & globals . channel_mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
if ( ( status = config_unicall ( FALSE ) ) ! = SWITCH_STATUS_SUCCESS )
return status ;
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
unicall_endpoint_interface = switch_loadable_module_create_interface ( * module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
unicall_endpoint_interface - > interface_name = " unicall " ;
unicall_endpoint_interface - > io_routines = & unicall_io_routines ;
unicall_endpoint_interface - > state_handler = & unicall_state_handlers ;
/* Indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
/*
SWITCH_MODULE_RUNTIME_FUNCTION ( mod_unicall_runtime )
{
return SWITCH_STATUS_TERM ;
}
*/
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_unicall_shutdown )
{
int x = 0 ;
for ( x = 0 , running = - 1 ; running & & x < = 100 ; x + + )
switch_yield ( 20000 ) ;
return SWITCH_STATUS_SUCCESS ;
}