1package Data::AMF::Packet; 2use Any::Moose; 3 4require bytes; 5use Data::AMF::Parser; 6use Data::AMF::Formatter; 7use Data::AMF::IO; 8 9use Data::AMF::Header; 10use Data::AMF::Message; 11 12has version => ( 13 is => 'rw', 14 isa => 'Int', 15 lazy => 1, 16 default => sub { 0 }, 17); 18 19has headers => ( 20 is => 'rw', 21 isa => 'ArrayRef', 22 lazy => 1, 23 default => sub { [] }, 24); 25 26has messages => ( 27 is => 'rw', 28 isa => 'ArrayRef', 29 lazy => 1, 30 default => sub { [] }, 31); 32 33no Any::Moose; 34 35sub deserialize 36{ 37 my ($class, $data) = @_; 38 39 my $io = Data::AMF::IO->new(data => $data); 40 41 my $ver = $io->read_u16; 42 my $header_count = $io->read_u16; 43 my $message_count = $io->read_u16; 44 45 my $parser = Data::AMF::Parser->new(version => 0); 46 47 my @headers; 48 for my $i (1 .. $header_count) 49 { 50 my $name = $io->read_utf8; 51 my $must = $io->read_u32; 52 my $len = $io->read_u32; 53 54 my $data = $io->read($len); 55 my ($value) = $parser->parse($data); 56 57 push @headers, Data::AMF::Header->new( 58 name => $name, 59 must_understand => $must, 60 value => $value, 61 version => $ver, 62 ); 63 } 64 65 my @messages; 66 for my $i (1 .. $message_count) 67 { 68 my $target_uri = $io->read_utf8; 69 my $response_uri = $io->read_utf8; 70 my $len = $io->read_u32; 71 72 my $data = $io->read($len); 73 my ($value) = $parser->parse($data); 74 75 push @messages, Data::AMF::Message->new( 76 target_uri => $target_uri, 77 response_uri => $response_uri, 78 value => $value, 79 version => $ver, 80 source => $data 81 ); 82 } 83 84 return Data::AMF::Packet->new( 85 version => $ver, 86 headers => \@headers, 87 messages => \@messages, 88 ); 89} 90 91sub serialize 92{ 93 my $self = shift; 94 95 my $io = Data::AMF::IO->new( data => q[] ); 96 97 $io->write_u16($self->version); 98 $io->write_u16(scalar @{ $self->headers }); 99 $io->write_u16(scalar @{ $self->messages }); 100 101 for my $header (@{ $self->headers }) 102 { 103 $io->write_utf8( $header->name ); 104 $io->write_u32( $header->must_understand ); 105 106 my $data; 107 108 if ($self->version == 3) 109 { 110 my $formatter = Data::AMF::Formatter->new(version => 3)->new; 111 $formatter->io->write_u8(0x11); 112 $formatter->write($header->value); 113 114 $data = $formatter->io->data; 115 } 116 else 117 { 118 $data = Data::AMF::Formatter->new(version => 0)->format($header->value); 119 } 120 121 $io->write_u32(bytes::length($data)); 122 $io->write($data); 123 } 124 125 for my $message (@{ $self->messages }) 126 { 127 $io->write_utf8($message->target_uri); 128 $io->write_utf8($message->response_uri); 129 130 my $data; 131 132 if ($self->version == 3) 133 { 134 my $formatter = Data::AMF::Formatter->new(version => 3)->new; 135 $formatter->io->write_u8(0x11); 136 $formatter->write($message->value); 137 138 $data = $formatter->io->data; 139 } 140 else 141 { 142 $data = Data::AMF::Formatter->new(version => 0)->format($message->value); 143 } 144 145 $io->write_u32(bytes::length($data)); 146 $io->write($data); 147 } 148 149 return $io->data; 150} 151 152__PACKAGE__->meta->make_immutable; 153 154__END__ 155 156=head1 NAME 157 158Data::AMF::Packet - serialize / deserialize AMF message packet 159 160=head1 SYNOPSIS 161 162 use Data::AMF::Packet 163 164 my $packet = Data::AMF::Packet->deserialize($data); 165 my $data = $packet->serialize; 166 167=head1 DESCRIPTION 168 169Data::AMF::Packet provides to serialize/deserialize AMF Packet. 170 171AMF Packet is an extended format of AMF, and is used for Flash's HTTP based Remote Procidure Call (known as Flash Remoting). 172 173=head1 SEE ALSO 174 175L<Data::AMF>, L<Catalyst::Controller::FlashRemoting> 176 177=head1 METHODS 178 179=head2 serialize 180 181Serialize Data::AMF::Packet object into AMF Packet data. 182 183=head2 deserialize($amf_packet) 184 185Deserialize AMF Packet, and return Data::AMF::Packet object. 186 187=head1 ACCESSORS 188 189=head2 version 190 191return AMF Packet version. 192 193=head2 headers 194 195return AMF Packet header objects. (ArrayRef of L<Data::AMF::Header>) 196 197=head2 messages 198 199return AMF Packet Message objects. (ArrayRef of L<Data::AMF::Message>) 200 201=head1 AUTHOR 202 203Daisuke Murase <typester@cpan.org> 204 205=head1 COPYRIGHT 206 207This program is free software; you can redistribute 208it and/or modify it under the same terms as Perl itself. 209 210The full text of the license can be found in the 211LICENSE file included with this module. 212 213=cut 214 215