| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
21
|
|
|
21
|
|
212841
|
use v5.40; |
|
|
21
|
|
|
|
|
79
|
|
|
2
|
21
|
|
|
21
|
|
214
|
use feature 'class'; |
|
|
21
|
|
|
|
|
44
|
|
|
|
21
|
|
|
|
|
2722
|
|
|
3
|
21
|
|
|
21
|
|
123
|
no warnings 'experimental::class'; |
|
|
21
|
|
|
|
|
59
|
|
|
|
21
|
|
|
|
|
983
|
|
|
4
|
21
|
|
|
21
|
|
506
|
use Net::BitTorrent::Emitter; |
|
|
21
|
|
|
|
|
48
|
|
|
|
21
|
|
|
|
|
2479
|
|
|
5
|
|
|
|
|
|
|
class Net::BitTorrent::Tracker::WebSeed v2.0.0 : isa(Net::BitTorrent::Emitter) { |
|
6
|
21
|
|
|
21
|
|
721
|
use HTTP::Tiny; |
|
|
21
|
|
|
|
|
41854
|
|
|
|
21
|
|
|
|
|
17875
|
|
|
7
|
|
|
|
|
|
|
field $url : param : reader; # Base URL |
|
8
|
|
|
|
|
|
|
field $disabled : reader = 0; |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
method fetch_piece ($segments) { |
|
11
|
|
|
|
|
|
|
return undef if $disabled; |
|
12
|
|
|
|
|
|
|
my $http = HTTP::Tiny->new( max_redirect => 5 ); |
|
13
|
|
|
|
|
|
|
my $full_data = ''; |
|
14
|
|
|
|
|
|
|
for my $seg (@$segments) { |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# ... URL construction ... |
|
17
|
|
|
|
|
|
|
my $target_url = $self->_build_url($seg); |
|
18
|
|
|
|
|
|
|
my $response = $http->get( $target_url, { headers => { Range => "bytes=$seg->{offset}-" . ( $seg->{offset} + $seg->{length} - 1 ) } } ); |
|
19
|
|
|
|
|
|
|
if ( $response->{success} ) { |
|
20
|
|
|
|
|
|
|
$full_data .= $response->{content}; |
|
21
|
|
|
|
|
|
|
} |
|
22
|
|
|
|
|
|
|
elsif ( $response->{status} == 410 ) { |
|
23
|
|
|
|
|
|
|
$disabled = 1; |
|
24
|
|
|
|
|
|
|
$self->_emit( log => " [WebSeed] Resource 410 Gone: $target_url. Disabling webseed.\n", level => 'warn' ); |
|
25
|
|
|
|
|
|
|
return undef; |
|
26
|
|
|
|
|
|
|
} |
|
27
|
|
|
|
|
|
|
else { |
|
28
|
|
|
|
|
|
|
$self->_emit( log => "WebSeed fetch failed: $response->{status} $response->{reason} (URL: $target_url)", level => 'error' ); |
|
29
|
|
|
|
|
|
|
return undef; |
|
30
|
|
|
|
|
|
|
} |
|
31
|
|
|
|
|
|
|
} |
|
32
|
|
|
|
|
|
|
return $full_data; |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
method _build_url ($seg) { |
|
36
|
|
|
|
|
|
|
my $target_url = $url; |
|
37
|
|
|
|
|
|
|
if ( $target_url =~ m{/$} ) { |
|
38
|
|
|
|
|
|
|
my $rel = $seg->{rel_path} // $seg->{file}->path->basename; |
|
39
|
|
|
|
|
|
|
$target_url .= $rel; |
|
40
|
|
|
|
|
|
|
} |
|
41
|
|
|
|
|
|
|
return $target_url; |
|
42
|
|
|
|
|
|
|
} |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# Backward compatibility for single-file v1 |
|
45
|
|
|
|
|
|
|
method fetch_piece_legacy ( $index, $piece_length, $total_size ) { |
|
46
|
|
|
|
|
|
|
my $start = $index * $piece_length; |
|
47
|
|
|
|
|
|
|
my $end = $start + $piece_length - 1; |
|
48
|
|
|
|
|
|
|
$end = $total_size - 1 if $end >= $total_size; |
|
49
|
|
|
|
|
|
|
return $self->fetch_piece( [ { file => undef, offset => $start, length => ( $end - $start + 1 ), rel_path => undef } ] ); |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
} 1; |