@ -289,13 +289,6 @@ int conn_mgr_connect_node(struct CONN_MGR* mgr, uint64_t node_id, uint32_t idle_
cm_deliver_result ( entry , CONN_MGR_OK ) ;
cm_deliver_result ( entry , CONN_MGR_OK ) ;
return CONN_MGR_OK ;
return CONN_MGR_OK ;
}
}
entry = cm_ensure_entry ( mgr , node_id ) ;
if ( ! entry ) return CONN_MGR_ERR_INTERNAL ;
entry - > state = CONN_MGR_STATE_CONNECTING ;
{ struct cm_cb_node * cn = u_calloc ( 1 , sizeof ( struct cm_cb_node ) ) ;
if ( cn ) { cn - > cb = cb ; cn - > arg = cb_arg ; cn - > next = entry - > cb_list ; entry - > cb_list = cn ; } }
topo_group_new_conn ( group , existing ) ;
return CONN_MGR_OK ;
}
}
entry = cm_ensure_entry ( mgr , node_id ) ;
entry = cm_ensure_entry ( mgr , node_id ) ;
if ( ! entry ) return CONN_MGR_ERR_INTERNAL ;
if ( ! entry ) return CONN_MGR_ERR_INTERNAL ;
@ -481,6 +474,25 @@ static int cm_is_rtt_fresh(struct TOPO_NODEQ* nq, uint64_t now_tb) {
return ( last > 0 & & ( now_tb - last ) < ( uint64_t ) ( CONN_MGR_CANDIDATE_CACHE_MS * 10 ) ) ;
return ( last > 0 & & ( now_tb - last ) < ( uint64_t ) ( CONN_MGR_CANDIDATE_CACHE_MS * 10 ) ) ;
}
}
# define CM_V6_LINK_LOCAL 0
# define CM_V6_LOCAL 1
# define CM_V6_DIRECT 2
# define CM_V6_OTHER 3
static uint8_t cm_classify_v6_addr ( const uint8_t addr [ 16 ] ) {
if ( addr [ 0 ] = = 0xfe & & ( addr [ 1 ] & 0xc0 ) = = 0x80 ) return CM_V6_LINK_LOCAL ;
if ( addr [ 0 ] = = 0xfc | | addr [ 0 ] = = 0xfd ) return CM_V6_LOCAL ;
if ( addr [ 0 ] = = 0xff ) return CM_V6_OTHER ;
{ uint8_t zero [ 16 ] = { 0 } ; if ( memcmp ( addr , zero , 16 ) = = 0 ) return CM_V6_OTHER ; }
{ uint8_t lb [ 16 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ; if ( memcmp ( addr , lb , 16 ) = = 0 ) return CM_V6_OTHER ; }
return CM_V6_DIRECT ;
}
static uint8_t cm_sock_v6_classify ( const struct ETCP_SOCKET * s ) {
if ( s - > local_addr . ss_family ! = AF_INET6 ) return CM_V6_OTHER ;
return cm_classify_v6_addr ( ( ( const struct sockaddr_in6 * ) & s - > local_addr ) - > sin6_addr . s6_addr ) ;
}
static int cm_has_direct_ip ( struct TOPO_NODEQ * nq ) {
static int cm_has_direct_ip ( struct TOPO_NODEQ * nq ) {
if ( ! nq | | ! nq - > node ) return 0 ;
if ( ! nq | | ! nq - > node ) return 0 ;
for ( const struct TOPO_ADDR4 * a = nq - > node - > v4_addrs ; a ; a = a - > next ) {
for ( const struct TOPO_ADDR4 * a = nq - > node - > v4_addrs ; a ; a = a - > next ) {
@ -492,6 +504,13 @@ static int cm_has_direct_ip(struct TOPO_NODEQ* nq) {
}
}
}
}
}
}
for ( const struct TOPO_ADDR6 * a6 = nq - > node - > v6_addrs ; a6 ; a6 = a6 - > next ) {
if ( ( a6 - > type ! = TOPO_ADDR_NAT & & a6 - > type ! = TOPO_ADDR_INTERFACE ) | | cm_classify_v6_addr ( a6 - > addr ) ! = CM_V6_DIRECT ) continue ;
for ( const struct TOPO_SOCKMETA6 * m = nq - > node - > v6_sock_meta ; m ; m = m - > next )
if ( m - > id = = a6 - > 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 ;
}
return 0 ;
return 0 ;
}
}
@ -505,6 +524,14 @@ static int cm_has_local_addr(struct TOPO_NODEQ* nq) {
}
}
}
}
}
}
for ( const struct TOPO_ADDR6 * a6 = nq - > node - > v6_addrs ; a6 ; a6 = a6 - > next ) {
if ( a6 - > type ! = TOPO_ADDR_INTERFACE ) continue ;
uint8_t cls = cm_classify_v6_addr ( a6 - > addr ) ;
if ( cls ! = CM_V6_LINK_LOCAL & & cls ! = CM_V6_LOCAL ) continue ;
for ( const struct TOPO_SOCKMETA6 * m = nq - > node - > v6_sock_meta ; m ; m = m - > next )
if ( m - > id = = a6 - > socket_id & & ( m - > config_type = = CFG_SERVER_TYPE_PRIVATE | | m - > config_type = = CFG_SERVER_TYPE_LOCAL ) )
return 1 ;
}
return 0 ;
return 0 ;
}
}
@ -546,41 +573,71 @@ static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) {
entry - > local_scan_state = CM_TRY_FAILED ;
entry - > local_scan_state = CM_TRY_FAILED ;
}
}
static struct ETCP_CONN * cm_get_or_create_conn ( struct CONN_MGR_ENTRY * entry , const struct TOPO_NODEQ * target ) {
struct ETCP_CONN * conn = topo_group_find_conn_for_node ( entry - > mgr - > group , entry - > node_id ) ;
if ( ! conn ) conn = instance_find_conn ( entry - > mgr - > instance , entry - > node_id ) ;
if ( conn ) {
if ( conn - > peer_node_id = = entry - > node_id ) { struct etcp_cbk_entry * cbe = conn - > init_cbks ; while ( cbe ) { struct etcp_cbk_entry * n = cbe - > next ; u_free ( cbe ) ; cbe = n ; } conn - > init_cbks = NULL ; etcp_conn_add_init_cbk ( conn , cm_direct_init_cb , entry ) ; return conn ; }
DEBUG_WARN ( DEBUG_CATEGORY_GENERAL , " conn_mgr: existing conn peer_id mismatch 0x%016llx != 0x%016llx, ignoring " ,
( unsigned long long ) conn - > peer_node_id , ( unsigned long long ) entry - > node_id ) ;
}
conn = etcp_connection_create ( entry - > mgr - > instance , NULL ) ;
if ( ! conn ) return NULL ;
sc_init_ctx ( & conn - > crypto_ctx , & entry - > mgr - > instance - > my_keys ) ;
sc_set_peer_public_key ( & conn - > crypto_ctx , target - > node - > public_key , 0 ) ;
conn - > peer_node_id = entry - > node_id ;
etcp_update_log_name ( conn ) ;
etcp_conn_add_init_cbk ( conn , cm_direct_init_cb , entry ) ;
return conn ;
}
static void cm_add_v6_link ( struct ETCP_CONN * conn , const uint8_t addr [ 16 ] , uint16_t port , struct ETCP_SOCKET * s ) {
struct sockaddr_in6 sin6 ; memset ( & sin6 , 0 , sizeof ( sin6 ) ) ; sin6 . sin6_family = AF_INET6 ;
memcpy ( & sin6 . sin6_addr , addr , 16 ) ; sin6 . sin6_port = htons ( port ) ;
if ( cm_classify_v6_addr ( addr ) = = CM_V6_LINK_LOCAL ) { struct sockaddr_in6 * our = ( struct sockaddr_in6 * ) & s - > local_addr ; sin6 . sin6_scope_id = our - > sin6_scope_id ; }
struct sockaddr_storage sa ; memcpy ( & sa , & sin6 , sizeof ( sin6 ) ) ;
etcp_link_new ( conn , s , & sa , 0 ) ;
}
static void cm_start_phase_direct ( struct CONN_MGR_ENTRY * entry ) {
static void cm_start_phase_direct ( struct CONN_MGR_ENTRY * entry ) {
if ( entry - > main_connect_state = = CM_TRY_OK ) return ;
if ( entry - > main_connect_state = = CM_TRY_OK | | entry - > local_scan_state = = CM_TRY_OK ) return ;
if ( entry - > local_scan_state = = CM_TRY_OK ) return ;
struct TOPO_GROUP * group = entry - > mgr - > group ;
struct TOPO_GROUP * group = entry - > mgr - > group ;
struct TOPO_NODEQ * target = topo_node_find_by_id ( group , entry - > node_id ) ;
struct TOPO_NODEQ * target = topo_node_find_by_id ( group , entry - > node_id ) ;
if ( ! target | | ! target - > node ) { cm_deliver_result ( entry , CONN_MGR_ERR_NOT_FOUND ) ; return ; }
if ( ! target | | ! target - > node ) { cm_deliver_result ( entry , CONN_MGR_ERR_NOT_FOUND ) ; return ; }
struct ETCP_CONN * conn = cm_get_or_create_conn ( entry , target ) ;
if ( ! conn ) { cm_deliver_result ( entry , CONN_MGR_ERR_INTERNAL ) ; return ; }
int any_link = 0 ;
const char * timer_name = entry - > db_loaded ? " conn_mgr_db_direct " : " conn_mgr_direct " ;
if ( entry - > db_loaded ) {
if ( entry - > db_loaded ) {
for ( const struct TOPO_ADDR4 * a = target - > node - > v4_addrs ; a ; a = a - > next ) {
for ( const struct TOPO_ADDR4 * a = target - > node - > v4_addrs ; a ; a = a - > next ) {
if ( a - > protocol ! = TOPO_PROTO_UDP ) continue ;
if ( ! ( a - > protocol & TOPO_PROTO_UDP ) ) continue ;
struct ETCP_SOCKET * s = entry - > mgr - > instance - > etcp_sockets ;
struct ETCP_SOCKET * s = entry - > mgr - > instance - > etcp_sockets ;
while ( s ) {
while ( s ) {
if ( s - > local_addr . ss_family = = AF_INET ) {
if ( s - > local_addr . ss_family = = AF_INET ) {
struct sockaddr_in sin ; memset ( & sin , 0 , sizeof ( sin ) ) ; sin . sin_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 ) ;
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 sockaddr_storage sa ; memcpy ( & sa , & sin , sizeof ( sin ) ) ;
struct ETCP_CONN * conn = etcp_connection_create ( entry - > mgr - > instance , NULL ) ;
if ( etcp_link_new ( conn , s , & sa , 0 ) ) any_link = 1 ;
if ( conn ) {
etcp_conn_add_init_cbk ( conn , cm_direct_init_cb , entry ) ;
sc_init_ctx ( & conn - > crypto_ctx , & entry - > mgr - > instance - > my_keys ) ;
sc_set_peer_public_key ( & conn - > crypto_ctx , target - > node - > public_key , 0 ) ;
etcp_conn_set_peer_node_id ( conn , entry - > node_id ) ;
if ( etcp_link_new ( conn , s , & sa , 0 ) ) {
entry - > main . timer = uasync_set_timeout ( entry - > mgr - > instance - > ua , ( int ) ( entry - > mgr - > direct_timeout_ms * 10 ) , entry , cm_direct_timeout_cb , " conn_mgr_db_direct " ) ;
return ;
}
etcp_connection_close ( conn ) ;
}
}
}
s = s - > next ;
s = s - > next ;
}
}
}
}
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: db_node 0x%016llx direct failed (no compatible addr/socket) " , ( unsigned long long ) entry - > node_id ) ;
for ( const struct TOPO_ADDR6 * a6 = target - > node - > v6_addrs ; a6 ; a6 = a6 - > next ) {
cm_cleanup_db_node ( entry ) ;
if ( ! ( a6 - > protocol & TOPO_PROTO_UDP ) ) continue ;
cm_deliver_result ( entry , CONN_MGR_ERR_UNREACHABLE ) ;
uint8_t tclass = cm_classify_v6_addr ( a6 - > addr ) ; if ( tclass = = CM_V6_OTHER ) continue ;
struct ETCP_SOCKET * s = entry - > mgr - > instance - > etcp_sockets ;
while ( s ) { if ( cm_sock_v6_classify ( s ) = = tclass ) { cm_add_v6_link ( conn , a6 - > addr , a6 - > port , s ) ; any_link = 1 ; } s = s - > next ; }
}
if ( ! any_link ) {
etcp_connection_close ( conn ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: db_node 0x%016llx direct failed (no compatible addr/socket) " , ( unsigned long long ) entry - > node_id ) ;
cm_cleanup_db_node ( entry ) ; cm_deliver_result ( entry , CONN_MGR_ERR_UNREACHABLE ) ;
} else {
entry - > main . timer = uasync_set_timeout ( entry - > mgr - > instance - > ua , ( int ) ( entry - > mgr - > direct_timeout_ms * 10 ) , entry , cm_direct_timeout_cb , timer_name ) ;
}
return ;
return ;
}
}
@ -595,25 +652,26 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) {
if ( cm_nat_compatible ( s , m - > config_type , m - > nat_type ) & & s - > local_addr . ss_family = = AF_INET ) {
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 ;
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 ) ;
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 sockaddr_storage sa ; memcpy ( & sa , & sin , sizeof ( sin ) ) ;
struct ETCP_CONN * conn = etcp_connection_create ( entry - > mgr - > instance , NULL ) ;
if ( etcp_link_new ( conn , s , & sa , 0 ) ) any_link = 1 ;
if ( conn ) {
etcp_conn_add_init_cbk ( conn , cm_direct_init_cb , entry ) ;
sc_init_ctx ( & conn - > crypto_ctx , & entry - > mgr - > instance - > my_keys ) ;
sc_set_peer_public_key ( & conn - > crypto_ctx , target - > node - > public_key , 0 ) ;
etcp_conn_set_peer_node_id ( conn , entry - > node_id ) ;
if ( etcp_link_new ( conn , s , & sa , 0 ) ) {
entry - > main . timer = uasync_set_timeout ( entry - > mgr - > instance - > ua , ( int ) ( entry - > mgr - > direct_timeout_ms * 10 ) , entry , cm_direct_timeout_cb , " conn_mgr_direct " ) ;
return ;
}
etcp_connection_close ( conn ) ;
}
}
}
s = s - > next ;
s = s - > next ;
}
}
}
}
}
}
}
for ( const struct TOPO_ADDR6 * a6 = target - > node - > v6_addrs ; a6 ; a6 = a6 - > next ) {
if ( a6 - > type ! = priority_order [ pri ] ) continue ;
uint8_t tclass = cm_classify_v6_addr ( a6 - > addr ) ; if ( tclass = = CM_V6_OTHER ) continue ;
struct ETCP_SOCKET * s = entry - > mgr - > instance - > etcp_sockets ;
while ( s ) { if ( cm_sock_v6_classify ( s ) = = tclass ) { cm_add_v6_link ( conn , a6 - > addr , a6 - > port , s ) ; any_link = 1 ; } s = s - > next ; }
}
}
if ( any_link ) {
entry - > main . timer = uasync_set_timeout ( entry - > mgr - > instance - > ua , ( int ) ( entry - > mgr - > direct_timeout_ms * 10 ) , entry , cm_direct_timeout_cb , timer_name ) ;
return ;
}
etcp_connection_close ( conn ) ;
int has_our = cm_has_direct_ip ( group - > local_node ) ;
int has_our = cm_has_direct_ip ( group - > local_node ) ;
int has_target = cm_has_direct_ip ( target ) ;
int has_target = cm_has_direct_ip ( target ) ;
if ( has_our & & ! has_target ) { cm_start_phase_reverse ( entry ) ; return ; }
if ( has_our & & ! has_target ) { cm_start_phase_reverse ( entry ) ; return ; }
@ -1102,6 +1160,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 ; }
while ( l ) { if ( l - > initialized & & l - > link_status ) { has_active = 1 ; break ; } l = l - > next ; }
}
}
if ( ! has_active ) {
if ( ! has_active ) {
int sent_v4 = 0 ;
for ( const struct TOPO_ADDR4 * a = nq - > node - > v4_addrs ; a ; a = a - > next ) {
for ( const struct TOPO_ADDR4 * a = nq - > node - > v4_addrs ; a ; a = a - > next ) {
if ( a - > type ! = TOPO_ADDR_NAT & & a - > type ! = TOPO_ADDR_INTERFACE ) continue ;
if ( a - > type ! = TOPO_ADDR_NAT & & a - > type ! = TOPO_ADDR_INTERFACE ) continue ;
struct sockaddr_in sin ; memset ( & sin , 0 , sizeof ( sin ) ) ; sin . sin_family = AF_INET ;
struct sockaddr_in sin ; memset ( & sin , 0 , sizeof ( sin ) ) ; sin . sin_family = AF_INET ;
@ -1112,7 +1171,21 @@ static void cm_bg_ping_timer_cb(void* arg) {
if ( ! s ) break ;
if ( ! s ) break ;
etcp_send_ping_to_socket ( mgr - > instance , s , nq - > node - > public_key , & sa ,
etcp_send_ping_to_socket ( mgr - > instance , s , nq - > node - > public_key , & sa ,
CONN_PROBE_TIMEOUT_MS , cm_bg_ping_noop_cb , NULL , NULL , 0 , 0 ) ;
CONN_PROBE_TIMEOUT_MS , cm_bg_ping_noop_cb , NULL , NULL , 0 , 0 ) ;
break ;
sent_v4 = 1 ; break ;
}
if ( ! sent_v4 ) {
for ( const struct TOPO_ADDR6 * a6 = nq - > node - > v6_addrs ; a6 ; a6 = a6 - > next ) {
if ( a6 - > type ! = TOPO_ADDR_NAT & & a6 - > type ! = TOPO_ADDR_INTERFACE ) continue ;
struct sockaddr_in6 sin6 ; memset ( & sin6 , 0 , sizeof ( sin6 ) ) ; sin6 . sin6_family = AF_INET6 ;
memcpy ( & sin6 . sin6_addr , a6 - > addr , 16 ) ; sin6 . sin6_port = htons ( a6 - > port ) ;
struct sockaddr_storage sa ; memcpy ( & sa , & sin6 , sizeof ( sin6 ) ) ;
struct ETCP_SOCKET * s = mgr - > instance - > etcp_sockets ;
while ( s ) { if ( s - > local_addr . ss_family = = AF_INET6 ) break ; s = s - > next ; }
if ( ! s ) break ;
etcp_send_ping_to_socket ( mgr - > instance , s , nq - > node - > public_key , & sa ,
CONN_PROBE_TIMEOUT_MS , cm_bg_ping_noop_cb , NULL , NULL , 0 , 0 ) ;
break ;
}
}
}
}
}
}
}
@ -1364,7 +1437,7 @@ static void cm_invite_cleanup(struct cm_invite_pending* inv) {
int conn_mgr_connect_from_invite ( struct CONN_MGR * mgr , struct TOPO_NODE * ni ,
int conn_mgr_connect_from_invite ( struct CONN_MGR * mgr , struct TOPO_NODE * ni ,
uint64_t group_id , uint32_t timeout_ms ,
uint64_t group_id , uint32_t timeout_ms ,
conn_mgr_connect_callback_t cb , void * cb_arg ) {
conn_mgr_connect_callback_t cb , void * cb_arg ) {
if ( ! mgr | | ! ni | | ! ni - > v4_addrs ) { if ( cb ) cb ( CONN_MGR_ERR_INTERNAL , ni ? ni - > node_id : 0 , cb_arg ) ; return CONN_MGR_ERR_INTERNAL ; }
if ( ! mgr | | ! ni | | ( ! ni - > v4_addrs & & ! ni - > v6_addrs ) ) { if ( cb ) cb ( CONN_MGR_ERR_INTERNAL , ni ? ni - > node_id : 0 , cb_arg ) ; return CONN_MGR_ERR_INTERNAL ; }
uint64_t node_id = ni - > node_id ;
uint64_t node_id = ni - > node_id ;
if ( node_id = = 0 | | node_id = = mgr - > instance - > node_id ) { if ( cb ) cb ( CONN_MGR_ERR_INTERNAL , node_id , cb_arg ) ; return CONN_MGR_ERR_INTERNAL ; }
if ( node_id = = 0 | | node_id = = mgr - > instance - > node_id ) { if ( cb ) cb ( CONN_MGR_ERR_INTERNAL , node_id , cb_arg ) ; return CONN_MGR_ERR_INTERNAL ; }
struct TOPO_GROUP * group = mgr - > group ;
struct TOPO_GROUP * group = mgr - > group ;
@ -1386,7 +1459,14 @@ int conn_mgr_connect_from_invite(struct CONN_MGR* mgr, struct TOPO_NODE* ni,
a4 - > type = TOPO_ADDR_NAT ; a4 - > protocol = src - > protocol ; a4 - > socket_id = 0 ;
a4 - > type = TOPO_ADDR_NAT ; a4 - > protocol = src - > protocol ; a4 - > socket_id = 0 ;
a4 - > next = group_ni - > v4_addrs ; group_ni - > v4_addrs = a4 ;
a4 - > next = group_ni - > v4_addrs ; group_ni - > v4_addrs = a4 ;
}
}
if ( ! group_ni - > v4_addrs ) { u_free ( group_ni ) ; if ( cb ) cb ( CONN_MGR_ERR_NO_ADDRESSES , node_id , cb_arg ) ; return CONN_MGR_ERR_NO_ADDRESSES ; }
for ( const struct TOPO_ADDR6 * src6 = ni - > v6_addrs ; src6 ; src6 = src6 - > next ) {
struct TOPO_ADDR6 * a6 = memory_pool_alloc ( groups - > v6_addr_pool ) ;
if ( ! a6 ) continue ;
memset ( a6 , 0 , sizeof ( * a6 ) ) ; memcpy ( a6 - > addr , src6 - > addr , 16 ) ; a6 - > port = src6 - > port ;
a6 - > type = TOPO_ADDR_NAT ; a6 - > protocol = src6 - > protocol ; a6 - > socket_id = 0 ;
a6 - > next = group_ni - > v6_addrs ; group_ni - > v6_addrs = a6 ;
}
if ( ! group_ni - > v4_addrs & & ! group_ni - > v6_addrs ) { u_free ( group_ni ) ; if ( cb ) cb ( CONN_MGR_ERR_NO_ADDRESSES , node_id , cb_arg ) ; return CONN_MGR_ERR_NO_ADDRESSES ; }
group_ni = topo_node_registry_acquire ( groups , group_ni ) ; /* group_ni now owned by registry (ref=1) */
group_ni = topo_node_registry_acquire ( groups , group_ni ) ; /* group_ni now owned by registry (ref=1) */
if ( ! group_ni ) { if ( cb ) cb ( CONN_MGR_ERR_INTERNAL , node_id , cb_arg ) ; return CONN_MGR_ERR_INTERNAL ; }
if ( ! group_ni ) { if ( cb ) cb ( CONN_MGR_ERR_INTERNAL , node_id , cb_arg ) ; return CONN_MGR_ERR_INTERNAL ; }
@ -1433,6 +1513,25 @@ int conn_mgr_connect_from_invite(struct CONN_MGR* mgr, struct TOPO_NODE* ni,
s = s - > next ;
s = s - > next ;
}
}
}
}
for ( const struct TOPO_ADDR6 * a6 = group_ni - > v6_addrs ; a6 ; a6 = a6 - > next ) {
if ( ! ( a6 - > protocol & TOPO_PROTO_UDP ) ) continue ;
uint8_t tclass = cm_classify_v6_addr ( a6 - > addr ) ; if ( tclass = = CM_V6_OTHER ) continue ;
struct ETCP_SOCKET * s = mgr - > instance - > etcp_sockets ;
while ( s ) {
if ( cm_sock_v6_classify ( s ) = = tclass ) {
if ( ! udp_conn ) {
udp_conn = etcp_connection_create ( mgr - > instance , NULL ) ;
if ( udp_conn ) {
etcp_conn_add_init_cbk ( udp_conn , cm_invite_init_cb , inv ) ;
sc_init_ctx ( & udp_conn - > crypto_ctx , & mgr - > instance - > my_keys ) ;
sc_set_peer_public_key ( & udp_conn - > crypto_ctx , group_ni - > public_key , 0 ) ;
}
}
if ( udp_conn ) { cm_add_v6_link ( udp_conn , a6 - > addr , a6 - > port , s ) ; inv - > conn = udp_conn ; udp_connected = 1 ; }
}
s = s - > next ;
}
}
/* ── TCP: first address ── */
/* ── TCP: first address ── */
for ( const struct TOPO_ADDR4 * a = group_ni - > v4_addrs ; a ; a = a - > next ) {
for ( const struct TOPO_ADDR4 * a = group_ni - > v4_addrs ; a ; a = a - > next ) {
@ -1453,6 +1552,24 @@ int conn_mgr_connect_from_invite(struct CONN_MGR* mgr, struct TOPO_NODE* ni,
}
}
break ;
break ;
}
}
for ( const struct TOPO_ADDR6 * a6 = group_ni - > v6_addrs ; a6 ; a6 = a6 - > next ) {
if ( ! ( a6 - > protocol & TOPO_PROTO_TCP ) ) continue ;
struct sockaddr_in6 sin6 ; memset ( & sin6 , 0 , sizeof ( sin6 ) ) ; sin6 . sin6_family = AF_INET6 ;
memcpy ( & sin6 . sin6_addr , a6 - > addr , 16 ) ; sin6 . sin6_port = htons ( a6 - > port ) ;
struct sockaddr_storage sa ; memcpy ( & sa , & sin6 , sizeof ( sin6 ) ) ;
struct stcp_link_config tcp_cfg6 = {
. ua = mgr - > instance - > ua , . my_keys = & mgr - > instance - > my_keys , . inst = mgr - > instance ,
. peer_pubkey = group_ni - > public_key , . peer_pubkey_mode = 0 ,
. remote_addr = & sa , . remote_port = a6 - > port ,
} ;
inv - > tcp_link = stcp_link_connect ( & tcp_cfg6 ) ;
if ( inv - > tcp_link ) {
stcp_link_set_on_ready ( inv - > tcp_link , cm_tcp_ready_cb , inv ) ;
stcp_link_set_on_close ( inv - > tcp_link , cm_tcp_close_cb , inv ) ;
tcp_connected = 1 ;
}
break ;
}
if ( ! udp_connected & & ! tcp_connected ) {
if ( ! udp_connected & & ! tcp_connected ) {
cm_invite_fail ( inv , CONN_MGR_ERR_UNREACHABLE ) ; return CONN_MGR_ERR_UNREACHABLE ;
cm_invite_fail ( inv , CONN_MGR_ERR_UNREACHABLE ) ; return CONN_MGR_ERR_UNREACHABLE ;