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.
This commit is contained in:
Artem Boldariev 2024-09-04 18:53:35 +03:00 committed by Andoni Duarte
parent c6e6a7af8a
commit a67b325542
3 changed files with 52 additions and 4 deletions

View file

@ -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.
*/

View file

@ -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

View file

@ -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);
}