CVSROOT: /sources/gnash Module name: gnash Changes by: Rob Savoye <rsavoye> 08/02/01 01:42:41
Modified files: . : ChangeLog libamf : amf.cpp amf.h element.cpp element.h lcshm.cpp lcshm.h Log message: * libamf/amf.cpp: Oops, return original pointer as returned by new, not the incremented pointer. Use :encodeElement() for strings. Encode an array of AMF objects. * libamf/amf.h: Make all the encoding methods static. * libamf/element.{cpp,h}: Add function and variable data types, internal to Gnash. Initialize with an array of AMF objects. Create a new function block object in memory. Don't return nan, BSD doesn't support it. * libamf/lcshm.cpp: Correctly remove Listeners. Format a memory segment header. Send now works, and puts AMF objects into the memory segment. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5543&r2=1.5544 http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.cpp?cvsroot=gnash&r1=1.58&r2=1.59 http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/amf.h?cvsroot=gnash&r1=1.30&r2=1.31 http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.cpp?cvsroot=gnash&r1=1.8&r2=1.9 http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/element.h?cvsroot=gnash&r1=1.7&r2=1.8 http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/lcshm.cpp?cvsroot=gnash&r1=1.6&r2=1.7 http://cvs.savannah.gnu.org/viewcvs/gnash/libamf/lcshm.h?cvsroot=gnash&r1=1.6&r2=1.7 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.5543 retrieving revision 1.5544 diff -u -b -r1.5543 -r1.5544 --- ChangeLog 1 Feb 2008 01:30:28 -0000 1.5543 +++ ChangeLog 1 Feb 2008 01:42:40 -0000 1.5544 @@ -1,5 +1,17 @@ 2008-01-31 Rob Savoye <[EMAIL PROTECTED]> + * libamf/amf.cpp: Oops, return original pointer as returned by + new, not the incremented pointer. Use :encodeElement() for + strings. Encode an array of AMF objects. + * libamf/amf.h: Make all the encoding methods static. + * libamf/element.{cpp,h}: Add function and variable data types, + internal to Gnash. Initialize with an array of AMF objects. Create + a new function block object in memory. Don't return nan, BSD + doesn't support it. + * libamf/lcshm.cpp: Correctly remove Listeners. Format a memory + segment header. Send now works, and puts AMF objects into the + memory segment. + * configure.ac: Add test for IPC_INFO, which isn't portable to BSD. * server/asobj/LocalConnection.cpp: Don;t define any LC constants Index: libamf/amf.cpp =================================================================== RCS file: /sources/gnash/gnash/libamf/amf.cpp,v retrieving revision 1.58 retrieving revision 1.59 diff -u -b -r1.58 -r1.59 --- libamf/amf.cpp 31 Jan 2008 11:25:57 -0000 1.58 +++ libamf/amf.cpp 1 Feb 2008 01:42:40 -0000 1.59 @@ -162,8 +162,7 @@ AMF::readElements(boost::uint8_t *in) { GNASH_REPORT_FUNCTION; - - boost::uint8_t *x = in; +boost::uint8_t *x = in; astype_e type = (astype_e)*x; bool boolshift; const char *mstr = NULL; @@ -265,33 +264,6 @@ // Methods for encoding data into big endian formatted raw AMF data. // -/// Encode a string object -/// -/// @return a binary AMF packet in big endian format (header,data) which -/// needs to be deleted[] after being used. -/// -boost::uint8_t * -AMF::encodeString(const char *str) -{ -// GNASH_REPORT_FUNCTION; - boost::uint16_t length; - - int pktsize = strlen(str) + AMF_HEADER_SIZE; - // Encode a string value. The data follows a 2 byte length - // field. (which must be big-endian) - boost::uint8_t* x = new boost::uint8_t[pktsize + 1]; - memset(x, 0, pktsize); - *x++ = Element::STRING; - log_debug("Encoded data size is going to be %d", length); - swapBytes(&length, 2); - memcpy(x, &length, 2); - x += 2; - memcpy(x, str, pktsize - AMF_HEADER_SIZE); - x += pktsize - AMF_HEADER_SIZE; - - return x; -} - /// Encode a 64 bit number /// /// @return a binary AMF packet in big endian format (header,data) which @@ -304,15 +276,16 @@ int pktsize = AMF_NUMBER_SIZE + AMF_HEADER_SIZE; double num; // Encode the data as a 64 bit, big-endian, numeric value - boost::uint8_t* x = new boost::uint8_t[pktsize + 1]; + boost::uint8_t *ptr = new boost::uint8_t[pktsize + 1]; + boost::uint8_t *x = ptr; memset(x, 0, pktsize); *x++ = (char)Element::NUMBER; memcpy(&num, &indata, AMF_NUMBER_SIZE); swapBytes(&num, AMF_NUMBER_SIZE); memcpy(x, &num, AMF_NUMBER_SIZE); - x += pktsize - AMF_HEADER_SIZE; +// x += pktsize - AMF_HEADER_SIZE; - return x; + return ptr; } /// Encode a Boolean object @@ -328,15 +301,17 @@ // GNASH_REPORT_FUNCTION; int pktsize = AMF_HEADER_SIZE; - boost::uint8_t* x = new boost::uint8_t[pktsize + 1]; + boost::uint8_t*ptr = new boost::uint8_t[pktsize + 1]; + boost::uint8_t* x = ptr; memset(x, 0, pktsize); // Encode a boolean value. 0 for false, 1 for true *x++ = (char)Element::BOOLEAN; + x++; *x = flag; - swapBytes(x, 2); - x += sizeof(boost::uint16_t); +// swapBytes(x, 2); +// x += sizeof(boost::uint16_t); - return x; + return ptr; } /// Encode an object @@ -545,6 +520,35 @@ return 0; } +/// Encode a string object +/// +/// @return a binary AMF packet in big endian format (header,data) which +/// needs to be deleted[] after being used. +/// +boost::uint8_t * +AMF::encodeElement(const char *str) +{ +// GNASH_REPORT_FUNCTION; + boost::uint16_t length; + + int pktsize = strlen(str) + AMF_HEADER_SIZE; + // Encode a string value. The data follows a 2 byte length + // field. (which must be big-endian) + boost::uint8_t *ptr = new boost::uint8_t[pktsize + 1]; + boost::uint8_t *x = ptr; + memset(x, 0, pktsize); + *x++ = Element::STRING; + length = strlen(str); + log_debug("Encoded data size is going to be %d", length); + swapBytes(&length, 2); + memcpy(x, &length, 2); + x += 2; + memcpy(x, str, pktsize - AMF_HEADER_SIZE); + x += pktsize - AMF_HEADER_SIZE; + + return ptr; +} + /// \brief Write an AMF element /// /// This encodes the data supplied to an AMF formatted one. As the @@ -572,13 +576,13 @@ return 0; break; case Element::NUMBER: - return encodeNumber(*(reinterpret_cast<double *>(el->getData()))); + return encodeNumber(el->to_number()); break; case Element::BOOLEAN: - return encodeBoolean(*(reinterpret_cast<bool *>(el->getData()))); + return encodeBoolean(el->to_bool()); break; case Element::STRING: - return encodeBoolean(*(reinterpret_cast<const char *>(el->getData()))); + return encodeElement(el->to_string()); break; case Element::OBJECT: return encodeObject(el->getData(), el->getLength()); @@ -634,6 +638,85 @@ return 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<boost::uint8_t> * +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<boost::uint8_t> *vec = new vector<boost::uint8_t>; + boost::uint8_t* ptr = new boost::uint8_t[size + 1]; + memset(ptr, 0, size + 1); + + boost::uint8_t *x = ptr; + size = 0; + for (ait = data.begin(); ait != data.end(); ait++) { + amf::Element *el = (*(ait)); +// el->dump(); + boost::uint8_t *tmp = encodeElement(el); + boost::uint8_t *y = tmp; +#if 0 + boost::uint8_t *hexint; + hexint = new boost::uint8_t[(el->getLength() + 4) *3]; + hexify((boost::uint8_t *)hexint, (boost::uint8_t *)tmp, + el->getLength() + AMF_HEADER_SIZE, true); + log_msg(_("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 = AMF_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) { + // _children + } + if (el->getType() == Element::BOOLEAN) { + size = 3; + } + for (int i=0; i<size; i++) { + boost::uint8_t c = *y; + y++; +// printf("0x%x(%c) ", c, (isalpha(c)) ? c : '.'); + vec->push_back(c); + } +// delete[] tmp; + } + return vec; +} + + #if 0 /// \brief \ Each RTMP header consists of the following: /// @@ -1387,8 +1470,6 @@ boost::uint8_t *tmpptr; // uint8_t hexint[(bytes*2)+1]; - boost::uint8_t* hexint; - short length; if (in == 0) { @@ -1401,6 +1482,7 @@ // } #if 0 + boost::uint8_t* hexint; hexint = (boost::uint8_t*) malloc((bytes * 3) + 12); hexify((boost::uint8_t *)hexint, (boost::uint8_t *)in, bytes, true); log_msg(_("The packet body is: 0x%s"), hexint); @@ -1462,7 +1544,7 @@ case Element::XML_OBJECT: case Element::TYPED_OBJECT: default: - log_unimpl("%s: type %d", __PRETTY_FUNCTION__, (int)type); +// log_unimpl("%s: type %d", __PRETTY_FUNCTION__, (int)type); return 0; } Index: libamf/amf.h =================================================================== RCS file: /sources/gnash/gnash/libamf/amf.h,v retrieving revision 1.30 retrieving revision 1.31 diff -u -b -r1.30 -r1.31 --- libamf/amf.h 31 Jan 2008 11:25:57 -0000 1.30 +++ libamf/amf.h 1 Feb 2008 01:42:41 -0000 1.31 @@ -144,97 +144,97 @@ /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeString(const char *str); + static boost::uint8_t *encodeElement(const char *str); /// Encode a Boolean object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeBoolean(bool flag); + static boost::uint8_t *encodeBoolean(bool flag); /// Encode an "Undefined" object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeUndefined(); + static boost::uint8_t *encodeUndefined(); /// Encode a "NULL" object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeNull(); + static boost::uint8_t *encodeNull(); /// Encode a "Unsupported" object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeUnsupported(); + static boost::uint8_t *encodeUnsupported(); /// Encode an XML object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeXMLObject(boost::uint8_t *data, int size); + static boost::uint8_t *encodeXMLObject(boost::uint8_t *data, int size); /// Encode a Typed Object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeTypedObject(boost::uint8_t *data, int size); + static boost::uint8_t *encodeTypedObject(boost::uint8_t *data, int size); /// Encode a Reference to an object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeReference(boost::uint8_t *data, int size); + static boost::uint8_t *encodeReference(boost::uint8_t *data, int size); /// Encode a Movie Clip /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeMovieClip(boost::uint8_t *data, int size); + static boost::uint8_t *encodeMovieClip(boost::uint8_t *data, int size); /// Encode an ECMA Array /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeECMAArray(boost::uint8_t *data, int size); + static boost::uint8_t *encodeECMAArray(boost::uint8_t *data, int size); /// Encode a long string /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeLongString(boost::uint8_t *data, int size); + static boost::uint8_t *encodeLongString(boost::uint8_t *data, int size); /// Encode a Record Set /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeRecordSet(boost::uint8_t *data, int size); + static boost::uint8_t *encodeRecordSet(boost::uint8_t *data, int size); /// Encode a Date /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeDate(boost::uint8_t *data); + static boost::uint8_t *encodeDate(boost::uint8_t *data); /// Encode a Strict Array /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeStrictArray(boost::uint8_t *data, int size); + static boost::uint8_t *encodeStrictArray(boost::uint8_t *data, int size); /// Encode an object /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeObject(const boost::uint8_t *data, int size); + static boost::uint8_t *encodeObject(const boost::uint8_t *data, int size); /// Encode a 64 bit number /// /// @return a binary AMF packet in big endian format (header,data) /// - boost::uint8_t *encodeNumber(double num); + static boost::uint8_t *encodeNumber(double num); /// Encode a element. /// @@ -243,7 +243,16 @@ /// @return a newly allocated byte array. /// to be deleted by caller using delete [] operator, or NULL /// - boost::uint8_t *encodeElement(amf::Element *el); + static boost::uint8_t *encodeElement(amf::Element *el); + + /// 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 + /// + static std::vector<boost::uint8_t> *encodeElement(std::vector<amf::Element *> &els); /// Encode a variable. // @@ -271,40 +280,40 @@ /// /// @return an amf packet (header,data) /// - boost::uint8_t* encodeElement(Element::astype_e type, const void *in, int nbytes); + static boost::uint8_t* encodeElement(Element::astype_e type, const void *in, int nbytes); /// @return a newly allocated byte array, /// to be deleted by caller using delete [] operator, or NULL /// - boost::uint8_t* encodeVariable(const char *name); + static boost::uint8_t* encodeVariable(const char *name); /// Encode a boolean variable. This is a name followed by a boolean value. // /// @return a newly allocated byte array, /// to be deleted by caller using delete [] operator, or NULL /// - boost::uint8_t* encodeVariable(const char *name, bool flag); + static boost::uint8_t* encodeVariable(const char *name, bool flag); /// Encode a variable. // /// @return a newly allocated byte array, /// to be deleted by caller using delete [] operator, or NULL /// - boost::uint8_t* encodeVariable(const char *name, double num); + static boost::uint8_t* encodeVariable(const char *name, double num); /// Encode a variable. // /// @return a newly allocated byte array, /// to be deleted by caller using delete [] operator, or NULL /// - boost::uint8_t* encodeVariable(std::string &name, std::string &val); + static boost::uint8_t* encodeVariable(std::string &name, std::string &val); /// Encode a variable. // /// @return a newly allocated byte array, /// to be deleted by caller using delete [] operator, or NULL /// - boost::uint8_t* encodeVariable(const char *name, const char *val); + static boost::uint8_t* encodeVariable(const char *name, const char *val); void *encodeRTMPHeader(int amf_index, amf_headersize_e head_size, int total_size, content_types_e type, amfsource_e routing); @@ -331,6 +340,7 @@ boost::uint8_t *extractElement(amf::Element *el, boost::uint8_t *in); boost::uint8_t *extractVariable(amf::Element *el, boost::uint8_t *in); + #if 0 // FIXME: these should return an Element, and then use to_*() to convert. char *extractString(const boost::uint8_t* in); Index: libamf/element.cpp =================================================================== RCS file: /sources/gnash/gnash/libamf/element.cpp,v retrieving revision 1.8 retrieving revision 1.9 diff -u -b -r1.8 -r1.9 --- libamf/element.cpp 31 Jan 2008 10:27:06 -0000 1.8 +++ libamf/element.cpp 1 Feb 2008 01:42:41 -0000 1.9 @@ -23,6 +23,8 @@ #include <string> #include <vector> +#include <cmath> +#include <climits> #include "log.h" #include "amf.h" @@ -54,7 +56,9 @@ "Unsupported", "Recordset", "XMLObject", - "TypedObject" + "TypedObject", + "Varible (gnash)", + "Function (gnash)" }; Element::Element() @@ -72,44 +76,91 @@ if (_data) { delete [] _data; } + for (size_t i=0; i< _children.size(); i++) { + delete _children[i]; + } } Element::Element(boost::uint8_t *indata) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; init(indata); } Element::Element(double indata) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; init(indata); } +// Element(vector<double> &indata) +// { +// GNASH_REPORT_FUNCTION; +// init(indata); +// } + Element::Element(const string &indata) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; init(indata); } Element::Element(const string &name, const string &indata) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; init(name, indata); } Element::Element(const string &name, bool indata) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; init(name, indata); } Element::Element(bool indata) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; init(indata); } +// Create a function block for AMF +Element::Element(bool flag, double unknown1, double unknown2, + const string &methodname) +{ + GNASH_REPORT_FUNCTION; + init(flag, unknown1, unknown2, methodname); +} + +Element & +Element::init(bool flag, double unknown1, double unknown2, + const string &methodname) +{ + GNASH_REPORT_FUNCTION; + _type = Element::FUNCTION; + if (methodname.size()) { + _name = methodname; + } + + // Build up the children for the function block + Element *el = new Element(flag); + _children.push_back(el); + + el = new Element(unknown1); + _children.push_back(el); + + el = new Element(unknown2); + _children.push_back(el); + + el = new Element(methodname); + _children.push_back(el); + + _length = 3 + + ((AMF_HEADER_SIZE + AMF_NUMBER_SIZE) * 2) + + methodname.size() + AMF_HEADER_SIZE; +// memcpy(_data, &indata, _length); + return *this; +} + Element & Element::init(double indata) { @@ -197,7 +248,8 @@ if (_data) { return *(reinterpret_cast<double *>(_data)); } - return nan("NaN"); +// return ::nan("NaN"); + return -1.0; } const char * @@ -287,6 +339,19 @@ } Element & +Element::makeBoolean(bool &data) +{ +// GNASH_REPORT_FUNCTION; + + _type = Element::BOOLEAN; + _length = 1; + _data = new boost::uint8_t[2]; + memset(_data, 0, 2); + _data[1]= data; + return *this; +} + +Element & Element::makeBoolean(boost::uint8_t *data) { // GNASH_REPORT_FUNCTION; @@ -488,17 +553,19 @@ // GNASH_REPORT_FUNCTION; if (_name.size()) { - cerr << "Dumping AMF Varible: " << _name << endl; + cerr << "AMF object name: " << _name << endl; } cerr << astype_str[_type] << ": "; switch (_type) { + case Element::NOTYPE: + break; case Element::NUMBER: - cerr << "AMF Numeric value: " << to_number() << endl; + cerr << to_number() << endl; break; case Element::BOOLEAN: - cerr << "AMF Boolean value: " << (to_bool() ? "true" : "false") << endl; + cerr << (to_bool() ? "true" : "false") << endl; break; case Element::STRING: cerr << "(" << _length << " bytes): "; @@ -528,10 +595,17 @@ hexify((boost::uint8_t *)hexint, _data, _length, false); cerr << "AMF data is: 0x%s" << hexint << endl; break; + case Element::VARIABLE: + case Element::FUNCTION: + cerr << "# of children in object: " << _children.size() << endl; + for (size_t i=0; i< _children.size(); i++) { + _children[i]->dump(); + } + break; default: - log_unimpl("%s: type %d", __PRETTY_FUNCTION__, (int)_type); +// log_unimpl("%s: type %d", __PRETTY_FUNCTION__, (int)_type); + break; } - } } // end of amf namespace Index: libamf/element.h =================================================================== RCS file: /sources/gnash/gnash/libamf/element.h,v retrieving revision 1.7 retrieving revision 1.8 diff -u -b -r1.7 -r1.8 --- libamf/element.h 25 Jan 2008 18:08:00 -0000 1.7 +++ libamf/element.h 1 Feb 2008 01:42:41 -0000 1.8 @@ -56,29 +56,38 @@ RECORD_SET=0x0e, XML_OBJECT=0x0f, TYPED_OBJECT=0x10, - VARIABLE=0x11 // this isn't part of the AMF spec, it's used internally + // these aren't part of the AMF spec, they're used internally + VARIABLE=0x11, + FUNCTION=0x12 } astype_e; Element(); Element(boost::uint8_t *data); Element(double data); + Element(std::vector<double> &data); Element(const std::string &data); Element(const std::string &name, const std::string &data); Element(bool data); Element(const std::string &name, bool data); + // Create a function block for AMF + Element(bool, double, double, const std::string &str); ~Element(); void clear(); boost::uint8_t *init(boost::uint8_t *data); Element &init(const std::string &name, double data); Element &init(double data); + Element &init(std::vector<double> &data); Element &init(const std::string &name, const std::string &data); Element &init(const std::string &data); Element &init(const std::string &name, bool data); Element &init(bool data); + // Create a function block for AMF + Element &init(bool, double, double, const std::string &str); // These create the other "special" AMF types. Element &makeString(boost::uint8_t *data, int size); Element &makeNumber(boost::uint8_t *data); Element &makeBoolean(boost::uint8_t *data); + Element &makeBoolean(bool &data); Element &makeUndefined(); Element &makeUndefined(const std::string &name); Element &makeNull(); @@ -126,6 +135,7 @@ boost::int16_t _length; std::string _name; boost::uint8_t *_data; + std::vector<Element *> _children; }; // end of class definition Index: libamf/lcshm.cpp =================================================================== RCS file: /sources/gnash/gnash/libamf/lcshm.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -u -b -r1.6 -r1.7 --- libamf/lcshm.cpp 25 Jan 2008 18:48:29 -0000 1.6 +++ libamf/lcshm.cpp 1 Feb 2008 01:42:41 -0000 1.7 @@ -45,6 +45,9 @@ namespace gnash { // The maximum +// although a bool is one byte, it appears to be a short in AMF, +// plus the type byte. +const int AMF_BOOLEAN_SIZE = 3; const int LC_HEADER_SIZE = 16; const int MAX_LC_HEADER_SIZE = 40960; const int LC_LISTENERS_START = MAX_LC_HEADER_SIZE + LC_HEADER_SIZE; @@ -109,7 +112,7 @@ // see if a connection name exists in our list of listeners bool -Listener::findListener(std::string &name) +Listener::findListener(const string &name) { // GNASH_REPORT_FUNCTION; @@ -127,7 +130,7 @@ } bool -Listener::addListener(std::string &name) +Listener::addListener(const string &name) { GNASH_REPORT_FUNCTION; @@ -156,7 +159,7 @@ return false; } item += 4; - const char *x2 = "::4"; + const char *x2 = "::2"; if (!memcpy(item, x2, 4)) { return false; } @@ -164,28 +167,36 @@ return true; } +// I don't believe this function is support by other swf players, +// but we do, as it's nice to remove oneself from the listeners +// list so nobody knows we were here listening. bool -Listener::removeListener(std::string &name) +Listener::removeListener(const string &name) { GNASH_REPORT_FUNCTION; boost::uint8_t *addr = _baseaddr + LC_LISTENERS_START; + int len; char *item = reinterpret_cast<char *>(addr); while (*item != 0) { if (name == item) { - int len = strlen(item) + 1; while (*item != 0) { + len = strlen(item) + 8 + 1; strcpy(item, item + len); - item += len + 1; + item += len + strlen(item + len); } + + memset(item - len, 0, len); return true; } item += strlen(item) + 1; } + return false; } +// Get a list of alll the listeners waiting on this channel auto_ptr< vector<string> > Listener::listListeners() { @@ -251,7 +262,9 @@ continue; } } + if (el->getType() != Element::NOTYPE) { addObject(el); + } }; return _amfobjs; @@ -291,12 +304,19 @@ Element *el = new amf::Element; AMF amf; ptr = amf.extractElement(el, ptr); + if (ptr == 0) { + log_error("Didn't extract element from byte stream!"); + return 0; + } + _object.connection_name = el->to_string(); delete el; el = new amf::Element; ptr = amf.extractElement(el, ptr); + if (ptr != 0) { _object.hostname = el->to_string(); + } delete el; // el = new amf::Element; @@ -326,10 +346,35 @@ } boost::uint8_t * -LcShm::formatHeader(boost::uint8_t * /*data*/) +LcShm::formatHeader(const std::string &con, const std::string &host, bool domain) { -// GNASH_REPORT_FUNCTION; - return NULL; + GNASH_REPORT_FUNCTION; +// boost::uint8_t *ptr = data + LC_HEADER_SIZE; + int size = con.size() + host.size() + 9; + + boost::uint8_t *header = new boost::uint8_t[size + 1]; + boost::uint8_t *ptr = header; + + // This is the initial 16 bytes of the header + memset(ptr, 0, size + 1); + *ptr = 1; + ptr += 3; + *ptr = 1; + ptr = header + LC_HEADER_SIZE; + + // Which is then always followed by 3 AMF objects. + boost::uint8_t *tmp = AMF::encodeElement(con.c_str()); + memcpy(ptr, tmp, con.size()); + ptr += con.size(); + delete[] tmp; + + tmp = AMF::encodeElement(host.c_str()); + memcpy(ptr, tmp, host.size()); + ptr += host.size(); + + delete[] ptr; + +// return ptr; } /// \brief Prepares the LcShm object to receive commands from a @@ -339,12 +384,16 @@ /// send() command to signify which local connection to send the /// object to. bool -LcShm::connect(string &name) +LcShm::connect(const string &name) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; _name = name; + // the name here is optional, Gnash will pick a good default. + // When using sysv shared memory segments in compatibility mode, + // the name is ignored, and the SHMkey is specified in the user's + // ~/.gnashrc file. if (Shm::attach(name.c_str(), true) == false) { return false; } @@ -355,8 +404,13 @@ } Listener::setBaseAddress(reinterpret_cast<uint8_t *>(Shm::getAddr())); + _baseaddr = reinterpret_cast<uint8_t *>(Shm::getAddr()); boost::uint8_t *ptr = parseHeader(Listener::getBaseAddress()); - vector<amf::Element *> ellist = parseBody(ptr); +// vector<amf::Element *> ellist = parseBody(ptr); +// log_debug("Base address is: 0x%x, 0x%x", +// (unsigned int)Listener::getBaseAddress(), (unsigned int)_baseaddr); + + addListener(name); return true; } @@ -364,7 +418,7 @@ bool LcShm::connect(key_t key) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; if (Shm::attach(key, true) == false) { return false; @@ -376,18 +430,92 @@ } Listener::setBaseAddress(reinterpret_cast<uint8_t *>(Shm::getAddr())); + _baseaddr = reinterpret_cast<uint8_t *>(Shm::getAddr()); boost::uint8_t *ptr = parseHeader(Listener::getBaseAddress()); - vector<amf::Element *> ellist = parseBody(ptr); +// vector<amf::Element *> ellist = parseBody(ptr); +// log_debug("Base address is: 0x%x, 0x%x", +// (unsigned int)Listener::getBaseAddress(), (unsigned int)_baseaddr); return true; } /// \brief Invokes a method on a specified LcShm object. void -LcShm::send(const std::string & /*name*/, const std::string & /*dataname*/, amf::Element * /*data*/) +LcShm::send(const string &name, const string &domainname, + vector<amf::Element *> &data) { + GNASH_REPORT_FUNCTION; + +// log_debug("Base address is: 0x%x, 0x%x", +// (unsigned int)Listener::getBaseAddress(), (unsigned int)_baseaddr); + +// formatHeader(name, domainname, _object.domain); + + // Update the connection name + boost::uint8_t *ptr = Listener::getBaseAddress(); + if (ptr == reinterpret_cast<boost::uint8_t *>(0)) { + log_error("base address not set!"); + } + +// boost::uint8_t *tmp = AMF::encodeElement(name.c_str()); +// memcpy(ptr, tmp, name.size()); +// ptr += name.size() + AMF_HEADER_SIZE; +// delete[] tmp; + +// tmp = AMF::encodeElement(domainname.c_str()); +// memcpy(ptr, tmp, domainname.size()); +// ptr += domainname.size() + AMF_HEADER_SIZE; + +// ptr += LC_HEADER_SIZE; + boost::uint8_t *x = ptr; // just for debugging from gdb. temporary + + // This is the initial 16 bytes of the header + memset(ptr, 0, LC_HEADER_SIZE + 200); + *ptr = 1; + ptr += 4; + *ptr = 1; + ptr += LC_HEADER_SIZE - 4; + + // Which is then always followed by 3 AMF objects. + + boost::uint8_t *tmp = AMF::encodeElement(name.c_str()); + memcpy(ptr, tmp, name.size() + AMF_HEADER_SIZE); + delete[] tmp; + + ptr += name.size() + AMF_HEADER_SIZE; + + // Update the host on the other end of the connection. + tmp = AMF::encodeElement(domainname.c_str()); + memcpy(ptr, tmp, domainname.size() + AMF_HEADER_SIZE ); + delete[] tmp; + + ptr += domainname.size() + AMF_HEADER_SIZE; + +// // Set the domain flag to whatever it's current value is. +// // Element domain(_object.domain); +// tmp = AMF::encodeBoolean(_object.domain); +// memcpy(ptr, tmp, AMF_BOOLEAN_SIZE); +// // delete[] tmp; + +// ptr += AMF_BOOLEAN_SIZE; + + vector<boost::uint8_t> *vec = AMF::encodeElement(data); + vector<boost::uint8_t>::iterator vit; + // Can't do a memcpy with a std::vector +// log_debug("Number of bytes in the vector: %x", vec->size()); + for (vit = vec->begin(); vit != vec->end(); vit++) { + *ptr = *vit; +#if 0 // debugging crapola + if (isalpha(*ptr)) + printf("%c ", *ptr); + else + printf("0x%x ", *ptr); +#endif + ptr++; + } + +// delete[] tmp; - log_unimpl (__FUNCTION__); } void @@ -402,7 +530,7 @@ cerr << "Hostname Name:\t\t" << _object.hostname << endl; cerr << "Domain Allowed:\t\t" << ((_object.domain) ? "true" : "false") << endl; vector<amf::Element *>::iterator ait; -// cerr << "# of Elements in file: " << _amfobjs.size() << endl; + cerr << "# of Elements in file: " << _amfobjs.size() << endl; for (ait = _amfobjs.begin(); ait != _amfobjs.end(); ait++) { amf::Element *el = (*(ait)); el->dump(); @@ -410,11 +538,11 @@ vector<string>::const_iterator lit; auto_ptr< vector<string> > listeners ( listListeners() ); + cerr << "# of Listeners in file: " << listeners->size() << endl; for (lit=listeners->begin(); lit!=listeners->end(); lit++) { string str = *lit; if (str[0] != ':') { cerr << "Listeners:\t" << str << endl; -// total++; } } } Index: libamf/lcshm.h =================================================================== RCS file: /sources/gnash/gnash/libamf/lcshm.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -b -r1.6 -r1.7 --- libamf/lcshm.h 25 Jan 2008 18:48:29 -0000 1.6 +++ libamf/lcshm.h 1 Feb 2008 01:42:41 -0000 1.7 @@ -33,16 +33,16 @@ namespace gnash { // Manipulate the list of LocalConnection Listeners. We've made this a separate -// class from LocalConnection as it's used standalone for the dumpshm utility to -// dump the Listener lists. +// class from LocalConnection as it's used standalone for the +// dumpshm utility to dump the Listener lists. class Listener { public: Listener(); Listener(boost::uint8_t *baseaddr); ~Listener(); - bool addListener(std::string &name); - bool findListener(std::string &name); - bool removeListener(std::string &name); + bool addListener(const std::string &name); + bool findListener(const std::string &name); + bool removeListener(const std::string &name); std::auto_ptr< std::vector<std::string> > listListeners(); void setBaseAddress(boost::uint8_t *addr) { _baseaddr = addr; }; boost::uint8_t *getBaseAddress() { return _baseaddr; }; @@ -57,7 +57,8 @@ typedef struct { uint32_t unknown1; uint32_t unknown2; - uint32_t timestamp; // number of milliseconds that have elapsed since the system was started + uint32_t timestamp; // number of milliseconds that have + // elapsed since the system was started uint32_t length; } lc_header_t; typedef struct { @@ -77,14 +78,17 @@ LcShm(boost::uint8_t *baseaddr); LcShm(key_t key); ~LcShm(); - bool connect(std::string &name); + bool connect(const std::string &name); bool connect(key_t key); void close(void); - void send(const std::string &name, const std::string &dataname, amf::Element *data); + void send(const std::string &name, const std::string &dataname, + std::vector<amf::Element *> &data); void recv(std::string &name, std::string &dataname, amf::Element *data); std::vector<amf::Element *> parseBody(boost::uint8_t *data); boost::uint8_t *parseHeader(boost::uint8_t *data); - boost::uint8_t *formatHeader(boost::uint8_t *data); + boost::uint8_t *formatHeader(const std::string &con, const std::string &host, bool domain); + void addConnectionName(std::string &name); + void addHostname(std::string &name); void addObject(amf::Element *el) { _amfobjs.push_back(el); }; size_t size() { return _amfobjs.size(); }; std::vector<amf::Element *> getElements() { return _amfobjs; }; _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit