Rewrite dns_resolver and dns_request to use netmgr timeouts

- The `timeout_action` parameter to dns_dispatch_addresponse() been
  replaced with a netmgr callback that is called when a dispatch read
  times out.  this callback may optionally reset the read timer and
  resume reading.

- Added a function to convert isc_interval to milliseconds; this is used
  to translate fctx->interval into a value that can be passed to
  dns_dispatch_addresponse() as the timeout.

- Note that netmgr timeouts are accurate to the millisecond, so code to
  check whether a timeout has been reached cannot rely on microsecond
  accuracy.

- If serve-stale is configured, then a timeout received by the resolver
  may trigger it to return stale data, and then resume waiting for the
  read timeout. this is no longer based on a separate stale timer.

- The code for canceling requests in request.c has been altered so that
  it can run asynchronously.

- TCP timeout events apply to the dispatch, which may be shared by
  multiple queries.  since in the event of a timeout we have no query ID
  to use to identify the resp we wanted, we now just send the timeout to
  the oldest query that was pending.

- There was some additional refactoring in the resolver: combining
  fctx_join() and fctx_try_events() into one function to reduce code
  duplication, and using fixednames in fetchctx and fetchevent.

- Incidental fix: new_adbaddrinfo() can't return NULL anymore, so the
  code can be simplified.
This commit is contained in:
Evan Hunt 2021-04-22 18:58:01 -07:00
parent 308bc46a59
commit 08ce69a0ea
14 changed files with 601 additions and 827 deletions

View file

