[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libamf/...
From: |
Rob Savoye |
Subject: |
[Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libamf/... |
Date: |
Sat, 03 May 2008 18:44:09 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Rob Savoye <rsavoye> 08/05/03 18:44:09
Modified files:
libamf : amf.cpp element.cpp sol.cpp element.h
testsuite/libnet.all: Makefile.am
. : ChangeLog
libnet : handler.cpp netstats.h network.h rtmp.cpp
rtmp.h rtmp_server.cpp rtmp_server.h
Added files:
testsuite/libnet.all: test_rtmp.cpp
Log message:
* testsuite/libnet.all/test_rtmp.cpp: Unit tests for the RTMP
encoding and decoding.
* libamf/amf.cpp: Booleans are two bytes after all.
* libamf/sol.cpp: Booleans are two bytes after all.
* libamf/element.cpp: Copy the name, don't just grab the
pointer. Terminate Objects correctly.
* libnet/rtmp.cpp: Add methods to encode & decode the RTMP
header, and the Ping message.
* libnet/rtmp.h: Add methods to encode & decode the RTMP
header, and the messages. Add Ping message types and data
structure.
* libnet/rtmp_server.cpp: Actually handle the message type.
Modify
how the initial 1536 bytes handshake works.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.cpp?cvsroot=gnash&r1=1.76&r2=1.77
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.cpp?cvsroot=gnash&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/sol.cpp?cvsroot=gnash&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.h?cvsroot=gnash&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/Makefile.am?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/test_rtmp.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6484&r2=1.6485
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/handler.cpp?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/netstats.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/network.h?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.cpp?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.h?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_server.cpp?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_server.h?cvsroot=gnash&r1=1.2&r2=1.3
Patches:
Index: libamf/amf.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/amf.cpp,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -b -r1.76 -r1.77
--- libamf/amf.cpp 30 Apr 2008 18:19:40 -0000 1.76
+++ libamf/amf.cpp 3 May 2008 18:44:05 -0000 1.77
@@ -178,7 +178,7 @@
// GNASH_REPORT_FUNCTION;
double num;
// Encode the data as a 64 bit, big-endian, numeric value
- Buffer *buf = new Buffer(AMF0_NUMBER_SIZE + AMF_HEADER_SIZE);
+ Buffer *buf = new Buffer(AMF0_NUMBER_SIZE + 1); // only one additional
byte for the type
buf->append(Element::NUMBER_AMF0);
num = indata;
swapBytes(&num, AMF0_NUMBER_SIZE);
@@ -192,18 +192,18 @@
/// @return a binary AMF packet in big endian format (header,data) which
/// needs to be deleted[] after being used.
///
-/// Although a boolean is one byte in size, swf uses 16bit short integers
-/// heavily, so this value is also a short.
+/// Although a boolean is one byte in size.
Buffer *
AMF::encodeBoolean(bool flag)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
// Encode a boolean value. 0 for false, 1 for true
- Buffer *buf = new Buffer(AMF_HEADER_SIZE);
+ Buffer *buf = new Buffer(2);
buf->append(Element::BOOLEAN_AMF0);
- boost::uint16_t x = flag;
- swapBytes(&x, 2);
- buf->append(x);
+// Hum, AMF3 ???
+// boost::uint16_t x = flag;
+// swapBytes(&x, 2);
+ buf->append(flag);
return buf;
}
@@ -503,14 +503,19 @@
Buffer *
AMF::encodeElement(Element *el)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
Buffer *buf = 0;
Buffer *tmp;
- size_t outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
+ size_t outsize;
+ if (el->getType() == Element::BOOLEAN_AMF0) {
+ outsize = el->getNameSize() + 2;
+ } else {
+ outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
+ }
buf = new Buffer(outsize);
buf->clear(); // FIXME: temporary, makes buffers cleaner in
gdb.
- // If the name field is set, it's a "variable", followed by the data
+ // If the name field is set, it's a "property", followed by the data
if (el->getName()) {
// Add the length of the string for the name of the variable
size_t length = el->getNameSize();
@@ -556,7 +561,7 @@
case Element::ECMA_ARRAY_AMF0:
tmp = encodeECMAArray(el->getData(), el->getLength());
break;
- // The Object End gets added when creating the object, so we can jusy
ignore it here.
+ // The Object End gets added when creating the object, so we can just
ignore it here.
case Element::OBJECT_END_AMF0:
tmp = encodeObjectEnd();
break;
@@ -590,106 +595,20 @@
};
buf->append(tmp);
-// log_debug("Encoded buf size is %d", buf->size());
delete tmp;
-
return buf;
}
-#if 0
-/// Encode an array of elements.
-///
-/// @return a binary AMF packet in big endian format (header,data)
-
-/// @return a newly allocated byte array.
-/// to be deleted by caller using delete [] operator, or NULL
-///
-vector<Buffer> *
-AMF::encodeElement(vector<amf::Element *> &data)
-{
-// GNASH_REPORT_FUNCTION;
-
- int size = 0;
- bool pad = false;
-
- // Calculate how large the buffer has to be.
- vector<amf::Element *>::iterator ait;
- cerr << "# of Elements in file: " << data.size() << endl;
- for (ait = data.begin(); ait != data.end(); ait++) {
- amf::Element *el = (*(ait));
- size += el->getLength() + AMF_HEADER_SIZE;
-// el->dump();
- }
- vector<Network::byte_t> *vec = new vector<Network::byte_t>;
- Network::byte_t* ptr = new Network::byte_t[size + 1];
- memset(ptr, 0, size + 1);
-
-// Network::byte_t *x = ptr;
- size = 0;
- for (ait = data.begin(); ait != data.end(); ait++) {
- amf::Element *el = (*(ait));
-// el->dump();
- Network::byte_t *tmp = encodeElement(el);
- Network::byte_t *y = tmp;
-#if 0
- Network::byte_t *hexint;
- hexint = new Network::byte_t[(el->getLength() + 4) *3];
- hexify((Network::byte_t *)hexint, (Network::byte_t *)tmp,
- el->getLength() + AMF_HEADER_SIZE, true);
- log_debug(_("The packet head is: 0x%s"), hexint);
-#endif
- // The 'pad' in this case is a serious hack. I think it
- // may be an artifact, but one guess is it's a 16bit word
- // aligned memory segment due to some ancient heritage in
- // the other player, so after a 3 byte bool, and two 9 byte
- // numbers, another byte is needed for padding.
- // My guess is the pattern of boolean->number->number->methodname
- // is a function block ID. I need to dp more testing with a
- // wider variety of sef movies that use LocalConnection to
- // really tell.
- if (el->getType() == Element::NUMBER) {
- size = AMF0_NUMBER_SIZE + 1;
- pad = true;
- }
- if (el->getType() == Element::STRING) {
- if (pad) {
- vec->push_back('\0');
- pad = false;
- }
- size = el->getLength() + AMF_HEADER_SIZE;
- }
-// if (el->getType() == Element::FUNCTION) {
-// // _properties
-// }
- if (el->getType() == Element::BOOLEAN) {
- size = 3;
- }
- for (int i=0; i<size; i++) {
- Network::byte_t c = *y;
- y++;
-// printf("0x%x(%c) ", c, (isalpha(c)) ? c : '.');
- vec->push_back(c);
- }
-// delete[] tmp;
- }
- return vec;
-}
-#endif
-
Buffer *
AMF::encodeProperty(amf::Element *el)
{
// GNASH_REPORT_FUNCTION;
+ size_t outsize;
- size_t outsize = el->getNameSize() + el->getLength() + AMF_VAR_HEADER_SIZE;
+ outsize = el->getNameSize() + el->getLength() + AMF_VAR_HEADER_SIZE;
Buffer *buf = new Buffer(outsize);
_totalsize += outsize;
-// Network::byte_t *out = new Network::byte_t[outsize + 4]; // why +4 here
?
-// Network::byte_t *end = out + outsize+4; // why +4 ?
-
-// memset(out, 0, outsize + 2); // why +2 here ?
-// Network::byte_t *tmpptr = out;
// Add the length of the string for the name of the variable
size_t length = el->getNameSize();
@@ -710,8 +629,9 @@
// the type byte that's the value.
switch (el->getType()) {
case Element::BOOLEAN_AMF0:
- enclength = el->to_bool();
- buf->append(enclength);
+// enclength = el->to_bool();
+// buf->append(enclength);
+ buf->append(el->to_bool());
break;
case Element::NUMBER_AMF0:
if (el->getData()) {
@@ -789,7 +709,8 @@
ENSUREBYTES(tmpptr, tooFar, sizeof(boost::uint16_t));
#endif
el->makeBoolean(tmpptr);
- tmpptr += sizeof(boost::uint16_t); // although a bool is one byte,
it's stored as a short
+ tmpptr += sizeof(bool);
+// tmpptr += sizeof(boost::uint16_t); // although a bool is one byte,
it's stored as a short
break;
case Element::STRING_AMF0:
// get the length of the name
Index: libamf/element.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.cpp,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- libamf/element.cpp 30 Apr 2008 03:35:30 -0000 1.23
+++ libamf/element.cpp 3 May 2008 18:44:05 -0000 1.24
@@ -402,10 +402,9 @@
if (_type == Element::OBJECT_AMF0) {
// FIXME: we probably want a better size, to avoid the other
// appends from having to resize and copy the data all the time.
- buf = new Buffer(128);
+ buf = new Buffer(300);
buf->clear(); // FIXME: temporary, makes buffers cleaner in
gdb.
buf->append(Element::OBJECT_AMF0);
-// string name = _name;
if (_name > 0) {
// Buffer *top = AMF::encodeElement(this);
// buf->append(top);
@@ -418,7 +417,8 @@
for (size_t i=0; i<_properties.size(); i++) {
Buffer *partial = AMF::encodeElement(_properties[i]);
-// log_debug("Encoded partial size is %d", partial->size());
+ log_debug("Encoded partial size for is %d", partial->size());
+ partial->dump();
if (partial) {
buf->append(partial);
delete partial;
@@ -426,8 +426,13 @@
break;
}
}
+ log_debug("FIXME: Terminating object");
+ Network::byte_t pad = 0;
+ buf->append(pad);
+ buf->append(pad);
buf->append(TERMINATOR);
_buffer = buf;
+
return buf;
} else {
return AMF::encodeElement(this);
@@ -457,10 +462,10 @@
Element &
Element::operator=(Element *el)
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
_type = el->getType();
if (el->getNameSize()) {
- _name = el->getName();
+ _name = strdup(el->getName());
}
_buffer = new Buffer(el->getLength());
_buffer->copy(el->getData(), el->getLength());
@@ -565,6 +570,18 @@
}
Element &
+Element::makeNumber(const std::string &name, gnash::Network::byte_t *data)
+{
+// GNASH_REPORT_FUNCTION;
+ if (name.size()) {
+ setName(name);
+ }
+ _type = Element::NUMBER_AMF0;
+ check_buffer(AMF0_NUMBER_SIZE);
+ _buffer->copy(data);
+}
+
+Element &
Element::makeBoolean(bool flag)
{
// GNASH_REPORT_FUNCTION;
Index: libamf/sol.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/sol.cpp,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- libamf/sol.cpp 30 Apr 2008 18:19:41 -0000 1.35
+++ libamf/sol.cpp 3 May 2008 18:44:06 -0000 1.36
@@ -251,7 +251,7 @@
size_t outsize = 0;
switch (el->getType()) {
case Element::BOOLEAN_AMF0:
- outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
+ outsize = el->getNameSize() + 3;
memcpy(ptr, var->reference(), outsize);
ptr += outsize;
break;
@@ -333,7 +333,7 @@
// Make sure it's an SOL file
if (stat(filespec.c_str(), &st) == 0) {
-try {
+ try {
ifstream ifs(filespec.c_str(), ios::binary);
_filesize = st.st_size;
buf = new Network::byte_t[_filesize + sizeof(int)];
@@ -415,11 +415,10 @@
ifs.close();
return true;
-} catch (std::exception& e) {
+ } catch (std::exception& e) {
log_error("Reading SharedObject %s: %s", filespec, e.what());
return false;
-}
-
+ }
}
// log_error("Couldn't open file: %s", strerror(errno));
Index: libamf/element.h
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- libamf/element.h 30 Apr 2008 03:35:31 -0000 1.20
+++ libamf/element.h 3 May 2008 18:44:06 -0000 1.21
@@ -109,6 +109,7 @@
Element &makeNumber(double num);
Element &makeNumber(gnash::Network::byte_t *data);
Element &makeNumber(const std::string &name, double num);
+ Element &makeNumber(const std::string &name, gnash::Network::byte_t
*data);
Element &makeBoolean(gnash::Network::byte_t *data);
Element &makeBoolean(bool data);
Index: testsuite/libnet.all/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libnet.all/Makefile.am,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- testsuite/libnet.all/Makefile.am 6 Apr 2008 18:11:33 -0000 1.5
+++ testsuite/libnet.all/Makefile.am 3 May 2008 18:44:06 -0000 1.6
@@ -48,12 +48,17 @@
check_PROGRAMS = \
test_cque \
test_handler \
- test_http
+ test_http \
+ test_rtmp
test_http_SOURCES = test_http.cpp
test_http_LDADD = $(AM_LDFLAGS)
test_http_DEPENDENCIES = site-update
+test_rtmp_SOURCES = test_rtmp.cpp
+test_rtmp_LDADD = $(AM_LDFLAGS)
+test_rtmp_DEPENDENCIES = site-update
+
test_cque_SOURCES = test_cque.cpp
test_cque_LDADD = $(AM_LDFLAGS)
test_cque_DEPENDENCIES = site-update
@@ -62,10 +67,6 @@
test_handler_LDADD = $(AM_LDFLAGS)
test_handler_DEPENDENCIES = site-update
-#test_buffer_SOURCES = test_buffer.cpp
-#test_buffer_LDADD = $(AM_LDFLAGS)
-#test_buffer_DEPENDENCIES = site-update
-
# Rebuild with GCC 4.x Mudflap support
mudflap:
@echo "Rebuilding with GCC Mudflap support"
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6484
retrieving revision 1.6485
diff -u -b -r1.6484 -r1.6485
--- ChangeLog 3 May 2008 15:06:27 -0000 1.6484
+++ ChangeLog 3 May 2008 18:44:07 -0000 1.6485
@@ -1,3 +1,19 @@
+2008-05-03 Rob Savoye <address@hidden>
+
+ * testsuite/libnet.all/test_rtmp.cpp: Unit tests for the RTMP
+ encoding and decoding.
+ * libamf/amf.cpp: Booleans are two bytes after all.
+ * libamf/sol.cpp: Booleans are two bytes after all.
+ * libamf/element.cpp: Copy the name, don't just grab the
+ pointer. Terminate Objects correctly.
+ * libnet/rtmp.cpp: Add methods to encode & decode the RTMP
+ header, and the Ping message.
+ * libnet/rtmp.h: Add methods to encode & decode the RTMP
+ header, and the messages. Add Ping message types and data
+ structure.
+ * libnet/rtmp_server.cpp: Actually handle the message type. Modify
+ how the initial 1536 bytes handshake works.
+
2008-05-03 Sandro Santilli <address@hidden>
* server/as_value.cpp (to_number): more blocks to protect
Index: libnet/handler.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/handler.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- libnet/handler.cpp 1 Apr 2008 22:20:37 -0000 1.5
+++ libnet/handler.cpp 3 May 2008 18:44:08 -0000 1.6
@@ -215,11 +215,13 @@
size_t ret = hand->readNet(args->netfd, buf->reference(), buf->size(),
1);
// the read timed out as there was no data, but the socket is still
open.
if (ret == 0) {
+ log_debug("no data yet for fd #%d, continuing...", args->netfd);
continue;
}
// ret is "no position" when the socket is closed from the other end of
the connection,
// so we're done.
- if (ret == string::npos) {
+ if ((ret == string::npos) || (ret == -1)) {
+ log_debug("socket for fd #%d was closed...", args->netfd);
break;
}
// We got data. Resize the buffer if necessary.
Index: libnet/netstats.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/netstats.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libnet/netstats.h 28 Mar 2008 21:30:26 -0000 1.2
+++ libnet/netstats.h 3 May 2008 18:44:08 -0000 1.3
@@ -84,6 +84,30 @@
AUDIO,
VIDEO
} filetypes_e;
+ // This is what the ActionScript 'Client' class returns:
+ typedef struct {
+ int bytes_in; // Total number of bytes received.
+ int bytes_out; // Total number of bytes sent.
+ int msg_in; // Total number of RTMP messages received.
+ int msg_out; // Total number of RTMP messages sent.
+ int msg_dropped; // Total number of dropped RTMP messages.
+ int ping_rtt; // Length of time the client takes to respond
to a ping message.
+ int audio_queue_msgs; // Current number of audio messages in the
queue waiting to be delivered to the client.
+ int video_queue_msgs; // Current number of video messages in the
queue waiting to be delivered to the client.
+ int so_queue_msgs; // Current number of shared object messages in
the queue waiting to be delivered to the client.
+ int data_queue_msgs; // Current number of data messages in the queue
waiting to be delivered to the client.
+ int dropped_audio_msgs; // Number of audio messages that were
dropped.
+ int dropped_video_msgs; // Number of video messages that were
dropped.
+ int audio_queue_bytes; // Total size of all audio messages (in bytes)
in the queue waiting to be delivered to the client.
+ int video_queue_bytes; // Total size of all video messages (in bytes)
in the queue waiting to be delivered to the client.
+ int so_queue_bytes; // Total size of all shared object messages (in
bytes) in the queue waiting to be delivered to the client.
+ int data_queue_bytes; // Total size of all data messages (in bytes)
in the queue waiting to be delivered to the client.
+ int dropped_audio_bytes;// Total size of all audio messages (in bytes)
that were dropped.
+ int dropped_video_bytes;// Total size of all video messages (in bytes)
that were dropped.
+ int bw_out; // Current upstream (client to server)
bandwidth for this client.
+ int bw_in; // Current downstream (server to client)
bandwidth for this client.
+ int client_id; // A unique ID issued by the server for this
client.
+ } netstats_t;
// start the clock counting down
boost::posix_time::ptime startClock();
// stop the clock from counting down
Index: libnet/network.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/network.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libnet/network.h 1 Apr 2008 22:20:38 -0000 1.2
+++ libnet/network.h 3 May 2008 18:44:08 -0000 1.3
@@ -60,7 +60,7 @@
#endif
// Adjust for the constant size
-const size_t NETBUFSIZE = 2048; // 1500 appears to be the default size
as used by FMS
+const size_t NETBUFSIZE = 1357*2; // 1500 appears to be the default size
as used by FMS
class Network {
public:
Index: libnet/rtmp.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- libnet/rtmp.cpp 30 Apr 2008 18:19:41 -0000 1.9
+++ libnet/rtmp.cpp 3 May 2008 18:44:08 -0000 1.10
@@ -240,54 +240,148 @@
}
#endif
+RTMP::rtmp_head_t *
+RTMP::decodeHeader(Network::byte_t *in)
+{
+ GNASH_REPORT_FUNCTION;
+
+ Network::byte_t *tmpptr = in;
+
+ _header.channel = *tmpptr & RTMP_INDEX_MASK;
+ log_debug (_("The AMF channel index is %d"), _header.channel);
+
+ _header.head_size = headerSize(*tmpptr++);
+ printf (_("The header size is %d"), _header.head_size);
+
+ if (_header.head_size >= 4) {
+ _mystery_word = *tmpptr++;
+ _mystery_word = (_mystery_word << 12) + *tmpptr++;
+ _mystery_word = (_mystery_word << 8) + *tmpptr++;
+ log_debug(_("The mystery word is: %d"), _mystery_word);
+ }
+
+ if (_header.head_size >= 8) {
+ _header.bodysize = *tmpptr++;
+ _header.bodysize = (_header.bodysize << 12) + *tmpptr++;
+ _header.bodysize = (_header.bodysize << 8) + *tmpptr++;
+ _header.bodysize = _header.bodysize & 0xffffff;
+ log_debug(_("The body size is: %d"), _header.bodysize);
+ }
+
+ if (_header.head_size >= 8) {
+ _header.type = *(content_types_e *)tmpptr;
+ tmpptr++;
+ log_debug(_("The type is: %s"), content_str[_header.type]);
+ }
+
+// switch(_header.type) {
+// case CHUNK_SIZE:
+// case BYTES_READ:
+// case PING:
+// case SERVER:
+// case CLIENT:
+// case VIDEO_DATA:
+// case NOTIFY:
+// case SHARED_OBJ:
+// case INVOKE:
+// _packet_size = RTMP_VIDEO_PACKET_SIZE;
+// break;
+// case AUDIO_DATA:
+// _packet_size = RTMP_AUDIO_PACKET_SIZE;
+// break;
+// default:
+// log_error (_("ERROR: Unidentified AMF header data type 0x%x"),
_type);
+// break;
+// };
+
+ if (_header.head_size == 12) {
+ _header.src_dest = *(reinterpret_cast<rtmp_source_e *>(tmpptr));
+ tmpptr += sizeof(unsigned int);
+ log_debug(_("The source/destination is: %x"), _header.src_dest);
+ }
+
+ return &_header;
+}
+
/// \brief \ Each RTMP header consists of the following:
///
/// * Index & header size - The header size and amf channel index.
/// * Total size - The total size of the message
/// * Type - The type of the message
/// * Routing - The source/destination of the message
-Network::byte_t *
-RTMP::encodeRTMPHeader(int amf_index, rtmp_headersize_e head_size,
+//
+// There are 3 size of RTMP headers, 1, 4, 8, and 12.
+amf::Buffer *
+RTMP::encodeHeader(int amf_index, rtmp_headersize_e head_size,
size_t total_size, content_types_e type,
rtmp_source_e routing)
{
-// GNASH_REPORT_FUNCTION;
- Network::byte_t *out = new Network::byte_t[total_size + 12 + 4];
- memset(out, 0, total_size + 12 + 4);
- char *tmpptr = reinterpret_cast<char *>(out);
- // Make the index & header size byte
- *tmpptr = head_size & RTMP_HEADSIZE_MASK;
- *tmpptr += amf_index & RTMP_INDEX_MASK;
- tmpptr++;
+ GNASH_REPORT_FUNCTION;
+
+ amf::Buffer *buf;
+ switch(head_size) {
+ case HEADER_1:
+ buf = new Buffer(1);
+ break;
+ case HEADER_4:
+ buf = new Buffer(4);
+ break;
+ case HEADER_8:
+ buf = new Buffer(8);
+ break;
+ case HEADER_12:
+ buf = new Buffer(12);
+ break;
+ }
+
+// FIXME: this is only to make this more readeable with GDB, and is a
performance hit.
+// buf->clear();
+ Network::byte_t *ptr = buf->reference();
+
+ // Make the channel index & header size byte
+ *ptr = head_size & RTMP_HEADSIZE_MASK;
+ *ptr += amf_index & RTMP_INDEX_MASK;
+ ptr++;
// Add the unknown bytes. These seem to be used by video and
// audio, and only when the header size is 4 or more.
- if (head_size <= HEADER_4) {
- memset(tmpptr, 0, 3);
- tmpptr += 3;
+ if ((head_size == HEADER_4) || (head_size == HEADER_8) || (head_size ==
HEADER_12)) {
+ memset(ptr, 0, 3);
+ ptr += 3;
}
// Add the size of the message if the header size is 8 or more.
- if (head_size <= HEADER_8) {
+ // and add the type of the object if the header size is 8 or more.
+ if ((head_size == HEADER_8) || (head_size == HEADER_12)) {
int length = total_size;
- swapBytes(&length, 4);
- memcpy(tmpptr, ((char *)&length +1), 3);
- tmpptr += 3;
- }
-
- // Add the type of the objectif the header size is 8 or more.
- if (head_size <= HEADER_8) {
- *tmpptr = type;
- tmpptr++;
+ Network::byte_t *lenptr = reinterpret_cast<Network::byte_t *>(&length);
+//#ifndef BOOST_BIG_ENDIAN
+// swapBytes(&length, 4);
+ *ptr++ = *(lenptr + 2);
+ *ptr++ = *(lenptr + 1);
+ *ptr++ = *lenptr;
+// *(lenptr + 3) = *(lenptr);
+// memcpy(ptr, lenptr, 3);
+// #else
+// #ifdef BOOST_BIG_ENDIAN
+// memcpy(ptr, &length, 3);
+// #else
+// #error "No Endianess specified!"
+// #endif
+//#endif
+// swapBytes(&length, 4);
+// ptr += 3;
+ *ptr = type;
+ ptr++;
}
- // Add the routing of the message if the header size is 12 or more.
+ // Add the routing of the message if the header size is 12, the maximum.
if (head_size == HEADER_12) {
- memcpy(tmpptr, &routing, 4);
- tmpptr += 4;
+ memcpy(ptr, &routing, 4);
+ ptr += 4;
}
- return out;
+ return buf;
}
bool
@@ -295,7 +389,7 @@
{
GNASH_REPORT_FUNCTION;
- int packetsize = 0;
+// int packetsize = 0;
unsigned int amf_index, headersize;
Network::byte_t *ptr = buf->reference();
Network::byte_t *tooFar = ptr+buf->size();
@@ -308,7 +402,7 @@
log_debug (_("The AMF index is: 0x%x"), amf_index);
// if (headersize > 1) {
-// packetsize = parseHeader(ptr);
+// packetsize = decodeHeader(ptr);
// if (packetsize) {
// log_debug (_("Read first RTMP packet header of size %d"),
packetsize);
// } else {
@@ -324,7 +418,8 @@
log_debug("END is %x", (void *)end);
*end = '*';
#endif
- ptr = parseHeader(ptr);
+
+// ptr = decodeHeader(ptr);
// ptr += headersize;
amf::Element *el = amf.extractAMF(ptr, tooFar);
@@ -339,8 +434,8 @@
el->dump();
}
ptr += 1;
- size_t actual_size = static_cast<size_t>(_total_size - AMF_HEADER_SIZE);
- log_debug("Total size in header is %d, buffer size is: %d", _total_size,
buf->size());
+ size_t actual_size = static_cast<size_t>(_header.bodysize -
AMF_HEADER_SIZE);
+ log_debug("Total size in header is %d, buffer size is: %d",
_header.bodysize, buf->size());
// buf->dump();
if (buf->size() < actual_size) {
log_debug("FIXME: MERGING");
@@ -383,67 +478,196 @@
}
}
-Network::byte_t *
-RTMP::parseHeader(Network::byte_t *in)
+// A Ping packet has two parameters that ae always specified, and 2 that are
optional.
+// The first two bytes are the ping type, as in rtmp_ping_e, the second is the
ping
+// target, which is always zero as far as we can tell.
+//
+// More notes from: http://jira.red5.org/confluence/display/docs/Ping
+// type 0: Clear the stream. No third and fourth parameters. The second
parameter could be 0.
+// After the connection is established, a Ping 0,0 will be sent from server to
client. The
+// message will also be sent to client on the start of Play and in response of
a Seek or
+// Pause/Resume request. This Ping tells client to re-calibrate the clock with
the timestamp
+// of the next packet server sends.
+// type 1: Tell the stream to clear the playing buffer.
+// type 3: Buffer time of the client. The third parameter is the buffer time
in millisecond.
+// type 4: Reset a stream. Used together with type 0 in the case of VOD. Often
sent before type 0.
+// type 6: Ping the client from server. The second parameter is the current
time.
+// type 7: Pong reply from client. The second parameter is the time the server
sent with his
+// ping request.
+amf::Buffer *
+RTMP::encodeChunkSize()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeChunkSize()
{
-// GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
+}
- Network::byte_t *tmpptr = in;
+amf::Buffer *
+RTMP::encodeBytesRead()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeBytesRead()
+{
+ GNASH_REPORT_FUNCTION;
+}
- _amf_index = *tmpptr & RTMP_INDEX_MASK;
- log_debug (_("The AMF channel index is %d"), _amf_index);
+// A RTMP Ping packet looks like this: "03 00 00 00 00 00 00 0B B8", which is
the
+// Ping type byte, followed by two shorts that are the parameters. Only the
first
+// two paramters are required.
+amf::Buffer *
+RTMP::encodePing(rtmp_ping_e type, boost::uint16_t milliseconds)
+{
+ GNASH_REPORT_FUNCTION;
+ Buffer *buf = new Buffer(sizeof(boost::uint16_t) * 4);
+ Network::byte_t *ptr = buf->reference();
+ buf->clear(); // default everything to zeros, real data gets
optionally added.
+ boost::uint16_t typefield = *reinterpret_cast<boost::uint16_t *>(&type);
+ ptr += sizeof(boost::uint16_t); // go past the first short
+
+ boost::uint16_t swapped = 0;
+ buf->copy(typefield);
+ switch (type) {
+ // These two don't appear to have any paramaters
+ case PING_CLEAR:
+ case PING_PLAY:
+ break;
+ // the third parameter is the buffer time in milliseconds
+ case PING_TIME:
+ {
+ ptr += sizeof(boost::uint16_t); // go past the second short
+ swapped = htons(milliseconds);
+ buf->append(swapped);
+ break;
+ }
+ // reset doesn't have any parameters
+ case PING_RESET:
+ break;
+ // For Ping and Pong, the second parameter is always the milliseconds
+ case PING_CLIENT:
+ case PONG_CLIENT:
+ {
+ swapped = htons(milliseconds);
+// std::copy(&swapped, &swapped + sizeof(boost::uint16_t), ptr);
+ buf->append(swapped);
+ break;
+ }
+ default:
+ return 0;
+ break;
+ };
- _header_size = headerSize(*tmpptr++);
- printf (_("The header size is %d"), _header_size);
+ return buf;
+}
+RTMP::rtmp_ping_t *
+RTMP::decodePing(Network::byte_t *data)
+{
+ GNASH_REPORT_FUNCTION;
- if (_header_size >= 4) {
- _mystery_word = *tmpptr++;
- _mystery_word = (_mystery_word << 12) + *tmpptr++;
- _mystery_word = (_mystery_word << 8) + *tmpptr++;
- log_debug(_("The mystery word is: %d"), _mystery_word);
- }
+ Network::byte_t *ptr = reinterpret_cast<Network::byte_t *>(data);
+ rtmp_ping_t *ping = new rtmp_ping_t;
+ memset(ping, 0, sizeof(rtmp_ping_t));
- if (_header_size >= 8) {
- _total_size = *tmpptr++;
- _total_size = (_total_size << 12) + *tmpptr++;
- _total_size = (_total_size << 8) + *tmpptr++;
- _total_size = _total_size & 0xffffff;
- log_debug(_("The body size is: %d"), _total_size);
- }
+ boost::uint16_t type = *reinterpret_cast<rtmp_ping_e *>(ptr);
+ ping->type = static_cast<rtmp_ping_e>(type);
+ ptr += sizeof(boost::uint16_t);
- if (_header_size >= 8) {
- _type = *(content_types_e *)tmpptr;
- tmpptr++;
- log_debug(_("The type is: %s"), content_str[_type]);
- }
+ ping->target = *reinterpret_cast<boost::uint16_t *>(ptr);
+ ptr += sizeof(boost::uint16_t);
-// switch(_type) {
-// case CHUNK_SIZE:
-// case BYTES_READ:
-// case PING:
-// case SERVER:
-// case CLIENT:
-// case VIDEO_DATA:
-// case NOTIFY:
-// case SHARED_OBJ:
-// case INVOKE:
-// _packet_size = RTMP_VIDEO_PACKET_SIZE;
-// break;
-// case AUDIO_DATA:
-// _packet_size = RTMP_AUDIO_PACKET_SIZE;
-// break;
-// default:
-// log_error (_("ERROR: Unidentified AMF header data type 0x%x"),
_type);
-// break;
-// };
+ ping->param1 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
+ ptr += sizeof(boost::uint16_t);
- if (_header_size == 12) {
- _src_dest = *(reinterpret_cast<rtmp_source_e *>(tmpptr));
- tmpptr += sizeof(unsigned int);
- log_debug(_("The source/destination is: %x"), _src_dest);
- }
+ ping->param1 = ntohs(*reinterpret_cast<boost::uint16_t *>(ptr));
+
+ return ping;
+}
+RTMP::rtmp_ping_t *
+RTMP::decodePing(amf::Buffer *buf)
+{
+ GNASH_REPORT_FUNCTION;
+ return decodePing(buf->reference());
+}
+
+amf::Buffer *
+RTMP::encodeServer()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeServer()
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+amf::Buffer *
+RTMP::encodeClient()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeClient()
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+amf::Buffer *
+RTMP::encodeAudioData()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeAudioData()
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+amf::Buffer *
+RTMP::encodeVideoData()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeVideoData()
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+amf::Buffer *
+RTMP::encodeNotify()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeNotify()
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+amf::Buffer *
+RTMP::encodeSharedObj()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeSharedObj()
+{
+ GNASH_REPORT_FUNCTION;
+}
- return tmpptr;
+amf::Buffer *
+RTMP::encodeInvoke()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMP::decodeInvoke()
+{
+ GNASH_REPORT_FUNCTION;
}
} // end of gnash namespace
Index: libnet/rtmp.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- libnet/rtmp.h 30 Apr 2008 03:48:52 -0000 1.7
+++ libnet/rtmp.h 3 May 2008 18:44:08 -0000 1.8
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -40,6 +40,7 @@
const char RTMP_INDEX_MASK = 0x3f;
const int RTMP_VIDEO_PACKET_SIZE = 128;
const int RTMP_AUDIO_PACKET_SIZE = 64;
+const int RTMP_MAX_HEADER_SIZE = 12;
// For terminating sequences, a byte with value 0x09 is used.
const char TERMINATOR = 0x09;
@@ -109,6 +110,20 @@
// INITIAL_DATA = 0xb
// } sharedobj_types_e;
typedef enum {
+ PING_CLEAR = 0x0, // clear the stream
+ PING_PLAY = 0x1, // clear the playing buffer
+ PING_TIME = 0x3, // Buffer time in milliseconds
+ PING_RESET = 0x4, // Reset stream
+ PING_CLIENT = 0x6, // Ping the client from the server
+ PONG_CLIENT = 0x7 // pong reply from client to server
+ } rtmp_ping_e;
+ typedef struct {
+ rtmp_ping_e type; // the type of the ping message
+ boost::uint16_t target;
+ boost::uint16_t param1;
+ boost::uint16_t param2;
+ } rtmp_ping_t;
+ typedef enum {
RTMP_STATE_HANDSHAKE_SEND,
RTMP_STATE_HANDSHAKE_RECV,
RTMP_STATE_HANDSHAKE_ACK,
@@ -132,16 +147,17 @@
} rtmp_error_t;
// Each header consists of the following:
-//
-// * UTF string (including length bytes) - name
-// * Boolean - specifies if understanding the header is `required'
-// * Long - Length in bytes of header
-// * Variable - Actual data (including a type code)
+// a single byte that is the index of the RTMP channel,
+// then two bits that's a flag to note the size of the header,
+// which can be 1, 4, 8, or 12 bytes long.
+
+// More info at http://wiki.gnashdev.org/RTMP
typedef struct {
- amf::amfutf8_t name;
- boost::uint8_t required;
- boost::uint32_t length;
- void *data;
+ int channel;
+ int head_size;
+ int bodysize;
+ rtmp_source_e src_dest;
+ content_types_e type;
} rtmp_head_t;
typedef enum {
HEADER_12 = 0x0,
@@ -165,14 +181,15 @@
RTMP();
~RTMP();
- gnash::Network::byte_t *encodeRTMPHeader(int amf_index, rtmp_headersize_e
head_size,
+
+ // Decode
+ rtmp_head_t *decodeHeader(gnash::Network::byte_t *header);
+ rtmp_head_t *decodeHeader(amf::Buffer *data);
+ amf::Buffer *encodeHeader(int amf_index, rtmp_headersize_e head_size,
size_t total_size, content_types_e type,
rtmp_source_e routing);
-// bool handShakeWait();
bool handShakeRequest();
-// bool handShakeResponse();
bool clientFinish();
-// bool serverFinish();
bool packetRequest();
bool packetSend(amf::Buffer *buf);
bool packetRead(amf::Buffer *buf);
@@ -183,37 +200,54 @@
amf::Element *getProperty(const std::string &name);
void setHandler(Handler *hand) { _handler = hand; };
int headerSize(gnash::Network::byte_t header);
- Network::byte_t *parseHeader(gnash::Network::byte_t *header);
- int getHeaderSize() { return _header_size; };
- int getTotalSize() { return _total_size; };
+ rtmp_head_t *getHeader() { return &_header; };
+ int getHeaderSize() { return _header.head_size; };
+ int getTotalSize() { return _header.bodysize; };
+ rtmp_source_e getRouting() { return _header.src_dest; };
+ int getChannel() { return _header.channel; };
int getPacketSize() { return _packet_size; };
int getMysteryWord() { return _mystery_word; };
- rtmp_source_e getRouting() { return _src_dest; };
- int getAMFIndex() { return _amf_index; };
- //
- bool chunk_size();
- bool bytes_read();
- bool ping();
- bool server();
- bool client();
- bool audio_data();
- bool video_data();
- bool notify();
- bool shared_obj();
- bool invoke();
+ // These are handlers for the various types
+ virtual amf::Buffer *encodeChunkSize();
+ virtual void decodeChunkSize();
+
+ virtual amf::Buffer *encodeBytesRead();
+ virtual void decodeBytesRead();
+
+ virtual amf::Buffer *encodePing(rtmp_ping_e type, boost::uint16_t
milliseconds);
+ virtual rtmp_ping_t *decodePing(Network::byte_t *data);
+ rtmp_ping_t *decodePing(amf::Buffer *buf);
+
+ virtual amf::Buffer *encodeServer();
+ virtual void decodeServer();
+
+ virtual amf::Buffer *encodeClient();
+ virtual void decodeClient();
+
+ virtual amf::Buffer *encodeAudioData();
+ virtual void decodeAudioData();
+
+ virtual amf::Buffer *encodeVideoData();
+ virtual void decodeVideoData();
+
+ virtual amf::Buffer *encodeNotify();
+ virtual void decodeNotify();
+
+ virtual amf::Buffer *encodeSharedObj();
+ virtual void decodeSharedObj();
+
+ virtual amf::Buffer *encodeInvoke();
+ virtual void decodeInvoke();
+
void dump();
protected:
std::map<const char *, amf::Element *> _variables;
amf::Buffer *_handshake;
Handler *_handler;
- int _amf_index;
- int _header_size;
- int _total_size;
+ rtmp_head_t _header;
int _packet_size;
- rtmp_source_e _src_dest;
- content_types_e _type;
int _mystery_word;
};
Index: libnet/rtmp_server.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_server.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libnet/rtmp_server.cpp 30 Apr 2008 03:48:52 -0000 1.4
+++ libnet/rtmp_server.cpp 3 May 2008 18:44:08 -0000 1.5
@@ -80,18 +80,11 @@
log_debug("Que empty, net connection dropped for fd #%d",
_handler->getFileFd());
return false;
}
-// if (readNet(buffer, 1) == 1) {
- log_debug (_("Read initial Handshake Request"));
-// } else {
-// log_error (_("Couldn't read initial Handshake Request"));
-// return false;
-// }
-// _inbytes += 1;
- if (*(buf->reference()) == 0x3) {
- log_debug (_("Handshake is correct"));
+ if (*buf->reference() == RTMP_HANDSHAKE) {
+ log_debug (_("Handshake request is correct"));
} else {
- log_error (_("Handshake isn't correct"));
+ log_error (_("Handshake request isn't correct"));
return false;
}
@@ -104,11 +97,11 @@
_handshake->copy(buf->reference() + 1, RTMP_BODY_SIZE);
log_debug (_("Handshake Data matched"));
delete buf; // we're done with the buffer
- return true;
+// return true;
} else {
delete buf; // we're done with the buffer
log_error (_("Handshake Data didn't match"));
- return false;
+// return false;
}
return true;
@@ -121,13 +114,18 @@
{
GNASH_REPORT_FUNCTION;
- amf::Buffer *buf = new amf::Buffer((RTMP_BODY_SIZE * 2) + 1);
- Network::byte_t *ptr = buf->reference();
- *ptr = 0x3;
-
- std::copy(_handshake->begin(), _handshake->end(), (ptr + 1));
- std::copy(_handshake->begin(), _handshake->end(), ptr + _handshake->size()
+ 1);
- _handler->pushout(buf);
+ amf::Buffer *buf1 = new amf::Buffer(RTMP_BODY_SIZE + 1);
+ *buf1->begin() = RTMP_HANDSHAKE;
+ buf1->append(_handshake);
+ _handler->pushout(buf1);
+
+ amf::Buffer *buf2 = new amf::Buffer(RTMP_BODY_SIZE);
+ buf2->copy(_handshake->begin(), RTMP_BODY_SIZE);
+ _handler->pushout(buf2);
+
+// std::copy(_handshake->begin(), _handshake->end(), (buf1->begin() + 1));
+// amf::Buffer *buf = new amf::Buffer(RTMP_BODY_SIZE + 1);
+// std::copy(_handshake->begin(), _handshake->end(), buf->begin() + 1 +
RTMP_BODY_SIZE);
_handler->notifyout();
log_debug("Sent RTMP Handshake response");
@@ -152,7 +150,7 @@
// So after the handshake block, we strip that part off, and just pass on
// the remainder for processing.
if (buf->size() > RTMP_BODY_SIZE) {
- int size = buf->size() - RTMP_BODY_SIZE;
+ size_t size = buf->size() - RTMP_BODY_SIZE;
obj = new amf::Buffer[size];
obj->copy(buf->begin()+RTMP_BODY_SIZE, size);
} else {
@@ -215,8 +213,33 @@
log_debug("END is %x", (void *)end);
*end = '*';
#endif
- ptr = parseHeader(ptr);
-// ptr += headersize;
+ rtmp_head_t *head = decodeHeader(ptr);
+ ptr += headersize;
+
+ Network::byte_t* tooFar = ptr+300+sizeof(int); // FIXME:
+
+ AMF amf_obj;
+ amf::Element *el1 = amf_obj.extractAMF(ptr, tooFar);
+ ptr += amf_obj.totalsize();
+ amf::Element *el2 = amf_obj.extractAMF(ptr, tooFar);
+
+ int size = 0;
+ amf::Element *el;
+ while ( size < static_cast<boost::uint16_t>(_header.bodysize) - 24 ) {
+ if (ptr) {
+ el = amf_obj.extractProperty(ptr, tooFar);
+ if (el != 0) {
+ size += amf_obj.totalsize();
+ ptr += amf_obj.totalsize();
+// _variables[el->getName()] = el;
+ } else {
+ break;
+ }
+// log_debug("Bodysize is: %d size is: %d for %s", _total_size,
size, el->getName());
+ } else {
+ break;
+ }
+ }
# if 0
Element el;
@@ -253,21 +276,58 @@
RTMPproto::dump();
#endif
- switch(_type) {
+ switch(_header.type) {
case CHUNK_SIZE:
+ decodeChunkSize();
+ break;
case BYTES_READ:
+ decodeBytesRead();
+ break;
case PING:
+ {
+ rtmp_ping_t *ping = decodePing(ptr);
+ switch (ping->type) {
+ case PING_CLEAR:
+ break;
+ case PING_PLAY:
+ break;
+ case PING_TIME:
+ break;
+ case PING_RESET:
+ break;
+ case PING_CLIENT:
+ break;
+ case PONG_CLIENT:
+ break;
+ default:
+ return 0;
+ break;
+ };
+ break;
+ }
case SERVER:
+ decodeServer();
+ break;
case CLIENT:
+ decodeClient();
+ break;
case VIDEO_DATA:
+ decodeVideoData();
+ break;
case NOTIFY:
+ decodeNotify();
+ break;
case SHARED_OBJ:
+ decodeSharedObj();
+ break;
case INVOKE:
+ decodeInvoke();
break;
case AUDIO_DATA:
+ decodeAudioData();
break;
default:
- log_error (_("ERROR: Unidentified RTMP message content type 0x%x"),
_type);
+ log_error (_("ERROR: Unidentified RTMP message content type 0x%x"),
_header.type);
break;
};
@@ -288,68 +348,107 @@
return true;
}
+#if 0
// These process the incoming AMF object types from the data stream
-Network::byte_t *
-RTMPServer::decodeChunkSize(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeChunkSize()
{
GNASH_REPORT_FUNCTION;
}
-
-Network::byte_t *
-RTMPServer::decodeBytesRead(Network::byte_t *buf)
+void
+RTMPServer::decodeChunkSize()
{
GNASH_REPORT_FUNCTION;
}
-Network::byte_t *
-RTMPServer::decodePing(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeBytesRead()
{
GNASH_REPORT_FUNCTION;
}
-
-Network::byte_t *
-RTMPServer::decodeServer(Network::byte_t *buf)
+void
+RTMPServer::decodeBytesRead()
{
GNASH_REPORT_FUNCTION;
}
-Network::byte_t *
-RTMPServer::decodeClient(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeServer()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeServer()
{
GNASH_REPORT_FUNCTION;
}
-Network::byte_t *
-RTMPServer::decodeAudioData(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeClient()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeClient()
{
GNASH_REPORT_FUNCTION;
}
-Network::byte_t *
-RTMPServer::decodeVideoData(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeAudioData()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeAudioData()
{
GNASH_REPORT_FUNCTION;
}
-Network::byte_t *
-RTMPServer::decodeNotify(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeVideoData()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeVideoData()
{
GNASH_REPORT_FUNCTION;
}
-Network::byte_t *
-RTMPServer::decodeSharedObj(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeNotify()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeNotify()
{
GNASH_REPORT_FUNCTION;
}
-// Invoke a remote procedure call for an ActionScript class.
-Network::byte_t *
-RTMPServer::decodeInvoke(Network::byte_t *buf)
+amf::Buffer *
+RTMPServer::encodeSharedObj()
+{
+ GNASH_REPORT_FUNCTION;
+}
+void
+RTMPServer::decodeSharedObj()
{
GNASH_REPORT_FUNCTION;
+}
+amf::Buffer *
+RTMPServer::encodeInvoke()
+{
+ GNASH_REPORT_FUNCTION;
}
+void
+RTMPServer::decodeInvoke()
+{
+ GNASH_REPORT_FUNCTION;
+}
+#endif
// This is the thread for all incoming RTMP connections
void
Index: libnet/rtmp_server.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_server.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libnet/rtmp_server.h 1 Apr 2008 22:20:39 -0000 1.2
+++ libnet/rtmp_server.h 3 May 2008 18:44:08 -0000 1.3
@@ -42,17 +42,36 @@
bool packetSend(amf::Buffer *buf);
bool packetRead(amf::Buffer *buf);
- // These process the incoming RTMP message content types from the header
- gnash::Network::byte_t *decodeChunkSize(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeBytesRead(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodePing(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeServer(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeClient(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeAudioData(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeVideoData(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeNotify(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeSharedObj(gnash::Network::byte_t *buf);
- gnash::Network::byte_t *decodeInvoke(gnash::Network::byte_t *buf);
+ // These are handlers for the various types
+#if 0
+ amf::Buffer *encodeChunkSize();
+ void decodeChunkSize();
+
+ amf::Buffer *encodeBytesRead();
+ void decodeBytesRead();
+
+ amf::Buffer *encodeServer();
+ void decodeServer();
+
+ amf::Buffer *encodeClient();
+ void decodeClient();
+
+ amf::Buffer *encodeAudioData();
+ void decodeAudioData();
+
+ amf::Buffer *encodeVideoData();
+ void decodeVideoData();
+
+ amf::Buffer *encodeNotify();
+ void decodeNotify();
+
+ amf::Buffer *encodeSharedObj();
+ void decodeSharedObj();
+
+ amf::Buffer *encodeInvoke();
+ void decodeInvoke();
+#endif
+
void dump();
private:
};
Index: testsuite/libnet.all/test_rtmp.cpp
===================================================================
RCS file: testsuite/libnet.all/test_rtmp.cpp
diff -N testsuite/libnet.all/test_rtmp.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/libnet.all/test_rtmp.cpp 3 May 2008 18:44:06 -0000 1.1
@@ -0,0 +1,276 @@
+//
+// Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#ifdef HAVE_DEJAGNU_H
+
+//#include <netinet/in.h>
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <iostream>
+#include <string>
+
+#include "as_object.h"
+#include "dejagnu.h"
+#include "log.h"
+#include "amf.h"
+#include "rtmp_server.h"
+#include "rtmp.h"
+#include "buffer.h"
+#include "network.h"
+#include "element.h"
+#include "sol.h"
+#include "arg_parser.h"
+#include "gmemory.h"
+
+using namespace amf;
+using namespace gnash;
+using namespace std;
+
+static void usage (void);
+
+// Enable the display of memory allocation and timing data
+static bool memdebug = false;
+
+// We use the Memory profiling class to check the malloc buffers
+// in the kernel to make sure the allocations and frees happen
+// the way we expect them too. There is no real other way to tell.
+#if defined(HAVE_MALLINFO) && defined(USE_STATS_MEMORY)
+Memory *mem = 0;
+#endif
+
+static TestState runtest;
+
+static void test_header();
+static void test_types();
+
+LogFile& dbglogfile = LogFile::getDefaultInstance();
+
+// These next two functions are borrowed from Libgloss, part of the GNU
binutils,
+// of which I am the primary author and copyright holder.
+// convert an ascii hex digit to a number.
+// param is hex digit.
+// returns a decimal digit.
+Network::byte_t
+hex2digit (Network::byte_t digit)
+{
+ if (digit == 0)
+ return 0;
+
+ if (digit >= '0' && digit <= '9')
+ return digit - '0';
+ if (digit >= 'a' && digit <= 'f')
+ return digit - 'a' + 10;
+ if (digit >= 'A' && digit <= 'F')
+ return digit - 'A' + 10;
+
+ // shouldn't ever get this far
+ return -1;
+}
+
+// Convert the hex array pointed to by buf into binary to be placed in mem
+Buffer *
+hex2mem(const char *str)
+{
+ size_t count = strlen(str);
+ Network::byte_t ch = 0;
+ Buffer *buf = new Buffer(count + 12);
+ buf->clear();
+
+ Network::byte_t *ptr = const_cast<Network::byte_t
*>(reinterpret_cast<const Network::byte_t *>(str));
+
+ for (size_t i=0; i<count; i++) {
+ if (*ptr == ' ') { // skip spaces.
+ ptr++;
+ continue;
+ }
+ ch = hex2digit(*ptr++) << 4;
+ ch |= hex2digit(*ptr++);
+ buf->append(ch);
+ }
+ return buf;
+}
+
+int
+main(int argc, char *argv[])
+{
+ const Arg_parser::Option opts[] =
+ {
+ { 'h', "help", Arg_parser::no },
+ { 'v', "verbose", Arg_parser::no },
+ { 'w', "write", Arg_parser::no },
+// Unless you have support for memory debugging turned on, and
+// you have support for the Linux mallinfo() system call,
+// this option is totally useless. This doesn't really matter
+// as the memory testing is primarily used only during
+// debugging or development.
+ { 'm', "memstats", Arg_parser::no },
+ { 'd', "dump", Arg_parser::no },
+ };
+
+ Arg_parser parser(argc, argv, opts);
+ if( ! parser.error().empty() ) {
+ cout << parser.error() << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ for( int i = 0; i < parser.arguments(); ++i ) {
+ const int code = parser.code(i);
+ try {
+ switch( code ) {
+ case 'h':
+ usage ();
+ exit(EXIT_SUCCESS);
+ case 'v':
+ dbglogfile.setVerbosity();
+ log_debug(_("Verbose output turned on"));
+ break;
+ case 'm':
+ log_debug(_("Enabling memory statistics"));
+ memdebug = true;
+ break;
+ }
+ }
+
+ catch (Arg_parser::ArgParserException &e) {
+ cerr << _("Error parsing command line options: ") << e.what() <<
endl;
+ cerr << _("This is a Gnash bug.") << endl;
+ }
+ }
+
+#if defined(HAVE_MALLINFO) && defined(USE_STATS_MEMORY)
+ if (memdebug) {
+ mem = new Memory;
+ mem->startStats();
+ }
+#endif
+
+ test_header();
+ test_types();
+}
+
+void
+test_header()
+{
+ GNASH_REPORT_FUNCTION;
+ RTMP rtmp;
+
+ // this is a sample 12 bytes RTMP header
+ const char *x = "03 00 00 00 00 01 1f 14 00 00 00 00";
+ Buffer *buf1 = hex2mem(x);
+ Buffer *head = rtmp.encodeHeader(0x3, RTMP::HEADER_12, 287,
+ RTMP::INVOKE, RTMP::FROM_CLIENT);
+// cerr << hexify(head->begin(), 12, false) << endl;
+
+ if ((memcmp(buf1->reference(), head->reference(), 12) == 0)) {
+ runtest.pass("Encoded RTMP header");
+ } else {
+ runtest.fail("Encoded RTMP header");
+ }
+
+ RTMP::rtmp_head_t *header = rtmp.decodeHeader(buf1->reference());
+ if ((header->channel == 0x3) && (header->head_size == 12)
+ && (header->bodysize == 287) && (header->type == RTMP::INVOKE)) {
+ runtest.pass("Decoded RTMP header");
+ } else {
+ runtest.fail("Decoded RTMP header");
+ }
+
+ // cleanup after ourselves
+ delete buf1;
+ delete head;
+}
+
+
+void
+test_types()
+{
+ GNASH_REPORT_FUNCTION;
+ RTMP rtmp;
+
+ const char *x = "06 00 d2 04 00 00 00 00";
+ Buffer *buf1 = hex2mem(x);
+
+ RTMP::rtmp_ping_t *ping = rtmp.decodePing(buf1);
+ if (ping->type == RTMP::PING_CLIENT) {
+ runtest.pass("Decoded RTMP Ping message");
+ } else {
+ runtest.fail("Decoded RTMP Ping message");
+ }
+
+ Buffer *buf2 = rtmp.encodePing(RTMP::PING_CLIENT, 53764);
+ cerr << hexify(buf2->begin(), 8, false) << endl;
+ if ((memcmp(buf1->reference(), buf2->reference(), 8) == 0)) {
+ runtest.pass("Encoded RTMP Ping message");
+ } else {
+ runtest.fail("Encoded RTMP Ping message");
+ }
+ delete ping;
+ delete buf1;
+ delete buf2;
+}
+
+static void
+usage (void)
+{
+ cerr << "This program tests SOL support in the AMF library." << endl;
+ cerr << "Usage: test_sol [hv]" << endl;
+ cerr << "-h\tHelp" << endl;
+ cerr << "-v\tVerbose" << endl;
+ exit (-1);
+}
+
+#else
+
+int
+main(int /*argc*/, char /* *argv[]*/)
+{
+ // nop
+ return 0;
+}
+
+#endif
+
+// 03 00 00 04 00 01 1f 14 00 00 00 00 02 00 07 63 ...............c
+// 6f 6e 6e 65 63 74 00 3f f0 00 00 00 00 00 00 03 onnect.?........
+// 00 03 61 70 70 02 00 08 6f 66 6c 61 44 65 6d 6f ..app...oflaDemo
+// 00 08 66 6c 61 73 68 56 65 72 02 00 0c 4c 4e 58 ..flashVer...LNX
+// 20 39 2c 30 2c 33 31 2c 30 00 06 73 77 66 55 72 9,0,31,0..swfUr
+// 6c 02 00 33 68 74 74 70 3a 2f 2f 6c 6f 63 61 6c l..3http://local
+// 68 6f 73 74 2f 73 6f 66 74 77 61 72 65 2f 67 6e host/software/gn
+// 61 73 68 2f 74 65 73 74 73 2f 6f 66 6c 61 5f 64 ash/tests/ofla_d
+// 65 6d 6f 2e 73 77 66 00 05 74 63 55 c3 72 6c 02 emo.swf..tcU.rl.
+// 00 19 72 74 6d 70 3a 2f 2f 6c 6f 63 61 6c 68 6f ..rtmp://localho
+// 73 74 2f 6f 66 6c 61 44 65 6d 6f 00 04 66 70 61 st/oflaDemo..fpa
+// 64 01 00 00 0b 61 75 64 69 6f 43 6f 64 65 63 73 d....audioCodecs
+// 00 40 83 38 00 00 00 00 00 00 0b 76 69 64 65 6f address@hidden
+// 43 6f 64 65 63 73 00 40 5f 00 00 00 00 00 00 00 address@hidden
+// 0d 76 69 64 65 6f 46 75 6e 63 74 69 6f 6e 00 3f .videoFunction.?
+// f0 00 00 00 00 00 00 00 07 70 61 67 65 55 72 6c .........pageUrl
+// 02 00 26 68 74 74 70 3a 2f 2f 6c 6f 63 c3 61 6c ..&http://loc.al
+// 68 6f 73 74 2f 73 6f 66 74 77 61 72 65 2f 67 6e host/software/gn
+// 61 73 68 2f 74 65 73 74 73 2f 00 00 09
+
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libamf/...,
Rob Savoye <=