File Coverage

blib/lib/P2P/pDonkey/Met.pm
Criterion Covered Total %
statement 97 190 51.0
branch 23 62 37.1
condition 5 25 20.0
subroutine 21 42 50.0
pod 30 32 93.7
total 176 351 50.1


line stmt bran cond sub pod time code
1             # P2P::pDonkey::Met.pm
2             #
3             # Copyright (c) 2003-2004 Alexey klimkin .
4             # All rights reserved.
5             # This program is free software; you can redistribute it and/or
6             # modify it under the same terms as Perl itself.
7             #
8             package P2P::pDonkey::Met;
9              
10 2     2   6954 use 5.006;
  2         7  
  2         88  
11 2     2   11 use strict;
  2         5  
  2         66  
12 2     2   11 use warnings;
  2         9  
  2         462  
13              
14             require Exporter;
15              
16             our $VERSION = '0.05';
17              
18             our @ISA = qw(Exporter);
19              
20             # Items to export into callers namespace by default. Note: do not export
21             # names by default without a very good reason. Use EXPORT_OK instead.
22             # Do not simply export all your public functions/methods/constants.
23              
24             # This allows declaration use P2P::pDonkey ':all';
25             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
26             # will save memory.
27             our %EXPORT_TAGS = ( 'all' => [ qw(
28             MT_KNOWNMET MT_PARTMET MT_SERVERMET
29            
30             unpackServerDesc packServerDesc printServerDesc makeServerDesc
31             unpackServerDescList packServerDescList printServerDescList
32             unpackServerDescListU packServerDescListU printServerDescListU
33             unpackServerMet packServerMet printServerMet
34             readServerMet writeServerMet
35              
36             unpackPartMet packPartMet printPartMet
37             readPartMet writePartMet
38              
39             unpackKnownMet packKnownMet printKnownMet
40             readKnownMet writeKnownMet
41              
42             unpackPrefMet packPrefMet printPrefMet
43             readPrefMet writePrefMet
44              
45             readFile writeFile
46             ) ],
47             'server' => [ qw(
48             unpackServerDesc packServerDesc printServerDesc makeServerDesc
49             unpackServerDescList packServerDescList printServerDescList
50             unpackServerDescListU packServerDescListU printServerDescListU
51             unpackServerMet packServerMet printServerMet
52             readServerMet writeServerMet
53             ) ],
54             'part' => [ qw(
55             unpackPartMet packPartMet printPartMet
56             readPartMet writePartMet
57             ) ],
58             'known' => [ qw(
59             unpackKnownMet packKnownMet printKnownMet
60             readKnownMet writeKnownMet
61             ) ],
62             'pref' => [ qw(
63             unpackPrefMet packPrefMet printPrefMet
64             readPrefMet writePrefMet
65             ) ] );
66              
67             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
68              
69             our @EXPORT = qw(
70            
71             );
72              
73 2     2   12 use Carp;
  2         3  
  2         146  
74 2     2   1078 use Data::Hexdumper;
  2         7539  
  2         135  
75 2     2   1026 use P2P::pDonkey::Meta ':all';
  2         5  
  2         1656  
76 2     2   14 use P2P::pDonkey::Util qw( ip2addr );
  2         4  
  2         120  
77              
78             my $debug = 0;
79              
80             # Preloaded methods go here.
81              
82 2     2   10 use constant MT_SERVERMET => 0x0e;
  2         11  
  2         130  
83 2     2   11 use constant MT_PARTMET => 0xe1;
  2         3  
  2         91  
84 2     2   10 use constant MT_KNOWNMET => 0x0e;
  2         9  
  2         5211  
