_loop version for async funcs

So they can be used by the sync functions with a libmini_event loop
This commit is contained in:
Willem Toorop 2014-10-14 00:14:25 +02:00
parent 3ee930d44e
commit 768d8fbf4d
10 changed files with 220 additions and 224 deletions

View File

@ -752,17 +752,14 @@ set_ub_number_opt(struct getdns_context *ctx, char *opt, uint16_t value)
}
static void
getdns_context_request_count_changed(getdns_context *context, uint32_t prev_rc)
getdns_context_request_count_changed(getdns_context *context)
{
if ((!prev_rc && !context->outbound_requests->count) ||
( prev_rc && context->outbound_requests->count))
return;
if (context->outbound_requests->count)
if (context->outbound_requests->count && !context->ub_event.ev)
context->extension->vmt->schedule(
context->extension, ub_fd(context->unbound_ctx),
TIMEOUT_FOREVER, &context->ub_event);
else
else if (context->ub_event.ev)
context->extension->vmt->clear(
context->extension, &context->ub_event);
}
@ -771,11 +768,10 @@ static void
getdns_context_ub_read_cb(void *userarg)
{
getdns_context *context = (getdns_context *)userarg;
int32_t prev_rc = context->outbound_requests->count;
if (getdns_context_process_async(context)) return;
(void) getdns_context_get_num_pending_requests(context, NULL);
getdns_context_request_count_changed(context, prev_rc);
getdns_context_request_count_changed(context);
}
static getdns_return_t
@ -1694,14 +1690,11 @@ getdns_context_prepare_for_resolution(struct getdns_context *context,
getdns_return_t
getdns_context_track_outbound_request(getdns_dns_req * req)
{
uint32_t prev_rc;
ldns_rbnode_t *node;
if (!req)
return GETDNS_RETURN_INVALID_PARAMETER;
prev_rc = req->context->outbound_requests->count;
if (!(node = GETDNS_MALLOC(req->context->my_mf, ldns_rbnode_t)))
return GETDNS_RETURN_MEMORY_ERROR;
@ -1711,37 +1704,33 @@ getdns_context_track_outbound_request(getdns_dns_req * req)
GETDNS_FREE(req->context->my_mf, node);
return GETDNS_RETURN_GENERIC_ERROR;
}
getdns_context_request_count_changed(req->context, prev_rc);
getdns_context_request_count_changed(req->context);
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_clear_outbound_request(getdns_dns_req * req)
{
uint32_t prev_rc;
ldns_rbnode_t *node;
if (!req)
return GETDNS_RETURN_INVALID_PARAMETER;
prev_rc = req->context->outbound_requests->count;
node = ldns_rbtree_delete(
req->context->outbound_requests, &req->trans_id);
if (!node)
return GETDNS_RETURN_GENERIC_ERROR;
GETDNS_FREE(req->context->my_mf, node);
getdns_context_request_count_changed(req->context, prev_rc);
getdns_context_request_count_changed(req->context);
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_request_timed_out(struct getdns_dns_req
*req) {
getdns_context_request_timed_out(struct getdns_dns_req *req)
{
/* Don't use req after callback */
getdns_context* context = req->context;
uint32_t prev_rc = context->outbound_requests->count;
getdns_transaction_t trans_id = req->trans_id;
getdns_callback_t cb = req->user_callback;
void *user_arg = req->user_pointer;
@ -1752,7 +1741,7 @@ getdns_context_request_timed_out(struct getdns_dns_req
context->processing = 1;
cb(context, GETDNS_CALLBACK_TIMEOUT, response, user_arg, trans_id);
context->processing = 0;
getdns_context_request_count_changed(context, prev_rc);
getdns_context_request_count_changed(context);
return GETDNS_RETURN_GOOD;
}
@ -1806,6 +1795,10 @@ int getdns_context_fd(struct getdns_context* context) {
return ub_fd(context->unbound_ctx);
}
/* TODO: Remove next_timeout argument from getdns_context_get_num_pending_requests
*/
void getdns_handle_timeouts(struct getdns_event_base* base, struct timeval* now,
struct timeval* wait);
uint32_t
getdns_context_get_num_pending_requests(struct getdns_context* context,
struct timeval* next_timeout)
@ -1815,6 +1808,10 @@ getdns_context_get_num_pending_requests(struct getdns_context* context,
if (context->outbound_requests->count)
context->extension->vmt->run_once(context->extension, 0);
/* TODO: Remove this when next_timeout is gone */
getdns_handle_timeouts(context->mini_event.base,
&context->mini_event.time_tv, next_timeout);
return context->outbound_requests->count;
}
@ -1904,41 +1901,6 @@ getdns_context_set_eventloop(struct getdns_context* context, getdns_eventloop* l
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_schedule_timeout(getdns_context *context, uint64_t timeout,
getdns_eventloop_callback callback, void *userarg,
getdns_eventloop_event *el_ev)
{
RETURN_IF_NULL(context , GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(callback, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(el_ev , GETDNS_RETURN_INVALID_PARAMETER);
/* Initialize eev_data struct */
el_ev->userarg = userarg;
el_ev->read_cb = NULL;
el_ev->write_cb = NULL;
el_ev->timeout_cb = callback;
el_ev->ev = NULL;
return context->extension->vmt->schedule(
context->extension, -1, timeout, el_ev);
}
getdns_return_t
getdns_context_clear_timeout(getdns_context* context,
getdns_eventloop_event *el_ev)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(el_ev, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(el_ev->timeout_cb, GETDNS_RETURN_GOOD);
if (el_ev->timeout_cb) {
context->extension->vmt->clear(context->extension, el_ev);
el_ev->timeout_cb = NULL;
}
return GETDNS_RETURN_GOOD;
}
static inline getdns_return_t
priv_dict_set_list_if_not_null(getdns_dict* dict,
const char* name, getdns_list* list) {

View File

@ -179,14 +179,6 @@ void getdns_bindata_destroy(
struct mem_funcs *mfs,
struct getdns_bindata *bindata);
/* timeout scheduling */
getdns_return_t getdns_context_schedule_timeout(getdns_context* context,
uint64_t timeout, getdns_eventloop_callback callback, void* userarg,
getdns_eventloop_event *init_to_track);
getdns_return_t getdns_context_clear_timeout(getdns_context* context,
getdns_eventloop_event *timeout_data);
/* perform name resolution in /etc/hosts */
getdns_return_t getdns_context_local_namespace_resolve(getdns_dns_req* req,
struct getdns_dict **response,

View File

@ -152,104 +152,146 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
} /* ub_resolve_callback */
getdns_return_t
getdns_general_ub(struct getdns_context *context,
const char *name,
uint16_t request_type,
struct getdns_dict *extensions,
void *userarg,
getdns_transaction_t * transaction_id,
getdns_callback_t callbackfn,
int usenamespaces)
getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn, int usenamespaces)
{
getdns_return_t gr;
int r = GETDNS_RETURN_GOOD;
getdns_return_t r = GETDNS_RETURN_GOOD;
getdns_network_req *netreq;
getdns_dns_req *req;
getdns_dict *localnames_response;
size_t i;
if (!name) {
if (!context || !name)
return GETDNS_RETURN_INVALID_PARAMETER;
}
if ((r = validate_dname(name)))
return r;
gr = getdns_context_prepare_for_resolution(context, usenamespaces);
if (gr != GETDNS_RETURN_GOOD) {
return gr;
}
if (extensions && (r = validate_extensions(extensions)))
return r;
/* request state */
getdns_dns_req *req = dns_req_new(context,
name,
request_type,
extensions);
if (!req) {
return GETDNS_RETURN_GENERIC_ERROR;
}
/* Set up the context assuming we won't use the specified namespaces.
This is (currently) identical to setting up a pure DNS namespace */
if ((r = getdns_context_prepare_for_resolution(context, 0)))
return r;
/* create the request */
if (!(req = dns_req_new(context, loop, name, request_type, extensions)))
return GETDNS_RETURN_MEMORY_ERROR;
req->user_pointer = userarg;
req->user_callback = callbackfn;
if (transaction_id) {
if (transaction_id)
*transaction_id = req->trans_id;
}
getdns_context_track_outbound_request(req);
/* assign a timeout */
// req->ev_base = ev_base;
// req->timeout = evtimer_new(ev_base, ub_resolve_timeout, req);
/* schedule the timeout */
getdns_context_schedule_timeout(context, context->timeout,
ub_resolve_timeout, req, &req->timeout);
/* issue the first network req */
netreq = req->first_req;
while (r == GETDNS_RETURN_GOOD && netreq) {
r = submit_network_request(netreq);
netreq = netreq->next;
if (1 || context->resolution_type == GETDNS_RESOLUTION_RECURSING) {
/* schedule the timeout */
req->timeout.userarg = req;
req->timeout.read_cb = NULL;
req->timeout.write_cb = NULL;
req->timeout.timeout_cb = ub_resolve_timeout;
req->timeout.ev = NULL;
if ((r = loop->vmt->schedule(
loop, -1, context->timeout, &req->timeout)))
return r;
}
if (!usenamespaces)
/* issue all network requests */
for (netreq = req->first_req; !r && netreq; netreq = netreq->next)
r = submit_network_request(netreq);
else for (i = 0; i < context->namespace_count; i++) {
if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) {
if (!(r = getdns_context_local_namespace_resolve(
req, &localnames_response, context)))
priv_getdns_call_user_callback
( req, localnames_response);
break;
} else if (context->namespaces[i] == GETDNS_NAMESPACE_DNS) {
/* TODO: We will get a good return code here even if
the name is not found (NXDOMAIN). We should consider
if this means we go onto the next namespace instead
of returning */
netreq = req->first_req;
while (!r && netreq) {
r = submit_network_request(netreq);
netreq = netreq->next;
}
break;
} else
r = GETDNS_RETURN_BAD_CONTEXT;
}
if (r != 0) {
/* clean up the request */
getdns_context_clear_outbound_request(req);
dns_req_free(req);
return GETDNS_RETURN_GENERIC_ERROR;
return r;
}
return GETDNS_RETURN_GOOD;
} /* getdns_general_ub */
} /* getdns_general_ns */
getdns_return_t
getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callback)
{
return getdns_general_ns(context, loop,
name, request_type, extensions,
userarg, transaction_id, callback, 0);
} /* getdns_general_loop */
getdns_return_t
getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callback)
{
int cleanup_extensions = 0;
getdns_return_t r;
if (!extensions) {
if (!(extensions = getdns_dict_create_with_context(context)))
return GETDNS_RETURN_MEMORY_ERROR;
cleanup_extensions = 1;
}
if ((r = getdns_dict_set_int(extensions, "return_both_v4_and_v6",
GETDNS_EXTENSION_TRUE)))
return r;
r = getdns_general_ns(context, loop,
name, GETDNS_RRTYPE_A, extensions,
userarg, transaction_id, callback, 1);
if (cleanup_extensions)
getdns_dict_destroy(extensions);
return r;
} /* getdns_address_loop */
/**
* getdns_general
*/
getdns_return_t
getdns_general(struct getdns_context *context,
const char *name,
uint16_t request_type,
struct getdns_dict * extensions,
void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callback)
getdns_general(getdns_context *context,
const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t * transaction_id,
getdns_callback_t callback)
{
int extcheck = GETDNS_RETURN_GOOD;
if (!context) {
/* Can't do async without an event loop
* or callback
*/
return GETDNS_RETURN_INVALID_PARAMETER;
}
/* ensure callback is not NULL */
if (!callback || !name) {
return GETDNS_RETURN_INVALID_PARAMETER;
}
extcheck = validate_dname(name);
if (extcheck != GETDNS_RETURN_GOOD) {
return extcheck;
}
extcheck = validate_extensions(extensions);
if (extcheck != GETDNS_RETURN_GOOD)
return extcheck;
return getdns_general_ub(context,
name, request_type, extensions, userarg, transaction_id, callback, 0);
return getdns_general_loop(context, context->extension,
name, request_type, extensions,
userarg, transaction_id, callback);
} /* getdns_general */
@ -258,44 +300,14 @@ getdns_general(struct getdns_context *context,
*
*/
getdns_return_t
getdns_address(struct getdns_context *context,
const char *name,
struct getdns_dict * extensions,
void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callback)
getdns_address(getdns_context *context,
const char *name, getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callback)
{
int cleanup_extensions = 0;
int extcheck;
getdns_return_t result;
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;
if (!callback || !name)
return GETDNS_RETURN_INVALID_PARAMETER;
extcheck = validate_dname(name);
if (extcheck != GETDNS_RETURN_GOOD)
return extcheck;
/* we set the extensions that make general behave like getdns_address */
if (!extensions)
{
extensions = getdns_dict_create_with_context(context);
cleanup_extensions = 1;
}
getdns_dict_set_int(extensions,
GETDNS_STR_EXTENSION_RETURN_BOTH_V4_AND_V6, GETDNS_EXTENSION_TRUE);
extcheck = validate_extensions(extensions);
if (extcheck != GETDNS_RETURN_GOOD)
return extcheck;
result = getdns_general_ub(context,
name, GETDNS_RRTYPE_A, extensions, userarg, transaction_id, callback, 1);
if (cleanup_extensions)
getdns_dict_destroy(extensions);
return result;
return getdns_address_loop(context, context->extension,
name, extensions, userarg,
transaction_id, callback);
} /* getdns_address */
/* getdns_general.c */

View File

@ -42,15 +42,35 @@
/* private inner helper used by sync and async */
getdns_return_t
getdns_general_ub(struct getdns_context *context,
const char *name,
uint16_t request_type,
struct getdns_dict *extensions,
void *userarg,
getdns_transaction_t * transaction_id,
getdns_callback_t callbackfn,
int usenamespaces);
getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn, int usenamespaces);
void priv_getdns_call_user_callback(getdns_dns_req *, struct getdns_dict *);
getdns_return_t
getdns_general_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn);
getdns_return_t
getdns_address_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn);
getdns_return_t
getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
getdns_dict *address, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn);
getdns_return_t
getdns_service_loop(getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions,
void *userarg, getdns_transaction_t *transaction_id,
getdns_callback_t callbackfn);
#endif

View File

@ -50,11 +50,9 @@
*
*/
getdns_return_t
getdns_hostname(struct getdns_context *context,
struct getdns_dict * address,
struct getdns_dict * extensions,
void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callback)
getdns_hostname_loop(getdns_context *context, getdns_eventloop *loop,
getdns_dict *address, getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callback)
{
struct getdns_bindata *address_data;
struct getdns_bindata *address_type;
@ -83,10 +81,24 @@ getdns_hostname(struct getdns_context *context,
return GETDNS_RETURN_INVALID_PARAMETER;
if ((name = reverse_address(address_data)) == NULL)
return GETDNS_RETURN_INVALID_PARAMETER;
retval = getdns_general(context, name, req_type, extensions,
retval = getdns_general_loop(context, loop, name, req_type, extensions,
userarg, transaction_id, callback);
free(name);
return retval;
} /* getdns_hostname_loop */
/*
* getdns_hostname
*
*/
getdns_return_t
getdns_hostname(getdns_context *context,
getdns_dict *address, getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callback)
{
return getdns_hostname_loop(context, context->extension,
address, extensions, userarg, transaction_id, callback);
} /* getdns_hostname */
/* hostname.c */

View File

@ -91,10 +91,10 @@ getdns_root_trust_anchor
getdns_context_set_return_dnssec_status
getdns_dict_util_set_string
getdns_dict_util_get_string
getdns_context_get_num_pending_requests
getdns_context_fd
getdns_context_process_async
getdns_context_set_use_threads
getdns_extension_set_eventloop
getdns_context_get_extension_data
getdns_extension_detach_eventloop
getdns_context_get_num_pending_requests
getdns_context_process_async
getdns_context_set_eventloop
getdns_context_detach_eventloop
getdns_context_run

View File

@ -82,7 +82,6 @@ dns_req_free(getdns_dns_req * req)
return;
}
getdns_network_req *net_req = NULL;
struct getdns_context *context = req->context;
/* free extensions */
getdns_dict_destroy(req->extensions);
@ -95,7 +94,10 @@ dns_req_free(getdns_dns_req * req)
net_req = next;
}
getdns_context_clear_timeout(context, &req->timeout);
if (req->timeout.timeout_cb) {
req->loop->vmt->clear(req->loop, &req->timeout);
req->timeout.timeout_cb = NULL;
}
/* free strduped name */
GETDNS_FREE(req->my_mf, req->name);
@ -104,7 +106,7 @@ dns_req_free(getdns_dns_req * req)
/* create a new dns req to be submitted */
getdns_dns_req *
dns_req_new(struct getdns_context *context,
dns_req_new(struct getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, struct getdns_dict *extensions)
{
@ -119,10 +121,12 @@ dns_req_new(struct getdns_context *context,
result->my_mf = context->mf;
result->name = getdns_strdup(&(result->my_mf), name);
result->context = context;
result->loop = loop;
result->canceled = 0;
result->current_req = NULL;
result->first_req = NULL;
result->trans_id = ldns_get_random();
result->trans_id = (((uint64_t) ldns_get_random()) << 32)
^ ((intptr_t) result);
getdns_dict_copy(extensions, &result->extensions);
result->return_dnssec_status = context->return_dnssec_status;

View File

@ -43,35 +43,25 @@
*
*/
getdns_return_t
getdns_service(struct getdns_context *context,
const char *name,
struct getdns_dict * extensions,
void *userarg,
getdns_service_loop(struct getdns_context *context, getdns_eventloop *loop,
const char *name, getdns_dict *extensions, void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callback)
{
int parmcheck;
getdns_return_t result;
return getdns_general_ns(context, loop, name, GETDNS_RRTYPE_SRV,
extensions, userarg, transaction_id, callback, 1);
} /* getdns_service_loop */
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;
if (!callback || !name)
return GETDNS_RETURN_INVALID_PARAMETER;
parmcheck = validate_dname(name);
if (parmcheck != GETDNS_RETURN_GOOD)
return parmcheck;
if(extensions)
{
parmcheck = validate_extensions(extensions);
if (parmcheck != GETDNS_RETURN_GOOD)
return parmcheck;
}
result = getdns_general_ub(context,
name, GETDNS_RRTYPE_SRV, extensions, userarg, transaction_id, callback, 1);
return result;
/*
* getdns_service
*
*/
getdns_return_t
getdns_service(getdns_context *context,
const char *name, getdns_dict *extensions, void *userarg,
getdns_transaction_t *transaction_id, getdns_callback_t callback)
{
return getdns_service_loop(context, context->extension,
name, extensions, userarg, transaction_id, callback);
} /* getdns_service */
/* service.c */

View File

@ -163,7 +163,7 @@ getdns_general_sync_ns(struct getdns_context *context,
return response_status;
/* create the request */
req = dns_req_new(context, name, request_type, extensions);
req = dns_req_new(context, context->extension, name, request_type, extensions);
if (!req)
return GETDNS_RETURN_MEMORY_ERROR;

View File

@ -196,6 +196,9 @@ typedef struct getdns_dns_req
/* request extensions */
struct getdns_dict *extensions;
/* event loop */
getdns_eventloop *loop;
/* callback data */
getdns_callback_t user_callback;
void *user_pointer;
@ -203,6 +206,7 @@ typedef struct getdns_dns_req
/* the transaction id */
getdns_transaction_t trans_id;
/* for scheduling timeouts when using libunbound */
getdns_eventloop_event timeout;
/* dnssec status */
@ -246,8 +250,8 @@ getdns_network_req *network_req_new(getdns_dns_req * owner,
uint16_t request_class, struct getdns_dict *extensions);
/* dns request utils */
getdns_dns_req *dns_req_new(struct getdns_context *context,
const char *name, uint16_t request_type, struct getdns_dict *extensions);
getdns_dns_req *dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions);
void dns_req_free(getdns_dns_req * req);