File Coverage

blib/lib/Net/BitTorrent/Protocol/PeerHandler.pm
Criterion Covered Total %
statement 11 11 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 15 15 100.0


line stmt bran cond sub pod time code
1 20     20   235396 use v5.40;
  20         76  
2 20     20   137 use feature 'class';
  20         34  
  20         3250  
3 20     20   131 no warnings 'experimental::class';
  20         46  
  20         2385  
4 20     20   10057 class Net::BitTorrent::Protocol::PeerHandler v2.0.1 : isa(Net::BitTorrent::Protocol::BEP06) {
  20         71  
  20         35755  
5             field $peer : reader;
6             field $features : param = {};
7              
8             method set_peer ($p) {
9             $peer = $p;
10             if ( defined $peer ) {
11             builtin::weaken($peer);
12             $self->set_parent_emitter($peer);
13             }
14             }
15             ADJUST {
16             # Default all features to 1 if not provided
17             $features->{bep05} //= 1; # DHT
18             $features->{bep06} //= 1; # Fast Extension
19             $features->{bep09} //= 1; # Metadata
20             $features->{bep10} //= 1; # Extension Protocol
21             $features->{bep11} //= 1; # PEX
22              
23             # Populate local extensions for BEP 10
24             my $ext = $self->local_extensions;
25             $ext->{ut_metadata} = 1 if $features->{bep09};
26             $ext->{ut_pex} = 2 if $features->{bep11};
27             $ext->{ut_holepunch} = 3;
28              
29             # Set bits for Extension Protocol (byte 5, 0x10), DHT (byte 7, 0x01), Fast (byte 7, 0x04)
30             $self->set_reserved_bit( 5, 0x10 ) if $features->{bep10};
31             $self->set_reserved_bit( 7, 0x01 ) if $features->{bep05};
32             $self->set_reserved_bit( 7, 0x04 ) if $features->{bep06};
33              
34             # Event Listeners
35             $self->on(
36             handshake => sub ( $self, $ih, $id ) {
37             if ( $id eq $self->peer_id ) {
38             $self->_emit( log => " [DEBUG] Closing self-connection and banning endpoint\n", level => 'debug' ) if $self->debug;
39             if ( $peer && $peer->torrent ) {
40             $peer->torrent->ban_peer( $peer->ip, $peer->port );
41             }
42             $peer->disconnected() if $peer;
43             return;
44             }
45             if ( $features->{bep10} ) {
46             my $res = $self->reserved;
47             if ( ord( substr( $res, 5, 1 ) ) & 0x10 ) {
48             $self->_emit( log => " [DEBUG] Remote supports BEP 10, sending extended handshake\n", level => 'debug' ) if $self->debug;
49             $self->send_ext_handshake();
50             }
51             }
52             $peer->_emit('handshake_complete') if $peer;
53             }
54             );
55             $self->on(
56             ext_handshake => sub ( $self, $data ) {
57             $self->_emit( log => " [DEBUG] Received extended handshake from peer\n", level => 'debug' ) if $self->debug;
58             }
59             );
60             $self->on( metadata_request => sub ( $self, $piece ) { $peer->handle_metadata_request($piece) if $peer } );
61             $self->on(
62             metadata_data => sub ( $self, $piece, $total_size, $data ) {
63             $peer->handle_metadata_data( $piece, $total_size, $data ) if $peer;
64             }
65             );
66             $self->on( metadata_reject => sub ( $self, $piece ) { $peer->handle_metadata_reject($piece) if $peer } );
67             $self->on(
68             hash_request => sub ( $self, $root, $proof_layer, $base_layer, $index, $length ) {
69             $peer->handle_hash_request( $root, $proof_layer, $base_layer, $index, $length ) if $peer;
70             }
71             );
72             $self->on(
73             hashes => sub ( $self, $root, $proof_layer, $base_layer, $index, $length, $hashes ) {
74             $peer->handle_hashes( $root, $proof_layer, $base_layer, $index, $length, $hashes ) if $peer;
75             }
76             );
77             $self->on(
78             hash_reject => sub ( $self, $root, $proof_layer, $base_layer, $index, $length ) {
79             $peer->handle_hash_reject( $root, $proof_layer, $base_layer, $index, $length ) if $peer;
80             }
81             );
82             $self->on(
83             pex => sub ( $self, $added, $dropped, $added6, $dropped6 ) { $peer->handle_pex( $added, $dropped, $added6, $dropped6 ) if $peer } );
84             $self->on( hp_rendezvous => sub ( $self, $id ) { $peer->handle_hp_rendezvous($id) if $peer && $peer->can('handle_hp_rendezvous') } );
85             $self->on( hp_connect => sub ( $self, $ip, $port ) { $peer->handle_hp_connect( $ip, $port ) if $peer && $peer->can('handle_hp_connect') } );
86             $self->on( hp_error => sub ( $self, $err ) { $peer->handle_hp_error($err) if $peer && $peer->can('handle_hp_error') } );
87             }
88              
89             method _handle_message ( $id, $payload ) {
90              
91             # Feature check for Fast Extension (BEP 06) message IDs
92             if ( !$features->{bep06} && ( $id >= 13 && $id <= 17 ) ) {
93              
94             # Skip fast extension messages if disabled
95             return;
96             }
97              
98             # Feature check for Extension Protocol (BEP 10)
99             if ( !$features->{bep10} && $id == 20 ) {
100             return;
101             }
102             if ($peer) {
103             $peer->handle_message( $id, $payload );
104             }
105             $self->SUPER::_handle_message( $id, $payload );
106             }
107             } 1;