ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/DNS.pm
Revision: 1.109
Committed: Mon Jul 20 22:39:57 2009 UTC (14 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-4_86
Changes since 1.108: +1 -1 lines
Log Message:
4.86

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     AnyEvent::DNS - fully asynchronous DNS resolution
4    
5     =head1 SYNOPSIS
6    
7 root 1.57 use AnyEvent::DNS;
8    
9     my $cv = AnyEvent->condvar;
10     AnyEvent::DNS::a "www.google.de", $cv;
11     # ... later
12     my @addrs = $cv->recv;
13 root 1.26
14 root 1.1 =head1 DESCRIPTION
15    
16     This module offers both a number of DNS convenience functions as well
17     as a fully asynchronous and high-performance pure-perl stub resolver.
18    
19 root 1.46 The stub resolver supports DNS over IPv4 and IPv6, UDP and TCP, optional
20     EDNS0 support for up to 4kiB datagrams and automatically falls back to
21     virtual circuit mode for large responses.
22 root 1.12
23 root 1.1 =head2 CONVENIENCE FUNCTIONS
24    
25     =over 4
26    
27     =cut
28    
29     package AnyEvent::DNS;
30    
31 root 1.102 use Carp ();
32 root 1.29 use Socket qw(AF_INET SOCK_DGRAM SOCK_STREAM);
33    
34 root 1.107 use AnyEvent (); BEGIN { AnyEvent::common_sense }
35 root 1.37 use AnyEvent::Util qw(AF_INET6);
36 root 1.1
37 root 1.109 our $VERSION = 4.86;
38 root 1.39
39 root 1.32 our @DNS_FALLBACK = (v208.67.220.220, v208.67.222.222);
40    
41 root 1.4 =item AnyEvent::DNS::a $domain, $cb->(@addrs)
42    
43     Tries to resolve the given domain to IPv4 address(es).
44    
45 root 1.17 =item AnyEvent::DNS::aaaa $domain, $cb->(@addrs)
46    
47     Tries to resolve the given domain to IPv6 address(es).
48    
49 root 1.4 =item AnyEvent::DNS::mx $domain, $cb->(@hostnames)
50    
51     Tries to resolve the given domain into a sorted (lower preference value
52     first) list of domain names.
53    
54     =item AnyEvent::DNS::ns $domain, $cb->(@hostnames)
55    
56     Tries to resolve the given domain name into a list of name servers.
57    
58     =item AnyEvent::DNS::txt $domain, $cb->(@hostnames)
59    
60     Tries to resolve the given domain name into a list of text records.
61    
62     =item AnyEvent::DNS::srv $service, $proto, $domain, $cb->(@srv_rr)
63    
64     Tries to resolve the given service, protocol and domain name into a list
65     of service records.
66    
67 root 1.59 Each C<$srv_rr> is an array reference with the following contents:
68 root 1.4 C<[$priority, $weight, $transport, $target]>.
69    
70 root 1.49 They will be sorted with lowest priority first, then randomly
71     distributed by weight as per RFC 2782.
72 root 1.4
73     Example:
74    
75     AnyEvent::DNS::srv "sip", "udp", "schmorp.de", sub { ...
76     # @_ = ( [10, 10, 5060, "sip1.schmorp.de" ] )
77    
78 root 1.48 =item AnyEvent::DNS::ptr $domain, $cb->(@hostnames)
79    
80     Tries to make a PTR lookup on the given domain. See C<reverse_lookup>
81     and C<reverse_verify> if you want to resolve an IP address to a hostname
82     instead.
83    
84     =item AnyEvent::DNS::any $domain, $cb->(@rrs)
85    
86     Tries to resolve the given domain and passes all resource records found to
87     the callback.
88    
89     =item AnyEvent::DNS::reverse_lookup $ipv4_or_6, $cb->(@hostnames)
90 root 1.4
91     Tries to reverse-resolve the given IPv4 or IPv6 address (in textual form)
92 root 1.48 into it's hostname(s). Handles V4MAPPED and V4COMPAT IPv6 addresses
93     transparently.
94    
95     =item AnyEvent::DNS::reverse_verify $ipv4_or_6, $cb->(@hostnames)
96    
97     The same as C<reverse_lookup>, but does forward-lookups to verify that
98     the resolved hostnames indeed point to the address, which makes spoofing
99     harder.
100    
101     If you want to resolve an address into a hostname, this is the preferred
102     method: The DNS records could still change, but at least this function
103     verified that the hostname, at one point in the past, pointed at the IP
104     address you originally resolved.
105 root 1.4
106     Example:
107    
108     AnyEvent::DNS::ptr "2001:500:2f::f", sub { print shift };
109     # => f.root-servers.net
110    
111     =cut
112    
113 root 1.38 sub MAX_PKT() { 4096 } # max packet size we advertise and accept
114    
115     sub DOMAIN_PORT() { 53 } # if this changes drop me a note
116    
117 root 1.4 sub resolver;
118    
119     sub a($$) {
120     my ($domain, $cb) = @_;
121    
122     resolver->resolve ($domain => "a", sub {
123     $cb->(map $_->[3], @_);
124     });
125     }
126    
127 root 1.17 sub aaaa($$) {
128     my ($domain, $cb) = @_;
129    
130     resolver->resolve ($domain => "aaaa", sub {
131     $cb->(map $_->[3], @_);
132     });
133     }
134    
135 root 1.4 sub mx($$) {
136     my ($domain, $cb) = @_;
137    
138     resolver->resolve ($domain => "mx", sub {
139     $cb->(map $_->[4], sort { $a->[3] <=> $b->[3] } @_);
140     });
141     }
142    
143     sub ns($$) {
144     my ($domain, $cb) = @_;
145    
146     resolver->resolve ($domain => "ns", sub {
147     $cb->(map $_->[3], @_);
148     });
149     }
150    
151     sub txt($$) {
152     my ($domain, $cb) = @_;
153    
154     resolver->resolve ($domain => "txt", sub {
155     $cb->(map $_->[3], @_);
156     });
157     }
158    
159     sub srv($$$$) {
160     my ($service, $proto, $domain, $cb) = @_;
161    
162     # todo, ask for any and check glue records
163     resolver->resolve ("_$service._$proto.$domain" => "srv", sub {
164 root 1.49 my @res;
165    
166     # classify by priority
167     my %pri;
168     push @{ $pri{$_->[3]} }, [ @$_[3,4,5,6] ]
169     for @_;
170    
171     # order by priority
172 elmex 1.64 for my $pri (sort { $a <=> $b } keys %pri) {
173 root 1.49 # order by weight
174     my @rr = sort { $a->[1] <=> $b->[1] } @{ delete $pri{$pri} };
175    
176     my $sum; $sum += $_->[1] for @rr;
177    
178     while (@rr) {
179     my $w = int rand $sum + 1;
180     for (0 .. $#rr) {
181     if (($w -= $rr[$_][1]) <= 0) {
182     $sum -= $rr[$_][1];
183     push @res, splice @rr, $_, 1, ();
184     last;
185     }
186     }
187     }
188     }
189    
190     $cb->(@res);
191 root 1.4 });
192     }
193    
194     sub ptr($$) {
195 root 1.48 my ($domain, $cb) = @_;
196    
197     resolver->resolve ($domain => "ptr", sub {
198     $cb->(map $_->[3], @_);
199     });
200     }
201    
202     sub any($$) {
203     my ($domain, $cb) = @_;
204    
205     resolver->resolve ($domain => "*", $cb);
206     }
207    
208     # convert textual ip address into reverse lookup form
209     sub _munge_ptr($) {
210     my $ipn = $_[0]
211     or return;
212    
213     my $ptr;
214    
215     my $af = AnyEvent::Socket::address_family ($ipn);
216 root 1.4
217 root 1.48 if ($af == AF_INET6) {
218     $ipn = substr $ipn, 0, 16; # anticipate future expansion
219 root 1.4
220 root 1.48 # handle v4mapped and v4compat
221     if ($ipn =~ s/^\x00{10}(?:\xff\xff|\x00\x00)//) {
222     $af = AF_INET;
223     } else {
224     $ptr = join ".", (reverse split //, unpack "H32", $ipn), "ip6.arpa.";
225     }
226     }
227 root 1.37
228     if ($af == AF_INET) {
229 root 1.48 $ptr = join ".", (reverse unpack "C4", $ipn), "in-addr.arpa.";
230 root 1.4 }
231    
232 root 1.48 $ptr
233     }
234    
235     sub reverse_lookup($$) {
236     my ($ip, $cb) = @_;
237    
238     $ip = _munge_ptr AnyEvent::Socket::parse_address ($ip)
239     or return $cb->();
240    
241 root 1.17 resolver->resolve ($ip => "ptr", sub {
242 root 1.4 $cb->(map $_->[3], @_);
243     });
244     }
245 root 1.1
246 root 1.48 sub reverse_verify($$) {
247     my ($ip, $cb) = @_;
248    
249     my $ipn = AnyEvent::Socket::parse_address ($ip)
250     or return $cb->();
251    
252     my $af = AnyEvent::Socket::address_family ($ipn);
253    
254     my @res;
255     my $cnt;
256    
257     my $ptr = _munge_ptr $ipn
258     or return $cb->();
259    
260     $ip = AnyEvent::Socket::format_address ($ipn); # normalise into the same form
261    
262     ptr $ptr, sub {
263     for my $name (@_) {
264     ++$cnt;
265    
266     # () around AF_INET to work around bug in 5.8
267 root 1.55 resolver->resolve ("$name." => ($af == (AF_INET) ? "a" : "aaaa"), sub {
268 root 1.48 for (@_) {
269     push @res, $name
270     if $_->[3] eq $ip;
271     }
272     $cb->(@res) unless --$cnt;
273     });
274     }
275 root 1.5
276 root 1.48 $cb->() unless $cnt;
277     };
278 root 1.5 }
279    
280 root 1.36 #################################################################################
281 root 1.18
282 root 1.15 =back
283    
284 root 1.13 =head2 LOW-LEVEL DNS EN-/DECODING FUNCTIONS
285 root 1.1
286     =over 4
287    
288 root 1.11 =item $AnyEvent::DNS::EDNS0
289    
290 root 1.13 This variable decides whether dns_pack automatically enables EDNS0
291 root 1.24 support. By default, this is disabled (C<0>), unless overridden by
292 root 1.40 C<$ENV{PERL_ANYEVENT_EDNS0}>, but when set to C<1>, AnyEvent::DNS will use
293 root 1.21 EDNS0 in all requests.
294 root 1.11
295 root 1.1 =cut
296    
297 root 1.93 our $EDNS0 = $ENV{PERL_ANYEVENT_EDNS0}*1; # set to 1 to enable (partial) edns0
298 root 1.10
299 root 1.1 our %opcode_id = (
300     query => 0,
301     iquery => 1,
302     status => 2,
303 root 1.5 notify => 4,
304     update => 5,
305     map +($_ => $_), 3, 6..15
306 root 1.1 );
307    
308     our %opcode_str = reverse %opcode_id;
309    
310     our %rcode_id = (
311 root 1.5 noerror => 0,
312     formerr => 1,
313     servfail => 2,
314     nxdomain => 3,
315     notimp => 4,
316     refused => 5,
317     yxdomain => 6, # Name Exists when it should not [RFC 2136]
318     yxrrset => 7, # RR Set Exists when it should not [RFC 2136]
319     nxrrset => 8, # RR Set that should exist does not [RFC 2136]
320     notauth => 9, # Server Not Authoritative for zone [RFC 2136]
321     notzone => 10, # Name not contained in zone [RFC 2136]
322     # EDNS0 16 BADVERS Bad OPT Version [RFC 2671]
323     # EDNS0 16 BADSIG TSIG Signature Failure [RFC 2845]
324     # EDNS0 17 BADKEY Key not recognized [RFC 2845]
325     # EDNS0 18 BADTIME Signature out of time window [RFC 2845]
326     # EDNS0 19 BADMODE Bad TKEY Mode [RFC 2930]
327     # EDNS0 20 BADNAME Duplicate key name [RFC 2930]
328     # EDNS0 21 BADALG Algorithm not supported [RFC 2930]
329     map +($_ => $_), 11..15
330 root 1.1 );
331    
332     our %rcode_str = reverse %rcode_id;
333    
334     our %type_id = (
335     a => 1,
336     ns => 2,
337     md => 3,
338     mf => 4,
339     cname => 5,
340     soa => 6,
341     mb => 7,
342     mg => 8,
343     mr => 9,
344     null => 10,
345     wks => 11,
346     ptr => 12,
347     hinfo => 13,
348     minfo => 14,
349     mx => 15,
350     txt => 16,
351     aaaa => 28,
352     srv => 33,
353 root 1.47 naptr => 35, # rfc2915
354 root 1.90 dname => 39, # rfc2672
355 root 1.5 opt => 41,
356     spf => 99,
357     tkey => 249,
358     tsig => 250,
359     ixfr => 251,
360 root 1.1 axfr => 252,
361     mailb => 253,
362     "*" => 255,
363     );
364    
365     our %type_str = reverse %type_id;
366    
367     our %class_id = (
368 root 1.5 in => 1,
369     ch => 3,
370     hs => 4,
371     none => 254,
372     "*" => 255,
373 root 1.1 );
374    
375     our %class_str = reverse %class_id;
376    
377 root 1.34 sub _enc_name($) {
378 root 1.29 pack "(C/a*)*", (split /\./, shift), ""
379 root 1.1 }
380    
381 root 1.106 if ($[ < 5.008) {
382     # special slower 5.6 version
383     *_enc_name = sub {
384     join "", map +(pack "C/a*", $_), (split /\./, shift), ""
385     };
386     }
387    
388 root 1.1 sub _enc_qd() {
389 root 1.34 (_enc_name $_->[0]) . pack "nn",
390 root 1.1 ($_->[1] > 0 ? $_->[1] : $type_id {$_->[1]}),
391     ($_->[2] > 0 ? $_->[2] : $class_id{$_->[2] || "in"})
392     }
393    
394     sub _enc_rr() {
395     die "encoding of resource records is not supported";
396     }
397    
398     =item $pkt = AnyEvent::DNS::dns_pack $dns
399    
400 root 1.50 Packs a perl data structure into a DNS packet. Reading RFC 1035 is strongly
401 root 1.1 recommended, then everything will be totally clear. Or maybe not.
402    
403     Resource records are not yet encodable.
404    
405     Examples:
406    
407 root 1.57 # very simple request, using lots of default values:
408     { rd => 1, qd => [ [ "host.domain", "a"] ] }
409    
410     # more complex example, showing how flags etc. are named:
411    
412     {
413     id => 10000,
414     op => "query",
415     rc => "nxdomain",
416    
417     # flags
418     qr => 1,
419     aa => 0,
420     tc => 0,
421     rd => 0,
422     ra => 0,
423     ad => 0,
424     cd => 0,
425    
426     qd => [@rr], # query section
427     an => [@rr], # answer section
428     ns => [@rr], # authority section
429     ar => [@rr], # additional records section
430     }
431 root 1.1
432     =cut
433    
434     sub dns_pack($) {
435     my ($req) = @_;
436    
437 root 1.7 pack "nn nnnn a* a* a* a* a*",
438 root 1.1 $req->{id},
439    
440     ! !$req->{qr} * 0x8000
441     + $opcode_id{$req->{op}} * 0x0800
442     + ! !$req->{aa} * 0x0400
443     + ! !$req->{tc} * 0x0200
444     + ! !$req->{rd} * 0x0100
445     + ! !$req->{ra} * 0x0080
446 root 1.5 + ! !$req->{ad} * 0x0020
447     + ! !$req->{cd} * 0x0010
448 root 1.1 + $rcode_id{$req->{rc}} * 0x0001,
449    
450     scalar @{ $req->{qd} || [] },
451     scalar @{ $req->{an} || [] },
452     scalar @{ $req->{ns} || [] },
453 root 1.44 $EDNS0 + scalar @{ $req->{ar} || [] }, # EDNS0 option included here
454 root 1.1
455     (join "", map _enc_qd, @{ $req->{qd} || [] }),
456     (join "", map _enc_rr, @{ $req->{an} || [] }),
457     (join "", map _enc_rr, @{ $req->{ns} || [] }),
458 root 1.7 (join "", map _enc_rr, @{ $req->{ar} || [] }),
459    
460 root 1.44 ($EDNS0 ? pack "C nnNn", 0, 41, MAX_PKT, 0, 0 : "") # EDNS0 option
461 root 1.1 }
462    
463     our $ofs;
464     our $pkt;
465    
466     # bitches
467 root 1.34 sub _dec_name {
468 root 1.1 my @res;
469     my $redir;
470     my $ptr = $ofs;
471     my $cnt;
472    
473     while () {
474     return undef if ++$cnt >= 256; # to avoid DoS attacks
475    
476     my $len = ord substr $pkt, $ptr++, 1;
477    
478 root 1.34 if ($len >= 0xc0) {
479 root 1.1 $ptr++;
480     $ofs = $ptr if $ptr > $ofs;
481     $ptr = (unpack "n", substr $pkt, $ptr - 2, 2) & 0x3fff;
482     } elsif ($len) {
483     push @res, substr $pkt, $ptr, $len;
484     $ptr += $len;
485     } else {
486     $ofs = $ptr if $ptr > $ofs;
487     return join ".", @res;
488     }
489     }
490     }
491    
492     sub _dec_qd {
493 root 1.34 my $qname = _dec_name;
494 root 1.1 my ($qt, $qc) = unpack "nn", substr $pkt, $ofs; $ofs += 4;
495     [$qname, $type_str{$qt} || $qt, $class_str{$qc} || $qc]
496     }
497    
498     our %dec_rr = (
499 root 1.29 1 => sub { join ".", unpack "C4", $_ }, # a
500 root 1.34 2 => sub { local $ofs = $ofs - length; _dec_name }, # ns
501     5 => sub { local $ofs = $ofs - length; _dec_name }, # cname
502 root 1.1 6 => sub {
503     local $ofs = $ofs - length;
504 root 1.34 my $mname = _dec_name;
505     my $rname = _dec_name;
506 root 1.1 ($mname, $rname, unpack "NNNNN", substr $pkt, $ofs)
507     }, # soa
508 root 1.29 11 => sub { ((join ".", unpack "C4", $_), unpack "C a*", substr $_, 4) }, # wks
509 root 1.34 12 => sub { local $ofs = $ofs - length; _dec_name }, # ptr
510 root 1.29 13 => sub { unpack "C/a* C/a*", $_ }, # hinfo
511 root 1.34 15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_name) }, # mx
512 root 1.29 16 => sub { unpack "(C/a*)*", $_ }, # txt
513 root 1.100 28 => sub { AnyEvent::Socket::format_ipv6 ($_) }, # aaaa
514 root 1.34 33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_name) }, # srv
515 root 1.47 35 => sub { # naptr
516 root 1.66 # requires perl 5.10, sorry
517 root 1.47 my ($order, $preference, $flags, $service, $regexp, $offset) = unpack "nn C/a* C/a* C/a* .", $_;
518     local $ofs = $ofs + $offset - length;
519     ($order, $preference, $flags, $service, $regexp, _dec_name)
520     },
521 root 1.90 39 => sub { local $ofs = $ofs - length; _dec_name }, # dname
522 root 1.29 99 => sub { unpack "(C/a*)*", $_ }, # spf
523 root 1.1 );
524    
525     sub _dec_rr {
526 root 1.34 my $name = _dec_name;
527 root 1.1
528     my ($rt, $rc, $ttl, $rdlen) = unpack "nn N n", substr $pkt, $ofs; $ofs += 10;
529     local $_ = substr $pkt, $ofs, $rdlen; $ofs += $rdlen;
530    
531     [
532 root 1.34 $name,
533 root 1.1 $type_str{$rt} || $rt,
534     $class_str{$rc} || $rc,
535     ($dec_rr{$rt} || sub { $_ })->(),
536     ]
537     }
538    
539     =item $dns = AnyEvent::DNS::dns_unpack $pkt
540    
541     Unpacks a DNS packet into a perl data structure.
542    
543     Examples:
544    
545 root 1.57 # an unsuccessful reply
546     {
547     'qd' => [
548     [ 'ruth.plan9.de.mach.uni-karlsruhe.de', '*', 'in' ]
549     ],
550     'rc' => 'nxdomain',
551     'ar' => [],
552     'ns' => [
553     [
554     'uni-karlsruhe.de',
555     'soa',
556     'in',
557     'netserv.rz.uni-karlsruhe.de',
558     'hostmaster.rz.uni-karlsruhe.de',
559     2008052201, 10800, 1800, 2592000, 86400
560     ]
561     ],
562     'tc' => '',
563     'ra' => 1,
564     'qr' => 1,
565     'id' => 45915,
566     'aa' => '',
567     'an' => [],
568     'rd' => 1,
569     'op' => 'query'
570     }
571    
572     # a successful reply
573    
574     {
575     'qd' => [ [ 'www.google.de', 'a', 'in' ] ],
576     'rc' => 0,
577     'ar' => [
578     [ 'a.l.google.com', 'a', 'in', '209.85.139.9' ],
579     [ 'b.l.google.com', 'a', 'in', '64.233.179.9' ],
580     [ 'c.l.google.com', 'a', 'in', '64.233.161.9' ],
581     ],
582     'ns' => [
583     [ 'l.google.com', 'ns', 'in', 'a.l.google.com' ],
584     [ 'l.google.com', 'ns', 'in', 'b.l.google.com' ],
585     ],
586     'tc' => '',
587     'ra' => 1,
588     'qr' => 1,
589     'id' => 64265,
590     'aa' => '',
591     'an' => [
592     [ 'www.google.de', 'cname', 'in', 'www.google.com' ],
593     [ 'www.google.com', 'cname', 'in', 'www.l.google.com' ],
594     [ 'www.l.google.com', 'a', 'in', '66.249.93.104' ],
595     [ 'www.l.google.com', 'a', 'in', '66.249.93.147' ],
596     ],
597     'rd' => 1,
598     'op' => 0
599     }
600 root 1.1
601     =cut
602    
603     sub dns_unpack($) {
604     local $pkt = shift;
605     my ($id, $flags, $qd, $an, $ns, $ar)
606     = unpack "nn nnnn A*", $pkt;
607    
608     local $ofs = 6 * 2;
609    
610     {
611     id => $id,
612     qr => ! ! ($flags & 0x8000),
613     aa => ! ! ($flags & 0x0400),
614     tc => ! ! ($flags & 0x0200),
615     rd => ! ! ($flags & 0x0100),
616     ra => ! ! ($flags & 0x0080),
617 root 1.5 ad => ! ! ($flags & 0x0020),
618     cd => ! ! ($flags & 0x0010),
619 root 1.1 op => $opcode_str{($flags & 0x001e) >> 11},
620     rc => $rcode_str{($flags & 0x000f)},
621    
622     qd => [map _dec_qd, 1 .. $qd],
623     an => [map _dec_rr, 1 .. $an],
624     ns => [map _dec_rr, 1 .. $ns],
625     ar => [map _dec_rr, 1 .. $ar],
626     }
627     }
628    
629     #############################################################################
630    
631     =back
632    
633     =head2 THE AnyEvent::DNS RESOLVER CLASS
634    
635 root 1.13 This is the class which does the actual protocol work.
636 root 1.1
637     =over 4
638    
639     =cut
640    
641     use Carp ();
642     use Scalar::Util ();
643     use Socket ();
644    
645     our $NOW;
646    
647 root 1.2 =item AnyEvent::DNS::resolver
648    
649     This function creates and returns a resolver that is ready to use and
650     should mimic the default resolver for your system as good as possible.
651    
652     It only ever creates one resolver and returns this one on subsequent
653     calls.
654    
655     Unless you have special needs, prefer this function over creating your own
656     resolver object.
657    
658 root 1.102 The resolver is created with the following parameters:
659    
660     untaint enabled
661     max_outstanding $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS}
662    
663     C<os_config> will be used for OS-specific configuration, unless
664     C<$ENV{PERL_ANYEVENT_RESOLV_CONF}> is specified, in which case that file
665     gets parsed.
666    
667 root 1.2 =cut
668    
669     our $RESOLVER;
670    
671     sub resolver() {
672     $RESOLVER || do {
673 root 1.102 $RESOLVER = new AnyEvent::DNS
674     untaint => 1,
675     exists $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS}
676     ? (max_outstanding => $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS}*1 || 1) : (),
677     ;
678    
679     exists $ENV{PERL_ANYEVENT_RESOLV_CONF}
680     ? length $ENV{PERL_ANYEVENT_RESOLV_CONF} && $RESOLVER->_parse_resolv_conf_file ($ENV{PERL_ANYEVENT_RESOLV_CONF})
681     : $RESOLVER->os_config;
682    
683 root 1.2 $RESOLVER
684     }
685     }
686    
687 root 1.1 =item $resolver = new AnyEvent::DNS key => value...
688    
689 root 1.6 Creates and returns a new resolver.
690 root 1.2
691     The following options are supported:
692 root 1.1
693     =over 4
694    
695     =item server => [...]
696    
697 root 1.41 A list of server addresses (default: C<v127.0.0.1>) in network format
698 root 1.42 (i.e. as returned by C<AnyEvent::Socket::parse_address> - both IPv4 and
699 root 1.41 IPv6 are supported).
700 root 1.1
701     =item timeout => [...]
702    
703     A list of timeouts to use (also determines the number of retries). To make
704     three retries with individual time-outs of 2, 5 and 5 seconds, use C<[2,
705     5, 5]>, which is also the default.
706    
707     =item search => [...]
708    
709     The default search list of suffixes to append to a domain name (default: none).
710    
711 root 1.2 =item ndots => $integer
712 root 1.1
713     The number of dots (default: C<1>) that a name must have so that the resolver
714     tries to resolve the name without any suffixes first.
715    
716 root 1.2 =item max_outstanding => $integer
717 root 1.1
718 root 1.43 Most name servers do not handle many parallel requests very well. This
719     option limits the number of outstanding requests to C<$integer>
720     (default: C<10>), that means if you request more than this many requests,
721     then the additional requests will be queued until some other requests have
722     been resolved.
723 root 1.1
724 root 1.13 =item reuse => $seconds
725    
726 root 1.22 The number of seconds (default: C<300>) that a query id cannot be re-used
727 root 1.54 after a timeout. If there was no time-out then query ids can be reused
728 root 1.22 immediately.
729 root 1.13
730 root 1.93 =item untaint => $boolean
731    
732     When true, then the resolver will automatically untaint results, and might
733     also ignore certain environment variables.
734    
735 root 1.1 =back
736    
737     =cut
738    
739     sub new {
740     my ($class, %arg) = @_;
741    
742     my $self = bless {
743 root 1.32 server => [],
744 root 1.1 timeout => [2, 5, 5],
745     search => [],
746     ndots => 1,
747     max_outstanding => 10,
748 root 1.54 reuse => 300,
749 root 1.1 %arg,
750     reuse_q => [],
751     }, $class;
752    
753     # search should default to gethostname's domain
754     # but perl lacks a good posix module
755    
756 root 1.63 # try to create an ipv4 and an ipv6 socket
757     # only fail when we cannot create either
758     my $got_socket;
759    
760 root 1.1 Scalar::Util::weaken (my $wself = $self);
761 root 1.38
762 root 1.63 if (socket my $fh4, AF_INET , &Socket::SOCK_DGRAM, 0) {
763     ++$got_socket;
764    
765 root 1.38 AnyEvent::Util::fh_nonblocking $fh4, 1;
766     $self->{fh4} = $fh4;
767     $self->{rw4} = AnyEvent->io (fh => $fh4, poll => "r", cb => sub {
768     if (my $peer = recv $fh4, my $pkt, MAX_PKT, 0) {
769     $wself->_recv ($pkt, $peer);
770     }
771     });
772     }
773    
774 root 1.63 if (AF_INET6 && socket my $fh6, AF_INET6, &Socket::SOCK_DGRAM, 0) {
775     ++$got_socket;
776    
777 root 1.38 $self->{fh6} = $fh6;
778     AnyEvent::Util::fh_nonblocking $fh6, 1;
779     $self->{rw6} = AnyEvent->io (fh => $fh6, poll => "r", cb => sub {
780     if (my $peer = recv $fh6, my $pkt, MAX_PKT, 0) {
781     $wself->_recv ($pkt, $peer);
782     }
783     });
784     }
785 root 1.1
786 root 1.63 $got_socket
787     or Carp::croak "unable to create either an IPv4 or an IPv6 socket";
788    
789 root 1.1 $self->_compile;
790    
791     $self
792     }
793    
794 root 1.102 =item $resolver->parse_resolv_conf ($string)
795 root 1.1
796 root 1.24 Parses the given string as if it were a F<resolv.conf> file. The following
797     directives are supported (but not necessarily implemented).
798 root 1.1
799     C<#>-style comments, C<nameserver>, C<domain>, C<search>, C<sortlist>,
800     C<options> (C<timeout>, C<attempts>, C<ndots>).
801    
802     Everything else is silently ignored.
803    
804     =cut
805    
806     sub parse_resolv_conf {
807     my ($self, $resolvconf) = @_;
808    
809     $self->{server} = [];
810     $self->{search} = [];
811    
812     my $attempts;
813    
814     for (split /\n/, $resolvconf) {
815     if (/^\s*#/) {
816     # comment
817     } elsif (/^\s*nameserver\s+(\S+)\s*$/i) {
818     my $ip = $1;
819 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($ip)) {
820 root 1.25 push @{ $self->{server} }, $ipn;
821 root 1.1 } else {
822     warn "nameserver $ip invalid and ignored\n";
823     }
824     } elsif (/^\s*domain\s+(\S*)\s+$/i) {
825     $self->{search} = [$1];
826     } elsif (/^\s*search\s+(.*?)\s*$/i) {
827     $self->{search} = [split /\s+/, $1];
828     } elsif (/^\s*sortlist\s+(.*?)\s*$/i) {
829     # ignored, NYI
830     } elsif (/^\s*options\s+(.*?)\s*$/i) {
831     for (split /\s+/, $1) {
832     if (/^timeout:(\d+)$/) {
833     $self->{timeout} = [$1];
834     } elsif (/^attempts:(\d+)$/) {
835     $attempts = $1;
836     } elsif (/^ndots:(\d+)$/) {
837     $self->{ndots} = $1;
838     } else {
839     # debug, rotate, no-check-names, inet6
840     }
841     }
842     }
843     }
844    
845     $self->{timeout} = [($self->{timeout}[0]) x $attempts]
846     if $attempts;
847    
848     $self->_compile;
849     }
850    
851 root 1.102 sub _parse_resolv_conf_file {
852     my ($self, $resolv_conf) = @_;
853    
854 root 1.106 open my $fh, "<", $resolv_conf
855 root 1.102 or Carp::croak "$resolv_conf: $!";
856    
857     local $/;
858     $self->parse_resolv_conf (<$fh>);
859     }
860    
861 root 1.14 =item $resolver->os_config
862 root 1.1
863 root 1.93 Tries so load and parse F</etc/resolv.conf> on portable operating
864     systems. Tries various egregious hacks on windows to force the DNS servers
865     and searchlist out of the system.
866 root 1.1
867     =cut
868    
869 root 1.14 sub os_config {
870 root 1.1 my ($self) = @_;
871    
872 root 1.32 $self->{server} = [];
873     $self->{search} = [];
874    
875 root 1.102 if ((AnyEvent::WIN32 || $^O =~ /cygwin/i)) {
876 root 1.32 no strict 'refs';
877    
878     # there are many options to find the current nameservers etc. on windows
879     # all of them don't work consistently:
880     # - the registry thing needs separate code on win32 native vs. cygwin
881     # - the registry layout differs between windows versions
882     # - calling windows api functions doesn't work on cygwin
883     # - ipconfig uses locale-specific messages
884    
885 root 1.54 # we use ipconfig parsing because, despite all its brokenness,
886 root 1.32 # it seems most stable in practise.
887     # for good measure, we append a fallback nameserver to our list.
888 root 1.14
889     if (open my $fh, "ipconfig /all |") {
890 root 1.32 # parsing strategy: we go through the output and look for
891     # :-lines with DNS in them. everything in those is regarded as
892     # either a nameserver (if it parses as an ip address), or a suffix
893     # (all else).
894 root 1.14
895 root 1.32 my $dns;
896 root 1.14 while (<$fh>) {
897 root 1.32 if (s/^\s.*\bdns\b.*://i) {
898     $dns = 1;
899     } elsif (/^\S/ || /^\s[^:]{16,}: /) {
900     $dns = 0;
901     }
902     if ($dns && /^\s*(\S+)\s*$/) {
903     my $s = $1;
904 root 1.54 $s =~ s/%\d+(?!\S)//; # get rid of ipv6 scope id
905 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
906 root 1.32 push @{ $self->{server} }, $ipn;
907     } else {
908     push @{ $self->{search} }, $s;
909 root 1.14 }
910     }
911     }
912    
913 root 1.32 # always add one fallback server
914     push @{ $self->{server} }, $DNS_FALLBACK[rand @DNS_FALLBACK];
915 root 1.14
916     $self->_compile;
917     }
918     } else {
919 root 1.102 # try resolv.conf everywhere else
920 root 1.1
921 root 1.102 $self->_parse_resolv_conf_file ("/etc/resolv.conf")
922     if -e "/etc/resolv.conf";
923 root 1.14 }
924 root 1.1 }
925    
926 root 1.53 =item $resolver->timeout ($timeout, ...)
927    
928     Sets the timeout values. See the C<timeout> constructor argument (and note
929 root 1.54 that this method uses the values itself, not an array-reference).
930 root 1.53
931     =cut
932    
933     sub timeout {
934     my ($self, @timeout) = @_;
935    
936     $self->{timeout} = \@timeout;
937     $self->_compile;
938     }
939    
940     =item $resolver->max_outstanding ($nrequests)
941    
942     Sets the maximum number of outstanding requests to C<$nrequests>. See the
943     C<max_outstanding> constructor argument.
944    
945     =cut
946    
947     sub max_outstanding {
948     my ($self, $max) = @_;
949    
950     $self->{max_outstanding} = $max;
951     $self->_scheduler;
952     }
953    
954 root 1.1 sub _compile {
955     my $self = shift;
956    
957 root 1.38 my %search; $self->{search} = [grep 0 < length, grep !$search{$_}++, @{ $self->{search} }];
958     my %server; $self->{server} = [grep 0 < length, grep !$server{$_}++, @{ $self->{server} }];
959 root 1.32
960     unless (@{ $self->{server} }) {
961     # use 127.0.0.1 by default, and one opendns nameserver as fallback
962     $self->{server} = [v127.0.0.1, $DNS_FALLBACK[rand @DNS_FALLBACK]];
963     }
964    
965 root 1.1 my @retry;
966    
967     for my $timeout (@{ $self->{timeout} }) {
968     for my $server (@{ $self->{server} }) {
969     push @retry, [$server, $timeout];
970     }
971     }
972    
973     $self->{retry} = \@retry;
974     }
975    
976 root 1.6 sub _feed {
977     my ($self, $res) = @_;
978    
979 root 1.93 ($res) = $res =~ /^(.*)$/s
980     if AnyEvent::TAINT && $self->{untaint};
981    
982 root 1.6 $res = dns_unpack $res
983     or return;
984    
985     my $id = $self->{id}{$res->{id}};
986    
987     return unless ref $id;
988    
989     $NOW = time;
990     $id->[1]->($res);
991     }
992    
993 root 1.1 sub _recv {
994 root 1.38 my ($self, $pkt, $peer) = @_;
995 root 1.1
996 root 1.32 # we ignore errors (often one gets port unreachable, but there is
997     # no good way to take advantage of that.
998 root 1.1
999 root 1.38 my ($port, $host) = AnyEvent::Socket::unpack_sockaddr ($peer);
1000    
1001     return unless $port == 53 && grep $_ eq $host, @{ $self->{server} };
1002 root 1.1
1003 root 1.38 $self->_feed ($pkt);
1004 root 1.1 }
1005    
1006 root 1.22 sub _free_id {
1007     my ($self, $id, $timeout) = @_;
1008    
1009     if ($timeout) {
1010     # we need to block the id for a while
1011     $self->{id}{$id} = 1;
1012     push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $id];
1013     } else {
1014     # we can quickly recycle the id
1015     delete $self->{id}{$id};
1016     }
1017    
1018     --$self->{outstanding};
1019     $self->_scheduler;
1020     }
1021    
1022     # execute a single request, involves sending it with timeouts to multiple servers
1023 root 1.1 sub _exec {
1024 root 1.22 my ($self, $req) = @_;
1025    
1026     my $retry; # of retries
1027     my $do_retry;
1028    
1029     $do_retry = sub {
1030     my $retry_cfg = $self->{retry}[$retry++]
1031     or do {
1032     # failure
1033     $self->_free_id ($req->[2], $retry > 1);
1034     undef $do_retry; return $req->[1]->();
1035     };
1036 root 1.1
1037     my ($server, $timeout) = @$retry_cfg;
1038    
1039     $self->{id}{$req->[2]} = [AnyEvent->timer (after => $timeout, cb => sub {
1040     $NOW = time;
1041    
1042     # timeout, try next
1043 root 1.70 &$do_retry if $do_retry;
1044 root 1.1 }), sub {
1045     my ($res) = @_;
1046    
1047 root 1.6 if ($res->{tc}) {
1048     # success, but truncated, so use tcp
1049 root 1.38 AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub {
1050 root 1.52 return unless $do_retry; # some other request could have invalidated us already
1051    
1052 root 1.6 my ($fh) = @_
1053 root 1.22 or return &$do_retry;
1054 root 1.6
1055 root 1.97 require AnyEvent::Handle;
1056    
1057 root 1.52 my $handle; $handle = new AnyEvent::Handle
1058 root 1.6 fh => $fh,
1059 root 1.52 timeout => $timeout,
1060 root 1.6 on_error => sub {
1061 root 1.52 undef $handle;
1062     return unless $do_retry; # some other request could have invalidated us already
1063 root 1.6 # failure, try next
1064 root 1.22 &$do_retry;
1065 root 1.6 };
1066    
1067     $handle->push_write (pack "n/a", $req->[0]);
1068 root 1.27 $handle->push_read (chunk => 2, sub {
1069     $handle->unshift_read (chunk => (unpack "n", $_[1]), sub {
1070 root 1.52 undef $handle;
1071 root 1.6 $self->_feed ($_[1]);
1072     });
1073     });
1074    
1075 root 1.17 }, sub { $timeout });
1076 root 1.1
1077 root 1.6 } else {
1078     # success
1079 root 1.22 $self->_free_id ($req->[2], $retry > 1);
1080     undef $do_retry; return $req->[1]->($res);
1081 root 1.6 }
1082 root 1.1 }];
1083 root 1.38
1084     my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server);
1085    
1086 root 1.106 my $fh = AF_INET == AnyEvent::Socket::sockaddr_family ($sa)
1087 root 1.38 ? $self->{fh4} : $self->{fh6}
1088     or return &$do_retry;
1089 root 1.1
1090 root 1.38 send $fh, $req->[0], 0, $sa;
1091 root 1.22 };
1092 root 1.1
1093 root 1.22 &$do_retry;
1094 root 1.1 }
1095    
1096     sub _scheduler {
1097     my ($self) = @_;
1098    
1099 root 1.51 no strict 'refs';
1100    
1101 root 1.1 $NOW = time;
1102    
1103     # first clear id reuse queue
1104     delete $self->{id}{ (shift @{ $self->{reuse_q} })->[1] }
1105 root 1.13 while @{ $self->{reuse_q} } && $self->{reuse_q}[0][0] <= $NOW;
1106 root 1.1
1107     while ($self->{outstanding} < $self->{max_outstanding}) {
1108 root 1.13
1109     if (@{ $self->{reuse_q} } >= 30000) {
1110     # we ran out of ID's, wait a bit
1111     $self->{reuse_to} ||= AnyEvent->timer (after => $self->{reuse_q}[0][0] - $NOW, cb => sub {
1112     delete $self->{reuse_to};
1113     $self->_scheduler;
1114     });
1115     last;
1116     }
1117    
1118 root 1.51 if (my $req = shift @{ $self->{queue} }) {
1119     # found a request in the queue, execute it
1120     while () {
1121     $req->[2] = int rand 65536;
1122     last unless exists $self->{id}{$req->[2]};
1123     }
1124    
1125     ++$self->{outstanding};
1126     $self->{id}{$req->[2]} = 1;
1127     substr $req->[0], 0, 2, pack "n", $req->[2];
1128    
1129     $self->_exec ($req);
1130    
1131     } elsif (my $cb = shift @{ $self->{wait} }) {
1132     # found a wait_for_slot callback, call that one first
1133     $cb->($self);
1134 root 1.1
1135 root 1.51 } else {
1136     # nothing to do, just exit
1137     last;
1138 root 1.1 }
1139     }
1140     }
1141    
1142     =item $resolver->request ($req, $cb->($res))
1143    
1144 root 1.54 This is the main low-level workhorse for sending DNS requests.
1145    
1146     This function sends a single request (a hash-ref formated as specified
1147     for C<dns_pack>) to the configured nameservers in turn until it gets a
1148     response. It handles timeouts, retries and automatically falls back to
1149     virtual circuit mode (TCP) when it receives a truncated reply.
1150    
1151     Calls the callback with the decoded response packet if a reply was
1152     received, or no arguments in case none of the servers answered.
1153 root 1.1
1154     =cut
1155    
1156     sub request($$) {
1157     my ($self, $req, $cb) = @_;
1158    
1159 root 1.3 push @{ $self->{queue} }, [dns_pack $req, $cb];
1160 root 1.1 $self->_scheduler;
1161     }
1162    
1163 root 1.80 =item $resolver->resolve ($qname, $qtype, %options, $cb->(@rr))
1164 root 1.1
1165 root 1.44 Queries the DNS for the given domain name C<$qname> of type C<$qtype>.
1166    
1167 root 1.54 A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or
1168 root 1.44 a lowercase name (you have to look at the source to see which aliases are
1169 root 1.50 supported, but all types from RFC 1035, C<aaaa>, C<srv>, C<spf> and a few
1170 root 1.54 more are known to this module). A C<$qtype> of "*" is supported and means
1171 root 1.44 "any" record type.
1172 root 1.1
1173     The callback will be invoked with a list of matching result records or
1174     none on any error or if the name could not be found.
1175    
1176 root 1.61 CNAME chains (although illegal) are followed up to a length of 10.
1177 root 1.1
1178 root 1.83 The callback will be invoked with arraryefs of the form C<[$name, $type,
1179     $class, @data>], where C<$name> is the domain name, C<$type> a type string
1180     or number, C<$class> a class name and @data is resource-record-dependent
1181     data. For C<a> records, this will be the textual IPv4 addresses, for C<ns>
1182     or C<cname> records this will be a domain name, for C<txt> records these
1183     are all the strings and so on.
1184 root 1.44
1185 root 1.55 All types mentioned in RFC 1035, C<aaaa>, C<srv>, C<naptr> and C<spf> are
1186     decoded. All resource records not known to this module will have
1187 root 1.44 the raw C<rdata> field as fourth entry.
1188    
1189 root 1.24 Note that this resolver is just a stub resolver: it requires a name server
1190 root 1.3 supporting recursive queries, will not do any recursive queries itself and
1191     is not secure when used against an untrusted name server.
1192    
1193 root 1.1 The following options are supported:
1194    
1195     =over 4
1196    
1197     =item search => [$suffix...]
1198    
1199     Use the given search list (which might be empty), by appending each one
1200     in turn to the C<$qname>. If this option is missing then the configured
1201 root 1.55 C<ndots> and C<search> values define its value (depending on C<ndots>, the
1202     empty suffix will be prepended or appended to that C<search> value). If
1203     the C<$qname> ends in a dot, then the searchlist will be ignored.
1204 root 1.1
1205     =item accept => [$type...]
1206    
1207     Lists the acceptable result types: only result types in this set will be
1208     accepted and returned. The default includes the C<$qtype> and nothing
1209 root 1.44 else. If this list includes C<cname>, then CNAME-chains will not be
1210     followed (because you asked for the CNAME record).
1211 root 1.1
1212     =item class => "class"
1213    
1214     Specify the query class ("in" for internet, "ch" for chaosnet and "hs" for
1215 root 1.2 hesiod are the only ones making sense). The default is "in", of course.
1216 root 1.1
1217     =back
1218    
1219     Examples:
1220    
1221 root 1.46 # full example, you can paste this into perl:
1222 root 1.45 use Data::Dumper;
1223     use AnyEvent::DNS;
1224     AnyEvent::DNS::resolver->resolve (
1225     "google.com", "*", my $cv = AnyEvent->condvar);
1226     warn Dumper [$cv->recv];
1227    
1228     # shortened result:
1229     # [
1230     # [ 'google.com', 'soa', 'in', 'ns1.google.com', 'dns-admin.google.com',
1231     # 2008052701, 7200, 1800, 1209600, 300 ],
1232     # [
1233     # 'google.com', 'txt', 'in',
1234     # 'v=spf1 include:_netblocks.google.com ~all'
1235     # ],
1236     # [ 'google.com', 'a', 'in', '64.233.187.99' ],
1237     # [ 'google.com', 'mx', 'in', 10, 'smtp2.google.com' ],
1238     # [ 'google.com', 'ns', 'in', 'ns2.google.com' ],
1239     # ]
1240    
1241     # resolve a records:
1242     $res->resolve ("ruth.plan9.de", "a", sub { warn Dumper [@_] });
1243    
1244     # result:
1245     # [
1246     # [ 'ruth.schmorp.de', 'a', 'in', '129.13.162.95' ]
1247     # ]
1248 root 1.1
1249 root 1.45 # resolve any records, but return only a and aaaa records:
1250 root 1.1 $res->resolve ("test1.laendle", "*",
1251     accept => ["a", "aaaa"],
1252     sub {
1253     warn Dumper [@_];
1254     }
1255     );
1256    
1257 root 1.45 # result:
1258     # [
1259     # [ 'test1.laendle', 'a', 'in', '10.0.0.255' ],
1260     # [ 'test1.laendle', 'aaaa', 'in', '3ffe:1900:4545:0002:0240:0000:0000:f7e1' ]
1261     # ]
1262 root 1.1
1263     =cut
1264    
1265     sub resolve($%) {
1266     my $cb = pop;
1267     my ($self, $qname, $qtype, %opt) = @_;
1268    
1269     my @search = $qname =~ s/\.$//
1270     ? ""
1271     : $opt{search}
1272     ? @{ $opt{search} }
1273     : ($qname =~ y/.//) >= $self->{ndots}
1274     ? ("", @{ $self->{search} })
1275     : (@{ $self->{search} }, "");
1276    
1277     my $class = $opt{class} || "in";
1278    
1279     my %atype = $opt{accept}
1280     ? map +($_ => 1), @{ $opt{accept} }
1281     : ($qtype => 1);
1282    
1283     # advance in searchlist
1284 root 1.22 my ($do_search, $do_req);
1285    
1286     $do_search = sub {
1287 root 1.1 @search
1288 root 1.22 or (undef $do_search), (undef $do_req), return $cb->();
1289 root 1.1
1290 root 1.4 (my $name = lc "$qname." . shift @search) =~ s/\.$//;
1291 root 1.61 my $depth = 10;
1292 root 1.1
1293     # advance in cname-chain
1294 root 1.22 $do_req = sub {
1295 root 1.1 $self->request ({
1296     rd => 1,
1297     qd => [[$name, $qtype, $class]],
1298     }, sub {
1299     my ($res) = @_
1300     or return $do_search->();
1301    
1302     my $cname;
1303    
1304     while () {
1305 root 1.2 # results found?
1306 root 1.4 my @rr = grep $name eq lc $_->[0] && ($atype{"*"} || $atype{$_->[1]}), @{ $res->{an} };
1307 root 1.1
1308 root 1.22 (undef $do_search), (undef $do_req), return $cb->(@rr)
1309 root 1.1 if @rr;
1310    
1311     # see if there is a cname we can follow
1312 root 1.4 my @rr = grep $name eq lc $_->[0] && $_->[1] eq "cname", @{ $res->{an} };
1313 root 1.1
1314     if (@rr) {
1315     $depth--
1316     or return $do_search->(); # cname chain too long
1317    
1318     $cname = 1;
1319 root 1.99 $name = lc $rr[0][3];
1320 root 1.1
1321     } elsif ($cname) {
1322     # follow the cname
1323     return $do_req->();
1324    
1325     } else {
1326 root 1.2 # no, not found anything
1327 root 1.1 return $do_search->();
1328     }
1329     }
1330     });
1331     };
1332    
1333     $do_req->();
1334     };
1335    
1336     $do_search->();
1337     }
1338    
1339 root 1.51 =item $resolver->wait_for_slot ($cb->($resolver))
1340    
1341     Wait until a free request slot is available and call the callback with the
1342     resolver object.
1343    
1344     A request slot is used each time a request is actually sent to the
1345     nameservers: There are never more than C<max_outstanding> of them.
1346    
1347     Although you can submit more requests (they will simply be queued until
1348     a request slot becomes available), sometimes, usually for rate-limiting
1349     purposes, it is useful to instead wait for a slot before generating the
1350     request (or simply to know when the request load is low enough so one can
1351     submit requests again).
1352    
1353     This is what this method does: The callback will be called when submitting
1354     a DNS request will not result in that request being queued. The callback
1355     may or may not generate any requests in response.
1356    
1357     Note that the callback will only be invoked when the request queue is
1358     empty, so this does not play well if somebody else keeps the request queue
1359     full at all times.
1360    
1361     =cut
1362    
1363     sub wait_for_slot {
1364     my ($self, $cb) = @_;
1365    
1366     push @{ $self->{wait} }, $cb;
1367     $self->_scheduler;
1368     }
1369    
1370 root 1.17 use AnyEvent::Socket (); # circular dependency, so do not import anything and do it at the end
1371    
1372 root 1.1 1;
1373    
1374     =back
1375    
1376     =head1 AUTHOR
1377    
1378 root 1.58 Marc Lehmann <schmorp@schmorp.de>
1379     http://home.schmorp.de/
1380 root 1.1
1381     =cut
1382