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

connect vhost/app packet decoded.

This commit is contained in:
winlin 2013-10-19 21:32:41 +08:00
parent 2886672347
commit df400ef1c5
6 changed files with 324 additions and 59 deletions

View file

@ -24,6 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core_amf0.hpp> #include <srs_core_amf0.hpp>
#include <srs_core_log.hpp> #include <srs_core_log.hpp>
#include <srs_core_error.hpp>
#include <srs_core_stream.hpp> #include <srs_core_stream.hpp>
// AMF0 marker // AMF0 marker
@ -49,30 +50,34 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// origin array whos data takes the same form as LengthValueBytes // origin array whos data takes the same form as LengthValueBytes
#define RTMP_AMF0_OriginStrictArray 0x20 #define RTMP_AMF0_OriginStrictArray 0x20
std::string srs_amf0_read_utf8(SrsStream* stream) int srs_amf0_read_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*&);
int srs_amf0_read_utf8(SrsStream* stream, std::string& value)
{ {
std::string str; int ret = ERROR_SUCCESS;
// len // len
if (!stream->require(2)) { if (!stream->require(2)) {
srs_warn("amf0 read string length failed"); ret = ERROR_RTMP_AMF0_DECODE;
return str; srs_error("amf0 read string length failed. ret=%d", ret);
return ret;
} }
int16_t len = stream->read_2bytes(); int16_t len = stream->read_2bytes();
srs_verbose("amf0 read string length success. len=%d", len); srs_verbose("amf0 read string length success. len=%d", len);
// empty string // empty string
if (len <= 0) { if (len <= 0) {
srs_verbose("amf0 read empty string."); srs_verbose("amf0 read empty string. ret=%d", ret);
return str; return ret;
} }
// data // data
if (!stream->require(len)) { if (!stream->require(len)) {
srs_warn("amf0 read string data failed"); ret = ERROR_RTMP_AMF0_DECODE;
return str; srs_error("amf0 read string data failed. ret=%d", ret);
return ret;
} }
str = stream->read_string(len); std::string str = stream->read_string(len);
// support utf8-1 only // support utf8-1 only
// 1.3.1 Strings and UTF-8 // 1.3.1 Strings and UTF-8
@ -80,54 +85,104 @@ std::string srs_amf0_read_utf8(SrsStream* stream)
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
char ch = *(str.data() + i); char ch = *(str.data() + i);
if ((ch & 0x80) != 0) { if ((ch & 0x80) != 0) {
srs_warn("only support utf8-1, 0x00-0x7F, actual is %#x", (int)ch); ret = ERROR_RTMP_AMF0_DECODE;
return ""; srs_error("only support utf8-1, 0x00-0x7F, actual is %#x. ret=%d", (int)ch, ret);
return ret;
} }
} }
value = str;
srs_verbose("amf0 read string data success. str=%s", str.c_str()); srs_verbose("amf0 read string data success. str=%s", str.c_str());
return str; return ret;
} }
std::string srs_amf0_read_string(SrsStream* stream) int srs_amf0_read_string(SrsStream* stream, std::string& value)
{ {
int ret = ERROR_SUCCESS;
// marker // marker
if (!stream->require(1)) { if (!stream->require(1)) {
srs_warn("amf0 read string marker failed"); ret = ERROR_RTMP_AMF0_DECODE;
return ""; srs_error("amf0 read string marker failed. ret=%d", ret);
return ret;
} }
char marker = stream->read_char(); char marker = stream->read_char();
if (marker != RTMP_AMF0_String) { if (marker != RTMP_AMF0_String) {
srs_warn("amf0 check string marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_String); ret = ERROR_RTMP_AMF0_DECODE;
return ""; srs_error("amf0 check string marker failed. "
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_String, ret);
return ret;
} }
srs_verbose("amf0 read string marker success"); srs_verbose("amf0 read string marker success");
return srs_amf0_read_utf8(stream); return srs_amf0_read_utf8(stream, value);
} }
double srs_amf0_read_number(SrsStream* stream) int srs_amf0_read_boolean(SrsStream* stream, bool& value)
{ {
double value = 0; int ret = ERROR_SUCCESS;
// marker // marker
if (!stream->require(1)) { if (!stream->require(1)) {
srs_warn("amf0 read number marker failed"); ret = ERROR_RTMP_AMF0_DECODE;
return value; srs_error("amf0 read bool marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_char();
if (marker != RTMP_AMF0_Boolean) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check bool marker failed. "
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Boolean, ret);
return ret;
}
srs_verbose("amf0 read bool marker success");
// value
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read bool value failed. ret=%d", ret);
return ret;
}
if (stream->read_char() == 0) {
value = false;
} else {
value = true;
}
srs_verbose("amf0 read bool value success. value=%d", value);
return ret;
}
int srs_amf0_read_number(SrsStream* stream, double& value)
{
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_char(); char marker = stream->read_char();
if (marker != RTMP_AMF0_Number) { if (marker != RTMP_AMF0_Number) {
srs_warn("amf0 check number marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_Number); ret = ERROR_RTMP_AMF0_DECODE;
return value; srs_error("amf0 check number marker failed. "
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Number, ret);
return ret;
} }
srs_verbose("amf0 read number marker success"); srs_verbose("amf0 read number marker success");
// value // value
if (!stream->require(8)) { if (!stream->require(8)) {
srs_warn("amf0 read number value failed"); ret = ERROR_RTMP_AMF0_DECODE;
return value; srs_error("amf0 read number value failed. ret=%d", ret);
return ret;
} }
int64_t temp = stream->read_8bytes(); int64_t temp = stream->read_8bytes();
@ -135,13 +190,158 @@ double srs_amf0_read_number(SrsStream* stream)
srs_verbose("amf0 read number value success. value=%.2f", value); srs_verbose("amf0 read number value success. value=%.2f", value);
return value; return ret;
} }
SrsAmf0Object* srs_amf0_read_object(SrsStream* stream) int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
{ {
SrsAmf0Object* value = NULL; int ret = ERROR_SUCCESS;
return value;
// 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_char();
srs_verbose("amf0 any marker success");
// backward the 1byte marker.
stream->skip(-1);
switch (marker) {
case RTMP_AMF0_String: {
std::string data;
if ((ret = srs_amf0_read_string(stream, data)) != ERROR_SUCCESS) {
return ret;
}
value = new SrsAmf0String();
srs_amf0_convert<SrsAmf0String>(value)->value = data;
return ret;
}
case RTMP_AMF0_Boolean: {
bool data;
if ((ret = srs_amf0_read_boolean(stream, data)) != ERROR_SUCCESS) {
return ret;
}
value = new SrsAmf0Boolean();
srs_amf0_convert<SrsAmf0Boolean>(value)->value = data;
return ret;
}
case RTMP_AMF0_Number: {
double data;
if ((ret = srs_amf0_read_number(stream, data)) != ERROR_SUCCESS) {
return ret;
}
value = new SrsAmf0Number();
srs_amf0_convert<SrsAmf0Number>(value)->value = data;
return ret;
}
case RTMP_AMF0_ObjectEnd: {
SrsAmf0ObjectEOF* p = NULL;
if ((ret = srs_amf0_read_object_eof(stream, p)) != ERROR_SUCCESS) {
return ret;
}
value = p;
return ret;
}
case RTMP_AMF0_Object: {
SrsAmf0Object* p = NULL;
if ((ret = srs_amf0_read_object(stream, p)) != ERROR_SUCCESS) {
return ret;
}
value = p;
return ret;
}
default:
value = new SrsAmf0Any();
value->marker = stream->read_char();
return ret;
}
return ret;
}
int srs_amf0_read_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*& value)
{
int ret = ERROR_SUCCESS;
// 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_char();
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
value = new SrsAmf0ObjectEOF();
srs_verbose("amf0 read object eof marker success");
return ret;
}
int srs_amf0_read_object(SrsStream* stream, SrsAmf0Object*& value)
{
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_char();
if (marker != RTMP_AMF0_Object) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check object marker failed. "
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret);
return ret;
}
srs_verbose("amf0 read object marker success");
// value
value = new SrsAmf0Object();
while (!stream->empty()) {
// property-name: utf8 string
std::string property_name;
if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) {
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. "
"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) {
delete property_value;
}
srs_info("amf0 read object EOF.");
break;
}
// add property
value->properties[property_name] = property_value;
}
return ret;
} }
SrsAmf0Any::SrsAmf0Any() SrsAmf0Any::SrsAmf0Any()
@ -158,6 +358,11 @@ bool SrsAmf0Any::is_string()
return marker == RTMP_AMF0_String; return marker == RTMP_AMF0_String;
} }
bool SrsAmf0Any::is_boolean()
{
return marker == RTMP_AMF0_Boolean;
}
bool SrsAmf0Any::is_number() bool SrsAmf0Any::is_number()
{ {
return marker == RTMP_AMF0_Number; return marker == RTMP_AMF0_Number;
@ -168,6 +373,11 @@ bool SrsAmf0Any::is_object()
return marker == RTMP_AMF0_Object; return marker == RTMP_AMF0_Object;
} }
bool SrsAmf0Any::is_object_eof()
{
return marker == RTMP_AMF0_ObjectEnd;
}
SrsAmf0String::SrsAmf0String() SrsAmf0String::SrsAmf0String()
{ {
marker = RTMP_AMF0_String; marker = RTMP_AMF0_String;
@ -177,6 +387,16 @@ SrsAmf0String::~SrsAmf0String()
{ {
} }
SrsAmf0Boolean::SrsAmf0Boolean()
{
marker = RTMP_AMF0_Boolean;
value = false;
}
SrsAmf0Boolean::~SrsAmf0Boolean()
{
}
SrsAmf0Number::SrsAmf0Number() SrsAmf0Number::SrsAmf0Number()
{ {
marker = RTMP_AMF0_Number; marker = RTMP_AMF0_Number;
@ -185,12 +405,12 @@ SrsAmf0Number::SrsAmf0Number()
SrsAmf0Number::~SrsAmf0Number() SrsAmf0Number::~SrsAmf0Number()
{ {
marker = RTMP_AMF0_ObjectEnd;
} }
SrsAmf0ObjectEOF::SrsAmf0ObjectEOF() SrsAmf0ObjectEOF::SrsAmf0ObjectEOF()
{ {
utf8_empty = 0x00; utf8_empty = 0x00;
object_end_marker = RTMP_AMF0_ObjectEnd;
} }
SrsAmf0ObjectEOF::~SrsAmf0ObjectEOF() SrsAmf0ObjectEOF::~SrsAmf0ObjectEOF()

View file

@ -43,25 +43,30 @@ class SrsAmf0Object;
* UTF8-char = UTF8-1 | UTF8-2 | UTF8-3 | UTF8-4 * UTF8-char = UTF8-1 | UTF8-2 | UTF8-3 | UTF8-4
* UTF8-1 = %x00-7F * UTF8-1 = %x00-7F
* @remark only support UTF8-1 char. * @remark only support UTF8-1 char.
* @return default value is empty string.
*/ */
extern std::string srs_amf0_read_utf8(SrsStream* stream); extern int srs_amf0_read_utf8(SrsStream* stream, std::string& value);
/** /**
* read amf0 string from stream. * read amf0 string from stream.
* 2.4 String Type * 2.4 String Type
* string-type = string-marker UTF-8 * string-type = string-marker UTF-8
* @return default value is empty string.
*/ */
extern std::string srs_amf0_read_string(SrsStream* stream); extern int srs_amf0_read_string(SrsStream* stream, std::string& value);
/**
* read amf0 boolean from stream.
* 2.4 String Type
* boolean-type = boolean-marker U8
* 0 is false, <> 0 is true
*/
extern int srs_amf0_read_boolean(SrsStream* stream, bool& value);
/** /**
* read amf0 number from stream. * read amf0 number from stream.
* 2.2 Number Type * 2.2 Number Type
* number-type = number-marker DOUBLE * number-type = number-marker DOUBLE
* @return default value is 0.
*/ */
extern double srs_amf0_read_number(SrsStream* stream); extern int srs_amf0_read_number(SrsStream* stream, double& value);
/** /**
* read amf0 object from stream. * read amf0 object from stream.
@ -69,7 +74,7 @@ extern double srs_amf0_read_number(SrsStream* stream);
* anonymous-object-type = object-marker *(object-property) * anonymous-object-type = object-marker *(object-property)
* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker) * object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
*/ */
extern SrsAmf0Object* srs_amf0_read_object(SrsStream* stream); extern int srs_amf0_read_object(SrsStream* stream, SrsAmf0Object*& value);
/** /**
* any amf0 value. * any amf0 value.
@ -87,22 +92,10 @@ struct SrsAmf0Any
virtual ~SrsAmf0Any(); virtual ~SrsAmf0Any();
virtual bool is_string(); virtual bool is_string();
virtual bool is_boolean();
virtual bool is_number(); virtual bool is_number();
virtual bool is_object(); virtual bool is_object();
virtual bool is_object_eof();
/**
* 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* convert()
{
T* p = dynamic_cast<T>(this);
srs_assert(p != NULL);
return p;
}
}; };
/** /**
@ -119,6 +112,21 @@ struct SrsAmf0String : public SrsAmf0Any
virtual ~SrsAmf0String(); virtual ~SrsAmf0String();
}; };
/**
* 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.
*/
struct SrsAmf0Boolean : public SrsAmf0Any
{
bool value;
SrsAmf0Boolean();
virtual ~SrsAmf0Boolean();
};
/** /**
* read amf0 number from stream. * read amf0 number from stream.
* 2.2 Number Type * 2.2 Number Type
@ -138,10 +146,9 @@ struct SrsAmf0Number : public SrsAmf0Any
* object-end-type = UTF-8-empty object-end-marker * object-end-type = UTF-8-empty object-end-marker
* 0x00 0x00 0x09 * 0x00 0x00 0x09
*/ */
struct SrsAmf0ObjectEOF struct SrsAmf0ObjectEOF : public SrsAmf0Any
{ {
int16_t utf8_empty; int16_t utf8_empty;
char object_end_marker;
SrsAmf0ObjectEOF(); SrsAmf0ObjectEOF();
virtual ~SrsAmf0ObjectEOF(); virtual ~SrsAmf0ObjectEOF();
@ -161,4 +168,18 @@ struct SrsAmf0Object : public SrsAmf0Any
virtual ~SrsAmf0Object(); virtual ~SrsAmf0Object();
}; };
/**
* 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;
}
#endif #endif

View file

@ -281,7 +281,11 @@ int SrsMessage::decode_packet()
} }
srs_verbose("decode stream initialized success"); srs_verbose("decode stream initialized success");
std::string command = srs_amf0_read_string(stream); std::string command;
if ((ret = srs_amf0_read_string(stream, command)) != ERROR_SUCCESS) {
srs_error("decode AMF0 command name failed. ret=%d", ret);
return ret;
}
srs_verbose("AMF0 command message, command_name=%s", command.c_str()); srs_verbose("AMF0 command message, command_name=%s", command.c_str());
stream->reset(); stream->reset();
@ -337,7 +341,10 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
return ret; return ret;
} }
command_name = srs_amf0_read_string(stream); if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
srs_error("amf0 decode connect command_name failed. ret=%d", ret);
return ret;
}
if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CONNECT) { if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CONNECT) {
ret = ERROR_RTMP_AMF0_DECODE; ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 decode connect command_name failed. " srs_error("amf0 decode connect command_name failed. "
@ -345,7 +352,10 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
return ret; return ret;
} }
transaction_id = srs_amf0_read_number(stream); if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) {
srs_error("amf0 decode connect transaction_id failed. ret=%d", ret);
return ret;
}
if (transaction_id != 1.0) { if (transaction_id != 1.0) {
ret = ERROR_RTMP_AMF0_DECODE; ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 decode connect transaction_id failed. " srs_error("amf0 decode connect transaction_id failed. "
@ -353,7 +363,10 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
return ret; return ret;
} }
command_object = srs_amf0_read_object(stream); if ((ret = srs_amf0_read_object(stream, command_object)) != ERROR_SUCCESS) {
srs_error("amf0 decode connect command_object failed. ret=%d", ret);
return ret;
}
if (command_object == NULL) { if (command_object == NULL) {
ret = ERROR_RTMP_AMF0_DECODE; ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 decode connect command_object failed. ret=%d", ret); srs_error("amf0 decode connect command_object failed. ret=%d", ret);

View file

@ -238,6 +238,7 @@ public:
*pmsg = msg; *pmsg = msg;
*ppacket = pkt; *ppacket = pkt;
break;
} }
return ret; return ret;

View file

@ -70,7 +70,12 @@ bool SrsStream::empty()
bool SrsStream::require(int required_size) bool SrsStream::require(int required_size)
{ {
return !empty() && (required_size < bytes + size - p); return !empty() && (required_size <= bytes + size - p);
}
void SrsStream::skip(int size)
{
p += size;
} }
char SrsStream::read_char() char SrsStream::read_char()

View file

@ -65,6 +65,11 @@ public:
* @return true if stream can read/write specified required_size bytes. * @return true if stream can read/write specified required_size bytes.
*/ */
virtual bool require(int required_size); virtual bool require(int required_size);
/**
* to skip some size.
* @size can be any value. positive to forward; nagetive to backward.
*/
virtual void skip(int size);
public: public:
/** /**
* get 1bytes char from stream. * get 1bytes char from stream.