@ -18,16 +18,18 @@
struct stcp_server {
struct stcp_server * next ; // linked list in UTUN_INSTANCE
struct stcp_server * srv ; // stcp_server from stcp_server.h
struct stcp_link_config cfg ;
struct UTUN_INSTANCE * inst ;
stcp_server_on_link_cb on_link ;
struct ETCP_SOCKET * tcp_sock ;
} ;
struct stcp_link {
struct stcp_link_config cfg ;
struct stcp_client * cli ;
struct stcp_conn * conn ;
struct UTUN_INSTANCE * inst ; // для rx-диспатча (из etcp_conn->instance)
struct UASYNC * ua ; // event loop (из inst->ua)
struct ETCP_CONN * etcp_conn ; // parent ETCP_CONN (for rx dispatch / etcp_send compat)
struct ETCP_LINK * etcp_link ; // owning ETCP_LINK (for etcp_conn_input pkt->link)
@ -57,7 +59,7 @@ static void link_rx_cb(struct ll_queue *q, void *arg) {
struct ll_entry * e = queue_data_get ( q ) ;
if ( ! e ) { queue_resume_callback ( q ) ; return ; }
if ( link - > etcp_conn & & link - > etcp_link & & link - > cfg . inst ) {
if ( link - > etcp_conn & & link - > etcp_link & & link - > inst ) {
DEBUG_DEBUG ( DEBUG_CATEGORY_DEBUG , " [%s] stcp_rx: len=%u hdr=%02x%02x%02x sock=%p " ,
link - > etcp_conn - > log_name , e - > len ,
e - > dgram & & e - > len > = 3 ? e - > dgram [ 0 ] : 0 ,
@ -72,7 +74,7 @@ static void link_rx_cb(struct ll_queue *q, void *arg) {
return ;
}
if ( e - > len < 3 ) { DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " stcp_link rx too short: %u bytes " , e - > len ) ; queue_dgram_free ( e ) ; queue_entry_free ( e ) ; queue_resume_callback ( q ) ; return ; }
struct ETCP_DGRAM * pkt = memory_pool_alloc ( link - > cfg . inst - > pkt_pool ) ;
struct ETCP_DGRAM * pkt = memory_pool_alloc ( link - > inst - > pkt_pool ) ;
if ( ! pkt ) { queue_dgram_free ( e ) ; queue_entry_free ( e ) ; queue_resume_callback ( q ) ; return ; }
pkt - > timestamp = ( ( uint16_t * ) e - > dgram ) [ 0 ] ;
pkt - > flag_up = e - > dgram [ 2 ] & 1 ;
@ -84,7 +86,7 @@ static void link_rx_cb(struct ll_queue *q, void *arg) {
etcp_packet_decrypted ( sock , pkt , link - > etcp_link , e - > len ) ;
queue_dgram_free ( e ) ; queue_entry_free ( e ) ;
} else {
struct UTUN_INSTANCE * inst = link - > cfg . inst ;
struct UTUN_INSTANCE * inst = link - > inst ;
uint8_t id = ( e - > dgram & & e - > len > 0 ) ? e - > dgram [ 0 ] : 0 ;
if ( inst & & inst - > api_bindings . callbacks [ id ] )
inst - > api_bindings . callbacks [ id ] ( link - > etcp_conn ? link - > etcp_conn : NULL , e ) ;
@ -112,7 +114,8 @@ static void server_accept_cb(struct stcp_conn *conn, void *arg) {
struct stcp_server * ss = ( struct stcp_server * ) arg ;
struct stcp_link * link = u_calloc ( 1 , sizeof ( struct stcp_link ) ) ;
if ( ! link ) { stcp_conn_free ( conn ) ; return ; }
link - > cfg = ss - > cfg ;
link - > inst = ss - > inst ;
link - > ua = ss - > inst - > ua ;
link - > ready = 1 ;
link - > conn = conn ;
link - > peer_got_initial_pkt = conn - > peer_got_initial_pkt ;
@ -158,16 +161,12 @@ static void client_ready_cb(struct stcp_conn *conn, void *arg) {
queue_set_waiter_defer ( link - > tx_queue , 1 ) ;
stcp_conn_set_tx_queue ( conn , link - > tx_queue ) ;
if ( link - > cfg . remote_addr ) {
{
const struct sockaddr_storage * ra = link - > etcp_link ? & link - > etcp_link - > remote_addr : NULL ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " stcp_link: client handshake OK [%s] link=%d addr=%s gop=%d sid=%08x " ,
link - > etcp_conn ? link - > etcp_conn - > log_name : " ? " ,
link - > etcp_link ? link - > etcp_link - > local_link_id : - 1 ,
sockaddr_storage_to_str ( link - > cfg . remote_addr ) . str ,
link - > peer_got_initial_pkt , link - > peer_session_id ) ;
} else {
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " stcp_link: client handshake OK [%s] link=%d addr=? gop=%d sid=%08x " ,
link - > etcp_conn ? link - > etcp_conn - > log_name : " ? " ,
link - > etcp_link ? link - > etcp_link - > local_link_id : - 1 ,
ra ? sockaddr_storage_to_str ( ra ) . str : " ? " ,
link - > peer_got_initial_pkt , link - > peer_session_id ) ;
}
if ( link - > etcp_link ) etcp_link_enter_ready_tcp ( link - > etcp_link ) ;
@ -178,13 +177,14 @@ static void client_ready_cb(struct stcp_conn *conn, void *arg) {
struct stcp_server * stcp_server_listen ( struct stcp_link_config * cfg , uint16_t port ,
stcp_server_on_link_cb on_link , struct ETCP_SOCKET * tcp_sock ) {
if ( ! cfg | | ! cfg - > ua | | ! cfg - > my_keys ) return NULL ;
if ( ! cfg | | ! cfg - > inst ) return NULL ;
struct stcp_server * ss = u_calloc ( 1 , sizeof ( struct stcp_server ) ) ;
if ( ! ss ) return NULL ;
ss - > cfg = * cfg ;
ss - > inst = cfg - > inst ;
ss - > on_link = on_link ;
ss - > tcp_sock = tcp_sock ;
ss - > srv = stcp_server_create ( cfg - > ua , port , cfg - > my_keys , cfg - > inst ? cfg - > inst - > my_ed25519_pubkey : NULL , cfg - > inst , server_accept_cb , ss , NULL , NULL , cfg - > listen_family ) ;
ss - > srv = stcp_server_create ( cfg - > inst - > ua , port , & cfg - > inst - > my_keys , cfg - > inst - > my_ed25519_pubkey ,
cfg - > inst , server_accept_cb , ss , NULL , NULL , cfg - > listen_family ) ;
if ( ! ss - > srv ) { u_free ( ss ) ; return NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " port=%u " , port ) ;
return ss ;
@ -196,21 +196,24 @@ void stcp_link_server_destroy(struct stcp_server *ss) {
u_free ( ss ) ;
}
struct stcp_link * stcp_link_connect ( struct stcp_link_config * cfg ) {
if ( ! cfg | | ! cfg - > ua | | ! cfg - > my_keys | | ! cfg - > peer_pubkey | | ! cfg - > remote_addr )
struct stcp_link * stcp_link_connect ( struct ETCP_LINK * etcp_link ,
struct sockaddr_storage * remote_addr , uint16_t port ) {
if ( ! etcp_link | | ! etcp_link - > etcp | | ! remote_addr )
return NULL ;
struct ETCP_CONN * etcp = etcp_link - > etcp ;
struct UTUN_INSTANCE * inst = etcp - > instance ;
int family = cfg - > remote_addr - > ss_family ;
int family = remote_addr - > ss_family ;
char addr_str [ 64 ] ;
uint16_t port ;
uint16_t rport = port ;
if ( family = = AF_INET ) {
struct sockaddr_in * sa = ( struct sockaddr_in * ) cfg - > remote_addr ;
struct sockaddr_in * sa = ( struct sockaddr_in * ) remote_addr ;
inet_ntop ( AF_INET , & sa - > sin_addr , addr_str , sizeof ( addr_str ) ) ;
port = cfg - > remote_port ? cfg - > remote_port : ntohs ( sa - > sin_port ) ;
if ( ! rport ) rport = ntohs ( sa - > sin_port ) ;
} else if ( family = = AF_INET6 ) {
struct sockaddr_in6 * sa6 = ( struct sockaddr_in6 * ) cfg - > remote_addr ;
struct sockaddr_in6 * sa6 = ( struct sockaddr_in6 * ) remote_addr ;
getnameinfo ( ( struct sockaddr * ) sa6 , sizeof ( * sa6 ) , addr_str , sizeof ( addr_str ) , NULL , 0 , NI_NUMERICHOST ) ;
port = cfg - > remote_port ? cfg - > remote_port : ntohs ( sa6 - > sin6_port ) ;
if ( ! rport ) rport = ntohs ( sa6 - > sin6_port ) ;
} else {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " stcp_link: unsupported address family %d " , family ) ;
return NULL ;
@ -218,32 +221,32 @@ struct stcp_link *stcp_link_connect(struct stcp_link_config *cfg) {
struct stcp_link * link = u_calloc ( 1 , sizeof ( struct stcp_link ) ) ;
if ( ! link ) return NULL ;
link - > cfg = * cfg ;
uint8_t pubkey [ SC_PUBKEY_SIZE ] ;
if ( cfg - > peer_pubkey_mode ) {
struct secure_channel sc_tmp ;
sc_init_ctx ( & sc_tmp , cfg - > my_keys ) ;
if ( sc_set_peer_public_key ( & sc_tmp , cfg - > peer_pubkey , 1 ) ! = SC_OK ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " invalid peer pubkey hex " ) ;
u_free ( link ) ; return NULL ;
}
memcpy ( pubkey , sc_tmp . peer_public_key , SC_PUBKEY_SIZE ) ;
} else {
memcpy ( pubkey , cfg - > peer_pubkey , SC_PUBKEY_SIZE ) ;
}
link - > cli = stcp_client_connect ( cfg - > ua , addr_str , port , cfg - > my_keys , pubkey ,
cfg - > inst ? cfg - > inst - > my_ed25519_pubkey : NULL ,
cfg - > got_initial_pkt , cfg - > session_id ,
cfg - > inst ? cfg - > inst - > client_type : 0 ,
cfg - > inst ? cfg - > inst - > keepalive_interval : 200 ,
client_ready_cb , link , NULL , NULL , cfg - > local_addr ) ;
link - > inst = inst ;
link - > ua = inst - > ua ;
link - > etcp_conn = etcp ;
link - > etcp_link = etcp_link ;
struct sockaddr_storage bind_addr ;
const struct sockaddr_storage * local_addr = NULL ;
if ( etcp_link - > conn & & etcp_link - > conn - > interface_addr . ss_family ) {
memcpy ( & bind_addr , & etcp_link - > conn - > interface_addr , sizeof ( bind_addr ) ) ;
if ( bind_addr . ss_family = = AF_INET6 ) ( ( struct sockaddr_in6 * ) & bind_addr ) - > sin6_port = 0 ;
else ( ( struct sockaddr_in * ) & bind_addr ) - > sin_port = 0 ;
local_addr = & bind_addr ;
}
const uint8_t * pubkey = etcp - > crypto_ctx . peer_public_key ;
link - > cli = stcp_client_connect ( inst - > ua , addr_str , rport , & inst - > my_keys , pubkey ,
inst - > my_ed25519_pubkey ,
etcp - > got_initial_pkt , etcp - > session_id , etcp ,
inst - > client_type , inst - > keepalive_interval ,
client_ready_cb , link , NULL , NULL , local_addr ) ;
if ( ! link - > cli ) { u_free ( link ) ; return NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " stcp_link: connecting to %s:%u pubkey=%016llx bind=%s " ,
addr_str , port , ( unsigned long long ) * ( const uint64_t * ) pubkey ,
cfg - > local_addr ? sockaddr_storage_to_str ( cfg - > local_addr ) . str : " auto " ) ;
addr_str , r port, ( unsigned long long ) * ( const uint64_t * ) pubkey ,
local_addr ? sockaddr_storage_to_str ( local_addr ) . str : " auto " ) ;
return link ;
}
@ -281,13 +284,13 @@ void stcp_link_close(struct stcp_link *link) {
if ( link - > cli ) {
struct stcp_conn * c = stcp_client_get_conn ( link - > cli ) ;
if ( c ) {
if ( c - > hs_timer ) { uasync_cancel_timeout ( link - > cfg . ua , c - > hs_timer ) ; c - > hs_timer = NULL ; }
if ( c - > hs_timer ) { uasync_cancel_timeout ( link - > ua , c - > hs_timer ) ; c - > hs_timer = NULL ; }
if ( c - > state = = STCP_STATE_CLOSED | | c - > state = = STCP_STATE_ERROR ) {
link - > saved_rx_queue = c - > rx_queue ; c - > rx_queue = NULL ; link - > conn_pre_closed = 1 ;
}
}
}
uasync_call_soon ( link - > cfg . ua , link , stcp_link_close_impl ) ;
uasync_call_soon ( link - > ua , link , stcp_link_close_impl ) ;
}
int stcp_link_send ( struct stcp_link * link , const uint8_t * data , size_t len ) {
@ -321,7 +324,7 @@ void stcp_link_set_etcp_link(struct stcp_link *link, struct ETCP_LINK *elink) {
}
const struct sockaddr_storage * stcp_link_get_remote_addr ( struct stcp_link * link ) {
return link & & link - > cfg . remote_addr ? link - > cfg . remote_addr : NULL ;
return link & & link - > etcp_link ? & link - > etcp_link - > remote_addr : NULL ;
}
static struct sockaddr_storage g_peer_addr ;