File Coverage

blib/lib/XAS/Lib/Net/Client.pm
Criterion Covered Total %
statement 12 120 10.0
branch 0 36 0.0
condition n/a
subroutine 4 16 25.0
pod 10 11 90.9
total 26 183 14.2


line stmt bran cond sub pod time code
1             package XAS::Lib::Net::Client;
2              
3             our $VERSION = '0.03';
4              
5 1     1   4 use IO::Socket;
  1         1  
  1         7  
6 1     1   820 use IO::Select;
  1         1081  
  1         36  
7 1     1   5 use Errno ':POSIX';
  1         2  
  1         298  
8              
9             use XAS::Class
10 1         10 debug => 0,
11             version => $VERSION,
12             base => 'XAS::Base',
13             mixin => 'XAS::Lib::Mixins::Bufops',
14             utils => ':validation dotid trim',
15             accessors => 'handle select attempts',
16             mutators => 'timeout',
17             import => 'class',
18             vars => {
19             PARAMS => {
20             -port => 1,
21             -host => 1,
22             -timeout => { optional => 1, default => 60 },
23             -eol => { optional => 1, default => "\015\012" },
24             },
25             ERRNO => 0,
26             ERRSTR => '',
27             }
28 1     1   5 ;
  1         2  
29              
30              
31             #use Data::Hexdumper;
32              
33             # ----------------------------------------------------------------------
34             # Public Methods
35             # ----------------------------------------------------------------------
36              
37             sub connect {
38 0     0 1   my $self = shift;
39              
40 0           $self->class->var('ERRNO', 0);
41 0           $self->class->var('ERRSTR', '');
42              
43             $self->{'handle'} = IO::Socket::INET->new(
44             Proto => 'tcp',
45             PeerPort => $self->port,
46             PeerAddr => $self->host,
47             Timeout => $self->timeout,
48 0 0         ) or do {
49              
50 0           my $errno = $! + 0;
51 0           my $errstr = $!;
52              
53 0           $self->class->var('ERRNO', $errno);
54 0           $self->class->var('ERRSTR', $errstr);
55              
56 0           $self->throw_msg(
57             dotid($self->class) . '.connect.noconnect',
58             'net_client_noconnect',
59             $self->host,
60             $self->port,
61             $errstr
62             );
63              
64             };
65              
66 0           $self->handle->blocking(0);
67 0           $self->{'select'} = IO::Select->new($self->handle);
68              
69             }
70              
71             sub pending {
72 0     0 1   my $self = shift;
73              
74 0           return length($self->{'buffer'});
75              
76             }
77              
78             sub disconnect {
79 0     0 1   my $self = shift;
80              
81 0 0         if ($self->handle->connected) {
82              
83 0           $self->handle->close();
84              
85             }
86              
87             }
88              
89             sub get {
90 0     0 1   my $self = shift;
91 0           my ($length) = validate_params(\@_, [
92             { optional => 1, default => 512 }
93             ]);
94              
95 0           my $output;
96              
97 0 0         if ($self->pending > $length) {
98              
99 0           $output = $self->buf_slurp(\$self->{'buffer'}, $length);
100              
101             } else {
102              
103 0           $self->_fill_buffer();
104              
105 0 0         my $l = ($self->pending > $length) ? $length : $self->pending;
106 0           $output = $self->buf_slurp(\$self->{'buffer'}, $l);
107              
108             }
109              
110 0           return $output;
111              
112             }
113              
114             sub gets {
115 0     0 1   my $self = shift;
116              
117 0           my $buffer;
118 0           my $output = '';
119              
120 0           while (my $buf = $self->get()) {
121              
122 0           $buffer .= $buf;
123              
124 0 0         if ($output = $self->buf_get_line(\$buffer, $self->eol)) {
125              
126 0           $self->{'buffer'} = $buffer . $self->{'buffer'};
127 0           last;
128              
129             }
130              
131             }
132              
133 0           return trim($output);
134              
135             }
136              
137             sub put {
138 0     0 1   my $self = shift;
139 0           my ($buffer) = validate_params(\@_, [1]);
140              
141 0           my $counter = 0;
142 0           my $working = 1;
143 0           my $written = 0;
144 0           my $timeout = $self->timeout;
145 0           my $bufsize = length($buffer);
146              
147 0           $self->class->var('ERRNO', 0);
148 0           $self->class->var('ERRSTR', '');
149              
150 0           while ($working) {
151              
152 0           $self->handle->clearerr();
153              
154 0 0         if ($self->select->can_write($timeout)) {
155              
156 0 0         if (my $bytes = $self->handle->syswrite($buffer, $bufsize)) {
157              
158 0           $written += $bytes;
159 0           $buffer = substr($buffer, $bytes);
160 0 0         $working = 0 if ($written >= $bufsize);
161              
162             } else {
163              
164 0 0         if ($self->handle->error) {
165              
166 0           my $errno = $! + 0;
167 0           my $errstr = $!;
168              
169 0 0         if ($errno == EAGAIN) {
170              
171 0           $counter++;
172 0 0         $working = 0 if ($counter > $self->attempts);
173              
174             } else {
175              
176 0           $self->class->var('ERRNO', $errno);
177 0           $self->class->var('ERRSTR', $errstr);
178              
179 0           $self->throw_msg(
180             dotid($self->class) . '.put',
181             'net_client_network',
182             $errstr
183             );
184              
185             }
186              
187             }
188              
189             }
190              
191             } else {
192              
193 0           $working = 0;
194              
195             }
196              
197             }
198              
199 0           return $written;
200              
201             }
202              
203             sub puts {
204 0     0 1   my $self = shift;
205 0           my ($buffer) = validate_params(\@_, [1]);
206              
207 0           my $data = sprintf("%s%s", trim($buffer), $self->eol);
208 0           my $written = $self->put($data);
209              
210 0           return $written;
211              
212             }
213              
214             sub errno {
215 0     0 1   my $class = shift;
216 0           my ($value) = validate_params(\@_, [
217             { optional => 1, default => undef }
218             ]);
219              
220 0 0         class->var('ERRNO', $value) if (defined($value));
221              
222 0           return class->var('ERRNO');
223              
224             }
225              
226             sub errstr {
227 0     0 1   my $class = shift;
228 0           my ($value) = validate_params(\@_, [
229             { optional => 1, default => undef }
230             ]);
231              
232 0 0         class->var('ERRSTR', $value) if (defined($value));
233              
234 0           return class->var('ERRSTR');
235              
236             }
237              
238             sub setup {
239 0     0 0   my $self = shift;
240              
241             }
242              
243             # ----------------------------------------------------------------------
244             # Private Methods
245             # ----------------------------------------------------------------------
246              
247             sub init {
248 0     0 1   my $class = shift;
249              
250 0           my $self = $class->SUPER::init(@_);
251              
252 0           $self->{'attempts'} = 5;
253 0           $self->{'buffer'} = '';
254              
255 0           return $self;
256              
257             }
258              
259             sub _fill_buffer {
260 0     0     my $self = shift;
261            
262 0           my $counter = 0;
263 0           my $working = 1;
264 0           my $read = 0;
265 0           my $timeout = $self->timeout;
266              
267 0           $self->class->var('ERRNO', 0);
268 0           $self->class->var('ERRSTR', '');
269              
270 0           $self->handle->blocking(0);
271              
272 0           while ($working) {
273              
274 0           my $buf;
275              
276 0           $self->handle->clearerr();
277              
278 0 0         if ($self->select->can_read($timeout)) {
279              
280 0 0         if (my $bytes = $self->handle->sysread($buf, 512)) {
281              
282 0           $self->{'buffer'} .= $buf;
283 0           $read += $bytes;
284              
285             } else {
286              
287 0 0         if ($self->handle->error) {
288              
289 0           my $errno = $! + 0;
290 0           my $errstr = $!;
291              
292 0           $self->log->debug("fill_buffer: errno = $errno");
293              
294 0 0         if ($errno == EAGAIN) {
295              
296 0           $counter++;
297 0 0         $working = 0 if ($counter > $self->attempts);
298              
299             } else {
300              
301 0           $self->class->var('ERRNO', $errno);
302 0           $self->class->var('ERRSTR', $errstr);
303              
304 0           $self->throw_msg(
305             dotid($self->class) . '.fill_buffer',
306             'net_client_network',
307             $errstr
308             );
309              
310             }
311              
312             }
313              
314             }
315              
316             } else {
317              
318 0           $working = 0;
319              
320             }
321              
322             }
323              
324 0           $self->handle->blocking(1);
325              
326 0           return $read;
327              
328             }
329              
330             1;
331              
332             __END__