Schedule dnsreqs with absolute timeout/expiry time

This commit is contained in:
Willem Toorop 2017-03-13 14:20:47 +01:00
parent 5f3de12644
commit 639239f45c
8 changed files with 61 additions and 24 deletions

View File

@ -3032,6 +3032,7 @@ static void check_chain_complete(chain_head *chain)
int r = GETDNS_RETURN_GOOD;
getdns_network_req **netreq_p, *netreq;
uint64_t now_ms = 0;
dnsreq->avoid_dnssec_roadblocks = 1;
@ -3041,7 +3042,7 @@ static void check_chain_complete(chain_head *chain)
netreq->state = NET_REQ_NOT_SENT;
netreq->owner = dnsreq;
r = _getdns_submit_netreq(netreq);
r = _getdns_submit_netreq(netreq, &now_ms);
}
return;
}

View File

@ -91,6 +91,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
{
getdns_network_req **netreq_p, *netreq;
int results_found = 0, r;
uint64_t now_ms = 0;
for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++)
if (!_getdns_netreq_finished(netreq))
@ -126,7 +127,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
; (netreq = *netreq_p)
; netreq_p++ ) {
_getdns_netreq_reinit(netreq);
if ((r = _getdns_submit_netreq(netreq))) {
if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED)
return;
netreq->state = NET_REQ_FINISHED;
@ -164,7 +165,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
; (netreq = *netreq_p)
; netreq_p++ ) {
_getdns_netreq_reinit(netreq);
if ((r = _getdns_submit_netreq(netreq))) {
if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED)
return;
netreq->state = NET_REQ_FINISHED;
@ -248,7 +249,7 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
int
_getdns_submit_netreq(getdns_network_req *netreq)
_getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
{
getdns_return_t r;
getdns_dns_req *dns_req = netreq->owner;
@ -284,7 +285,8 @@ _getdns_submit_netreq(getdns_network_req *netreq)
_getdns_context_request_timed_out;
dns_req->timeout.ev = NULL;
if ((r = dns_req->loop->vmt->schedule(dns_req->loop, -1,
dns_req->context->timeout, &dns_req->timeout)))
_getdns_ms_until_expiry2(dns_req->expires, now_ms),
&dns_req->timeout)))
return r;
}
(void) gldns_wire2str_dname_buf(dns_req->name,
@ -314,7 +316,7 @@ _getdns_submit_netreq(getdns_network_req *netreq)
}
/* Submit with stub resolver */
dns_req->freed = &dnsreq_freed;
r = _getdns_submit_stub_request(netreq);
r = _getdns_submit_stub_request(netreq, now_ms);
if (dnsreq_freed)
return DNS_REQ_FINISHED;
dns_req->freed = NULL;
@ -413,6 +415,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
getdns_dns_req *req;
getdns_dict *localnames_response;
size_t i;
uint64_t now_ms = 0;
if (!context || !name || (!callbackfn && !internal_cb))
return GETDNS_RETURN_INVALID_PARAMETER;
@ -430,7 +433,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
/* create the request */
if (!(req = _getdns_dns_req_new(
context, loop, name, request_type, extensions)))
context, loop, name, request_type, extensions, &now_ms)))
return GETDNS_RETURN_MEMORY_ERROR;
req->user_pointer = userarg;
@ -448,7 +451,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p)
; netreq_p++) {
if ((r = _getdns_submit_netreq(netreq))) {
if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED) {
if (return_netreq_p)
*return_netreq_p = NULL;
@ -500,7 +503,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p)
; netreq_p++) {
if ((r = _getdns_submit_netreq(netreq))) {
if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED) {
if (return_netreq_p)
*return_netreq_p = NULL;

View File

@ -46,7 +46,7 @@
void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *);
void _getdns_check_dns_req_complete(getdns_dns_req *dns_req);
int _getdns_submit_netreq(getdns_network_req *netreq);
int _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms);
getdns_return_t

View File

@ -658,7 +658,8 @@ static const uint8_t no_suffixes[] = { 1, 0 };
/* create a new dns req to be submitted */
getdns_dns_req *
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions)
const char *name, uint16_t request_type, getdns_dict *extensions,
uint64_t *now_ms)
{
int dnssec_return_status = is_extension_set(
extensions, "dnssec_return_status",
@ -953,5 +954,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
netreq_sz - sizeof(getdns_network_req), max_query_sz,
extensions);
if (*now_ms == 0 && (*now_ms = _getdns_get_now_ms()) == 0)
result->expires = 0;
else
result->expires = *now_ms + context->timeout;
return result;
}

View File

