2006-08-25 23:55:59 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 / 2006 , Anthony Minessale II < anthmct @ yahoo . com >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthmct @ yahoo . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Anthony Minessale II < anthmct @ yahoo . com >
2006-10-18 22:57:35 +00:00
* Ken Rice , Asteria Solutions Group , Inc < ken @ asteriasgi . com >
2006-10-24 22:11:25 +00:00
* Paul D . Tinsley < pdt at jackhammer . org >
2007-02-25 21:00:26 +00:00
* Bret McDanel < trixter AT 0xdecafbad . com >
2006-08-25 23:55:59 +00:00
*
*
* mod_sofia . c - - SOFIA SIP Endpoint
*
*/
/* Best viewed in a 160 x 60 VT100 Terminal or so the line below at least fits across your screen*/
/*************************************************************************************************************************************************************/
2007-03-31 19:01:33 +00:00
# include "mod_sofia.h"
2006-08-25 23:55:59 +00:00
2007-06-13 14:35:55 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_sofia_load ) ;
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_sofia_shutdown ) ;
SWITCH_MODULE_DEFINITION ( mod_sofia , mod_sofia_load , mod_sofia_shutdown , NULL ) ;
2007-04-01 01:16:16 +00:00
struct mod_sofia_globals mod_sofia_globals ;
2007-06-20 07:15:53 +00:00
switch_endpoint_interface_t * sofia_endpoint_interface ;
2006-10-31 21:46:42 +00:00
static switch_frame_t silence_frame = { 0 } ;
2006-10-31 21:38:06 +00:00
static char silence_data [ 13 ] = " " ;
2006-08-25 23:55:59 +00:00
# define STRLEN 15
static switch_memory_pool_t * module_pool = NULL ;
static switch_status_t sofia_on_init ( switch_core_session_t * session ) ;
static switch_status_t sofia_on_loopback ( switch_core_session_t * session ) ;
static switch_status_t sofia_on_transmit ( switch_core_session_t * session ) ;
2007-03-29 22:31:56 +00:00
static switch_call_cause_t sofia_outgoing_channel ( switch_core_session_t * session ,
2007-03-30 00:15:25 +00:00
switch_caller_profile_t * outbound_profile , switch_core_session_t * * new_session ,
2007-12-20 21:42:00 +00:00
switch_memory_pool_t * * pool , switch_originate_flag_t flags ) ;
2007-03-30 00:13:31 +00:00
static switch_status_t sofia_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t sofia_write_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout , switch_io_flag_t flags , int stream_id ) ;
2007-04-19 21:40:50 +00:00
static switch_status_t sofia_read_video_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout , switch_io_flag_t flags , int stream_id ) ;
static switch_status_t sofia_write_video_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout , switch_io_flag_t flags , int stream_id ) ;
2006-08-25 23:55:59 +00:00
static switch_status_t sofia_kill_channel ( switch_core_session_t * session , int sig ) ;
2007-03-31 19:01:33 +00:00
/* BODY OF THE MODULE */
/*************************************************************************************************************************************************************/
2007-03-29 22:31:56 +00:00
2007-03-31 19:01:33 +00:00
/*
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 sofia_on_init ( switch_core_session_t * session )
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
tech_pvt - > read_frame . buflen = SWITCH_RTP_MAX_BUF_LEN ;
2006-08-25 23:55:59 +00:00
2007-12-24 18:26:39 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s SOFIA INIT \n " , switch_channel_get_name ( channel ) ) ;
2008-02-21 17:48:41 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) | | switch_channel_test_flag ( channel , CF_PROXY_MEDIA ) ) {
2007-03-31 19:01:33 +00:00
sofia_glue_tech_absorb_sdp ( tech_pvt ) ;
}
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_OUTBOUND ) ) {
2008-01-16 06:01:53 +00:00
const char * var ;
if ( ( var = switch_channel_get_variable ( channel , SOFIA_SECURE_MEDIA_VARIABLE ) ) & & ! switch_strlen_zero ( var ) ) {
if ( switch_true ( var ) | | ! strcasecmp ( var , SWITCH_RTP_CRYPTO_KEY_32 ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_SECURE ) ;
sofia_glue_build_crypto ( tech_pvt , 1 , AES_CM_128_HMAC_SHA1_32 , SWITCH_RTP_CRYPTO_SEND ) ;
} else if ( ! strcasecmp ( var , SWITCH_RTP_CRYPTO_KEY_80 ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_SECURE ) ;
sofia_glue_build_crypto ( tech_pvt , 1 , AES_CM_128_HMAC_SHA1_80 , SWITCH_RTP_CRYPTO_SEND ) ;
}
}
2007-03-31 19:01:33 +00:00
if ( sofia_glue_do_invite ( session ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-17 14:44:22 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_FALSE ;
}
}
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
/* Move Channel's State Machine to RING */
switch_channel_set_state ( channel , CS_RING ) ;
return SWITCH_STATUS_SUCCESS ;
}
2006-09-28 21:21:44 +00:00
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_on_ring ( switch_core_session_t * session )
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2007-03-19 21:09:53 +00:00
2007-12-24 18:26:39 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
2008-01-28 07:26:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s SOFIA RING \n " , switch_channel_get_name ( switch_core_session_get_channel ( session ) ) ) ;
2007-12-24 18:26:39 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_on_reset ( switch_core_session_t * session )
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
2007-12-24 18:26:39 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
2008-01-28 07:26:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s SOFIA RESET \n " , switch_channel_get_name ( switch_core_session_get_channel ( session ) ) ) ;
2007-12-24 18:26:39 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_on_hibernate ( switch_core_session_t * session )
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = switch_core_session_get_private ( session ) ;
2007-12-24 18:26:39 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
2008-01-28 07:26:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s SOFIA HIBERNATE \n " , switch_channel_get_name ( switch_core_session_get_channel ( session ) ) ) ;
2007-03-19 21:09:53 +00:00
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_SUCCESS ;
2007-03-19 21:09:53 +00:00
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_on_execute ( switch_core_session_t * session )
2007-03-19 21:09:53 +00:00
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2007-03-19 21:09:53 +00:00
2007-12-24 18:26:39 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
2008-01-28 07:26:10 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " %s SOFIA EXECUTE \n " , switch_channel_get_name ( switch_core_session_get_channel ( session ) ) ) ;
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_SUCCESS ;
2007-03-19 21:09:53 +00:00
}
2007-11-20 01:44:07 +00:00
/* map QSIG cause codes to SIP from RFC4497 section 8.4.1 */
2007-03-31 19:01:33 +00:00
static int hangup_cause_to_sip ( switch_call_cause_t cause )
2007-04-17 18:53:18 +00:00
{
2007-03-31 19:01:33 +00:00
switch ( cause ) {
case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET :
case SWITCH_CAUSE_NO_ROUTE_DESTINATION :
return 404 ;
case SWITCH_CAUSE_USER_BUSY :
return 486 ;
case SWITCH_CAUSE_NO_USER_RESPONSE :
return 408 ;
case SWITCH_CAUSE_NO_ANSWER :
return 480 ;
case SWITCH_CAUSE_SUBSCRIBER_ABSENT :
return 480 ;
case SWITCH_CAUSE_CALL_REJECTED :
return 603 ;
case SWITCH_CAUSE_NUMBER_CHANGED :
case SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION :
return 410 ;
case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER :
return 502 ;
case SWITCH_CAUSE_INVALID_NUMBER_FORMAT :
return 484 ;
case SWITCH_CAUSE_FACILITY_REJECTED :
return 501 ;
case SWITCH_CAUSE_NORMAL_UNSPECIFIED :
return 480 ;
case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL :
case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION :
case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER :
case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE :
case SWITCH_CAUSE_SWITCH_CONGESTION :
return 503 ;
case SWITCH_CAUSE_OUTGOING_CALL_BARRED :
case SWITCH_CAUSE_INCOMING_CALL_BARRED :
case SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH :
return 403 ;
case SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL :
return 503 ;
case SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL :
2007-04-17 18:53:18 +00:00
case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION :
2007-03-31 19:01:33 +00:00
return 488 ;
case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED :
case SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED :
return 501 ;
case SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE :
return 504 ;
case SWITCH_CAUSE_ORIGINATOR_CANCEL :
return 487 ;
2007-12-24 19:23:36 +00:00
case SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR :
return 483 ;
2007-03-31 19:01:33 +00:00
default :
return 480 ;
2006-11-14 18:12:17 +00:00
}
}
2007-03-31 19:01:33 +00:00
switch_status_t sofia_on_hangup ( switch_core_session_t * session )
2006-09-29 18:12:31 +00:00
{
2007-03-31 19:01:33 +00:00
switch_core_session_t * a_session ;
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2008-01-29 19:35:06 +00:00
switch_call_cause_t cause = switch_channel_get_cause ( channel ) ;
int sip_cause = hangup_cause_to_sip ( cause ) ;
2007-12-20 15:41:45 +00:00
if ( tech_pvt - > profile - > rtpip & & tech_pvt - > local_sdp_audio_port ) {
switch_rtp_release_port ( tech_pvt - > profile - > rtpip , tech_pvt - > local_sdp_audio_port ) ;
}
2007-12-20 02:55:36 +00:00
2007-12-24 18:26:39 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_SIP_HOLD ) & & cause ! = SWITCH_CAUSE_ATTENDED_TRANSFER ) {
2008-01-05 22:17:26 +00:00
const char * buuid ;
2008-01-29 19:35:06 +00:00
switch_core_session_t * bsession ;
switch_channel_t * bchannel ;
const char * lost_ext ;
2008-01-03 21:34:44 +00:00
2007-12-20 02:55:36 +00:00
if ( tech_pvt - > max_missed_packets ) {
switch_rtp_set_max_missed_packets ( tech_pvt - > rtp_session , tech_pvt - > max_missed_packets ) ;
}
switch_channel_presence ( tech_pvt - > channel , " unknown " , " unhold " ) ;
2008-01-05 22:17:26 +00:00
if ( ( buuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) ) ) {
2008-01-29 19:35:06 +00:00
if ( ( bsession = switch_core_session_locate ( buuid ) ) ) {
bchannel = switch_core_session_get_channel ( bsession ) ;
if ( switch_channel_test_flag ( bchannel , CF_BROADCAST ) ) {
if ( ( lost_ext = switch_channel_get_variable ( bchannel , " left_hanging_extension " ) ) ) {
switch_ivr_session_transfer ( bsession , lost_ext , NULL , NULL ) ;
}
2008-01-05 22:17:26 +00:00
switch_channel_stop_broadcast ( bchannel ) ;
2008-01-29 19:35:06 +00:00
}
switch_core_session_rwunlock ( bsession ) ;
}
}
2007-12-20 02:55:36 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
}
2007-12-24 18:26:39 +00:00
2007-03-31 19:01:33 +00:00
sofia_glue_deactivate_rtp ( tech_pvt ) ;
2006-09-29 18:12:31 +00:00
2007-03-31 19:01:33 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Channel %s hanging up, cause: %s \n " ,
2008-01-29 19:35:06 +00:00
switch_channel_get_name ( channel ) , switch_channel_cause2str ( cause ) ) ;
2006-09-29 18:12:31 +00:00
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > hash_key ) {
switch_core_hash_delete ( tech_pvt - > profile - > chat_hash , tech_pvt - > hash_key ) ;
2006-09-29 18:12:31 +00:00
}
2008-03-04 23:53:23 +00:00
if ( session & & ( tech_pvt - > profile - > pflags & PFLAG_PRESENCE ) ) {
2008-01-29 19:35:06 +00:00
char * sql = switch_mprintf ( " delete from sip_dialogs where call_id='%q' " , tech_pvt - > call_id ) ;
2007-12-18 01:12:50 +00:00
switch_assert ( sql ) ;
2008-03-05 20:31:18 +00:00
sofia_glue_execute_sql ( tech_pvt - > profile , & sql , SWITCH_TRUE ) ;
2007-12-18 01:12:50 +00:00
}
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > kick & & ( a_session = switch_core_session_locate ( tech_pvt - > kick ) ) ) {
switch_channel_t * a_channel = switch_core_session_get_channel ( a_session ) ;
switch_channel_hangup ( a_channel , switch_channel_get_cause ( channel ) ) ;
switch_core_session_rwunlock ( a_session ) ;
}
2006-12-13 20:10:00 +00:00
2007-06-19 16:29:59 +00:00
switch_mutex_lock ( tech_pvt - > profile - > flag_mutex ) ;
2007-11-20 01:44:07 +00:00
if ( tech_pvt - > nh & & ! switch_test_flag ( tech_pvt , TFLAG_BYE ) ) {
2008-02-22 15:02:16 +00:00
char reason [ 128 ] = " " ;
if ( cause > 1 & & cause < 128 ) {
switch_snprintf ( reason , sizeof ( reason ) , " Q.850;cause=%d;text= \" %s \" " , cause , switch_channel_cause2str ( cause ) ) ;
} else if ( cause = = SWITCH_CAUSE_PICKED_OFF ) {
switch_snprintf ( reason , sizeof ( reason ) , " SIP;cause=200;text= \" Call completed elsewhere \" " ) ;
} else {
switch_snprintf ( reason , sizeof ( reason ) , " FreeSWITCH;cause=%d;text= \" %s \" " , cause , switch_channel_cause2str ( cause ) ) ;
}
2007-11-20 01:44:07 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_ANS ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Sending BYE to %s \n " , switch_channel_get_name ( channel ) ) ;
2008-02-02 00:26:22 +00:00
nua_bye ( tech_pvt - > nh , SIPTAG_REASON_STR ( reason ) , TAG_END ( ) ) ;
2007-11-20 01:44:07 +00:00
} else {
if ( switch_test_flag ( tech_pvt , TFLAG_OUTBOUND ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Sending CANCEL to %s \n " , switch_channel_get_name ( channel ) ) ;
2008-02-22 15:02:16 +00:00
nua_cancel ( tech_pvt - > nh , SIPTAG_REASON_STR ( reason ) , TAG_END ( ) ) ;
2007-03-31 19:01:33 +00:00
} else {
2007-11-20 01:44:07 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Responding to INVITE with: %d \n " , sip_cause ) ;
2008-02-22 15:02:16 +00:00
nua_respond ( tech_pvt - > nh , sip_cause , sip_status_phrase ( sip_cause ) , SIPTAG_REASON_STR ( reason ) , TAG_END ( ) ) ;
2007-03-31 19:01:33 +00:00
}
2006-09-29 18:12:31 +00:00
}
2007-11-20 01:44:07 +00:00
switch_set_flag ( tech_pvt , TFLAG_BYE ) ;
2006-09-29 18:12:31 +00:00
}
2007-06-19 16:29:59 +00:00
switch_clear_flag ( tech_pvt , TFLAG_IO ) ;
2007-04-29 01:16:49 +00:00
tech_pvt - > profile - > inuse - - ;
switch_mutex_unlock ( tech_pvt - > profile - > flag_mutex ) ;
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > sofia_private ) {
* tech_pvt - > sofia_private - > uuid = ' \0 ' ;
2006-09-28 21:21:44 +00:00
}
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_SUCCESS ;
2006-09-28 21:21:44 +00:00
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_on_loopback ( switch_core_session_t * session )
2007-03-29 22:31:56 +00:00
{
2007-03-31 19:01:33 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SOFIA LOOPBACK \n " ) ;
return SWITCH_STATUS_SUCCESS ;
2006-09-27 03:44:14 +00:00
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_on_transmit ( switch_core_session_t * session )
2007-03-29 22:31:56 +00:00
{
2007-03-31 19:01:33 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " SOFIA TRANSMIT \n " ) ;
return SWITCH_STATUS_SUCCESS ;
2006-09-27 03:44:14 +00:00
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_answer_channel ( switch_core_session_t * session )
2006-09-27 03:44:14 +00:00
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-31 19:01:33 +00:00
switch_status_t status ;
2007-10-19 21:06:09 +00:00
uint32_t session_timeout = 0 ;
2007-11-01 11:28:26 +00:00
const char * val ;
2006-09-27 03:44:14 +00:00
2007-11-20 01:44:07 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_ANS ) | | switch_channel_test_flag ( channel , CF_OUTBOUND ) ) {
return SWITCH_STATUS_SUCCESS ;
}
2006-09-27 03:44:14 +00:00
2007-11-20 01:44:07 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_ANS ) ;
2007-03-05 06:04:37 +00:00
2008-02-21 17:48:41 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) | | switch_channel_test_flag ( channel , CF_PROXY_MEDIA ) ) {
2007-11-20 01:44:07 +00:00
const char * sdp = NULL ;
if ( ( sdp = switch_channel_get_variable ( channel , SWITCH_B_SDP_VARIABLE ) ) ) {
tech_pvt - > local_sdp_str = switch_core_session_strdup ( session , sdp ) ;
}
2008-02-21 17:48:41 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MEDIA ) ) {
sofia_glue_tech_patch_sdp ( tech_pvt ) ;
if ( sofia_glue_activate_rtp ( tech_pvt , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
return SWITCH_STATUS_FALSE ;
}
}
2007-11-20 01:44:07 +00:00
} else {
if ( switch_test_flag ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ;
if ( ! switch_channel_test_flag ( tech_pvt - > channel , CF_OUTBOUND ) ) {
const char * r_sdp = switch_channel_get_variable ( channel , SWITCH_R_SDP_VARIABLE ) ;
tech_pvt - > num_codecs = 0 ;
sofia_glue_tech_prepare_codecs ( tech_pvt ) ;
if ( sofia_glue_tech_media ( tech_pvt , r_sdp ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
2008-02-20 03:57:01 +00:00
//nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
2007-11-20 01:44:07 +00:00
return SWITCH_STATUS_FALSE ;
2007-03-31 19:01:33 +00:00
}
}
}
2007-04-29 01:16:49 +00:00
2008-02-21 17:48:41 +00:00
if ( ( status = sofia_glue_tech_choose_port ( tech_pvt , 0 ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-11-20 01:44:07 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return status ;
}
sofia_glue_set_local_sdp ( tech_pvt , NULL , 0 , NULL , 0 ) ;
if ( sofia_glue_activate_rtp ( tech_pvt , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2007-10-19 21:06:09 +00:00
2007-11-20 01:44:07 +00:00
if ( tech_pvt - > nh ) {
if ( tech_pvt - > local_sdp_str ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Local SDP %s: \n %s \n " , switch_channel_get_name ( channel ) ,
tech_pvt - > local_sdp_str ) ;
2007-10-19 21:06:09 +00:00
}
}
2007-11-20 01:44:07 +00:00
}
2007-10-19 21:06:09 +00:00
2007-11-20 01:44:07 +00:00
if ( ( val = switch_channel_get_variable ( channel , SOFIA_SESSION_TIMEOUT ) ) ) {
int v_session_timeout = atoi ( val ) ;
if ( v_session_timeout > = 0 ) {
session_timeout = v_session_timeout ;
}
2006-09-27 03:44:14 +00:00
}
2007-11-22 02:42:42 +00:00
2007-11-20 01:44:07 +00:00
nua_respond ( tech_pvt - > nh , SIP_200_OK ,
2008-01-03 00:50:53 +00:00
NUTAG_AUTOANSWER ( 0 ) ,
2007-11-20 01:44:07 +00:00
NUTAG_SESSION_TIMER ( session_timeout ) ,
SIPTAG_CONTACT_STR ( tech_pvt - > reply_contact ) ,
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) ,
2008-03-05 22:39:22 +00:00
SOATAG_REUSE_REJECTED ( 1 ) ,
SOATAG_ORDERED_USER ( 1 ) ,
2007-11-20 01:44:07 +00:00
SOATAG_AUDIO_AUX ( " cn telephone-event " ) ,
NUTAG_INCLUDE_EXTRA_SDP ( 1 ) ,
TAG_END ( ) ) ;
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_SUCCESS ;
2006-09-27 03:44:14 +00:00
}
2007-04-19 21:40:50 +00:00
static switch_status_t sofia_read_video_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout , switch_io_flag_t flags , int stream_id )
2006-08-25 23:55:59 +00:00
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-31 19:01:33 +00:00
int payload = 0 ;
2006-10-06 22:39:49 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2006-10-31 21:38:06 +00:00
2007-05-10 18:17:34 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HUP ) ) {
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_FALSE ;
2006-08-25 23:55:59 +00:00
}
2007-04-19 21:40:50 +00:00
while ( ! ( tech_pvt - > video_read_codec . implementation & & switch_rtp_ready ( tech_pvt - > video_rtp_session ) ) ) {
2007-03-31 19:01:33 +00:00
if ( switch_channel_ready ( channel ) ) {
switch_yield ( 10000 ) ;
} else {
return SWITCH_STATUS_GENERR ;
}
2006-08-25 23:55:59 +00:00
}
2007-04-19 21:40:50 +00:00
tech_pvt - > video_read_frame . datalen = 0 ;
2006-08-25 23:55:59 +00:00
2007-04-19 21:40:50 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
switch_status_t status ;
if ( ! switch_test_flag ( tech_pvt , TFLAG_RTP ) ) {
return SWITCH_STATUS_GENERR ;
}
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt - > rtp_session ! = NULL ) ;
2007-04-19 21:40:50 +00:00
tech_pvt - > video_read_frame . datalen = 0 ;
while ( switch_test_flag ( tech_pvt , TFLAG_IO ) & & tech_pvt - > video_read_frame . datalen = = 0 ) {
tech_pvt - > video_read_frame . flags = SFF_NONE ;
status = switch_rtp_zerocopy_read_frame ( tech_pvt - > video_rtp_session , & tech_pvt - > video_read_frame ) ;
if ( status ! = SWITCH_STATUS_SUCCESS & & status ! = SWITCH_STATUS_BREAK ) {
2007-10-31 13:08:45 +00:00
if ( status = = SWITCH_STATUS_TIMEOUT ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_MEDIA_TIMEOUT ) ;
}
return status ;
2007-04-19 21:40:50 +00:00
}
payload = tech_pvt - > video_read_frame . payload ;
if ( tech_pvt - > video_read_frame . datalen > 0 ) {
break ;
}
2006-10-09 02:24:43 +00:00
}
2007-03-31 19:01:33 +00:00
}
2006-10-09 02:24:43 +00:00
2007-04-19 21:40:50 +00:00
if ( tech_pvt - > video_read_frame . datalen = = 0 ) {
* frame = NULL ;
return SWITCH_STATUS_GENERR ;
}
* frame = & tech_pvt - > video_read_frame ;
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t sofia_write_video_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout , switch_io_flag_t flags , int stream_id )
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-04-19 21:40:50 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2007-04-19 21:40:50 +00:00
while ( ! ( tech_pvt - > video_read_codec . implementation & & switch_rtp_ready ( tech_pvt - > video_rtp_session ) ) ) {
if ( switch_channel_ready ( channel ) ) {
switch_yield ( 10000 ) ;
} else {
return SWITCH_STATUS_GENERR ;
}
}
2007-05-10 18:17:34 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HUP ) ) {
2007-04-19 21:40:50 +00:00
return SWITCH_STATUS_FALSE ;
}
if ( ! switch_test_flag ( tech_pvt , TFLAG_RTP ) ) {
return SWITCH_STATUS_GENERR ;
}
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
return SWITCH_STATUS_SUCCESS ;
}
if ( ! switch_test_flag ( frame , SFF_CNG ) ) {
2008-01-11 04:23:09 +00:00
switch_rtp_write_frame ( tech_pvt - > video_rtp_session , frame ) ;
2007-04-19 21:40:50 +00:00
}
return status ;
}
static switch_status_t sofia_read_frame ( switch_core_session_t * session , switch_frame_t * * frame , int timeout , switch_io_flag_t flags , int stream_id )
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = switch_core_session_get_private ( session ) ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-04-19 21:40:50 +00:00
int payload = 0 ;
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2007-04-19 21:40:50 +00:00
2008-01-14 21:52:38 +00:00
if ( ! ( tech_pvt - > profile - > pflags & PFLAG_RUNNING ) ) {
2008-01-08 16:35:20 +00:00
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_NORMAL_CLEARING ) ;
return SWITCH_STATUS_FALSE ;
}
2007-05-10 18:17:34 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HUP ) ) {
2007-04-19 21:40:50 +00:00
return SWITCH_STATUS_FALSE ;
}
while ( ! ( tech_pvt - > read_codec . implementation & & switch_rtp_ready ( tech_pvt - > rtp_session ) ) ) {
if ( switch_channel_ready ( channel ) ) {
switch_yield ( 10000 ) ;
} else {
return SWITCH_STATUS_GENERR ;
}
}
tech_pvt - > read_frame . datalen = 0 ;
switch_set_flag_locked ( tech_pvt , TFLAG_READING ) ;
2007-03-20 23:11:20 +00:00
2007-03-31 19:01:33 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
switch_status_t status ;
2007-06-13 20:40:06 +00:00
2007-03-31 19:01:33 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_RTP ) ) {
return SWITCH_STATUS_GENERR ;
2007-03-08 02:52:31 +00:00
}
2007-02-03 19:47:21 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt - > rtp_session ! = NULL ) ;
2007-03-31 19:01:33 +00:00
tech_pvt - > read_frame . datalen = 0 ;
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
while ( switch_test_flag ( tech_pvt , TFLAG_IO ) & & tech_pvt - > read_frame . datalen = = 0 ) {
tech_pvt - > read_frame . flags = SFF_NONE ;
2006-10-06 22:39:49 +00:00
2007-03-31 19:01:33 +00:00
status = switch_rtp_zerocopy_read_frame ( tech_pvt - > rtp_session , & tech_pvt - > read_frame ) ;
if ( status ! = SWITCH_STATUS_SUCCESS & & status ! = SWITCH_STATUS_BREAK ) {
2007-10-31 13:08:45 +00:00
if ( status = = SWITCH_STATUS_TIMEOUT ) {
switch_channel_hangup ( tech_pvt - > channel , SWITCH_CAUSE_MEDIA_TIMEOUT ) ;
}
return status ;
2007-03-31 19:01:33 +00:00
}
2007-10-31 13:08:45 +00:00
2007-03-31 19:01:33 +00:00
payload = tech_pvt - > read_frame . payload ;
2007-01-28 17:37:51 +00:00
2007-03-31 19:01:33 +00:00
if ( switch_rtp_has_dtmf ( tech_pvt - > rtp_session ) ) {
2007-12-22 00:32:20 +00:00
switch_dtmf_t dtmf = { 0 } ;
switch_rtp_dequeue_dtmf ( tech_pvt - > rtp_session , & dtmf ) ;
switch_channel_queue_dtmf ( channel , & dtmf ) ;
2007-03-29 22:31:56 +00:00
}
2006-10-31 21:38:06 +00:00
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > read_frame . datalen > 0 ) {
size_t bytes = 0 ;
int frames = 1 ;
2007-03-08 20:05:09 +00:00
2007-03-31 19:01:33 +00:00
if ( ! switch_test_flag ( ( & tech_pvt - > read_frame ) , SFF_CNG ) ) {
if ( ( bytes = tech_pvt - > read_codec . implementation - > encoded_bytes_per_frame ) ) {
frames = ( tech_pvt - > read_frame . datalen / bytes ) ;
}
tech_pvt - > read_frame . samples = ( int ) ( frames * tech_pvt - > read_codec . implementation - > samples_per_frame ) ;
}
break ;
}
2007-03-08 20:05:09 +00:00
}
2006-08-25 23:55:59 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-31 19:01:33 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_READING ) ;
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > read_frame . datalen = = 0 ) {
* frame = NULL ;
return SWITCH_STATUS_GENERR ;
2006-08-25 23:55:59 +00:00
}
2007-03-31 19:01:33 +00:00
* frame = & tech_pvt - > read_frame ;
2006-10-31 21:38:06 +00:00
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_write_frame ( switch_core_session_t * session , switch_frame_t * frame , int timeout , switch_io_flag_t flags , int stream_id )
2006-08-25 23:55:59 +00:00
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = switch_core_session_get_private ( session ) ;
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
2007-03-31 19:01:33 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
int bytes = 0 , samples = 0 , frames = 0 ;
2006-08-25 23:55:59 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
while ( ! ( tech_pvt - > read_codec . implementation & & switch_rtp_ready ( tech_pvt - > rtp_session ) ) ) {
if ( switch_channel_ready ( channel ) ) {
switch_yield ( 10000 ) ;
} else {
return SWITCH_STATUS_GENERR ;
}
2007-03-19 21:09:53 +00:00
}
2006-10-05 04:06:07 +00:00
2007-12-13 04:01:29 +00:00
if ( ! tech_pvt - > read_codec . implementation ) {
return SWITCH_STATUS_GENERR ;
}
2007-05-10 18:17:34 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_HUP ) ) {
2007-03-19 21:09:53 +00:00
return SWITCH_STATUS_FALSE ;
}
2006-10-19 16:42:41 +00:00
2007-03-31 19:01:33 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_RTP ) ) {
return SWITCH_STATUS_GENERR ;
2007-03-19 21:09:53 +00:00
}
2007-03-31 19:01:33 +00:00
if ( ! switch_test_flag ( tech_pvt , TFLAG_IO ) ) {
return SWITCH_STATUS_SUCCESS ;
2007-03-19 21:09:53 +00:00
}
2007-03-29 22:31:56 +00:00
2007-03-31 19:01:33 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_WRITING ) ;
2006-10-16 04:39:00 +00:00
2008-02-21 17:48:41 +00:00
if ( ! switch_test_flag ( frame , SFF_CNG ) & & ! switch_test_flag ( frame , SFF_PROXY_PACKET ) ) {
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > read_codec . implementation - > encoded_bytes_per_frame ) {
bytes = tech_pvt - > read_codec . implementation - > encoded_bytes_per_frame ;
frames = ( ( int ) frame - > datalen / bytes ) ;
} else
frames = 1 ;
2007-03-29 22:31:56 +00:00
2007-03-31 19:01:33 +00:00
samples = frames * tech_pvt - > read_codec . implementation - > samples_per_frame ;
2007-03-19 21:09:53 +00:00
}
2006-10-06 22:39:49 +00:00
2007-03-31 19:01:33 +00:00
tech_pvt - > timestamp_send + = samples ;
2008-01-11 04:23:09 +00:00
switch_rtp_write_frame ( tech_pvt - > rtp_session , frame ) ;
2006-10-18 22:57:35 +00:00
2007-03-31 19:01:33 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_WRITING ) ;
return status ;
}
2006-10-18 22:57:35 +00:00
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_kill_channel ( switch_core_session_t * session , int sig )
{
2008-01-28 07:26:10 +00:00
private_object_t * tech_pvt = switch_core_session_get_private ( session ) ;
2007-02-06 18:11:25 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2007-02-13 01:22:17 +00:00
2007-03-31 19:01:33 +00:00
switch ( sig ) {
case SWITCH_SIG_BREAK :
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
switch_rtp_set_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_BREAK ) ;
2007-02-13 01:22:17 +00:00
}
2007-04-19 21:40:50 +00:00
if ( switch_rtp_ready ( tech_pvt - > video_rtp_session ) ) {
switch_rtp_set_flag ( tech_pvt - > video_rtp_session , SWITCH_RTP_FLAG_BREAK ) ;
}
2007-03-31 19:01:33 +00:00
break ;
case SWITCH_SIG_KILL :
default :
switch_clear_flag_locked ( tech_pvt , TFLAG_IO ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_HUP ) ;
2007-03-29 22:31:56 +00:00
2007-03-31 19:01:33 +00:00
if ( switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
switch_rtp_kill_socket ( tech_pvt - > rtp_session ) ;
}
2007-04-19 21:40:50 +00:00
if ( switch_rtp_ready ( tech_pvt - > video_rtp_session ) ) {
switch_rtp_kill_socket ( tech_pvt - > video_rtp_session ) ;
}
2007-03-31 19:01:33 +00:00
break ;
2007-03-19 21:09:53 +00:00
}
return SWITCH_STATUS_SUCCESS ;
2006-10-06 22:39:49 +00:00
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_waitfor_read ( switch_core_session_t * session , int ms , int stream_id )
2006-10-06 22:39:49 +00:00
{
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-10-06 22:39:49 +00:00
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_waitfor_write ( switch_core_session_t * session , int ms , int stream_id )
2006-08-25 23:55:59 +00:00
{
return SWITCH_STATUS_SUCCESS ;
}
2007-12-22 00:32:20 +00:00
static switch_status_t sofia_send_dtmf ( switch_core_session_t * session , const switch_dtmf_t * dtmf )
2006-08-25 23:55:59 +00:00
{
2007-03-31 19:01:33 +00:00
private_object_t * tech_pvt ;
2007-12-22 00:32:20 +00:00
char message [ 128 ] = " " ;
2006-08-25 23:55:59 +00:00
tech_pvt = ( private_object_t * ) switch_core_session_get_private ( session ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2006-08-25 23:55:59 +00:00
2007-12-22 00:32:20 +00:00
switch ( tech_pvt - > dtmf_type ) {
case DTMF_2833 :
return switch_rtp_queue_rfc2833 ( tech_pvt - > rtp_session , dtmf ) ;
case DTMF_INFO :
2008-01-13 20:08:12 +00:00
snprintf ( message , sizeof ( message ) , " Signal=%c \r \n Duration=%d \r \n " , dtmf - > digit , dtmf - > duration / 8 ) ;
2007-12-22 00:32:20 +00:00
nua_info ( tech_pvt - > nh ,
SIPTAG_CONTENT_TYPE_STR ( " application/dtmf-relay " ) ,
SIPTAG_PAYLOAD_STR ( message ) ,
TAG_END ( ) ) ;
break ;
default :
break ;
}
return SWITCH_STATUS_SUCCESS ;
2006-09-12 22:24:39 +00:00
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_receive_message ( switch_core_session_t * session , switch_core_session_message_t * msg )
2006-08-25 23:55:59 +00:00
{
2008-01-28 07:26:10 +00:00
switch_channel_t * channel = switch_core_session_get_channel ( session ) ;
private_object_t * tech_pvt = switch_core_session_get_private ( session ) ;
2008-02-25 16:35:19 +00:00
switch_status_t status = SWITCH_STATUS_SUCCESS ;
2008-02-15 19:48:16 +00:00
if ( switch_channel_get_state ( channel ) > = CS_HANGUP | | ! tech_pvt ) {
2008-02-25 16:35:19 +00:00
status = SWITCH_STATUS_FALSE ;
goto end ;
2008-02-15 19:48:16 +00:00
}
2006-08-25 23:55:59 +00:00
2008-03-04 23:53:23 +00:00
if ( msg - > message_id = = SWITCH_MESSAGE_INDICATE_ANSWER | | msg - > message_id = = SWITCH_MESSAGE_INDICATE_PROGRESS ) {
const char * var ;
if ( ( var = switch_channel_get_variable ( channel , SOFIA_SECURE_MEDIA_VARIABLE ) ) & & switch_true ( var ) ) {
switch_set_flag_locked ( tech_pvt , TFLAG_SECURE ) ;
}
}
2007-03-31 19:01:33 +00:00
switch ( msg - > message_id ) {
2008-02-07 00:04:14 +00:00
case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ :
{
const char * pl =
" <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?> \r \n "
" <media_control> \r \n "
" <vc_primitive> \r \n "
" <to_encoder> \r \n "
" <picture_fast_update> \r \n "
" </picture_fast_update> \r \n "
" </to_encoder> \r \n "
" </vc_primitive> \r \n "
" </media_control> \r \n " ;
nua_info ( tech_pvt - > nh ,
SIPTAG_CONTENT_TYPE_STR ( " application/media_control+xml " ) ,
SIPTAG_PAYLOAD_STR ( pl ) ,
TAG_END ( ) ) ;
}
break ;
2007-05-01 21:21:35 +00:00
case SWITCH_MESSAGE_INDICATE_BROADCAST : {
2007-11-01 11:28:26 +00:00
const char * ip = NULL , * port = NULL ;
2007-05-01 21:21:35 +00:00
ip = switch_channel_get_variable ( channel , SWITCH_REMOTE_MEDIA_IP_VARIABLE ) ;
port = switch_channel_get_variable ( channel , SWITCH_REMOTE_MEDIA_PORT_VARIABLE ) ;
if ( ip & & port ) {
2007-05-02 19:37:40 +00:00
sofia_glue_set_local_sdp ( tech_pvt , ip , atoi ( port ) , msg - > string_arg , 1 ) ;
2007-05-01 21:21:35 +00:00
}
nua_respond ( tech_pvt - > nh , SIP_200_OK ,
2007-05-29 14:59:03 +00:00
SIPTAG_CONTACT_STR ( tech_pvt - > reply_contact ) ,
2007-11-20 01:44:07 +00:00
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) ,
2008-03-05 22:39:22 +00:00
SOATAG_REUSE_REJECTED ( 1 ) ,
SOATAG_ORDERED_USER ( 1 ) ,
2007-11-20 01:44:07 +00:00
SOATAG_AUDIO_AUX ( " cn telephone-event " ) ,
NUTAG_INCLUDE_EXTRA_SDP ( 1 ) ,
TAG_END ( ) ) ;
2007-05-01 21:21:35 +00:00
switch_channel_mark_answered ( channel ) ;
}
break ;
2007-09-19 18:24:47 +00:00
case SWITCH_MESSAGE_INDICATE_NOMEDIA :
{
2007-11-01 11:28:26 +00:00
const char * uuid ;
2007-03-31 19:01:33 +00:00
switch_core_session_t * other_session ;
switch_channel_t * other_channel ;
2007-11-01 11:28:26 +00:00
const char * ip = NULL , * port = NULL ;
2008-02-15 19:48:16 +00:00
2008-02-21 17:48:41 +00:00
switch_channel_set_flag ( channel , CF_PROXY_MODE ) ;
2007-03-31 19:01:33 +00:00
tech_pvt - > local_sdp_str = NULL ;
if ( ( uuid = switch_channel_get_variable ( channel , SWITCH_SIGNAL_BOND_VARIABLE ) )
& & ( other_session = switch_core_session_locate ( uuid ) ) ) {
other_channel = switch_core_session_get_channel ( other_session ) ;
ip = switch_channel_get_variable ( other_channel , SWITCH_REMOTE_MEDIA_IP_VARIABLE ) ;
port = switch_channel_get_variable ( other_channel , SWITCH_REMOTE_MEDIA_PORT_VARIABLE ) ;
switch_core_session_rwunlock ( other_session ) ;
if ( ip & & port ) {
sofia_glue_set_local_sdp ( tech_pvt , ip , atoi ( port ) , NULL , 1 ) ;
2006-09-18 16:32:47 +00:00
}
2006-09-08 03:28:49 +00:00
}
2007-03-31 19:01:33 +00:00
if ( ! tech_pvt - > local_sdp_str ) {
sofia_glue_tech_absorb_sdp ( tech_pvt ) ;
}
sofia_glue_do_invite ( session ) ;
2007-09-19 18:24:47 +00:00
}
2007-03-31 19:01:33 +00:00
break ;
2007-05-14 23:50:38 +00:00
2007-09-19 18:24:47 +00:00
case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT :
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Sending media re-direct: \n %s \n " , msg - > string_arg ) ;
tech_pvt - > local_sdp_str = switch_core_session_strdup ( session , msg - > string_arg ) ;
2008-02-26 20:31:53 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_SENT_UPDATE ) ;
2007-09-19 18:24:47 +00:00
sofia_glue_do_invite ( session ) ;
2007-05-14 23:50:38 +00:00
}
2007-09-19 18:24:47 +00:00
break ;
case SWITCH_MESSAGE_INDICATE_MEDIA :
{
2008-03-04 00:52:54 +00:00
uint32_t count = 0 , send_invite = 1 ;
2008-02-21 17:48:41 +00:00
switch_channel_clear_flag ( channel , CF_PROXY_MODE ) ;
2007-03-31 19:01:33 +00:00
tech_pvt - > local_sdp_str = NULL ;
2008-03-04 00:52:54 +00:00
if ( ! switch_channel_media_ready ( channel ) ) {
if ( ! switch_channel_test_flag ( tech_pvt - > channel , CF_OUTBOUND ) ) {
const char * r_sdp = switch_channel_get_variable ( channel , SWITCH_R_SDP_VARIABLE ) ;
tech_pvt - > num_codecs = 0 ;
sofia_glue_tech_prepare_codecs ( tech_pvt ) ;
if ( sofia_glue_tech_media ( tech_pvt , r_sdp ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
status = SWITCH_STATUS_FALSE ;
goto end ;
}
send_invite = 0 ;
}
}
2007-03-31 19:01:33 +00:00
if ( ! switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
2007-04-17 06:08:39 +00:00
sofia_glue_tech_prepare_codecs ( tech_pvt ) ;
2008-02-21 17:48:41 +00:00
if ( ( status = sofia_glue_tech_choose_port ( tech_pvt , 0 ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-17 14:44:22 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
2008-02-25 16:35:19 +00:00
goto end ;
2007-03-31 19:01:33 +00:00
}
}
sofia_glue_set_local_sdp ( tech_pvt , NULL , 0 , NULL , 1 ) ;
2007-05-09 19:30:41 +00:00
2008-03-04 00:52:54 +00:00
if ( send_invite ) {
sofia_glue_do_invite ( session ) ;
/* wait for rtp to start and first real frame to arrive */
tech_pvt - > read_frame . datalen = 0 ;
while ( switch_test_flag ( tech_pvt , TFLAG_IO ) & & switch_channel_get_state ( channel ) < CS_HANGUP & & ! switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
if ( + + count > 1000 ) {
status = SWITCH_STATUS_FALSE ;
goto end ;
}
if ( ! switch_rtp_ready ( tech_pvt - > rtp_session ) ) {
switch_yield ( 1000 ) ;
continue ;
}
break ;
2007-05-09 19:30:41 +00:00
}
2007-03-31 19:01:33 +00:00
}
}
break ;
2006-08-25 23:55:59 +00:00
2007-09-19 18:24:47 +00:00
case SWITCH_MESSAGE_INDICATE_HOLD :
{
2008-02-26 20:31:53 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
2007-03-31 19:01:33 +00:00
sofia_glue_do_invite ( session ) ;
}
break ;
2007-09-19 18:24:47 +00:00
case SWITCH_MESSAGE_INDICATE_UNHOLD :
{
2007-03-31 19:01:33 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_SIP_HOLD ) ;
sofia_glue_do_invite ( session ) ;
}
break ;
case SWITCH_MESSAGE_INDICATE_BRIDGE :
2007-05-09 19:30:41 +00:00
2007-03-31 19:01:33 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_XFER ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_XFER ) ;
if ( msg - > pointer_arg ) {
switch_core_session_t * a_session , * b_session = msg - > pointer_arg ;
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
if ( ( a_session = switch_core_session_locate ( tech_pvt - > xferto ) ) ) {
private_object_t * a_tech_pvt = switch_core_session_get_private ( a_session ) ;
private_object_t * b_tech_pvt = switch_core_session_get_private ( b_session ) ;
2006-08-25 23:55:59 +00:00
2008-02-26 20:31:53 +00:00
switch_set_flag_locked ( a_tech_pvt , TFLAG_REINVITE ) ;
2007-03-31 19:01:33 +00:00
a_tech_pvt - > remote_sdp_audio_ip = switch_core_session_strdup ( a_session , b_tech_pvt - > remote_sdp_audio_ip ) ;
a_tech_pvt - > remote_sdp_audio_port = b_tech_pvt - > remote_sdp_audio_port ;
a_tech_pvt - > local_sdp_audio_ip = switch_core_session_strdup ( a_session , b_tech_pvt - > local_sdp_audio_ip ) ;
a_tech_pvt - > local_sdp_audio_port = b_tech_pvt - > local_sdp_audio_port ;
2007-10-25 18:36:40 +00:00
if ( sofia_glue_activate_rtp ( a_tech_pvt , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-17 06:08:39 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2007-03-31 19:01:33 +00:00
b_tech_pvt - > kick = switch_core_session_strdup ( b_session , tech_pvt - > xferto ) ;
switch_core_session_rwunlock ( a_session ) ;
}
2006-08-25 23:55:59 +00:00
2007-03-31 19:01:33 +00:00
msg - > pointer_arg = NULL ;
2008-02-25 16:35:19 +00:00
status = SWITCH_STATUS_FALSE ;
goto end ;
2007-03-31 19:01:33 +00:00
}
2006-10-24 21:31:39 +00:00
}
2007-12-06 22:26:37 +00:00
/*
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > rtp_session & & switch_test_flag ( tech_pvt , TFLAG_TIMER ) ) {
switch_rtp_clear_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_USE_TIMER ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " De-activate timed RTP! \n " ) ;
2006-11-25 16:52:35 +00:00
}
2007-12-06 22:26:37 +00:00
*/
2006-08-25 23:55:59 +00:00
break ;
2007-03-31 19:01:33 +00:00
case SWITCH_MESSAGE_INDICATE_UNBRIDGE :
2007-12-06 22:26:37 +00:00
/*
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > rtp_session & & switch_test_flag ( tech_pvt , TFLAG_TIMER ) ) {
switch_rtp_set_flag ( tech_pvt - > rtp_session , SWITCH_RTP_FLAG_USE_TIMER ) ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Re-activate timed RTP! \n " ) ;
2007-03-29 22:31:56 +00:00
}
2007-12-06 22:26:37 +00:00
*/
2006-08-25 23:55:59 +00:00
break ;
2007-03-31 19:01:33 +00:00
case SWITCH_MESSAGE_INDICATE_REDIRECT :
if ( msg - > string_arg ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Re-directing to %s \n " , msg - > string_arg ) ;
nua_respond ( tech_pvt - > nh , SIP_302_MOVED_TEMPORARILY , SIPTAG_CONTACT_STR ( msg - > string_arg ) , TAG_END ( ) ) ;
2008-02-26 20:31:53 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
2007-03-29 22:31:56 +00:00
}
2006-08-25 23:55:59 +00:00
break ;
2008-01-03 23:42:15 +00:00
case SWITCH_MESSAGE_INDICATE_DEFLECT :
{
char ref_to [ 128 ] = " " ;
if ( ! strstr ( msg - > string_arg , " sip: " ) ) {
switch_snprintf ( ref_to , sizeof ( ref_to ) , " sip:%s@%s " , msg - > string_arg , tech_pvt - > profile - > sipip ) ;
} else {
switch_set_string ( ref_to , msg - > string_arg ) ;
}
nua_refer ( tech_pvt - > nh , SIPTAG_REFER_TO_STR ( ref_to ) , SIPTAG_REFERRED_BY_STR ( tech_pvt - > contact_url ) , TAG_END ( ) ) ;
}
break ;
2008-01-03 00:50:53 +00:00
case SWITCH_MESSAGE_INDICATE_RESPOND :
if ( msg - > numeric_arg | | msg - > string_arg ) {
int code = msg - > numeric_arg ;
const char * reason = NULL ;
2007-04-21 15:04:01 +00:00
2008-01-03 00:50:53 +00:00
if ( code ) {
reason = msg - > string_arg ;
} else {
2007-06-08 22:28:32 +00:00
if ( ! switch_strlen_zero ( msg - > string_arg ) ) {
2008-01-26 03:56:40 +00:00
if ( ( code = atoi ( msg - > string_arg ) ) ) {
if ( ( reason = strchr ( msg - > string_arg , ' ' ) ) ) {
reason + + ;
}
2008-01-03 00:50:53 +00:00
}
2007-06-08 22:28:32 +00:00
}
2008-01-03 00:50:53 +00:00
}
2007-06-08 22:28:32 +00:00
2008-01-07 18:02:01 +00:00
if ( ! code ) {
2008-01-03 00:50:53 +00:00
code = 488 ;
}
2008-02-08 15:44:39 +00:00
if ( ! reason & & code ! = 407 ) {
reason = " Call Refused " ;
if ( ! reason ) {
reason = sip_status_phrase ( code ) ;
if ( switch_strlen_zero ( reason ) ) {
reason = " Because " ;
}
2008-01-26 03:56:40 +00:00
}
}
if ( code = = 407 & & ! msg - > numeric_arg ) {
2008-01-03 00:50:53 +00:00
const char * to_uri = switch_channel_get_variable ( channel , " sip_to_uri " ) ;
const char * to_host = reason ;
2007-06-08 22:28:32 +00:00
2008-01-03 00:50:53 +00:00
if ( switch_strlen_zero ( to_host ) ) {
to_host = switch_channel_get_variable ( channel , " sip_to_host " ) ;
2007-06-08 22:28:32 +00:00
}
2008-01-03 00:50:53 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Challenging call %s \n " , to_uri ) ;
sofia_reg_auth_challange ( NULL , tech_pvt - > profile , tech_pvt - > nh , REG_INVITE , to_host , 0 ) ;
switch_channel_hangup ( channel , SWITCH_CAUSE_USER_CHALLENGE ) ;
2008-01-26 03:56:40 +00:00
} else if ( code = = 484 & & msg - > numeric_arg ) {
2008-01-24 20:49:53 +00:00
const char * to = switch_channel_get_variable ( channel , " sip_to_uri " ) ;
const char * max_forwards = switch_channel_get_variable ( channel , SWITCH_MAX_FORWARDS_VARIABLE ) ;
char * to_uri = NULL ;
if ( to ) {
char * p ;
to_uri = switch_core_session_sprintf ( session , " sip:%s " , to ) ;
if ( ( p = strstr ( to_uri , " :5060 " ) ) ) {
* p = ' \0 ' ;
}
}
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Overlap Dial with %d %s \n " , code , reason ) ;
nua_respond ( tech_pvt - > nh , code , reason , TAG_IF ( to_uri , SIPTAG_CONTACT_STR ( to_uri ) ) ,
SIPTAG_SUPPORTED_STR ( NULL ) , SIPTAG_ACCEPT_STR ( NULL ) ,
TAG_IF ( ! switch_strlen_zero ( max_forwards ) , SIPTAG_MAX_FORWARDS_STR ( max_forwards ) ) , TAG_END ( ) ) ;
2008-02-26 20:31:53 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
2008-01-03 00:50:53 +00:00
} else {
2008-01-07 18:02:01 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Responding with %d %s \n " , code , reason ) ;
2008-02-22 14:06:13 +00:00
2008-02-20 21:31:15 +00:00
if ( ! switch_strlen_zero ( ( ( char * ) msg - > pointer_arg ) ) ) {
2008-02-22 14:06:13 +00:00
tech_pvt - > local_sdp_str = switch_core_session_strdup ( tech_pvt - > session , ( char * ) msg - > pointer_arg ) ;
if ( switch_channel_test_flag ( channel , CF_PROXY_MEDIA ) ) {
sofia_glue_tech_patch_sdp ( tech_pvt ) ;
2008-02-22 15:27:40 +00:00
sofia_glue_tech_proxy_remote_addr ( tech_pvt ) ;
2008-02-22 14:06:13 +00:00
}
2008-02-20 21:31:15 +00:00
nua_respond ( tech_pvt - > nh , code , reason , SIPTAG_CONTACT_STR ( tech_pvt - > reply_contact ) ,
2008-02-22 14:06:13 +00:00
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) ,
2008-03-05 22:39:22 +00:00
SOATAG_REUSE_REJECTED ( 1 ) ,
SOATAG_ORDERED_USER ( 1 ) ,
2008-02-21 17:48:41 +00:00
SOATAG_AUDIO_AUX ( " cn telephone-event " ) ,
NUTAG_INCLUDE_EXTRA_SDP ( 1 ) ,
TAG_END ( ) ) ;
2008-02-20 21:31:15 +00:00
} else {
nua_respond ( tech_pvt - > nh , code , reason , SIPTAG_CONTACT_STR ( tech_pvt - > reply_contact ) , TAG_END ( ) ) ;
}
2008-02-26 20:31:53 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_BYE ) ;
2007-04-21 15:04:01 +00:00
}
2008-01-03 00:50:53 +00:00
2007-04-21 15:04:01 +00:00
}
break ;
2007-03-31 19:01:33 +00:00
case SWITCH_MESSAGE_INDICATE_RINGING :
2008-01-05 16:20:39 +00:00
if ( ! switch_channel_test_flag ( channel , CF_RING_READY ) & &
! switch_channel_test_flag ( channel , CF_EARLY_MEDIA ) & & ! switch_channel_test_flag ( channel , CF_ANSWERED ) ) {
2008-02-25 16:35:19 +00:00
nua_respond ( tech_pvt - > nh , SIP_180_RINGING , SIPTAG_CONTACT_STR ( tech_pvt - > reply_contact ) , TAG_END ( ) ) ;
2008-01-05 16:20:39 +00:00
switch_channel_mark_ring_ready ( channel ) ;
}
2007-04-16 16:53:30 +00:00
break ;
case SWITCH_MESSAGE_INDICATE_ANSWER :
2008-02-25 16:35:19 +00:00
status = sofia_answer_channel ( session ) ;
2006-08-25 23:55:59 +00:00
break ;
2008-02-15 19:48:16 +00:00
case SWITCH_MESSAGE_INDICATE_PROGRESS :
{
if ( ! switch_test_flag ( tech_pvt , TFLAG_ANS ) & & ! switch_test_flag ( tech_pvt , TFLAG_EARLY_MEDIA ) ) {
2007-04-16 16:53:30 +00:00
2008-02-26 20:31:53 +00:00
switch_set_flag_locked ( tech_pvt , TFLAG_EARLY_MEDIA ) ;
2007-03-31 19:01:33 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Asked to send early media by %s \n " , msg - > from ) ;
2008-02-20 03:57:01 +00:00
2007-03-31 19:01:33 +00:00
/* Transmit 183 Progress with SDP */
2008-02-21 17:48:41 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MODE ) | | switch_channel_test_flag ( channel , CF_PROXY_MEDIA ) ) {
2007-11-01 11:28:26 +00:00
const char * sdp = NULL ;
2007-03-31 19:01:33 +00:00
if ( ( sdp = switch_channel_get_variable ( channel , SWITCH_B_SDP_VARIABLE ) ) ) {
tech_pvt - > local_sdp_str = switch_core_session_strdup ( session , sdp ) ;
2006-08-25 23:55:59 +00:00
}
2008-02-21 17:48:41 +00:00
if ( switch_channel_test_flag ( channel , CF_PROXY_MEDIA ) ) {
sofia_glue_tech_patch_sdp ( tech_pvt ) ;
if ( sofia_glue_activate_rtp ( tech_pvt , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
2008-02-25 16:35:19 +00:00
status = SWITCH_STATUS_FALSE ;
goto end ;
2008-02-21 17:48:41 +00:00
}
}
2007-01-15 19:00:47 +00:00
} else {
2007-03-31 19:01:33 +00:00
if ( switch_test_flag ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ) {
switch_clear_flag_locked ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ;
2008-02-20 03:57:01 +00:00
2007-11-03 00:46:23 +00:00
if ( ! switch_channel_test_flag ( tech_pvt - > channel , CF_OUTBOUND ) ) {
const char * r_sdp = switch_channel_get_variable ( channel , SWITCH_R_SDP_VARIABLE ) ;
2008-02-20 03:57:01 +00:00
2007-11-03 00:46:23 +00:00
tech_pvt - > num_codecs = 0 ;
sofia_glue_tech_prepare_codecs ( tech_pvt ) ;
if ( sofia_glue_tech_media ( tech_pvt , r_sdp ) ! = SWITCH_STATUS_SUCCESS ) {
switch_channel_set_variable ( channel , SWITCH_ENDPOINT_DISPOSITION_VARIABLE , " CODEC NEGOTIATION ERROR " ) ;
2008-02-20 03:57:01 +00:00
//nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
2008-02-25 16:35:19 +00:00
status = SWITCH_STATUS_FALSE ;
goto end ;
2007-11-03 00:46:23 +00:00
}
}
2007-03-31 19:01:33 +00:00
}
2006-10-19 07:13:34 +00:00
2008-02-21 17:48:41 +00:00
if ( ( status = sofia_glue_tech_choose_port ( tech_pvt , 0 ) ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-17 14:44:22 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
2008-02-25 16:35:19 +00:00
goto end ;
2007-03-31 19:01:33 +00:00
}
sofia_glue_set_local_sdp ( tech_pvt , NULL , 0 , NULL , 0 ) ;
2007-10-25 18:36:40 +00:00
if ( sofia_glue_activate_rtp ( tech_pvt , 0 ) ! = SWITCH_STATUS_SUCCESS ) {
2007-04-17 06:08:39 +00:00
switch_channel_hangup ( channel , SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
}
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > local_sdp_str ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_INFO , " Ring SDP: \n %s \n " , tech_pvt - > local_sdp_str ) ;
}
}
2007-04-16 16:53:30 +00:00
switch_channel_mark_pre_answered ( channel ) ;
2007-03-31 19:01:33 +00:00
nua_respond ( tech_pvt - > nh ,
SIP_183_SESSION_PROGRESS ,
2008-01-03 00:50:53 +00:00
NUTAG_AUTOANSWER ( 0 ) ,
2007-10-24 00:06:33 +00:00
SIPTAG_CONTACT_STR ( tech_pvt - > reply_contact ) ,
2008-03-05 22:39:22 +00:00
SOATAG_REUSE_REJECTED ( 1 ) ,
SOATAG_ORDERED_USER ( 1 ) ,
2007-03-31 19:01:33 +00:00
SOATAG_USER_SDP_STR ( tech_pvt - > local_sdp_str ) , SOATAG_AUDIO_AUX ( " cn telephone-event " ) , TAG_END ( ) ) ;
2006-10-20 22:11:26 +00:00
}
2006-10-18 22:57:35 +00:00
}
2007-03-31 19:01:33 +00:00
break ;
default :
break ;
2006-10-18 22:57:35 +00:00
}
2007-03-29 22:31:56 +00:00
2008-02-25 16:35:19 +00:00
end :
return status ;
2006-10-18 22:57:35 +00:00
}
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_receive_event ( switch_core_session_t * session , switch_event_t * event )
2006-10-19 19:39:18 +00:00
{
2008-01-28 07:26:10 +00:00
struct private_object * tech_pvt = switch_core_session_get_private ( session ) ;
2007-03-31 19:01:33 +00:00
char * body ;
nua_handle_t * msg_nh ;
2006-10-19 19:39:18 +00:00
2007-12-12 23:21:45 +00:00
switch_assert ( tech_pvt ! = NULL ) ;
2006-10-20 22:11:26 +00:00
2007-03-31 19:01:33 +00:00
if ( ! ( body = switch_event_get_body ( event ) ) ) {
body = " " ;
2006-10-22 04:37:19 +00:00
}
2007-03-31 19:01:33 +00:00
if ( tech_pvt - > hash_key ) {
msg_nh = nua_handle ( tech_pvt - > profile - > nua , NULL ,
SIPTAG_FROM_STR ( tech_pvt - > chat_from ) ,
NUTAG_URL ( tech_pvt - > chat_to ) , SIPTAG_TO_STR ( tech_pvt - > chat_to ) , SIPTAG_CONTACT_STR ( tech_pvt - > profile - > url ) , TAG_END ( ) ) ;
2006-10-20 22:11:26 +00:00
2007-03-31 19:01:33 +00:00
nua_message ( msg_nh , SIPTAG_CONTENT_TYPE_STR ( " text/html " ) , SIPTAG_PAYLOAD_STR ( body ) , TAG_END ( ) ) ;
}
2006-10-20 22:11:26 +00:00
2007-03-31 19:01:33 +00:00
return SWITCH_STATUS_SUCCESS ;
2006-10-20 22:11:26 +00:00
}
2007-04-29 01:16:49 +00:00
typedef switch_status_t ( * sofia_command_t ) ( char * * argv , int argc , switch_stream_handle_t * stream ) ;
2007-05-01 15:22:57 +00:00
static const char * sofia_state_names [ ] = { " UNREGED " ,
" TRYING " ,
" REGISTER " ,
" REGED " ,
2007-09-18 17:31:36 +00:00
" UNREGISTER " ,
2007-05-01 15:22:57 +00:00
" FAILED " ,
" EXPIRED " ,
2007-09-18 17:31:36 +00:00
" NOREG " ,
NULL } ;
2007-05-01 15:22:57 +00:00
struct cb_helper {
sofia_profile_t * profile ;
switch_stream_handle_t * stream ;
} ;
# define switch_time_from_sec(sec) ((switch_time_t)(sec) * 1000000)
static int show_reg_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
struct cb_helper * cb = ( struct cb_helper * ) pArg ;
char exp_buf [ 128 ] = " " ;
switch_time_exp_t tm ;
2007-10-19 03:27:03 +00:00
if ( argv [ 6 ] ) {
switch_time_t etime = atoi ( argv [ 6 ] ) ;
2007-05-01 15:22:57 +00:00
switch_size_t retsize ;
switch_time_exp_lt ( & tm , switch_time_from_sec ( etime ) ) ;
switch_strftime ( exp_buf , & retsize , sizeof ( exp_buf ) , " %Y-%m-%d %T " , & tm ) ;
}
2007-11-20 01:44:07 +00:00
2007-05-01 15:22:57 +00:00
cb - > stream - > write_function ( cb - > stream ,
2007-10-19 03:27:03 +00:00
" Call-ID \t %s \n "
2007-05-01 15:22:57 +00:00
" User \t %s@%s \n "
" Contact \t %s \n "
2007-12-15 00:39:53 +00:00
" Agent \t %s \n "
2007-05-01 15:22:57 +00:00
" Status \t %s(%s) EXP(%s) \n \n " ,
2007-10-19 03:27:03 +00:00
switch_str_nil ( argv [ 0 ] ) , switch_str_nil ( argv [ 1 ] ) , switch_str_nil ( argv [ 2 ] ) , switch_str_nil ( argv [ 3 ] ) ,
2007-12-15 00:39:53 +00:00
switch_str_nil ( argv [ 7 ] ) ,
switch_str_nil ( argv [ 4 ] ) ,
switch_str_nil ( argv [ 5 ] ) ,
exp_buf ) ;
2007-05-01 15:22:57 +00:00
return 0 ;
}
2007-04-29 01:16:49 +00:00
static switch_status_t cmd_status ( char * * argv , int argc , switch_stream_handle_t * stream )
{
sofia_profile_t * profile = NULL ;
2007-05-01 15:22:57 +00:00
sofia_gateway_t * gp ;
2007-04-29 01:16:49 +00:00
switch_hash_index_t * hi ;
void * val ;
2007-04-30 20:35:35 +00:00
const void * vvar ;
2007-04-29 01:16:49 +00:00
int c = 0 ;
2007-04-30 20:35:35 +00:00
int ac = 0 ;
2007-05-02 23:32:45 +00:00
const char * line = " ================================================================================================= " ;
2007-04-29 01:16:49 +00:00
2007-05-01 15:22:57 +00:00
if ( argc > 0 ) {
if ( argc = = 1 ) {
stream - > write_function ( stream , " Invalid Syntax! \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
if ( ! strcasecmp ( argv [ 0 ] , " gateway " ) ) {
if ( ( gp = sofia_reg_find_gateway ( argv [ 1 ] ) ) ) {
2007-12-12 23:21:45 +00:00
switch_assert ( gp - > state < REG_STATE_LAST ) ;
2007-05-01 15:22:57 +00:00
stream - > write_function ( stream , " %s \n " , line ) ;
stream - > write_function ( stream , " Name \t %s \n " , switch_str_nil ( gp - > name ) ) ;
stream - > write_function ( stream , " Scheme \t %s \n " , switch_str_nil ( gp - > register_scheme ) ) ;
stream - > write_function ( stream , " Realm \t %s \n " , switch_str_nil ( gp - > register_realm ) ) ;
stream - > write_function ( stream , " Username \t %s \n " , switch_str_nil ( gp - > register_username ) ) ;
stream - > write_function ( stream , " Password \t %s \n " , switch_strlen_zero ( gp - > register_password ) ? " no " : " yes " ) ;
stream - > write_function ( stream , " From \t %s \n " , switch_str_nil ( gp - > register_from ) ) ;
stream - > write_function ( stream , " Contact \t %s \n " , switch_str_nil ( gp - > register_contact ) ) ;
stream - > write_function ( stream , " To \t %s \n " , switch_str_nil ( gp - > register_to ) ) ;
stream - > write_function ( stream , " Proxy \t %s \n " , switch_str_nil ( gp - > register_proxy ) ) ;
stream - > write_function ( stream , " Context \t %s \n " , switch_str_nil ( gp - > register_context ) ) ;
stream - > write_function ( stream , " Expires \t %s \n " , switch_str_nil ( gp - > expires_str ) ) ;
stream - > write_function ( stream , " Freq \t %d \n " , gp - > freq ) ;
stream - > write_function ( stream , " State \t %s \n " , sofia_state_names [ gp - > state ] ) ;
stream - > write_function ( stream , " %s \n " , line ) ;
sofia_reg_release_gateway ( gp ) ;
} else {
stream - > write_function ( stream , " Invalid Gateway! \n " ) ;
}
} else if ( ! strcasecmp ( argv [ 0 ] , " profile " ) ) {
struct cb_helper cb ;
if ( ( profile = sofia_glue_find_profile ( argv [ 1 ] ) ) ) {
stream - > write_function ( stream , " %s \n " , line ) ;
stream - > write_function ( stream , " Name \t %s \n " , switch_str_nil ( argv [ 1 ] ) ) ;
2008-01-21 20:14:53 +00:00
stream - > write_function ( stream , " Domain Name \t %s \n " , switch_str_nil ( profile - > domain_name ) ) ;
2007-05-01 15:22:57 +00:00
if ( strcasecmp ( argv [ 1 ] , profile - > name ) ) {
stream - > write_function ( stream , " Alias Of \t %s \n " , switch_str_nil ( profile - > name ) ) ;
}
stream - > write_function ( stream , " DBName \t %s \n " , switch_str_nil ( profile - > dbname ) ) ;
stream - > write_function ( stream , " Dialplan \t %s \n " , switch_str_nil ( profile - > dialplan ) ) ;
stream - > write_function ( stream , " RTP-IP \t %s \n " , switch_str_nil ( profile - > rtpip ) ) ;
if ( profile - > extrtpip ) {
stream - > write_function ( stream , " Ext-RTP-IP \t %s \n " , profile - > extrtpip ) ;
}
stream - > write_function ( stream , " SIP-IP \t %s \n " , switch_str_nil ( profile - > sipip ) ) ;
if ( profile - > extsipip ) {
stream - > write_function ( stream , " Ext-SIP-IP \t %s \n " , profile - > extsipip ) ;
}
stream - > write_function ( stream , " URL \t %s \n " , switch_str_nil ( profile - > url ) ) ;
stream - > write_function ( stream , " BIND-URL \t %s \n " , switch_str_nil ( profile - > bindurl ) ) ;
2008-01-19 01:12:48 +00:00
if ( sofia_test_pflag ( profile , PFLAG_TLS ) ) {
stream - > write_function ( stream , " TLS-URL \t %s \n " , switch_str_nil ( profile - > tls_url ) ) ;
stream - > write_function ( stream , " TLS-BIND-URL \t %s \n " , switch_str_nil ( profile - > tls_bindurl ) ) ;
}
2007-05-01 15:22:57 +00:00
stream - > write_function ( stream , " HOLD-MUSIC \t %s \n " , switch_str_nil ( profile - > hold_music ) ) ;
stream - > write_function ( stream , " CODECS \t %s \n " , switch_str_nil ( profile - > codec_string ) ) ;
stream - > write_function ( stream , " TEL-EVENT \t %d \n " , profile - > te ) ;
stream - > write_function ( stream , " CNG \t %d \n " , profile - > cng_pt ) ;
2007-10-19 21:06:09 +00:00
stream - > write_function ( stream , " SESSION-TO \t %d \n " , profile - > session_timeout ) ;
stream - > write_function ( stream , " MAX-DIALOG \t %d \n " , profile - > max_proceeding ) ;
2007-05-01 15:22:57 +00:00
stream - > write_function ( stream , " \n Registrations: \n %s \n " , line ) ;
cb . profile = profile ;
cb . stream = stream ;
sofia_glue_execute_sql_callback ( profile , SWITCH_FALSE , profile - > ireg_mutex ,
" select * from sip_registrations " ,
show_reg_callback , & cb ) ;
stream - > write_function ( stream , " %s \n " , line ) ;
2007-05-03 01:55:25 +00:00
sofia_glue_release_profile ( profile ) ;
2007-05-01 15:22:57 +00:00
} else {
stream - > write_function ( stream , " Invalid Profile! \n " ) ;
}
} else {
stream - > write_function ( stream , " Invalid Syntax! \n " ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
stream - > write_function ( stream , " %25s \t %s \t %32s \t %s \n " , " Name " , " Type " , " Data " , " State " ) ;
2007-04-30 20:35:35 +00:00
stream - > write_function ( stream , " %s \n " , line ) ;
2007-04-29 01:16:49 +00:00
switch_mutex_lock ( mod_sofia_globals . hash_mutex ) ;
2007-09-24 19:34:25 +00:00
for ( hi = switch_hash_first ( NULL , mod_sofia_globals . profile_hash ) ; hi ; hi = switch_hash_next ( hi ) ) {
2007-04-30 20:35:35 +00:00
switch_hash_this ( hi , & vvar , NULL , & val ) ;
2007-04-29 01:16:49 +00:00
profile = ( sofia_profile_t * ) val ;
if ( sofia_test_pflag ( profile , PFLAG_RUNNING ) ) {
2007-04-30 20:35:35 +00:00
if ( strcmp ( vvar , profile - > name ) ) {
ac + + ;
2007-05-02 23:32:45 +00:00
stream - > write_function ( stream , " %25s \t %s \t %32s \t %s \n " , vvar , " alias " , profile - > name , " ALIASED " ) ;
2007-04-30 20:35:35 +00:00
} else {
2007-05-03 01:55:25 +00:00
stream - > write_function ( stream , " %25s \t %s \t %32s \t %s (%u) \n " , profile - > name , " profile " , profile - > url ,
sofia_test_pflag ( profile , PFLAG_RUNNING ) ? " RUNNING " : " DOWN " , profile - > inuse ) ;
2008-01-19 01:28:36 +00:00
if ( sofia_test_pflag ( profile , PFLAG_TLS ) ) {
stream - > write_function ( stream , " %25s \t %s \t %32s \t %s (%u) (TLS) \n " , profile - > name , " profile " , profile - > tls_url ,
sofia_test_pflag ( profile , PFLAG_RUNNING ) ? " RUNNING " : " DOWN " , profile - > inuse ) ;
}
2007-04-30 20:35:35 +00:00
c + + ;
2007-05-01 15:22:57 +00:00
for ( gp = profile - > gateways ; gp ; gp = gp - > next ) {
2007-12-12 23:21:45 +00:00
switch_assert ( gp - > state < REG_STATE_LAST ) ;
2007-05-10 16:15:07 +00:00
stream - > write_function ( stream , " %25s \t %s \t %32s \t %s " , gp - > name , " gateway " , gp - > register_to , sofia_state_names [ gp - > state ] ) ;
if ( gp - > state = = REG_STATE_FAILED | | gp - > state = = REG_STATE_TRYING ) {
2008-01-11 00:43:49 +00:00
stream - > write_function ( stream , " (retry: %ds) " , gp - > retry - switch_timestamp ( NULL ) ) ;
2007-05-10 16:15:07 +00:00
}
stream - > write_function ( stream , " \n " ) ;
2007-05-01 15:22:57 +00:00
}
2007-04-30 20:35:35 +00:00
}
2007-04-29 01:16:49 +00:00
}
}
switch_mutex_unlock ( mod_sofia_globals . hash_mutex ) ;
2007-04-30 20:35:35 +00:00
stream - > write_function ( stream , " %s \n " , line ) ;
2007-05-02 23:32:45 +00:00
stream - > write_function ( stream , " %d profile%s %d alias%s \n " , c , c = = 1 ? " " : " s " , ac , ac = = 1 ? " " : " es " ) ;
2007-04-29 01:16:49 +00:00
return SWITCH_STATUS_SUCCESS ;
}
static switch_status_t cmd_profile ( char * * argv , int argc , switch_stream_handle_t * stream )
{
sofia_profile_t * profile = NULL ;
char * profile_name = argv [ 0 ] ;
2007-05-03 01:55:25 +00:00
const char * err ;
switch_xml_t xml_root ;
2007-04-29 01:16:49 +00:00
if ( argc < 2 ) {
stream - > write_function ( stream , " Invalid Args! \n " ) ;
return SWITCH_STATUS_SUCCESS ;
}
if ( ! strcasecmp ( argv [ 1 ] , " start " ) ) {
2007-05-03 01:55:25 +00:00
if ( argc > 2 & & ! strcasecmp ( argv [ 2 ] , " reloadxml " ) ) {
if ( ( xml_root = switch_xml_open_root ( 1 , & err ) ) ) {
switch_xml_free ( xml_root ) ;
}
stream - > write_function ( stream , " Reload XML [%s] \n " , err ) ;
}
2007-04-29 01:16:49 +00:00
if ( config_sofia ( 1 , argv [ 0 ] ) = = SWITCH_STATUS_SUCCESS ) {
stream - > write_function ( stream , " %s started successfully \n " , argv [ 0 ] ) ;
} else {
stream - > write_function ( stream , " Failure starting %s \n " , argv [ 0 ] ) ;
}
return SWITCH_STATUS_SUCCESS ;
}
if ( switch_strlen_zero ( profile_name ) | | ! ( profile = sofia_glue_find_profile ( profile_name ) ) ) {
stream - > write_function ( stream , " Invalid Profile [%s] " , switch_str_nil ( profile_name ) ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-11-07 19:39:24 +00:00
if ( ! strcasecmp ( argv [ 1 ] , " flush_inbound_reg " ) ) {
sofia_reg_check_expire ( profile , 0 ) ;
stream - > write_function ( stream , " +OK \n " ) ;
goto done ;
}
2007-05-10 16:15:07 +00:00
if ( ! strcasecmp ( argv [ 1 ] , " register " ) ) {
char * gname = argv [ 2 ] ;
sofia_gateway_t * gateway_ptr ;
if ( switch_strlen_zero ( gname ) ) {
stream - > write_function ( stream , " No gateway name provided! \n " ) ;
goto done ;
}
if ( ! strcasecmp ( gname , " all " ) ) {
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
gateway_ptr - > retry = 0 ;
gateway_ptr - > state = REG_STATE_UNREGED ;
}
stream - > write_function ( stream , " +OK \n " ) ;
} else if ( ( gateway_ptr = sofia_reg_find_gateway ( gname ) ) ) {
gateway_ptr - > retry = 0 ;
gateway_ptr - > state = REG_STATE_UNREGED ;
stream - > write_function ( stream , " +OK \n " ) ;
sofia_reg_release_gateway ( gateway_ptr ) ;
} else {
stream - > write_function ( stream , " Invalid gateway! \n " ) ;
}
goto done ;
}
2007-09-18 17:31:36 +00:00
if ( ! strcasecmp ( argv [ 1 ] , " unregister " ) ) {
char * gname = argv [ 2 ] ;
sofia_gateway_t * gateway_ptr ;
if ( switch_strlen_zero ( gname ) ) {
stream - > write_function ( stream , " No gateway name provided! \n " ) ;
goto done ;
}
if ( ! strcasecmp ( gname , " all " ) ) {
for ( gateway_ptr = profile - > gateways ; gateway_ptr ; gateway_ptr = gateway_ptr - > next ) {
gateway_ptr - > retry = 0 ;
gateway_ptr - > state = REG_STATE_UNREGISTER ;
}
stream - > write_function ( stream , " +OK \n " ) ;
} else if ( ( gateway_ptr = sofia_reg_find_gateway ( gname ) ) ) {
gateway_ptr - > retry = 0 ;
gateway_ptr - > state = REG_STATE_UNREGISTER ;
stream - > write_function ( stream , " +OK \n " ) ;
sofia_reg_release_gateway ( gateway_ptr ) ;
} else {
stream - > write_function ( stream , " Invalid gateway! \n " ) ;
}
goto done ;
}
2007-05-03 01:55:25 +00:00
if ( ! strcasecmp ( argv [ 1 ] , " stop " ) | | ! strcasecmp ( argv [ 1 ] , " restart " ) ) {
2007-05-10 18:17:34 +00:00
int rsec = 3 ;
2008-01-11 00:43:49 +00:00
int diff = ( int ) ( switch_timestamp ( NULL ) - profile - > started ) ;
2007-05-03 01:55:25 +00:00
int remain = rsec - diff ;
if ( diff < rsec ) {
stream - > write_function ( stream , " Profile %s must be up for at least %d seconds to stop/restart. \n Please wait %d second%s \n " ,
profile - > name , rsec , remain , remain = = 1 ? " " : " s " ) ;
2007-05-02 23:32:45 +00:00
} else {
2007-05-03 01:55:25 +00:00
if ( argc > 2 & & ! strcasecmp ( argv [ 2 ] , " reloadxml " ) ) {
if ( ( xml_root = switch_xml_open_root ( 1 , & err ) ) ) {
switch_xml_free ( xml_root ) ;
}
stream - > write_function ( stream , " Reload XML [%s] \n " , err ) ;
}
if ( ! strcasecmp ( argv [ 1 ] , " stop " ) ) {
sofia_clear_pflag_locked ( profile , PFLAG_RUNNING ) ;
stream - > write_function ( stream , " stopping: %s " , profile - > name ) ;
} else {
sofia_set_pflag_locked ( profile , PFLAG_RESPAWN ) ;
sofia_clear_pflag_locked ( profile , PFLAG_RUNNING ) ;
stream - > write_function ( stream , " restarting: %s " , profile - > name ) ;
}
2007-05-02 23:32:45 +00:00
}
2007-11-07 19:39:24 +00:00
goto done ;
2007-05-01 00:26:41 +00:00
}
2007-04-29 01:16:49 +00:00
2007-11-07 19:39:24 +00:00
stream - > write_function ( stream , " -ERR Unknown command! \n " ) ;
2007-05-10 16:15:07 +00:00
done :
2007-04-29 01:16:49 +00:00
if ( profile ) {
2007-05-03 01:55:25 +00:00
sofia_glue_release_profile ( profile ) ;
2007-04-29 01:16:49 +00:00
}
return SWITCH_STATUS_SUCCESS ;
}
2007-10-18 01:02:01 +00:00
static int contact_callback ( void * pArg , int argc , char * * argv , char * * columnNames )
{
struct cb_helper * cb = ( struct cb_helper * ) pArg ;
char * contact ;
if ( ! switch_strlen_zero ( argv [ 0 ] ) & & ( contact = sofia_glue_get_url_from_contact ( argv [ 0 ] , 1 ) ) ) {
cb - > stream - > write_function ( cb - > stream , " sofia/%s/%s, " , cb - > profile - > name , contact + 4 ) ;
free ( contact ) ;
}
return 0 ;
}
SWITCH_STANDARD_API ( sofia_contact_function )
{
char * data ;
char * user = NULL ;
char * domain = NULL ;
char * profile_name = NULL ;
char * p ;
2008-02-11 21:20:43 +00:00
sofia_profile_t * profile = NULL ;
2007-10-18 01:02:01 +00:00
if ( ! cmd ) {
stream - > write_function ( stream , " %s " , " " ) ;
return SWITCH_STATUS_SUCCESS ;
}
data = strdup ( cmd ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( data ) ;
2007-10-18 01:02:01 +00:00
if ( ( p = strchr ( data , ' / ' ) ) ) {
profile_name = data ;
* p + + = ' \0 ' ;
user = p ;
} else {
user = data ;
}
if ( ( domain = strchr ( user , ' @ ' ) ) ) {
* domain + + = ' \0 ' ;
}
if ( ! profile_name & & domain ) {
profile_name = domain ;
}
if ( user & & profile_name ) {
char * sql ;
if ( ! ( profile = sofia_glue_find_profile ( profile_name ) ) ) {
profile_name = domain ;
domain = NULL ;
}
if ( ! profile & & profile_name ) {
profile = sofia_glue_find_profile ( profile_name ) ;
}
if ( profile ) {
struct cb_helper cb ;
switch_stream_handle_t mystream = { 0 } ;
if ( ! domain | | ! strchr ( domain , ' . ' ) ) {
domain = profile - > name ;
}
SWITCH_STANDARD_STREAM ( mystream ) ;
cb . profile = profile ;
cb . stream = & mystream ;
2007-11-15 16:55:46 +00:00
sql = switch_mprintf ( " select contact from sip_registrations where sip_user='%q' and sip_host='%q' " , user , domain ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( sql ) ;
2007-10-18 01:02:01 +00:00
sofia_glue_execute_sql_callback ( profile , SWITCH_FALSE , profile - > ireg_mutex , sql , contact_callback , & cb ) ;
switch_safe_free ( sql ) ;
if ( mystream . data ) {
char * str = mystream . data ;
* ( str + ( strlen ( str ) - 1 ) ) = ' \0 ' ;
}
stream - > write_function ( stream , " %s " , mystream . data ) ;
switch_safe_free ( mystream . data ) ;
goto end ;
}
}
stream - > write_function ( stream , " %s " , " " ) ;
2007-11-20 01:44:07 +00:00
end :
2007-10-18 01:02:01 +00:00
switch_safe_free ( data ) ;
2008-02-11 21:20:43 +00:00
if ( profile ) {
sofia_glue_release_profile ( profile ) ;
}
2007-10-18 01:02:01 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2007-05-12 21:36:15 +00:00
SWITCH_STANDARD_API ( sofia_function )
2007-04-29 01:16:49 +00:00
{
char * argv [ 1024 ] = { 0 } ;
int argc = 0 ;
char * mycmd = NULL ;
switch_status_t status = SWITCH_STATUS_SUCCESS ;
sofia_command_t func = NULL ;
int lead = 1 ;
const char * usage_string = " USAGE: \n "
" -------------------------------------------------------------------------------- \n "
" sofia help \n "
2007-11-08 02:20:48 +00:00
" sofia profile <profile_name> [start|stop|restart|flush_inbound_reg|[register|unregister] [<gateway name>|all]] [reloadxml] \n "
2007-05-01 15:22:57 +00:00
" sofia status [[profile | gateway] <name>] \n "
2007-12-13 02:42:00 +00:00
" sofia loglevel [0-9] \n "
2007-04-29 01:16:49 +00:00
" -------------------------------------------------------------------------------- \n " ;
2007-05-12 21:36:15 +00:00
if ( session ) {
2007-04-29 01:16:49 +00:00
return SWITCH_STATUS_FALSE ;
}
if ( switch_strlen_zero ( cmd ) ) {
stream - > write_function ( stream , " %s " , usage_string ) ;
goto done ;
}
if ( ! ( mycmd = strdup ( cmd ) ) ) {
status = SWITCH_STATUS_MEMERR ;
goto done ;
}
2007-12-13 04:01:29 +00:00
if ( ! ( argc = switch_separate_string ( mycmd , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) | | ! argv [ 0 ] ) {
2007-04-29 01:16:49 +00:00
stream - > write_function ( stream , " %s " , usage_string ) ;
goto done ;
}
2007-10-19 21:06:09 +00:00
2007-04-29 01:16:49 +00:00
if ( ! strcasecmp ( argv [ 0 ] , " profile " ) ) {
func = cmd_profile ;
} else if ( ! strcasecmp ( argv [ 0 ] , " status " ) ) {
func = cmd_status ;
2007-12-13 02:42:00 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " loglevel " ) ) {
if ( argc > 1 & & argv [ 1 ] ) {
int level ;
level = atoi ( argv [ 1 ] ) ;
if ( level > = 0 & & level < = 9 ) {
su_log_set_level ( NULL , atoi ( argv [ 1 ] ) ) ;
stream - > write_function ( stream , " Sofia-sip log level set to [%d] " , level ) ;
} else {
stream - > write_function ( stream , " %s " , usage_string ) ;
}
} else {
stream - > write_function ( stream , " %s " , usage_string ) ;
}
goto done ;
2007-04-29 01:16:49 +00:00
} else if ( ! strcasecmp ( argv [ 0 ] , " help " ) ) {
stream - > write_function ( stream , " %s " , usage_string ) ;
goto done ;
}
if ( func ) {
status = func ( & argv [ lead ] , argc - lead , stream ) ;
} else {
stream - > write_function ( stream , " Unknown Command [%s] \n " , argv [ 0 ] ) ;
}
done :
switch_safe_free ( mycmd ) ;
return status ;
}
2007-10-29 18:10:06 +00:00
switch_io_routines_t sofia_io_routines = {
2007-03-31 19:01:33 +00:00
/*.outgoing_channel */ sofia_outgoing_channel ,
/*.read_frame */ sofia_read_frame ,
/*.write_frame */ sofia_write_frame ,
/*.kill_channel */ sofia_kill_channel ,
/*.waitfor_read */ sofia_waitfor_read ,
/*.waitfor_read */ sofia_waitfor_write ,
/*.send_dtmf */ sofia_send_dtmf ,
/*.receive_message */ sofia_receive_message ,
2007-04-19 21:40:50 +00:00
/*.receive_event */ sofia_receive_event ,
/*.state_change*/ NULL ,
/*.read_video_frame*/ sofia_read_video_frame ,
/*.write_video_frame*/ sofia_write_video_frame
2007-03-31 19:01:33 +00:00
} ;
2007-10-29 18:10:06 +00:00
switch_state_handler_table_t sofia_event_handlers = {
2007-03-31 19:01:33 +00:00
/*.on_init */ sofia_on_init ,
/*.on_ring */ sofia_on_ring ,
/*.on_execute */ sofia_on_execute ,
/*.on_hangup */ sofia_on_hangup ,
/*.on_loopback */ sofia_on_loopback ,
2007-12-24 18:26:39 +00:00
/*.on_transmit */ sofia_on_transmit ,
/*.on_hold */ NULL ,
/*.on_hibernate*/ sofia_on_hibernate ,
/*.on_reset*/ sofia_on_reset
2007-03-31 19:01:33 +00:00
} ;
2006-10-20 22:11:26 +00:00
2007-03-31 19:01:33 +00:00
static switch_status_t sofia_manage ( char * relative_oid , switch_management_action_t action , char * data , switch_size_t datalen )
{
return SWITCH_STATUS_SUCCESS ;
}
2006-10-20 06:17:00 +00:00
2007-03-31 19:01:33 +00:00
static switch_call_cause_t sofia_outgoing_channel ( switch_core_session_t * session ,
switch_caller_profile_t * outbound_profile , switch_core_session_t * * new_session ,
2007-12-20 21:42:00 +00:00
switch_memory_pool_t * * pool , switch_originate_flag_t flags )
2006-10-12 00:59:09 +00:00
{
2007-03-31 19:01:33 +00:00
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2007-12-21 04:29:41 +00:00
switch_core_session_t * nsession = NULL ;
2007-03-31 19:01:33 +00:00
char * data , * profile_name , * dest ;
2007-04-29 01:16:49 +00:00
sofia_profile_t * profile = NULL ;
2007-03-31 19:01:33 +00:00
switch_caller_profile_t * caller_profile = NULL ;
private_object_t * tech_pvt = NULL ;
switch_channel_t * nchannel ;
2008-02-11 20:47:20 +00:00
char * host = NULL , * dest_to = NULL ;
2006-10-20 06:17:00 +00:00
2007-03-31 19:01:33 +00:00
* new_session = NULL ;
2006-10-20 06:17:00 +00:00
2007-06-20 07:15:53 +00:00
if ( ! ( nsession = switch_core_session_request ( sofia_endpoint_interface , pool ) ) ) {
2007-03-31 19:01:33 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error Creating Session \n " ) ;
2007-12-21 04:29:41 +00:00
goto error ;
2007-03-29 22:31:56 +00:00
}
2006-10-20 06:17:00 +00:00
2007-03-31 19:01:33 +00:00
if ( ! ( tech_pvt = ( struct private_object * ) switch_core_session_alloc ( nsession , sizeof ( * tech_pvt ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_CRIT , " Error Creating Session \n " ) ;
2007-12-21 04:29:41 +00:00
goto error ;
2006-10-20 06:17:00 +00:00
}
2007-04-13 22:15:58 +00:00
switch_mutex_init ( & tech_pvt - > flag_mutex , SWITCH_MUTEX_NESTED , switch_core_session_get_pool ( nsession ) ) ;
2006-10-18 22:57:35 +00:00
2007-03-31 19:01:33 +00:00
data = switch_core_session_strdup ( nsession , outbound_profile - > destination_number ) ;
profile_name = data ;
2006-10-20 22:11:26 +00:00
2007-12-04 13:48:20 +00:00
nchannel = switch_core_session_get_channel ( nsession ) ;
2007-03-31 19:01:33 +00:00
if ( ! strncasecmp ( profile_name , " gateway " , 7 ) ) {
2008-01-17 17:37:49 +00:00
char * gw , * params ;
2007-04-29 01:16:49 +00:00
sofia_gateway_t * gateway_ptr = NULL ;
2006-10-20 06:17:00 +00:00
2007-03-31 19:01:33 +00:00
if ( ! ( gw = strchr ( profile_name , ' / ' ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid URL \n " ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
2007-12-21 04:29:41 +00:00
goto error ;
2007-03-31 19:01:33 +00:00
}
2006-10-18 22:57:35 +00:00
2007-03-31 19:01:33 +00:00
* gw + + = ' \0 ' ;
2006-10-18 22:57:35 +00:00
2007-03-31 19:01:33 +00:00
if ( ! ( dest = strchr ( gw , ' / ' ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid URL \n " ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
2007-12-21 04:29:41 +00:00
goto error ;
2006-10-18 22:57:35 +00:00
}
2007-03-31 19:01:33 +00:00
* dest + + = ' \0 ' ;
2006-10-15 05:10:34 +00:00
2007-03-31 19:01:33 +00:00
if ( ! ( gateway_ptr = sofia_reg_find_gateway ( gw ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Gateway \n " ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
2007-12-21 04:29:41 +00:00
goto error ;
2006-10-15 05:10:34 +00:00
}
2007-03-31 19:01:33 +00:00
2008-01-17 17:37:49 +00:00
tech_pvt - > transport = gateway_ptr - > register_transport ;
/*
* Handle params , strip them off the destination and add them to the
* invite contact .
*
* TODO :
* - Add parameters back to destination url ?
*/
if ( ( params = strchr ( dest , ' ; ' ) ) ) {
char * tp_param ;
* params + + = ' \0 ' ;
if ( ( tp_param = ( char * ) switch_stristr ( " port= " , params ) ) ) {
tp_param + = 5 ;
tech_pvt - > transport = sofia_glue_str2transport ( tp_param ) ;
if ( tech_pvt - > transport = = SOFIA_TRANSPORT_UNKNOWN ) {
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
}
}
}
if ( tech_pvt - > transport ! = gateway_ptr - > register_transport ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " You are trying to use a different transport type for this gateway (overriding the register-transport), this is unsupported! \n " ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
goto error ;
}
2007-03-31 19:01:33 +00:00
profile = gateway_ptr - > profile ;
2007-12-04 13:48:20 +00:00
tech_pvt - > gateway_name = switch_core_session_strdup ( nsession , gateway_ptr - > name ) ;
switch_channel_set_variable ( nchannel , " sip_gateway_name " , gateway_ptr - > name ) ;
2008-01-17 17:37:49 +00:00
2007-04-20 16:05:37 +00:00
if ( ! switch_test_flag ( gateway_ptr , REG_FLAG_CALLERID ) ) {
2007-04-18 20:21:53 +00:00
tech_pvt - > gateway_from_str = switch_core_session_strdup ( nsession , gateway_ptr - > register_from ) ;
}
2008-01-17 17:37:49 +00:00
2007-03-31 19:01:33 +00:00
if ( ! strchr ( dest , ' @ ' ) ) {
tech_pvt - > dest = switch_core_session_sprintf ( nsession , " sip:%s@%s " , dest , gateway_ptr - > register_proxy + 4 ) ;
2006-10-20 06:17:00 +00:00
} else {
2007-03-31 19:01:33 +00:00
tech_pvt - > dest = switch_core_session_sprintf ( nsession , " sip:%s " , dest ) ;
2006-10-20 06:17:00 +00:00
}
2008-01-17 17:37:49 +00:00
if ( params ) {
tech_pvt - > invite_contact = switch_core_session_sprintf ( nsession , " %s;%s " , gateway_ptr - > register_contact , params ) ;
} else {
tech_pvt - > invite_contact = switch_core_session_strdup ( nsession , gateway_ptr - > register_contact ) ;
}
2006-10-15 05:10:34 +00:00
} else {
2007-03-31 19:01:33 +00:00
if ( ! ( dest = strchr ( profile_name , ' / ' ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid URL \n " ) ;
cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT ;
2007-12-21 04:29:41 +00:00
goto error ;
2007-03-31 19:01:33 +00:00
}
* dest + + = ' \0 ' ;
2006-10-15 05:10:34 +00:00
2007-03-31 19:01:33 +00:00
if ( ! ( profile = sofia_glue_find_profile ( profile_name ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Invalid Profile \n " ) ;
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER ;
2007-12-21 04:29:41 +00:00
goto error ;
2007-03-31 19:01:33 +00:00
}
2006-10-15 05:10:34 +00:00
2008-01-21 23:52:34 +00:00
if ( profile - > domain_name & & profile - > domain_name ! = profile - > name ) {
profile_name = profile - > domain_name ;
}
2007-03-31 19:01:33 +00:00
if ( ( dest_to = strchr ( dest , ' ^ ' ) ) ) {
* dest_to + + = ' \0 ' ;
}
2007-03-29 22:31:56 +00:00
2007-03-31 19:01:33 +00:00
if ( ( host = strchr ( dest , ' % ' ) ) ) {
char buf [ 128 ] ;
* host = ' @ ' ;
tech_pvt - > e_dest = switch_core_session_strdup ( nsession , dest ) ;
* host + + = ' \0 ' ;
if ( sofia_reg_find_reg_url ( profile , dest , host , buf , sizeof ( buf ) ) ) {
tech_pvt - > dest = switch_core_session_strdup ( nsession , buf ) ;
2007-11-30 21:02:41 +00:00
tech_pvt - > local_url = switch_core_session_sprintf ( nsession , " %s@%s " , dest , host ) ;
2007-03-31 19:01:33 +00:00
} else {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cannot locate registered user %s@%s \n " , dest , host ) ;
cause = SWITCH_CAUSE_NO_ROUTE_DESTINATION ;
2007-12-21 04:29:41 +00:00
goto error ;
2007-03-29 22:31:56 +00:00
}
2008-02-11 20:47:20 +00:00
} else if ( ! ( host = strchr ( dest , ' @ ' ) ) ) {
2007-03-31 19:01:33 +00:00
char buf [ 128 ] ;
tech_pvt - > e_dest = switch_core_session_strdup ( nsession , dest ) ;
2008-01-21 23:52:34 +00:00
if ( sofia_reg_find_reg_url ( profile , dest , profile_name , buf , sizeof ( buf ) ) ) {
2007-03-31 19:01:33 +00:00
tech_pvt - > dest = switch_core_session_strdup ( nsession , buf ) ;
2008-01-21 23:52:34 +00:00
tech_pvt - > local_url = switch_core_session_sprintf ( nsession , " %s@%s " , dest , profile_name ) ;
2008-02-11 20:47:20 +00:00
host = profile_name ;
2007-03-31 19:01:33 +00:00
} else {
2008-01-21 23:52:34 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_WARNING , " Cannot locate registered user %s@%s \n " , dest , profile_name ) ;
2007-03-31 19:01:33 +00:00
cause = SWITCH_CAUSE_NO_ROUTE_DESTINATION ;
2007-12-21 04:29:41 +00:00
goto error ;
2007-03-29 22:31:56 +00:00
}
2007-03-31 19:01:33 +00:00
} else {
tech_pvt - > dest = switch_core_session_alloc ( nsession , strlen ( dest ) + 5 ) ;
2007-12-12 21:53:32 +00:00
switch_snprintf ( tech_pvt - > dest , strlen ( dest ) + 5 , " sip:%s " , dest ) ;
2007-03-29 22:31:56 +00:00
}
2006-10-12 00:59:09 +00:00
}
2008-02-11 20:47:20 +00:00
if ( dest_to ) {
if ( strchr ( dest_to , ' @ ' ) ) {
tech_pvt - > dest_to = switch_core_session_sprintf ( nsession , " sip:%s " , dest_to ) ;
} else {
tech_pvt - > dest_to = switch_core_session_sprintf ( nsession , " sip:%s@%s " , dest_to , host ) ;
}
}
2007-03-31 19:01:33 +00:00
if ( ! tech_pvt - > dest_to ) {
tech_pvt - > dest_to = tech_pvt - > dest ;
}
2006-10-12 00:59:09 +00:00
2007-03-31 19:01:33 +00:00
sofia_glue_attach_private ( nsession , profile , tech_pvt , dest ) ;
2007-12-04 13:48:20 +00:00
2007-11-30 21:02:41 +00:00
if ( tech_pvt - > local_url ) {
switch_channel_set_variable ( nchannel , " sip_local_url " , tech_pvt - > local_url ) ;
2007-12-18 01:12:50 +00:00
if ( sofia_test_pflag ( profile , PFLAG_PRESENCE ) ) {
switch_channel_set_variable ( nchannel , " presence_id " , tech_pvt - > local_url ) ;
}
2007-11-30 21:02:41 +00:00
}
switch_channel_set_variable ( nchannel , " sip_destination_url " , tech_pvt - > dest ) ;
2008-01-17 17:37:49 +00:00
2007-03-31 19:01:33 +00:00
caller_profile = switch_caller_profile_clone ( nsession , outbound_profile ) ;
2008-01-05 01:03:08 +00:00
caller_profile - > destination_number = switch_core_strdup ( caller_profile - > pool , dest ) ;
2007-03-31 19:01:33 +00:00
switch_channel_set_caller_profile ( nchannel , caller_profile ) ;
switch_channel_set_flag ( nchannel , CF_OUTBOUND ) ;
switch_set_flag_locked ( tech_pvt , TFLAG_OUTBOUND ) ;
2007-11-03 00:46:23 +00:00
switch_clear_flag_locked ( tech_pvt , TFLAG_LATE_NEGOTIATION ) ;
2008-01-26 01:53:42 +00:00
if ( switch_channel_get_state ( nchannel ) = = CS_NEW ) {
switch_channel_set_state ( nchannel , CS_INIT ) ;
}
2007-11-19 17:09:46 +00:00
tech_pvt - > caller_profile = caller_profile ;
2007-03-31 19:01:33 +00:00
* new_session = nsession ;
cause = SWITCH_CAUSE_SUCCESS ;
2007-12-18 01:12:50 +00:00
2007-03-31 19:01:33 +00:00
if ( session ) {
switch_ivr_transfer_variable ( session , nsession , SOFIA_REPLACES_HEADER ) ;
2008-01-12 04:00:21 +00:00
switch_ivr_transfer_variable ( session , nsession , " sip_auto_answer " ) ;
2007-03-31 19:01:33 +00:00
switch_ivr_transfer_variable ( session , nsession , SOFIA_SIP_HEADER_PREFIX_T ) ;
2008-02-07 22:42:27 +00:00
switch_ivr_transfer_variable ( session , nsession , " sip_video_fmtp " ) ;
2007-03-31 19:01:33 +00:00
if ( switch_core_session_compare ( session , nsession ) ) {
/* It's another sofia channel! so lets cache what they use as a pt for telephone event so
we can keep it the same
*/
private_object_t * ctech_pvt ;
ctech_pvt = switch_core_session_get_private ( session ) ;
2007-12-12 23:21:45 +00:00
switch_assert ( ctech_pvt ! = NULL ) ;
2007-03-31 19:01:33 +00:00
tech_pvt - > bte = ctech_pvt - > te ;
tech_pvt - > bcng_pt = ctech_pvt - > cng_pt ;
2006-10-12 00:59:09 +00:00
}
2006-10-15 05:10:34 +00:00
}
2006-10-12 00:59:09 +00:00
2007-12-21 04:29:41 +00:00
goto done ;
error :
if ( nsession ) {
switch_core_session_destroy ( & nsession ) ;
}
* pool = NULL ;
2007-03-31 19:01:33 +00:00
done :
2008-01-16 06:01:53 +00:00
2007-04-29 01:16:49 +00:00
if ( profile ) {
2007-05-03 01:55:25 +00:00
sofia_glue_release_profile ( profile ) ;
2007-04-29 01:16:49 +00:00
}
2007-03-31 19:01:33 +00:00
return cause ;
2006-10-12 00:59:09 +00:00
}
2007-06-13 14:35:55 +00:00
SWITCH_MODULE_LOAD_FUNCTION ( mod_sofia_load )
2006-08-25 23:55:59 +00:00
{
2007-06-20 07:15:53 +00:00
switch_chat_interface_t * chat_interface ;
switch_api_interface_t * api_interface ;
switch_management_interface_t * management_interface ;
2006-08-25 23:55:59 +00:00
2006-10-31 21:38:06 +00:00
silence_frame . data = silence_data ;
silence_frame . datalen = sizeof ( silence_data ) ;
silence_frame . buflen = sizeof ( silence_data ) ;
silence_frame . flags = SFF_CNG ;
2007-06-20 07:15:53 +00:00
module_pool = pool ;
2006-08-25 23:55:59 +00:00
2007-04-01 01:16:16 +00:00
memset ( & mod_sofia_globals , 0 , sizeof ( mod_sofia_globals ) ) ;
switch_mutex_init ( & mod_sofia_globals . mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
2007-01-19 19:11:44 +00:00
2007-04-01 01:16:16 +00:00
switch_find_local_ip ( mod_sofia_globals . guess_ip , sizeof ( mod_sofia_globals . guess_ip ) , AF_INET ) ;
2006-09-27 20:18:14 +00:00
2007-04-01 01:16:16 +00:00
switch_core_hash_init ( & mod_sofia_globals . profile_hash , module_pool ) ;
switch_core_hash_init ( & mod_sofia_globals . gateway_hash , module_pool ) ;
switch_mutex_init ( & mod_sofia_globals . hash_mutex , SWITCH_MUTEX_NESTED , module_pool ) ;
2007-05-01 16:12:02 +00:00
2007-04-13 23:19:51 +00:00
switch_mutex_lock ( mod_sofia_globals . mutex ) ;
mod_sofia_globals . running = 1 ;
switch_mutex_unlock ( mod_sofia_globals . mutex ) ;
2006-10-18 22:57:35 +00:00
2008-02-07 22:13:40 +00:00
if ( config_sofia ( 0 , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
mod_sofia_globals . running = 0 ;
return SWITCH_STATUS_GENERR ;
}
2007-05-01 16:12:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_DEBUG , " Waiting for profiles to start \n " ) ;
switch_yield ( 1500000 ) ;
2007-06-20 07:15:53 +00:00
if ( switch_event_bind ( modname , SWITCH_EVENT_CUSTOM , MULTICAST_EVENT , event_handler , NULL ) ! = SWITCH_STATUS_SUCCESS ) {
2007-05-01 16:12:02 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_TERM ;
}
2007-06-20 07:15:53 +00:00
if ( switch_event_bind ( modname , SWITCH_EVENT_PRESENCE_IN , SWITCH_EVENT_SUBCLASS_ANY , sofia_presence_event_handler , NULL )
2007-04-02 19:54:25 +00:00
! = SWITCH_STATUS_SUCCESS ) {
2006-10-12 00:59:09 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2006-08-25 23:55:59 +00:00
2007-06-20 07:15:53 +00:00
if ( switch_event_bind ( modname , SWITCH_EVENT_PRESENCE_OUT , SWITCH_EVENT_SUBCLASS_ANY , sofia_presence_event_handler , NULL )
2007-04-02 19:54:25 +00:00
! = SWITCH_STATUS_SUCCESS ) {
2006-10-12 00:59:09 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
2006-12-19 17:48:50 +00:00
return SWITCH_STATUS_GENERR ;
}
2007-06-20 07:15:53 +00:00
if ( switch_event_bind ( modname , SWITCH_EVENT_PRESENCE_PROBE , SWITCH_EVENT_SUBCLASS_ANY , sofia_presence_event_handler , NULL )
2007-04-02 19:54:25 +00:00
! = SWITCH_STATUS_SUCCESS ) {
2006-12-19 17:48:50 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
2006-10-12 00:59:09 +00:00
return SWITCH_STATUS_GENERR ;
}
2007-06-20 07:15:53 +00:00
if ( switch_event_bind ( modname , SWITCH_EVENT_ROSTER , SWITCH_EVENT_SUBCLASS_ANY , sofia_presence_event_handler , NULL )
2007-04-02 19:54:25 +00:00
! = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2007-06-20 07:15:53 +00:00
if ( switch_event_bind ( modname , SWITCH_EVENT_MESSAGE_WAITING , SWITCH_EVENT_SUBCLASS_ANY , sofia_presence_mwi_event_handler , NULL )
2007-04-02 19:54:25 +00:00
! = SWITCH_STATUS_SUCCESS ) {
2006-10-12 00:59:09 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Couldn't bind! \n " ) ;
return SWITCH_STATUS_GENERR ;
}
2006-10-09 17:11:39 +00:00
2006-08-25 23:55:59 +00:00
/* connect my internal structure to the blank pointer passed to me */
2007-06-20 07:15:53 +00:00
* module_interface = switch_loadable_module_create_module_interface ( pool , modname ) ;
sofia_endpoint_interface = switch_loadable_module_create_interface ( * module_interface , SWITCH_ENDPOINT_INTERFACE ) ;
2007-06-20 18:45:35 +00:00
sofia_endpoint_interface - > interface_name = " sofia " ;
2007-06-20 07:15:53 +00:00
sofia_endpoint_interface - > io_routines = & sofia_io_routines ;
sofia_endpoint_interface - > state_handler = & sofia_event_handlers ;
management_interface = switch_loadable_module_create_interface ( * module_interface , SWITCH_MANAGEMENT_INTERFACE ) ;
management_interface - > relative_oid = " 1 " ;
management_interface - > management_function = sofia_manage ;
SWITCH_ADD_API ( api_interface , " sofia " , " Sofia Controls " , sofia_function , " <cmd> <args> " ) ;
2007-10-18 01:02:01 +00:00
SWITCH_ADD_API ( api_interface , " sofia_contact " , " Sofia Contacts " , sofia_contact_function , " [profile/]<user>@<domain> " ) ;
2007-06-20 07:15:53 +00:00
SWITCH_ADD_CHAT ( chat_interface , SOFIA_CHAT_PROTO , sofia_presence_chat_send ) ;
2006-08-25 23:55:59 +00:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
2007-06-13 14:35:55 +00:00
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_sofia_shutdown )
2006-08-25 23:55:59 +00:00
{
2007-04-13 23:19:51 +00:00
int sanity = 0 ;
2007-04-01 01:16:16 +00:00
switch_mutex_lock ( mod_sofia_globals . mutex ) ;
if ( mod_sofia_globals . running = = 1 ) {
2007-04-13 23:19:51 +00:00
mod_sofia_globals . running = 0 ;
2006-09-27 03:44:14 +00:00
}
2007-04-01 01:16:16 +00:00
switch_mutex_unlock ( mod_sofia_globals . mutex ) ;
2006-09-27 03:44:14 +00:00
2007-04-13 23:19:51 +00:00
while ( mod_sofia_globals . threads ) {
2006-09-27 03:44:14 +00:00
switch_yield ( 1000 ) ;
2007-04-13 23:19:51 +00:00
if ( + + sanity > = 5000 ) {
break ;
}
2006-09-27 03:44:14 +00:00
}
2006-08-25 23:55:59 +00:00
su_deinit ( ) ;
2007-09-29 01:06:08 +00:00
switch_core_hash_destroy ( & mod_sofia_globals . profile_hash ) ;
switch_core_hash_destroy ( & mod_sofia_globals . gateway_hash ) ;
2006-08-25 23:55:59 +00:00
return SWITCH_STATUS_SUCCESS ;
}
2006-11-27 22:30:48 +00:00
/* For Emacs:
* Local Variables :
* mode : c
2008-02-03 22:14:57 +00:00
* indent - tabs - mode : t
2006-11-27 22:30:48 +00:00
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 expandtab :
*/