gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog libamf/amf.cpp libamf/amf.h lib...


From: Rob Savoye
Subject: [Gnash-commit] gnash ChangeLog libamf/amf.cpp libamf/amf.h lib...
Date: Fri, 16 May 2008 03:46:40 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Rob Savoye <rsavoye>    08/05/16 03:46:39

Modified files:
        .              : ChangeLog 
        libamf         : amf.cpp amf.h buffer.cpp buffer.h element.cpp 
                         element.h sol.cpp sol.h 
        libnet         : Makefile.am handler.cpp http.cpp rtmp.cpp 
                         rtmp.h rtmp_server.cpp rtmp_server.h 
        testsuite/libamf.all: test_sol.cpp 
        testsuite/libnet.all: test_cque.cpp test_handler.cpp 
                              test_rtmp.cpp 
Added files:
        libnet         : rtmp_client.cpp rtmp_client.h rtmp_msg.cpp 
                         rtmp_msg.h 

Log message:
                * libamf/amf.cpp: Trap the new AMF3 type. Decode objects
                correctly. 
                * libamf.buffer.{h,cpp}: Resize to hold the data up to the 
current
                seek pointer if no argument.
                * libamf/element.cpp: Trap the switch from AMF0 to AMF3. Dump
                properties too.
                * libamf/sol.cpp: Properties in a SOL file have a zero byte
                terminator after each one.
                * libnet/Makefile.am: Add new files, rtmp_msg.* and 
rtmp_client.*.
                * libnet/rtmp_client.{g,cpp}: Client side support for RTMP.
                * libnet/rtmp_msg.{g,cpp}: Represent an RTMP packet, inckuding 
the
                header. 
                * libnet/http.cpp: Cleanup warnings.
                * libnet/rtmp.cpp: Move client side methods to new RTMPClient
                class and other to RTMPMsg. Decode result messages from media
                server. Cleanup warnings.
                * libnet/rtmp_server.cpp: Build result messages for client.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6610&r2=1.6611
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.cpp?cvsroot=gnash&r1=1.78&r2=1.79
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.h?cvsroot=gnash&r1=1.42&r2=1.43
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/buffer.cpp?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/buffer.h?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.cpp?cvsroot=gnash&r1=1.25&r2=1.26
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.h?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/sol.cpp?cvsroot=gnash&r1=1.36&r2=1.37
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/sol.h?cvsroot=gnash&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/Makefile.am?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/handler.cpp?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/http.cpp?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.cpp?cvsroot=gnash&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.h?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_server.cpp?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_server.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_client.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_client.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_msg.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_msg.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libamf.all/test_sol.cpp?cvsroot=gnash&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/test_cque.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/test_handler.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/test_rtmp.cpp?cvsroot=gnash&r1=1.1&r2=1.2

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6610
retrieving revision 1.6611
diff -u -b -r1.6610 -r1.6611
--- ChangeLog   15 May 2008 14:41:09 -0000      1.6610
+++ ChangeLog   16 May 2008 03:46:11 -0000      1.6611
@@ -1,3 +1,23 @@
+2008-05-15  Rob Savoye  <address@hidden>
+
+       * libamf/amf.cpp: Trap the new AMF3 type. Decode objects
+       correctly. 
+       * libamf.buffer.{h,cpp}: Resize to hold the data up to the current
+       seek pointer if no argument.
+       * libamf/element.cpp: Trap the switch from AMF0 to AMF3. Dump
+       properties too.
+       * libamf/sol.cpp: Properties in a SOL file have a zero byte
+       terminator after each one.
+       * libnet/Makefile.am: Add new files, rtmp_msg.* and rtmp_client.*.
+       * libnet/rtmp_client.{g,cpp}: Client side support for RTMP.
+       * libnet/rtmp_msg.{g,cpp}: Represent an RTMP packet, inckuding the
+       header. 
+       * libnet/http.cpp: Cleanup warnings.
+       * libnet/rtmp.cpp: Move client side methods to new RTMPClient
+       class and other to RTMPMsg. Decode result messages from media
+       server. Cleanup warnings.
+       * libnet/rtmp_server.cpp: Build result messages for client.
+
 2008-05-15 Sandro Santilli <address@hidden>
 
        * server/parser/movie_def_impl.cpp (readHeader): limit FPS to a max of

Index: libamf/amf.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/amf.cpp,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -b -r1.78 -r1.79
--- libamf/amf.cpp      7 May 2008 20:59:29 -0000       1.78
+++ libamf/amf.cpp      16 May 2008 03:46:17 -0000      1.79
@@ -70,7 +70,8 @@
     "Unsupported",
     "Recordset",
     "XMLObject",
-    "TypedObject"
+    "TypedObject",
+    "AMF3 Data"
 };
 
 AMF::AMF() 
@@ -196,7 +197,7 @@
 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(2);
     buf->append(Element::BOOLEAN_AMF0);
