Fix timeout handling & simultaneous 4 & 6 requests

Simultaneous 4 & 6 requests for async only.
Also get rid of the postponing of callbacks hack.
This commit is contained in:
Willem Toorop 2014-10-07 15:52:41 +02:00
parent 65db103c6d
commit a21895d145
4 changed files with 68 additions and 113 deletions

View File

@ -530,6 +530,15 @@ void getdns_handle_timeouts(struct getdns_event_base* base,
/** call select and callbacks for that */ /** call select and callbacks for that */
int getdns_handle_select(struct getdns_event_base* base, struct timeval* wait); int getdns_handle_select(struct getdns_event_base* base, struct timeval* wait);
int
getdns_mini_event_settime(getdns_mini_event_extension *e)
{
if (gettimeofday(e->base->time_tv, NULL) < 0)
return -1;
*e->base->time_secs = (time_t)e->base->time_tv->tv_sec;
return 0;
}
static void static void
getdns_mini_event_timeout_cb(int fd, short bits, void *arg) getdns_mini_event_timeout_cb(int fd, short bits, void *arg)
{ {
@ -552,6 +561,8 @@ getdns_mini_event_schedule_timeout(getdns_context *context, void *ext,
timeout_data->extension_timer = ev; timeout_data->extension_timer = ev;
getdns_event_set(ev, -1, EV_TIMEOUT, getdns_mini_event_timeout_cb, getdns_event_set(ev, -1, EV_TIMEOUT, getdns_mini_event_timeout_cb,
timeout_data); timeout_data);
(void) getdns_mini_event_settime(e);
(void) getdns_event_base_set(e->base, ev); (void) getdns_event_base_set(e->base, ev);
(void) getdns_event_add(ev, &tv); (void) getdns_event_add(ev, &tv);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -1539,13 +1550,10 @@ cancel_dns_req(getdns_dns_req * req)
{ {
getdns_network_req *netreq = req->first_req; getdns_network_req *netreq = req->first_req;
while (netreq) { while (netreq) {
if (netreq->state == NET_REQ_IN_FLIGHT) { if (netreq->unbound_id != -1) {
/* for ev based ub, this should always prevent ub_cancel(req->context->unbound_ctx,
* the callback from firing */ netreq->unbound_id);
ub_cancel(req->context->unbound_ctx, netreq->unbound_id); netreq->unbound_id = -1;
netreq->state = NET_REQ_CANCELED;
} else if (netreq->state == NET_REQ_NOT_SENT) {
netreq->state = NET_REQ_CANCELED;
} }
netreq = netreq->next; netreq = netreq->next;
} }
@ -1919,22 +1927,18 @@ uint32_t
getdns_context_get_num_pending_requests(struct getdns_context* context, getdns_context_get_num_pending_requests(struct getdns_context* context,
struct timeval* next_timeout) struct timeval* next_timeout)
{ {
static struct timeval dummy = { 0, 0 };
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (context->outbound_requests->count && if (context->outbound_requests->count &&
context->extension == (void *)&context->mini_event_extension.ext) { context->extension == (void *)&context->mini_event_extension.ext &&
getdns_mini_event_settime(&context->mini_event_extension) == 0)
struct getdns_event_base *base = getdns_handle_timeouts(
context->mini_event_extension.base; context->mini_event_extension.base,
context->mini_event_extension.base->time_tv,
if (gettimeofday(base->time_tv, NULL) >= 0) {
struct timeval dummy;
*base->time_secs = (time_t) base->time_tv->tv_sec;
getdns_handle_timeouts(base, base->time_tv,
next_timeout ? next_timeout : &dummy); next_timeout ? next_timeout : &dummy);
}
}
return context->outbound_requests->count; return context->outbound_requests->count;
} }

View File

@ -51,7 +51,6 @@
/* declarations */ /* declarations */
static void ub_resolve_callback(void* mydata, int err, struct ub_result* result); static void ub_resolve_callback(void* mydata, int err, struct ub_result* result);
static getdns_return_t ub_resolve_timeout(void *arg); static getdns_return_t ub_resolve_timeout(void *arg);
static getdns_return_t ub_local_resolve_timeout(void *arg);
static void handle_network_request_error(getdns_network_req * netreq, int err); static void handle_network_request_error(getdns_network_req * netreq, int err);
static void handle_dns_request_complete(getdns_dns_req * dns_req); static void handle_dns_request_complete(getdns_dns_req * dns_req);
@ -72,27 +71,6 @@ ub_resolve_timeout(void *arg)
return getdns_context_request_timed_out(dns_req); return getdns_context_request_timed_out(dns_req);
} }
static getdns_return_t
ub_local_resolve_timeout(void *arg)
{
netreq_cb_data *cb_data = (netreq_cb_data *) arg;
/* cleanup the local timer here since the memory may be
* invalid after calling ub_resolve_callback
*/
getdns_dns_req *dnsreq = cb_data->netreq->owner;
/* clear the timeout */
getdns_context_clear_timeout(dnsreq->context, &dnsreq->local_timeout);
/* just call ub_resolve_callback */
ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->ub_res);
/* cleanup the state */
GETDNS_FREE(dnsreq->my_mf, cb_data);
return GETDNS_RETURN_GOOD;
}
void priv_getdns_call_user_callback(getdns_dns_req *dns_req, void priv_getdns_call_user_callback(getdns_dns_req *dns_req,
struct getdns_dict *response) struct getdns_dict *response)
{ {
@ -139,7 +117,6 @@ submit_network_request(getdns_network_req * netreq)
netreq, netreq,
ub_resolve_callback, ub_resolve_callback,
&(netreq->unbound_id)); &(netreq->unbound_id));
netreq->state = NET_REQ_IN_FLIGHT;
return r; return r;
} }
@ -149,48 +126,29 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
// char *bogus) // char *bogus)
{ {
getdns_network_req *netreq = (getdns_network_req *) arg; getdns_network_req *netreq = (getdns_network_req *) arg;
getdns_dns_req *dnsreq = netreq->owner;
netreq->state = NET_REQ_FINISHED;
if (err != 0) { if (err != 0) {
handle_network_request_error(netreq, err); handle_network_request_error(netreq, err);
return; return;
} }
/* if netreq->state == NET_REQ_NOT_SENT here, that implies /* parse */
* that ub called us back immediately - probably from a local file. if (getdns_apply_network_result(netreq, ub_res)) {
* This most likely means that getdns_general has not returned ub_resolve_free(ub_res);
*/ handle_network_request_error(netreq, err);
if (netreq->state == NET_REQ_NOT_SENT) {
/* just do a very short timer since this was called immediately.
* we can make this less hacky, but it gets interesting when multiple
* netreqs need to be issued and some resolve immediately vs. not.
*/
getdns_dns_req *dnsreq = netreq->owner;
netreq_cb_data *cb_data = GETDNS_MALLOC(dnsreq->my_mf, netreq_cb_data);
cb_data->netreq = netreq;
cb_data->err = err;
cb_data->ub_res = ub_res;
getdns_context_schedule_timeout(dnsreq->context, 1,
ub_local_resolve_timeout, cb_data, &dnsreq->local_timeout);
return; return;
} }
netreq->state = NET_REQ_FINISHED;
/* parse */
/* TODO: optimize */
getdns_return_t r = getdns_apply_network_result(netreq, ub_res);
ub_resolve_free(ub_res); ub_resolve_free(ub_res);
if (r != GETDNS_RETURN_GOOD) {
handle_network_request_error(netreq, err); netreq = dnsreq->first_req;
} else { while (netreq) {
/* is this the last request */ if (netreq->state != NET_REQ_FINISHED &&
if (!netreq->next) { netreq->state != NET_REQ_CANCELED)
/* finished */ return;
handle_dns_request_complete(netreq->owner); netreq = netreq->next;
} else {
/* not finished - update to next request and ship it */
getdns_dns_req *dns_req = netreq->owner;
dns_req->current_req = netreq->next;
submit_network_request(netreq->next);
}
} }
handle_dns_request_complete(dnsreq);
} /* ub_resolve_callback */ } /* ub_resolve_callback */
getdns_return_t getdns_return_t
@ -204,7 +162,8 @@ getdns_general_ub(struct getdns_context *context,
int usenamespaces) int usenamespaces)
{ {
getdns_return_t gr; getdns_return_t gr;
int r; int r = GETDNS_RETURN_GOOD;
getdns_network_req *netreq;
if (!name) { if (!name) {
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
@ -241,9 +200,11 @@ getdns_general_ub(struct getdns_context *context,
ub_resolve_timeout, req, &req->timeout); ub_resolve_timeout, req, &req->timeout);
/* issue the first network req */ /* issue the first network req */
netreq = req->first_req;
r = submit_network_request(req->first_req); while (r == GETDNS_RETURN_GOOD && netreq) {
r = submit_network_request(netreq);
netreq = netreq->next;
}
if (r != 0) { if (r != 0) {
/* clean up the request */ /* clean up the request */
getdns_context_clear_outbound_request(req); getdns_context_clear_outbound_request(req);

View File

@ -36,6 +36,7 @@
#include "config.h" #include "config.h"
#include "types-internal.h" #include "types-internal.h"
#include "util-internal.h" #include "util-internal.h"
#include "gldns/rrdef.h"
void void
network_req_free(getdns_network_req * net_req) network_req_free(getdns_network_req * net_req)
@ -94,7 +95,6 @@ dns_req_free(getdns_dns_req * req)
net_req = next; net_req = next;
} }
getdns_context_clear_timeout(context, &req->local_timeout);
getdns_context_clear_timeout(context, &req->timeout); getdns_context_clear_timeout(context, &req->timeout);
/* free strduped name */ /* free strduped name */
@ -110,9 +110,7 @@ dns_req_new(struct getdns_context *context,
getdns_dns_req *result = NULL; getdns_dns_req *result = NULL;
getdns_network_req *req = NULL; getdns_network_req *req = NULL;
uint32_t klass = GLDNS_RR_CLASS_IN;
getdns_return_t r;
uint32_t klass;
result = GETDNS_MALLOC(context->mf, getdns_dns_req); result = GETDNS_MALLOC(context->mf, getdns_dns_req);
if (result == NULL) { if (result == NULL) {
@ -133,13 +131,9 @@ dns_req_new(struct getdns_context *context,
result->user_pointer = NULL; result->user_pointer = NULL;
result->user_callback = NULL; result->user_callback = NULL;
memset(&result->timeout, 0, sizeof(getdns_timeout_data_t)); memset(&result->timeout, 0, sizeof(getdns_timeout_data_t));
memset(&result->local_timeout, 0, sizeof(getdns_timeout_data_t));
/* check the specify_class extension */ /* check the specify_class extension */
if ((r = getdns_dict_get_int(extensions, "specify_class", &klass)) (void) getdns_dict_get_int(extensions, "specify_class", &klass);
!= GETDNS_RETURN_GOOD) {
klass = LDNS_RR_CLASS_IN;
}
/* create the requests */ /* create the requests */
req = network_req_new(result, request_type, klass, extensions); req = network_req_new(result, request_type, klass, extensions);
@ -156,13 +150,11 @@ dns_req_new(struct getdns_context *context,
(request_type == GETDNS_RRTYPE_A || (request_type == GETDNS_RRTYPE_A ||
request_type == GETDNS_RRTYPE_AAAA)) { request_type == GETDNS_RRTYPE_AAAA)) {
uint16_t next_req_type = uint16_t next_req_type = (request_type == GETDNS_RRTYPE_A) ?
(request_type == GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A;
GETDNS_RRTYPE_A) ? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A;
getdns_network_req *next_req = network_req_new(result, getdns_network_req *next_req = network_req_new(result,
next_req_type, next_req_type, LDNS_RR_CLASS_IN, extensions);
LDNS_RR_CLASS_IN,
extensions);
if (!next_req) { if (!next_req) {
dns_req_free(result); dns_req_free(result);
return NULL; return NULL;

View File

@ -199,8 +199,6 @@ typedef struct getdns_dns_req
getdns_transaction_t trans_id; getdns_transaction_t trans_id;
getdns_timeout_data_t timeout; getdns_timeout_data_t timeout;
/* Hack to prevent immediate callbacks */
getdns_timeout_data_t local_timeout;
/* dnssec status */ /* dnssec status */
int return_dnssec_status; int return_dnssec_status;