File Coverage

blib/lib/Net/Whois/Gateway/Client.pm
Criterion Covered Total %
statement 9 83 10.8
branch 0 32 0.0
condition 0 38 0.0
subroutine 3 13 23.0
pod 1 5 20.0
total 13 171 7.6


line stmt bran cond sub pod time code
1             package Net::Whois::Gateway::Client;
2              
3 1     1   2916 use strict;
  1         4  
  1         63  
4             #use Data::Dumper;
5 1     1   8 use Carp;
  1         2  
  1         108  
6 1     1   8114 use IO::Socket::INET;
  1         77552  
  1         10  
7              
8             require bytes;
9             require Storable;
10              
11             our $VERSION = 0.12;
12             our $DEBUG = 0;
13              
14             our $online;
15              
16             our %POSTPROCESS;
17             our $default_host = "localhost";
18             our $default_port = 54321;
19             our @answer;
20              
21              
22             our $configuration;
23              
24             our %SOCKET_FACTORY;
25              
26             # get whois info from gateway
27             # %param: queries*, gateway_host, gateway_post, timeout, ?????
28             sub whois {
29 0     0 1   my %param = @_;
30              
31 0 0         exists $param{query}
32             or die "No query given";
33              
34 0           my @answer = _send_request( %param );
35              
36 0           return apply_postprocess(@answer);
37             }
38              
39             sub _send_request {
40 0     0     my %param = @_;
41              
42 0   0       my $timeout = $param{timeout} || 30;
43 0           my $buffer;
44              
45             local $SIG{__DIE__} = sub {
46 0     0     $online = 0;
47 0           die @_;
48 0           };
49              
50 0           my $resp;
51              
52 0           foreach my $critical (0..1) {
53 0           $resp = eval {
54 0 0   0     local $SIG{ALRM} = sub { warn "timeout\n"; die "timeout\n" } if $timeout;
  0            
  0            
55 0 0         alarm $timeout*1.2 if $timeout;
56              
57 0           my ($socket, $new_socket) = _get_socket( \%param );
58 0 0         $socket or die "WHOIS: cannot open socket: $!";
59              
60 0 0 0       if ( $new_socket && $configuration ) {
61             # repeat configuration as not critical one
62 0           ping( default_config => $configuration );
63             }
64              
65             #use Data::Dumper;
66             #warn Dumper $socket;
67              
68             # $socket->connected
69             # or die "WHOIS: socket is not connected";
70              
71 0           my $frozen = Storable::nfreeze( [ \%param ] );
72 0           $frozen = bytes::length( $frozen ). "\0" . $frozen;
73            
74 0           my $w = $socket->syswrite( $frozen, bytes::length( $frozen ) );
75            
76 0 0 0       if ( ! defined $w || $w <= 0 ) {
77 0           die "WHOIS: Cannot syswrite to socket: $!";
78             }
79              
80 0           my $r = $socket->sysread( $buffer, 65536 );
81              
82 0 0 0       if ( ! defined $r || $r <= 0 ) {
83 0           die "WHOIS: Cannot sysread from socket: $!";
84             }
85              
86 0           return 1;
87             };
88              
89 0 0         if ( $@ ) {
90 0           _fail_socket( \%param );
91 0 0 0       warn $@ if ! $critical && $@ ne "timeout\n";
92             }
93              
94 0 0         last if $resp;
95             }
96              
97 0 0         alarm 0 if $timeout;
98              
99 0 0         if ( $@ ) {
100 0 0         if ( $@ eq "timeout\n" ) {
101 0           die "WHOIS: timeout calling sysread/syswrite";
102             }
103             else {
104 0           die $@;
105             }
106             }
107              
108 0           my $answer;
109              
110 0 0 0       if (
      0        
111             $buffer &&
112             $buffer =~ /^(\d+)\0/o &&
113             bytes::length( $buffer ) >= $1 + bytes::length($1) + 1
114             ) {
115 0           $answer = Storable::thaw( substr( $buffer, bytes::length($1) + 1, $1 ) );
116             }
117             else {
118 0           die "WHOIS: Cannot parse BUFFER";
119             }
120              
121 0           return @$answer;
122             }
123              
124             sub _fail_socket {
125 0     0     my $param_ref = shift;
126              
127 0   0       my $gateway_host = $param_ref->{gateway_host} || $default_host;
128 0   0       my $gateway_port = $param_ref->{gateway_port} || $default_port;
129              
130 0           my $addr = $gateway_host.':'.$gateway_port;
131              
132 0           delete $SOCKET_FACTORY{ $addr };
133             }
134              
135             sub _get_socket {
136 0     0     my $param_ref = shift;
137              
138 0   0       my $gateway_host = $param_ref->{gateway_host} || $default_host;
139 0   0       my $gateway_port = $param_ref->{gateway_port} || $default_port;
140              
141 0           my $addr = $gateway_host.':'.$gateway_port;
142              
143             # use Data::Dumper;
144             # warn Dumper \%SOCKET_FACTORY;
145              
146             #warn $SOCKET_FACTORY{$addr} && $SOCKET_FACTORY{$addr}->connected;
147              
148 0 0 0       return ($SOCKET_FACTORY{ $addr }, 0) if $SOCKET_FACTORY{ $addr }
149             && $SOCKET_FACTORY{ $addr }->connected;
150              
151             #warn "reconnection $addr";
152 0           $SOCKET_FACTORY{ $addr } = IO::Socket::INET->new( $addr );
153              
154 0           return ($SOCKET_FACTORY{ $addr }, 1);
155             }
156              
157             sub close_sockets {
158 0     0 0   $_->close() foreach values %SOCKET_FACTORY;
159 0           %SOCKET_FACTORY = ();
160             }
161              
162             sub configure {
163 0     0 0   my $new_config = shift;
164 0           $configuration = $new_config;
165             }
166              
167             sub ping {
168 0     0 0   my %params = (ping => 1, @_);
169 0           my $res;
170 0           $online = 1;
171 0           eval {
172 0           ($res) = _send_request(%params);
173             };
174 0           return $res;
175             }
176              
177             sub apply_postprocess {
178 0     0 0   my @all_results = @_;
179 0           my @out_results;
180            
181 0           foreach my $result ( @all_results ) {
182 0           my $server = $result->{server};
183 0 0 0       if ($result->{whois} && defined $POSTPROCESS{$server}) {
184 0           $result->{whois} = $POSTPROCESS{$server}->($result->{whois});
185             }
186 0           push @out_results, $result;
187             }
188            
189 0           return @out_results;
190             }
191              
192             1;
193             __END__