@ -1358,8 +1358,8 @@ stub_udp_read_cb(void *userarg)
dnsreq)) == -1)
break;
upstream_schedule_netreq(netreq->upstream, netreq);
GETDNS_SCHEDULE_EVENT(
dnsreq->loop, -1, dnsreq->context->timeout,
GETDNS_SCHEDULE_EVENT(dnsreq->loop, -1,
_getdns_ms_until_expiry(dnsreq->expires),
getdns_eventloop_event_init(&netreq->event,
netreq, NULL, NULL, stub_timeout_cb));
@ -1421,8 +1421,8 @@ stub_udp_write_cb(void *userarg)
#endif
return;
}
GETDNS_SCHEDULE_EVENT(
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
GETDNS_SCHEDULE_EVENT(dnsreq->loop, netreq->fd,
_getdns_ms_until_expiry(dnsreq->expires),
getdns_eventloop_event_init(&netreq->event, netreq,
stub_udp_read_cb, NULL, stub_timeout_cb));
}
@ -1928,12 +1928,13 @@ upstream_find_for_netreq(getdns_network_req *netreq)
static int
fallback_on_write(getdns_network_req *netreq)
{
uint64_t now_ms = 0;
/* Deal with UDP one day*/
DEBUG_STUB("%s %-35s: MSG: %p FALLING BACK \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq);
/* Try to find a fallback transport*/
getdns_return_t result = _getdns_submit_stub_request(netreq);
getdns_return_t result = _getdns_submit_stub_request(netreq, &now_ms);
if (result != GETDNS_RETURN_GOOD)
return STUB_TCP_ERROR;
@ -1997,8 +1998,8 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
if (upstream->queries_sent == 0) {
/* Set a timeout on the upstream so we can catch failed setup*/
upstream->event.timeout_cb = upstream_setup_timeout_cb;
GETDNS_SCHEDULE_EVENT(upstream->loop,
upstream->fd, netreq->owner->context->timeout / 2,
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
_getdns_ms_until_expiry(netreq->owner->expires)/2,
&upstream->event);
} else {
GETDNS_SCHEDULE_EVENT(upstream->loop,
@ -2027,7 +2028,7 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
}
getdns_return_t
_getdns_submit_stub_request(getdns_network_req *netreq)
_getdns_submit_stub_request(getdns_network_req *netreq, uint64_t *now_ms)
{
DEBUG_STUB("%s %-35s: MSG: %p TYPE: %d\n", STUB_DEBUG_ENTRY, __FUNC__,
(void*)netreq, netreq->request_type);
@ -2046,8 +2047,8 @@ _getdns_submit_stub_request(getdns_network_req *netreq)
case GETDNS_TRANSPORT_UDP:
netreq->fd = fd;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
GETDNS_SCHEDULE_EVENT(
dnsreq->loop, netreq->fd, dnsreq->context->timeout,
GETDNS_SCHEDULE_EVENT(dnsreq->loop, netreq->fd,
_getdns_ms_until_expiry2(dnsreq->expires, now_ms),
getdns_eventloop_event_init(&netreq->event, netreq,
NULL, stub_udp_write_cb, stub_timeout_cb));
return GETDNS_RETURN_GOOD;
@ -2121,7 +2122,7 @@ _getdns_submit_stub_request(getdns_network_req *netreq)
*/
GETDNS_SCHEDULE_EVENT(
dnsreq->loop, -1,
dnsreq->context->timeout,
_getdns_ms_until_expiry2(dnsreq->expires, now_ms),
getdns_eventloop_event_init(
&netreq->event, netreq, NULL, NULL,
stub_timeout_cb));

View File

@ -37,7 +37,8 @@
#include "getdns/getdns.h"
#include "types-internal.h"
getdns_return_t _getdns_submit_stub_request(getdns_network_req *netreq);
getdns_return_t _getdns_submit_stub_request(
getdns_network_req *netreq, uint64_t *now_ms);
void _getdns_cancel_stub_request(getdns_network_req *netreq);

View File

@ -338,6 +338,11 @@ typedef struct getdns_dns_req {
/* the transaction id */
getdns_transaction_t trans_id;
/* Absolute time (in miliseconds since epoch),
* after which this dns request is expired; i.e. timed out
*/
uint64_t expires;
/* for scheduling timeouts when using libunbound */
getdns_eventloop_event timeout;
@ -408,7 +413,7 @@ extern getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks;
/* dns request utils */
getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions);
const char *name, uint16_t request_type, getdns_dict *extensions, uint64_t *now_ms);
void _getdns_dns_req_free(getdns_dns_req * req);

View File

@ -198,5 +198,25 @@ INLINE void _dname_canonicalize2(uint8_t *dname)
_dname_canonicalize(dname, dname);
}
INLINE uint64_t _getdns_get_now_ms()
{
struct timeval tv;
(void) gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
INLINE uint64_t _getdns_ms_until_expiry(uint64_t expires)
{
uint64_t now_ms = _getdns_get_now_ms();
return now_ms >= expires ? 0 : expires - now_ms;
}
INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms)
{
if (*now_ms == 0) *now_ms = _getdns_get_now_ms();
return *now_ms >= expires ? 0 : expires - *now_ms;
}
#endif
/* util-internal.h */