From 5781ff3a937c3fc826b57caa68103d30084a6bf5 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Tue, 2 Jul 2024 16:16:59 +0300 Subject: [PATCH] Drop expired but not accepted TCP connections This commit ensures that we are not attempting to accept an expired TCP connection as we are not interested in any data that could have been accumulated in its internal buffers. Now we just drop them for good. --- lib/isc/netmgr/netmgr-int.h | 7 +++++++ lib/isc/netmgr/tcp.c | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 51bcf9430e..51da0a309e 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -641,6 +642,12 @@ struct isc_nmsocket { bool reading; bool timedout; + /*% + * A timestamp of when the connection acceptance was delayed due + * to quota. + */ + isc_nanosecs_t quota_accept_ts; + /*% * Established an outgoing connection, as client not server. */ diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index c6bb2812ff..5b475bbebc 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -549,6 +549,7 @@ tcp_connection_cb(uv_stream_t *server, int status) { &csock->quotacb, quota_accept_cb, csock); if (result == ISC_R_QUOTA) { + csock->quota_accept_ts = isc_time_monotonic(); isc__nm_incstats(ssock, STATID_ACCEPTFAIL); goto done; } @@ -901,6 +902,28 @@ accept_connection(isc_nmsocket_t *csock) { goto failure; } + /* Check if the connection is not expired */ + if (csock->quota_accept_ts != 0) { + /* The timestamp is given in nanoseconds */ + const uint64_t time_elapsed_ms = + (isc_time_monotonic() - csock->quota_accept_ts) / + NS_PER_MS; + + if (time_elapsed_ms >= csock->read_timeout) { + /* + * At this point we have received a connection from a + * queue of accepted connections (via uv_accept()), but + * it has expired. We cannot do anything better than + * drop it on the floor at this point. + */ + result = ISC_R_TIMEDOUT; + goto failure; + } else { + /* Adjust the initial read timeout accordingly */ + csock->read_timeout -= time_elapsed_ms; + } + } + r = uv_tcp_getpeername(&csock->uv_handle.tcp, (struct sockaddr *)&ss, &(int){ sizeof(ss) }); if (r != 0) {