From 5e4f6a6fa366678030cbec9ac0b07cf9dac5f7f9 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Wed, 14 Oct 2026 19:13:29 +0800 Subject: [PATCH] Time client-side TCP connections when idle, not only while connecting ss-local, ss-tunnel and ss-redir only timed the upstream connect (as the C relays did), so a client that never finished its SOCKS handshake, or a stream whose peer vanished without a FIN, held a pool slot forever. With the pool now a hard cap that pauses accepting when full, enough of them stopped the listener for good. Every connection now starts with the idle deadline, connected() re-arms it, and traffic refreshes it for all kinds (the idle timeout keeps its 24 h floor, MIN_TCP_IDLE_TIMEOUT). --- src/relay/tcp.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/relay/tcp.cpp b/src/relay/tcp.cpp index 086d3aa2..118546cf 100644 --- a/src/relay/tcp.cpp +++ b/src/relay/tcp.cpp @@ -412,6 +412,10 @@ Flow Connection::start(ss_socket_t fd) noexcept return close(); } const TcpConfig &cfg = relay_->config_; + // Every connection is timed from the start, so a client that never + // finishes its handshake cannot hold a pool slot forever. Later stages + // replace this with their own deadline. + relay_->set_deadline(*this, Timed::idle); switch (cfg.kind) { case Kind::local: if (verbose) { @@ -443,7 +447,6 @@ Flow Connection::start(ss_socket_t fd) noexcept return close(); } stage_ = Stage::header; - relay_->set_deadline(*this, Timed::idle); update_interest(); return Flow::proceed; } @@ -974,7 +977,7 @@ Flow Connection::server_connect(const sockaddr *target) noexcept Flow Connection::connected() noexcept { if (client_kind()) { - relay_->clear_deadline(*this); // only the connect was timed + relay_->set_deadline(*this, Timed::idle); // replaces the connect deadline } stage_ = Stage::stream; if (pump_to_upstream() == Flow::closed) { @@ -1044,7 +1047,7 @@ Connection::Pull Connection::pull(ss_socket_t fd, bool decode, FixedBufferset_deadline(*this, Timed::idle); } std::span in(relay_->scratch_.data(), *r);