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@
$(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
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
WINDRES
CHECKLOCK_OBJ
staticexe
+UNBOUND_EVENT_UNINSTALL
+UNBOUND_EVENT_INSTALL
HAVE_SSL
CONFIG_DATE
NETBSD_LINTFLAGS
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
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
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);
+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.
#include "util/data/packed_rrset.h"
struct libworker;
struct tube;
+struct event_base;
/**
* The context structure
/** 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 */
/* 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 <ctype.h>
#include "libunbound/context.h"
#include <iphlpapi.h>
#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;
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;
}
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);
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))
#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;
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)
#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"
/** 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);
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));
}
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;
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)
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
#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);
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;
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,
struct comm_reply;
struct regional;
struct tube;
+struct event_base;
/**
* The library-worker status structure
*/
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);
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.
ub_ctx_create
+ub_ctx_create_event
ub_ctx_delete
ub_ctx_get_option
ub_ctx_set_option
ub_process
ub_resolve
ub_resolve_async
+ub_resolve_event
ub_cancel
ub_resolve_free
ub_strerror
--- /dev/null
+/*
+ * 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 */
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);
{
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;
}
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)
{
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)
{
*/
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.