File Coverage

blib/lib/Net/BitTorrent/PeerPacket.pm
Criterion Covered Total %
statement 90 90 100.0
branch 13 18 72.2
condition n/a
subroutine 22 22 100.0
pod 2 2 100.0
total 127 132 96.2


line stmt bran cond sub pod time code
1             #!/usr/local/bin/perl
2              
3             package Net::BitTorrent::PeerPacket;
4              
5 1     1   26225 use strict;
  1         3  
  1         42  
6 1     1   6 use warnings;
  1         2  
  1         32  
7 1     1   6 use Carp qw(croak);
  1         6  
  1         87  
8 1     1   5 use base 'Exporter';
  1         2  
  1         207  
9              
10             our $VERSION = '1.2';
11              
12             # Build list of packet names, order is significant, as the index of the type
13             # represents it's code in BitTorrent
14             my ( @code_num_to_str, %code_str_to_num );
15              
16             BEGIN {
17 1     1   4 @code_num_to_str = qw(
18             BT_CHOKE
19             BT_UNCHOKE
20             BT_INTERESTED
21             BT_UNINTERESTED
22             BT_HAVE
23             BT_BITFIELD
24             BT_REQUEST
25             BT_PIECE
26             BT_CANCEL
27             );
28              
29             # The array @code_num_to_str serves as a packet code to packet name
30             # map. Flip that into a hash that serves as a name to code map
31 9         26 %code_str_to_num =
32 1         4 map { $code_num_to_str[$_] => $_ } 0 .. $#code_num_to_str;
33              
34 1         20 $code_str_to_num{'BT_HANDSHAKE'} = -1;
35             }
36              
37             # Turn the hash of name-id pairs into a bunch of constants based on the names
38 1     1   5 use constant \%code_str_to_num;
  1         2  
  1         2062  
