1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00
srs/trunk/src/protocol/srs_protocol_amf0.cpp

2008 lines
48 KiB
C++
Raw Normal View History

2017-03-25 09:21:39 +00:00
/**
* The MIT License (MIT)
*
2017-03-25 13:29:29 +00:00
* Copyright (c) 2013-2017 OSSRS(winlin)
2017-03-25 09:21:39 +00:00
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
2013-11-23 03:36:07 +00:00
2015-09-22 01:05:21 +00:00
#include <srs_protocol_amf0.hpp>
2013-11-23 03:36:07 +00:00
#include <utility>
#include <vector>
#include <sstream>
using namespace std;
2013-11-23 03:36:07 +00:00
#include <srs_kernel_log.hpp>
#include <srs_kernel_error.hpp>
2015-09-22 00:48:55 +00:00
#include <srs_kernel_buffer.hpp>
#include <srs_protocol_json.hpp>
2013-11-23 03:36:07 +00:00
using namespace _srs_internal;
2013-11-23 03:36:07 +00:00
// AMF0 marker
2014-03-18 03:32:58 +00:00
#define RTMP_AMF0_Number 0x00
#define RTMP_AMF0_Boolean 0x01
#define RTMP_AMF0_String 0x02
#define RTMP_AMF0_Object 0x03
#define RTMP_AMF0_MovieClip 0x04 // reserved, not supported
#define RTMP_AMF0_Null 0x05
#define RTMP_AMF0_Undefined 0x06
#define RTMP_AMF0_Reference 0x07
#define RTMP_AMF0_EcmaArray 0x08
#define RTMP_AMF0_ObjectEnd 0x09
#define RTMP_AMF0_StrictArray 0x0A
#define RTMP_AMF0_Date 0x0B
#define RTMP_AMF0_LongString 0x0C
#define RTMP_AMF0_UnSupported 0x0D
#define RTMP_AMF0_RecordSet 0x0E // reserved, not supported
#define RTMP_AMF0_XmlDocument 0x0F
#define RTMP_AMF0_TypedObject 0x10
2013-11-23 03:36:07 +00:00
// AVM+ object is the AMF3 object.
2014-03-18 03:32:58 +00:00
#define RTMP_AMF0_AVMplusObject 0x11
2013-11-23 03:36:07 +00:00
// origin array whos data takes the same form as LengthValueBytes
2014-03-18 03:32:58 +00:00
#define RTMP_AMF0_OriginStrictArray 0x20
2013-11-23 03:36:07 +00:00
// User defined
2014-03-18 03:32:58 +00:00
#define RTMP_AMF0_Invalid 0x3F
2013-11-23 03:36:07 +00:00
SrsAmf0Any::SrsAmf0Any()
{
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_Invalid;
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any::~SrsAmf0Any()
{
}
bool SrsAmf0Any::is_string()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_String;
2013-11-23 03:36:07 +00:00
}
bool SrsAmf0Any::is_boolean()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_Boolean;
2013-11-23 03:36:07 +00:00
}
bool SrsAmf0Any::is_number()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_Number;
2013-11-23 03:36:07 +00:00
}
bool SrsAmf0Any::is_null()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_Null;
2013-11-23 03:36:07 +00:00
}
bool SrsAmf0Any::is_undefined()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_Undefined;
2013-11-23 03:36:07 +00:00
}
bool SrsAmf0Any::is_object()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_Object;
2013-11-23 03:36:07 +00:00
}
bool SrsAmf0Any::is_ecma_array()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_EcmaArray;
2013-11-23 03:36:07 +00:00
}
bool SrsAmf0Any::is_strict_array()
{
return marker == RTMP_AMF0_StrictArray;
}
bool SrsAmf0Any::is_date()
{
return marker == RTMP_AMF0_Date;
}
bool SrsAmf0Any::is_complex_object()
{
return is_object() || is_object_eof() || is_ecma_array() || is_strict_array();
}
2014-03-08 06:13:31 +00:00
string SrsAmf0Any::to_str()
{
2014-07-06 09:12:26 +00:00
SrsAmf0String* p = dynamic_cast<SrsAmf0String*>(this);
2014-03-18 03:32:58 +00:00
srs_assert(p != NULL);
return p->value;
}
const char* SrsAmf0Any::to_str_raw()
{
2014-07-06 09:12:26 +00:00
SrsAmf0String* p = dynamic_cast<SrsAmf0String*>(this);
srs_assert(p != NULL);
return p->value.data();
}
2014-03-08 06:13:31 +00:00
bool SrsAmf0Any::to_boolean()
{
2014-07-06 09:12:26 +00:00
SrsAmf0Boolean* p = dynamic_cast<SrsAmf0Boolean*>(this);
2014-03-18 03:32:58 +00:00
srs_assert(p != NULL);
return p->value;
2014-03-08 06:13:31 +00:00
}
double SrsAmf0Any::to_number()
{
2014-07-06 09:12:26 +00:00
SrsAmf0Number* p = dynamic_cast<SrsAmf0Number*>(this);
2014-03-18 03:32:58 +00:00
srs_assert(p != NULL);
return p->value;
}
int64_t SrsAmf0Any::to_date()
{
SrsAmf0Date* p = dynamic_cast<SrsAmf0Date*>(this);
srs_assert(p != NULL);
return p->date();
}
int16_t SrsAmf0Any::to_date_time_zone()
{
SrsAmf0Date* p = dynamic_cast<SrsAmf0Date*>(this);
srs_assert(p != NULL);
return p->time_zone();
}
SrsAmf0Object* SrsAmf0Any::to_object()
{
2014-03-18 03:32:58 +00:00
SrsAmf0Object* p = dynamic_cast<SrsAmf0Object*>(this);
srs_assert(p != NULL);
return p;
}
2014-03-08 14:07:40 +00:00
SrsAmf0EcmaArray* SrsAmf0Any::to_ecma_array()
{
2014-03-18 03:32:58 +00:00
SrsAmf0EcmaArray* p = dynamic_cast<SrsAmf0EcmaArray*>(this);
srs_assert(p != NULL);
return p;
}
SrsAmf0StrictArray* SrsAmf0Any::to_strict_array()
{
SrsAmf0StrictArray* p = dynamic_cast<SrsAmf0StrictArray*>(this);
srs_assert(p != NULL);
return p;
}
void SrsAmf0Any::set_number(double value)
{
2014-07-06 09:12:26 +00:00
SrsAmf0Number* p = dynamic_cast<SrsAmf0Number*>(this);
srs_assert(p != NULL);
p->value = value;
}
2013-11-23 03:36:07 +00:00
bool SrsAmf0Any::is_object_eof()
{
2014-03-18 03:32:58 +00:00
return marker == RTMP_AMF0_ObjectEnd;
2013-11-23 03:36:07 +00:00
}
void srs_fill_level_spaces(stringstream& ss, int level)
{
for (int i = 0; i < level; i++) {
ss << " ";
}
}
void srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level)
{
2017-06-13 08:10:46 +00:00
std::ios_base::fmtflags oflags = ss.flags();
if (any->is_boolean()) {
ss << "Boolean " << (any->to_boolean()? "true":"false") << endl;
} else if (any->is_number()) {
ss << "Number " << std::fixed << any->to_number() << endl;
} else if (any->is_string()) {
ss << "String " << any->to_str() << endl;
} else if (any->is_date()) {
2017-03-25 09:21:39 +00:00
ss << "Date " << std::hex << any->to_date()
<< "/" << std::hex << any->to_date_time_zone() << endl;
} else if (any->is_null()) {
ss << "Null" << endl;
} else if (any->is_ecma_array()) {
SrsAmf0EcmaArray* obj = any->to_ecma_array();
ss << "EcmaArray " << "(" << obj->count() << " items)" << endl;
for (int i = 0; i < obj->count(); i++) {
srs_fill_level_spaces(ss, level + 1);
ss << "Elem '" << obj->key_at(i) << "' ";
if (obj->value_at(i)->is_complex_object()) {
srs_amf0_do_print(obj->value_at(i), ss, level + 1);
} else {
srs_amf0_do_print(obj->value_at(i), ss, 0);
}
}
} else if (any->is_strict_array()) {
SrsAmf0StrictArray* obj = any->to_strict_array();
ss << "StrictArray " << "(" << obj->count() << " items)" << endl;
for (int i = 0; i < obj->count(); i++) {
srs_fill_level_spaces(ss, level + 1);
ss << "Elem ";
if (obj->at(i)->is_complex_object()) {
srs_amf0_do_print(obj->at(i), ss, level + 1);
} else {
srs_amf0_do_print(obj->at(i), ss, 0);
}
}
} else if (any->is_object()) {
SrsAmf0Object* obj = any->to_object();
ss << "Object " << "(" << obj->count() << " items)" << endl;
for (int i = 0; i < obj->count(); i++) {
srs_fill_level_spaces(ss, level + 1);
ss << "Property '" << obj->key_at(i) << "' ";
if (obj->value_at(i)->is_complex_object()) {
srs_amf0_do_print(obj->value_at(i), ss, level + 1);
} else {
srs_amf0_do_print(obj->value_at(i), ss, 0);
}
}
} else {
ss << "Unknown" << endl;
}
2017-06-13 08:10:46 +00:00
ss.flags(oflags);
}
char* SrsAmf0Any::human_print(char** pdata, int* psize)
{
stringstream ss;
ss.precision(1);
srs_amf0_do_print(this, ss, 0);
string str = ss.str();
if (str.empty()) {
return NULL;
}
char* data = new char[str.length() + 1];
memcpy(data, str.data(), str.length());
data[str.length()] = 0;
if (pdata) {
*pdata = data;
}
if (psize) {
*psize = (int)str.length();
}
return data;
}
SrsJsonAny* SrsAmf0Any::to_json()
{
switch (marker) {
case RTMP_AMF0_String: {
return SrsJsonAny::str(to_str().c_str());
}
case RTMP_AMF0_Boolean: {
return SrsJsonAny::boolean(to_boolean());
}
case RTMP_AMF0_Number: {
double dv = to_number();
int64_t iv = (int64_t)dv;
if (iv == dv) {
return SrsJsonAny::integer(iv);
} else {
return SrsJsonAny::number(dv);
}
}
case RTMP_AMF0_Null: {
return SrsJsonAny::null();
}
case RTMP_AMF0_Undefined: {
return SrsJsonAny::null();
}
case RTMP_AMF0_Object: {
// amf0 object implements it.
srs_assert(false);
}
case RTMP_AMF0_EcmaArray: {
// amf0 ecma array implements it.
srs_assert(false);
}
case RTMP_AMF0_StrictArray: {
// amf0 strict array implements it.
srs_assert(false);
}
case RTMP_AMF0_Date: {
// TODO: FIXME: implements it.
return SrsJsonAny::null();
}
default: {
return SrsJsonAny::null();
}
}
}
SrsAmf0Any* SrsAmf0Any::str(const char* value)
{
2014-07-06 09:12:26 +00:00
return new SrsAmf0String(value);
}
2014-03-08 06:13:31 +00:00
SrsAmf0Any* SrsAmf0Any::boolean(bool value)
2013-11-23 03:36:07 +00:00
{
2014-07-06 09:12:26 +00:00
return new SrsAmf0Boolean(value);
}
SrsAmf0Any* SrsAmf0Any::number(double value)
{
2014-07-06 09:12:26 +00:00
return new SrsAmf0Number(value);
}
SrsAmf0Any* SrsAmf0Any::null()
2013-11-23 03:36:07 +00:00
{
2014-07-06 09:12:26 +00:00
return new SrsAmf0Null();
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any* SrsAmf0Any::undefined()
2013-11-23 03:36:07 +00:00
{
2014-07-06 09:12:26 +00:00
return new SrsAmf0Undefined();
2013-11-23 03:36:07 +00:00
}
SrsAmf0Object* SrsAmf0Any::object()
{
2014-03-18 03:32:58 +00:00
return new SrsAmf0Object();
}
2014-03-08 08:56:35 +00:00
SrsAmf0Any* SrsAmf0Any::object_eof()
{
2014-07-06 09:12:26 +00:00
return new SrsAmf0ObjectEOF();
2014-03-08 08:56:35 +00:00
}
2014-03-08 14:07:40 +00:00
SrsAmf0EcmaArray* SrsAmf0Any::ecma_array()
{
2014-03-18 03:32:58 +00:00
return new SrsAmf0EcmaArray();
}
SrsAmf0StrictArray* SrsAmf0Any::strict_array()
{
return new SrsAmf0StrictArray();
}
SrsAmf0Any* SrsAmf0Any::date(int64_t value)
{
return new SrsAmf0Date(value);
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Any::discovery(SrsBuffer* stream, SrsAmf0Any** ppvalue)
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// detect the object-eof specially
if (srs_amf0_is_object_eof(stream)) {
2014-07-06 09:12:26 +00:00
*ppvalue = new SrsAmf0ObjectEOF();
2014-03-18 03:32:58 +00:00
return ret;
}
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read any marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
srs_verbose("amf0 any marker success");
// backward the 1byte marker.
stream->skip(-1);
switch (marker) {
case RTMP_AMF0_String: {
*ppvalue = SrsAmf0Any::str();
return ret;
}
case RTMP_AMF0_Boolean: {
*ppvalue = SrsAmf0Any::boolean();
return ret;
}
case RTMP_AMF0_Number: {
*ppvalue = SrsAmf0Any::number();
return ret;
}
case RTMP_AMF0_Null: {
*ppvalue = SrsAmf0Any::null();
return ret;
}
case RTMP_AMF0_Undefined: {
*ppvalue = SrsAmf0Any::undefined();
return ret;
}
case RTMP_AMF0_Object: {
*ppvalue = SrsAmf0Any::object();
return ret;
}
case RTMP_AMF0_EcmaArray: {
*ppvalue = SrsAmf0Any::ecma_array();
return ret;
}
case RTMP_AMF0_StrictArray: {
*ppvalue = SrsAmf0Any::strict_array();
return ret;
}
case RTMP_AMF0_Date: {
*ppvalue = SrsAmf0Any::date();
return ret;
}
2014-03-18 03:32:58 +00:00
case RTMP_AMF0_Invalid:
default: {
ret = ERROR_RTMP_AMF0_INVALID;
srs_error("invalid amf0 message type. marker=%#x, ret=%d", marker, ret);
return ret;
}
}
}
2014-07-06 09:12:26 +00:00
SrsUnSortedHashtable::SrsUnSortedHashtable()
{
}
2014-07-06 09:12:26 +00:00
SrsUnSortedHashtable::~SrsUnSortedHashtable()
2013-11-23 03:36:07 +00:00
{
clear();
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
int SrsUnSortedHashtable::count()
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return (int)properties.size();
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
void SrsUnSortedHashtable::clear()
2013-11-23 03:36:07 +00:00
{
std::vector<SrsAmf0ObjectPropertyType>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0ObjectPropertyType& elem = *it;
SrsAmf0Any* any = elem.second;
srs_freep(any);
}
2014-03-18 03:32:58 +00:00
properties.clear();
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
string SrsUnSortedHashtable::key_at(int index)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
srs_assert(index < count());
SrsAmf0ObjectPropertyType& elem = properties[index];
2014-03-18 03:32:58 +00:00
return elem.first;
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
const char* SrsUnSortedHashtable::key_raw_at(int index)
{
srs_assert(index < count());
SrsAmf0ObjectPropertyType& elem = properties[index];
return elem.first.data();
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsUnSortedHashtable::value_at(int index)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
srs_assert(index < count());
SrsAmf0ObjectPropertyType& elem = properties[index];
2014-03-18 03:32:58 +00:00
return elem.second;
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
void SrsUnSortedHashtable::set(string key, SrsAmf0Any* value)
2013-11-23 03:36:07 +00:00
{
std::vector<SrsAmf0ObjectPropertyType>::iterator it;
2014-03-18 03:32:58 +00:00
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0ObjectPropertyType& elem = *it;
2014-03-18 03:32:58 +00:00
std::string name = elem.first;
SrsAmf0Any* any = elem.second;
if (key == name) {
srs_freep(any);
properties.erase(it);
break;
}
}
if (value) {
properties.push_back(std::make_pair(key, value));
}
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsUnSortedHashtable::get_property(string name)
2013-11-23 03:36:07 +00:00
{
std::vector<SrsAmf0ObjectPropertyType>::iterator it;
2014-03-18 03:32:58 +00:00
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0ObjectPropertyType& elem = *it;
2014-03-18 03:32:58 +00:00
std::string key = elem.first;
SrsAmf0Any* any = elem.second;
if (key == name) {
return any;
}
}
return NULL;
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsUnSortedHashtable::ensure_property_string(string name)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
SrsAmf0Any* prop = get_property(name);
if (!prop) {
return NULL;
}
if (!prop->is_string()) {
return NULL;
}
return prop;
2013-11-23 03:36:07 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsUnSortedHashtable::ensure_property_number(string name)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
SrsAmf0Any* prop = get_property(name);
if (!prop) {
return NULL;
}
if (!prop->is_number()) {
return NULL;
}
return prop;
2013-11-23 03:36:07 +00:00
}
void SrsUnSortedHashtable::remove(string name)
{
std::vector<SrsAmf0ObjectPropertyType>::iterator it;
for (it = properties.begin(); it != properties.end();) {
std::string key = it->first;
SrsAmf0Any* any = it->second;
if (key == name) {
srs_freep(any);
it = properties.erase(it);
} else {
++it;
}
}
}
2014-07-06 09:12:26 +00:00
void SrsUnSortedHashtable::copy(SrsUnSortedHashtable* src)
{
std::vector<SrsAmf0ObjectPropertyType>::iterator it;
for (it = src->properties.begin(); it != src->properties.end(); ++it) {
SrsAmf0ObjectPropertyType& elem = *it;
std::string key = elem.first;
SrsAmf0Any* any = elem.second;
set(key, any->copy());
}
}
2014-07-06 09:12:26 +00:00
SrsAmf0ObjectEOF::SrsAmf0ObjectEOF()
{
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_ObjectEnd;
}
2014-07-06 09:12:26 +00:00
SrsAmf0ObjectEOF::~SrsAmf0ObjectEOF()
{
}
2014-07-06 09:12:26 +00:00
int SrsAmf0ObjectEOF::total_size()
{
2014-03-18 03:32:58 +00:00
return SrsAmf0Size::object_eof();
}
2015-09-22 00:57:31 +00:00
int SrsAmf0ObjectEOF::read(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
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. "
2017-03-25 09:21:39 +00:00
"must be 0x00, actual is %#x, ret=%d", temp, ret);
2014-03-18 03:32:58 +00:00
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. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read object eof marker success");
srs_verbose("amf0 read object eof success");
return ret;
2014-03-08 08:56:35 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0ObjectEOF::write(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
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;
2014-03-08 08:56:35 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsAmf0ObjectEOF::copy()
{
2014-07-06 09:12:26 +00:00
return new SrsAmf0ObjectEOF();
}
2013-11-23 03:36:07 +00:00
SrsAmf0Object::SrsAmf0Object()
{
2014-07-06 09:12:26 +00:00
properties = new SrsUnSortedHashtable();
eof = new SrsAmf0ObjectEOF();
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_Object;
2013-11-23 03:36:07 +00:00
}
SrsAmf0Object::~SrsAmf0Object()
{
2014-03-18 03:32:58 +00:00
srs_freep(properties);
srs_freep(eof);
2013-11-23 03:36:07 +00:00
}
int SrsAmf0Object::total_size()
{
2014-03-18 03:32:58 +00:00
int size = 1;
for (int i = 0; i < properties->count(); i++){
std::string name = key_at(i);
SrsAmf0Any* value = value_at(i);
size += SrsAmf0Size::utf8(name);
size += SrsAmf0Size::any(value);
}
size += SrsAmf0Size::object_eof();
return size;
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Object::read(SrsBuffer* stream)
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read object marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_Object) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check object marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read object marker success");
// value
while (!stream->empty()) {
// detect whether is eof.
if (srs_amf0_is_object_eof(stream)) {
2014-07-06 09:12:26 +00:00
SrsAmf0ObjectEOF pbj_eof;
2014-03-18 03:32:58 +00:00
if ((ret = pbj_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) {
2014-03-18 03:32:58 +00:00
srs_error("amf0 object read property name failed. ret=%d", ret);
return ret;
}
// property-value: any
SrsAmf0Any* property_value = NULL;
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
srs_error("amf0 object read property_value failed. "
2017-03-25 09:21:39 +00:00
"name=%s, ret=%d", property_name.c_str(), ret);
2014-03-18 03:32:58 +00:00
srs_freep(property_value);
return ret;
}
// add property
this->set(property_name, property_value);
}
return ret;
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Object::write(SrsBuffer* stream)
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write object marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_Object);
srs_verbose("amf0 write object marker success");
// value
for (int i = 0; i < properties->count(); i++) {
std::string name = this->key_at(i);
SrsAmf0Any* any = this->value_at(i);
if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) {
srs_error("write object property name failed. ret=%d", ret);
return ret;
}
if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) {
srs_error("write object property value failed. ret=%d", ret);
return ret;
}
srs_verbose("write amf0 property success. name=%s", name.c_str());
}
if ((ret = eof->write(stream)) != ERROR_SUCCESS) {
srs_error("write object eof failed. ret=%d", ret);
return ret;
}
srs_verbose("write amf0 object success.");
return ret;
}
SrsAmf0Any* SrsAmf0Object::copy()
{
SrsAmf0Object* copy = new SrsAmf0Object();
copy->properties->copy(properties);
return copy;
}
SrsJsonAny* SrsAmf0Object::to_json()
{
SrsJsonObject* obj = SrsJsonAny::object();
for (int i = 0; i < properties->count(); i++) {
std::string name = this->key_at(i);
SrsAmf0Any* any = this->value_at(i);
obj->set(name, any->to_json());
}
return obj;
}
2014-05-29 06:16:34 +00:00
void SrsAmf0Object::clear()
{
properties->clear();
}
int SrsAmf0Object::count()
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->count();
2013-11-23 03:36:07 +00:00
}
string SrsAmf0Object::key_at(int index)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->key_at(index);
2013-11-23 03:36:07 +00:00
}
const char* SrsAmf0Object::key_raw_at(int index)
{
return properties->key_raw_at(index);
}
2013-11-23 03:36:07 +00:00
SrsAmf0Any* SrsAmf0Object::value_at(int index)
{
2014-03-18 03:32:58 +00:00
return properties->value_at(index);
2013-11-23 03:36:07 +00:00
}
void SrsAmf0Object::set(string key, SrsAmf0Any* value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
properties->set(key, value);
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any* SrsAmf0Object::get_property(string name)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->get_property(name);
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any* SrsAmf0Object::ensure_property_string(string name)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->ensure_property_string(name);
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any* SrsAmf0Object::ensure_property_number(string name)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->ensure_property_number(name);
2013-11-23 03:36:07 +00:00
}
void SrsAmf0Object::remove(string name)
{
properties->remove(name);
}
SrsAmf0EcmaArray::SrsAmf0EcmaArray()
2013-11-23 03:36:07 +00:00
{
_count = 0;
2014-07-06 09:12:26 +00:00
properties = new SrsUnSortedHashtable();
eof = new SrsAmf0ObjectEOF();
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_EcmaArray;
2013-11-23 03:36:07 +00:00
}
SrsAmf0EcmaArray::~SrsAmf0EcmaArray()
{
2014-03-18 03:32:58 +00:00
srs_freep(properties);
srs_freep(eof);
}
int SrsAmf0EcmaArray::total_size()
{
2014-03-18 03:32:58 +00:00
int size = 1 + 4;
for (int i = 0; i < properties->count(); i++){
std::string name = key_at(i);
SrsAmf0Any* value = value_at(i);
size += SrsAmf0Size::utf8(name);
size += SrsAmf0Size::any(value);
}
size += SrsAmf0Size::object_eof();
return size;
}
2015-09-22 00:57:31 +00:00
int SrsAmf0EcmaArray::read(SrsBuffer* stream)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read ecma_array marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_EcmaArray) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check ecma_array marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_EcmaArray, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read ecma_array marker success");
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
// count
if (!stream->require(4)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read ecma_array count failed. ret=%d", ret);
return ret;
}
int32_t count = stream->read_4bytes();
srs_verbose("amf0 read ecma_array count success. count=%d", count);
// value
this->_count = count;
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
while (!stream->empty()) {
// detect whether is eof.
if (srs_amf0_is_object_eof(stream)) {
2014-07-06 09:12:26 +00:00
SrsAmf0ObjectEOF pbj_eof;
2014-03-18 03:32:58 +00:00
if ((ret = pbj_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) {
srs_error("amf0 ecma_array read property name failed. ret=%d", ret);
return ret;
}
// property-value: any
SrsAmf0Any* property_value = NULL;
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
srs_error("amf0 ecma_array read property_value failed. "
2017-03-25 09:21:39 +00:00
"name=%s, ret=%d", property_name.c_str(), ret);
2014-03-18 03:32:58 +00:00
return ret;
}
// add property
this->set(property_name, property_value);
}
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0EcmaArray::write(SrsBuffer* stream)
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write ecma_array marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_EcmaArray);
srs_verbose("amf0 write ecma_array marker success");
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
// count
if (!stream->require(4)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write ecma_array count failed. ret=%d", ret);
return ret;
}
stream->write_4bytes(this->_count);
srs_verbose("amf0 write ecma_array count success. count=%d", _count);
// value
for (int i = 0; i < properties->count(); i++) {
std::string name = this->key_at(i);
SrsAmf0Any* any = this->value_at(i);
if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) {
srs_error("write ecma_array property name failed. ret=%d", ret);
return ret;
}
if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) {
srs_error("write ecma_array property value failed. ret=%d", ret);
return ret;
}
srs_verbose("write amf0 property success. name=%s", name.c_str());
}
if ((ret = eof->write(stream)) != ERROR_SUCCESS) {
srs_error("write ecma_array eof failed. ret=%d", ret);
return ret;
}
srs_verbose("write ecma_array object success.");
return ret;
}
SrsAmf0Any* SrsAmf0EcmaArray::copy()
{
SrsAmf0EcmaArray* copy = new SrsAmf0EcmaArray();
copy->properties->copy(properties);
copy->_count = _count;
return copy;
}
SrsJsonAny* SrsAmf0EcmaArray::to_json()
{
SrsJsonObject* obj = SrsJsonAny::object();
for (int i = 0; i < properties->count(); i++) {
std::string name = this->key_at(i);
SrsAmf0Any* any = this->value_at(i);
obj->set(name, any->to_json());
}
return obj;
}
void SrsAmf0EcmaArray::clear()
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
properties->clear();
2013-11-23 03:36:07 +00:00
}
int SrsAmf0EcmaArray::count()
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->count();
2013-11-23 03:36:07 +00:00
}
string SrsAmf0EcmaArray::key_at(int index)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->key_at(index);
2013-11-23 03:36:07 +00:00
}
const char* SrsAmf0EcmaArray::key_raw_at(int index)
{
return properties->key_raw_at(index);
}
SrsAmf0Any* SrsAmf0EcmaArray::value_at(int index)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->value_at(index);
2013-11-23 03:36:07 +00:00
}
void SrsAmf0EcmaArray::set(string key, SrsAmf0Any* value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
properties->set(key, value);
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any* SrsAmf0EcmaArray::get_property(string name)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->get_property(name);
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_string(string name)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
return properties->ensure_property_string(name);
2013-11-23 03:36:07 +00:00
}
SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_number(string name)
{
2014-03-18 03:32:58 +00:00
return properties->ensure_property_number(name);
}
SrsAmf0StrictArray::SrsAmf0StrictArray()
{
marker = RTMP_AMF0_StrictArray;
_count = 0;
}
SrsAmf0StrictArray::~SrsAmf0StrictArray()
{
std::vector<SrsAmf0Any*>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0Any* any = *it;
srs_freep(any);
}
properties.clear();
}
int SrsAmf0StrictArray::total_size()
{
int size = 1 + 4;
for (int i = 0; i < (int)properties.size(); i++){
SrsAmf0Any* any = properties[i];
size += any->total_size();
}
return size;
}
2015-09-22 00:57:31 +00:00
int SrsAmf0StrictArray::read(SrsBuffer* stream)
{
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read strict_array marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_StrictArray) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check strict_array marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_StrictArray, ret);
return ret;
}
srs_verbose("amf0 read strict_array marker success");
2017-03-25 09:21:39 +00:00
// count
if (!stream->require(4)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read strict_array count failed. ret=%d", ret);
return ret;
}
int32_t count = stream->read_4bytes();
srs_verbose("amf0 read strict_array count success. count=%d", count);
// value
this->_count = count;
2017-03-25 09:21:39 +00:00
for (int i = 0; i < count && !stream->empty(); i++) {
// property-value: any
SrsAmf0Any* elem = NULL;
if ((ret = srs_amf0_read_any(stream, &elem)) != ERROR_SUCCESS) {
srs_error("amf0 strict_array read value failed. ret=%d", ret);
return ret;
}
// add property
properties.push_back(elem);
}
return ret;
}
2015-09-22 00:57:31 +00:00
int SrsAmf0StrictArray::write(SrsBuffer* stream)
{
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write strict_array marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_StrictArray);
srs_verbose("amf0 write strict_array marker success");
2017-03-25 09:21:39 +00:00
// count
if (!stream->require(4)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write strict_array count failed. ret=%d", ret);
return ret;
}
stream->write_4bytes(this->_count);
srs_verbose("amf0 write strict_array count success. count=%d", _count);
// value
for (int i = 0; i < (int)properties.size(); i++) {
SrsAmf0Any* any = properties[i];
if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) {
srs_error("write strict_array property value failed. ret=%d", ret);
return ret;
}
srs_verbose("write amf0 property success.");
}
srs_verbose("write strict_array object success.");
return ret;
}
SrsAmf0Any* SrsAmf0StrictArray::copy()
{
SrsAmf0StrictArray* copy = new SrsAmf0StrictArray();
std::vector<SrsAmf0Any*>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0Any* any = *it;
copy->append(any->copy());
}
copy->_count = _count;
return copy;
}
SrsJsonAny* SrsAmf0StrictArray::to_json()
{
SrsJsonArray* arr = SrsJsonAny::array();
for (int i = 0; i < (int)properties.size(); i++) {
SrsAmf0Any* any = properties[i];
arr->append(any->to_json());
}
return arr;
}
void SrsAmf0StrictArray::clear()
{
properties.clear();
}
int SrsAmf0StrictArray::count()
{
return (int)properties.size();
}
SrsAmf0Any* SrsAmf0StrictArray::at(int index)
{
srs_assert(index < (int)properties.size());
return properties.at(index);
}
2014-05-28 11:01:47 +00:00
void SrsAmf0StrictArray::append(SrsAmf0Any* any)
{
properties.push_back(any);
_count = (int32_t)properties.size();
2014-05-28 11:01:47 +00:00
}
int SrsAmf0Size::utf8(string value)
{
2014-03-18 03:32:58 +00:00
return 2 + value.length();
}
int SrsAmf0Size::str(string value)
{
2014-03-18 03:32:58 +00:00
return 1 + SrsAmf0Size::utf8(value);
}
int SrsAmf0Size::number()
{
2014-03-18 03:32:58 +00:00
return 1 + 8;
}
int SrsAmf0Size::date()
{
return 1 + 8 + 2;
}
int SrsAmf0Size::null()
{
2014-03-18 03:32:58 +00:00
return 1;
}
int SrsAmf0Size::undefined()
{
2014-03-18 03:32:58 +00:00
return 1;
}
int SrsAmf0Size::boolean()
{
2014-03-18 03:32:58 +00:00
return 1 + 1;
}
int SrsAmf0Size::object(SrsAmf0Object* obj)
{
2014-03-18 03:32:58 +00:00
if (!obj) {
return 0;
}
return obj->total_size();
}
int SrsAmf0Size::object_eof()
{
2014-03-18 03:32:58 +00:00
return 2 + 1;
}
2014-03-08 14:07:40 +00:00
int SrsAmf0Size::ecma_array(SrsAmf0EcmaArray* arr)
{
2014-03-18 03:32:58 +00:00
if (!arr) {
return 0;
}
return arr->total_size();
}
int SrsAmf0Size::strict_array(SrsAmf0StrictArray* arr)
{
if (!arr) {
return 0;
}
return arr->total_size();
}
int SrsAmf0Size::any(SrsAmf0Any* o)
{
2014-03-18 03:32:58 +00:00
if (!o) {
return 0;
}
return o->total_size();
}
2014-07-06 09:12:26 +00:00
SrsAmf0String::SrsAmf0String(const char* _value)
2014-03-08 06:13:31 +00:00
{
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_String;
if (_value) {
value = _value;
}
2014-03-08 06:13:31 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0String::~SrsAmf0String()
2014-03-08 06:13:31 +00:00
{
}
2014-07-06 09:12:26 +00:00
int SrsAmf0String::total_size()
2014-03-08 06:13:31 +00:00
{
2014-03-18 03:32:58 +00:00
return SrsAmf0Size::str(value);
2014-03-08 06:13:31 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0String::read(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_read_string(stream, value);
2014-03-08 08:56:35 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0String::write(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_write_string(stream, value);
2014-03-08 08:56:35 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsAmf0String::copy()
{
2014-07-06 09:12:26 +00:00
SrsAmf0String* copy = new SrsAmf0String(value.c_str());
return copy;
}
2014-07-06 09:12:26 +00:00
SrsAmf0Boolean::SrsAmf0Boolean(bool _value)
2014-03-08 06:13:31 +00:00
{
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_Boolean;
value = _value;
2014-03-08 06:13:31 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Boolean::~SrsAmf0Boolean()
2014-03-08 06:13:31 +00:00
{
}
2014-07-06 09:12:26 +00:00
int SrsAmf0Boolean::total_size()
2014-03-08 06:13:31 +00:00
{
2014-03-18 03:32:58 +00:00
return SrsAmf0Size::boolean();
2014-03-08 06:13:31 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Boolean::read(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_read_boolean(stream, value);
2014-03-08 08:56:35 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Boolean::write(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_write_boolean(stream, value);
2014-03-08 08:56:35 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsAmf0Boolean::copy()
{
2014-07-06 09:12:26 +00:00
SrsAmf0Boolean* copy = new SrsAmf0Boolean(value);
return copy;
}
2014-07-06 09:12:26 +00:00
SrsAmf0Number::SrsAmf0Number(double _value)
{
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_Number;
value = _value;
}
2014-07-06 09:12:26 +00:00
SrsAmf0Number::~SrsAmf0Number()
{
}
2014-07-06 09:12:26 +00:00
int SrsAmf0Number::total_size()
{
2014-03-18 03:32:58 +00:00
return SrsAmf0Size::number();
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Number::read(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_read_number(stream, value);
2014-03-08 08:56:35 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Number::write(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_write_number(stream, value);
2014-03-08 08:56:35 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsAmf0Number::copy()
{
2014-07-06 09:12:26 +00:00
SrsAmf0Number* copy = new SrsAmf0Number(value);
return copy;
}
SrsAmf0Date::SrsAmf0Date(int64_t value)
{
marker = RTMP_AMF0_Date;
_date_value = value;
_time_zone = 0;
}
SrsAmf0Date::~SrsAmf0Date()
{
}
int SrsAmf0Date::total_size()
{
return SrsAmf0Size::date();
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Date::read(SrsBuffer* stream)
{
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read date marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_Date) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check date marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Date, ret);
return ret;
}
srs_verbose("amf0 read date marker success");
2017-03-25 09:21:39 +00:00
// date value
2017-03-25 09:21:39 +00:00
// An ActionScript Date is serialized as the number of milliseconds
// elapsed since the epoch of midnight on 1st Jan 1970 in the UTC
// time zone.
if (!stream->require(8)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read date failed. ret=%d", ret);
return ret;
}
_date_value = stream->read_8bytes();
srs_verbose("amf0 read date success. date=%" PRId64, _date_value);
// time zone
2017-03-25 09:21:39 +00:00
// While the design of this type reserves room for time zone offset
// information, it should not be filled in, nor used, as it is unconventional
// to change time zones when serializing dates on a network. It is suggested
// that the time zone be queried independently as needed.
if (!stream->require(2)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read time zone failed. ret=%d", ret);
return ret;
}
_time_zone = stream->read_2bytes();
srs_verbose("amf0 read time zone success. zone=%d", _time_zone);
return ret;
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Date::write(SrsBuffer* stream)
{
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write date marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_Date);
srs_verbose("amf0 write date marker success");
2017-03-25 09:21:39 +00:00
// date value
if (!stream->require(8)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write date failed. ret=%d", ret);
return ret;
}
stream->write_8bytes(_date_value);
srs_verbose("amf0 write date success. date=%" PRId64, _date_value);
2017-03-25 09:21:39 +00:00
// time zone
if (!stream->require(2)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write time zone failed. ret=%d", ret);
return ret;
}
stream->write_2bytes(_time_zone);
srs_verbose("amf0 write time zone success. date=%d", _time_zone);
srs_verbose("write date object success.");
return ret;
}
SrsAmf0Any* SrsAmf0Date::copy()
{
SrsAmf0Date* copy = new SrsAmf0Date(0);
copy->_date_value = _date_value;
copy->_time_zone = _time_zone;
return copy;
}
int64_t SrsAmf0Date::date()
{
return _date_value;
}
int16_t SrsAmf0Date::time_zone()
{
return _time_zone;
}
2014-07-06 09:12:26 +00:00
SrsAmf0Null::SrsAmf0Null()
{
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_Null;
}
2014-07-06 09:12:26 +00:00
SrsAmf0Null::~SrsAmf0Null()
{
}
2014-07-06 09:12:26 +00:00
int SrsAmf0Null::total_size()
{
2014-03-18 03:32:58 +00:00
return SrsAmf0Size::null();
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Null::read(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_read_null(stream);
2014-03-08 08:56:35 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Null::write(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_write_null(stream);
2014-03-08 08:56:35 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsAmf0Null::copy()
{
2014-07-06 09:12:26 +00:00
SrsAmf0Null* copy = new SrsAmf0Null();
return copy;
}
2014-07-06 09:12:26 +00:00
SrsAmf0Undefined::SrsAmf0Undefined()
{
2014-03-18 03:32:58 +00:00
marker = RTMP_AMF0_Undefined;
}
2014-07-06 09:12:26 +00:00
SrsAmf0Undefined::~SrsAmf0Undefined()
{
}
2014-07-06 09:12:26 +00:00
int SrsAmf0Undefined::total_size()
{
2014-03-18 03:32:58 +00:00
return SrsAmf0Size::undefined();
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Undefined::read(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_read_undefined(stream);
2014-03-08 08:56:35 +00:00
}
2015-09-22 00:57:31 +00:00
int SrsAmf0Undefined::write(SrsBuffer* stream)
2014-03-08 08:56:35 +00:00
{
2014-03-18 03:32:58 +00:00
return srs_amf0_write_undefined(stream);
2014-03-08 08:56:35 +00:00
}
2014-07-06 09:12:26 +00:00
SrsAmf0Any* SrsAmf0Undefined::copy()
{
2014-07-06 09:12:26 +00:00
SrsAmf0Undefined* copy = new SrsAmf0Undefined();
return copy;
}
2015-09-22 00:57:31 +00:00
int srs_amf0_read_any(SrsBuffer* stream, SrsAmf0Any** ppvalue)
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
if ((ret = SrsAmf0Any::discovery(stream, ppvalue)) != ERROR_SUCCESS) {
srs_error("amf0 discovery any elem failed. ret=%d", ret);
return ret;
}
srs_assert(*ppvalue);
if ((ret = (*ppvalue)->read(stream)) != ERROR_SUCCESS) {
srs_error("amf0 parse elem failed. ret=%d", ret);
srs_freep(*ppvalue);
return ret;
}
return ret;
}
2015-09-22 00:57:31 +00:00
int srs_amf0_read_string(SrsBuffer* stream, string& value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read string marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_String) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check string marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_String, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read string marker success");
return srs_amf0_read_utf8(stream, value);
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_write_string(SrsBuffer* stream, string value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write string marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_String);
srs_verbose("amf0 write string marker success");
return srs_amf0_write_utf8(stream, value);
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_read_boolean(SrsBuffer* stream, bool& value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read bool marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_Boolean) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check bool marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Boolean, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read bool marker success");
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
// value
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read bool value failed. ret=%d", ret);
return ret;
}
2017-03-25 09:21:39 +00:00
value = (stream->read_1bytes() != 0);
2014-03-18 03:32:58 +00:00
srs_verbose("amf0 read bool value success. value=%d", value);
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_write_boolean(SrsBuffer* stream, bool value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write bool marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_Boolean);
srs_verbose("amf0 write bool marker success");
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
// value
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write bool value failed. ret=%d", ret);
return ret;
}
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
if (value) {
stream->write_1bytes(0x01);
} else {
stream->write_1bytes(0x00);
}
srs_verbose("amf0 write bool value success. value=%d", value);
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_read_number(SrsBuffer* stream, double& value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read number marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_Number) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check number marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Number, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read number marker success");
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
// value
if (!stream->require(8)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read number value failed. ret=%d", ret);
return ret;
}
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
int64_t temp = stream->read_8bytes();
memcpy(&value, &temp, 8);
srs_verbose("amf0 read number value success. value=%.2f", value);
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_write_number(SrsBuffer* stream, double value)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write number marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_Number);
srs_verbose("amf0 write number marker success");
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
// value
if (!stream->require(8)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write number value failed. ret=%d", ret);
return ret;
}
2017-03-25 09:21:39 +00:00
2014-03-18 03:32:58 +00:00
int64_t temp = 0x00;
memcpy(&temp, &value, 8);
stream->write_8bytes(temp);
srs_verbose("amf0 write number value success. value=%.2f", value);
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_read_null(SrsBuffer* stream)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read null marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_Null) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check null marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Null, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read null success");
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_write_null(SrsBuffer* stream)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write null marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_Null);
srs_verbose("amf0 write null marker success");
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_read_undefined(SrsBuffer* stream)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read undefined marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_Undefined) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check undefined marker failed. "
2017-03-25 09:21:39 +00:00
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Undefined, ret);
2014-03-18 03:32:58 +00:00
return ret;
}
srs_verbose("amf0 read undefined success");
return ret;
2013-11-23 03:36:07 +00:00
}
2015-09-22 00:57:31 +00:00
int srs_amf0_write_undefined(SrsBuffer* stream)
2013-11-23 03:36:07 +00:00
{
2014-03-18 03:32:58 +00:00
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write undefined marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_Undefined);
srs_verbose("amf0 write undefined marker success");
return ret;
2013-11-23 03:36:07 +00:00
}
2014-03-08 08:56:35 +00:00
namespace _srs_internal
2013-11-23 03:36:07 +00:00
{
2015-09-22 00:57:31 +00:00
int srs_amf0_read_utf8(SrsBuffer* stream, string& value)
{
int ret = ERROR_SUCCESS;
// len
if (!stream->require(2)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read string length failed. ret=%d", ret);
return ret;
}
int16_t len = stream->read_2bytes();
srs_verbose("amf0 read string length success. len=%d", len);
// empty string
if (len <= 0) {
srs_verbose("amf0 read empty string. ret=%d", ret);
return ret;
}
// data
if (!stream->require(len)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read string data failed. ret=%d", ret);
return ret;
}
std::string str = stream->read_string(len);
// support utf8-1 only
// 1.3.1 Strings and UTF-8
// UTF8-1 = %x00-7F
// TODO: support other utf-8 strings
/*for (int i = 0; i < len; i++) {
2017-03-25 09:21:39 +00:00
char ch = *(str.data() + i);
if ((ch & 0x80) != 0) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("ignored. only support utf8-1, 0x00-0x7F, actual is %#x. ret=%d", (int)ch, ret);
ret = ERROR_SUCCESS;
}
}*/
value = str;
srs_verbose("amf0 read string data success. str=%s", str.c_str());
2014-03-18 03:32:58 +00:00
return ret;
}
2015-09-22 00:57:31 +00:00
int srs_amf0_write_utf8(SrsBuffer* stream, string value)
{
int ret = ERROR_SUCCESS;
// len
if (!stream->require(2)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write string length failed. ret=%d", ret);
return ret;
}
stream->write_2bytes(value.length());
srs_verbose("amf0 write string length success. len=%d", (int)value.length());
// empty string
if (value.length() <= 0) {
srs_verbose("amf0 write empty string. ret=%d", ret);
return ret;
}
// data
if (!stream->require(value.length())) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write string data failed. ret=%d", ret);
return ret;
}
stream->write_string(value);
srs_verbose("amf0 write string data success. str=%s", value.c_str());
2014-03-18 03:32:58 +00:00
return ret;
}
2017-03-25 09:21:39 +00:00
bool srs_amf0_is_object_eof(SrsBuffer* stream)
{
// detect the object-eof specially
if (stream->require(3)) {
int32_t flag = stream->read_3bytes();
stream->skip(-3);
return 0x09 == flag;
}
return false;
}
2014-03-18 03:32:58 +00:00
2015-09-22 00:57:31 +00:00
int srs_amf0_write_object_eof(SrsBuffer* stream, SrsAmf0ObjectEOF* value)
{
int ret = ERROR_SUCCESS;
srs_assert(value != NULL);
// 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;
}
2017-03-25 09:21:39 +00:00
2015-09-22 00:57:31 +00:00
int srs_amf0_write_any(SrsBuffer* stream, SrsAmf0Any* value)
{
srs_assert(value != NULL);
return value->write(stream);
}
2013-11-23 03:36:07 +00:00
}
2014-08-02 14:18:39 +00:00