File Coverage

blib/lib/IO/Lambda/DNS.pm
Criterion Covered Total %
statement 45 61 73.7
branch 10 28 35.7
condition 5 9 55.5
subroutine 7 8 87.5
pod 2 2 100.0
total 69 108 63.8


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   943 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   5 use strict;
  1         1  
  1         23  
11 1     1   909 use Socket;
  1         4799  
  1         665  
12 1     1   917 use Net::DNS::Resolver;
  1         93501  
  1         35  
13 1     1   9 use IO::Lambda qw(:all);
  1         1  
  1         1033  
14              
15             # given the options, returns new dns lambda
16             sub new
17             {
18 5     5 1 9650 shift;
19              
20             # get the options
21 5         8 my @ctx;
22 5         12 my $timeout = $TIMEOUT;
23 5         9 my $retries = $RETRIES;
24 5         11 my %opt;
25 5         31 for ( my $i = 0; $i < @_; $i++) {
26 6 50 66     46 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     30 my $simple_query = (( 1 == @ctx) and not ref($ctx[0]));
47              
48             # proceed
49             lambda {
50 5     5   45 my $obj = Net::DNS::Resolver-> new( %opt);
51 5         233 my $bg_obj = $obj-> bgsend( @ctx);
52 5 50       6066 return "send error: " . $obj-> errorstring unless $bg_obj;
53              
54 5         9 my $sock;
55 5 50       20 if ( $Net::DNS::VERSION == 1.03 ) {
56             # this is a IO::Select object
57 0         0 my @handles = $bg_obj->handles;
58 0 0       0 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 0         0 $sock = $handles[0]->[0];
63             } else {
64 5         9 $sock = $bg_obj;
65             }
66              
67 5         21 context $sock, $timeout;
68             readable {
69 5 50       17 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         53 my $err = unpack('i', getsockopt($sock, SOL_SOCKET, SO_ERROR));
75 5 50       23 if ( $err) {
76 0         0 $! = $err;
77 0         0 return "socket error: $!";
78             }
79 5 50       32 return again unless $obj-> bgisready($bg_obj);
80              
81 5         597 my $packet = $obj-> bgread( $bg_obj);
82 5         8983 undef $sock;
83 5         9 undef $bg_obj;
84            
85 5 50       18 return "recv error: " . $obj-> errorstring unless $packet;
86              
87 5 100       16 if ( $simple_query) {
88             # behave like inet_aton, return single IP address
89 4         17 for ( $packet-> answer) {
90 4 50       51 return $_-> address if $_-> type eq 'A';
91             }
92 0         0 return 'response doesn\'t contain an IP address';
93             }
94              
95 1         5 return $packet;
96 5         48 }}}
  5         86  
97              
98 0     0 1   sub dns(&) { IO::Lambda::DNS-> new(context)-> condition(shift, \&dns, 'dns') }
99              
100             1;
101              
102             __DATA__