Initial pass at using unbound stock

This commit is contained in:
Neel Goyal 2014-01-21 15:31:22 -05:00
parent d9e3485f8b
commit 2bcfedcf78
15 changed files with 282 additions and 8861 deletions

8601
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

26
configure vendored
View File

@ -7103,6 +7103,10 @@ _lt_linker_boilerplate=`cat conftest.err`
$RM -r conftest* $RM -r conftest*
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then if test -n "$compiler"; then
lt_prog_compiler_no_builtin_flag= lt_prog_compiler_no_builtin_flag=
@ -11014,9 +11018,9 @@ fi
found_libunbound=1 found_libunbound=1
{ $as_echo "$as_me:${as_lineno-$LINENO}: Checking for dependency libunbound" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: Checking for dependency libunbound" >&5
$as_echo "$as_me: Checking for dependency libunbound" >&6;} $as_echo "$as_me: Checking for dependency libunbound" >&6;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ub_ctx_set_event in -lunbound" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ub_fd in -lunbound" >&5
$as_echo_n "checking for ub_ctx_set_event in -lunbound... " >&6; } $as_echo_n "checking for ub_fd in -lunbound... " >&6; }
if ${ac_cv_lib_unbound_ub_ctx_set_event+:} false; then : if ${ac_cv_lib_unbound_ub_fd+:} false; then :
$as_echo_n "(cached) " >&6 $as_echo_n "(cached) " >&6
else else
ac_check_lib_save_LIBS=$LIBS ac_check_lib_save_LIBS=$LIBS
@ -11030,27 +11034,27 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
char ub_ctx_set_event (); char ub_fd ();
int int
main () main ()
{ {
return ub_ctx_set_event (); return ub_fd ();
; ;
return 0; return 0;
} }
_ACEOF _ACEOF
if ac_fn_c_try_link "$LINENO"; then : if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_unbound_ub_ctx_set_event=yes ac_cv_lib_unbound_ub_fd=yes
else else
ac_cv_lib_unbound_ub_ctx_set_event=no ac_cv_lib_unbound_ub_fd=no
fi fi
rm -f core conftest.err conftest.$ac_objext \ rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS LIBS=$ac_check_lib_save_LIBS
fi fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unbound_ub_ctx_set_event" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unbound_ub_fd" >&5
$as_echo "$ac_cv_lib_unbound_ub_ctx_set_event" >&6; } $as_echo "$ac_cv_lib_unbound_ub_fd" >&6; }
if test "x$ac_cv_lib_unbound_ub_ctx_set_event" = xyes; then : if test "x$ac_cv_lib_unbound_ub_fd" = xyes; then :
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
#define HAVE_LIBUNBOUND 1 #define HAVE_LIBUNBOUND 1
_ACEOF _ACEOF
@ -11063,7 +11067,7 @@ fi
if test $found_libunbound == 0 if test $found_libunbound == 0
then then
as_fn_error $? "libunbound is missing or does not incude event code, you may need to patch your libunbound sources and rebuild. See the getdns build instructions" "$LINENO" 5 as_fn_error $? "libunbound is missing." "$LINENO" 5
fi fi
for ac_prog in doxygen for ac_prog in doxygen

View File

@ -138,14 +138,14 @@ then
AC_MSG_ERROR([One more dependencies is missing]) AC_MSG_ERROR([One more dependencies is missing])
fi fi
# break out libunbound from other libraries since we are currently using a # break out libunbound from other libraries since we are currently using a
# patch to the sources # patch to the sources
found_libunbound=1 found_libunbound=1
AC_MSG_NOTICE([Checking for dependency libunbound]) AC_MSG_NOTICE([Checking for dependency libunbound])
AC_CHECK_LIB([unbound], [ub_ctx_set_event], [], [found_libunbound=0]) AC_CHECK_LIB([unbound], [ub_fd], [], [found_libunbound=0])
if test $found_libunbound == 0 if test $found_libunbound == 0
then then
AC_MSG_ERROR([libunbound is missing or does not incude event code, you may need to patch your libunbound sources and rebuild. See the getdns build instructions]) AC_MSG_ERROR([libunbound is missing.])
fi fi
AC_CHECK_PROGS([DOXYGEN], [doxygen]) AC_CHECK_PROGS([DOXYGEN], [doxygen])

View File

