2011-03-25 09:38:07 +00:00
/*
2015-06-20 17:58:34 +00:00
* Copyright ( C ) 2010 - 2015 Mamadou DIOP .
*
* 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 tnet_transport.c
* @ brief Network transport layer .
*
* < h2 > 10.2 Tansport < / h2 >
2014-12-19 17:09:09 +00:00
* A transport layer always has a master socket which determine what kind of network traffic we expect ( stream or dgram ) .
2011-03-25 09:38:07 +00:00
* Stream transport can manage TCP , TLS and SCTP sockets . Datagram socket can only manage UDP sockets . < br >
* A transport can hold both IPv4 and IPv6 sockets .
*/
# include "tnet_transport.h"
2015-06-20 17:58:34 +00:00
# include "tnet_proxy_plugin.h"
# include "tnet_proxydetect.h"
2013-01-07 15:37:02 +00:00
# include "tls/tnet_tls.h"
# include "tls/tnet_dtls.h"
2011-03-25 09:38:07 +00:00
2014-05-11 22:25:35 +00:00
# include "stun/tnet_stun_types.h"
2011-03-25 09:38:07 +00:00
# include "tsk_memory.h"
# include "tsk_string.h"
# include "tsk_debug.h"
# include "tsk_thread.h"
# include "tsk_buffer.h"
# include <string.h> /* memcpy, ...(<#void * #>, <#const void * #>, <#tsk_size_t #>) */
2013-01-07 15:37:02 +00:00
# ifndef TNET_CIPHER_LIST
2014-02-14 01:32:49 +00:00
# define TNET_CIPHER_LIST "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"
2013-01-07 15:37:02 +00:00
# endif
2018-04-06 03:17:24 +00:00
// https://mta.openssl.org/pipermail/openssl-dev/2015-May/001449.html
2018-04-06 02:12:35 +00:00
# if BUILD_TYPE_GE
# define TNET_DTLS_method DTLSv1_2_method
# define TNET_SSL_client_method TLSv1_2_client_method
# define TNET_SSL_server_method TLSv1_2_server_method
# else // For backward compatibility, negotiate
2018-04-06 03:17:24 +00:00
# if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
# define TNET_DTLS_method DTLS_method // 1.1 or 1.2 (negotiated)
# define TNET_SSL_client_method TLS_client_method // Any method (from SSLv23 to TLS1.2)
# define TNET_SSL_server_method TLS_server_method // Any method (from SSLv23 to TLS1.2)
# else
# define TNET_DTLS_method DTLSv1_method
# define TNET_SSL_client_method SSLv23_client_method
# define TNET_SSL_server_method SSLv23_server_method
# endif
2018-04-06 02:12:35 +00:00
# endif
2013-01-07 15:37:02 +00:00
2011-03-25 09:38:07 +00:00
extern int tnet_transport_prepare ( tnet_transport_t * transport ) ;
extern int tnet_transport_unprepare ( tnet_transport_t * transport ) ;
2013-02-17 18:56:03 +00:00
extern void * TSK_STDCALL tnet_transport_mainthread ( void * param ) ;
2011-03-25 09:38:07 +00:00
extern int tnet_transport_stop ( tnet_transport_t * transport ) ;
2013-02-17 18:56:03 +00:00
static void * TSK_STDCALL run ( void * self ) ;
2013-01-07 15:37:02 +00:00
static int _tnet_transport_dtls_cb ( const void * usrdata , tnet_dtls_socket_event_type_t e , const tnet_dtls_socket_handle_t * handle , const void * data , tsk_size_t size ) ;
2011-03-25 09:38:07 +00:00
2013-01-07 15:37:02 +00:00
static int _tnet_transport_ssl_init ( tnet_transport_t * transport )
{
2016-02-23 21:00:35 +00:00
if ( ! transport ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2013-01-07 15:37:02 +00:00
# if HAVE_OPENSSL
2015-06-20 17:58:34 +00:00
{
tnet_socket_type_t type = tnet_transport_get_type ( transport ) ;
tsk_bool_t is_tls = ( TNET_SOCKET_TYPE_IS_TLS ( type ) | | TNET_SOCKET_TYPE_IS_WSS ( type ) ) ;
tsk_bool_t is_dtls = transport - > dtls . enabled /* TNET_SOCKET_TYPE_IS_DTLS(type)*/ ; // DTLS-RTP, not raw DTLS
2016-02-23 21:00:35 +00:00
if ( is_dtls & & ! tnet_dtls_is_supported ( ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Requesting to create DTLS transport but source code not built with support for this feature " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
if ( is_tls & & ! tnet_tls_is_supported ( ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Requesting to create TLS transport but source code not built with support for this feature " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
if ( ( transport - > tls . enabled = is_tls ) ) {
2018-04-06 02:12:35 +00:00
if ( ! transport - > tls . ctx_client & & ! ( transport - > tls . ctx_client = SSL_CTX_new ( TNET_SSL_client_method ( ) ) ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Failed to create SSL client context " ) ;
return - 2 ;
}
2018-04-06 02:12:35 +00:00
if ( ! transport - > tls . ctx_server & & ! ( transport - > tls . ctx_server = SSL_CTX_new ( TNET_SSL_server_method ( ) ) ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Failed to create SSL server context " ) ;
return - 3 ;
}
SSL_CTX_set_mode ( transport - > tls . ctx_client , SSL_MODE_AUTO_RETRY ) ;
SSL_CTX_set_mode ( transport - > tls . ctx_server , SSL_MODE_AUTO_RETRY ) ;
SSL_CTX_set_verify ( transport - > tls . ctx_server , SSL_VERIFY_NONE , tsk_null ) ; // to be updated by tnet_transport_tls_set_certs()
SSL_CTX_set_verify ( transport - > tls . ctx_client , SSL_VERIFY_NONE , tsk_null ) ; // to be updated by tnet_transport_tls_set_certs()
2016-02-23 21:00:35 +00:00
if ( SSL_CTX_set_cipher_list ( transport - > tls . ctx_client , TNET_CIPHER_LIST ) < = 0 | | SSL_CTX_set_cipher_list ( transport - > tls . ctx_server , TNET_CIPHER_LIST ) < = 0 ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " SSL_CTX_set_cipher_list failed [%s] " , ERR_error_string ( ERR_get_error ( ) , tsk_null ) ) ;
return - 4 ;
}
}
2013-01-07 15:37:02 +00:00
# if HAVE_OPENSSL_DTLS
2016-02-23 21:00:35 +00:00
if ( ( transport - > dtls . enabled = is_dtls ) ) {
2018-04-06 02:12:35 +00:00
if ( ! transport - > dtls . ctx & & ! ( transport - > dtls . ctx = SSL_CTX_new ( TNET_DTLS_method ( ) ) ) ) {
2016-02-23 21:00:35 +00:00
TSK_DEBUG_ERROR ( " Failed to create DTLSv1 context " ) ;
TSK_OBJECT_SAFE_FREE ( transport ) ;
return - 5 ;
}
SSL_CTX_set_read_ahead ( transport - > dtls . ctx , 1 ) ;
SSL_CTX_set_verify ( transport - > dtls . ctx , SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT , tsk_null ) ; // to be updated by tnet_transport_tls_set_certs()
if ( SSL_CTX_set_cipher_list ( transport - > dtls . ctx , TNET_CIPHER_LIST ) < = 0 ) {
TSK_DEBUG_ERROR ( " SSL_CTX_set_cipher_list failed [%s] " , ERR_error_string ( ERR_get_error ( ) , tsk_null ) ) ;
return - 6 ;
}
//!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP
// Up to the DTLS socket to set the default MTU value
SSL_CTX_set_options ( transport - > dtls . ctx , SSL_OP_NO_QUERY_MTU ) ;
SSL_CTX_ctrl ( transport - > dtls . ctx , SSL_CTRL_SET_MTU , TNET_DTLS_MTU - 28 , NULL ) ;
transport - > dtls . activated = tsk_true ;
}
2013-01-07 15:37:02 +00:00
# endif /* HAVE_OPENSSL_DTLS */
2015-06-20 17:58:34 +00:00
}
2013-01-07 15:37:02 +00:00
# endif /* HAVE_OPENSSL */
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return 0 ;
2013-01-07 15:37:02 +00:00
}
static int _tnet_transport_ssl_deinit ( tnet_transport_t * transport )
{
2016-02-23 21:00:35 +00:00
if ( ! transport ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2013-01-07 15:37:02 +00:00
# if HAVE_OPENSSL
2016-02-23 21:00:35 +00:00
if ( transport - > tls . ctx_client ) {
2015-06-20 17:58:34 +00:00
SSL_CTX_free ( transport - > tls . ctx_client ) ;
transport - > tls . ctx_client = tsk_null ;
}
2016-02-23 21:00:35 +00:00
if ( transport - > tls . ctx_server ) {
2015-06-20 17:58:34 +00:00
SSL_CTX_free ( transport - > tls . ctx_server ) ;
transport - > tls . ctx_server = tsk_null ;
}
2016-02-23 21:00:35 +00:00
if ( transport - > dtls . ctx ) {
2015-06-20 17:58:34 +00:00
SSL_CTX_free ( transport - > dtls . ctx ) ;
transport - > dtls . ctx = tsk_null ;
}
2013-01-07 15:37:02 +00:00
# endif /* HAVE_OPENSSL */
2015-06-20 17:58:34 +00:00
return 0 ;
2013-01-07 15:37:02 +00:00
}
2011-03-25 09:38:07 +00:00
tnet_transport_t * tnet_transport_create ( const char * host , tnet_port_t port , tnet_socket_type_t type , const char * description )
2014-12-19 17:09:09 +00:00
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport ;
2016-02-23 21:00:35 +00:00
if ( ( transport = tsk_object_new ( tnet_transport_def_t ) ) ) {
2015-06-20 17:58:34 +00:00
transport - > description = tsk_strdup ( description ) ;
transport - > local_host = tsk_strdup ( host ) ;
transport - > req_local_port = port ;
transport - > type = type ;
transport - > context = tnet_transport_context_create ( ) ;
2016-02-23 21:00:35 +00:00
if ( ( transport - > master = tnet_socket_create ( transport - > local_host , transport - > req_local_port , transport - > type ) ) ) {
2015-06-20 17:58:34 +00:00
transport - > local_ip = tsk_strdup ( transport - > master - > ip ) ;
transport - > bind_local_port = transport - > master - > port ;
2016-05-23 22:11:39 +00:00
transport - > type = transport - > master - > type ;
2015-06-20 17:58:34 +00:00
}
2016-02-23 21:00:35 +00:00
else {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Failed to create master socket " ) ;
TSK_OBJECT_SAFE_FREE ( transport ) ;
}
2016-02-23 21:00:35 +00:00
if ( _tnet_transport_ssl_init ( transport ) ! = 0 ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Failed to initialize TLS and/or DTLS caps " ) ;
TSK_OBJECT_SAFE_FREE ( transport ) ;
}
// set priority
tsk_runnable_set_priority ( TSK_RUNNABLE ( transport ) , TSK_THREAD_PRIORITY_TIME_CRITICAL ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return transport ;
2012-05-02 10:42:55 +00:00
}
tnet_transport_t * tnet_transport_create_2 ( tnet_socket_t * master , const char * description )
2011-03-25 09:38:07 +00:00
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport ;
2016-02-23 21:00:35 +00:00
if ( ! master ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return tsk_null ;
}
2016-02-23 21:00:35 +00:00
if ( ( transport = tsk_object_new ( tnet_transport_def_t ) ) ) {
2015-06-20 17:58:34 +00:00
transport - > description = tsk_strdup ( description ) ;
transport - > local_host = tsk_strdup ( master - > ip ) ;
transport - > req_local_port = master - > port ;
transport - > type = master - > type ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
transport - > master = tsk_object_ref ( master ) ;
transport - > local_ip = tsk_strdup ( transport - > master - > ip ) ;
transport - > bind_local_port = transport - > master - > port ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
transport - > context = tnet_transport_context_create ( ) ;
2016-02-23 21:00:35 +00:00
if ( _tnet_transport_ssl_init ( transport ) ! = 0 ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Failed to initialize TLS and/or DTLS caps " ) ;
TSK_OBJECT_SAFE_FREE ( transport ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
// set priority
tsk_runnable_set_priority ( TSK_RUNNABLE ( transport ) , TSK_THREAD_PRIORITY_TIME_CRITICAL ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return transport ;
2011-03-25 09:38:07 +00:00
}
tnet_transport_event_t * tnet_transport_event_create ( tnet_transport_event_type_t type , const void * callback_data , tnet_fd_t fd )
{
2015-06-20 17:58:34 +00:00
return tsk_object_new ( tnet_transport_event_def_t , type , callback_data , fd ) ;
2011-03-25 09:38:07 +00:00
}
2013-01-07 15:37:02 +00:00
int tnet_transport_tls_set_certs ( tnet_transport_handle_t * handle , const char * ca , const char * pbk , const char * pvk , tsk_bool_t verify )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
static const char * ssl_password = tsk_null ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport ) {
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
tsk_strupdate ( & transport - > tls . ca , ca ) ;
tsk_strupdate ( & transport - > tls . pvk , pvk ) ;
tsk_strupdate ( & transport - > tls . pbk , pbk ) ;
transport - > tls . verify = verify ;
2016-02-23 21:00:35 +00:00
2013-01-07 15:37:02 +00:00
# if HAVE_OPENSSL
2015-06-20 17:58:34 +00:00
{
int32_t i , ret ;
SSL_CTX * contexts [ 3 ] = { tsk_null } ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
/* init DTLS/TLS contexts */
2016-02-23 21:00:35 +00:00
if ( ( ret = _tnet_transport_ssl_init ( transport ) ) ) {
2015-06-20 17:58:34 +00:00
return ret ;
}
2016-02-23 21:00:35 +00:00
if ( transport - > tls . enabled ) {
2015-06-20 17:58:34 +00:00
contexts [ 0 ] = transport - > tls . ctx_client ;
contexts [ 1 ] = transport - > tls . ctx_server ;
}
2016-02-23 21:00:35 +00:00
if ( transport - > dtls . enabled ) {
2015-06-20 17:58:34 +00:00
contexts [ 2 ] = transport - > dtls . ctx ;
/* Reset fingerprints */
memset ( transport - > dtls . fingerprints , 0 , sizeof ( transport - > dtls . fingerprints ) ) ;
}
2016-02-23 21:00:35 +00:00
for ( i = 0 ; i < sizeof ( contexts ) / sizeof ( contexts [ 0 ] ) ; + + i ) {
if ( ! contexts [ i ] ) {
2015-06-20 17:58:34 +00:00
continue ;
}
SSL_CTX_set_verify ( contexts [ i ] , transport - > tls . verify ? ( SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT ) : SSL_VERIFY_NONE , tsk_null ) ;
2016-02-23 21:00:35 +00:00
if ( ! tsk_strnullORempty ( transport - > tls . pbk ) | | ! tsk_strnullORempty ( transport - > tls . pvk ) | | ! tsk_strnullORempty ( transport - > tls . ca ) ) {
2015-06-20 17:58:34 +00:00
/* Sets Public key (cert) */
if ( ! tsk_strnullORempty ( transport - > tls . pbk ) & & ( ret = SSL_CTX_use_certificate_file ( contexts [ i ] , transport - > tls . pbk , SSL_FILETYPE_PEM ) ) ! = 1 ) {
TSK_DEBUG_ERROR ( " SSL_CTX_use_certificate_file failed [%d,%s] " , ret , ERR_error_string ( ERR_get_error ( ) , tsk_null ) ) ;
return - 3 ;
}
/*Sets the password of the private key*/
2016-02-23 21:00:35 +00:00
if ( ! tsk_strnullORempty ( ssl_password ) ) {
2015-06-20 17:58:34 +00:00
SSL_CTX_set_default_passwd_cb_userdata ( contexts [ i ] , ( void * ) ssl_password ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
/* Sets Private key (cert) */
if ( ! tsk_strnullORempty ( transport - > tls . pvk ) & & ( ret = SSL_CTX_use_PrivateKey_file ( contexts [ i ] , transport - > tls . pvk , SSL_FILETYPE_PEM ) ) ! = 1 ) {
TSK_DEBUG_ERROR ( " SSL_CTX_use_PrivateKey_file failed [%d,%s] " , ret , ERR_error_string ( ERR_get_error ( ) , tsk_null ) ) ;
return - 4 ;
}
/* Checks private key */
if ( ! tsk_strnullORempty ( transport - > tls . pvk ) & & SSL_CTX_check_private_key ( contexts [ i ] ) = = 0 ) {
TSK_DEBUG_ERROR ( " SSL_CTX_check_private_key failed [%d,%s] " , ret , ERR_error_string ( ERR_get_error ( ) , tsk_null ) ) ;
return - 5 ;
}
/* Sets trusted CAs and CA file */
if ( ! tsk_strnullORempty ( transport - > tls . ca ) & & ( ret = SSL_CTX_load_verify_locations ( contexts [ i ] , transport - > tls . ca , /*tlsdir_cas*/ tsk_null ) ) ! = 1 ) {
TSK_DEBUG_ERROR ( " SSL_CTX_load_verify_locations failed [%d, %s] " , ret , ERR_error_string ( ERR_get_error ( ) , tsk_null ) ) ;
return - 5 ;
}
}
}
}
2013-01-07 15:37:02 +00:00
# endif /* HAVE_OPENSSL */
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return 0 ;
2013-01-07 15:37:02 +00:00
}
2011-03-25 09:38:07 +00:00
int tnet_transport_start ( tnet_transport_handle_t * handle )
{
2015-06-20 17:58:34 +00:00
int ret = - 1 ;
2016-02-23 21:00:35 +00:00
if ( handle ) {
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
/* prepare transport */
2016-02-23 21:00:35 +00:00
if ( ( ret = tnet_transport_prepare ( transport ) ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Failed to prepare transport. " ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
/* start transport */
TSK_RUNNABLE ( transport ) - > run = run ;
2016-02-23 21:00:35 +00:00
if ( ( ret = tsk_runnable_start ( TSK_RUNNABLE ( transport ) , tnet_transport_event_def_t ) ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Failed to start transport. " ) ;
goto bail ;
}
}
2016-02-23 21:00:35 +00:00
else {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " NULL transport object. " ) ;
}
2016-02-23 21:00:35 +00:00
2011-03-25 09:38:07 +00:00
bail :
2015-06-20 17:58:34 +00:00
return ret ;
2011-03-25 09:38:07 +00:00
}
int tnet_transport_issecure ( const tnet_transport_handle_t * handle )
{
2016-02-23 21:00:35 +00:00
if ( handle ) {
2015-06-20 17:58:34 +00:00
const tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
if ( transport - > master ) {
2015-06-20 17:58:34 +00:00
return TNET_SOCKET_TYPE_IS_SECURE ( transport - > master - > type ) ;
}
}
2016-02-23 21:00:35 +00:00
else {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " NULL transport object. " ) ;
}
return 0 ;
2011-03-25 09:38:07 +00:00
}
const char * tnet_transport_get_description ( const tnet_transport_handle_t * handle )
{
2016-02-23 21:00:35 +00:00
if ( handle ) {
2015-06-20 17:58:34 +00:00
const tnet_transport_t * transport = handle ;
return transport - > description ;
}
2016-02-23 21:00:35 +00:00
else {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " NULL transport object. " ) ;
return tsk_null ;
}
2011-03-25 09:38:07 +00:00
}
int tnet_transport_get_ip_n_port ( const tnet_transport_handle_t * handle , tnet_fd_t fd , tnet_ip_t * ip , tnet_port_t * port )
{
2016-02-23 21:00:35 +00:00
if ( handle ) {
2015-06-20 17:58:34 +00:00
return tnet_get_ip_n_port ( fd , tsk_true /*local*/ , ip , port ) ;
}
2016-02-23 21:00:35 +00:00
else {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " NULL transport object. " ) ;
}
return - 1 ;
2011-03-25 09:38:07 +00:00
}
int tnet_transport_get_ip_n_port_2 ( const tnet_transport_handle_t * handle , tnet_ip_t * ip , tnet_port_t * port )
{
2015-06-20 17:58:34 +00:00
const tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
if ( transport ) {
2015-06-20 17:58:34 +00:00
// do not check the master, let the application die if "null"
2016-02-23 21:00:35 +00:00
if ( ip ) {
2015-06-20 17:58:34 +00:00
memcpy ( * ip , transport - > master - > ip , sizeof ( transport - > master - > ip ) ) ;
}
2016-02-23 21:00:35 +00:00
if ( port ) {
2015-06-20 17:58:34 +00:00
* port = transport - > master - > port ;
}
return 0 ;
}
2016-02-23 21:00:35 +00:00
else {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " NULL transport object. " ) ;
return - 1 ;
}
2011-03-25 09:38:07 +00:00
}
2014-05-11 22:25:35 +00:00
int tnet_transport_set_natt_ctx ( tnet_transport_handle_t * handle , struct tnet_nat_ctx_s * natt_ctx )
2011-03-25 09:38:07 +00:00
{
2015-06-20 17:58:34 +00:00
if ( ! handle ) {
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
TSK_OBJECT_SAFE_FREE ( ( ( tnet_transport_t * ) handle ) - > natt_ctx ) ;
( ( tnet_transport_t * ) handle ) - > natt_ctx = tsk_object_ref ( natt_ctx ) ;
return 0 ;
2011-03-25 09:38:07 +00:00
}
int tnet_transport_get_public_ip_n_port ( const tnet_transport_handle_t * handle , tnet_fd_t fd , tnet_ip_t * ip , tnet_port_t * port )
{
2015-06-20 17:58:34 +00:00
tsk_bool_t stun_ok = tsk_false ;
struct tnet_nat_ctx_s * natt_ctx ;
const tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
if ( ! transport ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( TNET_SOCKET_TYPE_IS_DGRAM ( transport - > type ) & & ( natt_ctx = tsk_object_ref ( transport - > natt_ctx ) ) ) {
tnet_stun_binding_id_t bind_id = kStunBindingInvalidId ;
// if the socket is already monitored by the transport we should pause because both the transport and
// NAT binder will try to read from it
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
// Pause the soket
tnet_transport_pause_socket ( transport , fd , tsk_true ) ;
// Performs STUN binding
bind_id = tnet_nat_stun_bind ( transport - > natt_ctx , fd ) ;
// Resume the socket
tnet_transport_pause_socket ( transport , fd , tsk_false ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( bind_id ! = kStunBindingInvalidId ) {
char * public_ip = tsk_null ;
2016-02-23 21:00:35 +00:00
if ( tnet_nat_stun_get_reflexive_address ( transport - > natt_ctx , bind_id , & public_ip , port ) = = 0 ) {
if ( ip & & public_ip ) {
2015-06-20 17:58:34 +00:00
tsk_size_t ip_len = tsk_strlen ( public_ip ) ;
memcpy ( ip , public_ip , ip_len > sizeof ( * ip ) ? sizeof ( * ip ) : ip_len ) ;
}
stun_ok = tsk_true ;
}
TSK_FREE ( public_ip ) ;
tnet_nat_stun_unbind ( transport - > natt_ctx , bind_id ) ;
}
tsk_object_unref ( natt_ctx ) ;
}
2016-02-23 21:00:35 +00:00
if ( ! stun_ok ) {
if ( fd = = TNET_INVALID_FD & & transport - > local_ip ) {
2015-06-20 17:58:34 +00:00
memcpy ( * ip , transport - > local_ip , TSK_MIN ( sizeof ( tnet_ip_t ) , tsk_strlen ( transport - > local_ip ) ) ) ;
* port = transport - > bind_local_port ;
return 0 ;
}
2016-02-23 21:00:35 +00:00
else {
2015-06-20 17:58:34 +00:00
return tnet_transport_get_ip_n_port ( handle , fd , ip , port ) ;
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return 0 ;
2011-03-25 09:38:07 +00:00
}
2013-01-07 15:37:02 +00:00
const char * tnet_transport_dtls_get_local_fingerprint ( const tnet_transport_handle_t * handle , tnet_dtls_hash_type_t hash )
2011-03-25 09:38:07 +00:00
{
2015-06-20 17:58:34 +00:00
const tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
if ( ! transport ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return tsk_null ;
}
2016-02-23 21:00:35 +00:00
if ( ! transport - > dtls . enabled ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " DTLS not enabled on this transport " ) ;
return tsk_null ;
}
2016-02-23 21:00:35 +00:00
if ( hash > sizeof ( transport - > dtls . fingerprints ) / sizeof ( transport - > dtls . fingerprints [ 0 ] ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " %d not valid for fingerprint hash " , hash ) ;
return tsk_null ;
}
2016-02-23 21:00:35 +00:00
if ( tsk_strnullORempty ( transport - > tls . pbk ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " No certificate for which to get fingerprint " ) ;
return tsk_null ;
}
2016-02-23 21:00:35 +00:00
if ( tnet_dtls_get_fingerprint ( transport - > tls . pbk , & ( ( tnet_transport_t * ) transport ) - > dtls . fingerprints [ hash ] , hash ) = = 0 ) {
2015-06-20 17:58:34 +00:00
return ( const char * ) transport - > dtls . fingerprints [ hash ] ;
}
return tsk_null ;
2011-03-25 09:38:07 +00:00
}
2013-01-07 15:37:02 +00:00
/*
2015-06-20 17:58:34 +00:00
rfc5764 : 4.1 . The use_srtp Extension
*/
2013-01-07 15:37:02 +00:00
int tnet_transport_dtls_use_srtp ( tnet_transport_handle_t * handle , const char * srtp_profiles , struct tnet_socket_s * * sockets , tsk_size_t sockets_count )
2011-03-25 09:38:07 +00:00
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
if ( ! transport | | ! srtp_profiles ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
if ( ! transport - > dtls . enabled ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " DTLS not enabled on this transport " ) ;
return - 2 ;
}
2013-01-07 15:37:02 +00:00
# if HAVE_OPENSSL_DTLS_SRTP
2015-06-20 17:58:34 +00:00
{
tsk_size_t i ;
transport - > dtls . use_srtp = tsk_true ;
SSL_CTX_set_tlsext_use_srtp ( transport - > dtls . ctx , srtp_profiles ) ;
2016-02-23 21:00:35 +00:00
if ( sockets ) {
for ( i = 0 ; i < sockets_count ; + + i ) {
if ( sockets [ i ] & & sockets [ i ] - > dtlshandle ) {
2015-06-20 17:58:34 +00:00
tnet_dtls_socket_use_srtp ( sockets [ i ] - > dtlshandle ) ;
}
}
}
return 0 ;
}
2013-01-07 15:37:02 +00:00
# else
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Your OpenSSL version do not support DTLS-SRTP " ) ;
return - 2 ;
2013-01-07 15:37:02 +00:00
# endif
}
int tnet_transport_dtls_set_remote_fingerprint ( tnet_transport_handle_t * handle , const tnet_fingerprint_t * fingerprint , tnet_dtls_hash_type_t hash , struct tnet_socket_s * * sockets , tsk_size_t sockets_count )
{
2015-06-20 17:58:34 +00:00
const tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
if ( ! transport | | ! fingerprint ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
if ( ! transport - > dtls . enabled ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " DTLS not enabled on this transport " ) ;
return - 2 ;
}
2013-01-07 15:37:02 +00:00
# if HAVE_OPENSSL_DTLS
2016-02-23 21:00:35 +00:00
if ( sockets ) {
2015-06-20 17:58:34 +00:00
tsk_size_t i ;
2016-02-23 21:00:35 +00:00
for ( i = 0 ; i < sockets_count ; + + i ) {
if ( sockets [ i ] & & sockets [ i ] - > dtlshandle ) {
2015-06-20 17:58:34 +00:00
tnet_dtls_socket_set_remote_fingerprint ( sockets [ i ] - > dtlshandle , fingerprint , hash ) ;
}
}
}
return 0 ;
2013-01-07 15:37:02 +00:00
# else
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Your OpenSSL version do not support DTLS " ) ;
return - 2 ;
2013-01-07 15:37:02 +00:00
# endif
}
tsk_bool_t tnet_transport_dtls_is_enabled ( const tnet_transport_handle_t * handle )
{
2015-06-20 17:58:34 +00:00
const tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
if ( ! transport ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
return transport - > dtls . enabled ;
2013-01-07 15:37:02 +00:00
}
/*
2015-06-20 17:58:34 +00:00
Enable or disable DTLS on the transport and all coresponding sockets
* @ param handle The transport for which to enable or disable DTLS
* @ param enabled Whether to enable or disable DTLS
* @ param sockets List of all sockets for which to enable or disable DLS could be null . You should include the master socket in this list .
* @ param sockets_count The number of sockets
* @ return 0 if succeed , otherwise non - zero error code
*/
2013-01-07 15:37:02 +00:00
int tnet_transport_dtls_set_enabled ( tnet_transport_handle_t * handle , tsk_bool_t enabled , struct tnet_socket_s * * sockets , tsk_size_t sockets_count )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
tnet_socket_type_t type ;
int ret ;
2016-02-23 21:00:35 +00:00
if ( ! transport ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
type = tnet_transport_get_type ( transport ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( enabled & ! tnet_dtls_is_supported ( ) ) {
TSK_DEBUG_ERROR ( " Trying to enable DTLS but code source not built with this feature " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ( transport - > dtls . enabled = enabled ) ) {
if ( ( ret = _tnet_transport_ssl_init ( transport ) ) ) {
return ret ;
}
}
else {
ret = _tnet_transport_ssl_deinit ( transport ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( sockets & & sockets_count ) {
tsk_size_t i ;
for ( i = 0 ; i < sockets_count ; + + i ) {
if ( ! sockets [ i ] ) {
continue ;
}
if ( enabled ) {
if ( ! sockets [ i ] - > dtlshandle ) {
if ( ! ( sockets [ i ] - > dtlshandle = tnet_dtls_socket_create ( sockets [ i ] , transport - > dtls . ctx ) ) ) {
return - 4 ;
}
}
if ( transport - > dtls . use_srtp ) {
tnet_dtls_socket_use_srtp ( sockets [ i ] - > dtlshandle ) ;
}
tnet_dtls_socket_set_callback ( sockets [ i ] - > dtlshandle , transport , _tnet_transport_dtls_cb ) ;
}
else {
TSK_OBJECT_SAFE_FREE ( sockets [ i ] - > dtlshandle ) ;
}
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return ret ;
2013-01-07 15:37:02 +00:00
}
int tnet_transport_dtls_set_setup ( tnet_transport_handle_t * handle , tnet_dtls_setup_t setup , struct tnet_socket_s * * sockets , tsk_size_t sockets_count )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport ) {
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport - > dtls . enabled ) {
TSK_DEBUG_ERROR ( " DTLS not enabled on this transport " ) ;
return - 2 ;
}
if ( sockets & & sockets_count ) {
tsk_size_t i ;
for ( i = 0 ; i < sockets_count ; + + i ) {
if ( ! sockets [ i ] | | ! sockets [ i ] - > dtlshandle ) {
continue ;
}
tnet_dtls_socket_set_setup ( sockets [ i ] - > dtlshandle , setup ) ;
}
}
return 0 ;
2013-01-07 15:37:02 +00:00
}
2014-05-11 22:25:35 +00:00
int tnet_transport_dtls_set_store_handshakingdata ( tnet_transport_handle_t * handle , tsk_bool_t handshake_storedata , struct tnet_socket_s * * sockets , tsk_size_t sockets_count )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport ) {
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport - > dtls . enabled ) {
TSK_DEBUG_ERROR ( " DTLS not enabled on this transport " ) ;
return - 2 ;
}
if ( sockets & & sockets_count ) {
tsk_size_t i ;
for ( i = 0 ; i < sockets_count ; + + i ) {
if ( ! sockets [ i ] | | ! sockets [ i ] - > dtlshandle ) {
continue ;
}
tnet_dtls_socket_set_store_handshakingdata ( sockets [ i ] - > dtlshandle , handshake_storedata ) ;
}
}
return 0 ;
2014-05-11 22:25:35 +00:00
}
2013-01-07 15:37:02 +00:00
int tnet_transport_dtls_do_handshake ( tnet_transport_handle_t * handle , struct tnet_socket_s * * sockets , tsk_size_t sockets_count , const struct sockaddr_storage * * remote_addrs , tsk_size_t remote_addrs_count )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
tsk_size_t i ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport | | ! sockets ) {
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport - > dtls . enabled ) {
TSK_DEBUG_ERROR ( " DTLS not enabled on this transport " ) ;
return - 2 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( sockets ) {
int ret ;
for ( i = 0 ; i < sockets_count ; + + i ) {
if ( sockets [ i ] & & sockets [ i ] - > dtlshandle ) {
if ( ( ret = tnet_dtls_socket_do_handshake ( sockets [ i ] - > dtlshandle ,
2016-02-23 21:00:35 +00:00
( remote_addrs & & i < remote_addrs_count ) ? remote_addrs [ i ] : tsk_null ) ) ! = 0 ) {
2015-06-20 17:58:34 +00:00
return ret ;
}
}
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return 0 ;
2013-01-07 15:37:02 +00:00
}
2014-05-11 22:25:35 +00:00
int tnet_transport_dtls_get_handshakingdata ( tnet_transport_handle_t * handle , const struct tnet_socket_s * * sockets , tsk_size_t sockets_count , const void * data [ ] , tsk_size_t size [ ] )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = handle ;
tsk_size_t i ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport | | ! sockets ) {
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport - > dtls . enabled ) {
TSK_DEBUG_ERROR ( " DTLS not enabled on this transport " ) ;
return - 2 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( sockets ) {
int ret ;
for ( i = 0 ; i < sockets_count ; + + i ) {
if ( sockets [ i ] & & sockets [ i ] - > dtlshandle ) {
2016-02-23 21:00:35 +00:00
if ( ( ret = tnet_dtls_socket_get_handshakingdata ( sockets [ i ] - > dtlshandle , & data [ i ] , & size [ i ] ) ) ! = 0 ) {
2015-06-20 17:58:34 +00:00
return ret ;
}
}
else {
data [ i ] = tsk_null ;
size [ i ] = 0 ;
}
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return 0 ;
2014-05-11 22:25:35 +00:00
}
2013-01-07 15:37:02 +00:00
tnet_socket_type_t tnet_transport_get_type ( const tnet_transport_handle_t * handle )
{
2016-02-23 21:00:35 +00:00
if ( ! handle ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return tnet_socket_type_invalid ;
}
return ( ( const tnet_transport_t * ) handle ) - > type ;
2013-01-07 15:37:02 +00:00
}
tnet_fd_t tnet_transport_get_master_fd ( const tnet_transport_handle_t * handle )
{
2016-02-23 21:00:35 +00:00
if ( ! handle ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return TNET_INVALID_FD ;
}
return ( ( const tnet_transport_t * ) handle ) - > master ? ( ( const tnet_transport_t * ) handle ) - > master - > fd : TNET_INVALID_FD ;
2011-03-25 09:38:07 +00:00
}
2015-08-12 20:36:14 +00:00
int tnet_transport_get_bytes_count ( const tnet_transport_handle_t * handle , uint64_t * bytes_in , uint64_t * bytes_out )
{
2016-02-23 21:00:35 +00:00
if ( ! handle ) {
2015-08-12 20:36:14 +00:00
TSK_DEBUG_ERROR ( " Invalid parameter " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
if ( bytes_in ) {
* bytes_in = ( ( const tnet_transport_t * ) handle ) - > bytes_in ;
}
if ( bytes_out ) {
* bytes_out = ( ( const tnet_transport_t * ) handle ) - > bytes_out ;
}
2015-08-12 20:36:14 +00:00
return 0 ;
}
2011-03-25 09:38:07 +00:00
/**
2015-06-20 17:58:34 +00:00
* Connects a socket .
* @ param handle The transport to use to connect ( ) the socket . The new socket will be managed by this transport .
* @ param host The remote @ a host to connect ( ) to .
* @ param port The remote @ a port to connect ( ) to .
* @ param type The type of the socket to use to connect ( ) to the remote @ a host .
* @ retval The newly connected socket . For non - blocking sockets you should use @ ref tnet_sockfd_waitUntilWritable to check
* the socket for writability .
* @ sa tnet_sockfd_waitUntilWritable .
*/
2011-03-25 09:38:07 +00:00
tnet_fd_t tnet_transport_connectto ( const tnet_transport_handle_t * handle , const char * host , tnet_port_t port , tnet_socket_type_t type )
2014-10-27 00:41:22 +00:00
{
2015-06-20 17:58:34 +00:00
return tnet_transport_connectto_3 ( handle , tsk_null /*socket*/ , host , port , type ) ;
2014-10-27 00:41:22 +00:00
}
tnet_fd_t tnet_transport_connectto_3 ( const tnet_transport_handle_t * handle , struct tnet_socket_s * socket , const char * host , tnet_port_t port , tnet_socket_type_t type )
2011-03-25 09:38:07 +00:00
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = ( tnet_transport_t * ) handle ;
struct sockaddr_storage to ;
int status = - 1 ;
tnet_fd_t fd = socket ? socket - > fd : TNET_INVALID_FD ;
tnet_tls_socket_handle_t * tls_handle = tsk_null ;
tsk_bool_t owe_socket = socket ? tsk_false : tsk_true ;
tsk_bool_t use_proxy = TNET_SOCKET_TYPE_IS_STREAM ( type ) ;
const char * to_host = host ;
tnet_port_t to_port = port ;
tnet_socket_type_t to_type = type ;
tnet_proxyinfo_t * proxy_info = tsk_null ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport | | ! transport - > master ) {
TSK_DEBUG_ERROR ( " Invalid transport handle " ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ( TNET_SOCKET_TYPE_IS_STREAM ( transport - > master - > type ) & & ! TNET_SOCKET_TYPE_IS_STREAM ( type ) ) | |
2016-02-23 21:00:35 +00:00
( TNET_SOCKET_TYPE_IS_DGRAM ( transport - > master - > type ) & & ! TNET_SOCKET_TYPE_IS_DGRAM ( type ) ) ) {
2015-06-20 17:58:34 +00:00
TSK_DEBUG_ERROR ( " Master/destination types mismatch [%u/%u] " , transport - > master - > type , type ) ;
goto bail ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( use_proxy ) {
// auto-detect the proxy
if ( transport - > proxy . auto_detect ) {
char * url = tsk_null ;
// The proxy detection implementations are designed for a browser and expect a "http://" or "https://" schemes (will work with socks).
tsk_sprintf ( & url , " %s://%s:%d " , TNET_SOCKET_TYPE_IS_TLS ( to_type ) ? " https " : " http " , to_host , to_port ) ;
proxy_info = tnet_proxydetect_get_info_fast ( url , to_type ) ;
TSK_FREE ( url ) ;
}
// fall-back to the hard proxy if auto-detection failed
if ( ! tnet_proxyinfo_is_valid ( proxy_info ) & & tnet_proxyinfo_is_valid ( transport - > proxy . info ) ) {
proxy_info = tsk_object_ref ( transport - > proxy . info ) ;
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
use_proxy & = tnet_proxyinfo_is_valid ( proxy_info ) ;
if ( use_proxy ) {
if ( tnet_proxy_node_is_nettransport_supported ( proxy_info - > type , type ) ) {
to_host = proxy_info - > hostname ;
to_port = proxy_info - > port ;
// SOCKS still doesn't define RFC for SSL security (https://tools.ietf.org/html/draft-ietf-aft-socks-ssl-00) but Kerberos6 authentication is supported
if ( proxy_info - > type = = tnet_proxy_type_http | | proxy_info - > type = = tnet_proxy_type_socks4 | | proxy_info - > type = = tnet_proxy_type_socks4a | | proxy_info - > type = = tnet_proxy_type_socks5 ) {
// Send CONNET to the proxy using unsecure connection then begin SSL handshaking if needed
TNET_SOCKET_TYPE_UNSET ( to_type , TLS ) ; // Make the type unsecure (will keep other flags-e.g. IP version-)
TNET_SOCKET_TYPE_SET ( to_type , TCP ) ; // Use plain TCP
}
}
else {
// Not an error.
TSK_DEBUG_INFO ( " No proxy plugin to handle network transport type = %d " , type ) ;
use_proxy = tsk_false ;
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
TSK_DEBUG_INFO ( " tnet_transport_connectto_3(host=%s, port=%d, type=%d, fd=%d, use_proxy=%d, to_host=%s, to_port=%d, to_type=%d, proxy_type=%d) " , host , port , type , fd , use_proxy , to_host , to_port , to_type , proxy_info ? proxy_info - > type : 0 ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
/* Init destination sockaddr fields */
if ( ( status = tnet_sockaddr_init ( to_host , to_port , to_type , & to ) ) ) {
TSK_DEBUG_ERROR ( " Invalid HOST/PORT [%s/%u] " , host , port ) ;
goto bail ;
}
if ( TNET_SOCKET_TYPE_IS_IPV46 ( type ) ) {
/* Update the type (unambiguously) */
if ( to . ss_family = = AF_INET6 ) {
TNET_SOCKET_TYPE_SET_IPV6Only ( type ) ;
}
else {
TNET_SOCKET_TYPE_SET_IPV4Only ( type ) ;
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
/*
* STREAM = = > create new socket and connect it to the remote host .
* DGRAM = = > connect the master to the remote host .
*/
if ( fd = = TNET_INVALID_FD ) {
// Create client socket descriptor.
if ( ( status = tnet_sockfd_init ( transport - > local_host , TNET_SOCKET_PORT_ANY , to_type , & fd ) ) ) {
TSK_DEBUG_ERROR ( " Failed to create new sockfd. " ) ;
goto bail ;
}
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ( status = tnet_sockfd_connectto ( fd , ( const struct sockaddr_storage * ) & to ) ) ) {
if ( fd ! = transport - > master - > fd ) {
tnet_sockfd_close ( & fd ) ;
}
goto bail ;
}
else {
static const tsk_bool_t __isClient = tsk_true ;
if ( TNET_SOCKET_TYPE_IS_TLS ( to_type ) | | TNET_SOCKET_TYPE_IS_WSS ( to_type ) ) {
2013-03-11 08:37:03 +00:00
# if HAVE_OPENSSL
2015-06-20 17:58:34 +00:00
tls_handle = tnet_tls_socket_create ( fd , transport - > tls . ctx_client ) ;
if ( socket ) {
TSK_OBJECT_SAFE_FREE ( socket - > tlshandle ) ;
socket - > tlshandle = tsk_object_ref ( tls_handle ) ;
}
if ( ( status = tnet_tls_socket_connect ( tls_handle ) ) ) {
tnet_sockfd_close ( & fd ) ;
goto bail ;
}
2013-03-11 08:37:03 +00:00
# endif
2015-06-20 17:58:34 +00:00
}
/* Add the socket */
// socket must be added after connect() otherwise many Linux systems will return POLLHUP as the fd is not active yet
if ( ( status = tnet_transport_add_socket_2 ( handle , fd , to_type , owe_socket , __isClient , tls_handle , host , port , proxy_info ) ) ) {
TNET_PRINT_LAST_ERROR ( " Failed to add new socket " ) ;
tnet_sockfd_close ( & fd ) ;
goto bail ;
}
}
2016-02-23 21:00:35 +00:00
2011-03-25 09:38:07 +00:00
bail :
2015-06-20 17:58:34 +00:00
TSK_OBJECT_SAFE_FREE ( tls_handle ) ;
TSK_OBJECT_SAFE_FREE ( proxy_info ) ;
return status = = 0 ? fd : TNET_INVALID_FD ;
2011-03-25 09:38:07 +00:00
}
int tnet_transport_set_callback ( const tnet_transport_handle_t * handle , tnet_transport_cb_f callback , const void * callback_data )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = ( tnet_transport_t * ) handle ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( ! transport ) {
TSK_DEBUG_ERROR ( " Invalid server handle. " ) ;
return - 1 ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
transport - > callback = callback ;
transport - > callback_data = callback_data ;
return 0 ;
}
2014-12-19 17:09:09 +00:00
2015-06-20 17:58:34 +00:00
int tnet_transport_set_proxy_auto_detect ( tnet_transport_handle_t * handle , tsk_bool_t auto_detect )
{
tnet_transport_t * transport = ( tnet_transport_t * ) handle ;
if ( ! transport ) {
TSK_DEBUG_ERROR ( " Invalid server handle. " ) ;
return - 1 ;
}
transport - > proxy . auto_detect = auto_detect ;
return 0 ;
}
2011-03-25 09:38:07 +00:00
2015-06-20 17:58:34 +00:00
int tnet_transport_set_proxy_info ( tnet_transport_handle_t * handle , enum tnet_proxy_type_e type , const char * host , tnet_port_t port , const char * login , const char * password )
{
tnet_transport_t * transport = ( tnet_transport_t * ) handle ;
tnet_proxyinfo_t * proxy_info ;
if ( ! transport ) {
TSK_DEBUG_ERROR ( " Invalid server handle. " ) ;
return - 1 ;
}
if ( ( proxy_info = tnet_proxyinfo_create ( ) ) ) {
proxy_info - > type = type ;
proxy_info - > hostname = tsk_strdup ( host ) ;
proxy_info - > port = port ;
proxy_info - > username = tsk_strdup ( login ) ;
proxy_info - > password = tsk_strdup ( password ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
TSK_OBJECT_SAFE_FREE ( transport - > proxy . info ) ;
transport - > proxy . info = proxy_info ;
return 0 ;
}
else {
return - 1 ;
}
2011-03-25 09:38:07 +00:00
}
int tnet_transport_shutdown ( tnet_transport_handle_t * handle )
{
2015-06-20 17:58:34 +00:00
if ( handle ) {
int ret ;
2016-02-23 21:00:35 +00:00
if ( ( ret = tnet_transport_stop ( handle ) ) = = 0 ) {
2015-06-20 17:58:34 +00:00
ret = tnet_transport_unprepare ( handle ) ;
}
return ret ;
}
else {
TSK_DEBUG_ERROR ( " NULL transport object. " ) ;
return - 1 ;
}
2011-03-25 09:38:07 +00:00
}
2013-01-07 15:37:02 +00:00
static int _tnet_transport_dtls_cb ( const void * usrdata , tnet_dtls_socket_event_type_t dtls_e , const tnet_dtls_socket_handle_t * handle , const void * data , tsk_size_t size )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = ( tnet_transport_t * ) usrdata ;
if ( transport ) {
tnet_transport_event_type_t t_e ;
const struct sockaddr_storage * remote_addr ;
tnet_fd_t fd ;
tnet_transport_event_t * e ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
switch ( dtls_e ) {
2016-02-23 21:00:35 +00:00
case tnet_dtls_socket_event_type_handshake_started :
t_e = event_dtls_handshake_started ;
break ;
case tnet_dtls_socket_event_type_handshake_succeed :
t_e = event_dtls_handshake_succeed ;
break ;
case tnet_dtls_socket_event_type_handshake_failed :
t_e = event_dtls_handshake_failed ;
break ;
case tnet_dtls_socket_event_type_fingerprint_mismatch :
t_e = event_dtls_fingerprint_mismatch ;
break ;
case tnet_dtls_socket_event_type_dtls_srtp_profile_selected :
t_e = event_dtls_srtp_profile_selected ;
break ;
case tnet_dtls_socket_event_type_dtls_srtp_data :
t_e = event_dtls_srtp_data ;
break ;
case tnet_dtls_socket_event_type_error :
t_e = event_dtls_error ;
break ;
default :
TSK_DEBUG_ERROR ( " DTLS event = %d ignored " , dtls_e ) ;
return - 1 ;
2015-06-20 17:58:34 +00:00
}
remote_addr = tnet_dtls_socket_get_remote_addr ( handle ) ;
fd = tnet_dtls_socket_get_fd ( handle ) ;
if ( ( e = tnet_transport_event_create ( t_e , transport - > callback_data , fd ) ) ) {
if ( data & & size & & ( e - > data = tsk_malloc ( size ) ) ) {
memcpy ( e - > data , data , size ) ;
e - > size = size ;
}
if ( remote_addr ) {
e - > remote_addr = * remote_addr ;
}
if ( TSK_RUNNABLE ( transport ) - > initialized & & TSK_RUNNABLE ( transport ) - > running & & TSK_RUNNABLE ( transport ) - > started ) {
TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE ( TSK_RUNNABLE ( transport ) , e ) ;
}
else {
TSK_DEBUG_INFO ( " Delivering network event synchronously. " ) ;
// network transport not started (happens when TURN is using the sockets instead of the RTP manager)
if ( transport - > callback ) {
transport - > callback ( e ) ;
}
TSK_OBJECT_SAFE_FREE ( e ) ;
}
return 0 ;
}
}
return - 1 ;
2013-01-07 15:37:02 +00:00
}
2011-03-25 09:38:07 +00:00
/*
2015-06-20 17:58:34 +00:00
* Runnable interface implementation .
*/
2013-02-17 18:56:03 +00:00
static void * TSK_STDCALL run ( void * self )
2011-03-25 09:38:07 +00:00
{
2015-06-20 17:58:34 +00:00
int ret = 0 ;
tsk_list_item_t * curr ;
tnet_transport_t * transport = self ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
TSK_DEBUG_INFO ( " Transport::run(%s) - enter " , transport - > description ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
/* create main thread */
2016-02-23 21:00:35 +00:00
if ( ( ret = tsk_thread_create ( transport - > mainThreadId , tnet_transport_mainthread , transport ) ) ) { /* More important than "tsk_runnable_start" ==> start it first. */
2015-06-20 17:58:34 +00:00
TSK_FREE ( transport - > context ) ; /* Otherwise (tsk_thread_create is ok) will be freed when mainthread exit. */
TSK_DEBUG_FATAL ( " Failed to create main thread [%d] " , ret ) ;
return tsk_null ;
}
/* set thread priority
iOS and OSX : no incoming pkts ( STUN , rtp , dtls . . . ) when thread priority is changed - > to be checked
*/
2013-07-08 09:56:07 +00:00
# if !TNET_UNDER_APPLE
2015-06-20 17:58:34 +00:00
ret = tsk_thread_set_priority ( transport - > mainThreadId [ 0 ] , TSK_THREAD_PRIORITY_TIME_CRITICAL ) ;
2013-04-09 23:14:23 +00:00
# endif
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
TSK_RUNNABLE_RUN_BEGIN ( transport ) ;
2016-02-23 21:00:35 +00:00
if ( ( curr = TSK_RUNNABLE_POP_FIRST_SAFE ( TSK_RUNNABLE ( transport ) ) ) ) {
2015-06-20 17:58:34 +00:00
const tnet_transport_event_t * e = ( const tnet_transport_event_t * ) curr - > data ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
if ( transport - > callback ) {
transport - > callback ( e ) ;
}
tsk_object_unref ( curr ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
TSK_RUNNABLE_RUN_END ( transport ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
TSK_DEBUG_INFO ( " Transport::run(%s) - exit " , transport - > description ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return tsk_null ;
2011-03-25 09:38:07 +00:00
}
//=================================================================================================
// Transport object definition
//
static tsk_object_t * tnet_transport_ctor ( tsk_object_t * self , va_list * app )
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = self ;
2016-02-23 21:00:35 +00:00
if ( transport ) {
2015-06-20 17:58:34 +00:00
}
return self ;
2011-03-25 09:38:07 +00:00
}
static tsk_object_t * tnet_transport_dtor ( tsk_object_t * self )
2014-12-19 17:09:09 +00:00
{
2015-06-20 17:58:34 +00:00
tnet_transport_t * transport = self ;
2016-02-23 21:00:35 +00:00
if ( transport ) {
2015-06-20 17:58:34 +00:00
tnet_transport_set_callback ( transport , tsk_null , tsk_null ) ;
tnet_transport_shutdown ( transport ) ;
TSK_OBJECT_SAFE_FREE ( transport - > master ) ;
TSK_OBJECT_SAFE_FREE ( transport - > context ) ;
TSK_OBJECT_SAFE_FREE ( transport - > natt_ctx ) ;
TSK_FREE ( transport - > local_ip ) ;
TSK_FREE ( transport - > local_host ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
// proxy
TSK_OBJECT_SAFE_FREE ( transport - > proxy . info ) ;
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
// (tls and dtls) = ssl
TSK_FREE ( transport - > tls . ca ) ;
TSK_FREE ( transport - > tls . pbk ) ;
TSK_FREE ( transport - > tls . pvk ) ;
_tnet_transport_ssl_deinit ( transport ) ; // openssl contexts
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
TSK_DEBUG_INFO ( " *** Transport (%s) destroyed *** " , transport - > description ) ;
TSK_FREE ( transport - > description ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return self ;
2011-03-25 09:38:07 +00:00
}
2016-02-23 21:00:35 +00:00
static const tsk_object_def_t tnet_transport_def_s = {
2015-06-20 17:58:34 +00:00
sizeof ( tnet_transport_t ) ,
tnet_transport_ctor ,
tnet_transport_dtor ,
tsk_null ,
2011-03-25 09:38:07 +00:00
} ;
const tsk_object_def_t * tnet_transport_def_t = & tnet_transport_def_s ;
//=================================================================================================
// Transport event object definition
//
static tsk_object_t * tnet_transport_event_ctor ( tsk_object_t * self , va_list * app )
{
2015-06-20 17:58:34 +00:00
tnet_transport_event_t * e = self ;
2016-02-23 21:00:35 +00:00
if ( e ) {
2015-06-20 17:58:34 +00:00
e - > type = va_arg ( * app , tnet_transport_event_type_t ) ;
e - > callback_data = va_arg ( * app , const void * ) ;
e - > local_fd = va_arg ( * app , tnet_fd_t ) ;
}
return self ;
2011-03-25 09:38:07 +00:00
}
static tsk_object_t * tnet_transport_event_dtor ( tsk_object_t * self )
2014-12-19 17:09:09 +00:00
{
2015-06-20 17:58:34 +00:00
tnet_transport_event_t * e = self ;
2016-02-23 21:00:35 +00:00
if ( e ) {
2015-06-20 17:58:34 +00:00
TSK_FREE ( e - > data ) ;
}
2016-02-23 21:00:35 +00:00
2015-06-20 17:58:34 +00:00
return self ;
2011-03-25 09:38:07 +00:00
}
2016-02-23 21:00:35 +00:00
static const tsk_object_def_t tnet_transport_event_def_s = {
2015-06-20 17:58:34 +00:00
sizeof ( tnet_transport_event_t ) ,
tnet_transport_event_ctor ,
tnet_transport_event_dtor ,
0 ,
2011-03-25 09:38:07 +00:00
} ;
const tsk_object_def_t * tnet_transport_event_def_t = & tnet_transport_event_def_s ;