async dns

Marc Lehmann schmorp at
Mon Mar 16 22:09:55 CET 2009

On Sun, Mar 15, 2009 at 09:59:28AM +0100, Ryan Dahl <ry at> wrote:
> Is anyone doing DNS lookups with libev?

Oh yes, via AnyEvent::DNS and EV::ADNS :)

> Do you use Ian Jackson's adns?
> Perhaps you have some code you can share?

apart form what others might say, a few comments thta might or might not be

EV::ADNS (the perl module) has C code to integrate libadns into ev.

libadns is a fine library, but:

a) it doesn't support cname-to-cname (which is illegal, but unfortunately,
   with google relying on it, there is little to do) - so cname resolution
   has to be done manually (which is possible).
b) it seemingly lacks support for ipv6, but in fact, it fully supports
   ipv6 (you just have to know how dns works...)
c) like many other "asynchronous resolvers" it is of course fully synchronous
   and even blockign when it has to fall back to e.g. virtual circuit mode
   (for large replies). this is not uncommon.

If despite this, you still want to use adns (which is still a fine
library), below is some sample code (in perl, however), which implements
cname resolution and ipv6 support on top of adns.

(BTW, I did investigate quite a few other resolvers, and they usually had
a worse API or similar issues - I would actually recommend using libeio's
thread pool and using a custom getaddrinfo call - this way, your resolver
will actually be compatible with other programs, which is good for a few
dozen or so concurent resolves. All alternative resolver suffer form minor
to major incompatibilities to system resolvers, such as not resolving
hostnames users expect to be resolved, or using ipv6 when ipv4 should be
preferred etc.).

   } elsif (&has_ev_adns) {
      # work around some idiotic adns rfc readings
      # rather hackish support for AAAA records

      my $loop = 10; # follow cname chains up to this length
      my $qt;
      my $acb; $acb = sub {
         my ($status, undef, @a) = @_;

         if ($status == &EV::ADNS::s_ok) {
            if ($qt eq "a") {
               return $cb->(Socket::inet_aton $a[0]);
            } elsif ($qt eq "aaaa") {
               return $cb->($a[0]);
            } elsif ($qt eq "cname") {
               $name = $a[0];
               $qt = "a";
               return EV::ADNS::submit ($name, &EV::ADNS::r_a, 0, $acb);
         } elsif ($status == &EV::ADNS::s_prohibitedcname) {
            # follow cname chains
            if ($loop--) {
               $qt = "cname";
               return EV::ADNS::submit ($name, &EV::ADNS::r_cname, 0, $acb);
         } elsif ($status == &EV::ADNS::s_nodata) {
            if ($qt eq "a") {
               # ask for raw AAAA
               $qt = "aaaa";
               return EV::ADNS::submit ($name, &EV::ADNS::r_unknown | 28, 0, $acb);


      $qt = "a";
      EV::ADNS::submit ($name, &EV::ADNS::r_a, 0, $acb);

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_    
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      pcg at
      -=====/_/_//_/\_,_/ /_/\_\

More information about the libev mailing list