@ -291,6 +291,7 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
void etcp_fire_conn_status ( struct ETCP_CONN * etcp , int status ) {
if ( ! etcp | | ! etcp - > instance ) return ;
if ( etcp - > state = = 2 & & status ! = ETCP_CONN_STATUS_DELETE ) return ; // при state==2 допустим только DELETE
static const char * names [ ] = { " NEW " , " UP " , " DOWN " , " DELETE " } ;
DEBUG_INFO ( DEBUG_CATEGORY_GENERAL , " [%s] Connection status changed to %s " , etcp - > log_name ,
( status > = 0 & & status < ( int ) ( sizeof ( names ) / sizeof ( names [ 0 ] ) ) ) ? names [ status ] : " ? " ) ;
@ -300,6 +301,7 @@ void etcp_fire_conn_status(struct ETCP_CONN* etcp, int status) {
void etcp_cbk_fire ( struct ETCP_CONN * conn , int event ) {
if ( ! conn ) return ;
if ( conn - > state = = 2 ) return ; // после DELETE per-connection события не идут
static const char * names [ ] = { " INIT " , " REINIT " , " UP " , " DOWN " , " NODE_CHANGED " } ;
int idx = 0 , e = event ; while ( e > > = 1 ) idx + + ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " [%s] callback event: %s " , conn - > log_name , ( idx > = 0 & & idx < ( int ) ( sizeof ( names ) / sizeof ( names [ 0 ] ) ) ) ? names [ idx ] : " ? " ) ;
@ -310,6 +312,7 @@ void etcp_cbk_fire(struct ETCP_CONN* conn, int event) {
}
static void etcp_on_up ( struct ETCP_CONN * etcp ) {
if ( etcp - > state = = 2 ) return ; // defensive: после DELETE UP не стреляет
int total_links = 0 ; for ( struct ETCP_LINK * l = etcp - > links ; l ; l = l - > next ) total_links + + ;
uint64_t elapsed_ms = ( get_time_tb ( ) - etcp - > setup_start_tb ) / 10 ;
struct strbuf sb = strbuf_new ( ) ; int any = 0 ;
@ -400,8 +403,14 @@ void etcp_connection_close(struct ETCP_CONN* etcp) {
// === PHASE 1: detach from external world ===
/* Финальный DOWN если соединение ещё UP (переход UP→DOWN до state=2):
с т р о г а я п о с л е д о в а т е л ь н о с т ь . . . → UP → DOWN → DELETE , б е з д у б л е й . */
if ( etcp - > links_up ! = 0 ) {
etcp - > links_up = 0 ;
etcp_cbk_fire ( etcp , ETCP_CBK_EVENT_DOWN ) ;
}
etcp - > state = 2 ; // deleted — blocks ref_take and etcp_send immediately
if ( etcp - > links_up ! = 0 ) etcp - > links_up = 0 ;
if ( etcp - > peer_sleep_phase ) {
etcp - > peer_sleep_phase = 0 ;
@ -411,7 +420,6 @@ void etcp_connection_close(struct ETCP_CONN* etcp) {
etcp_fire_conn_status ( etcp , ETCP_CONN_STATUS_DELETE ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " [%s] close: state=2 conn=%p peer=%016llx (DELETE fired) " , etcp - > log_name , ( void * ) etcp , ( unsigned long long ) etcp - > peer_node_id ) ;
etcp_cbk_fire ( etcp , ETCP_CBK_EVENT_DOWN ) ;
// Cancel active timers
if ( etcp - > retrans_timer ) { uasync_cancel_timeout ( etcp - > instance - > ua , etcp - > retrans_timer ) ; etcp - > retrans_timer = NULL ; }
@ -1066,6 +1074,7 @@ static void ack_response_timer_cb(void* arg) {// проверяем неотпр
static void etcp_link_ready_callback ( struct ETCP_CONN * etcp ) {
DEBUG_TRACE ( DEBUG_CATEGORY_ETCP , " " ) ;
if ( ! etcp ) return ;
if ( etcp - > state = = 2 ) return ; // удалённый conn не поднимается
if ( etcp - > tx_state = = 0 ) {
DEBUG_WARN ( DEBUG_CATEGORY_ETCP , " ETCP not ready, skip link state change " ) ;