@@ -442,7 +443,7 @@
 Buffer *
 AMF::encodeString(Network::byte_t *data, size_t size)
 {
-    GNASH_REPORT_FUNCTION;
+//    GNASH_REPORT_FUNCTION;
     boost::uint16_t length;
     
     Buffer *buf = new Buffer(size + AMF_HEADER_SIZE);
@@ -503,9 +504,9 @@
 Buffer *
 AMF::encodeElement(Element *el)
 {
-    GNASH_REPORT_FUNCTION;
+//    GNASH_REPORT_FUNCTION;
     Buffer *buf = 0;
-    Buffer *tmp;
+    Buffer *tmp = 0;
     
     size_t outsize;
     if (el->getType() == Element::BOOLEAN_AMF0) {
@@ -541,7 +542,7 @@
          tmp = encodeBoolean(el->to_bool());
           break;
       case Element::STRING_AMF0:
-         tmp = encodeString(el->getData(), el->getLength()-1);
+         tmp = encodeString(el->getData(), el->getLength());
          break;
       case Element::OBJECT_AMF0:
          tmp = el->encode();
@@ -593,6 +594,9 @@
 //       case Element::VARIABLE:
 //       case Element::FUNCTION:
 //          break;
+      case Element::AMF3_DATA:
+         log_error("FIXME: got AMF3 data type");
+         break;
       default:
          tmp = 0;
           break;
@@ -669,10 +673,10 @@
 Element *
 AMF::extractAMF(Network::byte_t *in, Network::byte_t* tooFar)
 {
-//    GNASH_REPORT_FUNCTION;
+    GNASH_REPORT_FUNCTION;
 
     Element *el = new Element;    
-    Network::byte_t *tmpptr;
+    Network::byte_t *tmpptr = in;
     boost::uint16_t length;
 
     if (in == 0) {
@@ -680,8 +684,6 @@
         return 0;
     }
 
-    tmpptr = in;
-    
     // All elements look like this:
     // the first two bytes is the length of name of the element
     // Then the next bytes are the element name
@@ -694,62 +696,60 @@
     // mostly to make valgrind shut up, as it has a tendency to
     // complain about legit code when it comes to all this byte
     // manipulation stuff.
-#ifndef GNASH_TRUST_AMF
-    ENSUREBYTES(tmpptr, tooFar, 1);
-#endif
     char c = *(reinterpret_cast<char *>(tmpptr));
     Element::amf0_type_e type = static_cast<Element::amf0_type_e>(c);
-    tmpptr++;                        // skip the header byte
+    tmpptr++;                        // skip past the header byte
 
     AMF amf_obj;
     switch (type) {
       case Element::NUMBER_AMF0:
-#ifndef GNASH_TRUST_AMF
-          ENSUREBYTES(tmpptr, tooFar, AMF0_NUMBER_SIZE);
-#endif
          el->makeNumber(tmpptr); 
          tmpptr += AMF0_NUMBER_SIZE; // all numbers are 8 bit big endian
          break;
       case Element::BOOLEAN_AMF0:
-#ifndef GNASH_TRUST_AMF
-          ENSUREBYTES(tmpptr, tooFar, sizeof(boost::uint16_t));
-#endif
          el->makeBoolean(tmpptr);
          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
-#ifndef GNASH_TRUST_AMF
-          ENSUREBYTES(tmpptr, tooFar, sizeof(boost::uint16_t));
-#endif
          length = ntohs((*(boost::uint16_t *)tmpptr) & 0xffff);
          tmpptr += sizeof(boost::uint16_t);
-         log_debug(_("AMF String length is: %d"), length);
+         if (length >= SANE_STR_SIZE) {
+             log_error("%d bytes for a string is over the safe limit of %d",
+                       length, SANE_STR_SIZE);
+             return 0;
+         }
+//       log_debug(_("AMF String length is: %d"), length);
          if (length > 0) {
              // get the name of the element
-#ifndef GNASH_TRUST_AMF
-              ENSUREBYTES(tmpptr, tooFar, length);
-#endif
              el->makeString(tmpptr, length);
-             log_debug(_("AMF String is: %s"), el->to_string());
+//           log_debug(_("AMF String is: %s"), el->to_string());
              tmpptr += length;
          } else {
              el->setType(Element::STRING_AMF0);
          };
          break;
       case Element::OBJECT_AMF0:
+      {
          el->makeObject();
-         Element *child;
-         do {
-             child = amf_obj.extractProperty(tmpptr, tooFar); 
-#ifndef GNASH_TRUST_AMF
-              ENSUREBYTES(tmpptr, tooFar, amf_obj.totalsize()-1);
-#endif
-             tmpptr += amf_obj.totalsize() - 1;
+         while (tmpptr < (tooFar - AMF_HEADER_SIZE)) {
+             if (*tmpptr == TERMINATOR) {
+//               log_debug("No data associated with Property in object");
+                 tmpptr++;
+                 break;
+             }
+             Element *child = amf_obj.extractProperty(tmpptr, tooFar); 
+             if (child == 0) {
+                 break;
+             }
+//           child->dump();
              el->addProperty(child);
-         } while (tmpptr < tooFar && *tmpptr != Element::OBJECT_END_AMF0);
+             tmpptr += amf_obj.totalsize();
+         };
+         tmpptr += AMF_HEADER_SIZE;            // skip past the terminator 
bytes
          break;
+      }
       case Element::MOVIECLIP_AMF0:
       case Element::NULL_AMF0:
       case Element::UNDEFINED_AMF0:
@@ -763,13 +763,14 @@
       case Element::RECORD_SET_AMF0:
       case Element::XML_OBJECT_AMF0:
       case Element::TYPED_OBJECT_AMF0:
+      case Element::AMF3_DATA:
       default:
-//       log_unimpl("%s: type %d", __PRETTY_FUNCTION__, (int)type);
+         log_unimpl("%s: type %d", __PRETTY_FUNCTION__, (int)type);
          return 0;
     }
     
     // Calculate the offset for the next read
-    _totalsize = (tmpptr - in) + 1;
+    _totalsize = (tmpptr - in);
 
     return el;
 }
@@ -787,142 +788,60 @@
 Element *
 AMF::extractProperty(Network::byte_t *in, Network::byte_t* tooFar)
 {
-//    GNASH_REPORT_FUNCTION;
+    GNASH_REPORT_FUNCTION;
     Network::byte_t *tmpptr = in;
-    boost::uint16_t length = 0;
-
-#ifndef GNASH_TRUST_AMF
-    ENSUREBYTES(tmpptr, tooFar, sizeof(boost::uint16_t));
-#endif
+    boost::uint16_t length;
 
-    length = *(reinterpret_cast<boost::uint16_t *>(tmpptr));
-//     length = tmpptr[1];             // FIXME: hack. This supports
-//                             // strings up to 256 characters
-//                             // but keep svalgrind happy.
-    swapBytes(&length, sizeof(boost::uint16_t));
+    length = ntohs((*(boost::uint16_t *)tmpptr) & 0xffff);
+    // go past the length bytes, which leaves us pointing at the raw data
     tmpptr += sizeof(boost::uint16_t);
     
+    // sanity check the length of the data. The length is usually only zero if
+    // we've gone all the way to the end of the object.
+
+    // valrind comlains length is unintialized, which as we just set
+    // length to a value, this is tottaly bogus, and I'm tired of
+    // braindamaging code to keep valgrind happy.
     if (length <= 0) {
-//     if (*(in+2) == Element::OBJECT_END) {
-           log_debug(_("End of Object definition"));
-//            el->setType(Element::OBJECT_END);
-//             return el;
-//         }
-//     delete el;
+       log_debug("No Property name, object done");
        return 0;
     }    
-    
-    Element *el = new Element;
-    // get the name of the element, the length of which we just decoded
-    if (length > 0) {
-//        log_debug(_("AMF element length is: %d"), length);
-#ifndef GNASH_TRUST_AMF
-       ENSUREBYTES(tmpptr, tooFar, length);
-#endif
-        el->setName(tmpptr, length);
-//     log_debug(_("AMF element name is: %s"), el->getName());
-       tmpptr += length;
+    if (length >= SANE_STR_SIZE) {
+       log_error("%d bytes for a string is over the safe limit of %d",
+                 length, SANE_STR_SIZE);
+       return 0;
     }
     
-    // get the type of the element, which is a single byte.
-#ifndef GNASH_TRUST_AMF
-    ENSUREBYTES(tmpptr, tooFar, 1);
-#endif
-    char c = *(reinterpret_cast<char *>(tmpptr));
-    Element::amf0_type_e type = static_cast<Element::amf0_type_e>(c);
-    tmpptr++;
-
-    if (type != Element::TYPED_OBJECT_AMF0) {
-//        log_debug(_("AMF type is: %s"), amftype_str[(int)type]);
-       el->setType(type);
-    }
+    // name is just debugging help to print cleaner, and should be removed 
later
+    log_debug(_("AMF property name length is: %d"), length);
+    const char *name = strndup(reinterpret_cast<const char *>(tmpptr), length);
+    log_debug(_("AMF property name is: %s"), name);
 
-    switch (type) {
-      case Element::NUMBER_AMF0:
-      {
-#ifndef GNASH_TRUST_AMF
-          ENSUREBYTES(tmpptr, tooFar, sizeof(double));
-#endif
-         double num = *reinterpret_cast<const double*>(tmpptr);
-          swapBytes(&num, AMF0_NUMBER_SIZE);
-         el->makeNumber(num);
-          tmpptr += AMF0_NUMBER_SIZE;
-         break;
-      }
-      case Element::BOOLEAN_AMF0:
-      {
-#ifndef GNASH_TRUST_AMF
-          ENSUREBYTES(tmpptr, tooFar, 1); 
-#endif
-          // 
-          // @@strk@@ :  we read 2 bytes from ::extractAMF, why only 1 here in 
::extractProperty ?
-          //
-         bool sheet = *(reinterpret_cast<bool *>(tmpptr));
-          el->makeBoolean(sheet);
-         tmpptr += 1;
-         break;
-      }
-      case Element::STRING_AMF0:
-         // extractString returns a printable char *. First 2 bytes for the 
length,
-         // and then read the string, which is NOT NULL terminated.
-#ifndef GNASH_TRUST_AMF
-          ENSUREBYTES(tmpptr, tooFar, sizeof(boost::uint16_t)); 
-#endif
-         length = *reinterpret_cast<boost::uint16_t *>(tmpptr);
-         swapBytes(&length, sizeof(boost::uint16_t));
-         tmpptr += sizeof(boost::uint16_t);
-         if (length > 0) {
-#ifndef GNASH_TRUST_AMF
-              ENSUREBYTES(tmpptr, tooFar, length);
-#endif
-             el->makeString(tmpptr, length);
+    Element *el = 0;
+    // If we get a NULL object, there is no data. In that case, we only return
+    // the name of the property.
+    if (*(tmpptr+length) == Element::NULL_AMF0) {
+       log_debug("No data associated with Property \"%s\"", name);
+       el = new Element;
+       el->setName(name, length);
+       tmpptr += length + 1;
+       // Calculate the offset for the next read
+    } else {
+       // process the data with associated with the property.
+       // Go past the data to the start of the next AMF object, which
+       // should be a type byte.
              tmpptr += length;
+       el = extractAMF(tmpptr, tooFar);
+       if (el) {
+           el->setName(name, length);
+           tmpptr += totalsize();
          }
-         if (length == 0) {
-//           log_debug("NullString");
-             el->makeNullString();
-         }
-//       log_debug(_("Property \"%s\" is: %s"), el->getName(), 
el->to_string());
-          break;
-      case Element::OBJECT_AMF0:
-         while ( (tmpptr<tooFar) && ( *(tmpptr++) != Element::OBJECT_END_AMF0) 
) {
-//           log_debug("Looking for end of object...");
-         }
-         break;
-      case Element::MOVIECLIP_AMF0:
-      case Element::NULL_AMF0:
-         el->makeUndefined();
-         break;
-      case Element::UNDEFINED_AMF0:
-         el->makeUndefined();
-          break;
-      case Element::REFERENCE_AMF0:
-      case Element::ECMA_ARRAY_AMF0:
-                       // FIXME this shouldn't fall thru
-      case Element::OBJECT_END_AMF0:
-//          log_debug(_("End of Object definition"));
-         el->makeObjectEnd();
-          break;
-      case Element::TYPED_OBJECT_AMF0:
-         el->makeTypedObject(tmpptr, 0); // TODO: pass tooFar over ?
-          break;
-      case Element::STRICT_ARRAY_AMF0:
-      case Element::DATE_AMF0:
-         el->makeDate(tmpptr); // TODO: pass tooFar over ?
-          break;
-      case Element::LONG_STRING_AMF0:
-      case Element::UNSUPPORTED_AMF0:
-      case Element::RECORD_SET_AMF0:
-      case Element::XML_OBJECT_AMF0:
-      default:
-          log_unimpl(_("amf0_type_e of value: %x"), (int)type);
-         delete el;
-         return 0;
     }
 
+    delete name;
+    
     // Calculate the offset for the next read
-    _totalsize = (tmpptr - in) + 1;
-//    log_debug("Total number of bytes read from byte stream is: %d", 
_totalsize);
+    _totalsize = (tmpptr - in);
     
     return el;
 }

Index: libamf/amf.h
===================================================================
RCS file: /sources/gnash/gnash/libamf/amf.h,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -b -r1.42 -r1.43
--- libamf/amf.h        30 Apr 2008 18:19:40 -0000      1.42
+++ libamf/amf.h        16 May 2008 03:46:19 -0000      1.43
@@ -65,6 +65,12 @@
 // For terminating sequences, a byte with value 0x09 is used.
 const gnash::Network::byte_t TERMINATOR = 0x09;
 
+// As if there is a parsing error, we'll often see the symptom of the length
+// for the following value is bogus. Although the length field is a short, it
+// seems silly to assume we'll ever see a string 65,000 characters long. Still,
+// it makes sense to make this an adjustable thing.
+const int SANE_STR_SIZE = 1024;
+
 // An AMF object is the binary representation of an ActionScript object. AMF
 // is used to send objects, wheather to a SharedObject .sol file, a memory 
based
 // LocalConnection segment, or over an RTMP connection for streaming.

Index: libamf/buffer.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/buffer.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- libamf/buffer.cpp   30 Apr 2008 03:35:30 -0000      1.9
+++ libamf/buffer.cpp   16 May 2008 03:46:20 -0000      1.10
@@ -29,6 +29,51 @@
 namespace amf
 {
 
+#if 0
+// 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 *
+Buffer::hex2mem(const char *str)
+{
+    size_t count = strlen(str);
+    Network::byte_t ch = 0;
+    _ptr = new Buffer((count/3)+1);
+//    buf->clear();
+
+    Network::byte_t *strdata = const_cast<Network::byte_t 
*>(reinterpret_cast<const Network::byte_t *>(str));
+    
+    for (size_t i=0; i<count; i++) {
+        if (*strdata == ' ') {      // skip spaces.
+            strdata++;
+            continue;
+        }
+        ch = hex2digit(*strdata++) << 4;
+        ch |= hex2digit(*strdata++);
+        append(ch);
+    }
+    return _ptr;
+}
+#endif
+
 void *
 Buffer::init(size_t nbytes)
 {
@@ -191,12 +236,8 @@
 Buffer::append(boost::uint32_t num)
 {
 //    GNASH_REPORT_FUNCTION;
-    if ((_seekptr + sizeof(boost::uint32_t)) <= (_ptr + _nbytes)) {
-       std::copy(&num, &num + sizeof(boost::uint32_t), _seekptr);    
-       _seekptr += sizeof(boost::uint32_t);
-       return _seekptr;
-    }
-    return 0;
+    Network::byte_t *ptr = reinterpret_cast< Network::byte_t *>(&num);    
+    return append(ptr, sizeof(boost::uint32_t));
 }
 
 Network::byte_t *
@@ -432,6 +473,14 @@
 }
 
 // Resize the buffer that holds the data.
+// Resize the buffer that holds the data.
+void *
+Buffer::resize()
+{
+//    GNASH_REPORT_FUNCTION;
+    return resize(_seekptr - _ptr);
+}
+
 void *
 Buffer::resize(size_t size)
 {

Index: libamf/buffer.h
===================================================================
RCS file: /sources/gnash/gnash/libamf/buffer.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- libamf/buffer.h     30 Apr 2008 03:35:30 -0000      1.6
+++ libamf/buffer.h     16 May 2008 03:46:21 -0000      1.7
@@ -45,6 +45,7 @@
     bool empty() { return (_seekptr)?true:false; };
 
     // Resize the buffer that holds the data
+    void *resize();
     void *resize(size_t nbytes);
 
     // Put data into the buffer. This overwrites all data, and resets the seek 
ptr.
@@ -102,6 +103,7 @@
     Buffer &operator+=(Buffer &buf);
     gnash::Network::byte_t operator[](int x) { return *(_ptr + x); };
     gnash::Network::byte_t *at(int x) { return _ptr + x; };
+//    Buffer *hex2mem(const char *str);
     
     // debug stuff, not need for running Cygnal
     void dump();

Index: libamf/element.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.cpp,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -b -r1.25 -r1.26
--- libamf/element.cpp  7 May 2008 19:22:33 -0000       1.25
+++ libamf/element.cpp  16 May 2008 03:46:21 -0000      1.26
@@ -58,8 +58,7 @@
     "Recordset",
     "XMLObject",
     "TypedObject",
-    "Varible (gnash)",
-    "Function (gnash)"
+    "AMF3 Data"
 };
 
 Element::Element()
@@ -397,28 +396,29 @@
 Buffer *
 Element::encode()
 {
-//    GNASH_REPORT_FUNCTION;
+    GNASH_REPORT_FUNCTION;
     Buffer *buf = 0;
     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(300);
+       buf = new Buffer(300);  // FIXME: calculate a sensible size
        buf->clear();           // FIXME: temporary, makes buffers cleaner in 
gdb.
        buf->append(Element::OBJECT_AMF0);
        if (_name > 0) {
-//         Buffer *top = AMF::encodeElement(this);
-//         buf->append(top);
-           buf->append(reinterpret_cast<Network::byte_t *>(_name), 
getNameSize());
            size_t length = getNameSize();
            boost::uint16_t enclength = length;
            swapBytes(&enclength, 2);
            buf->append(enclength);
+           string str = _name;
+           buf->append(str);
+           Network::byte_t byte = static_cast<Network::byte_t>(0x5);
+           buf->append(byte);
        }
 
        for (size_t i=0; i<_properties.size(); i++) {
            Buffer *partial = AMF::encodeElement(_properties[i]);
-           log_debug("Encoded partial size for is %d", partial->size());
-           partial->dump();
+//         log_debug("Encoded partial size for is %d", partial->size());
+//         partial->dump();
            if (partial) {
                buf->append(partial);
                delete partial;
@@ -426,7 +426,7 @@
                break;
            }
        }
-       log_debug("FIXME: Terminating object");
+//     log_debug("FIXME: Terminating object");
        Network::byte_t pad = 0;
        buf->append(pad);
        buf->append(pad);
@@ -485,16 +485,18 @@
 {
 //    GNASH_REPORT_FUNCTION;
     _type = Element::STRING_AMF0;
+
     // Make room for an additional NULL terminator
     check_buffer(size+1);
+    _buffer->clear();          // FIXME: this could be a performance issue
     _buffer->copy(data, size);
     
     // Unlike other buffers, people like to print strings, so we must add
     // a NULL terminator to the string. When encoding, we are careful to
     // to adjust the byte count down by one, as the NULL terminator doesn't
     // get written.
-    *(_buffer->end() - 1) = 0;
-
+//     *(_buffer->end() - 1) = 0;
+    _buffer->setSize(size);
     return *this;
 }
 
@@ -537,6 +539,13 @@
 }
 
 Element &
+Element::makeNumber(Buffer *buf)
+{
+//    GNASH_REPORT_FUNCTION;
+    return makeNumber(buf->reference());
+}
+
+Element &
 Element::makeNumber(Network::byte_t *data)
 {
 //    GNASH_REPORT_FUNCTION;
@@ -876,6 +885,14 @@
 }
 
 void
+Element::setName(const char *name, size_t size)
+{
+//    GNASH_REPORT_FUNCTION;
+    Network::byte_t *ptr = reinterpret_cast<Network::byte_t *>(const_cast<char 
*>(name));
+    return setName(ptr, size);
+}
+
+void
 Element::setName(Network::byte_t *name, size_t size)
 {
 //    GNASH_REPORT_FUNCTION;
@@ -945,8 +962,11 @@
       case Element::RECORD_SET_AMF0:
       case Element::XML_OBJECT_AMF0:
       case Element::TYPED_OBJECT_AMF0:
-//       cerr << "AMF data is: 0x" << hexify(_data, _length, false) << endl;
-         log_debug("FIXME: got a typed object!");
+      case Element::AMF3_DATA:
+         if (getLength() != 0) {
+             log_debug("FIXME: got AMF3 data!");
+         }
+//       cerr << "AMF3 data is: 0x" << hexify(_data, _length, false) << endl;
          break;
 //       case Element::VARIABLE:
 //       case Element::FUNCTION:
@@ -959,6 +979,19 @@
 //       log_unimpl("%s: type %d", __PRETTY_FUNCTION__, (int)_type);
          break;
     }
+
+    if (_buffer) {
+       _buffer->dump();
+    }
+
+    if (_properties.size() > 0) {
+       vector<amf::Element *>::iterator ait;
+       cerr << "# of Properties in object" << _properties.size() << endl;
+       for (ait = _properties.begin(); ait != _properties.end(); ait++) {
+           amf::Element *el = (*(ait));
+           el->dump();
+       }
+    }
 }
 
 } // end of amf namespace

Index: libamf/element.h
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- libamf/element.h    3 May 2008 18:44:06 -0000       1.21
+++ libamf/element.h    16 May 2008 03:46:22 -0000      1.22
@@ -55,8 +55,9 @@
         RECORD_SET_AMF0=0x0e,
         XML_OBJECT_AMF0=0x0f,
         TYPED_OBJECT_AMF0=0x10,
+       AMF3_DATA=0x11,
 //     // these aren't part of the AMF spec, they're used internally
-//     VARIABLE=0x11,
+       RTMP_HEADER=0x20,
 //     FUNCTION=0x12
     } amf0_type_e;
     // AMF3, was introduced with ActionScript 3 in SWF version 9
@@ -107,6 +108,7 @@
     Element &makeString(const std::string &name, const std::string &data);
     
     Element &makeNumber(double num); 
+    Element &makeNumber(amf::Buffer *buf); 
     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); 
@@ -158,6 +160,8 @@
     Element &makeStrictArray(gnash::Network::byte_t *data, size_t size);
 //    Element &makeArray();
 
+//    Element &makeConnect();
+    
     // Test to see if Elements are the same
     bool operator==(Element &);
     bool operator==(Element *);
@@ -188,6 +192,7 @@
     size_t getNameSize();
     void setName(const std::string &name);
     void setName(gnash::Network::byte_t *name, size_t x);
+    void setName(const char *name, size_t x);
 
     // Manipulate the children Elements of an object
     Element *getProperty(size_t x) { return _properties[x]; };
@@ -197,7 +202,7 @@
     Element *popProperty()        { return _properties.front(); };
     size_t propertySize()         { return _properties.size(); };
     amf::Buffer *encode();
-    
+    std::vector<Element *> getProperties() { return _properties; };
     void dump();
 private:
     void check_buffer(size_t size);

Index: libamf/sol.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/sol.cpp,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -b -r1.36 -r1.37
--- libamf/sol.cpp      3 May 2008 18:44:06 -0000       1.36
+++ libamf/sol.cpp      16 May 2008 03:46:22 -0000      1.37
@@ -394,14 +394,15 @@
            ptr += 4;
            
            AMF amf_obj;
-           int size = 0;
            amf::Element *el;
-           while ( size < static_cast<boost::uint16_t>(bodysize) - 24 ) {
+           while ( ptr < tooFar) {
                if (ptr) {
                    el = amf_obj.extractProperty(ptr, tooFar);
                    if (el != 0) {
-                       size += amf_obj.totalsize();
-                       ptr += amf_obj.totalsize();
+                       // Unlike RTMP, SOL files tack an extra
+                       // zero byte after every property, so we
+                       // want to skip past this one too.
+                       ptr += amf_obj.totalsize() + 1;
                        _amfobjs.push_back(el);
                    } else {
                        break;
@@ -446,15 +447,16 @@
         }
         if (el->getType() == Element::NUMBER_AMF0) {
             double ddd = *((double *)el->getData());
+           swapBytes(&ddd, sizeof(double));
              cerr << ddd << " ";
 
             cerr << "( " << hexify(el->getData(), 8, false) << ")";
         }
-        if ((*(it))->getType() == Element::BOOLEAN_AMF0) {
-            if (el[0] == true) {
+        if (el->getType() == Element::BOOLEAN_AMF0) {
+            if (el->to_bool() == true) {
                 cerr << "true";
             }
-            if (el[0] == false) {
+            if (el->to_bool() == false) {
                 cerr << "false";
             }
         }

Index: libamf/sol.h
===================================================================
RCS file: /sources/gnash/gnash/libamf/sol.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- libamf/sol.h        30 Apr 2008 03:35:31 -0000      1.13
+++ libamf/sol.h        16 May 2008 03:46:23 -0000      1.14
@@ -77,10 +77,7 @@
     void addObj(amf::Element *x);
 
     /// Return a reference to the elements in this object
-    std::vector<amf::Element *>& getElements()
-    {
-        return _amfobjs;
-    }
+    std::vector<amf::Element *>& getElements() { return _amfobjs; }
 
     /// Get an element by index
     //

Index: libnet/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libnet/Makefile.am,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libnet/Makefile.am  1 Apr 2008 22:20:36 -0000       1.4
+++ libnet/Makefile.am  16 May 2008 03:46:24 -0000      1.5
@@ -54,6 +54,8 @@
        network.h \
        netstats.h \
        rtmp.h \
+       rtmp_msg.h \
+       rtmp_client.h \
        rtmp_server.h \
        statistics.h
 
@@ -65,6 +67,8 @@
        network.cpp \
        netstats.cpp \
        rtmp.cpp \
+       rtmp_msg.cpp \
+       rtmp_client.cpp \
        rtmp_server.cpp \
        statistics.cpp
 

Index: libnet/handler.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/handler.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- libnet/handler.cpp  3 May 2008 18:44:08 -0000       1.6
+++ libnet/handler.cpp  16 May 2008 03:46:24 -0000      1.7
@@ -220,7 +220,7 @@
        }
        // ret is "no position" when the socket is closed from the other end of 
the connection,
        // so we're done.
-       if ((ret == string::npos) || (ret == -1)) {
+       if ((ret == string::npos) || (ret == 0xffffffff)) {
            log_debug("socket for fd #%d was closed...", args->netfd);
            break;
        }

Index: libnet/http.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/http.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- libnet/http.cpp     30 Apr 2008 03:48:52 -0000      1.9
+++ libnet/http.cpp     16 May 2008 03:46:25 -0000      1.10
@@ -173,7 +173,7 @@
 
 
 bool
-HTTP::formatHeader(int filesize, http_status_e type)
+HTTP::formatHeader(int filesize, http_status_e /* type */)
 {
 //    GNASH_REPORT_FUNCTION;
 
@@ -389,6 +389,7 @@
 HTTP::formatLastModified(const string &date)
 {
     _header << "Last-Modified: " << date << "\r\n";
+    return true;
 }
 
 bool
@@ -473,7 +474,7 @@
 }
 
 bool
-HTTP::sendPostReply(rtmpt_cmd_e code)
+HTTP::sendPostReply(rtmpt_cmd_e /* code */)
 {
     GNASH_REPORT_FUNCTION;
 
@@ -660,7 +661,7 @@
     // force the case to make comparisons easier
 //     std::transform(body.begin(), body.end(), body.begin(), 
 //                (int(*)(int)) toupper);
-    string::size_type start, end;
+    string::size_type start; 
 
     // Extract the command
     start = body.find("GET", 0);
@@ -705,7 +706,7 @@
 //    GNASH_REPORT_FUNCTION;
     
     string body = reinterpret_cast<const char *>(data);
-    string::size_type start, end, length, pos;
+    string::size_type start, end;
     string pattern = "Accept-Ranges: ";
     start = body.find(pattern, 0);
     if (start == string::npos) {
@@ -1190,7 +1191,6 @@
 httphandler(Handler::thread_params_t *args)
 {
     GNASH_REPORT_FUNCTION;
-    int retries = 10;
 //    struct thread_params thread_data;
     string url, filespec, parameters;
     string::size_type pos;
@@ -1216,7 +1216,8 @@
            log_debug("Not waiting no more, no more for more HTTP data for fd 
#%d...", args->netfd);
            map<int, Handler *>::iterator hit = handlers.find(args->netfd);
            if ((*hit).second) {
-               log_debug("Removing handle %x for HTTP on fd #%d", (void 
*)hand), args->netfd;
+               log_debug("Removing handle %x for HTTP on fd #%d",
+                         (void *)hand, args->netfd);
                handlers.erase(args->netfd);
                delete (*hit).second;
            }
@@ -1266,7 +1267,8 @@
            log_debug (_("File to load is: %s"), filespec.c_str());
            log_debug (_("Parameters are: %s"), parameters.c_str());
            struct stat st;
-           int filefd, ret;
+           int filefd;
+           size_t ret;
 #ifdef USE_STATISTICS
            struct timespec start;
            clock_gettime (CLOCK_REALTIME, &start);

Index: libnet/rtmp.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- libnet/rtmp.cpp     3 May 2008 18:44:08 -0000       1.10
+++ libnet/rtmp.cpp     16 May 2008 03:46:25 -0000      1.11
@@ -154,91 +154,15 @@
            return el;
        }
     }
+    return 0;
 }
 
-// A request for a handshake is initiated by sending a byte with a
-// value of 0x3, followed by a message body of unknown format.
-bool
-RTMP::handShakeRequest()
-{
-    GNASH_REPORT_FUNCTION;
-
-#if 0
-    char buffer[RTMP_BODY_SIZE+1];
-    char c = 0x3;
-    int  i, ret;
-    
-    ret = writeNet(&c, 1);
-    _outbytes += 1;
-    // something went wrong, chances are the other end of the network
-    // connection is down, or never initialized.
-    if (ret <= 0) {
-        return false;
-    }
-
-    // Since we don't know what the format is, create a pattern we can
-    // recognize if we stumble across it later on.
-    for (i=0; i<RTMP_BODY_SIZE; i++) {
-        buffer[i] = i^256;
-    }
-    
-    _outbytes += RTMP_BODY_SIZE;
-    ret = writeNet(buffer, RTMP_BODY_SIZE);
-#endif
-    
-    return true;
-}
-
-// The client finished the handshake process by sending the second
-// data block we get from the server as the response
-bool
-RTMP::clientFinish()
-{
-    GNASH_REPORT_FUNCTION;
-
-#if 0
-    char buffer[RTMP_BODY_SIZE+1];
-    memset(buffer, 0, RTMP_BODY_SIZE+1);
-
-    if (readNet(buffer, RTMP_BODY_SIZE) == RTMP_BODY_SIZE) {        
-        log_debug (_("Read first data block in handshake"));
-    } else {
-        log_error (_("Couldn't read first data block in handshake"));
-        return false;
-    }
-    _inbytes += RTMP_BODY_SIZE;
-    if (readNet(buffer, RTMP_BODY_SIZE) == RTMP_BODY_SIZE) {        
-        log_debug (_("Read second data block in handshake"));
-//         _body = new char(RTMP_BODY_SIZE+1);
-//         memcpy(_body, buffer, RTMP_BODY_SIZE);
-    } else {
-        log_error (_("Couldn't read second data block in handshake"));
-        return false;
-    }
-    _inbytes += RTMP_BODY_SIZE;
-
-    writeNet(buffer, RTMP_BODY_SIZE);
-    _outbytes += RTMP_BODY_SIZE;
-#endif
-    
-    return true;
-}
-
-bool
-RTMP::packetRequest()
-{
-    GNASH_REPORT_FUNCTION;
-    return false;
-}
-
-#if 0
-bool
-RTMP::packetSend(amf::Buffer * /* buf */)
+RTMP::rtmp_head_t *
+RTMP::decodeHeader(Buffer *buf)
 {
     GNASH_REPORT_FUNCTION;
-    return false;
+    return decodeHeader(buf->reference());
 }
-#endif
 
 RTMP::rtmp_head_t *
 RTMP::decodeHeader(Network::byte_t *in)
@@ -251,12 +175,13 @@
     log_debug (_("The AMF channel index is %d"), _header.channel);
     
     _header.head_size = headerSize(*tmpptr++);
-    printf (_("The header size is %d"), _header.head_size);
+    log_debug (_("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);
     }
 
@@ -295,7 +220,7 @@
 //     };
     
     if (_header.head_size == 12) {
-        _header.src_dest = *(reinterpret_cast<rtmp_source_e *>(tmpptr));
+        _header.src_dest = *(reinterpret_cast<RTMPMsg::rtmp_source_e 
*>(tmpptr));
         tmpptr += sizeof(unsigned int);
         log_debug(_("The source/destination is: %x"), _header.src_dest);
     }
@@ -310,11 +235,26 @@
 /// * Type - The type of the message
 /// * Routing - The source/destination of the message
 //
+
+amf::Buffer *
+RTMP::encodeHeader(int amf_index, rtmp_headersize_e head_size)
+{
+    GNASH_REPORT_FUNCTION;
+    amf::Buffer *buf = new Buffer(1);
+    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;
+
+    return buf;
+}
+
 // 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)
+                      RTMPMsg::rtmp_source_e routing)
 {
     GNASH_REPORT_FUNCTION;
 
@@ -390,7 +330,7 @@
     GNASH_REPORT_FUNCTION;
 
 //    int packetsize = 0;
-    unsigned int amf_index, headersize;
+    size_t amf_index, headersize;
     Network::byte_t *ptr = buf->reference();
     Network::byte_t *tooFar = ptr+buf->size();
     AMF amf;
@@ -423,15 +363,15 @@
 //    ptr += headersize;
     
     amf::Element *el = amf.extractAMF(ptr, tooFar);
-    el->dump();
+//    el->dump();
     el = amf.extractAMF(ptr, tooFar) + 1; // @@strk@@ : what's the +1 for ?
-    el->dump();
+//    el->dump();
     log_debug (_("Reading AMF packets till we're done..."));
-    buf->dump();
+//    buf->dump();
     while (ptr < end) {
        amf::Element *el = amf.extractProperty(ptr, tooFar);
        addProperty(el);
-       el->dump();
+//     el->dump();
     }
     ptr += 1;
     size_t actual_size = static_cast<size_t>(_header.bodysize - 
AMF_HEADER_SIZE);
@@ -441,13 +381,13 @@
        log_debug("FIXME: MERGING");
        buf = _handler->merge(buf);
     }
-    while ((ptr - buf->begin()) < actual_size) {
+    while ((ptr - buf->begin()) < static_cast<int>(actual_size)) {
        amf::Element *el = amf.extractProperty(ptr, tooFar);
        addProperty(el);
-       el->dump();             // FIXME: dump the AMF objects as they are read 
in
+//     el->dump();             // FIXME: dump the AMF objects as they are read 
in
     }
 
-    dump();
+//    dump();
     
     amf::Element *url = getProperty("tcUrl");
     amf::Element *file = getProperty("swfUrl");
@@ -494,75 +434,12 @@
 // 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;
-}
     
-amf::Buffer *
-RTMP::encodeBytesRead()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void
-RTMP::decodeBytesRead()
-{
-    GNASH_REPORT_FUNCTION;
-}
-
-// 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
+// A RTMP Ping packet looks like this: "02 00 00 00 00 00 06 04 00 00 00 00 00 
00 00 00 00 0",
+// 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;
-    };
-    
-    return buf;
-}
+// This seems to be a ping message, 12 byte header, system channel 2
+// 02 00 00 00 00 00 06 04 00 00 00 00 00 00 00 00 00 00
 RTMP::rtmp_ping_t *
 RTMP::decodePing(Network::byte_t *data)
 {
@@ -572,17 +449,22 @@
     rtmp_ping_t *ping = new rtmp_ping_t;
     memset(ping, 0, sizeof(rtmp_ping_t));
     
-    boost::uint16_t type = *reinterpret_cast<rtmp_ping_e *>(ptr);
+    // All the data fields in a ping message are 2 bytes long.
+    boost::uint16_t type = ntohs(*reinterpret_cast<rtmp_ping_e *>(ptr));
     ping->type = static_cast<rtmp_ping_e>(type);
     ptr += sizeof(boost::uint16_t);
 
-    ping->target = *reinterpret_cast<boost::uint16_t *>(ptr);
+    ping->target = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
     ptr += sizeof(boost::uint16_t);
     
     ping->param1 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
     ptr += sizeof(boost::uint16_t);
     
-    ping->param1 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
+//     ping->param2 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
+//     ptr += sizeof(boost::uint16_t);
+
+//    ping->param3 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
+    ping->param3 = 0;
 
     return ping;    
 }
@@ -593,81 +475,246 @@
     return decodePing(buf->reference());
 }
 
+// Decode the result we get from the server after we've made a request.
+//
+// 03 00 00 00 00 00 81 14 00 00 00 00 02 00 07 5f  ..............._
+// 72 65 73 75 6c 74 00 3f f0 00 00 00 00 00 00 05  result.?........
+// 03 00 0b 61 70 70 6c 69 63 61 74 69 6f 6e 05 00  ...application..
+// 05 6c 65 76 65 6c 02 00 06 73 74 61 74 75 73 00  .level...status.
+// 0b 64 65 73 63 72 69 70 74 69 6f 6e 02 00 15 43  .description...C
+// 6f 6e 6e 65 63 74 69 6f 6e 20 73 75 63 63 65 65  onnection succee
+// 64 65 64 2e 00 04 63 6f 64 65 02 00 1d 4e 65 74  ded...code...Net
+// 43 6f 6e 6e 65 63 74 69 6f 6e 2e 43 6f 6e 6e 65  Connection.Conne
+// 63 74 2e 53 75 63 63 65 73 73 00 00 c3 09        ct.Success....
+//
+// 43 00 00 00 00 00 48 14 02 00 06 5f 65 72 72 6f  C.....H...._erro
+// 72 00 40 00 00 00 00 00 00 00 05 03 00 04 63 6f  address@hidden
+// 64 65 02 00 19 4e 65 74 43 6f 6e 6e 65 63 74 69  de...NetConnecti
+// 6f 6e 2e 43 61 6c 6c 2e 46 61 69 6c 65 64 00 05  on.Call.Failed..
+// 6c 65 76 65 6c 02 00 05 65 72 72 6f 72 00 00 09  level...error...
+//
+// T 127.0.0.1:1935 -> 127.0.0.1:38167 [AP]
+// 44 00 00 00 00 00 b2 14 02 00 08 6f 6e 53 74 61  D..........onSta
+// 74 75 73 00 3f f0 00 00 00 00 00 00 05 03 00 08  tus.?...........
+// 63 6c 69 65 6e 74 69 64 00 3f f0 00 00 00 00 00  clientid.?......
+// 00 00 05 6c 65 76 65 6c 02 00 06 73 74 61 74 75  ...level...statu
+// 73 00 07 64 65 74 61 69 6c 73 02 00 16 6f 6e 32  s..details...on2
+// 5f 66 6c 61 73 68 38 5f 77 5f 61 75 64 69 6f 2e  _flash8_w_audio.
+// 66 6c 76 00 0b 64 65 73 63 72 69 70 74 69 6f 6e  flv..description
+// 02 00 27 53 74 61 72 74 65 64 20 70 6c 61 79 69  ..'Started playi
+// 6e 67 20 6f 6e 32 5f 66 c4 6c 61 73 68 38 5f 77  ng on2_f.lash8_w
+// 5f 61 75 64 69 6f 2e 66 6c 76 2e 00 04 63 6f 64  _audio.flv...cod
+// 65 02 00 14 4e 65 74 53 74 72 65 61 6d 2e 50 6c  e...NetStream.Pl
+// 61 79 2e 53 74 61 72 74 00 00 09                 ay.Start...
+//
+// 
^^^_result^?^^^^^^^^^^^application^^^level^^^status^^description^^^Connection 
succeeded.^^code^^^NetConnection.Connect.Success^^^^
+// 02 00 07 5f 72 65 73 75 6c 74 00 3f f0 00 00 00 00 00 00 05 03 00 0b 61 70 
70 6c 69 63 61 74 69 6f 6e 05 00 05 6c 65 76 65 6c 02 00 06 73 74 61 74 75 73 
00 0b 64 65 73 63 72 69 70 74 69 6f 6e 02 00 15 43 6f 6e 6e 65 63 74 69 6f 6e 
20 73 75 63 63 65 65 64 65 64 2e 00 04 63 6f 64 65 02 00 1d 4e 65 74 43 6f 6e 
6e 65 63 74 69 6f 6e 2e 43 6f 6e 6e 65 63 74 2e 53 75 63 63 65 73 73 00 00 c3 
09 
+// 10629:3086592224] 20:01:20 DEBUG: read 29 bytes from fd 3 from port 0
+// address@hidden
+// 43 00 00 00 00 00 15 14 02 00 08 6f 6e 42 57 44 6f 6e 65 00 40 00 00 00 00 
00 00 00 05
+RTMPMsg *
+RTMP::decodeMsgBody(Network::byte_t *data, size_t size)
+{
+    GNASH_REPORT_FUNCTION;
+    AMF amf_obj;
+    Network::byte_t *ptr = data;
+    Network::byte_t* tooFar = ptr + size;
+    bool status = false;
+
+    // The first data object is the method name of this object.
+    Element *name = amf_obj.extractAMF(ptr, tooFar);
+    if (name) {
+       ptr += name->getLength() + 3; // skip the length bytes too
+    } else {
+       log_error("Name field of RTMP Message corrupted!");
+       return 0;
+    }
+
+    // The stream ID is the second data object. All messages have these two 
objects
+    // at the minimum.
+    Element *streamid = amf_obj.extractAMF(ptr, tooFar);
+    if (streamid) {
+       ptr += streamid->getLength() + 2;
+    } else {
+       log_error("Stream ID field of RTMP Message corrupted!");
+       return 0;
+    }
+
+    // This will need to be deleted manually later after usage, it is not
+    // automatically deallocated.
+    RTMPMsg *msg = new RTMPMsg;
+
+    msg->setMethodName(name->to_string());
+    double swapped = streamid->to_number();
+    swapBytes(&swapped, amf::AMF0_NUMBER_SIZE);
+    msg->setStreamID(swapped);
+
+    if ((msg->getMethodName() == "_result") || (msg->getMethodName() == 
"error")) {
+       status = true;
+    }
+    
+    // Then there are a series of AMF objects, often a higher level 
ActionScript object with
+    // properties attached.
+    while (ptr < tooFar) {
+       // These pointers get deleted automatically when the msg object is 
deleted
+        amf::Element *el = amf_obj.extractAMF(ptr, tooFar);
+        if (el == 0) {
+           break;
+       }
+//     el->dump();
+       msg->addObject(el);
+       if (status) {
+           msg->checkStatus(el);
+       }
+       ptr += amf_obj.totalsize();
+    };
+    
+    // cleanup after ourselves
+    delete name;
+    delete streamid;
+    
+    return msg;
+}
+
+RTMPMsg *
+RTMP::decodeMsgBody(amf::Buffer *buf)
+{
+//    GNASH_REPORT_FUNCTION;
+    return decodeMsgBody(buf->reference(), buf->size());
+}
+
+amf::Buffer *
+RTMP::encodeChunkSize()
+{
+    GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
+}
+
+void
+RTMP::decodeChunkSize()
+{
+    GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+}
+    
+amf::Buffer *
+RTMP::encodeBytesRead()
+{
+    GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
+}
+
+void
+RTMP::decodeBytesRead()
+{
+    GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+}
+
 amf::Buffer *
 RTMP::encodeServer()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
 }
+
 void 
 RTMP::decodeServer()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
 }
     
 amf::Buffer *
 RTMP::encodeClient()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
 }
+
 void 
 RTMP::decodeClient()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
 }
     
 amf::Buffer *
 RTMP::encodeAudioData()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
 }
