Test script to transfer data over GTP without a tracker
[VCS-Git-Torrent.git] / lib / VCS / Git / Torrent / PWP / Message / Reels.pm
blob94a95ea125e12ed5ff2ee357ee4cbb39b84eb1a2
2 package VCS::Git::Torrent::PWP::Message::Reels;
4 =head1 NAME
6 VCS::Git::Torrent::PWP::Message::Reels
8 =head1 SYNOPSIS
10 use VCS::Git::Torrent::PWP qw(:all);
11 my $reels_message = pwp_message( GTP_PWP_REELS, @reels );
13 =head2 DESCRIPTION
15 Implements the Reels message from the RFC.
16 L<http://gittorrent.utsl.gen.nz/rfc.html#pwp-reels>
18 =cut
20 use Moose;
21 with "VCS::Git::Torrent::PWP::Message";
22 use Carp;
23 use VCS::Git::Torrent::PWP qw(:pwp_constants unpack_hex pack_hex pack_num unpack_num);
25 has 'reels' =>
26 isa => "ArrayRef[VCS::Git::Torrent::CommitReel]",
27 is => "rw",
28 # trigger => sub {
29 # my $self = shift;
30 # $self->payload($self->pack_payload);
31 # };
34 sub pack_payload {
35 my $self = shift;
36 my $payload = "";
38 for my $reel ( @{ $self->reels } ) {
39 my (@sha1_pair) = @{ $reel->reel_id };
40 $payload .= join("", (map { pack_hex($_) } @sha1_pair));
41 $payload .= pack_num($reel->size);
44 $payload;
47 sub unpack_payload {
48 my $self = shift;
49 my $payload = shift;
51 (length($payload) % 44) == 0
52 or croak "bad Reels payload length ".length($payload);
54 my %args;
55 my @reels;
56 while ( length($payload) ) {
57 my (@sha1_pair) = map { unpack_hex($_) }
58 (substr($payload, 0, 20),
59 substr($payload, 20, 20));
61 $args{'start'} = $sha1_pair[0];
62 $args{'end'} = $sha1_pair[1];
64 my $size = unpack_num(substr($payload, 40, 4));
65 substr($payload, 0, 44)="";
67 $args{'size'} = $size;
68 push @reels,
69 VCS::Git::Torrent::CommitReel->new(%args);
72 $self->reels(\@reels);
75 sub args {
76 my $class = shift;
77 my $reels;
79 if ( ref($_[0]) eq 'ARRAY' ) {
80 $reels = shift;
82 else {
83 $reels = [ @_ ];
86 return( reels => $reels );
89 sub action {
90 my $self = shift;
91 my $local_peer = shift;
92 my $connection = shift;
94 if ( scalar(@{ $self->reels }) ) { # we got some reels from someone
95 # check for duplicates
96 my @new_reels = map {
97 my $reel = $_;
99 my $num = grep {
100 $reel->reel_id->[0] eq $_->reel_id->[0] &&
101 $reel->reel_id->[1] eq $_->reel_id->[1]
102 } @{ $local_peer->torrent->reels };
104 $num ? () : ($reel)
105 } @{ $self->reels };
107 push @{ $local_peer->torrent->reels }, @new_reels;
108 push @{ $connection->remote->reels }, @{ $self->reels };
110 for my $reel ( @{ $self->reels } ) {
111 $local_peer->send_message(
112 $connection->remote, GTP_PWP_BLOCKS,
113 $reel
117 else { # it was a request for our reels
118 $local_peer->send_message($connection->remote, GTP_PWP_REELS,
119 $local_peer->torrent->reels
120 ) if ( # make sure we have reels to send
121 scalar(@{ $local_peer->torrent->reels })