mirror of https://github.com/getdnsapi/getdns.git
Timeouts via default mini_event extension
This commit is contained in:
parent
58b3e553de
commit
54e0b42dcd
404
src/context.c
404
src/context.c
|
@ -65,7 +65,6 @@ getdns_return_t destroy_local_hosts(struct getdns_context *context);
|
||||||
static struct getdns_list *create_default_root_servers(void);
|
static struct getdns_list *create_default_root_servers(void);
|
||||||
static getdns_return_t set_os_defaults(struct getdns_context *);
|
static getdns_return_t set_os_defaults(struct getdns_context *);
|
||||||
static int transaction_id_cmp(const void *, const void *);
|
static int transaction_id_cmp(const void *, const void *);
|
||||||
static int timeout_cmp(const void *, const void *);
|
|
||||||
static int local_host_cmp(const void *, const void *);
|
static int local_host_cmp(const void *, const void *);
|
||||||
static void dispatch_updated(struct getdns_context *, uint16_t);
|
static void dispatch_updated(struct getdns_context *, uint16_t);
|
||||||
static void cancel_dns_req(getdns_dns_req *);
|
static void cancel_dns_req(getdns_dns_req *);
|
||||||
|
@ -486,35 +485,6 @@ transaction_id_cmp(const void *id1, const void *id2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
timeout_cmp(const void *to1, const void *to2)
|
|
||||||
{
|
|
||||||
if (to1 == NULL && to2 == NULL) {
|
|
||||||
return 0;
|
|
||||||
} else if (to1 == NULL && to2 != NULL) {
|
|
||||||
return 1;
|
|
||||||
} else if (to1 != NULL && to2 == NULL) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
const getdns_timeout_data_t* t1 = (const getdns_timeout_data_t*) to1;
|
|
||||||
const getdns_timeout_data_t* t2 = (const getdns_timeout_data_t*) to2;
|
|
||||||
if (t1->timeout_time.tv_sec < t2->timeout_time.tv_sec) {
|
|
||||||
return -1;
|
|
||||||
} else if (t1->timeout_time.tv_sec > t2->timeout_time.tv_sec) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
/* compare usec.. */
|
|
||||||
if (t1->timeout_time.tv_usec < t2->timeout_time.tv_usec) {
|
|
||||||
return -1;
|
|
||||||
} else if (t1->timeout_time.tv_usec > t2->timeout_time.tv_usec) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return transaction_id_cmp(&t1->transaction_id, &t2->transaction_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
local_host_cmp(const void *id1, const void *id2)
|
local_host_cmp(const void *id1, const void *id2)
|
||||||
{
|
{
|
||||||
|
@ -547,6 +517,99 @@ create_ldns_rbtree(getdns_context * context,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
******************************************************************************
|
||||||
|
*****
|
||||||
|
***** Start of mini_event extension
|
||||||
|
***** TODO: Move to own source file
|
||||||
|
*****/
|
||||||
|
|
||||||
|
/** call timeouts handlers, and return how long to wait for next one or -1 */
|
||||||
|
void getdns_handle_timeouts(struct getdns_event_base* base,
|
||||||
|
struct timeval* now, struct timeval* wait);
|
||||||
|
/** call select and callbacks for that */
|
||||||
|
int getdns_handle_select(struct getdns_event_base* base, struct timeval* wait);
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
getdns_mini_event_cleanup(getdns_context *context, void *ext)
|
||||||
|
{
|
||||||
|
getdns_mini_event_extension *e = (getdns_mini_event_extension *)ext;
|
||||||
|
|
||||||
|
/* TODO: Cleanup all events? Maybe not... */
|
||||||
|
getdns_event_base_free(e->base);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
getdns_mini_event_timeout_cb(int fd, short bits, void *arg)
|
||||||
|
{
|
||||||
|
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*)arg;
|
||||||
|
timeout_data->callback(timeout_data->userarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
getdns_mini_event_schedule_timeout(getdns_context *context, void *ext,
|
||||||
|
uint64_t timeout, getdns_timeout_data_t *timeout_data)
|
||||||
|
{
|
||||||
|
getdns_mini_event_extension *e = (getdns_mini_event_extension *)ext;
|
||||||
|
struct timeval tv;
|
||||||
|
struct getdns_event *ev;
|
||||||
|
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
|
||||||
|
ev = GETDNS_MALLOC(context->mf, struct getdns_event);
|
||||||
|
timeout_data->extension_timer = ev;
|
||||||
|
getdns_event_set(ev, -1, EV_TIMEOUT, getdns_mini_event_timeout_cb,
|
||||||
|
timeout_data);
|
||||||
|
(void) getdns_event_base_set(e->base, ev);
|
||||||
|
(void) getdns_event_add(ev, &tv);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
getdns_mini_event_clear_timeout(getdns_context *context, void *ext, void *timer)
|
||||||
|
{
|
||||||
|
/* getdns_mini_event_extension *e = (getdns_mini_event_extension *)ext;
|
||||||
|
*/
|
||||||
|
struct getdns_event *ev = (struct getdns_event *)timer;
|
||||||
|
|
||||||
|
(void) getdns_event_del(ev);
|
||||||
|
GETDNS_FREE(context->mf, ev);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getdns_return_t
|
||||||
|
getdns_mini_event_request_count_changed(getdns_context *context,
|
||||||
|
uint32_t request_count, void *ext)
|
||||||
|
{
|
||||||
|
getdns_mini_event_extension *e = (getdns_mini_event_extension *)ext;
|
||||||
|
|
||||||
|
if (request_count == 0)
|
||||||
|
(void) getdns_event_del(&e->ub_event);
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
getdns_return_t
|
||||||
|
getdns_mini_event_extension_init(getdns_mini_event_extension *e)
|
||||||
|
{
|
||||||
|
e->base = getdns_event_init(&e->time_secs, &e->time_tv);
|
||||||
|
if (!e->base)
|
||||||
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
e->ub_event.ev_fd = -1;
|
||||||
|
e->ext.cleanup_data = getdns_mini_event_cleanup;
|
||||||
|
e->ext.schedule_timeout = getdns_mini_event_schedule_timeout;
|
||||||
|
e->ext.clear_timeout = getdns_mini_event_clear_timeout;
|
||||||
|
e->ext.request_count_changed = getdns_mini_event_request_count_changed;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****
|
||||||
|
***** End of mini_event extension
|
||||||
|
*****
|
||||||
|
*****************************************************************************
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* getdns_context_create
|
* getdns_context_create
|
||||||
*
|
*
|
||||||
|
@ -593,8 +656,6 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->resolution_type_set = 0;
|
result->resolution_type_set = 0;
|
||||||
|
|
||||||
result->outbound_requests = create_ldns_rbtree(result, transaction_id_cmp);
|
result->outbound_requests = create_ldns_rbtree(result, transaction_id_cmp);
|
||||||
result->timeouts_by_time = create_ldns_rbtree(result, timeout_cmp);
|
|
||||||
result->timeouts_by_id = create_ldns_rbtree(result, transaction_id_cmp);
|
|
||||||
result->local_hosts = create_ldns_rbtree(result, local_host_cmp);
|
result->local_hosts = create_ldns_rbtree(result, local_host_cmp);
|
||||||
|
|
||||||
|
|
||||||
|
@ -616,8 +677,10 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->edns_version = 0;
|
result->edns_version = 0;
|
||||||
result->edns_do_bit = 1;
|
result->edns_do_bit = 1;
|
||||||
|
|
||||||
result->extension = NULL;
|
result->extension = &result->mini_event_extension.ext;
|
||||||
result->extension_data = NULL;
|
result->extension_data = (void *)&result->mini_event_extension;
|
||||||
|
if (getdns_mini_event_extension_init(&result->mini_event_extension))
|
||||||
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
|
||||||
result->fchg_resolvconf = NULL;
|
result->fchg_resolvconf = NULL;
|
||||||
result->fchg_hosts = NULL;
|
result->fchg_hosts = NULL;
|
||||||
|
@ -634,8 +697,6 @@ getdns_context_create_with_extended_memory_functions(
|
||||||
result->has_ta = priv_getdns_parse_ta_file(NULL, NULL);
|
result->has_ta = priv_getdns_parse_ta_file(NULL, NULL);
|
||||||
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
|
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
|
||||||
if (!result->outbound_requests ||
|
if (!result->outbound_requests ||
|
||||||
!result->timeouts_by_id ||
|
|
||||||
!result->timeouts_by_time ||
|
|
||||||
!result->local_hosts) {
|
!result->local_hosts) {
|
||||||
getdns_context_destroy(result);
|
getdns_context_destroy(result);
|
||||||
return GETDNS_RETURN_MEMORY_ERROR;
|
return GETDNS_RETURN_MEMORY_ERROR;
|
||||||
|
@ -743,10 +804,6 @@ getdns_context_destroy(struct getdns_context *context)
|
||||||
|
|
||||||
if (context->outbound_requests)
|
if (context->outbound_requests)
|
||||||
GETDNS_FREE(context->my_mf, context->outbound_requests);
|
GETDNS_FREE(context->my_mf, context->outbound_requests);
|
||||||
if (context->timeouts_by_id)
|
|
||||||
GETDNS_FREE(context->my_mf, context->timeouts_by_id);
|
|
||||||
if (context->timeouts_by_time)
|
|
||||||
GETDNS_FREE(context->my_mf, context->timeouts_by_time);
|
|
||||||
if (context->local_hosts) {
|
if (context->local_hosts) {
|
||||||
ldns_traverse_postorder(context->local_hosts,
|
ldns_traverse_postorder(context->local_hosts,
|
||||||
destroy_local_host, context);
|
destroy_local_host, context);
|
||||||
|
@ -1833,92 +1890,41 @@ int getdns_context_fd(struct getdns_context* context) {
|
||||||
|
|
||||||
uint32_t
|
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)
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
{
|
||||||
uint32_t r = context->outbound_requests->count;
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
if (r > 0) {
|
|
||||||
if (!context->extension && next_timeout) {
|
if (context->outbound_requests->count &&
|
||||||
/* default is 1 second */
|
context->extension == (void *)&context->mini_event_extension.ext) {
|
||||||
next_timeout->tv_sec = 1;
|
|
||||||
next_timeout->tv_usec = 0;
|
if (gettimeofday(context->mini_event_extension.base->time_tv,
|
||||||
struct timeval now;
|
NULL) >= 0) {
|
||||||
if (gettimeofday(&now, NULL) == 0) {
|
|
||||||
/* get the first timeout */
|
*context->mini_event_extension.base->time_secs =(time_t)
|
||||||
ldns_rbnode_t* first = ldns_rbtree_first(context->timeouts_by_time);
|
context->mini_event_extension.base->time_tv->tv_sec;
|
||||||
if (first) {
|
getdns_handle_timeouts(
|
||||||
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) first->data;
|
context->mini_event_extension.base,
|
||||||
/* subtract next_timeout from now */
|
context->mini_event_extension.base->time_tv,
|
||||||
if (timeout_data->timeout_time.tv_sec > now.tv_sec ||
|
next_timeout);
|
||||||
(timeout_data->timeout_time.tv_sec == now.tv_sec &&
|
}
|
||||||
timeout_data->timeout_time.tv_usec >= now.tv_usec)) {
|
}
|
||||||
next_timeout->tv_sec = timeout_data->timeout_time.tv_sec - now.tv_sec;
|
return context->outbound_requests->count;
|
||||||
if (timeout_data->timeout_time.tv_usec < now.tv_usec) {
|
|
||||||
/* we only enter this condition when timeout_data.tv_sec > now.tv_sec */
|
|
||||||
next_timeout->tv_usec = (timeout_data->timeout_time.tv_usec + 100000) - now.tv_usec;
|
|
||||||
next_timeout->tv_sec--;
|
|
||||||
} else {
|
|
||||||
next_timeout->tv_usec = timeout_data->timeout_time.tv_usec - now.tv_usec;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* timeout passed already */
|
|
||||||
/* usec already 0 per setting default */
|
|
||||||
next_timeout->tv_sec = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process async reqs */
|
/* process async reqs */
|
||||||
getdns_return_t getdns_context_process_async(struct getdns_context* context) {
|
getdns_return_t getdns_context_process_async(struct getdns_context* context)
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
{
|
||||||
context->processing = 1;
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
if (ub_poll(context->unbound_ctx)) {
|
|
||||||
if (ub_process(context->unbound_ctx) != 0) {
|
|
||||||
/* need an async return code? */
|
|
||||||
context->processing = 0;
|
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// reset the processing flag
|
|
||||||
context->processing = 0;
|
|
||||||
if (context->extension != NULL) {
|
|
||||||
/* no need to process timeouts since it is delegated
|
|
||||||
* to the extension */
|
|
||||||
return GETDNS_RETURN_GOOD;
|
|
||||||
}
|
|
||||||
getdns_timeout_data_t key;
|
|
||||||
/* set to 0 so it is the last timeout if we have
|
|
||||||
* two with the same time */
|
|
||||||
key.transaction_id = 0;
|
|
||||||
if (gettimeofday(&key.timeout_time, NULL) != 0) {
|
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
ldns_rbnode_t* next_timeout = ldns_rbtree_first(context->timeouts_by_time);
|
|
||||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
|
||||||
while (next_timeout && r == GETDNS_RETURN_GOOD) {
|
|
||||||
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) next_timeout->data;
|
|
||||||
if (timeout_cmp(timeout_data, &key) > 0) {
|
|
||||||
/* no more timeouts need to be fired. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* get the next_timeout */
|
|
||||||
next_timeout = ldns_rbtree_next(next_timeout);
|
|
||||||
/* delete the node */
|
|
||||||
/* timeout data and the timeouts_by_id node are freed in the clear_timeout */
|
|
||||||
ldns_rbnode_t* to_del = ldns_rbtree_delete(context->timeouts_by_time, timeout_data);
|
|
||||||
if (to_del) {
|
|
||||||
/* should always exist .. */
|
|
||||||
GETDNS_FREE(context->my_mf, to_del);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fire the timeout */
|
context->processing = 1;
|
||||||
r = timeout_data->callback(timeout_data->userarg);
|
if (ub_poll(context->unbound_ctx) && ub_process(context->unbound_ctx)){
|
||||||
}
|
/* need an async return code? */
|
||||||
|
context->processing = 0;
|
||||||
return r;
|
return GETDNS_RETURN_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
// reset the processing flag
|
||||||
|
context->processing = 0;
|
||||||
|
return GETDNS_RETURN_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct timeout_accumulator {
|
typedef struct timeout_accumulator {
|
||||||
|
@ -1951,27 +1957,27 @@ cancel_outstanding_requests(struct getdns_context* context, int fire_callback) {
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_extension_detach_eventloop(struct getdns_context* context)
|
getdns_extension_detach_eventloop(struct getdns_context* context)
|
||||||
{
|
{
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
|
||||||
getdns_return_t r = GETDNS_RETURN_GOOD;
|
getdns_return_t r = GETDNS_RETURN_GOOD;
|
||||||
if (context->extension) {
|
|
||||||
/* When called from within a callback, do not execute pending
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
* context destroys.
|
|
||||||
* The (other) callback handler will handle it.
|
/* When called from within a callback, do not execute pending
|
||||||
*
|
* context destroys.
|
||||||
* ( because callbacks occur in cancel_outstanding_requests,
|
* The (other) callback handler will handle it.
|
||||||
* and they may destroy the context )
|
*
|
||||||
*/
|
* ( because callbacks occur in cancel_outstanding_requests,
|
||||||
context->processing = 1;
|
* and they may destroy the context )
|
||||||
/* cancel all outstanding requests */
|
*/
|
||||||
cancel_outstanding_requests(context, 1);
|
context->processing = 1;
|
||||||
r = context->extension->cleanup_data(context,
|
/* cancel all outstanding requests */
|
||||||
context->extension_data);
|
cancel_outstanding_requests(context, 1);
|
||||||
if (r == GETDNS_RETURN_GOOD) {
|
r = context->extension->cleanup_data(context,
|
||||||
context->extension = NULL;
|
context->extension_data);
|
||||||
context->extension_data = NULL;
|
if (r == GETDNS_RETURN_GOOD) {
|
||||||
}
|
context->extension = NULL;
|
||||||
context->processing = 0;
|
context->extension_data = NULL;
|
||||||
}
|
}
|
||||||
|
context->processing = 0;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1991,101 +1997,37 @@ getdns_extension_set_eventloop(struct getdns_context* context,
|
||||||
}
|
}
|
||||||
|
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_schedule_timeout(struct getdns_context* context,
|
getdns_context_schedule_timeout(getdns_context* context, uint64_t timeout,
|
||||||
getdns_transaction_t id, uint64_t timeout, getdns_timeout_callback callback,
|
getdns_timeout_callback callback, void* userarg,
|
||||||
void* userarg) {
|
getdns_timeout_data_t *timeout_data)
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
{
|
||||||
RETURN_IF_NULL(callback, GETDNS_RETURN_INVALID_PARAMETER);
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
getdns_return_t result;
|
RETURN_IF_NULL(callback, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
/* create a timeout */
|
RETURN_IF_NULL(timeout_data, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
getdns_timeout_data_t* timeout_data = GETDNS_MALLOC(context->my_mf, getdns_timeout_data_t);
|
|
||||||
if (!timeout_data) {
|
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
timeout_data->context = context;
|
|
||||||
timeout_data->transaction_id = id;
|
|
||||||
timeout_data->callback = callback;
|
|
||||||
timeout_data->userarg = userarg;
|
|
||||||
timeout_data->extension_timer = NULL;
|
|
||||||
|
|
||||||
/* insert into transaction tree */
|
/* Initialize timeout_data struct */
|
||||||
ldns_rbnode_t *node = GETDNS_MALLOC(context->my_mf, ldns_rbnode_t);
|
timeout_data->context = context;
|
||||||
if (!node) {
|
timeout_data->callback = callback;
|
||||||
GETDNS_FREE(context->my_mf, timeout_data);
|
timeout_data->userarg = userarg;
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
timeout_data->extension_timer = NULL;
|
||||||
}
|
|
||||||
node->key = &(timeout_data->transaction_id);
|
|
||||||
node->data = timeout_data;
|
|
||||||
node->left = NULL;
|
|
||||||
node->right = NULL;
|
|
||||||
if (!ldns_rbtree_insert(context->timeouts_by_id, node)) {
|
|
||||||
/* free the node */
|
|
||||||
GETDNS_FREE(context->my_mf, timeout_data);
|
|
||||||
GETDNS_FREE(context->my_mf, node);
|
|
||||||
return GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context->extension) {
|
return context->extension->schedule_timeout(context,
|
||||||
result = context->extension->schedule_timeout(context, context->extension_data,
|
context->extension_data, timeout, timeout_data);
|
||||||
timeout, timeout_data);
|
|
||||||
} else {
|
|
||||||
result = GETDNS_RETURN_GENERIC_ERROR;
|
|
||||||
if (gettimeofday(&timeout_data->timeout_time, NULL) == 0) {
|
|
||||||
/* timeout is in millis */
|
|
||||||
uint16_t num_secs = timeout / 1000;
|
|
||||||
uint16_t num_usecs = (timeout % 1000) * 1000;
|
|
||||||
timeout_data->timeout_time.tv_usec += num_usecs;
|
|
||||||
/* overflow check */
|
|
||||||
if (timeout_data->timeout_time.tv_usec > 1000000) {
|
|
||||||
timeout_data->timeout_time.tv_usec -= 1000000;
|
|
||||||
num_secs++;
|
|
||||||
}
|
|
||||||
timeout_data->timeout_time.tv_sec += num_secs;
|
|
||||||
|
|
||||||
ldns_rbnode_t* id_node = GETDNS_MALLOC(context->my_mf, ldns_rbnode_t);
|
|
||||||
if (id_node) {
|
|
||||||
id_node->key = timeout_data;
|
|
||||||
id_node->data = timeout_data;
|
|
||||||
id_node->left = NULL;
|
|
||||||
id_node->right = NULL;
|
|
||||||
if (!ldns_rbtree_insert(context->timeouts_by_time, id_node)) {
|
|
||||||
GETDNS_FREE(context->my_mf, id_node);
|
|
||||||
} else {
|
|
||||||
result = GETDNS_RETURN_GOOD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result != GETDNS_RETURN_GOOD) {
|
|
||||||
GETDNS_FREE(context->my_mf, timeout_data);
|
|
||||||
GETDNS_FREE(context->my_mf, node);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getdns_return_t
|
getdns_return_t
|
||||||
getdns_context_clear_timeout(struct getdns_context* context,
|
getdns_context_clear_timeout(getdns_context* context,
|
||||||
getdns_transaction_t id) {
|
getdns_timeout_data_t *timeout_data)
|
||||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
{
|
||||||
/* find the timeout_data by id */
|
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
ldns_rbnode_t* node = ldns_rbtree_delete(context->timeouts_by_id, &id);
|
RETURN_IF_NULL(timeout_data, GETDNS_RETURN_INVALID_PARAMETER);
|
||||||
if (!node) {
|
RETURN_IF_NULL(timeout_data->context, GETDNS_RETURN_GOOD);
|
||||||
return GETDNS_RETURN_UNKNOWN_TRANSACTION;
|
|
||||||
}
|
context->extension->clear_timeout(context,
|
||||||
getdns_timeout_data_t* timeout_data = (getdns_timeout_data_t*) node->data;
|
context->extension_data, timeout_data->extension_timer);
|
||||||
GETDNS_FREE(context->my_mf, node);
|
timeout_data->context = NULL;
|
||||||
if (context->extension) {
|
|
||||||
context->extension->clear_timeout(context, context->extension_data,
|
return GETDNS_RETURN_GOOD;
|
||||||
timeout_data->extension_timer);
|
|
||||||
} else {
|
|
||||||
/* make sure it is removed from the timeout node */
|
|
||||||
ldns_rbnode_t* to_del = ldns_rbtree_delete(context->timeouts_by_time, timeout_data);
|
|
||||||
if (to_del) {
|
|
||||||
GETDNS_FREE(context->my_mf, to_del);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GETDNS_FREE(context->my_mf, timeout_data);
|
|
||||||
return GETDNS_RETURN_GOOD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
|
|
|
@ -39,7 +39,9 @@
|
||||||
|
|
||||||
#include "getdns/getdns.h"
|
#include "getdns/getdns.h"
|
||||||
#include "getdns/getdns_extra.h"
|
#include "getdns/getdns_extra.h"
|
||||||
|
#include "config.h"
|
||||||
#include "types-internal.h"
|
#include "types-internal.h"
|
||||||
|
#include "util/mini_event.h"
|
||||||
|
|
||||||
struct getdns_dns_req;
|
struct getdns_dns_req;
|
||||||
struct ldns_rbtree_t;
|
struct ldns_rbtree_t;
|
||||||
|
@ -80,6 +82,14 @@ typedef struct getdns_upstreams {
|
||||||
struct getdns_upstream upstreams[];
|
struct getdns_upstream upstreams[];
|
||||||
} getdns_upstreams;
|
} getdns_upstreams;
|
||||||
|
|
||||||
|
typedef struct getdns_mini_event_extention {
|
||||||
|
getdns_eventloop_extension ext;
|
||||||
|
time_t time_secs;
|
||||||
|
struct timeval time_tv;
|
||||||
|
struct getdns_event_base *base;
|
||||||
|
struct getdns_event ub_event;
|
||||||
|
} getdns_mini_event_extension;
|
||||||
|
|
||||||
struct getdns_context {
|
struct getdns_context {
|
||||||
/* Context values */
|
/* Context values */
|
||||||
getdns_resolution_t resolution_type;
|
getdns_resolution_t resolution_type;
|
||||||
|
@ -139,13 +149,8 @@ struct getdns_context {
|
||||||
*/
|
*/
|
||||||
void* extension_data;
|
void* extension_data;
|
||||||
|
|
||||||
/*
|
/* The default extension */
|
||||||
* Timeout info one tree to manage timeout data
|
getdns_mini_event_extension mini_event_extension;
|
||||||
* keyed by transaction id. Second to manage by
|
|
||||||
* timeout time (ascending)
|
|
||||||
*/
|
|
||||||
struct ldns_rbtree_t *timeouts_by_id;
|
|
||||||
struct ldns_rbtree_t *timeouts_by_time;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* state data used to detect changes to the system config files
|
* state data used to detect changes to the system config files
|
||||||
|
@ -191,12 +196,12 @@ void getdns_bindata_destroy(
|
||||||
struct getdns_bindata *bindata);
|
struct getdns_bindata *bindata);
|
||||||
|
|
||||||
/* timeout scheduling */
|
/* timeout scheduling */
|
||||||
getdns_return_t getdns_context_schedule_timeout(struct getdns_context* context,
|
getdns_return_t getdns_context_schedule_timeout(getdns_context* context,
|
||||||
getdns_transaction_t id, uint64_t timeout, getdns_timeout_callback callback,
|
uint64_t timeout, getdns_timeout_callback callback, void* userarg,
|
||||||
void* userarg);
|
getdns_timeout_data_t *init_to_track);
|
||||||
|
|
||||||
getdns_return_t getdns_context_clear_timeout(struct getdns_context* context,
|
getdns_return_t getdns_context_clear_timeout(getdns_context* context,
|
||||||
getdns_transaction_t id);
|
getdns_timeout_data_t *timeout_data);
|
||||||
|
|
||||||
/* perform name resolution in /etc/hosts */
|
/* perform name resolution in /etc/hosts */
|
||||||
getdns_return_t getdns_context_local_namespace_resolve(getdns_dns_req* req,
|
getdns_return_t getdns_context_local_namespace_resolve(getdns_dns_req* req,
|
||||||
|
|
|
@ -83,8 +83,7 @@ ub_local_resolve_timeout(void *arg)
|
||||||
getdns_dns_req *dnsreq = cb_data->netreq->owner;
|
getdns_dns_req *dnsreq = cb_data->netreq->owner;
|
||||||
/* clear the timeout */
|
/* clear the timeout */
|
||||||
|
|
||||||
getdns_context_clear_timeout(dnsreq->context, dnsreq->local_timeout_id);
|
getdns_context_clear_timeout(dnsreq->context, &dnsreq->local_timeout);
|
||||||
dnsreq->local_timeout_id = 0;
|
|
||||||
|
|
||||||
/* just call ub_resolve_callback */
|
/* just call ub_resolve_callback */
|
||||||
ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->ub_res);
|
ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->ub_res);
|
||||||
|
@ -169,10 +168,8 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
|
||||||
cb_data->err = err;
|
cb_data->err = err;
|
||||||
cb_data->ub_res = ub_res;
|
cb_data->ub_res = ub_res;
|
||||||
|
|
||||||
dnsreq->local_timeout_id = ldns_get_random();
|
getdns_context_schedule_timeout(dnsreq->context, 1,
|
||||||
|
ub_local_resolve_timeout, cb_data, &dnsreq->local_timeout);
|
||||||
getdns_context_schedule_timeout(dnsreq->context,
|
|
||||||
dnsreq->local_timeout_id, 1, ub_local_resolve_timeout, cb_data);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
netreq->state = NET_REQ_FINISHED;
|
netreq->state = NET_REQ_FINISHED;
|
||||||
|
@ -240,8 +237,8 @@ getdns_general_ub(struct getdns_context *context,
|
||||||
// req->ev_base = ev_base;
|
// req->ev_base = ev_base;
|
||||||
// req->timeout = evtimer_new(ev_base, ub_resolve_timeout, req);
|
// req->timeout = evtimer_new(ev_base, ub_resolve_timeout, req);
|
||||||
/* schedule the timeout */
|
/* schedule the timeout */
|
||||||
getdns_context_schedule_timeout(context, req->trans_id,
|
getdns_context_schedule_timeout(context, context->timeout,
|
||||||
context->timeout, ub_resolve_timeout, req);
|
ub_resolve_timeout, req, &req->timeout);
|
||||||
|
|
||||||
/* issue the first network req */
|
/* issue the first network req */
|
||||||
|
|
||||||
|
|
|
@ -94,15 +94,11 @@ dns_req_free(getdns_dns_req * req)
|
||||||
net_req = next;
|
net_req = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->local_timeout_id != 0) {
|
getdns_context_clear_timeout(context, &req->local_timeout);
|
||||||
getdns_context_clear_timeout(context, req->local_timeout_id);
|
getdns_context_clear_timeout(context, &req->timeout);
|
||||||
}
|
|
||||||
|
|
||||||
getdns_context_clear_timeout(context, req->trans_id);
|
|
||||||
|
|
||||||
/* free strduped name */
|
/* free strduped name */
|
||||||
GETDNS_FREE(req->my_mf, req->name);
|
GETDNS_FREE(req->my_mf, req->name);
|
||||||
|
|
||||||
GETDNS_FREE(req->my_mf, req);
|
GETDNS_FREE(req->my_mf, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +132,8 @@ dns_req_new(struct getdns_context *context,
|
||||||
/* will be set by caller */
|
/* will be set by caller */
|
||||||
result->user_pointer = NULL;
|
result->user_pointer = NULL;
|
||||||
result->user_callback = NULL;
|
result->user_callback = NULL;
|
||||||
result->local_timeout_id = 0;
|
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))
|
if ((r = getdns_dict_get_int(extensions, "specify_class", &klass))
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <ldns/ldns.h>
|
#include <ldns/ldns.h>
|
||||||
#include "getdns/getdns.h"
|
#include "getdns/getdns.h"
|
||||||
|
#include "getdns/getdns_extra.h"
|
||||||
struct getdns_context;
|
struct getdns_context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,7 +173,6 @@ typedef struct getdns_network_req
|
||||||
*/
|
*/
|
||||||
typedef struct getdns_dns_req
|
typedef struct getdns_dns_req
|
||||||
{
|
{
|
||||||
|
|
||||||
/* name */
|
/* name */
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
@ -198,14 +198,15 @@ typedef struct getdns_dns_req
|
||||||
/* the transaction id */
|
/* the transaction id */
|
||||||
getdns_transaction_t trans_id;
|
getdns_transaction_t trans_id;
|
||||||
|
|
||||||
/* local timeout id */
|
getdns_timeout_data_t timeout;
|
||||||
getdns_transaction_t local_timeout_id;
|
/* Hack to prevent immediate callbacks */
|
||||||
|
getdns_timeout_data_t local_timeout;
|
||||||
|
|
||||||
/* dnssec status */
|
/* dnssec status */
|
||||||
int return_dnssec_status;
|
int return_dnssec_status;
|
||||||
|
|
||||||
/* mem funcs */
|
/* mem funcs */
|
||||||
struct mem_funcs my_mf;
|
struct mem_funcs my_mf;
|
||||||
|
|
||||||
} getdns_dns_req;
|
} getdns_dns_req;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,22 @@ cd ub
|
||||||
for f in mini_event.c mini_event.h rbtree.c rbtree.h
|
for f in mini_event.c mini_event.h rbtree.c rbtree.h
|
||||||
do
|
do
|
||||||
wget http://unbound.net/svn/trunk/util/$f
|
wget http://unbound.net/svn/trunk/util/$f
|
||||||
sed -e 's/event_/getdns_event_/g' -e 's/signal_add/getdns_signal_add/g' -e 's/signal_del/getdns_signal_del/g' -e 's/struct event/struct getdns_event/g' -e 's/mini_ev_cmp/getdns_mini_ev_cmp/g' -e 's/#include "rbtree\.h"/#include "util\/rbtree.h"/g' -e 's/rbnode_/getdns_rbnode_/g' -e 's/rbtree_/getdns_rbtree_/g' -e 's/#include "fptr_wlist\.h"/#include "util\/fptr_wlist.h"/g' -e 's/#include "log\.h"/#include "util\/log.h"/g' $f > ../$f
|
sed -e 's/event_/getdns_event_/g' \
|
||||||
|
-e 's/signal_add/getdns_signal_add/g' \
|
||||||
|
-e 's/signal_del/getdns_signal_del/g' \
|
||||||
|
-e 's/signal_set/getdns_signal_set/g' \
|
||||||
|
-e 's/evtimer_/getdns_evtimer_/g' \
|
||||||
|
-e 's/struct event/struct getdns_event/g' \
|
||||||
|
-e 's/mini_ev_cmp/getdns_mini_ev_cmp/g' \
|
||||||
|
-e 's/static void handle_timeouts/void handle_timeouts/g' \
|
||||||
|
-e 's/handle_timeouts/getdns_handle_timeouts/g' \
|
||||||
|
-e 's/static int handle_select/int handle_select/g' \
|
||||||
|
-e 's/handle_select/getdns_handle_select/g' \
|
||||||
|
-e 's/#include "rbtree\.h"/#include "util\/rbtree.h"/g' \
|
||||||
|
-e 's/rbnode_/getdns_rbnode_/g' \
|
||||||
|
-e 's/rbtree_/getdns_rbtree_/g' \
|
||||||
|
-e 's/#include "fptr_wlist\.h"/#include "util\/fptr_wlist.h"/g' \
|
||||||
|
-e 's/#include "log\.h"/#include "util\/log.h"/g' $f > ../$f
|
||||||
done
|
done
|
||||||
cd ..
|
cd ..
|
||||||
rm -r ub
|
rm -r ub
|
||||||
|
|
|
@ -139,7 +139,7 @@ const char *getdns_event_get_method(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** call timeouts handlers, and return how long to wait for next one or -1 */
|
/** call timeouts handlers, and return how long to wait for next one or -1 */
|
||||||
static void handle_timeouts(struct getdns_event_base* base, struct timeval* now,
|
void getdns_handle_timeouts(struct getdns_event_base* base, struct timeval* now,
|
||||||
struct timeval* wait)
|
struct timeval* wait)
|
||||||
{
|
{
|
||||||
struct getdns_event* p;
|
struct getdns_event* p;
|
||||||
|
@ -175,7 +175,7 @@ static void handle_timeouts(struct getdns_event_base* base, struct timeval* now,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** call select and callbacks for that */
|
/** call select and callbacks for that */
|
||||||
static int handle_select(struct getdns_event_base* base, struct timeval* wait)
|
int getdns_handle_select(struct getdns_event_base* base, struct timeval* wait)
|
||||||
{
|
{
|
||||||
fd_set r, w;
|
fd_set r, w;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
@ -235,11 +235,11 @@ int getdns_event_base_dispatch(struct getdns_event_base* base)
|
||||||
while(!base->need_to_exit)
|
while(!base->need_to_exit)
|
||||||
{
|
{
|
||||||
/* see if timeouts need handling */
|
/* see if timeouts need handling */
|
||||||
handle_timeouts(base, base->time_tv, &wait);
|
getdns_handle_timeouts(base, base->time_tv, &wait);
|
||||||
if(base->need_to_exit)
|
if(base->need_to_exit)
|
||||||
return 0;
|
return 0;
|
||||||
/* do select */
|
/* do select */
|
||||||
if(handle_select(base, &wait) < 0) {
|
if(getdns_handle_select(base, &wait) < 0) {
|
||||||
if(base->need_to_exit)
|
if(base->need_to_exit)
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -155,16 +155,16 @@ int getdns_event_add(struct getdns_event *, struct timeval *);
|
||||||
int getdns_event_del(struct getdns_event *);
|
int getdns_event_del(struct getdns_event *);
|
||||||
|
|
||||||
/** add a timer */
|
/** add a timer */
|
||||||
#define evtimer_add(ev, tv) getdns_event_add(ev, tv)
|
#define getdns_evtimer_add(ev, tv) getdns_event_add(ev, tv)
|
||||||
/** remove a timer */
|
/** remove a timer */
|
||||||
#define evtimer_del(ev) getdns_event_del(ev)
|
#define getdns_evtimer_del(ev) getdns_event_del(ev)
|
||||||
|
|
||||||
/* uses different implementation. Cannot mix fd/timeouts and signals inside
|
/* uses different implementation. Cannot mix fd/timeouts and signals inside
|
||||||
* the same struct getdns_event. create several event structs for that. */
|
* the same struct getdns_event. create several event structs for that. */
|
||||||
/** install signal handler */
|
/** install signal handler */
|
||||||
int getdns_signal_add(struct getdns_event *, struct timeval *);
|
int getdns_signal_add(struct getdns_event *, struct timeval *);
|
||||||
/** set signal event contents */
|
/** set signal event contents */
|
||||||
#define signal_set(ev, x, cb, arg) \
|
#define getdns_signal_set(ev, x, cb, arg) \
|
||||||
getdns_event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
|
getdns_event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
|
||||||
/** remove signal handler */
|
/** remove signal handler */
|
||||||
int getdns_signal_del(struct getdns_event *);
|
int getdns_signal_del(struct getdns_event *);
|
||||||
|
|
Loading…
Reference in New Issue