]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Do not un-throttle TCP connections on isc_nm_read()
authorArtem Boldariev <artem@boldariev.com>
Tue, 11 Jun 2024 14:20:22 +0000 (17:20 +0300)
committerArtem Boldariev <artem@boldariev.com>
Wed, 12 Jun 2024 10:44:37 +0000 (13:44 +0300)
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
lib/isc/netmgr/tcp.c

index f5d8c114189fd5385792dd43f15e6bb6eb58df72..51bcf9430e9f2b96f635077384625d96d781d9cd 100644 (file)
@@ -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;
 
index 45e1c79c733064124eb1b3c8bb26adda26632d99..71eee4a2d9cf40c2ca90ed5c10395630a790cafa 100644 (file)
@@ -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);
                }