"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: