diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 063b5f41c3..2cd65eb99a 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -135,16 +135,27 @@ isc_nmhandle_getextra(isc_nmhandle_t *handle); bool isc_nmhandle_is_stream(isc_nmhandle_t *handle); -/* - * isc_nmhandle_t has a void * opaque field (usually - ns_client_t). +void +isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg, + isc_nm_opaquecb_t doreset, isc_nm_opaquecb_t dofree); +/*%< + * isc_nmhandle_t has a void* opaque field (for example, ns_client_t). * We reuse handle and `opaque` can also be reused between calls. * This function sets this field and two callbacks: * - doreset resets the `opaque` to initial state * - dofree frees everything associated with `opaque` */ + void -isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg, - isc_nm_opaquecb_t doreset, isc_nm_opaquecb_t dofree); +isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout); +/*%< + * Set the read/recv timeout for the socket connected to 'handle' + * to 'timeout', and reset the timer. + * + * When this is called on a 'wrapper' socket handle (for example, + * a TCPDNS socket wrapping a TCP connection), the timer is set for + * both socket layers. + */ isc_sockaddr_t isc_nmhandle_peeraddr(isc_nmhandle_t *handle); @@ -359,9 +370,9 @@ isc_nm_tcpdns_sequential(isc_nmhandle_t *handle); */ void -isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle); +isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle, bool value); /*%< - * Enable keepalive on this connection. + * Enable/disable keepalive on this connection by setting it to 'value'. * * When keepalive is active, we switch to using the keepalive timeout * to determine when to close a connection, rather than the idle timeout. diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index e99631d151..f4ff2186b1 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -748,6 +748,15 @@ isc__nm_udp_shutdown(isc_nmsocket_t *sock); void isc__nm_udp_stoplistening(isc_nmsocket_t *sock); +/*%< + * Stop listening on 'sock'. + */ + +void +isc__nm_udp_settimeout(isc_nmhandle_t *handle, uint32_t timeout); +/*%< + * Set the recv timeout for the UDP socket associated with 'handle'. + */ void isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0); @@ -813,6 +822,15 @@ isc__nm_tcp_cancelread(isc_nmhandle_t *handle); void isc__nm_tcp_stoplistening(isc_nmsocket_t *sock); +/*%< + * Stop listening on 'sock'. + */ + +void +isc__nm_tcp_settimeout(isc_nmhandle_t *handle, uint32_t timeout); +/*%< + * Set the read timeout for the TCP socket associated with 'handle'. + */ void isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ev0); @@ -858,6 +876,16 @@ isc__nm_tcpdns_close(isc_nmsocket_t *sock); void isc__nm_tcpdns_stoplistening(isc_nmsocket_t *sock); +/*%< + * Stop listening on 'sock'. + */ + +void +isc__nm_tcpdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout); +/*%< + * Set the read timeout and reset the timer for the TCPDNS socket + * associated with 'handle', and the TCP socket it wraps around. + */ void isc__nm_async_tcpdnscancel(isc__networker_t *worker, isc__netievent_t *ev0); diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 9607349532..a5981c217e 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1385,6 +1385,26 @@ isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg, handle->dofree = dofree; } +void +isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout) { + REQUIRE(VALID_NMHANDLE(handle)); + + switch (handle->sock->type) { + case isc_nm_udpsocket: + isc__nm_udp_settimeout(handle, timeout); + break; + case isc_nm_tcpsocket: + isc__nm_tcp_settimeout(handle, timeout); + break; + case isc_nm_tcpdnssocket: + isc__nm_tcpdns_settimeout(handle, timeout); + break; + default: + INSIST(0); + ISC_UNREACHABLE(); + } +} + void * isc_nmhandle_getextra(isc_nmhandle_t *handle) { REQUIRE(VALID_NMHANDLE(handle)); diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index d0e753e534..83236e4aeb 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -813,6 +813,10 @@ isc__nm_tcp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { sock->recv_cb = cb; sock->recv_cbarg = cbarg; + sock->read_timeout = (atomic_load(&sock->keepalive) + ? sock->mgr->keepalive + : sock->mgr->idle); + ievent = isc__nm_get_ievent(sock->mgr, netievent_tcpstartread); ievent->sock = sock; @@ -885,9 +889,9 @@ isc__nm_async_tcp_startread(isc__networker_t *worker, isc__netievent_t *ev0) { if (sock->read_timeout != 0) { if (!sock->timer_initialized) { uv_timer_init(&worker->loop, &sock->timer); - uv_handle_set_data((uv_handle_t *)&sock->timer, sock); sock->timer_initialized = true; } + uv_handle_set_data((uv_handle_t *)&sock->timer, sock); uv_timer_start(&sock->timer, readtimeout_cb, sock->read_timeout, 0); sock->timer_running = true; @@ -987,10 +991,6 @@ read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { cb(sock->statichandle, ISC_R_SUCCESS, ®ion, cbarg); } - sock->read_timeout = (atomic_load(&sock->keepalive) - ? sock->mgr->keepalive - : sock->mgr->idle); - if (sock->timer_initialized && sock->read_timeout != 0) { /* The timer will be updated */ uv_timer_start(&sock->timer, readtimeout_cb, @@ -1471,3 +1471,18 @@ isc__nm_async_tcpcancel(isc__networker_t *worker, isc__netievent_t *ev0) { isc_nmhandle_detach(&handle); } + +void +isc__nm_tcp_settimeout(isc_nmhandle_t *handle, uint32_t timeout) { + isc_nmsocket_t *sock = NULL; + + REQUIRE(VALID_NMHANDLE(handle)); + + sock = handle->sock; + + sock->read_timeout = timeout; + if (sock->timer_running) { + uv_timer_start(&sock->timer, readtimeout_cb, sock->read_timeout, + 0); + } +} diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index ad85928d17..b06d56415d 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -470,7 +470,7 @@ isc_nm_tcpdns_sequential(isc_nmhandle_t *handle) { } void -isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle) { +isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle, bool value) { REQUIRE(VALID_NMHANDLE(handle)); if (handle->sock->type != isc_nm_tcpdnssocket || @@ -479,8 +479,8 @@ isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle) { return; } - atomic_store(&handle->sock->keepalive, true); - atomic_store(&handle->sock->outerhandle->sock->keepalive, true); + atomic_store(&handle->sock->keepalive, value); + atomic_store(&handle->sock->outerhandle->sock->keepalive, value); } static void @@ -831,6 +831,10 @@ isc__nm_tcpdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { sock->recv_cb = cb; sock->recv_cbarg = cbarg; + sock->read_timeout = (atomic_load(&sock->keepalive) + ? sock->mgr->keepalive + : sock->mgr->idle); + /* * Add a reference to the handle to keep it from being freed by * the caller; it will be detached in in isc__nm_async_tcpdnsread(). @@ -943,3 +947,22 @@ isc__nm_async_tcpdnscancel(isc__networker_t *worker, isc__netievent_t *ev0) { isc_nmhandle_detach(&handle); } + +void +isc__nm_tcpdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout) { + isc_nmsocket_t *sock = NULL; + + REQUIRE(VALID_NMHANDLE(handle)); + + sock = handle->sock; + + if (sock->outerhandle != NULL) { + isc__nm_tcp_settimeout(sock->outerhandle, timeout); + } + + sock->read_timeout = timeout; + if (sock->timer_running) { + uv_timer_start(&sock->timer, dnstcp_readtimeout, + sock->read_timeout, 0); + } +} diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 2dcd48f46e..5d8cbebb22 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -1146,3 +1146,18 @@ isc__nm_async_udpcancel(isc__networker_t *worker, isc__netievent_t *ev0) { isc_nmhandle_detach(&handle); } + +void +isc__nm_udp_settimeout(isc_nmhandle_t *handle, uint32_t timeout) { + isc_nmsocket_t *sock = NULL; + + REQUIRE(VALID_NMHANDLE(handle)); + + sock = handle->sock; + + sock->read_timeout = timeout; + if (sock->timer_running) { + uv_timer_start(&sock->timer, readtimeout_cb, sock->read_timeout, + 0); + } +} diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index 9ee446ca39..d696169ea7 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -443,6 +443,7 @@ isc_nmhandle_netmgr isc_nmhandle_localaddr isc_nmhandle_peeraddr isc_nmhandle_setdata +isc_nmhandle_settimeout isc_nm_cancelread isc_nm_closedown isc_nm_destroy