@ -33,7 +33,7 @@ CFLAGS=@CFLAGS@ -Wall -I$(srcdir)/ -I/usr/local/include -std=c99
LDFLAGS=@LDFLAGS@ @LIBS@ LDFLAGS=@LDFLAGS@ @LIBS@
GETDNS_OBJ=sync.lo context.lo list.lo dict.lo convert.lo general.lo \ GETDNS_OBJ=sync.lo context.lo list.lo dict.lo convert.lo general.lo \
hostname.lo service.lo request-internal.lo validate_dnssec.lo \ hostname.lo service.lo request-internal.lo validate_dnssec.lo \
util-internal.lo getdns_error.lo util-internal.lo getdns_error.lo extension_libevent.lo
.SUFFIXES: .c .o .a .lo .h .SUFFIXES: .c .o .a .lo .h

View File

@ -29,17 +29,11 @@
*/ */
#include "config.h" #include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
#endif
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ldns/ldns.h> #include <ldns/ldns.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unbound-event.h>
#include <unbound.h> #include <unbound.h>
#include "context.h" #include "context.h"
@ -275,11 +269,7 @@ getdns_context_create_with_extended_memory_functions(
result->mf.mf.ext.realloc = realloc; result->mf.mf.ext.realloc = realloc;
result->mf.mf.ext.free = free; result->mf.mf.ext.free = free;
result->event_base_sync = event_base_new(); result->unbound_ctx = ub_ctx_create();
result->unbound_sync = ub_ctx_create_event(result->event_base_sync);
/* create the async one also so options are kept up to date */
result->unbound_async = ub_ctx_create_event(result->event_base_sync);
result->event_base_async = NULL;
result->resolution_type_set = 0; result->resolution_type_set = 0;
@ -375,10 +365,7 @@ getdns_context_destroy(struct getdns_context *context)
getdns_list_destroy(context->upstream_list); getdns_list_destroy(context->upstream_list);
/* destroy the ub context */ /* destroy the ub context */
ub_ctx_delete(context->unbound_async); ub_ctx_delete(context->unbound_ctx);
ub_ctx_delete(context->unbound_sync);
event_base_free(context->event_base_sync);
ldns_rbtree_free(context->outbound_requests); ldns_rbtree_free(context->outbound_requests);
@ -407,8 +394,7 @@ getdns_context_set_context_update_callback(struct getdns_context *context,
static void static void
set_ub_string_opt(struct getdns_context *ctx, char *opt, char *value) set_ub_string_opt(struct getdns_context *ctx, char *opt, char *value)
{ {
ub_ctx_set_option(ctx->unbound_sync, opt, value); ub_ctx_set_option(ctx->unbound_ctx, opt, value);
ub_ctx_set_option(ctx->unbound_async, opt, value);
} }
static void static void
@ -883,27 +869,6 @@ getdns_context_set_memory_functions(struct getdns_context *context,
context, MF_PLAIN, mf.ext.malloc, mf.ext.realloc, mf.ext.free); context, MF_PLAIN, mf.ext.malloc, mf.ext.realloc, mf.ext.free);
} /* getdns_context_set_memory_functions*/ } /* getdns_context_set_memory_functions*/
/*
* getdns_extension_set_libevent_base
*
*/
getdns_return_t
getdns_extension_set_libevent_base(struct getdns_context *context,
struct event_base * this_event_base)
{
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
if (this_event_base) {
ub_ctx_set_event(context->unbound_async, this_event_base);
context->event_base_async = this_event_base;
} else {
ub_ctx_set_event(context->unbound_async,
context->event_base_sync);
context->event_base_async = NULL;
}
return GETDNS_RETURN_GOOD;
} /* getdns_extension_set_libevent_base */
/* cancel the request */ /* cancel the request */
static void static void
cancel_dns_req(getdns_dns_req * req) cancel_dns_req(getdns_dns_req * req)
@ -913,7 +878,7 @@ cancel_dns_req(getdns_dns_req * req)
if (netreq->state == NET_REQ_IN_FLIGHT) { if (netreq->state == NET_REQ_IN_FLIGHT) {
/* for ev based ub, this should always prevent /* for ev based ub, this should always prevent
* the callback from firing */ * the callback from firing */
ub_cancel(req->unbound, netreq->unbound_id); ub_cancel(req->context->unbound_ctx, netreq->unbound_id);
netreq->state = NET_REQ_CANCELED; netreq->state = NET_REQ_CANCELED;
} else if (netreq->state == NET_REQ_NOT_SENT) { } else if (netreq->state == NET_REQ_NOT_SENT) {
netreq->state = NET_REQ_CANCELED; netreq->state = NET_REQ_CANCELED;
@ -1063,19 +1028,15 @@ getdns_context_prepare_for_resolution(struct getdns_context *context)
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
} }
/* set upstreams */ /* set upstreams */
ub_setup_stub(context->unbound_async, context->upstream_list, ub_setup_stub(context->unbound_ctx, context->upstream_list,
upstream_len);
ub_setup_stub(context->unbound_sync, context->upstream_list,
upstream_len); upstream_len);
/* use /etc/hosts */ /* use /etc/hosts */
ub_ctx_hosts(context->unbound_sync, NULL); ub_ctx_hosts(context->unbound_ctx, NULL);
ub_ctx_hosts(context->unbound_async, NULL);
} else if (context->resolution_type == GETDNS_CONTEXT_RECURSING) { } else if (context->resolution_type == GETDNS_CONTEXT_RECURSING) {
/* set recursive */ /* set recursive */
/* TODO: use the root servers via root hints file */ /* TODO: use the root servers via root hints file */
ub_ctx_set_fwd(context->unbound_async, NULL); ub_ctx_set_fwd(context->unbound_ctx, NULL);
ub_ctx_set_fwd(context->unbound_sync, NULL);
} else { } else {
/* bogus? */ /* bogus? */
@ -1121,6 +1082,23 @@ getdns_context_clear_outbound_request(getdns_dns_req * req)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
/* get the fd */
int getdns_context_fd(struct getdns_context* context) {
RETURN_IF_NULL(context, -1);
return ub_fd(context->unbound_ctx);
}
/* process async reqs */
getdns_return_t getdns_context_process_async(struct getdns_context* context) {
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
if (ub_process(context->unbound_ctx) != 0) {
/* need an async return code? */
return GETDNS_RETURN_GENERIC_ERROR;
}
return GETDNS_RETURN_GOOD;
}
char * char *
getdns_strdup(const struct mem_funcs *mfs, const char *s) getdns_strdup(const struct mem_funcs *mfs, const char *s)
{ {

View File

@ -33,7 +33,6 @@
#include <getdns/getdns.h> #include <getdns/getdns.h>
#include "types-internal.h" #include "types-internal.h"
struct event_base;
struct getdns_dns_req; struct getdns_dns_req;
struct ldns_rbtree_t; struct ldns_rbtree_t;
struct ub_ctx; struct ub_ctx;
@ -63,15 +62,9 @@ struct getdns_context {
struct mem_funcs mf; struct mem_funcs mf;
struct mem_funcs my_mf; struct mem_funcs my_mf;
/* Event loop for sync requests */
struct event_base *event_base_sync;
/* Event loop for async requests */
struct event_base *event_base_async;
/* The underlying unbound contexts that do /* The underlying unbound contexts that do
* the real work */ * the real work */
struct ub_ctx *unbound_sync; struct ub_ctx *unbound_ctx;
struct ub_ctx *unbound_async;
/* which resolution type the contexts are configured for /* which resolution type the contexts are configured for
* 0 means nothing set * 0 means nothing set

47
src/extension_libevent.c Normal file
View File

@ -0,0 +1,47 @@
#include "config.h"
#include "context.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
# define evutil_socket_t int
# define event_free free
# define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
#endif
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
#ifndef HAVE_EVENT2_EVENT_H
static struct event *
event_new(struct event_base *b, evutil_socket_t fd, short ev, void* cb, void *arg)
{
struct event* e = (struct event*)calloc(1, sizeof(struct event));
if(!e) return NULL;
event_set(e, fd, ev, cb, arg);
event_base_set(b, e);
return e;
}
#endif /* no event2 */
void getdns_libevent_cb(evutil_socket_t fd, short what, void *userarg) {
struct getdns_context* context = (struct getdns_context*) userarg;
getdns_context_process_async(context);
}
/*
* getdns_extension_set_libevent_base
*
*/
getdns_return_t
getdns_extension_set_libevent_base(struct getdns_context *context,
struct event_base * this_event_base)
{
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
RETURN_IF_NULL(this_event_base, GETDNS_RETURN_INVALID_PARAMETER);
/* TODO: cleanup current extension base */
int fd = getdns_context_fd(context);
struct event *getdns_event = event_new(this_event_base, fd, EV_READ | EV_PERSIST, getdns_libevent_cb, context);
event_add(getdns_event, NULL);
return GETDNS_RETURN_GOOD;
} /* getdns_extension_set_libevent_base */

View File

@ -35,17 +35,8 @@
*/ */
#include "config.h" #include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
# define evutil_socket_t int
# define event_free free
# define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
#endif
#include <string.h> #include <string.h>
#include <unbound.h> #include <unbound.h>
#include <unbound-event.h>
#include <ldns/ldns.h> #include <ldns/ldns.h>
#include "context.h" #include "context.h"
#include "types-internal.h" #include "types-internal.h"
@ -56,11 +47,10 @@
#define UNUSED_PARAM(x) ((void)(x)) #define UNUSED_PARAM(x) ((void)(x))
/* declarations */ /* declarations */
static void ub_resolve_callback(void *arg, int err, ldns_buffer * result, static void ub_resolve_callback(void* mydata, int err, struct ub_result* result);
int sec, char *bogus); // static void ub_resolve_timeout(evutil_socket_t fd, short what, void *arg);
static void ub_resolve_timeout(evutil_socket_t fd, short what, void *arg); // static void ub_local_resolve_timeout(evutil_socket_t fd, short what,
static void ub_local_resolve_timeout(evutil_socket_t fd, short what, // void *arg);
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);
@ -75,60 +65,48 @@ typedef struct netreq_cb_data
char *bogus; char *bogus;
} netreq_cb_data; } netreq_cb_data;
#ifndef HAVE_EVENT2_EVENT_H // /* cancel, cleanup and send timeout to callback */
static struct event * // static void
event_new(struct event_base *b, evutil_socket_t fd, short ev, void* cb, void *arg) // ub_resolve_timeout(evutil_socket_t fd, short what, void *arg)
{ // {
struct event* e = (struct event*)calloc(1, sizeof(struct event)); // getdns_dns_req *dns_req = (getdns_dns_req *) arg;
if(!e) return NULL; // struct getdns_context *context = dns_req->context;
event_set(e, fd, ev, cb, arg); // getdns_transaction_t trans_id = dns_req->trans_id;
event_base_set(b, e); // getdns_callback_t cb = dns_req->user_callback;
return e; // void *user_arg = dns_req->user_pointer;
}
#endif /* no event2 */
/* cancel, cleanup and send timeout to callback */ // /* cancel the req - also clears it from outbound */
static void // getdns_context_cancel_request(context, trans_id, 0);
ub_resolve_timeout(evutil_socket_t fd, short what, void *arg)
{
getdns_dns_req *dns_req = (getdns_dns_req *) arg;
struct getdns_context *context = dns_req->context;
getdns_transaction_t trans_id = dns_req->trans_id;
getdns_callback_t cb = dns_req->user_callback;
void *user_arg = dns_req->user_pointer;
/* cancel the req - also clears it from outbound */ // /* cleanup */
getdns_context_cancel_request(context, trans_id, 0); // dns_req_free(dns_req);
/* cleanup */ // cb(context, GETDNS_CALLBACK_TIMEOUT, NULL, user_arg, trans_id);
dns_req_free(dns_req); // }
cb(context, GETDNS_CALLBACK_TIMEOUT, NULL, user_arg, trans_id); // static void
} // ub_local_resolve_timeout(evutil_socket_t fd, short what, void *arg)
// {
// netreq_cb_data *cb_data = (netreq_cb_data *) arg;
static void // /* cleanup the local timer here since the memory may be
ub_local_resolve_timeout(evutil_socket_t fd, short what, void *arg) // * invalid after calling ub_resolve_callback
{ // */
netreq_cb_data *cb_data = (netreq_cb_data *) arg; // getdns_dns_req *dnsreq = cb_data->netreq->owner;
// event_free(dnsreq->local_cb_timer);
// dnsreq->local_cb_timer = NULL;
/* cleanup the local timer here since the memory may be // /* just call ub_resolve_callback */
* invalid after calling ub_resolve_callback // ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->result,
*/ // cb_data->sec, cb_data->bogus);
getdns_dns_req *dnsreq = cb_data->netreq->owner;
event_free(dnsreq->local_cb_timer);
dnsreq->local_cb_timer = NULL;
/* just call ub_resolve_callback */ // /* cleanup the state */
ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->result, // ldns_buffer_free(cb_data->result);
cb_data->sec, cb_data->bogus); // if (cb_data->bogus) {
// free(cb_data->bogus);
/* cleanup the state */ // }
ldns_buffer_free(cb_data->result); // free(cb_data);
if (cb_data->bogus) { // }
free(cb_data->bogus);
}
free(cb_data);
}
/* cleanup and send an error to the user callback */ /* cleanup and send an error to the user callback */
static void static void
@ -174,7 +152,7 @@ static int
submit_network_request(getdns_network_req * netreq) submit_network_request(getdns_network_req * netreq)
{ {
getdns_dns_req *dns_req = netreq->owner; getdns_dns_req *dns_req = netreq->owner;
int r = ub_resolve_event(dns_req->unbound, int r = ub_resolve_async(dns_req->context->unbound_ctx,
dns_req->name, dns_req->name,
netreq->request_type, netreq->request_type,
netreq->request_class, netreq->request_class,
@ -186,82 +164,84 @@ submit_network_request(getdns_network_req * netreq)
} }
static void static void
ub_resolve_callback(void *arg, int err, ldns_buffer * result, int sec, ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
char *bogus) // ub_resolve_callback(void *arg, int err, ldns_buffer * result, int sec,
// char *bogus)
{ {
getdns_network_req *netreq = (getdns_network_req *) arg; getdns_network_req *netreq = (getdns_network_req *) arg;
if (err != 0) {
handle_network_request_error(netreq, err);
return;
}
/* if netreq->state == NET_REQ_NOT_SENT here, that implies /* if netreq->state == NET_REQ_NOT_SENT here, that implies
* that ub called us back immediately - probably from a local file. * that ub called us back immediately - probably from a local file.
* This most likely means that getdns_general has not returned * This most likely means that getdns_general has not returned
*/ */
if (netreq->state == NET_REQ_NOT_SENT) { if (netreq->state == NET_REQ_NOT_SENT) {
/* TODO!!!! */
/* just do a very short timer since this was called immediately. /* just do a very short timer since this was called immediately.
* we can make this less hacky, but it gets interesting when multiple * we can make this less hacky, but it gets interesting when multiple
* netreqs need to be issued and some resolve immediately vs. not. * netreqs need to be issued and some resolve immediately vs. not.
*/ */
struct timeval tv; // struct timeval tv;
getdns_dns_req *dnsreq = netreq->owner; // getdns_dns_req *dnsreq = netreq->owner;
netreq_cb_data *cb_data = // netreq_cb_data *cb_data =
(netreq_cb_data *) malloc(sizeof(netreq_cb_data)); // (netreq_cb_data *) malloc(sizeof(netreq_cb_data));
cb_data->netreq = netreq; // cb_data->netreq = netreq;
cb_data->err = err; // cb_data->err = err;
cb_data->sec = sec; // cb_data->sec = sec;
cb_data->result = NULL; // cb_data->result = NULL;
cb_data->bogus = NULL; /* unused but here in case we need it */ // cb_data->bogus = NULL; /* unused but here in case we need it */
if (result) { // if (result) {
cb_data->result = // cb_data->result =
ldns_buffer_new(ldns_buffer_limit(result)); // ldns_buffer_new(ldns_buffer_limit(result));
if (!cb_data->result) { // if (!cb_data->result) {
cb_data->err = GETDNS_RETURN_GENERIC_ERROR; // cb_data->err = GETDNS_RETURN_GENERIC_ERROR;
} else { // } else {
/* copy */ // /* copy */
ldns_buffer_copy(cb_data->result, result); // ldns_buffer_copy(cb_data->result, result);
} // }
} // }
/* schedule the timeout */ // /* schedule the timeout */
dnsreq->local_cb_timer = // dnsreq->local_cb_timer =
evtimer_new(dnsreq->ev_base, ub_local_resolve_timeout, // evtimer_new(dnsreq->ev_base, ub_local_resolve_timeout,
cb_data); // cb_data);
tv.tv_sec = 0; // tv.tv_sec = 0;
/* half ms */ // /* half ms */
tv.tv_usec = 500; // tv.tv_usec = 500;
evtimer_add(dnsreq->local_cb_timer, &tv); // evtimer_add(dnsreq->local_cb_timer, &tv);
return; return;
} }
netreq->state = NET_REQ_FINISHED; netreq->state = NET_REQ_FINISHED;
if (err) { /* parse */
handle_network_request_error(netreq, err); /* TODO: optimize */
} else { getdns_return_t r = getdns_apply_network_result(netreq, ub_res);
/* parse */ ub_resolve_free(ub_res);
ldns_status r = if (r != GETDNS_RETURN_GOOD) {
ldns_buffer2pkt_wire(&(netreq->result), result); handle_network_request_error(netreq, err);
if (r != LDNS_STATUS_OK) { } else {
handle_network_request_error(netreq, r); /* is this the last request */
if (!netreq->next) {
/* finished */
handle_dns_request_complete(netreq->owner);
} else { } else {
/* is this the last request */ /* not finished - update to next request and ship it */
if (!netreq->next) { getdns_dns_req *dns_req = netreq->owner;
/* finished */ dns_req->current_req = netreq->next;
handle_dns_request_complete(netreq->owner); submit_network_request(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);
}
} }
} }
} }
getdns_return_t getdns_return_t
getdns_general_ub(struct ub_ctx *unbound, getdns_general_ub(struct getdns_context *context,
struct event_base *ev_base,
struct getdns_context *context,
const char *name, const char *name,
uint16_t request_type, uint16_t request_type,
struct getdns_dict *extensions, struct getdns_dict *extensions,
void *userarg, void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn) getdns_transaction_t * transaction_id,
getdns_callback_t callbackfn)
{ {
/* timeout */ /* timeout */
struct timeval tv; struct timeval tv;
@ -279,7 +259,6 @@ getdns_general_ub(struct ub_ctx *unbound,
/* request state */ /* request state */
getdns_dns_req *req = dns_req_new(context, getdns_dns_req *req = dns_req_new(context,
unbound,
name, name,
request_type, request_type,
extensions); extensions);
@ -296,12 +275,13 @@ getdns_general_ub(struct ub_ctx *unbound,
getdns_context_track_outbound_request(req); getdns_context_track_outbound_request(req);
/* assign a timeout */ /* TODO: timeout.. */
req->ev_base = ev_base; // /* assign a timeout */
req->timeout = evtimer_new(ev_base, ub_resolve_timeout, req); // req->ev_base = ev_base;
tv.tv_sec = context->timeout / 1000; // req->timeout = evtimer_new(ev_base, ub_resolve_timeout, req);
tv.tv_usec = (context->timeout % 1000) * 1000; // tv.tv_sec = context->timeout / 1000;
evtimer_add(req->timeout, &tv); // tv.tv_usec = (context->timeout % 1000) * 1000;
// evtimer_add(req->timeout, &tv);
/* issue the first network req */ /* issue the first network req */
@ -329,7 +309,7 @@ getdns_general(struct getdns_context *context,
{ {
int extcheck = GETDNS_RETURN_GOOD; int extcheck = GETDNS_RETURN_GOOD;
if (!context || !context->event_base_async) { if (!context) {
/* Can't do async without an event loop /* Can't do async without an event loop
* or callback * or callback
*/ */
@ -345,9 +325,7 @@ getdns_general(struct getdns_context *context,
if (extcheck != GETDNS_RETURN_GOOD) if (extcheck != GETDNS_RETURN_GOOD)
return extcheck; return extcheck;
return getdns_general_ub(context->unbound_async, return getdns_general_ub(context,
context->event_base_async,
context,
name, request_type, extensions, userarg, transaction_id, callback); name, request_type, extensions, userarg, transaction_id, callback);
} /* getdns_general */ } /* getdns_general */

View File

@ -9,7 +9,7 @@
/* /*
* Copyright (c) 2013, Versign, Inc. * Copyright (c) 2013, Versign, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
@ -40,13 +40,8 @@
/* private inner helper used by sync and async */ /* private inner helper used by sync and async */
struct ub_ctx;
struct event_base;
getdns_return_t getdns_return_t
getdns_general_ub(struct ub_ctx *unbound, getdns_general_ub(struct getdns_context *context,
struct event_base *ev_base,
struct getdns_context *context,
const char *name, const char *name,
uint16_t request_type, uint16_t request_type,
struct getdns_dict *extensions, struct getdns_dict *extensions,

View File

@ -884,4 +884,11 @@ getdns_return_t
getdns_extension_set_libevent_base(struct getdns_context *context, getdns_extension_set_libevent_base(struct getdns_context *context,
struct event_base *this_event_base); struct event_base *this_event_base);
/* get the fd */
int getdns_context_fd(struct getdns_context* context);
/* process async reqs */
getdns_return_t getdns_context_process_async(struct getdns_context* context);
#endif /* GETDNS_H */ #endif /* GETDNS_H */

View File

@ -9,7 +9,7 @@
/* /*
* Copyright (c) 2013, Versign, Inc. * Copyright (c) 2013, Versign, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
@ -34,15 +34,8 @@
*/ */
#include "config.h" #include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
# define event_free free
#endif
#include "types-internal.h" #include "types-internal.h"
#include "util-internal.h" #include "util-internal.h"
#include <unbound.h>
void void
network_req_free(getdns_network_req * net_req) network_req_free(getdns_network_req * net_req)
@ -103,17 +96,6 @@ dns_req_free(getdns_dns_req * req)
net_req = next; net_req = next;
} }
/* cleanup timeout */
if (req->timeout) {
event_del(req->timeout);
event_free(req->timeout);
}
if (req->local_cb_timer) {
event_del(req->local_cb_timer);
event_free(req->local_cb_timer);
}
/* free strduped name */ /* free strduped name */
free(req->name); free(req->name);
@ -123,7 +105,6 @@ dns_req_free(getdns_dns_req * req)
/* create a new dns req to be submitted */ /* create a new dns req to be submitted */
getdns_dns_req * getdns_dns_req *
dns_req_new(struct getdns_context *context, dns_req_new(struct getdns_context *context,
struct ub_ctx *unbound,
const char *name, uint16_t request_type, struct getdns_dict *extensions) const char *name, uint16_t request_type, struct getdns_dict *extensions)
{ {
@ -139,14 +120,13 @@ dns_req_new(struct getdns_context *context,
result->name = strdup(name); result->name = strdup(name);
result->context = context; result->context = context;
result->unbound = unbound;
result->canceled = 0; result->canceled = 0;
result->current_req = NULL; result->current_req = NULL;
result->first_req = NULL; result->first_req = NULL;
result->trans_id = ldns_get_random(); result->trans_id = ldns_get_random();
result->timeout = NULL; // result->timeout = NULL;
result->local_cb_timer = NULL; // result->local_cb_timer = NULL;
result->ev_base = NULL; // result->ev_base = NULL;
getdns_dict_copy(extensions, &result->extensions); getdns_dict_copy(extensions, &result->extensions);

View File

@ -34,13 +34,8 @@
*/ */
#include "config.h" #include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
#endif
#include <getdns/getdns.h> #include <getdns/getdns.h>
#include <unbound-event.h> #include <unbound.h>
#include "context.h" #include "context.h"
#include "general.h" #include "general.h"
#include "types-internal.h" #include "types-internal.h"
@ -51,14 +46,28 @@
#define UNUSED_PARAM(x) ((void)(x)) #define UNUSED_PARAM(x) ((void)(x))
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code; #define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
static void getdns_return_t submit_request_sync(getdns_dns_req* req) {
sync_callback_func(struct getdns_context *context, struct ub_result* ub_res = NULL;
uint16_t callback_type, getdns_return_t gr = GETDNS_RETURN_GOOD;
struct getdns_dict *response, getdns_network_req *netreq = req->first_req;
void *userarg, getdns_transaction_t transaction_id) while (netreq) {
{ int r = ub_resolve(req->context->unbound_ctx,
req->name,
*((struct getdns_dict **) userarg) = response; netreq->request_type,
netreq->request_class,
&ub_res);
if (r != 0) {
return GETDNS_RETURN_GENERIC_ERROR;
}
gr = getdns_apply_network_result(netreq, ub_res);
ub_resolve_free(ub_res);
ub_res = NULL;
if (gr != GETDNS_RETURN_GOOD) {
return gr;
}
netreq = netreq->next;
}
return gr;
} }
getdns_return_t getdns_return_t
@ -73,12 +82,22 @@ getdns_general_sync(struct getdns_context *context,
RETURN_IF_NULL(response, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(response, GETDNS_RETURN_INVALID_PARAMETER);
response_status = validate_extensions(extensions); response_status = validate_extensions(extensions);
if (response_status == GETDNS_RETURN_GOOD) { if (response_status == GETDNS_RETURN_GOOD) {
response_status = getdns_general_ub(context->unbound_sync, /* for each netreq we call ub_ctx_resolve */
context->event_base_sync, /* request state */
context, name, request_type, getdns_dns_req *req = dns_req_new(context,
extensions, (void *) response, NULL, sync_callback_func); name,
request_type,
event_base_dispatch(context->event_base_sync); extensions);
if (!req) {
return GETDNS_RETURN_GENERIC_ERROR;
}
response_status = submit_request_sync(req);
if (response_status != GETDNS_RETURN_GOOD) {
dns_req_free(req);
return response_status;
}
*response = create_getdns_response(req);
dns_req_free(req);
} }
return response_status; return response_status;
} }

View File

@ -9,7 +9,7 @@
/* /*
* Copyright (c) 2013, Versign, Inc. * Copyright (c) 2013, Versign, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
@ -99,9 +99,6 @@ struct getdns_context;
/* declarations */ /* declarations */
struct getdns_dns_req; struct getdns_dns_req;
struct getdns_network_req; struct getdns_network_req;
struct ub_ctx;
struct event;
struct event_base;
typedef enum network_req_state_enum typedef enum network_req_state_enum
{ {
@ -164,21 +161,9 @@ typedef struct getdns_dns_req
/* first request in list */ /* first request in list */
struct getdns_network_req *first_req; struct getdns_network_req *first_req;
/* request timeout event */
struct event *timeout;
/* local callback timer */
struct event *local_cb_timer;
/* event base this req is scheduled on */
struct event_base *ev_base;
/* context that owns the request */ /* context that owns the request */
struct getdns_context *context; struct getdns_context *context;
/* ub_ctx issuing the request */
struct ub_ctx *unbound;
/* request extensions */ /* request extensions */
struct getdns_dict *extensions; struct getdns_dict *extensions;
@ -246,7 +231,6 @@ getdns_network_req *network_req_new(getdns_dns_req * owner,
/* dns request utils */ /* dns request utils */
getdns_dns_req *dns_req_new(struct getdns_context *context, getdns_dns_req *dns_req_new(struct getdns_context *context,
struct ub_ctx *unbound,
const char *name, uint16_t request_type, struct getdns_dict *extensions); const char *name, uint16_t request_type, struct getdns_dict *extensions);
void dns_req_free(getdns_dns_req * req); void dns_req_free(getdns_dns_req * req);

View File

@ -11,7 +11,7 @@
/* /*
* Copyright (c) 2013, Versign, Inc. * Copyright (c) 2013, Versign, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
@ -41,6 +41,7 @@
#include "list.h" #include "list.h"
#include "util-internal.h" #include "util-internal.h"
#include "types-internal.h" #include "types-internal.h"
#include <unbound.h>
/** /**
* this is a comprehensive list of extensions and their data types * this is a comprehensive list of extensions and their data types
@ -374,7 +375,7 @@ add_only_addresses(struct getdns_list * addrs, ldns_rr_list * rr_list)
int r = GETDNS_RETURN_GOOD; int r = GETDNS_RETURN_GOOD;
size_t i = 0; size_t i = 0;
size_t item_idx = 0; size_t item_idx = 0;
r = getdns_list_get_length(addrs, &item_idx); r = getdns_list_get_length(addrs, &item_idx);
for (i = 0; r == GETDNS_RETURN_GOOD && for (i = 0; r == GETDNS_RETURN_GOOD &&
i < ldns_rr_list_rr_count(rr_list); ++i) { i < ldns_rr_list_rr_count(rr_list); ++i) {
@ -405,7 +406,7 @@ add_only_addresses(struct getdns_list * addrs, ldns_rr_list * rr_list)
? &IPv4_str_bindata : &IPv6_str_bindata)); ? &IPv4_str_bindata : &IPv6_str_bindata));
r |= getdns_dict_set_bindata(this_address, r |= getdns_dict_set_bindata(this_address,
GETDNS_STR_ADDRESS_DATA, &rbin); GETDNS_STR_ADDRESS_DATA, &rbin);
r |= getdns_list_set_dict(addrs, item_idx++, r |= getdns_list_set_dict(addrs, item_idx++,
this_address); this_address);
getdns_dict_destroy(this_address); getdns_dict_destroy(this_address);
} }
@ -418,7 +419,7 @@ create_reply_dict(struct getdns_context *context, getdns_network_req * req,
struct getdns_list * just_addrs) struct getdns_list * just_addrs)
{ {
/* turn a packet into this glorious structure /* turn a packet into this glorious structure
* *
* { # This is the first reply * { # This is the first reply
* "header": { "id": 23456, "qr": 1, "opcode": 0, ... }, * "header": { "id": 23456, "qr": 1, "opcode": 0, ... },
* "question": { "qname": <bindata for "www.example.com">, "qtype": 1, "qclass": 1 }, * "question": { "qname": <bindata for "www.example.com">, "qtype": 1, "qclass": 1 },
@ -454,7 +455,7 @@ create_reply_dict(struct getdns_context *context, getdns_network_req * req,
* "canonical_name": <bindata for "www.example.com">, * "canonical_name": <bindata for "www.example.com">,
* "answer_type": GETDNS_NAMETYPE_DNS * "answer_type": GETDNS_NAMETYPE_DNS
* } * }
* *
*/ */
int r = 0; int r = 0;
ldns_pkt *reply = req->result; ldns_pkt *reply = req->result;
@ -677,4 +678,20 @@ validate_extensions(struct getdns_dict * extensions)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* validate_extensions */ } /* validate_extensions */
getdns_return_t getdns_apply_network_result(getdns_network_req* netreq,
struct ub_result* ub_res) {
ldns_buffer *result = ldns_buffer_new(ub_res->answer_len);
if (!result) {
return GETDNS_RETURN_GENERIC_ERROR;
}
ldns_buffer_new_frm_data(result, ub_res->answer_packet, ub_res->answer_len);
ldns_status r =
ldns_buffer2pkt_wire(&(netreq->result), result);
ldns_buffer_free(result);
if (r != LDNS_STATUS_OK) {
return GETDNS_RETURN_GENERIC_ERROR;
}
return GETDNS_RETURN_GOOD;
}
/* util-internal.c */ /* util-internal.c */

View File

@ -10,7 +10,7 @@
/* /*
* Copyright (c) 2013, Versign, Inc. * Copyright (c) 2013, Versign, Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
@ -41,6 +41,10 @@
#include <ldns/ldns.h> #include <ldns/ldns.h>
#include "context.h" #include "context.h"
struct ub_result;
struct getdns_network_req;
getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, struct ub_result* result);
/** /**
* add an item to the tail of a list - note that this was not in the getdns API * add an item to the tail of a list - note that this was not in the getdns API
* description but the list_set functions seem to be designed to modify an existing * description but the list_set functions seem to be designed to modify an existing