File Coverage

blib/lib/Net/Random/QRBG.pm
Criterion Covered Total %
statement 91 120 75.8
branch 15 34 44.1
condition 14 30 46.6
subroutine 16 21 76.1
pod 10 10 100.0
total 146 215 67.9


line stmt bran cond sub pod time code
1             package Net::Random::QRBG;
2              
3 4     4   152260 use warnings;
  4         11  
  4         147  
4 4     4   26 use strict;
  4         9  
  4         214  
5              
6             =head1 NAME
7              
8             Net::Random::QRBG - Gather random data from the QRBG Service
9              
10             =head1 VERSION
11              
12             Version 0.02
13              
14             =cut
15              
16             our $VERSION = '0.02';
17              
18 4     4   4716 use bytes;
  4         56  
  4         24  
19 4     4   119 use Carp ();
  4         9  
  4         82  
20 4     4   23 use Config;
  4         10  
  4         172  
21 4     4   5060 use IO::Socket::INET;
  4         158277  
  4         38  
22 4     4   5848 use List::Util qw(max);
  4         11  
  4         6427  
23              
24             =head1 SYNOPSIS
25              
26             Module retrieves random data from the QRBG Service
27              
28             use Net::Random::QRBG;
29              
30             my $foo = Net::Random::QRBG->new();
31             my $integer = $foo->getInt();
32              
33             =head1 FUNCTIONS
34              
35             =head2 new
36              
37             =cut
38              
39             sub new {
40 3     3 1 48 my ($package, %params) = @_;
41            
42 3         11 my $user = delete $params{user};
43 3   100     25 $user ||= 'nulluser';
44              
45 3         9 my $pass = delete $params{pass};
46 3   100     19 $pass ||= 'nullpass';
47            
48 3         7 my $server = delete $params{server};
49 3   50     30 $server ||= 'random.irb.hr';
50              
51 3         6 my $port = delete $params{port};
52 3   50     23 $port ||= '1227';
53              
54 3         8 my $cache_size = delete $params{cache_size};
55 3   50     19 $cache_size ||= 4096;
56              
57 3         8 my $cache = '';
58              
59 3         27 my $self = bless {
60             server => $server,
61             port => $port,
62             user => $user,
63             pass => $pass,
64             cache_size => $cache_size,
65             cache => $cache,
66             }, $package;
67              
68 3         17 return $self;
69             }
70              
71             =head2 credentials( $user, $pass )
72              
73             Get/Set user login details
74              
75             =cut
76              
77             sub credentials {
78 2     2 1 2271 my $self = shift;
79 2 100       10 if (@_) {
80 1         4 my ($user, $pass) = @_;
81 1         2 $self->{user} = $user;
82 1         4 $self->{pass} = $pass;
83             }
84 2         13 return ($self->{user}, $self->{pass});
85             }
86              
87             =head2 setCache( $cache_size )
88              
89             Get/Set the cacheSize
90              
91             =cut
92              
93             sub setCache {
94 2     2 1 1658 my ($self) = shift;
95 2 100       9 if (@_) {
96 1         3 my $new_size = shift;
97 1         2 $self->{cache_size} = $new_size;
98             }
99 2         8 return $self->{cache_size};
100             }
101              
102             =head2 getChar( $sign )
103              
104             Returns one char (8-bit) value.
105             Default signed, pass any value for unsigned.
106              
107             =cut
108              
109             sub getChar {
110 1     1 1 929 my ($self,$sign) = @_;
111 1   50     15 $sign ||= 0;
112 1         5 my $i = $self->_acquireBytes(1);
113 1 50       6 return undef unless $i;
114 1 50       7 if( $sign ) {
115 0         0 return unpack("C", $i);
116             } else {
117 1         9 return unpack("c", $i);
118             }
119             }
120              
121             =head2 getHexChar ( $end )
122              
123             Return hex char.
124             Default Big-Ended, pass any value for Little-Ended
125              
126             =cut
127              
128             sub getHexChar {
129 1     1 1 1140 my ($self,$end) = @_;
130 1   50     9 $end ||= 0;
131 1         5 my $i = $self->_acquireBytes(1);
132 1 50       6 return undef unless $i;
133 1 50       5 if ($end) {
134 0         0 return unpack("H", $i);
135             } else {
136 1         6 return unpack("h", $i);
137             }
138             }
139              
140             =head2 getShort( $sign )
141              
142             Returns one short (16-bits) value.
143             Default signed, pass any value for unsigned.
144              
145             =cut
146              
147             sub getShort {
148 1     1 1 949 my ($self,$sign) = @_;
149 1   50     14 $sign ||= 0;
150 1         5 my $i = $self->_acquireBytes(2);
151 1 50       6 return undef unless $i;
152 1 50       5 if( $sign ) {
153 0         0 return unpack("C", $i);
154             } else {
155 1         7 return unpack("c", $i);
156             }
157             }
158              
159             =head2 getLong( $sign )
160              
161             Returns one long (32-bit) value.
162             Default signed, pass any value for unsigned.
163              
164             =cut
165              
166             sub getLong {
167 1     1 1 1408 my ($self,$sign) = @_;
168 1   50     9 $sign ||= 0;
169 1         4 my $i = $self->_acquireBytes(4);
170 1 50       13 return undef unless $i;
171 1 50       6 if( $sign ) {
172 0         0 return unpack("L", $i);
173             } else {
174 1         9 return unpack("l", $i);
175             }
176             }
177              
178             =head2 getQuad( $sign )
179              
180             Returns one quad (64-bit) value.
181             Default signed, pass any value for unsigned.
182              
183             =cut
184              
185             sub getQuad {
186 0     0 1 0 my ($self,$sign) = @_;
187 0   0     0 $sign ||= 0;
188 0         0 my $i = $self->_acquireBytes(8);
189 0 0       0 return undef unless $i;
190 0 0       0 if( $sign ) {
191 0         0 return unpack("Q", $i);
192             } else {
193 0         0 return unpack("q", $i);
194             }
195             }
196              
197             =head2 getInt ( $sign )
198              
199             Return integer (Dependent on architecture)
200             Default signed, pass any value for unsigned.
201              
202             =cut
203              
204             sub getInt {
205 0     0 1 0 my ($self,$sign) = @_;
206 0   0     0 $sign ||= 0;
207 0         0 my $i = $self->_acquireBytes( $Config{intsize} );
208 0 0       0 return undef unless $i;
209 0 0       0 if( $sign ) {
210 0         0 return unpack("I", $i);
211             } else {
212 0         0 return unpack("i", $i);
213             }
214             }
215              
216             sub _fillCache {
217 0     0   0 my ($self) = @_;
218 0         0 return $self->_getMoreBytes( $self->{cache_size} );
219             }
220              
221             sub _acquireBytes {
222 4     4   102 my ($self, $count) = @_;
223 4 50 66     30 if ( ( bytes::length($self->{cache}) < $count ) && !$self->_getMoreBytes( max( $self->{cache_size}, $count ) ) ) {
224 0         0 return undef;
225             }
226 4         77 my $r = substr( $self->{cache}, 0, $count );
227 4         31 $self->{cache} = substr( $self->{cache}, $count );
228 4         19 return $r;
229             }
230              
231             sub _getMoreBytes {
232 1     1   1266 my ($self, $count) = @_;
233            
234 1 50       13 my $sock = IO::Socket::INET->new(
235             Proto => 'tcp',
236             PeerPort => $self->{port},
237             PeerAddr => $self->{server}
238             ) or die "Unable to create socket: $!\n";
239              
240 1         126183 my $un_length = length( $self->{user} );
241 1         5 my $pw_length = length( $self->{pass} );
242 1         4 my $content_size = 6 + $un_length + $pw_length;
243              
244 1         9 my $pcode = "xnca$un_length"."ca$pw_length"."N";
245 1         15 my $data = pack( $pcode, $content_size, $un_length, $self->{user}, $pw_length, $self->{pass}, $count );
246            
247 1         22 $sock->send($data);
248              
249 1         128 my $received = '';
250 1         102260 while( my $rcv = <$sock> ) {
251 12         44238 $received .= $rcv;
252             }
253 1         96 close($sock);
254              
255 1         32 my ($code, $code2, $bytes_returned, $rawdata) = unpack("ccNa*", $received);
256              
257 1 50 33     26 if( $code || $code2 ) {
258 0         0 $self->_seterror($code, $code2);
259 0         0 return undef;
260             }
261            
262 1         16 $self->{cache} .= $rawdata;
263 1         40 return 1;
264             }
265              
266             sub _seterror {
267 0     0     my ( $self, $c1, $c2 ) = @_;
268            
269 0           my @service_errors = (
270             "OK",
271             "Service was shutting down",
272             "Server was/is experiencing internal errors",
273             "Service said we have requested some unsupported operation",
274             "Service said we sent an ill-formed request packet",
275             "Service said we were sending our request too slow",
276             "Authentication failed",
277             "User quota exceeded" );
278              
279 0           my @service_fixes = (
280             "None",
281             "Try again later",
282             "Try again later",
283             "Upgrade your client software",
284             "Upgrade your client software",
285             "Check your network connection",
286             "Check your login credentials",
287             "Try again later, or contact Service admin to increase your quota(s)" );
288              
289 0           $self->{error} = $service_errors[$c1] . ": " . $service_fixes[$c2];
290             }
291              
292             =head2 errstr( )
293              
294             Return last error
295              
296             =cut
297              
298             sub errstr {
299 0     0 1   my $self = shift;
300 0   0       return $self->{error} || "";
301             }
302            
303             =head1 AUTHOR
304              
305             Brent Garber, C<< >>
306              
307             =head1 BUGS
308              
309             Please report any bugs or feature requests to C, or through
310             the web interface at L. I will be notified, and then you'll
311             automatically be notified of progress on your bug as I make changes.
312              
313              
314              
315              
316             =head1 SUPPORT
317              
318             You can find documentation for this module with the perldoc command.
319              
320             perldoc Net::Random::QRBG
321              
322              
323             You can also look for information at:
324              
325             =over 4
326              
327             =item * RT: CPAN's request tracker
328              
329             L
330              
331             =item * AnnoCPAN: Annotated CPAN documentation
332              
333             L
334              
335             =item * CPAN Ratings
336              
337             L
338              
339             =item * Search CPAN
340              
341             L
342              
343             =back
344              
345              
346             =head1 ACKNOWLEDGEMENTS
347              
348             Yea, the POD sucks. I'll fix it eventually.
349              
350             =head1 COPYRIGHT & LICENSE
351              
352             Copyright 2009 Brent Garber, all rights reserved.
353              
354             This program is free software; you can redistribute it and/or modify it
355             under the same terms as Perl itself.
356              
357              
358             =cut
359              
360             1; # End of Net::Random::QRBG