File Coverage

blib/lib/IO/Socket/CLI.pm
Criterion Covered Total %
statement 92 144 63.8
branch 38 72 52.7
condition 10 23 43.4
subroutine 16 25 64.0
pod 17 17 100.0
total 173 281 61.5


line stmt bran cond sub pod time code
1             package IO::Socket::CLI;
2             $IO::Socket::CLI::VERSION = '0.041';
3 2     2   1281 use 5.006;
  2         5  
  2         66  
4 2     2   8 use strict;
  2         3  
  2         68  
5 2     2   22 use warnings;
  2         3  
  2         61  
6 2     2   1494 use IO::Socket::SSL;
  2         153102  
  2         16  
7 2     2   1351 use IO::Socket::INET6;
  2         7538  
  2         12  
8 2     2   1049 use Carp;
  2         3  
  2         2424  
9              
10             # defaults
11             my $DEBUG = 0; # boolean?
12             my $DELAY = 10; # number of milliseconds between each attempt at reading the response from the server.
13             my $TIMEOUT = 5; # number of seconds to wait for a response from server before returning an empty list.
14             my $PRINT_RESPONSE = 1; # boolean
15             my $PREPEND = 1; # boolean
16             our $SSL = 0; # boolean
17             my $HOST = '127.0.0.1'; # IP or domain
18             our $PORT = '143'; # port
19             our $BYE = qr'^\* BYE( |\r?$)'; # string server sends when it hangs up.
20              
21             sub new {
22 1     1 1 938 my $this = shift;
23 1   33     8 my $class = ref($this) || $this;
24 1         3 my $self = {};
25 1 50       7 my $args = (ref($_[0]) eq 'HASH') ? $_[0] : {@_};
26              
27 1 50       5 $self->{_HOST} = ($args->{HOST}) ? $args->{HOST} : $HOST;
28 1 50       5 $self->{_PORT} = ($args->{PORT}) ? $args->{PORT} : $PORT;
29 1 50       5 $self->{_BYE} = ($args->{BYE}) ? $args->{BYE} : $BYE;
30 1 50       4 $self->{_DELAY} = ($args->{DELAY}) ? $args->{DELAY} : $DELAY;
31 1 50       4 $self->{_TIMEOUT} = ($args->{TIMEOUT}) ? $args->{TIMEOUT} : $TIMEOUT;
32 1 50       6 $self->{_PRINT_RESPONSE} = (defined $args->{PRINT_RESPONSE}) ? $args->{PRINT_RESPONSE} : $PRINT_RESPONSE;
33 1 50       3 $self->{_PREPEND} = (defined $args->{PREPEND}) ? $args->{PREPEND} : $PREPEND;
34 1 50       5 $self->{_DEBUG} = (defined $args->{DEBUG}) ? $args->{DEBUG} : $DEBUG;
35 1 50       4 $self->{_SSL} = (defined $args->{SSL}) ? $args->{SSL} : $SSL;
36 1   50     10 $self->{_SOCKET} = IO::Socket::INET6->new(PeerAddr => $self->{_HOST},
37             PeerPort => $self->{_PORT},
38             Blocking => 0) ||
39             die "Can't bind : $@\n";
40              
41 1 50       909 ($self->{_SSL}) and IO::Socket::SSL->start_SSL($self->{_SOCKET});
42 1 50       10 $self->{_OPEN} = ($self->{_SOCKET}->connected()) ? 1 : 0;
43 1         13 $self->{_COMMAND} = '';
44 1         3 $self->{_SERVER_RESPONSE} = [];
45              
46 1         2 bless ($self, $class);
47 1         3 return $self;
48             }
49              
50             sub read {
51 0     0 1 0 my $self = shift;
52 0         0 my $i = 0;
53 0         0 my $max_i = $self->{_TIMEOUT} / ($self->{_DELAY} / 1000);
54              
55 0         0 do {
56 0         0 select(undef, undef, undef, $self->{_DELAY} / 1000);
57 0         0 @{$self->{_SERVER_RESPONSE}} = $self->{_SOCKET}->getlines;
  0         0  
58 0         0 $i++;
59 0   0     0 } while (!@{$self->{_SERVER_RESPONSE}} && $i < $max_i);
60              
61 0 0 0     0 if ($DEBUG || $self->{_DEBUG}) {
62 0         0 print STDOUT "D: response took roughly " . ($i * $self->{_DELAY}) . " milliseconds\n";
63             }
64              
65 0 0       0 $self->print_resp() if ($self->{_PRINT_RESPONSE});
66              
67 0         0 return @{$self->{_SERVER_RESPONSE}};
  0         0  
68             }
69              
70             sub response {
71 0     0 1 0 my $self = shift;
72 0         0 return @{$self->{_SERVER_RESPONSE}};
  0         0  
73             }
74              
75             sub print_resp {
76 0     0 1 0 my $self = shift;
77 0         0 foreach (@{$self->{_SERVER_RESPONSE}}) {
  0         0  
78 0 0       0 print STDOUT "" . (($self->{_PREPEND}) ? "S: " : "") . "$_";
79             }
80             }
81              
82             sub is_open {
83 0     0 1 0 my $self = shift;
84 0         0 my $bye = $self->{_BYE};
85 0 0       0 $self->{_OPEN} = ($self->{_SOCKET}->connected()) ? 1 : 0;
86 0         0 foreach (@{$self->{_SERVER_RESPONSE}}) {
  0         0  
87 0 0       0 $self->{_OPEN} = 0 if (/$bye/);
88 0         0 last;
89             }
90 0         0 return $self->{_OPEN};
91             }
92              
93             sub send($) {
94 0     0 1 0 my $self = shift;
95 0         0 chomp (my $command = shift);
96 0         0 $self->{_COMMAND} = $command;
97 0 0       0 print STDOUT "" . ($self->{_PREPEND} ? "C: " : "") . "$command\r\n" if ($self->{_PRINT_RESPONSE});
    0          
98 0         0 $self->{_SOCKET}->syswrite("$command\r\n");
99             }
100              
101             sub prompt {
102 0     0 1 0 my $self = shift;
103 0 0       0 print STDOUT "C: " if ($self->{_PREPEND}); # client prompt
104 0         0 chomp(my $command = );
105 0         0 $self->{_COMMAND} = $command;
106 0         0 $self->{_SOCKET}->syswrite("$command\r\n");
107             }
108              
109             sub command() {
110 0     0 1 0 my $self = shift;
111 0         0 return $self->{_COMMAND};
112             }
113              
114             sub print_response {
115 4     4 1 2506 my $self = shift;
116 4 100       13 if (@_) {
117 3         2 my $boolean = shift;
118 3 100 66     17 if ($boolean and $boolean != 1) {
119 2         238 carp "warning: valid settings for print_response() are 0 or 1 -- setting to $PRINT_RESPONSE";
120 2         66 $boolean = $PRINT_RESPONSE;
121             }
122 3         6 $self->{_PRINT_RESPONSE} = $boolean;
123             }
124 4         16 return $self->{_PRINT_RESPONSE};
125             }
126              
127             sub prepend {
128 4     4 1 8 my $self = shift;
129 4 100       10 if (@_) {
130 3         3 my $boolean = shift;
131 3 100 66     14 if ($boolean and $boolean != 1) {
132 2         158 carp "warning: valid settings for prepend() are 0 or 1 -- setting to $PREPEND";
133 2         56 $boolean = $PREPEND;
134             }
135 3         6 $self->{_PREPEND} = $boolean;
136             }
137 4         18 return $self->{_PREPEND};
138             }
139              
140             sub timeout {
141 4     4 1 7 my $self = shift;
142 4 100       10 if (@_) {
143 3         3 my $seconds = shift;
144 3 100       7 if ($seconds < 0) {
145 1         80 carp "warning: timeout() must be non-negative -- setting to $TIMEOUT";
146 1         28 $seconds = $TIMEOUT;
147             }
148 3         7 $self->{_TIMEOUT} = $seconds;
149             }
150 4         15 return $self->{_TIMEOUT};
151             }
152              
153             sub delay {
154 4     4 1 7 my $self = shift;
155 4 100       12 if (@_) {
156 3         4 my $milliseconds = shift;
157 3 100       8 if ($milliseconds < 1) {
158 2         197 carp "warning: delay() must be positive -- setting to $DELAY";
159 2         70 $milliseconds = $DELAY;
160             }
161 3         6 $self->{_DELAY} = $milliseconds;
162             }
163 4         16 return $self->{_DELAY};
164             }
165              
166             sub bye {
167 3     3 1 5 my $self = shift;
168 3 100       8 if (@_) {
169 2         3 my $bye = shift;
170 2 100       11 unless ($bye =~ /\(\?(?:-xism|\^):.*\)/) {
171 1         81 carp "warning: bye() must be a regexp-like quote: qr/STRING/ -- setting to '$BYE' instead of '$bye'";
172 1         34 $bye = $BYE;
173             }
174 2         4 $self->{_BYE} = $bye;
175             }
176 3         20 return $self->{_BYE};
177             }
178              
179             sub debug {
180 5     5 1 9 my $self = shift;
181 5 100       12 if (@_) {
182 4         4 my $boolean = shift;
183 4 100 100     19 if ($boolean and $boolean != 1) {
184 2         169 carp "warning: valid settings for debug() are 0 or 1 -- setting to 1";
185 2         57 $boolean = 1;
186             }
187 4         8 $self->{_DEBUG} = $boolean;
188             }
189 5         48 return $self->{_DEBUG};
190             }
191              
192             #sub debug {
193             # my $self = shift;
194             # confess 'error: thing->debug($level)' unless @_ == 1;
195             # my $level = shift;
196             # if (ref($self)) {
197             # $self->{_DEBUG} = $level; # just myself
198             # } else {
199             # $DEBUG = $level; # whole class
200             # }
201             #}
202              
203             sub socket {
204 0     0 1 0 my $self = shift;
205 0         0 return $self->{_SOCKET};
206             }
207              
208             sub errstr {
209 0     0 1 0 my $self = shift;
210 0 0       0 if ($self->{_SSL}) {
211 0         0 return $self->{_SOCKET}->errstr();
212             } else {
213 0         0 return undef;
214             }
215             }
216              
217             sub close {
218 1     1 1 6 my $self = shift;
219 1         13 return $self->{_SOCKET}->close();
220 0 0       0 if ($self->{_SSL}) {
221 0         0 return $self->{_SOCKET}->stop_SSL(SSL_ctx_free => 1);
222             } else {
223 0         0 return $self->{_SOCKET}->close();
224             }
225             }
226              
227             # object destructor
228             sub DESTROY {
229 1     1   1903 my $self = shift;
230 1 50 33     9 if ($DEBUG || $self->{"_DEBUG"}) {
231 0         0 carp "Destroying $self " . $self->{_HOST} . ":" . $self->{_PORT};
232             }
233 1         4 $self->close();
234             }
235              
236             # class destructor
237             sub END {
238 1 50   1     if ($DEBUG) {
239 0           print STDOUT "class destroyed.\n";
240             }
241             }
242              
243             1;
244              
245             __END__