Hi,

As suggested by theo@, it is probably time to make the async resolver
API public, so that people can start using it.

So, here is a diff that does two things (will be committed separately).

First, move asr.h to include/ and install the manpages.  It only
exposes the API that has been in libc for a while now, so there is no
new symbol strictly speaking, but maybe it still deserves a minor bump.

The other thing is to add a simple wrapper to our libevent, so that
libevent programs can immediatly and easily benefit from the async
resolver.

You have to run "make includes" in /usr/src/include before building.

Comments welcome.

Eric.

Index: include/Makefile
===================================================================
RCS file: /cvs/src/include/Makefile,v
retrieving revision 1.181
diff -u -p -r1.181 Makefile
--- include/Makefile    8 Dec 2013 17:05:09 -0000       1.181
+++ include/Makefile    26 Dec 2013 16:50:20 -0000
@@ -9,7 +9,7 @@
 
 .include <bsd.own.mk>
 
-FILES= a.out.h ar.h assert.h bitstring.h blf.h bm.h bsd_auth.h \
+FILES= a.out.h ar.h asr.h assert.h bitstring.h blf.h bm.h bsd_auth.h \
        complex.h cpio.h ctype.h curses.h db.h dbm.h des.h dirent.h disktab.h \
        dlfcn.h elf_abi.h err.h errno.h fenv.h float.h fnmatch.h fstab.h fts.h \
        ftw.h getopt.h glob.h grp.h ifaddrs.h inttypes.h iso646.h kvm.h \
Index: include/asr.h
===================================================================
RCS file: include/asr.h
diff -N include/asr.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/asr.h       26 Dec 2013 16:50:20 -0000
@@ -0,0 +1,100 @@
+/*     $OpenBSD: asr.h,v 1.7 2013/07/12 14:36:21 eric Exp $    */
+/*
+ * Copyright (c) 2012 Eric Faurot <e...@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+/*
+ * This part is the generic API for the async mechanism.  It could be useful
+ * beyond the resolver.
+ */
+
+/* Return values for async_run() */
+#define ASYNC_COND     0 /* wait for fd condition */
+#define ASYNC_YIELD    1 /* partial result */
+#define ASYNC_DONE     2 /* done */
+
+/* Expected fd conditions  */
+#define ASYNC_READ     1
+#define ASYNC_WRITE    2
+
+/* This opaque structure holds an async query state. */
+struct async;
+
+/*
+ * This is the structure through which async_run() returns async
+ * results to the caller.
+ */
+struct async_res {
+       int      ar_cond;
+       int      ar_fd;
+       int      ar_timeout;
+
+       int      ar_errno;
+       int      ar_h_errno;
+       int      ar_gai_errno;
+       int      ar_rrset_errno;
+
+       int      ar_count;
+
+       int      ar_rcode;
+       void    *ar_data;
+       int      ar_datalen;
+       union {
+               struct sockaddr         sa;
+               struct sockaddr_in      sain;
+               struct sockaddr_in6     sain6;
+       }        ar_sa;
+
+       struct addrinfo  *ar_addrinfo;
+       struct rrsetinfo *ar_rrsetinfo;
+       struct hostent   *ar_hostent;
+       struct netent    *ar_netent;
+};
+
+int  asr_async_run(struct async *, struct async_res *);
+int  asr_async_run_sync(struct async *, struct async_res *);
+void asr_async_abort(struct async *);
+
+/* This opaque structure holds an async resolver context. */
+struct asr;
+
+struct asr *asr_resolver(const char *);
+void       asr_resolver_done(struct asr *);
+
+/* Async version of the resolver API */
+
+struct async *res_send_async(const unsigned char *, int, struct asr *);
+struct async *res_query_async(const char *, int, int, struct asr *);
+struct async *res_search_async(const char *, int, int, struct asr *);
+
+struct async *getrrsetbyname_async(const char *, unsigned int, unsigned int,
+    unsigned int, struct asr *);
+
+struct async *gethostbyname_async(const char *, struct asr *);
+struct async *gethostbyname2_async(const char *, int, struct asr *);
+struct async *gethostbyaddr_async(const void *, socklen_t, int, struct asr *);
+
+struct async *getnetbyname_async(const char *, struct asr *);
+struct async *getnetbyaddr_async(in_addr_t, int, struct asr *);
+
+struct async *getaddrinfo_async(const char *, const char *,
+    const struct addrinfo *, struct asr *);
+struct async *getnameinfo_async(const struct sockaddr *, socklen_t, char *,
+    size_t, char *, size_t, int, struct asr *);
Index: lib/libc/shlib_version
===================================================================
RCS file: /cvs/src/lib/libc/shlib_version,v
retrieving revision 1.157
diff -u -p -r1.157 shlib_version
--- lib/libc/shlib_version      17 Dec 2013 16:34:27 -0000      1.157
+++ lib/libc/shlib_version      26 Dec 2013 16:50:21 -0000
@@ -1,4 +1,4 @@
 major=72