39              
40             # Allow for the export of our build and parse subroutines and bt codes
41             our @EXPORT_OK =
42             ( 'bt_build_packet', 'bt_parse_packet', keys %code_str_to_num );
43              
44             # create an :all tag for subroutines and constants and a :constants tag for
45             # just the constants
46             our %EXPORT_TAGS = (
47             'all' => [@EXPORT_OK],
48             'constants' => [@code_num_to_str],
49             );
50              
51             # Map build and parse subroutines
52             my $bt_base_code = -1;
53             my (%bt_dispatch) = map( { $bt_base_code++ => $_ }{
54             build => \&_build_handshake_packet,
55             parse => sub { croak('unimplemented') },
56             },
57             {
58             build => sub { return _build_packet(BT_CHOKE) },
59             parse => { bt_code => BT_CHOKE },
60             },
61             {
62             build => sub { return _build_packet(BT_UNCHOKE) },
63             parse => { bt_code => BT_UNCHOKE },
64             },
65             {
66             build => sub { return _build_packet(BT_INTERESTED) },
67             parse => { bt_code => BT_INTERESTED },
68             },
69             {
70             build => sub { return _build_packet(BT_UNINTERESTED) },
71             parse => { bt_code => BT_UNINTERESTED },
72             },
73             {
74             build => \&_build_have_packet,
75             parse => \&_parse_have_packet,
76             },
77             {
78             build => \&_build_bitfield_packet,
79             parse => \&_parse_bitfield_packet,
80             },
81             {
82             build => \&_build_request_packet,
83             parse => \&_parse_request_packet,
84             },
85             {
86             build => \&_build_piece_packet,
87             parse => \&_parse_piece_packet,
88             },
89             {
90             build => \&_build_cancel_packet,
91             parse => \&_parse_cancel_packet,
92             },
93             );
94              
95             ##########################################################################
96             # P U B L I C S U B R O U T I N E S
97             ##########################################################################
98              
99             sub bt_build_packet {
100              
101             # hashify arguments
102 10 50   10 1 7729 @_ % 2 == 0
103             or croak("Even number of elements expected, but not received");
104              
105 10         37 my %args = @_;
106              
107 10         28 _hash_defines( \%args, 'bt_code' );
108              
109 10         20 my $bt_code = $args{bt_code};
110              
111             # look-up build subroutine
112 10 50       31 defined $bt_dispatch{$bt_code}
113             or croak("Invalid BT code ($bt_code) found");
114              
115 10         21 my $sub_ref = $bt_dispatch{$bt_code}{build};
116              
117             # execute the subroutine
118 10         32 return $sub_ref->( \%args );
119             }
120              
121             sub bt_parse_packet {
122 10     10 1 5064 my ($packet_ref) = @_;
123              
124             # handle the handshake if it is passed in
125 10 100       17 if ( unpack( 'c', ${$packet_ref} ) eq 0x13 ) {
  10         49  
126 1         4 return _parse_handshake_packet($packet_ref);
127             }
128              
129 9         16 my ($bt_code) = unpack( 'x4C', ${$packet_ref} );
  9         27  
130              
131 9 50       31 defined $bt_dispatch{$bt_code}
132             or croak("Invalid BT code ($bt_code) found");
133              
134 9         16 my $parse_ref = $bt_dispatch{$bt_code}{parse};
135              
136             # for easy packets, we just get the hash ref back
137 9 100       33 return $parse_ref if ( ref $parse_ref eq 'HASH' );
138              
139             # execute the subroutine
140 5         8 return $parse_ref->( \substr( ${$packet_ref}, 5 ) );
  5         29  
141             }
142              
143             1;
144              
145             ##########################################################################
146             # P R I V A T E S U B R O U T I N E S
147             ##########################################################################
148              
149             #
150             # _build_handshake_packet INFO_HASH PEER_ID
151             # Return a handshake packet
152             #
153             sub _build_handshake_packet {
154 1     1   3 my ($args) = @_;
155              
156 1         2 _hash_defines( $args, 'info_hash', 'peer_id' );
157              
158 1         8 my $packet = pack( 'c/a* a8 a20 a20',
159             'BitTorrent protocol',
160             '', $args->{info_hash}, $args->{peer_id} );
161              
162 1         4 return $packet;
163             }
164              
165             #
166             # _build_have_packet PIECE_INDEX
167             # Return a have packet
168             #
169             sub _build_have_packet {
170 1     1   2 my ($args) = @_;
171              
172 1         2 _hash_defines( $args, 'piece_index' );
173              
174 1         17 my $packet_body = pack( 'N', $args->{piece_index} );
175              
176 1         3 return _build_packet( BT_HAVE, $packet_body );
177             }
178              
179             #
180             # _build_bitfield_packet BITFIELD
181             # Return a bitfield packet
182             #
183             sub _build_bitfield_packet {
184 1     1   4 my ($args) = @_;
185              
186 1         6 _hash_defines( $args, 'bitfield_ref' );
187              
188 1         6 return _build_packet( BT_BITFIELD, '', $args->{bitfield_ref} );
189             }
190              
191             #
192             # _build_request_packet PIECE_INDEX BIT_OFFSET BIT_LENGTH
193             # Return a request packet
194             #
195             sub _build_request_packet {
196 1     1   3 my ($args) = @_;
197              
198 1         5 _hash_defines( $args, 'piece_index', 'block_offset', 'block_size' );
199              
200 1         10 my $packet_body = pack( 'NNN',
201             $args->{piece_index}, $args->{block_offset}, $args->{block_size} );
202              
203 1         6 return _build_packet( BT_REQUEST, $packet_body );
204             }
205              
206             #
207             # _build_piece_packet PIECE_INDEX BIT_OFFSET DATA
208             # Return a piece packet
209             #
210             sub _build_piece_packet {
211 1     1   4 my ($args) = @_;
212              
213 1         11 _hash_defines( $args, 'piece_index', 'block_offset', 'data_ref' );
214              
215 1         8 my $packet_body = pack( 'NN', $args->{piece_index}, $args->{block_offset} );
216              
217 1         7 return _build_packet( BT_PIECE, $packet_body, $args->{data_ref} );
218             }
219              
220             #
221             # _build_cancel_packet PIECE_INDEX BIT_OFFSET BIT_LENGTH
222             # Return a cancel packet
223             #
224             sub _build_cancel_packet {
225 1     1   4 my ($args) = @_;
226              
227 1         4 _hash_defines( $args, 'piece_index', 'block_offset', 'block_size' );
228              
229 1         8 my $packet_body = pack( 'NNN',
230             $args->{piece_index}, $args->{block_offset}, $args->{block_size} );
231 1         5 return _build_packet( BT_CANCEL, $packet_body );
232             }
233              
234             #
235             # _build_packet BT_CODE PACKET_BODY DATA_REF
236             # _build_packet ends up getting called by all of the _build_*_packet
237             # subroutines. This routine accepts the BitTorrent packet code (as
238             # an integer), an optional packet body and optional data reference.
239             #
240             sub _build_packet {
241 9     9   21 my ( $_code, $packet_body, $data_ref ) = @_;
242              
243 9 100       23 $packet_body = '' unless defined $packet_body;
244 9 100       24 $data_ref = \'' unless defined $data_ref;
245              
246 9         25 my $packet = pack( 'NCa*a*',
247 9         47 length($packet_body) + length( ${$data_ref} ) + 1,
248 9         25 $_code, $packet_body, ${$data_ref} );
249              
250 9         40 return $packet;
251             }
252              
253             #
254             # _parse_handshake_packet ENTIRE_PACKET
255             # Return a parsed handshake packet
256             #
257             sub _parse_handshake_packet {
258 1     1   3 my ($packet_ref) = @_;
259              
260 1         5 my ( $protocol_name, $reserved_space, $info_hash, $peer_id ) =
261 1         1 unpack( 'c/a* a8 a20 a20', ${$packet_ref} );
262              
263             return {
264 1         6 bt_code => BT_HANDSHAKE,
265             protocol => $protocol_name,
266             info_hash => $info_hash,
267             peer_id => $peer_id,
268             };
269             }
270              
271             #
272             # _parse_have_packet PACKET_PAYLOAD
273             # Return a parsed have packet
274             #
275             sub _parse_have_packet {
276 1     1   2 my ($packet_ref) = @_;
277              
278 1         4 my ($piece_index) = unpack( 'N', $$packet_ref );
279              
280             return {
281 1         2694 bt_code => BT_HAVE,
282             piece_index => $piece_index
283             };
284             }
285              
286             #
287             # _parse_bitfield_packet PACKET_PAYLOAD
288             # Return a parsed bitfield packet
289             #
290             sub _parse_bitfield_packet {
291 1     1   4 my ($packet_ref) = @_;
292              
293             return {
294 1         9 bt_code => BT_BITFIELD,
295             bitfield_ref => $packet_ref,
296             };
297             }
298              
299             #
300             # _parse_request_packet PACKET_PAYLOAD
301             # Return a parsed request packet
302             #
303             sub _parse_request_packet {
304 1     1   3 my ($packet_ref) = @_;
305              
306 1         9 my ( $piece_index, $block_offset, $block_size ) =
307             unpack( 'NNN', $$packet_ref );
308              
309             return {
310 1         12 bt_code => BT_REQUEST,
311             piece_index => $piece_index,
312             block_offset => $block_offset,
313             block_size => $block_size,
314             };
315             }
316              
317             #
318             # _parse_piece_packet PACKET_PAYLOAD
319             # Return a parsed piece packet
320             #
321             sub _parse_piece_packet {
322 1     1   3 my ($packet_ref) = @_;
323              
324 1         6 my ( $piece_index, $block_offset ) = unpack( 'NN', $$packet_ref );
325              
326             return {
327 1         16 bt_code => BT_PIECE,
328             piece_index => $piece_index,
329             block_offset => $block_offset,
330             data_ref => \substr( $$packet_ref, 8 ),
331             };
332             }
333              
334             #
335             # _parse_cancel_packet PACKET_PAYLOAD
336             # Return a parsed cancel packet
337             #
338             sub _parse_cancel_packet {
339 1     1   2 my ($packet_ref) = @_;
340              
341 1         5 my ( $piece_index, $block_offset, $block_size ) =
342             unpack( 'NNN', $$packet_ref );
343              
344             return {
345 1         6 bt_code => BT_CANCEL,
346             piece_index => $piece_index,
347             block_offset => $block_offset,
348             block_size => $block_size,
349             };
350             }
351              
352             #
353             # _hash_defines HASH_REFERENCE LIST_OF_KEYS
354             # Makes sure that the given hash defines values for all keys in the list.
355             #
356             sub _hash_defines {
357 16     16   43 my ( $hash, @keys ) = @_;
358              
359 16 50       59 ref $hash eq 'HASH'
360             or croak("Hash reference not found");
361              
362 16         34 for my $key (@keys) {
363 23 50       92 defined $hash->{$key}
364             or croak("$key not specified");
365             }
366              
367 16         41 return 1;
368             }
369              
370             1;
371              
372             =pod
373              
374             =head1 NAME
375              
376             Net::BitTorrent::PeerPacket - Parse/Build Peer Packets from BitTorrent
377              
378             =head1 SYNOPSIS
379              
380             # import everything
381             use Net::BitTorrent::PeerPacket qw(:all);
382              
383             # or be more selective
384             use Net::BitTorrent::PeerPacket qw(bt_build_packet :constants);
385              
386             # Encode a packet
387             my $binary_packet = bt_build_packet($key1, $value1, $key2, $value2);
388              
389             # Decode a packet
390             my $parsed_packet = bt_parse_packet($binary_data);
391              
392             =head1 DESCRIPTION
393              
394             C handles parsing and building binary data
395             shared between BitTorrent peers. The module optionally exports a single
396             subroutine for building packets and another for parsing packets, as well
397             as, a constant for each packet type defined by BitTorrent.
398              
399             =head1 CONSTANTS
400              
401             There are ten primary types of packets that are shared between peers on a
402             BitTorrent network. The following constants are how the type of packet
403             being build/parsed are represented within this module.
404              
405             =over 4
406              
407             =item BT_HANDSHAKE
408              
409             Used to start communication between peers.
410              
411             =item BT_CHOKE
412              
413             Tell a peer that it is choked.
414              
415             =item BT_UNCHOKE
416              
417             Tell a peer that it is unchoked.
418              
419             =item BT_INTERESTED
420              
421             Used to tell a peer that it has a piece that you need.
422              
423             =item BT_UNINTERESTED
424              
425             Used to tell a peer that it has no pieces that you need.
426              
427             =item BT_HAVE
428              
429             Used to tell a peer that you now have a specific piece.
430              
431             =item BT_BITFIELD
432              
433             Used right after a handshake, this tells a peer all of the pieces
434             that you have and don't have in one message.
435              
436             =item BT_REQUEST
437              
438             Used to request a block of data from a piece that a peer has.
439              
440             =item BT_PIECE
441              
442             Used to return a block of data that was requested.
443              
444             =item BT_CANCEL
445              
446             Used to tell a peer that you no longer need the piece that you
447             were downloading from them.
448              
449             =back
450              
451             =head1 SUBROUTINES
452              
453             =head2 bt_build_packet
454              
455             This subroutine is responsible for building all types of BitTorrent packets.
456             The arguments are passed into the subroutine as a list of key-value pairs.
457             The resultant packet is sent back as a scalar.
458              
459             Depending on the requested packet type, the required arguments vary. One
460             argument that is common to all calls is the C. The C maps
461             to a C constant exported by this module and determines the type of
462             packet that will be built.
463              
464             What follows is a list of the different BT codes and the details of calling
465             this subroutine with those codes.
466              
467             =head3 BT_HANDSHAKE
468              
469             Passing the C code causes a handshake packet to be generated.
470             This type of packet is sent as soon as peers are connected and requires two
471             additional keys:
472              
473             =over 4
474              
475             =item * info_hash
476              
477             The hash found in the C<.torrent> file that represents the download.
478              
479             =item * peer_id
480              
481             The peer ID for the local peer. This should be the same as what is reported
482             to the tracker for the swarm.
483              
484             =back
485              
486             =head3 BT_CHOKE
487              
488             Passing the C code causes a choke packet to be generated. This type of
489             packet requires no additional data and therefore no additional arguments.
490              
491             =head3 BT_UNCHOKE
492              
493             Passing the C code causes an unchoke packet to be generated. This
494             type of packet requires no additional data and therefore no additional
495             arguments.
496              
497             =head3 BT_INTERESTED
498              
499             Passing the C code causes an interested packet to be generated.
500             This type of packet requires no additional data and therefore no additional
501             arguments.
502              
503             =head3 BT_UNINTERESTED
504              
505             Passing the C code causes an uninterested packet to be generated.
506             This type of packet requires no additional data and therefore no additional
507             arguments.
508              
509             =head3 BT_HAVE
510              
511             Passing the C code causes a have packet to be generated. This type of
512             packet requires a piece index in addition to the BT code.
513              
514             =over 4
515              
516             =item piece_index
517              
518             The piece index is the zero-based numeric index of a piece within a torrent.
519              
520             =back
521              
522             =head3 BT_BITFIELD
523              
524             Passing the C code causes a bit field packet to be generated. This
525             type of packet requires the bit field be specified in addition to the BT code.
526              
527             =over 4
528              
529             =item bitfield_ref
530              
531             The bit field is passed in as a reference to a scalar. The scalar contains
532             binary data representing the pieces that are present and missing.
533              
534             =back
535              
536             =head3 BT_REQUEST
537              
538             Passing the C code causes a request packet to be generated. This
539             type of packet requires the piece index along with block offset and size in
540             addition to the BT code.
541              
542             =over 4
543              
544             =item piece_index
545              
546             The piece index is the zero-based numeric index of a piece within a torrent.
547              
548             =item block_offset
549              
550             The block offset is the zero-based byte offset of the requested data within the
551             specified piece.
552              
553             =item block_size
554              
555             The block size is the size of the data requested. Be sure not to set this
556             value too large, as some clients will end your connection if your request is
557             too big.
558              
559             =back
560              
561             =head3 BT_PIECE
562              
563             Passing the C code causes a piece packet to be generated. This
564             type of packet requires the piece index along with block offset and the data
565             to be transferred in addition to the BT code.
566              
567             =over 4
568              
569             =item piece_index
570              
571             The piece index is the zero-based numeric index of a piece within a torrent.
572              
573             =item block_offset
574              
575             The block offset is the zero-based byte offset of the requested data within the
576             specified piece.
577              
578             =item data_ref
579              
580             The data reference is a reference to a scalar containing the data at the
581             specified block offset within the specified piece.
582              
583             =back
584              
585             =head3 BT_CANCEL
586              
587             Passing the C code causes a cancel packet to be generated. This
588             type of packet requires the piece index along with block offset and size in
589             addition to the BT code.
590              
591             =over 4
592              
593             =item piece_index
594              
595             The piece index is the zero-based numeric index of a piece within a torrent.
596              
597             =item block_offset
598              
599             The block offset is the zero-based byte offset of the requested data within the
600             specified piece.
601              
602             =item block_size
603              
604             The block size is the size of the data requested. Be sure not to set this
605             value too large, as some clients will end your connection if your request is
606             too big.
607              
608             =back
609              
610             =head2 bt_parse_packet
611              
612             This subroutine is responsible for parsing all types of BitTorrent packets.
613             It accepts a single argument, which is a reference to a scalar that contains
614             the raw packet data. It returns a hash reference containing the parsed data.
615              
616             Depending on the packet type, the keys in the returned hash vary. One
617             key that is common to all packets is the bt_code. The bt_code maps to a
618             BT_ constant exported by this module and reveals the type of packet that
619             was parsed.
620              
621             What follows is a list of the different BT codes that might be returned and the
622             additional keys that will be packaged with each code.
623              
624             =head3 BT_CHOKE
625              
626             The resultant hash from a choke packet will only contain the C key.
627              
628             =head3 BT_UNCHOKE
629              
630             The resultant hash from an unchoke packet will only contain the C key.
631              
632             =head3 BT_INTERESTED
633              
634             The resultant hash from an interested packet will only contain the C
635             key.
636              
637             =head3 BT_UNINTERESTED
638              
639             The resultant hash from an uninterested packet will only contain the C
640             key.
641              
642             =head3 BT_HAVE
643              
644             The resultant hash from a have packet will only contain the C
645             key and the following additional keys.
646              
647             =over 4
648              
649             =item piece_index
650              
651             The piece index is the zero-based numeric index of a piece within a torrent.
652              
653             =back
654              
655             =head3 BT_BITFIELD
656              
657             The resultant hash from a bit field packet will only contain the C
658             key and the following additional keys.
659              
660             =over 4
661              
662             =item bitfield_ref
663              
664             The bit field is passed in as a reference to a scalar. The scalar contains
665             binary data representing the pieces that are present and missing.
666              
667             =back
668              
669             =head3 BT_REQUEST
670              
671             The resultant hash from a request packet will only contain the C
672             key and the following additional keys.
673              
674             =over 4
675              
676             =item piece_index
677              
678             The piece index is the zero-based numeric index of a piece within a torrent.
679              
680             =item block_offset
681              
682             The block offset is the zero-based byte offset of the requested data within the
683             specified piece.
684              
685             =item block_size
686              
687             The block size is the size of the data requested. Be sure not to set this
688             value too large, as some clients will end your connection if your request is
689             too big.
690              
691             =back
692              
693             =head3 BT_PIECE
694              
695             The resultant hash from a piece packet will only contain the C
696             key and the following additional keys.
697              
698             =over 4
699              
700             =item piece_index
701              
702             The piece index is the zero-based numeric index of a piece within a torrent.
703              
704             =item block_offset
705              
706             The block offset is the zero-based byte offset of the requested data within the
707             specified piece.
708              
709             =item data_ref
710              
711             The data reference is a reference to a scalar containing the data at the
712             specified block offset within the specified piece.
713              
714             =back
715              
716             =head3 BT_CANCEL
717              
718             The resultant hash from a cancel packet will only contain the C
719             key and the following additional keys.
720              
721             =over 4
722              
723             =item piece_index
724              
725             The piece index is the zero-based numeric index of a piece within a torrent.
726              
727             =item block_offset
728              
729             The block offset is the zero-based byte offset of the requested data within the
730             specified piece.
731              
732             =item block_size
733              
734             The block size is the size of the data requested. Be sure not to set this
735             value too large, as some clients will end your connection if your request is
736             too big.
737              
738             =back
739              
740             =head1 INSTALL
741              
742             perl Build.PL
743             ./Build
744             ./Build test
745             ./Build install
746              
747             =head1 AUTHOR
748              
749             Josh McAdams
750              
751             =cut
752              
753             __END__