File Coverage

blib/lib/IO/Lambda/DNS.pm
Criterion Covered Total %
statement 47 61 77.0
branch 11 28 39.2
condition 5 9 55.5
subroutine 7 8 87.5
pod 2 2 100.0
total 72 108 66.6


line stmt bran cond sub pod time code
1             # $Id: DNS.pm,v 1.10 2009/08/02 21:24:40 dk Exp $
2             package IO::Lambda::DNS;
3 1     1   1113 use vars qw($DEBUG $TIMEOUT $RETRIES @ISA);
  1         2  
  1         103  
4             @ISA = qw(Exporter);
5             @EXPORT_OK = qw(dns);
6             %EXPORT_TAGS = ( all => \@EXPORT_OK);
7             $TIMEOUT = 4.0; # seconds
8             $RETRIES = 4; # times
9              
10 1     1   4 use strict;
  1         2  
  1         24  
11 1     1   895 use Socket;
  1         5018  
  1         647  
12 1     1   993 use Net::DNS::Resolver;
  1         106363  
  1         48  
13 1     1   12 use IO::Lambda qw(:all);
  1         2  
  1         1514  
14              
15             # given the options, returns new dns lambda
16             sub new
17             {
18 5     5 1 22763 shift;
19              
20             # get the options
21 5         13 my @ctx;
22 5         12 my $timeout = $TIMEOUT;
23 5         10 my $retries = $RETRIES;
24 5         12 my %opt;
25 5         32 for ( my $i = 0; $i < @_; $i++) {
26 6 50 66     43 if ( $i == 0 or $i == $#_ or not defined($_[$i])) {
    0 33        
    0          
    0          
27             # first or last or undef parameter in no way can be an option
28 6         37 push @ctx, $_[$i];
29             } elsif ( $_[$i] =~ /^(timeout|deadline)$/) {
30 0         0 $timeout = $_[++$i];
31             } elsif ( $_[$i] eq 'retry') {
32 0         0 $retries = $_[++$i];
33             } elsif ( $_[$i] =~ /^(
34             nameservers|recurse|debug|config_file|
35             domain|port|srcaddr|srcport|retrans|
36             usevc|stayopen|igntc|defnames|dnsrch|
37             persistent_tcp|persistent_udp|dnssec
38             )$/x) {
39 0         0 $opt{$_[$i]} = $_[$i + 1];
40 0         0 $i++;
41             } else {
42 0         0 push @ctx, $_[$i];
43             }
44             }
45              
46 5   66     38 my $simple_query = (( 1 == @ctx) and not ref($ctx[0]));
47              
48             # proceed
49             lambda {
50 5     5   47 my $obj = Net::DNS::Resolver-> new( %opt);
51 5         242 my $bg_obj = $obj-> bgsend( @ctx);
52 5 50       7219 return "send error: " . $obj-> errorstring unless $bg_obj;
53              
54 5         11 my $sock;
55 5 50       19 if ( $Net::DNS::VERSION > 1.02 ) {
56             # this is a IO::Select object
57 5         20 my @handles = $bg_obj->handles;
58 5 50       160 if ( 1 != @handles ) {
59 0         0 warn "There's something wrong with Net::DNS version $Net::DNS::VERSION, please notify the author\n";
60 0         0 return "panic: Net::DNS returned not 1 socket\n";
61             }
62 5         13 $sock = $handles[0]->[0];
63             } else {
64 0         0 $sock = $bg_obj;
65             }
66              
67 5         61 context $sock, $timeout;
68             readable {
69 5 50       20 unless ( shift) {
70 0 0       0 return 'connect timeout' if $retries-- <= 0;
71 0         0 return this-> start; # restart the whole lambda
72             }
73              
74 5         60 my $err = unpack('i', getsockopt($sock, SOL_SOCKET, SO_ERROR));
75 5 50       19 if ( $err) {
76 0         0 $! = $err;
77 0         0 return "socket error: $!";
78             }
79 5 50       31 return again unless $obj-> bgisready($bg_obj);
80              
81 5         270 my $packet = $obj-> bgread( $bg_obj);
82 5         12810 undef $sock;
83 5         18 undef $bg_obj;
84            
85 5 50       20 return "recv error: " . $obj-> errorstring unless $packet;
86              
87 5 100       19 if ( $simple_query) {
88             # behave like inet_aton, return single IP address
89 4         16 for ( $packet-> answer) {
90 4 50       58 return $_-> address if $_-> type eq 'A';
91             }
92 0         0 return 'response doesn\'t contain an IP address';
93             }
94              
95 1         7 return $packet;
96 5         56 }}}
  5         44  
97              
98 0     0 1   sub dns(&) { IO::Lambda::DNS-> new(context)-> condition(shift, \&dns, 'dns') }
99              
100             1;
101              
102             __DATA__