- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
- etcp_router: SVC_ROUTE_HDR (+8B), ETCP_ROUTER_CONN/TRANSIT_QUEUE хеши расширены под group_id
- Все caller'ы (proxy, routing, conn_mgr, nat, chatgui, tests) обновлены
- topo_group: глобальный реестр TOPO_NODE по node_id, ref_count=0 при создании
- BGP-обмен активируется для всех групп (а не только дефолтной)
- Протокол: group_id добавлен в WITHDRAW/TABLE_REQ/TABLE_COMPLETE/ERR_GROUP_MISMATCH
- Per-connection коллбэки заменены на instance-level conn_status
- msg_transport полностью удалён из проекта
57/57 тестов
waiter-based backpressure (commit ba14e31e) could starve HTTPS CONNECT
worker under concurrent 4-worker load — send_q never drained below threshold
fast enough for the waiter to fire before curl timed out (exit=28).
Add retry_timer (500ms, force=1) alongside etcp_router_on_send_ready
waiter: waiter gives instant wake when send_q drains, timer guarantees
delivery via force=1 if waiter hasn't fired in time.
Also improve socks_proxy DEBUG diagnostics in backpressure branches.
- tcp_proxy_server: drain_cb uses etcp_router_on_send_ready instead of retry_timer
- socks_proxy: on_read_cb + tx_waiter_cb use etcp_router_on_send_ready instead of waiter_register
- Result: FIFO round-robin via ll_queue waiters on send_q, all streams get fair share
- No timers — wakeup is event-driven via queue_data_get → check_waiters
- TCP backpressure: read_queue callback_suspended prevents over-reading
- etcp_connections: fix link leak & UAF in etcp_socket_remove — remove_link inside etcp_link_close shifts array, skip NULL set and i++
- stcp_server: fix UAF in stcp_conn_process_recv — defer free via uasync_call_soon after stcp_conn_do_close
- etcp: save pkt_len before queue_data_put to output_queue (callback may free entry synchronously)
- socks_proxy: add pool bounds check before memcpy, UINT16_MAX truncation guard, freed flag
- tcp_proxy_server: reorder cleanup (cancel waiters before tcp_conn_destroy), UINT16_MAX guard
- test_route6_lib: increase nodes[] array to STRESS_NODES + STRESS_OPS
Previous edit accidentally removed tcp_conn_destroy, timer cancellations,
and etcp_router_cancel_send_ready from conn_free. Without tcp_conn_destroy
the socket was never removed from uasync, causing repeated EPOLLERR →
repeated conn_free on freed memory → double-free crash.
Added debug logs for freed guard entry and u_free.
error_cb can fire twice for the same fd in one epoll batch,
or conn_free called from multiple callbacks during restart/shutdown.
freed flag makes conn_free idempotent.
tcp_conn_destroy: set read/write queue callbacks to NULL before
queue_free to stop deferred autofetch (drain_cb on freed rc).
write_on_get_cb: throttle consumer_ack to every 8th write_queue
dequeue instead of every single one (was 30+ ACK/sec).
ack_batch field in tcp_proxy_server_conn.
handle_connect: send first consumer_ack after setting consumer_ack=1
to unblock client router — fixes rq=32/send_q=256 deadlock.
diag_timer_cb: added send_q=N to DIAG line for instant root cause visibility.
read_queue_drain_cb: SOCK:BACKPRESSURE log with send_q count.
write_on_get_cb: SOCK:ACK debug log on each consumer_ack.
1-sec diag_timer_cb prints rq/wq counts+bytes, outstanding pool
allocations, tcp kernel buffer sizes (SO_RCVBUF/SO_SNDBUF).
Started in handle_connect, cancelled in conn_free.
External code pushes to write_queue directly (entry_pool + data_pool).
Added queue_set_threshold(write_queue, 32, 0) for write backpressure.
Tests split data into write_chunk_size chunks before queue put.
lib/u_async: uasync_set_socket_read/write — O(1) EPOLL_CTL_MOD toggle per socket
lib/ll_queue: queue_set_empty_callback — one-shot deferred callback on queue drain
lib/tcp_io: TCP connection management via uasync + ll_queue with pool alloc
- read: direct recv into pool buffer, high/low water flow control
- write: autofetch via ll_queue callback, partial send via write_buf
- on_fin/on_error/on_flushed callbacks, FIN deferred until read_queue drained
- getpeername for pre-connected socket detection
tcp_proxy_server: migrated to tcp_io (22→13 fields, 437→270 lines, -7 functions)
tests: test_tcp_io (5 tests), test_tcp_proxy_server rewritten for tcp_conn
- tcp_proxy_client_handle_error: set error flag + send CLOSE once if flag was clear
- tcp_proxy_client_handle_data/handle_close: drop silently, don't send ERROR back
- tcp_proxy_server_handle_data/handle_close: drop silently, don't send ERROR back
- Add recv→send 1MB integration test (3 clients × 3 requests, shell + python)