diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 7bb06828..198a1c61 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -2010,7 +2010,8 @@ static int etcp_link_publish_rx(struct ETCP_LINK* link, int old_state, int old_s conn->log_name, link->local_link_id, old_status, link->link_status, link->recv_keepalive, link->remote_keepalive, link->link_state, link->initialized); if (old_status && !link->link_status) etcp_on_link_down(conn, link); - else if (link->initialized && link->link_status) loadbalancer_link_ready(link); + else if (link->initialized && link->link_status && (old_status != link->link_status || old_state != link->link_state)) + loadbalancer_link_ready(link); return etcp_link_rx_alive(conn, link); } diff --git a/src/transport_layer/etcp_connections.h b/src/transport_layer/etcp_connections.h index 870e6a99..e974b879 100644 --- a/src/transport_layer/etcp_connections.h +++ b/src/transport_layer/etcp_connections.h @@ -229,8 +229,8 @@ struct ETCP_LINK { uint8_t remote_socket_id; // socket id peer uint8_t remote_only_local; // only_local flag from peer uint8_t remote_type; // CFG_SERVER_TYPE_* (type of peer's socket) - uint8_t recv_keepalive; // 1 - up, 0 - down (принимаются ли пакеты) - uint8_t remote_keepalive; // 1 - up, 0 - down (удаленная сторона сообщает - принимаются ли у нее пакеты) + uint8_t recv_keepalive; // Принимаем допустимые пакеты этого линка; INIT также обновляет RX и его deadline + uint8_t remote_keepalive; // Входной flag_up: пир принимает наши пакеты; INIT(0) не сохраняет прежнюю единицу uint8_t link_status; // 1 - up, 0 - down (итоговый статус - если есть проблемы на любой стороне - линк down) uint8_t link_state; // 0 - just init, 1 - handshake, 2 - try reconnect, 3 - connected @@ -439,6 +439,9 @@ void etcp_tcp_link_start_connect(struct ETCP_LINK *link, struct sockaddr_storage void etcp_tcp_link_start_reconnect(struct ETCP_LINK *link); +/* Принять plaintext установленного линка: session/формат проверяются до соответствующей обработки RX. + * 0 — pkt потреблён; ненулевой код — pkt остаётся вызывающему. RX/handshake callbacks могут запросить close; + * callbacks_running удерживает teardown до выхода, сброс сессии прекращает обработку старого потока. */ int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt, struct ETCP_LINK* link, size_t pkt_len); diff --git a/tests/test_etcp_init_liveness.c b/tests/test_etcp_init_liveness.c index bcb979e8..0319054b 100644 --- a/tests/test_etcp_init_liveness.c +++ b/tests/test_etcp_init_liveness.c @@ -160,6 +160,15 @@ static void close_in_callback(unsigned action) { teardown(); } +/* При отказе показать конкретные живые блоки вместо одного несовпавшего счётчика. */ +static void check_memory(size_t baseline) { + if (u_get_allocated_count() == baseline) return; + DEBUG_ERROR(DEBUG_CATEGORY_DEBUG, "Memory imbalance: baseline=%zu actual=%zu", baseline, u_get_allocated_count()); + debug_set_category_level(DEBUG_CATEGORY_SYS, DEBUG_LEVEL_DEBUG); + u_report_unfreed_blocks(); + CHECK(u_get_allocated_count() == baseline); +} + int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); debug_set_category_level(DEBUG_CATEGORY_CRYPTO, DEBUG_LEVEL_DISABLED); @@ -167,9 +176,9 @@ int main(void) { test_clock_init(10); CHECK(socket_platform_init() == 0); size_t baseline = u_get_allocated_count(); for (unsigned swapped = 0; swapped < 2; swapped++) for (unsigned order = 0; order < 2; order++) { - one_way(swapped, 1 - order); CHECK(u_get_allocated_count() == baseline); + one_way(swapped, 1 - order); check_memory(baseline); } - for (unsigned action = 1; action <= 2; action++) { close_in_callback(action); CHECK(u_get_allocated_count() == baseline); } + for (unsigned action = 1; action <= 2; action++) { close_in_callback(action); check_memory(baseline); } DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS encrypted INIT liveness: cold start, one-way loss, repeated INIT, recovery and callback close"); test_clock_finish(); socket_platform_cleanup(); return 0; }