| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#!/usr/bin/perl -w |
|
2
|
|
|
|
|
|
|
package Net::BitTorrent::Util; |
|
3
|
|
|
|
|
|
|
{ |
|
4
|
13
|
|
|
13
|
|
736619
|
use strict; |
|
|
13
|
|
|
|
|
42
|
|
|
|
13
|
|
|
|
|
750
|
|
|
5
|
13
|
|
|
13
|
|
72
|
use warnings; |
|
|
13
|
|
|
|
|
24
|
|
|
|
13
|
|
|
|
|
453
|
|
|
6
|
13
|
|
|
13
|
|
69
|
use Carp qw[carp]; |
|
|
13
|
|
|
|
|
25
|
|
|
|
13
|
|
|
|
|
770
|
|
|
7
|
13
|
|
|
13
|
|
66
|
use List::Util qw[min max shuffle sum]; |
|
|
13
|
|
|
|
|
20
|
|
|
|
13
|
|
|
|
|
1245
|
|
|
8
|
13
|
|
|
13
|
|
70
|
use version qw[qv]; |
|
|
13
|
|
|
|
|
24
|
|
|
|
13
|
|
|
|
|
133
|
|
|
9
|
|
|
|
|
|
|
our $VERSION_BASE = 50; our $UNSTABLE_RELEASE = 0; our $VERSION = sprintf(($UNSTABLE_RELEASE ? q[%.3f_%03d] : q[%.3f]), (version->new(($VERSION_BASE))->numify / 1000), $UNSTABLE_RELEASE); |
|
10
|
13
|
|
|
13
|
|
1724
|
use vars qw[@EXPORT_OK %EXPORT_TAGS]; |
|
|
13
|
|
|
|
|
26
|
|
|
|
13
|
|
|
|
|
749
|
|
|
11
|
13
|
|
|
13
|
|
69
|
use Exporter qw[]; |
|
|
13
|
|
|
|
|
46
|
|
|
|
13
|
|
|
|
|
15159
|
|
|
12
|
|
|
|
|
|
|
*import = *import = *Exporter::import; |
|
13
|
|
|
|
|
|
|
@EXPORT_OK = qw[bencode bdecode compact uncompact]; |
|
14
|
|
|
|
|
|
|
%EXPORT_TAGS = (all => [@EXPORT_OK], |
|
15
|
|
|
|
|
|
|
bencode => [qw[bencode bdecode]], |
|
16
|
|
|
|
|
|
|
compact => [qw[compact uncompact]], |
|
17
|
|
|
|
|
|
|
); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub bencode { |
|
20
|
5129
|
|
|
5129
|
1
|
120752
|
my ($ref) = @_; |
|
21
|
5129
|
100
|
|
|
|
9936
|
$ref = defined $ref ? $ref : q[]; |
|
22
|
5129
|
100
|
|
|
|
17202
|
if (not ref $ref) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
23
|
4221
|
100
|
66
|
|
|
70842
|
return ( (defined $ref and $ref =~ m[^[-+]?\d+$]) |
|
24
|
|
|
|
|
|
|
? (q[i] . $ref . q[e]) |
|
25
|
|
|
|
|
|
|
: (length($ref) . q[:] . $ref) |
|
26
|
|
|
|
|
|
|
); |
|
27
|
|
|
|
|
|
|
} |
|
28
|
|
|
|
|
|
|
elsif (ref $ref eq q[ARRAY]) { |
|
29
|
209
|
|
|
|
|
325
|
return join(q[], q[l], (map { bencode($_) } @{$ref}), q[e]); |
|
|
320
|
|
|
|
|
1008
|
|
|
|
209
|
|
|
|
|
894
|
|
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
elsif (ref $ref eq q[HASH]) { |
|
32
|
|
|
|
|
|
|
return |
|
33
|
2213
|
|
|
|
|
4865
|
join(q[], q[d], |
|
34
|
697
|
|
|
|
|
4554
|
(map { bencode($_) . bencode($ref->{$_}) } |
|
35
|
697
|
|
|
|
|
1090
|
sort keys %{$ref} |
|
36
|
|
|
|
|
|
|
), |
|
37
|
|
|
|
|
|
|
q[e] |
|
38
|
|
|
|
|
|
|
); |
|
39
|
|
|
|
|
|
|
} |
|
40
|
2
|
|
|
|
|
10
|
return q[]; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub bdecode { |
|
44
|
10675
|
|
|
10675
|
1
|
18762
|
my ($string) = @_; |
|
45
|
10675
|
100
|
|
|
|
24155
|
return if not defined $string; |
|
46
|
10674
|
|
|
|
|
16091
|
my ($return, $leftover); |
|
47
|
10674
|
100
|
100
|
|
|
83070
|
if ( $string =~ m[^([1-9]\d*):]s |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
or $string =~ m[^(0+):]s) |
|
49
|
8605
|
|
|
|
|
16868
|
{ my $size = $1; |
|
50
|
8605
|
100
|
|
|
|
28246
|
$return = q[] if $1 =~ m[^0+$]; |
|
51
|
8605
|
|
|
|
|
116893
|
$string =~ s|^$size:||s; |
|
52
|
8605
|
|
|
|
|
23535
|
while ($size) { |
|
53
|
8598
|
|
|
|
|
28749
|
my $this_time = min($size, 32766); |
|
54
|
8598
|
|
|
|
|
142853
|
$string =~ s|^(.{$this_time})||s; |
|
55
|
8598
|
100
|
|
|
|
30522
|
return if not $1; |
|
56
|
8597
|
|
|
|
|
15260
|
$return .= $1; |
|
57
|
8597
|
|
|
|
|
56186
|
$size = max(0, ($size - $this_time)); |
|
58
|
|
|
|
|
|
|
} |
|
59
|
8604
|
100
|
|
|
|
49771
|
return wantarray ? ($return, $string) : $return; # byte string |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
elsif ($string =~ s|^i([-+]?\d+)e||s) { # integer |
|
62
|
407
|
100
|
|
|
|
2421
|
return wantarray ? (int($1), $string) : int($1); |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
elsif ($string =~ s|^l(.*)||s) { # list |
|
65
|
246
|
|
|
|
|
970
|
$leftover = $1; |
|
66
|
246
|
|
100
|
|
|
4986
|
while ($leftover and $leftover !~ s|^e||s) { |
|
67
|
367
|
|
|
|
|
854
|
(my ($piece), $leftover) = bdecode($leftover); |
|
68
|
367
|
|
|
|
|
2899
|
push @$return, $piece; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
246
|
100
|
|
|
|
1730
|
return wantarray ? (\@$return, $leftover) : \@$return; |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
elsif ($string =~ s|^d(.*)||s) { # dictionary |
|
73
|
1405
|
|
|
|
|
3764
|
$leftover = $1; |
|
74
|
1405
|
|
100
|
|
|
8111
|
while ($leftover and $leftover !~ s|^e||s) { |
|
75
|
4804
|
|
|
|
|
6187
|
my ($key, $value); |
|
76
|
4804
|
|
|
|
|
11196
|
($key, $leftover) = bdecode($leftover); |
|
77
|
4804
|
50
|
|
|
|
16695
|
($value, $leftover) = bdecode($leftover) if $leftover; |
|
78
|
4804
|
50
|
|
|
|
50411
|
$return->{$key} = $value if defined $key; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
1405
|
100
|
|
|
|
7813
|
return wantarray ? (\%$return, $leftover) : \%$return; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
11
|
|
|
|
|
71
|
return; |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub compact { |
|
86
|
206
|
|
|
206
|
1
|
739
|
my (@peers) = @_; |
|
87
|
206
|
100
|
|
|
|
745
|
if (not @peers) {return} |
|
|
62
|
|
|
|
|
350
|
|
|
88
|
144
|
|
|
|
|
471
|
my $return; |
|
89
|
|
|
|
|
|
|
my %seen; |
|
90
|
144
|
|
100
|
|
|
2505
|
PEER: for my $peer (grep(defined && !$seen{$_}++, @peers)) { |
|
91
|
455
|
100
|
|
|
|
1000
|
next if not $peer; |
|
92
|
454
|
|
|
|
|
1485
|
my ($ip, $port) = split(q[:], $peer, 2); |
|
93
|
454
|
100
|
|
|
|
4036
|
if ($peer |
|
|
|
100
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
!~ m[^(?:(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.]?){4}):\d+$] |
|
95
|
|
|
|
|
|
|
) |
|
96
|
5
|
|
|
|
|
742
|
{ carp q[Invalid IP address: ] . $peer; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
elsif ($port > 2**16) { |
|
99
|
1
|
|
|
|
|
97
|
carp q[Port number beyond ephemeral range: ] . $peer; |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
else { |
|
102
|
448
|
|
|
|
|
4447
|
$return .= pack q[C4n], |
|
103
|
|
|
|
|
|
|
($ip =~ m[^([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)$]), |
|
104
|
|
|
|
|
|
|
int $port; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
} |
|
107
|
144
|
|
|
|
|
1031
|
return $return; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub uncompact { |
|
111
|
198
|
|
|
198
|
1
|
2196
|
my $string = shift; |
|
112
|
198
|
100
|
|
|
|
872
|
if (not defined $string) { return; } |
|
|
14
|
|
|
|
|
54
|
|
|
113
|
184
|
|
|
|
|
324
|
my %peers; |
|
114
|
184
|
|
|
|
|
1303
|
while ($string =~ m|(....)(..)|g) { |
|
115
|
|
|
|
|
|
|
$peers{ |
|
116
|
574
|
|
|
|
|
6020
|
sprintf(q[%d.%d.%d.%d:%d], |
|
117
|
|
|
|
|
|
|
unpack(q[C4], $1), |
|
118
|
|
|
|
|
|
|
unpack(q[n], $2)) |
|
119
|
|
|
|
|
|
|
}++; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
184
|
100
|
|
|
|
4052
|
return (shuffle(%peers ? keys %peers : ())); |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
1; |
|
124
|
|
|
|
|
|
|
} |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=pod |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=head1 NAME |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Net::BitTorrent::Util - BitTorrent Related Utility Functions |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=head1 Importing From Net::BitTorrent::Util |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
By default, nothing is exported. |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
You may import any of the following or use one or more of these tags: |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=over 2 |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=item C<:all> |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Everything is imported into your namespace. |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=item C<:bencode> |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
You get the two Bencode-related functions: L |
|
147
|
|
|
|
|
|
|
and L. For more on Bencoding, see the |
|
148
|
|
|
|
|
|
|
BitTorrent Protocol documentation. |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item C<:compact> |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Imports the tracker response-related functions |
|
153
|
|
|
|
|
|
|
L and L. |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=back |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head1 Functions |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=over 4 |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=item C |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
Expects a single value (basic scalar, array reference, or hash |
|
164
|
|
|
|
|
|
|
reference) and returns a single string. |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Bencoding is the BitTorrent protocol's basic serialization and |
|
167
|
|
|
|
|
|
|
data organization format. The specification supports integers, |
|
168
|
|
|
|
|
|
|
lists (arrays), dictionaries (hashes), and byte strings. |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=item C |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
Expects a bencoded string. The return value depends on the type of |
|
173
|
|
|
|
|
|
|
data contained in the string. |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=item C |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Compacts a list of IPv4:port strings into a single string. |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
A compact peer is 6 bytes; the first four bytes are the host (in network |
|
180
|
|
|
|
|
|
|
byte order), the last two bytes are the port (again, in network byte |
|
181
|
|
|
|
|
|
|
order). |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=item C |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Inflates a compacted string of peers and returns a list of IPv4:port |
|
186
|
|
|
|
|
|
|
strings. |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=back |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 See Also |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=over |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item The BitTorrent Protocol Specification |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
http://bittorrent.org/beps/bep_0003.html#the-connectivity-is-as-follows |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=item BEP 32: Tracker Returns Compact Peer Lists |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
http://bittorrent.org/beps/bep_0023.html |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item Other Bencode related modules: |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=over |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=item L |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=item L |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=item L |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=back |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=back |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head1 Author |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Sanko Robinson - http://sankorobinson.com/ |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
CPAN ID: SANKO |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=head1 License and Legal |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
Copyright (C) 2008-2009 by Sanko Robinson Esanko@cpan.orgE |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
|
227
|
|
|
|
|
|
|
it under the terms of The Artistic License 2.0. See the F |
|
228
|
|
|
|
|
|
|
file included with this distribution or |
|
229
|
|
|
|
|
|
|
http://www.perlfoundation.org/artistic_license_2_0. For |
|
230
|
|
|
|
|
|
|
clarification, see http://www.perlfoundation.org/artistic_2_0_notes. |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
When separated from the distribution, all POD documentation is covered |
|
233
|
|
|
|
|
|
|
by the Creative Commons Attribution-Share Alike 3.0 License. See |
|
234
|
|
|
|
|
|
|
http://creativecommons.org/licenses/by-sa/3.0/us/legalcode. For |
|
235
|
|
|
|
|
|
|
clarification, see http://creativecommons.org/licenses/by-sa/3.0/us/. |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Neither this module nor the L is affiliated with |
|
238
|
|
|
|
|
|
|
BitTorrent, Inc. |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=for svn $Id: Util.pm 07f0c35 2010-04-02 18:31:29Z sanko@cpan.org $ |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=cut |