File Coverage

lib/Haineko/DNS.pm
Criterion Covered Total %
statement 73 74 98.6
branch 11 14 78.5
condition 5 6 83.3
subroutine 17 17 100.0
pod 7 8 87.5
total 113 119 94.9


line stmt bran cond sub pod time code
1             package Haineko::DNS;
2 2     2   9829 use feature ':5.10';
  2         5  
  2         290  
3 2     2   11 use strict;
  2         4  
  2         116  
4 2     2   9 use warnings;
  2         3  
  2         64  
5 2     2   19918 use Net::DNS;
  2         341335  
  2         209  
6 2     2   2149 use Try::Tiny;
  2         3409  
  2         132  
7 2     2   1045 use Class::Accessor::Lite;
  2         1086  
  2         17  
8              
9             my $rwaccessors = [
10             'A', # (ArrayRef) A
11             'MX', # (ArrayRef) MX
12             'NS', # (ArrayRef) NS
13             'TXT', # (ArrayRef) TXT
14             ];
15             my $roaccessors = [
16             'name', # (String) domain name
17             ];
18             my $woaccessors = [];
19             Class::Accessor::Lite->mk_accessors( @$rwaccessors );
20             Class::Accessor::Lite->mk_ro_accessors( @$roaccessors );
21              
22             my $DNSRR = [ 'A', 'MX', 'NS', 'TXT' ];
23              
24             sub new {
25 7     7 1 2948 my $class = shift;
26 7   100     33 my $argvs = shift // return undef;
27 6         32 my $param = { 'name' => lc $argvs };
28              
29 6         27 return bless $param, __PACKAGE__;
30             }
31              
32             sub flush {
33 4     4 0 11 my $self = shift;
34              
35 4         15 for my $e ( @$DNSRR ) {
36 16 50       89 delete $self->{ $e } if exists $self->{ $e };
37             }
38 4         53 return $self;
39             }
40              
41             sub resolve {
42 26     26 1 41824 my $self = shift;
43 26   100     154 my $type = shift || 'A';
44 26         73 my $name = $self->{'name'};
45              
46 26         51 my $rrresolver = undef;
47 26         52 my $rrqueryset = undef;
48 26         42 my $resolvedrr = undef;
49 26         161 my $methodlist = {
50             'A' => 'address',
51             'MX' => 'exchange',
52             'NS' => 'nsdname',
53             'TXT' => 'txtdata',
54             };
55              
56             try {
57 26     26   4283 $rrresolver = Net::DNS::Resolver->new;
58 26         2644 $rrqueryset = $rrresolver->query( $self->{'name'}, $type );
59 26         1063905 $resolvedrr = [];
60              
61 26         260 for my $e ( $rrqueryset->answer ) {
62             # $rrqueryset is a Net::DNS::Packet object
63 22         1294 my $ttlsec = $e->ttl;
64 22         423 my $method = $methodlist->{ $type };
65 22         379 my $record = {
66             'rr' => $e->$method,
67             'ttl' => $ttlsec,
68             'exp' => time + $ttlsec,
69             'p' => 0,
70             };
71              
72 22 100       1237 $record->{'p'} = $e->preference if $type eq 'MX';
73 22         273 push @$resolvedrr, $record;
74             }
75              
76             } catch {
77             # ...
78 9     9   162 $resolvedrr = [];
79 26         313 };
80              
81 26 100       1572 if( $type eq 'MX' ) {
82             # Sort by preference
83 7         51 $self->{'MX'} = [ sort { $a->{'p'} <=> $b->{'p'} } @$resolvedrr ];
  0         0  
84              
85             } else {
86 19         145 $self->{ $type } = $resolvedrr;
87             }
88              
89 26         1111 return $self;
90             }
91              
92             sub rr {
93 20     20 1 45 my $self = shift;
94 20 50 50     93 my $type = shift || 'A'; $type = 'A' unless grep { $type eq $_ } @$DNSRR;
  20         70  
  80         274  
95 20         37 my $dnsr = undef;
96              
97             my $pick = sub {
98 26     26   76 my $list = [];
99 26 100       137 return [] unless ref $self->$type eq 'ARRAY';
100              
101 22         209 for my $r ( @{ $self->$type } ) {
  22         77  
102 19 50       124 next if $r->{'exp'} < time;
103 19         65 push @$list, $r->{'rr'};
104             }
105 22         134 return $list;
106 20         131 };
107              
108 20         60 $dnsr = $pick->();
109 20 100       171 return $dnsr if scalar @$dnsr;
110              
111 6         20 $self->resolve( $type );
112 6         22 return $pick->();
113             }
114              
115             sub arr {
116 6     6 1 16845 my $self = shift;
117 6         27 return $self->rr('A');
118             }
119              
120             sub mxrr {
121 6     6 1 6833 my $self = shift;
122 6         24 return $self->rr('MX');
123             }
124              
125             sub nsrr {
126 4     4 1 20071 my $self = shift;
127 4         17 return $self->rr('NS');
128             }
129              
130             sub txtrr {
131 4     4 1 10277 my $self = shift;
132 4         16 return $self->rr('TXT');
133             }
134              
135             1;
136             __END__