uint64_t read_timeout;
uint64_t connect_timeout;
+ /*%
+ * TCP write timeout timer.
+ */
+ uv_timer_t write_timer;
+ uint64_t write_timeout;
+ int64_t writes;
+
/*% outer socket is for 'wrapped' sockets - e.g. tcpdns in tcp */
isc_nmsocket_t *outer;
isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, bool async);
void
-isc__nmsocket_connecttimeout_cb(uv_timer_t *timer);
+isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota);
+/*
+ * Timeout callbacks
+ */
void
-isc__nm_accept_connection_log(isc_result_t result, bool can_log_quota);
+isc__nmsocket_connecttimeout_cb(uv_timer_t *timer);
+void
+isc__nmsocket_readtimeout_cb(uv_timer_t *timer);
+void
+isc__nmsocket_writetimeout_cb(uv_timer_t *timer);
+/*%<
+ *
+ * Maximum number of simultaneous handles in flight supported for a single
+ * connected TCPDNS socket. This value was chosen arbitrarily, and may be
+ * changed in the future.
+ */
#define STREAM_CLIENTS_PER_CONN 23
#define UV_RUNTIME_CHECK(func, ret) \
isc_result_totext(result));
}
-static void
+void
+isc__nmsocket_writetimeout_cb(uv_timer_t *timer) {
+ isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
+
+ int r = uv_timer_stop(&sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_stop, r);
+
+ /* The shutdown will be handled in the respective close functions */
+ r = uv_tcp_close_reset(&sock->uv_handle.tcp, NULL);
+ UV_RUNTIME_CHECK(uv_tcp_close_reset, r);
+
+ isc__nmsocket_shutdown(sock);
+}
+
+void
isc__nmsocket_readtimeout_cb(uv_timer_t *timer) {
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
atomic_store(&sock->keepalive, value);
sock->read_timeout = value ? atomic_load(&sock->mgr->keepalive)
: atomic_load(&sock->mgr->idle);
+ sock->write_timeout = value ? atomic_load(&sock->mgr->keepalive)
+ : atomic_load(&sock->mgr->idle);
break;
default:
/*
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ r = uv_timer_init(&worker->loop, &sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
if (r != 0) {
isc__nm_closesocket(sock->fd);
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ r = uv_timer_init(&worker->loop, &sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+
LOCK(&sock->parent->lock);
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock);
+ r = uv_timer_init(&worker->loop, &csock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&csock->write_timer, csock);
+
r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream);
if (r != 0) {
result = isc__nm_uverr2result(r);
uvreq->cb.send = cb;
uvreq->cbarg = cbarg;
+ if (sock->write_timeout == 0) {
+ sock->write_timeout =
+ (atomic_load(&sock->keepalive)
+ ? atomic_load(&sock->mgr->keepalive)
+ : atomic_load(&sock->mgr->idle));
+ }
+
ievent = isc__nm_get_netievent_tcpsend(sock->mgr, sock, uvreq);
isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
static void
tcp_send_cb(uv_write_t *req, int status) {
isc__nm_uvreq_t *uvreq = (isc__nm_uvreq_t *)req->data;
+
REQUIRE(VALID_UVREQ(uvreq));
REQUIRE(VALID_NMHANDLE(uvreq->handle));
isc_nmsocket_t *sock = uvreq->sock;
+ if (--sock->writes == 0) {
+ int r = uv_timer_stop(&sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_stop, r);
+ }
+
if (status < 0) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]);
failed_send_cb(sock, uvreq, isc__nm_uverr2result(status));
return (ISC_R_CANCELED);
}
+ r = uv_timer_start(&sock->write_timer, isc__nmsocket_writetimeout_cb,
+ sock->write_timeout, 0);
+ UV_RUNTIME_CHECK(uv_timer_start, r);
+ RUNTIME_CHECK(sock->writes++ >= 0);
+
r = uv_write(&req->uv_req.write, &sock->uv_handle.stream, &req->uvbuf,
1, tcp_send_cb);
if (r < 0) {
}
static void
-timer_close_cb(uv_handle_t *handle) {
+read_timer_close_cb(uv_handle_t *handle) {
isc_nmsocket_t *sock = uv_handle_get_data(handle);
uv_handle_set_data(handle, NULL);
}
}
+static void
+write_timer_close_cb(uv_handle_t *timer) {
+ isc_nmsocket_t *sock = uv_handle_get_data(timer);
+ uv_handle_set_data(timer, NULL);
+
+ REQUIRE(VALID_NMSOCK(sock));
+
+ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb);
+}
+
static void
stop_tcp_child(isc_nmsocket_t *sock) {
REQUIRE(sock->type == isc_nm_tcpsocket);
static void
tcp_close_direct(isc_nmsocket_t *sock) {
+ int r;
+
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(atomic_load(&sock->closing));
isc__nmsocket_timer_stop(sock);
isc__nm_stop_reading(sock);
- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
- uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb);
+ r = uv_timer_stop(&sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_stop, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+ uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb);
}
void
#include "netmgr-int.h"
#include "uv-compat.h"
-/*%<
- *
- * Maximum number of simultaneous handles in flight supported for a single
- * connected TCPDNS socket. This value was chosen arbitrarily, and may be
- * changed in the future.
- */
-
static atomic_uint_fast32_t last_tcpdnsquota_log = ATOMIC_VAR_INIT(0);
static bool
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ r = uv_timer_init(&worker->loop, &sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+
if (isc__nm_closing(sock)) {
result = ISC_R_CANCELED;
goto error;
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ r = uv_timer_init(&worker->loop, &sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+
LOCK(&sock->parent->lock);
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock);
+ r = uv_timer_init(&worker->loop, &csock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&csock->write_timer, csock);
+
r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream);
if (r != 0) {
result = isc__nm_uverr2result(r);
uvreq->cb.send = cb;
uvreq->cbarg = cbarg;
+ if (sock->write_timeout == 0) {
+ sock->write_timeout =
+ (atomic_load(&sock->keepalive)
+ ? atomic_load(&sock->mgr->keepalive)
+ : atomic_load(&sock->mgr->idle));
+ }
+
ievent = isc__nm_get_netievent_tcpdnssend(sock->mgr, sock, uvreq);
isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
sock = uvreq->sock;
+ if (--sock->writes == 0) {
+ int r = uv_timer_stop(&sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_stop, r);
+ }
+
if (status < 0) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]);
isc__nm_failed_send_cb(sock, uvreq,
goto fail;
}
+ r = uv_timer_start(&sock->write_timer, isc__nmsocket_writetimeout_cb,
+ sock->write_timeout, 0);
+ UV_RUNTIME_CHECK(uv_timer_start, r);
+ RUNTIME_CHECK(sock->writes++ >= 0);
+
r = uv_write(&uvreq->uv_req.write, &sock->uv_handle.stream, bufs, nbufs,
tcpdns_send_cb);
if (r < 0) {
}
static void
-timer_close_cb(uv_handle_t *timer) {
+read_timer_close_cb(uv_handle_t *timer) {
isc_nmsocket_t *sock = uv_handle_get_data(timer);
uv_handle_set_data(timer, NULL);
}
}
+static void
+write_timer_close_cb(uv_handle_t *timer) {
+ isc_nmsocket_t *sock = uv_handle_get_data(timer);
+ uv_handle_set_data(timer, NULL);
+
+ REQUIRE(VALID_NMSOCK(sock));
+
+ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb);
+}
+
static void
stop_tcpdns_child(isc_nmsocket_t *sock) {
REQUIRE(sock->type == isc_nm_tcpdnssocket);
static void
tcpdns_close_direct(isc_nmsocket_t *sock) {
+ int r;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(atomic_load(&sock->closing));
isc__nmsocket_timer_stop(sock);
isc__nm_stop_reading(sock);
- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
- uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb);
+ r = uv_timer_stop(&sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_stop, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+ uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb);
}
void
udp_close_cb(uv_handle_t *handle);
static void
-timer_close_cb(uv_handle_t *handle);
+read_timer_close_cb(uv_handle_t *handle);
+
+static void
+write_timer_close_cb(uv_handle_t *handle);
static void
udp_close_direct(isc_nmsocket_t *sock);
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ r = uv_timer_init(&worker->loop, &sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+
LOCK(&sock->parent->lock);
r = uv_udp_open(&sock->uv_handle.udp, sock->fd);
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ r = uv_timer_init(&worker->loop, &sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_init, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+
r = uv_udp_open(&sock->uv_handle.udp, sock->fd);
if (r != 0) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]);
}
static void
-timer_close_cb(uv_handle_t *handle) {
+read_timer_close_cb(uv_handle_t *handle) {
isc_nmsocket_t *sock = uv_handle_get_data(handle);
uv_handle_set_data(handle, NULL);
}
}
+static void
+write_timer_close_cb(uv_handle_t *timer) {
+ isc_nmsocket_t *sock = uv_handle_get_data(timer);
+ uv_handle_set_data(timer, NULL);
+
+ REQUIRE(VALID_NMSOCK(sock));
+
+ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+ uv_close((uv_handle_t *)&sock->read_timer, read_timer_close_cb);
+}
+
static void
stop_udp_child(isc_nmsocket_t *sock) {
REQUIRE(sock->type == isc_nm_udpsocket);
static void
udp_close_direct(isc_nmsocket_t *sock) {
+ int r;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- uv_close((uv_handle_t *)&sock->read_timer, timer_close_cb);
+ r = uv_timer_stop(&sock->write_timer);
+ UV_RUNTIME_CHECK(uv_timer_stop, r);
+ uv_handle_set_data((uv_handle_t *)&sock->write_timer, sock);
+ uv_close((uv_handle_t *)&sock->write_timer, write_timer_close_cb);
}
void