diff --git a/trunk/configure b/trunk/configure index 7798be411..f2ba0495e 100755 --- a/trunk/configure +++ b/trunk/configure @@ -390,7 +390,7 @@ if [ $SRS_UTEST = YES ]; then MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_kernel" "srs_utest_core" "srs_utest_config" "srs_utest_rtmp" "srs_utest_http" "srs_utest_avc" "srs_utest_reload" "srs_utest_mp4" "srs_utest_service" "srs_utest_app" "srs_utest_rtc" - "srs_utest_protocol") + "srs_utest_protocol" "srs_utest_protocol2") if [[ $SRS_SRT == YES ]]; then MODULE_FILES+=("srs_utest_srt") fi diff --git a/trunk/src/utest/srs_utest_protocol.cpp b/trunk/src/utest/srs_utest_protocol.cpp index cddc971fd..c63424e1b 100644 --- a/trunk/src/utest/srs_utest_protocol.cpp +++ b/trunk/src/utest/srs_utest_protocol.cpp @@ -3460,3578 +3460,3 @@ VOID TEST(ProtocolRTMPTest, RTMPHandshakeBytes) EXPECT_TRUE(bytes.s0s1s2 != NULL); } -struct MockStage -{ - http_parser parser; - const char* at; - size_t length; - - MockStage(http_parser* from); -}; - -MockStage::MockStage(http_parser* from) -{ - parser = *from; - at = NULL; - length = 0; -} - -class MockParser -{ -private: - http_parser_settings settings; - http_parser* parser; - size_t parsed; -public: - MockStage* message_begin; - MockStage* url; - MockStage* status; - MockStage* header_field; - MockStage* header_value; - MockStage* headers_complete; - MockStage* body; - MockStage* message_complete; - MockStage* chunk_header; - MockStage* chunk_complete; -public: - MockParser(); - virtual ~MockParser(); -public: - srs_error_t parse(string data); -private: - static int on_message_begin(http_parser* parser); - static int on_url(http_parser* parser, const char* at, size_t length); - static int on_status(http_parser* parser, const char* at, size_t length); - static int on_header_field(http_parser* parser, const char* at, size_t length); - static int on_header_value(http_parser* parser, const char* at, size_t length); - static int on_headers_complete(http_parser* parser); - static int on_body(http_parser* parser, const char* at, size_t length); - static int on_message_complete(http_parser* parser); - static int on_chunk_header(http_parser* parser); - static int on_chunk_complete(http_parser* parser); -}; - -MockParser::MockParser() -{ - parser = new http_parser(); - http_parser_init(parser, HTTP_REQUEST); - parser->data = (void*)this; - parsed = 0; - - memset(&settings, 0, sizeof(settings)); - settings.on_message_begin = on_message_begin; - settings.on_url = on_url; - settings.on_status = on_status; - settings.on_header_field = on_header_field; - settings.on_header_value = on_header_value; - settings.on_headers_complete = on_headers_complete; - settings.on_body = on_body; - settings.on_message_complete = on_message_complete; - settings.on_chunk_header = on_chunk_header; - settings.on_chunk_complete = on_chunk_complete; - - message_begin = NULL; - url = NULL; - status = NULL; - header_field = NULL; - header_value = NULL; - headers_complete = NULL; - body = NULL; - message_complete = NULL; - chunk_header = NULL; - chunk_complete = NULL; -} - -MockParser::~MockParser() -{ - srs_freep(parser); - - srs_freep(message_begin); - srs_freep(url); - srs_freep(status); - srs_freep(header_field); - srs_freep(header_value); - srs_freep(headers_complete); - srs_freep(body); - srs_freep(message_complete); - srs_freep(chunk_header); - srs_freep(chunk_complete); -} - -int MockParser::on_message_begin(http_parser* parser) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->message_begin); - obj->message_begin = new MockStage(parser); - - return 0; -} - -int MockParser::on_url(http_parser* parser, const char* at, size_t length) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->url); - obj->url = new MockStage(parser); - obj->url->at = at; - obj->url->length = length; - - return 0; -} - -int MockParser::on_status(http_parser* parser, const char* at, size_t length) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->status); - obj->status = new MockStage(parser); - obj->status->at = at; - obj->status->length = length; - - return 0; -} - -int MockParser::on_header_field(http_parser* parser, const char* at, size_t length) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->header_field); - obj->header_field = new MockStage(parser); - obj->header_field->at = at; - obj->header_field->length = length; - - return 0; -} - -int MockParser::on_header_value(http_parser* parser, const char* at, size_t length) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->header_value); - obj->header_value = new MockStage(parser); - obj->header_value->at = at; - obj->header_value->length = length; - - return 0; -} - -int MockParser::on_headers_complete(http_parser* parser) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->headers_complete); - obj->headers_complete = new MockStage(parser); - - return 0; -} - -int MockParser::on_body(http_parser* parser, const char* at, size_t length) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->body); - obj->body = new MockStage(parser); - obj->body->at = at; - obj->body->length = length; - - return 0; -} - -int MockParser::on_message_complete(http_parser* parser) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->message_complete); - obj->message_complete = new MockStage(parser); - - return 0; -} - -int MockParser::on_chunk_header(http_parser* parser) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->chunk_header); - obj->chunk_header = new MockStage(parser); - - return 0; -} - -int MockParser::on_chunk_complete(http_parser* parser) -{ - MockParser* obj = (MockParser*)parser->data; - srs_assert(obj); - - srs_freep(obj->chunk_complete); - obj->chunk_complete = new MockStage(parser); - - return 0; -} - -srs_error_t MockParser::parse(string data) -{ - srs_error_t err = srs_success; - - const char* buf = (const char*)data.data(); - size_t size = (size_t)data.length(); - size_t nparsed = http_parser_execute(parser, &settings, buf, size); - parsed = nparsed; - - if (nparsed != size) { - return srs_error_new(-1, "nparsed=%d, size=%d", nparsed, size); - } - - return err; -} - -VOID TEST(ProtocolHTTPTest, HTTPParser) -{ - srs_error_t err; - - if (true) { - MockParser parser; - // size = 70, nparsed = 70, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n")); - EXPECT_EQ(70, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_TRUE(!parser.body); - EXPECT_TRUE(parser.headers_complete); - EXPECT_TRUE(!parser.message_complete); - } - - if (true) { - MockParser parser; - // size = 75, nparsed = 75, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); - EXPECT_EQ(75, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_TRUE(parser.body && 5 == parser.body->length); - EXPECT_TRUE(parser.headers_complete); - EXPECT_TRUE(parser.message_complete); - } - - if (true) { - MockParser parser; - // size = 150, nparsed = 150, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld")); - EXPECT_EQ(150, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 70, nparsed = 70, nread = 0, content_length = 5, Header("Content-Length", 5) - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n")); - EXPECT_EQ(70, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_EQ(5, (int)parser.parser->content_length); - - // size = 79, nparsed = 5, nread = 1, content_length = -1, Header("Content-Length", 5) - HELPER_EXPECT_FAILED(parser.parse("elloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); - EXPECT_EQ(5, (int)parser.parsed); - EXPECT_EQ(1, (int)parser.parser->nread); - EXPECT_EQ(-1, (int64_t)parser.parser->content_length); - } - - if (true) { - MockParser parser; - // size = 70, nparsed = 70, nread = 0, content_length = 5, Header("Content-Length", 5) - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n")); - EXPECT_EQ(70, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_EQ(5, (int)parser.parser->content_length); - - // size = 80, nparsed = 70, nread = 0, content_length = 0, Header("Content-Length", 5) - HELPER_EXPECT_SUCCESS(parser.parse("HelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld")); - EXPECT_EQ(80, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_EQ(0, (int)parser.parser->content_length); - } - - if (true) { - MockParser parser; - // size = 73, nparsed = 73, nread = 0, content_length = 2, Header("Content-Length", 5) - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHel")); - EXPECT_EQ(73, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - EXPECT_EQ(2, (int)parser.parser->content_length); - } - - if (true) { - MockParser parser; - // size = 82, nparsed = 75, nread = 1, content_length = -1, Header("Content-Length", 5) - HELPER_EXPECT_FAILED(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello World!")); - EXPECT_EQ(75, (int)parser.parsed); - EXPECT_EQ(1, (int)parser.parser->nread); - EXPECT_EQ(-1, (int64_t)parser.parser->content_length); - } - - if (true) { - MockParser parser; - // size = 34, nparsed = 34, nread = 34 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHo")); - EXPECT_EQ(34, (int)parser.parsed); - EXPECT_EQ(34, (int)parser.parser->nread); - - // size = 41, nparsed = 41, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("st: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); - EXPECT_EQ(41, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 41, nparsed = 41, nread = 41 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: oss")); - EXPECT_EQ(41, (int)parser.parsed); - EXPECT_EQ(41, (int)parser.parser->nread); - - // size = 34, nparsed = 34, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("rs.net\r\nContent-Length: 5\r\n\r\nHello")); - EXPECT_EQ(34, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 48, nparsed = 48, nread = 48 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r")); - EXPECT_EQ(48, (int)parser.parsed); - EXPECT_EQ(48, (int)parser.parser->nread); - - // size = 27, nparsed = 27, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("\nContent-Length: 5\r\n\r\nHello")); - EXPECT_EQ(27, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 68, nparsed = 68, nread = 68 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n")); - EXPECT_EQ(68, (int)parser.parsed); - EXPECT_EQ(68, (int)parser.parser->nread); - - // size = 7, nparsed = 7, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("\r\nHello")); - EXPECT_EQ(7, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 69, nparsed = 69, nread = 69 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r")); - EXPECT_EQ(69, (int)parser.parsed); - EXPECT_EQ(69, (int)parser.parser->nread); - - // size = 6, nparsed = 6, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("\nHello")); - EXPECT_EQ(6, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 75, nparsed = 75, nread = 0 - HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); - EXPECT_EQ(75, (int)parser.parsed); - EXPECT_EQ(0, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // nparsed = 2, size = 2, nread = 2 - HELPER_EXPECT_SUCCESS(parser.parse("GE")); - EXPECT_EQ(2, (int)parser.parsed); - EXPECT_EQ(2, (int)parser.parser->nread); - - // size = 0, nparsed = 1, nread=2 - HELPER_EXPECT_FAILED(parser.parse("")); - EXPECT_EQ(1, (int)parser.parsed); - EXPECT_EQ(2, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 2, nparsed = 2, nread = 2 - HELPER_EXPECT_SUCCESS(parser.parse("GE")); - EXPECT_EQ(2, (int)parser.parsed); - EXPECT_EQ(2, (int)parser.parser->nread); - - // size = 1, nparsed = 0, nread = 3 - HELPER_EXPECT_FAILED(parser.parse("X")); - EXPECT_EQ(0, (int)parser.parsed); - EXPECT_EQ(3, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 2, nparsed = 2, nread = 2 - HELPER_EXPECT_SUCCESS(parser.parse("GE")); - EXPECT_EQ(2, (int)parser.parsed); - EXPECT_EQ(2, (int)parser.parser->nread); - - // size = 1, nparsed = 1, nread = 3 - HELPER_EXPECT_SUCCESS(parser.parse("T")); - EXPECT_EQ(1, (int)parser.parsed); - EXPECT_EQ(3, (int)parser.parser->nread); - } - - if (true) { - MockParser parser; - // size = 3, nparsed = 3, nread = 3 - HELPER_EXPECT_SUCCESS(parser.parse("GET")); - EXPECT_EQ(3, (int)parser.parsed); - EXPECT_EQ(3, (int)parser.parser->nread); - } -} - -VOID TEST(ProtocolHTTPTest, ParseHTTPMessage) -{ - srs_error_t err = srs_success; - - if (true) { - MockBufferIO bio; - SrsHttpParser hp; - - bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello"); - HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); - - ISrsHttpMessage* req = NULL; - HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); - - // We should read body, or next parsing message will fail. - // @see https://github.com/ossrs/srs/issues/1181 - EXPECT_FALSE(req->body_reader()->eof()); - srs_freep(req); - - // Got new packet, notice that previous body still exists in bio. - bio.append("GET /gslb/v2/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello"); - - // Should fail because there is body which not read. - // @see https://github.com/ossrs/srs/issues/1181 - HELPER_ASSERT_FAILED(hp.parse_message(&bio, &req)); - srs_freep(req); - } - - if (true) { - MockBufferIO bio; - SrsHttpParser hp; - - bio.append("GET"); - HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); - - // Should fail if not completed message. - ISrsHttpMessage* req = NULL; - HELPER_ASSERT_FAILED(hp.parse_message(&bio, &req)); - srs_freep(req); - } - - if (true) { - MockBufferIO bio; - SrsHttpParser hp; - - bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello"); - HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); - - ISrsHttpMessage* req = NULL; - SrsAutoFree(ISrsHttpMessage, req); - HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); - - char v[64] = {0}; - HELPER_ASSERT_SUCCESS(req->body_reader()->read(v, sizeof(v), NULL)); - EXPECT_TRUE(string("Hello") == string(v)); - - EXPECT_TRUE(req->body_reader()->eof()); - } - - if (true) { - MockBufferIO bio; - SrsHttpParser hp; - - bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 0\r\n\r\n"); - HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); - - ISrsHttpMessage* req = NULL; - SrsAutoFree(ISrsHttpMessage, req); - HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); - } - - if (true) { - MockBufferIO bio; - SrsHttpParser hp; - - bio.append("GET /gslb/v1/versions HTTP/1.1\r\n\r\n"); - HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); - - ISrsHttpMessage* req = NULL; - SrsAutoFree(ISrsHttpMessage, req); - HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); - } - - if (true) { - MockBufferIO bio; - SrsHttpParser hp; - - bio.append("GET /gslb/v1/versions HTTP/1.1\r\n\r\n"); - HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); - - ISrsHttpMessage* req = NULL; - SrsAutoFree(ISrsHttpMessage, req); - HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); - } -} - -VOID TEST(ProtocolProtobufTest, VarintsSize) -{ - EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x00)); - EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x70)); - EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x7f)); - EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x80)); - EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x3ff0)); - EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x3fff)); - EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x4000)); - EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x1ffff0)); - EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x1fffff)); - EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x200000)); - EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x0ffffff0)); - EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x0fffffff)); - EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x10000000)); - EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x7fffffff0)); - EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x7ffffffff)); - EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x800000000)); - EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x3fffffffff0)); - EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x3ffffffffff)); - EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x40000000000)); - EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x1fffffffffff0)); - EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x1ffffffffffff)); - EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x2000000000000)); - EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x0fffffffffffff0)); - EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x0ffffffffffffff)); - EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x100000000000000)); - EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x7ffffffffffffff0)); - EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x7fffffffffffffff)); - EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0x8000000000000000)); - EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0xfffffffffffffff0)); - EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0xffffffffffffffff)); -} - -VOID TEST(ProtocolProtobufTest, VarintsEncode) -{ - srs_error_t err = srs_success; - static char buf[128]; - - if (true) { - SrsBuffer b(buf, 1); uint8_t expect[] = {0x00}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 1); uint8_t expect[] = {0x70}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x70)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 1); uint8_t expect[] = {0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7f)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 2); uint8_t expect[] = {0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x80)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 2); uint8_t expect[] = {0xf0, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3ff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 2); uint8_t expect[] = {0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3fff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 3); uint8_t expect[] = {0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x4000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 3); uint8_t expect[] = {0xf0, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1ffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 3); uint8_t expect[] = {0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1fffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 4); uint8_t expect[] = {0x80, 0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x200000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 4); uint8_t expect[] = {0xf0, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 4); uint8_t expect[] = {0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 5); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x10000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 5); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7fffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 5); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7ffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 6); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x800000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 6); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3fffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 6); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3ffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 7); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x40000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 7); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1fffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 7); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1ffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 8); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x2000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 8); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 8); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 9); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x100000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 9); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7ffffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 9); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7fffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 10); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x8000000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 10); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } - if (true) { - SrsBuffer b(buf, 10); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}; - HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); - } -} - -VOID TEST(ProtocolProtobufTest, String) -{ - srs_error_t err = srs_success; - static char buf[128]; - - if (true) { - EXPECT_EQ(1 + 10, SrsProtobufString::sizeof_string("HelloWorld")); - - SrsBuffer b(buf, 1 + 10); - HELPER_ASSERT_SUCCESS(SrsProtobufString::encode(&b, "HelloWorld")); - - uint8_t expect[] = {0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64}; - EXPECT_TRUE(srs_bytes_equals(buf, (char *) expect, sizeof(expect))); - } - - if (true) { - EXPECT_EQ(1, SrsProtobufString::sizeof_string("")); - - SrsBuffer b(buf, 1); - HELPER_ASSERT_SUCCESS(SrsProtobufString::encode(&b, "")); - - uint8_t expect[] = {0x00}; - EXPECT_TRUE(srs_bytes_equals(buf, (char *) expect, sizeof(expect))); - } -} - -class MockProtobufObject : public ISrsEncoder -{ -public: - uint64_t nb_bytes() { - return 1; - } - srs_error_t encode(SrsBuffer* b) { - b->write_1bytes(0x0f); - return srs_success; - } -}; - -VOID TEST(ProtocolProtobufTest, FieldKey) -{ - srs_error_t err = srs_success; - static char buf[128]; - - EXPECT_EQ(2, SrsProtobufFieldString); - EXPECT_EQ(2, SrsProtobufFieldBytes); - EXPECT_EQ(2, SrsProtobufFieldObject); - EXPECT_EQ(2, SrsProtobufFieldLengthDelimited); - - EXPECT_EQ(1, SrsProtobufKey::sizeof_key()); - - MockProtobufObject obj; - EXPECT_EQ(2, SrsProtobufObject::sizeof_object(&obj)); - if (true) { - SrsBuffer b(buf, 2); - HELPER_ASSERT_SUCCESS(SrsProtobufObject::encode(&b, &obj)); - EXPECT_EQ(0x01, buf[0]); EXPECT_EQ(0x0f, buf[1]); - } - - // Encode the field key as [ID=1, TYPE=2(Length delimited)] - if (true) { - SrsBuffer b(buf, 1); - HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 1, SrsProtobufFieldLengthDelimited)); - EXPECT_EQ(0x0a, buf[0]); - } - - // Encode the field value as [ID=2, TYPE=2(Length delimited)] - if (true) { - SrsBuffer b(buf, 1); - HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 2, SrsProtobufFieldLengthDelimited)); - EXPECT_EQ(0x12, buf[0]); - } - - // Encode the field time as [ID=1, TYPE=0(Varint)] - if (true) { - SrsBuffer b(buf, 1); - HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 1, SrsProtobufFieldVarint)); - EXPECT_EQ(0x08, buf[0]); - } - - // Encode the field source as [ID=4, TYPE=2(Length delimited)] - if (true) { - SrsBuffer b(buf, 1); - HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 4, SrsProtobufFieldLengthDelimited)); - EXPECT_EQ(0x22, buf[0]); - } -} - -VOID TEST(ProtocolKbpsTest, NewDelta) -{ - if (true) { - SrsEphemeralDelta ed; - - ISrsKbpsDelta* delta = (ISrsKbpsDelta*)&ed; - int64_t in, out; - delta->remark(&in, &out); - EXPECT_EQ(0, in); - EXPECT_EQ(0, out); - - ed.add_delta(100 * 1000, 100 * 1000); - delta->remark(&in, &out); - EXPECT_EQ(100 * 1000, in); - EXPECT_EQ(100 * 1000, out); - - delta->remark(&in, &out); - EXPECT_EQ(0, in); - EXPECT_EQ(0, out); - } - - if (true) { - SrsNetworkDelta nd; - - ISrsKbpsDelta* delta = (ISrsKbpsDelta*)&nd; - int64_t in, out; - delta->remark(&in, &out); - EXPECT_EQ(0, in); - EXPECT_EQ(0, out); - - MockStatistic ms; - ms.set_in(100 * 1000)->set_out(100*1000); - nd.set_io(&ms, &ms); - delta->remark(&in, &out); - EXPECT_EQ(100 * 1000, in); - EXPECT_EQ(100 * 1000, out); - - ms.add_in(10 * 1000)->add_out(10 * 1000); - delta->remark(&in, &out); - EXPECT_EQ(10 * 1000, in); - EXPECT_EQ(10 * 1000, out); - - delta->remark(&in, &out); - EXPECT_EQ(0, in); - EXPECT_EQ(0, out); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVMessage) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x20, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x30, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x30, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -* the continue chunks use fmt=1 header -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt1) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x30, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -* the continue chunks use fmt=2 header -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt2) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x83, - 0x00, 0x00, 0x10, // timestamp - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x83, - 0x00, 0x00, 0x10, // timestamp - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x30, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -* the continue chunks use fmt=3 header -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt3) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0xC3, - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0xC3, - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x30, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -* the continue chunks use fmt=1, last video with fmt=1 header -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt11) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x20, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x40, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -* the continue chunks use fmt=1, last video with fmt=1 header, -* last video changed length -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt11Length) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x20, // length, 288 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x20, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x40, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -* the continue chunks use fmt=1, last video with fmt=2 header -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt12) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x83, - 0x00, 0x00, 0x20, // timestamp - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x40, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } -} - -/** -* recv video, audio, video and video, interlaced in chunks. -* the continue chunks use fmt=1, last video with fmt=2 header, -* last video changed length -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt12Length) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x04, - 0x00, 0x00, 0x15, // timestamp - 0x00, 0x00, 0x90, // length, 144 - 0x08, // message_type - 0x01, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x43, - 0x00, 0x00, 0x10, // timestamp - 0x00, 0x01, 0x20, // length, 288 - 0x09, // message_type - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // audio message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC4, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#1 - if (true) { - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x83, - 0x00, 0x00, 0x20, // timestamp - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#2 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - // video message, chunk#3 - if (true) { - uint8_t data[] = { - 0xC3, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - } - - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - EXPECT_EQ(0x110, msg->header.payload_length); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_audio()); - EXPECT_EQ(0x15, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x20, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - EXPECT_EQ(0x120, msg->header.payload_length); - } - if (true) { - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x40, msg->header.timestamp); - EXPECT_EQ(0x01, msg->header.stream_id); - EXPECT_EQ(0x120, msg->header.payload_length); - } -} - -/** -* recv video, with extended timestamp. -* small timestamp < 0xffffff -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0xff, 0xff, 0xff, // timestamp - 0x00, 0x00, 0x04, // length - 0x09, // message_type - 0x00, 0x00, 0x00, 0x00, // stream_id - 0x00, 0x00, 0x00, 0x10, // extended timestamp - // msg payload start - 0x00, 0x00, 0x07, 0x63 - }; - bio.in_buffer.append((char*)data, sizeof(data)); - - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x10, msg->header.timestamp); -} - -/** -* recv video, with extended timestamp. -* big timestamp > 0xffffff -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage2) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0xff, 0xff, 0xff, // timestamp - 0x00, 0x00, 0x04, // length - 0x09, // message_type - 0x00, 0x00, 0x00, 0x00, // stream_id - 0x7f, 0x01, 0x02, 0x03, // extended timestamp - // msg payload start - 0x00, 0x00, 0x07, 0x63 - }; - bio.in_buffer.append((char*)data, sizeof(data)); - - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - EXPECT_EQ(0x7f010203, msg->header.timestamp); -} - -/** -* recv video, with extended timestamp. -* always use 31bits timestamp. -*/ -// always use 31bits timestamp, for some server may use 32bits extended timestamp. -VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage3) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - /** - * parse the message header. - * 3bytes: timestamp delta, fmt=0,1,2 - * 3bytes: payload length, fmt=0,1 - * 1bytes: message type, fmt=0,1 - * 4bytes: stream id, fmt=0 - * where: - * fmt=0, 0x0X - * fmt=1, 0x4X - * fmt=2, 0x8X - * fmt=3, 0xCX - */ - - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0xff, 0xff, 0xff, // timestamp - 0x00, 0x00, 0x04, // length - 0x09, // message_type - 0x00, 0x00, 0x00, 0x00, // stream_id - 0xff, 0x01, 0x02, 0x03, // extended timestamp - // msg payload start - 0x00, 0x00, 0x07, 0x63 - }; - bio.in_buffer.append((char*)data, sizeof(data)); - - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - // always use 31bits timestamp - EXPECT_EQ(0x7f010203, msg->header.timestamp); -} - -/** -* recv video, with extended timestamp, in 2 chunks packet. -* always send extended timestamp in 0xCX chunk packets. -*/ -/** -* RTMP specification and ffmpeg/librtmp is false, -* but, adobe changed the specification, so flash/FMLE/FMS always true. -* default to true to support flash/FMLE/FMS. -* -* ffmpeg/librtmp may donot send this filed, need to detect the value. -* @see also: http://blog.csdn.net/win_lin/article/details/13363699 -* compare to the chunk timestamp, which is set by chunk message header -* type 0,1 or 2. -* -* @remark, nginx send the extended-timestamp in sequence-header, -* and timestamp delta in continue C1 chunks, and so compatible with ffmpeg, -* that is, there is no continue chunks and extended-timestamp in nginx-rtmp. -* -* @remark, srs always send the extended-timestamp, to keep simple, -* and compatible with adobe products. -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVExtTime2Trunk) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - // video message - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0xff, 0xff, 0xff, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x00, 0x00, 0x00, 0x00, // stream_id - 0x00, 0x01, 0x02, 0x03, // extended timestamp - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, - // chunk #2 - 0xC3, - 0x00, 0x01, 0x02, 0x03, // extended timestamp - /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // chunk #2 - 0xC3, - 0x00, 0x01, 0x02, 0x03, // extended timestamp - /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - // 0xCX with extended timestamp. - EXPECT_EQ(0x00010203, msg->header.timestamp); -} - -/** -* recv video, with extended timestamp, in 2 chunks packet. -* never send extended timestamp in 0xCX chunk packets. -*/ -// FFMPEG/librtmp, RTMP specification standard protocol. -VOID TEST(ProtocolStackTest, ProtocolRecvVExtTime2Trunk2) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - // video message - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x03, - 0xff, 0xff, 0xff, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x00, 0x00, 0x00, 0x00, // stream_id - 0x00, 0x01, 0x02, 0x03, // extended timestamp - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, - // chunk #2 - 0xC3, - /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // chunk #2 - 0xC3, - /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - // 0xCX without extended timestamp. - EXPECT_EQ(0x00010203, msg->header.timestamp); -} - -/** -* a video message, in 2 chunks packet. -* use 1B chunk header, min chunk id is 2. -*/ -VOID TEST(ProtocolStackTest, ProtocolRecvVCid1BMin) -{ - MockBufferIO bio; - SrsProtocol proto(&bio); - - // video message - uint8_t data[] = { - // 12bytes header, 1byts chunk header, 11bytes msg heder - 0x02, - 0x00, 0x00, 0x00, // timestamp - 0x00, 0x01, 0x10, // length, 272 - 0x09, // message_type - 0x00, 0x00, 0x00, 0x00, // stream_id - // msg payload start - 0x02, 0x00, 0x07, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, - 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, - 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, - 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, - // chunk #2 - 0xC2, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, - 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, - 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, - 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, - 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // chunk #2 - 0xC2, /*next chunk.*/ - 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e - }; - bio.in_buffer.append((char*)data, sizeof(data)); - - SrsCommonMessage* msg = NULL; - ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); - SrsAutoFree(SrsCommonMessage, msg); - EXPECT_TRUE(msg->header.is_video()); - // 1B cid(6bits), min is 2 - EXPECT_EQ(0x02, msg->header.perfer_cid); -} - -VOID TEST(ProtocolKbpsTest, Connections) -{ - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); - SrsAutoFree(SrsKbps, kbps); - - SrsNetworkDelta* delta = new SrsNetworkDelta(); - SrsAutoFree(SrsNetworkDelta, delta); - delta->set_io(io, io); - - // No data, 0kbps. - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(30 * 100 * 1000)->set_out(30 * 100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 300s. - clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(330 * 100 * 1000)->set_out(330 * 100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(800, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(800, kbps->get_send_kbps_5m()); - } - - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); - SrsAutoFree(SrsKbps, kbps); - - SrsNetworkDelta* delta = new SrsNetworkDelta(); - SrsAutoFree(SrsNetworkDelta, delta); - delta->set_io(io, io); - - // No data, 0kbps. - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(30 * 100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 300s. - clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(330 * 100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(800, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - } - - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); - SrsAutoFree(SrsKbps, kbps); - - SrsNetworkDelta* delta = new SrsNetworkDelta(); - SrsAutoFree(SrsNetworkDelta, delta); - delta->set_io(io, io); - - // No data, 0kbps. - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_out(30 * 100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 300s. - clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_out(330 * 100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(800, kbps->get_send_kbps_5m()); - } -} - -VOID TEST(ProtocolKbpsTest, Delta) -{ - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkDelta* delta = new SrsNetworkDelta(); - SrsAutoFree(SrsNetworkDelta, delta); - delta->set_io(io, io); - - // No data. - int64_t in, out; - delta->remark(&in, &out); - EXPECT_EQ(0, in); - EXPECT_EQ(0, out); - - // 800kb. - io->set_in(100 * 1000)->set_out(100 * 1000); - delta->remark(&in, &out); - EXPECT_EQ(100 * 1000, in); - EXPECT_EQ(100 * 1000, out); - - // No data. - delta->remark(&in, &out); - EXPECT_EQ(0, in); - EXPECT_EQ(0, out); - } - - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkDelta* delta = new SrsNetworkDelta(); - SrsAutoFree(SrsNetworkDelta, delta); - delta->set_io(io, io); - - // No data. - int64_t in, out; - delta->remark(&in, &out); - EXPECT_EQ(0, in); - EXPECT_EQ(0, out); - - // 800kb. - io->set_in(100 * 1000)->set_out(100 * 1000); - delta->remark(&in, &out); - EXPECT_EQ(100 * 1000, in); - EXPECT_EQ(100 * 1000, out); - - // Kbps without io, gather delta. - SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); - SrsAutoFree(SrsKbps, kbps); - - // No data, 0kbps. - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - kbps->add_delta(30 * in, 30 * out); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - } -} - -VOID TEST(ProtocolKbpsTest, RAWStatistic) -{ - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkDelta* delta = new SrsNetworkDelta(); - SrsAutoFree(SrsNetworkDelta, delta); - delta->set_io(io, io); - - SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); - SrsAutoFree(SrsKbps, kbps); - - // No data, 0kbps. - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_out(30 * 100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - } - - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - - SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); - SrsAutoFree(SrsKbps, kbps); - - // No io, no data. - EXPECT_EQ(0, kbps->get_recv_bytes()); - EXPECT_EQ(0, kbps->get_send_bytes()); - - // With io, zero data. - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkDelta* delta = new SrsNetworkDelta(); - SrsAutoFree(SrsNetworkDelta, delta); - delta->set_io(io, io); - - kbps->add_delta(delta); - kbps->sample(); - EXPECT_EQ(0, kbps->get_recv_bytes()); - EXPECT_EQ(0, kbps->get_send_bytes()); - - // With io with data. - io->set_in(100 * 1000)->set_out(100 * 1000); - kbps->add_delta(delta); - kbps->sample(); - EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); - - // No io, cached data. - delta->set_io(NULL, NULL); - kbps->add_delta(delta); - kbps->sample(); - EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); - - // Use the same IO, but as a fresh io. - delta->set_io(io, io); - kbps->add_delta(delta); - kbps->sample(); - EXPECT_EQ(200 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(200 * 1000, kbps->get_send_bytes()); - - io->set_in(150 * 1000)->set_out(150 * 1000); - kbps->add_delta(delta); - kbps->sample(); - EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); - - // No io, cached data. - delta->set_io(NULL, NULL); - kbps->add_delta(delta); - kbps->sample(); - EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); - } -} - -VOID TEST(ProtocolKbpsTest, WriteLargeIOVs) -{ - srs_error_t err; - - if (true) { - iovec iovs[1]; - iovs[0].iov_base = (char*)"Hello"; - iovs[0].iov_len = 5; - - MockBufferIO io; - ssize_t nn = 0; - HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, 1, &nn)); - EXPECT_EQ(5, nn); - EXPECT_EQ(5, io.sbytes); - } - - if (true) { - iovec iovs[1024]; - int nn_iovs = (int)(sizeof(iovs)/sizeof(iovec)); - for (int i = 0; i < nn_iovs; i++) { - iovs[i].iov_base = (char*)"Hello"; - iovs[i].iov_len = 5; - } - - MockBufferIO io; - ssize_t nn = 0; - HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn)); - EXPECT_EQ(5 * nn_iovs, nn); - EXPECT_EQ(5 * nn_iovs, io.sbytes); - } - - if (true) { - iovec iovs[1025]; - int nn_iovs = (int)(sizeof(iovs)/sizeof(iovec)); - for (int i = 0; i < nn_iovs; i++) { - iovs[i].iov_base = (char*)"Hello"; - iovs[i].iov_len = 5; - } - - MockBufferIO io; - ssize_t nn = 0; - HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn)); - EXPECT_EQ(5 * nn_iovs, nn); - EXPECT_EQ(5 * nn_iovs, io.sbytes); - } - - if (true) { - iovec iovs[4096]; - int nn_iovs = (int)(sizeof(iovs)/sizeof(iovec)); - for (int i = 0; i < nn_iovs; i++) { - iovs[i].iov_base = (char*)"Hello"; - iovs[i].iov_len = 5; - } - - MockBufferIO io; - ssize_t nn = 0; - HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn)); - EXPECT_EQ(5 * nn_iovs, nn); - EXPECT_EQ(5 * nn_iovs, io.sbytes); - } -} - -VOID TEST(ProtocolKbpsTest, ConnectionsSugar) -{ - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); - SrsAutoFree(SrsNetworkKbps, kbps); - kbps->set_io(io, io); - - // No data, 0kbps. - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(30 * 100 * 1000)->set_out(30 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 300s. - clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(330 * 100 * 1000)->set_out(330 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(800, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(800, kbps->get_send_kbps_5m()); - } - - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); - SrsAutoFree(SrsNetworkKbps, kbps); - kbps->set_io(io, io); - - // No data, 0kbps. - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(30 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 300s. - clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(330 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(800, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - } - - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); - SrsAutoFree(SrsNetworkKbps, kbps); - kbps->set_io(io, io); - - // No data, 0kbps. - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_out(30 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 300s. - clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_out(330 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(800, kbps->get_send_kbps_5m()); - } -} - -VOID TEST(ProtocolKbpsTest, DeltaSugar) -{ - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - // Kbps without io, gather delta. - SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); - SrsAutoFree(SrsNetworkKbps, kbps); - kbps->set_io(io, io); - - // No data, 0kbps. - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_in(30 * 100 * 1000)->set_out(30 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(800, kbps->get_recv_kbps()); - EXPECT_EQ(800, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - } -} - -VOID TEST(ProtocolKbpsTest, RAWStatisticSugar) -{ - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - - SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); - SrsAutoFree(SrsNetworkKbps, kbps); - kbps->set_io(io, io); - - // No data, 0kbps. - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(0, kbps->get_send_kbps()); - EXPECT_EQ(0, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - - // 800kbps in 30s. - clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); - io->set_out(30 * 100 * 1000); - kbps->sample(); - - EXPECT_EQ(0, kbps->get_recv_kbps()); - EXPECT_EQ(0, kbps->get_recv_kbps_30s()); - EXPECT_EQ(0, kbps->get_recv_kbps_5m()); - - EXPECT_EQ(800, kbps->get_send_kbps()); - EXPECT_EQ(800, kbps->get_send_kbps_30s()); - EXPECT_EQ(0, kbps->get_send_kbps_5m()); - } - - if (true) { - MockWallClock* clock = new MockWallClock(); - SrsAutoFree(MockWallClock, clock); - - SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); - SrsAutoFree(SrsNetworkKbps, kbps); - - // No io, no data. - EXPECT_EQ(0, kbps->get_recv_bytes()); - EXPECT_EQ(0, kbps->get_send_bytes()); - - // With io, zero data. - MockStatistic* io = new MockStatistic(); - SrsAutoFree(MockStatistic, io); - kbps->set_io(io, io); - - kbps->sample(); - EXPECT_EQ(0, kbps->get_recv_bytes()); - EXPECT_EQ(0, kbps->get_send_bytes()); - - // With io with data. - io->set_in(100 * 1000)->set_out(100 * 1000); - kbps->sample(); - EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); - - // No io, cached data. - kbps->set_io(NULL, NULL); - kbps->sample(); - EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); - - // Use the same IO, but as a fresh io. - kbps->set_io(io, io); - kbps->sample(); - EXPECT_EQ(200 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(200 * 1000, kbps->get_send_bytes()); - - io->set_in(150 * 1000)->set_out(150 * 1000); - kbps->sample(); - EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); - - // No io, cached data. - kbps->set_io(NULL, NULL); - kbps->sample(); - EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); - EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); - } -} - -VOID TEST(ProtocolKbpsTest, StreamIdentify) -{ - EXPECT_STREQ("/live/livestream", srs_generate_stream_url("", "live", "livestream").c_str()); - EXPECT_STREQ("/live/livestream", srs_generate_stream_url("", "live", "livestream.flv").c_str()); - EXPECT_STREQ("/live/livestream", srs_generate_stream_url("", "live", "livestream.m3u8").c_str()); - EXPECT_STREQ("/live/livestream", srs_generate_stream_url("__defaultVhost__", "live", "livestream").c_str()); - - EXPECT_STREQ("ossrs.io/live/livestream", srs_generate_stream_url("ossrs.io", "live", "livestream").c_str()); - EXPECT_STREQ("ossrs.io/live/livestream", srs_generate_stream_url("ossrs.io", "live", "livestream.flv").c_str()); - EXPECT_STREQ("ossrs.io/live/livestream", srs_generate_stream_url("ossrs.io", "live", "livestream.m3u8").c_str()); -} - diff --git a/trunk/src/utest/srs_utest_protocol2.cpp b/trunk/src/utest/srs_utest_protocol2.cpp new file mode 100644 index 000000000..92bf733b4 --- /dev/null +++ b/trunk/src/utest/srs_utest_protocol2.cpp @@ -0,0 +1,3608 @@ +// +// Copyright (c) 2013-2022 The SRS Authors +// +// SPDX-License-Identifier: MIT or MulanPSL-2.0 +// +#include + +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +VOID TEST(ProtocolKbpsTest, ParseUrlFailed) +{ + string tcUrl = "rtmp://__defaultVhost__/live", stream = "livestream"; + string schema, host, vhost, app, param; int port = 0; + srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param); + EXPECT_STREQ("rtmp", schema.c_str()); + EXPECT_STREQ("__defaultVhost__", host.c_str()); + EXPECT_STREQ("__defaultVhost__", vhost.c_str()); + EXPECT_EQ(1935, port); +} + +/** +* recv video, audio, video and video, interlaced in chunks. +* the continue chunks use fmt=1, last video with fmt=1 header +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt11) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x20, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x40, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } +} + +/** +* recv video, audio, video and video, interlaced in chunks. +* the continue chunks use fmt=1, last video with fmt=1 header, +* last video changed length +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt11Length) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x20, // length, 288 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x20, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x40, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } +} + +/** +* recv video, audio, video and video, interlaced in chunks. +* the continue chunks use fmt=1, last video with fmt=2 header +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt12) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x83, + 0x00, 0x00, 0x20, // timestamp + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x40, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } +} + +/** +* recv video, audio, video and video, interlaced in chunks. +* the continue chunks use fmt=1, last video with fmt=2 header, +* last video changed length +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt12Length) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x20, // length, 288 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x83, + 0x00, 0x00, 0x20, // timestamp + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + EXPECT_EQ(0x110, msg->header.payload_length); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + EXPECT_EQ(0x120, msg->header.payload_length); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x40, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + EXPECT_EQ(0x120, msg->header.payload_length); + } +} + +/** +* recv video, with extended timestamp. +* small timestamp < 0xffffff +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0xff, 0xff, 0xff, // timestamp + 0x00, 0x00, 0x04, // length + 0x09, // message_type + 0x00, 0x00, 0x00, 0x00, // stream_id + 0x00, 0x00, 0x00, 0x10, // extended timestamp + // msg payload start + 0x00, 0x00, 0x07, 0x63 + }; + bio.in_buffer.append((char*)data, sizeof(data)); + + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); +} + +/** +* recv video, with extended timestamp. +* big timestamp > 0xffffff +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage2) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0xff, 0xff, 0xff, // timestamp + 0x00, 0x00, 0x04, // length + 0x09, // message_type + 0x00, 0x00, 0x00, 0x00, // stream_id + 0x7f, 0x01, 0x02, 0x03, // extended timestamp + // msg payload start + 0x00, 0x00, 0x07, 0x63 + }; + bio.in_buffer.append((char*)data, sizeof(data)); + + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x7f010203, msg->header.timestamp); +} + +/** +* recv video, with extended timestamp. +* always use 31bits timestamp. +*/ +// always use 31bits timestamp, for some server may use 32bits extended timestamp. +VOID TEST(ProtocolStackTest, ProtocolRecvExtTimeMessage3) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0xff, 0xff, 0xff, // timestamp + 0x00, 0x00, 0x04, // length + 0x09, // message_type + 0x00, 0x00, 0x00, 0x00, // stream_id + 0xff, 0x01, 0x02, 0x03, // extended timestamp + // msg payload start + 0x00, 0x00, 0x07, 0x63 + }; + bio.in_buffer.append((char*)data, sizeof(data)); + + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + // always use 31bits timestamp + EXPECT_EQ(0x7f010203, msg->header.timestamp); +} + +/** +* recv video, with extended timestamp, in 2 chunks packet. +* always send extended timestamp in 0xCX chunk packets. +*/ +/** +* RTMP specification and ffmpeg/librtmp is false, +* but, adobe changed the specification, so flash/FMLE/FMS always true. +* default to true to support flash/FMLE/FMS. +* +* ffmpeg/librtmp may donot send this filed, need to detect the value. +* @see also: http://blog.csdn.net/win_lin/article/details/13363699 +* compare to the chunk timestamp, which is set by chunk message header +* type 0,1 or 2. +* +* @remark, nginx send the extended-timestamp in sequence-header, +* and timestamp delta in continue C1 chunks, and so compatible with ffmpeg, +* that is, there is no continue chunks and extended-timestamp in nginx-rtmp. +* +* @remark, srs always send the extended-timestamp, to keep simple, +* and compatible with adobe products. +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVExtTime2Trunk) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + // video message + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0xff, 0xff, 0xff, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x00, 0x00, 0x00, 0x00, // stream_id + 0x00, 0x01, 0x02, 0x03, // extended timestamp + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, + // chunk #2 + 0xC3, + 0x00, 0x01, 0x02, 0x03, // extended timestamp + /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // chunk #2 + 0xC3, + 0x00, 0x01, 0x02, 0x03, // extended timestamp + /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + // 0xCX with extended timestamp. + EXPECT_EQ(0x00010203, msg->header.timestamp); +} + +/** +* recv video, with extended timestamp, in 2 chunks packet. +* never send extended timestamp in 0xCX chunk packets. +*/ +// FFMPEG/librtmp, RTMP specification standard protocol. +VOID TEST(ProtocolStackTest, ProtocolRecvVExtTime2Trunk2) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + // video message + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0xff, 0xff, 0xff, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x00, 0x00, 0x00, 0x00, // stream_id + 0x00, 0x01, 0x02, 0x03, // extended timestamp + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, + // chunk #2 + 0xC3, + /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // chunk #2 + 0xC3, + /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + // 0xCX without extended timestamp. + EXPECT_EQ(0x00010203, msg->header.timestamp); +} + +/** +* a video message, in 2 chunks packet. +* use 1B chunk header, min chunk id is 2. +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVCid1BMin) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + // video message + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x02, + 0x00, 0x00, 0x00, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x00, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, + // chunk #2 + 0xC2, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // chunk #2 + 0xC2, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + // 1B cid(6bits), min is 2 + EXPECT_EQ(0x02, msg->header.perfer_cid); +} + +VOID TEST(ProtocolKbpsTest, Connections) +{ + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); + SrsAutoFree(SrsKbps, kbps); + + SrsNetworkDelta* delta = new SrsNetworkDelta(); + SrsAutoFree(SrsNetworkDelta, delta); + delta->set_io(io, io); + + // No data, 0kbps. + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(30 * 100 * 1000)->set_out(30 * 100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 300s. + clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(330 * 100 * 1000)->set_out(330 * 100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(800, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(800, kbps->get_send_kbps_5m()); + } + + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); + SrsAutoFree(SrsKbps, kbps); + + SrsNetworkDelta* delta = new SrsNetworkDelta(); + SrsAutoFree(SrsNetworkDelta, delta); + delta->set_io(io, io); + + // No data, 0kbps. + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(30 * 100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 300s. + clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(330 * 100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(800, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + } + + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); + SrsAutoFree(SrsKbps, kbps); + + SrsNetworkDelta* delta = new SrsNetworkDelta(); + SrsAutoFree(SrsNetworkDelta, delta); + delta->set_io(io, io); + + // No data, 0kbps. + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_out(30 * 100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 300s. + clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_out(330 * 100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(800, kbps->get_send_kbps_5m()); + } +} + +VOID TEST(ProtocolKbpsTest, Delta) +{ + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkDelta* delta = new SrsNetworkDelta(); + SrsAutoFree(SrsNetworkDelta, delta); + delta->set_io(io, io); + + // No data. + int64_t in, out; + delta->remark(&in, &out); + EXPECT_EQ(0, in); + EXPECT_EQ(0, out); + + // 800kb. + io->set_in(100 * 1000)->set_out(100 * 1000); + delta->remark(&in, &out); + EXPECT_EQ(100 * 1000, in); + EXPECT_EQ(100 * 1000, out); + + // No data. + delta->remark(&in, &out); + EXPECT_EQ(0, in); + EXPECT_EQ(0, out); + } + + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkDelta* delta = new SrsNetworkDelta(); + SrsAutoFree(SrsNetworkDelta, delta); + delta->set_io(io, io); + + // No data. + int64_t in, out; + delta->remark(&in, &out); + EXPECT_EQ(0, in); + EXPECT_EQ(0, out); + + // 800kb. + io->set_in(100 * 1000)->set_out(100 * 1000); + delta->remark(&in, &out); + EXPECT_EQ(100 * 1000, in); + EXPECT_EQ(100 * 1000, out); + + // Kbps without io, gather delta. + SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); + SrsAutoFree(SrsKbps, kbps); + + // No data, 0kbps. + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + kbps->add_delta(30 * in, 30 * out); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + } +} + +VOID TEST(ProtocolKbpsTest, RAWStatistic) +{ + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkDelta* delta = new SrsNetworkDelta(); + SrsAutoFree(SrsNetworkDelta, delta); + delta->set_io(io, io); + + SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); + SrsAutoFree(SrsKbps, kbps); + + // No data, 0kbps. + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_out(30 * 100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + } + + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + + SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); + SrsAutoFree(SrsKbps, kbps); + + // No io, no data. + EXPECT_EQ(0, kbps->get_recv_bytes()); + EXPECT_EQ(0, kbps->get_send_bytes()); + + // With io, zero data. + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkDelta* delta = new SrsNetworkDelta(); + SrsAutoFree(SrsNetworkDelta, delta); + delta->set_io(io, io); + + kbps->add_delta(delta); + kbps->sample(); + EXPECT_EQ(0, kbps->get_recv_bytes()); + EXPECT_EQ(0, kbps->get_send_bytes()); + + // With io with data. + io->set_in(100 * 1000)->set_out(100 * 1000); + kbps->add_delta(delta); + kbps->sample(); + EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); + + // No io, cached data. + delta->set_io(NULL, NULL); + kbps->add_delta(delta); + kbps->sample(); + EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); + + // Use the same IO, but as a fresh io. + delta->set_io(io, io); + kbps->add_delta(delta); + kbps->sample(); + EXPECT_EQ(200 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(200 * 1000, kbps->get_send_bytes()); + + io->set_in(150 * 1000)->set_out(150 * 1000); + kbps->add_delta(delta); + kbps->sample(); + EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); + + // No io, cached data. + delta->set_io(NULL, NULL); + kbps->add_delta(delta); + kbps->sample(); + EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); + } +} + +VOID TEST(ProtocolKbpsTest, WriteLargeIOVs) +{ + srs_error_t err; + + if (true) { + iovec iovs[1]; + iovs[0].iov_base = (char*)"Hello"; + iovs[0].iov_len = 5; + + MockBufferIO io; + ssize_t nn = 0; + HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, 1, &nn)); + EXPECT_EQ(5, nn); + EXPECT_EQ(5, io.sbytes); + } + + if (true) { + iovec iovs[1024]; + int nn_iovs = (int)(sizeof(iovs)/sizeof(iovec)); + for (int i = 0; i < nn_iovs; i++) { + iovs[i].iov_base = (char*)"Hello"; + iovs[i].iov_len = 5; + } + + MockBufferIO io; + ssize_t nn = 0; + HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn)); + EXPECT_EQ(5 * nn_iovs, nn); + EXPECT_EQ(5 * nn_iovs, io.sbytes); + } + + if (true) { + iovec iovs[1025]; + int nn_iovs = (int)(sizeof(iovs)/sizeof(iovec)); + for (int i = 0; i < nn_iovs; i++) { + iovs[i].iov_base = (char*)"Hello"; + iovs[i].iov_len = 5; + } + + MockBufferIO io; + ssize_t nn = 0; + HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn)); + EXPECT_EQ(5 * nn_iovs, nn); + EXPECT_EQ(5 * nn_iovs, io.sbytes); + } + + if (true) { + iovec iovs[4096]; + int nn_iovs = (int)(sizeof(iovs)/sizeof(iovec)); + for (int i = 0; i < nn_iovs; i++) { + iovs[i].iov_base = (char*)"Hello"; + iovs[i].iov_len = 5; + } + + MockBufferIO io; + ssize_t nn = 0; + HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn)); + EXPECT_EQ(5 * nn_iovs, nn); + EXPECT_EQ(5 * nn_iovs, io.sbytes); + } +} + +VOID TEST(ProtocolKbpsTest, ConnectionsSugar) +{ + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); + SrsAutoFree(SrsNetworkKbps, kbps); + kbps->set_io(io, io); + + // No data, 0kbps. + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(30 * 100 * 1000)->set_out(30 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 300s. + clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(330 * 100 * 1000)->set_out(330 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(800, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(800, kbps->get_send_kbps_5m()); + } + + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); + SrsAutoFree(SrsNetworkKbps, kbps); + kbps->set_io(io, io); + + // No data, 0kbps. + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(30 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 300s. + clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(330 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(800, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + } + + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); + SrsAutoFree(SrsNetworkKbps, kbps); + kbps->set_io(io, io); + + // No data, 0kbps. + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_out(30 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 300s. + clock->set_clock(330 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_out(330 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(800, kbps->get_send_kbps_5m()); + } +} + +VOID TEST(ProtocolKbpsTest, DeltaSugar) +{ + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + // Kbps without io, gather delta. + SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); + SrsAutoFree(SrsNetworkKbps, kbps); + kbps->set_io(io, io); + + // No data, 0kbps. + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_in(30 * 100 * 1000)->set_out(30 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(800, kbps->get_recv_kbps()); + EXPECT_EQ(800, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + } +} + +VOID TEST(ProtocolKbpsTest, RAWStatisticSugar) +{ + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + + SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); + SrsAutoFree(SrsNetworkKbps, kbps); + kbps->set_io(io, io); + + // No data, 0kbps. + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(0, kbps->get_send_kbps()); + EXPECT_EQ(0, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + + // 800kbps in 30s. + clock->set_clock(30 * 1000 * SRS_UTIME_MILLISECONDS); + io->set_out(30 * 100 * 1000); + kbps->sample(); + + EXPECT_EQ(0, kbps->get_recv_kbps()); + EXPECT_EQ(0, kbps->get_recv_kbps_30s()); + EXPECT_EQ(0, kbps->get_recv_kbps_5m()); + + EXPECT_EQ(800, kbps->get_send_kbps()); + EXPECT_EQ(800, kbps->get_send_kbps_30s()); + EXPECT_EQ(0, kbps->get_send_kbps_5m()); + } + + if (true) { + MockWallClock* clock = new MockWallClock(); + SrsAutoFree(MockWallClock, clock); + + SrsNetworkKbps* kbps = new SrsNetworkKbps(clock->set_clock(0)); + SrsAutoFree(SrsNetworkKbps, kbps); + + // No io, no data. + EXPECT_EQ(0, kbps->get_recv_bytes()); + EXPECT_EQ(0, kbps->get_send_bytes()); + + // With io, zero data. + MockStatistic* io = new MockStatistic(); + SrsAutoFree(MockStatistic, io); + kbps->set_io(io, io); + + kbps->sample(); + EXPECT_EQ(0, kbps->get_recv_bytes()); + EXPECT_EQ(0, kbps->get_send_bytes()); + + // With io with data. + io->set_in(100 * 1000)->set_out(100 * 1000); + kbps->sample(); + EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); + + // No io, cached data. + kbps->set_io(NULL, NULL); + kbps->sample(); + EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); + + // Use the same IO, but as a fresh io. + kbps->set_io(io, io); + kbps->sample(); + EXPECT_EQ(200 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(200 * 1000, kbps->get_send_bytes()); + + io->set_in(150 * 1000)->set_out(150 * 1000); + kbps->sample(); + EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); + + // No io, cached data. + kbps->set_io(NULL, NULL); + kbps->sample(); + EXPECT_EQ(250 * 1000, kbps->get_recv_bytes()); + EXPECT_EQ(250 * 1000, kbps->get_send_bytes()); + } +} + +VOID TEST(ProtocolKbpsTest, StreamIdentify) +{ + EXPECT_STREQ("/live/livestream", srs_generate_stream_url("", "live", "livestream").c_str()); + EXPECT_STREQ("/live/livestream", srs_generate_stream_url("", "live", "livestream.flv").c_str()); + EXPECT_STREQ("/live/livestream", srs_generate_stream_url("", "live", "livestream.m3u8").c_str()); + EXPECT_STREQ("/live/livestream", srs_generate_stream_url("__defaultVhost__", "live", "livestream").c_str()); + + EXPECT_STREQ("ossrs.io/live/livestream", srs_generate_stream_url("ossrs.io", "live", "livestream").c_str()); + EXPECT_STREQ("ossrs.io/live/livestream", srs_generate_stream_url("ossrs.io", "live", "livestream.flv").c_str()); + EXPECT_STREQ("ossrs.io/live/livestream", srs_generate_stream_url("ossrs.io", "live", "livestream.m3u8").c_str()); +} + +VOID TEST(ProtocolHTTPTest, ParseHTTPMessage) +{ + srs_error_t err = srs_success; + + if (true) { + MockBufferIO bio; + SrsHttpParser hp; + + bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello"); + HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); + + ISrsHttpMessage* req = NULL; + HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); + + // We should read body, or next parsing message will fail. + // @see https://github.com/ossrs/srs/issues/1181 + EXPECT_FALSE(req->body_reader()->eof()); + srs_freep(req); + + // Got new packet, notice that previous body still exists in bio. + bio.append("GET /gslb/v2/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello"); + + // Should fail because there is body which not read. + // @see https://github.com/ossrs/srs/issues/1181 + HELPER_ASSERT_FAILED(hp.parse_message(&bio, &req)); + srs_freep(req); + } + + if (true) { + MockBufferIO bio; + SrsHttpParser hp; + + bio.append("GET"); + HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); + + // Should fail if not completed message. + ISrsHttpMessage* req = NULL; + HELPER_ASSERT_FAILED(hp.parse_message(&bio, &req)); + srs_freep(req); + } + + if (true) { + MockBufferIO bio; + SrsHttpParser hp; + + bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello"); + HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); + + ISrsHttpMessage* req = NULL; + SrsAutoFree(ISrsHttpMessage, req); + HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); + + char v[64] = {0}; + HELPER_ASSERT_SUCCESS(req->body_reader()->read(v, sizeof(v), NULL)); + EXPECT_TRUE(string("Hello") == string(v)); + + EXPECT_TRUE(req->body_reader()->eof()); + } + + if (true) { + MockBufferIO bio; + SrsHttpParser hp; + + bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 0\r\n\r\n"); + HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); + + ISrsHttpMessage* req = NULL; + SrsAutoFree(ISrsHttpMessage, req); + HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); + } + + if (true) { + MockBufferIO bio; + SrsHttpParser hp; + + bio.append("GET /gslb/v1/versions HTTP/1.1\r\n\r\n"); + HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); + + ISrsHttpMessage* req = NULL; + SrsAutoFree(ISrsHttpMessage, req); + HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); + } + + if (true) { + MockBufferIO bio; + SrsHttpParser hp; + + bio.append("GET /gslb/v1/versions HTTP/1.1\r\n\r\n"); + HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_REQUEST)); + + ISrsHttpMessage* req = NULL; + SrsAutoFree(ISrsHttpMessage, req); + HELPER_ASSERT_SUCCESS(hp.parse_message(&bio, &req)); + } +} + +VOID TEST(ProtocolProtobufTest, VarintsSize) +{ + EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x00)); + EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x70)); + EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x7f)); + EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x80)); + EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x3ff0)); + EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x3fff)); + EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x4000)); + EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x1ffff0)); + EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x1fffff)); + EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x200000)); + EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x0ffffff0)); + EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x0fffffff)); + EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x10000000)); + EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x7fffffff0)); + EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x7ffffffff)); + EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x800000000)); + EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x3fffffffff0)); + EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x3ffffffffff)); + EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x40000000000)); + EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x1fffffffffff0)); + EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x1ffffffffffff)); + EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x2000000000000)); + EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x0fffffffffffff0)); + EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x0ffffffffffffff)); + EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x100000000000000)); + EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x7ffffffffffffff0)); + EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x7fffffffffffffff)); + EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0x8000000000000000)); + EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0xfffffffffffffff0)); + EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0xffffffffffffffff)); +} + +VOID TEST(ProtocolProtobufTest, VarintsEncode) +{ + srs_error_t err = srs_success; + static char buf[128]; + + if (true) { + SrsBuffer b(buf, 1); uint8_t expect[] = {0x00}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 1); uint8_t expect[] = {0x70}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x70)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 1); uint8_t expect[] = {0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7f)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 2); uint8_t expect[] = {0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x80)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 2); uint8_t expect[] = {0xf0, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3ff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 2); uint8_t expect[] = {0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3fff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 3); uint8_t expect[] = {0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x4000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 3); uint8_t expect[] = {0xf0, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1ffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 3); uint8_t expect[] = {0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1fffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 4); uint8_t expect[] = {0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x200000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 4); uint8_t expect[] = {0xf0, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 4); uint8_t expect[] = {0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 5); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x10000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 5); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7fffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 5); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7ffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 6); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x800000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 6); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3fffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 6); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3ffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 7); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x40000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 7); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1fffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 7); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1ffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 8); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x2000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 8); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 8); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 9); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x100000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 9); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7ffffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 9); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7fffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 10); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x8000000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 10); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 10); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } +} + +VOID TEST(ProtocolProtobufTest, String) +{ + srs_error_t err = srs_success; + static char buf[128]; + + if (true) { + EXPECT_EQ(1 + 10, SrsProtobufString::sizeof_string("HelloWorld")); + + SrsBuffer b(buf, 1 + 10); + HELPER_ASSERT_SUCCESS(SrsProtobufString::encode(&b, "HelloWorld")); + + uint8_t expect[] = {0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64}; + EXPECT_TRUE(srs_bytes_equals(buf, (char *) expect, sizeof(expect))); + } + + if (true) { + EXPECT_EQ(1, SrsProtobufString::sizeof_string("")); + + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufString::encode(&b, "")); + + uint8_t expect[] = {0x00}; + EXPECT_TRUE(srs_bytes_equals(buf, (char *) expect, sizeof(expect))); + } +} + +class MockProtobufObject : public ISrsEncoder +{ +public: + uint64_t nb_bytes() { + return 1; + } + srs_error_t encode(SrsBuffer* b) { + b->write_1bytes(0x0f); + return srs_success; + } +}; + +VOID TEST(ProtocolProtobufTest, FieldKey) +{ + srs_error_t err = srs_success; + static char buf[128]; + + EXPECT_EQ(2, SrsProtobufFieldString); + EXPECT_EQ(2, SrsProtobufFieldBytes); + EXPECT_EQ(2, SrsProtobufFieldObject); + EXPECT_EQ(2, SrsProtobufFieldLengthDelimited); + + EXPECT_EQ(1, SrsProtobufKey::sizeof_key()); + + MockProtobufObject obj; + EXPECT_EQ(2, SrsProtobufObject::sizeof_object(&obj)); + if (true) { + SrsBuffer b(buf, 2); + HELPER_ASSERT_SUCCESS(SrsProtobufObject::encode(&b, &obj)); + EXPECT_EQ(0x01, buf[0]); EXPECT_EQ(0x0f, buf[1]); + } + + // Encode the field key as [ID=1, TYPE=2(Length delimited)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 1, SrsProtobufFieldLengthDelimited)); + EXPECT_EQ(0x0a, buf[0]); + } + + // Encode the field value as [ID=2, TYPE=2(Length delimited)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 2, SrsProtobufFieldLengthDelimited)); + EXPECT_EQ(0x12, buf[0]); + } + + // Encode the field time as [ID=1, TYPE=0(Varint)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 1, SrsProtobufFieldVarint)); + EXPECT_EQ(0x08, buf[0]); + } + + // Encode the field source as [ID=4, TYPE=2(Length delimited)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 4, SrsProtobufFieldLengthDelimited)); + EXPECT_EQ(0x22, buf[0]); + } +} + +VOID TEST(ProtocolKbpsTest, NewDelta) +{ + if (true) { + SrsEphemeralDelta ed; + + ISrsKbpsDelta* delta = (ISrsKbpsDelta*)&ed; + int64_t in, out; + delta->remark(&in, &out); + EXPECT_EQ(0, in); + EXPECT_EQ(0, out); + + ed.add_delta(100 * 1000, 100 * 1000); + delta->remark(&in, &out); + EXPECT_EQ(100 * 1000, in); + EXPECT_EQ(100 * 1000, out); + + delta->remark(&in, &out); + EXPECT_EQ(0, in); + EXPECT_EQ(0, out); + } + + if (true) { + SrsNetworkDelta nd; + + ISrsKbpsDelta* delta = (ISrsKbpsDelta*)&nd; + int64_t in, out; + delta->remark(&in, &out); + EXPECT_EQ(0, in); + EXPECT_EQ(0, out); + + MockStatistic ms; + ms.set_in(100 * 1000)->set_out(100*1000); + nd.set_io(&ms, &ms); + delta->remark(&in, &out); + EXPECT_EQ(100 * 1000, in); + EXPECT_EQ(100 * 1000, out); + + ms.add_in(10 * 1000)->add_out(10 * 1000); + delta->remark(&in, &out); + EXPECT_EQ(10 * 1000, in); + EXPECT_EQ(10 * 1000, out); + + delta->remark(&in, &out); + EXPECT_EQ(0, in); + EXPECT_EQ(0, out); + } +} + +/** +* recv video, audio, video and video, interlaced in chunks. +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVMessage) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x20, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x30, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x30, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } +} + +/** +* recv video, audio, video and video, interlaced in chunks. +* the continue chunks use fmt=1 header +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt1) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x43, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x30, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } +} + +/** +* recv video, audio, video and video, interlaced in chunks. +* the continue chunks use fmt=2 header +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt2) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x83, + 0x00, 0x00, 0x10, // timestamp + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x83, + 0x00, 0x00, 0x10, // timestamp + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x30, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } +} + +/** +* recv video, audio, video and video, interlaced in chunks. +* the continue chunks use fmt=3 header +*/ +VOID TEST(ProtocolStackTest, ProtocolRecvVAVVFmt3) +{ + MockBufferIO bio; + SrsProtocol proto(&bio); + + /** + * parse the message header. + * 3bytes: timestamp delta, fmt=0,1,2 + * 3bytes: payload length, fmt=0,1 + * 1bytes: message type, fmt=0,1 + * 4bytes: stream id, fmt=0 + * where: + * fmt=0, 0x0X + * fmt=1, 0x4X + * fmt=2, 0x8X + * fmt=3, 0xCX + */ + + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x03, + 0x00, 0x00, 0x10, // timestamp + 0x00, 0x01, 0x10, // length, 272 + 0x09, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0x04, + 0x00, 0x00, 0x15, // timestamp + 0x00, 0x00, 0x90, // length, 144 + 0x08, // message_type + 0x01, 0x00, 0x00, 0x00, // stream_id + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0xC3, + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // audio message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC4, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#1 + if (true) { + uint8_t data[] = { + // 12bytes header, 1byts chunk header, 11bytes msg heder + 0xC3, + // msg payload start + 0x02, 0x00, 0x07, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x61, 0x70, 0x70, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65, 0x00, 0x08, 0x66, 0x6c, + 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x02, 0x00, 0x0d, 0x57, 0x49, 0x4e, 0x20, 0x31, 0x32, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x34, 0x31, 0x00, 0x06, 0x73, 0x77, 0x66, 0x55, 0x72, 0x6c, 0x02, 0x00, + 0x51, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x73, 0x73, 0x72, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x35, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x65, + 0x72, 0x73, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2f, 0x73, 0x72, 0x73, 0x5f, 0x70, 0x6c + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#2 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ 0x61, 0x79, 0x65, 0x72, + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e, + 0x32, 0x33, 0x00, 0x05, 0x74, 0x63, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x14, 0x72, 0x74, 0x6d, 0x70, + 0x3a, 0x2f, 0x2f, 0x64, 0x65, 0x76, 0x3a, 0x31, 0x39, 0x33, 0x35, 0x2f, 0x6c, 0x69, 0x76, 0x65, + 0x00, 0x04, 0x66, 0x70, 0x61, 0x64, 0x01, 0x00, 0x00, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x00, 0x40, 0x6d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x73, 0x00, 0x40, 0xab, 0xee, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x43, 0x6f, 0x64, 0x65, + 0x63, 0x73, 0x00, 0x40, 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + // video message, chunk#3 + if (true) { + uint8_t data[] = { + 0xC3, /*next chunk.*/ + 0x2e, 0x73, 0x77, 0x66, 0x3f, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x31, 0x2e + }; + bio.in_buffer.append((char*)data, sizeof(data)); + } + + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x10, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_audio()); + EXPECT_EQ(0x15, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x20, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } + if (true) { + SrsCommonMessage* msg = NULL; + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); + SrsAutoFree(SrsCommonMessage, msg); + EXPECT_TRUE(msg->header.is_video()); + EXPECT_EQ(0x30, msg->header.timestamp); + EXPECT_EQ(0x01, msg->header.stream_id); + } +} + +struct MockStage +{ + http_parser parser; + const char* at; + size_t length; + + MockStage(http_parser* from); +}; + +MockStage::MockStage(http_parser* from) +{ + parser = *from; + at = NULL; + length = 0; +} + +class MockParser +{ +private: + http_parser_settings settings; + http_parser* parser; + size_t parsed; +public: + MockStage* message_begin; + MockStage* url; + MockStage* status; + MockStage* header_field; + MockStage* header_value; + MockStage* headers_complete; + MockStage* body; + MockStage* message_complete; + MockStage* chunk_header; + MockStage* chunk_complete; +public: + MockParser(); + virtual ~MockParser(); +public: + srs_error_t parse(string data); +private: + static int on_message_begin(http_parser* parser); + static int on_url(http_parser* parser, const char* at, size_t length); + static int on_status(http_parser* parser, const char* at, size_t length); + static int on_header_field(http_parser* parser, const char* at, size_t length); + static int on_header_value(http_parser* parser, const char* at, size_t length); + static int on_headers_complete(http_parser* parser); + static int on_body(http_parser* parser, const char* at, size_t length); + static int on_message_complete(http_parser* parser); + static int on_chunk_header(http_parser* parser); + static int on_chunk_complete(http_parser* parser); +}; + +MockParser::MockParser() +{ + parser = new http_parser(); + http_parser_init(parser, HTTP_REQUEST); + parser->data = (void*)this; + parsed = 0; + + memset(&settings, 0, sizeof(settings)); + settings.on_message_begin = on_message_begin; + settings.on_url = on_url; + settings.on_status = on_status; + settings.on_header_field = on_header_field; + settings.on_header_value = on_header_value; + settings.on_headers_complete = on_headers_complete; + settings.on_body = on_body; + settings.on_message_complete = on_message_complete; + settings.on_chunk_header = on_chunk_header; + settings.on_chunk_complete = on_chunk_complete; + + message_begin = NULL; + url = NULL; + status = NULL; + header_field = NULL; + header_value = NULL; + headers_complete = NULL; + body = NULL; + message_complete = NULL; + chunk_header = NULL; + chunk_complete = NULL; +} + +MockParser::~MockParser() +{ + srs_freep(parser); + + srs_freep(message_begin); + srs_freep(url); + srs_freep(status); + srs_freep(header_field); + srs_freep(header_value); + srs_freep(headers_complete); + srs_freep(body); + srs_freep(message_complete); + srs_freep(chunk_header); + srs_freep(chunk_complete); +} + +int MockParser::on_message_begin(http_parser* parser) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->message_begin); + obj->message_begin = new MockStage(parser); + + return 0; +} + +int MockParser::on_url(http_parser* parser, const char* at, size_t length) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->url); + obj->url = new MockStage(parser); + obj->url->at = at; + obj->url->length = length; + + return 0; +} + +int MockParser::on_status(http_parser* parser, const char* at, size_t length) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->status); + obj->status = new MockStage(parser); + obj->status->at = at; + obj->status->length = length; + + return 0; +} + +int MockParser::on_header_field(http_parser* parser, const char* at, size_t length) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->header_field); + obj->header_field = new MockStage(parser); + obj->header_field->at = at; + obj->header_field->length = length; + + return 0; +} + +int MockParser::on_header_value(http_parser* parser, const char* at, size_t length) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->header_value); + obj->header_value = new MockStage(parser); + obj->header_value->at = at; + obj->header_value->length = length; + + return 0; +} + +int MockParser::on_headers_complete(http_parser* parser) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->headers_complete); + obj->headers_complete = new MockStage(parser); + + return 0; +} + +int MockParser::on_body(http_parser* parser, const char* at, size_t length) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->body); + obj->body = new MockStage(parser); + obj->body->at = at; + obj->body->length = length; + + return 0; +} + +int MockParser::on_message_complete(http_parser* parser) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->message_complete); + obj->message_complete = new MockStage(parser); + + return 0; +} + +int MockParser::on_chunk_header(http_parser* parser) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->chunk_header); + obj->chunk_header = new MockStage(parser); + + return 0; +} + +int MockParser::on_chunk_complete(http_parser* parser) +{ + MockParser* obj = (MockParser*)parser->data; + srs_assert(obj); + + srs_freep(obj->chunk_complete); + obj->chunk_complete = new MockStage(parser); + + return 0; +} + +srs_error_t MockParser::parse(string data) +{ + srs_error_t err = srs_success; + + const char* buf = (const char*)data.data(); + size_t size = (size_t)data.length(); + size_t nparsed = http_parser_execute(parser, &settings, buf, size); + parsed = nparsed; + + if (nparsed != size) { + return srs_error_new(-1, "nparsed=%d, size=%d", nparsed, size); + } + + return err; +} + +VOID TEST(ProtocolHTTPTest, HTTPParser) +{ + srs_error_t err; + + if (true) { + MockParser parser; + // size = 70, nparsed = 70, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n")); + EXPECT_EQ(70, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + EXPECT_TRUE(!parser.body); + EXPECT_TRUE(parser.headers_complete); + EXPECT_TRUE(!parser.message_complete); + } + + if (true) { + MockParser parser; + // size = 75, nparsed = 75, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); + EXPECT_EQ(75, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + EXPECT_TRUE(parser.body && 5 == parser.body->length); + EXPECT_TRUE(parser.headers_complete); + EXPECT_TRUE(parser.message_complete); + } + + if (true) { + MockParser parser; + // size = 150, nparsed = 150, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld")); + EXPECT_EQ(150, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 70, nparsed = 70, nread = 0, content_length = 5, Header("Content-Length", 5) + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n")); + EXPECT_EQ(70, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + EXPECT_EQ(5, (int)parser.parser->content_length); + + // size = 79, nparsed = 5, nread = 1, content_length = -1, Header("Content-Length", 5) + HELPER_EXPECT_FAILED(parser.parse("elloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); + EXPECT_EQ(5, (int)parser.parsed); + EXPECT_EQ(1, (int)parser.parser->nread); + EXPECT_EQ(-1, (int64_t)parser.parser->content_length); + } + + if (true) { + MockParser parser; + // size = 70, nparsed = 70, nread = 0, content_length = 5, Header("Content-Length", 5) + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n")); + EXPECT_EQ(70, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + EXPECT_EQ(5, (int)parser.parser->content_length); + + // size = 80, nparsed = 70, nread = 0, content_length = 0, Header("Content-Length", 5) + HELPER_EXPECT_SUCCESS(parser.parse("HelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld")); + EXPECT_EQ(80, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + EXPECT_EQ(0, (int)parser.parser->content_length); + } + + if (true) { + MockParser parser; + // size = 73, nparsed = 73, nread = 0, content_length = 2, Header("Content-Length", 5) + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHel")); + EXPECT_EQ(73, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + EXPECT_EQ(2, (int)parser.parser->content_length); + } + + if (true) { + MockParser parser; + // size = 82, nparsed = 75, nread = 1, content_length = -1, Header("Content-Length", 5) + HELPER_EXPECT_FAILED(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello World!")); + EXPECT_EQ(75, (int)parser.parsed); + EXPECT_EQ(1, (int)parser.parser->nread); + EXPECT_EQ(-1, (int64_t)parser.parser->content_length); + } + + if (true) { + MockParser parser; + // size = 34, nparsed = 34, nread = 34 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHo")); + EXPECT_EQ(34, (int)parser.parsed); + EXPECT_EQ(34, (int)parser.parser->nread); + + // size = 41, nparsed = 41, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("st: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); + EXPECT_EQ(41, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 41, nparsed = 41, nread = 41 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: oss")); + EXPECT_EQ(41, (int)parser.parsed); + EXPECT_EQ(41, (int)parser.parser->nread); + + // size = 34, nparsed = 34, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("rs.net\r\nContent-Length: 5\r\n\r\nHello")); + EXPECT_EQ(34, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 48, nparsed = 48, nread = 48 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r")); + EXPECT_EQ(48, (int)parser.parsed); + EXPECT_EQ(48, (int)parser.parser->nread); + + // size = 27, nparsed = 27, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("\nContent-Length: 5\r\n\r\nHello")); + EXPECT_EQ(27, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 68, nparsed = 68, nread = 68 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n")); + EXPECT_EQ(68, (int)parser.parsed); + EXPECT_EQ(68, (int)parser.parser->nread); + + // size = 7, nparsed = 7, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("\r\nHello")); + EXPECT_EQ(7, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 69, nparsed = 69, nread = 69 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r")); + EXPECT_EQ(69, (int)parser.parsed); + EXPECT_EQ(69, (int)parser.parser->nread); + + // size = 6, nparsed = 6, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("\nHello")); + EXPECT_EQ(6, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 75, nparsed = 75, nread = 0 + HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello")); + EXPECT_EQ(75, (int)parser.parsed); + EXPECT_EQ(0, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // nparsed = 2, size = 2, nread = 2 + HELPER_EXPECT_SUCCESS(parser.parse("GE")); + EXPECT_EQ(2, (int)parser.parsed); + EXPECT_EQ(2, (int)parser.parser->nread); + + // size = 0, nparsed = 1, nread=2 + HELPER_EXPECT_FAILED(parser.parse("")); + EXPECT_EQ(1, (int)parser.parsed); + EXPECT_EQ(2, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 2, nparsed = 2, nread = 2 + HELPER_EXPECT_SUCCESS(parser.parse("GE")); + EXPECT_EQ(2, (int)parser.parsed); + EXPECT_EQ(2, (int)parser.parser->nread); + + // size = 1, nparsed = 0, nread = 3 + HELPER_EXPECT_FAILED(parser.parse("X")); + EXPECT_EQ(0, (int)parser.parsed); + EXPECT_EQ(3, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 2, nparsed = 2, nread = 2 + HELPER_EXPECT_SUCCESS(parser.parse("GE")); + EXPECT_EQ(2, (int)parser.parsed); + EXPECT_EQ(2, (int)parser.parser->nread); + + // size = 1, nparsed = 1, nread = 3 + HELPER_EXPECT_SUCCESS(parser.parse("T")); + EXPECT_EQ(1, (int)parser.parsed); + EXPECT_EQ(3, (int)parser.parser->nread); + } + + if (true) { + MockParser parser; + // size = 3, nparsed = 3, nread = 3 + HELPER_EXPECT_SUCCESS(parser.parse("GET")); + EXPECT_EQ(3, (int)parser.parsed); + EXPECT_EQ(3, (int)parser.parser->nread); + } +} + diff --git a/trunk/src/utest/srs_utest_protocol2.hpp b/trunk/src/utest/srs_utest_protocol2.hpp new file mode 100644 index 000000000..29289306e --- /dev/null +++ b/trunk/src/utest/srs_utest_protocol2.hpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2013-2022 The SRS Authors +// +// SPDX-License-Identifier: MIT or MulanPSL-2.0 +// + +#ifndef SRS_UTEST_PROTOCOL2_HPP +#define SRS_UTEST_PROTOCOL2_HPP + +/* +#include +*/ +#include + +#endif +