isc__nm_cb_t cb; /* callback */
void *cbarg; /* callback argument */
isc_nm_timer_t *timer; /* TCP write timer */
+ int connect_tries; /* connect retries */
union {
uv_handle_t handle;
req = isc_mem_get(mgr->mctx, sizeof(*req));
}
- *req = (isc__nm_uvreq_t){ .magic = 0 };
+ *req = (isc__nm_uvreq_t){
+ .magic = 0,
+ .connect_tries = 3,
+ };
ISC_LINK_INIT(req, link);
req->uv_req.req.data = req;
isc___nmsocket_attach(sock, &req->sock FLARG_PASS);
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- isc__nmsocket_timer_stop(sock);
- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
-
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
if (atomic_load(&sock->timedout)) {
result = ISC_R_TIMEDOUT;
goto error;
- }
-
- if (!atomic_load(&sock->connecting)) {
+ } else if (!atomic_load(&sock->connecting)) {
/*
* The connect was cancelled from timeout; just clean up
* the req.
/* Timeout status code here indicates hard error */
result = ISC_R_TIMEDOUT;
goto error;
+ } else if (status == UV_EADDRINUSE) {
+ /*
+ * On FreeBSD the TCP connect() call sometimes results in a
+ * spurious transient EADDRINUSE. Try a few more times before
+ * giving up.
+ */
+ if (--req->connect_tries > 0) {
+ r = uv_tcp_connect(&req->uv_req.connect,
+ &sock->uv_handle.tcp,
+ &req->peer.type.sa, tcp_connect_cb);
+ if (r != 0) {
+ isc__nm_incstats(sock, STATID_CONNECTFAIL);
+ result = isc_uverr2result(r);
+ goto error;
+ }
+ return;
+ }
+ result = isc_uverr2result(status);
+ goto error;
} else if (status != 0) {
result = isc_uverr2result(status);
goto error;
}
+ isc__nmsocket_timer_stop(sock);
+ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+
isc__nm_incstats(sock, STATID_CONNECT);
r = uv_tcp_getpeername(&sock->uv_handle.tcp, (struct sockaddr *)&ss,
&(int){ sizeof(ss) });
isc__nm_connectcb(sock, req, ISC_R_SUCCESS, false);
return;
-
error:
isc__nm_failed_connect_cb(sock, req, result, false);
}
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- isc__nmsocket_timer_stop(sock);
- uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
-
req = uv_handle_get_data((uv_handle_t *)uvreq);
REQUIRE(VALID_UVREQ(req));
if (atomic_load(&sock->timedout)) {
result = ISC_R_TIMEDOUT;
goto error;
- }
-
- if (isc__nm_closing(sock)) {
+ } else if (isc__nm_closing(sock)) {
/* Network manager shutting down */
result = ISC_R_SHUTTINGDOWN;
goto error;
/* Timeout status code here indicates hard error */
result = ISC_R_TIMEDOUT;
goto error;
+ } else if (status == UV_EADDRINUSE) {
+ /*
+ * On FreeBSD the TCP connect() call sometimes results in a
+ * spurious transient EADDRINUSE. Try a few more times before
+ * giving up.
+ */
+ if (--req->connect_tries > 0) {
+ r = uv_tcp_connect(
+ &req->uv_req.connect, &sock->uv_handle.tcp,
+ &req->peer.type.sa, tcpdns_connect_cb);
+ if (r != 0) {
+ isc__nm_incstats(sock, STATID_CONNECTFAIL);
+ result = isc_uverr2result(r);
+ goto error;
+ }
+ return;
+ }
+ result = isc_uverr2result(status);
+ goto error;
} else if (status != 0) {
result = isc_uverr2result(status);
goto error;
}
+ isc__nmsocket_timer_stop(sock);
+ uv_handle_set_data((uv_handle_t *)&sock->read_timer, sock);
+
isc__nm_incstats(sock, STATID_CONNECT);
r = uv_tcp_getpeername(&sock->uv_handle.tcp, (struct sockaddr *)&ss,
&(int){ sizeof(ss) });
isc__nm_connectcb(sock, req, ISC_R_SUCCESS, false);
return;
-
error:
isc__nm_failed_connect_cb(sock, req, result, false);
}
if (atomic_load(&sock->timedout)) {
result = ISC_R_TIMEDOUT;
goto error;
- }
-
- if (isc__nm_closing(sock)) {
+ } else if (isc__nm_closing(sock)) {
/* Network manager shutting down */
result = ISC_R_SHUTTINGDOWN;
goto error;
/* Timeout status code here indicates hard error */
result = ISC_R_TIMEDOUT;
goto error;
+ } else if (status == UV_EADDRINUSE) {
+ /*
+ * On FreeBSD the TCP connect() call sometimes results in a
+ * spurious transient EADDRINUSE. Try a few more times before
+ * giving up.
+ */
+ if (--req->connect_tries > 0) {
+ r = uv_tcp_connect(
+ &req->uv_req.connect, &sock->uv_handle.tcp,
+ &req->peer.type.sa, tlsdns_connect_cb);
+ if (r != 0) {
+ isc__nm_incstats(sock, STATID_CONNECTFAIL);
+ result = isc_uverr2result(r);
+ goto error;
+ }
+ return;
+ }
+ result = isc_uverr2result(status);
+ goto error;
} else if (status != 0) {
result = isc_uverr2result(status);
goto error;
isc__networker_t *worker = NULL;
int uv_bind_flags = UV_UDP_REUSEADDR;
isc_result_t result = ISC_R_UNSET;
- int tries = 3;
int r;
REQUIRE(isc__nm_in_netthread());
do {
r = isc_uv_udp_connect(&sock->uv_handle.udp,
&req->peer.type.sa);
- } while (r == UV_EADDRINUSE && --tries > 0);
+ } while (r == UV_EADDRINUSE && --req->connect_tries > 0);
if (r != 0) {
isc__nm_incstats(sock, STATID_CONNECTFAIL);
goto done;