gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libamf/...


From: Rob Savoye
Subject: [Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libamf/...
Date: Sat, 03 May 2008 18:44:09 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Rob Savoye <rsavoye>    08/05/03 18:44:09

Modified files:
        libamf         : amf.cpp element.cpp sol.cpp element.h 
        testsuite/libnet.all: Makefile.am 
        .              : ChangeLog 
        libnet         : handler.cpp netstats.h network.h rtmp.cpp 
                         rtmp.h rtmp_server.cpp rtmp_server.h 
Added files:
        testsuite/libnet.all: test_rtmp.cpp 

Log message:
                * testsuite/libnet.all/test_rtmp.cpp: Unit tests for the RTMP
                encoding and decoding.
                * libamf/amf.cpp: Booleans are two bytes after all.
                * libamf/sol.cpp: Booleans are two bytes after all.
                * libamf/element.cpp: Copy the name, don't just grab the
                pointer. Terminate Objects correctly.
                * libnet/rtmp.cpp: Add methods to encode & decode the RTMP
                header, and the Ping message.
                * libnet/rtmp.h: Add methods to encode & decode the RTMP
                header, and the messages. Add Ping message types and data
                structure.
                * libnet/rtmp_server.cpp: Actually handle the message type. 
Modify
                how the initial 1536 bytes handshake works.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.cpp?cvsroot=gnash&r1=1.76&r2=1.77
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.cpp?cvsroot=gnash&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/sol.cpp?cvsroot=gnash&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.h?cvsroot=gnash&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/Makefile.am?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/test_rtmp.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6484&r2=1.6485
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/handler.cpp?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/netstats.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/network.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.cpp?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.h?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_server.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_server.h?cvsroot=gnash&r1=1.2&r2=1.3

Patches:
Index: libamf/amf.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/amf.cpp,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -b -r1.76 -r1.77
--- libamf/amf.cpp      30 Apr 2008 18:19:40 -0000      1.76
+++ libamf/amf.cpp      3 May 2008 18:44:05 -0000       1.77
@@ -178,7 +178,7 @@
 //    GNASH_REPORT_FUNCTION;
     double num;
     // Encode the data as a 64 bit, big-endian, numeric value
-    Buffer *buf = new Buffer(AMF0_NUMBER_SIZE + AMF_HEADER_SIZE);
+    Buffer *buf = new Buffer(AMF0_NUMBER_SIZE + 1); // only one additional 
byte for the type
     buf->append(Element::NUMBER_AMF0);
     num = indata;
     swapBytes(&num, AMF0_NUMBER_SIZE);
@@ -192,18 +192,18 @@
 /// @return a binary AMF packet in big endian format (header,data) which
 /// needs to be deleted[] after being used.
 ///
-/// Although a boolean is one byte in size, swf uses 16bit short integers
-/// heavily, so this value is also a short.
+/// Although a boolean is one byte in size.
 Buffer *
 AMF::encodeBoolean(bool flag)
 {
-//    GNASH_REPORT_FUNCTION;
+    GNASH_REPORT_FUNCTION;
     // Encode a boolean value. 0 for false, 1 for true
-    Buffer *buf = new Buffer(AMF_HEADER_SIZE);
+    Buffer *buf = new Buffer(2);
     buf->append(Element::BOOLEAN_AMF0);
-    boost::uint16_t x = flag;
-    swapBytes(&x, 2);
-    buf->append(x);
+// Hum, AMF3 ???
+//     boost::uint16_t x = flag;
+//     swapBytes(&x, 2);
+    buf->append(flag);
     
     return buf;
 }
@@ -503,14 +503,19 @@
 Buffer *
 AMF::encodeElement(Element *el)
 {
-//    GNASH_REPORT_FUNCTION;
+    GNASH_REPORT_FUNCTION;
     Buffer *buf = 0;
     Buffer *tmp;
     
-    size_t outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
+    size_t outsize;
+    if (el->getType() == Element::BOOLEAN_AMF0) {
+       outsize = el->getNameSize() + 2;
+    } else {
+       outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
+    }
     buf = new Buffer(outsize);
     buf->clear();              // FIXME: temporary, makes buffers cleaner in 
gdb.
-    // If the name field is set, it's a "variable", followed by the data
+    // If the name field is set, it's a "property", followed by the data
     if (el->getName()) {
        // Add the length of the string for the name of the variable
        size_t length = el->getNameSize();
@@ -556,7 +561,7 @@
       case Element::ECMA_ARRAY_AMF0:
          tmp = encodeECMAArray(el->getData(), el->getLength());
           break;
-         // The Object End gets added when creating the object, so we can jusy 
ignore it here.
+         // The Object End gets added when creating the object, so we can just 
ignore it here.
       case Element::OBJECT_END_AMF0:
          tmp = encodeObjectEnd();
           break;
@@ -590,106 +595,20 @@
     };
 
     buf->append(tmp);
-//    log_debug("Encoded buf size is %d", buf->size());
     delete tmp;
-
     return buf;
 }
 
-#if 0
-/// Encode an array of elements. 
-///
-/// @return a binary AMF packet in big endian format (header,data)
-
-/// @return a newly allocated byte array.
-/// to be deleted by caller using delete [] operator, or NULL
-///
-vector<Buffer> *
-AMF::encodeElement(vector<amf::Element *> &data)
-{
-//    GNASH_REPORT_FUNCTION;
-
-    int size = 0;
-    bool pad = false;
-
-    // Calculate how large the buffer has to be.
-    vector<amf::Element *>::iterator ait;
-    cerr << "# of Elements in file: " << data.size() << endl;
-    for (ait = data.begin(); ait != data.end(); ait++) {
-       amf::Element *el = (*(ait));
-       size += el->getLength() + AMF_HEADER_SIZE;
-//        el->dump();
-    }
-    vector<Network::byte_t> *vec = new vector<Network::byte_t>;
-    Network::byte_t* ptr = new Network::byte_t[size + 1];
-    memset(ptr, 0, size + 1);
-    
-//    Network::byte_t *x = ptr;
-    size = 0;
-    for (ait = data.begin(); ait != data.end(); ait++) {
-       amf::Element *el = (*(ait));
-//     el->dump();
-       Network::byte_t *tmp = encodeElement(el);
-       Network::byte_t *y = tmp;
-#if 0
-       Network::byte_t *hexint;
-       hexint = new Network::byte_t[(el->getLength() + 4) *3];
-       hexify((Network::byte_t *)hexint, (Network::byte_t *)tmp,
-              el->getLength() + AMF_HEADER_SIZE, true);
-       log_debug(_("The packet head is: 0x%s"), hexint);
-#endif
-       // The 'pad' in this case is a serious hack. I think it
-       // may be an artifact, but one guess is it's a 16bit word
-       // aligned memory segment due to some ancient heritage in
-       // the other player, so after a 3 byte bool, and two 9 byte
-       // numbers, another byte is needed for padding.
-       // My guess is the pattern of boolean->number->number->methodname
-       // is a function block ID. I need to dp more testing with a
-       // wider variety of sef movies that use LocalConnection to
-       // really tell.
-       if (el->getType() == Element::NUMBER) {
-           size = AMF0_NUMBER_SIZE + 1;
-           pad = true;
-       }
-       if (el->getType() == Element::STRING) {
-           if (pad) {
-               vec->push_back('\0');
-               pad = false;
-           }
-           size = el->getLength() + AMF_HEADER_SIZE;
-       }
-//     if (el->getType() == Element::FUNCTION) {
-//         // _properties
-//     }
-       if (el->getType() == Element::BOOLEAN) {
-           size = 3;
-       }
-       for (int i=0; i<size; i++) {
-           Network::byte_t c = *y;
-           y++;
-//         printf("0x%x(%c) ", c, (isalpha(c)) ? c : '.');
-           vec->push_back(c);
-       }
-//     delete[] tmp;
-    }
-    return vec;
-}
-#endif
-
 Buffer *
 AMF::encodeProperty(amf::Element *el)
 {
 //    GNASH_REPORT_FUNCTION;
+    size_t outsize;
     
-    size_t outsize = el->getNameSize() + el->getLength() + AMF_VAR_HEADER_SIZE;
+    outsize = el->getNameSize() + el->getLength() + AMF_VAR_HEADER_SIZE;
 
     Buffer *buf = new Buffer(outsize);
     _totalsize += outsize;
-//     Network::byte_t *out = new Network::byte_t[outsize + 4]; // why +4 here 
?
-//     Network::byte_t *end = out + outsize+4; // why +4 ?
-
-//    memset(out, 0, outsize + 2); // why +2 here ?
-//    Network::byte_t *tmpptr = out;
 
     // Add the length of the string for the name of the variable
     size_t length = el->getNameSize();
@@ -710,8 +629,9 @@
     // the type byte that's the value.
     switch (el->getType()) {
       case Element::BOOLEAN_AMF0:
-         enclength = el->to_bool();
-         buf->append(enclength);
+//       enclength = el->to_bool();
+//       buf->append(enclength);
+         buf->append(el->to_bool());
          break;
       case Element::NUMBER_AMF0:
          if (el->getData()) {
@@ -789,7 +709,8 @@
           ENSUREBYTES(tmpptr, tooFar, sizeof(boost::uint16_t));
 #endif
          el->makeBoolean(tmpptr);
-         tmpptr += sizeof(boost::uint16_t); // although a bool is one byte, 
it's stored as a short
+         tmpptr += sizeof(bool);
+//       tmpptr += sizeof(boost::uint16_t); // although a bool is one byte, 
it's stored as a short
          break;
       case Element::STRING_AMF0:
          // get the length of the name

Index: libamf/element.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.cpp,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- libamf/element.cpp  30 Apr 2008 03:35:30 -0000      1.23
+++ libamf/element.cpp  3 May 2008 18:44:05 -0000       1.24
@@ -402,10 +402,9 @@
     if (_type == Element::OBJECT_AMF0) {
        // FIXME: we probably want a better size, to avoid the other
        // appends from having to resize and copy the data all the time.
-       buf = new Buffer(128);
+       buf = new Buffer(300);
        buf->clear();           // FIXME: temporary, makes buffers cleaner in 
gdb.
        buf->append(Element::OBJECT_AMF0);
-//     string name = _name;
        if (_name > 0) {
 //         Buffer *top = AMF::encodeElement(this);
 //         buf->append(top);
@@ -418,7 +417,8 @@
 
        for (size_t i=0; i<_properties.size(); i++) {
            Buffer *partial = AMF::encodeElement(_properties[i]);
-//         log_debug("Encoded partial size is %d", partial->size());
+           log_debug("Encoded partial size for is %d", partial->size());
+           partial->dump();
            if (partial) {
                buf->append(partial);
                delete partial;
@@ -426,8 +426,13 @@
                break;
            }
        }
+       log_debug("FIXME: Terminating object");
+       Network::byte_t pad = 0;
+       buf->append(pad);
+       buf->append(pad);
        buf->append(TERMINATOR);
        _buffer = buf;
+
        return buf;
     } else {
        return AMF::encodeElement(this);
@@ -457,10 +462,10 @@
 Element &
 Element::operator=(Element *el)
 {
-//    GNASH_REPORT_FUNCTION;
+    GNASH_REPORT_FUNCTION;
     _type = el->getType();
     if (el->getNameSize()) {
-        _name = el->getName();
+        _name = strdup(el->getName());
     }
     _buffer = new Buffer(el->getLength());
     _buffer->copy(el->getData(), el->getLength());
@@ -565,6 +570,18 @@
 }
 
 Element &
+Element::makeNumber(const std::string &name, gnash::Network::byte_t *data)
+{
+//    GNASH_REPORT_FUNCTION;
+    if (name.size()) {
+        setName(name);
+    }
+    _type = Element::NUMBER_AMF0;
+    check_buffer(AMF0_NUMBER_SIZE);
+    _buffer->copy(data);
+}
+
+Element &
 Element::makeBoolean(bool flag)
 {
 //    GNASH_REPORT_FUNCTION;

Index: libamf/sol.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/sol.cpp,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- libamf/sol.cpp      30 Apr 2008 18:19:41 -0000      1.35
+++ libamf/sol.cpp      3 May 2008 18:44:06 -0000       1.36
@@ -251,7 +251,7 @@
         size_t outsize = 0;
         switch (el->getType()) {
          case Element::BOOLEAN_AMF0:
-             outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
+             outsize = el->getNameSize() + 3;
              memcpy(ptr, var->reference(), outsize); 
              ptr += outsize;
              break;
@@ -333,7 +333,7 @@
     // Make sure it's an SOL file
     if (stat(filespec.c_str(), &st) == 0) {
 
-try {
+       try {
         ifstream ifs(filespec.c_str(), ios::binary);
         _filesize = st.st_size;
        buf = new Network::byte_t[_filesize + sizeof(int)];
@@ -415,11 +415,10 @@
        
         ifs.close();
         return true;
-} catch (std::exception& e) {
+       } catch (std::exception& e) {
        log_error("Reading SharedObject %s: %s", filespec, e.what());
        return false;
-}
-
+       }
     }
     
 //    log_error("Couldn't open file: %s", strerror(errno));

Index: libamf/element.h
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- libamf/element.h    30 Apr 2008 03:35:31 -0000      1.20
+++ libamf/element.h    3 May 2008 18:44:06 -0000       1.21
@@ -109,6 +109,7 @@
     Element &makeNumber(double num); 
     Element &makeNumber(gnash::Network::byte_t *data); 
     Element &makeNumber(const std::string &name, double num);
+    Element &makeNumber(const std::string &name, gnash::Network::byte_t 
*data); 
     
     Element &makeBoolean(gnash::Network::byte_t *data); 
     Element &makeBoolean(bool data); 

Index: testsuite/libnet.all/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libnet.all/Makefile.am,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- testsuite/libnet.all/Makefile.am    6 Apr 2008 18:11:33 -0000       1.5
+++ testsuite/libnet.all/Makefile.am    3 May 2008 18:44:06 -0000       1.6
@@ -48,12 +48,17 @@
 check_PROGRAMS = \
        test_cque \
        test_handler \
-       test_http
+       test_http \
+       test_rtmp 
 
 test_http_SOURCES = test_http.cpp
 test_http_LDADD = $(AM_LDFLAGS) 
 test_http_DEPENDENCIES = site-update
 
+test_rtmp_SOURCES = test_rtmp.cpp
+test_rtmp_LDADD = $(AM_LDFLAGS) 
+test_rtmp_DEPENDENCIES = site-update
+
 test_cque_SOURCES = test_cque.cpp
 test_cque_LDADD = $(AM_LDFLAGS) 
 test_cque_DEPENDENCIES = site-update
@@ -62,10 +67,6 @@
 test_handler_LDADD = $(AM_LDFLAGS) 
 test_handler_DEPENDENCIES = site-update
 
-#test_buffer_SOURCES = test_buffer.cpp
-#test_buffer_LDADD = $(AM_LDFLAGS) 
-#test_buffer_DEPENDENCIES = site-update
-
 # Rebuild with GCC 4.x Mudflap support
 mudflap:
        @echo "Rebuilding with GCC Mudflap support"

Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6484
retrieving revision 1.6485
diff -u -b -r1.6484 -r1.6485
--- ChangeLog   3 May 2008 15:06:27 -0000       1.6484
+++ ChangeLog   3 May 2008 18:44:07 -0000       1.6485
@@ -1,3 +1,19 @@
+2008-05-03  Rob Savoye  <address@hidden>
+
+       * testsuite/libnet.all/test_rtmp.cpp: Unit tests for the RTMP
+       encoding and decoding.
+       * libamf/amf.cpp: Booleans are two bytes after all.
+       * libamf/sol.cpp: Booleans are two bytes after all.
+       * libamf/element.cpp: Copy the name, don't just grab the
+       pointer. Terminate Objects correctly.
+       * libnet/rtmp.cpp: Add methods to encode & decode the RTMP
+       header, and the Ping message.
+       * libnet/rtmp.h: Add methods to encode & decode the RTMP
+       header, and the messages. Add Ping message types and data
+       structure.
+       * libnet/rtmp_server.cpp: Actually handle the message type. Modify
+       how the initial 1536 bytes handshake works.
+
 2008-05-03 Sandro Santilli <address@hidden>
 
        * server/as_value.cpp (to_number): more blocks to protect

Index: libnet/handler.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/handler.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- libnet/handler.cpp  1 Apr 2008 22:20:37 -0000       1.5
+++ libnet/handler.cpp  3 May 2008 18:44:08 -0000       1.6
@@ -215,11 +215,13 @@
        size_t ret = hand->readNet(args->netfd, buf->reference(), buf->size(), 
1);
        // the read timed out as there was no data, but the socket is still 
open.
        if (ret == 0) {
+           log_debug("no data yet for fd #%d, continuing...", args->netfd);
            continue;
        }
        // ret is "no position" when the socket is closed from the other end of 
the connection,
        // so we're done.
-       if (ret == string::npos) {
+       if ((ret == string::npos) || (ret == -1)) {
+           log_debug("socket for fd #%d was closed...", args->netfd);
            break;
        }
        // We got data. Resize the buffer if necessary.

Index: libnet/netstats.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/netstats.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libnet/netstats.h   28 Mar 2008 21:30:26 -0000      1.2
+++ libnet/netstats.h   3 May 2008 18:44:08 -0000       1.3
@@ -84,6 +84,30 @@
         AUDIO,
         VIDEO
     } filetypes_e;
+    // This is what the ActionScript 'Client' class returns:
+    typedef struct {
+        int bytes_in;          // Total number of bytes received. 
+        int bytes_out;         // Total number of bytes sent.
+        int msg_in;            // Total number of RTMP messages received.
+        int msg_out;           // Total number of RTMP messages sent.
+        int msg_dropped;       // Total number of dropped RTMP messages.
+        int ping_rtt;          // Length of time the client takes to respond 
to a ping message.
+        int audio_queue_msgs;  // Current number of audio messages in the 
queue waiting to be delivered to the client.
+        int video_queue_msgs;  // Current number of video messages in the 
queue waiting to be delivered to the client.
+        int so_queue_msgs;     // Current number of shared object messages in 
the queue waiting to be delivered to the client.
+        int data_queue_msgs;   // Current number of data messages in the queue 
waiting to be delivered to the client.
+        int dropped_audio_msgs;        // Number of audio messages that were 
dropped.
+        int dropped_video_msgs;        // Number of video messages that were 
dropped.
+        int audio_queue_bytes; // Total size of all audio messages (in bytes) 
in the queue waiting to be delivered to the client.
+        int video_queue_bytes; // Total size of all video messages (in bytes) 
in the queue waiting to be delivered to the client.
+        int so_queue_bytes;    // Total size of all shared object messages (in 
bytes) in the queue waiting to be delivered to the client.
+        int data_queue_bytes;  // Total size of all data messages (in bytes) 
in the queue waiting to be delivered to the client.
+        int dropped_audio_bytes;// Total size of all audio messages (in bytes) 
that were dropped.
+        int dropped_video_bytes;// Total size of all video messages (in bytes) 
that were dropped.
+        int bw_out;            // Current upstream (client to server) 
bandwidth for this client.
+        int bw_in;             // Current downstream (server to client) 
bandwidth for this client.
+        int client_id;         // A unique ID issued by the server for this 
client.
+    } netstats_t;
     // start the clock counting down
     boost::posix_time::ptime startClock();
     // stop the clock from counting down

Index: libnet/network.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/network.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libnet/network.h    1 Apr 2008 22:20:38 -0000       1.2
+++ libnet/network.h    3 May 2008 18:44:08 -0000       1.3
@@ -60,7 +60,7 @@
 #endif
 
 // Adjust for the constant size
-const size_t NETBUFSIZE = 2048;        // 1500 appears to be the default size 
as used by FMS
+const size_t NETBUFSIZE = 1357*2;      // 1500 appears to be the default size 
as used by FMS
 
 class Network {
 public:

Index: libnet/rtmp.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- libnet/rtmp.cpp     30 Apr 2008 18:19:41 -0000      1.9
+++ libnet/rtmp.cpp     3 May 2008 18:44:08 -0000       1.10
@@ -240,54 +240,148 @@
 }
 #endif
 
+RTMP::rtmp_head_t *
+RTMP::decodeHeader(Network::byte_t *in)
+{
+    GNASH_REPORT_FUNCTION;
+    
+    Network::byte_t *tmpptr = in;
+    
+    _header.channel = *tmpptr & RTMP_INDEX_MASK;
+    log_debug (_("The AMF channel index is %d"), _header.channel);
+    
+    _header.head_size = headerSize(*tmpptr++);
+    printf (_("The header size is %d"), _header.head_size);
+
+    if (_header.head_size >= 4) {
+        _mystery_word = *tmpptr++;
+        _mystery_word = (_mystery_word << 12) + *tmpptr++;
+        _mystery_word = (_mystery_word << 8) + *tmpptr++;
+        log_debug(_("The mystery word is: %d"), _mystery_word);
+    }
+
+    if (_header.head_size >= 8) {
+        _header.bodysize = *tmpptr++;
+        _header.bodysize = (_header.bodysize << 12) + *tmpptr++;
+        _header.bodysize = (_header.bodysize << 8) + *tmpptr++;
+        _header.bodysize = _header.bodysize & 0xffffff;
+        log_debug(_("The body size is: %d"), _header.bodysize);
+    }
+
+    if (_header.head_size >= 8) {
+        _header.type = *(content_types_e *)tmpptr;
+        tmpptr++;
+        log_debug(_("The type is: %s"), content_str[_header.type]);
+    }
+
+//     switch(_header.type) {
+//       case CHUNK_SIZE:
+//       case BYTES_READ:
+//       case PING:
+//       case SERVER:
+//       case CLIENT:
+//       case VIDEO_DATA:
+//       case NOTIFY:
+//       case SHARED_OBJ:
+//       case INVOKE:
+//           _packet_size = RTMP_VIDEO_PACKET_SIZE;
+//           break;
+//       case AUDIO_DATA:
+//           _packet_size = RTMP_AUDIO_PACKET_SIZE;
+//           break;
+//       default:
+//           log_error (_("ERROR: Unidentified AMF header data type 0x%x"), 
_type);
+//           break;
+//     };
+    
+    if (_header.head_size == 12) {
+        _header.src_dest = *(reinterpret_cast<rtmp_source_e *>(tmpptr));
+        tmpptr += sizeof(unsigned int);
+        log_debug(_("The source/destination is: %x"), _header.src_dest);
+    }
+
+    return &_header;
+}
+
 /// \brief \ Each RTMP header consists of the following:
 ///
 /// * Index & header size - The header size and amf channel index.
 /// * Total size - The total size of the message
 /// * Type - The type of the message
 /// * Routing - The source/destination of the message
-Network::byte_t *
-RTMP::encodeRTMPHeader(int amf_index, rtmp_headersize_e head_size,
+//
+// There are 3 size of RTMP headers, 1, 4, 8, and 12.
+amf::Buffer *
+RTMP::encodeHeader(int amf_index, rtmp_headersize_e head_size,
                            size_t total_size, content_types_e type,
                            rtmp_source_e routing)
 {
-//    GNASH_REPORT_FUNCTION;
-    Network::byte_t *out = new Network::byte_t[total_size + 12 + 4];
-    memset(out, 0, total_size + 12 + 4);
-    char *tmpptr = reinterpret_cast<char *>(out);
-    // Make the index & header size byte
-    *tmpptr = head_size & RTMP_HEADSIZE_MASK;    
-    *tmpptr += amf_index  & RTMP_INDEX_MASK;
-    tmpptr++;
+    GNASH_REPORT_FUNCTION;
+
+    amf::Buffer *buf;
+    switch(head_size) {
+      case HEADER_1:
+         buf = new Buffer(1);
+         break;
+      case HEADER_4:
+         buf = new Buffer(4);
+         break;
+      case HEADER_8:
+         buf = new Buffer(8);
+         break;
+      case HEADER_12:
+         buf = new Buffer(12);
+         break;
+    }
+       
+// FIXME: this is only to make this more readeable with GDB, and is a 
performance hit.
+//    buf->clear();
+    Network::byte_t *ptr = buf->reference();
+    
+    // Make the channel index & header size byte
+    *ptr = head_size & RTMP_HEADSIZE_MASK;  
+    *ptr += amf_index  & RTMP_INDEX_MASK;
+    ptr++;
 
     // Add the unknown bytes. These seem to be used by video and
     // audio, and only when the header size is 4 or more.
-    if (head_size <= HEADER_4) {
-        memset(tmpptr, 0, 3);
-        tmpptr += 3;
+    if ((head_size == HEADER_4) || (head_size == HEADER_8) || (head_size == 
HEADER_12)) {
+       memset(ptr, 0, 3);
+       ptr += 3;
     }
 
     // Add the size of the message if the header size is 8 or more.
-    if (head_size <= HEADER_8) {
+    // and add the type of the object if the header size is 8 or more.
+    if ((head_size == HEADER_8) || (head_size == HEADER_12)) {
         int length = total_size;
-        swapBytes(&length, 4);
-        memcpy(tmpptr, ((char *)&length +1), 3);
-        tmpptr += 3;
-    }
-    
-    // Add the type of the objectif the header size is 8 or more.
-    if (head_size <= HEADER_8) {
-        *tmpptr = type;
-        tmpptr++;
+       Network::byte_t *lenptr = reinterpret_cast<Network::byte_t *>(&length);
+//#ifndef      BOOST_BIG_ENDIAN
+//     swapBytes(&length, 4);
+       *ptr++ = *(lenptr + 2);
+       *ptr++ = *(lenptr + 1);
+       *ptr++ = *lenptr;       
+//     *(lenptr + 3) = *(lenptr);
+//     memcpy(ptr, lenptr, 3);
+// #else
+// #ifdef BOOST_BIG_ENDIAN
+//     memcpy(ptr, &length, 3);
+// #else
+// #error "No Endianess specified!"
+// #endif
+//#endif
+//      swapBytes(&length, 4);
+//        ptr += 3;
+        *ptr = type;
+        ptr++;
     }
 
-    // Add the routing of the message if the header size is 12 or more.
+    // Add the routing of the message if the header size is 12, the maximum.
     if (head_size == HEADER_12) {
-        memcpy(tmpptr, &routing, 4);
-        tmpptr += 4;
+        memcpy(ptr, &routing, 4);
+        ptr += 4;
     }
 
-    return out;
+    return buf;
 }
 
 bool
@@ -295,7 +389,7 @@
 {
     GNASH_REPORT_FUNCTION;
 
-    int packetsize = 0;
+//    int packetsize = 0;
     unsigned int amf_index, headersize;
     Network::byte_t *ptr = buf->reference();
     Network::byte_t *tooFar = ptr+buf->size();
@@ -308,7 +402,7 @@
     log_debug (_("The AMF index is: 0x%x"), amf_index);
 
 //     if (headersize > 1) {
-//     packetsize = parseHeader(ptr);
+//     packetsize = decodeHeader(ptr);
 //         if (packetsize) {
 //             log_debug (_("Read first RTMP packet header of size %d"), 
packetsize);
 //         } else {
@@ -324,7 +418,8 @@
     log_debug("END is %x", (void *)end);
     *end = '*';
 #endif
-    ptr = parseHeader(ptr);
+    
+//    ptr = decodeHeader(ptr);
 //     ptr += headersize;
     
     amf::Element *el = amf.extractAMF(ptr, tooFar);
@@ -339,8 +434,8 @@
        el->dump();
     }
     ptr += 1;
-    size_t actual_size = static_cast<size_t>(_total_size - AMF_HEADER_SIZE);
-    log_debug("Total size in header is %d, buffer size is: %d", _total_size, 
buf->size());
+    size_t actual_size = static_cast<size_t>(_header.bodysize - 
AMF_HEADER_SIZE);
+    log_debug("Total size in header is %d, buffer size is: %d", 
_header.bodysize, buf->size());
 //    buf->dump();
     if (buf->size() < actual_size) {
        log_debug("FIXME: MERGING");
@@ -383,67 +478,196 @@
     }
 }
 
-Network::byte_t *
-RTMP::parseHeader(Network::byte_t *in)
+// A Ping packet has two parameters that ae always specified, and 2 that are 
optional.
+// The first two bytes are the ping type, as in rtmp_ping_e, the second is the 
ping
+// target, which is always zero as far as we can tell.
+//
+// More notes from: http://jira.red5.org/confluence/display/docs/Ping
+// type 0: Clear the stream. No third and fourth parameters. The second 
parameter could be 0.
+// After the connection is established, a Ping 0,0 will be sent from server to 
client. The
+// message will also be sent to client on the start of Play and in response of 
a Seek or
+// Pause/Resume request. This Ping tells client to re-calibrate the clock with 
the timestamp
+// of the next packet server sends.
+// type 1: Tell the stream to clear the playing buffer.
+// type 3: Buffer time of the client. The third parameter is the buffer time 
in millisecond.
+// type 4: Reset a stream. Used together with type 0 in the case of VOD. Often 
sent before type 0.
+// type 6: Ping the client from server. The second parameter is the current 
time.
+// type 7: Pong reply from client. The second parameter is the time the server 
sent with his
+//         ping request.
+amf::Buffer *
+RTMP::encodeChunkSize()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeChunkSize()
 {
-//    GNASH_REPORT_FUNCTION;
+    GNASH_REPORT_FUNCTION;
+}
 
-    Network::byte_t *tmpptr = in;
+amf::Buffer *
+RTMP::encodeBytesRead()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeBytesRead()
+{
+    GNASH_REPORT_FUNCTION;
+}
     
-    _amf_index = *tmpptr & RTMP_INDEX_MASK;
-    log_debug (_("The AMF channel index is %d"), _amf_index);
+// A RTMP Ping packet looks like this: "03 00 00 00 00 00 00 0B B8", which is 
the
+// Ping type byte, followed by two shorts that are the parameters. Only the 
first
+// two paramters are required.
+amf::Buffer *
+RTMP::encodePing(rtmp_ping_e type, boost::uint16_t milliseconds)
+{
+    GNASH_REPORT_FUNCTION;
+    Buffer *buf = new Buffer(sizeof(boost::uint16_t) * 4);
+    Network::byte_t *ptr = buf->reference();
+    buf->clear();              // default everything to zeros, real data gets 
optionally added.
+    boost::uint16_t typefield = *reinterpret_cast<boost::uint16_t *>(&type);
+    ptr += sizeof(boost::uint16_t); // go past the first short
+
+    boost::uint16_t swapped = 0;
+    buf->copy(typefield);
+    switch (type) {
+        // These two don't appear to have any paramaters
+      case PING_CLEAR:
+      case PING_PLAY:
+         break;
+         // the third parameter is the buffer time in milliseconds
+      case PING_TIME:
+      {
+         ptr += sizeof(boost::uint16_t); // go past the second short
+         swapped = htons(milliseconds);
+         buf->append(swapped);
+         break;
+      }
+      // reset doesn't have any parameters
+      case PING_RESET:
+         break;
+         // For Ping and Pong, the second parameter is always the milliseconds
+      case PING_CLIENT:
+      case PONG_CLIENT:
+      {
+         swapped = htons(milliseconds);
+//       std::copy(&swapped, &swapped + sizeof(boost::uint16_t), ptr);
+         buf->append(swapped);
+         break;
+      }
+      default:
+         return 0;
+         break;
+    };
     
-    _header_size = headerSize(*tmpptr++);
-    printf (_("The header size is %d"), _header_size);
+    return buf;
+}
+RTMP::rtmp_ping_t *
+RTMP::decodePing(Network::byte_t *data)
+{
+    GNASH_REPORT_FUNCTION;
 
-    if (_header_size >= 4) {
-        _mystery_word = *tmpptr++;
-        _mystery_word = (_mystery_word << 12) + *tmpptr++;
-        _mystery_word = (_mystery_word << 8) + *tmpptr++;
-        log_debug(_("The mystery word is: %d"), _mystery_word);
-    }
+    Network::byte_t *ptr = reinterpret_cast<Network::byte_t *>(data);
+    rtmp_ping_t *ping = new rtmp_ping_t;
+    memset(ping, 0, sizeof(rtmp_ping_t));
 
-    if (_header_size >= 8) {
-        _total_size = *tmpptr++;
-        _total_size = (_total_size << 12) + *tmpptr++;
-        _total_size = (_total_size << 8) + *tmpptr++;
-        _total_size = _total_size & 0xffffff;
-        log_debug(_("The body size is: %d"), _total_size);
-    }
+    boost::uint16_t type = *reinterpret_cast<rtmp_ping_e *>(ptr);
+    ping->type = static_cast<rtmp_ping_e>(type);
+    ptr += sizeof(boost::uint16_t);
 
-    if (_header_size >= 8) {
-        _type = *(content_types_e *)tmpptr;
-        tmpptr++;
-        log_debug(_("The type is: %s"), content_str[_type]);
-    }
+    ping->target = *reinterpret_cast<boost::uint16_t *>(ptr);
+    ptr += sizeof(boost::uint16_t);
 
-//     switch(_type) {
-//       case CHUNK_SIZE:
-//       case BYTES_READ:
-//       case PING:
-//       case SERVER:
-//       case CLIENT:
-//       case VIDEO_DATA:
-//       case NOTIFY:
-//       case SHARED_OBJ:
-//       case INVOKE:
-//           _packet_size = RTMP_VIDEO_PACKET_SIZE;
-//           break;
-//       case AUDIO_DATA:
-//           _packet_size = RTMP_AUDIO_PACKET_SIZE;
-//           break;
-//       default:
-//           log_error (_("ERROR: Unidentified AMF header data type 0x%x"), 
_type);
-//           break;
-//     };
+    ping->param1 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
+    ptr += sizeof(boost::uint16_t);
     
-    if (_header_size == 12) {
-        _src_dest = *(reinterpret_cast<rtmp_source_e *>(tmpptr));
-        tmpptr += sizeof(unsigned int);
-        log_debug(_("The source/destination is: %x"), _src_dest);
-    }
+    ping->param1 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
+
+    return ping;    
+}
+RTMP::rtmp_ping_t *
+RTMP::decodePing(amf::Buffer *buf)
+{
+    GNASH_REPORT_FUNCTION;
+    return decodePing(buf->reference());
+}
+
+amf::Buffer *
+RTMP::encodeServer()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMP::decodeServer()
+{
+    GNASH_REPORT_FUNCTION;
+}
+    
+amf::Buffer *
+RTMP::encodeClient()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMP::decodeClient()
+{
+    GNASH_REPORT_FUNCTION;
+}
+    
+amf::Buffer *
+RTMP::encodeAudioData()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMP::decodeAudioData()
+{
+    GNASH_REPORT_FUNCTION;
+}
+    
+amf::Buffer *
+RTMP::encodeVideoData()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMP::decodeVideoData()
+{
+    GNASH_REPORT_FUNCTION;
+}
+    
+amf::Buffer *
+RTMP::encodeNotify()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMP::decodeNotify()
+{
+    GNASH_REPORT_FUNCTION;
+}
+    
+amf::Buffer *
+RTMP::encodeSharedObj()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMP::decodeSharedObj()
+{
+    GNASH_REPORT_FUNCTION;
+}
 
-    return tmpptr;
+amf::Buffer *
+RTMP::encodeInvoke()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMP::decodeInvoke()
+{
+    GNASH_REPORT_FUNCTION;
 }
 
 } // end of gnash namespace

Index: libnet/rtmp.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- libnet/rtmp.h       30 Apr 2008 03:48:52 -0000      1.7
+++ libnet/rtmp.h       3 May 2008 18:44:08 -0000       1.8
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+//   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
 // 
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@
 const char RTMP_INDEX_MASK = 0x3f;
 const int  RTMP_VIDEO_PACKET_SIZE = 128;
 const int  RTMP_AUDIO_PACKET_SIZE = 64;
+const int  RTMP_MAX_HEADER_SIZE = 12;
 
 // For terminating sequences, a byte with value 0x09 is used.
 const char TERMINATOR = 0x09;
@@ -109,6 +110,20 @@
 //         INITIAL_DATA = 0xb
 //     } sharedobj_types_e;
     typedef enum {
+       PING_CLEAR  = 0x0,      // clear the stream
+       PING_PLAY   = 0x1,      // clear the playing buffer
+       PING_TIME   = 0x3,      // Buffer time in milliseconds
+       PING_RESET  = 0x4,      // Reset stream
+       PING_CLIENT = 0x6,      // Ping the client from the server
+       PONG_CLIENT = 0x7       // pong reply from client to server
+    } rtmp_ping_e;
+    typedef struct {
+       rtmp_ping_e type;       // the type of the ping message
+       boost::uint16_t target;
+       boost::uint16_t param1;
+       boost::uint16_t param2;
+    } rtmp_ping_t;
+    typedef enum {
         RTMP_STATE_HANDSHAKE_SEND,
         RTMP_STATE_HANDSHAKE_RECV,
         RTMP_STATE_HANDSHAKE_ACK,
@@ -132,16 +147,17 @@
     } rtmp_error_t;
 
 // Each header consists of the following:
-//
-// * UTF string (including length bytes) - name
-// * Boolean - specifies if understanding the header is `required'
-// * Long - Length in bytes of header
-// * Variable - Actual data (including a type code)
+// a single byte that is the index of the RTMP channel,
+// then two bits that's a flag to note the size of the header,
+// which can be 1, 4, 8, or 12 bytes long.
+    
+// More info at http://wiki.gnashdev.org/RTMP
     typedef struct {
-        amf::amfutf8_t name;
-       boost::uint8_t required;
-       boost::uint32_t length;
-        void *data;
+       int             channel;
+       int             head_size;
+       int             bodysize;
+       rtmp_source_e   src_dest;
+       content_types_e type;
     } rtmp_head_t;    
     typedef enum {
         HEADER_12 = 0x0,
@@ -165,14 +181,15 @@
     
     RTMP();
     ~RTMP();
-    gnash::Network::byte_t *encodeRTMPHeader(int amf_index, rtmp_headersize_e 
head_size,
+
+    // Decode
+    rtmp_head_t *decodeHeader(gnash::Network::byte_t *header);
+    rtmp_head_t *decodeHeader(amf::Buffer *data);
+    amf::Buffer *encodeHeader(int amf_index, rtmp_headersize_e head_size,
                                size_t total_size, content_types_e type, 
rtmp_source_e routing);
     
-//     bool handShakeWait();
     bool handShakeRequest();
-//    bool handShakeResponse();
     bool clientFinish();
-//  bool serverFinish();
     bool packetRequest();
     bool packetSend(amf::Buffer *buf);
     bool packetRead(amf::Buffer *buf);
@@ -183,37 +200,54 @@
     amf::Element *getProperty(const std::string &name);
     void setHandler(Handler *hand) { _handler = hand; };
     int headerSize(gnash::Network::byte_t header);
-    Network::byte_t *parseHeader(gnash::Network::byte_t *header);
 
-    int getHeaderSize()         { return _header_size; }; 
-    int getTotalSize()          { return _total_size; }; 
+    rtmp_head_t *getHeader()    { return &_header; };
+    int getHeaderSize()         { return _header.head_size; }; 
+    int getTotalSize()          { return _header.bodysize; }; 
+    rtmp_source_e getRouting()  { return _header.src_dest; };
+    int getChannel()            { return _header.channel; };
     int getPacketSize()         { return _packet_size; };
     int getMysteryWord()        { return _mystery_word; };
-    rtmp_source_e getRouting()  { return _src_dest; };
-    int getAMFIndex()           { return _amf_index; };
 
-    // 
-    bool chunk_size();
-    bool bytes_read();
-    bool ping();
-    bool server();
-    bool client();
-    bool audio_data();
-    bool video_data();
-    bool notify();
-    bool shared_obj();
-    bool invoke();
+    // These are handlers for the various types
+    virtual amf::Buffer *encodeChunkSize();
+    virtual void decodeChunkSize();
+    
+    virtual amf::Buffer *encodeBytesRead();
+    virtual void decodeBytesRead();
+    
+    virtual amf::Buffer *encodePing(rtmp_ping_e type, boost::uint16_t 
milliseconds);
+    virtual rtmp_ping_t *decodePing(Network::byte_t *data);
+    rtmp_ping_t *decodePing(amf::Buffer *buf);
+    
+    virtual amf::Buffer *encodeServer();
+    virtual void decodeServer();
+    
+    virtual amf::Buffer *encodeClient();
+    virtual void decodeClient();
+    
+    virtual amf::Buffer *encodeAudioData();
+    virtual void decodeAudioData();
+    
+    virtual amf::Buffer *encodeVideoData();
+    virtual void decodeVideoData();
+    
+    virtual amf::Buffer *encodeNotify();
+    virtual void decodeNotify();
+    
+    virtual amf::Buffer *encodeSharedObj();
+    virtual void decodeSharedObj();
+    
+    virtual amf::Buffer *encodeInvoke();
+    virtual void decodeInvoke();
+    
     void dump();
   protected:
     std::map<const char *, amf::Element *> _variables;
     amf::Buffer                *_handshake;
     Handler            *_handler;
-    int                 _amf_index;
-    int                 _header_size;
-    int                 _total_size;
+    rtmp_head_t        _header;
     int                 _packet_size;
-    rtmp_source_e       _src_dest;
-    content_types_e     _type;
     int                 _mystery_word;
 };
 

Index: libnet/rtmp_server.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_server.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libnet/rtmp_server.cpp      30 Apr 2008 03:48:52 -0000      1.4
+++ libnet/rtmp_server.cpp      3 May 2008 18:44:08 -0000       1.5
@@ -80,18 +80,11 @@
        log_debug("Que empty, net connection dropped for fd #%d", 
_handler->getFileFd());
        return false;
     }    
-//     if (readNet(buffer, 1) == 1) {
-    log_debug (_("Read initial Handshake Request"));
-//     } else {
-//         log_error (_("Couldn't read initial Handshake Request"));
-//         return false;
-//     }
-//    _inbytes += 1;
 
-    if (*(buf->reference()) == 0x3) {
-        log_debug (_("Handshake is correct"));
+    if (*buf->reference() == RTMP_HANDSHAKE) {
+        log_debug (_("Handshake request is correct"));
     } else {
-        log_error (_("Handshake isn't correct"));
+        log_error (_("Handshake request isn't correct"));
         return false;
     }
 
@@ -104,11 +97,11 @@
        _handshake->copy(buf->reference() + 1, RTMP_BODY_SIZE);
        log_debug (_("Handshake Data matched"));
        delete buf;                     // we're done with the buffer
-       return true;
+//     return true;
     } else {
        delete buf;                     // we're done with the buffer
        log_error (_("Handshake Data didn't match"));
-       return false;
+//     return false;
     }
     
     return true;
@@ -121,13 +114,18 @@
 {
     GNASH_REPORT_FUNCTION;
 
-    amf::Buffer *buf = new amf::Buffer((RTMP_BODY_SIZE * 2) + 1);
-    Network::byte_t *ptr = buf->reference();
-    *ptr = 0x3;
-
-    std::copy(_handshake->begin(), _handshake->end(), (ptr + 1));
-    std::copy(_handshake->begin(), _handshake->end(), ptr + _handshake->size() 
+ 1);
-    _handler->pushout(buf);
+    amf::Buffer *buf1 = new amf::Buffer(RTMP_BODY_SIZE + 1);
+    *buf1->begin() = RTMP_HANDSHAKE;
+    buf1->append(_handshake);
+    _handler->pushout(buf1);
+
+    amf::Buffer *buf2 = new amf::Buffer(RTMP_BODY_SIZE);
+    buf2->copy(_handshake->begin(), RTMP_BODY_SIZE);
+    _handler->pushout(buf2);
+    
+//     std::copy(_handshake->begin(), _handshake->end(), (buf1->begin() + 1)); 
   
+//     amf::Buffer *buf = new amf::Buffer(RTMP_BODY_SIZE + 1);
+//     std::copy(_handshake->begin(), _handshake->end(), buf->begin() + 1 + 
RTMP_BODY_SIZE);
     _handler->notifyout();
 
     log_debug("Sent RTMP Handshake response");
@@ -152,7 +150,7 @@
     // So after the handshake block, we strip that part off, and just pass on
     // the remainder for processing.
     if (buf->size() > RTMP_BODY_SIZE) {
-       int size = buf->size() - RTMP_BODY_SIZE;  
+       size_t size = buf->size() - RTMP_BODY_SIZE;  
        obj = new amf::Buffer[size];
        obj->copy(buf->begin()+RTMP_BODY_SIZE, size);
     } else {
@@ -215,8 +213,33 @@
     log_debug("END is %x", (void *)end);
     *end = '*';
 #endif
-    ptr = parseHeader(ptr);
-//     ptr += headersize;
+    rtmp_head_t *head = decodeHeader(ptr);
+    ptr += headersize;
+
+    Network::byte_t* tooFar = ptr+300+sizeof(int); // FIXME:
+    
+    AMF amf_obj;
+    amf::Element *el1 = amf_obj.extractAMF(ptr, tooFar);
+    ptr += amf_obj.totalsize();
+    amf::Element *el2 = amf_obj.extractAMF(ptr, tooFar);
+
+    int size = 0;
+    amf::Element *el;
+    while ( size < static_cast<boost::uint16_t>(_header.bodysize) - 24 ) {
+       if (ptr) {
+           el = amf_obj.extractProperty(ptr, tooFar);
+           if (el != 0) {
+               size += amf_obj.totalsize();
+               ptr += amf_obj.totalsize();
+//             _variables[el->getName()] = el;
+           } else {
+               break;
+           }
+//             log_debug("Bodysize is: %d size is: %d for %s", _total_size, 
size, el->getName());
+       } else {
+           break;
+       }
+    }
 
 # if 0    
     Element el;
@@ -253,21 +276,58 @@
     
     RTMPproto::dump();
 #endif
-    switch(_type) {
+    switch(_header.type) {
       case CHUNK_SIZE:
+         decodeChunkSize();
+         break;
       case BYTES_READ:
+         decodeBytesRead();
+         break;
       case PING:
+      {
+         rtmp_ping_t *ping = decodePing(ptr);
+         switch (ping->type) {
+           case PING_CLEAR:
+               break;
+           case PING_PLAY:
+               break;
+           case PING_TIME:
+               break;
+           case PING_RESET:
+               break;
+           case PING_CLIENT:
+               break;
+           case PONG_CLIENT:
+               break;
+           default:
+               return 0;
+               break;
+         };
+         break;
+      }
       case SERVER:
+         decodeServer();
+         break;
       case CLIENT:
+         decodeClient();
+         break;
       case VIDEO_DATA:
+         decodeVideoData();
+         break;
       case NOTIFY:
+         decodeNotify();
+         break;
       case SHARED_OBJ:
+         decodeSharedObj();
+         break;
       case INVOKE:
+         decodeInvoke();
           break;
       case AUDIO_DATA:
+         decodeAudioData();
           break;
       default:
-          log_error (_("ERROR: Unidentified RTMP message content type 0x%x"), 
_type);
+          log_error (_("ERROR: Unidentified RTMP message content type 0x%x"), 
_header.type);
           break;
     };
     
@@ -288,68 +348,107 @@
     return true;
 }
 
+#if 0
 // These process the incoming AMF object types from the data stream
-Network::byte_t *
-RTMPServer::decodeChunkSize(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeChunkSize()
 {
     GNASH_REPORT_FUNCTION;
 }
-
-Network::byte_t *
-RTMPServer::decodeBytesRead(Network::byte_t *buf)
+void 
+RTMPServer::decodeChunkSize()
 {
     GNASH_REPORT_FUNCTION;
 }
 
-Network::byte_t *
-RTMPServer::decodePing(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeBytesRead()
 {
     GNASH_REPORT_FUNCTION;
 }
-
-Network::byte_t *
-RTMPServer::decodeServer(Network::byte_t *buf)
+void 
+RTMPServer::decodeBytesRead()
 {
     GNASH_REPORT_FUNCTION;
 }
 
-Network::byte_t *
-RTMPServer::decodeClient(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeServer()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeServer()
 {
     GNASH_REPORT_FUNCTION;
 }
 
-Network::byte_t *
-RTMPServer::decodeAudioData(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeClient()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMPServer::decodeClient()
 {
     GNASH_REPORT_FUNCTION;
 }
 
-Network::byte_t *
-RTMPServer::decodeVideoData(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeAudioData()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMPServer::decodeAudioData()
 {
     GNASH_REPORT_FUNCTION;
 }
 
-Network::byte_t *
-RTMPServer::decodeNotify(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeVideoData()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMPServer::decodeVideoData()
 {
     GNASH_REPORT_FUNCTION;
 }
     
-Network::byte_t *
-RTMPServer::decodeSharedObj(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeNotify()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeNotify()
 {
     GNASH_REPORT_FUNCTION;
 }
 
-// Invoke a remote procedure call for an ActionScript class.
-Network::byte_t *
-RTMPServer::decodeInvoke(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeSharedObj()
+{
+    GNASH_REPORT_FUNCTION;
+}
+void 
+RTMPServer::decodeSharedObj()
 {
     GNASH_REPORT_FUNCTION;
+}
     
+amf::Buffer *
+RTMPServer::encodeInvoke()
+{
+    GNASH_REPORT_FUNCTION;
 }
+void 
+RTMPServer::decodeInvoke()
+{
+    GNASH_REPORT_FUNCTION;
+}
+#endif
 
 // This is the thread for all incoming RTMP connections
 void

Index: libnet/rtmp_server.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_server.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libnet/rtmp_server.h        1 Apr 2008 22:20:39 -0000       1.2
+++ libnet/rtmp_server.h        3 May 2008 18:44:08 -0000       1.3
@@ -42,17 +42,36 @@
     bool packetSend(amf::Buffer *buf);
     bool packetRead(amf::Buffer *buf);
 
-    // These process the incoming RTMP message content types from the header
-    gnash::Network::byte_t *decodeChunkSize(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeBytesRead(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodePing(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeServer(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeClient(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeAudioData(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeVideoData(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeNotify(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeSharedObj(gnash::Network::byte_t *buf);
-    gnash::Network::byte_t *decodeInvoke(gnash::Network::byte_t *buf);
+    // These are handlers for the various types
+#if 0
+    amf::Buffer *encodeChunkSize();
+    void decodeChunkSize();
+    
+    amf::Buffer *encodeBytesRead();
+    void decodeBytesRead();
+    
+    amf::Buffer *encodeServer();
+    void decodeServer();
+    
+    amf::Buffer *encodeClient();
+    void decodeClient();
+    
+    amf::Buffer *encodeAudioData();
+    void decodeAudioData();
+    
+    amf::Buffer *encodeVideoData();
+    void decodeVideoData();
+    
+    amf::Buffer *encodeNotify();
+    void decodeNotify();
+    
+    amf::Buffer *encodeSharedObj();
+    void decodeSharedObj();
+    
+    amf::Buffer *encodeInvoke();
+    void decodeInvoke();
+#endif
+    
     void dump();
   private:
 };

Index: testsuite/libnet.all/test_rtmp.cpp
===================================================================
RCS file: testsuite/libnet.all/test_rtmp.cpp
diff -N testsuite/libnet.all/test_rtmp.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ testsuite/libnet.all/test_rtmp.cpp  3 May 2008 18:44:06 -0000       1.1
@@ -0,0 +1,276 @@
+// 
+//   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#ifdef HAVE_DEJAGNU_H
+
+//#include <netinet/in.h>
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <iostream>
+#include <string>
+
+#include "as_object.h"
+#include "dejagnu.h"
+#include "log.h"
+#include "amf.h"
+#include "rtmp_server.h"
+#include "rtmp.h"
+#include "buffer.h"
+#include "network.h"
+#include "element.h"
+#include "sol.h"
+#include "arg_parser.h"
+#include "gmemory.h"
+
+using namespace amf;
+using namespace gnash;
+using namespace std;
+
+static void usage (void);
+
+// Enable the display of memory allocation and timing data
+static bool memdebug = false;
+
+// We use the Memory profiling class to check the malloc buffers
+// in the kernel to make sure the allocations and frees happen
+// the way we expect them too. There is no real other way to tell.
+#if defined(HAVE_MALLINFO) && defined(USE_STATS_MEMORY)
+Memory *mem = 0;
+#endif
+
+static TestState runtest;
+
+static void test_header();
+static void test_types();
+
+LogFile& dbglogfile = LogFile::getDefaultInstance();
+
+// These next two functions are borrowed from Libgloss, part of the GNU 
binutils,
+// of which I am the primary author and copyright holder.
+// convert an ascii hex digit to a number.
+//      param is hex digit.
+//      returns a decimal digit.
+Network::byte_t
+hex2digit (Network::byte_t digit)
+{  
+    if (digit == 0)
+        return 0;
+    
+    if (digit >= '0' && digit <= '9')
+        return digit - '0';
+    if (digit >= 'a' && digit <= 'f')
+        return digit - 'a' + 10;
+    if (digit >= 'A' && digit <= 'F')
+        return digit - 'A' + 10;
+    
+    // shouldn't ever get this far
+    return -1;
+}
+
+// Convert the hex array pointed to by buf into binary to be placed in mem
+Buffer *
+hex2mem(const char *str)
+{
+    size_t count = strlen(str);
+    Network::byte_t ch = 0;
+    Buffer *buf = new Buffer(count + 12);
+    buf->clear();
+
+    Network::byte_t *ptr = const_cast<Network::byte_t 
*>(reinterpret_cast<const Network::byte_t *>(str));
+    
+    for (size_t i=0; i<count; i++) {
+        if (*ptr == ' ') {      // skip spaces.
+            ptr++;
+            continue;
+        }
+        ch = hex2digit(*ptr++) << 4;
+        ch |= hex2digit(*ptr++);
+        buf->append(ch);
+    }
+    return buf;
+}
+
+int
+main(int argc, char *argv[])
+{
+    const Arg_parser::Option opts[] =
+        {
+            { 'h', "help",          Arg_parser::no  },
+            { 'v', "verbose",       Arg_parser::no  },
+            { 'w', "write",         Arg_parser::no  },
+// Unless you have support for memory debugging turned on, and
+// you have support for the Linux mallinfo() system call,
+// this option is totally useless. This doesn't really matter
+// as the memory testing is primarily used only during
+// debugging or development.
+            { 'm', "memstats",      Arg_parser::no  },
+            { 'd', "dump",          Arg_parser::no  },
+        };
+    
+    Arg_parser parser(argc, argv, opts);
+    if( ! parser.error().empty() ) {
+        cout << parser.error() << endl;
+        exit(EXIT_FAILURE);
+    }
+    
+    for( int i = 0; i < parser.arguments(); ++i ) {
+        const int code = parser.code(i);
+        try {
+            switch( code ) {
+              case 'h':
+                  usage ();
+                  exit(EXIT_SUCCESS);
+              case 'v':
+                    dbglogfile.setVerbosity();
+                    log_debug(_("Verbose output turned on"));
+                    break;
+              case 'm':
+                    log_debug(_("Enabling memory statistics"));
+                    memdebug = true;
+                    break;
+           }
+        }
+        
+        catch (Arg_parser::ArgParserException &e) {
+            cerr << _("Error parsing command line options: ") << e.what() << 
endl;
+            cerr << _("This is a Gnash bug.") << endl;
+        }
+    }
+
+#if defined(HAVE_MALLINFO) && defined(USE_STATS_MEMORY)
+    if (memdebug) {
+        mem = new Memory;
+        mem->startStats();
+    }
+#endif
+    
+    test_header();
+    test_types();
+}
+
+void
+test_header()
+{
+    GNASH_REPORT_FUNCTION;
+    RTMP rtmp;
+    
+    // this is a sample 12 bytes RTMP header
+    const char *x = "03 00 00 00 00 01 1f 14 00 00 00 00";
+    Buffer *buf1 = hex2mem(x);
+    Buffer *head = rtmp.encodeHeader(0x3, RTMP::HEADER_12, 287,
+                                     RTMP::INVOKE, RTMP::FROM_CLIENT);
+//     cerr << hexify(head->begin(), 12, false) << endl;
+    
+     if ((memcmp(buf1->reference(), head->reference(), 12) == 0)) {
+         runtest.pass("Encoded RTMP header");
+     } else {
+         runtest.fail("Encoded RTMP header");
+     }
+
+     RTMP::rtmp_head_t *header = rtmp.decodeHeader(buf1->reference());
+     if ((header->channel == 0x3) && (header->head_size == 12)
+         && (header->bodysize == 287) && (header->type ==  RTMP::INVOKE)) {
+         runtest.pass("Decoded RTMP header");
+     } else {
+         runtest.fail("Decoded RTMP header");
+     }
+     
+     // cleanup after ourselves
+     delete buf1;
+     delete head;
+}
+
+
+void
+test_types()
+{
+    GNASH_REPORT_FUNCTION;
+    RTMP rtmp;
+
+    const char *x = "06 00 d2 04 00 00 00 00";
+    Buffer *buf1 = hex2mem(x);
+    
+    RTMP::rtmp_ping_t *ping = rtmp.decodePing(buf1);
+    if (ping->type == RTMP::PING_CLIENT) {
+         runtest.pass("Decoded RTMP Ping message");
+     } else {
+         runtest.fail("Decoded RTMP Ping message");
+     }
+    
+    Buffer *buf2 = rtmp.encodePing(RTMP::PING_CLIENT, 53764);
+    cerr << hexify(buf2->begin(), 8, false) << endl;
+     if ((memcmp(buf1->reference(), buf2->reference(), 8) == 0)) {
+         runtest.pass("Encoded RTMP Ping message");
+     } else {
+         runtest.fail("Encoded RTMP Ping message");
+     }
+     delete ping;
+     delete buf1;
+     delete buf2;
+}
+
+static void
+usage (void)
+{
+    cerr << "This program tests SOL support in the AMF library." << endl;
+    cerr << "Usage: test_sol [hv]" << endl;
+    cerr << "-h\tHelp" << endl;
+    cerr << "-v\tVerbose" << endl;
+    exit (-1);
+}
+
+#else
+
+int
+main(int /*argc*/, char /* *argv[]*/)
+{
+  // nop
+  return 0;  
+}
+
+#endif
+
+// 03 00 00 04 00 01 1f 14 00 00 00 00 02 00 07 63   ...............c
+// 6f 6e 6e 65 63 74 00 3f f0 00 00 00 00 00 00 03   onnect.?........
+// 00 03 61 70 70 02 00 08 6f 66 6c 61 44 65 6d 6f   ..app...oflaDemo
+// 00 08 66 6c 61 73 68 56 65 72 02 00 0c 4c 4e 58   ..flashVer...LNX
+// 20 39 2c 30 2c 33 31 2c 30 00 06 73 77 66 55 72    9,0,31,0..swfUr
+// 6c 02 00 33 68 74 74 70 3a 2f 2f 6c 6f 63 61 6c   l..3http://local
+// 68 6f 73 74 2f 73 6f 66 74 77 61 72 65 2f 67 6e   host/software/gn
+// 61 73 68 2f 74 65 73 74 73 2f 6f 66 6c 61 5f 64   ash/tests/ofla_d
+// 65 6d 6f 2e 73 77 66 00 05 74 63 55 c3 72 6c 02   emo.swf..tcU.rl.
+// 00 19 72 74 6d 70 3a 2f 2f 6c 6f 63 61 6c 68 6f   ..rtmp://localho
+// 73 74 2f 6f 66 6c 61 44 65 6d 6f 00 04 66 70 61   st/oflaDemo..fpa
+// 64 01 00 00 0b 61 75 64 69 6f 43 6f 64 65 63 73   d....audioCodecs
+// 00 40 83 38 00 00 00 00 00 00 0b 76 69 64 65 6f   address@hidden
+// 43 6f 64 65 63 73 00 40 5f 00 00 00 00 00 00 00   address@hidden
+// 0d 76 69 64 65 6f 46 75 6e 63 74 69 6f 6e 00 3f   .videoFunction.?
+// f0 00 00 00 00 00 00 00 07 70 61 67 65 55 72 6c   .........pageUrl
+// 02 00 26 68 74 74 70 3a 2f 2f 6c 6f 63 c3 61 6c   ..&http://loc.al
+// 68 6f 73 74 2f 73 6f 66 74 77 61 72 65 2f 67 6e   host/software/gn
+// 61 73 68 2f 74 65 73 74 73 2f 00 00 09
+
+    




reply via email to

[Prev in Thread] Current Thread [Next in Thread]