@ -2237,11 +2237,9 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
find->options |= DNS_ADBFIND_LAMEPRUNED;
goto nextv4;
}
addrinfo = new_adbaddrinfo(adb, entry, find->port);
if (addrinfo == NULL) {
find->partial_result |= DNS_ADBFIND_INET;
goto out;
}
/*
* Found a valid entry. Add it to the find's list.
*/
@ -2275,10 +2273,7 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
goto nextv6;
}
addrinfo = new_adbaddrinfo(adb, entry, find->port);
if (addrinfo == NULL) {
find->partial_result |= DNS_ADBFIND_INET6;
goto out;
}
/*
* Found a valid entry. Add it to the find's list.
*/
@ -2292,7 +2287,6 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find,
}
}
out:
if (bucket != DNS_ADB_INVALIDBUCKET) {
UNLOCK(&adb->entrylocks[bucket]);
}
@ -3962,8 +3956,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
clean_target(adb, &name->target);
name->expire_target = INT_MAX;
result = set_target(adb, &name->name,
dns_fixedname_name(&dev->foundname),
result = set_target(adb, &name->name, dev->foundname,
dev->rdataset, &name->target);
if (result == ISC_R_SUCCESS) {
DP(NCACHE_LEVEL,
@ -4533,12 +4526,8 @@ dns_adb_findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *sa,
port = isc_sockaddr_getport(sa);
addr = new_adbaddrinfo(adb, entry, port);
if (addr == NULL) {
result = ISC_R_NOMEMORY;
} else {
inc_entry_refcnt(adb, entry, false);
*addrp = addr;
}
inc_entry_refcnt(adb, entry, false);
*addrp = addr;
unlock:
UNLOCK(&adb->entrylocks[bucket]);

View file

@ -579,9 +579,9 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
isc_result_t vresult = ISC_R_SUCCESS;
bool want_restart;
bool send_event = false;
dns_name_t *name, *prefix;
dns_name_t *name = NULL, *prefix = NULL;
dns_fixedname_t foundname, fixed;
dns_rdataset_t *trdataset;
dns_rdataset_t *trdataset = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned int nlabels;
int order;
@ -643,7 +643,7 @@ client_resfind(resctx_t *rctx, dns_fetchevent_t *event) {
node = event->node;
result = event->result;
vresult = event->vresult;
fname = dns_fixedname_name(&event->foundname);
fname = event->foundname;
INSIST(event->rdataset == rctx->rdataset);
INSIST(event->sigrdataset == rctx->sigrdataset);
}

View file

@ -37,6 +37,8 @@
#include <dns/stats.h>
#include <dns/types.h>
#define DISPATCH_TRACE
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
typedef struct dispsocket dispsocket_t;
@ -89,8 +91,8 @@ struct dns_dispentry {
isc_task_t *task;
isc_nm_cb_t connected;
isc_nm_cb_t sent;
isc_nm_cb_t timedout;
isc_taskaction_t action;
isc_taskaction_t timeout_action;
void *arg;
bool item_out;
dispsocket_t *dispsocket;
@ -729,7 +731,6 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
dns_dispatchmgr_t *mgr = NULL;
isc_sockaddr_t peer;
isc_netaddr_t netaddr;
isc_taskaction_t action;
int match;
REQUIRE(VALID_DISPSOCK(dispsock));
@ -767,8 +768,7 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
}
if (dispsock == NULL) {
UNLOCK(&disp->lock);
return;
goto next;
}
resp = dispsock->resp;
@ -777,12 +777,20 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
peer = isc_nmhandle_peeraddr(handle);
isc_netaddr_fromsockaddr(&netaddr, &peer);
if (eresult == ISC_R_TIMEDOUT && resp->timedout != NULL) {
resp->timedout(handle, ISC_R_TIMEDOUT, resp->arg);
if (isc_nmhandle_timer_running(handle)) {
goto next;
}
}
if (eresult != ISC_R_SUCCESS) {
/*
* This is most likely either a timeout or a network
* error on a connected socket. It makes no sense to
* check the address or parse the packet, but it
* will help to return the error to the caller.
* This is most likely a network error on a connected
* socket, or a timeout on a timer that has not been
* reset. It makes no sense to check the address or
* parse the packet, but it will help to return the
* error to the caller.
*/
goto sendevent;
}
@ -858,12 +866,11 @@ sendevent:
isc_buffer_add(&rev->buffer, rev->region.length);
}
rev->result = eresult;
if (queue_response) {
ISC_LIST_APPEND(resp->items, rev, ev_link);
} else {
ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
action, resp->arg, resp, NULL, NULL);
resp->action, resp->arg, resp, NULL, NULL);
request_log(disp, resp, LVL(90),
"[a] Sent event %p buffer %p len %d to task %p",
rev, rev->buffer.base, rev->buffer.length,
@ -900,6 +907,7 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
dns_messageid_t id;
isc_result_t dres;
unsigned int flags;
dispsocket_t *dispsock = NULL;
dns_dispentry_t *resp = NULL;
dns_dispatchevent_t *rev = NULL;
unsigned int bucket;
@ -910,7 +918,6 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
char buf[ISC_SOCKADDR_FORMATSIZE];
isc_buffer_t source;
isc_sockaddr_t peer;
isc_taskaction_t action;
REQUIRE(VALID_DISPATCH(disp));
@ -940,6 +947,8 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
switch (eresult) {
case ISC_R_CANCELED:
dispatch_log(disp, LVL(90), "shutting down on cancel");
do_cancel(disp);
break;
case ISC_R_EOF:
@ -952,8 +961,26 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
goto logit;
case ISC_R_TIMEDOUT:
id = 0; /* XXX this is broken */
goto sendevent;
/*
* Time out the first active response for which
* no event has already been sent.
*/
for (dispsock = ISC_LIST_HEAD(disp->activesockets);
dispsock != NULL;
dispsock = ISC_LIST_NEXT(dispsock, link))
{
resp = dispsock->resp;
if (resp->item_out) {
continue;
}
ISC_LIST_UNLINK(disp->activesockets, dispsock,
link);
ISC_LIST_APPEND(disp->activesockets, dispsock,
link);
goto sendevent;
}
INSIST(0);
ISC_UNREACHABLE();
default:
level = ISC_LOG_ERROR;
@ -1014,20 +1041,20 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
goto next;
}
sendevent:
/*
* Response.
* We have a response; find the associated dispentry.
*/
bucket = dns_hash(qid, &peer, id, disp->localport);
LOCK(&qid->lock);
resp = entry_search(qid, &peer, id, disp->localport, bucket);
dispatch_log(disp, LVL(90), "search for response in bucket %d: %s",
bucket, (resp == NULL ? "not found" : "found"));
UNLOCK(&qid->lock);
if (resp == NULL) {
UNLOCK(&qid->lock);
goto next;
}
sendevent:
queue_response = resp->item_out;
rev = allocate_devent(disp);
@ -1052,14 +1079,13 @@ sendevent:
ISC_LIST_APPEND(resp->items, rev, ev_link);
} else {
ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
action, resp->arg, resp, NULL, NULL);
resp->action, resp->arg, resp, NULL, NULL);
request_log(disp, resp, LVL(90),
"[b] Sent event %p buffer %p len %d to task %p",
rev, rev->buffer.base, rev->buffer.length,
resp->task);
isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
}
UNLOCK(&qid->lock);
next:
startrecv(disp, NULL);
@ -1710,8 +1736,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
unsigned int timeout, const isc_sockaddr_t *dest,
isc_task_t *task, isc_nm_cb_t connected,
isc_nm_cb_t sent, isc_taskaction_t action,
isc_taskaction_t timeout_action, void *arg,
dns_messageid_t *idp, dns_dispentry_t **resp) {
isc_nm_cb_t timedout, void *arg, dns_messageid_t *idp,
dns_dispentry_t **resp) {
isc_result_t result;
dns_dispentry_t *res = NULL;
dispsocket_t *dispsocket = NULL;
@ -1829,8 +1855,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
.peer = *dest,
.connected = connected,
.sent = sent,
.timedout = timedout,
.action = action,
.timeout_action = timeout_action,
.arg = arg,
.dispsocket = dispsocket };

