File Coverage

blib/lib/Net/BitTorrent/Protocol/BEP11.pm
Criterion Covered Total %
statement 17 17 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 23 23 100.0


line stmt bran cond sub pod time code
1 21     21   215027 use v5.40;
  21         88  
2 21     21   152 use feature 'class', 'try';
  21         66  
  21         3042  
3 21     21   140 no warnings 'experimental::class', 'experimental::try';
  21         34  
  21         2466  
4 21     21   12085 class Net::BitTorrent::Protocol::BEP11 v2.0.0 : isa(Net::BitTorrent::Protocol::BEP09) {
  21         72  
  21         1269  
5 21     21   141 use Net::BitTorrent::Protocol::BEP03::Bencode qw[bencode bdecode];
  21         74  
  21         1322  
6 21     21   1030 use Net::BitTorrent::Protocol::BEP23;
  21         49  
  21         22774  
7             ADJUST {
8             $self->on(
9             extended_message => sub ( $self, $name, $payload ) {
10             return unless $name eq 'ut_pex';
11             my $dict;
12             try {
13             my @res = bdecode( $payload, 1 );
14             if ( @res > 2 ) {
15             pop @res; # Discard leftover
16             $dict = {@res};
17             }
18             else {
19             $dict = $res[0];
20             }
21             }
22             catch ($e) {
23             $self->_emit( log => " [ERROR] Malformed ut_pex message: $e\n", level => 'error' );
24             return;
25             }
26             if ( ref $dict ne 'HASH' ) {
27             $self->_emit( log => " [ERROR] Malformed ut_pex message: dict is not a hash\n", level => 'error' );
28             return;
29             }
30             my $added = Net::BitTorrent::Protocol::BEP23::unpack_peers_ipv4( $dict->{added} // '' );
31             my $dropped = Net::BitTorrent::Protocol::BEP23::unpack_peers_ipv4( $dict->{dropped} // '' );
32             my $added6 = $dict->{added6} ? Net::BitTorrent::Protocol::BEP23::unpack_peers_ipv6( $dict->{added6} ) : [];
33             my $dropped6 = $dict->{dropped6} ? Net::BitTorrent::Protocol::BEP23::unpack_peers_ipv6( $dict->{dropped6} ) : [];
34              
35             # Extract flags if present
36             if ( $dict->{'added.f'} ) {
37             my @flags = unpack( 'C*', $dict->{'added.f'} );
38             for my $i ( 0 .. $#$added ) {
39             $added->[$i]{flags} = $flags[$i] if defined $flags[$i];
40             }
41             }
42             if ( $dict->{'added6.f'} ) {
43             my @flags = unpack( 'C*', $dict->{'added6.f'} );
44             for my $i ( 0 .. $#$added6 ) {
45             $added6->[$i]{flags} = $flags[$i] if defined $flags[$i];
46             }
47             }
48             $self->_emit( pex => $added, $dropped, $added6, $dropped6 );
49             }
50             );
51             }
52              
53             method send_pex ( $added = [], $dropped = [], $added6 = [], $dropped6 = [] ) {
54             return unless exists $self->remote_extensions->{ut_pex};
55             my $payload = {
56             added => Net::BitTorrent::Protocol::BEP23::pack_peers_ipv4(@$added),
57             dropped => Net::BitTorrent::Protocol::BEP23::pack_peers_ipv4(@$dropped),
58             };
59             $payload->{'added.f'} = pack( 'C*', map { $_->{flags} // 0 } @$added ) if @$added;
60             if ( @$added6 || @$dropped6 ) {
61             $payload->{added6} = Net::BitTorrent::Protocol::BEP23::pack_peers_ipv6(@$added6);
62             $payload->{dropped6} = Net::BitTorrent::Protocol::BEP23::pack_peers_ipv6(@$dropped6);
63             $payload->{'added6.f'} = pack( 'C*', map { $_->{flags} // 0 } @$added6 ) if @$added6;
64             }
65             $self->send_ext_message( 'ut_pex', bencode($payload) );
66             }
67             } 1;