From 253d425ca8753bd8c7e2426d1360d73f104c161d Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Thu, 26 Sep 2013 08:34:14 +0000 Subject: [PATCH] - unbound-event.h is installed if configured --with-libevent. It contains low-level library calls, that use libevent's event_base and an ldns_buffer for the wire return packet to perform async resolution in the client's eventloop. git-svn-id: file:///svn/unbound/trunk@2970 be551aaa-1e26-0410-a405-d3ace91eadb9 --- Makefile.in | 13 +++- configure | 6 ++ configure.ac | 2 + daemon/worker.c | 7 +++ doc/Changelog | 6 ++ libunbound/context.h | 6 ++ libunbound/libunbound.c | 109 +++++++++++++++++++++++++------- libunbound/libworker.c | 105 ++++++++++++++++++++++++++++--- libunbound/libworker.h | 30 +++++++++ libunbound/ubsyms.def | 2 + libunbound/unbound-event.h | 125 +++++++++++++++++++++++++++++++++++++ smallapp/worker_cb.c | 7 +++ util/fptr_wlist.c | 1 + util/netevent.c | 31 +++++++++ util/netevent.h | 15 +++++ 15 files changed, 434 insertions(+), 31 deletions(-) create mode 100644 libunbound/unbound-event.h diff --git a/Makefile.in b/Makefile.in index bb1643010..ea4370408 100644 --- a/Makefile.in +++ b/Makefile.in @@ -30,6 +30,8 @@ PYTHONMOD_INSTALL=@PYTHONMOD_INSTALL@ PYTHONMOD_UNINSTALL=@PYTHONMOD_UNINSTALL@ PYUNBOUND_INSTALL=@PYUNBOUND_INSTALL@ PYUNBOUND_UNINSTALL=@PYUNBOUND_UNINSTALL@ +UNBOUND_EVENT_INSTALL=@UNBOUND_EVENT_INSTALL@ +UNBOUND_EVENT_UNINSTALL=@UNBOUND_EVENT_UNINSTALL@ UNBOUND_VERSION_MAJOR=@UNBOUND_VERSION_MAJOR@ UNBOUND_VERSION_MINOR=@UNBOUND_VERSION_MINOR@ UNBOUND_VERSION_MICRO=@UNBOUND_VERSION_MICRO@ @@ -455,7 +457,11 @@ pyunbound-install: $(LIBTOOL) --mode=install cp _unbound.la $(DESTDIR)$(PYTHON_SITE_PKG) $(LIBTOOL) --mode=finish $(DESTDIR)$(PYTHON_SITE_PKG) -install: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) +unbound-event-install: + $(INSTALL) -m 755 -d $(DESTDIR)$(includedir) + $(LIBTOOL) --mode=install cp $(srcdir)/libunbound/unbound-event.h $(DESTDIR)$(includedir)/unbound-event.h + +install: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) $(UNBOUND_EVENT_INSTALL) $(INSTALL) -m 755 -d $(DESTDIR)$(sbindir) $(INSTALL) -m 755 -d $(DESTDIR)$(mandir) $(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8 @@ -500,7 +506,10 @@ pyunbound-uninstall: rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(PYTHON_SITE_PKG)/_unbound.la -uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL) +unbound-event-uninstall: + rm -f -- $(DESTDIR)$(includedir)/unbound-event.h + +uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL) $(UNBOUND_EVENT_UNINSTALL) rm -f -- $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control-setup rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8 $(DESTDIR)$(mandir)/man8/unbound-anchor.8 $(DESTDIR)$(mandir)/man8/unbound-control-setup.8 rm -f -- $(DESTDIR)$(mandir)/man1/unbound-host.1 $(DESTDIR)$(mandir)/man3/libunbound.3 diff --git a/configure b/configure index 8a18c3c42..daf78e944 100755 --- a/configure +++ b/configure @@ -651,6 +651,8 @@ WINAPPS WINDRES CHECKLOCK_OBJ staticexe +UNBOUND_EVENT_UNINSTALL +UNBOUND_EVENT_INSTALL HAVE_SSL CONFIG_DATE NETBSD_LINTFLAGS @@ -17245,6 +17247,10 @@ done if test -n "$BAK_LDFLAGS_SET"; then LDFLAGS="$BAK_LDFLAGS" fi + UNBOUND_EVENT_INSTALL=unbound-event-install + + UNBOUND_EVENT_UNINSTALL=unbound-event-uninstall + else $as_echo "#define USE_MINI_EVENT 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index c9db08ac5..b0ee08c9c 100644 --- a/configure.ac +++ b/configure.ac @@ -802,6 +802,8 @@ large outgoing port ranges. ]) if test -n "$BAK_LDFLAGS_SET"; then LDFLAGS="$BAK_LDFLAGS" fi + AC_SUBST(UNBOUND_EVENT_INSTALL, [unbound-event-install]) + AC_SUBST(UNBOUND_EVENT_UNINSTALL, [unbound-event-uninstall]) else AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events]) fi diff --git a/daemon/worker.c b/daemon/worker.c index 37d019dff..c7620962c 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1354,6 +1354,13 @@ void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), log_assert(0); } +void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), + ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), + char* ATTR_UNUSED(why_bogus)) +{ + log_assert(0); +} + int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) { log_assert(0); diff --git a/doc/Changelog b/doc/Changelog index e9c39a69e..523f0973a 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,9 @@ +26 Sep 2013: Wouter + - unbound-event.h is installed if configured --with-libevent. It + contains low-level library calls, that use libevent's event_base + and an ldns_buffer for the wire return packet to perform async + resolution in the client's eventloop. + 19 Sep 2013: Wouter - 1.4.21 tag created. - trunk has 1.4.22 number inside it. diff --git a/libunbound/context.h b/libunbound/context.h index 23db869ac..4447b02eb 100644 --- a/libunbound/context.h +++ b/libunbound/context.h @@ -48,6 +48,7 @@ #include "util/data/packed_rrset.h" struct libworker; struct tube; +struct event_base; /** * The context structure @@ -111,6 +112,11 @@ struct ub_ctx { /** random state used to seed new random state structures */ struct ub_randstate* seed_rnd; + /** event base for event oriented interface */ + struct event_base* event_base; + /** libworker for event based interface */ + struct libworker* event_worker; + /** next query number (to try) to use */ int next_querynum; /** number of async queries outstanding */ diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index 999478ef3..847ac1a54 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -43,6 +43,7 @@ /* include the public api first, it should be able to stand alone */ #include "libunbound/unbound.h" +#include "libunbound/unbound-event.h" #include "config.h" #include #include "libunbound/context.h" @@ -69,8 +70,8 @@ #include #endif /* UB_ON_WINDOWS */ -struct ub_ctx* -ub_ctx_create(void) +/** create context functionality, but no pipes */ +static struct ub_ctx* ub_ctx_create_nopipe(void) { struct ub_ctx* ctx; unsigned int seed; @@ -105,28 +106,11 @@ ub_ctx_create(void) return NULL; } seed = 0; - if((ctx->qq_pipe = tube_create()) == NULL) { - int e = errno; - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = e; - return NULL; - } - if((ctx->rr_pipe = tube_create()) == NULL) { - int e = errno; - tube_delete(ctx->qq_pipe); - ub_randfree(ctx->seed_rnd); - free(ctx); - errno = e; - return NULL; - } lock_basic_init(&ctx->qqpipe_lock); lock_basic_init(&ctx->rrpipe_lock); lock_basic_init(&ctx->cfglock); ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env)); if(!ctx->env) { - tube_delete(ctx->qq_pipe); - tube_delete(ctx->rr_pipe); ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; @@ -134,8 +118,6 @@ ub_ctx_create(void) } ctx->env->cfg = config_create_forlib(); if(!ctx->env->cfg) { - tube_delete(ctx->qq_pipe); - tube_delete(ctx->rr_pipe); free(ctx->env); ub_randfree(ctx->seed_rnd); free(ctx); @@ -150,6 +132,50 @@ ub_ctx_create(void) return ctx; } +struct ub_ctx* +ub_ctx_create(void) +{ + struct ub_ctx* ctx = ub_ctx_create_nopipe(); + if(!ctx) + return NULL; + if((ctx->qq_pipe = tube_create()) == NULL) { + int e = errno; + ub_randfree(ctx->seed_rnd); + config_delete(ctx->env->cfg); + modstack_desetup(&ctx->mods, ctx->env); + free(ctx->env); + free(ctx); + errno = e; + return NULL; + } + if((ctx->rr_pipe = tube_create()) == NULL) { + int e = errno; + tube_delete(ctx->qq_pipe); + ub_randfree(ctx->seed_rnd); + config_delete(ctx->env->cfg); + modstack_desetup(&ctx->mods, ctx->env); + free(ctx->env); + free(ctx); + errno = e; + return NULL; + } + return ctx; +} + +struct ub_ctx* +ub_ctx_create_event(struct event_base* eb) +{ + struct ub_ctx* ctx = ub_ctx_create_nopipe(); + if(!ctx) + return NULL; + /* no pipes, but we have the locks to make sure everything works */ + ctx->created_bg = 0; + ctx->dothread = 1; /* the processing is in the same process, + makes ub_cancel and ub_ctx_delete do the right thing */ + ctx->event_base = eb; + return ctx; +} + /** delete q */ static void delq(rbnode_t* n, void* ATTR_UNUSED(arg)) @@ -218,6 +244,7 @@ ub_ctx_delete(struct ub_ctx* ctx) #endif /* HAVE_PTHREAD */ if(do_stop) ub_stop_bg(ctx); + libworker_delete_event(ctx->event_worker); modstack_desetup(&ctx->mods, ctx->env); a = ctx->alloc_list; @@ -612,6 +639,46 @@ ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype, return UB_NOERROR; } +int +ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, + int rrclass, void* mydata, ub_event_callback_t callback, int* async_id) +{ + struct ctx_query* q; + int r; + + if(async_id) + *async_id = 0; + lock_basic_lock(&ctx->cfglock); + if(!ctx->finalized) { + int r = context_finalize(ctx); + if(r) { + lock_basic_unlock(&ctx->cfglock); + return r; + } + } + if(!ctx->event_worker) { + ctx->event_worker = libworker_create_event(ctx, + ctx->event_base); + if(!ctx->event_worker) { + lock_basic_unlock(&ctx->cfglock); + return UB_INITFAIL; + } + } + lock_basic_unlock(&ctx->cfglock); + + /* create new ctx_query and attempt to add to the list */ + q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback, + mydata); + if(!q) + return UB_NOMEM; + + /* attach to mesh */ + if((r=libworker_attach_mesh(ctx, q, async_id)) != 0) + return r; + return UB_NOERROR; +} + + int ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, void* mydata, ub_callback_t callback, int* async_id) diff --git a/libunbound/libworker.c b/libunbound/libworker.c index 8f2aa489c..313b41680 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -50,6 +50,7 @@ #include "libunbound/libworker.h" #include "libunbound/context.h" #include "libunbound/unbound.h" +#include "libunbound/unbound-event.h" #include "services/outside_network.h" #include "services/mesh.h" #include "services/localzone.h" @@ -73,11 +74,10 @@ /** handle new query command for bg worker */ static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len); -/** delete libworker struct */ +/** delete libworker env */ static void -libworker_delete(struct libworker* w) +libworker_delete_env(struct libworker* w) { - if(!w) return; if(w->env) { outside_network_quit_prepare(w->back); mesh_delete(w->env->mesh); @@ -94,13 +94,30 @@ libworker_delete(struct libworker* w) SSL_CTX_free(w->sslctx); #endif outside_network_delete(w->back); +} + +/** delete libworker struct */ +static void +libworker_delete(struct libworker* w) +{ + if(!w) return; + libworker_delete_env(w); comm_base_delete(w->base); free(w); } +void +libworker_delete_event(struct libworker* w) +{ + if(!w) return; + libworker_delete_env(w); + comm_base_delete_no_base(w->base); + free(w); +} + /** setup fresh libworker struct */ static struct libworker* -libworker_setup(struct ub_ctx* ctx, int is_bg) +libworker_setup(struct ub_ctx* ctx, int is_bg, struct event_base* eb) { unsigned int seed; struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); @@ -188,7 +205,9 @@ libworker_setup(struct ub_ctx* ctx, int is_bg) } seed = 0; - w->base = comm_base_create(0); + if(eb) + w->base = comm_base_create_event(eb); + else w->base = comm_base_create(0); if(!w->base) { libworker_delete(w); return NULL; @@ -233,6 +252,12 @@ libworker_setup(struct ub_ctx* ctx, int is_bg) return w; } +struct libworker* libworker_create_event(struct ub_ctx* ctx, + struct event_base* eb) +{ + return libworker_setup(ctx, 0, eb); +} + /** handle cancel command for bg worker */ static void handle_cancel(struct libworker* w, uint8_t* buf, uint32_t len) @@ -349,7 +374,7 @@ int libworker_bg(struct ub_ctx* ctx) lock_basic_lock(&ctx->cfglock); if(ctx->dothread) { lock_basic_unlock(&ctx->cfglock); - w = libworker_setup(ctx, 1); + w = libworker_setup(ctx, 1, NULL); if(!w) return UB_NOMEM; w->is_bg_thread = 1; #ifdef ENABLE_LOCK_CHECKS @@ -364,7 +389,7 @@ int libworker_bg(struct ub_ctx* ctx) #else /* HAVE_FORK */ switch((ctx->bg_pid=fork())) { case 0: - w = libworker_setup(ctx, 1); + w = libworker_setup(ctx, 1, NULL); if(!w) fatal_exit("out of memory"); /* close non-used parts of the pipes */ tube_close_write(ctx->qq_pipe); @@ -571,7 +596,7 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q, int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) { - struct libworker* w = libworker_setup(ctx, 0); + struct libworker* w = libworker_setup(ctx, 0, NULL); uint16_t qflags, qid; struct query_info qinfo; struct edns_data edns; @@ -611,6 +636,70 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) return UB_NOERROR; } +void +libworker_event_done_cb(void* arg, int rcode, ldns_buffer* buf, + enum sec_status s, char* why_bogus) +{ + struct ctx_query* q = (struct ctx_query*)arg; + ub_event_callback_t cb = (ub_event_callback_t)q->cb; + void* cb_arg = q->cb_arg; + + /* delete it now */ + struct ub_ctx* ctx = q->w->ctx; + lock_basic_lock(&ctx->cfglock); + (void)rbtree_delete(&ctx->queries, q->node.key); + ctx->num_async--; + context_query_delete(q); + lock_basic_unlock(&ctx->cfglock); + + if(!q->cancelled) { + /* call callback */ + int sec = 0; + if(s == sec_status_bogus) + sec = 1; + else if(s == sec_status_secure) + sec = 2; + (*cb)(cb_arg, rcode, (void*)buf, sec, why_bogus); + } +} + +int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, + int* async_id) +{ + struct libworker* w = ctx->event_worker; + uint16_t qflags, qid; + struct query_info qinfo; + struct edns_data edns; + if(!w) + return UB_INITFAIL; + if(!setup_qinfo_edns(w, q, &qinfo, &edns)) + return UB_SYNTAX; + qid = 0; + qflags = BIT_RD; + q->w = w; + /* see if there is a fixed answer */ + ldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); + ldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); + if(local_zones_answer(ctx->local_zones, &qinfo, &edns, + w->back->udp_buff, w->env->scratch)) { + regional_free_all(w->env->scratch); + free(qinfo.qname); + libworker_event_done_cb(q, LDNS_RCODE_NOERROR, + w->back->udp_buff, sec_status_insecure, NULL); + return UB_NOERROR; + } + /* process new query */ + if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, + w->back->udp_buff, qid, libworker_event_done_cb, q)) { + free(qinfo.qname); + return UB_NOMEM; + } + free(qinfo.qname); + if(async_id) + *async_id = q->querynum; + return UB_NOERROR; +} + /** add result to the bg worker result queue */ static void add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt, diff --git a/libunbound/libworker.h b/libunbound/libworker.h index c3896fc5a..66644a90f 100644 --- a/libunbound/libworker.h +++ b/libunbound/libworker.h @@ -57,6 +57,7 @@ struct comm_point; struct comm_reply; struct regional; struct tube; +struct event_base; /** * The library-worker status structure @@ -106,6 +107,31 @@ int libworker_bg(struct ub_ctx* ctx); */ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q); +/** + * create worker for event-based interface. + * @param ctx: context with config. + * @param eb: event base. + * @return new worker or NULL. + */ +struct libworker* libworker_create_event(struct ub_ctx* ctx, + struct event_base* eb); + +/** + * Attach context_query to mesh for callback in event-driven setup. + * @param ctx: context + * @param q: context query entry + * @param async_id: store query num if query takes long. + * @return 0 if finished OK, else error. + */ +int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, + int* async_id); + +/** + * delete worker for event-based interface. does not free the event_base. + * @param w: event-based worker to delete. + */ +void libworker_delete_event(struct libworker* w); + /** cleanup the cache to remove all rrset IDs from it, arg is libworker */ void libworker_alloc_cleanup(void* arg); @@ -155,6 +181,10 @@ void libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, void libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s, char* why_bogus); +/** mesh callback with event results */ +void libworker_event_done_cb(void* arg, int rcode, ldns_buffer* buf, + enum sec_status s, char* why_bogus); + /** * fill result from parsed message, on error fills servfail * @param res: is clear at start, filled in at end. diff --git a/libunbound/ubsyms.def b/libunbound/ubsyms.def index 7e3fdd1e2..26040921b 100644 --- a/libunbound/ubsyms.def +++ b/libunbound/ubsyms.def @@ -1,4 +1,5 @@ ub_ctx_create +ub_ctx_create_event ub_ctx_delete ub_ctx_get_option ub_ctx_set_option @@ -18,6 +19,7 @@ ub_fd ub_process ub_resolve ub_resolve_async +ub_resolve_event ub_cancel ub_resolve_free ub_strerror diff --git a/libunbound/unbound-event.h b/libunbound/unbound-event.h new file mode 100644 index 000000000..bbc956f11 --- /dev/null +++ b/libunbound/unbound-event.h @@ -0,0 +1,125 @@ +/* + * unbound-event.h - unbound validating resolver public API with events + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains the unbound interface for use with libevent. + * You have to use the same libevent that unbound was compiled with, + * otherwise it wouldn't work, the event and event_base structures would + * be different. If unbound is compiled without libevent support then + * this header file is not supposed to be installed on the system. + * + * TODO + * Use ub_ctx_create_event_base() to create an unbound context that uses + * the event base that you have made. Then, use the ub_resolve_event call + * to add DNS resolve queries to the context. Those then run when you + * call event_dispatch() on your event_base, and when they are done you + * get a function callback. + * + * This method does not fork another process or create a thread, the effort + * is done by the unbound state machines that are connected to the event_base. + */ +#ifndef _UB_UNBOUND_EVENT_H +#define _UB_UNBOUND_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct ub_ctx; +struct ub_result; +struct event_base; +struct ldns_buffer; + +typedef void (*ub_event_callback_t)(void*, int, struct ldns_buffer*, int, char*); + +/** + * Create a resolving and validation context. + * The information from /etc/resolv.conf and /etc/hosts is not utilised by + * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. + * @param base: the event base that the caller has created. The unbound + * context uses this event base. + * @return a new context. default initialisation. + * returns NULL on error. + * You must use ub_resolve_event with this context. + * Do not call ub_ctx_async, ub_poll, ub_wait, ub_process, this is all done + * with the event_base. Setup the options you like with the other functions. + */ +struct ub_ctx* ub_ctx_create_event(struct event_base* base); + +/** + * Perform resolution and validation of the target name. + * Asynchronous, after a while, the callback will be called with your + * data and the result. Uses the event_base user installed by creating the + * context with ub_ctx_create_event(). + * @param ctx: context with event_base in it. + * The context is finalized, and can no longer accept all config changes. + * @param name: domain name in text format (a string). + * @param rrtype: type of RR in host order, 1 is A. + * @param rrclass: class of RR in host order, 1 is IN (for internet). + * @param mydata: this data is your own data (you can pass NULL), + * and is passed on to the callback function. + * @param callback: this is called on completion of the resolution. + * It is called as: + * void callback(void* mydata, int rcode, ldns_buffer* packet, int sec, + * char* why_bogus) + * with mydata: the same as passed here, you may pass NULL, + * with rcode: 0 on no error, nonzero for mostly SERVFAIL situations, + * this is a DNS rcode. + * with packet: ldns_buffer of a DNS wireformat packet with the answer. + * do not inspect if rcode != 0. + * with sec: 0 if insecure, 1 if bogus, 2 if DNSSEC secure. + * with why_bogus: text string explaining why it is bogus (or NULL). + * These point to buffers inside unbound; do not deallocate the packet or + * error string. + * + * If an error happens during processing, your callback will be called + * with error set to a nonzero value (and result==NULL). + * For localdata (etc/hosts) the callback is called immediately, before + * resolve_event returns, async_id=0 is returned. + * @param async_id: if you pass a non-NULL value, an identifier number is + * returned for the query as it is in progress. It can be used to + * cancel the query. + * @return 0 if OK, else error. + */ +int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, + int rrclass, void* mydata, ub_event_callback_t callback, int* async_id); + +#ifdef __cplusplus +} +#endif + +#endif /* _UB_UNBOUND_H */ diff --git a/smallapp/worker_cb.c b/smallapp/worker_cb.c index bc37e3307..4fc2e7d90 100644 --- a/smallapp/worker_cb.c +++ b/smallapp/worker_cb.c @@ -179,6 +179,13 @@ void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), log_assert(0); } +void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode), + ldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s), + char* ATTR_UNUSED(why_bogus)) +{ + log_assert(0); +} + int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) { log_assert(0); diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 6bb95a531..537e3675a 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -388,6 +388,7 @@ int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr) { if(fptr == &libworker_fg_done_cb) return 1; else if(fptr == &libworker_bg_done_cb) return 1; + else if(fptr == &libworker_event_done_cb) return 1; else if(fptr == &probe_answer_cb) return 1; return 0; } diff --git a/util/netevent.c b/util/netevent.c index 193fa8714..c25d42c2d 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -234,6 +234,22 @@ comm_base_create(int sigs) return b; } +struct comm_base* comm_base_create_event(struct event_base* base) +{ + struct comm_base* b = (struct comm_base*)calloc(1, + sizeof(struct comm_base)); + if(!b) + return NULL; + b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); + if(!b->eb) { + free(b); + return NULL; + } + b->eb->base = base; + comm_base_now(b); + return b; +} + void comm_base_delete(struct comm_base* b) { @@ -257,6 +273,21 @@ comm_base_delete(struct comm_base* b) free(b); } +void +comm_base_delete_no_base(struct comm_base* b) +{ + if(!b) + return; + if(b->eb->slow_accept_enabled) { + if(event_del(&b->eb->slow_accept) != 0) { + log_err("could not event_del slow_accept"); + } + } + b->eb->base = NULL; + free(b->eb); + free(b); +} + void comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv) { diff --git a/util/netevent.h b/util/netevent.h index 86fa28569..f75c394d7 100644 --- a/util/netevent.h +++ b/util/netevent.h @@ -294,6 +294,21 @@ struct comm_signal { */ struct comm_base* comm_base_create(int sigs); +/** + * Create comm base that uses the given event_base (underlying event + * mechanism pointer). + * @param base: underlying lib event base. + * @return: the new comm base. NULL on error. + */ +struct comm_base* comm_base_create_event(struct event_base* base); + +/** + * Delete comm base structure but not the underlying lib event base. + * All comm points must have been deleted. + * @param b: the base to delete. + */ +void comm_base_delete_no_base(struct comm_base* b); + /** * Destroy a comm base. * All comm points must have been deleted. -- 2.47.2