-minor=0
+minor=1
 # note: If changes were made to include/thread_private.h or if system
 # calls were added/changed then librthread/shlib_version also be updated.
Index: lib/libc/asr/Makefile.inc
===================================================================
RCS file: /cvs/src/lib/libc/asr/Makefile.inc,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile.inc
--- lib/libc/asr/Makefile.inc   8 Aug 2013 06:55:42 -0000       1.6
+++ lib/libc/asr/Makefile.inc   26 Dec 2013 16:50:22 -0000
@@ -8,11 +8,13 @@ SRCS+=        asr.c asr_debug.c asr_utils.c \
        gethostnamadr_async.c getnetnamadr_async.c \
        getaddrinfo_async.c getnameinfo_async.c
 
-MLINKS+ = \
+MAN+=  asr_resolver.3
+
+MLINKS+= \
        asr_resolver.3  asr_resolver_done.3     \
        asr_resolver.3  asr_async_run.3         \
        asr_resolver.3  asr_async_run_sync.3    \
-       asr_resolver.3  asr_async_abort.3               \
+       asr_resolver.3  asr_async_abort.3       \
        asr_resolver.3  res_send_async.3        \
        asr_resolver.3  res_query_async.3       \
        asr_resolver.3  res_search_async.3      \
Index: lib/libc/asr/asr.h
===================================================================
RCS file: lib/libc/asr/asr.h
diff -N lib/libc/asr/asr.h
--- lib/libc/asr/asr.h  12 Jul 2013 14:36:21 -0000      1.7
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,100 +0,0 @@
-/*     $OpenBSD: asr.h,v 1.7 2013/07/12 14:36:21 eric Exp $    */
-/*
- * Copyright (c) 2012 Eric Faurot <e...@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-
-/*
- * This part is the generic API for the async mechanism.  It could be useful
- * beyond the resolver.
- */
-
-/* Return values for async_run() */
-#define ASYNC_COND     0 /* wait for fd condition */
-#define ASYNC_YIELD    1 /* partial result */
-#define ASYNC_DONE     2 /* done */
-
-/* Expected fd conditions  */
-#define ASYNC_READ     1
-#define ASYNC_WRITE    2
-
-/* This opaque structure holds an async query state. */
-struct async;
-
-/*
- * This is the structure through which async_run() returns async
- * results to the caller.
- */
-struct async_res {
-       int      ar_cond;
-       int      ar_fd;
-       int      ar_timeout;
-
-       int      ar_errno;
-       int      ar_h_errno;
-       int      ar_gai_errno;
-       int      ar_rrset_errno;
-
-       int      ar_count;
-
-       int      ar_rcode;
-       void    *ar_data;
-       int      ar_datalen;
-       union {
-               struct sockaddr         sa;
-               struct sockaddr_in      sain;
-               struct sockaddr_in6     sain6;
-       }        ar_sa;
-
-       struct addrinfo  *ar_addrinfo;
-       struct rrsetinfo *ar_rrsetinfo;
-       struct hostent   *ar_hostent;
-       struct netent    *ar_netent;
-};
-
-int  asr_async_run(struct async *, struct async_res *);
-int  asr_async_run_sync(struct async *, struct async_res *);
-void asr_async_abort(struct async *);
-
-/* This opaque structure holds an async resolver context. */
-struct asr;
-
-struct asr *asr_resolver(const char *);
-void       asr_resolver_done(struct asr *);
-
-/* Async version of the resolver API */
-
-struct async *res_send_async(const unsigned char *, int, struct asr *);
-struct async *res_query_async(const char *, int, int, struct asr *);
-struct async *res_search_async(const char *, int, int, struct asr *);
-
-struct async *getrrsetbyname_async(const char *, unsigned int, unsigned int,
-    unsigned int, struct asr *);
-
-struct async *gethostbyname_async(const char *, struct asr *);
-struct async *gethostbyname2_async(const char *, int, struct asr *);
-struct async *gethostbyaddr_async(const void *, socklen_t, int, struct asr *);
-
-struct async *getnetbyname_async(const char *, struct asr *);
-struct async *getnetbyaddr_async(in_addr_t, int, struct asr *);
-
-struct async *getaddrinfo_async(const char *, const char *,
-    const struct addrinfo *, struct asr *);
-struct async *getnameinfo_async(const struct sockaddr *, socklen_t, char *,
-    size_t, char *, size_t, int, struct asr *);
Index: lib/libevent/Makefile
===================================================================
RCS file: /cvs/src/lib/libevent/Makefile,v
retrieving revision 1.31
diff -u -p -r1.31 Makefile
--- lib/libevent/Makefile       2 Aug 2012 13:38:38 -0000       1.31
+++ lib/libevent/Makefile       26 Dec 2013 16:50:24 -0000
@@ -26,6 +26,8 @@ MLINKS=       event.3 bufferevent_base_set.3 \
        event.3 evbuffer_readline.3 \
        event.3 evbuffer_write.3 \
        event.3 event_add.3 \
