winlin

amf0 object decode framework

@@ -43,5 +43,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -43,5 +43,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43 #define srs_assert(expression) assert(expression) 43 #define srs_assert(expression) assert(expression)
44 44
45 #include <stddef.h> 45 #include <stddef.h>
  46 +#include <sys/types.h>
46 47
47 #endif 48 #endif
@@ -49,23 +49,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -49,23 +49,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 // origin array whos data takes the same form as LengthValueBytes 49 // origin array whos data takes the same form as LengthValueBytes
50 #define RTMP_AMF0_OriginStrictArray 0x20 50 #define RTMP_AMF0_OriginStrictArray 0x20
51 51
52 -std::string srs_amf0_read_string(SrsStream* stream) 52 +std::string srs_amf0_read_utf8(SrsStream* stream)
53 { 53 {
54 std::string str; 54 std::string str;
55 55
56 - // marker  
57 - if (!stream->require(1)) {  
58 - srs_warn("amf0 read string marker failed");  
59 - return str;  
60 - }  
61 -  
62 - char marker = stream->read_char();  
63 - if (marker != RTMP_AMF0_String) {  
64 - srs_warn("amf0 check string marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_String);  
65 - return str;  
66 - }  
67 - srs_verbose("amf0 read string marker success");  
68 -  
69 // len 56 // len
70 if (!stream->require(2)) { 57 if (!stream->require(2)) {
71 srs_warn("amf0 read string length failed"); 58 srs_warn("amf0 read string length failed");
@@ -74,6 +61,12 @@ std::string srs_amf0_read_string(SrsStream* stream) @@ -74,6 +61,12 @@ std::string srs_amf0_read_string(SrsStream* stream)
74 int16_t len = stream->read_2bytes(); 61 int16_t len = stream->read_2bytes();
75 srs_verbose("amf0 read string length success. len=%d", len); 62 srs_verbose("amf0 read string length success. len=%d", len);
76 63
  64 + // empty string
  65 + if (len <= 0) {
  66 + srs_verbose("amf0 read empty string.");
  67 + return str;
  68 + }
  69 +
77 // data 70 // data
78 if (!stream->require(len)) { 71 if (!stream->require(len)) {
79 srs_warn("amf0 read string data failed"); 72 srs_warn("amf0 read string data failed");
@@ -96,8 +89,125 @@ std::string srs_amf0_read_string(SrsStream* stream) @@ -96,8 +89,125 @@ std::string srs_amf0_read_string(SrsStream* stream)
96 return str; 89 return str;
97 } 90 }
98 91
  92 +std::string srs_amf0_read_string(SrsStream* stream)
  93 +{
  94 + // marker
  95 + if (!stream->require(1)) {
  96 + srs_warn("amf0 read string marker failed");
  97 + return "";
  98 + }
  99 +
  100 + char marker = stream->read_char();
  101 + if (marker != RTMP_AMF0_String) {
  102 + srs_warn("amf0 check string marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_String);
  103 + return "";
  104 + }
  105 + srs_verbose("amf0 read string marker success");
  106 +
  107 + return srs_amf0_read_utf8(stream);
  108 +}
  109 +
99 double srs_amf0_read_number(SrsStream* stream) 110 double srs_amf0_read_number(SrsStream* stream)
100 { 111 {
101 - return 0; 112 + double value = 0;
  113 +
  114 + // marker
  115 + if (!stream->require(1)) {
  116 + srs_warn("amf0 read number marker failed");
  117 + return value;
  118 + }
  119 +
  120 + char marker = stream->read_char();
  121 + if (marker != RTMP_AMF0_Number) {
  122 + srs_warn("amf0 check number marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_Number);
  123 + return value;
  124 + }
  125 + srs_verbose("amf0 read number marker success");
  126 +
  127 + // value
  128 + if (!stream->require(8)) {
  129 + srs_warn("amf0 read number value failed");
  130 + return value;
  131 + }
  132 +
  133 + int64_t temp = stream->read_8bytes();
  134 + memcpy(&value, &temp, 8);
  135 +
  136 + srs_verbose("amf0 read number value success. value=%.2f", value);
  137 +
  138 + return value;
  139 +}
  140 +
  141 +SrsAmf0Object* srs_amf0_read_object(SrsStream* stream)
  142 +{
  143 + SrsAmf0Object* value = NULL;
  144 + return value;
  145 +}
  146 +
  147 +SrsAmf0Any::SrsAmf0Any()
  148 +{
  149 + marker = RTMP_AMF0_Null;
  150 +}
  151 +
  152 +SrsAmf0Any::~SrsAmf0Any()
  153 +{
  154 +}
  155 +
  156 +bool SrsAmf0Any::is_string()
  157 +{
  158 + return marker == RTMP_AMF0_String;
  159 +}
  160 +
  161 +bool SrsAmf0Any::is_number()
  162 +{
  163 + return marker == RTMP_AMF0_Number;
  164 +}
  165 +
  166 +bool SrsAmf0Any::is_object()
  167 +{
  168 + return marker == RTMP_AMF0_Object;
  169 +}
  170 +
  171 +SrsAmf0String::SrsAmf0String()
  172 +{
  173 + marker = RTMP_AMF0_String;
  174 +}
  175 +
  176 +SrsAmf0String::~SrsAmf0String()
  177 +{
  178 +}
  179 +
  180 +SrsAmf0Number::SrsAmf0Number()
  181 +{
  182 + marker = RTMP_AMF0_Number;
  183 + value = 0;
  184 +}
  185 +
  186 +SrsAmf0Number::~SrsAmf0Number()
  187 +{
  188 +}
  189 +
  190 +SrsAmf0ObjectEOF::SrsAmf0ObjectEOF()
  191 +{
  192 + utf8_empty = 0x00;
  193 + object_end_marker = RTMP_AMF0_ObjectEnd;
  194 +}
  195 +
  196 +SrsAmf0ObjectEOF::~SrsAmf0ObjectEOF()
  197 +{
102 } 198 }
103 199
  200 +SrsAmf0Object::SrsAmf0Object()
  201 +{
  202 + marker = RTMP_AMF0_Object;
  203 +}
  204 +
  205 +SrsAmf0Object::~SrsAmf0Object()
  206 +{
  207 + std::map<std::string, SrsAmf0Any*>::iterator it;
  208 + for (it = properties.begin(); it != properties.end(); ++it) {
  209 + SrsAmf0Any* any = it->second;
  210 + delete any;
  211 + }
  212 + properties.clear();
  213 +}
@@ -31,13 +31,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,13 +31,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <srs_core.hpp> 31 #include <srs_core.hpp>
32 32
33 #include <string> 33 #include <string>
  34 +#include <map>
34 35
35 class SrsStream; 36 class SrsStream;
  37 +class SrsAmf0Object;
  38 +
  39 +/**
  40 +* read amf0 utf8 string from stream.
  41 +* 1.3.1 Strings and UTF-8
  42 +* UTF-8 = U16 *(UTF8-char)
  43 +* UTF8-char = UTF8-1 | UTF8-2 | UTF8-3 | UTF8-4
  44 +* UTF8-1 = %x00-7F
  45 +* @remark only support UTF8-1 char.
  46 +* @return default value is empty string.
  47 +*/
  48 +extern std::string srs_amf0_read_utf8(SrsStream* stream);
36 49
37 /** 50 /**
38 * read amf0 string from stream. 51 * read amf0 string from stream.
39 * 2.4 String Type 52 * 2.4 String Type
40 * string-type = string-marker UTF-8 53 * string-type = string-marker UTF-8
  54 +* @return default value is empty string.
41 */ 55 */
42 extern std::string srs_amf0_read_string(SrsStream* stream); 56 extern std::string srs_amf0_read_string(SrsStream* stream);
43 57
@@ -45,7 +59,106 @@ extern std::string srs_amf0_read_string(SrsStream* stream); @@ -45,7 +59,106 @@ extern std::string srs_amf0_read_string(SrsStream* stream);
45 * read amf0 number from stream. 59 * read amf0 number from stream.
46 * 2.2 Number Type 60 * 2.2 Number Type
47 * number-type = number-marker DOUBLE 61 * number-type = number-marker DOUBLE
  62 +* @return default value is 0.
48 */ 63 */
49 extern double srs_amf0_read_number(SrsStream* stream); 64 extern double srs_amf0_read_number(SrsStream* stream);
50 65
  66 +/**
  67 +* read amf0 object from stream.
  68 +* 2.5 Object Type
  69 +* anonymous-object-type = object-marker *(object-property)
  70 +* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
  71 +*/
  72 +extern SrsAmf0Object* srs_amf0_read_object(SrsStream* stream);
  73 +
  74 +/**
  75 +* any amf0 value.
  76 +* 2.1 Types Overview
  77 +* value-type = number-type | boolean-type | string-type | object-type
  78 +* | null-marker | undefined-marker | reference-type | ecma-array-type
  79 +* | strict-array-type | date-type | long-string-type | xml-document-type
  80 +* | typed-object-type
  81 +*/
  82 +struct SrsAmf0Any
  83 +{
  84 + char marker;
  85 +
  86 + SrsAmf0Any();
  87 + virtual ~SrsAmf0Any();
  88 +
  89 + virtual bool is_string();
  90 + virtual bool is_number();
  91 + virtual bool is_object();
  92 +
  93 + /**
  94 + * convert the any to specified object.
  95 + * @return T*, the converted object. never NULL.
  96 + * @remark, user must ensure the current object type,
  97 + * or the covert will cause assert failed.
  98 + */
  99 + template<class T>
  100 + T* convert()
  101 + {
  102 + T* p = dynamic_cast<T>(this);
  103 + srs_assert(p != NULL);
  104 + return p;
  105 + }
  106 +};
  107 +
  108 +/**
  109 +* read amf0 string from stream.
  110 +* 2.4 String Type
  111 +* string-type = string-marker UTF-8
  112 +* @return default value is empty string.
  113 +*/
  114 +struct SrsAmf0String : public SrsAmf0Any
  115 +{
  116 + std::string value;
  117 +
  118 + SrsAmf0String();
  119 + virtual ~SrsAmf0String();
  120 +};
  121 +
  122 +/**
  123 +* read amf0 number from stream.
  124 +* 2.2 Number Type
  125 +* number-type = number-marker DOUBLE
  126 +* @return default value is 0.
  127 +*/
  128 +struct SrsAmf0Number : public SrsAmf0Any
  129 +{
  130 + double value;
  131 +
  132 + SrsAmf0Number();
  133 + virtual ~SrsAmf0Number();
  134 +};
  135 +
  136 +/**
  137 +* 2.11 Object End Type
  138 +* object-end-type = UTF-8-empty object-end-marker
  139 +* 0x00 0x00 0x09
  140 +*/
  141 +struct SrsAmf0ObjectEOF
  142 +{
  143 + int16_t utf8_empty;
  144 + char object_end_marker;
  145 +
  146 + SrsAmf0ObjectEOF();
  147 + virtual ~SrsAmf0ObjectEOF();
  148 +};
  149 +
  150 +/**
  151 +* 2.5 Object Type
  152 +* anonymous-object-type = object-marker *(object-property)
  153 +* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
  154 +*/
  155 +struct SrsAmf0Object : public SrsAmf0Any
  156 +{
  157 + std::map<std::string, SrsAmf0Any*> properties;
  158 + SrsAmf0ObjectEOF eof;
  159 +
  160 + SrsAmf0Object();
  161 + virtual ~SrsAmf0Object();
  162 +};
  163 +
51 #endif 164 #endif
@@ -320,6 +320,9 @@ int SrsPacket::decode(SrsStream* /*stream*/) @@ -320,6 +320,9 @@ int SrsPacket::decode(SrsStream* /*stream*/)
320 320
321 SrsConnectAppPacket::SrsConnectAppPacket() 321 SrsConnectAppPacket::SrsConnectAppPacket()
322 { 322 {
  323 + command_name = RTMP_AMF0_COMMAND_CONNECT;
  324 + transaction_id = 1;
  325 + command_object = NULL;
323 } 326 }
324 327
325 SrsConnectAppPacket::~SrsConnectAppPacket() 328 SrsConnectAppPacket::~SrsConnectAppPacket()
@@ -335,9 +338,10 @@ int SrsConnectAppPacket::decode(SrsStream* stream) @@ -335,9 +338,10 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
335 } 338 }
336 339
337 command_name = srs_amf0_read_string(stream); 340 command_name = srs_amf0_read_string(stream);
338 - if (command_name.empty()) { 341 + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CONNECT) {
339 ret = ERROR_RTMP_AMF0_DECODE; 342 ret = ERROR_RTMP_AMF0_DECODE;
340 - srs_error("amf0 decode connect command_name failed. ret=%d", ret); 343 + srs_error("amf0 decode connect command_name failed. "
  344 + "command_name=%s, ret=%d", command_name.c_str(), ret);
341 return ret; 345 return ret;
342 } 346 }
343 347
@@ -349,6 +353,15 @@ int SrsConnectAppPacket::decode(SrsStream* stream) @@ -349,6 +353,15 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
349 return ret; 353 return ret;
350 } 354 }
351 355
  356 + command_object = srs_amf0_read_object(stream);
  357 + if (command_object == NULL) {
  358 + ret = ERROR_RTMP_AMF0_DECODE;
  359 + srs_error("amf0 decode connect command_object failed. ret=%d", ret);
  360 + return ret;
  361 + }
  362 +
  363 + srs_info("amf0 decode connect packet success");
  364 +
352 return ret; 365 return ret;
353 } 366 }
354 367
@@ -44,6 +44,7 @@ class SrsPacket; @@ -44,6 +44,7 @@ class SrsPacket;
44 class SrsStream; 44 class SrsStream;
45 class SrsMessage; 45 class SrsMessage;
46 class SrsChunkStream; 46 class SrsChunkStream;
  47 +class SrsAmf0Object;
