Files in the top-level directory in any check-in
- ares.c
- CHANGES
- Makefile
- README
- TODO
"ares" is lightweight asynchronous resolver for POSIX systems, designed as a
first step to getting this functionality into portable scripting languages
(notably Tcl) without large code footprint or overhead. By which I mean
around 500 loc and 10k ELF executable.
The basic design uses pthreads. One dispatcher thread, managing N resolver
threads. Communication with the dispatcher is over a (AF_LOCAL) socket. The
dispatcher sits in a select() loop, forwarding requests to (spawned on demand)
threads. Resolvers use gethostbyname() and gethostbyaddr() to resolve the
given hostname to a set of IP address strings. Once spawned, resolver threads
wait around to be reused, or to be terminated by a special request to the
dispatcher. Client code only needs to be aware of a single socket, which can
be trivially integrated into a select() loop in your main program.
Threads are all created with detachstate=1, so they can be cleaned up by
closing file descriptors without having to call pthread_wait().
== Tested on ==
* Linux (Debian jessie, gcc + glibc)
* FreeBSD (10.1, clang)
== System Requirements ==
The following POSIX interfaces are assumed:
* libpthread, including pthread_setdetachstate() so we don't have to wait
* socketpair
* getnameinfo/getaddrinfo
== Internal Communication ==
Requests and responses are exchanged in length+value encoding, with the length
a uint16_t in host byte order and the value an (unterminated) ASCII string.
Two layers of communication are used: host program <-> dispatcher and
dispatcher <-> resolver. Both request and response strings must be no longer
than NI_HOSTMAX.
Dispatcher request:
| length | hostname |
Dispatcher response:
| length | hostname | length | ipaddr |
Resolver request:
| length | hostname |
Resolver responses:
| length | ipaddr |
Special cases:
* a 0-length request tells the dispatcher to kill all idle threads
* a 0-length ipaddr follows the final result for a given request
* dispatcher signals resolvers to shut down by closing their fd
* main signals dispatcher to shut down by closing its fd
== Out of Scope ==
This utility isn't very general, so it makes certain assumptions:
* responses are always strings from getaddrinfo(), and include IPv4 and v6
addresses without discrimination.
* getnameinfo flags are fixed at AF_UNSPEC + IPPROTO_TCP. The latter only
to ensure we do not get duplicate IP address responses for a hostname.
* getaddrinfo hints are fixed at AI_ADDRCONFIG.
* no support for IDN.
== Rejected Alternatives ==
* http://c-ares.haxx.se/: rolls its own resolv.conf parser, ignores
nsswitch, loads of code
* getaddrinfo_a: glibc-only, though it builds on POSIX sigevent/lio_listio
* asr.h: BSD's version. Also non-portable
* OpenMP: much, much nicer than pthread, and almost as available, but
unlike Tcl_Thread
Tcl users may be interested in Treso, which is more mature and complete and
knows how to use <asr.h> on BSD. When not using asr, Treso uses a single
thread (and pipe) per request and makes no attempt to cap the number of
threads spawned.
== Usage ==
Parameters are always const.
`int ares_init(int)`: takes a maximum number of resolver threads as a
parameter, and returns a file descriptor.
`void ares_request(int fd, char *hostname, int hlen)`