req->handle = isc__nmhandle_get(sock, &sock->peer, &sock->iface->addr);
isc__nmsocket_clearcb(sock);
- isc__nm_connectcb_force_async(sock, req, result);
+ isc__nm_connectcb(sock, req, result, true);
}
static void
void
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
- isc_result_t eresult);
-
-void
-isc__nm_connectcb_force_async(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
- isc_result_t eresult);
+ isc_result_t eresult, bool async);
void
isc__nm_async_connectcb(isc__networker_t *worker, isc__netievent_t *ev0);
void
isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
+void
+isc__nmsocket_connecttimeout_cb(uv_timer_t *timer);
+
#define STREAM_CLIENTS_PER_CONN 23
NETIEVENT_SOCKET_REQ_DEF(tcpsend);
NETIEVENT_SOCKET_REQ_DEF(tlssend);
NETIEVENT_SOCKET_REQ_DEF(udpconnect);
-
NETIEVENT_SOCKET_REQ_RESULT_DEF(connectcb);
NETIEVENT_SOCKET_REQ_RESULT_DEF(readcb);
NETIEVENT_SOCKET_REQ_RESULT_DEF(sendcb);
int active_handles;
bool destroy = false;
+ NETMGR_TRACE_LOG("%s():%p->references = %" PRIuFAST32 "\n", __func__,
+ sock, isc_refcount_current(&sock->references));
+
if (sock->parent != NULL) {
/*
* This is a child socket and cannot be destroyed except
}
}
+static void
+isc__nmsocket_shutdown(isc_nmsocket_t *sock);
+
static void
nmhandle_detach_cb(isc_nmhandle_t **handlep FLARG) {
isc_nmsocket_t *sock = NULL;
REQUIRE(atomic_load(&sock->connecting));
REQUIRE(req->cb.connect != NULL);
+ isc__nmsocket_timer_stop(sock);
+
atomic_store(&sock->connecting, false);
isc__nmsocket_clearcb(sock);
-
- isc__nm_connectcb(sock, req, eresult);
+ isc__nm_connectcb(sock, req, eresult, true);
isc__nmsocket_prep_destroy(sock);
}
}
}
+void
+isc__nmsocket_connecttimeout_cb(uv_timer_t *timer) {
+ uv_connect_t *uvreq = uv_handle_get_data((uv_handle_t *)timer);
+ isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)uvreq->handle);
+ isc__nm_uvreq_t *req = uv_handle_get_data((uv_handle_t *)uvreq);
+
+ REQUIRE(VALID_NMSOCK(sock));
+ REQUIRE(sock->tid == isc_nm_tid());
+ REQUIRE(atomic_load(&sock->connecting));
+ REQUIRE(atomic_load(&sock->client));
+ REQUIRE(VALID_UVREQ(req));
+ REQUIRE(VALID_NMHANDLE(req->handle));
+
+ isc__nmsocket_timer_stop(sock);
+
+ /* Call the connect callback directly */
+ req->cb.connect(req->handle, ISC_R_TIMEDOUT, req->cbarg);
+
+ /* Timer is not running, cleanup and shutdown everything */
+ if (!isc__nmsocket_timer_running(sock)) {
+ isc__nmsocket_clearcb(sock);
+ isc__nmsocket_shutdown(sock);
+ atomic_store(&sock->connecting, false);
+ }
+}
+
static void
isc__nmsocket_readtimeout_cb(uv_timer_t *timer) {
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)timer);
REQUIRE(sock->reading);
if (atomic_load(&sock->client)) {
+ uv_timer_stop(timer);
+
if (sock->recv_cb != NULL) {
isc__nm_uvreq_t *req = isc__nm_get_read_req(sock, NULL);
isc__nm_readcb(sock, req, ISC_R_TIMEDOUT);
void
isc__nmsocket_timer_restart(isc_nmsocket_t *sock) {
+ int r = 0;
+
REQUIRE(VALID_NMSOCK(sock));
- if (sock->read_timeout == 0) {
- return;
+ if (atomic_load(&sock->connecting)) {
+ if (sock->connect_timeout == 0) {
+ return;
+ }
+
+ r = uv_timer_start(&sock->timer,
+ isc__nmsocket_connecttimeout_cb,
+ sock->connect_timeout + 10, 0);
+
+ } else {
+ if (sock->read_timeout == 0) {
+ return;
+ }
+
+ r = uv_timer_start(&sock->timer, isc__nmsocket_readtimeout_cb,
+ sock->read_timeout, 0);
}
- int r = uv_timer_start(&sock->timer, isc__nmsocket_readtimeout_cb,
- sock->read_timeout, 0);
RUNTIME_CHECK(r == 0);
}
}
}
-static void
-nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq, isc_result_t eresult,
- bool force_async) {
- isc__netievent_connectcb_t *ievent = NULL;
-
+void
+isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
+ isc_result_t eresult, bool async) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(VALID_UVREQ(uvreq));
REQUIRE(VALID_NMHANDLE(uvreq->handle));
- ievent = isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq,
- eresult);
- if (force_async) {
- isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
- (isc__netievent_t *)ievent);
- } else {
- isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
- (isc__netievent_t *)ievent);
+ if (!async) {
+ isc__netievent_connectcb_t ievent = { .sock = sock,
+ .req = uvreq,
+ .result = eresult };
+ isc__nm_async_connectcb(NULL, (isc__netievent_t *)&ievent);
+ return;
}
-}
-
-void
-isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
- isc_result_t eresult) {
- nm_connectcb(sock, uvreq, eresult, false);
-}
-
-void
-isc__nm_connectcb_force_async(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
- isc_result_t eresult) {
- nm_connectcb(sock, uvreq, eresult, true);
+ isc__netievent_connectcb_t *ievent = isc__nm_get_netievent_connectcb(
+ sock->mgr, sock, uvreq, eresult);
+ isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
+ (isc__netievent_t *)ievent);
}
void
}
static void
-shutdown_walk_cb(uv_handle_t *handle, void *arg) {
- isc_nmsocket_t *sock = uv_handle_get_data(handle);
- UNUSED(arg);
-
- if (uv_is_closing(handle)) {
- return;
- }
-
- switch (handle->type) {
- case UV_UDP:
- case UV_TCP:
- break;
- default:
- return;
- }
-
+isc__nmsocket_shutdown(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
switch (sock->type) {
case isc_nm_udpsocket:
}
}
+static void
+shutdown_walk_cb(uv_handle_t *handle, void *arg) {
+ isc_nmsocket_t *sock = uv_handle_get_data(handle);
+ UNUSED(arg);
+
+ if (uv_is_closing(handle)) {
+ return;
+ }
+
+ switch (handle->type) {
+ case UV_UDP:
+ case UV_TCP:
+ break;
+ default:
+ return;
+ }
+
+ isc__nmsocket_shutdown(sock);
+}
+
void
isc__nm_async_shutdown(isc__networker_t *worker, isc__netievent_t *ev0) {
UNUSED(ev0);
}
}
-static void
-failed_connect_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
- isc_result_t eresult) {
- REQUIRE(VALID_NMSOCK(sock));
- REQUIRE(VALID_UVREQ(req));
- REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(atomic_load(&sock->connecting));
- REQUIRE(req->cb.connect != NULL);
-
- atomic_store(&sock->connecting, false);
-
- isc__nmsocket_clearcb(sock);
- isc__nm_connectcb(sock, req, eresult);
-
- isc__nmsocket_prep_destroy(sock);
-}
-
static isc_result_t
tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
isc__networker_t *worker = NULL;
REQUIRE(isc__nm_in_netthread());
REQUIRE(sock->tid == isc_nm_tid());
- result = isc__nm_socket_connectiontimeout(sock->fd,
- sock->connect_timeout);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
-
worker = &sock->mgr->workers[sock->tid];
atomic_store(&sock->connecting, true);
+ /* 2 minute timeout */
+ result = isc__nm_socket_connectiontimeout(sock->fd, 120 * 1000);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
RUNTIME_CHECK(r == 0);
uv_handle_set_data(&sock->uv_handle.handle, sock);
r = uv_timer_init(&worker->loop, &sock->timer);
RUNTIME_CHECK(r == 0);
- uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd);
if (r != 0) {
}
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]);
+ uv_handle_set_data((uv_handle_t *)&sock->timer, &req->uv_req.connect);
+ isc__nmsocket_timer_start(sock);
+
atomic_store(&sock->connected, true);
done:
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(atomic_load(&sock->connecting));
+
+ isc__nmsocket_timer_stop(sock);
+ uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
REQUIRE(VALID_NMHANDLE(req->handle));
- /* Socket was closed midflight by isc__nm_tcp_shutdown() */
- if (!isc__nmsocket_active(sock)) {
+ if (!atomic_load(&sock->connecting)) {
+ /*
+ * The connect was cancelled from timeout; just clean up
+ * the req.
+ */
+ isc__nm_uvreq_put(&req, sock);
+ return;
+ } else if (!isc__nmsocket_active(sock)) {
+ /* Socket was closed midflight by isc__nm_tcp_shutdown() */
result = ISC_R_CANCELED;
goto error;
- }
-
- if (status != 0) {
+ } else if (status == UV_ETIMEDOUT) {
+ /* Timeout status code here indicates hard error */
+ result = ISC_R_TIMEDOUT;
+ goto error;
+ } else if (status != 0) {
result = isc__nm_uverr2result(status);
goto error;
}
+ uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
+
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]);
r = uv_tcp_getpeername(&sock->uv_handle.tcp, (struct sockaddr *)&ss,
&(int){ sizeof(ss) });
result = isc_sockaddr_fromsockaddr(&sock->peer, (struct sockaddr *)&ss);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc__nm_connectcb(sock, req, ISC_R_SUCCESS);
+ isc__nm_connectcb(sock, req, ISC_R_SUCCESS, false);
return;
error:
- failed_connect_cb(sock, req, result);
+ isc__nm_failed_connect_cb(sock, req, result);
}
isc_result_t
}
static void
-tcp_close_cb(uv_handle_t *handle) {
- isc_nmsocket_t *sock = uv_handle_get_data(handle);
- uv_handle_set_data(handle, NULL);
-
+tcp_close_sock(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(atomic_load(&sock->closing));
isc__nmsocket_prep_destroy(sock);
}
+static void
+tcp_close_cb(uv_handle_t *handle) {
+ isc_nmsocket_t *sock = uv_handle_get_data(handle);
+ uv_handle_set_data(handle, NULL);
+
+ tcp_close_sock(sock);
+}
+
static void
timer_close_cb(uv_handle_t *handle) {
isc_nmsocket_t *sock = uv_handle_get_data(handle);
if (sock->parent) {
uv_close(&sock->uv_handle.handle, tcp_stop_cb);
+ } else if (uv_is_closing(&sock->uv_handle.handle)) {
+ tcp_close_sock(sock);
} else {
uv_close(&sock->uv_handle.handle, tcp_close_cb);
}
tcp_close_direct(sock);
}
+static void
+tcp_close_connect_cb(uv_handle_t *handle) {
+ isc_nmsocket_t *sock = uv_handle_get_data(handle);
+
+ REQUIRE(VALID_NMSOCK(sock));
+
+ REQUIRE(isc__nm_in_netthread());
+ REQUIRE(sock->tid == isc_nm_tid());
+
+ isc__nmsocket_prep_destroy(sock);
+ isc__nmsocket_detach(&sock);
+}
+
void
isc__nm_tcp_shutdown(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
return;
}
- if (atomic_load(&sock->connecting) || sock->accepting) {
+ if (sock->accepting) {
+ return;
+ }
+
+ if (atomic_load(&sock->connecting)) {
+ isc_nmsocket_t *tsock = NULL;
+ isc__nmsocket_attach(sock, &tsock);
+ uv_close(&sock->uv_handle.handle, tcp_close_connect_cb);
return;
}
}
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]);
+ uv_handle_set_data((uv_handle_t *)&sock->timer, &req->uv_req.connect);
+ isc__nmsocket_timer_start(sock);
+
atomic_store(&sock->connected, true);
done:
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(atomic_load(&sock->connecting));
+
+ isc__nmsocket_timer_stop(sock);
+ uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
REQUIRE(VALID_NMHANDLE(req->handle));
- /* Socket was closed midflight by isc__nm_tcpdns_shutdown() */
- if (!isc__nmsocket_active(sock)) {
+ if (!atomic_load(&sock->connecting)) {
+ /*
+ * The connect was cancelled from timeout; just clean up
+ * the req.
+ */
+ isc__nm_uvreq_put(&req, sock);
+ return;
+ } else if (!isc__nmsocket_active(sock)) {
+ /* Socket was closed midflight by isc__nm_tcpdns_shutdown() */
result = ISC_R_CANCELED;
goto error;
- }
-
- if (status != 0) {
+ } else if (status == UV_ETIMEDOUT) {
+ /* Timeout status code here indicates hard error */
+ result = ISC_R_CANCELED;
+ goto error;
+ } else if (status != 0) {
result = isc__nm_uverr2result(status);
goto error;
}
result = isc_sockaddr_fromsockaddr(&sock->peer, (struct sockaddr *)&ss);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- isc__nm_connectcb(sock, req, ISC_R_SUCCESS);
+ isc__nm_connectcb(sock, req, ISC_R_SUCCESS, false);
return;
sock->fd = fd;
atomic_init(&sock->client, true);
- result = isc__nm_socket_connectiontimeout(fd, timeout);
+ result = isc__nm_socket_connectiontimeout(fd, 120 * 1000); /* 2 mins */
RUNTIME_CHECK(result == ISC_R_SUCCESS);
req = isc__nm_uvreq_get(mgr, sock);
}
static void
-tcpdns_close_cb(uv_handle_t *handle) {
- isc_nmsocket_t *sock = uv_handle_get_data(handle);
-
- uv_handle_set_data(handle, NULL);
-
+tcpdns_close_sock(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(atomic_load(&sock->closing));
}
static void
-timer_close_cb(uv_handle_t *handle) {
+tcpdns_close_cb(uv_handle_t *handle) {
isc_nmsocket_t *sock = uv_handle_get_data(handle);
+
uv_handle_set_data(handle, NULL);
+ tcpdns_close_sock(sock);
+}
+
+static void
+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));
+
if (sock->parent) {
uv_close(&sock->uv_handle.handle, tcpdns_stop_cb);
+ } else if (uv_is_closing(&sock->uv_handle.handle)) {
+ tcpdns_close_sock(sock);
} else {
uv_close(&sock->uv_handle.handle, tcpdns_close_cb);
}
isc__nmsocket_timer_stop(sock);
isc__nm_stop_reading(sock);
+
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
}
tcpdns_close_direct(sock);
}
+static void
+tcpdns_close_connect_cb(uv_handle_t *handle) {
+ isc_nmsocket_t *sock = uv_handle_get_data(handle);
+
+ REQUIRE(VALID_NMSOCK(sock));
+
+ REQUIRE(isc__nm_in_netthread());
+ REQUIRE(sock->tid == isc_nm_tid());
+
+ isc__nmsocket_prep_destroy(sock);
+ isc__nmsocket_detach(&sock);
+}
+
void
isc__nm_tcpdns_shutdown(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
return;
}
- if (atomic_load(&sock->connecting) || sock->accepting) {
+ if (sock->accepting) {
+ return;
+ }
+
+ if (atomic_load(&sock->connecting)) {
+ isc_nmsocket_t *tsock = NULL;
+ isc__nmsocket_attach(sock, &tsock);
+ uv_close(&sock->uv_handle.handle, tcpdns_close_connect_cb);
return;
}
}
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]);
+ uv_handle_set_data((uv_handle_t *)&sock->timer, &req->uv_req.connect);
+ isc__nmsocket_timer_start(sock);
+
atomic_store(&sock->connected, true);
done:
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(atomic_load(&sock->connecting));
+
+ isc__nmsocket_timer_stop(sock);
+ uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
REQUIRE(VALID_NMHANDLE(req->handle));
- /* Socket was closed midflight by isc__nm_tlsdns_shutdown() */
- if (!isc__nmsocket_active(sock)) {
+ if (!atomic_load(&sock->connecting)) {
+ /*
+ * The connect was cancelled from timeout; just clean up
+ * the req.
+ */
+ isc__nm_uvreq_put(&req, sock);
+ return;
+ } else if (!isc__nmsocket_active(sock)) {
+ /* Socket was closed midflight by isc__nm_tcpdns_shutdown() */
result = ISC_R_CANCELED;
goto error;
- }
-
- if (status != 0) {
+ } else if (status == UV_ETIMEDOUT) {
+ /* Timeout status code here indicates hard error */
+ result = ISC_R_CANCELED;
+ goto error;
+ } else if (status != 0) {
result = isc__nm_uverr2result(status);
goto error;
}
#if HAVE_SSL_SET0_RBIO && HAVE_SSL_SET0_WBIO
/*
- * Note that if the rbio and wbio are the same then SSL_set0_rbio() and
- * SSL_set0_wbio() each take ownership of one reference. Therefore it
- * may be necessary to increment the number of references available
- * using BIO_up_ref(3) before calling the set0 functions.
+ * Note that if the rbio and wbio are the same then
+ * SSL_set0_rbio() and SSL_set0_wbio() each take ownership of
+ * one reference. Therefore it may be necessary to increment the
+ * number of references available using BIO_up_ref(3) before
+ * calling the set0 functions.
*/
SSL_set0_rbio(sock->tls.tls, sock->tls.ssl_rbio);
SSL_set0_wbio(sock->tls.tls, sock->tls.ssl_wbio);
sa_family = peer->addr.type.sa.sa_family;
/*
- * The socket() call can fail spuriously on FreeBSD 12, so we need to
- * handle the failure early and gracefully.
+ * The socket() call can fail spuriously on FreeBSD 12, so we
+ * need to handle the failure early and gracefully.
*/
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &fd);
if (result != ISC_R_SUCCESS) {
atomic_init(&sock->client, true);
- result = isc__nm_socket_connectiontimeout(fd, timeout);
+ result = isc__nm_socket_connectiontimeout(fd, 120 * 1000); /* 2 mins */
RUNTIME_CHECK(result == ISC_R_SUCCESS);
req = isc__nm_uvreq_get(mgr, sock);
#endif
/*
- * The callback will run in the same thread uv_listen() was called
- * from, so a race with tlsdns_connection_cb() isn't possible.
+ * The callback will run in the same thread uv_listen() was
+ * called from, so a race with tlsdns_connection_cb() isn't
+ * possible.
*/
r = uv_listen((uv_stream_t *)&sock->uv_handle.tcp, sock->backlog,
tlsdns_connection_cb);
}
/*
- * If network manager is interlocked, re-enqueue the event for later.
+ * If network manager is interlocked, re-enqueue the event for
+ * later.
*/
if (!isc__nm_acquire_interlocked(sock->mgr)) {
enqueue_stoplistening(sock);
destroy:
isc__nmsocket_prep_destroy(sock);
- /* We need to detach from quota after the read callback function had a
- * chance to be executed. */
+ /* We need to detach from quota after the read callback function
+ * had a chance to be executed. */
if (sock->quota) {
isc_quota_detach(&sock->quota);
}
ievent = isc__nm_get_netievent_tlsdnsread(sock->mgr, sock);
/*
- * This MUST be done asynchronously, no matter which thread we're
- * in. The callback function for isc_nm_read() often calls
+ * This MUST be done asynchronously, no matter which thread
+ * we're in. The callback function for isc_nm_read() often calls
* isc_nm_read() again; if we tried to do that synchronously
- * we'd clash in processbuffer() and grow the stack indefinitely.
+ * we'd clash in processbuffer() and grow the stack
+ * indefinitely.
*/
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
/*
* We need to launch the resume_processing after the buffer has
- * been consumed, thus we need to delay the detaching the handle.
+ * been consumed, thus we need to delay the detaching the
+ * handle.
*/
isc_nmhandle_attach(req->handle, &handle);
req->uvbuf.len = len;
/*
- * If isc__nm_tlsdns_read() was called, it will be satisfied by single
- * DNS message in the next call.
+ * If isc__nm_tlsdns_read() was called, it will be satisfied by
+ * single DNS message in the next call.
*/
sock->recv_read = false;
/*
- * The assertion failure here means that there's a errnoneous extra
- * nmhandle detach happening in the callback and resume_processing gets
- * called while we are still processing the buffer.
+ * The assertion failure here means that there's a errnoneous
+ * extra nmhandle detach happening in the callback and
+ * resume_processing gets called while we are still processing
+ * the buffer.
*/
REQUIRE(sock->processing == false);
sock->processing = true;
sock->buf + sock->buf_len,
sock->buf_size - sock->buf_len, &len);
if (rv != 1) {
- /* Process what's in the buffer so far */
+ /* Process what's in the buffer so far
+ */
isc__nm_process_sock_buffer(sock);
- /* FIXME: Should we call failed_read_cb()? */
+ /* FIXME: Should we call
+ * failed_read_cb()? */
break;
}
atomic_store(&sock->connecting, false);
- isc__nm_connectcb(sock, req, ISC_R_SUCCESS);
+ isc__nm_connectcb(sock, req, ISC_R_SUCCESS, true);
}
async_tlsdns_cycle(sock);
}
req->uvbuf.len - err);
req->uvbuf.len = req->uvbuf.len - err;
} else if (err == UV_ENOSYS || err == UV_EAGAIN) {
- /* uv_try_write is not supported, send asynchronously */
+ /* uv_try_write is not supported, send
+ * asynchronously */
} else {
result = isc__nm_uverr2result(err);
isc__nm_uvreq_put(&req, sock);
REQUIRE(VALID_NMSOCK(sock));
/*
- * Create a tlsdnsaccept event and pass it using the async channel.
+ * Create a tlsdnsaccept event and pass it using the async
+ * channel.
*/
isc__netievent_tlsdnsaccept_t *ievent =
}
/*
- * The handle will be either detached on acceptcb failure or in the
- * readcb.
+ * The handle will be either detached on acceptcb failure or in
+ * the readcb.
*/
handle = isc__nmhandle_get(csock, NULL, &local);
#if HAVE_SSL_SET0_RBIO && HAVE_SSL_SET0_WBIO
/*
- * Note that if the rbio and wbio are the same then SSL_set0_rbio() and
- * SSL_set0_wbio() each take ownership of one reference. Therefore it
- * may be necessary to increment the number of references available
- * using BIO_up_ref(3) before calling the set0 functions.
+ * Note that if the rbio and wbio are the same then
+ * SSL_set0_rbio() and SSL_set0_wbio() each take ownership of
+ * one reference. Therefore it may be necessary to increment the
+ * number of references available using BIO_up_ref(3) before
+ * calling the set0 functions.
*/
SSL_set0_rbio(csock->tls.tls, csock->tls.ssl_rbio);
SSL_set0_wbio(csock->tls.tls, csock->tls.ssl_wbio);
csock->closehandle_cb = isc__nm_resume_processing;
/*
- * We need to keep the handle alive until we fail to read or connection
- * is closed by the other side, it will be detached via
- * prep_destroy()->tlsdns_close_direct().
+ * We need to keep the handle alive until we fail to read or
+ * connection is closed by the other side, it will be detached
+ * via prep_destroy()->tlsdns_close_direct().
*/
isc_nmhandle_attach(handle, &csock->recv_handle);
/*
- * The initial timer has been set, update the read timeout for the next
- * reads.
+ * The initial timer has been set, update the read timeout for
+ * the next reads.
*/
csock->read_timeout = (atomic_load(&csock->keepalive)
? atomic_load(&csock->mgr->keepalive)
}
/*
- * There's no SSL_writev(), so we need to use a local buffer to assemble
- * the whole message
+ * There's no SSL_writev(), so we need to use a local buffer to
+ * assemble the whole message
*/
worker = &sock->mgr->workers[sock->tid];
sendlen = req->uvbuf.len + sizeof(uint16_t);
}
static void
-tlsdns_close_cb(uv_handle_t *handle) {
- isc_nmsocket_t *sock = uv_handle_get_data(handle);
- uv_handle_set_data(handle, NULL);
-
+tlsdns_close_sock(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(atomic_load(&sock->closing));
}
static void
-timer_close_cb(uv_handle_t *handle) {
+tlsdns_close_cb(uv_handle_t *handle) {
isc_nmsocket_t *sock = uv_handle_get_data(handle);
+ uv_handle_set_data(handle, NULL);
+
+ tlsdns_close_sock(sock);
+}
+static void
+timer_close_cb(uv_handle_t *handle) {
+ isc_nmsocket_t *sock = uv_handle_get_data(handle);
uv_handle_set_data(handle, NULL);
+ REQUIRE(VALID_NMSOCK(sock));
+
if (sock->parent) {
uv_close(&sock->uv_handle.handle, tlsdns_stop_cb);
+ } else if (uv_is_closing(&sock->uv_handle.handle)) {
+ tlsdns_close_sock(sock);
} else {
uv_close(&sock->uv_handle.handle, tlsdns_close_cb);
}
tlsdns_close_direct(sock);
} else {
/*
- * We need to create an event and pass it using async channel
+ * We need to create an event and pass it using async
+ * channel
*/
isc__netievent_tlsdnsclose_t *ievent =
isc__nm_get_netievent_tlsdnsclose(sock->mgr, sock);
tlsdns_close_direct(sock);
}
+static void
+tlsdns_close_connect_cb(uv_handle_t *handle) {
+ isc_nmsocket_t *sock = uv_handle_get_data(handle);
+
+ REQUIRE(VALID_NMSOCK(sock));
+
+ REQUIRE(isc__nm_in_netthread());
+ REQUIRE(sock->tid == isc_nm_tid());
+
+ isc__nmsocket_prep_destroy(sock);
+ isc__nmsocket_detach(&sock);
+}
+
void
isc__nm_tlsdns_shutdown(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
return;
}
+ if (sock->accepting) {
+ return;
+ }
+
if (sock->tls.pending_req != NULL) {
isc__nm_uvreq_t *req = sock->tls.pending_req;
sock->tls.pending_req = NULL;
+
isc__nm_failed_connect_cb(sock, req, ISC_R_CANCELED);
+
+ return;
}
- if (atomic_load(&sock->connecting) || sock->accepting) {
+ if (atomic_load(&sock->connecting)) {
+ isc_nmsocket_t *tsock = NULL;
+ isc__nmsocket_attach(sock, &tsock);
+ uv_close(&sock->uv_handle.handle, tlsdns_close_connect_cb);
return;
}
* The callback has to be called after the socket has been
* initialized
*/
- isc__nm_connectcb(sock, req, ISC_R_SUCCESS);
+ isc__nm_connectcb(sock, req, ISC_R_SUCCESS, true);
}
/*