"Fossies" - the Fresh Open Source Software Archive 
Member "gnash-0.8.10/cygnal/libamf/amf_msg.cpp" (19 Jan 2012, 11016 Bytes) of package /linux/www/old/gnash-0.8.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 // amf.cpp: AMF (Action Message Format) rpc marshalling, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20
21 #include "log.h"
22 #include "GnashException.h"
23 #include "buffer.h"
24 #include "amf.h"
25 #include "amf_msg.h"
26 #include "element.h"
27 #include "network.h"
28 #include "GnashSystemNetHeaders.h"
29
30 #include <boost/shared_ptr.hpp>
31 #include <string>
32 #include <boost/cstdint.hpp> // For C99 int types
33
34 using gnash::GnashException;
35 using gnash::log_error;
36 using std::cout;
37 using std::endl;
38
39
40 namespace cygnal
41 {
42
43 boost::shared_ptr<cygnal::Buffer>
44 AMF_msg::encodeContextHeader(boost::uint16_t version, boost::uint16_t headers,
45 boost::uint16_t messages)
46 {
47 // GNASH_REPORT_FUNCTION;
48 size_t size = sizeof(AMF_msg::context_header_t);
49 boost::shared_ptr<cygnal::Buffer> buf (new cygnal::Buffer(size));
50
51 // use a short as a temporary, as it turns out htons() returns a 32bit int
52 // instead when compiling with -O2. This forces appending bytes to get the
53 // right size.
54 boost::uint16_t swapped = htons(version);
55 *buf = swapped;
56 swapped = htons(headers);
57 *buf += swapped;
58 swapped = htons(messages);
59 *buf += swapped;
60
61 return buf;
62 }
63
64 boost::shared_ptr<cygnal::Buffer>
65 AMF_msg::encodeContextHeader(AMF_msg::context_header_t *head)
66 {
67 // GNASH_REPORT_FUNCTION;
68 return encodeContextHeader(head->version, head->headers, head->messages);
69 }
70
71 // example message header::
72 // 00 06 67 65 74 77 61 79 <- getway, message #1
73 // 00 04 2f 32 32 39 <- /229, operation name
74 // 00 00 00 0e <- byte length of message
75 boost::shared_ptr<cygnal::Buffer>
76 AMF_msg::encodeMsgHeader(AMF_msg::message_header_t *head)
77 {
78 // GNASH_REPORT_FUNCTION;
79 // The size of the buffer are the two strings, their lenght fields, and the integer.
80 // size_t size = head->target.size() + head->response.size() + sizeof(boost::uint32_t)
81 // + (sizeof(boost::uint16_t) * 2);
82 boost::shared_ptr<cygnal::Buffer> buf (new cygnal::Buffer(sizeof(AMF_msg::message_header_t)));
83
84 // Encode the target URI, which usually looks something like ."getway"
85 boost::uint16_t length = head->target.size();
86 *buf = length;
87 *buf += head->target;
88
89 // Encode the response URI, which usually looks something like "/229"
90 length = head->response.size();
91 *buf += length;
92 *buf += head->target;
93
94 // Encode the size of the encoded message
95 *buf += static_cast<boost::uint32_t>(head->size);
96
97 return buf;
98 }
99
100 // These methods parse the raw data of the AMF packet
101 boost::shared_ptr<AMF_msg::context_header_t>
102 AMF_msg::parseContextHeader(cygnal::Buffer &data)
103 {
104 // GNASH_REPORT_FUNCTION;
105 return parseContextHeader(data.reference(), data.size());
106 }
107
108 boost::shared_ptr<AMF_msg::context_header_t>
109 AMF_msg::parseContextHeader(boost::uint8_t *data, size_t /* size */)
110 {
111 // GNASH_REPORT_FUNCTION;
112 boost::shared_ptr<AMF_msg::context_header_t> msg (new AMF_msg::context_header_t);
113
114 boost::uint16_t tmpnum = *reinterpret_cast<boost::uint16_t *>(data);
115 msg->version = tmpnum;
116 tmpnum = *reinterpret_cast<boost::uint16_t *>(data + sizeof(boost::uint16_t));
117 msg->headers = ntohs(tmpnum);
118 tmpnum = *reinterpret_cast<boost::uint16_t *>(data + sizeof(boost::uint32_t));
119 msg->messages = ntohs(tmpnum);
120
121 return msg;
122 }
123
124 boost::shared_ptr<AMF_msg::message_header_t>
125 AMF_msg::parseMessageHeader(cygnal::Buffer &data)
126 {
127 // GNASH_REPORT_FUNCTION;
128 return parseMessageHeader(data.reference(), data.size());
129 }
130
131 boost::shared_ptr<AMF_msg::message_header_t>
132 AMF_msg::parseMessageHeader(boost::uint8_t *data, size_t size)
133 {
134 // GNASH_REPORT_FUNCTION;
135 AMF amf;
136 boost::uint8_t *tmpptr = data;
137 boost::shared_ptr<AMF_msg::message_header_t> msg (new AMF_msg::message_header_t);
138
139 // The target is a standard length->bytes field
140 boost::uint16_t length = ntohs((*(boost::uint16_t *)tmpptr) & 0xffff);
141 if (length == 0) {
142 boost::format msg("Length of string shouldn't be zero! amf_msg.cpp::%1%(): %2%");
143 msg % __FUNCTION__ % __LINE__;
144 throw GnashException(msg.str());
145 }
146 tmpptr += sizeof(boost::uint16_t);
147 std::string str1(reinterpret_cast<const char *>(tmpptr), length);
148 msg->target = str1;
149 if ((tmpptr - data) > static_cast<int>(size)) {
150 boost::format msg("Trying to read past the end of data! Wants %1% bytes, given %2% bytes");
151 msg % length % size;
152 throw GnashException(msg.str());
153 } else {
154 tmpptr += length;
155 }
156
157 // The response is a standard length->bytes field
158 length = ntohs((*(boost::uint16_t *)tmpptr) & 0xffff);
159 if (length == 0) {
160 boost::format msg("Length of string shouldn't be zero! amf_msg.cpp::%1%(): %2%");
161 msg % __FUNCTION__ % __LINE__;
162 throw GnashException(msg.str());
163 }
164 tmpptr += sizeof(boost::uint16_t);
165 std::string str2(reinterpret_cast<const char *>(tmpptr), length);
166 msg->response = str2;
167 tmpptr += length;
168 if ((tmpptr - data) > static_cast<int>(size)) {
169 boost::format msg("Trying to read past the end of data! Wants %1% bytes, given %2% bytes");
170 msg % length % size;
171 throw GnashException(msg.str());
172 }
173
174 // The length is a 4 word integer
175 msg->size = ntohl((*(boost::uint32_t *)tmpptr));
176
177 if (msg->target.empty()) {
178 log_error(_("AMF Message \'target\' field missing!"));
179 }
180 if (msg->response.empty()) {
181 log_error(_("AMF Message \'reply\' field missing!"));
182 }
183 if (msg->size == 0) {
184 log_error(_("AMF Message \'size\' field missing!"));
185 } else {
186 msg->size = size;
187 }
188
189 // AMF_msg::dump(*msg);
190 return msg;
191 }
192
193 boost::shared_ptr<AMF_msg::context_header_t>
194 AMF_msg::parseAMFPacket(cygnal::Buffer &data)
195 {
196 // GNASH_REPORT_FUNCTION;
197 return parseAMFPacket(data.reference(), data.size());
198 }
199
200 boost::shared_ptr<AMF_msg::context_header_t>
201 AMF_msg::parseAMFPacket(boost::uint8_t *data, size_t size)
202 {
203 GNASH_REPORT_FUNCTION;
204 // _messages.push_back();
205 boost::uint8_t *ptr = data + sizeof(AMF_msg::context_header_t);
206 boost::shared_ptr<context_header_t> header = AMF_msg::parseContextHeader(data, size);
207
208 // log_debug("%s: %s", __PRETTY_FUNCTION__, hexify(data, size, true));
209
210 AMF amf;
211 /// Read all the messages from the AMF packet
212 try {
213 for (int i=0; i<header->messages; i++) {
214 boost::shared_ptr<AMF_msg::amf_message_t> msgpkt(new AMF_msg::amf_message_t);
215 boost::shared_ptr<AMF_msg::message_header_t> msghead = AMF_msg::parseMessageHeader(ptr, size);
216 if (msghead) {
217 ptr += msghead->target.size() + msghead->response.size()
218 + (sizeof(boost::uint16_t) * 2)
219 + (sizeof(boost::uint32_t));
220 boost::shared_ptr<cygnal::Element> el = amf.extractAMF(ptr, ptr+size);
221 msgpkt->header.target = msghead->target;
222 msgpkt->header.response = msghead->response;
223 msgpkt->header.size = msghead->size;
224 msgpkt->data = el;
225 ptr += amf.totalsize();
226
227 _messages.push_back(msgpkt);
228 }
229 }
230 } catch(std::exception& e) {
231 log_error(_("Error parsing the AMF packet: \n\t%s"), e.what());
232 }
233
234 return header;
235 }
236
237 boost::shared_ptr<cygnal::Buffer>
238 AMF_msg::encodeAMFPacket(const std::string & /* target */,
239 const std::string & /*response */, size_t /* size */)
240 {
241 // GNASH_REPORT_FUNCTION;
242
243 return encodeAMFPacket();
244 }
245
246 boost::shared_ptr<cygnal::Buffer>
247 AMF_msg::encodeAMFPacket()
248 {
249 // GNASH_REPORT_FUNCTION;
250 boost::shared_ptr<cygnal::Buffer> buf(new cygnal::Buffer);
251
252 // Encode the packet header
253 boost::shared_ptr<cygnal::Buffer> buf1 = encodeContextHeader(0, 0, _messages.size());
254 *buf = buf1;
255
256 // Now encode all the messages
257
258 std::vector<boost::shared_ptr<AMF_msg::amf_message_t> >::iterator it;
259 for (it = _messages.begin(); it != _messages.end(); it++) {
260 boost::shared_ptr<AMF_msg::amf_message_t> msg = (*(it));
261
262 boost::shared_ptr<cygnal::Buffer> buf2 = encodeMsgHeader(msg->header.target,
263 msg->header.response,
264 msg->header.size);
265
266 // AMF_msg::dump(msg->header);
267 // msg->data->dump();
268 boost::shared_ptr<cygnal::Buffer> buf3 = msg->data->encode();
269 *buf += buf2;
270 *buf += buf3;
271 }
272
273 return buf;
274 }
275
276 boost::shared_ptr<cygnal::Buffer>
277 AMF_msg::encodeMsgHeader(const std::string &target,
278 const std::string &response, size_t size)
279 {
280 // GNASH_REPORT_FUNCTION;
281 size_t total = target.size() + sizeof(boost::uint16_t);
282 total += response.size() + sizeof(boost::uint16_t);
283 total += sizeof(boost::uint32_t);
284
285 boost::shared_ptr<cygnal::Buffer> buf (new cygnal::Buffer(total));
286 boost::uint16_t length = target.size();
287 swapBytes(&length, sizeof(boost::uint16_t));
288 *buf += length;
289 *buf += target;
290
291 length = response.size();
292 swapBytes(&length, sizeof(boost::uint16_t));
293 *buf += length;
294 *buf += response;
295
296 boost::uint32_t swapped = htonl(size);
297 *buf += swapped;
298
299 return buf;
300 }
301
302 void
303 AMF_msg::dump(AMF_msg::message_header_t &data)
304 {
305 // GNASH_REPORT_FUNCTION;
306 cout << "Target is: " << data.target << endl;
307 cout << "Response is: " << data.response << endl;
308 cout << "Data size is: " << data.size << endl;
309 }
310
311 void
312 AMF_msg::dump(AMF_msg::context_header_t &data)
313 {
314 // GNASH_REPORT_FUNCTION;
315 cout << "AMF Version: " << data.version << endl;
316 cout << "Number of headers: " << data.headers << endl;
317 cout << "Number of messages: " << data.messages << endl;
318 }
319
320 void
321 AMF_msg::dump()
322 {
323 // GNASH_REPORT_FUNCTION;
324 cout << "AMF Packet has " << _messages.size() << " messages." << endl;
325 std::vector<boost::shared_ptr<AMF_msg::amf_message_t> >::iterator it;
326 for (it = _messages.begin(); it != _messages.end(); it++) {
327 boost::shared_ptr<AMF_msg::amf_message_t> msg = (*(it));
328 AMF_msg::dump(msg->header);
329 msg->data->dump();
330 }
331 }
332
333
334 } // end of amf namespace
335
336 // local Variables:
337 // mode: C++
338 // indent-tabs-mode: t
339 // End: