tres

All Top-level Files
Login

Files in the top-level directory in any check-in


"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)`