+       event.3 event_async.3 \
+       event.3 event_async_cancel.3 \
        event.3 event_base_dispatch.3 \
        event.3 event_base_free.3 \
        event.3 event_base_loop.3 \
Index: lib/libevent/event.3
===================================================================
RCS file: /cvs/src/lib/libevent/event.3,v
retrieving revision 1.41
diff -u -p -r1.41 event.3
--- lib/libevent/event.3        22 Apr 2010 16:35:45 -0000      1.41
+++ lib/libevent/event.3        26 Dec 2013 16:50:25 -0000
@@ -45,6 +45,8 @@
 .Nm event_base_once ,
 .Nm event_pending ,
 .Nm event_initialized ,
+.Nm event_async ,
+.Nm event_async_cancel,
 .Nm event_priority_init ,
 .Nm event_priority_set ,
 .Nm evtimer_set ,
@@ -121,6 +123,10 @@
 .Fn "event_priority_init" "int npriorities"
 .Ft int
 .Fn "event_priority_set" "struct event *ev" "int priority"
+.Ft "struct event_async *"
+.Fn "event_async" "struct async *as" "void (*fn)(int, struct async_res *, void 
*)" "void *"
+.Ft void
+.Fn "event_async_cancel" "struct event_async *eva"
 .Ft void
 .Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void 
*arg"
 .Ft void
@@ -398,6 +404,39 @@ will proceed normally.
 .Pp
 It is the responsibility of the caller to provide these functions with
 pre-allocated event structures.
+.Sh ASYNC RESOLVER QUERIES
+This version of
+.Nm libevent
+provides helper functions to run asr async queries.
+.Pp
+The
+.Nm event_async
+function is used to setup the
+.Fa async
+query (created through the asr API) to run within
+.Nm libevent .
+All necessary events are handled internally.
+When the query is done, the user callback
+.Fa fn
+is called with the return value of the last call to
+.Xr asr_async_run 3 ,
+a structure filled with the result, and the user-provided data pointer
+.Fa arg .
+The caller is expected to clear the results as for
+.Xr asr_async_run 3 ,
+but the structure itself must not be freed.
+This functions returns an opaque handle to the internal
+.Nm libevent
+context for this query.
+.Pp
+The
+.Nm event_async_cancel
+function cancels the 
+.Fa eva
+async query context previously created with
+.Nm event_async .
+This function will abort the underlying async query.
+It must not be called if the callback has already been fired.
 .Sh EVENT PRIORITIES
 By default
 .Nm libevent
