From a67b3255426160c55faa9d1d3aa6e7579439b2b4 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Wed, 4 Sep 2024 18:53:35 +0300 Subject: [PATCH] Implement TCP manual read timer control functionality This commit adds a manual TCP read timer control mode which is supposed to override automatic resetting of the timer when any data is received. That can be accomplished by `isc__nmhandle_set_manual_timer()`. This functionality is supposed to be used by multilevel networking transports which require finer grained control over the read timer (TLS Stream, DoH). The commit is essentially an implementation of the functionality from newer versions of BIND. --- lib/isc/netmgr/netmgr-int.h | 11 +++++++++++ lib/isc/netmgr/netmgr.c | 19 +++++++++++++++++++ lib/isc/netmgr/tcp.c | 26 ++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index a99153a8f2..48f2ef99f0 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -1229,6 +1229,7 @@ struct isc_nmsocket { isc_barrier_t barrier; bool barrier_initialised; + atomic_bool manual_read_timer; #ifdef NETMGR_TRACE void *backtrace[TRACE_SIZE]; int backtrace_size; @@ -1547,6 +1548,9 @@ isc__nm_tcp_settimeout(isc_nmhandle_t *handle, uint32_t timeout); * Set the read timeout for the TCP socket associated with 'handle'. */ +void +isc__nmhandle_tcp_set_manual_timer(isc_nmhandle_t *handle, const bool manual); + void isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ev0); void @@ -2278,3 +2282,10 @@ isc__nmsocket_writetimeout_cb(void *data, isc_result_t eresult); void isc__nmsocket_log_tls_session_reuse(isc_nmsocket_t *sock, isc_tls_t *tls); + +void +isc__nmhandle_set_manual_timer(isc_nmhandle_t *handle, const bool manual); +/* + * Set manual read timer control mode - so that it will not get reset + * automatically on read nor get started when read is initiated. + */ diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index a7b82ce69b..49982767bc 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1627,6 +1627,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type, atomic_init(&sock->keepalive, false); atomic_init(&sock->connected, false); atomic_init(&sock->timedout, false); + atomic_init(&sock->manual_read_timer, false); atomic_init(&sock->active_child_connections, 0); @@ -3932,6 +3933,24 @@ isc__nmsocket_log_tls_session_reuse(isc_nmsocket_t *sock, isc_tls_t *tls) { client_sabuf, local_sabuf); } +void +isc__nmhandle_set_manual_timer(isc_nmhandle_t *handle, const bool manual) { + REQUIRE(VALID_NMHANDLE(handle)); + REQUIRE(VALID_NMSOCK(handle->sock)); + + isc_nmsocket_t *sock = handle->sock; + + switch (sock->type) { + case isc_nm_tcpsocket: + isc__nmhandle_tcp_set_manual_timer(handle, manual); + return; + default: + break; + }; + + UNREACHABLE(); +} + #ifdef NETMGR_TRACE /* * Dump all active sockets in netmgr. We output to stderr diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index db589aecc7..fbe1394ab9 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -784,7 +784,9 @@ isc__nm_async_tcpstartread(isc__networker_t *worker, isc__netievent_t *ev0) { return; } - isc__nmsocket_timer_start(sock); + if (!atomic_load(&sock->manual_read_timer)) { + isc__nmsocket_timer_start(sock); + } } void @@ -822,7 +824,9 @@ isc__nm_async_tcppauseread(isc__networker_t *worker, isc__netievent_t *ev0) { REQUIRE(sock->tid == isc_nm_tid()); UNUSED(worker); - isc__nmsocket_timer_stop(sock); + if (!atomic_load(&sock->manual_read_timer)) { + isc__nmsocket_timer_stop(sock); + } isc__nm_stop_reading(sock); } @@ -931,8 +935,10 @@ isc__nm_tcp_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { } } - /* The timer will be updated */ - isc__nmsocket_timer_restart(sock); + if (!atomic_load(&sock->manual_read_timer)) { + /* The timer will be updated */ + isc__nmsocket_timer_restart(sock); + } } free: @@ -1521,3 +1527,15 @@ isc__nm_tcp_listener_nactive(isc_nmsocket_t *listener) { INSIST(nactive >= 0); return nactive; } + +void +isc__nmhandle_tcp_set_manual_timer(isc_nmhandle_t *handle, const bool manual) { + isc_nmsocket_t *sock; + + REQUIRE(VALID_NMHANDLE(handle)); + sock = handle->sock; + REQUIRE(VALID_NMSOCK(sock)); + REQUIRE(sock->type == isc_nm_tcpsocket); + + atomic_store(&sock->manual_read_timer, manual); +}