View file

@ -312,8 +312,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
unsigned int timeout, const isc_sockaddr_t *dest,
isc_task_t *task, isc_nm_cb_t connected,
isc_nm_cb_t sent, isc_taskaction_t action,
isc_taskaction_t timeout_action, void *arg,
dns_messageid_t *idp, dns_dispentry_t **resp);
isc_nm_cb_t timedout, void *arg, dns_messageid_t *idp,
dns_dispentry_t **resp);
/*%<
* Add a response entry for this dispatch.
*
@ -321,7 +321,9 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
* to contain the magic token used to request event flow stop.
*
* The 'connected' and 'sent' callbacks are run to inform the caller when
* the connection and send functions are complete.
* the connect and send functions are complete. The 'timedout' callback
* is run to inform the caller that a read has timed out; it may optionally
* reset the read timer.
*
* The specified 'task' is sent the 'action' callback for response packets.
* (Later, this should be updated to a network manager callback function,
@ -329,8 +331,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options,
* it must be returned using dns_dispatch_freeevent() or through
* dns_dispatch_removeresponse() for another to be delivered.
*
* On timeout, 'timeout_action' will be sent to the task.
*
* All three callback functions are sent 'arg' as a parameter.
*
* Requires:

View file

@ -74,7 +74,8 @@ typedef struct dns_fetchevent {
dns_dbnode_t * node;
dns_rdataset_t * rdataset;
dns_rdataset_t * sigrdataset;
dns_fixedname_t foundname;
dns_fixedname_t fname;
dns_name_t * foundname;
const isc_sockaddr_t *client;
dns_messageid_t id;
isc_result_t vresult;

View file

@ -140,10 +140,10 @@ view_find(dns_lookup_t *lookup, dns_name_t *foundname) {
static void
lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
isc_result_t result;
isc_result_t result = ISC_R_SUCCESS;
bool want_restart;
bool send_event;
dns_name_t *name, *fname, *prefix;
dns_name_t *name = NULL, *fname = NULL, *prefix = NULL;
dns_fixedname_t foundname, fixed;
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned int nlabels;
@ -156,7 +156,6 @@ lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
LOCK(&lookup->lock);
result = ISC_R_SUCCESS;
name = dns_fixedname_name(&lookup->name);
do {
@ -202,12 +201,10 @@ lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
}
} else if (event != NULL) {
result = event->result;
fname = dns_fixedname_name(&event->foundname);
fname = event->foundname;
dns_resolver_destroyfetch(&lookup->fetch);
INSIST(event->rdataset == &lookup->rdataset);
INSIST(event->sigrdataset == &lookup->sigrdataset);
} else {
fname = NULL; /* Silence compiler warning. */
}
/*

View file

@ -16,6 +16,7 @@
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
#include <isc/task.h>
#include <isc/util.h>
@ -75,24 +76,20 @@ struct dns_request {
isc_buffer_t *tsig;
dns_tsigkey_t *tsigkey;
isc_socketevent_t sendevent;
isc_event_t ctlevent;
bool canceling; /* ctlevent outstanding */
isc_sockaddr_t destaddr;
unsigned int timeout;
unsigned int udpcount;
isc_dscp_t dscp;
};
#define DNS_REQUEST_F_CONNECTING 0x0001
#define DNS_REQUEST_F_SENDING 0x0002
#define DNS_REQUEST_F_CANCELED \
0x0004 /*%< ctlevent received, or otherwise \
* synchronously canceled */
#define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< canceled due to a timeout */
#define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
#define DNS_REQUEST_F_CANCELED 0x0004
#define DNS_REQUEST_F_TCP 0x0010
#define DNS_REQUEST_CANCELED(r) (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
#define DNS_REQUEST_CONNECTING(r) (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
#define DNS_REQUEST_SENDING(r) (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
#define DNS_REQUEST_TIMEDOUT(r) (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
/***
*** Forward
@ -113,21 +110,19 @@ req_render(dns_message_t *message, isc_buffer_t **buffer, unsigned int options,
static void
req_response(isc_task_t *task, isc_event_t *event);
static void
req_timeout(isc_task_t *task, isc_event_t *event);
static void
req_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
static void
req_sendevent(dns_request_t *request, isc_result_t result);
static void
req_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
static void
req_cancel(dns_request_t *request);
req_timeout(isc_nmhandle_t *handle, isc_result_t eresult, void *arg);
static void
req_destroy(dns_request_t *request);
static void
req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
static void
do_cancel(isc_task_t *task, isc_event_t *event);
void
request_cancel(dns_request_t *request);
/***
*** Public
@ -236,9 +231,6 @@ static void
mgr_shutdown(dns_requestmgr_t *requestmgr) {
dns_request_t *request;
/*
* Caller holds lock.
*/
if (!requestmgr->exiting) {
requestmgr->exiting = true;
for (request = ISC_LIST_HEAD(requestmgr->requests);
@ -422,9 +414,6 @@ new_request(isc_mem_t *mctx, dns_request_t **requestp) {
request = isc_mem_get(mctx, sizeof(*request));
*request = (dns_request_t){ .dscp = -1 };
ISC_LINK_INIT(request, link);
ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, NULL,
NULL);
isc_mem_attach(mctx, &request->mctx);
@ -574,16 +563,6 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
return (result);
}
if (udptimeout == 0 && udpretries != 0) {
udptimeout = timeout / (udpretries + 1);
if (udptimeout == 0) {
udptimeout = 1;
}
}
timeout *= 1000;
udptimeout *= 1000;
request->udpcount = udpretries;
request->dscp = dscp;
@ -603,6 +582,15 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512) {
tcp = true;
request->timeout = timeout * 1000;
} else {
if (udptimeout == 0 && udpretries != 0) {
udptimeout = timeout / (udpretries + 1);
}
if (udptimeout == 0) {
udptimeout = 1;
}
request->timeout = udptimeout * 1000;
}
again:
@ -618,9 +606,9 @@ again:
}
result = dns_dispatch_addresponse(
request->dispatch, dispopt, tcp ? timeout : udptimeout,
destaddr, task, req_connected, req_senddone, req_response,
req_timeout, request, &id, &request->dispentry);
request->dispatch, dispopt, request->timeout, destaddr, task,
req_connected, req_senddone, req_response, req_timeout, request,
&id, &request->dispentry);
if (result != ISC_R_SUCCESS) {
if ((options & DNS_REQUESTOPT_FIXEDID) != 0 && !newtcp) {
newtcp = true;
@ -708,7 +696,7 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_result_t result;
isc_mem_t *mctx;
dns_messageid_t id;
bool tcp;
bool tcp = false;
bool settsigkey = true;
bool connected = false;
@ -738,16 +726,6 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
return (result);
}
if (udptimeout == 0 && udpretries != 0) {
udptimeout = timeout / (udpretries + 1);
if (udptimeout == 0) {
udptimeout = 1;
}
}
timeout *= 1000;
udptimeout *= 1000;
request->udpcount = udpretries;
request->dscp = dscp;
@ -763,7 +741,19 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
}
use_tcp:
tcp = ((options & DNS_REQUESTOPT_TCP) != 0);
if ((options & DNS_REQUESTOPT_TCP) != 0) {
tcp = true;
request->timeout = timeout * 1000;
} else {
if (udptimeout == 0 && udpretries != 0) {
udptimeout = timeout / (udpretries + 1);
}
if (udptimeout == 0) {
udptimeout = 1;
}
request->timeout = udptimeout * 1000;
}
result = get_dispatch(tcp, false, requestmgr, srcaddr, destaddr, dscp,
&connected, &request->dispatch);
if (result != ISC_R_SUCCESS) {
@ -771,9 +761,9 @@ use_tcp:
}
result = dns_dispatch_addresponse(
request->dispatch, 0, tcp ? timeout : udptimeout, destaddr,
task, req_connected, req_senddone, req_response, req_timeout,
request, &id, &request->dispentry);
request->dispatch, 0, request->timeout, destaddr, task,
req_connected, req_senddone, req_response, req_timeout, request,
&id, &request->dispentry);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
@ -952,26 +942,28 @@ cleanup:
*/
static void
send_if_done(dns_request_t *request, isc_result_t result) {
if (request->event != NULL && !request->canceling) {
if (request->event != NULL) {
req_sendevent(request, result);
}
}
/*
* Handle the control event.
*/
static void
do_cancel(isc_task_t *task, isc_event_t *event) {
dns_request_t *request = event->ev_arg;
UNUSED(task);
INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
LOCK(&request->requestmgr->locks[request->hash]);
request->canceling = false;
void
request_cancel(dns_request_t *request) {
if (!DNS_REQUEST_CANCELED(request)) {
req_cancel(request);
req_log(ISC_LOG_DEBUG(3), "do_cancel: request %p", request);
request->flags |= DNS_REQUEST_F_CANCELED;
request->flags &= ~DNS_REQUEST_F_CONNECTING;
if (request->dispentry != NULL) {
dns_dispatch_cancel(NULL, request->dispentry,
DNS_REQUEST_SENDING(request),
DNS_REQUEST_CONNECTING(request));
dns_dispatch_removeresponse(&request->dispentry, NULL);
}
dns_dispatch_detach(&request->dispatch);
}
send_if_done(request, ISC_R_CANCELED);
UNLOCK(&request->requestmgr->locks[request->hash]);
}
void
@ -979,15 +971,9 @@ dns_request_cancel(dns_request_t *request) {
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
REQUIRE(VALID_REQUEST(request));
LOCK(&request->requestmgr->locks[request->hash]);
if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
isc_event_t *ev = &request->ctlevent;
isc_task_send(request->event->ev_sender, &ev);
request->canceling = true;
}
request_cancel(request);
send_if_done(request, ISC_R_CANCELED);
UNLOCK(&request->requestmgr->locks[request->hash]);
}
@ -1054,8 +1040,8 @@ dns_request_destroy(dns_request_t **requestp) {
UNLOCK(&request->requestmgr->lock);
/*
* These should have been cleaned up by req_cancel() before
* the completion event was sent.
* These should have been cleaned up before the completion
* event was sent.
*/
INSIST(!ISC_LINK_LINKED(request, link));
INSIST(request->dispentry == NULL);
@ -1073,6 +1059,10 @@ req_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
UNUSED(handle);
if (eresult == ISC_R_CANCELED) {
return;
}
REQUIRE(VALID_REQUEST(request));
REQUIRE(DNS_REQUEST_CONNECTING(request));
@ -1081,22 +1071,17 @@ req_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
LOCK(&request->requestmgr->locks[request->hash]);
request->flags &= ~DNS_REQUEST_F_CONNECTING;
if (DNS_REQUEST_CANCELED(request)) {
/*
* Send delayed event.
*/
if (DNS_REQUEST_TIMEDOUT(request)) {
send_if_done(request, ISC_R_TIMEDOUT);
} else {
send_if_done(request, ISC_R_CANCELED);
}
if (eresult == ISC_R_TIMEDOUT) {
dns_dispatch_removeresponse(&request->dispentry, NULL);
dns_dispatch_detach(&request->dispatch);
send_if_done(request, eresult);
} else if (DNS_REQUEST_CANCELED(request)) {
send_if_done(request, ISC_R_CANCELED);
} else if (eresult == ISC_R_SUCCESS) {
req_send(request);
} else {
if (eresult == ISC_R_SUCCESS) {
req_send(request);
} else {
req_cancel(request);
send_if_done(request, ISC_R_CANCELED);
}
request_cancel(request);
send_if_done(request, ISC_R_CANCELED);
}
UNLOCK(&request->requestmgr->locks[request->hash]);
}
@ -1116,19 +1101,39 @@ req_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
request->flags &= ~DNS_REQUEST_F_SENDING;
if (DNS_REQUEST_CANCELED(request)) {
if (DNS_REQUEST_TIMEDOUT(request)) {
send_if_done(request, ISC_R_TIMEDOUT);
if (eresult == ISC_R_TIMEDOUT) {
send_if_done(request, eresult);
} else {
send_if_done(request, ISC_R_CANCELED);
}
} else if (eresult != ISC_R_SUCCESS) {
req_cancel(request);
request_cancel(request);
send_if_done(request, ISC_R_CANCELED);
}
UNLOCK(&request->requestmgr->locks[request->hash]);
}
static void
req_timeout(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
dns_request_t *request = (dns_request_t *)arg;
REQUIRE(VALID_REQUEST(request));
UNUSED(eresult);
req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
LOCK(&request->requestmgr->locks[request->hash]);
if (--request->udpcount != 0) {
isc_nmhandle_settimeout(handle, request->timeout);
if (!DNS_REQUEST_SENDING(request)) {
req_send(request);
}
}
UNLOCK(&request->requestmgr->locks[request->hash]);
}
static void
req_response(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
@ -1164,7 +1169,8 @@ done:
* Cleanup.
*/
dns_dispatch_removeresponse(&request->dispentry, &devent);
req_cancel(request);
request_cancel(request);
/*
* Send completion event.
*/
@ -1172,29 +1178,6 @@ done:
UNLOCK(&request->requestmgr->locks[request->hash]);
}
static void
req_timeout(isc_task_t *task, isc_event_t *event) {
dns_request_t *request = event->ev_arg;
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
UNUSED(task);
LOCK(&request->requestmgr->locks[request->hash]);
if (request->udpcount-- != 0) {
if (!DNS_REQUEST_SENDING(request)) {
req_send(request);
}
} else {
request->flags |= DNS_REQUEST_F_TIMEDOUT;
req_cancel(request);
send_if_done(request, ISC_R_TIMEDOUT);
}
UNLOCK(&request->requestmgr->locks[request->hash]);
isc_event_free(&event);
}
static void
req_sendevent(dns_request_t *request, isc_result_t result) {
isc_task_t *task;
@ -1246,29 +1229,6 @@ req_destroy(dns_request_t *request) {
isc_mem_putanddetach(&request->mctx, request, sizeof(*request));
}
/*
* Stop the current request. Must be called from the request's task.
*/
static void
req_cancel(dns_request_t *request) {
REQUIRE(VALID_REQUEST(request));
req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
/*
* Lock held by caller.
*/
request->flags |= DNS_REQUEST_F_CANCELED;
if (request->dispentry != NULL) {
dns_dispatch_cancel(NULL, request->dispentry,
DNS_REQUEST_SENDING(request),
DNS_REQUEST_CONNECTING(request));
dns_dispatch_removeresponse(&request->dispentry, NULL);
}
dns_dispatch_detach(&request->dispatch);
}
static void
req_log(int level, const char *fmt, ...) {
va_list ap;

File diff suppressed because it is too large Load diff

View file

@ -576,8 +576,8 @@ fetch_callback_ds(isc_task_t *task, isc_event_t *event) {
} else if (eresult == DNS_R_SERVFAIL) {
goto unexpected;
} else if (eresult != DNS_R_CNAME &&
isdelegation(dns_fixedname_name(&devent->foundname),
&val->frdataset, eresult))
isdelegation(devent->foundname, &val->frdataset,
eresult))
{
/*
* Failed to find a DS while trying to prove

View file

@ -160,6 +160,12 @@ isc_nmhandle_cleartimeout(isc_nmhandle_t *handle);
* a TCPDNS socket wrapping a TCP connection), the timer is set for
* both socket layers.
*/
bool
isc_nmhandle_timer_running(isc_nmhandle_t *handle);
/*%<
* Return true if the timer for the socket connected to 'handle'
* is running.
*/
void
isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value);

View file

@ -71,6 +71,16 @@ isc_interval_iszero(const isc_interval_t *i);
*\li 'i' is a valid pointer.
*/
unsigned int
isc_interval_ms(const isc_interval_t *i);
/*%<
* Returns interval 'i' expressed as a number of milliseconds.
*
* Requires:
*
*\li 'i' is a valid pointer.
*/
/***
*** Absolute Times
***/

View file

@ -2404,6 +2404,14 @@ isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value) {
}
}
bool
isc_nmhandle_timer_running(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
return (isc__nmsocket_timer_running(handle->sock));
}
void *
isc_nmhandle_getextra(isc_nmhandle_t *handle) {
REQUIRE(VALID_NMHANDLE(handle));

View file

@ -31,6 +31,7 @@
#define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
#define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
#define NS_PER_MS 1000000 /*%< Nanoseconds per millisecond. */
#define MS_PER_S 1000 /*%< Milliseonds per second. */
#if defined(CLOCK_REALTIME)
#define CLOCKSOURCE_HIRES CLOCK_REALTIME
@ -77,6 +78,14 @@ isc_interval_iszero(const isc_interval_t *i) {
return (false);
}
unsigned int
isc_interval_ms(const isc_interval_t *i) {
REQUIRE(i != NULL);
INSIST(i->nanoseconds < NS_PER_S);
return ((i->seconds * MS_PER_S) + (i->nanoseconds / NS_PER_MS));
}
/***
*** Absolute Times
***/

View file

@ -6652,7 +6652,7 @@ query_resume(query_ctx_t *qctx) {
} else if (REDIRECT(qctx->client)) {
tname = qctx->client->query.redirect.fname;
} else {
tname = dns_fixedname_name(&qctx->event->foundname);
tname = qctx->event->foundname;
}
dns_name_copy(tname, qctx->fname);