From 4b7a1656fce3bb9e1e75721d5b63abc1b5aff60e Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sun, 31 May 2026 00:02:01 +0300 Subject: [PATCH] final RST fix: tcp_recved before closing_tun, feed stop after CLOSE, free unsent before tcp_close, proxy_try_close helper - proxy_recv_cb(p==NULL): tcp_recved(pcb,gap) before closing_tun - proxy_feed_from_transport: stop when closing_sent - proxy_poll_cb cleanup: free unsent before tcp_close - proxy_try_close helper: shared between poll_cb (500ms) and recv_cb - pending_out check: don't close if data still queued for exit - Configs: traffic=info, tun=info for diagnostics --- src/tcp_proxy.c | 28 +++++++++++++++++----------- tests/tcp_proxy_full/client.conf | 4 ++-- tests/tcp_proxy_full/exit.conf | 4 +--- tests/tcp_proxy_full/run_test.sh | 3 ++- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/tcp_proxy.c b/src/tcp_proxy.c index edc35ac8..95b9eaf4 100644 --- a/src/tcp_proxy.c +++ b/src/tcp_proxy.c @@ -52,6 +52,7 @@ static int etcp_transport_send(struct tcp_proxy_transport* t, const uint8_t* da static void etcp_transport_close(struct tcp_proxy_transport* t); static void etcp_transport_destroy(struct tcp_proxy_transport* t); static void sock_transport_connect(struct sock_transport* st); +static void proxy_try_close(struct proxy_conn *pc); static struct sock_transport* sock_transport_create(struct proxy_conn* pc, struct UASYNC* ua); static struct etcp_transport* etcp_transport_create(struct proxy_conn* pc, struct UTUN_INSTANCE* inst, uint64_t remote_node_id); @@ -308,20 +309,25 @@ static void proxy_err_cb(void *arg, err_t err) { if (pc->transport && !pc->closing_sent) pc->transport->ops->close(pc->transport); } +static void proxy_try_close(struct proxy_conn *pc) { + if (!pc->closing_tun || pc->closing_sent || pc->closing_rem) return; + if (!pc->transport || !pc->pcb) return; + uint32_t pending = pc->transport_to_uip ? queue_entry_count(pc->transport_to_uip) : 0; + uint32_t pending_out = pc->uip_to_transport ? queue_entry_count(pc->uip_to_transport) : 0; + int done = (pending == 0 && pending_out == 0 && pc->pcb->unsent == NULL && pc->pcb->unacked == NULL); + uint32_t sndbuf = tcp_sndbuf(pc->pcb); + if (done || sndbuf == 0) { + DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLOSE stream=%016llx tun=1 pending=%u pending_out=%u done=%d sndbuf=%u cwnd=%u unsent=%p unacked=%p", + (unsigned long long)pc->remote_stream_id, pending, pending_out, done, sndbuf, + pc->pcb->cwnd, (void*)pc->pcb->unsent, (void*)pc->pcb->unacked); + pc->transport->ops->close(pc->transport); + } +} + static err_t proxy_poll_cb(void *arg, struct tcp_pcb *pcb) { struct proxy_conn *pc = (struct proxy_conn *)arg; if (!pc) return LERR_OK; - if (pc->closing_tun && !pc->closing_sent && !pc->closing_rem && pc->transport && pc->pcb) { - uint32_t pending = pc->transport_to_uip ? queue_entry_count(pc->transport_to_uip) : 0; - int done = (pending == 0 && pc->pcb->unsent == NULL && pc->pcb->unacked == NULL); - uint32_t sndbuf = tcp_sndbuf(pc->pcb); - if (done || sndbuf == 0) { - DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLOSE stream=%016llx tun=1 pending=%u done=%d sndbuf=%u cwnd=%u unsent=%p unacked=%p", - (unsigned long long)pc->remote_stream_id, pending, done, sndbuf, - pc->pcb->cwnd, (void*)pc->pcb->unsent, (void*)pc->pcb->unacked); - pc->transport->ops->close(pc->transport); - } - } + proxy_try_close(pc); if (pc->closing_tun && (pc->closing_rem || pc->closing_sent) && pc->pcb) { DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "PROXY CLEANUP stream=%016llx tun=1 rem=%d sent=%d cwnd=%u sndbuf=%u unsent=%p unacked=%p", (unsigned long long)pc->remote_stream_id, pc->closing_rem, pc->closing_sent, diff --git a/tests/tcp_proxy_full/client.conf b/tests/tcp_proxy_full/client.conf index fdbd7bab..f6e4c1d7 100644 --- a/tests/tcp_proxy_full/client.conf +++ b/tests/tcp_proxy_full/client.conf @@ -25,5 +25,5 @@ via_node=0xAAAA000000000001 connection=info socket=info general=info -traffic=debug -tun=debug +traffic=info +tun=info diff --git a/tests/tcp_proxy_full/exit.conf b/tests/tcp_proxy_full/exit.conf index 7b7feffc..887a297f 100644 --- a/tests/tcp_proxy_full/exit.conf +++ b/tests/tcp_proxy_full/exit.conf @@ -19,6 +19,4 @@ enabled=yes [debug] connection=info socket=info -general=info -traffic=debug -tun=debug +traffic=info diff --git a/tests/tcp_proxy_full/run_test.sh b/tests/tcp_proxy_full/run_test.sh index 5e58e438..2d587d36 100755 --- a/tests/tcp_proxy_full/run_test.sh +++ b/tests/tcp_proxy_full/run_test.sh @@ -85,7 +85,8 @@ cleanup() { wait_for_etcp() { for i in $(seq 1 30); do - grep -q "Connection established" "$LOG_DIR/exit_utun.log" 2>/dev/null && return 0 + grep -q "Connection established\|initialized and marked as UP (client)" "$LOG_DIR/exit_utun.log" 2>/dev/null && return 0 + grep -q "initialized and marked as UP (client)" "$LOG_DIR/client_utun.log" 2>/dev/null && return 0 sleep 0.5 done return 1