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