+
 void 
 RTMP::decodeAudioData()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
 }
     
 amf::Buffer *
 RTMP::encodeVideoData()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
 }
+
 void 
 RTMP::decodeVideoData()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
 }
     
 amf::Buffer *
 RTMP::encodeNotify()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
 }
+
 void 
 RTMP::decodeNotify()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
 }
     
 amf::Buffer *
 RTMP::encodeSharedObj()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
 }
+
 void 
 RTMP::decodeSharedObj()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
 }
     
 amf::Buffer *
 RTMP::encodeInvoke()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
 }
 void 
 RTMP::decodeInvoke()
 {
     GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
 }
 
 } // end of gnash namespace

Index: libnet/rtmp.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- libnet/rtmp.h       3 May 2008 18:44:08 -0000       1.8
+++ libnet/rtmp.h       16 May 2008 03:46:26 -0000      1.9
@@ -20,14 +20,14 @@
 
 #include <boost/cstdint.hpp>
 #include <string>
-#include <map>
+#include <vector>
 
 #include "amf.h"
 #include "element.h"
 #include "handler.h"
 #include "network.h"
 #include "buffer.h"
-#include "amfutf8.h"
+#include "rtmp_msg.h"
 
 namespace gnash
 {
@@ -41,6 +41,7 @@
 const int  RTMP_VIDEO_PACKET_SIZE = 128;
 const int  RTMP_AUDIO_PACKET_SIZE = 64;
 const int  RTMP_MAX_HEADER_SIZE = 12;
+const int  PING_MSG_SIZE = 6;
 
 // For terminating sequences, a byte with value 0x09 is used.
 const char TERMINATOR = 0x09;
@@ -73,14 +74,22 @@
 class DSOEXPORT RTMP
 {
 public:
+    typedef enum {
+       RAW=0x0,
+       ADPCM=0x01,
+       MP3=0x02,
+       NELLYMOSER_8khz=0x05,
+       NEYYNOSER=0x6
+    } audiocodecs_e;
+    typedef enum {
+       H263=0x2,
+       SCREEN0x3,
+       VP6=0x4
+    } videocodecs_e;
     // The second byte of the AMF file/stream is appears to be 0x00 if the
     // client is the Flash Player and 0x01 if the client is the FlashCom
     // server.
     typedef enum {
-       FROM_CLIENT,                     // Flash player
-       FROM_SERVER                      // Flash com server
-    } rtmp_source_e;
-    typedef enum {
         NONE = 0x0,
         CHUNK_SIZE = 0x1,
         UNKNOWN = 0x2,
@@ -119,9 +128,10 @@
     } 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 target; // all Ping message data fields
+       boost::uint16_t param1; // are 2 bytes long
        boost::uint16_t param2;
+       boost::uint16_t param3;
     } rtmp_ping_t;
     typedef enum {
         RTMP_STATE_HANDSHAKE_SEND,
@@ -133,6 +143,12 @@
         RTMP_STATE_HEADER,
         RTMP_STATE_DONE
     } rtmp_state_t;
+//     typedef struct {
+//     rtmp_status_e status;
+//     std::string   method;
+//     double        streamid;
+//     std::vector<amf::Element *> objs;
+//     } rtmp_msg_t;
     typedef enum {
         RTMP_ERR_UNDEF=0,
         RTMP_ERR_NOTFOUND,
@@ -156,7 +172,7 @@
        int             channel;
        int             head_size;
        int             bodysize;
-       rtmp_source_e   src_dest;
+       RTMPMsg::rtmp_source_e   src_dest;
        content_types_e type;
     } rtmp_head_t;
     typedef enum {
@@ -172,25 +188,23 @@
 // * UTF String - Response
 // * Long - Body length in bytes
 // * Variable - Actual data (including a type code)
-    typedef struct {
-        amf::amfutf8_t target;
-        amf::amfutf8_t response;
-       boost::uint32_t length;
-        void *data;
-    } rtmp_body_t;
+//     typedef struct {
+//         amf::amfutf8_t target;
+//         amf::amfutf8_t response;
+//     boost::uint32_t length;
+//         void *data;
+//     } rtmp_body_t;
     
     RTMP();
-    ~RTMP();
+    virtual ~RTMP();
 
     // 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);
+                             size_t total_size, content_types_e type, 
RTMPMsg::rtmp_source_e routing);
+    amf::Buffer *encodeHeader(int amf_index, rtmp_headersize_e head_size);
     
-    bool handShakeRequest();
-    bool clientFinish();
-    bool packetRequest();
     bool packetSend(amf::Buffer *buf);
     bool packetRead(amf::Buffer *buf);
 
@@ -204,22 +218,24 @@
     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; };
+    RTMPMsg::rtmp_source_e getRouting()  { return _header.src_dest; };
     int getChannel()            { return _header.channel; };
     int getPacketSize()         { return _packet_size; };
     int getMysteryWord()        { return _mystery_word; };
 
+    // Decode the an RTMP message
+    RTMPMsg *decodeMsgBody(Network::byte_t *data, size_t size);
+    RTMPMsg *decodeMsgBody(amf::Buffer *buf);
+    
+    virtual rtmp_ping_t *decodePing(Network::byte_t *data);
+    rtmp_ping_t *decodePing(amf::Buffer *buf);
+    
     // 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();
     

Index: libnet/rtmp_server.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_server.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- libnet/rtmp_server.cpp      3 May 2008 18:44:08 -0000       1.5
+++ libnet/rtmp_server.cpp      16 May 2008 03:46:32 -0000      1.6
@@ -24,6 +24,7 @@
 #include <iostream>
 #include <string>
 #include <map>
+#include <boost/cstdint.hpp>
 
 #if ! (defined(_WIN32) || defined(WIN32))
 #      include <netinet/in.h>
@@ -92,7 +93,7 @@
 //     secret = _handler->merge(buf->reference());
 //     }
 
-    if (buf->size() >= RTMP_BODY_SIZE) {
+    if (buf->size() >= static_cast<size_t>(RTMP_BODY_SIZE)) {
        _handshake = new amf::Buffer(RTMP_BODY_SIZE);
        _handshake->copy(buf->reference() + 1, RTMP_BODY_SIZE);
        log_debug (_("Handshake Data matched"));
@@ -149,7 +150,7 @@
     // The first data packet is often buried in with the end of the handshake.
     // So after the handshake block, we strip that part off, and just pass on
     // the remainder for processing.
-    if (buf->size() > RTMP_BODY_SIZE) {
+    if (buf->size() >= static_cast<size_t>(RTMP_BODY_SIZE)) {
        size_t size = buf->size() - RTMP_BODY_SIZE;  
        obj = new amf::Buffer[size];
        obj->copy(buf->begin()+RTMP_BODY_SIZE, size);
@@ -184,8 +185,6 @@
 {
     GNASH_REPORT_FUNCTION;
 
-    int ret;
-    int packetsize = 0;
     unsigned int amf_index, headersize;
     Network::byte_t *ptr = buf->reference();
     AMF amf;
@@ -206,14 +205,14 @@
 //         }
 //     }
 
-#if 1
-    Network::byte_t *end = buf->remove(0xc3);
-#else
-    Network::byte_t *end = buf->find(0xc3);
-    log_debug("END is %x", (void *)end);
-    *end = '*';
-#endif
-    rtmp_head_t *head = decodeHeader(ptr);
+// #if 1
+//     Network::byte_t *end = buf->remove(0xc3);
+// #else
+//     Network::byte_t *end = buf->find(0xc3);
+//     log_debug("END is %x", (void *)end);
+//     *end = '*';
+// #endif
+    decodeHeader(ptr);
     ptr += headersize;
 
     Network::byte_t* tooFar = ptr+300+sizeof(int); // FIXME:
@@ -241,6 +240,9 @@
        }
     }
 
+    delete el1;
+    delete el2;
+    
 # if 0
     Element el;
     ptr = amf.extractElement(&el, ptr);
@@ -348,107 +350,160 @@
     return true;
 }
 
-#if 0
-// These process the incoming AMF object types from the data stream
+// A result packet looks like this:
+// 
+// 03 00 00 00 00 00 81 14 00 00 00 00 02 00 07 5f   ..............._
+// 72 65 73 75 6c 74 00 3f f0 00 00 00 00 00 00 05   result.?........
+// 03 00 0b 61 70 70 6c 69 63 61 74 69 6f 6e 05 00   ...application..
+// 05 6c 65 76 65 6c 02 00 06 73 74 61 74 75 73 00   .level...status.
+// 0b 64 65 73 63 72 69 70 74 69 6f 6e 02 00 15 43   .description...C
+// 6f 6e 6e 65 63 74 69 6f 6e 20 73 75 63 63 65 65   onnection succee
+// 64 65 64 2e 00 04 63 6f 64 65 02 00 1d 4e 65 74   ded...code...Net
+// 43 6f 6e 6e 65 63 74 69 6f 6e 2e 43 6f 6e 6e 65   Connection.Conne
+// 63 74 2e 53 75 63 63 65 73 73 00 00 c3 09         ct.Success....
+//
+// _result(double ClientStream, NULL, double ServerStream)
+// These are handlers for the various types
 amf::Buffer *
-RTMPServer::encodeChunkSize()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void 
-RTMPServer::decodeChunkSize()
+RTMPServer::encodeResult(RTMPMsg::rtmp_status_e status)
 {
     GNASH_REPORT_FUNCTION;
-}
     
-amf::Buffer *
-RTMPServer::encodeBytesRead()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void 
-RTMPServer::decodeBytesRead()
-{
-    GNASH_REPORT_FUNCTION;
-}
-
-amf::Buffer *
-RTMPServer::encodeServer()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void
-RTMPServer::decodeServer()
-{
-    GNASH_REPORT_FUNCTION;
-}
-    
-amf::Buffer *
-RTMPServer::encodeClient()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void 
-RTMPServer::decodeClient()
-{
-    GNASH_REPORT_FUNCTION;
-}
-    
-amf::Buffer *
-RTMPServer::encodeAudioData()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void 
-RTMPServer::decodeAudioData()
-{
-    GNASH_REPORT_FUNCTION;
-}
-    
-amf::Buffer *
-RTMPServer::encodeVideoData()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void 
-RTMPServer::decodeVideoData()
-{
-    GNASH_REPORT_FUNCTION;
-}
-    
-amf::Buffer *
-RTMPServer::encodeNotify()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void
-RTMPServer::decodeNotify()
-{
-    GNASH_REPORT_FUNCTION;
-}
+//    Buffer *buf = new Buffer;
+//     Network::byte_t *ptr = buf->reference();
+//     buf->clear();           // default everything to zeros, real data gets 
optionally added.
+//    ptr += sizeof(boost::uint16_t); // go past the first short
+//     const char *capabilities = 0;
+//     const char *description = 0;
+//     const char *code = 0;
+//     const char *status = 0;
+
+    Element *str = new Element;
+    str->makeString("_result");
+
+    Element *number = new Element;
+    // add The server ID
+    number->makeNumber(1);     // FIXME: needs a real value, which should 
increment
+
+    Element top;
+    top.makeObject("application");
+    
+    switch (status) {
+      case RTMPMsg::APP_GC:
+      case RTMPMsg::APP_RESOURCE_LOWMEMORY:
+      case RTMPMsg::APP_SCRIPT_ERROR:
+      case RTMPMsg::APP_SCRIPT_WARNING:
+      case RTMPMsg::APP_SHUTDOWN:
+      case RTMPMsg::NC_CALL_BADVERSION:
+      case RTMPMsg::NC_CALL_FAILED:
+//       status = 0;
+//       code = "NetConnection.Call.Failed";
+      case RTMPMsg::NC_CONNECT_APPSHUTDOWN:
+      case RTMPMsg::NC_CONNECT_CLOSED:
+      case RTMPMsg::NC_CONNECT_FAILED:
+      {
+//       errstr = new Element;
+//       errstr->makeString("error");
+         Element *level = new Element;
+         level->makeString("level", "error");
+         top.addProperty(level);
+
+         Element *description = new Element;
+         description->makeString("description", "Connection Failed.");
+         top.addProperty(description);
+         
+         Element *code = new Element;
+         code->makeString("code", "Connection.Connect.Failed");
+         top.addProperty(code);
+      }
+      case RTMPMsg::NC_CONNECT_INVALID_APPLICATION:
+      case RTMPMsg::NC_CONNECT_REJECTED:
+      {
+//       delete str;
+//       str = new Element;
+//       str->makeString("error");
+         Element *level = new Element;
+         level->makeString("level", "error");
+         top.addProperty(level);
+
+         Element *description = new Element;
+         description->makeString("description", "Connection Rejected.");
+         top.addProperty(description);
+         
+         Element *code = new Element;
+         code->makeString("code", "NetConnection.Connect.Rejected");
+         top.addProperty(code);
+      }
+      case RTMPMsg::NC_CONNECT_SUCCESS:
+      {
+         Element *level = new Element;
+         level->makeString("level", "status");
+         top.addProperty(level);
+
+         Element *description = new Element;
+         description->makeString("description", "Connection succeeded.");
+         top.addProperty(description);
+         
+         Element *code = new Element;
+         code->makeString("code", "NetConnection.Connect.Success");
+         top.addProperty(code);
+      }
+      break;
+      case RTMPMsg::NS_CLEAR_FAILED:
+      case RTMPMsg::NS_CLEAR_SUCCESS:
+      case RTMPMsg::NS_DATA_START:
+      case RTMPMsg::NS_FAILED:
+      case RTMPMsg::NS_INVALID_ARGUMENT:
+      case RTMPMsg::NS_PAUSE_NOTIFY:
+      case RTMPMsg::NS_PLAY_COMPLETE:
+      case RTMPMsg::NS_PLAY_FAILED:
+      case RTMPMsg::NS_PLAY_FILE_STRUCTURE_INVALID:
+      case RTMPMsg::NS_PLAY_INSUFFICIENT_BW:
+      case RTMPMsg::NS_PLAY_NO_SUPPORTED_TRACK_FOUND:
+      case RTMPMsg::NS_PLAY_PUBLISHNOTIFY:
+      case RTMPMsg::NS_PLAY_RESET:
+      case RTMPMsg::NS_PLAY_START:
+      case RTMPMsg::NS_PLAY_STOP:
+      case RTMPMsg::NS_PLAY_STREAMNOTFOUND:
+      case RTMPMsg::NS_PLAY_SWITCH:
+      case RTMPMsg::NS_PLAY_UNPUBLISHNOTIFY:
+      case RTMPMsg::NS_PUBLISH_BADNAME:
+      case RTMPMsg::NS_PUBLISH_START:
+      case RTMPMsg::NS_RECORD_FAILED:
+      case RTMPMsg::NS_RECORD_NOACCESS:
+      case RTMPMsg::NS_RECORD_START:
+      case RTMPMsg::NS_RECORD_STOP:
+      case RTMPMsg::NS_SEEK_FAILED:
+      case RTMPMsg::NS_SEEK_NOTIFY:
+      case RTMPMsg::NS_UNPAUSE_NOTIFY:
+      case RTMPMsg::NS_UNPUBLISHED_SUCCESS:
+      case RTMPMsg::SO_CREATION_FAILED:
+      case RTMPMsg::SO_NO_READ_ACCESS:
+      case RTMPMsg::SO_NO_WRITE_ACCESS:
+      case RTMPMsg::SO_PERSISTENCE_MISMATCH:
+      default:
+         break;
+    };
     
-amf::Buffer *
-RTMPServer::encodeSharedObj()
-{
-    GNASH_REPORT_FUNCTION;
-}
-void 
-RTMPServer::decodeSharedObj()
-{
-    GNASH_REPORT_FUNCTION;
-}
+    Buffer *strbuf = str->encode();
+    Buffer *numbuf = number->encode();
+    Buffer *topbuf = top.encode();
+
+    Buffer *buf = new Buffer(strbuf->size() + numbuf->size() + topbuf->size());
+    buf->append(strbuf);
+    buf->append(numbuf);
+    Network::byte_t byte = static_cast<Network::byte_t>(RTMP::SERVER & 
0x000000ff);
+    buf->append(byte);
+    buf->append(topbuf);
+
+    delete str;
+    delete number;
+    delete strbuf;
+    delete numbuf;
+//    delete topbuf;//   FIXME: deleting this shouldn't core dump.
     
-amf::Buffer *
-RTMPServer::encodeInvoke()
-{
-    GNASH_REPORT_FUNCTION;
+    return buf;
 }
-void 
-RTMPServer::decodeInvoke()
-{
-    GNASH_REPORT_FUNCTION;
-}
-#endif
 
 // This is the thread for all incoming RTMP connections
 void
@@ -534,6 +589,78 @@
     }
 }    
 
