From 55b1a093ea97aa6d355dfc63dfc89f9c69a4fa4c Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Tue, 11 Jun 2024 17:20:22 +0300 Subject: [PATCH] Do not un-throttle TCP connections on isc_nm_read() Due to omission it was possible to un-throttle a TCP connection previously throttled due to the peer not reading back data we are sending. In particular, that affected DoH code, but it could also affect other transports (the current or future ones) that pause/resume reading according to its internal state. --- lib/isc/netmgr/netmgr-int.h | 6 ++++++ lib/isc/netmgr/tcp.c | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index f5d8c11418..51bcf9430e 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -585,6 +585,12 @@ struct isc_nmsocket { */ uint64_t write_timeout; + /* + * Reading was throttled over TCP as the peer does not read the + * data we are sending back. + */ + bool reading_throttled; + /*% outer socket is for 'wrapped' sockets - e.g. tcpdns in tcp */ isc_nmsocket_t *outer; diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 45e1c79c73..71eee4a2d9 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -697,9 +697,11 @@ isc__nm_tcp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { goto failure; } - result = isc__nm_start_reading(sock); - if (result != ISC_R_SUCCESS) { - goto failure; + if (!sock->reading_throttled) { + result = isc__nm_start_reading(sock); + if (result != ISC_R_SUCCESS) { + goto failure; + } } sock->reading = true; @@ -791,6 +793,7 @@ isc__nm_tcp_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { "throttling TCP connection, the other side is " "not reading the data (%zu)", write_queue_size); + sock->reading_throttled = true; isc__nm_stop_reading(sock); } } else if (uv_is_active(&sock->uv_handle.handle) && @@ -1042,6 +1045,7 @@ tcp_maybe_restart_reading(isc_nmsocket_t *sock) { "is reading the data again (%zu)", write_queue_size); isc__nm_start_reading(sock); + sock->reading_throttled = false; } } } @@ -1064,6 +1068,11 @@ tcp_send_cb(uv_write_t *req, int status) { isc__nm_failed_send_cb(sock, uvreq, isc_uverr2result(status), false); if (!sock->client && sock->reading) { + /* + * As we are resuming reading, it is not throttled + * anymore (technically). + */ + sock->reading_throttled = false; isc__nm_start_reading(sock); isc__nmsocket_reset(sock); }