@ -273,18 +273,19 @@ int conn_mgr_add_alien_node(struct CONN_MGR* mgr, const uint8_t* nodeinfo_data,
if ( ! mgr | | ! nodeinfo_data | | len < sizeof ( struct NODEINFO ) ) return CONN_MGR_ERR_INTERNAL ;
struct ROUTE_BGP * bgp = mgr - > instance - > bgp ;
if ( ! bgp ) return CONN_MGR_ERR_INTERNAL ;
const struct NODEINFO * ni = ( const struct NODEINFO * ) nodeinfo_data ;
uint64_t node_id = ni - > node_id ;
const struct NODEINFO * src = ( const struct NODEINFO * ) nodeinfo_data ;
uint64_t node_id = src - > node_id ;
struct NODEINFO_Q * existing = nodeinfo_find_by_id ( bgp , node_id ) ;
if ( existing ) { DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: alien node 0x%016llx already exists, ignoring " , ( unsigned long long ) node_id ) ; return CONN_MGR_OK ; }
size_t dyn_sz = len - sizeof ( struct NODEINFO ) ;
size_t data_sz = sizeof ( struct NODEINFO_Q ) - sizeof ( struct ll_entry ) + dyn_sz + 8 ;
struct NODEINFO_Q * nq = ( struct NODEINFO_Q * ) queue_entry_new ( data_sz ) ;
if ( ! nq ) { DEBUG_ERROR ( DEBUG_CATEGORY_GENERAL , " conn_mgr: alien node alloc failed " ) ; return CONN_MGR_ERR_INTERNAL ; }
memcpy ( & nq - > node , nodeinfo_data , len ) ;
nq - > alien = 1 ;
nq - > dirty = 0 ;
nq - > last_ver = ni - > ver ;
struct NODEINFO * ni = u_calloc ( 1 , sizeof ( struct NODEINFO ) ) ;
if ( ! ni ) return CONN_MGR_ERR_INTERNAL ;
memcpy ( ni , nodeinfo_data , len < sizeof ( * ni ) ? len : sizeof ( * ni ) ) ;
ni - > ref_count = 1 ;
struct NODEINFO_Q * nq = ( struct NODEINFO_Q * ) queue_entry_new ( sizeof ( struct NODEINFO_Q ) ) ;
if ( ! nq ) { u_free ( ni ) ; return CONN_MGR_ERR_INTERNAL ; }
nq - > node = ni ; nodeinfo_ref ( ni ) ;
nq - > hash_node_id = ni - > node_id ;
nq - > alien = 1 ; nq - > dirty = 0 ; nq - > last_ver = ni - > ver ;
nq - > connectivity . ping_req_time = 0 ;
if ( bgp - > nodes ) queue_data_put_with_index ( bgp - > nodes , & nq - > ll ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: added alien node 0x%016llx " , ( unsigned long long ) node_id ) ;
@ -386,17 +387,12 @@ static int cm_is_rtt_fresh(struct NODEINFO_Q* nq, uint64_t now_tb) {
}
static int cm_has_direct_ip ( struct NODEINFO_Q * nq ) {
if ( ! nq ) return 0 ;
const struct NODEINFO_IPV4_ADDR * addrs = NULL ;
const struct NODEINFO_IPV4_SOCKET_META * metas = NULL ;
int addr_count = get_node_v4_addrs ( nq , & addrs ) ;
int meta_count = get_node_v4_sockets_meta ( nq , & metas ) ;
for ( int i = 0 ; i < addr_count ; i + + ) {
if ( addrs [ i ] . type = = ADDR_TYPE_REAL | | addrs [ i ] . type = = ADDR_TYPE_NAT ) {
for ( int j = 0 ; j < meta_count ; j + + ) {
if ( metas [ j ] . id = = addrs [ i ] . socket_id & &
( metas [ j ] . config_type = = CFG_SERVER_TYPE_PUBLIC | | metas [ j ] . config_type = = CFG_SERVER_TYPE_UNKNOWN
| | metas [ j ] . nat_type = = NAT_VERIFIED_EIM | | metas [ j ] . nat_type = = NAT_VERIFIED_DIRECT ) )
if ( ! nq | | ! nq - > node ) return 0 ;
for ( const struct NI_IPV4_ADDR * a = nq - > node - > v4_addrs ; a ; a = a - > next ) {
if ( a - > type = = ADDR_TYPE_REAL | | a - > type = = ADDR_TYPE_NAT ) {
for ( const struct NI_IPV4_SOCKET_META * m = nq - > node - > v4_sock_meta ; m ; m = m - > next ) {
if ( m - > id = = a - > socket_id & & ( m - > config_type = = CFG_SERVER_TYPE_PUBLIC | | m - > config_type = = CFG_SERVER_TYPE_UNKNOWN
| | m - > nat_type = = NAT_VERIFIED_EIM | | m - > nat_type = = NAT_VERIFIED_DIRECT ) )
return 1 ;
}
}
@ -405,16 +401,11 @@ static int cm_has_direct_ip(struct NODEINFO_Q* nq) {
}
static int cm_has_local_addr ( struct NODEINFO_Q * nq ) {
if ( ! nq ) return 0 ;
const struct NODEINFO_IPV4_ADDR * addrs = NULL ;
const struct NODEINFO_IPV4_SOCKET_META * metas = NULL ;
int addr_count = get_node_v4_addrs ( nq , & addrs ) ;
int meta_count = get_node_v4_sockets_meta ( nq , & metas ) ;
for ( int i = 0 ; i < addr_count ; i + + ) {
if ( addrs [ i ] . type = = ADDR_TYPE_INTERFACE ) {
for ( int j = 0 ; j < meta_count ; j + + ) {
if ( metas [ j ] . id = = addrs [ i ] . socket_id & &
( metas [ j ] . config_type = = CFG_SERVER_TYPE_PRIVATE | | metas [ j ] . config_type = = CFG_SERVER_TYPE_LOCAL ) )
if ( ! nq | | ! nq - > node ) return 0 ;
for ( const struct NI_IPV4_ADDR * a = nq - > node - > v4_addrs ; a ; a = a - > next ) {
if ( a - > type = = ADDR_TYPE_INTERFACE ) {
for ( const struct NI_IPV4_SOCKET_META * m = nq - > node - > v4_sock_meta ; m ; m = m - > next ) {
if ( m - > id = = a - > socket_id & & ( m - > config_type = = CFG_SERVER_TYPE_PRIVATE | | m - > config_type = = CFG_SERVER_TYPE_LOCAL ) )
return 1 ;
}
}
@ -437,36 +428,20 @@ struct cm_ping_ctx {
static void cm_start_local_scan ( struct CONN_MGR_ENTRY * entry ) {
struct ROUTE_BGP * bgp = entry - > mgr - > instance - > bgp ;
struct NODEINFO_Q * target = nodeinfo_find_by_id ( bgp , entry - > node_id ) ;
if ( ! target ) { entry - > local_scan_state = CM_TRY_FAILED ; return ; }
const struct NODEINFO_IPV4_ADDR * addrs = NULL ;
const struct NODEINFO_IPV4_SOCKET_META * metas = NULL ;
int addr_count = get_node_v4_addrs ( target , & addrs ) ;
int meta_count = get_node_v4_sockets_meta ( target , & metas ) ;
for ( int i = 0 ; i < addr_count ; i + + ) {
if ( addrs [ i ] . type ! = ADDR_TYPE_INTERFACE ) continue ;
for ( int j = 0 ; j < meta_count ; j + + ) {
if ( metas [ j ] . id ! = addrs [ i ] . socket_id | |
( metas [ j ] . config_type ! = CFG_SERVER_TYPE_PRIVATE & & metas [ j ] . config_type ! = CFG_SERVER_TYPE_LOCAL ) ) continue ;
if ( ! target | | ! target - > node ) { entry - > local_scan_state = CM_TRY_FAILED ; return ; }
for ( const struct NI_IPV4_ADDR * a = target - > node - > v4_addrs ; a ; a = a - > next ) {
if ( a - > type ! = ADDR_TYPE_INTERFACE ) continue ;
for ( const struct NI_IPV4_SOCKET_META * m = target - > node - > v4_sock_meta ; m ; m = m - > next ) {
if ( m - > id ! = a - > socket_id | | ( m - > config_type ! = CFG_SERVER_TYPE_PRIVATE & & m - > config_type ! = CFG_SERVER_TYPE_LOCAL ) ) continue ;
struct ETCP_SOCKET * s = entry - > mgr - > instance - > etcp_sockets ;
while ( s ) {
if ( ( s - > type = = CFG_SERVER_TYPE_PRIVATE | | s - > type = = CFG_SERVER_TYPE_LOCAL ) & & s - > local_addr . ss_family = = AF_INET ) {
struct sockaddr_in sin ;
memset ( & sin , 0 , sizeof ( sin ) ) ;
sin . sin_family = AF_INET ;
memcpy ( & sin . sin_addr . s_addr , addrs [ i ] . addr , 4 ) ;
sin . sin_port = htons ( addrs [ i ] . port ) ;
struct sockaddr_storage sa ;
memset ( & sa , 0 , sizeof ( sa ) ) ;
memcpy ( & sa , & sin , sizeof ( sin ) ) ;
struct cm_ping_ctx * ctx = u_calloc ( 1 , sizeof ( struct cm_ping_ctx ) ) ;
if ( ! ctx ) continue ;
ctx - > entry = entry ;
ctx - > addr = sa ;
ctx - > sock = s ;
ctx - > phase = 0 ;
ctx - > attempt = 0 ;
etcp_send_ping_to_socket ( entry - > mgr - > instance , s , target - > node . public_key , & sa ,
CONN_MGR_LOCAL_SCAN_TIMEOUT_MS , cm_ping_cb , ctx , NULL , 0 ) ;
struct sockaddr_in sin ; memset ( & sin , 0 , sizeof ( sin ) ) ; sin . sin_family = AF_INET ;
memcpy ( & sin . sin_addr . s_addr , a - > addr , 4 ) ; sin . sin_port = htons ( a - > port ) ;
struct sockaddr_storage sa ; memset ( & sa , 0 , sizeof ( sa ) ) ; memcpy ( & sa , & sin , sizeof ( sin ) ) ;
struct cm_ping_ctx * ctx = u_calloc ( 1 , sizeof ( struct cm_ping_ctx ) ) ; if ( ! ctx ) continue ;
ctx - > entry = entry ; ctx - > addr = sa ; ctx - > sock = s ; ctx - > phase = 0 ; ctx - > attempt = 0 ;
etcp_send_ping_to_socket ( entry - > mgr - > instance , s , target - > node - > public_key , & sa , CONN_MGR_LOCAL_SCAN_TIMEOUT_MS , cm_ping_cb , ctx , NULL , 0 ) ;
return ;
}
s = s - > next ;
@ -474,7 +449,6 @@ static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) {
}
}
entry - > local_scan_state = CM_TRY_FAILED ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: local scan no candidates for 0x%016llx " , ( unsigned long long ) entry - > node_id ) ;
}
static void cm_start_phase_direct ( struct CONN_MGR_ENTRY * entry ) {
@ -482,39 +456,25 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) {
if ( entry - > local_scan_state = = CM_TRY_OK ) return ;
struct ROUTE_BGP * bgp = entry - > mgr - > instance - > bgp ;
struct NODEINFO_Q * target = nodeinfo_find_by_id ( bgp , entry - > node_id ) ;
if ( ! target ) { cm_deliver_result ( entry , CONN_MGR_ERR_NOT_FOUND ) ; return ; }
const struct NODEINFO_IPV4_ADDR * addrs = NULL ;
const struct NODEINFO_IPV4_SOCKET_META * metas = NULL ;
int addr_count = get_node_v4_addrs ( target , & addrs ) ;
int meta_count = get_node_v4_sockets_meta ( target , & metas ) ;
if ( ! target | | ! target - > node ) { cm_deliver_result ( entry , CONN_MGR_ERR_NOT_FOUND ) ; return ; }
uint8_t priority_order [ ] = { ADDR_TYPE_REAL , ADDR_TYPE_NAT , ADDR_TYPE_INTERFACE } ;
for ( int pri = 0 ; pri < 3 ; pri + + ) {
for ( int i = 0 ; i < addr_count ; i + + ) {
if ( addrs [ i ] . type ! = priority_order [ pri ] ) continue ;
for ( int j = 0 ; j < meta_count ; j + + ) {
if ( metas [ j ] . id ! = addrs [ i ] . socket_id ) continue ;
for ( const struct NI_IPV4_ADDR * a = target - > node - > v4_addrs ; a ; a = a - > next ) {
if ( a - > type ! = priority_order [ pri ] ) continue ;
for ( const struct NI_IPV4_SOCKET_META * m = target - > node - > v4_sock_meta ; m ; m = m - > next ) {
if ( m - > id ! = a - > socket_id ) continue ;
struct ETCP_SOCKET * s = entry - > mgr - > instance - > etcp_sockets ;
while ( s ) {
int compat = cm_nat_compatible ( s , metas [ j ] . config_type , metas [ j ] . nat_type ) ;
if ( compat & & s - > local_addr . ss_family = = AF_INET ) {
struct sockaddr_in sin ;
memset ( & sin , 0 , sizeof ( sin ) ) ;
sin . sin_family = AF_INET ;
memcpy ( & sin . sin_addr . s_addr , addrs [ i ] . addr , 4 ) ;
sin . sin_port = htons ( addrs [ i ] . port ) ;
struct sockaddr_storage sa ;
memset ( & sa , 0 , sizeof ( sa ) ) ;
memcpy ( & sa , & sin , sizeof ( sin ) ) ;
if ( cm_nat_compatible ( s , m - > config_type , m - > nat_type ) & & s - > local_addr . ss_family = = AF_INET ) {
struct sockaddr_in sin ; memset ( & sin , 0 , sizeof ( sin ) ) ; sin . sin_family = AF_INET ;
memcpy ( & sin . sin_addr . s_addr , a - > addr , 4 ) ; sin . sin_port = htons ( a - > port ) ;
struct sockaddr_storage sa ; memset ( & sa , 0 , sizeof ( sa ) ) ; memcpy ( & sa , & sin , sizeof ( sin ) ) ;
struct ETCP_CONN * conn = etcp_connection_create ( entry - > mgr - > instance , NULL ) ;
if ( conn ) {
etcp_conn_set_ready_cbk ( conn , cm_direct_ready_cb , entry ) ;
sc_set_peer_public_key ( & conn - > crypto_ctx , target - > node . public_key , 0 ) ;
struct ETCP_LINK * link = etcp_link_new ( conn , s , & sa , 0 ) ;
if ( link ) {
entry - > main . timer = uasync_set_timeout ( entry - > mgr - > instance - > ua ,
CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS * 10 , entry , cm_direct_timeout_cb , " conn_mgr_direct " ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: phase 1 (direct) started INIT to 0x%016llx " ,
( unsigned long long ) entry - > node_id ) ;
sc_set_peer_public_key ( & conn - > crypto_ctx , target - > node - > public_key , 0 ) ;
if ( etcp_link_new ( conn , s , & sa , 0 ) ) {
entry - > main . timer = uasync_set_timeout ( entry - > mgr - > instance - > ua , CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS * 10 , entry , cm_direct_timeout_cb , " conn_mgr_direct " ) ;
return ;
}
}
@ -524,8 +484,6 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) {
}
}
}
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: phase 1 (direct) no compatible pairs for 0x%016llx " ,
( unsigned long long ) entry - > node_id ) ;
int has_our = cm_has_direct_ip ( bgp - > local_node ) ;
int has_target = cm_has_direct_ip ( target ) ;
if ( has_our & & ! has_target ) { cm_start_phase_reverse ( entry ) ; return ; }
@ -584,7 +542,7 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
ctx - > attempt + + ;
if ( ctx - > attempt < CONN_MGR_LOCAL_SCAN_ATTEMPTS & & ctx - > phase = = 0 ) {
etcp_send_ping_to_socket ( entry - > mgr - > instance , ctx - > sock ,
nodeinfo_find_by_id ( entry - > mgr - > instance - > bgp , entry - > node_id ) - > node . public_key ,
nodeinfo_find_by_id ( entry - > mgr - > instance - > bgp , entry - > node_id ) - > node - > public_key ,
& ctx - > addr , CONN_MGR_LOCAL_SCAN_TIMEOUT_MS , cm_ping_cb , ctx , NULL , 0 ) ;
return ;
}
@ -597,28 +555,19 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
static void cm_start_phase_reverse ( struct CONN_MGR_ENTRY * entry ) {
struct ROUTE_BGP * bgp = entry - > mgr - > instance - > bgp ;
struct NODEINFO_Q * local = bgp - > local_node ;
if ( ! local ) { cm_deliver_result ( entry , CONN_MGR_ERR_INTERNAL ) ; return ; }
if ( ! local | | ! local - > node ) { cm_deliver_result ( entry , CONN_MGR_ERR_INTERNAL ) ; return ; }
uint32_t req_id = + + entry - > mgr - > next_request_id ;
entry - > main . request_id = req_id ;
entry - > main . phase = 2 ;
const struct NODEINFO_IPV4_ADDR * addrs = NULL ;
const struct NODEINFO_IPV4_SOCKET_META * metas = NULL ;
int addr_count = get_node_v4_addrs ( local , & addrs ) ;
int meta_count = get_node_v4_sockets_meta ( local , & metas ) ;
entry - > main . request_id = req_id ; entry - > main . phase = 2 ;
uint8_t direct_count = 0 ;
struct { uint8_t type ; uint8_t ip [ 4 ] ; uint16_t port ; uint8_t socket_id ; } out_addrs [ 8 ] ;
for ( int i = 0 ; i < addr_count & & direct_count < 8 ; i + + ) {
if ( addrs [ i ] . type ! = ADDR_TYPE_REAL & & addrs [ i ] . type ! = ADDR_TYPE_NAT ) continue ;
for ( int j = 0 ; j < meta_count ; j + + ) {
if ( metas [ j ] . id = = addrs [ i ] . socket_id & &
( metas [ j ] . config_type = = CFG_SERVER_TYPE_PUBLIC | | metas [ j ] . config_type = = CFG_SERVER_TYPE_UNKNOWN
| | metas [ j ] . nat_type = = NAT_VERIFIED_EIM | | metas [ j ] . nat_type = = NAT_VERIFIED_DIRECT ) ) {
out_addrs [ direct_count ] . type = addrs [ i ] . type ;
memcpy ( out_addrs [ direct_count ] . ip , addrs [ i ] . addr , 4 ) ;
out_addrs [ direct_count ] . port = htons ( addrs [ i ] . port ) ;
out_addrs [ direct_count ] . socket_id = addrs [ i ] . socket_id ;
direct_count + + ;
break ;
for ( const struct NI_IPV4_ADDR * a = local - > node - > v4_addrs ; a & & direct_count < 8 ; a = a - > next ) {
if ( a - > type ! = ADDR_TYPE_REAL & & a - > type ! = ADDR_TYPE_NAT ) continue ;
for ( const struct NI_IPV4_SOCKET_META * m = local - > node - > v4_sock_meta ; m ; m = m - > next ) {
if ( m - > id = = a - > socket_id & & ( m - > config_type = = CFG_SERVER_TYPE_PUBLIC | | m - > config_type = = CFG_SERVER_TYPE_UNKNOWN
| | m - > nat_type = = NAT_VERIFIED_EIM | | m - > nat_type = = NAT_VERIFIED_DIRECT ) ) {
out_addrs [ direct_count ] . type = a - > type ; memcpy ( out_addrs [ direct_count ] . ip , a - > addr , 4 ) ;
out_addrs [ direct_count ] . port = htons ( a - > port ) ; out_addrs [ direct_count ] . socket_id = a - > socket_id ;
direct_count + + ; break ;
}
}
}
@ -904,7 +853,7 @@ static void cm_handle_direct_req(struct ETCP_CONN* conn, const uint8_t* data, si
struct ETCP_CONN * new_conn = etcp_connection_create ( conn - > instance , NULL ) ;
if ( new_conn ) {
struct NODEINFO_Q * nq = nodeinfo_find_by_id ( conn - > instance - > bgp , src_node_id ) ;
if ( nq ) sc_set_peer_public_key ( & new_conn - > crypto_ctx , nq - > node . public_key , 0 ) ;
if ( nq ) sc_set_peer_public_key ( & new_conn - > crypto_ctx , nq - > node - > public_key , 0 ) ;
struct cm_reverse_pending * rp = u_calloc ( 1 , sizeof ( struct cm_reverse_pending ) ) ;
if ( rp ) { rp - > request_id = req - > request_id ; rp - > entry = NULL ; rp - > next = mgr - > reverse_pending ;
etcp_conn_set_ready_cbk ( new_conn , cm_reverse_ready_cb , rp ) ; mgr - > reverse_pending = rp ; }
@ -991,7 +940,7 @@ static void cm_bg_ping_timer_cb(void* arg) {
while ( e & & cursor < mgr - > bg_ping_cursor ) { cursor + + ; e = e - > next ; }
if ( e ) {
struct NODEINFO_Q * nq = ( struct NODEINFO_Q * ) e ;
uint64_t node_id = nq - > node . node_id ;
uint64_t node_id = nq - > node - > node_id ;
if ( node_id ! = mgr - > instance - > node_id ) {
struct ETCP_CONN * dconn = route_bgp_find_conn_for_node ( bgp , node_id ) ;
int has_active = 0 ;
@ -1000,7 +949,7 @@ static void cm_bg_ping_timer_cb(void* arg) {
while ( l ) { if ( l - > initialized & & l - > link_status ) { has_active = 1 ; break ; } l = l - > next ; }
}
if ( ! has_active ) {
etcp_send_ping ( mgr - > instance , nq - > node . public_key , NULL , CONN_PROBE_TIMEOUT_MS ,
etcp_send_ping ( mgr - > instance , nq - > node - > public_key , NULL , CONN_PROBE_TIMEOUT_MS ,
NULL , NULL , NULL , 0 ) ;
}
}
@ -1032,7 +981,7 @@ static void cm_candidate_ping_timer_cb(void* arg) {
while ( l ) { if ( l - > initialized & & l - > link_status ) { has_active = 1 ; break ; } l = l - > next ; }
}
if ( has_active )
etcp_send_ping ( mgr - > instance , nq - > node . public_key , & dconn - > links - > remote_addr , CONN_PROBE_TIMEOUT_MS , NULL , NULL , NULL , 0 ) ;
etcp_send_ping ( mgr - > instance , nq - > node - > public_key , & dconn - > links - > remote_addr , CONN_PROBE_TIMEOUT_MS , NULL , NULL , NULL , 0 ) ;
else
route_connectivity_probe_node ( mgr - > instance , nq ) ;
}