+// 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.
+
+// A RTMP Ping packet looks like this: "02 00 00 00 00 00 06 04 00 00 00 00 00 
00 00 00 00 0",
+// which is the Ping type byte, followed by two shorts that are the 
parameters. Only the first
+// two paramters are required.
+amf::Buffer *
+RTMPServer::encodePing(rtmp_ping_e type)
+{
+    GNASH_REPORT_FUNCTION;
+    return encodePing(type, 0);
+}
+
+amf::Buffer *
+RTMPServer::encodePing(rtmp_ping_e type, boost::uint32_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::uint32_t swapped = 0;
+    swapBytes(&typefield, sizeof(boost::uint16_t));
+    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 = htonl(milliseconds);
+         buf->append(htonl(milliseconds));
+         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 = htonl(milliseconds);
+         buf->append(htonl(milliseconds));
+         break;
+      }
+      default:
+         return 0;
+         break;
+    };
+    
+    return buf;
+}
+
 } // end of gnash namespace
 
 // local Variables:

Index: libnet/rtmp_server.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_server.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- libnet/rtmp_server.h        3 May 2008 18:44:08 -0000       1.3
+++ libnet/rtmp_server.h        16 May 2008 03:46:34 -0000      1.4
@@ -43,34 +43,9 @@
     bool packetRead(amf::Buffer *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
+    amf::Buffer *encodeResult(RTMPMsg::rtmp_status_e status);
+    amf::Buffer *encodePing(rtmp_ping_e type, boost::uint32_t milliseconds);
+    amf::Buffer *encodePing(rtmp_ping_e type);
     
     void dump();
   private:

Index: testsuite/libamf.all/test_sol.cpp
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libamf.all/test_sol.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- testsuite/libamf.all/test_sol.cpp   30 Apr 2008 03:35:31 -0000      1.13
+++ testsuite/libamf.all/test_sol.cpp   16 May 2008 03:46:34 -0000      1.14
@@ -187,6 +187,8 @@
     GNASH_REPORT_FUNCTION;
     struct stat st;
 
+    Buffer *hex1 = hex2mem("00 bf 00 00 01 28 54 43 53 4f 00 04 00 00 00 00 00 
08 73 65 74 74 69 6e 67 73 00 00 00 00 00 04 67 61 69 6e 00 40 49 00 00 00 00 
00 00 00 00 0f 65 63 68 6f 73 75 70 70 72 65 73 73 69 6f 6e 01 00 00 00 11 64 
65 66 61 75 6c 74 6d 69 63 72 6f 70 68 6f 6e 65 02 00 0e 2f 64 65 76 2f 69 6e 
70 75 74 2f 6d 69 63 00 00 0d 64 65 66 61 75 6c 74 63 61 6d 65 72 61 02 00 00 
00 00 0d 64 65 66 61 75 6c 74 6b 6c 69 6d 69 74 00 40 59 00 00 00 00 00 00 00 
00 0d 64 65 66 61 75 6c 74 61 6c 77 61 79 73 01 00 00 00 10 63 72 6f 73 73 64 
6f 6d 61 69 6e 41 6c 6c 6f 77 01 01 00 00 11 63 72 6f 73 73 64 6f 6d 61 69 6e 
41 6c 77 61 79 73 01 01 00 00 18 61 6c 6c 6f 77 54 68 69 72 64 50 61 72 74 79 
4c 53 4f 41 63 63 65 73 73 01 01 00 00 0c 74 72 75 73 74 65 64 50 61 74 68 73 
03 00 00 09 00 00 0c 6c 6f 63 61 6c 53 65 63 50 61 74 68 02 00 00 00 00 10 6c 
6f 63 61 6c 53 65 63 50 61 74 68 54 69 6d 65 00 42 71 6d 14 10 22 e0 00 00");
+
     if (stat(filespec.c_str(), &st) == 0) {
         SOL sol;
         sol.readFile(filespec);

Index: testsuite/libnet.all/test_cque.cpp
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libnet.all/test_cque.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- testsuite/libnet.all/test_cque.cpp  7 Apr 2008 19:35:11 -0000       1.4
+++ testsuite/libnet.all/test_cque.cpp  16 May 2008 03:46:35 -0000      1.5
@@ -73,8 +73,8 @@
         ptr[i] = i+' ';
     }
 
-    boost::uint8_t *test = new uint8_t[6];
-    memcpy(test, "hell", 4);
+//     boost::uint8_t *test = new uint8_t[6];
+//     memcpy(test, "hell", 4);
 
     // Push one buffer on the fifo. The default is the incoming fifo,
     // which is the one where data flows from the network to the queue.

Index: testsuite/libnet.all/test_handler.cpp
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libnet.all/test_handler.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- testsuite/libnet.all/test_handler.cpp       6 Apr 2008 18:11:33 -0000       
1.3
+++ testsuite/libnet.all/test_handler.cpp       16 May 2008 03:46:38 -0000      
1.4
@@ -66,8 +66,8 @@
     Handler que;
 
     Buffer buf;
-    boost::uint8_t *test = new uint8_t[6];
-    memcpy(test, "hell", 4);
+//     boost::uint8_t *test = new uint8_t[6];
+//     memcpy(test, "hell", 4);
 
     // Push one buffer on the fifo. The default is the incoming fifo,
     // which is the one where data flows from the network to the queue.

Index: testsuite/libnet.all/test_rtmp.cpp
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libnet.all/test_rtmp.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- testsuite/libnet.all/test_rtmp.cpp  3 May 2008 18:44:06 -0000       1.1
+++ testsuite/libnet.all/test_rtmp.cpp  16 May 2008 03:46:38 -0000      1.2
@@ -36,8 +36,9 @@
 #include "dejagnu.h"
 #include "log.h"
 #include "amf.h"
-#include "rtmp_server.h"
 #include "rtmp.h"
+#include "rtmp_client.h"
+#include "rtmp_server.h"
 #include "buffer.h"
 #include "network.h"
 #include "element.h"
@@ -65,6 +66,8 @@
 
 static void test_header();
 static void test_types();
+static void test_results();
+static void test_system();
 
 LogFile& dbglogfile = LogFile::getDefaultInstance();
 
@@ -96,7 +99,7 @@
 {
     size_t count = strlen(str);
     Network::byte_t ch = 0;
-    Buffer *buf = new Buffer(count + 12);
+    Buffer *buf = new Buffer((count/3)+1);
     buf->clear();
 
     Network::byte_t *ptr = const_cast<Network::byte_t 
*>(reinterpret_cast<const Network::byte_t *>(str));
@@ -168,68 +171,294 @@
 #endif
     
     test_header();
-    test_types();
+    test_system();
+    test_results();
+//    test_types();
+}
+
+void
+test_system()
+{
+    GNASH_REPORT_FUNCTION;
+    
+    RTMPClient client;
+    RTMPServer server;
+
+    
+//    const char *x1 = "00 00 00 00 00 00";
+    Buffer *buf1 = hex2mem("00 00 00 00 00 00");  // clear buffer message
+//    const char *x2 = "00 06 cf 03 04 c3";
+    Buffer *buf2 = hex2mem("00 06 cf 03 04 c3"); // ping client from server
+//    const char *x3 = "00 07 cf 03 04 c3";
+    Buffer *buf3 = hex2mem("00 07 cf 03 04 c3"); // Pong, reply from client
+//    const char *x4 = "00 00 00 00 00 01";
+    Buffer *buf4 = hex2mem("00 00 00 00 00 01"); // clear buffer message
+    
+    RTMP::rtmp_ping_t *ping1 = client.decodePing(buf1);
+    if (ping1->type == RTMP::PING_CLEAR) {
+        runtest.pass("Decoded RTMP Ping message");
+    } else {
+        runtest.fail("Decoded RTMP Ping message");
+    }
+    
+    Buffer *enc1 = server.encodePing(RTMP::PING_CLEAR);
+    if ((memcmp(buf1->reference(), enc1->reference(), 6) == 0)) {
+        runtest.pass("Encoded RTMP Ping Clear message");
+    } else {
+        runtest.fail("Encoded RTMP Ping Clear message");
+    }
+
+    boost::uint32_t time = *(reinterpret_cast<boost::uint32_t 
*>(buf2->reference() + 2));
+    Buffer *enc2 = server.encodePing(RTMP::PING_CLIENT, htonl(time));
+//    cerr << hexify(enc2->begin(), enc2->size(), false) << endl;
+    if ((memcmp(buf2->reference(), enc2->reference(), 6) == 0)) {
+        runtest.pass("Encoded RTMP Ping Client message");
+    } else {
+        runtest.fail("Encoded RTMP Ping Client message");
+    }
+
+    RTMP::rtmp_ping_t *ping2 = client.decodePing(buf2);
+    if ((ping2->type == RTMP::PING_CLIENT)
+        && (ping2->target == 0xcf03)
+        && (ping2->param1 == 0x4c3)) {
+        runtest.pass("Decoded RTMP Ping Client message");
+    } else {
+        runtest.fail("Decoded RTMP Ping Client message");
+    }    
+
+#if 0
+    for (double dub=0; dub<=200; dub ++) {
+        Element el11;
+        el11.makeNumber(dub);
+        Buffer *buf11 = el11.getBuffer();
+        cerr << "FIXME: " << el11.to_number() << ":     ";
+        swapBytes(buf11->begin(), 8);
+        cerr << hexify(buf11->begin(), buf11->size(), false) << endl;
+    }
+#endif
+    
+    // cleanup
+    delete ping1;
+    delete ping2;
+    delete buf1;
+    delete buf2;
+    delete buf3;
+    delete buf4;
+    
+    delete enc1;
+    delete enc2;
 }
 
 void
 test_header()
 {
     GNASH_REPORT_FUNCTION;
-    RTMP rtmp;
+    RTMPClient client;
+    RTMPServer server;
     
     // 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;
+//    const char *x1 = "03 00 00 00 00 01 1f 14 00 00 00 00";
+    Buffer *buf1 = hex2mem("03 00 00 00 00 01 1f 14 00 00 00 00");
+    Buffer *head1 = server.encodeHeader(0x3, RTMP::HEADER_12, 287,
+                                        RTMP::INVOKE, RTMPMsg::FROM_SERVER);
+//    cerr << hexify(head1->begin(), RTMP_MAX_HEADER_SIZE, false) << endl;
+    
+     if ((memcmp(buf1->reference(), head1->reference(), RTMP_MAX_HEADER_SIZE) 
== 0)) {
+         runtest.pass("Encoded RTMP header(Invoke)");
+     } else {
+         runtest.fail("Encoded RTMP header(Invoke)");
+     }
+
+     RTMP::rtmp_head_t *header1 = server.decodeHeader(buf1->reference());
+     if ((header1->channel == 0x3) && (header1->head_size == 
RTMP_MAX_HEADER_SIZE)
+         && (header1->bodysize == 287) && (header1->type ==  RTMP::INVOKE)) {
+         runtest.pass("Decoded RTMP header(Invoke)");
+     } else {
+         runtest.fail("Decoded RTMP header(Invoke)");
+     }
+
+     Buffer *buf2 = hex2mem("02 00 00 00 00 00 06 04 00 00 00 00");
+     Buffer *head2 = server.encodeHeader(0x2, RTMP::HEADER_12, PING_MSG_SIZE,
+                                     RTMP::PING, RTMPMsg::FROM_SERVER);
+//     cerr << hexify(head2->begin(), RTMP_MAX_HEADER_SIZE, false) << endl;
+     if ((memcmp(buf2->reference(), head2->reference(), 8) == 0)) {
+         runtest.pass("Encoded RTMP header(Ping 0)");
+     } else {
+         runtest.fail("Encoded RTMP header(Ping 0)");
+     }
+
+     Buffer *buf3 = hex2mem("02 ff e3 6c 00 00 06 04 00 00 00 00");
+     Buffer *head3 = server.encodeHeader(0x2, RTMP::HEADER_12, PING_MSG_SIZE,
+                                     RTMP::PING, RTMPMsg::FROM_SERVER);
+//     cerr << hexify(head3->begin(), RTMP_MAX_HEADER_SIZE, false) << endl;
+     if ((memcmp(buf2->reference(), head3->reference(), 8) == 0)) {
+         runtest.pass("Encoded RTMP header(Ping 1)");
+     } else {
+         runtest.fail("Encoded RTMP header(Ping 1)");
+     }
     
-     if ((memcmp(buf1->reference(), head->reference(), 12) == 0)) {
-         runtest.pass("Encoded RTMP header");
+     RTMP::rtmp_head_t *header2 = client.decodeHeader(buf3);
+     if ((header2->channel == 0x2) && (header2->head_size == 
RTMP_MAX_HEADER_SIZE)
+         && (header2->bodysize == 6) && (header2->type ==  RTMP::PING)) {
+         runtest.pass("Decoded RTMP header(Ping)");
      } else {
-         runtest.fail("Encoded RTMP header");
+         runtest.fail("Decoded RTMP header(Ping)");
      }
 
-     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");
+     Buffer *buf4 = hex2mem("c2");
+     Buffer *head4 = server.encodeHeader(0x2, RTMP::HEADER_1);
+//     cerr << hexify(head4->begin(), RTMP_MAX_HEADER_SIZE, false) << endl;
+     if ((memcmp(buf4->reference(), head4->reference(), 1) == 0)) {
+         runtest.pass("Encoded RTMP header(size 1)");
      } else {
-         runtest.fail("Decoded RTMP header");
+         runtest.fail("Encoded RTMP header(size 1)");
      }
      
      // cleanup after ourselves
      delete buf1;
-     delete head;
+     delete buf2;
+     delete buf3;
+     delete buf4;
+     delete head1;
+     delete head2;
+     delete head3;
+     delete head4;
+//     delete header1;
+//      delete header2;
 }
 
-
 void
-test_types()
+test_results()
 {
     GNASH_REPORT_FUNCTION;
-    RTMP rtmp;
+    RTMPServer rtmpserv;
+//   03 00 00 00 00 00 81 14    00 00 00 00 02 00 07 5f    ..............._
+//   72 65 73 75 6c 74 00 3f    f0 00 00 00 00 00 00 05    result.?........
+//   03 00 0b 61 70 70 6c 69    63 61 74 69 6f 6e 05 00    ...application..
+//   05 6c 65 76 65 6c 02 00    06 73 74 61 74 75 73 00    .level...status.
+//   0b 64 65 73 63 72 69 70    74 69 6f 6e 02 00 15 43    .description...C
+//   6f 6e 6e 65 63 74 69 6f    6e 20 73 75 63 63 65 65    onnection succee
+//   64 65 64 2e 00 04 63 6f    64 65 02 00 1d 4e 65 74    ded...code...Net
+//   43 6f 6e 6e 65 63 74 69    6f 6e 2e 43 6f 6e 6e 65    Connection.Conne
+//   63 74 2e 53 75 63 63 65    73 73 00 00 c3 09          ct.Success....
+    Buffer *hex2 = hex2mem("02 00 07 5f 72 65 73 75 6c 74 00 3f f0 00 00 00 00 
00 00 05 03 00 0b 61 70 70 6c 69 63 61 74 69 6f 6e 05 00 05 6c 65 76 65 6c 02 
00 06 73 74 61 74 75 73 00 0b 64 65 73 63 72 69 70 74 69 6f 6e 02 00 15 43 6f 
6e 6e 65 63 74 69 6f 6e 20 73 75 63 63 65 65 64 65 64 2e 00 04 63 6f 64 65 02 
00 1d 4e 65 74 43 6f 6e 6e 65 63 74 69 6f 6e 2e 43 6f 6e 6e 65 63 74 2e 53 75 
63 63 65 73 73 00 00 09");
+
+    RTMPMsg *msg1 = rtmpserv.decodeMsgBody(hex2);
+    if (msg1) {
+        std::vector<amf::Element *> hell = msg1->getElements();
+        std::vector<amf::Element *> props = hell[0]->getProperties();        
+//         printf("FIXME: %d, %d, %s:%s\n", props.size(), msg1->getStatus(),
+//                props[3]->getName(), props[3]->to_string());
+//         msg1->dump();
+        if ((msg1->getStatus() ==  RTMPMsg::NC_CONNECT_SUCCESS)
+            && (msg1->getMethodName() == "_result")
+            && (msg1->getStreamID() == 1)
+            && (msg1->size() == 1)) { // the msg has one element, which has 4 
properties
+            runtest.pass("Decoded RTMP Result(NC_CONNECT_SUCCESS) message");
+        } else {
+            runtest.fail("Decoded RTMP Result(NC_CONNECT_SUCCESS) message");
+        }
+    } else {
+        runtest.untested("Decoded RTMP Result(NC_CONNECT_SUCCESS) message");
+    }
+    delete msg1;
 
-    const char *x = "06 00 d2 04 00 00 00 00";
-    Buffer *buf1 = hex2mem(x);
+    Buffer *buf2 = rtmpserv.encodeResult(RTMPMsg::NC_CONNECT_SUCCESS);
+//    cerr << hexify(buf2->begin(), 122, true) << endl;
+    if ((memcmp(hex2->reference(), buf2->reference(), 122) == 0)) {
+        runtest.pass("Encoded RTMP result(NC_CONNECT_SUCCESS)");
+    } else {
+        runtest.fail("Encoded RTMP result(NC_CONNECT_SUCCESS)");
+    }
+    delete buf2;
+    delete hex2;
     
-    RTMP::rtmp_ping_t *ping = rtmp.decodePing(buf1);
-    if (ping->type == RTMP::PING_CLIENT) {
-         runtest.pass("Decoded RTMP Ping message");
+    Buffer *hex3 = hex2mem("02 00 07 5f 72 65 73 75 6c 74 00 3f f0 00 00 00 00 
00 00 05 03 00 0b 61 70 70 6c 69 63 61 74 69 6f 6e 05 00 05 6c 65 76 65 6c 02 
00 05 65 72 72 6f 72 00 0b 64 65 73 63 72 69 70 74 69 6f 6e 02 00 00 00 04 63 
6f 64 65 02 00 1c 4e 65 74 43 6f 6e 6e 65 63 74 69 6f 6e 2e 43 6f 6e 6e 65 63 
74 2e 46 61 69 6c 65 64 00 00 09");
+    RTMPMsg *msg2 = rtmpserv.decodeMsgBody(hex3);
+    std::vector<amf::Element *> hell = msg2->getElements();
+    std::vector<amf::Element *> props = hell[0]->getProperties();        
+//     printf("FIXME: %d, %d, %s:%s\n", props.size(), msg1->getStatus(),
+//            props[3]->getName(), props[3]->to_string());
+    if (msg2) {
+//        msg2->dump();
+        if ((msg2->getStatus() ==  RTMPMsg::NC_CONNECT_FAILED)
+            && (msg2->getMethodName() == "_result")
+            && (msg2->getStreamID() == 1)
+            && (msg2->size() == 1)) {
+            runtest.pass("Decoded RTMP result(NC_CONNECT_FAILED(as result)");
      } else {
-         runtest.fail("Decoded RTMP Ping message");
+            runtest.fail("Decoded RTMP result(NC_CONNECT_FAILED(as result)");
      }
+    } else {
+        runtest.untested("Decoded RTMP result(NC_CONNECT_FAILED(as result)");
+    }
+
+    delete msg2;
     
-    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");
+    delete hex3;
+    
+//     Buffer hex4 = "43 00 00 00 00 00 48 14 02 00 06 5f 65 72 72 6f 72 00 40 
00 00 00 00 00 00 00 05 03 00 04 63 6f 64 65 02 00 19 4e 65 74 43 6f 6e 6e 65 
63 74 69 6f 6e 2e 43 61 6c 6c 2e 46 61 69 6c 65 64 00 05 6c 65 76 65 6c 02 00 
05 65 72 72 6f 72 00 00 09";
+//     if ((memcmp(hex4->reference(), buf4->reference(), hex4->size()) == 0)) {
+//         runtest.pass("Encoded RTMP result(NC_CONNECT_FAILED(as result)");
+//     } else {
+//         runtest.fail("Encoded RTMP result(NC_CONNECT_FAILED(as result)");
+//     }
+//     delete buf4;
+
+    
+#if 0
+//    const char *x4 = "";
+    Buffer *hex4 = hex2mem("");
+    Buffer *buf4 = rtmpserv.encodeResult(RTMPMsg::NC_CONNECT_REJECTED);
+    if ((memcmp(hex4->reference(), buf4->reference(), buf4->size()) == 0)) {
+        runtest.pass("Encoded RTMP result(NC_CONNECT_REJECTED");
      } else {
-         runtest.fail("Encoded RTMP Ping message");
+        runtest.fail("Encoded RTMP result(NC_CONNECT_REJECTED)");
      }
-     delete ping;
-     delete buf1;
-     delete buf2;
+    delete buf4;
+    
+//    const char *x5 = "";
+    Buffer *hex5 = hex2mem("");
+    Buffer *buf5 = rtmpserv.encodeResult(RTMPMsg::NC_CONNECT_APPSHUTDOWN);
+    if ((memcmp(hex5->reference(), buf5->reference(), buf5->size()) == 0)) {
+        runtest.pass("Encoded RTMP result(NC_CONNECT_APPSHUTDOWN)");
+    } else {
+        runtest.fail("Encoded RTMP result(NC_CONNECT_APPSHUTDOWN)");
+    }
+    delete buf5;
+    
+//    const char *x6 = "";
+    Buffer *hex6 = hex2mem("");
+    Buffer *buf6 = 
rtmpserv.encodeResult(RTMPMsg::NC_CONNECT_INVALID_APPLICATION);
+    if ((memcmp(hex6->reference(), buf6->reference(), buf6->size()) == 0)) {
+        runtest.pass("Encoded RTMP result(NC_CONNECT_INVALID_APPLICATION)");
+    } else {
+        runtest.fail("Encoded RTMP result(NC_CONNECT_INVALID_APPLICATION)");
+    }
+    delete buf6;
+    
+//    const char *x7 = "";
+    Buffer *hex7 = hex2mem("");
+    Buffer *buf7 = rtmpserv.encodeResult(RTMPMsg::NC_CONNECT_CLOSED);
+    if ((memcmp(hex7->reference(), buf7->reference(), buf7->size()) == 0)) {
+        runtest.pass("Encoded RTMP result(NC_CONNECT_INVALID_CLOSED)");
+    } else {
+        runtest.fail("Encoded RTMP result(NC_CONNECT_INVALID_CLOSED)");
+    }
+    delete buf7;
+#endif
+
+}
+
+void
+test_types()
+{
+    GNASH_REPORT_FUNCTION;
+    RTMP rtmp;
+
+    const char *x = "06 00 d2 04 00 00 00 00";
+    Buffer *buf1 = hex2mem(x);
+    
 }
 
 static void

Index: libnet/rtmp_client.cpp
===================================================================
RCS file: libnet/rtmp_client.cpp
diff -N libnet/rtmp_client.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libnet/rtmp_client.cpp      16 May 2008 03:46:27 -0000      1.1
@@ -0,0 +1,277 @@
+// rtmp.cpp:  Adobe/Macromedia Real Time Message Protocol handler, for Gnash.
+// 
+//   Copyright (C) 2005, 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
+// 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
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#if ! (defined(_WIN32) || defined(WIN32))
+#      include <netinet/in.h>
+#endif
+
+#include "log.h"
+#include "rc.h"
+#include "amf.h"
+#include "rtmp.h"
+#include "rtmp_client.h"
+#include "network.h"
+#include "element.h"
+#include "handler.h"
+#include "utility.h"
+#include "buffer.h"
+
+using namespace gnash;
+using namespace std;
+using namespace amf;
+
+namespace gnash
+{
+
+// The rcfile is loaded and parsed here:
+static RcInitFile& rcfile = RcInitFile::getDefaultInstance();
+
+extern map<int, Handler *> handlers;
+
+RTMPClient::RTMPClient()
+    : _connections(0)
+{
+//    GNASH_REPORT_FUNCTION;
+}
+
+RTMPClient::~RTMPClient()
+{
+//    GNASH_REPORT_FUNCTION;
+    _variables.clear();
+//    delete _body;
+}
+
+
+// These are used for creating the primary objects
+
+// Make the NetConnection object that is used to connect to the
+// server.
+amf::Buffer *
+RTMPClient::encodeConnect(const char *app, const char *swfUrl, const char 
*tcUrl,
+                          double audioCodecs, double videoCodecs, double 
videoFunction,
+                          const char *pageUrl)
+{
+    GNASH_REPORT_FUNCTION;
+    
+    AMF amf_obj;
+
+    Element *connect = new Element;
+    connect->makeString("connect");
+
+    Element *connum = new Element;
+//     const char *connumStr = "00 00 00 00 00 00 f0 3f";
+//     Buffer *connumBuf = hex2mem(connumStr);
+    // update the counter for the number of connections. This number is used 
heavily
+    // in RTMP to help keep communications clear when there are multiple 
streams.
+    _connections++;
+    connum->makeNumber(_connections);
+    
+    // Make the top level object
+    Element obj;
+    obj.makeObject();
+    
+    Element *appnode = new Element;
+    appnode->makeString("app", app);
+    obj.addProperty(appnode);
+
+    const char *version = 0;
+    if (rcfile.getFlashVersionString().size() > 0) {
+        version = rcfile.getFlashVersionString().c_str();
+    } else {
+        version = "LNX 9,0,31,0";
+    }  
+
+    Element *flashVer = new Element;
+    flashVer->makeString("flashVer", "LNX 9,0,31,0");
+    obj.addProperty(flashVer);
+    
+    Element *swfUrlnode = new Element;
+//    swfUrl->makeString("swfUrl", 
"http://192.168.1.70/software/gnash/tests/ofla_demo.swf";);
+    swfUrlnode->makeString("swfUrl", swfUrl);
+    obj.addProperty(swfUrlnode);
+
+//    filespec = "rtmp://localhost/oflaDemo";
+    Element *tcUrlnode = new Element;
+    tcUrlnode->makeString("tcUrl", tcUrl);
+    obj.addProperty(tcUrlnode);
+
+    Element *fpad = new Element;
+    fpad->makeBoolean("fpad", false);
+    obj.addProperty(fpad);
+
+    Element *audioCodecsnode = new Element;
+//    audioCodecsnode->makeNumber("audioCodecs", 615);
+    audioCodecsnode->makeNumber("audioCodecs", audioCodecs);
+    obj.addProperty(audioCodecsnode);
+    
+    Element *videoCodecsnode = new Element;
+//    videoCodecsnode->makeNumber("videoCodecs", 124);
+    videoCodecsnode->makeNumber("videoCodecs", videoCodecs);
+    obj.addProperty(videoCodecsnode);
+
+    Element *videoFunctionnode = new Element;
+//    videoFunctionnode->makeNumber("videoFunction", 0x1);
+    videoFunctionnode->makeNumber("videoFunction", videoFunction);
+    obj.addProperty(videoFunctionnode);
+
+    Element *pageUrlnode = new Element;
+//    pageUrlnode->makeString("pageUrl", 
"http://x86-ubuntu/software/gnash/tests/";);
+    pageUrlnode->makeString("pageUrl", pageUrl);
+    obj.addProperty(pageUrlnode);
+
+//    size_t total_size = 227;
+//     Buffer *out = encodeHeader(0x3, RTMP::HEADER_12, total_size,
+//                                      RTMP::INVOKE, RTMP::FROM_CLIENT);
+//     const char *rtmpStr = "03 00 00 04 00 01 1f 14 00 00 00 00";
+//     Buffer *rtmpBuf = hex2mem(rtmpStr);
+    Buffer *conobj = connect->encode();
+    Buffer *numobj = connum->encode();
+    Buffer *encobj = obj.encode();
+
+    Buffer *buf = new Buffer(conobj->size() + numobj->size() + encobj->size());
+//    buf->append(out);
+    buf->append(conobj);
+    buf->append(numobj);
+    buf->append(encobj);
+
+    return buf;
+}
+
+// 43 00 1a 21 00 00 19 14 02 00 0c 63 72 65 61 74  C..!.......creat
+// 65 53 74 72 65 61 6d 00 40 08 00 00 00 00 00 00  address@hidden
+// 05                                                    .               
+amf::Buffer *
+RTMPClient::encodeStream(double /* id */)
+{
+    GNASH_REPORT_FUNCTION;
+    
+    struct timespec now;
+    clock_gettime (CLOCK_REALTIME, &now);
+    
+//     log_debug("Buffer %x (%d) stayed in queue for %f seconds",
+//           (void *)_ptr, _nbytes,
+//           (float)((now.tv_sec - _stamp.tv_sec) + ((now.tv_nsec - 
_stamp.tv_nsec)/1e9)));
+
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
+}
+
+// 127.0.0.1:38167 -> 127.0.0.1:1935 [AP]
+// 08 00 1b 1b 00 00 2a 14 01 00 00 00 02 00 04 70  ......*........p
+// 6c 61 79 00 00 00 00 00 00 00 00 00 05 02 00 16  lay.............
+// 6f 6e 32 5f 66 6c 61 73 68 38 5f 77 5f 61 75 64  on2_flash8_w_aud
+// 69 6f 2e 66 6c 76 c2 00 03 00 00 00 01 00 00 27  io.flv.........'
+// 10
+amf::Buffer *
+RTMPClient::encodePublish()
+{
+    GNASH_REPORT_FUNCTION;
+    log_unimpl(__PRETTY_FUNCTION__);
+    return 0;
+}    
+
+// A request for a handshake is initiated by sending a byte with a
+// value of 0x3, followed by a message body of unknown format.
+bool
+RTMPClient::handShakeRequest()
+{
+    GNASH_REPORT_FUNCTION;
+
+#if 0
+    char buffer[RTMP_BODY_SIZE+1];
+    char c = 0x3;
+    int  i, ret;
+    
+    ret = writeNet(&c, 1);
+    _outbytes += 1;
+    // something went wrong, chances are the other end of the network
+    // connection is down, or never initialized.
+    if (ret <= 0) {
+        return false;
+    }
+
+    // Since we don't know what the format is, create a pattern we can
+    // recognize if we stumble across it later on.
+    for (i=0; i<RTMP_BODY_SIZE; i++) {
+        buffer[i] = i^256;
+    }
+    
+    _outbytes += RTMP_BODY_SIZE;
+    ret = writeNet(buffer, RTMP_BODY_SIZE);
+#endif
+    
+    return true;
+}
+
+// The client finished the handshake process by sending the second
+// data block we get from the server as the response
+bool
+RTMPClient::clientFinish()
+{
+    GNASH_REPORT_FUNCTION;
+
+#if 0
+    char buffer[RTMP_BODY_SIZE+1];
+    memset(buffer, 0, RTMP_BODY_SIZE+1);
+
+    if (readNet(buffer, RTMP_BODY_SIZE) == RTMP_BODY_SIZE) {        
+        log_debug (_("Read first data block in handshake"));
+    } else {
+        log_error (_("Couldn't read first data block in handshake"));
+        return false;
+    }
+    _inbytes += RTMP_BODY_SIZE;
+    if (readNet(buffer, RTMP_BODY_SIZE) == RTMP_BODY_SIZE) {        
+        log_debug (_("Read second data block in handshake"));
+//         _body = new char(RTMP_BODY_SIZE+1);
+//         memcpy(_body, buffer, RTMP_BODY_SIZE);
+    } else {
+        log_error (_("Couldn't read second data block in handshake"));
+        return false;
+    }
+    _inbytes += RTMP_BODY_SIZE;
+
+    writeNet(buffer, RTMP_BODY_SIZE);
+    _outbytes += RTMP_BODY_SIZE;
+#endif
+    
+    return true;
+}
+
+// bool
+// RTMPClient::packetRequest()
+// {
+//     GNASH_REPORT_FUNCTION;
+//     return false;
+// }
+
+} // end of gnash namespace
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: libnet/rtmp_client.h
===================================================================
RCS file: libnet/rtmp_client.h
diff -N libnet/rtmp_client.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libnet/rtmp_client.h        16 May 2008 03:46:27 -0000      1.1
@@ -0,0 +1,73 @@
+// 
+//   Copyright (C) 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
+
+#ifndef _RTMP_CLIENT_H_
+#define _RTMP_CLIENT_H_ 1
+
+#include <boost/cstdint.hpp>
+#include <string>
+#include <map>
+#include <time.h>
+
+#include "rtmp.h"
+#include "amf.h"
+#include "element.h"
+#include "handler.h"
+#include "network.h"
+#include "buffer.h"
+
+namespace gnash
+{
+
+class DSOEXPORT RTMPClient : public RTMP
+{
+public:
+    RTMPClient();
+    ~RTMPClient();
+
+    bool handShakeWait();
+    bool handShakeResponse();
+    bool clientFinish();
+    bool handShakeRequest();
+    
+    // These are used for creating the primary objects
+    // Create the initial object sent to the server, which is 
NetConnection::connect()
+    amf::Buffer *encodeConnect(const char *app, const char *swfUrl, const char 
*tcUrl,
+                              double audioCodecs, double videoCodecs, double 
videoFunction,
+                              const char *pageUrl);
+    // Create the second object sent to the server, which is 
NetStream():;NetStream()
+    amf::Buffer *encodeStream(double id);
+
+    amf::Buffer *encodePublish();
+    
+    void dump();
+  private:
+    double _connections;
+};
+
+// This is the thread for all incoming RTMP connections
+void rtmp_handler(Handler::thread_params_t *args);
+
+} // end of gnash namespace
+// end of _RTMP_CLIENT_H_
+#endif
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
+

