1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

amf0 utest: refine interface of amf0, only export required objects

This commit is contained in:
winlin 2014-03-08 21:56:14 +08:00
parent b55efef2ee
commit 3129c738cb
5 changed files with 357 additions and 288 deletions

View file

@ -57,18 +57,139 @@ using namespace std;
#define RTMP_AMF0_Invalid 0x3F #define RTMP_AMF0_Invalid 0x3F
/** /**
* convert the any to specified object. * read amf0 string from stream.
* @return T, the converted object. never NULL. * 2.4 String Type
* @remark, user must ensure the current object type, * string-type = string-marker UTF-8
* or the covert will cause assert failed. * @return default value is empty string.
* @remark: use SrsAmf0Any::str() to create it.
*/ */
template<class T> class __SrsAmf0String : public SrsAmf0Any
T srs_amf0_convert(SrsAmf0Any* any)
{ {
T p = dynamic_cast<T>(any); public:
srs_assert(p != NULL); std::string value;
return p;
} __SrsAmf0String(const char* _value);
virtual ~__SrsAmf0String();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 boolean from stream.
* 2.4 String Type
* boolean-type = boolean-marker U8
* 0 is false, <> 0 is true
* @return default value is false.
*/
class __SrsAmf0Boolean : public SrsAmf0Any
{
public:
bool value;
__SrsAmf0Boolean(bool _value);
virtual ~__SrsAmf0Boolean();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 number from stream.
* 2.2 Number Type
* number-type = number-marker DOUBLE
* @return default value is 0.
*/
class __SrsAmf0Number : public SrsAmf0Any
{
public:
double value;
__SrsAmf0Number(double _value);
virtual ~__SrsAmf0Number();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 null from stream.
* 2.7 null Type
* null-type = null-marker
*/
class __SrsAmf0Null : public SrsAmf0Any
{
public:
__SrsAmf0Null();
virtual ~__SrsAmf0Null();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 undefined from stream.
* 2.8 undefined Type
* undefined-type = undefined-marker
*/
class __SrsAmf0Undefined : public SrsAmf0Any
{
public:
__SrsAmf0Undefined();
virtual ~__SrsAmf0Undefined();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* to ensure in inserted order.
* for the FMLE will crash when AMF0Object is not ordered by inserted,
* if ordered in map, the string compare order, the FMLE will creash when
* get the response of connect app.
*/
class __SrsUnSortedHashtable
{
private:
typedef std::pair<std::string, SrsAmf0Any*> SrsObjectPropertyType;
std::vector<SrsObjectPropertyType> properties;
public:
__SrsUnSortedHashtable();
virtual ~__SrsUnSortedHashtable();
virtual int size();
virtual void clear();
virtual std::string key_at(int index);
virtual SrsAmf0Any* value_at(int index);
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name);
};
/**
* 2.11 Object End Type
* object-end-type = UTF-8-empty object-end-marker
* 0x00 0x00 0x09
*/
class __SrsAmf0ObjectEOF : public SrsAmf0Any
{
public:
int16_t utf8_empty;
__SrsAmf0ObjectEOF();
virtual ~__SrsAmf0ObjectEOF();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/** /**
* read amf0 utf8 string from stream. * read amf0 utf8 string from stream.
@ -130,20 +251,37 @@ bool SrsAmf0Any::is_ecma_array()
string SrsAmf0Any::to_str() string SrsAmf0Any::to_str()
{ {
__SrsAmf0String* o = srs_amf0_convert<__SrsAmf0String*>(this); __SrsAmf0String* p = dynamic_cast<__SrsAmf0String*>(this);
return o->value; srs_assert(p != NULL);
return p->value;
} }
bool SrsAmf0Any::to_boolean() bool SrsAmf0Any::to_boolean()
{ {
__SrsAmf0Boolean* o = srs_amf0_convert<__SrsAmf0Boolean*>(this); __SrsAmf0Boolean* p = dynamic_cast<__SrsAmf0Boolean*>(this);
return o->value; srs_assert(p != NULL);
return p->value;
} }
double SrsAmf0Any::to_number() double SrsAmf0Any::to_number()
{ {
__SrsAmf0Number* o = srs_amf0_convert<__SrsAmf0Number*>(this); __SrsAmf0Number* p = dynamic_cast<__SrsAmf0Number*>(this);
return o->value; srs_assert(p != NULL);
return p->value;
}
SrsAmf0Object* SrsAmf0Any::to_object()
{
SrsAmf0Object* p = dynamic_cast<SrsAmf0Object*>(this);
srs_assert(p != NULL);
return p;
}
SrsAmf0EcmaArray* SrsAmf0Any::to_array()
{
SrsAmf0EcmaArray* p = dynamic_cast<SrsAmf0EcmaArray*>(this);
srs_assert(p != NULL);
return p;
} }
bool SrsAmf0Any::is_object_eof() bool SrsAmf0Any::is_object_eof()
@ -216,31 +354,31 @@ int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue)
switch (marker) { switch (marker) {
case RTMP_AMF0_String: { case RTMP_AMF0_String: {
*ppvalue = new __SrsAmf0String(); *ppvalue = SrsAmf0Any::str();
return ret; return ret;
} }
case RTMP_AMF0_Boolean: { case RTMP_AMF0_Boolean: {
*ppvalue = new __SrsAmf0Boolean(); *ppvalue = SrsAmf0Any::boolean();
return ret; return ret;
} }
case RTMP_AMF0_Number: { case RTMP_AMF0_Number: {
*ppvalue = new __SrsAmf0Number(); *ppvalue = SrsAmf0Any::number();
return ret; return ret;
} }
case RTMP_AMF0_Null: { case RTMP_AMF0_Null: {
*ppvalue = new __SrsAmf0Null(); *ppvalue = SrsAmf0Any::null();
return ret; return ret;
} }
case RTMP_AMF0_Undefined: { case RTMP_AMF0_Undefined: {
*ppvalue = new __SrsAmf0Undefined(); *ppvalue = SrsAmf0Any::undefined();
return ret; return ret;
} }
case RTMP_AMF0_Object: { case RTMP_AMF0_Object: {
*ppvalue = new SrsAmf0Object(); *ppvalue = SrsAmf0Any::object();
return ret; return ret;
} }
case RTMP_AMF0_EcmaArray: { case RTMP_AMF0_EcmaArray: {
*ppvalue = new SrsAmf0EcmaArray(); *ppvalue = SrsAmf0Any::array();
return ret; return ret;
} }
case RTMP_AMF0_Invalid: case RTMP_AMF0_Invalid:
@ -445,11 +583,15 @@ int __SrsAmf0ObjectEOF::write(SrsStream* stream)
SrsAmf0Object::SrsAmf0Object() SrsAmf0Object::SrsAmf0Object()
{ {
properties = new __SrsUnSortedHashtable();
eof = new __SrsAmf0ObjectEOF();
marker = RTMP_AMF0_Object; marker = RTMP_AMF0_Object;
} }
SrsAmf0Object::~SrsAmf0Object() SrsAmf0Object::~SrsAmf0Object()
{ {
srs_freep(properties);
srs_freep(eof);
} }
int SrsAmf0Object::read(SrsStream* stream) int SrsAmf0Object::read(SrsStream* stream)
@ -476,8 +618,8 @@ int SrsAmf0Object::read(SrsStream* stream)
while (!stream->empty()) { while (!stream->empty()) {
// detect whether is eof. // detect whether is eof.
if (srs_amf0_is_object_eof(stream)) { if (srs_amf0_is_object_eof(stream)) {
__SrsAmf0ObjectEOF eof; __SrsAmf0ObjectEOF pbj_eof;
if ((ret = eof.read(stream)) != ERROR_SUCCESS) { if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) {
srs_error("amf0 object read eof failed. ret=%d", ret); srs_error("amf0 object read eof failed. ret=%d", ret);
return ret; return ret;
} }
@ -522,7 +664,7 @@ int SrsAmf0Object::write(SrsStream* stream)
srs_verbose("amf0 write object marker success"); srs_verbose("amf0 write object marker success");
// value // value
for (int i = 0; i < properties.size(); i++) { for (int i = 0; i < properties->size(); i++) {
std::string name = this->key_at(i); std::string name = this->key_at(i);
SrsAmf0Any* any = this->value_at(i); SrsAmf0Any* any = this->value_at(i);
@ -539,7 +681,7 @@ int SrsAmf0Object::write(SrsStream* stream)
srs_verbose("write amf0 property success. name=%s", name.c_str()); srs_verbose("write amf0 property success. name=%s", name.c_str());
} }
if ((ret = eof.write(stream)) != ERROR_SUCCESS) { if ((ret = eof->write(stream)) != ERROR_SUCCESS) {
srs_error("write object eof failed. ret=%d", ret); srs_error("write object eof failed. ret=%d", ret);
return ret; return ret;
} }
@ -553,7 +695,7 @@ int SrsAmf0Object::size()
{ {
int size = 1; int size = 1;
for (int i = 0; i < properties.size(); i++){ for (int i = 0; i < properties->size(); i++){
std::string name = key_at(i); std::string name = key_at(i);
SrsAmf0Any* value = value_at(i); SrsAmf0Any* value = value_at(i);
@ -568,41 +710,45 @@ int SrsAmf0Object::size()
std::string SrsAmf0Object::key_at(int index) std::string SrsAmf0Object::key_at(int index)
{ {
return properties.key_at(index); return properties->key_at(index);
} }
SrsAmf0Any* SrsAmf0Object::value_at(int index) SrsAmf0Any* SrsAmf0Object::value_at(int index)
{ {
return properties.value_at(index); return properties->value_at(index);
} }
void SrsAmf0Object::set(std::string key, SrsAmf0Any* value) void SrsAmf0Object::set(std::string key, SrsAmf0Any* value)
{ {
properties.set(key, value); properties->set(key, value);
} }
SrsAmf0Any* SrsAmf0Object::get_property(std::string name) SrsAmf0Any* SrsAmf0Object::get_property(std::string name)
{ {
return properties.get_property(name); return properties->get_property(name);
} }
SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name) SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name)
{ {
return properties.ensure_property_string(name); return properties->ensure_property_string(name);
} }
SrsAmf0Any* SrsAmf0Object::ensure_property_number(std::string name) SrsAmf0Any* SrsAmf0Object::ensure_property_number(std::string name)
{ {
return properties.ensure_property_number(name); return properties->ensure_property_number(name);
} }
SrsAmf0EcmaArray::SrsAmf0EcmaArray() SrsAmf0EcmaArray::SrsAmf0EcmaArray()
{ {
properties = new __SrsUnSortedHashtable();
eof = new __SrsAmf0ObjectEOF();
marker = RTMP_AMF0_EcmaArray; marker = RTMP_AMF0_EcmaArray;
} }
SrsAmf0EcmaArray::~SrsAmf0EcmaArray() SrsAmf0EcmaArray::~SrsAmf0EcmaArray()
{ {
srs_freep(properties);
srs_freep(eof);
} }
int SrsAmf0EcmaArray::read(SrsStream* stream) int SrsAmf0EcmaArray::read(SrsStream* stream)
@ -641,8 +787,8 @@ int SrsAmf0EcmaArray::read(SrsStream* stream)
while (!stream->empty()) { while (!stream->empty()) {
// detect whether is eof. // detect whether is eof.
if (srs_amf0_is_object_eof(stream)) { if (srs_amf0_is_object_eof(stream)) {
__SrsAmf0ObjectEOF eof; __SrsAmf0ObjectEOF pbj_eof;
if ((ret = eof.read(stream)) != ERROR_SUCCESS) { if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) {
srs_error("amf0 ecma_array read eof failed. ret=%d", ret); srs_error("amf0 ecma_array read eof failed. ret=%d", ret);
return ret; return ret;
} }
@ -695,7 +841,7 @@ int SrsAmf0EcmaArray::write(SrsStream* stream)
srs_verbose("amf0 write ecma_array count success. count=%d", value->count); srs_verbose("amf0 write ecma_array count success. count=%d", value->count);
// value // value
for (int i = 0; i < properties.size(); i++) { for (int i = 0; i < properties->size(); i++) {
std::string name = this->key_at(i); std::string name = this->key_at(i);
SrsAmf0Any* any = this->value_at(i); SrsAmf0Any* any = this->value_at(i);
@ -712,7 +858,7 @@ int SrsAmf0EcmaArray::write(SrsStream* stream)
srs_verbose("write amf0 property success. name=%s", name.c_str()); srs_verbose("write amf0 property success. name=%s", name.c_str());
} }
if ((ret = eof.write(stream)) != ERROR_SUCCESS) { if ((ret = eof->write(stream)) != ERROR_SUCCESS) {
srs_error("write ecma_array eof failed. ret=%d", ret); srs_error("write ecma_array eof failed. ret=%d", ret);
return ret; return ret;
} }
@ -726,7 +872,7 @@ int SrsAmf0EcmaArray::size()
{ {
int size = 1 + 4; int size = 1 + 4;
for (int i = 0; i < properties.size(); i++){ for (int i = 0; i < properties->size(); i++){
std::string name = key_at(i); std::string name = key_at(i);
SrsAmf0Any* value = value_at(i); SrsAmf0Any* value = value_at(i);
@ -741,32 +887,32 @@ int SrsAmf0EcmaArray::size()
void SrsAmf0EcmaArray::clear() void SrsAmf0EcmaArray::clear()
{ {
properties.clear(); properties->clear();
} }
std::string SrsAmf0EcmaArray::key_at(int index) std::string SrsAmf0EcmaArray::key_at(int index)
{ {
return properties.key_at(index); return properties->key_at(index);
} }
SrsAmf0Any* SrsAmf0EcmaArray::value_at(int index) SrsAmf0Any* SrsAmf0EcmaArray::value_at(int index)
{ {
return properties.value_at(index); return properties->value_at(index);
} }
void SrsAmf0EcmaArray::set(std::string key, SrsAmf0Any* value) void SrsAmf0EcmaArray::set(std::string key, SrsAmf0Any* value)
{ {
properties.set(key, value); properties->set(key, value);
} }
SrsAmf0Any* SrsAmf0EcmaArray::get_property(std::string name) SrsAmf0Any* SrsAmf0EcmaArray::get_property(std::string name)
{ {
return properties.get_property(name); return properties->get_property(name);
} }
SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_string(std::string name) SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_string(std::string name)
{ {
return properties.ensure_property_string(name); return properties->ensure_property_string(name);
} }
int SrsAmf0Size::utf8(string value) int SrsAmf0Size::utf8(string value)
@ -1353,7 +1499,7 @@ int srs_amf0_read_object(SrsStream* stream, SrsAmf0Object*& value)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
value = new SrsAmf0Object(); value = SrsAmf0Any::object();
if ((ret = value->read(stream)) != ERROR_SUCCESS) { if ((ret = value->read(stream)) != ERROR_SUCCESS) {
srs_freep(value); srs_freep(value);
@ -1371,7 +1517,7 @@ int srs_amf0_read_ecma_array(SrsStream* stream, SrsAmf0EcmaArray*& value)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
value = new SrsAmf0EcmaArray(); value = SrsAmf0Any::array();
if ((ret = value->read(stream)) != ERROR_SUCCESS) { if ((ret = value->read(stream)) != ERROR_SUCCESS) {
srs_freep(value); srs_freep(value);

View file

@ -36,6 +36,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsStream; class SrsStream;
class SrsAmf0Object; class SrsAmf0Object;
class SrsAmf0EcmaArray; class SrsAmf0EcmaArray;
class __SrsUnSortedHashtable;
class __SrsAmf0ObjectEOF;
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -46,21 +48,20 @@ class SrsAmf0EcmaArray;
// if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) { // if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) {
// return ret; // return ret;
// } // }
// srs_assert(pany); // if success, always valid object.
// 2. SrsAmf0Any: convert to specifid type, for instance, string // 2. SrsAmf0Any: convert to specifid type, for instance, string
// SrsAmf0Any* pany = ... // SrsAmf0Any* pany = ...
// if (pany && pany->is_string()) { // if (pany->is_string()) {
// string v = pany->to_str(); // string v = pany->to_str();
// } // }
// 3. SrsAmf0Any: parse specified type to any, for instance, string // 3. SrsAmf0Any: parse specified type to any, for instance, string
// SrsAmf0Any* pany = SrsAmf0Any::str("winlin"); // SrsAmf0Any* pany = SrsAmf0Any::str("winlin");
// 4. SrsAmf0Size: get amf0 instance size // 4. SrsAmf0Size: get amf0 instance size
// int size = SrsAmf0Size::str("winlin"); // int size = SrsAmf0Size::str("winlin");
// 5. SrsAmf0Object: the amf0 object, directly new is ok. // 5. SrsAmf0Object: the amf0 object.
// SrsAmf0Object* obj = SrsAmf0Any::object(); // SrsAmf0Object* obj = SrsAmf0Any::object();
// SrsAmf0Object* obj = new SrsAmf0Object(); // 5. SrsAmf0EcmaArray: the amf0 ecma array.
// 5. SrsAmf0EcmaArray: the amf0 ecma array, directly new is ok.
// SrsAmf0EcmaArray* arr = SrsAmf0Any::array(); // SrsAmf0EcmaArray* arr = SrsAmf0Any::array();
// SrsAmf0EcmaArray* arr = new SrsAmf0EcmaArray();
// for detail usage, see interfaces of each object. // for detail usage, see interfaces of each object.
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -106,6 +107,16 @@ public:
* user must ensure the type is a number, or assert failed. * user must ensure the type is a number, or assert failed.
*/ */
virtual double to_number(); virtual double to_number();
/**
* get the object of any when is_object() indicates true.
* user must ensure the type is a object, or assert failed.
*/
virtual SrsAmf0Object* to_object();
/**
* get the ecma array of any when is_ecma_array() indicates true.
* user must ensure the type is a ecma array, or assert failed.
*/
virtual SrsAmf0EcmaArray* to_array();
public: public:
/** /**
* get the size of amf0 any, including the marker size. * get the size of amf0 any, including the marker size.
@ -129,50 +140,6 @@ public:
static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue); static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
}; };
/**
* to ensure in inserted order.
* for the FMLE will crash when AMF0Object is not ordered by inserted,
* if ordered in map, the string compare order, the FMLE will creash when
* get the response of connect app.
*/
class __SrsUnSortedHashtable
{
private:
typedef std::pair<std::string, SrsAmf0Any*> SrsObjectPropertyType;
std::vector<SrsObjectPropertyType> properties;
public:
__SrsUnSortedHashtable();
virtual ~__SrsUnSortedHashtable();
virtual int size();
virtual void clear();
virtual std::string key_at(int index);
virtual SrsAmf0Any* value_at(int index);
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name);
};
/**
* 2.11 Object End Type
* object-end-type = UTF-8-empty object-end-marker
* 0x00 0x00 0x09
*/
class __SrsAmf0ObjectEOF : public SrsAmf0Any
{
public:
int16_t utf8_empty;
__SrsAmf0ObjectEOF();
virtual ~__SrsAmf0ObjectEOF();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/** /**
* 2.5 Object Type * 2.5 Object Type
* anonymous-object-type = object-marker *(object-property) * anonymous-object-type = object-marker *(object-property)
@ -181,11 +148,14 @@ public:
class SrsAmf0Object : public SrsAmf0Any class SrsAmf0Object : public SrsAmf0Any
{ {
private: private:
__SrsUnSortedHashtable properties; __SrsUnSortedHashtable* properties;
public: __SrsAmf0ObjectEOF* eof;
__SrsAmf0ObjectEOF eof;
private:
// use SrsAmf0Any::object() to create it.
friend class SrsAmf0Any;
SrsAmf0Object(); SrsAmf0Object();
public:
virtual ~SrsAmf0Object(); virtual ~SrsAmf0Object();
virtual int read(SrsStream* stream); virtual int read(SrsStream* stream);
@ -210,12 +180,15 @@ public:
class SrsAmf0EcmaArray : public SrsAmf0Any class SrsAmf0EcmaArray : public SrsAmf0Any
{ {
private: private:
__SrsUnSortedHashtable properties; __SrsUnSortedHashtable* properties;
public: __SrsAmf0ObjectEOF* eof;
int32_t count; int32_t count;
__SrsAmf0ObjectEOF eof;
private:
// use SrsAmf0Any::array() to create it.
friend class SrsAmf0Any;
SrsAmf0EcmaArray(); SrsAmf0EcmaArray();
public:
virtual ~SrsAmf0EcmaArray(); virtual ~SrsAmf0EcmaArray();
virtual int read(SrsStream* stream); virtual int read(SrsStream* stream);
@ -249,99 +222,10 @@ public:
static int any(SrsAmf0Any* o); static int any(SrsAmf0Any* o);
}; };
/**
* read amf0 string from stream.
* 2.4 String Type
* string-type = string-marker UTF-8
* @return default value is empty string.
* @remark: use SrsAmf0Any::str() to create it.
*/
class __SrsAmf0String : public SrsAmf0Any
{
public:
std::string value;
__SrsAmf0String(const char* _value = NULL);
virtual ~__SrsAmf0String();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 boolean from stream.
* 2.4 String Type
* boolean-type = boolean-marker U8
* 0 is false, <> 0 is true
* @return default value is false.
*/
class __SrsAmf0Boolean : public SrsAmf0Any
{
public:
bool value;
__SrsAmf0Boolean(bool _value = false);
virtual ~__SrsAmf0Boolean();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 number from stream.
* 2.2 Number Type
* number-type = number-marker DOUBLE
* @return default value is 0.
*/
class __SrsAmf0Number : public SrsAmf0Any
{
public:
double value;
__SrsAmf0Number(double _value = 0.0);
virtual ~__SrsAmf0Number();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 null from stream.
* 2.7 null Type
* null-type = null-marker
*/
class __SrsAmf0Null : public SrsAmf0Any
{
public:
__SrsAmf0Null();
virtual ~__SrsAmf0Null();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/**
* read amf0 undefined from stream.
* 2.8 undefined Type
* undefined-type = undefined-marker
*/
class __SrsAmf0Undefined : public SrsAmf0Any
{
public:
__SrsAmf0Undefined();
virtual ~__SrsAmf0Undefined();
virtual int size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
};
/** /**
* read anything from stream. * read anything from stream.
* @param ppvalue, the output amf0 any elem.
* NULL if error; otherwise, never NULL and user must free it.
*/ */
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue); extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue);

View file

@ -279,7 +279,7 @@ int SrsRtmpClient::connect_app(string app, string tc_url)
SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); SrsConnectAppPacket* pkt = new SrsConnectAppPacket();
msg->set_packet(pkt, 0); msg->set_packet(pkt, 0);
pkt->command_object = new SrsAmf0Object(); pkt->command_object = SrsAmf0Any::object();
pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); pkt->command_object->set("app", SrsAmf0Any::str(app.c_str()));
pkt->command_object->set("swfUrl", SrsAmf0Any::str()); pkt->command_object->set("swfUrl", SrsAmf0Any::str());
pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str()));
@ -706,7 +706,7 @@ int SrsRtmpServer::response_connect_app(SrsRequest *req, const char* server_ip)
pkt->info->set(StatusCode, SrsAmf0Any::str(StatusCodeConnectSuccess)); pkt->info->set(StatusCode, SrsAmf0Any::str(StatusCodeConnectSuccess));
pkt->info->set(StatusDescription, SrsAmf0Any::str("Connection succeeded")); pkt->info->set(StatusDescription, SrsAmf0Any::str("Connection succeeded"));
pkt->info->set("objectEncoding", SrsAmf0Any::number(req->objectEncoding)); pkt->info->set("objectEncoding", SrsAmf0Any::number(req->objectEncoding));
SrsAmf0EcmaArray* data = new SrsAmf0EcmaArray(); SrsAmf0EcmaArray* data = SrsAmf0Any::array();
pkt->info->set("data", data); pkt->info->set("data", data);
data->set("version", SrsAmf0Any::str(RTMP_SIG_FMS_VER)); data->set("version", SrsAmf0Any::str(RTMP_SIG_FMS_VER));

View file

@ -1828,8 +1828,8 @@ SrsConnectAppResPacket::SrsConnectAppResPacket()
transaction_id = 1; transaction_id = 1;
// TODO: FIXME: memory leak for decode will set the props and info. // TODO: FIXME: memory leak for decode will set the props and info.
// TODO: FIXME: bug#22, refine the amf0. // TODO: FIXME: bug#22, refine the amf0.
props = new SrsAmf0Object(); props = SrsAmf0Any::object();
info = new SrsAmf0Object(); info = SrsAmf0Any::object();
} }
SrsConnectAppResPacket::~SrsConnectAppResPacket() SrsConnectAppResPacket::~SrsConnectAppResPacket()
@ -2718,7 +2718,7 @@ SrsPlayResPacket::SrsPlayResPacket()
command_name = RTMP_AMF0_COMMAND_RESULT; command_name = RTMP_AMF0_COMMAND_RESULT;
transaction_id = 0; transaction_id = 0;
command_object = SrsAmf0Any::null(); command_object = SrsAmf0Any::null();
desc = new SrsAmf0Object(); desc = SrsAmf0Any::object();
} }
SrsPlayResPacket::~SrsPlayResPacket() SrsPlayResPacket::~SrsPlayResPacket()
@ -2837,7 +2837,7 @@ SrsOnStatusCallPacket::SrsOnStatusCallPacket()
command_name = RTMP_AMF0_COMMAND_ON_STATUS; command_name = RTMP_AMF0_COMMAND_ON_STATUS;
transaction_id = 0; transaction_id = 0;
args = SrsAmf0Any::null(); args = SrsAmf0Any::null();
data = new SrsAmf0Object(); data = SrsAmf0Any::object();
} }
SrsOnStatusCallPacket::~SrsOnStatusCallPacket() SrsOnStatusCallPacket::~SrsOnStatusCallPacket()
@ -2900,7 +2900,7 @@ SrsBandwidthPacket::SrsBandwidthPacket()
command_name = RTMP_AMF0_COMMAND_ON_STATUS; command_name = RTMP_AMF0_COMMAND_ON_STATUS;
transaction_id = 0; transaction_id = 0;
args = SrsAmf0Any::null(); args = SrsAmf0Any::null();
data = new SrsAmf0Object(); data = SrsAmf0Any::object();
} }
SrsBandwidthPacket::~SrsBandwidthPacket() SrsBandwidthPacket::~SrsBandwidthPacket()
@ -3055,7 +3055,7 @@ SrsBandwidthPacket* SrsBandwidthPacket::set_command(string command)
SrsOnStatusDataPacket::SrsOnStatusDataPacket() SrsOnStatusDataPacket::SrsOnStatusDataPacket()
{ {
command_name = RTMP_AMF0_COMMAND_ON_STATUS; command_name = RTMP_AMF0_COMMAND_ON_STATUS;
data = new SrsAmf0Object(); data = SrsAmf0Any::object();
} }
SrsOnStatusDataPacket::~SrsOnStatusDataPacket() SrsOnStatusDataPacket::~SrsOnStatusDataPacket()
@ -3156,7 +3156,7 @@ int SrsSampleAccessPacket::encode_packet(SrsStream* stream)
SrsOnMetaDataPacket::SrsOnMetaDataPacket() SrsOnMetaDataPacket::SrsOnMetaDataPacket()
{ {
name = RTMP_AMF0_DATA_ON_METADATA; name = RTMP_AMF0_DATA_ON_METADATA;
metadata = new SrsAmf0Object(); metadata = SrsAmf0Any::object();
} }
SrsOnMetaDataPacket::~SrsOnMetaDataPacket() SrsOnMetaDataPacket::~SrsOnMetaDataPacket()
@ -3190,27 +3190,27 @@ int SrsOnMetaDataPacket::decode(SrsStream* stream)
return ret; return ret;
} }
if (any && any->is_object()) { srs_assert(any);
if (any->is_object()) {
srs_freep(metadata); srs_freep(metadata);
metadata = dynamic_cast<SrsAmf0Object*>(any); metadata = any->to_object();
srs_info("decode metadata object success"); srs_info("decode metadata object success");
return ret; return ret;
} }
SrsAmf0EcmaArray* arr = dynamic_cast<SrsAmf0EcmaArray*>(any); SrsAutoFree(SrsAmf0Any, any, false);
if (!arr) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("decode metadata array failed. ret=%d", ret);
return ret;
}
// if ecma array, copy to object. if (any->is_ecma_array()) {
SrsAutoFree(SrsAmf0EcmaArray, arr, false); SrsAmf0EcmaArray* arr = any->to_array();
for (int i = 0; i < arr->size(); i++) {
metadata->set(arr->key_at(i), arr->value_at(i)); // if ecma array, copy to object.
for (int i = 0; i < arr->size(); i++) {
metadata->set(arr->key_at(i), arr->value_at(i));
}
arr->clear();
srs_info("decode metadata array success");
} }
arr->clear();
srs_info("decode metadata array success");
return ret; return ret;
} }

