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

amf0 utest: elem read/write refined

This commit is contained in:
winlin 2014-03-08 16:56:35 +08:00
parent bfe771bbba
commit 4306db099d
6 changed files with 514 additions and 137 deletions

View file

@ -56,9 +56,32 @@ using namespace std;
// User defined
#define RTMP_AMF0_Invalid 0x3F
int srs_amf0_read_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF*&);
int srs_amf0_write_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF*);
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value);
/**
* convert the any to specified object.
* @return T, the converted object. never NULL.
* @remark, user must ensure the current object type,
* or the covert will cause assert failed.
*/
template<class T>
T srs_amf0_convert(SrsAmf0Any* any)
{
T p = dynamic_cast<T>(any);
srs_assert(p != NULL);
return p;
}
/**
* read amf0 utf8 string from stream.
* 1.3.1 Strings and UTF-8
* UTF-8 = U16 *(UTF8-char)
* UTF8-char = UTF8-1 | UTF8-2 | UTF8-3 | UTF8-4
* UTF8-1 = %x00-7F
* @remark only support UTF8-1 char.
*/
extern int srs_amf0_read_utf8(SrsStream* stream, std::string& value);
extern int srs_amf0_write_utf8(SrsStream* stream, std::string value);
bool srs_amf0_is_object_eof(SrsStream* stream);
int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value);
SrsAmf0Any::SrsAmf0Any()
@ -107,19 +130,19 @@ bool SrsAmf0Any::is_ecma_array()
string SrsAmf0Any::to_str()
{
__SrsAmf0String* o = srs_amf0_convert<__SrsAmf0String>(this);
__SrsAmf0String* o = srs_amf0_convert<__SrsAmf0String*>(this);
return o->value;
}
bool SrsAmf0Any::to_boolean()
{
__SrsAmf0Boolean* o = srs_amf0_convert<__SrsAmf0Boolean>(this);
__SrsAmf0Boolean* o = srs_amf0_convert<__SrsAmf0Boolean*>(this);
return o->value;
}
double SrsAmf0Any::to_number()
{
__SrsAmf0Number* o = srs_amf0_convert<__SrsAmf0Number>(this);
__SrsAmf0Number* o = srs_amf0_convert<__SrsAmf0Number*>(this);
return o->value;
}
@ -153,6 +176,11 @@ SrsAmf0Any* SrsAmf0Any::undefined()
return new __SrsAmf0Undefined();
}
SrsAmf0Any* SrsAmf0Any::object_eof()
{
return new __SrsAmf0ObjectEOF();
}
__SrsUnSortedHashtable::__SrsUnSortedHashtable()
{
}
@ -194,6 +222,11 @@ SrsAmf0Any* __SrsUnSortedHashtable::value_at(int index)
void __SrsUnSortedHashtable::set(std::string key, SrsAmf0Any* value)
{
if (!value) {
srs_warn("add a NULL propertity %s", key.c_str());
return;
}
std::vector<SrsObjectPropertyType>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
@ -272,6 +305,71 @@ int __SrsAmf0ObjectEOF::size()
return SrsAmf0Size::object_eof();
}
int __SrsAmf0ObjectEOF::read(SrsStream* stream)
{
int ret = ERROR_SUCCESS;
// value
if (!stream->require(2)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read object eof value failed. ret=%d", ret);
return ret;
}
int16_t temp = stream->read_2bytes();
if (temp != 0x00) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read object eof value check failed. "
"must be 0x00, actual is %#x, ret=%d", temp, ret);
return ret;
}
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read object eof marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_ObjectEnd) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check object eof marker failed. "
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret);
return ret;
}
srs_verbose("amf0 read object eof marker success");
srs_verbose("amf0 read object eof success");
return ret;
}
int __SrsAmf0ObjectEOF::write(SrsStream* stream)
{
int ret = ERROR_SUCCESS;
// value
if (!stream->require(2)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write object eof value failed. ret=%d", ret);
return ret;
}
stream->write_2bytes(0x00);
srs_verbose("amf0 write object eof value success");
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write object eof marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_ObjectEnd);
srs_verbose("amf0 read object eof success");
return ret;
}
SrsAmf0Object::SrsAmf0Object()
{
marker = RTMP_AMF0_Object;
@ -303,6 +401,17 @@ int SrsAmf0Object::read(SrsStream* stream)
// value
while (!stream->empty()) {
// detect whether is eof.
if (srs_amf0_is_object_eof(stream)) {
__SrsAmf0ObjectEOF eof;
if ((ret = eof.read(stream)) != ERROR_SUCCESS) {
srs_error("amf0 object read eof failed. ret=%d", ret);
return ret;
}
srs_info("amf0 read object EOF.");
break;
}
// property-name: utf8 string
std::string property_name;
if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) {
@ -311,21 +420,13 @@ int SrsAmf0Object::read(SrsStream* stream)
}
// property-value: any
SrsAmf0Any* property_value = NULL;
if ((ret = srs_amf0_read_any(stream, property_value)) != ERROR_SUCCESS) {
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
srs_error("amf0 object read property_value failed. "
"name=%s, ret=%d", property_name.c_str(), ret);
srs_freep(property_value);
return ret;
}
// AMF0 Object EOF.
if (property_name.empty() || !property_value || property_value->is_object_eof()) {
if (property_value) {
srs_freep(property_value);
}
srs_info("amf0 read object EOF.");
break;
}
// add property
this->set(property_name, property_value);
}
@ -365,7 +466,7 @@ int SrsAmf0Object::write(SrsStream* stream)
srs_verbose("write amf0 property success. name=%s", name.c_str());
}
if ((ret = srs_amf0_write_object_eof(stream, &this->eof)) != ERROR_SUCCESS) {
if ((ret = eof.write(stream)) != ERROR_SUCCESS) {
srs_error("write object eof failed. ret=%d", ret);
return ret;
}
@ -465,6 +566,17 @@ int SrsAmf0EcmaArray::read(SrsStream* stream)
this->count = count;
while (!stream->empty()) {
// detect whether is eof.
if (srs_amf0_is_object_eof(stream)) {
__SrsAmf0ObjectEOF eof;
if ((ret = eof.read(stream)) != ERROR_SUCCESS) {
srs_error("amf0 ecma_array read eof failed. ret=%d", ret);
return ret;
}
srs_info("amf0 read ecma_array EOF.");
break;
}
// property-name: utf8 string
std::string property_name;
if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) {
@ -473,21 +585,12 @@ int SrsAmf0EcmaArray::read(SrsStream* stream)
}
// property-value: any
SrsAmf0Any* property_value = NULL;
if ((ret = srs_amf0_read_any(stream, property_value)) != ERROR_SUCCESS) {
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
srs_error("amf0 ecma_array read property_value failed. "
"name=%s, ret=%d", property_name.c_str(), ret);
return ret;
}
// AMF0 Object EOF.
if (property_name.empty() || !property_value || property_value->is_object_eof()) {
if (property_value) {
srs_freep(property_value);
}
srs_info("amf0 read ecma_array EOF.");
break;
}
// add property
this->set(property_name, property_value);
}
@ -536,7 +639,7 @@ int SrsAmf0EcmaArray::write(SrsStream* stream)
srs_verbose("write amf0 property success. name=%s", name.c_str());
}
if ((ret = srs_amf0_write_object_eof(stream, &this->eof)) != ERROR_SUCCESS) {
if ((ret = eof.write(stream)) != ERROR_SUCCESS) {
srs_error("write ecma_array eof failed. ret=%d", ret);
return ret;
}
@ -672,6 +775,16 @@ int __SrsAmf0String::size()
return SrsAmf0Size::str(value);
}
int __SrsAmf0String::read(SrsStream* stream)
{
return srs_amf0_read_string(stream, value);
}
int __SrsAmf0String::write(SrsStream* stream)
{
return srs_amf0_write_string(stream, value);
}
__SrsAmf0Boolean::__SrsAmf0Boolean(bool _value)
{
marker = RTMP_AMF0_Boolean;
@ -687,6 +800,16 @@ int __SrsAmf0Boolean::size()
return SrsAmf0Size::boolean();
}
int __SrsAmf0Boolean::read(SrsStream* stream)
{
return srs_amf0_read_boolean(stream, value);
}
int __SrsAmf0Boolean::write(SrsStream* stream)
{
return srs_amf0_write_boolean(stream, value);
}
__SrsAmf0Number::__SrsAmf0Number(double _value)
{
marker = RTMP_AMF0_Number;
@ -702,6 +825,16 @@ int __SrsAmf0Number::size()
return SrsAmf0Size::number();
}
int __SrsAmf0Number::read(SrsStream* stream)
{
return srs_amf0_read_number(stream, value);
}
int __SrsAmf0Number::write(SrsStream* stream)
{
return srs_amf0_write_number(stream, value);
}
__SrsAmf0Null::__SrsAmf0Null()
{
marker = RTMP_AMF0_Null;
@ -716,6 +849,16 @@ int __SrsAmf0Null::size()
return SrsAmf0Size::null();
}
int __SrsAmf0Null::read(SrsStream* stream)
{
return srs_amf0_read_null(stream);
}
int __SrsAmf0Null::write(SrsStream* stream)
{
return srs_amf0_write_null(stream);
}
__SrsAmf0Undefined::__SrsAmf0Undefined()
{
marker = RTMP_AMF0_Undefined;
@ -730,6 +873,16 @@ int __SrsAmf0Undefined::size()
return SrsAmf0Size::undefined();
}
int __SrsAmf0Undefined::read(SrsStream* stream)
{
return srs_amf0_read_undefined(stream);
}
int __SrsAmf0Undefined::write(SrsStream* stream)
{
return srs_amf0_write_undefined(stream);
}
int srs_amf0_read_utf8(SrsStream* stream, std::string& value)
{
int ret = ERROR_SUCCESS;
@ -1055,10 +1208,33 @@ int srs_amf0_write_undefined(SrsStream* stream)
return ret;
}
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
bool srs_amf0_is_object_eof(SrsStream* stream)
{
// detect the object-eof specially
if (stream->require(3)) {
int32_t flag = stream->read_3bytes();
stream->skip(-3);
return 0x09 == flag;
}
return false;
}
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue)
{
int ret = ERROR_SUCCESS;
// detect the object-eof specially
if (srs_amf0_is_object_eof(stream)) {
*ppvalue = new __SrsAmf0ObjectEOF();
if ((ret = (*ppvalue)->read(stream)) != ERROR_SUCCESS) {
srs_freep(*ppvalue);
return ret;
}
return ret;
}
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
@ -1078,7 +1254,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
if ((ret = srs_amf0_read_string(stream, data)) != ERROR_SUCCESS) {
return ret;
}
value = SrsAmf0Any::str(data.c_str());
*ppvalue = SrsAmf0Any::str(data.c_str());
return ret;
}
case RTMP_AMF0_Boolean: {
@ -1086,7 +1262,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
if ((ret = srs_amf0_read_boolean(stream, data)) != ERROR_SUCCESS) {
return ret;
}
value = SrsAmf0Any::boolean(data);
*ppvalue = SrsAmf0Any::boolean(data);
return ret;
}
case RTMP_AMF0_Number: {
@ -1094,25 +1270,17 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
if ((ret = srs_amf0_read_number(stream, data)) != ERROR_SUCCESS) {
return ret;
}
value = SrsAmf0Any::number(data);
*ppvalue = SrsAmf0Any::number(data);
return ret;
}
case RTMP_AMF0_Null: {
stream->skip(1);
value = new __SrsAmf0Null();
*ppvalue = new __SrsAmf0Null();
return ret;
}
case RTMP_AMF0_Undefined: {
stream->skip(1);
value = new __SrsAmf0Undefined();
return ret;
}
case RTMP_AMF0_ObjectEnd: {
__SrsAmf0ObjectEOF* p = NULL;
if ((ret = srs_amf0_read_object_eof(stream, p)) != ERROR_SUCCESS) {
return ret;
}
value = p;
*ppvalue = new __SrsAmf0Undefined();
return ret;
}
case RTMP_AMF0_Object: {
@ -1120,7 +1288,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
if ((ret = srs_amf0_read_object(stream, p)) != ERROR_SUCCESS) {
return ret;
}
value = p;
*ppvalue = p;
return ret;
}
case RTMP_AMF0_EcmaArray: {
@ -1128,7 +1296,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
if ((ret = srs_amf0_read_ecma_array(stream, p)) != ERROR_SUCCESS) {
return ret;
}
value = p;
*ppvalue = p;
return ret;
}
case RTMP_AMF0_Invalid:
@ -1149,15 +1317,15 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
switch (value->marker) {
case RTMP_AMF0_String: {
std::string data = srs_amf0_convert<__SrsAmf0String>(value)->value;
std::string data = srs_amf0_convert<__SrsAmf0String*>(value)->value;
return srs_amf0_write_string(stream, data);
}
case RTMP_AMF0_Boolean: {
bool data = srs_amf0_convert<__SrsAmf0Boolean>(value)->value;
bool data = srs_amf0_convert<__SrsAmf0Boolean*>(value)->value;
return srs_amf0_write_boolean(stream, data);
}
case RTMP_AMF0_Number: {
double data = srs_amf0_convert<__SrsAmf0Number>(value)->value;
double data = srs_amf0_convert<__SrsAmf0Number*>(value)->value;
return srs_amf0_write_number(stream, data);
}
case RTMP_AMF0_Null: {
@ -1167,15 +1335,15 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
return srs_amf0_write_undefined(stream);
}
case RTMP_AMF0_ObjectEnd: {
__SrsAmf0ObjectEOF* p = srs_amf0_convert<__SrsAmf0ObjectEOF>(value);
return srs_amf0_write_object_eof(stream, p);
__SrsAmf0ObjectEOF* p = srs_amf0_convert<__SrsAmf0ObjectEOF*>(value);
return p->write(stream);
}
case RTMP_AMF0_Object: {
SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object>(value);
SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object*>(value);
return srs_amf0_write_object(stream, p);
}
case RTMP_AMF0_EcmaArray: {
SrsAmf0EcmaArray* p = srs_amf0_convert<SrsAmf0EcmaArray>(value);
SrsAmf0EcmaArray* p = srs_amf0_convert<SrsAmf0EcmaArray*>(value);
return srs_amf0_write_ecma_array(stream, p);
}
case RTMP_AMF0_Invalid:
@ -1189,49 +1357,6 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
return ret;
}
int srs_amf0_read_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF*& value)
{
int ret = ERROR_SUCCESS;
// auto skip -2 to read the object eof.
srs_assert(stream->pos() >= 2);
stream->skip(-2);
// value
if (!stream->require(2)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read object eof value failed. ret=%d", ret);
return ret;
}
int16_t temp = stream->read_2bytes();
if (temp != 0x00) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read object eof value check failed. "
"must be 0x00, actual is %#x, ret=%d", temp, ret);
return ret;
}
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read object eof marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_ObjectEnd) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check object eof marker failed. "
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret);
return ret;
}
srs_verbose("amf0 read object eof marker success");
value = new __SrsAmf0ObjectEOF();
srs_verbose("amf0 read object eof success");
return ret;
}
int srs_amf0_write_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF* value)
{
int ret = ERROR_SUCCESS;