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);
+isc__nm_tlsdns_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result,
+ bool async);
isc_result_t
isc__nm_tcpdns_processbuffer(isc_nmsocket_t *sock);
isc__nm_failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult);
void
isc__nm_failed_connect_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
- isc_result_t eresult);
+ isc_result_t eresult, bool async);
void
-isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
+isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, bool async);
void
isc__nmsocket_connecttimeout_cb(uv_timer_t *timer);
void
isc__nm_failed_connect_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
- isc_result_t eresult) {
+ isc_result_t eresult, bool async) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(VALID_UVREQ(req));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(atomic_load(&sock->connecting));
REQUIRE(req->cb.connect != NULL);
isc__nmsocket_timer_stop(sock);
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
- atomic_store(&sock->connecting, false);
+ INSIST(atomic_compare_exchange_strong(&sock->connecting,
+ &(bool){ true }, false));
isc__nmsocket_clearcb(sock);
- isc__nm_connectcb(sock, req, eresult, true);
+ isc__nm_connectcb(sock, req, eresult, async);
isc__nmsocket_prep_destroy(sock);
}
void
-isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
+isc__nm_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, bool async) {
REQUIRE(VALID_NMSOCK(sock));
switch (sock->type) {
case isc_nm_udpsocket:
isc__nm_tcpdns_failed_read_cb(sock, result);
return;
case isc_nm_tlsdnssocket:
- isc__nm_tlsdns_failed_read_cb(sock, result);
+ isc__nm_tlsdns_failed_read_cb(sock, result, async);
return;
default:
INSIST(0);
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);
+ if (sock->tls.pending_req != NULL) {
+ REQUIRE(req == sock->tls.pending_req);
+ sock->tls.pending_req = NULL;
+ }
+
/* 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)) {
+ INSIST(atomic_compare_exchange_strong(&sock->connecting,
+ &(bool){ true }, false));
+ isc__nm_uvreq_put(&req, sock);
isc__nmsocket_clearcb(sock);
isc__nmsocket_shutdown(sock);
- atomic_store(&sock->connecting, false);
}
}
if (!isc__nmsocket_timer_running(sock)) {
isc__nmsocket_clearcb(sock);
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
}
} else {
- isc__nm_failed_read_cb(sock, ISC_R_TIMEDOUT);
+ isc__nm_failed_read_cb(sock, ISC_R_TIMEDOUT, false);
}
}
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__nmsocket_timer_stop(sock);
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
+ if (!atomic_load(&sock->connecting)) {
+ return;
+ }
+
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
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) });
return;
error:
- isc__nm_failed_connect_cb(sock, req, result);
+ isc__nm_failed_connect_cb(sock, req, result, false);
}
void
r = uv_timer_init(&worker->loop, &sock->timer);
RUNTIME_CHECK(r == 0);
- uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
if (isc__nm_closing(sock)) {
result = ISC_R_CANCELED;
isc__nmsocket_timer_stop(sock);
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
+ if (!atomic_load(&sock->connecting)) {
+ return;
+ }
+
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
REQUIRE(VALID_NMHANDLE(req->handle));
- 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_closing(sock)) {
+ if (isc__nmsocket_closing(sock)) {
/* Socket was closed midflight by isc__nm_tcpdns_shutdown() */
result = ISC_R_CANCELED;
goto error;
return;
error:
- isc__nm_failed_connect_cb(sock, req, result);
+ isc__nm_failed_connect_cb(sock, req, result, false);
}
void
if (isc__nmsocket_closing(sock)) {
sock->reading = true;
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
REQUIRE(buf != NULL);
if (isc__nmsocket_closing(sock)) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, true);
goto free;
}
sock->statsindex[STATID_RECVFAIL]);
}
- isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nread));
+ isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nread), true);
goto free;
}
}
if (sock->statichandle != NULL) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- isc__nm_failed_read_cb(sock, ISC_R_EOF);
+ isc__nm_failed_read_cb(sock, ISC_R_EOF, false);
}
void
result = tlsdns_connect_direct(sock, req);
if (result != ISC_R_SUCCESS) {
+ INSIST(atomic_compare_exchange_strong(&sock->connecting,
+ &(bool){ true }, false));
isc__nmsocket_clearcb(sock);
isc__nm_connectcb(sock, req, result, true);
atomic_store(&sock->active, false);
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
+ if (!atomic_load(&sock->connecting)) {
+ return;
+ }
+
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
REQUIRE(VALID_NMHANDLE(req->handle));
- 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_closing(sock)) {
+ if (isc__nmsocket_closing(sock)) {
/* Socket was closed midflight by isc__nm_tlsdns_shutdown() */
result = ISC_R_CANCELED;
goto error;
return;
error:
- isc__nm_failed_connect_cb(sock, req, result);
+ isc__nm_failed_connect_cb(sock, req, result, false);
}
void
sock->result = ISC_R_DEFAULT;
sock->tls.ctx = sslctx;
atomic_init(&sock->client, true);
+ atomic_init(&sock->connecting, true);
req = isc__nm_uvreq_get(mgr, sock);
req->cb.connect = cb;
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock->fd);
if (result != ISC_R_SUCCESS) {
- if (isc__nm_in_netthread()) {
- sock->tid = isc_nm_tid();
- }
- isc__nmsocket_clearcb(sock);
- isc__nm_connectcb(sock, req, result, true);
- atomic_store(&sock->closed, true);
- isc__nmsocket_detach(&sock);
- return;
+ goto failure;
+ }
+
+ if (isc__nm_closing(sock)) {
+ goto failure;
}
/* 2 minute timeout */
atomic_store(&sock->active, true);
BROADCAST(&sock->scond);
UNLOCK(&sock->lock);
+ return;
+failure:
+ if (isc__nm_in_netthread()) {
+ sock->tid = isc_nm_tid();
+ }
+
+ INSIST(atomic_compare_exchange_strong(&sock->connecting,
+ &(bool){ true }, false));
+ isc__nmsocket_clearcb(sock);
+ isc__nm_connectcb(sock, req, result, true);
+ atomic_store(&sock->closed, true);
+ isc__nmsocket_detach(&sock);
}
static uv_os_sock_t
}
void
-isc__nm_tlsdns_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
+isc__nm_tlsdns_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result,
+ bool async) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(result != ISC_R_SUCCESS);
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);
+ isc__nm_failed_connect_cb(sock, req, ISC_R_CANCELED, async);
}
if (!sock->recv_read) {
if (isc__nmsocket_closing(sock)) {
sock->reading = true;
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
result = tls_cycle(sock);
if (result != ISC_R_SUCCESS) {
- isc__nm_failed_read_cb(sock, result);
+ isc__nm_failed_read_cb(sock, result, false);
}
}
isc__nmsocket_timer_stop(sock);
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
- atomic_store(&sock->connecting, false);
-
+ INSIST(atomic_compare_exchange_strong(
+ &sock->connecting, &(bool){ true }, false));
isc__nm_connectcb(sock, req, ISC_R_SUCCESS, true);
}
async_tlsdns_cycle(sock);
if (atomic_load(&sock->connecting)) {
isc__nm_uvreq_t *req = sock->tls.pending_req;
sock->tls.pending_req = NULL;
- isc__nm_failed_connect_cb(sock, req, result);
+
+ isc__nm_failed_connect_cb(sock, req, result, false);
} else {
- isc__nm_tlsdns_failed_read_cb(sock, result);
+ isc__nm_tlsdns_failed_read_cb(sock, result, false);
}
break;
case TLS_STATE_ERROR:
REQUIRE(buf != NULL);
if (isc__nmsocket_closing(sock)) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, true);
goto free;
}
sock->statsindex[STATID_RECVFAIL]);
}
- isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nread));
+ isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nread), true);
goto free;
}
rv = BIO_write_ex(sock->tls.app_wbio, buf->base, (size_t)nread, &len);
if (rv <= 0 || (size_t)nread != len) {
- isc__nm_failed_read_cb(sock, ISC_R_TLSERROR);
+ isc__nm_failed_read_cb(sock, ISC_R_TLSERROR, true);
goto free;
}
result = tls_cycle(sock);
if (result != ISC_R_SUCCESS) {
- isc__nm_failed_read_cb(sock, result);
+ isc__nm_failed_read_cb(sock, result, true);
}
free:
async_tlsdns_cycle(sock);
isc__nm_uvreq_t *req = sock->tls.pending_req;
sock->tls.pending_req = NULL;
- isc__nm_failed_connect_cb(sock, req, ISC_R_CANCELED);
+ isc__nm_failed_connect_cb(sock, req, ISC_R_CANCELED,
+ false);
return;
}
}
if (sock->statichandle != NULL) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- isc__nm_failed_read_cb(sock, ISC_R_EOF);
+ isc__nm_failed_read_cb(sock, ISC_R_EOF, false);
}
void
* we can free the buffer and bail.
*/
if (addr == NULL) {
- isc__nm_failed_read_cb(sock, ISC_R_EOF);
+ isc__nm_failed_read_cb(sock, ISC_R_EOF, false);
goto free;
}
* - If the socket is no longer active.
*/
if (!isc__nmsocket_active(sock)) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
goto free;
}
if (nrecv < 0) {
- isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nrecv));
+ isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nrecv),
+ false);
goto free;
}
if (isc__nmsocket_closing(sock)) {
sock->reading = true;
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
* interested in the callback.
*/
if (sock->statichandle != NULL) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(atomic_load(&sock->client));
- isc__nm_failed_read_cb(sock, ISC_R_EOF);
+ isc__nm_failed_read_cb(sock, ISC_R_EOF, false);
}
#define T_ADVERTISED 120 * 1000
#define T_CONNECT 30 * 1000
-#define WAIT_REPEATS 100
+/* Wait for 1 second (1000 * 1000 microseconds) */
+#define WAIT_REPEATS 1000
#define T_WAIT 1000 /* In microseconds */
#define WAIT_FOR(v, op, val) \
skip_long_tests = true;
}
+ if (isc_tlsctx_createserver(NULL, NULL, &tcp_listen_tlsctx) !=
+ ISC_R_SUCCESS) {
+ return (-1);
+ }
+ if (isc_tlsctx_createclient(&tcp_connect_tlsctx) != ISC_R_SUCCESS) {
+ return (-1);
+ }
+
return (0);
}
static int
_teardown(void **state __attribute__((unused))) {
+ isc_tlsctx_free(&tcp_connect_tlsctx);
+ isc_tlsctx_free(&tcp_listen_tlsctx);
+
isc_test_end();
return (0);
isc__nm_closesocket(tcp_listen_sock);
tcp_listen_sock = -1;
- if (isc_tlsctx_createserver(NULL, NULL, &tcp_listen_tlsctx) !=
- ISC_R_SUCCESS) {
- return (-1);
- }
- if (isc_tlsctx_createclient(&tcp_connect_tlsctx) != ISC_R_SUCCESS) {
- return (-1);
- }
-
atomic_store(&do_send, true);
atomic_store(&nsends, esends);
isc_nm_destroy(&listen_nm);
assert_null(listen_nm);
- isc_tlsctx_free(&tcp_connect_tlsctx);
- isc_tlsctx_free(&tcp_listen_tlsctx);
-
WAIT_FOR_EQ(active_cconnects, 0);
WAIT_FOR_EQ(active_csends, 0);
WAIT_FOR_EQ(active_csends, 0);
isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0);
while (atomic_load(&do_send)) {
- uint_fast32_t active = isc_refcount_current(&active_cconnects);
+ uint_fast32_t active =
+ isc_refcount_increment0(&active_cconnects);
if (active > workers) {
/*
* If we have more active connections than workers,
static void
udp_connect(isc_nm_t *nm) {
- isc_refcount_increment0(&active_cconnects);
isc_nm_udpconnect(nm, (isc_nmiface_t *)&udp_connect_addr,
(isc_nmiface_t *)&udp_listen_addr, connect_connect_cb,
NULL, T_CONNECT, 0);
static void
tcp_connect(isc_nm_t *nm) {
- isc_refcount_increment0(&active_cconnects);
isc_nm_tcpconnect(nm, (isc_nmiface_t *)&tcp_connect_addr,
(isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb,
NULL, 1, 0);
static void
tcpdns_connect(isc_nm_t *nm) {
- isc_refcount_increment0(&active_cconnects);
isc_nm_tcpdnsconnect(nm, (isc_nmiface_t *)&tcp_connect_addr,
(isc_nmiface_t *)&tcp_listen_addr,
connect_connect_cb, NULL, T_CONNECT, 0);
static void
tlsdns_connect(isc_nm_t *nm) {
- isc_refcount_increment0(&active_cconnects);
isc_nm_tlsdnsconnect(nm, (isc_nmiface_t *)&tcp_connect_addr,
(isc_nmiface_t *)&tcp_listen_addr,
connect_connect_cb, NULL, T_CONNECT, 0,