View file

@ -46,221 +46,239 @@ VOID TEST(AMF0Test, Size)
// object: empty // object: empty
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
// object: elem // object: elem
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("age")+SrsAmf0Size::number(); size += SrsAmf0Size::utf8("age")+SrsAmf0Size::number();
o.set("age", SrsAmf0Any::number(9)); o->set("age", SrsAmf0Any::number(9));
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("email")+SrsAmf0Size::null(); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::null();
o.set("email", SrsAmf0Any::null()); o->set("email", SrsAmf0Any::null());
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("email")+SrsAmf0Size::undefined(); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::undefined();
o.set("email", SrsAmf0Any::undefined()); o->set("email", SrsAmf0Any::undefined());
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("sex")+SrsAmf0Size::boolean(); size += SrsAmf0Size::utf8("sex")+SrsAmf0Size::boolean();
o.set("sex", SrsAmf0Any::boolean(true)); o->set("sex", SrsAmf0Any::boolean(true));
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
// array: empty // array: empty
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
// array: elem // array: elem
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("age")+SrsAmf0Size::number(); size += SrsAmf0Size::utf8("age")+SrsAmf0Size::number();
o.set("age", SrsAmf0Any::number(9)); o->set("age", SrsAmf0Any::number(9));
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("email")+SrsAmf0Size::null(); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::null();
o.set("email", SrsAmf0Any::null()); o->set("email", SrsAmf0Any::null());
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("email")+SrsAmf0Size::undefined(); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::undefined();
o.set("email", SrsAmf0Any::undefined()); o->set("email", SrsAmf0Any::undefined());
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("sex")+SrsAmf0Size::boolean(); size += SrsAmf0Size::utf8("sex")+SrsAmf0Size::boolean();
o.set("sex", SrsAmf0Any::boolean(true)); o->set("sex", SrsAmf0Any::boolean(true));
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
// object: array // object: array
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
SrsAmf0EcmaArray* args = new SrsAmf0EcmaArray(); SrsAmf0EcmaArray* args = SrsAmf0Any::array();
args->set("p0", SrsAmf0Any::str("function")); args->set("p0", SrsAmf0Any::str("function"));
size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args);
o.set("args", args); o->set("args", args);
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
SrsAmf0EcmaArray* args = new SrsAmf0EcmaArray(); SrsAmf0EcmaArray* args = SrsAmf0Any::array();
args->set("p0", SrsAmf0Any::str("function")); args->set("p0", SrsAmf0Any::str("function"));
size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args);
o.set("args", args); o->set("args", args);
SrsAmf0EcmaArray* params = new SrsAmf0EcmaArray(); SrsAmf0EcmaArray* params = SrsAmf0Any::array();
params->set("p1", SrsAmf0Any::number(10)); params->set("p1", SrsAmf0Any::number(10));
size += SrsAmf0Size::utf8("params")+SrsAmf0Size::array(params); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::array(params);
o.set("params", params); o->set("params", params);
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
// array: object // array: object
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
SrsAmf0Object* args = new SrsAmf0Object(); SrsAmf0Object* args = SrsAmf0Any::object();
args->set("p0", SrsAmf0Any::str("function")); args->set("p0", SrsAmf0Any::str("function"));
size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args);
o.set("args", args); o->set("args", args);
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
SrsAmf0Object* args = new SrsAmf0Object(); SrsAmf0Object* args = SrsAmf0Any::object();
args->set("p0", SrsAmf0Any::str("function")); args->set("p0", SrsAmf0Any::str("function"));
size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args);
o.set("args", args); o->set("args", args);
SrsAmf0Object* params = new SrsAmf0Object(); SrsAmf0Object* params = SrsAmf0Any::object();
params->set("p1", SrsAmf0Any::number(10)); params->set("p1", SrsAmf0Any::number(10));
size += SrsAmf0Size::utf8("params")+SrsAmf0Size::object(params); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::object(params);
o.set("params", params); o->set("params", params);
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
// object: object // object: object
if (true) { if (true) {
int size = 1+3; int size = 1+3;
SrsAmf0Object o; SrsAmf0Object* o = SrsAmf0Any::object();
SrsAutoFree(SrsAmf0Object, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
SrsAmf0Object* args = new SrsAmf0Object(); SrsAmf0Object* args = SrsAmf0Any::object();
args->set("p0", SrsAmf0Any::str("function")); args->set("p0", SrsAmf0Any::str("function"));
size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args);
o.set("args", args); o->set("args", args);
SrsAmf0Object* params = new SrsAmf0Object(); SrsAmf0Object* params = SrsAmf0Any::object();
params->set("p1", SrsAmf0Any::number(10)); params->set("p1", SrsAmf0Any::number(10));
size += SrsAmf0Size::utf8("params")+SrsAmf0Size::object(params); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::object(params);
o.set("params", params); o->set("params", params);
EXPECT_EQ(size, SrsAmf0Size::object(&o)); EXPECT_EQ(size, SrsAmf0Size::object(o));
} }
// array: array // array: array
if (true) { if (true) {
int size = 1+4+3; int size = 1+4+3;
SrsAmf0EcmaArray o; SrsAmf0EcmaArray* o = SrsAmf0Any::array();
SrsAutoFree(SrsAmf0EcmaArray, o, false);
size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin");
o.set("name", SrsAmf0Any::str("winlin")); o->set("name", SrsAmf0Any::str("winlin"));
SrsAmf0EcmaArray* args = new SrsAmf0EcmaArray(); SrsAmf0EcmaArray* args = SrsAmf0Any::array();
args->set("p0", SrsAmf0Any::str("function")); args->set("p0", SrsAmf0Any::str("function"));
size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args);
o.set("args", args); o->set("args", args);
SrsAmf0EcmaArray* params = new SrsAmf0EcmaArray(); SrsAmf0EcmaArray* params = SrsAmf0Any::array();
params->set("p1", SrsAmf0Any::number(10)); params->set("p1", SrsAmf0Any::number(10));
size += SrsAmf0Size::utf8("params")+SrsAmf0Size::array(params); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::array(params);
o.set("params", params); o->set("params", params);
EXPECT_EQ(size, SrsAmf0Size::array(&o)); EXPECT_EQ(size, SrsAmf0Size::array(o));
} }
} }
@ -656,3 +674,24 @@ VOID TEST(AMF0Test, AnyIO)
srs_freep(po); srs_freep(po);
} }
} }
VOID TEST(AMF0Test, AnyAssert)
{
SrsStream s;
SrsAmf0Any* o = NULL;
char buf[1024];
memset(buf, 0, sizeof(buf));
EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf)));
// read any
if (true) {
s.reset();
s.current()[0] = 0x12;
EXPECT_NE(ERROR_SUCCESS, srs_amf0_read_any(&s, &o));
EXPECT_TRUE(NULL == o);
srs_freep(o);
}
//
}