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.
(cherry picked from commit
d228aa8bbb944fbd04baf22d151fde5c33561e26)
*/
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;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(atomic_load(&sock->reading));
if (atomic_load(&sock->client)) {
uv_timer_stop(timer);
isc__netievent_tcpstartread_t *ievent =
(isc__netievent_tcpstartread_t *)ev0;
isc_nmsocket_t *sock = ievent->sock;
- isc_result_t result;
+ isc_result_t result = ISC_R_SUCCESS;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
if (isc__nmsocket_closing(sock)) {
result = ISC_R_CANCELED;
- } else {
+ } else if (!sock->reading_throttled) {
result = isc__nm_start_reading(sock);
}
"the other side is "
"not reading the data (%zu)",
write_queue_size);
+ sock->reading_throttled = true;
isc__nm_stop_reading(sock);
}
}
static void
tcp_maybe_restart_reading(isc_nmsocket_t *sock) {
- if (!sock->client && sock->reading &&
+ if (!sock->client && sock->reading_throttled &&
!uv_is_active(&sock->uv_handle.handle))
{
/*
"resuming TCP connection, the other side "
"is reading the data again (%zu)",
write_queue_size);
+ sock->reading_throttled = false;
isc__nm_start_reading(sock);
}
}
isc__nm_failed_send_cb(sock, uvreq,
isc__nm_uverr2result(status));
- if (!sock->client && sock->reading) {
+ if (!sock->client &&
+ (atomic_load(&sock->reading) || sock->reading_throttled))
+ {
+ /*
+ * As we are resuming reading, it is not throttled
+ * anymore (technically).
+ */
+ sock->reading_throttled = false;
isc__nm_start_reading(sock);
isc__nmsocket_reset(sock);
}
isc__netievent_tcpdnsread_t *ievent =
(isc__netievent_tcpdnsread_t *)ev0;
isc_nmsocket_t *sock = ievent->sock;
- isc_result_t result;
+ isc_result_t result = ISC_R_SUCCESS;
UNUSED(worker);
if (isc__nmsocket_closing(sock)) {
result = ISC_R_CANCELED;
- } else {
+ } else if (!sock->reading_throttled) {
result = isc__nm_process_sock_buffer(sock);
}
"the other side is "
"not reading the data (%zu)",
write_queue_size);
+ sock->reading_throttled = true;
isc__nm_stop_reading(sock);
}
}
static void
tcpdns_maybe_restart_reading(isc_nmsocket_t *sock) {
- if (!sock->client && sock->reading &&
+ if (!sock->client && sock->reading_throttled &&
!uv_is_active(&sock->uv_handle.handle))
{
/*
"resuming TCP connection, the other side "
"is reading the data again (%zu)",
write_queue_size);
+ sock->reading_throttled = false;
isc__nm_start_reading(sock);
}
}
isc__nm_failed_send_cb(sock, uvreq,
isc__nm_uverr2result(status));
- if (!sock->client && sock->reading) {
+ if (!sock->client &&
+ (atomic_load(&sock->reading) || sock->reading_throttled))
+ {
+ /*
+ * As we are resuming reading, it is not throttled
+ * anymore (technically).
+ */
+ sock->reading_throttled = false;
isc__nm_start_reading(sock);
isc__nmsocket_reset(sock);
}