Index: libnet/rtmp_msg.cpp
===================================================================
RCS file: libnet/rtmp_msg.cpp
diff -N libnet/rtmp_msg.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libnet/rtmp_msg.cpp 16 May 2008 03:46:29 -0000      1.1
@@ -0,0 +1,146 @@
+// rtmp.cpp:  Adobe/Macromedia Real Time Message Protocol handler, for Gnash.
+// 
+//   Copyright (C) 2005, 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
+// 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
+
+#include <iostream>
+#include <string>
+#include <map>
+
+#if ! (defined(_WIN32) || defined(WIN32))
+#      include <netinet/in.h>
+#endif
+
+#include "log.h"
+#include "amf.h"
+#include "rtmp.h"
+#include "rtmp_msg.h"
+#include "network.h"
+#include "element.h"
+#include "handler.h"
+#include "utility.h"
+#include "buffer.h"
+
+using namespace gnash;
+using namespace std;
+using namespace amf;
+
+namespace gnash
+{
+
+RTMPMsg::RTMPMsg()
+    : _routing(FROM_SERVER),
+      _status(APP_SHUTDOWN),
+      _streamid(0),
+      _channel(9)
+{
+//    GNASH_REPORT_FUNCTION;
+//     _inbytes = 0;
+//     _outbytes = 0;
+    
+//    _body = new unsigned char(RTMP_BODY_SIZE+1);
+//    memset(_body, 0, RTMP_BODY_SIZE+1);
+}
+
+RTMPMsg::~RTMPMsg()
+{
+//    GNASH_REPORT_FUNCTION;
+    vector<amf::Element *>::iterator it;
+    for (it = _amfobjs.begin(); it != _amfobjs.end(); it++) {
+       amf::Element *el = (*(it));
+       if (el) {
+//             el->dump();
+           delete el;
+       }
+    }
+    
+}
+
+RTMPMsg::rtmp_status_e
+RTMPMsg::checkStatus(amf::Element * /* el */)
+{
+//    GNASH_REPORT_FUNCTION;
+    if (_amfobjs.size() > 0) {
+       vector<amf::Element *>::iterator pit;
+       vector<amf::Element *>::iterator cit;
+//     cerr << "# of Properties in object" << _amfobjs.size() << endl;
+       for (pit = _amfobjs.begin(); pit != _amfobjs.end(); pit++) {
+           amf::Element *el = (*(pit));
+           std::vector<amf::Element *> props = el->getProperties();
+//         printf("FIXME2: %d, %s:%s\n", props.size(),
+//                props[2]->getName(), props[2]->to_string());
+           if (el->getType() == Element::OBJECT_AMF0) {
+               for (cit = props.begin(); cit != props.end(); cit++) {
+                   amf::Element *child = (*(cit));
+//                 child->dump();
+                   string name = child->getName();
+                   string value;
+                   if (child->getLength()) {
+                       value = child->to_string();
+                       if (name == "code") {
+//                         log_debug("Name is: %s, Value is: %s", 
name.c_str(), value.c_str());
+                           if (value == "NetConnection.Connect.Success") {
+                               _status = RTMPMsg::NC_CONNECT_SUCCESS;
+                               return _status;
+                           }
+                           if (value == "NetConnection.Connect.Failed") {
+                               _status = RTMPMsg::NC_CONNECT_FAILED;
+                               return _status;
+                           }
+                           if (value == "NetConnection.Call.Failed") {
+                               _status = RTMPMsg::NC_CALL_FAILED;      
+                               return _status;
+                           }
+                       }
+                   }
+               }
+           }
+       }
+    }
+    return _status;
+}
+
+void
+RTMPMsg::dump()
+{
+//    GNASH_REPORT_FUNCTION;
+
+//     cerr <<"Timestamp: " << _header.timestamp << endl;
+//     cerr << "Length: " << _header.length << endl;
+    
+    cerr << "Method Name:\t" << _method << endl;
+//    cerr << "Stream ID:\t" << hexify((const unsigned char *)&_streamid, 8, 
false) << endl;
+    cerr << "Stream ID:\t" << _streamid << endl;
+
+    vector<amf::Element *>::iterator ait;
+    cerr << "# of Elements in file: " << _amfobjs.size() << endl;
+    for (ait = _amfobjs.begin(); ait != _amfobjs.end(); ait++) {
+       amf::Element *el = (*(ait));
+        el->dump();
+    }
+}
+
+} // end of gnash namespace
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: libnet/rtmp_msg.h
===================================================================
RCS file: libnet/rtmp_msg.h
diff -N libnet/rtmp_msg.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libnet/rtmp_msg.h   16 May 2008 03:46:31 -0000      1.1
@@ -0,0 +1,129 @@
+// 
+//   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
+// 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
+
+#ifndef _RTMPMSG_H_
+#define _RTMPMSG_H_
+
+#include <boost/cstdint.hpp>
+#include <string>
+#include <vector>
+
+#include "amf.h"
+#include "rtmp.h"
+#include "element.h"
+#include "handler.h"
+#include "network.h"
+#include "buffer.h"
+
+namespace gnash
+{
+
+class DSOEXPORT RTMPMsg
+{
+public:
+    typedef enum {
+       APP_GC,
+       APP_RESOURCE_LOWMEMORY,
+       APP_SCRIPT_ERROR,
+       APP_SCRIPT_WARNING,
+       APP_SHUTDOWN,
+       NC_CALL_BADVERSION,
+       NC_CALL_FAILED,
+       NC_CONNECT_APPSHUTDOWN,
+       NC_CONNECT_CLOSED,
+       NC_CONNECT_FAILED,
+       NC_CONNECT_INVALID_APPLICATION,
+       NC_CONNECT_REJECTED,
+       NC_CONNECT_SUCCESS,
+       NS_CLEAR_FAILED,
+       NS_CLEAR_SUCCESS,
+       NS_DATA_START,
+       NS_FAILED,
+       NS_INVALID_ARGUMENT,
+       NS_PAUSE_NOTIFY,
+       NS_PLAY_COMPLETE,
+       NS_PLAY_FAILED,
+       NS_PLAY_FILE_STRUCTURE_INVALID,
+       NS_PLAY_INSUFFICIENT_BW,
+       NS_PLAY_NO_SUPPORTED_TRACK_FOUND,
+       NS_PLAY_PUBLISHNOTIFY,
+       NS_PLAY_RESET,
+       NS_PLAY_START,
+       NS_PLAY_STOP,
+       NS_PLAY_STREAMNOTFOUND,
+       NS_PLAY_SWITCH,
+       NS_PLAY_UNPUBLISHNOTIFY,
+       NS_PUBLISH_BADNAME,
+       NS_PUBLISH_START,
+       NS_RECORD_FAILED,
+       NS_RECORD_NOACCESS,
+       NS_RECORD_START,
+       NS_RECORD_STOP,
+       NS_SEEK_FAILED,
+       NS_SEEK_NOTIFY,
+       NS_UNPAUSE_NOTIFY,
+       NS_UNPUBLISHED_SUCCESS,
+       SO_CREATION_FAILED,
+       SO_NO_READ_ACCESS,
+       SO_NO_WRITE_ACCESS,
+       SO_PERSISTENCE_MISMATCH
+    } rtmp_status_e;
+    typedef enum {
+       FROM_SERVER,                      // Flash com server
+       FROM_CLIENT                       // Flash player
+    } rtmp_source_e;
+    RTMPMsg();
+    ~RTMPMsg();
+    
+    void addObject(amf::Element *el) { _amfobjs.push_back(el); };
+    size_t size() { return _amfobjs.size(); };
+    std::vector<amf::Element *> getElements() { return _amfobjs; };
+
+    void setMethodName(const std::string &name) { _method = name; } ;
+    std::string &getMethodName()         { return _method; };
+
+    void setStreamID(double num)         { _streamid = num; };
+    double getStreamID()                { return _streamid; };
+
+    rtmp_status_e checkStatus(amf::Element *el);
+    void setStatus(rtmp_status_e st)     { _status = st; };
+    rtmp_status_e getStatus()           { return _status; };
+
+    void setChannel(Network::byte_t num) { _channel = num; };
+    Network::byte_t getChannel()         { return _channel; } ;
+
+    // Dump internal status to the terminal
+    void dump();
+    
+  protected:
+    rtmp_source_e        _routing;
+    rtmp_status_e        _status;
+    std::string           _method;
+    double                _streamid;
+    std::vector<amf::Element *> _amfobjs;
+    Network::byte_t       _channel;
+};
+
+} // end of gnash namespace
+// end of _RTMPMSG_H_
+#endif
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
+




reply via email to

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