2011-03-25 09:38:07 +00:00
/*
2015-07-13 23:20:07 +00:00
* Copyright ( C ) 2010 - 2011 Mamadou Diop .
* Copyright ( C ) 2012 Doubango Telecom < http : //doubango.org>
*
* This file is part of Open Source Doubango Framework .
*
* DOUBANGO is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* DOUBANGO is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO .
*
*/
2011-03-25 09:38:07 +00:00
/**@file tsip.c
* @ brief SIP ( RFC 3261 ) and 3 GPP IMS / LTE ( TS 24.229 ) implementation .
*/
# include "tsip.h"
# include "tinysip/tsip_event.h"
# include "tinysip/parsers/tsip_parser_uri.h"
# include "tinysip/transactions/tsip_transac_layer.h"
# include "tinysip/dialogs/tsip_dialog_layer.h"
# include "tinysip/transports/tsip_transport_layer.h"
# include "tinysip/api/tsip_api_register.h"
# include "tinysip/api/tsip_api_subscribe.h"
# include "tinysip/api/tsip_api_message.h"
2013-06-01 00:54:48 +00:00
# include "tinymedia/tmedia_defaults.h"
2011-03-25 09:38:07 +00:00
# include "tnet.h"
# include "tsk_memory.h"
# include "tsk_debug.h"
# include "tsk_time.h"
# include <stdarg.h>
# include <string.h>
2013-02-17 18:56:03 +00:00
static void * TSK_STDCALL run ( void * self ) ;
2011-03-25 09:38:07 +00:00
/* For tests:
2015-07-13 23:20:07 +00:00
* http : //www.voip-info.org/wiki/view/PROTOS+Test-Suite
* http : //tools.ietf.org/html/rfc4475
* http : //portal.etsi.org/docbox/EC_Files/EC_Files/ts_10202702v030101p.pdf
*/
2011-03-25 09:38:07 +00:00
/**@defgroup tsip_stack_group 3GPP IMS/LTE Stack
2015-07-13 23:20:07 +00:00
*/
2011-03-25 09:38:07 +00:00
extern tsip_event_t * tsip_event_create ( tsip_ssession_t * ss , short code , const char * phrase , const tsip_message_t * sipmessage , tsip_event_type_t type ) ;
# define TSIP_STACK_SIGNAL(self, code, phrase) \
2015-07-13 23:20:07 +00:00
{ \
tsip_event_t * e ; \
if ( ( e = tsip_event_create ( tsk_null , code , phrase , tsk_null , tsip_event_stack ) ) ) { \
TSK_RUNNABLE_ENQUEUE_OBJECT ( TSK_RUNNABLE ( self ) , e ) ; \
} \
}
2011-03-25 09:38:07 +00:00
2012-11-12 08:13:42 +00:00
static int __tsip_stack_get_transport_idx_by_name ( tsip_stack_t * self , const char * name )
{
2016-02-23 21:00:35 +00:00
if ( tsk_strnullORempty ( name ) & & TSIP_STACK_MODE_IS_CLIENT ( self ) ) {
2015-07-13 23:20:07 +00:00
return self - > network . transport_idx_default ; // for backward compatibility
}
return tsip_transport_get_idx_by_name ( name ) ;
2012-11-12 08:13:42 +00:00
}
2011-03-25 09:38:07 +00:00
/* Internal function used to set all user's parameters */
2012-11-12 08:13:42 +00:00
static int __tsip_stack_set ( tsip_stack_t * self , va_list * app )
2011-03-25 09:38:07 +00:00
{
2015-07-13 23:20:07 +00:00
tsip_stack_param_type_t curr ;
2016-02-23 21:00:35 +00:00
while ( ( curr = va_arg ( * app , tsip_stack_param_type_t ) ) ! = tsip_pname_null ) {
switch ( curr ) {
/* === Identity === */
case tsip_pname_display_name : {
/* (const char*)NAME_STR */
const char * NAME_STR = va_arg ( * app , const char * ) ;
tsk_strupdate ( & self - > identity . display_name , NAME_STR ) ;
2016-08-12 01:35:24 +00:00
if ( self - > identity . impu ) {
tsk_strupdate ( & self - > identity . impu - > display_name , NAME_STR ) ;
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_impu :
case tsip_pname_preferred_id : {
/* (const char*)URI_STR */
const char * URI_STR = va_arg ( * app , const char * ) ;
if ( ! tsk_strnullORempty ( URI_STR ) ) {
tsip_uri_t * uri = tsip_uri_parse ( URI_STR , tsk_strlen ( URI_STR ) ) ;
if ( uri ) {
2016-08-12 01:35:24 +00:00
tsk_strupdate ( & uri - > display_name , self - > identity . display_name ) ;
2016-02-23 21:00:35 +00:00
if ( curr = = tsip_pname_impu ) {
TSK_OBJECT_SAFE_FREE ( self - > identity . impu ) ;
self - > identity . impu = uri ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else {
TSK_OBJECT_SAFE_FREE ( self - > identity . preferred ) ;
self - > identity . preferred = uri ;
2015-07-13 23:20:07 +00:00
}
}
2016-02-23 21:00:35 +00:00
else {
TSK_DEBUG_ERROR ( " '%s' is an invalid SIP/TEL URI " , URI_STR ) ;
if ( curr = = tsip_pname_impu ) {
return - 1 ; /* IMPU is mandatory but P-Preferred-Identity isn't. */
}
2015-07-13 23:20:07 +00:00
}
}
2016-02-23 21:00:35 +00:00
else if ( curr = = tsip_pname_impu ) {
TSK_DEBUG_ERROR ( " IMPU (IMS Public Identity) is mandatory. " ) ;
return - 1 ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_impi : {
/* (const char*)IMPI_STR */
const char * IMPI_STR = va_arg ( * app , const char * ) ;
if ( tsk_strnullORempty ( IMPI_STR ) ) {
TSK_DEBUG_ERROR ( " IMPI (IMS Private Identity) is mandatory. " ) ;
return - 1 ; /* mandatory */
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
tsk_strupdate ( & self - > identity . impi , IMPI_STR ) ;
break ;
}
case tsip_pname_password : {
/* (const char*)PASSORD_STR */
const char * PASSORD_STR = va_arg ( * app , const char * ) ;
tsk_strupdate ( & self - > identity . password , PASSORD_STR ) ;
break ;
}
/* === SigComp === */
case tsip_pname_sigcomp : {
/* (unsigned)DMS_UINT, (unsigned)SMS_UINT, (unsigned)CPB_UINT, (tsk_bool_t)PRES_DICT_BOOL */
self - > sigcomp . dms = va_arg ( * app , unsigned ) ;
self - > sigcomp . sms = va_arg ( * app , unsigned ) ;
self - > sigcomp . cpb = va_arg ( * app , unsigned ) ;
self - > sigcomp . pres_dict = va_arg ( * app , tsk_bool_t ) ;
break ;
}
case tsip_pname_sigcomp_add_compartment : {
/* (const char*)COMPARTMENT_ID_STR */
if ( ! self - > sigcomp . handle ) {
self - > sigcomp . handle = tsip_sigcomp_handler_create ( self - > sigcomp . cpb , self - > sigcomp . dms , self - > sigcomp . sms ) ;
tsip_sigcomp_handler_set_dicts ( self - > sigcomp . handle , self - > sigcomp . sip_dict , self - > sigcomp . pres_dict ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
tsip_sigcomp_handler_add_compartment ( self - > sigcomp . handle , va_arg ( * app , const char * ) ) ;
break ;
}
case tsip_pname_sigcomp_remove_compartment : {
/* (const char*)COMPARTMENT_ID_STR */
if ( self - > sigcomp . handle ) {
tsip_sigcomp_handler_remove_compartment ( self - > sigcomp . handle , va_arg ( * app , const char * ) ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
/* === Network === */
case tsip_pname_realm : {
/* (const char*)URI_STR */
const char * URI_STR = va_arg ( * app , const char * ) ;
tsip_uri_t * uri ;
if ( ! tsk_strnullORempty ( URI_STR ) & & ( uri = tsip_uri_parse ( URI_STR , tsk_strlen ( URI_STR ) ) ) ) {
if ( uri - > type = = uri_unknown ) { /* scheme is missing or unsupported? */
tsk_strupdate ( & uri - > scheme , " sip " ) ;
uri - > type = uri_sip ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
TSK_OBJECT_SAFE_FREE ( self - > network . realm ) ; /* delete old */
self - > network . realm = uri ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else {
TSK_DEBUG_ERROR ( " '%s' is an invalid SIP/TEL URI " , URI_STR ) ;
return - 1 ; /* mandatory */
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_local_ip : {
/* (const char*)TRANSPORT_STR, (const char*)IP_STR */
const char * TRANSPORT_STR = va_arg ( * app , const char * ) ;
const char * IP_STR = va_arg ( * app , const char * ) ;
int t_idx = __tsip_stack_get_transport_idx_by_name ( self , TRANSPORT_STR ) ;
if ( t_idx < 0 ) {
TSK_DEBUG_ERROR ( " %s not valid as transport or you're probably using deprecated function " , TRANSPORT_STR ) ;
return - 1 ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
tsk_strupdate ( & self - > network . local_ip [ t_idx ] , IP_STR ) ;
self - > network . local_ip_is_set_by_user [ t_idx ] = tsk_true ; // do not query best source when stack is re-started
if ( TSIP_STACK_MODE_IS_SERVER ( self ) & & ! tsk_strnullORempty ( TRANSPORT_STR ) ) {
self - > network . transport_types [ t_idx ] = tsip_transport_get_type_by_name ( TRANSPORT_STR ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_local_port : {
/* (const char*)TRANSPORT_STR, (unsigned)PORT_UINT */
const char * TRANSPORT_STR = va_arg ( * app , const char * ) ;
unsigned PORT_UINT = va_arg ( * app , unsigned ) ;
int t_idx = __tsip_stack_get_transport_idx_by_name ( self , TRANSPORT_STR ) ;
if ( t_idx < 0 ) {
TSK_DEBUG_ERROR ( " %s not valid as transport or you're probably using deprecated function " , TRANSPORT_STR ) ;
return - 1 ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
self - > network . local_port [ t_idx ] = PORT_UINT ;
if ( TSIP_STACK_MODE_IS_SERVER ( self ) & & ! tsk_strnullORempty ( TRANSPORT_STR ) ) {
self - > network . transport_types [ t_idx ] = tsip_transport_get_type_by_name ( TRANSPORT_STR ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_aor : {
/* (const char*)TRANSPORT_STR, (const char*)IP_STR, (unsigned)PORT_UINT */
const char * TRANSPORT_STR = va_arg ( * app , const char * ) ;
const char * IP_STR = va_arg ( * app , const char * ) ;
tnet_port_t PORT_UINT = ( tnet_port_t ) va_arg ( * app , unsigned ) ;
int t_idx = __tsip_stack_get_transport_idx_by_name ( self , TRANSPORT_STR ) ;
if ( t_idx < 0 ) {
TSK_DEBUG_ERROR ( " %s not valid as transport or you're probably using deprecated function " , TRANSPORT_STR ) ;
return - 1 ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
if ( ! tsk_strnullORempty ( IP_STR ) ) {
tsk_strupdate ( & self - > network . aor . ip [ t_idx ] , IP_STR ) ;
}
if ( PORT_UINT ) {
self - > network . aor . port [ t_idx ] = PORT_UINT ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_discovery_naptr : {
/* (tsk_bool_t)ENABLED_BOOL */
self - > network . discovery_naptr = va_arg ( * app , tsk_bool_t ) ;
break ;
}
case tsip_pname_discovery_dhcp : {
/* (tsk_bool_t)ENABLED_BOOL */
self - > network . discovery_dhcp = va_arg ( * app , tsk_bool_t ) ;
break ;
}
case tsip_pname_proxy_cscf : {
/* (const char*)FQDN_STR, (unsigned)PORT_UINT, (const char*)TRANSPORT_STR, (const char*)IP_VERSION_STR */
const char * FQDN_STR = va_arg ( * app , const char * ) ;
tnet_port_t PORT_UINT = va_arg ( * app , unsigned ) ;
const char * TRANSPORT_STR = va_arg ( * app , const char * ) ;
const char * IP_VERSION_STR = va_arg ( * app , const char * ) ;
int t_idx = __tsip_stack_get_transport_idx_by_name ( self , TRANSPORT_STR ) ;
if ( t_idx < 0 ) {
TSK_DEBUG_ERROR ( " %s not valid as transport or you're probably using deprecated function " , TRANSPORT_STR ) ;
return - 1 ;
}
if ( TSIP_STACK_MODE_IS_CLIENT ( self ) ) {
// "client" mode support a unique proxy_cscf -> reset previous transports
int k ;
for ( k = 0 ; k < sizeof ( self - > network . proxy_cscf_type ) / sizeof ( self - > network . proxy_cscf_type [ 0 ] ) ; + + k ) {
self - > network . proxy_cscf_type [ k ] = tnet_socket_type_invalid ;
2015-07-13 23:20:07 +00:00
}
}
2016-02-23 21:00:35 +00:00
/* IP Address */
tsk_strupdate ( & self - > network . proxy_cscf [ t_idx ] , FQDN_STR ) ;
/* Port */
if ( PORT_UINT ) {
self - > network . proxy_cscf_port [ t_idx ] = PORT_UINT ;
}
/* Transport */
if ( tsk_strnullORempty ( TRANSPORT_STR ) | | tsk_striequals ( TRANSPORT_STR , " UDP " ) ) {
TNET_SOCKET_TYPE_SET_UDP ( self - > network . proxy_cscf_type [ t_idx ] ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else if ( tsk_striequals ( TRANSPORT_STR , " DTLS " ) ) {
TNET_SOCKET_TYPE_SET_DTLS ( self - > network . proxy_cscf_type [ t_idx ] ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else if ( tsk_striequals ( TRANSPORT_STR , " TCP " ) ) {
TNET_SOCKET_TYPE_SET_TCP ( self - > network . proxy_cscf_type [ t_idx ] ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else if ( tsk_striequals ( TRANSPORT_STR , " TLS " ) ) {
TNET_SOCKET_TYPE_SET_TLS ( self - > network . proxy_cscf_type [ t_idx ] ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else if ( tsk_striequals ( TRANSPORT_STR , " SCTP " ) ) {
TNET_SOCKET_TYPE_SET_SCTP ( self - > network . proxy_cscf_type [ t_idx ] ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else if ( tsk_striequals ( TRANSPORT_STR , " WS " ) ) {
TNET_SOCKET_TYPE_SET_WS ( self - > network . proxy_cscf_type [ t_idx ] ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else if ( tsk_striequals ( TRANSPORT_STR , " WSS " ) ) {
TNET_SOCKET_TYPE_SET_WSS ( self - > network . proxy_cscf_type [ t_idx ] ) ;
}
TNET_SOCKET_TYPE_SET_IPV4 ( self - > network . proxy_cscf_type [ t_idx ] ) ; // IPv4 is the default version
/* whether to use ipv6 or not */
if ( ! tsk_strnullORempty ( IP_VERSION_STR ) ) {
if ( tsk_strcontains ( IP_VERSION_STR , tsk_strlen ( IP_VERSION_STR ) , " 6 " ) ) {
TNET_SOCKET_TYPE_SET_IPV6Only ( self - > network . proxy_cscf_type [ t_idx ] ) ; // "only" to clear IPv4 flag
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
if ( tsk_strcontains ( IP_VERSION_STR , tsk_strlen ( IP_VERSION_STR ) , " 4 " ) ) {
TNET_SOCKET_TYPE_SET_IPV4 ( self - > network . proxy_cscf_type [ t_idx ] ) ; /* Not IPV4only ==> '46'/'64' */
2015-07-13 23:20:07 +00:00
}
}
2016-02-23 21:00:35 +00:00
/* use same transport type as the proxy-cscf */
self - > network . transport_types [ t_idx ] = self - > network . proxy_cscf_type [ t_idx ] ;
/* set default transport */
self - > network . transport_idx_default = t_idx ;
break ;
}
case tsip_pname_dnsserver : {
/* (const char*)IP_STR */
const char * IP_STR = va_arg ( * app , const char * ) ;
if ( tnet_dns_add_server ( self - > dns_ctx , IP_STR ) ) {
TSK_DEBUG_ERROR ( " Failed to add [%s] as DNS server " , IP_STR ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_max_fds : {
/* (unsigned)MAX_FDS_UINT */
self - > network . max_fds = va_arg ( * app , unsigned ) ;
break ;
}
case tsip_pname_mode : {
/* (tsip_stack_mode_t)MODE_ENUM */
self - > network . mode = va_arg ( * app , tsip_stack_mode_t ) ;
break ;
}
/* === Security === */
case tsip_pname_early_ims : {
/* (tsk_bool_t)ENABLED_BOOL */
self - > security . earlyIMS = va_arg ( * app , tsk_bool_t ) ;
break ;
}
case tsip_pname_secagree_ipsec : {
/* (const char*)TRANSPORT_STR, (tsk_bool_t)ENABLED_BOOL */
const char * TRANSPORT_STR = va_arg ( * app , const char * ) ;
tsk_bool_t ENABLED_BOOL = va_arg ( * app , tsk_bool_t ) ;
int t_idx = __tsip_stack_get_transport_idx_by_name ( self , TRANSPORT_STR ) ;
if ( t_idx < 0 ) {
TSK_DEBUG_ERROR ( " %s not valid as transport or you're probably using deprecated function " , TRANSPORT_STR ) ;
return - 1 ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
if ( ENABLED_BOOL ) {
tsk_strupdate ( & self - > security . secagree_mech , " ipsec-3gpp " ) ;
TNET_SOCKET_TYPE_SET_IPSEC ( self - > network . proxy_cscf_type [ t_idx ] ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else {
TNET_SOCKET_TYPE_UNSET ( self - > network . proxy_cscf_type [ t_idx ] , IPSEC ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_secagree_tls : {
/* (tsk_bool_t)ENABLED_BOOL */
if ( ( self - > security . enable_secagree_tls = va_arg ( * app , tsk_bool_t ) ) ) {
tsk_strupdate ( & self - > security . secagree_mech , " tls " ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_amf : {
/* (uint16_t)AMF_UINT16 */
unsigned amf = va_arg ( * app , unsigned ) ;
self - > security . amf [ 0 ] = ( amf > > 8 ) ;
self - > security . amf [ 1 ] = ( amf & 0xFF ) ;
break ;
}
case tsip_pname_operator_id : {
/* (const char*)OPID_HEX_STR */
const char * hexstr = va_arg ( * app , const char * ) ;
tsk_size_t len = tsk_strlen ( hexstr ) ;
if ( len & & ! ( len & 0x01 ) ) {
tsk_size_t i , j ;
if ( tsk_strindexOf ( hexstr , tsk_strlen ( hexstr ) , " 0x " ) = = 0 ) {
hexstr + = 2 ;
len - = 2 ;
}
/* reset old value */
memset ( self - > security . operator_id , 0 , sizeof ( self - > security . operator_id ) ) ;
/* set new value */
if ( len ) { /* perhaps there were only 2 chars*/
for ( i = 0 , j = 0 ; ( i < ( sizeof ( operator_id_t ) * 2 ) & & i < len ) ; i + = 2 , j + + ) {
#if 0 /* Could cause SIGBUS error (if memory misaligned) */
sscanf ( & hexstr [ i ] , " %2x " , & self - > security . operator_id [ j ] ) ;
# else
static unsigned _1bytes ; /* do not use neither int8_t nor uint8_t */
sscanf ( & hexstr [ i ] , " %2x " , & _1bytes ) ;
self - > security . operator_id [ j ] = ( _1bytes & 0xFF ) ;
# endif
}
}
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
else {
TSK_DEBUG_ERROR ( " %s is invalid for an Operator Id value. " , hexstr ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
case tsip_pname_ipsec_params : {
/* (const char*)ALG_STR, (const char*)EALG_STR, (const char*)MODE_STR, (const char*)PROTOCOL_STR*/
tsk_strupdate ( & self - > security . ipsec . alg , va_arg ( * app , const char * ) ) ;
tsk_strupdate ( & self - > security . ipsec . ealg , va_arg ( * app , const char * ) ) ;
tsk_strupdate ( & self - > security . ipsec . mode , va_arg ( * app , const char * ) ) ;
tsk_strupdate ( & self - > security . ipsec . protocol , va_arg ( * app , const char * ) ) ;
break ;
}
case tsip_pname_tls_certs : {
/* (const char*)CA_FILE_STR, (const char*)PUB_FILE_STR, (const char*)PRIV_FILE_STR, (tsk_bool_t)VERIF_BOOL */
tsk_strupdate ( & self - > security . tls . ca , va_arg ( * app , const char * ) ) ;
tsk_strupdate ( & self - > security . tls . pbk , va_arg ( * app , const char * ) ) ;
tsk_strupdate ( & self - > security . tls . pvk , va_arg ( * app , const char * ) ) ;
self - > security . tls . verify = va_arg ( * app , tsk_bool_t ) ;
break ;
}
/* === Dummy Headers === */
case tsip_pname_header : {
/* (const char*)NAME_STR, (const char*)VALUE_STR */
const char * NAME_STR = va_arg ( * app , const char * ) ;
const char * VALUE_STR = va_arg ( * app , const char * ) ;
if ( VALUE_STR = = ( ( const char * ) - 1 ) ) { /* UNSET */
tsk_params_remove_param ( self - > headers , NAME_STR ) ;
}
else { /* SET */
tsk_params_add_param ( & self - > headers , NAME_STR , VALUE_STR ) ;
2015-07-13 23:20:07 +00:00
}
2016-02-23 21:00:35 +00:00
break ;
}
/* === Nat Traversal === */
case tsip_pname_stun_server : {
/* (const char*)IP_STR, (unsigned)PORT_UINT */
const char * IP_STR = va_arg ( * app , const char * ) ;
unsigned PORT_UINT = va_arg ( * app , unsigned ) ;
/* do not check, Null==> disable STUN */
tsk_strupdate ( & self - > natt . stun . ip , IP_STR ) ;
self - > natt . stun . port = PORT_UINT ;
break ;
}
case tsip_pname_stun_cred : {
/* (const char*)USR_STR, (const char*)PASSORD_STR */
const char * USR_STR = va_arg ( * app , const char * ) ;
const char * PASSORD_STR = va_arg ( * app , const char * ) ;
tsk_strupdate ( & self - > natt . stun . login , USR_STR ) ;
tsk_strupdate ( & self - > natt . stun . pwd , PASSORD_STR ) ;
break ;
}
case tsip_pname_stun_enabled : {
/* (tsk_bool_t)ENABLED_BOOL */
self - > natt . stun . enabled = va_arg ( * app , tsk_bool_t ) ;
break ;
}
/* === User Data === */
case tsip_pname_userdata : {
/* (const void*)DATA_PTR */
self - > userdata = va_arg ( * app , const void * ) ;
break ;
}
default : {
/* va_list will be unsafe ==> must exit */
TSK_DEBUG_WARN ( " Found unknown pname. " ) ;
goto bail ;
}
2015-07-13 23:20:07 +00:00
} /* switch */
} /* while */
2016-02-23 21:00:35 +00:00
2011-03-25 09:38:07 +00:00
bail :
2015-07-13 23:20:07 +00:00
return 0 ;
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
* Creates new 3 GPP IMS / LTE stack handle .
* As the 3 GPP IMS / LTE stack depends on the network library ( tinyNET ) , you MUST call < a href = " http://doubango.org/API/tinyNET/tnet_8c.html#affba6c2710347476f615b0135777c640 " > tnet_startup ( ) < / a > before using any SIP function ( tsip_ * ) .
* < a href = " http://doubango.org/API/tinyNET/tnet_8c.html#ac42b22a7ac5831f04326aee9de033c84 " > tnet_cleanup ( ) < / a > is used to terminate use of network functions .
* @ param callback Callback function to call to alert the application for new SIP or media events .
* @ param realm_uri The realm is the name of the domain name to authenticate to . It should be a valid SIP URI ( e . g . sip : open - ims . test ) .
* @ param impi_uri The IMPI is a unique identifier assigned to a user ( or UE ) by the home network .
* It could be either a SIP URI ( e . g . sip : bob @ open - ims . test ) , a tel URI ( e . g . tel : + 33100000 ) or any alphanumeric string ( e . g . bob @ open - ims . test or bob ) .
* It is used to authenticate the UE ( username field in SIP Authorization / Proxy - Authorization header ) .
* @ param impu_uri As its name says , it <EFBFBD> s you public visible identifier where you are willing to receive calls or any demands .
* An IMPU could be either a SIP or tel URI ( e . g . tel : + 33100000 or sip : bob @ open - ims . test ) . In IMS world , a user can have multiple IMPUs associated to its unique IMPI .
* @ param . . . Any TSIP_STACK_SET_ * ( ) macros .
* @ retval A valid handle if succeed and Null - handle otherwise . As a stack is a well - defined object , you should use @ a TSK_OBJECT_SAFE_FREE ( ) to safely destroy the handle .
*
* @ code
int app_callback ( const tsip_event_t * sipevent ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
const char * realm_uri = " sip:open-ims.test " ;
const char * impi_uri = " bob@open-ims.test " ;
const char * impu_uri = " sip:bob@open-ims.test " ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
tsip_stack_handle_t * stack = tsip_stack_create ( app_callback , realm_uri , impi_uri , impu_uri ,
TSIP_STACK_SET_PASSWORD ( " mysecret " ) ,
// ...other macros...
TSIP_STACK_SET_NULL ( ) ) ;
2016-02-23 21:00:35 +00:00
2011-03-25 09:38:07 +00:00
// ...whatever
2016-02-23 21:00:35 +00:00
2011-03-25 09:38:07 +00:00
TSK_OBJECT_SAFE_FREE ( stack ) ;
2015-07-13 23:20:07 +00:00
* @ endcode
* @ sa @ ref tsip_stack_set ( ) < br > @ ref tsip_stack_start ( )
*/
2011-03-25 09:38:07 +00:00
tsip_stack_handle_t * tsip_stack_create ( tsip_stack_callback_f callback , const char * realm_uri , const char * impi_uri , const char * impu_uri , . . . )
{
2015-07-13 23:20:07 +00:00
tsip_stack_t * stack = tsk_null ;
va_list ap ;
int i ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === check values === */
2016-02-23 21:00:35 +00:00
if ( ! realm_uri | | ! impi_uri | | ! impu_uri ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter. " ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === create the stack === */
2016-02-23 21:00:35 +00:00
if ( ! ( stack = tsk_object_new ( tsip_stack_def_t ) ) ) { /* should never happen */
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Failed to create the stack. " ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Set mandatory values (realm, IMPI and IMPU) === */
if ( tsip_stack_set ( stack ,
TSIP_STACK_SET_REALM ( realm_uri ) ,
TSIP_STACK_SET_IMPI ( impi_uri ) ,
TSIP_STACK_SET_IMPU ( impu_uri ) ,
2016-02-23 21:00:35 +00:00
TSIP_STACK_SET_NULL ( ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter. " ) ;
TSK_OBJECT_SAFE_FREE ( stack ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Default values (Network) === */
stack - > network . mode = tsip_stack_mode_ua ;
2016-02-23 21:00:35 +00:00
for ( i = 0 ; i < sizeof ( stack - > network . local_port ) / sizeof ( stack - > network . local_port [ 0 ] ) ; + + i ) {
stack - > network . local_port [ i ] = TNET_SOCKET_PORT_ANY ;
}
for ( i = 0 ; i < sizeof ( stack - > network . proxy_cscf_port ) / sizeof ( stack - > network . proxy_cscf_port [ 0 ] ) ; + + i ) {
stack - > network . proxy_cscf_port [ i ] = 5060 ;
}
for ( i = 0 ; i < sizeof ( stack - > network . proxy_cscf_type ) / sizeof ( stack - > network . proxy_cscf_type [ 0 ] ) ; + + i ) {
stack - > network . proxy_cscf_type [ i ] = tnet_socket_type_invalid ;
}
2015-07-13 23:20:07 +00:00
stack - > network . max_fds = tmedia_defaults_get_max_fds ( ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
// all events should be delivered to the user before the stack stop
tsk_runnable_set_important ( TSK_RUNNABLE ( stack ) , tsk_true ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === SigComp === */
// only create the handler on-demand: when compartment is added
stack - > sigcomp . dms = TSIP_SIGCOMP_DMS ;
stack - > sigcomp . sms = TSIP_SIGCOMP_SMS ;
stack - > sigcomp . cpb = TSIP_SIGCOMP_CPB ;
stack - > sigcomp . sip_dict = TSIP_SIGCOMP_SIP_DICT ;
stack - > sigcomp . pres_dict = TSIP_SIGCOMP_PRES_DICT ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === DNS context ===
* Because of TSIP_STACK_SET_DNS_SERVER ( ) , ctx should be created before calling __tsip_stack_set ( )
*/
stack - > dns_ctx = tnet_dns_ctx_create ( ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === DHCP context === */
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === NAT Traversal === */
{
const char * server_ip , * usr_name , * usr_pwd ;
uint16_t server_port ;
stack - > natt . stun . enabled = tmedia_defaults_get_stun_enabled ( ) ;
2016-02-23 21:00:35 +00:00
if ( tmedia_defaults_get_stun_server ( & server_ip , & server_port ) = = 0 ) {
2015-07-13 23:20:07 +00:00
tsk_strupdate ( & stack - > natt . stun . ip , server_ip ) ;
stack - > natt . stun . port = server_port ;
}
2016-02-23 21:00:35 +00:00
if ( tmedia_defaults_get_stun_cred ( & usr_name , & usr_pwd ) = = 0 ) {
2015-07-13 23:20:07 +00:00
tsk_strupdate ( & stack - > natt . stun . login , usr_name ) ;
tsk_strupdate ( & stack - > natt . stun . pwd , usr_pwd ) ;
}
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Set user supplied parameters === */
va_start ( ap , impu_uri ) ;
2016-02-23 21:00:35 +00:00
if ( __tsip_stack_set ( stack , & ap ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter. " ) ;
TSK_OBJECT_SAFE_FREE ( stack ) ;
va_end ( ap ) ;
goto bail ;
}
va_end ( ap ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Internals === */
stack - > callback = callback ;
2016-02-23 21:00:35 +00:00
if ( ! stack - > ssessions ) {
2015-07-13 23:20:07 +00:00
stack - > ssessions = tsk_list_create ( ) ;
}
2016-02-23 21:00:35 +00:00
if ( ! stack - > headers ) { /* could be created by tsk_params_add_param() */
2015-07-13 23:20:07 +00:00
stack - > headers = tsk_list_create ( ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Layers === */
2016-02-23 21:00:35 +00:00
if ( ! ( stack - > layer_dialog = tsip_dialog_layer_create ( stack ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Failed to create Dialog layer " ) ;
TSK_OBJECT_SAFE_FREE ( stack ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
if ( ! ( stack - > layer_transac = tsip_transac_layer_create ( stack ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Failed to create Transac layer " ) ;
TSK_OBJECT_SAFE_FREE ( stack ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
if ( ! ( stack - > layer_transport = tsip_transport_layer_create ( stack ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Failed to create Transport layer " ) ;
TSK_OBJECT_SAFE_FREE ( stack ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2011-03-25 09:38:07 +00:00
bail :
2015-07-13 23:20:07 +00:00
return stack ;
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
* Starts a 3 GPP IMS / LTE stack . This function MUST be called before you start calling any SIP function ( @ a tsip_ * ) .
* @ param self The 3 GPP IMS / LTE stack to start . This handle should be created using @ ref tsip_stack_create ( ) .
* @ retval Zero if succeed and non - zero error code otherwise .
*/
2011-03-25 09:38:07 +00:00
int tsip_stack_start ( tsip_stack_handle_t * self )
{
2015-07-13 23:20:07 +00:00
int ret = - 1 , t_idx , tx_count ;
tsip_stack_t * stack = self ;
tnet_socket_type_t * tx_values ;
const char * stack_error_desc = " Failed to start the stack " ;
2016-02-23 21:00:35 +00:00
if ( ! stack ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
if ( stack - > started ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " Stack Already started " ) ;
return 0 ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
tsk_safeobj_lock ( stack ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
// transports
2016-02-23 21:00:35 +00:00
if ( TSIP_STACK_MODE_IS_SERVER ( stack ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " Stack running in SERVER mode " ) ;
tx_values = & stack - > network . transport_types [ 0 ] ;
tx_count = sizeof ( stack - > network . transport_types ) / sizeof ( stack - > network . transport_types [ 0 ] ) ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " Stack running in CLIENT mode " ) ;
tx_values = & stack - > network . proxy_cscf_type [ 0 ] ;
tx_count = sizeof ( stack - > network . proxy_cscf_type ) / sizeof ( stack - > network . proxy_cscf_type [ 0 ] ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Timer manager === */
2016-02-23 21:00:35 +00:00
if ( ! stack - > timer_mgr_global ) {
2015-07-13 23:20:07 +00:00
stack - > timer_mgr_global = tsk_timer_mgr_global_ref ( ) ;
}
2016-02-23 21:00:35 +00:00
if ( ( ret = tsk_timer_manager_start ( stack - > timer_mgr_global ) ) ) {
2015-07-13 23:20:07 +00:00
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Set P-Preferred-Identity === */
2016-02-23 21:00:35 +00:00
if ( ! stack - > identity . preferred & & stack - > identity . impu ) {
2015-07-13 23:20:07 +00:00
stack - > identity . preferred = tsk_object_ref ( ( void * ) stack - > identity . impu ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Set Max FDs === */
if ( stack - > network . max_fds > 0 & & stack - > network . max_fds < 0xFFFF ) {
TSK_DEBUG_INFO ( " Setting max FDs to %u " , ( unsigned ) stack - > network . max_fds ) ;
ret = tnet_set_fd_max_allowed ( stack - > network . max_fds ) ;
if ( ret ) {
TSK_DEBUG_ERROR ( " Failed to set max FDs to %u " , ( unsigned ) stack - > network . max_fds ) ;
/* goto bail; */ // Not fatal error
}
}
2016-02-23 21:00:35 +00:00
2022-03-04 19:23:41 +00:00
TSK_DEBUG_INFO ( " secagree_mech=%s \n " , stack - > security . secagree_mech ) ;
stack - > security . enable_secagree_ipsec = tsk_true ;
TSK_DEBUG_INFO ( " enable_secagree_ipsec=%d \n " , stack - > security . enable_secagree_ipsec ) ;
2015-07-13 23:20:07 +00:00
/* === Transport type === */
2016-02-23 21:00:35 +00:00
if ( ! tsk_strnullORempty ( stack - > security . secagree_mech ) ) {
if ( tsk_striequals ( stack - > security . secagree_mech , " ipsec-3gpp " ) & & stack - > security . enable_secagree_ipsec ) {
2012-11-12 08:13:42 +00:00
#if 0
2015-07-13 23:20:07 +00:00
TNET_SOCKET_TYPE_SET_IPSEC ( stack - > network . proxy_cscf_type ) ;
2012-11-12 08:13:42 +00:00
# endif
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Not implemented " ) ;
}
//else if if(tsk_striquals(stack->security.secagree_mech, "ipsec-ike"))
}
2016-02-23 21:00:35 +00:00
for ( t_idx = 0 ; t_idx < tx_count ; + + t_idx ) {
if ( ! TNET_SOCKET_TYPE_IS_VALID ( tx_values [ t_idx ] ) ) {
2015-07-13 23:20:07 +00:00
continue ;
}
/* === Use DNS NAPTR+SRV for the P-CSCF discovery if we are in client mode === */
2016-02-23 21:00:35 +00:00
if ( TSIP_STACK_MODE_IS_CLIENT ( stack ) ) {
if ( tsk_strnullORempty ( stack - > network . proxy_cscf [ t_idx ] ) | | ( stack - > network . discovery_dhcp | | stack - > network . discovery_naptr ) ) {
if ( stack - > network . discovery_dhcp ) { /* DHCP v4/v6 */
2015-07-13 23:20:07 +00:00
/* FIXME: */
TSK_DEBUG_ERROR ( " Unexpected code called " ) ;
ret = - 2 ;
} /* DHCP */
2016-02-23 21:00:35 +00:00
else { /* DNS NAPTR + SRV*/
2015-07-13 23:20:07 +00:00
char * hostname = tsk_null ;
tnet_port_t port = 0 ;
const char * service = TNET_SOCKET_TYPE_IS_DGRAM ( tx_values [ t_idx ] ) ? " SIP+D2U " : ( TNET_SOCKET_TYPE_IS_TLS ( tx_values [ t_idx ] ) ? " SIPS+D2T " : " SIP+D2T " ) ;
2016-02-23 21:00:35 +00:00
if ( ( ret = tnet_dns_query_naptr_srv ( stack - > dns_ctx , stack - > network . realm - > host , service , & hostname , & port ) ) = = 0 ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " DNS SRV(NAPTR(%s, %s) = [%s / %d] " , stack - > network . realm - > host , service , hostname , port ) ;
tsk_strupdate ( & stack - > network . proxy_cscf [ t_idx ] , hostname ) ;
2016-02-23 21:00:35 +00:00
if ( ! stack - > network . proxy_cscf_port [ t_idx ] | | stack - > network . proxy_cscf_port [ t_idx ] = = 5060 ) { /* Only if the Proxy-CSCF port is missing or default */
2015-07-13 23:20:07 +00:00
stack - > network . proxy_cscf_port [ t_idx ] = port ;
}
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " P-CSCF discovery using DNS NAPTR failed. The stack will use the user supplied address and port. " ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_FREE ( hostname ) ;
} /* NAPTR */
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Check Proxy-CSCF IP address */
2016-02-23 21:00:35 +00:00
if ( ! tsk_strnullORempty ( stack - > network . proxy_cscf [ t_idx ] ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " Proxy-CSCF=[%s]:%d " , stack - > network . proxy_cscf [ t_idx ] , stack - > network . proxy_cscf_port [ t_idx ] ) ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Proxy-CSCF IP address is Null. " ) ;
ret = - 1983 ;
goto bail ;
}
} // !Server mode
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Get Best source address === */
// Best local address must be updated if not defined or none is set by the user.
// The local address could be no-null if the stack is re-starting: https://code.google.com/p/doubango/issues/detail?id=454 and https://code.google.com/p/idoubs/issues/detail?id=195
if ( ! stack - > network . local_ip_is_set_by_user [ t_idx ] | | tsk_strnullORempty ( stack - > network . local_ip [ t_idx ] ) | | tsk_striequals ( stack - > network . local_ip [ t_idx ] , " 127.0.0.1 " ) ) { /* loacal-ip is missing? */
tnet_ip_t bestsource ;
if ( ( ret = tnet_getbestsource ( stack - > network . proxy_cscf [ t_idx ] ? stack - > network . proxy_cscf [ t_idx ] : " google.com " ,
2016-02-23 21:00:35 +00:00
stack - > network . proxy_cscf_port [ t_idx ] ? stack - > network . proxy_cscf_port [ t_idx ] : 5060 ,
tx_values [ t_idx ] ,
& bestsource ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Failed to get best source [%d] " , ret ) ;
/* do not exit ==> will use default IP address */
}
else {
tsk_strupdate ( & stack - > network . local_ip [ t_idx ] , bestsource ) ;
TSK_DEBUG_INFO ( " Best source at %d: %s " , t_idx , bestsource ) ;
}
}
else {
TSK_DEBUG_INFO ( " Do not query for best source address at %d, local_ip_is_set_by_user=%d, local_ip=%s " , t_idx , stack - > network . local_ip_is_set_by_user [ t_idx ] , stack - > network . local_ip [ t_idx ] ) ;
}
} /* for (t_idx...) */
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Runnable === */
TSK_RUNNABLE ( stack ) - > run = run ;
2016-02-23 21:00:35 +00:00
if ( ( ret = tsk_runnable_start ( TSK_RUNNABLE ( stack ) , tsip_event_def_t ) ) ) {
2015-07-13 23:20:07 +00:00
stack_error_desc = " Failed to start runnable " ;
TSK_DEBUG_ERROR ( " %s " , stack_error_desc ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
// must be here because the runnable object is only valid after start()
TSIP_STACK_SIGNAL ( self , tsip_event_code_stack_starting , " Stack starting " ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Nat Traversal === */
// delete previous context
TSK_OBJECT_SAFE_FREE ( stack - > natt . ctx ) ;
2016-02-23 21:00:35 +00:00
if ( stack - > natt . stun . enabled & & ! tsk_strnullORempty ( stack - > natt . stun . ip ) ) {
if ( stack - > natt . stun . port = = 0 ) {
2015-07-13 23:20:07 +00:00
/* FIXME: for now only UDP(IPv4/IPv6) is supported */
stack - > natt . stun . port = kStunPortDefaultTcpUdp ;
}
TSK_DEBUG_INFO ( " STUN server = %s:%u " , stack - > natt . stun . ip , stack - > natt . stun . port ) ;
stack - > natt . ctx = tnet_nat_context_create ( TNET_SOCKET_TYPE_IS_IPV6 ( tx_values [ stack - > network . transport_idx_default ] ) ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4 ,
2016-02-23 21:00:35 +00:00
stack - > natt . stun . login , stack - > natt . stun . pwd ) ;
2015-07-13 23:20:07 +00:00
ret = tnet_nat_set_server ( stack - > natt . ctx , stack - > natt . stun . ip , stack - > natt . stun . port ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === Transport Layer === */
2016-02-23 21:00:35 +00:00
for ( t_idx = 0 ; t_idx < tx_count ; + + t_idx ) {
if ( ! TNET_SOCKET_TYPE_IS_VALID ( tx_values [ t_idx ] ) ) {
2015-07-13 23:20:07 +00:00
continue ;
}
2016-02-23 21:00:35 +00:00
if ( ( ret = tsip_transport_layer_add ( stack - > layer_transport , stack - > network . local_ip [ t_idx ] , stack - > network . local_port [ t_idx ] , tx_values [ t_idx ] , " SIP transport " ) ) ) {
2015-07-13 23:20:07 +00:00
stack_error_desc = " Failed to add new transport " ;
TSK_DEBUG_ERROR ( " %s " , stack_error_desc ) ;
goto bail ;
}
}
/* Starts the transport Layer */
2016-02-23 21:00:35 +00:00
if ( ( ret = tsip_transport_layer_start ( stack - > layer_transport ) ) ) {
2015-07-13 23:20:07 +00:00
stack_error_desc = " Failed to start sip transport " ;
TSK_DEBUG_ERROR ( " %s " , stack_error_desc ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Update the local_ip */
2016-02-23 21:00:35 +00:00
for ( t_idx = 0 ; t_idx < tx_count ; + + t_idx ) {
if ( ! TNET_SOCKET_TYPE_IS_VALID ( tx_values [ t_idx ] ) ) {
2015-07-13 23:20:07 +00:00
continue ;
}
2016-02-23 21:00:35 +00:00
if ( tsk_strnullORempty ( stack - > network . local_ip [ t_idx ] ) ) {
2015-07-13 23:20:07 +00:00
const tsip_transport_t * transport = tsip_transport_layer_find_by_type ( stack - > layer_transport , tx_values [ t_idx ] ) ;
2016-02-23 21:00:35 +00:00
if ( transport ) {
2015-07-13 23:20:07 +00:00
tnet_ip_t ip ;
2016-02-23 21:00:35 +00:00
if ( ! tnet_transport_get_ip_n_port_2 ( transport - > net_transport , & ip , tsk_null ) ) {
2015-07-13 23:20:07 +00:00
tsk_strupdate ( & stack - > network . local_ip [ t_idx ] , ip ) ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_WARN ( " Failed to get local_ip for transport type = %d " , tx_values [ t_idx ] ) ;
/* Do not exit */
}
}
}
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* === ALL IS OK === */
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
stack - > started = tsk_true ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Signal to the end-user that the stack has been started */
TSIP_STACK_SIGNAL ( self , tsip_event_code_stack_started , " Stack started " ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " SIP STACK -- START " ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
tsk_safeobj_unlock ( stack ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
return 0 ;
2016-02-23 21:00:35 +00:00
2011-03-25 09:38:07 +00:00
bail :
2015-07-13 23:20:07 +00:00
TSIP_STACK_SIGNAL ( self , tsip_event_code_stack_failed_to_start , stack_error_desc ) ;
/* stop all running instances */
2016-02-23 21:00:35 +00:00
if ( stack - > layer_transport ) {
2015-07-13 23:20:07 +00:00
tsip_transport_layer_shutdown ( stack - > layer_transport ) ;
}
2016-02-23 21:00:35 +00:00
if ( TSK_RUNNABLE ( stack ) - > running ) {
2015-07-13 23:20:07 +00:00
tsk_runnable_stop ( TSK_RUNNABLE ( stack ) ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
tsk_safeobj_unlock ( stack ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
return ret ;
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
* Configures the stack .
* @ param self The 3 GPP IMS / LTE stack to configure . This handle should be created using @ ref tsip_stack_create ( ) .
* @ param . . . Any TSIP_STACK_SET_ * ( ) or TSIP_STACK_UNSET_ * ( ) macros .
* @ retval Zero if succeed and non - zero error code otherwise .
*
* @ code
int ret = tsip_stack_set ( stack ,
TSIP_STACK_SET_HEADER ( " User-Agent " , " IM-client/OMA1.0 doubango/v1.0.0 " ) ,
TSIP_STACK_SET_NULL ( ) ) ;
* @ endcode
*
* @ sa @ ref tsip_stack_create ( )
*/
2011-03-25 09:38:07 +00:00
int tsip_stack_set ( tsip_stack_handle_t * self , . . . )
{
2016-02-23 21:00:35 +00:00
if ( self ) {
2015-07-13 23:20:07 +00:00
int ret ;
tsip_stack_t * stack = self ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
va_list ap ;
va_start ( ap , self ) ;
ret = __tsip_stack_set ( stack , & ap ) ;
va_end ( ap ) ;
return ret ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
* Gets user ' s data , previously set using @ ref TSIP_STACK_SET_USERDATA ( ) macro .
* @ param self Stack from which to get the user ' s data .
*/
2011-03-25 09:38:07 +00:00
const void * tsip_stack_get_userdata ( const tsip_stack_handle_t * self )
{
2016-02-23 21:00:35 +00:00
if ( self ) {
2015-07-13 23:20:07 +00:00
return ( ( const tsip_stack_t * ) self ) - > userdata ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return tsk_null ;
}
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
*/
2011-03-25 09:38:07 +00:00
tnet_dns_ctx_t * tsip_stack_get_dnsctx ( tsip_stack_handle_t * self )
{
2016-02-23 21:00:35 +00:00
if ( self ) {
2015-07-13 23:20:07 +00:00
return ( tnet_dns_ctx_t * ) tsk_object_ref ( ( ( tsip_stack_t * ) self ) - > dns_ctx ) ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return tsk_null ;
}
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
*/
2011-03-25 09:38:07 +00:00
tsip_uri_t * tsip_stack_get_preferred_id ( tsip_stack_handle_t * self )
{
2016-02-23 21:00:35 +00:00
if ( self ) {
2015-07-13 23:20:07 +00:00
return ( tsip_uri_t * ) tsk_object_ref ( ( ( tsip_stack_t * ) self ) - > identity . preferred ) ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return tsk_null ;
}
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
*/
2011-03-25 09:38:07 +00:00
int tsip_stack_get_local_ip_n_port ( const tsip_stack_handle_t * self , const char * protocol , tnet_port_t * port , tnet_ip_t * ip )
{
2015-07-13 23:20:07 +00:00
const tsip_stack_t * stack = self ;
2016-02-23 21:00:35 +00:00
if ( ! stack | | ! port | | ! ip ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
if ( stack ) {
2015-07-13 23:20:07 +00:00
tsk_list_item_t * item ;
2016-02-23 21:00:35 +00:00
tsk_list_foreach ( item , stack - > layer_transport - > transports ) {
2015-07-13 23:20:07 +00:00
tsip_transport_t * transport = item - > data ;
2016-02-23 21:00:35 +00:00
if ( transport ) {
if ( tsk_striequals ( transport - > protocol , protocol ) ) {
2015-07-13 23:20:07 +00:00
return tnet_transport_get_public_ip_n_port ( transport - > net_transport , transport - > connectedFD , ip , port ) ;
}
}
}
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_DEBUG_ERROR ( " No transport with such protocol (%s) could be found " , protocol ) ;
return - 2 ;
2011-03-25 09:38:07 +00:00
}
/**@ingroup tsip_stack_group
2015-07-13 23:20:07 +00:00
* Stops the stack .
* @ param self The 3 GPP IMS / LTE stack to stop . This handle should be created using @ ref tsip_stack_create ( ) and started using tsip_stack_start ( ) .
* This function is also called by the garbage collector when the stack is destroyed but you should call it yourself before destroying the stack . < br >
* Before stopping , the stack will hangup all SIP dialogs ( starting with non - register dialogs ) and destroy all sessions . This is called shutdown phase .
* At the end of this phase , all the SIP sessions will be destroyed .
* @ sa @ ref tsip_stack_create ( ) < br > @ ref tsip_stack_start ( )
*/
2011-03-25 09:38:07 +00:00
int tsip_stack_stop ( tsip_stack_handle_t * self )
{
2015-07-13 23:20:07 +00:00
tsip_stack_t * stack = self ;
2016-02-23 21:00:35 +00:00
if ( stack ) {
2015-07-13 23:20:07 +00:00
tsk_bool_t one_failed = tsk_false ;
int ret = 0 ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
tsk_safeobj_lock ( stack ) ;
2016-02-23 21:00:35 +00:00
if ( ! stack - > started ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " Stack already stopped " ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSIP_STACK_SIGNAL ( self , tsip_event_code_stack_stopping , " Stack stopping " ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Hangup all dialogs starting by REGISTER */
2016-02-23 21:00:35 +00:00
if ( ( ret = tsip_dialog_layer_shutdownAll ( stack - > layer_dialog ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_WARN ( " Failed to hang-up all dialogs " ) ;
one_failed = tsk_true ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* do not try to clean up transactions ==> each dialog will cancel its transactions.
* see tsip_dialog_deinit ( ) which call tsip_transac_layer_cancel_by_dialog ( ) */
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Stop the timer manager */
// not done as it's global (shared). Will be done when all instance are destoyed
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Stop the transport layer */
2016-02-23 21:00:35 +00:00
if ( ( ret = tsip_transport_layer_shutdown ( stack - > layer_transport ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_WARN ( " Failed to stop the transport layer " ) ;
one_failed = tsk_true ;
}
2016-02-23 21:00:35 +00:00
/* Signal to the end-user that the stack has been stopped
2015-07-13 23:20:07 +00:00
* should be done before tsk_runnable_stop ( ) which will stop the thread
* responsible for the callbacks . The enqueued data have been marked as " important " .
* As both the timer manager and the transport layer have been stoped there is no
* chance to got additional events */
2016-02-23 21:00:35 +00:00
if ( one_failed ) {
2015-07-13 23:20:07 +00:00
TSIP_STACK_SIGNAL ( self , tsip_event_code_stack_failed_to_stop , " Stack failed to stop " ) ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
TSIP_STACK_SIGNAL ( self , tsip_event_code_stack_stopped , " Stack stopped " ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Stop runnable (run() thread) */
2016-02-23 21:00:35 +00:00
if ( ( ret = tsk_runnable_stop ( TSK_RUNNABLE ( stack ) ) ) ) {
2015-07-13 23:20:07 +00:00
TSK_DEBUG_WARN ( " Failed to stop the stack " ) ;
one_failed = tsk_true ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Close all SigComp Compartments (do not remove them) */
2016-02-23 21:00:35 +00:00
if ( stack - > sigcomp . handle ) {
2015-07-13 23:20:07 +00:00
tsip_sigcomp_close_all ( stack - > sigcomp . handle ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* reset AoR */
TSK_FREE_TABLE ( stack - > network . aor . ip ) ;
memset ( stack - > network . aor . port , 0 , sizeof ( stack - > network . aor . port ) ) ;
2016-02-23 21:00:35 +00:00
2013-03-20 21:40:26 +00:00
/* stops timer manager */
2016-02-23 21:00:35 +00:00
if ( stack - > timer_mgr_global ) {
2013-03-20 21:40:26 +00:00
tsk_timer_mgr_global_unref ( & stack - > timer_mgr_global ) ;
}
2016-02-23 21:00:35 +00:00
if ( ! one_failed ) {
2015-07-13 23:20:07 +00:00
stack - > started = tsk_false ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " SIP STACK -- STOP " ) ;
2016-02-23 21:00:35 +00:00
bail :
2015-07-13 23:20:07 +00:00
tsk_safeobj_unlock ( stack ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
return ret ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
return - 1 ;
2011-03-25 09:38:07 +00:00
}
/* internal function used to construct a valid contact URI */
tsip_uri_t * tsip_stack_get_contacturi ( const tsip_stack_t * stack , const char * protocol )
{
2016-02-23 21:00:35 +00:00
if ( stack ) {
2015-07-13 23:20:07 +00:00
tsk_list_item_t * item ;
2016-02-23 21:00:35 +00:00
tsk_list_foreach ( item , stack - > layer_transport - > transports ) {
2015-07-13 23:20:07 +00:00
tsip_transport_t * transport = item - > data ;
2016-02-23 21:00:35 +00:00
if ( transport ) {
if ( tsk_striequals ( transport - > protocol , protocol ) ) {
2015-07-13 23:20:07 +00:00
tsip_uri_t * uri = tsk_null ;
2016-02-23 21:00:35 +00:00
if ( ( uri = tsip_transport_get_uri ( transport , tsk_false ) ) ) {
2015-07-13 23:20:07 +00:00
tsk_strupdate ( & uri - > user_name , stack - > identity . impu - > user_name ) ;
return uri ;
}
}
}
}
}
return tsk_null ;
2011-03-25 09:38:07 +00:00
}
/* internal function used to construct a valid Proxy-CSCF URI used as the default first route */
2012-11-12 08:13:42 +00:00
tsip_uri_t * tsip_stack_get_pcscf_uri ( const tsip_stack_t * stack , tnet_socket_type_t type , tsk_bool_t lr )
2011-03-25 09:38:07 +00:00
{
2016-02-23 21:00:35 +00:00
if ( stack ) {
2015-07-13 23:20:07 +00:00
const tsip_transport_t * transport = tsk_null ;
2016-02-23 21:00:35 +00:00
if ( ! TNET_SOCKET_TYPE_IS_VALID ( type ) & & ! TSK_LIST_IS_EMPTY ( stack - > layer_transport - > transports ) ) {
2015-07-13 23:20:07 +00:00
transport = stack - > layer_transport - > transports - > head - > data ;
}
2016-02-23 21:00:35 +00:00
else {
2015-07-13 23:20:07 +00:00
transport = tsip_transport_layer_find_by_type ( stack - > layer_transport , type ) ;
}
2016-02-23 21:00:35 +00:00
if ( transport ) {
2015-07-13 23:20:07 +00:00
tsip_uri_t * uri = tsk_null ;
tsk_bool_t ipv6 = TNET_SOCKET_TYPE_IS_IPV6 ( transport - > type ) ;
tsk_bool_t quote_ip = ( ipv6 & & tsk_strcontains ( stack - > network . proxy_cscf [ transport - > idx ] , tsk_strlen ( stack - > network . proxy_cscf [ transport - > idx ] ) , " : " ) ) /* IPv6 IP string?*/ ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
char * uristring = tsk_null ;
tsk_sprintf ( & uristring , " %s:%s%s%s:%d;%s;transport=%s " ,
transport - > scheme ,
quote_ip ? " [ " : " " ,
stack - > network . proxy_cscf [ transport - > idx ] ,
quote_ip ? " ] " : " " ,
stack - > network . proxy_cscf_port [ transport - > idx ] ,
lr ? " lr " : " " ,
transport - > protocol ) ;
2016-02-23 21:00:35 +00:00
if ( uristring ) {
if ( ( uri = tsip_uri_parse ( uristring , tsk_strlen ( uristring ) ) ) ) {
2015-07-13 23:20:07 +00:00
//uri->host_type = ipv6 ? thttp_host_ipv6 : thttp_host_ipv4;
}
TSK_FREE ( uristring ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
return uri ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
}
return tsk_null ;
2011-03-25 09:38:07 +00:00
}
2013-02-17 18:56:03 +00:00
static void * TSK_STDCALL run ( void * self )
2011-03-25 09:38:07 +00:00
{
2015-07-13 23:20:07 +00:00
tsk_list_item_t * curr ;
tsip_stack_t * stack = self ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " SIP STACK::run -- START " ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_RUNNABLE_RUN_BEGIN ( stack ) ;
2016-02-23 21:00:35 +00:00
if ( ( curr = TSK_RUNNABLE_POP_FIRST ( stack ) ) ) {
2015-07-13 23:20:07 +00:00
tsip_event_t * sipevent = ( tsip_event_t * ) curr - > data ;
2016-02-23 21:00:35 +00:00
if ( stack - > callback ) {
2015-07-13 23:20:07 +00:00
sipevent - > userdata = stack - > userdata ; // needed by sessionless events
stack - > callback ( sipevent ) ;
2016-02-23 21:00:35 +00:00
}
2015-07-13 23:20:07 +00:00
tsk_object_unref ( curr ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_RUNNABLE_RUN_END ( self ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " SIP STACK::run -- STOP " ) ;
return 0 ;
2011-03-25 09:38:07 +00:00
}
//========================================================
// SIP stack object definition
//
static tsk_object_t * tsip_stack_ctor ( tsk_object_t * self , va_list * app )
{
2015-07-13 23:20:07 +00:00
tsip_stack_t * stack = self ;
2016-02-23 21:00:35 +00:00
if ( stack ) {
2015-07-13 23:20:07 +00:00
tsk_safeobj_init ( stack ) ;
}
return self ;
2011-03-25 09:38:07 +00:00
}
static tsk_object_t * tsip_stack_dtor ( tsk_object_t * self )
2016-02-23 21:00:35 +00:00
{
2015-07-13 23:20:07 +00:00
tsip_stack_t * stack = self ;
2016-02-23 21:00:35 +00:00
if ( stack ) {
2015-07-13 23:20:07 +00:00
/* /!\ Order in which objects are destroyed is very important */
2016-02-23 21:00:35 +00:00
/* Stop
2015-07-13 23:20:07 +00:00
* Will try to hangup all dialogs */
2016-02-23 21:00:35 +00:00
if ( stack - > started ) {
2015-07-13 23:20:07 +00:00
tsip_stack_stop ( stack ) ;
}
2016-02-23 21:00:35 +00:00
/* Layers(1/1): Transacs and dialogs use timer_mgr when destroyed
2015-07-13 23:20:07 +00:00
* Dialogs = > ( use ) = > transacs = > ( use ) = > transport . */
TSK_OBJECT_SAFE_FREE ( stack - > layer_dialog ) ;
TSK_OBJECT_SAFE_FREE ( stack - > layer_transac ) ;
TSK_OBJECT_SAFE_FREE ( stack - > layer_transport ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Internals(1/2) */
2016-02-23 21:00:35 +00:00
if ( stack - > timer_mgr_global ) {
2013-03-20 21:40:26 +00:00
tsk_timer_mgr_global_unref ( & stack - > timer_mgr_global ) ;
}
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Identity */
TSK_FREE ( stack - > identity . display_name ) ;
TSK_OBJECT_SAFE_FREE ( stack - > identity . impu ) ;
TSK_OBJECT_SAFE_FREE ( stack - > identity . preferred ) ;
//TSK_OBJECT_SAFE_FREE(stack->associated_identity);
TSK_FREE ( stack - > identity . impi ) ;
TSK_FREE ( stack - > identity . password ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Network(1/1) */
TSK_FREE_TABLE ( stack - > network . local_ip ) ;
TSK_OBJECT_SAFE_FREE ( stack - > network . realm ) ;
TSK_FREE_TABLE ( stack - > network . proxy_cscf ) ;
TSK_OBJECT_SAFE_FREE ( stack - > paths ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_FREE_TABLE ( stack - > network . aor . ip ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_OBJECT_SAFE_FREE ( stack - > service_routes ) ;
TSK_OBJECT_SAFE_FREE ( stack - > associated_uris ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* SigComp (MUST be done after transports) */
TSK_OBJECT_SAFE_FREE ( stack - > sigcomp . handle ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Security(1/1) */
TSK_FREE ( stack - > security . secagree_mech ) ;
TSK_FREE ( stack - > security . ipsec . alg ) ;
TSK_FREE ( stack - > security . ipsec . ealg ) ;
TSK_FREE ( stack - > security . ipsec . mode ) ;
TSK_FREE ( stack - > security . ipsec . protocol ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_FREE ( stack - > security . tls . ca ) ;
TSK_FREE ( stack - > security . tls . pbk ) ;
TSK_FREE ( stack - > security . tls . pvk ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* DNS */
TSK_OBJECT_SAFE_FREE ( stack - > dns_ctx ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* NAT Traversal context */
TSK_FREE ( stack - > natt . stun . ip ) ;
TSK_FREE ( stack - > natt . stun . login ) ;
TSK_FREE ( stack - > natt . stun . pwd ) ;
TSK_OBJECT_SAFE_FREE ( stack - > natt . ctx ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* DHCP */
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* features */
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* QoS */
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
/* Internals (2/2) */
TSK_OBJECT_SAFE_FREE ( stack - > ssessions ) ;
TSK_OBJECT_SAFE_FREE ( stack - > headers ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
tsk_safeobj_deinit ( stack ) ;
2016-02-23 21:00:35 +00:00
2015-07-13 23:20:07 +00:00
TSK_DEBUG_INFO ( " *** SIP Stack destroyed *** " ) ;
}
return self ;
2011-03-25 09:38:07 +00:00
}
2016-02-23 21:00:35 +00:00
static const tsk_object_def_t tsip_stack_def_s = {
2015-07-13 23:20:07 +00:00
sizeof ( tsip_stack_t ) ,
2016-02-23 21:00:35 +00:00
tsip_stack_ctor ,
2015-07-13 23:20:07 +00:00
tsip_stack_dtor ,
2016-02-23 21:00:35 +00:00
tsk_null ,
2011-03-25 09:38:07 +00:00
} ;
const tsk_object_def_t * tsip_stack_def_t = & tsip_stack_def_s ;