Add a stale/never-active session reaper and raise the listen backlog

TCPServer accepted a connection and never revisited it again once it
stopped generating epoll events - a connection that completes the TCP
handshake and then goes permanently silent (an incomplete TLS
handshake, a port scanner/prober) sat in sessions forever, one
TCPSession + one fd each. sweepStaleSessions() now drops any session
that has gone 30+ seconds without a single byte of real data ever
passing through onDataReceived(), run each time a new connection
arrives rather than needing a dedicated timer. hasReceivedData latches
permanently true on a sessions first real byte, so an ordinary
connected-but-briefly-idle client is never at risk.

Also raised listen()s backlog from 20 to 128, so a burst of connection
attempts has more headroom before the kernel starts dropping SYNs.

Verified live on zephora.barant.com: a silent connection held open was
reaped within the grace window while a real concurrent connection was
left untouched, with the service remaining healthy throughout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Matt ArantandClaude Sonnet 5 committed 2026-10-06 17:54:20 +00:00
1 parent d058322cc6
commit 6483729de3
4 files changed
+103 -1

No files matched your search

+36
View File
@@ -6,6 +6,7 @@
#include "TLS.h"
#include "TLSInfo.h"
#include "IPAddress.h"
#include <chrono>
namespace core {
@@ -150,6 +151,41 @@ namespace core {
void performTLSHandshake();
///
/// Set once, at construction, and never touched again - how long
/// this specific socket has been open since accept()/connect(),
/// regardless of whether anything has actually happened on it
/// since. TCPServer::sweepStaleSessions() reads this (alongside
/// hasReceivedData below) to find connections that completed a
/// TCP handshake but then never progressed - a scanner/prober
/// probing an open port, or a TLS handshake that never finished -
/// which otherwise sit in TCPServer::sessions forever: nothing in
/// the existing design ever revisits a socket that stops
/// generating epoll events (see sweepStaleSessions()'s own doc
/// comment for the full reasoning).
///
std::chrono::steady_clock::time_point acceptedAt = std::chrono::steady_clock::now();
///
/// Flips to true the first time onDataReceived() sees a non-empty
/// read - true for both a plaintext socket's raw bytes and a TLS
/// session's already-decrypted ones, since both paths funnel
/// through the same onDataReceived() override below. A session
/// that reaches sweepStaleSessions()'s grace period with this
/// still false has never had a real exchange of any kind, TLS
/// handshake included (a stuck/incomplete SSL_accept() never
/// surfaces anything to onDataReceived) - the specific, narrow
/// condition that sweep treats as abandoned. Deliberately NOT
/// reset afterward and never consulted again once true, so a
/// legitimate client that sends something once and then goes
/// idle for a long time (an ordinary connected-but-idle game
/// session) is never at risk from this - only a connection that
/// NEVER said anything at all within the grace window is.
///
bool hasReceivedData = false;
protected:
bool term = false;
TLSInfo *tlsInfo;