mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Fix TCPDNS and TLSDNS timers
After the TCPDNS refactoring the initial and idle timers were broken and only the tcp-initial-timeout was always applied on the whole TCP connection. This broke any TCP connection that took longer than tcp-initial-timeout, most often this would affect large zone AXFRs. This commit changes the timeout logic in this way: * On TCP connection accept the tcp-initial-timeout is applied and the timer is started * When we are processing and/or sending any DNS message the timer is stopped * When we stop processing all DNS messages, the tcp-idle-timeout is applied and the timer is started again
This commit is contained in:
@@ -162,9 +162,11 @@ isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg,
|
||||
|
||||
void
|
||||
isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
|
||||
void
|
||||
isc_nmhandle_cleartimeout(isc_nmhandle_t *handle);
|
||||
/*%<
|
||||
* Set the read/recv timeout for the socket connected to 'handle'
|
||||
* to 'timeout', and reset the timer.
|
||||
* Set/clear the read/recv timeout for the socket connected to 'handle'
|
||||
* to 'timeout', and reset the timer, in miliseconds.
|
||||
*
|
||||
* When this is called on a 'wrapper' socket handle (for example,
|
||||
* a TCPDNS socket wrapping a TCP connection), the timer is set for
|
||||
|
@@ -1764,7 +1764,7 @@ failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
|
||||
if (req->cb.send != NULL) {
|
||||
isc__nm_sendcb(sock, req, eresult);
|
||||
isc__nm_sendcb(sock, req, eresult, true);
|
||||
} else {
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
@@ -2537,6 +2537,22 @@ isc__nm_http_cleanup_data(isc_nmsocket_t *sock) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_http_cleartimeout(isc_nmhandle_t *handle) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
REQUIRE(handle->sock->type == isc_nm_httpsocket);
|
||||
|
||||
sock = handle->sock;
|
||||
if (sock->h2.session != NULL && sock->h2.session->handle) {
|
||||
INSIST(VALID_HTTP2_SESSION(sock->h2.session));
|
||||
INSIST(VALID_NMHANDLE(sock->h2.session->handle));
|
||||
isc_nmhandle_cleartimeout(sock->h2.session->handle);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_http_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
@@ -769,6 +769,12 @@ typedef struct isc_nmsocket_h2 {
|
||||
} connect;
|
||||
} isc_nmsocket_h2_t;
|
||||
|
||||
typedef void (*isc_nm_closehandlecb_t)(void *arg);
|
||||
/*%<
|
||||
* Opaque callback function, used for isc_nmhandle 'reset' and 'free'
|
||||
* callbacks.
|
||||
*/
|
||||
|
||||
struct isc_nmsocket {
|
||||
/*% Unlocked, RO */
|
||||
int magic;
|
||||
@@ -1015,7 +1021,7 @@ struct isc_nmsocket {
|
||||
* as the argument whenever a handle's references drop
|
||||
* to zero, after its reset callback has been called.
|
||||
*/
|
||||
isc_nm_opaquecb_t closehandle_cb;
|
||||
isc_nm_closehandlecb_t closehandle_cb;
|
||||
|
||||
isc_nmhandle_t *recv_handle;
|
||||
isc_nm_recv_cb_t recv_cb;
|
||||
@@ -1154,6 +1160,16 @@ isc__nmsocket_clearcb(isc_nmsocket_t *sock);
|
||||
* Clear the recv and accept callbacks in 'sock'.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nmsocket_timer_stop(isc_nmsocket_t *sock);
|
||||
void
|
||||
isc__nmsocket_timer_start(isc_nmsocket_t *sock);
|
||||
void
|
||||
isc__nmsocket_timer_restart(isc_nmsocket_t *sock);
|
||||
/*%<
|
||||
* Start/stop/restart the read timeout on the socket
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult);
|
||||
@@ -1182,7 +1198,7 @@ isc__nm_async_readcb(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
void
|
||||
isc__nm_sendcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult);
|
||||
isc_result_t eresult, bool async);
|
||||
void
|
||||
isc__nm_async_sendcb(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
/*%<
|
||||
@@ -1238,7 +1254,7 @@ isc__nm_udp_stoplistening(isc_nmsocket_t *sock);
|
||||
void
|
||||
isc__nm_udp_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
|
||||
/*%<
|
||||
* Set the recv timeout for the UDP socket associated with 'handle'.
|
||||
* Set or clear the recv timeout for the UDP socket associated with 'handle'.
|
||||
*/
|
||||
|
||||
void
|
||||
@@ -1532,6 +1548,8 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_tls_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
|
||||
void
|
||||
isc__nm_tls_cleartimeout(isc_nmhandle_t *handle);
|
||||
/*%<
|
||||
* Set the read timeout and reset the timer for the socket
|
||||
* associated with 'handle', and the TCP socket it wraps
|
||||
@@ -1543,6 +1561,8 @@ isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
void
|
||||
isc__nm_http_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
|
||||
void
|
||||
isc__nm_http_cleartimeout(isc_nmhandle_t *handle);
|
||||
/*%<
|
||||
* Set the read timeout and reset the timer for the socket
|
||||
* associated with 'handle', and the TLS/TCP socket it wraps
|
||||
@@ -1821,3 +1841,12 @@ NETIEVENT_DECL(pause);
|
||||
NETIEVENT_DECL(resume);
|
||||
NETIEVENT_DECL(shutdown);
|
||||
NETIEVENT_DECL(stop);
|
||||
|
||||
void
|
||||
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
|
||||
void
|
||||
isc__nm_tcp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
|
||||
void
|
||||
isc__nm_tcpdns_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
|
||||
void
|
||||
isc__nm_tlsdns_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
|
||||
|
@@ -1583,33 +1583,323 @@ 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) {
|
||||
static void
|
||||
isc__nmsocket_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
switch (sock->type) {
|
||||
case isc_nm_udpsocket:
|
||||
isc__nm_udp_settimeout(handle, timeout);
|
||||
break;
|
||||
isc__nm_udp_failed_read_cb(sock, result);
|
||||
return;
|
||||
case isc_nm_tcpsocket:
|
||||
isc__nm_tcp_settimeout(handle, timeout);
|
||||
isc__nm_tcp_failed_read_cb(sock, result);
|
||||
return;
|
||||
case isc_nm_tcpdnssocket:
|
||||
isc__nm_tcpdns_failed_read_cb(sock, result);
|
||||
return;
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_failed_read_cb(sock, result);
|
||||
return;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isc__nmsocket_readtimeout_cb(uv_timer_t *timer) {
|
||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(sock->reading);
|
||||
|
||||
isc__nmsocket_failed_read_cb(sock, ISC_R_TIMEDOUT);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nmsocket_timer_restart(isc_nmsocket_t *sock) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
|
||||
if (sock->read_timeout == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int r = uv_timer_start(&sock->timer, isc__nmsocket_readtimeout_cb,
|
||||
sock->read_timeout, 0);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nmsocket_timer_start(isc_nmsocket_t *sock) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
|
||||
if (uv_is_active((uv_handle_t *)&sock->timer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
isc__nmsocket_timer_restart(sock);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nmsocket_timer_stop(isc_nmsocket_t *sock) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
|
||||
if (!uv_is_active((uv_handle_t *)&sock->timer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int r = uv_timer_stop(&sock->timer);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
}
|
||||
|
||||
isc__nm_uvreq_t *
|
||||
isc__nm_get_read_req(isc_nmsocket_t *sock, isc_sockaddr_t *sockaddr) {
|
||||
isc__nm_uvreq_t *req = NULL;
|
||||
|
||||
req = isc__nm_uvreq_get(sock->mgr, sock);
|
||||
req->cb.recv = sock->recv_cb;
|
||||
req->cbarg = sock->recv_cbarg;
|
||||
|
||||
if (atomic_load(&sock->client)) {
|
||||
isc_nmhandle_attach(sock->statichandle, &req->handle);
|
||||
} else {
|
||||
req->handle = isc__nmhandle_get(sock, sockaddr, NULL);
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/*%<
|
||||
* Allocator for read operations. Limited to size 2^16.
|
||||
*
|
||||
* Note this doesn't actually allocate anything, it just assigns the
|
||||
* worker's receive buffer to a socket, and marks it as "in use".
|
||||
*/
|
||||
void
|
||||
isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
|
||||
isc_nmsocket_t *sock = uv_handle_get_data(handle);
|
||||
isc__networker_t *worker = NULL;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(isc__nm_in_netthread());
|
||||
|
||||
switch (sock->type) {
|
||||
case isc_nm_udpsocket:
|
||||
REQUIRE(size <= ISC_NETMGR_RECVBUF_SIZE);
|
||||
size = ISC_NETMGR_RECVBUF_SIZE;
|
||||
break;
|
||||
case isc_nm_tcpdnssocket:
|
||||
isc__nm_tcpdns_settimeout(handle, timeout);
|
||||
break;
|
||||
case isc_nm_tlsdnssocket:
|
||||
isc__nm_tlsdns_settimeout(handle, timeout);
|
||||
break;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_settimeout(handle, timeout);
|
||||
break;
|
||||
case isc_nm_httpsocket:
|
||||
isc__nm_http_settimeout(handle, timeout);
|
||||
/*
|
||||
* We need to limit the individual chunks to be read, so the
|
||||
* BIO_write() will always succeed and the consumed before the
|
||||
* next readcb is called.
|
||||
*/
|
||||
if (size >= ISC_NETMGR_TLSBUF_SIZE) {
|
||||
size = ISC_NETMGR_TLSBUF_SIZE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
worker = &sock->mgr->workers[sock->tid];
|
||||
INSIST(!worker->recvbuf_inuse);
|
||||
|
||||
buf->base = worker->recvbuf;
|
||||
buf->len = size;
|
||||
worker->recvbuf_inuse = true;
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_start_reading(isc_nmsocket_t *sock) {
|
||||
int r;
|
||||
|
||||
if (sock->reading) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sock->type) {
|
||||
case isc_nm_udpsocket:
|
||||
r = uv_udp_recv_start(&sock->uv_handle.udp, isc__nm_alloc_cb,
|
||||
isc__nm_udp_read_cb);
|
||||
break;
|
||||
case isc_nm_tcpdnssocket:
|
||||
r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb,
|
||||
isc__nm_tcpdns_read_cb);
|
||||
break;
|
||||
case isc_nm_tlsdnssocket:
|
||||
r = uv_read_start(&sock->uv_handle.stream, isc__nm_alloc_cb,
|
||||
isc__nm_tlsdns_read_cb);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
RUNTIME_CHECK(r == 0);
|
||||
sock->reading = true;
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_stop_reading(isc_nmsocket_t *sock) {
|
||||
int r;
|
||||
|
||||
if (!sock->reading) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sock->type) {
|
||||
case isc_nm_udpsocket:
|
||||
r = uv_udp_recv_stop(&sock->uv_handle.udp);
|
||||
break;
|
||||
case isc_nm_tcpdnssocket:
|
||||
case isc_nm_tlsdnssocket:
|
||||
r = uv_read_stop(&sock->uv_handle.stream);
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
RUNTIME_CHECK(r == 0);
|
||||
sock->reading = false;
|
||||
}
|
||||
|
||||
bool
|
||||
isc__nm_inactive(isc_nmsocket_t *sock) {
|
||||
return (!isc__nmsocket_active(sock) || atomic_load(&sock->closing) ||
|
||||
atomic_load(&sock->mgr->closing) ||
|
||||
(sock->server != NULL && !isc__nmsocket_active(sock->server)));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
processbuffer(isc_nmsocket_t *sock) {
|
||||
switch (sock->type) {
|
||||
case isc_nm_tcpdnssocket:
|
||||
return (isc__nm_tcpdns_processbuffer(sock));
|
||||
case isc_nm_tlsdnssocket:
|
||||
return (isc__nm_tcpdns_processbuffer(sock));
|
||||
default:
|
||||
INSIST(0);
|
||||
ISC_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a DNS message.
|
||||
*
|
||||
* If we only have an incomplete DNS message, we don't touch any
|
||||
* timers. If we do have a full message, reset the timer.
|
||||
*
|
||||
* Stop reading if this is a client socket, or if the server socket
|
||||
* has been set to sequential mode, or the number of queries we are
|
||||
* processing simultaneously has reached the clients-per-connection
|
||||
* limit. In this case we'll be called again by resume_processing()
|
||||
* later.
|
||||
*/
|
||||
void
|
||||
isc__nm_process_sock_buffer(isc_nmsocket_t *sock) {
|
||||
for (;;) {
|
||||
int_fast32_t ah = atomic_load(&sock->ah);
|
||||
isc_result_t result = processbuffer(sock);
|
||||
switch (result) {
|
||||
case ISC_R_NOMORE:
|
||||
/*
|
||||
* Don't reset the timer until we have a
|
||||
* full DNS message.
|
||||
*/
|
||||
isc__nm_start_reading(sock);
|
||||
/*
|
||||
* Start the timer only if there are no externally used
|
||||
* active handles, there's always one active handle
|
||||
* attached internally to sock->recv_handle in
|
||||
* accept_connection()
|
||||
*/
|
||||
if (ah == 1) {
|
||||
isc__nmsocket_timer_start(sock);
|
||||
}
|
||||
return;
|
||||
case ISC_R_CANCELED:
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
isc__nm_stop_reading(sock);
|
||||
return;
|
||||
case ISC_R_SUCCESS:
|
||||
/*
|
||||
* Stop the timer on the successful message read, this
|
||||
* also allows to restart the timer when we have no more
|
||||
* data.
|
||||
*/
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
|
||||
if (atomic_load(&sock->client) ||
|
||||
atomic_load(&sock->sequential) ||
|
||||
ah >= STREAM_CLIENTS_PER_CONN)
|
||||
{
|
||||
isc__nm_stop_reading(sock);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
INSIST(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_resume_processing(void *arg) {
|
||||
isc_nmsocket_t *sock = (isc_nmsocket_t *)arg;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(!atomic_load(&sock->client));
|
||||
|
||||
if (isc__nm_inactive(sock)) {
|
||||
return;
|
||||
}
|
||||
|
||||
isc__nm_process_sock_buffer(sock);
|
||||
}
|
||||
|
||||
void
|
||||
isc_nmhandle_cleartimeout(isc_nmhandle_t *handle) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
switch (handle->sock->type) {
|
||||
case isc_nm_httpsocket:
|
||||
isc__nm_http_cleartimeout(handle);
|
||||
return;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_cleartimeout(handle);
|
||||
return;
|
||||
default:
|
||||
handle->sock->read_timeout = 0;
|
||||
|
||||
if (uv_is_active((uv_handle_t *)&handle->sock->timer)) {
|
||||
isc__nmsocket_timer_stop(handle->sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
switch (handle->sock->type) {
|
||||
case isc_nm_httpsocket:
|
||||
isc__nm_http_settimeout(handle, timeout);
|
||||
return;
|
||||
case isc_nm_tlssocket:
|
||||
isc__nm_tls_settimeout(handle, timeout);
|
||||
return;
|
||||
default:
|
||||
handle->sock->read_timeout = timeout;
|
||||
if (uv_is_active((uv_handle_t *)&handle->sock->timer)) {
|
||||
isc__nmsocket_timer_restart(handle->sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
@@ -1956,22 +2246,23 @@ isc__nm_async_readcb(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
|
||||
void
|
||||
isc__nm_sendcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult) {
|
||||
isc_result_t eresult, bool async) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(VALID_UVREQ(uvreq));
|
||||
REQUIRE(VALID_NMHANDLE(uvreq->handle));
|
||||
|
||||
if (eresult == ISC_R_SUCCESS) {
|
||||
if (!async) {
|
||||
isc__netievent_sendcb_t ievent = { .sock = sock,
|
||||
.req = uvreq,
|
||||
.result = eresult };
|
||||
isc__nm_async_sendcb(NULL, (isc__netievent_t *)&ievent);
|
||||
} else {
|
||||
isc__netievent_sendcb_t *ievent = isc__nm_get_netievent_sendcb(
|
||||
sock->mgr, sock, uvreq, eresult);
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
return;
|
||||
}
|
||||
|
||||
isc__netievent_sendcb_t *ievent =
|
||||
isc__nm_get_netievent_sendcb(sock->mgr, sock, uvreq, eresult);
|
||||
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -86,9 +86,6 @@ stop_tcp_parent(isc_nmsocket_t *sock);
|
||||
static void
|
||||
stop_tcp_child(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
start_sock_timer(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
start_reading(isc_nmsocket_t *sock);
|
||||
|
||||
@@ -719,6 +716,11 @@ destroy:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tcp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
failed_read_cb(sock, result);
|
||||
}
|
||||
|
||||
static void
|
||||
failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
isc_result_t eresult) {
|
||||
@@ -726,7 +728,7 @@ failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
|
||||
if (req->cb.send != NULL) {
|
||||
isc__nm_sendcb(sock, req, eresult);
|
||||
isc__nm_sendcb(sock, req, eresult, true);
|
||||
} else {
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
@@ -744,35 +746,6 @@ get_read_req(isc_nmsocket_t *sock) {
|
||||
return req;
|
||||
}
|
||||
|
||||
static void
|
||||
readtimeout_cb(uv_timer_t *timer) {
|
||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(sock->reading);
|
||||
|
||||
/*
|
||||
* Timeout; stop reading and process whatever we have.
|
||||
*/
|
||||
failed_read_cb(sock, ISC_R_TIMEDOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
start_sock_timer(isc_nmsocket_t *sock) {
|
||||
if (sock->read_timeout > 0) {
|
||||
int r = uv_timer_start(&sock->timer, readtimeout_cb,
|
||||
sock->read_timeout, 0);
|
||||
REQUIRE(r == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_sock_timer(isc_nmsocket_t *sock) {
|
||||
int r = uv_timer_stop(&sock->timer);
|
||||
REQUIRE(r == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
start_reading(isc_nmsocket_t *sock) {
|
||||
if (sock->reading) {
|
||||
@@ -782,8 +755,6 @@ start_reading(isc_nmsocket_t *sock) {
|
||||
int r = uv_read_start(&sock->uv_handle.stream, tcp_alloc_cb, read_cb);
|
||||
REQUIRE(r == 0);
|
||||
sock->reading = true;
|
||||
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -796,7 +767,7 @@ stop_reading(isc_nmsocket_t *sock) {
|
||||
REQUIRE(r == 0);
|
||||
sock->reading = false;
|
||||
|
||||
stop_sock_timer(sock);
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -879,6 +850,7 @@ isc__nm_async_tcpstartread(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
}
|
||||
|
||||
start_reading(sock);
|
||||
isc__nmsocket_timer_start(sock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -997,7 +969,7 @@ read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
|
||||
/* The readcb could have paused the reading */
|
||||
if (sock->reading) {
|
||||
/* The timer will be updated */
|
||||
start_sock_timer(sock);
|
||||
isc__nmsocket_timer_restart(sock);
|
||||
}
|
||||
|
||||
free:
|
||||
@@ -1199,7 +1171,7 @@ tcp_send_cb(uv_write_t *req, int status) {
|
||||
return;
|
||||
}
|
||||
|
||||
isc__nm_sendcb(sock, uvreq, ISC_R_SUCCESS);
|
||||
isc__nm_sendcb(sock, uvreq, ISC_R_SUCCESS, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1479,20 +1451,6 @@ isc__nm_async_tcpcancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
failed_read_cb(sock, ISC_R_EOF);
|
||||
}
|
||||
|
||||
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 (uv_is_active((uv_handle_t *)&sock->timer)) {
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
}
|
||||
|
||||
int_fast32_t
|
||||
isc__nm_tcp_listener_nactive(isc_nmsocket_t *listener) {
|
||||
int_fast32_t nactive;
|
||||
|
@@ -69,8 +69,6 @@ tcpdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req);
|
||||
static void
|
||||
tcpdns_close_direct(isc_nmsocket_t *sock);
|
||||
|
||||
static isc_result_t
|
||||
tcpdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req);
|
||||
static void
|
||||
tcpdns_connect_cb(uv_connect_t *uvreq, int status);
|
||||
|
||||
@@ -101,9 +99,6 @@ stop_tcpdns_parent(isc_nmsocket_t *sock);
|
||||
static void
|
||||
stop_tcpdns_child(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
start_sock_timer(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
process_sock_buffer(isc_nmsocket_t *sock);
|
||||
|
||||
@@ -730,6 +725,7 @@ failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(result != ISC_R_SUCCESS);
|
||||
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
|
||||
if (!sock->recv_read) {
|
||||
@@ -753,6 +749,11 @@ destroy:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tcpdns_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
failed_read_cb(sock, result);
|
||||
}
|
||||
|
||||
static void
|
||||
failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
isc_result_t eresult) {
|
||||
@@ -760,7 +761,7 @@ failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
|
||||
if (req->cb.send != NULL) {
|
||||
isc__nm_sendcb(sock, req, eresult);
|
||||
isc__nm_sendcb(sock, req, eresult, true);
|
||||
} else {
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
@@ -783,36 +784,6 @@ get_read_req(isc_nmsocket_t *sock) {
|
||||
return (req);
|
||||
}
|
||||
|
||||
static void
|
||||
readtimeout_cb(uv_timer_t *timer) {
|
||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(sock->reading);
|
||||
|
||||
/*
|
||||
* Timeout; stop reading and process whatever we have.
|
||||
*/
|
||||
|
||||
failed_read_cb(sock, ISC_R_TIMEDOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
start_sock_timer(isc_nmsocket_t *sock) {
|
||||
if (sock->read_timeout > 0) {
|
||||
int r = uv_timer_start(&sock->timer, readtimeout_cb,
|
||||
sock->read_timeout, 0);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_sock_timer(isc_nmsocket_t *sock) {
|
||||
int r = uv_timer_stop(&sock->timer);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
start_reading(isc_nmsocket_t *sock) {
|
||||
int r;
|
||||
@@ -824,8 +795,6 @@ start_reading(isc_nmsocket_t *sock) {
|
||||
r = uv_read_start(&sock->uv_handle.stream, tcpdns_alloc_cb, read_cb);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
sock->reading = true;
|
||||
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -839,8 +808,6 @@ stop_reading(isc_nmsocket_t *sock) {
|
||||
r = uv_read_stop(&sock->uv_handle.stream);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
sock->reading = false;
|
||||
|
||||
stop_sock_timer(sock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1209,7 +1176,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
|
||||
* prep_destroy()->tcpdns_close_direct().
|
||||
*/
|
||||
isc_nmhandle_attach(handle, &csock->recv_handle);
|
||||
start_reading(csock);
|
||||
process_sock_buffer(csock);
|
||||
|
||||
/*
|
||||
* The initial timer has been set, update the read timeout for the next
|
||||
@@ -1284,7 +1251,7 @@ tcpdns_send_cb(uv_write_t *req, int status) {
|
||||
return;
|
||||
}
|
||||
|
||||
isc__nm_sendcb(sock, uvreq, ISC_R_SUCCESS);
|
||||
isc__nm_sendcb(sock, uvreq, ISC_R_SUCCESS, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1292,50 +1259,72 @@ tcpdns_send_cb(uv_write_t *req, int status) {
|
||||
*/
|
||||
void
|
||||
isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc_result_t result;
|
||||
isc__netievent_tcpdnssend_t *ievent =
|
||||
(isc__netievent_tcpdnssend_t *)ev0;
|
||||
|
||||
REQUIRE(ievent->sock->type == isc_nm_tcpdnssocket);
|
||||
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
||||
REQUIRE(VALID_NMSOCK(ievent->sock));
|
||||
REQUIRE(VALID_UVREQ(ievent->req));
|
||||
REQUIRE(ievent->sock->tid == isc_nm_tid());
|
||||
|
||||
isc_result_t result;
|
||||
isc_nmsocket_t *sock = ievent->sock;
|
||||
isc__nm_uvreq_t *uvreq = ievent->req;
|
||||
uv_buf_t bufs[2] = { { .base = uvreq->tcplen, .len = 2 },
|
||||
{ .base = uvreq->uvbuf.base,
|
||||
.len = uvreq->uvbuf.len } };
|
||||
int nbufs = 2;
|
||||
int r;
|
||||
|
||||
UNUSED(worker);
|
||||
|
||||
REQUIRE(sock->type == isc_nm_tcpdnssocket);
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
if (inactive(sock)) {
|
||||
result = ISC_R_CANCELED;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
result = tcpdns_send_direct(sock, uvreq);
|
||||
r = uv_try_write(&sock->uv_handle.stream, bufs, nbufs);
|
||||
|
||||
if (r == (int)(bufs[0].len + bufs[1].len)) {
|
||||
/* Wrote everything */
|
||||
isc__nm_sendcb(sock, uvreq, ISC_R_SUCCESS, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == 1) {
|
||||
/* Partial write of DNSMSG length */
|
||||
bufs[0].base = uvreq->tcplen + 1;
|
||||
bufs[0].len = 1;
|
||||
} else if (r > 0) {
|
||||
/* Partial write of DNSMSG */
|
||||
nbufs = 1;
|
||||
bufs[0].base = uvreq->uvbuf.base + (r - 2);
|
||||
bufs[0].len = uvreq->uvbuf.len - (r - 2);
|
||||
} else if (r == UV_ENOSYS || r == UV_EAGAIN) {
|
||||
/* uv_try_write not support, send asynchronously */
|
||||
} else {
|
||||
/* error sending data */
|
||||
result = isc__nm_uverr2result(r);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = uv_write(&uvreq->uv_req.write, &sock->uv_handle.stream, bufs, nbufs,
|
||||
tcpdns_send_cb);
|
||||
if (r < 0) {
|
||||
result = isc__nm_uverr2result(r);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]);
|
||||
failed_send_cb(sock, uvreq, result);
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tcpdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||
int r;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(sock->type == isc_nm_tcpdnssocket);
|
||||
|
||||
uv_buf_t bufs[2] = { { .base = req->tcplen, .len = 2 },
|
||||
{ .base = req->uvbuf.base,
|
||||
.len = req->uvbuf.len } };
|
||||
|
||||
if (inactive(sock)) {
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
r = uv_write(&req->uv_req.write, &sock->uv_handle.stream, bufs, 2,
|
||||
tcpdns_send_cb);
|
||||
if (r < 0) {
|
||||
return (isc__nm_uverr2result(r));
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
tcpdns_stop_cb(uv_handle_t *handle) {
|
||||
isc_nmsocket_t *sock = uv_handle_get_data(handle);
|
||||
@@ -1462,6 +1451,7 @@ tcpdns_close_direct(isc_nmsocket_t *sock) {
|
||||
isc_nmhandle_detach(&sock->recv_handle);
|
||||
}
|
||||
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
|
||||
}
|
||||
@@ -1567,21 +1557,6 @@ isc__nm_async_tcpdnscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
failed_read_cb(sock, ISC_R_EOF);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tcpdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
sock = handle->sock;
|
||||
|
||||
sock->read_timeout = timeout;
|
||||
if (uv_is_active((uv_handle_t *)&sock->timer)) {
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc_nm_tcpdns_sequential(isc_nmhandle_t *handle) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
@@ -1601,6 +1576,7 @@ isc_nm_tcpdns_sequential(isc_nmhandle_t *handle) {
|
||||
* is released.
|
||||
*/
|
||||
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
atomic_store(&sock->sequential, true);
|
||||
}
|
||||
@@ -1618,33 +1594,47 @@ isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle, bool value) {
|
||||
atomic_store(&sock->keepalive, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a DNS message.
|
||||
*
|
||||
* If we only have an incomplete DNS message, we don't touch any
|
||||
* timers. If we do have a full message, reset the timer.
|
||||
*
|
||||
* Stop reading if this is a client socket, or if the server socket
|
||||
* has been set to sequential mode, or the number of queries we are
|
||||
* processing simultaneously has reached the clients-per-connection
|
||||
* limit. In this event we'll be called again by resume_processing()
|
||||
* later.
|
||||
*/
|
||||
static void
|
||||
process_sock_buffer(isc_nmsocket_t *sock) {
|
||||
/*
|
||||
* 1. When process_buffer receives incomplete DNS message,
|
||||
* we don't touch any timers
|
||||
*
|
||||
* 2. When we receive at least one full DNS message, we stop the timers
|
||||
* until resume_processing calls this function again and restarts the
|
||||
* reading and the timers
|
||||
*/
|
||||
|
||||
/*
|
||||
* Process a DNS messages. Stop if this is client socket, or the server
|
||||
* socket has been set to sequential mode or the number of queries we
|
||||
* are processing simultaneously have reached the clients-per-connection
|
||||
* limit.
|
||||
*/
|
||||
for (;;) {
|
||||
int_fast32_t ah = atomic_load(&sock->ah);
|
||||
isc_result_t result = processbuffer(sock);
|
||||
switch (result) {
|
||||
case ISC_R_NOMORE:
|
||||
/*
|
||||
* Don't reset the timer until we have a
|
||||
* full DNS message.
|
||||
*/
|
||||
start_reading(sock);
|
||||
/* Start the timer if there are no active handles */
|
||||
if (ah == 1) {
|
||||
isc__nmsocket_timer_start(sock);
|
||||
}
|
||||
return;
|
||||
case ISC_R_CANCELED:
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
return;
|
||||
case ISC_R_SUCCESS:
|
||||
/*
|
||||
* Stop the timer on the successful message read, this
|
||||
* also allows to restart the timer when we have no more
|
||||
* data.
|
||||
*/
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
|
||||
if (atomic_load(&sock->client) ||
|
||||
atomic_load(&sock->sequential) ||
|
||||
atomic_load(&sock->ah) >= TCPDNS_CLIENTS_PER_CONN)
|
||||
@@ -1672,10 +1662,5 @@ resume_processing(void *arg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_load(&sock->ah) == 0) {
|
||||
/* Nothing is active; sockets can timeout now */
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
|
||||
process_sock_buffer(sock);
|
||||
}
|
||||
|
@@ -100,9 +100,6 @@ start_reading(isc_nmsocket_t *sock);
|
||||
static void
|
||||
stop_reading(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
start_sock_timer(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
process_sock_buffer(isc_nmsocket_t *sock);
|
||||
|
||||
@@ -372,7 +369,8 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) {
|
||||
|
||||
sock->tls.pending_req = req;
|
||||
|
||||
start_reading(sock);
|
||||
process_sock_buffer(sock);
|
||||
|
||||
result = tls_cycle(sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto error;
|
||||
@@ -861,6 +859,7 @@ failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(result != ISC_R_SUCCESS);
|
||||
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
|
||||
if (sock->tls.pending_req) {
|
||||
@@ -890,6 +889,11 @@ destroy:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tlsdns_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
failed_read_cb(sock, result);
|
||||
}
|
||||
|
||||
static void
|
||||
failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
isc_result_t eresult) {
|
||||
@@ -897,7 +901,7 @@ failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
|
||||
if (req->cb.send != NULL) {
|
||||
isc__nm_sendcb(sock, req, eresult);
|
||||
isc__nm_sendcb(sock, req, eresult, true);
|
||||
} else {
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
@@ -920,36 +924,6 @@ get_read_req(isc_nmsocket_t *sock) {
|
||||
return (req);
|
||||
}
|
||||
|
||||
static void
|
||||
readtimeout_cb(uv_timer_t *timer) {
|
||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(sock->reading);
|
||||
|
||||
/*
|
||||
* Timeout; stop reading and process whatever we have.
|
||||
*/
|
||||
|
||||
failed_read_cb(sock, ISC_R_TIMEDOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
start_sock_timer(isc_nmsocket_t *sock) {
|
||||
if (sock->read_timeout > 0) {
|
||||
int r = uv_timer_start(&sock->timer, readtimeout_cb,
|
||||
sock->read_timeout, 0);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_sock_timer(isc_nmsocket_t *sock) {
|
||||
int r = uv_timer_stop(&sock->timer);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
start_reading(isc_nmsocket_t *sock) {
|
||||
int r;
|
||||
@@ -961,8 +935,6 @@ start_reading(isc_nmsocket_t *sock) {
|
||||
r = uv_read_start(&sock->uv_handle.stream, tlsdns_alloc_cb, read_cb);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
sock->reading = true;
|
||||
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -976,8 +948,6 @@ stop_reading(isc_nmsocket_t *sock) {
|
||||
r = uv_read_stop(&sock->uv_handle.stream);
|
||||
RUNTIME_CHECK(r == 0);
|
||||
sock->reading = false;
|
||||
|
||||
stop_sock_timer(sock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1069,7 +1039,6 @@ isc__nm_async_tlsdnsread(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
|
||||
result = tls_cycle(sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
stop_reading(sock);
|
||||
failed_read_cb(sock, result);
|
||||
}
|
||||
}
|
||||
@@ -1216,7 +1185,7 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
||||
if (sock->tls.state == TLS_STATE_NONE &&
|
||||
!SSL_is_init_finished(sock->tls.tls)) {
|
||||
sock->tls.state = TLS_STATE_HANDSHAKE;
|
||||
start_reading(sock);
|
||||
process_sock_buffer(sock);
|
||||
}
|
||||
/* else continue reading */
|
||||
break;
|
||||
@@ -1269,9 +1238,8 @@ static void
|
||||
tls_error(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
switch (sock->tls.state) {
|
||||
case TLS_STATE_HANDSHAKE:
|
||||
stop_reading(sock);
|
||||
break;
|
||||
case TLS_STATE_IO:
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
break;
|
||||
case TLS_STATE_ERROR:
|
||||
@@ -1709,7 +1677,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) {
|
||||
|
||||
isc_nmhandle_detach(&handle);
|
||||
|
||||
start_reading(csock);
|
||||
process_sock_buffer(csock);
|
||||
|
||||
/*
|
||||
* sock is now attached to the handle.
|
||||
@@ -1832,7 +1800,7 @@ tlsdns_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||
/* SSL_write_ex() doesn't do partial writes */
|
||||
INSIST(sendlen == bytes);
|
||||
|
||||
isc__nm_sendcb(sock, req, ISC_R_SUCCESS);
|
||||
isc__nm_sendcb(sock, req, ISC_R_SUCCESS, true);
|
||||
async_tlsdns_cycle(sock);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
@@ -2001,6 +1969,7 @@ tlsdns_close_direct(isc_nmsocket_t *sock) {
|
||||
isc_nmhandle_detach(&sock->recv_handle);
|
||||
}
|
||||
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
|
||||
}
|
||||
@@ -2112,21 +2081,6 @@ isc__nm_async_tlsdnscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
failed_read_cb(sock, ISC_R_EOF);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tlsdns_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
sock = handle->sock;
|
||||
|
||||
sock->read_timeout = timeout;
|
||||
if (uv_is_active((uv_handle_t *)&sock->timer)) {
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc_nm_tlsdns_sequential(isc_nmhandle_t *handle) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
@@ -2146,6 +2100,7 @@ isc_nm_tlsdns_sequential(isc_nmhandle_t *handle) {
|
||||
* is released.
|
||||
*/
|
||||
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
atomic_store(&sock->sequential, true);
|
||||
}
|
||||
@@ -2163,33 +2118,47 @@ isc_nm_tlsdns_keepalive(isc_nmhandle_t *handle, bool value) {
|
||||
atomic_store(&sock->keepalive, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a DNS message.
|
||||
*
|
||||
* If we only have an incomplete DNS message, we don't touch any
|
||||
* timers. If we do have a full message, reset the timer.
|
||||
*
|
||||
* Stop reading if this is a client socket, or if the server socket
|
||||
* has been set to sequential mode, or the number of queries we are
|
||||
* processing simultaneously has reached the clients-per-connection
|
||||
* limit. In this event we'll be called again by resume_processing()
|
||||
* later.
|
||||
*/
|
||||
static void
|
||||
process_sock_buffer(isc_nmsocket_t *sock) {
|
||||
/*
|
||||
* 1. When process_buffer receives incomplete DNS message,
|
||||
* we don't touch any timers
|
||||
*
|
||||
* 2. When we receive at least one full DNS message, we stop the timers
|
||||
* until resume_processing calls this function again and restarts the
|
||||
* reading and the timers
|
||||
*/
|
||||
|
||||
/*
|
||||
* Process a DNS messages. Stop if this is client socket, or the server
|
||||
* socket has been set to sequential mode or the number of queries we
|
||||
* are processing simultaneously have reached the clients-per-connection
|
||||
* limit.
|
||||
*/
|
||||
for (;;) {
|
||||
int_fast32_t ah = atomic_load(&sock->ah);
|
||||
isc_result_t result = processbuffer(sock);
|
||||
switch (result) {
|
||||
case ISC_R_NOMORE:
|
||||
/*
|
||||
* Don't reset the timer until we have a
|
||||
* full DNS message.
|
||||
*/
|
||||
start_reading(sock);
|
||||
/* Start the timer if there are no active handles */
|
||||
if (ah == 1) {
|
||||
isc__nmsocket_timer_start(sock);
|
||||
}
|
||||
return;
|
||||
case ISC_R_CANCELED:
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
stop_reading(sock);
|
||||
return;
|
||||
case ISC_R_SUCCESS:
|
||||
/*
|
||||
* Stop the timer on the successful message read, this
|
||||
* also allows to restart the timer when we have no more
|
||||
* data.
|
||||
*/
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
|
||||
if (atomic_load(&sock->client) ||
|
||||
atomic_load(&sock->sequential) ||
|
||||
atomic_load(&sock->ah) >= TLSDNS_CLIENTS_PER_CONN)
|
||||
@@ -2217,10 +2186,5 @@ resume_processing(void *arg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_load(&sock->ah) == 0) {
|
||||
/* Nothing is active; sockets can timeout now */
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
|
||||
process_sock_buffer(sock);
|
||||
}
|
||||
|
@@ -948,6 +948,21 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_cleartimeout(isc_nmhandle_t *handle) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
REQUIRE(handle->sock->type == isc_nm_tlssocket);
|
||||
|
||||
sock = handle->sock;
|
||||
if (sock->outerhandle != NULL) {
|
||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||
isc_nmhandle_cleartimeout(sock->outerhandle);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_tls_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
@@ -596,7 +596,7 @@ udp_send_cb(uv_udp_send_t *req, int status) {
|
||||
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]);
|
||||
}
|
||||
|
||||
isc__nm_sendcb(sock, uvreq, result);
|
||||
isc__nm_sendcb(sock, uvreq, result, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -900,6 +900,11 @@ failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
|
||||
failed_read_cb(sock, result);
|
||||
}
|
||||
|
||||
static void
|
||||
failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
isc_result_t eresult) {
|
||||
@@ -907,7 +912,7 @@ failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
|
||||
if (req->cb.send != NULL) {
|
||||
isc__nm_sendcb(sock, req, eresult);
|
||||
isc__nm_sendcb(sock, req, eresult, true);
|
||||
} else {
|
||||
isc__nm_uvreq_put(&req, sock);
|
||||
}
|
||||
@@ -930,20 +935,6 @@ get_read_req(isc_nmsocket_t *sock, isc_sockaddr_t *sockaddr) {
|
||||
return req;
|
||||
}
|
||||
|
||||
static void
|
||||
readtimeout_cb(uv_timer_t *handle) {
|
||||
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)handle);
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(sock->reading);
|
||||
|
||||
/*
|
||||
* Timeout; stop reading and process whatever we have.
|
||||
*/
|
||||
failed_read_cb(sock, ISC_R_TIMEDOUT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Asynchronous 'udpread' call handler: start or resume reading on a
|
||||
* socket; pause reading and call the 'recv' callback after each
|
||||
@@ -966,21 +957,7 @@ isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
}
|
||||
|
||||
start_reading(sock);
|
||||
}
|
||||
|
||||
static void
|
||||
start_sock_timer(isc_nmsocket_t *sock) {
|
||||
if (sock->read_timeout > 0) {
|
||||
int r = uv_timer_start(&sock->timer, readtimeout_cb,
|
||||
sock->read_timeout, 0);
|
||||
REQUIRE(r == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stop_sock_timer(isc_nmsocket_t *sock) {
|
||||
int r = uv_timer_stop(&sock->timer);
|
||||
REQUIRE(r == 0);
|
||||
isc__nmsocket_timer_start(sock);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -993,8 +970,6 @@ start_reading(isc_nmsocket_t *sock) {
|
||||
udp_read_cb);
|
||||
REQUIRE(r == 0);
|
||||
sock->reading = true;
|
||||
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1007,7 +982,7 @@ stop_reading(isc_nmsocket_t *sock) {
|
||||
REQUIRE(r == 0);
|
||||
sock->reading = false;
|
||||
|
||||
stop_sock_timer(sock);
|
||||
isc__nmsocket_timer_stop(sock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1263,16 +1238,3 @@ isc__nm_async_udpcancel(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
|
||||
failed_read_cb(sock, ISC_R_EOF);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_udp_settimeout(isc_nmhandle_t *handle, uint32_t timeout) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
|
||||
isc_nmsocket_t *sock = handle->sock;
|
||||
|
||||
sock->read_timeout = timeout;
|
||||
if (uv_is_active((uv_handle_t *)&sock->timer)) {
|
||||
start_sock_timer(sock);
|
||||
}
|
||||
}
|
||||
|
@@ -440,6 +440,7 @@ isc_netaddr_unspec
|
||||
isc_netscope_pton
|
||||
isc__nmhandle_attach
|
||||
isc__nmhandle_detach
|
||||
isc_nmhandle_cleartimeout
|
||||
isc_nmhandle_getdata
|
||||
isc_nmhandle_getextra
|
||||
isc_nmhandle_is_stream
|
||||
|
Reference in New Issue
Block a user