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) {