Index: lib/libevent/event.c
===================================================================
RCS file: /cvs/src/lib/libevent/event.c,v
retrieving revision 1.27
diff -u -p -r1.27 event.c
--- lib/libevent/event.c        17 Apr 2013 15:31:49 -0000      1.27
+++ lib/libevent/event.c        26 Dec 2013 16:50:26 -0000
@@ -52,6 +52,7 @@
 #include <string.h>
 #include <assert.h>
 #include <time.h>
+#include <asr.h>
 
 #include "event.h"
 #include "event-internal.h"
@@ -1032,4 +1033,71 @@ const char *
 event_get_method(void)
 {
        return (current_base->evsel->name);
+}
+
+/*
+ * libevent wrapper for asr async dns lookups
+ *
+ */
+
+struct event_async {
+       struct event     ev;
+       struct async    *async;
+       void            (*cb)(int, struct async_res *, void *);
+       void            *arg;
+};
+
+static void event_async_cb(int, short, void *);
+
+struct event_async *
+event_async(struct async * async, void (*cb)(int, struct async_res *, void *),
+    void *arg)
+{
+       struct event_async      *eva;
+       struct timeval           tv;
+
+       eva = calloc(1, sizeof *eva);
+       if (eva == NULL)
+               return (NULL);
+       eva->async = async;
+       eva->cb = cb;
+       eva->arg = arg;
+       tv.tv_sec = 0;
+       tv.tv_usec = 0;
+       evtimer_set(&eva->ev, event_async_cb, eva);
+       evtimer_add(&eva->ev, &tv);
+       return (eva);
+}
+
+void
+event_async_cancel(struct event_async *eva)
+{
+       event_del(&eva->ev);
+       asr_async_abort(eva->async);
+       free(eva);
+}
+
+static void
+event_async_cb(int fd, short ev, void *arg)
+{
+       struct event_async      *eva = arg;
+       struct async_res         ar;
+       int                      r;
+       struct timeval           tv;
+
+       while ((r = asr_async_run(eva->async, &ar)) == ASYNC_YIELD)
+               eva->cb(r, &ar, eva->arg);
+
+       event_del(&eva->ev);
+       if (r == ASYNC_COND) {
+               event_set(&eva->ev, ar.ar_fd,
+                   ar.ar_cond == ASYNC_READ ? EV_READ : EV_WRITE,
+                   event_async_cb, eva);
+               tv.tv_sec = ar.ar_timeout / 1000;
+               tv.tv_usec = (ar.ar_timeout % 1000) * 1000;
+               event_add(&eva->ev, &tv);
+       } else { /* ASYNC_DONE */
+               eva->cb(r, &ar, eva->arg);
+               free(eva);
+       }
 }
Index: lib/libevent/event.h
===================================================================
RCS file: /cvs/src/lib/libevent/event.h,v
retrieving revision 1.25
diff -u -p -r1.25 event.h
--- lib/libevent/event.h        28 Aug 2012 09:09:56 -0000      1.25
+++ lib/libevent/event.h        26 Dec 2013 16:50:27 -0000
@@ -702,6 +702,33 @@ int        event_base_priority_init(struct even
   */
 int    event_priority_set(struct event *, int);
 
+/* These functions are helpers to use the async */
+
+struct async;
+struct async_res;
+struct event_async;
+
+/**
+  Run an async resolver query within libevent.
+
+  @param async an async request built with the asr API
+  @param cb the function to call when the query is done
+  @param arg additionnal user data
+  @return NULL on error, a pointer to a libevent internal structure
+       representing the async query context
+  */
+struct event_async *event_async(struct async *,
+    void (*)(int, struct async_res *, void *), void *);
+
+/**
+  Cancel a running event_async query.
+
+  The underlying async query is also canceled.
+
+  @param eva a pointer to a async query event as returned by event_async()
+  */
+void event_async_cancel(struct event_async *);
+
 
 /* These functions deal with buffering input and output */
 
Index: lib/libevent/shlib_version
===================================================================
RCS file: /cvs/src/lib/libevent/shlib_version,v
retrieving revision 1.9
diff -u -p -r1.9 shlib_version
--- lib/libevent/shlib_version  13 Aug 2013 05:52:13 -0000      1.9
+++ lib/libevent/shlib_version  26 Dec 2013 16:50:27 -0000
@@ -1,2 +1,2 @@
 major=4
-minor=0
+minor=1

Reply via email to