r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
if (r != 0) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]);
+ /* Socket was never opened; no need for tcp_close_direct() */
+ atomic_store(&sock->closed, true);
+ sock->result = isc__nm_uverr2result(r);
+ atomic_store(&sock->connect_error, true);
return (r);
}
if (r != 0) {
isc__nm_incstats(sock->mgr,
sock->statsindex[STATID_BINDFAIL]);
+ sock->result = isc__nm_uverr2result(r);
+ atomic_store(&sock->connect_error, true);
tcp_close_direct(sock);
return (r);
}
}
+
uv_handle_set_data(&sock->uv_handle.handle, sock);
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->mgr,
+ sock->statsindex[STATID_CONNECTFAIL]);
+ sock->result = isc__nm_uverr2result(r);
+ atomic_store(&sock->connect_error, true);
+ tcp_close_direct(sock);
+ }
return (r);
}
isc__nm_uvreq_t *req = ievent->req;
int r;
- REQUIRE(sock->type == isc_nm_tcpsocket);
- REQUIRE(worker->id == ievent->req->sock->mgr->workers[isc_nm_tid()].id);
+ UNUSED(worker);
r = tcp_connect_direct(sock, req);
if (r != 0) {
/* We need to issue callbacks ourselves */
tcp_connect_cb(&req->uv_req.connect, r);
+ goto done;
}
+
+ atomic_store(&sock->connected, true);
+
+done:
+ LOCK(&sock->lock);
+ SIGNAL(&sock->cond);
+ UNLOCK(&sock->lock);
}
static void
struct sockaddr_storage ss;
isc_nmhandle_t *handle = NULL;
+ sock = uv_handle_get_data((uv_handle_t *)uvreq->handle);
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]);
uv_tcp_getpeername(&sock->uv_handle.tcp, (struct sockaddr *)&ss,
&(int){ sizeof(ss) });
* TODO:
* Handle the connect error properly and free the socket.
*/
- isc__nm_incstats(sock->mgr,
- sock->statsindex[STATID_CONNECTFAIL]);
req->cb.connect(NULL, isc__nm_uverr2result(status), req->cbarg);
isc__nm_uvreq_put(&req, sock);
}
}
+isc_result_t
+isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
+ isc_nm_cb_t cb, void *cbarg, size_t extrahandlesize) {
+ isc_nmsocket_t *nsock = NULL;
+ isc__netievent_tcpconnect_t *ievent = NULL;
+ isc__nm_uvreq_t *req = NULL;
+
+ REQUIRE(VALID_NM(mgr));
+
+ nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
+ isc__nmsocket_init(nsock, mgr, isc_nm_tcpsocket, local);
+ nsock->extrahandlesize = extrahandlesize;
+ nsock->result = ISC_R_SUCCESS;
+
+ req = isc__nm_uvreq_get(mgr, nsock);
+ req->cb.connect = cb;
+ req->cbarg = cbarg;
+ req->peer = peer->addr;
+
+ ievent = isc__nm_get_ievent(mgr, netievent_tcpconnect);
+ ievent->sock = nsock;
+ ievent->req = req;
+
+ if (isc__nm_in_netthread()) {
+ nsock->tid = isc_nm_tid();
+ isc__nm_async_tcpconnect(&mgr->workers[nsock->tid],
+ (isc__netievent_t *)ievent);
+ isc__nm_put_ievent(mgr, ievent);
+ } else {
+ nsock->tid = isc_random_uniform(mgr->nworkers);
+ isc__nm_enqueue_ievent(&mgr->workers[nsock->tid],
+ (isc__netievent_t *)ievent);
+
+ LOCK(&nsock->lock);
+ while (!atomic_load(&nsock->connected) &&
+ !atomic_load(&nsock->connect_error)) {
+ WAIT(&nsock->cond, &nsock->lock);
+ }
+ UNLOCK(&nsock->lock);
+ }
+
+ if (nsock->result != ISC_R_SUCCESS) {
+ isc_result_t result = nsock->result;
+ isc__nmsocket_detach(&nsock);
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
isc_result_t
isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
void *cbarg, size_t extrahandlesize, int backlog,
r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
if (r != 0) {
- /* It was never opened */
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]);
+ /* The socket was never opened, so no need for uv_close() */
atomic_store(&sock->closed, true);
sock->result = isc__nm_uverr2result(r);
atomic_store(&sock->listen_error, true);
tcp_send_cb(uv_write_t *req, int status) {
isc_result_t result = ISC_R_SUCCESS;
isc__nm_uvreq_t *uvreq = (isc__nm_uvreq_t *)req->data;
+ isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_UVREQ(uvreq));
REQUIRE(VALID_NMHANDLE(uvreq->handle));
}
uvreq->cb.send(uvreq->handle, result, uvreq->cbarg);
+
+ sock = uvreq->handle->sock;
isc_nmhandle_unref(uvreq->handle);
- isc__nm_uvreq_put(&uvreq, uvreq->handle->sock);
+ isc__nm_uvreq_put(&uvreq, sock);
}
/*
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CLOSE]);
atomic_store(&sock->closed, true);
+ atomic_store(&sock->connected, false);
isc__nmsocket_prep_destroy(sock);
}