isc__nm_decstats(sock->mgr, sock->statsindex[STATID_ACTIVE]);
}
- if (sock->tcphandle != NULL) {
- isc_nmhandle_unref(sock->tcphandle);
- sock->tcphandle = NULL;
+ sock->tcphandle = NULL;
+
+ if (sock->outerhandle != NULL) {
+ isc_nmhandle_unref(sock->outerhandle);
+ sock->outerhandle = NULL;
+ }
+
+ if (sock->outer != NULL) {
+ isc__nmsocket_detach(&sock->outer);
}
while ((handle = isc_astack_pop(sock->inactivehandles)) != NULL) {
isc_refcount_increment0(&handle->references);
}
- handle->sock = sock;
+ isc__nmsocket_attach(sock, &handle->sock);
+
if (peer != NULL) {
memcpy(&handle->peer, peer, sizeof(isc_sockaddr_t));
} else {
void
isc_nmhandle_unref(isc_nmhandle_t *handle) {
- isc_nmsocket_t *sock = NULL, *tmp = NULL;
+ isc_nmsocket_t *sock = NULL;
REQUIRE(VALID_NMHANDLE(handle));
* be deleted by another thread while we're deactivating the
* handle.
*/
- isc__nmsocket_attach(sock, &tmp);
nmhandle_deactivate(sock, handle);
/*
}
}
- isc__nmsocket_detach(&tmp);
+ isc__nmsocket_detach(&sock);
}
void *
tcp_connect_cb(uv_connect_t *uvreq, int status) {
isc__nm_uvreq_t *req = (isc__nm_uvreq_t *)uvreq->data;
isc_nmsocket_t *sock = NULL;
+
sock = uv_handle_get_data((uv_handle_t *)uvreq->handle);
REQUIRE(VALID_UVREQ(req));
if (status == 0) {
isc_result_t result;
- isc_nmhandle_t *handle = NULL;
struct sockaddr_storage ss;
+ isc_nmhandle_t *handle = NULL;
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_CONNECT]);
uv_tcp_getpeername(&sock->uv_handle.tcp, (struct sockaddr *)&ss,
handle = isc__nmhandle_get(sock, NULL, NULL);
req->cb.connect(handle, ISC_R_SUCCESS, req->cbarg);
+
+ isc__nm_uvreq_put(&req, sock);
+
+ /*
+ * The sock is now attached to the handle.
+ */
+ isc__nmsocket_detach(&sock);
+
+ /*
+ * If the connect callback wants to hold on to the handle,
+ * it needs to attach to it.
+ */
+ isc_nmhandle_unref(handle);
} else {
/*
* TODO:
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__nm_uvreq_put(&req, sock);
}
isc_result_t
nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
isc__nmsocket_init(nsock, mgr, isc_nm_tcplistener, iface);
- nsock->rcb.accept = cb;
- nsock->rcbarg = cbarg;
+ nsock->accept_cb.accept = cb;
+ nsock->accept_cbarg = cbarg;
nsock->extrahandlesize = extrahandlesize;
nsock->backlog = backlog;
nsock->result = ISC_R_SUCCESS;
handle = isc__nmhandle_get(csock, NULL, &local);
- INSIST(ssock->rcb.accept != NULL);
+ INSIST(ssock->accept_cb.accept != NULL);
csock->read_timeout = ssock->mgr->init;
- ssock->rcb.accept(handle, ISC_R_SUCCESS, ssock->rcbarg);
+ ssock->accept_cb.accept(handle, ISC_R_SUCCESS, ssock->accept_cbarg);
+
+ /*
+ * csock is now attached to the handle.
+ */
isc__nmsocket_detach(&csock);
+
+ /*
+ * If the accept callback wants to hold on to the handle,
+ * it needs to attach to it.
+ */
+ isc_nmhandle_unref(handle);
return;
error:
REQUIRE(VALID_NMSOCK(sock));
- isc__nmsocket_detach(&sock->server);
+ if (sock->server != NULL) {
+ isc__nmsocket_detach(&sock->server);
+ }
uv_close(&sock->uv_handle.handle, tcp_close_cb);
}
timer_close_cb(uv_handle_t *handle) {
isc_nmsocket_t *sock = (isc_nmsocket_t *)uv_handle_get_data(handle);
INSIST(VALID_NMSOCK(sock));
- isc__nmsocket_detach(&sock);
}
static void
dnssock->extrahandlesize = dnslistensock->extrahandlesize;
isc__nmsocket_attach(dnslistensock, &dnssock->listener);
- isc__nmsocket_attach(handle->sock, &dnssock->outer);
+
+ dnssock->outerhandle = handle;
+ isc_nmhandle_ref(dnssock->outerhandle);
+
dnssock->peer = handle->sock->peer;
dnssock->read_timeout = handle->sock->mgr->init;
dnssock->tid = isc_nm_tid();
uv_timer_start(&dnssock->timer, dnstcp_readtimeout,
dnssock->read_timeout, 0);
- isc_nm_read(handle, dnslisten_readcb, dnssock);
+ isc_nmhandle_ref(handle);
+ result = isc_nm_read(handle, dnslisten_readcb, dnssock);
+ if (result != ISC_R_SUCCESS) {
+ isc_nmhandle_unref(handle);
+ }
}
/*
dnssock->buf_len);
}
+ /*
+ * dnssock is now attached to dnshandle
+ */
+ isc__nmsocket_detach(&dnssock);
+
*handlep = dnshandle;
return (ISC_R_SUCCESS);
}
/*
* We have a packet: stop timeout timers
*/
- atomic_store(&dnssock->outer->processing, true);
+ atomic_store(&dnssock->outerhandle->sock->processing, true);
if (dnssock->timer_initialized) {
uv_timer_stop(&dnssock->timer);
}
* one packet, so we're done until the next read
* completes.
*/
- isc_nm_pauseread(dnssock->outer);
+ isc_nm_pauseread(dnssock->outerhandle->sock);
done = true;
} else {
/*
*/
if (atomic_load(&dnssock->ah) >=
TCPDNS_CLIENTS_PER_CONN) {
- isc_nm_pauseread(dnssock->outer);
+ isc_nm_pauseread(dnssock->outerhandle->sock);
done = true;
}
}
sock->rcbarg = NULL;
if (sock->outer != NULL) {
- isc_nm_stoplistening(sock->outer);
+ isc__nm_tcp_stoplistening(sock->outer);
isc__nmsocket_detach(&sock->outer);
}
}
REQUIRE(VALID_NMHANDLE(handle));
if (handle->sock->type != isc_nm_tcpdnssocket ||
- handle->sock->outer == NULL) {
+ handle->sock->outerhandle == NULL)
+ {
return;
}
* closehandle_cb callback, called whenever a handle
* is released.
*/
- isc_nm_pauseread(handle->sock->outer);
+ isc_nm_pauseread(handle->sock->outerhandle->sock);
atomic_store(&handle->sock->sequential, true);
}
REQUIRE(VALID_NMHANDLE(handle));
if (handle->sock->type != isc_nm_tcpdnssocket ||
- handle->sock->outer == NULL) {
+ handle->sock->outerhandle == NULL)
+ {
return;
}
atomic_store(&handle->sock->keepalive, true);
- atomic_store(&handle->sock->outer->keepalive, true);
+ atomic_store(&handle->sock->outerhandle->sock->keepalive, true);
}
typedef struct tcpsend {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- if (sock->type != isc_nm_tcpdnssocket || sock->outer == NULL) {
+ if (sock->type != isc_nm_tcpdnssocket || sock->outerhandle == NULL) {
return;
}
if (atomic_load(&sock->ah) == 0) {
/* Nothing is active; sockets can timeout now */
- atomic_store(&sock->outer->processing, false);
+ atomic_store(&sock->outerhandle->sock->processing, false);
if (sock->timer_initialized) {
uv_timer_start(&sock->timer, dnstcp_readtimeout,
sock->read_timeout, 0);
result = processbuffer(sock, &handle);
if (result == ISC_R_SUCCESS) {
- atomic_store(&sock->outer->processing, true);
+ atomic_store(&sock->outerhandle->sock->processing,
+ true);
if (sock->timer_initialized) {
uv_timer_stop(&sock->timer);
}
isc_nmhandle_unref(handle);
- } else if (sock->outer != NULL) {
- isc_nm_resumeread(sock->outer);
+ } else if (sock->outerhandle != NULL) {
+ isc_nm_resumeread(sock->outerhandle->sock);
}
return;
/*
* Nothing in the buffer; resume reading.
*/
- if (sock->outer != NULL) {
- isc_nm_resumeread(sock->outer);
+ if (sock->outerhandle != NULL) {
+ isc_nm_resumeread(sock->outerhandle->sock);
}
break;
if (sock->timer_initialized) {
uv_timer_stop(&sock->timer);
}
- atomic_store(&sock->outer->processing, true);
+ atomic_store(&sock->outerhandle->sock->processing, true);
isc_nmhandle_unref(dnshandle);
} while (atomic_load(&sock->ah) < TCPDNS_CLIENTS_PER_CONN);
}
tcpdnssend_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
tcpsend_t *ts = (tcpsend_t *)cbarg;
- UNUSED(handle);
-
ts->cb(ts->orighandle, result, ts->cbarg);
isc_mem_put(ts->mctx, ts->region.base, ts->region.length);
isc_nmhandle_unref(ts->orighandle);
isc_mem_putanddetach(&ts->mctx, ts, sizeof(*ts));
+
+ isc_nmhandle_unref(handle);
}
/*
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tcpdnssocket);
- if (sock->outer == NULL) {
+ if (sock->outerhandle == NULL) {
/* The socket is closed */
return (ISC_R_NOTCONNECTED);
}
*t = (tcpsend_t){
.cb = cb,
.cbarg = cbarg,
- .handle = handle->sock->outer->tcphandle,
+ .handle = handle->sock->outerhandle,
};
isc_mem_attach(sock->mgr->mctx, &t->mctx);
* At this point we're certain that there are no external
* references, we can close everything.
*/
- if (sock->outer != NULL) {
- sock->outer->rcb.recv = NULL;
- isc__nmsocket_detach(&sock->outer);
+ if (sock->outerhandle != NULL) {
+ sock->outerhandle->sock->rcb.recv = NULL;
+ isc_nmhandle_unref(sock->outerhandle);
+ sock->outerhandle = NULL;
}
if (sock->listener != NULL) {
isc__nmsocket_detach(&sock->listener);
}
atomic_store(&sock->closed, true);
+ isc__nmsocket_prep_destroy(sock);
}
}