AnyEvent-BitTorrent
view release on metacpan or search on metacpan
lib/AnyEvent/BitTorrent.pm view on Meta::CPAN
$total_offset = 0;
}
return length $data;
}
sub hashcheck (;@) {
my $s = shift;
my @indexes = @_ ? @_ : (0 .. $s->piece_count);
AE::log trace => sub {
require Data::Dump;
'Hashcheck of : ' . Data::Dump::dump(\@indexes);
};
$s->bitfield; # Makes sure it's built
my $total_size = $s->size;
for my $index (@indexes) {
next if $index < 0 || $index > $s->piece_count;
my $piece = $s->_read($index,
0,
$index == $s->piece_count
?
$total_size % $s->piece_length
: $s->piece_length
);
my $expected = substr($s->pieces, $index * 20, 20);
my $reality = sha1($piece);
my $ok = defined($piece)
&& ($expected eq $reality);
vec($s->{bitfield}, $index, 1) = $ok;
AE::log trace => sub {
"Validate piece #%06d %s, Expected: %s\n"
. " Reality: %s",
$index, ($ok ? 'PASS' : 'FAIL'), unpack('H*', $expected),
unpack('H*', $reality);
};
$ok ?
$s->_trigger_hash_pass($index)
: $s->_trigger_hash_fail($index);
}
}
has peers => (is => 'ro',
lazy => 1,
isa => HashRef,
clearer => '_clear_peers',
builder => '_build_peers'
);
sub _build_peers { {} }
sub _add_peer {
my ($s, $h) = @_;
$s->{peers}{+$h} = {
handle => $h,
peerid => '',
bitfield => (pack 'b*', "\0" x $s->piece_count),
remote_choked => 1,
remote_interested => 0,
remote_requests => [],
local_choked => 1,
local_interested => 0,
local_requests => [],
timeout => AE::timer(20, 0, sub { $s->_del_peer($h) }),
keepalive => AE::timer(
30, 120,
sub {
$s->_send_encrypted($h, build_keepalive());
}
),
# BEP06
local_allowed => [],
remote_allowed => [],
local_suggest => [],
remote_suggest => [],
# No encryption :(
encryption => '?'
};
}
sub _del_peer {
my ($s, $h) = @_;
$s->peers->{$h} // return;
for my $req (@{$s->peers->{$h}{local_requests}}) {
my ($i, $o, $l) = @$req;
$s->working_pieces->{$i}{$o}[3] = ();
}
delete $s->peers->{$h};
$h->destroy;
}
my $shuffle;
has trackers => (is => 'ro',
lazy => 1,
builder => '_build_trackers',
isa => ArrayRef [HashRef],
init_arg => undef
);
sub _build_trackers {
my $s = shift;
$shuffle //= sub {
my $deck = shift; # $deck is a reference to an array
return unless @$deck; # must not be empty!
my $i = @$deck;
while (--$i) {
my $j = int rand($i + 1);
@$deck[$i, $j] = @$deck[$j, $i];
}
};
my $trackers = [
map {
{urls => $_,
complete => 0,
incomplete => 0,
peers => '',
peers6 => '',
announcer => undef,
ticker => AE::timer(
1,
15 * 60,
sub {
return if $s->state eq 'stopped';
$s->announce('started');
}
),
failures => 0
( run in 0.790 second using v1.01-cache-2.11-cpan-df04353d9ac )