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