mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
change from isc_nmhandle_ref/unref to isc_nmhandle attach/detach
Attaching and detaching handle pointers will make it easier to
determine where and why reference counting errors have occurred.
A handle needs to be referenced more than once when multiple
asynchronous operations are in flight, so callers must now maintain
multiple handle pointers for each pending operation. For example,
ns_client objects now contain:
- reqhandle: held while waiting for a request callback (query,
notify, update)
- sendhandle: held while waiting for a send callback
- fetchhandle: held while waiting for a recursive fetch to
complete
- updatehandle: held while waiting for an update-forwarding
task to complete
control channel connection objects now contain:
- readhandle: held while waiting for a read callback
- sendhandle: held while waiting for a send callback
- cmdhandle: held while an rndc command is running
httpd connections contain:
- readhandle: held while waiting for a read callback
- sendhandle: held while waiting for a send callback
This commit is contained in:
parent
cfa4ea64bc
commit
57b4dde974
26 changed files with 416 additions and 309 deletions
|
|
@ -67,9 +67,11 @@ struct controlkey {
|
|||
};
|
||||
|
||||
struct controlconnection {
|
||||
isc_nmhandle_t *handle;
|
||||
isc_nmhandle_t *readhandle;
|
||||
isc_nmhandle_t *sendhandle;
|
||||
isc_nmhandle_t *cmdhandle;
|
||||
isccc_ccmsg_t ccmsg;
|
||||
bool ccmsg_valid;
|
||||
bool reading;
|
||||
bool sending;
|
||||
controllistener_t *listener;
|
||||
isccc_sexpr_t *ctrl;
|
||||
|
|
@ -221,10 +223,8 @@ control_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
|
||||
conn->sending = false;
|
||||
|
||||
isc_nmhandle_unref(handle);
|
||||
|
||||
if (result == ISC_R_CANCELED) {
|
||||
return;
|
||||
if (listener->controls->shuttingdown || result == ISC_R_CANCELED) {
|
||||
goto cleanup_sendhandle;
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
char socktext[ISC_SOCKADDR_FORMATSIZE];
|
||||
|
||||
|
|
@ -233,16 +233,31 @@ control_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
|
||||
"error sending command response to %s: %s",
|
||||
socktext, isc_result_totext(result));
|
||||
return;
|
||||
goto cleanup_sendhandle;
|
||||
}
|
||||
|
||||
isc_nmhandle_attach(handle, &conn->readhandle);
|
||||
conn->reading = true;
|
||||
|
||||
isc_nmhandle_detach(&conn->sendhandle);
|
||||
|
||||
result = isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage,
|
||||
conn);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_detach(&conn->readhandle);
|
||||
conn->reading = false;
|
||||
|
||||
maybe_free_listener(listener);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
listener->listening = true;
|
||||
|
||||
return;
|
||||
|
||||
cleanup_sendhandle:
|
||||
isc_nmhandle_detach(&conn->sendhandle);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -257,6 +272,25 @@ log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
|
|||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
static void
|
||||
conn_cleanup(controlconnection_t *conn) {
|
||||
controllistener_t *listener = conn->listener;
|
||||
|
||||
if (conn->response != NULL) {
|
||||
isccc_sexpr_free(&conn->response);
|
||||
}
|
||||
if (conn->request != NULL) {
|
||||
isccc_sexpr_free(&conn->request);
|
||||
}
|
||||
if (conn->secret.rstart != NULL) {
|
||||
isc_mem_put(listener->mctx, conn->secret.rstart,
|
||||
REGION_SIZE(conn->secret));
|
||||
}
|
||||
if (conn->text != NULL) {
|
||||
isc_buffer_free(&conn->text);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
control_respond(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
controlconnection_t *conn = (controlconnection_t *)arg;
|
||||
|
|
@ -324,29 +358,21 @@ control_respond(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
r.base = conn->buffer->base;
|
||||
r.length = conn->buffer->used;
|
||||
|
||||
isc_nmhandle_ref(handle);
|
||||
isc_nmhandle_attach(handle, &conn->sendhandle);
|
||||
conn->sending = true;
|
||||
result = isc_nm_send(handle, &r, control_senddone, conn);
|
||||
conn_cleanup(conn);
|
||||
|
||||
isc_nmhandle_detach(&conn->cmdhandle);
|
||||
|
||||
result = isc_nm_send(conn->sendhandle, &r, control_senddone, conn);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&conn->sendhandle);
|
||||
conn->sending = false;
|
||||
}
|
||||
|
||||
return;
|
||||
cleanup:
|
||||
if (conn->response != NULL) {
|
||||
isccc_sexpr_free(&conn->response);
|
||||
}
|
||||
if (conn->request != NULL) {
|
||||
isccc_sexpr_free(&conn->request);
|
||||
}
|
||||
|
||||
if (conn->secret.rstart != NULL) {
|
||||
isc_mem_put(listener->mctx, conn->secret.rstart,
|
||||
REGION_SIZE(conn->secret));
|
||||
}
|
||||
if (conn->text != NULL) {
|
||||
isc_buffer_free(&conn->text);
|
||||
}
|
||||
conn_cleanup(conn);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -356,17 +382,17 @@ control_command(isc_task_t *task, isc_event_t *event) {
|
|||
|
||||
UNUSED(task);
|
||||
|
||||
/*
|
||||
* An extra ref and two unrefs are needed here to
|
||||
* ensure the handle isn't cleaned up if we're running
|
||||
* an "rndc stop" command.
|
||||
*/
|
||||
isc_nmhandle_ref(conn->handle);
|
||||
if (listener->controls->shuttingdown) {
|
||||
isc_nmhandle_detach(&conn->cmdhandle);
|
||||
conn_cleanup(conn);
|
||||
goto done;
|
||||
}
|
||||
|
||||
conn->result = named_control_docommand(conn->request,
|
||||
listener->readonly, &conn->text);
|
||||
control_respond(conn->handle, conn->result, conn);
|
||||
isc_nmhandle_unref(conn->handle);
|
||||
isc_nmhandle_unref(conn->handle);
|
||||
control_respond(conn->cmdhandle, conn->result, conn);
|
||||
|
||||
done:
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
|
|
@ -380,26 +406,21 @@ control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
isccc_time_t exp;
|
||||
uint32_t nonce;
|
||||
|
||||
conn->ccmsg_valid = false;
|
||||
conn->reading = false;
|
||||
|
||||
/* Is the server shutting down? */
|
||||
if (listener->controls->shuttingdown) {
|
||||
return;
|
||||
goto cleanup_readhandle;
|
||||
}
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (result == ISC_R_CANCELED) {
|
||||
/*
|
||||
* Don't bother with any more scheduled command events.
|
||||
*/
|
||||
listener->controls->shuttingdown = true;
|
||||
isc_task_purge(named_g_server->task, NULL,
|
||||
NAMED_EVENT_COMMAND, NULL);
|
||||
} else if (result != ISC_R_EOF) {
|
||||
log_invalid(&conn->ccmsg, result);
|
||||
}
|
||||
|
||||
return;
|
||||
goto cleanup_readhandle;
|
||||
}
|
||||
|
||||
for (key = ISC_LIST_HEAD(listener->keys); key != NULL;
|
||||
|
|
@ -424,7 +445,7 @@ control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
REGION_SIZE(conn->secret));
|
||||
if (result != ISCCC_R_BADAUTH) {
|
||||
log_invalid(&conn->ccmsg, result);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -496,7 +517,8 @@ control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
|
||||
isc_buffer_allocate(listener->mctx, &conn->text, 2 * 2048);
|
||||
|
||||
conn->ccmsg_valid = true;
|
||||
isc_nmhandle_attach(handle, &conn->cmdhandle);
|
||||
isc_nmhandle_detach(&conn->readhandle);
|
||||
|
||||
if (conn->nonce == 0) {
|
||||
/*
|
||||
|
|
@ -513,26 +535,23 @@ control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
/*
|
||||
* Trigger the command.
|
||||
*/
|
||||
isc_nmhandle_ref(handle);
|
||||
|
||||
event = isc_event_allocate(listener->mctx, conn, NAMED_EVENT_COMMAND,
|
||||
control_command, conn, sizeof(isc_event_t));
|
||||
isc_task_send(named_g_server->task, &event);
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
if (conn->response != NULL) {
|
||||
isccc_sexpr_free(&conn->response);
|
||||
}
|
||||
if (conn->request != NULL) {
|
||||
isccc_sexpr_free(&conn->request);
|
||||
}
|
||||
conn_cleanup(conn);
|
||||
|
||||
if (conn->secret.rstart != NULL) {
|
||||
isc_mem_put(listener->mctx, conn->secret.rstart,
|
||||
REGION_SIZE(conn->secret));
|
||||
}
|
||||
if (conn->text != NULL) {
|
||||
isc_buffer_free(&conn->text);
|
||||
cleanup_readhandle:
|
||||
/*
|
||||
* readhandle could be NULL if we're shutting down,
|
||||
* but if not we need to detach it.
|
||||
*/
|
||||
if (conn->readhandle != NULL) {
|
||||
isc_nmhandle_detach(&conn->readhandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -545,7 +564,7 @@ conn_reset(void *arg) {
|
|||
isc_buffer_free(&conn->buffer);
|
||||
}
|
||||
|
||||
if (conn->ccmsg_valid) {
|
||||
if (conn->reading) {
|
||||
isccc_ccmsg_cancelread(&conn->ccmsg);
|
||||
return;
|
||||
}
|
||||
|
|
@ -583,18 +602,11 @@ newconnection(controllistener_t *listener, isc_nmhandle_t *handle) {
|
|||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3),
|
||||
"allocate new control connection");
|
||||
*conn = (controlconnection_t){ .handle = NULL };
|
||||
}
|
||||
|
||||
if (conn->handle == NULL) {
|
||||
isc_nmhandle_setdata(handle, conn, conn_reset, conn_put);
|
||||
} else {
|
||||
INSIST(conn->handle == handle);
|
||||
}
|
||||
|
||||
*conn = (controlconnection_t){ .handle = handle,
|
||||
.listener = listener,
|
||||
.ccmsg_valid = true,
|
||||
*conn = (controlconnection_t){ .listener = listener,
|
||||
.reading = false,
|
||||
.alg = DST_ALG_UNKNOWN };
|
||||
|
||||
isccc_ccmsg_init(listener->mctx, handle, &conn->ccmsg);
|
||||
|
|
@ -604,9 +616,14 @@ newconnection(controllistener_t *listener, isc_nmhandle_t *handle) {
|
|||
|
||||
ISC_LINK_INIT(conn, link);
|
||||
|
||||
isc_nmhandle_attach(handle, &conn->readhandle);
|
||||
conn->reading = true;
|
||||
|
||||
result = isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage,
|
||||
conn);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_detach(&conn->readhandle);
|
||||
conn->reading = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14866,14 +14866,15 @@ named_server_zonestatus(named_server_t *server, isc_lex_t *lex,
|
|||
|
||||
/* Serial number */
|
||||
result = dns_zone_getserial(mayberaw, &serial);
|
||||
/* XXXWPK TODO this is to mirror old behavior with dns_zone_getserial */
|
||||
|
||||
/* This is to mirror old behavior with dns_zone_getserial */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
serial = 0;
|
||||
}
|
||||
|
||||
snprintf(serbuf, sizeof(serbuf), "%u", serial);
|
||||
if (hasraw) {
|
||||
result = dns_zone_getserial(zone, &signed_serial);
|
||||
/* XXXWPK TODO ut supra */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
serial = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/net.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/refcount.h>
|
||||
|
|
@ -89,6 +90,8 @@ static uint32_t serial;
|
|||
static bool quiet = false;
|
||||
static bool showresult = false;
|
||||
static bool shuttingdown = false;
|
||||
static isc_nmhandle_t *recvdone_handle = NULL;
|
||||
static isc_nmhandle_t *recvnonce_handle = NULL;
|
||||
|
||||
static void
|
||||
rndc_startconnect(isc_sockaddr_t *addr);
|
||||
|
|
@ -288,19 +291,21 @@ get_addresses(const char *host, in_port_t port) {
|
|||
|
||||
static void
|
||||
rndc_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
UNUSED(arg);
|
||||
isc_nmhandle_t *sendhandle = (isc_nmhandle_t *)arg;
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("send failed: %s", isc_result_totext(result));
|
||||
}
|
||||
|
||||
REQUIRE(sendhandle == handle);
|
||||
isc_nmhandle_detach(&sendhandle);
|
||||
|
||||
if (atomic_fetch_sub_release(&sends, 1) == 1 &&
|
||||
atomic_load_acquire(&recvs) == 0)
|
||||
{
|
||||
shuttingdown = true;
|
||||
isc_task_shutdown(rndc_task);
|
||||
isc_app_shutdown();
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -315,10 +320,12 @@ rndc_recvdone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
|
||||
REQUIRE(ccmsg != NULL);
|
||||
|
||||
atomic_fetch_sub_release(&recvs, 1);
|
||||
|
||||
if (shuttingdown && (result == ISC_R_EOF || result == ISC_R_CANCELED)) {
|
||||
isc_nmhandle_unref(handle);
|
||||
atomic_fetch_sub_release(&recvs, 1);
|
||||
if (handle != NULL) {
|
||||
REQUIRE(recvdone_handle == handle);
|
||||
isc_nmhandle_detach(&recvdone_handle);
|
||||
}
|
||||
return;
|
||||
} else if (result == ISC_R_EOF) {
|
||||
fatal("connection to remote host closed.\n"
|
||||
|
|
@ -376,10 +383,13 @@ rndc_recvdone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
|
||||
isccc_sexpr_free(&response);
|
||||
|
||||
REQUIRE(recvdone_handle == handle);
|
||||
isc_nmhandle_detach(&recvdone_handle);
|
||||
|
||||
if (atomic_load_acquire(&sends) == 0 &&
|
||||
atomic_load_acquire(&recvs) == 0) {
|
||||
atomic_fetch_sub_release(&recvs, 1) == 1)
|
||||
{
|
||||
shuttingdown = true;
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_task_shutdown(rndc_task);
|
||||
isc_app_shutdown();
|
||||
}
|
||||
|
|
@ -400,10 +410,12 @@ rndc_recvnonce(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
|
||||
REQUIRE(ccmsg != NULL);
|
||||
|
||||
atomic_fetch_sub_release(&recvs, 1);
|
||||
|
||||
if (shuttingdown && result == ISC_R_EOF) {
|
||||
isc_nmhandle_unref(handle);
|
||||
atomic_fetch_sub_release(&recvs, 1);
|
||||
if (handle != NULL) {
|
||||
REQUIRE(recvnonce_handle == handle);
|
||||
isc_nmhandle_detach(&recvnonce_handle);
|
||||
}
|
||||
return;
|
||||
} else if (result == ISC_R_EOF) {
|
||||
fatal("connection to remote host closed.\n"
|
||||
|
|
@ -467,12 +479,19 @@ rndc_recvnonce(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
r.base = databuf->base;
|
||||
r.length = databuf->used;
|
||||
|
||||
isc_nmhandle_attach(handle, &recvdone_handle);
|
||||
atomic_fetch_add_relaxed(&recvs, 1);
|
||||
DO("schedule recv",
|
||||
isccc_ccmsg_readmessage(ccmsg, rndc_recvdone, ccmsg));
|
||||
atomic_fetch_add_relaxed(&recvs, 1);
|
||||
|
||||
DO("send message", isc_nm_send(handle, &r, rndc_senddone, NULL));
|
||||
isc_nmhandle_t *sendhandle = NULL;
|
||||
isc_nmhandle_attach(handle, &sendhandle);
|
||||
atomic_fetch_add_relaxed(&sends, 1);
|
||||
DO("send message", isc_nm_send(handle, &r, rndc_senddone, sendhandle));
|
||||
|
||||
REQUIRE(recvnonce_handle == handle);
|
||||
isc_nmhandle_detach(&recvnonce_handle);
|
||||
atomic_fetch_sub_release(&recvs, 1);
|
||||
|
||||
isccc_sexpr_free(&response);
|
||||
isccc_sexpr_free(&request);
|
||||
|
|
@ -488,12 +507,12 @@ rndc_connected(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
isccc_time_t now;
|
||||
isc_region_t r;
|
||||
isc_buffer_t b;
|
||||
isc_nmhandle_t *connhandle = NULL;
|
||||
|
||||
REQUIRE(ccmsg != NULL);
|
||||
|
||||
atomic_fetch_sub_release(&connects, 1);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
atomic_fetch_sub_release(&connects, 1);
|
||||
isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
|
||||
sizeof(socktext));
|
||||
if (++currentaddr < nserveraddrs) {
|
||||
|
|
@ -507,6 +526,8 @@ rndc_connected(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
isc_nmhandle_attach(handle, &connhandle);
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
|
||||
now, now + 60, &request));
|
||||
|
|
@ -534,14 +555,18 @@ rndc_connected(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
isccc_ccmsg_init(rndc_mctx, handle, ccmsg);
|
||||
isccc_ccmsg_setmaxsize(ccmsg, 1024 * 1024);
|
||||
|
||||
isc_nmhandle_ref(handle);
|
||||
|
||||
isc_nmhandle_attach(handle, &recvnonce_handle);
|
||||
atomic_fetch_add_relaxed(&recvs, 1);
|
||||
DO("schedule recv",
|
||||
isccc_ccmsg_readmessage(ccmsg, rndc_recvnonce, ccmsg));
|
||||
atomic_fetch_add_relaxed(&recvs, 1);
|
||||
|
||||
DO("send message", isc_nm_send(handle, &r, rndc_senddone, NULL));
|
||||
isc_nmhandle_t *sendhandle = NULL;
|
||||
isc_nmhandle_attach(handle, &sendhandle);
|
||||
atomic_fetch_add_relaxed(&sends, 1);
|
||||
DO("send message", isc_nm_send(handle, &r, rndc_senddone, sendhandle));
|
||||
|
||||
isc_nmhandle_detach(&connhandle);
|
||||
atomic_fetch_sub_release(&connects, 1);
|
||||
|
||||
isccc_sexpr_free(&request);
|
||||
}
|
||||
|
|
@ -573,11 +598,11 @@ rndc_startconnect(isc_sockaddr_t *addr) {
|
|||
ISC_UNREACHABLE();
|
||||
}
|
||||
|
||||
atomic_fetch_add_relaxed(&connects, 1);
|
||||
DO("create connection",
|
||||
isc_nm_tcpconnect(netmgr, (isc_nmiface_t *)local,
|
||||
(isc_nmiface_t *)addr, rndc_connected, &rndc_ccmsg,
|
||||
0));
|
||||
atomic_fetch_add_relaxed(&connects, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1068,16 +1093,18 @@ main(int argc, char **argv) {
|
|||
isc_task_detach(&rndc_task);
|
||||
isc_taskmgr_destroy(&taskmgr);
|
||||
|
||||
isc_nm_destroy(&netmgr);
|
||||
isc_nm_closedown(netmgr);
|
||||
|
||||
/*
|
||||
* Note: when TCP connections are shut down, there will be a final
|
||||
* call to the isccc callback routine with &rndc_ccmsg as its
|
||||
* argument. We therefore need to delay invalidating it until
|
||||
* after the netmgr is destroyed.
|
||||
* after the netmgr is closed down.
|
||||
*/
|
||||
isccc_ccmsg_invalidate(&rndc_ccmsg);
|
||||
|
||||
isc_nm_destroy(&netmgr);
|
||||
|
||||
isc_log_destroy(&log);
|
||||
isc_log_setcontext(NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ options {
|
|||
listen-on { 10.53.0.4; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation yes;
|
||||
};
|
||||
|
||||
view normal {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,10 @@ struct isc_httpd {
|
|||
isc_httpdmgr_t *mgr; /*%< our parent */
|
||||
ISC_LINK(isc_httpd_t) link;
|
||||
|
||||
isc_nmhandle_t *handle;
|
||||
isc_nmhandle_t *handle; /* Permanent pointer to handle */
|
||||
isc_nmhandle_t *readhandle; /* Waiting for a read callback */
|
||||
isc_nmhandle_t *sendhandle; /* Waiting for a send callback */
|
||||
|
||||
state_t state;
|
||||
int flags;
|
||||
|
||||
|
|
@ -636,6 +639,7 @@ new_httpd(isc_httpdmgr_t *httpdmgr, isc_nmhandle_t *handle) {
|
|||
|
||||
if (httpd->handle == NULL) {
|
||||
isc_nmhandle_setdata(handle, httpd, httpd_reset, httpd_put);
|
||||
httpd->handle = handle;
|
||||
} else {
|
||||
INSIST(httpd->handle == handle);
|
||||
}
|
||||
|
|
@ -663,10 +667,10 @@ new_httpd(isc_httpdmgr_t *httpdmgr, isc_nmhandle_t *handle) {
|
|||
ISC_LIST_APPEND(httpdmgr->running, httpd, link);
|
||||
UNLOCK(&httpdmgr->lock);
|
||||
|
||||
isc_nmhandle_ref(handle);
|
||||
isc_nmhandle_attach(handle, &httpd->readhandle);
|
||||
result = isc_nm_read(handle, httpd_request, httpdmgr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&httpd->readhandle);
|
||||
}
|
||||
|
||||
return (result);
|
||||
|
|
@ -849,7 +853,7 @@ httpd_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
REQUIRE(httpd->state == RECV);
|
||||
|
||||
if (eresult != ISC_R_SUCCESS) {
|
||||
goto done;
|
||||
goto cleanup_readhandle;
|
||||
}
|
||||
|
||||
result = process_request(httpd, region);
|
||||
|
|
@ -858,9 +862,9 @@ httpd_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
/* don't unref, continue reading */
|
||||
return;
|
||||
}
|
||||
goto done;
|
||||
goto cleanup_readhandle;
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
goto done;
|
||||
goto cleanup_readhandle;
|
||||
}
|
||||
|
||||
isc_buffer_initnull(&httpd->bodybuffer);
|
||||
|
|
@ -958,18 +962,18 @@ httpd_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
isc_nm_pauseread(handle);
|
||||
httpd->state = SEND;
|
||||
|
||||
isc_nmhandle_ref(handle);
|
||||
isc_nmhandle_attach(handle, &httpd->sendhandle);
|
||||
result = isc_nm_send(handle, &r, httpd_senddone, httpd);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nm_resumeread(handle);
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&httpd->sendhandle);
|
||||
|
||||
httpd->state = RECV;
|
||||
isc_nm_resumeread(handle);
|
||||
}
|
||||
|
||||
return;
|
||||
done:
|
||||
isc_nmhandle_unref(handle);
|
||||
cleanup_readhandle:
|
||||
isc_nmhandle_detach(&httpd->readhandle);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -990,7 +994,7 @@ isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp) {
|
|||
|
||||
httpd = ISC_LIST_HEAD(httpdmgr->running);
|
||||
while (httpd != NULL) {
|
||||
isc_nmhandle_unref(httpd->handle);
|
||||
isc_nm_cancelread(httpd->readhandle);
|
||||
httpd = ISC_LIST_NEXT(httpd, link);
|
||||
}
|
||||
UNLOCK(&httpdmgr->lock);
|
||||
|
|
@ -1137,9 +1141,10 @@ httpd_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
return;
|
||||
}
|
||||
|
||||
isc_nmhandle_detach(&httpd->sendhandle);
|
||||
|
||||
httpd->state = RECV;
|
||||
isc_nm_resumeread(handle);
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
|
|||
|
|
@ -110,9 +110,9 @@ isc_nmsocket_close(isc_nmsocket_t **sockp);
|
|||
*/
|
||||
|
||||
void
|
||||
isc_nmhandle_ref(isc_nmhandle_t *handle);
|
||||
isc_nmhandle_attach(isc_nmhandle_t *handle, isc_nmhandle_t **dest);
|
||||
void
|
||||
isc_nmhandle_unref(isc_nmhandle_t *handle);
|
||||
isc_nmhandle_detach(isc_nmhandle_t **handlep);
|
||||
/*%<
|
||||
* Increment/decrement the reference counter in a netmgr handle,
|
||||
* but (unlike the attach/detach functions) do not change the pointer
|
||||
|
|
|
|||
|
|
@ -746,8 +746,7 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree) {
|
|||
sock->statichandle = NULL;
|
||||
|
||||
if (sock->outerhandle != NULL) {
|
||||
isc_nmhandle_unref(sock->outerhandle);
|
||||
sock->outerhandle = NULL;
|
||||
isc_nmhandle_detach(&sock->outerhandle);
|
||||
}
|
||||
|
||||
if (sock->outer != NULL) {
|
||||
|
|
@ -1107,6 +1106,13 @@ isc__nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
|
|||
(sock->type == isc_nm_udpsocket && atomic_load(&sock->client)))
|
||||
{
|
||||
INSIST(sock->statichandle == NULL);
|
||||
|
||||
/*
|
||||
* statichandle must be assigned, not attached;
|
||||
* otherwise, if a handle was detached elsewhere
|
||||
* it could never reach 0 references, and the
|
||||
* handle and socket would never be freed.
|
||||
*/
|
||||
sock->statichandle = handle;
|
||||
}
|
||||
|
||||
|
|
@ -1114,10 +1120,12 @@ isc__nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
|
|||
}
|
||||
|
||||
void
|
||||
isc_nmhandle_ref(isc_nmhandle_t *handle) {
|
||||
isc_nmhandle_attach(isc_nmhandle_t *handle, isc_nmhandle_t **handlep) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(handlep != NULL && *handlep == NULL);
|
||||
|
||||
isc_refcount_increment(&handle->references);
|
||||
*handlep = handle;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -1173,14 +1181,20 @@ nmhandle_deactivate(isc_nmsocket_t *sock, isc_nmhandle_t *handle) {
|
|||
}
|
||||
|
||||
void
|
||||
isc_nmhandle_unref(isc_nmhandle_t *handle) {
|
||||
isc_nmhandle_detach(isc_nmhandle_t **handlep) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
isc_nmhandle_t *handle = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(handlep != NULL);
|
||||
REQUIRE(VALID_NMHANDLE(*handlep));
|
||||
|
||||
handle = *handlep;
|
||||
*handlep = NULL;
|
||||
|
||||
if (isc_refcount_decrement(&handle->references) > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We need an acquire memory barrier here */
|
||||
(void)isc_refcount_current(&handle->references);
|
||||
|
||||
|
|
@ -1215,6 +1229,7 @@ isc_nmhandle_unref(isc_nmhandle_t *handle) {
|
|||
}
|
||||
|
||||
if (handle == sock->statichandle) {
|
||||
/* statichandle is assigned, not attached. */
|
||||
sock->statichandle = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1319,7 +1334,7 @@ isc__nm_uvreq_put(isc__nm_uvreq_t **req0, isc_nmsocket_t *sock) {
|
|||
}
|
||||
|
||||
if (handle != NULL) {
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&handle);
|
||||
}
|
||||
|
||||
isc__nmsocket_detach(&sock);
|
||||
|
|
|
|||
|
|
@ -183,10 +183,10 @@ tcp_connect_cb(uv_connect_t *uvreq, int status) {
|
|||
isc__nmsocket_detach(&sock);
|
||||
|
||||
/*
|
||||
* If the connect callback wants to hold on to the handle,
|
||||
* it needs to attach to it.
|
||||
* The connect callback should have attached to the handle.
|
||||
* If it didn't, the socket will be closed now.
|
||||
*/
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&handle);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -498,10 +498,10 @@ isc__nm_async_tcpchildaccept(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||
isc__nmsocket_detach(&csock);
|
||||
|
||||
/*
|
||||
* If the accept callback wants to hold on to the handle,
|
||||
* it needs to attach to it.
|
||||
* The accept callback should have attached to the handle.
|
||||
* If it didn't, the socket will be closed now.
|
||||
*/
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&handle);
|
||||
return;
|
||||
|
||||
error:
|
||||
|
|
@ -959,8 +959,7 @@ isc__nm_tcp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
|||
uvreq = isc__nm_uvreq_get(sock->mgr, sock);
|
||||
uvreq->uvbuf.base = (char *)region->base;
|
||||
uvreq->uvbuf.len = region->length;
|
||||
uvreq->handle = handle;
|
||||
isc_nmhandle_ref(uvreq->handle);
|
||||
isc_nmhandle_attach(handle, &uvreq->handle);
|
||||
uvreq->cb.send = cb;
|
||||
uvreq->cbarg = cbarg;
|
||||
|
||||
|
|
@ -1003,7 +1002,6 @@ tcp_send_cb(uv_write_t *req, int status) {
|
|||
uvreq->cb.send(uvreq->handle, result, uvreq->cbarg);
|
||||
|
||||
sock = uvreq->handle->sock;
|
||||
isc_nmhandle_unref(uvreq->handle);
|
||||
isc__nm_uvreq_put(&uvreq, sock);
|
||||
}
|
||||
|
||||
|
|
@ -1035,8 +1033,6 @@ tcp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
|||
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
REQUIRE(sock->type == isc_nm_tcpsocket);
|
||||
|
||||
isc_nmhandle_ref(req->handle);
|
||||
r = uv_write(&req->uv_req.write, &sock->uv_handle.stream, &req->uvbuf,
|
||||
1, tcp_send_cb);
|
||||
if (r < 0) {
|
||||
|
|
@ -1143,6 +1139,7 @@ isc__nm_tcp_cancelread(isc_nmhandle_t *handle) {
|
|||
|
||||
sock = handle->sock;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
REQUIRE(sock->type == isc_nm_tcpsocket);
|
||||
|
||||
if (atomic_load(&sock->client) && sock->rcb.recv != NULL) {
|
||||
|
|
|
|||
|
|
@ -98,8 +98,7 @@ dnstcp_readtimeout(uv_timer_t *timer) {
|
|||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
/* Close the TCP connection; its closure should fire ours. */
|
||||
isc_nmhandle_unref(sock->outerhandle);
|
||||
sock->outerhandle = NULL;
|
||||
isc_nmhandle_detach(&sock->outerhandle);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -109,6 +108,7 @@ static isc_result_t
|
|||
dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
isc_nmsocket_t *dnslistensock = (isc_nmsocket_t *)cbarg;
|
||||
isc_nmsocket_t *dnssock = NULL;
|
||||
isc_nmhandle_t *readhandle = NULL;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(dnslistensock));
|
||||
REQUIRE(dnslistensock->type == isc_nm_tcpdnslistener);
|
||||
|
|
@ -135,8 +135,7 @@ dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
|
||||
isc__nmsocket_attach(dnssock, &dnssock->self);
|
||||
|
||||
dnssock->outerhandle = handle;
|
||||
isc_nmhandle_ref(dnssock->outerhandle);
|
||||
isc_nmhandle_attach(handle, &dnssock->outerhandle);
|
||||
|
||||
dnssock->peer = handle->sock->peer;
|
||||
dnssock->read_timeout = handle->sock->mgr->init;
|
||||
|
|
@ -150,10 +149,15 @@ dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
uv_timer_start(&dnssock->timer, dnstcp_readtimeout,
|
||||
dnssock->read_timeout, 0);
|
||||
|
||||
isc_nmhandle_ref(handle);
|
||||
result = isc_nm_read(handle, dnslisten_readcb, dnssock);
|
||||
/*
|
||||
* Add a reference to handle to keep it from being freed by
|
||||
* the caller. It will be detached in dnslisted_readcb() when
|
||||
* the connection is closed or there is no more data to be read.
|
||||
*/
|
||||
isc_nmhandle_attach(handle, &readhandle);
|
||||
result = isc_nm_read(readhandle, dnslisten_readcb, dnssock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&readhandle);
|
||||
}
|
||||
isc__nmsocket_detach(&dnssock);
|
||||
|
||||
|
|
@ -190,17 +194,17 @@ processbuffer(isc_nmsocket_t *dnssock, isc_nmhandle_t **handlep) {
|
|||
*/
|
||||
len = dnslen(dnssock->buf);
|
||||
if (len <= dnssock->buf_len - 2) {
|
||||
isc_nmhandle_t *dnshandle;
|
||||
isc_nmhandle_t *dnshandle = NULL;
|
||||
isc_nmsocket_t *listener = NULL;
|
||||
|
||||
if (atomic_load(&dnssock->client) &&
|
||||
dnssock->statichandle != NULL) {
|
||||
dnshandle = dnssock->statichandle;
|
||||
isc_nmhandle_ref(dnshandle);
|
||||
isc_nmhandle_attach(dnssock->statichandle, &dnshandle);
|
||||
} else {
|
||||
dnshandle = isc__nmhandle_get(dnssock, NULL, NULL);
|
||||
}
|
||||
|
||||
isc_nmsocket_t *listener = dnssock->listener;
|
||||
|
||||
listener = dnssock->listener;
|
||||
if (listener != NULL && listener->rcb.recv != NULL) {
|
||||
listener->rcb.recv(
|
||||
dnshandle, ISC_R_SUCCESS,
|
||||
|
|
@ -238,8 +242,8 @@ processbuffer(isc_nmsocket_t *dnssock, isc_nmhandle_t **handlep) {
|
|||
}
|
||||
|
||||
/*
|
||||
* We've got a read on our underlying socket, need to check if we have
|
||||
* a complete DNS packet and, if so - call the callback
|
||||
* We've got a read on our underlying socket. Check whether
|
||||
* we have a complete DNS packet and, if so, call the callback.
|
||||
*/
|
||||
static void
|
||||
dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
|
|
@ -254,18 +258,15 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
|
||||
if (region == NULL || eresult != ISC_R_SUCCESS) {
|
||||
/* Connection closed */
|
||||
if (eresult != ISC_R_CANCELED) {
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
dnssock->result = eresult;
|
||||
if (dnssock->self != NULL) {
|
||||
isc__nmsocket_detach(&dnssock->self);
|
||||
}
|
||||
isc__nmsocket_clearcb(dnssock);
|
||||
if (dnssock->outerhandle != NULL) {
|
||||
isc_nmhandle_unref(dnssock->outerhandle);
|
||||
dnssock->outerhandle = NULL;
|
||||
isc_nmhandle_detach(&dnssock->outerhandle);
|
||||
}
|
||||
isc_nmhandle_detach(&handle);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -305,11 +306,11 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
if (atomic_load(&dnssock->sequential) ||
|
||||
dnssock->rcb.recv == NULL) {
|
||||
/*
|
||||
* Two reasons we might want to pause here:
|
||||
* - If we're in sequential mode and we've received
|
||||
* There are two reasons we might want to pause here:
|
||||
* - We're in sequential mode and we've received
|
||||
* a whole packet, so we're done until it's been
|
||||
* processed;
|
||||
* - If we no longer have a read callback.
|
||||
* processed; or
|
||||
* - We no longer have a read callback.
|
||||
*/
|
||||
isc_nm_pauseread(dnssock->outerhandle);
|
||||
done = true;
|
||||
|
|
@ -328,7 +329,7 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
}
|
||||
}
|
||||
|
||||
isc_nmhandle_unref(dnshandle);
|
||||
isc_nmhandle_detach(&dnshandle);
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
|
|
@ -460,12 +461,11 @@ resume_processing(void *arg) {
|
|||
if (sock->timer_initialized) {
|
||||
uv_timer_stop(&sock->timer);
|
||||
}
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&handle);
|
||||
} else if (sock->outerhandle != NULL) {
|
||||
result = isc_nm_resumeread(sock->outerhandle);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_unref(sock->outerhandle);
|
||||
sock->outerhandle = NULL;
|
||||
isc_nmhandle_detach(&sock->outerhandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -495,7 +495,7 @@ resume_processing(void *arg) {
|
|||
uv_timer_stop(&sock->timer);
|
||||
}
|
||||
atomic_store(&sock->outerhandle->sock->processing, true);
|
||||
isc_nmhandle_unref(dnshandle);
|
||||
isc_nmhandle_detach(&dnshandle);
|
||||
} while (atomic_load(&sock->ah) < TCPDNS_CLIENTS_PER_CONN);
|
||||
}
|
||||
|
||||
|
|
@ -508,6 +508,7 @@ tcpdnssend_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
req->cb.send(req->handle, result, req->cbarg);
|
||||
isc_mem_put(req->sock->mgr->mctx, req->uvbuf.base, req->uvbuf.len);
|
||||
isc__nm_uvreq_put(&req, req->handle->sock);
|
||||
isc_nmhandle_detach(&handle);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -522,11 +523,16 @@ isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||
|
||||
result = ISC_R_NOTCONNECTED;
|
||||
if (atomic_load(&sock->active) && sock->outerhandle != NULL) {
|
||||
isc_nmhandle_t *sendhandle = NULL;
|
||||
isc_region_t r;
|
||||
|
||||
r.base = (unsigned char *)req->uvbuf.base;
|
||||
r.length = req->uvbuf.len;
|
||||
result = isc_nm_send(sock->outerhandle, &r, tcpdnssend_cb, req);
|
||||
isc_nmhandle_attach(sock->outerhandle, &sendhandle);
|
||||
result = isc_nm_send(sendhandle, &r, tcpdnssend_cb, req);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_detach(&sendhandle);
|
||||
}
|
||||
}
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -552,8 +558,7 @@ isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region,
|
|||
REQUIRE(sock->type == isc_nm_tcpdnssocket);
|
||||
|
||||
uvreq = isc__nm_uvreq_get(sock->mgr, sock);
|
||||
uvreq->handle = handle;
|
||||
isc_nmhandle_ref(uvreq->handle);
|
||||
isc_nmhandle_attach(handle, &uvreq->handle);
|
||||
uvreq->cb.send = cb;
|
||||
uvreq->cbarg = cbarg;
|
||||
|
||||
|
|
@ -563,13 +568,20 @@ isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region,
|
|||
memmove(uvreq->uvbuf.base + 2, region->base, region->length);
|
||||
|
||||
if (sock->tid == isc_nm_tid()) {
|
||||
isc_result_t result;
|
||||
isc_nmhandle_t *sendhandle = NULL;
|
||||
isc_region_t r;
|
||||
|
||||
r.base = (unsigned char *)uvreq->uvbuf.base;
|
||||
r.length = uvreq->uvbuf.len;
|
||||
|
||||
return (isc_nm_send(sock->outerhandle, &r, tcpdnssend_cb,
|
||||
uvreq));
|
||||
isc_nmhandle_attach(sock->outerhandle, &sendhandle);
|
||||
result = isc_nm_send(sock->outerhandle, &r, tcpdnssend_cb,
|
||||
uvreq);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_detach(&sendhandle);
|
||||
}
|
||||
return (result);
|
||||
} else {
|
||||
isc__netievent_tcpdnssend_t *ievent = NULL;
|
||||
|
||||
|
|
@ -609,8 +621,7 @@ tcpdns_close_direct(isc_nmsocket_t *sock) {
|
|||
*/
|
||||
if (sock->outerhandle != NULL) {
|
||||
isc__nmsocket_clearcb(sock->outerhandle->sock);
|
||||
isc_nmhandle_unref(sock->outerhandle);
|
||||
sock->outerhandle = NULL;
|
||||
isc_nmhandle_detach(&sock->outerhandle);
|
||||
}
|
||||
if (sock->listener != NULL) {
|
||||
isc__nmsocket_detach(&sock->listener);
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ udp_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
|
|||
}
|
||||
|
||||
/*
|
||||
* handle 'udplisten' async call - start listening on a socket.
|
||||
* Asynchronous 'udplisten' call handler: start listening on a UDP socket.
|
||||
*/
|
||||
void
|
||||
isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
|
|
@ -311,7 +311,7 @@ isc__nm_udp_stoplistening(isc_nmsocket_t *sock) {
|
|||
}
|
||||
|
||||
/*
|
||||
* handle 'udpstop' async call - stop listening on a socket.
|
||||
* Asynchronous 'udpstop' call handler: stop listening on a UDP socket.
|
||||
*/
|
||||
void
|
||||
isc__nm_async_udpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
|
|
@ -375,9 +375,9 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
|||
#endif
|
||||
|
||||
/*
|
||||
* Three reasons to return now without processing:
|
||||
* - If addr == NULL that's the end of stream - we can
|
||||
* free the buffer and bail.
|
||||
* Three possible reasons to return now without processing:
|
||||
* - If addr == NULL, in which case it's the end of stream;
|
||||
* we can free the buffer and bail.
|
||||
* - If we're simulating a firewall blocking UDP packets
|
||||
* bigger than 'maxudp' bytes for testing purposes.
|
||||
* - If the socket is no longer active.
|
||||
|
|
@ -395,11 +395,7 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
|||
|
||||
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
if (!atomic_load(&sock->connected)) {
|
||||
nmhandle = isc__nmhandle_get(sock, &sockaddr, NULL);
|
||||
} else {
|
||||
nmhandle = sock->statichandle;
|
||||
}
|
||||
nmhandle = isc__nmhandle_get(sock, &sockaddr, NULL);
|
||||
region.base = (unsigned char *)buf->base;
|
||||
region.length = nrecv;
|
||||
|
||||
|
|
@ -418,13 +414,13 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
|
|||
* If the recv callback wants to hold on to the handle,
|
||||
* it needs to attach to it.
|
||||
*/
|
||||
isc_nmhandle_unref(nmhandle);
|
||||
isc_nmhandle_detach(&nmhandle);
|
||||
}
|
||||
|
||||
/*
|
||||
* isc__nm_udp_send sends buf to a peer on a socket.
|
||||
* It tries to find a proper sibling/child socket so that we won't have
|
||||
* to jump to another thread.
|
||||
* Send the data in 'region' to a peer via a UDP socket. We try to find
|
||||
* a proper sibling/child socket so that we won't have to jump to another
|
||||
* thread.
|
||||
*/
|
||||
isc_result_t
|
||||
isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
||||
|
|
@ -446,7 +442,7 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
|||
* we need to do so here.
|
||||
*/
|
||||
if (maxudp != 0 && region->length > maxudp) {
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&handle);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
@ -486,8 +482,7 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
|||
uvreq->uvbuf.base = (char *)region->base;
|
||||
uvreq->uvbuf.len = region->length;
|
||||
|
||||
uvreq->handle = handle;
|
||||
isc_nmhandle_ref(uvreq->handle);
|
||||
isc_nmhandle_attach(handle, &uvreq->handle);
|
||||
|
||||
uvreq->cb.send = cb;
|
||||
uvreq->cbarg = cbarg;
|
||||
|
|
@ -514,7 +509,7 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
|
|||
}
|
||||
|
||||
/*
|
||||
* handle 'udpsend' async event - send a packet on the socket
|
||||
* Asynchronous 'udpsend' event handler: send a packet on a UDP socket.
|
||||
*/
|
||||
void
|
||||
isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
|
|
@ -531,9 +526,6 @@ isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* udp_send_cb - callback
|
||||
*/
|
||||
static void
|
||||
udp_send_cb(uv_udp_send_t *req, int status) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
|
@ -549,7 +541,6 @@ udp_send_cb(uv_udp_send_t *req, int status) {
|
|||
}
|
||||
|
||||
uvreq->cb.send(uvreq->handle, result, uvreq->cbarg);
|
||||
isc_nmhandle_unref(uvreq->handle);
|
||||
isc__nm_uvreq_put(&uvreq, uvreq->sock);
|
||||
}
|
||||
|
||||
|
|
@ -570,7 +561,6 @@ udp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
|||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
isc_nmhandle_ref(req->handle);
|
||||
sa = atomic_load(&sock->connected) ? NULL : &peer->type.sa;
|
||||
rv = uv_udp_send(&req->uv_req.udp_send, &sock->uv_handle.udp,
|
||||
&req->uvbuf, 1, sa, udp_send_cb);
|
||||
|
|
|
|||
|
|
@ -436,15 +436,15 @@ isc_netaddr_setzone
|
|||
isc_netaddr_totext
|
||||
isc_netaddr_unspec
|
||||
isc_netscope_pton
|
||||
isc_nmhandle_attach
|
||||
isc_nmhandle_detach
|
||||
isc_nmhandle_getdata
|
||||
isc_nmhandle_getextra
|
||||
isc_nmhandle_is_stream
|
||||
isc_nmhandle_netmgr
|
||||
isc_nmhandle_localaddr
|
||||
isc_nmhandle_peeraddr
|
||||
isc_nmhandle_ref
|
||||
isc_nmhandle_setdata
|
||||
isc_nmhandle_unref
|
||||
isc_nm_cancelread
|
||||
isc_nm_closedown
|
||||
isc_nm_destroy
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ recv_data(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
done:
|
||||
isc_nm_pauseread(handle);
|
||||
ccmsg->cb(handle, ccmsg->result, ccmsg->cbarg);
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -149,18 +148,14 @@ isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_nm_cb_t cb, void *cbarg) {
|
|||
ccmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
|
||||
ccmsg->length_received = false;
|
||||
|
||||
isc_nmhandle_ref(ccmsg->handle);
|
||||
if (ccmsg->reading) {
|
||||
result = isc_nm_resumeread(ccmsg->handle);
|
||||
} else {
|
||||
result = isc_nm_read(ccmsg->handle, recv_data, ccmsg);
|
||||
ccmsg->reading = true;
|
||||
}
|
||||
if (result == ISC_R_CANCELED) {
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ccmsg->reading = false;
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
ccmsg->reading = false;
|
||||
isc_nmhandle_unref(ccmsg->handle);
|
||||
}
|
||||
|
||||
return (result);
|
||||
|
|
@ -172,6 +167,7 @@ isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
|
|||
|
||||
if (ccmsg->reading) {
|
||||
isc_nm_cancelread(ccmsg->handle);
|
||||
ccmsg->reading = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,9 @@ void
|
|||
isccc_ccmsg_init(isc_mem_t *mctx, isc_nmhandle_t *handle, isccc_ccmsg_t *ccmsg);
|
||||
/*%
|
||||
* Associate a cc message state with a given memory context and
|
||||
* netmgr handle.
|
||||
* netmgr handle. (Note that the caller must hold a reference to
|
||||
* the handle during asynchronous ccmsg operations; the ccmsg code
|
||||
* does not hold the reference itself.)
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ static void
|
|||
client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
ns_client_t *client = cbarg;
|
||||
|
||||
REQUIRE(client->handle == handle);
|
||||
REQUIRE(client->sendhandle == handle);
|
||||
|
||||
CTRACE("senddone");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -284,7 +284,7 @@ client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
"send failed: %s", isc_result_totext(result));
|
||||
}
|
||||
|
||||
isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_detach(&client->sendhandle);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -325,13 +325,18 @@ client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
|
|||
|
||||
static isc_result_t
|
||||
client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
|
||||
isc_result_t result;
|
||||
isc_region_t r;
|
||||
|
||||
REQUIRE(client->sendhandle == NULL);
|
||||
|
||||
isc_buffer_usedregion(buffer, &r);
|
||||
|
||||
INSIST(client->handle != NULL);
|
||||
|
||||
return (isc_nm_send(client->handle, &r, client_senddone, client));
|
||||
isc_nmhandle_attach(client->handle, &client->sendhandle);
|
||||
result = isc_nm_send(client->handle, &r, client_senddone, client);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_detach(&client->sendhandle);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -383,7 +388,6 @@ done:
|
|||
}
|
||||
|
||||
ns_client_drop(client, result);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -405,17 +409,13 @@ ns_client_send(ns_client_t *client) {
|
|||
isc_region_t zr;
|
||||
#endif /* HAVE_DNSTAP */
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
|
||||
/*
|
||||
* XXXWPK TODO
|
||||
* Delay the response according to the -T delay option
|
||||
*/
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
/*
|
||||
* We need to do it to make sure the client and handle
|
||||
* won't disappear from under us with client_senddone.
|
||||
*/
|
||||
|
||||
env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
|
||||
|
||||
CTRACE("send");
|
||||
|
|
@ -591,12 +591,7 @@ renderend:
|
|||
|
||||
respsize = isc_buffer_usedlength(&buffer);
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
result = client_sendpkg(client, &buffer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* We won't get a callback to clean it up */
|
||||
isc_nmhandle_unref(client->handle);
|
||||
}
|
||||
|
||||
switch (isc_sockaddr_pf(&client->peeraddr)) {
|
||||
case AF_INET:
|
||||
|
|
@ -626,12 +621,7 @@ renderend:
|
|||
|
||||
respsize = isc_buffer_usedlength(&buffer);
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
result = client_sendpkg(client, &buffer);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
/* We won't get a callback to clean it up */
|
||||
isc_nmhandle_unref(client->handle);
|
||||
}
|
||||
|
||||
switch (isc_sockaddr_pf(&client->peeraddr)) {
|
||||
case AF_INET:
|
||||
|
|
@ -1683,6 +1673,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
ns__client_put_cb);
|
||||
client->handle = handle;
|
||||
}
|
||||
|
||||
if (isc_nmhandle_is_stream(handle)) {
|
||||
client->attributes |= NS_CLIENTATTR_TCP;
|
||||
}
|
||||
|
|
@ -1697,8 +1688,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
isc_buffer_add(&tbuffer, region->length);
|
||||
buffer = &tbuffer;
|
||||
|
||||
client->peeraddr = isc_nmhandle_peeraddr(client->handle);
|
||||
|
||||
client->peeraddr = isc_nmhandle_peeraddr(handle);
|
||||
client->peeraddr_valid = true;
|
||||
|
||||
reqsize = isc_buffer_usedlength(buffer);
|
||||
|
|
@ -1968,8 +1958,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
isc_netaddr_fromsockaddr(&client->destaddr,
|
||||
&client->manager->interface->addr);
|
||||
} else {
|
||||
isc_sockaddr_t sockaddr =
|
||||
isc_nmhandle_localaddr(client->handle);
|
||||
isc_sockaddr_t sockaddr = isc_nmhandle_localaddr(handle);
|
||||
isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
|
||||
}
|
||||
|
||||
|
|
@ -2174,8 +2163,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
&client->requesttime, NULL, buffer);
|
||||
#endif /* HAVE_DNSTAP */
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
ns_query_start(client);
|
||||
ns_query_start(client, handle);
|
||||
break;
|
||||
case dns_opcode_update:
|
||||
CTRACE("update");
|
||||
|
|
@ -2185,14 +2173,12 @@ ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||
&client->requesttime, NULL, buffer);
|
||||
#endif /* HAVE_DNSTAP */
|
||||
ns_client_settimeout(client, 60);
|
||||
isc_nmhandle_ref(client->handle);
|
||||
ns_update_start(client, sigresult);
|
||||
ns_update_start(client, handle, sigresult);
|
||||
break;
|
||||
case dns_opcode_notify:
|
||||
CTRACE("notify");
|
||||
ns_client_settimeout(client, 60);
|
||||
isc_nmhandle_ref(client->handle);
|
||||
ns_notify_start(client);
|
||||
ns_notify_start(client, handle);
|
||||
break;
|
||||
case dns_opcode_iquery:
|
||||
CTRACE("iquery");
|
||||
|
|
|
|||
|
|
@ -183,14 +183,19 @@ struct ns_client {
|
|||
isc_task_t * task;
|
||||
dns_view_t * view;
|
||||
dns_dispatch_t * dispatch;
|
||||
isc_nmhandle_t * handle;
|
||||
unsigned char * tcpbuf;
|
||||
dns_message_t * message;
|
||||
unsigned char * sendbuf;
|
||||
dns_rdataset_t * opt;
|
||||
uint16_t udpsize;
|
||||
uint16_t extflags;
|
||||
int16_t ednsversion; /* -1 noedns */
|
||||
isc_nmhandle_t * handle; /* Permanent pointer to handle */
|
||||
isc_nmhandle_t * sendhandle; /* Waiting for send callback */
|
||||
isc_nmhandle_t * reqhandle; /* Waiting for request callback
|
||||
(query, update, notify) */
|
||||
isc_nmhandle_t *fetchhandle; /* Waiting for recursive fetch */
|
||||
isc_nmhandle_t *updatehandle; /* Waiting for update callback */
|
||||
unsigned char * tcpbuf;
|
||||
dns_message_t * message;
|
||||
unsigned char * sendbuf;
|
||||
dns_rdataset_t *opt;
|
||||
uint16_t udpsize;
|
||||
uint16_t extflags;
|
||||
int16_t ednsversion; /* -1 noedns */
|
||||
void (*cleanup)(ns_client_t *);
|
||||
void (*shutdown)(void *arg, isc_result_t result);
|
||||
void * shutdown_arg;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
***/
|
||||
|
||||
void
|
||||
ns_notify_start(ns_client_t *client);
|
||||
ns_notify_start(ns_client_t *client, isc_nmhandle_t *handle);
|
||||
|
||||
/*%<
|
||||
* Examines the incoming message to determine appropriate zone.
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ void
|
|||
ns_query_free(ns_client_t *client);
|
||||
|
||||
void
|
||||
ns_query_start(ns_client_t *client);
|
||||
ns_query_start(ns_client_t *client, isc_nmhandle_t *handle);
|
||||
|
||||
void
|
||||
ns_query_cancel(ns_client_t *client);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
***/
|
||||
|
||||
void
|
||||
ns_update_start(ns_client_t *client, isc_result_t sigresult);
|
||||
ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
|
||||
isc_result_t sigresult);
|
||||
|
||||
#endif /* NS_UPDATE_H */
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ respond(ns_client_t *client, isc_result_t result) {
|
|||
}
|
||||
if (msg_result != ISC_R_SUCCESS) {
|
||||
ns_client_drop(client, msg_result);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
return;
|
||||
}
|
||||
message->rcode = rcode;
|
||||
|
|
@ -65,11 +65,11 @@ respond(ns_client_t *client, isc_result_t result) {
|
|||
}
|
||||
|
||||
ns_client_send(client);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
}
|
||||
|
||||
void
|
||||
ns_notify_start(ns_client_t *client) {
|
||||
ns_notify_start(ns_client_t *client, isc_nmhandle_t *handle) {
|
||||
dns_message_t *request = client->message;
|
||||
isc_result_t result;
|
||||
dns_name_t *zonename;
|
||||
|
|
@ -79,6 +79,11 @@ ns_notify_start(ns_client_t *client) {
|
|||
char tsigbuf[DNS_NAME_FORMATSIZE * 2 + sizeof(": TSIG '' ()")];
|
||||
dns_tsigkey_t *tsigkey;
|
||||
|
||||
/*
|
||||
* Attach to the request handle
|
||||
*/
|
||||
isc_nmhandle_attach(handle, &client->reqhandle);
|
||||
|
||||
/*
|
||||
* Interpret the question section.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ query_send(ns_client_t *client) {
|
|||
|
||||
inc_stats(client, counter);
|
||||
ns_client_send(client);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -577,7 +577,7 @@ query_error(ns_client_t *client, isc_result_t result, int line) {
|
|||
log_queryerror(client, result, line, loglevel);
|
||||
|
||||
ns_client_error(client, result);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -590,7 +590,7 @@ query_next(ns_client_t *client, isc_result_t result) {
|
|||
inc_stats(client, ns_statscounter_failure);
|
||||
}
|
||||
ns_client_drop(client, result);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -2475,7 +2475,7 @@ prefetch_done(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
|
||||
free_devent(client, &event, &devent);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->fetchhandle);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2518,7 +2518,7 @@ query_prefetch(ns_client_t *client, dns_name_t *qname,
|
|||
peeraddr = NULL;
|
||||
}
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
isc_nmhandle_attach(client->handle, &client->fetchhandle);
|
||||
options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH;
|
||||
result = dns_resolver_createfetch(
|
||||
client->view->resolver, qname, rdataset->type, NULL, NULL, NULL,
|
||||
|
|
@ -2527,7 +2527,7 @@ query_prefetch(ns_client_t *client, dns_name_t *qname,
|
|||
&client->query.prefetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_putrdataset(client, &tmprdataset);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->fetchhandle);
|
||||
}
|
||||
|
||||
dns_rdataset_clearprefetch(rdataset);
|
||||
|
|
@ -2732,7 +2732,7 @@ query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) {
|
|||
}
|
||||
|
||||
options = client->query.fetchoptions;
|
||||
isc_nmhandle_ref(client->handle);
|
||||
isc_nmhandle_attach(client->handle, &client->fetchhandle);
|
||||
result = dns_resolver_createfetch(
|
||||
client->view->resolver, qname, type, NULL, NULL, NULL, peeraddr,
|
||||
client->message->id, options, 0, NULL, client->task,
|
||||
|
|
@ -2740,7 +2740,7 @@ query_rpzfetch(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t type) {
|
|||
&client->query.prefetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_putrdataset(client, &tmprdataset);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->fetchhandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5703,6 +5703,8 @@ fetch_callback(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
UNLOCK(&client->manager->reclock);
|
||||
|
||||
isc_nmhandle_detach(&client->fetchhandle);
|
||||
|
||||
client->query.attributes &= ~NS_QUERYATTR_RECURSING;
|
||||
client->state = NS_CLIENTSTATE_WORKING;
|
||||
|
||||
|
|
@ -5748,7 +5750,6 @@ fetch_callback(isc_task_t *task, isc_event_t *event) {
|
|||
}
|
||||
|
||||
dns_resolver_destroyfetch(&fetch);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -5940,14 +5941,14 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
|
|||
peeraddr = &client->peeraddr;
|
||||
}
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
isc_nmhandle_attach(client->handle, &client->fetchhandle);
|
||||
result = dns_resolver_createfetch(
|
||||
client->view->resolver, qname, qtype, qdomain, nameservers,
|
||||
NULL, peeraddr, client->message->id, client->query.fetchoptions,
|
||||
0, NULL, client->task, fetch_callback, client, rdataset,
|
||||
sigrdataset, &client->query.fetch);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->fetchhandle);
|
||||
ns_client_putrdataset(client, &rdataset);
|
||||
if (sigrdataset != NULL) {
|
||||
ns_client_putrdataset(client, &sigrdataset);
|
||||
|
|
@ -11108,7 +11109,7 @@ log_queryerror(ns_client_t *client, isc_result_t result, int line, int level) {
|
|||
}
|
||||
|
||||
void
|
||||
ns_query_start(ns_client_t *client) {
|
||||
ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
|
||||
isc_result_t result;
|
||||
dns_message_t *message;
|
||||
dns_rdataset_t *rdataset;
|
||||
|
|
@ -11118,6 +11119,11 @@ ns_query_start(ns_client_t *client) {
|
|||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
|
||||
/*
|
||||
* Attach to the request handle
|
||||
*/
|
||||
isc_nmhandle_attach(handle, &client->reqhandle);
|
||||
|
||||
message = client->message;
|
||||
saved_extflags = client->extflags;
|
||||
saved_flags = client->message->flags;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ notify_test_SOURCES = \
|
|||
|
||||
notify_test_LDFLAGS = \
|
||||
$(LDFLAGS) \
|
||||
-Wl,--wrap=isc_nmhandle_unref
|
||||
-Wl,--wrap=isc_nmhandle_attach \
|
||||
-Wl,--wrap=isc_nmhandle_detach
|
||||
|
||||
query_test_SOURCES = \
|
||||
query_test.c \
|
||||
|
|
@ -40,7 +41,7 @@ query_test_SOURCES = \
|
|||
|
||||
query_test_LDFLAGS = \
|
||||
$(LDFLAGS) \
|
||||
-Wl,--wrap=isc_nmhandle_unref
|
||||
-Wl,--wrap=isc_nmhandle_detach
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ static void
|
|||
notify_start(void **state) {
|
||||
isc_result_t result;
|
||||
ns_client_t *client = NULL;
|
||||
isc_nmhandle_t *handle = NULL;
|
||||
dns_message_t *nmsg = NULL;
|
||||
unsigned char ndata[4096];
|
||||
isc_buffer_t nbuf;
|
||||
|
|
@ -130,13 +131,16 @@ notify_start(void **state) {
|
|||
client->message = nmsg;
|
||||
nmsg = NULL;
|
||||
client->sendcb = check_response;
|
||||
ns_notify_start(client);
|
||||
ns_notify_start(client, client->handle);
|
||||
|
||||
/*
|
||||
* Clean up
|
||||
*/
|
||||
ns_test_cleanup_zone();
|
||||
isc_nmhandle_unref(client->handle);
|
||||
|
||||
handle = client->handle;
|
||||
isc_nmhandle_detach(&client->handle);
|
||||
isc_nmhandle_detach(&handle);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -78,10 +78,32 @@ atomic_uint_fast32_t client_refs[32];
|
|||
atomic_uintptr_t client_addrs[32];
|
||||
|
||||
void
|
||||
__wrap_isc_nmhandle_unref(isc_nmhandle_t *handle);
|
||||
__wrap_isc_nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp);
|
||||
void
|
||||
__wrap_isc_nmhandle_detach(isc_nmhandle_t **handlep);
|
||||
|
||||
void
|
||||
__wrap_isc_nmhandle_unref(isc_nmhandle_t *handle) {
|
||||
__wrap_isc_nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp) {
|
||||
ns_client_t *client = (ns_client_t *)source;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (atomic_load(&client_addrs[i]) == (uintptr_t)client) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
INSIST(i < 32);
|
||||
INSIST(atomic_load(&client_refs[i]) > 0);
|
||||
|
||||
atomic_fetch_add(&client_refs[i], 1);
|
||||
|
||||
*targetp = source;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
__wrap_isc_nmhandle_detach(isc_nmhandle_t **handlep) {
|
||||
isc_nmhandle_t *handle = *handlep;
|
||||
ns_client_t *client = (ns_client_t *)handle;
|
||||
int i;
|
||||
|
||||
|
|
@ -90,7 +112,7 @@ __wrap_isc_nmhandle_unref(isc_nmhandle_t *handle) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
REQUIRE(i < 32);
|
||||
INSIST(i < 32);
|
||||
|
||||
if (atomic_fetch_sub(&client_refs[i], 1) == 1) {
|
||||
dns_view_detach(&client->view);
|
||||
|
|
@ -99,6 +121,8 @@ __wrap_isc_nmhandle_unref(isc_nmhandle_t *handle) {
|
|||
ns__client_put_cb(client);
|
||||
isc_mem_put(mctx, client, sizeof(ns_client_t));
|
||||
}
|
||||
|
||||
*handlep = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -743,11 +767,13 @@ create_qctx_for_client(ns_client_t *client, query_ctx_t **qctxp) {
|
|||
saved_hook_table = ns__hook_table;
|
||||
ns__hook_table = query_hooks;
|
||||
|
||||
ns_query_start(client);
|
||||
ns_query_start(client, client->handle);
|
||||
|
||||
ns__hook_table = saved_hook_table;
|
||||
ns_hooktable_free(mctx, (void **)&query_hooks);
|
||||
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
|
||||
if (*qctxp == NULL) {
|
||||
return (ISC_R_NOMEMORY);
|
||||
} else {
|
||||
|
|
@ -760,6 +786,7 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
|
|||
query_ctx_t **qctxp) {
|
||||
ns_client_t *client = NULL;
|
||||
isc_result_t result;
|
||||
isc_nmhandle_t *handle = NULL;
|
||||
|
||||
REQUIRE(params != NULL);
|
||||
REQUIRE(params->qname != NULL);
|
||||
|
|
@ -810,17 +837,19 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
|
|||
}
|
||||
|
||||
/*
|
||||
* Reference count for "client" is now at 2, so decrement it in order
|
||||
* for it to drop to zero when "qctx" gets destroyed.
|
||||
* The reference count for "client" is now at 2, so we need to
|
||||
* decrement it in order for it to drop to zero when "qctx" gets
|
||||
* destroyed.
|
||||
*/
|
||||
isc_nmhandle_unref(client->handle);
|
||||
handle = client->handle;
|
||||
isc_nmhandle_detach(&handle);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
destroy_query:
|
||||
dns_message_destroy(&client->message);
|
||||
detach_client:
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->handle);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
|
@ -842,7 +871,7 @@ ns_test_qctx_destroy(query_ctx_t **qctxp) {
|
|||
dns_db_detach(&qctx->db);
|
||||
}
|
||||
if (qctx->client != NULL) {
|
||||
isc_nmhandle_unref(qctx->client->handle);
|
||||
isc_nmhandle_detach(&qctx->client->handle);
|
||||
}
|
||||
|
||||
isc_mem_put(mctx, qctx, sizeof(*qctx));
|
||||
|
|
|
|||
|
|
@ -26,15 +26,22 @@
|
|||
#include <ns/client.h>
|
||||
|
||||
/*
|
||||
* This overrides calls to isc_nmhandle_unref(), sending them to
|
||||
* __wrap_isc_nmhandle_unref(), when libtool is in use and LD_WRAP
|
||||
* can't be used.
|
||||
* This overrides calls to isc_nmhandle_attach/detach(), sending them to
|
||||
* __wrap_isc_nmhandle_attach/detach() instead, when libtool is in use
|
||||
* and LD_WRAP can't be used.
|
||||
*/
|
||||
|
||||
void
|
||||
__wrap_isc_nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp);
|
||||
extern void
|
||||
__wrap_isc_nmhandle_unref(isc_nmhandle_t *handle);
|
||||
__wrap_isc_nmhandle_detach(isc_nmhandle_t **handlep);
|
||||
|
||||
void
|
||||
isc_nmhandle_unref(isc_nmhandle_t *handle) {
|
||||
__wrap_isc_nmhandle_unref(handle);
|
||||
isc_nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp) {
|
||||
__wrap_isc_nmhandle_attach(source, targetp);
|
||||
}
|
||||
|
||||
void
|
||||
isc_nmhandle_detach(isc_nmhandle_t **handlep) {
|
||||
__wrap_isc_nmhandle_detach(handlep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1567,7 +1567,7 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) {
|
|||
client->nupdates++;
|
||||
event->ev_arg = client;
|
||||
|
||||
isc_nmhandle_ref(client->handle);
|
||||
isc_nmhandle_attach(client->handle, &client->updatehandle);
|
||||
dns_zone_gettask(zone, &zonetask);
|
||||
isc_task_send(zonetask, ISC_EVENT_PTR(&event));
|
||||
|
||||
|
|
@ -1585,7 +1585,6 @@ respond(ns_client_t *client, isc_result_t result) {
|
|||
client->message->rcode = dns_result_torcode(result);
|
||||
|
||||
ns_client_send(client);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
return;
|
||||
|
||||
msg_failure:
|
||||
|
|
@ -1594,17 +1593,23 @@ msg_failure:
|
|||
"could not create update response message: %s",
|
||||
isc_result_totext(msg_result));
|
||||
ns_client_drop(client, msg_result);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
}
|
||||
|
||||
void
|
||||
ns_update_start(ns_client_t *client, isc_result_t sigresult) {
|
||||
ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
|
||||
isc_result_t sigresult) {
|
||||
dns_message_t *request = client->message;
|
||||
isc_result_t result;
|
||||
dns_name_t *zonename;
|
||||
dns_rdataset_t *zone_rdataset;
|
||||
dns_zone_t *zone = NULL, *raw = NULL;
|
||||
|
||||
/*
|
||||
* Attach to the request handle
|
||||
*/
|
||||
isc_nmhandle_attach(handle, &client->reqhandle);
|
||||
|
||||
/*
|
||||
* Interpret the zone section.
|
||||
*/
|
||||
|
|
@ -1673,6 +1678,8 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) {
|
|||
default:
|
||||
FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
|
||||
}
|
||||
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
return;
|
||||
|
||||
failure:
|
||||
|
|
@ -1690,6 +1697,7 @@ failure:
|
|||
if (zone != NULL) {
|
||||
dns_zone_detach(&zone);
|
||||
}
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -3497,6 +3505,7 @@ common:
|
|||
}
|
||||
uev->ev_type = DNS_EVENT_UPDATEDONE;
|
||||
uev->ev_action = updatedone_action;
|
||||
|
||||
isc_task_send(client->task, &event);
|
||||
|
||||
INSIST(ver == NULL);
|
||||
|
|
@ -3510,8 +3519,9 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
|
|||
|
||||
UNUSED(task);
|
||||
|
||||
INSIST(event->ev_type == DNS_EVENT_UPDATEDONE);
|
||||
INSIST(task == client->task);
|
||||
REQUIRE(event->ev_type == DNS_EVENT_UPDATEDONE);
|
||||
REQUIRE(task == client->task);
|
||||
REQUIRE(client->updatehandle == client->handle);
|
||||
|
||||
INSIST(client->nupdates > 0);
|
||||
switch (uev->result) {
|
||||
|
|
@ -3528,16 +3538,18 @@ updatedone_action(isc_task_t *task, isc_event_t *event) {
|
|||
if (uev->zone != NULL) {
|
||||
dns_zone_detach(&uev->zone);
|
||||
}
|
||||
|
||||
client->nupdates--;
|
||||
|
||||
respond(client, uev->result);
|
||||
|
||||
isc_event_free(&event);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->updatehandle);
|
||||
}
|
||||
|
||||
/*%
|
||||
* Update forwarding support.
|
||||
*/
|
||||
|
||||
static void
|
||||
forward_fail(isc_task_t *task, isc_event_t *event) {
|
||||
ns_client_t *client = (ns_client_t *)event->ev_arg;
|
||||
|
|
@ -3548,7 +3560,7 @@ forward_fail(isc_task_t *task, isc_event_t *event) {
|
|||
client->nupdates--;
|
||||
respond(client, DNS_R_SERVFAIL);
|
||||
isc_event_free(&event);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->updatehandle);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3568,6 +3580,7 @@ forward_callback(void *arg, isc_result_t result, dns_message_t *answer) {
|
|||
uev->answer = answer;
|
||||
inc_stats(client, zone, ns_statscounter_updaterespfwd);
|
||||
}
|
||||
|
||||
isc_task_send(client->task, ISC_EVENT_PTR(&uev));
|
||||
dns_zone_detach(&zone);
|
||||
}
|
||||
|
|
@ -3584,7 +3597,7 @@ forward_done(isc_task_t *task, isc_event_t *event) {
|
|||
ns_client_sendraw(client, uev->answer);
|
||||
dns_message_destroy(&uev->answer);
|
||||
isc_event_free(&event);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->updatehandle);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3636,7 +3649,7 @@ send_forward_event(ns_client_t *client, dns_zone_t *zone) {
|
|||
namebuf, classbuf);
|
||||
|
||||
dns_zone_gettask(zone, &zonetask);
|
||||
isc_nmhandle_ref(client->handle);
|
||||
isc_nmhandle_attach(client->handle, &client->updatehandle);
|
||||
isc_task_send(zonetask, ISC_EVENT_PTR(&event));
|
||||
|
||||
if (event != NULL) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/stats.h>
|
||||
#include <isc/timer.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
|
|
@ -34,7 +33,6 @@
|
|||
#include <dns/rriterator.h>
|
||||
#include <dns/soa.h>
|
||||
#include <dns/stats.h>
|
||||
#include <dns/timer.h>
|
||||
#include <dns/tsig.h>
|
||||
#include <dns/view.h>
|
||||
#include <dns/zone.h>
|
||||
|
|
@ -1192,7 +1190,7 @@ failure:
|
|||
NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3),
|
||||
"zone transfer setup failed");
|
||||
ns_client_error(client, result);
|
||||
isc_nmhandle_unref(client->handle);
|
||||
isc_nmhandle_detach(&client->reqhandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1276,11 +1274,6 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
|
|||
xfr->txmem = mem;
|
||||
xfr->txmemlen = len;
|
||||
|
||||
#if 0
|
||||
CHECK(dns_timer_setidle(xfr->client->timer,
|
||||
maxtime,idletime,false));
|
||||
#endif /* if 0 */
|
||||
|
||||
/*
|
||||
* Register a shutdown callback with the client, so that we
|
||||
* can stop the transfer immediately when the client task
|
||||
|
|
@ -1572,15 +1565,17 @@ sendstream(xfrout_ctx_t *xfr) {
|
|||
xfrout_log(xfr, ISC_LOG_DEBUG(8),
|
||||
"sending TCP message of %d bytes", used.length);
|
||||
|
||||
CHECK(isc_nm_send(xfr->client->handle, &used, xfrout_senddone,
|
||||
xfr));
|
||||
isc_nmhandle_attach(xfr->client->handle,
|
||||
&xfr->client->sendhandle);
|
||||
CHECK(isc_nm_send(xfr->client->sendhandle, &used,
|
||||
xfrout_senddone, xfr));
|
||||
xfr->sends++;
|
||||
xfr->cbytes = used.length;
|
||||
} else {
|
||||
xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
|
||||
ns_client_send(xfr->client);
|
||||
xfr->stream->methods->pause(xfr->stream);
|
||||
isc_nmhandle_unref(xfr->client->handle);
|
||||
isc_nmhandle_detach(&xfr->client->reqhandle);
|
||||
xfrout_ctx_destroy(&xfr);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1623,6 +1618,10 @@ failure:
|
|||
return;
|
||||
}
|
||||
|
||||
if (xfr->client->sendhandle != NULL) {
|
||||
isc_nmhandle_detach(&xfr->client->sendhandle);
|
||||
}
|
||||
|
||||
xfrout_fail(xfr, result, "sending zone data");
|
||||
}
|
||||
|
||||
|
|
@ -1675,6 +1674,8 @@ xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
xfr->sends--;
|
||||
INSIST(xfr->sends == 0);
|
||||
|
||||
isc_nmhandle_detach(&xfr->client->sendhandle);
|
||||
|
||||
/*
|
||||
* Update transfer statistics if sending succeeded, accounting for the
|
||||
* two-byte TCP length prefix included in the number of bytes sent.
|
||||
|
|
@ -1684,10 +1685,6 @@ xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
xfr->stats.nbytes += xfr->cbytes;
|
||||
}
|
||||
|
||||
#if 0
|
||||
(void)isc_timer_touch(xfr->client->timer);
|
||||
#endif /* if 0 */
|
||||
|
||||
if (xfr->shuttingdown) {
|
||||
xfrout_maybe_destroy(xfr);
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -1716,9 +1713,12 @@ xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
|||
(unsigned int)(msecs % 1000), (unsigned int)persec,
|
||||
xfr->end_serial);
|
||||
|
||||
/*
|
||||
* We're done, unreference the handle and destroy the xfr
|
||||
* context.
|
||||
*/
|
||||
isc_nmhandle_detach(&xfr->client->reqhandle);
|
||||
xfrout_ctx_destroy(&xfr);
|
||||
/* We're done, unreference the handle */
|
||||
isc_nmhandle_unref(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1732,23 +1732,11 @@ xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
|
|||
|
||||
static void
|
||||
xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
|
||||
INSIST(xfr->shuttingdown);
|
||||
#if 0
|
||||
if (xfr->sends > 0) {
|
||||
/*
|
||||
* If we are currently sending, cancel it and wait for
|
||||
* cancel event before destroying the context.
|
||||
*/
|
||||
isc_socket_cancel(xfr->client->tcpsocket,xfr->client->task,
|
||||
ISC_SOCKCANCEL_SEND);
|
||||
} else {
|
||||
#endif /* if 0 */
|
||||
REQUIRE(xfr->shuttingdown);
|
||||
|
||||
ns_client_drop(xfr->client, ISC_R_CANCELED);
|
||||
isc_nmhandle_unref(xfr->client->handle);
|
||||
isc_nmhandle_detach(&xfr->client->reqhandle);
|
||||
xfrout_ctx_destroy(&xfr);
|
||||
#if 0
|
||||
}
|
||||
#endif /* if 0 */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Reference in a new issue