File Coverage

blib/lib/Alvis/Tana.pm
Criterion Covered Total %
statement 3 196 1.5
branch 0 128 0.0
condition 0 9 0.0
subroutine 1 10 10.0
pod 0 9 0.0
total 4 352 1.1


line stmt bran cond sub pod time code
1             package Alvis::Tana;
2              
3             $Alvis::Tana::VERSION = '0.1';
4              
5             # use Data::Dumper;
6              
7 1     1   5 use strict;
  1         2  
  1         3003  
8              
9             my %ERROR;
10             my $debug = 0;
11              
12             ######################################################################
13             #
14             # Public methods
15             #
16             ###################################################################
17              
18             sub error($)
19             {
20 0     0 0   my ($client) = @_;
21 0           return $ERROR{$client};
22             }
23              
24             sub readname($)
25             {
26 0     0 0   my ($client) = @_;
27              
28 0           my $len = readnum($client);
29 0 0         if(!defined($len))
30             {
31 0           return undef;
32             }
33              
34 0           my ($name,$got) = readbytes($client, $len);
35 0 0         if(!defined($name))
36             {
37 0           return undef;
38             }
39            
40 0           return $name;
41             }
42              
43             sub readnum($)
44             {
45 0     0 0   my ($client) = @_;
46              
47 0           my $got = 0;
48 0           my $num = '';
49 0           my $char = '0';
50              
51 0           while($char =~ /[0-9]/)
52             {
53 0           my $bytes = CORE::sysread($client, $char, 1);
54 0 0         if($bytes != 1)
55             {
56 0           $ERROR{$client} = "Readnum error: $@";
57 0 0         !$debug || print STDERR "readnum: $ERROR{$client}\n";
58 0           return undef;
59             }
60              
61 0 0         if($char =~ /[0-9]/)
62             {
63 0           $num .= $char;
64 0           $got++;
65             }
66             }
67              
68 0 0         if($char =~ /[^\n ]/)
69             {
70 0           $ERROR{$client} = "Non-eol/space at end of number. Got '$char' instead.";
71 0 0         !$debug || print STDERR "readnum: $ERROR{$client}\n";
72 0           return undef;
73             }
74 0 0         if(0 == $got)
75             {
76 0           $ERROR{$client} = "No numbers in readnum, got '$char' instead.";
77 0 0         !$debug || print STDERR "readnum: $ERROR{$client}\n";
78 0           return undef;
79             }
80              
81             # warn "Alvis::Tana::readnum() read num $num";
82            
83 0           return $num;
84             }
85              
86             sub readbytes($$)
87             {
88 0     0 0   my ($client, $len) = @_;
89              
90 0           my $str = '';
91              
92              
93 0           my $got = CORE::sysread($client, $str, $len);
94             # if($len != $got)
95             # {
96             # warn "Alvis::Tana::readbytes(): Wanted $len bytes, got $got";
97             # $ERROR{$client} = "Wanted $len bytes, got $got";
98             # !$debug || print STDERR "readnum: $ERROR{$client}\n";
99             # return undef;
100             # }
101              
102             # warn "Alvis::Tana::readbytes(): read $str";
103            
104 0           return ($str,$got);
105             }
106              
107             sub read_field_header($)
108             {
109 0     0 0   my ($client) = @_;
110              
111 0           my $keylen = readnum($client);
112 0 0         if(!defined($keylen))
113             {
114 0 0         !$debug || print STDERR "read: $ERROR{$client}\n";
115 0           return (undef, undef);
116             }
117 0 0         !$debug || print "keylen = *$keylen*\n";
118            
119 0           my ($key,$got) = readbytes($client, $keylen);
120 0 0         if(!defined($key))
121             {
122 0 0         !$debug || print STDERR "read: $ERROR{$client}\n";
123 0           return (undef, undef);
124             }
125 0 0         !$debug || print "key = $key\n";
126            
127 0           my $dummy;
128 0           ($dummy,$got)=readbytes($client, 2);
129 0 0         if(!defined($dummy))
130             {
131 0 0         !$debug || print STDERR "read: $ERROR{$client}\n";
132 0           return (undef, undef);
133             }
134            
135 0           return ($keylen, $key);
136             }
137              
138             sub read
139             {
140 0     0 0   my ($client, $autoread_arb) = @_;
141              
142 0           my $mtype = '';
143 0           my $got = CORE::sysread($client, $mtype, 4);
144 0 0         if(4 != $got)
145             {
146 0           warn "Tana read() Expected 4, got $got";
147 0           $ERROR{$client} = "$@";
148 0           return undef;
149             }
150 0           $mtype =~ s/(...)./$1/;
151              
152 0           my $fieldc = readnum($client);
153 0 0         if(!defined($fieldc))
154             {
155 0           return undef;
156             }
157            
158 0 0 0       if(($mtype ne 'arb') && ($mtype ne 'fix'))
159             {
160 0           $ERROR{$client} = "Invalid message type '$mtype'";
161 0 0         !$debug || print STDERR "read: $ERROR{$client}\n";
162 0           return undef;
163             }
164              
165 0           my $read_arb = 1;
166 0 0         if(defined($$autoread_arb))
167             {
168 0 0         if(! $$autoread_arb)
169             {
170 0           $read_arb = 0;
171             }
172             }
173              
174 0           my $msg = {};
175              
176 0 0 0       if(($mtype eq 'arb') && (!$read_arb))
177             {
178 0           $fieldc--;
179             }
180              
181 0           for(my $i = 0; $i < $fieldc; $i++)
182             {
183 0           my ($keylen, $key) = read_field_header($client);
184              
185             # warn "Alvis::Tana::read(): keylen:$keylen key: $key";
186              
187 0 0         if(!defined($keylen))
188             {
189 0           return undef;
190             }
191              
192 0           my $len = readnum($client);
193 0 0         if(!defined($len))
194             {
195 0 0         !$debug || print STDERR "read: $ERROR{$client}\n";
196 0           return undef;
197             }
198 0 0         !$debug || print "len = $len\n";
199              
200 0           my $value = '';
201 0           my $gotten_so_far=0;
202 0 0         if($len > 0)
203             {
204 0           while ($gotten_so_far<$len)
205             {
206             # warn "before reading to get ",$len-$gotten_so_far," bytes";
207 0           my ($value_piece,$got) = readbytes($client,
208             $len-$gotten_so_far);
209 0 0         if(!defined($value_piece))
210             {
211 0 0         !$debug || print STDERR "read: $ERROR{$client}\n";
212 0           return undef;
213             }
214 0 0         !$debug || print "value = $value_piece\n";
215            
216             # warn "after reading $got bytes. Value:$value_piece";
217            
218 0           $gotten_so_far+=$got;
219 0           $value.=$value_piece;
220             }
221              
222 0           my ($dummy,$got)=readbytes($client, 1);
223 0 0         if(!defined($dummy))
224             {
225 0 0         !$debug || print STDERR "read: $ERROR{$client}\n";
226 0           return undef;
227             }
228             }
229            
230 0           $msg->{$key} = $value;
231             }
232              
233 0 0 0       if(($mtype eq 'arb') && (!$read_arb))
    0          
234             {
235 0           my ($keylen, $key) = read_field_header($client);
236              
237 0 0         if(!defined($keylen))
238             {
239 0           return undef;
240             }
241              
242 0 0         !$debug || print STDERR "Alvis::Tana::read() set autoread_arb to -$key-\n";
243 0           $$autoread_arb = $key;
244             }
245             elsif(defined($autoread_arb))
246             {
247 0           $$autoread_arb = undef;
248             }
249              
250 0           return $msg;
251             }
252              
253             sub read_arb($$$)
254             {
255 0     0 0   my ($client, $len, $eof) = @_;
256              
257 0           my $str = '';
258              
259 0           $$eof = 0;
260              
261 0           while($len > 0)
262             {
263 0           my $char;
264 0           my $got = CORE::sysread($client, $char, 1);
265              
266 0 0         if(1 != $got)
267             {
268 0           $ERROR{$client} = "Wanted 1 bytes, got $got";
269 0 0         !$debug || print STDERR "read_arb: $ERROR{$client}\n";
270 0           return undef;
271             }
272              
273 0 0         !$debug || print STDERR "Read arb '$char'\n";
274 0 0         if($char eq "\\")
    0          
275             {
276 0           $got = CORE::sysread($client, $char, 1);
277 0 0         if(1 != $got)
278             {
279 0           $ERROR{$client} = "Wanted 1 bytes, got $got";
280 0 0         !$debug || print STDERR "read_arb: $ERROR{$client}\n";
281 0           return undef;
282             }
283              
284 0 0         !$debug || print STDERR "Read arb '$char'\n";
285 0 0         if($char eq 'n')
    0          
286             {
287 0           $str .= "\n";
288             }
289             elsif($char eq "\\")
290             {
291 0           $str .= "\\";
292             }
293             else
294             {
295 0           $ERROR{$client} = "Invalid escaped char '$char' after '\\'";
296 0 0         !$debug || print STDERR "read_arb: $ERROR{$client}\n";
297 0           return undef;
298             }
299             }
300             elsif($char eq "\n")
301             {
302 0           $$eof = 1;
303 0           last;
304             }
305             else
306             {
307 0           $str .= $char;
308             }
309              
310 0           $len--;
311             }
312              
313 0           return $str;
314             }
315              
316              
317             sub write_arb($$$)
318             {
319 0     0 0   my ($client, $str, $final) = @_;
320              
321 0           while(length($str) > 0)
322             {
323 0           $str =~ s/(.)(.*)/$2/s;
324 0 0         !$debug || print STDERR "Sending arb '$1'\n";
325 0 0         if($1 eq "\\")
    0          
326             {
327 0           my $out = "\\\\";
328 0 0         if(length($out) != CORE::syswrite($client, $out, length($out)))
329             {
330 0           $ERROR{$client} = "write to socket failed: $@";
331 0           return 0;
332             }
333             }
334             elsif($1 eq "\n")
335             {
336 0           my $out = "\\n";
337 0 0         if(length($out) != CORE::syswrite($client, $out, length($out)))
338             {
339 0           $ERROR{$client} = "write to socket failed: $@";
340 0           return 0;
341             }
342             }
343             else
344             {
345 0           my $out = $1;
346 0 0         if(length($out) != CORE::syswrite($client, $out, length($out)))
347             {
348 0           $ERROR{$client} = "write to socket failed: $@";
349 0           return 0;
350             }
351             }
352             }
353              
354 0 0         if($final)
355             {
356 0           my $out = "\n";
357 0 0         if(length($out) != CORE::syswrite($client, $out, length($out)))
358             {
359 0           $ERROR{$client} = "write to socket failed: $@";
360 0           return 0;
361             }
362             }
363              
364 0           return 1;
365             }
366              
367             sub write($$$)
368             {
369 0     0 0   my ($client, $msg, $type) = @_;
370              
371 0           my @keys = keys(%$msg);
372 0           my $fieldc = scalar(@keys);
373              
374             # warn "Writing ", Dumper($msg);
375             # warn "Client: ", Dumper($client);
376             # warn "Type: ", Dumper($type);
377              
378 0 0         if(defined($type))
379             {
380 0           my $afc = $fieldc + 1;
381              
382 0           my $out = "arb $afc\n";
383 0 0         if(length($out) != CORE::syswrite($client, $out))
384             {
385 0           $ERROR{$client} = "write to socket failed: $@\n";
386 0           return 0;
387             }
388             }
389             else
390             {
391 0           my $out = "fix $fieldc\n";
392             # warn "Alvis::Tana syswriting",Dumper($out);
393 0           my $len = CORE::syswrite($client, $out);
394 0 0         if(length($out) != $len)
395             {
396             # warn "Alvis::Tana length mismatch lenth8out):",length($out),
397             # " len:",$len;
398 0           $ERROR{$client} = "write to socket failed: $@";
399 0           return 0;
400             }
401             }
402 0           my $key;
403 0           foreach $key (@keys)
404             {
405 0           my $len = length($msg->{$key});
406 0           my $val = $msg->{$key};
407 0           my $keylen = length($key);
408 0           my $out = "$keylen $key: $len $val\n";
409              
410             # warn "Alvis::Tana::write() key:\"$key\" value:\"$val\" length of value:$len";
411              
412 0 0         if($len == 0)
413             {
414 0           $out = "$keylen $key: $len\n";
415             }
416 0 0         if(length($out) != CORE::syswrite($client, $out))
417             {
418 0           $ERROR{$client} = "write to socket failed: $@";
419 0           return 0;
420             }
421             }
422 0 0         if(defined($type))
423             {
424 0           my $klen = length($type);
425 0           my $out = "$klen $type: ";
426 0 0         if(length($out) != CORE::syswrite($client, $out))
427             {
428 0           print "TANA4\n";
429 0           $ERROR{$client} = "write to socket failed: $@";
430 0           return 0;
431             }
432             }
433              
434             # warn "Alvis::Tana at end of of write()";
435              
436 0           return 1;
437             }
438              
439             1;
440              
441             __END__