[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libnet/...
From: |
Rob Savoye |
Subject: |
[Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libnet/... |
Date: |
Fri, 06 Jun 2008 14:21:34 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Rob Savoye <rsavoye> 08/06/06 14:21:33
Modified files:
libamf : amf.cpp element.cpp
libnet : rtmp.h rtmp_client.cpp rtmp_client.h
testsuite/libnet.all: test_rtmp.cpp
. : ChangeLog
Log message:
* libamf/amf.cpp: Add support for NULL objects.
* libamf/element.cpp: Set the boolean data correctly, it was
offset by one byte. Make a NULL object.
* libnet/rtmp.h: Add Stream operations, play, stop, pause, seek,
publish.
* libnet/rtmp_client.{h,cpp}: Build NetStream operation packets.
* testsuite/libnet.all/test_rtmp.cpp: Test NetStream operations
packets for the client side.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.cpp?cvsroot=gnash&r1=1.80&r2=1.81
http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.cpp?cvsroot=gnash&r1=1.26&r2=1.27
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp.h?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_client.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/libnet/rtmp_client.h?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/libnet.all/test_rtmp.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6835&r2=1.6836
Patches:
Index: libamf/amf.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/amf.cpp,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -b -r1.80 -r1.81
--- libamf/amf.cpp 17 May 2008 20:10:36 -0000 1.80
+++ libamf/amf.cpp 6 Jun 2008 14:21:31 -0000 1.81
@@ -193,7 +193,6 @@
/// @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.
Buffer *
AMF::encodeBoolean(bool flag)
{
@@ -201,9 +200,6 @@
// Encode a boolean value. 0 for false, 1 for true
Buffer *buf = new Buffer(2);
buf->append(Element::BOOLEAN_AMF0);
-// Hum, AMF3 ???
-// boost::uint16_t x = flag;
-// swapBytes(&x, 2);
buf->append(flag);
return buf;
@@ -312,8 +308,10 @@
{
// GNASH_REPORT_FUNCTION;
- log_unimpl("NULL AMF object not supported yet");
- return 0;
+ Buffer *buf = new Buffer(1);
+ buf->append(Element::NULL_AMF0);
+
+ return buf;
}
/// Encode an XML object
@@ -514,6 +512,10 @@
} else {
outsize = el->getNameSize() + AMF_VAR_HEADER_SIZE;
}
+ // A NULL object is a single byte
+ if (el->getType() == Element::NULL_AMF0) {
+ outsize = 1;
+ }
buf = new Buffer(outsize);
buf->clear(); // FIXME: temporary, makes buffers cleaner in
gdb.
// If the name field is set, it's a "property", followed by the data
Index: libamf/element.cpp
===================================================================
RCS file: /sources/gnash/gnash/libamf/element.cpp,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- libamf/element.cpp 16 May 2008 03:46:21 -0000 1.26
+++ libamf/element.cpp 6 Jun 2008 14:21:32 -0000 1.27
@@ -597,7 +597,8 @@
// GNASH_REPORT_FUNCTION;
_type = Element::BOOLEAN_AMF0;
check_buffer(sizeof(bool));
- _buffer->append(flag);
+ *(_buffer->reference()) = flag;
+
return *this;
}
@@ -638,13 +639,12 @@
return makeUndefined();
}
+// a NULL amf Object consists of a single byte, which is the type
Element &
Element::makeNull()
{
// GNASH_REPORT_FUNCTION;
_type = Element::NULL_AMF0;
- check_buffer(sizeof(Network::byte_t));
- *(_buffer->reference()) = 0;
return *this;
}
Index: libnet/rtmp.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- libnet/rtmp.h 16 May 2008 03:46:26 -0000 1.9
+++ libnet/rtmp.h 6 Jun 2008 14:21:32 -0000 1.10
@@ -126,6 +126,13 @@
PING_CLIENT = 0x6, // Ping the client from the server
PONG_CLIENT = 0x7 // pong reply from client to server
} rtmp_ping_e;
+ typedef enum {
+ STREAM_PLAY, // play the existing stream
+ STREAM_PAUSE, // pause the existing stream
+ STREAM_PUBLISH, // publish the existing stream
+ STREAM_STOP, // stop the existing stream
+ STREAM_SEEK // seek in the existing stream
+ } rtmp_op_e;
typedef struct {
rtmp_ping_e type; // the type of the ping message
boost::uint16_t target; // all Ping message data fields
Index: libnet/rtmp_client.cpp
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_client.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libnet/rtmp_client.cpp 16 May 2008 03:46:27 -0000 1.1
+++ libnet/rtmp_client.cpp 6 Jun 2008 14:21:32 -0000 1.2
@@ -79,16 +79,16 @@
AMF amf_obj;
- Element *connect = new Element;
- connect->makeString("connect");
+ Element connect;
+ connect.makeString("connect");
- Element *connum = new Element;
+ Element connum;
// 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);
+ connum.makeNumber(_connections);
// Make the top level object
Element obj;
@@ -148,8 +148,8 @@
// 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 *conobj = connect.encode();
+ Buffer *numobj = connum.encode();
Buffer *encobj = obj.encode();
Buffer *buf = new Buffer(conobj->size() + numobj->size() + encobj->size());
@@ -158,6 +158,8 @@
buf->append(numobj);
buf->append(encobj);
+ // Now that we have an encoded buffer, nuke the Element
+
return buf;
}
@@ -165,19 +167,37 @@
// 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 */)
+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)));
+ Element str = new Element;
+ str.makeString("createStream");
+ Buffer *strobj = str.encode();
+ if (!strobj) {
+ return 0;
+ }
- log_unimpl(__PRETTY_FUNCTION__);
+ Element num = new Element;
+ num.makeNumber(id);
+ Buffer *numobj = num.encode();
+ if (!numobj) {
return 0;
+ }
+
+ Buffer *buf = new Buffer(strobj->size() + numobj->size());
+ if (!buf) {
+ return 0;
+ }
+ buf->append(strobj);
+ buf->append(numobj);
+
+ delete strobj;
+ delete numobj;
+ return buf;
}
// 127.0.0.1:38167 -> 127.0.0.1:1935 [AP]
@@ -187,11 +207,133 @@
// 69 6f 2e 66 6c 76 c2 00 03 00 00 00 01 00 00 27 io.flv.........'
// 10
amf::Buffer *
-RTMPClient::encodePublish()
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag)
+{
+// GNASH_REPORT_FUNCTION;
+ return encodeStreamOp(id, op, flag, "", 0);
+}
+
+amf::Buffer *
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag, double pos)
+{
+// GNASH_REPORT_FUNCTION;
+ return encodeStreamOp(id, op, flag, "", pos);
+}
+
+amf::Buffer *
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag, const
std::string &name)
+{
+// GNASH_REPORT_FUNCTION;
+ return encodeStreamOp(id, op, flag, name, 0);
+}
+
+// A seek packet is the operation name "seek", followed by the
+// stream ID, then a NULL object, followed by the location to seek to.
+//
+// A pause packet is the operation name "pause", followed by the stream ID,
+// then a NULL object, a boolean (always true from what I can tell), and then
+// a location, which appears to always be 0.
+amf::Buffer *
+RTMPClient::encodeStreamOp(double id, rtmp_op_e op, bool flag, const
std::string &name, double pos)
{
GNASH_REPORT_FUNCTION;
- log_unimpl(__PRETTY_FUNCTION__);
+
+ // Set the operations command name
+ Element str;
+ switch (op) {
+ case STREAM_PLAY: // play the existing stream
+ str.makeString("play");
+ break;
+ case STREAM_PAUSE: // pause the existing stream
+ str.makeString("pause");
+ break;
+ case STREAM_PUBLISH: // publish the existing stream
+ str.makeString("publish");
+ break;
+ case STREAM_STOP: // stop the existing stream
+ str.makeString("stop");
+ break;
+ case STREAM_SEEK: // seek in the existing stream
+ str.makeString("seek");
+ break;
+ default:
return 0;
+ };
+
+ Buffer *strobj = str.encode();
+ if (!strobj) {
+ return 0;
+ }
+
+ // Set the stream ID, which follows the command
+ Element strid;
+ strid.makeNumber(id);
+ Buffer *stridobj = strid.encode();
+ if (!stridobj) {
+ return 0;
+ }
+
+ // Set the NULL object element that follows the stream ID
+ Element null;
+ null.makeNull();
+ Buffer *nullobj = null.encode();
+ if (!nullobj) {
+ return 0;
+ }
+
+ // Set the BOOLEAN object element that is the last field in the packet
+ Element boolean;
+ boolean.makeBoolean(flag);
+ Buffer *boolobj = boolean.encode();
+ if (!boolobj) {
+ return 0;
+ }
+
+ // Calculate the packet size, rather than use the default as we want to
+ // to be concious of the memory usage. The command name and the optional
+ // file name are the only two dynamically sized fields.
+ size_t pktsize = strobj->size() + name.size();
+ // Add 2 bytes for the Boolean, and 16 bytes for the two doubles, which are
+ // 8 bytes apiece.
+ pktsize += (sizeof(double) * 2) + 2;
+// Buffer *buf = new Buffer(pktsize);
+ Buffer *buf = new Buffer;
+
+ if (!buf) {
+ return 0;
+ }
+ buf->append(strobj);
+ delete strobj;
+ buf->append(stridobj);
+ delete stridobj;
+ buf->append(nullobj);
+ delete nullobj;
+ // Seek doesn't use the boolean flag
+ if (op != STREAM_SEEK) {
+ buf->append(boolobj);
+ }
+ delete boolobj;
+
+ // The play command has an optional field, which is the name of the file
+ // used for the stream. A Play command without this name set play an
+ // existing stream that is already open.
+ if (!name.empty()) {
+ buf->append(name);
+ }
+
+ // The seek command also may have an optional location to seek to
+ if ((op == STREAM_PAUSE) || (op == STREAM_SEEK)) {
+ Element seek;
+ seek.makeNumber(pos);
+ Buffer *posobj = seek.encode();
+ if (!posobj) {
+ return 0;
+ }
+ buf->append(posobj);
+ delete posobj;
+ }
+
+ return buf;
}
// A request for a handshake is initiated by sending a byte with a
Index: libnet/rtmp_client.h
===================================================================
RCS file: /sources/gnash/gnash/libnet/rtmp_client.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libnet/rtmp_client.h 16 May 2008 03:46:27 -0000 1.1
+++ libnet/rtmp_client.h 6 Jun 2008 14:21:32 -0000 1.2
@@ -51,8 +51,10 @@
const char *pageUrl);
// Create the second object sent to the server, which is
NetStream():;NetStream()
amf::Buffer *encodeStream(double id);
-
- amf::Buffer *encodePublish();
+ amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag);
+ amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag, double
pos);
+ amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag, const
std::string &name);
+ amf::Buffer *encodeStreamOp(double id, rtmp_op_e op, bool flag, const
std::string &name, double pos);
void dump();
private:
Index: testsuite/libnet.all/test_rtmp.cpp
===================================================================
RCS file: /sources/gnash/gnash/testsuite/libnet.all/test_rtmp.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- testsuite/libnet.all/test_rtmp.cpp 16 May 2008 03:46:38 -0000 1.2
+++ testsuite/libnet.all/test_rtmp.cpp 6 Jun 2008 14:21:32 -0000 1.3
@@ -68,6 +68,7 @@
static void test_types();
static void test_results();
static void test_system();
+static void test_client();
LogFile& dbglogfile = LogFile::getDefaultInstance();
@@ -113,6 +114,7 @@
ch |= hex2digit(*ptr++);
buf->append(ch);
}
+
return buf;
}
@@ -173,6 +175,7 @@
test_header();
test_system();
test_results();
+ test_client();
// test_types();
}
@@ -184,14 +187,9 @@
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);
@@ -459,6 +457,79 @@
const char *x = "06 00 d2 04 00 00 00 00";
Buffer *buf1 = hex2mem(x);
+ delete buf1;
+}
+
+void
+test_client()
+{
+ GNASH_REPORT_FUNCTION;
+ RTMPClient rtmp;
+
+ Buffer *buf1 = hex2mem("02 00 04 70 6c 61 79 00 00 00 00 00 00 00 00 00 05
01 00");
+ Buffer *buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_PLAY, false);
+ if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+ runtest.pass("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PLAY)");
+ } else {
+ runtest.fail("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PLAY)");
+ }
+ delete buf1;
+ delete buf2;
+
+ buf1 = hex2mem("02 00 05 70 61 75 73 65 00 00 00 00 00 00 00 00 00 05 01
01 00 00 00 00 00 00 00 00 00");
+ buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_PAUSE, true, 0);
+ if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+ runtest.pass("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PAUSE)");
+ } else {
+ runtest.fail("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_PAUSE)");
+ }
+ delete buf1;
+ delete buf2;
+
+ buf1 = hex2mem("02 00 04 73 74 6f 70 00 00 00 00 00 00 00 00 00 05 01 00");
+ buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_STOP, false);
+ if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+ runtest.pass("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_STOP)");
+ } else {
+ runtest.fail("Encoded RTMPClient::encodeStreamOp(RTMP::STREAM_STOP)");
+ }
+ delete buf1;
+ delete buf2;
+
+#if 0
+ buf1 = hex2mem("02 00 07 70 75 62 6c 69 73 68 00 00 00 00 00 00 00 00 00
05 02 00 06 73 74 72 65 61 6d 02 00 04 6c 69 76 65 0d 00 02 ba 00 00 1a 14 02
00 00 00 02 00");
+ buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_PUBLISH, false);
+ cerr << hexify(buf1->begin(), buf1->size(), false) << endl;
+ cerr << hexify(buf2->begin(), buf1->size(), false) << endl;
+ if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+ runtest.pass("Encoded
RTMPClient::encodeStreamOp(RTMP::STREAM_PUBLISH)");
+ } else {
+ runtest.fail("Encoded
RTMPClient::encodeStreamOp(RTMP::STREAM_PUBLISH)");
+ }
+ delete buf1;
+ delete buf2;
+#endif
+
+ buf1 = hex2mem("02 00 04 73 65 65 6b 00 00 00 00 00 00 00 00 00 05 00 00
00 00 00 00 00 00 00");
+ buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_SEEK, false);
+ if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+ runtest.pass("Encoded RTMPClient::encodeStream(RTMP::SEEK)");
+ } else {
+ runtest.fail("Encoded RTMPClient::encodeStream(RTMP::SEEK)");
+ }
+ delete buf1;
+ delete buf2;
+
+ buf1 = hex2mem("02 00 04 73 65 65 6b 00 00 00 00 00 00 00 00 00 05 00 40
c7 70 00 00 00 00 00");
+ buf2 = rtmp.encodeStreamOp(0, RTMP::STREAM_SEEK, false, 12000);
+ if ((memcmp(buf1->reference(), buf2->reference(), buf1->size()) == 0)) {
+ runtest.pass("Encoded RTMPClient::encodeStream(RTMP::SEEK, double)");
+ } else {
+ runtest.fail("Encoded RTMPClient::encodeStream(RTMP::SEEK, double)");
+ }
+ delete buf1;
+ delete buf2;
+
}
static void
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6835
retrieving revision 1.6836
diff -u -b -r1.6835 -r1.6836
--- ChangeLog 6 Jun 2008 10:51:39 -0000 1.6835
+++ ChangeLog 6 Jun 2008 14:21:33 -0000 1.6836
@@ -1,3 +1,14 @@
+2008-06-06 Rob Savoye <address@hidden>
+
+ * libamf/amf.cpp: Add support for NULL objects.
+ * libamf/element.cpp: Set the boolean data correctly, it was
+ offset by one byte. Make a NULL object.
+ * libnet/rtmp.h: Add Stream operations, play, stop, pause, seek,
+ publish.
+ * libnet/rtmp_client.{h,cpp}: Build NetStream operation packets.
+ * testsuite/libnet.all/test_rtmp.cpp: Test NetStream operations
+ packets for the client side.
+
2008-06-06 Benjamin Wolsey <address@hidden>
* libbase/utility.h: include gnashconfig.h, fix some old-style casts,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] gnash libamf/amf.cpp libamf/element.cpp libnet/...,
Rob Savoye <=