47 48
48 /** 49 /**
49 * 4.1. Message Header 50 * 4.1. Message Header
@@ -164,6 +165,7 @@ private: @@ -164,6 +165,7 @@ private:
164 private: 165 private:
165 std::string command_name; 166 std::string command_name;
166 double transaction_id; 167 double transaction_id;
  168 + SrsAmf0Object* command_object;
167 public: 169 public:
168 SrsConnectAppPacket(); 170 SrsConnectAppPacket();
169 virtual ~SrsConnectAppPacket(); 171 virtual ~SrsConnectAppPacket();
@@ -92,6 +92,24 @@ int16_t SrsStream::read_2bytes() @@ -92,6 +92,24 @@ int16_t SrsStream::read_2bytes()
92 return value; 92 return value;
93 } 93 }
94 94
  95 +int64_t SrsStream::read_8bytes()
  96 +{
  97 + srs_assert(require(8));
  98 +
  99 + int64_t value;
  100 + pp = (char*)&value;
  101 + pp[7] = *p++;
  102 + pp[6] = *p++;
  103 + pp[5] = *p++;
  104 + pp[4] = *p++;
  105 + pp[3] = *p++;
  106 + pp[2] = *p++;
  107 + pp[1] = *p++;
  108 + pp[0] = *p++;
  109 +
  110 + return value;
  111 +}
  112 +
95 std::string SrsStream::read_string(int len) 113 std::string SrsStream::read_string(int len)
96 { 114 {
97 srs_assert(require(len)); 115 srs_assert(require(len));
@@ -75,6 +75,10 @@ public: @@ -75,6 +75,10 @@ public:
75 */ 75 */
76 virtual int16_t read_2bytes(); 76 virtual int16_t read_2bytes();
77 /** 77 /**
  78 + * get 8bytes int from stream.
  79 + */
  80 + virtual int64_t read_8bytes();
  81 + /**
78 * get string from stream, length specifies by param len. 82 * get string from stream, length specifies by param len.
79 */ 83 */
80 virtual std::string read_string(int len); 84 virtual std::string read_string(int len);