85              
86              
87             sub readFile {
88 6     6 0 14 my ($fname, $tag) = @_;
89 6         9 my ($handle, $buf);
90 6         18 my $rs = $/;
91 6         16 undef $/;
92 6 50 0     369 open($handle, "<$fname")
      0        
93             or warn "Can't open '$fname': $!\n"
94             and $/ = $rs
95             and return;
96 6         23 binmode($handle);
97 6 100       20 if ($tag) {
98 5 50 33     199 if (read($handle, $buf, 1) != 1 || unpack('C',$buf) != $tag) {
99 0         0 warn "File '$fname' without tag!\n";
100 0         0 close($handle);
101 0         0 $/ = $rs;
102 0         0 return;
103             }
104 5         185 $buf .= <$handle>;
105             } else {
106 1         33 $buf = <$handle>;
107             }
108 6         82 close($handle);
109 6         18 $/ = $rs;
110 6         42 return \$buf;
111             };
112              
113             sub writeFile($$) {
114 0     0 0 0 my ($fname, $buf) = @_;
115 0         0 my $handle;
116 0 0 0     0 open($handle, ">$fname") or warn "Can't open `$fname': $!\n" and return;
117 0         0 binmode($handle);
118 0         0 print $handle $$buf;
119 0         0 close($handle);
120 0         0 return 1;
121             };
122              
123             # -----------------------------------------------------------------------------
124             # server.met
125              
126             sub unpackServerDesc {
127 69     69 1 81 my ($ip, $port, $meta);
128 69 50       148 ($ip, $port) = &unpackAddr or return;
129 69 50       156 $meta = &unpackMetaListU or return;
130             # Hash is for compatibility with Info structure
131 69         475 return {Hash => '01234567012345670123456701234567', IP => $ip, Port => $port, Meta => $meta};
132             }
133             sub packServerDesc {
134 0     0 1 0 my ($d) = @_;
135 0         0 return packAddr($d) . packMetaListU($d->{Meta});
136             }
137             sub printServerDesc {
138 0     0 1 0 my ($d) = @_;
139 0         0 printAddr($d);
140 0         0 print "\n";
141 0         0 printMetaListU($d->{Meta});
142             }
143             sub makeServerDesc {
144 0     0 1 0 my ($ip, $port, $name, $desc, $nusers, $nfiles, $preference) = @_;
145 0 0 0     0 defined($ip) && defined($port) or confess "Specify ip and port of server!";
146 0 0       0 $name or $name = '';
147 0 0       0 $desc or $desc = '';
148 0 0       0 $preference or $preference = 0;
149 0         0 my %meta;
150 0         0 tie %meta, "Tie::IxHash";
151 0         0 $meta{Name} = makeMeta(TT_NAME, $name);
152 0         0 $meta{Description} = makeMeta(TT_DESCRIPTION, $desc);
153 0         0 $meta{IP} = makeMeta(TT_IP, $ip);
154 0         0 $meta{Port} = makeMeta(TT_PORT, $port);
155 0 0       0 $meta{users} = makeMeta(TT_UNDEFINED, $nusers, "users", VT_INTEGER) if defined $nusers;
156 0 0       0 $meta{files} = makeMeta(TT_UNDEFINED, $nfiles, "files", VT_INTEGER) if defined $nfiles;
157 0         0 $meta{Preference} = makeMeta(TT_PREFERENCE, $preference);
158 0         0 return {Hash => '01234567012345670123456701234567', IP => $ip, Port => $port, Meta => \%meta};
159             }
160              
161             sub unpackServerDescList {
162 0     0 1 0 my ($n, @l, $d);
163 0 0       0 defined($n = &unpackD) or return;
164 0         0 @l = ();
165 0         0 while ($n--) {
166 0 0       0 $d = &unpackServerDesc or return;
167 0         0 push @l, $d;
168             }
169 0         0 return \@l;
170             }
171             sub packServerDescList {
172 0     0 1 0 my ($l) = @_;
173 0         0 my ($res);
174 0         0 $res = packD(scalar @$l);
175 0         0 foreach my $d (@$l) {
176 0         0 $res .= packServerDesc($d);
177             }
178 0         0 return $res;
179             }
180             sub printServerDescList {
181 0     0 1 0 foreach my $d (@{$_[0]}) {
  0         0  
182 0         0 printServerDesc($d);
183             }
184             }
185              
186             sub unpackServerDescListU {
187 1     1 1 2 my ($n, %l, $d);
188 1         6 tie %l, "Tie::IxHash";
189 1 50       23 defined($n = &unpackD) or return;
190 1         13 %l = ();
191 1         24 while ($n--) {
192 69 50       1061 $d = &unpackServerDesc or return;
193 69         219 $l{idAddr($d)} = $d;
194             }
195 1         13 return \%l;
196             }
197             sub packServerDescListU {
198 0     0 1 0 my ($res, $d);
199 0         0 my $n = 0;
200 0         0 $res = '';
201 0         0 while ((undef, $d) = each %{$_[0]}) {
  0         0  
202 0         0 $res .= packServerDesc($d);
203 0         0 $n++;
204             }
205 0         0 return packD($n) . $res;
206             }
207             sub printServerDescListU {
208 0     0 1 0 my $d;
209 0         0 while ((undef, $d) = each %{$_[0]}) {
  0         0  
210 0         0 printServerDesc($d);
211             }
212             }
213              
214             sub unpackServerMet {
215 1 50   1 1 4 &unpackB == MT_SERVERMET or return;
216 1         4 return &unpackServerDescListU;
217             }
218             sub packServerMet {
219 0     0 1 0 return packB(MT_SERVERMET) . &packServerDescListU;
220             }
221             sub printServerMet {
222 0     0 1 0 &printServerDescListU;
223             }
224              
225             # parse server.met file && create hash
226             sub readServerMet {
227 1     1 1 89 my ($fname) = @_;
228 1         2 my ($off, $buf, $res);
229 1 50       18 $buf = readFile($fname, MT_SERVERMET) or return;
230 1         2 $off = 0;
231 1         6 $res = unpackServerMet($$buf, $off);
232 1 50 33     8 if ($res && $off != length $$buf) {
233 0         0 warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off);
234             }
235 1         6 return $res;
236             }
237              
238             sub writeServerMet {
239 0     0 1 0 my ($fname, $servers) = @_;
240 0         0 my $buf = packServerMet($servers);
241 0         0 return writeFile($fname, \$buf);
242             }
243              
244             # -----------------------------------------------------------------------------
245             # .part.met
246              
247             sub unpackPartMet {
248 1     1 1 6 my $v = &unpackB;
249 1 50       4 $v == MT_PARTMET or return;
250 1         6 return &unpackFileInfo;
251             }
252             sub packPartMet {
253 0     0 1 0 return packB(MT_PARTMET) . &packFileInfo;
254             }
255             sub printPartMet {
256 0     0 1 0 &printInfo;
257             }
258              
259             sub readPartMet {
260 1     1 1 9 my ($fname) = @_;
261 1         3 my ($off, $buf, $res);
262 1 50       6 $buf = readFile($fname, MT_PARTMET) or return;
263 1         3 $off = 0;
264 1         4 $res = unpackPartMet($$buf, $off);
265 1         4 $res->{Path} = $fname;
266 1 50 33     8 if ($res && $off != length $$buf) {
267 0         0 warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off);
268             }
269 1         4 return $res;
270             }
271              
272             sub writePartMet {
273 0     0 1 0 my ($fname, $p) = @_;
274 0         0 my $buf = packPartMet($p);
275 0         0 return writeFile($fname, \$buf);
276             }
277              
278              
279             # -----------------------------------------------------------------------------
280             # known.met
281             sub unpackKnownMet {
282 1 50   1 1 6 &unpackB == MT_KNOWNMET or return;
283 1         4 return &unpackFileInfoList;
284             }
285             sub packKnownMet {
286 0     0 1 0 return packB(MT_KNOWNMET) . &packFileInfoList;
287             }
288             sub printKnownMet {
289 0     0 1 0 &printInfoList;
290             }
291             sub readKnownMet {
292 1     1 1 662 my ($fname) = @_;
293 1         2 my ($off, $buf, $res);
294 1 50       55 $buf = readFile($fname, MT_KNOWNMET) or return;
295 1         3 $off = 0;
296 1         5 $res = unpackKnownMet($$buf, $off);
297 1 50 33     8 if ($res && $off != length $$buf) {
298 0         0 warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off);
299             }
300 1         6 return $res;
301             }
302             sub writeKnownMet {
303 0     0 1 0 my ($fname, $p) = @_;
304 0         0 my $buf = packKnownMet($p);
305 0         0 return writeFile($fname, \$buf);
306             }
307              
308             # -----------------------------------------------------------------------------
309             # pref.met
310              
311             sub unpackPrefMet {
312 1     1 1 2 my ($ip, $port, $hash, $meta, $pref, $name, $m);
313 1 50       4 ($ip, $port) = &unpackAddr or return;
314 1 50       5 $hash = &unpackHash or return;
315 1 50       3 $meta = &unpackMetaListU or return;
316 1 50       5 $pref = &unpackMetaListU or return;
317 1         7 return {IP => $ip, Port => $port, Hash => $hash, Meta => $meta, Pref => $pref};
318             }
319             sub packPrefMet {
320 0     0 1 0 my ($p) = @_;
321 0         0 return packAddr($p) . packHash($p->{Hash})
322             . packMetaListU($p->{Meta}) . packMetaListU($p->{Pref});
323             }
324             sub printPrefMet {
325 0     0 1 0 my ($d) = @_;
326 0         0 print "Address: ";
327 0         0 printAddr($d);
328 0         0 print "\n";
329 0         0 print "Hash: $d->{Hash}\n";
330 0         0 print "Meta:\n";
331 0         0 printMetaListU($d->{Meta});
332 0         0 print "Preferencies:\n";
333 0         0 printMetaListU($d->{Pref});
334             }
335              
336             sub readPrefMet {
337 1     1 1 468 my ($fname) = @_;
338 1         2 my ($off, $buf, $res);
339 1 50       4 $buf = readFile($fname) or return;
340 1         2 $off = 0;
341 1         5 $res = unpackPrefMet($$buf, $off);
342 1 50 33     10 if ($res && $off != length $$buf) {
343 0         0 warn "Unhandled bytes at the end:\n", hexdump(data=>$$buf, start_position=>$off);
344             }
345 1         4 return $res;
346             }
347             sub writePrefMet {
348 0     0 1   my ($fname, $p) = @_;
349 0           my $buf = packPrefMet($p);
350 0           return writeFile($fname, \$buf);
351             }
352              
353             1;
354             __END__