@ -154,24 +154,20 @@ int cm_has_local_addr(struct CONN_MGR* mgr, struct TOPO_GROUP_NODE* nq) {
/* ═══════ entries ═══════ */
struct CONN_MGR_ENTRY * cm_find_entry ( struct CONN_MGR * mgr , uint64_t node_id ) {
for ( size_t i = 0 ; i < mgr - > entry_count ; i + + )
if ( mgr - > entries [ i ] . node_id = = node_id & & mgr - > entries [ i ] . state ! = CONN_MGR_STATE_DISCONNECTED )
return & mgr - > entries [ i ] ;
return NULL ;
if ( ! mgr | | ! mgr - > entries ) return NULL ;
struct ll_entry * e = queue_find_data_by_index ( mgr - > entries , & node_id ) ;
return e ? ( struct CONN_MGR_ENTRY * ) e : NULL ;
}
struct CONN_MGR_ENTRY * cm_ensure_entry ( struct CONN_MGR * mgr , uint64_t node_id ) {
struct CONN_MGR_ENTRY * e = cm_find_entry ( mgr , node_id ) ;
if ( e ) return e ;
if ( mgr - > entry_count > = mgr - > entry_capacity ) {
size_t cap = mgr - > entry_capacity * 2 ;
struct CONN_MGR_ENTRY * ne = u_realloc ( mgr - > entries , cap * sizeof ( struct CONN_MGR_ENTRY ) ) ;
if ( ! ne ) { DEBUG_ERROR ( DEBUG_CATEGORY_GENERAL , " conn_mgr: realloc entries failed " ) ; return NULL ; }
memset ( ne + mgr - > entry_capacity , 0 , ( cap - mgr - > entry_capacity ) * sizeof ( struct CONN_MGR_ENTRY ) ) ;
mgr - > entries = ne ; mgr - > entry_capacity = cap ;
}
struct CONN_MGR_ENTRY * new_e = & mgr - > entries [ mgr - > entry_count + + ] ;
memset ( new_e , 0 , sizeof ( * new_e ) ) ; new_e - > node_id = node_id ; new_e - > mgr = mgr ;
struct ll_entry * qe = queue_entry_new ( sizeof ( struct CONN_MGR_ENTRY ) - sizeof ( struct ll_entry ) ) ;
if ( ! qe ) { DEBUG_ERROR ( DEBUG_CATEGORY_GENERAL , " conn_mgr: queue_entry_new failed " ) ; return NULL ; }
struct CONN_MGR_ENTRY * new_e = ( struct CONN_MGR_ENTRY * ) qe ;
memset ( ( uint8_t * ) new_e + sizeof ( struct ll_entry ) , 0 , sizeof ( * new_e ) - sizeof ( struct ll_entry ) ) ;
new_e - > node_id = node_id ; new_e - > mgr = mgr ;
queue_data_put_with_index ( mgr - > entries , qe ) ;
return new_e ;
}
@ -192,6 +188,9 @@ void cm_entry_cleanup(struct CONN_MGR_ENTRY* entry) {
entry - > handles = NULL ;
cm_clear_nodeinfo ( entry - > mgr , entry - > node_id ) ;
entry - > state = CONN_MGR_STATE_DISCONNECTED ; entry - > conn_type = CONN_TYPE_NONE ;
{ struct CONN_MGR * m = entry - > mgr ;
queue_remove_data ( m - > entries , & entry - > ll ) ;
queue_entry_free ( & entry - > ll ) ; }
}
void cm_clear_nodeinfo ( struct CONN_MGR * mgr , uint64_t node_id ) {
@ -276,7 +275,7 @@ void cm_invite_ncd_callback(struct NODE_CONN_DIRECT* ncd_h, enum ncd_event ncd_e
switch ( ncd_ev ) {
case NCD_EVENT_UP :
if ( inv - > state ! = CM_INVITE_CONNECTING ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: invite INIT OK node=0x%016llx " , ( unsigned long long ) inv - > node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: invite INIT OK node=0x%016llx group=0x%016llx " , ( unsigned long long ) inv - > node_id , ( unsigned long long ) inv - > mgr - > group - > group _id ) ;
inv - > state = CM_INVITE_WAIT_INFO ;
{ struct CM_INVITE_REQ req ; memset ( & req , 0 , sizeof ( req ) ) ;
req . cmd = ETCP_RT_ID_CONN_MGR ; req . subcmd = CM_SUBCMD_INVITE_INFO_REQ ; req . group_id = inv - > mgr - > group - > group_id ;
@ -306,8 +305,10 @@ struct CONN_MGR* conn_mgr_init(struct TOPO_GROUP* group) {
struct CONN_MGR * mgr = u_calloc ( 1 , sizeof ( struct CONN_MGR ) ) ;
if ( ! mgr ) { DEBUG_ERROR ( DEBUG_CATEGORY_GENERAL , " alloc failed " ) ; return NULL ; }
mgr - > instance = group - > instance ; mgr - > group = group ;
mgr - > entry_capacity = 8 ; mgr - > direct_timeout_ms = CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS ;
mgr - > entries = u_calloc ( mgr - > entry_capacity , sizeof ( struct CONN_MGR_ENTRY ) ) ;
mgr - > direct_timeout_ms = CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS ;
mgr - > entries = queue_new ( mgr - > instance - > ua , 256 ,
offsetof ( struct CONN_MGR_ENTRY , node_id ) - sizeof ( struct ll_entry ) ,
8 , " conn_mgr_entries " ) ;
if ( ! mgr - > entries ) { DEBUG_ERROR ( DEBUG_CATEGORY_GENERAL , " entries alloc failed " ) ; u_free ( mgr ) ; return NULL ; }
mgr - > bg_ping_timer = uasync_set_timeout ( mgr - > instance - > ua , CONN_MGR_BG_PING_INTERVAL_TB , mgr , cm_bg_ping_timer_cb , " conn_mgr_bg_ping " ) ;
mgr - > candidate_ping_timer = uasync_set_timeout ( mgr - > instance - > ua , CONN_MGR_CANDIDATE_PING_TB , mgr , cm_candidate_ping_timer_cb , " conn_mgr_cand_ping " ) ;
@ -326,16 +327,18 @@ void conn_mgr_destroy(struct CONN_MGR* mgr) {
/* Отвязываемся от etcp_router (если ещё не отвязаны) */
etcp_router_unbind ( mgr - > instance , ETCP_RT_ID_CONN_MGR ) ;
etcp_unbind ( mgr - > instance , ETCP_RT_ID_CONN_MGR ) ;
for ( size_t i = 0 ; i < mgr - > entry_count ; i + + ) cm_entry_cleanup ( & mgr - > entries [ i ] ) ;
while ( mgr - > invite_list ) cm_invite_fail ( mgr - > invite_list ) ;
while ( mgr - > exchange_pending ) {
struct cm_exchange_pending * ep = mgr - > exchange_pending ; mgr - > exchange_pending = ep - > next ;
if ( ep - > timer ) uasync_cancel_timeout ( mgr - > instance - > ua , ep - > timer ) ;
u_free ( ep ) ;
}
while ( mgr - > reverse_pending ) { struct cm_reverse_pending * rp = mgr - > reverse_pending ; mgr - > reverse_pending = rp - > next ; u_free ( rp ) ; }
u_free ( mgr - > entries ) ; mgr - > initialized = 0 ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: destroyed, entries=%zu " , ( size_t ) mgr - > entry_count ) ;
{ size_t ec = queue_entry_count ( mgr - > entries ) ;
struct ll_entry * e = mgr - > entries - > head ;
while ( e ) { struct ll_entry * next = e - > next ; struct CONN_MGR_ENTRY * entry = ( struct CONN_MGR_ENTRY * ) e ; cm_entry_cleanup ( entry ) ; e = next ; }
while ( mgr - > invite_list ) cm_invite_fail ( mgr - > invite_list ) ;
while ( mgr - > exchange_pending ) {
struct cm_exchange_pending * ep = mgr - > exchange_pending ; mgr - > exchange_pending = ep - > next ;
if ( ep - > timer ) uasync_cancel_timeout ( mgr - > instance - > ua , ep - > timer ) ;
u_free ( ep ) ;
}
while ( mgr - > reverse_pending ) { struct cm_reverse_pending * rp = mgr - > reverse_pending ; mgr - > reverse_pending = rp - > next ; u_free ( rp ) ; }
queue_free ( mgr - > entries ) ; mgr - > initialized = 0 ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: destroyed, entries=%zu " , ec ) ; }
u_free ( mgr ) ;
}
@ -743,6 +746,9 @@ void cm_handle_invite_info_resp(struct CONN_MGR* mgr, const uint8_t* data, size_
if ( inv - > mgr - > instance - > topo_sqlite_db ) topo_node_sqlite_node_put ( inv - > mgr - > instance - > topo_sqlite_db , inv - > mgr - > instance - > topo_groups , inv - > temp_nq , ( time_t ) ( get_time_tb ( ) / 10000 ) ) ;
}
if ( inv - > overall_timer ) { uasync_cancel_timeout ( inv - > mgr - > instance - > ua , inv - > overall_timer ) ; inv - > overall_timer = NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: invite JOIN OK node=0x%016llx group=0x%016llx name=%.*s " ,
( unsigned long long ) inv - > node_id , ( unsigned long long ) inv - > mgr - > group - > group_id ,
resp - > node_name_len , resp - > node_name_len ? ( const char * ) resp - > node_name : " " ) ;
if ( inv - > cb ) inv - > cb ( inv - > handle , inv - > node_id , inv - > mgr - > group - > group_id , CONN_EVENT_JOIN , inv - > cb_arg ) ;
cm_invite_cleanup ( inv ) ;
}
@ -764,7 +770,17 @@ void cm_invite_fail(struct cm_invite_pending* inv) {
if ( e ) queue_remove_data ( inv - > mgr - > instance - > tcp_connections , e ) ;
stcp_link_close ( inv - > tcp_link ) ; inv - > tcp_link = NULL ;
}
if ( inv - > ncd_handle ) { node_conn_direct_close ( inv - > ncd_handle ) ; inv - > ncd_handle = NULL ; }
if ( inv - > ncd_handle ) {
/* проверяем: есть ли зарегистрированные хендлы на этом соединении */
struct TOPO_GROUP_NODE * nq = topo_node_find_by_id ( inv - > mgr - > group , inv - > node_id ) ;
if ( nq & & nq - > handle ! = NULL ) {
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: invite fail node=0x%016llx — handle registered, skip NCD close " ,
( unsigned long long ) inv - > node_id ) ;
} else {
node_conn_direct_close ( inv - > ncd_handle ) ;
}
inv - > ncd_handle = NULL ;
}
if ( inv - > temp_nq ) {
queue_remove_data ( inv - > mgr - > group - > nodes , & inv - > temp_nq - > ll ) ;
topo_nodeq_free_group_fields ( inv - > mgr - > instance - > topo_groups , inv - > temp_nq ) ;
@ -788,7 +804,7 @@ static void cm_tcp_ready_cb(struct stcp_link* link, void* arg) {
if ( ! qe ) { cm_invite_fail ( inv ) ; return ; }
{ struct tcp_conn_entry * te = ( struct tcp_conn_entry * ) qe - > data ; te - > node_id = inv - > node_id ; te - > link = link ; te - > etcp_conn = etcp ; }
queue_data_put_with_index ( inv - > mgr - > instance - > tcp_connections , qe ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: TCP invite ready node=0x%016llx " , ( unsigned long long ) inv - > node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: TCP invite ready node=0x%016llx group=0x%016llx " , ( unsigned long long ) inv - > node_id , ( unsigned long long ) inv - > mgr - > group - > group _id ) ;
inv - > state = CM_INVITE_WAIT_INFO ;
{ struct CM_INVITE_REQ req ; memset ( & req , 0 , sizeof ( req ) ) ;
req . cmd = ETCP_RT_ID_CONN_MGR ; req . subcmd = CM_SUBCMD_INVITE_INFO_REQ ; req . group_id = inv - > mgr - > group - > group_id ;
@ -816,7 +832,11 @@ static int cm_invite_tcp_connect(struct cm_invite_pending* inv, const struct TOP
struct stcp_link_config cfg = { . ua = inv - > mgr - > instance - > ua , . my_keys = & inv - > mgr - > instance - > my_keys , . inst = inv - > mgr - > instance ,
. peer_pubkey = ni - > public_key , . peer_pubkey_mode = 0 , . remote_addr = & sa , . remote_port = a - > port } ;
inv - > tcp_link = stcp_link_connect ( & cfg ) ;
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 ) ; return 1 ; }
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 ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: TCP connect %d.%d.%d.%d:%d node=0x%016llx group=0x%016llx " ,
a - > addr [ 0 ] , a - > addr [ 1 ] , a - > addr [ 2 ] , a - > addr [ 3 ] , ( int ) a - > port ,
( unsigned long long ) inv - > node_id , ( unsigned long long ) inv - > mgr - > group - > group_id ) ;
return 1 ; }
return 0 ;
}
for ( const struct TOPO_ADDR6 * a6 = ni - > v6_addrs ; a6 ; a6 = a6 - > next ) {
@ -831,7 +851,10 @@ static int cm_invite_tcp_connect(struct cm_invite_pending* inv, const struct TOP
struct stcp_link_config cfg = { . ua = inv - > mgr - > instance - > ua , . my_keys = & inv - > mgr - > instance - > my_keys , . inst = inv - > mgr - > instance ,
. peer_pubkey = ni - > public_key , . peer_pubkey_mode = 0 , . remote_addr = & sa , . remote_port = a6 - > port } ;
inv - > tcp_link = stcp_link_connect ( & cfg ) ;
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 ) ; return 1 ; }
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 ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: TCP6 connect port=%d node=0x%016llx group=0x%016llx " ,
( int ) a6 - > port , ( unsigned long long ) inv - > node_id , ( unsigned long long ) inv - > mgr - > group - > group_id ) ;
return 1 ; }
return 0 ;
}
return 0 ;
@ -905,7 +928,17 @@ int conn_mgr_open_invite(struct UTUN_INSTANCE* inst,
if ( ! udp & & ! tcp ) { cm_invite_fail ( inv ) ; if ( out_handle ) * out_handle = NULL ; return - 1 ; }
inv - > overall_timer = uasync_set_timeout ( inst - > ua , CM_INVITE_DEFAULT_TIMEOUT_MS * 10 , inv , cm_invite_overall_timeout , " conn_mgr_invite " ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: invite started node=0x%016llx group=0x%016llx " ,
( unsigned long long ) nid , ( unsigned long long ) group_id ) ;
{
char addrs [ 256 ] = " " ; int aoff = 0 ;
for ( const struct TOPO_ADDR4 * a = gni - > v4_addrs ; a ; a = a - > next )
aoff + = snprintf ( addrs + aoff , sizeof ( addrs ) - ( size_t ) aoff , " %d.%d.%d.%d:%d(%s) " ,
a - > addr [ 0 ] , a - > addr [ 1 ] , a - > addr [ 2 ] , a - > addr [ 3 ] , ( int ) a - > port ,
a - > protocol = = TOPO_PROTO_UDP ? " UDP " : a - > protocol = = TOPO_PROTO_TCP ? " TCP " : " ? " ) ;
for ( const struct TOPO_ADDR6 * a6 = gni - > v6_addrs ; a6 ; a6 = a6 - > next )
aoff + = snprintf ( addrs + aoff , sizeof ( addrs ) - ( size_t ) aoff , " [v6]:%d(%s) " , ( int ) a6 - > port ,
a6 - > protocol = = TOPO_PROTO_UDP ? " UDP " : a6 - > protocol = = TOPO_PROTO_TCP ? " TCP " : " ? " ) ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " conn_mgr: invite started node=0x%016llx group=0x%016llx udp=%d tcp=%d%s " ,
( unsigned long long ) nid , ( unsigned long long ) group_id , udp , tcp , addrs ) ;
}
return 0 ;
}