/* The MIT License (MIT) Copyright (c) 2013-2019 Winlin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include using namespace std; #include #include #include #include #include #include #include #include #include #include MockEmptyIO::MockEmptyIO() { } MockEmptyIO::~MockEmptyIO() { } srs_error_t MockEmptyIO::read_fully(void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/) { return srs_success; } srs_error_t MockEmptyIO::write(void* /*buf*/, size_t /*size*/, ssize_t* /*nwrite*/) { return srs_success; } void MockEmptyIO::set_recv_timeout(srs_utime_t /*tm*/) { } srs_utime_t MockEmptyIO::get_recv_timeout() { return -1; } int64_t MockEmptyIO::get_recv_bytes() { return -1; } void MockEmptyIO::set_send_timeout(srs_utime_t /*tm*/) { } srs_utime_t MockEmptyIO::get_send_timeout() { return 0; } int64_t MockEmptyIO::get_send_bytes() { return 0; } srs_error_t MockEmptyIO::writev(const iovec */*iov*/, int /*iov_size*/, ssize_t* /*nwrite*/) { return srs_success; } srs_error_t MockEmptyIO::read(void* /*buf*/, size_t /*size*/, ssize_t* /*nread*/) { return srs_success; } MockBufferIO::MockBufferIO() { rtm = stm = SRS_UTIME_NO_TIMEOUT; rbytes = sbytes = 0; in_err = out_err = srs_success; } MockBufferIO::~MockBufferIO() { } int MockBufferIO::length() { return in_buffer.length(); } MockBufferIO* MockBufferIO::append(string data) { in_buffer.append((char*)data.data(), data.length()); return this; } MockBufferIO* MockBufferIO::append(MockBufferIO* data) { in_buffer.append(&data->in_buffer); return this; } MockBufferIO* MockBufferIO::append(uint8_t* data, int size) { in_buffer.append((char*)data, size); return this; } int MockBufferIO::out_length() { return out_buffer.length(); } MockBufferIO* MockBufferIO::out_append(string data) { out_buffer.append((char*)data.data(), data.length()); return this; } MockBufferIO* MockBufferIO::out_append(MockBufferIO* data) { out_buffer.append(&data->out_buffer); return this; } MockBufferIO* MockBufferIO::out_append(uint8_t* data, int size) { out_buffer.append((char*)data, size); return this; } srs_error_t MockBufferIO::read_fully(void* buf, size_t size, ssize_t* nread) { if (in_err != srs_success) { return srs_error_copy(in_err); } if (in_buffer.length() < (int)size) { return srs_error_new(ERROR_SOCKET_READ, "read"); } memcpy(buf, in_buffer.bytes(), size); rbytes += size; if (nread) { *nread = size; } in_buffer.erase(size); return srs_success; } srs_error_t MockBufferIO::write(void* buf, size_t size, ssize_t* nwrite) { if (out_err != srs_success) { return srs_error_copy(out_err); } sbytes += size; if (nwrite) { *nwrite = size; } out_buffer.append((char*)buf, size); return srs_success; } void MockBufferIO::set_recv_timeout(srs_utime_t tm) { rtm = tm; } srs_utime_t MockBufferIO::get_recv_timeout() { return rtm; } int64_t MockBufferIO::get_recv_bytes() { return rbytes; } void MockBufferIO::set_send_timeout(srs_utime_t tm) { stm = tm; } srs_utime_t MockBufferIO::get_send_timeout() { return stm; } int64_t MockBufferIO::get_send_bytes() { return sbytes; } srs_error_t MockBufferIO::writev(const iovec *iov, int iov_size, ssize_t* nwrite) { srs_error_t err = srs_success; if (out_err != srs_success) { return srs_error_copy(out_err); } ssize_t total = 0; for (int i = 0; i copy_to(&c1, c1s1_joined_bytes, 1536 - 32, false)); bool is_valid; ASSERT_EQ(ERROR_SUCCESS, c1.c1_validate_digest(is_valid)); ASSERT_TRUE(is_valid); // 128bytes key uint8_t key[] = { 0x01, 0xc6, 0xba, 0xe4, 0xb8, 0xd5, 0xbd, 0x7b, 0x43, 0xc9, 0x69, 0x6b, 0x40, 0xf7, 0xdc, 0x65, 0xa4, 0xf7, 0xca, 0x1f, 0xd8, 0xe5, 0xba, 0x4c, 0xdf, 0xe4, 0x64, 0x9e, 0x7d, 0xbd, 0x54, 0x13, 0x13, 0xc6, 0x0c, 0xb8, 0x1d, 0x31, 0x0a, 0x49, 0xe2, 0x43, 0xb6, 0x95, 0x5f, 0x05, 0x6e, 0x66, 0xf4, 0x21, 0xa8, 0x65, 0xce, 0xf8, 0x8e, 0xcc, 0x16, 0x1e, 0xbb, 0xd8, 0x0e, 0xcb, 0xd2, 0x48, 0x37, 0xaf, 0x4e, 0x67, 0x45, 0xf1, 0x79, 0x69, 0xd2, 0xee, 0xa4, 0xb5, 0x01, 0xbf, 0x57, 0x0f, 0x68, 0x37, 0xbe, 0x4e, 0xff, 0xc9, 0xb9, 0x92, 0x23, 0x06, 0x75, 0xa0, 0x42, 0xe4, 0x0a, 0x30, 0xf0, 0xaf, 0xb0, 0x54, 0x88, 0x7c, 0xc0, 0xc1, 0x0c, 0x6d, 0x01, 0x36, 0x63, 0xf3, 0x3d, 0xbc, 0x72, 0xf6, 0x96, 0xc8, 0x87, 0xab, 0x8b, 0x0c, 0x91, 0x2f, 0x42, 0x2a, 0x11, 0xf6, 0x2d, 0x5e }; EXPECT_TRUE(srs_bytes_equals(c1.get_key(), (char*)key, 128)); // 32bytes digest uint8_t digest[] = { 0x6c, 0x96, 0x9f, 0x26, 0xeb, 0xdc, 0x61, 0xc4, 0x8f, 0xd3, 0x2b, 0x81, 0x86, 0x6c, 0x9c, 0xc2, 0xb1, 0xb5, 0xbc, 0xa6, 0xd6, 0xd6, 0x1d, 0xce, 0x93, 0x78, 0xb3, 0xec, 0xa8, 0x64, 0x19, 0x13 }; EXPECT_TRUE(srs_bytes_equals(c1.get_digest(), (char*)digest, 32)); } VOID TEST(ProtocolHandshakeTest, ComplexHandshake) { srs_error_t err; uint8_t c0c1[] = { 0x03, 0x01, 0x14, 0xf7, 0x4e, 0x80, 0x00, 0x07, 0x02, 0xac, 0x14, 0x98, 0x57, 0x0a, 0x07, 0x58, 0x44, 0x96, 0x47, 0xb5, 0x9a, 0x73, 0xf6, 0x07, 0x0f, 0x49, 0x0d, 0x72, 0xb8, 0x16, 0xbb, 0xb2, 0xb7, 0x61, 0x17, 0x79, 0xa0, 0xe9, 0x98, 0xca, 0xb2, 0x86, 0x64, 0x5f, 0x65, 0x3e, 0xfc, 0x4d, 0xc0, 0x0e, 0x4c, 0xfa, 0x91, 0xc7, 0x0f, 0x2e, 0x57, 0x31, 0x4b, 0x96, 0xef, 0xc9, 0x81, 0x02, 0x00, 0x54, 0x25, 0x2b, 0xb2, 0x0d, 0x7c, 0xee, 0xba, 0xdb, 0xe4, 0x06, 0x78, 0xcd, 0x70, 0x2c, 0x54, 0x5a, 0x3a, 0x03, 0x13, 0x2e, 0xe7, 0x4b, 0x87, 0x40, 0x77, 0x0b, 0x9f, 0xd2, 0xab, 0x32, 0x07, 0x6f, 0x1e, 0x75, 0x74, 0xe9, 0xc7, 0x44, 0xd9, 0x76, 0x53, 0xba, 0xe2, 0x52, 0xfa, 0xcc, 0xef, 0x34, 0xd5, 0x14, 0x61, 0xac, 0xcc, 0x63, 0xfd, 0x2b, 0x2d, 0xb3, 0xb8, 0xdd, 0x8a, 0x51, 0x9a, 0x2d, 0x0e, 0xfa, 0x84, 0x25, 0x55, 0xb2, 0xb7, 0x94, 0x54, 0x68, 0xfb, 0x94, 0xdf, 0xd8, 0xeb, 0x43, 0xd0, 0x11, 0x70, 0x8f, 0xf5, 0x48, 0xfc, 0x69, 0x4d, 0x5b, 0xc6, 0x53, 0x8a, 0x22, 0xea, 0x62, 0x84, 0x89, 0x6b, 0xfe, 0x4e, 0xab, 0x51, 0x98, 0xf4, 0x4f, 0xae, 0xf8, 0xdf, 0xac, 0x43, 0xed, 0x5a, 0x04, 0x97, 0xc4, 0xbe, 0x44, 0x5b, 0x99, 0x20, 0x68, 0x67, 0x0f, 0xe3, 0xfa, 0x4c, 0x9d, 0xe7, 0x0b, 0x3f, 0x80, 0x7c, 0x4c, 0x35, 0xf6, 0xdd, 0x20, 0x05, 0xfd, 0x0f, 0x39, 0xb7, 0x36, 0x45, 0x4c, 0xb7, 0x62, 0x92, 0x35, 0x2a, 0xcd, 0xb9, 0x49, 0xea, 0x12, 0x0b, 0x5f, 0x39, 0xae, 0x3b, 0x49, 0x29, 0xe6, 0x30, 0xc7, 0x7c, 0x77, 0xaf, 0x00, 0x43, 0x4d, 0x06, 0x45, 0x72, 0x73, 0x25, 0x71, 0x5e, 0x35, 0x04, 0xbd, 0xe9, 0x48, 0x23, 0x64, 0x4d, 0x15, 0x0b, 0xc5, 0x3f, 0x6e, 0x3a, 0xd5, 0xd5, 0xa6, 0xae, 0x3b, 0x4c, 0x66, 0x6a, 0x70, 0x8b, 0xf3, 0x6a, 0x43, 0xc4, 0xb9, 0xbd, 0xa0, 0x09, 0x72, 0xbc, 0xce, 0x7a, 0xea, 0x49, 0xf2, 0x86, 0xa7, 0xd8, 0x4a, 0x87, 0x28, 0xca, 0x2c, 0x53, 0xee, 0x96, 0x0b, 0xbe, 0x15, 0x14, 0xa8, 0x00, 0xca, 0x76, 0x08, 0x4d, 0x0f, 0xef, 0x78, 0x4b, 0xf6, 0x47, 0x60, 0xfc, 0x16, 0x00, 0x7c, 0x6b, 0x49, 0x39, 0x64, 0x36, 0xee, 0x45, 0x3a, 0x9a, 0xa5, 0xbf, 0xfb, 0x7b, 0xe7, 0xcf, 0x42, 0x82, 0x48, 0x1b, 0x30, 0xfe, 0x0d, 0xba, 0x10, 0xb8, 0xe1, 0x40, 0xcc, 0x6f, 0x36, 0x1c, 0x94, 0x5d, 0x50, 0x9e, 0x21, 0x08, 0xc9, 0xd5, 0xb0, 0x32, 0x51, 0x6a, 0x8f, 0xfa, 0x57, 0x8d, 0x45, 0xd7, 0xd2, 0xd0, 0xd6, 0x6c, 0x78, 0x95, 0xe9, 0xe1, 0x20, 0x97, 0x1a, 0x43, 0x40, 0xa3, 0xb5, 0xcc, 0x4b, 0x12, 0x84, 0x1e, 0x0e, 0xd3, 0x32, 0xca, 0x99, 0xc3, 0x2b, 0x78, 0x17, 0x24, 0x6b, 0xc7, 0xbc, 0x9d, 0x05, 0xc6, 0xaf, 0x8f, 0x19, 0x75, 0x3c, 0x08, 0xa6, 0x08, 0x26, 0x5b, 0xf4, 0x10, 0x40, 0xaa, 0x6a, 0x7e, 0xb9, 0xde, 0x0b, 0x23, 0x3f, 0x53, 0x5a, 0x20, 0x13, 0x62, 0xec, 0x53, 0x86, 0x81, 0x1f, 0xf6, 0x8e, 0xe3, 0xd1, 0xaa, 0xb5, 0x41, 0x87, 0x62, 0xd2, 0xb7, 0x09, 0x12, 0x71, 0x01, 0x2c, 0xac, 0x6d, 0x9d, 0x37, 0x46, 0x5b, 0xdc, 0x76, 0x2c, 0x96, 0x61, 0x88, 0x55, 0x5a, 0x20, 0xc2, 0x84, 0x95, 0xbd, 0x72, 0xc4, 0xb7, 0x22, 0xae, 0xeb, 0x49, 0x0e, 0x16, 0xf1, 0xf1, 0xbf, 0xc5, 0xc7, 0xa8, 0x8d, 0xfb, 0xe1, 0x08, 0x6c, 0xc4, 0x79, 0x81, 0x13, 0xe8, 0x39, 0xbf, 0x6e, 0x5c, 0xa1, 0x62, 0xfb, 0x32, 0x2a, 0x62, 0xf0, 0x12, 0x07, 0x31, 0x93, 0x40, 0xf3, 0xc0, 0xea, 0x1d, 0xd8, 0x65, 0xba, 0x12, 0xb3, 0x9b, 0xf5, 0x59, 0x9c, 0x4e, 0xf6, 0xb9, 0xf7, 0x85, 0xa1, 0xd9, 0x2f, 0x7c, 0x8b, 0xd0, 0xfc, 0x53, 0x3b, 0xed, 0x85, 0xa4, 0xd2, 0x5e, 0x69, 0x61, 0x02, 0x53, 0xb6, 0x19, 0xc7, 0x82, 0xea, 0x8a, 0x45, 0x01, 0x5d, 0x4b, 0xb3, 0x06, 0x86, 0x7f, 0x4b, 0x2f, 0xe7, 0xa8, 0xd0, 0x28, 0x62, 0x02, 0xe8, 0xf3, 0x9e, 0x1e, 0x72, 0x82, 0x07, 0x9f, 0xdd, 0xd2, 0x83, 0x7d, 0x89, 0x73, 0x1b, 0x6f, 0x35, 0x20, 0xb7, 0x88, 0x15, 0x92, 0xa7, 0x11, 0xfe, 0x81, 0x68, 0xed, 0x14, 0x07, 0xdf, 0x4a, 0x06, 0x9c, 0x5e, 0x7e, 0x34, 0x3a, 0x2a, 0x8a, 0xd3, 0xe8, 0xf8, 0xd4, 0xdb, 0xe3, 0xe9, 0x73, 0xbf, 0xa7, 0xe9, 0x73, 0x62, 0xf2, 0x9d, 0xc1, 0xf7, 0x51, 0xeb, 0xff, 0xb7, 0xe6, 0xd9, 0xac, 0x46, 0x06, 0x74, 0xe2, 0x25, 0x3f, 0x46, 0x43, 0xce, 0x49, 0x52, 0x25, 0x1b, 0xf9, 0x24, 0x5c, 0xda, 0xfd, 0x7f, 0xf6, 0xef, 0xb3, 0xd5, 0xe9, 0x6e, 0x35, 0xb8, 0xd1, 0x0e, 0x2c, 0xc1, 0x48, 0x5a, 0x27, 0x0a, 0x81, 0x01, 0x0f, 0xe4, 0x51, 0xcf, 0x89, 0x36, 0xd3, 0xe8, 0x5e, 0x05, 0xb9, 0x83, 0x42, 0xf3, 0xa5, 0x94, 0x67, 0x6d, 0x6a, 0x6e, 0xad, 0xf8, 0x90, 0xb1, 0x1d, 0x63, 0x18, 0x52, 0xc1, 0xbf, 0xbc, 0xad, 0xf4, 0xd2, 0xc5, 0xef, 0xca, 0x4c, 0xfe, 0xa1, 0xda, 0x15, 0x92, 0x4c, 0x42, 0x3d, 0xfc, 0x80, 0x7e, 0x49, 0x13, 0x4e, 0xf6, 0xe1, 0xee, 0x70, 0xca, 0xd9, 0x0a, 0xde, 0x9b, 0xea, 0xcd, 0xf9, 0x90, 0xfd, 0xae, 0x09, 0xce, 0xb6, 0xa0, 0xf7, 0xd1, 0xe6, 0x0c, 0x55, 0x1e, 0x3f, 0xbb, 0x1e, 0xff, 0x3d, 0xdb, 0xdd, 0x27, 0x80, 0x06, 0x53, 0x7e, 0x0b, 0x2a, 0x80, 0x24, 0x51, 0x5c, 0x6a, 0xab, 0x32, 0x5d, 0x37, 0x8a, 0xf4, 0xb7, 0x11, 0xa7, 0xc1, 0x9e, 0x05, 0x2c, 0x16, 0xc2, 0x08, 0xe2, 0xac, 0x1a, 0xeb, 0x60, 0xf8, 0xd2, 0xea, 0x39, 0x01, 0x1c, 0x64, 0xbd, 0x22, 0x80, 0x19, 0x20, 0xc9, 0x6f, 0xdd, 0x5c, 0x73, 0x8c, 0xa1, 0x53, 0x48, 0x2e, 0x99, 0x1d, 0xc0, 0x8f, 0x28, 0xf1, 0xe3, 0xc5, 0xc5, 0x65, 0x53, 0xf2, 0x44, 0x44, 0x24, 0xb9, 0xe2, 0x73, 0xe4, 0x76, 0x14, 0x56, 0xb8, 0x82, 0xe3, 0xb4, 0xfd, 0x68, 0x31, 0xed, 0x40, 0x10, 0x99, 0xd3, 0x3d, 0xe5, 0x6b, 0x14, 0x61, 0x66, 0x9a, 0xf6, 0x33, 0x98, 0xc5, 0x4d, 0x11, 0xbb, 0xf8, 0x56, 0xf8, 0x8f, 0xd7, 0xb9, 0xda, 0xa3, 0x56, 0x1a, 0xe0, 0x9e, 0xbe, 0x5f, 0x56, 0xe5, 0xb9, 0xd8, 0xf3, 0xbc, 0x19, 0xf5, 0xe9, 0x1f, 0xd2, 0xea, 0xf4, 0x5a, 0xde, 0xed, 0xd4, 0x9e, 0xc8, 0xf5, 0x54, 0x83, 0x8b, 0x8c, 0x2d, 0x24, 0x0e, 0x30, 0xb1, 0x84, 0xa2, 0xbe, 0x2c, 0x86, 0xe6, 0x42, 0x82, 0xaa, 0x37, 0x64, 0x55, 0x51, 0xbc, 0xde, 0xc0, 0x63, 0x88, 0xf6, 0x31, 0x71, 0x52, 0xd5, 0x34, 0x0f, 0x8e, 0xcb, 0x28, 0x65, 0x93, 0x1a, 0x66, 0x3b, 0x21, 0x00, 0xaa, 0x7a, 0xda, 0x2d, 0xf6, 0x7e, 0xb5, 0x27, 0x79, 0xf4, 0x50, 0x3b, 0x10, 0x6b, 0x3c, 0xd7, 0x99, 0x9d, 0xf6, 0xc5, 0x01, 0x91, 0xa0, 0xd5, 0x4f, 0xd3, 0x76, 0x54, 0xa8, 0x5c, 0x35, 0x1d, 0xe2, 0x35, 0x6a, 0x68, 0x67, 0x03, 0xc4, 0x1f, 0xe9, 0x60, 0xb8, 0x49, 0xb1, 0x9a, 0x40, 0xd9, 0x3c, 0x4c, 0x73, 0xaa, 0x88, 0x63, 0xaf, 0xfe, 0xe8, 0xa8, 0x0c, 0x96, 0xbe, 0xb4, 0x65, 0x7c, 0x27, 0xfb, 0xc1, 0x27, 0x24, 0x58, 0xab, 0x4b, 0xa0, 0x5a, 0x7d, 0xc7, 0xca, 0x2d, 0xa5, 0x22, 0xa7, 0xed, 0x26, 0x87, 0xd5, 0x44, 0x1a, 0xc7, 0xdd, 0xfb, 0x60, 0xfc, 0xe5, 0x50, 0xd9, 0x8d, 0xa7, 0xdb, 0x78, 0xb6, 0x9d, 0x80, 0x0f, 0xb9, 0x5f, 0xa7, 0x53, 0x92, 0x5d, 0x18, 0xce, 0x89, 0xc2, 0x69, 0xee, 0xcf, 0xb6, 0x66, 0xe5, 0x66, 0xd2, 0xe3, 0x35, 0x74, 0x0b, 0x83, 0xb6, 0xde, 0xf1, 0xfb, 0xb4, 0x1d, 0x4b, 0x94, 0x95, 0x06, 0x82, 0xe7, 0x1c, 0xf8, 0xc5, 0xe6, 0xd0, 0xf2, 0x17, 0x37, 0x44, 0xfe, 0x99, 0x43, 0x82, 0xbb, 0x88, 0xe4, 0x43, 0x67, 0xcc, 0x4d, 0x5f, 0xa6, 0x26, 0xd7, 0x53, 0xd6, 0x45, 0x96, 0x2b, 0x63, 0xd1, 0x2a, 0xa1, 0x2c, 0x41, 0x59, 0x8b, 0xb8, 0xc1, 0x89, 0x03, 0x3a, 0x61, 0x13, 0xc4, 0x2c, 0x37, 0xa5, 0xbf, 0xd7, 0xdb, 0xd8, 0x53, 0x5f, 0xa1, 0xdb, 0xdb, 0xa5, 0x73, 0xb6, 0xf7, 0x74, 0xa0, 0xf8, 0x93, 0xf5, 0x61, 0xee, 0x3c, 0xe7, 0x00, 0x01, 0x98, 0xe0, 0xa1, 0x22, 0xb6, 0x9a, 0x83, 0x44, 0xa1, 0xe6, 0x70, 0x56, 0x65, 0x92, 0x1e, 0xf0, 0xbc, 0x73, 0xa5, 0x7a, 0xc1, 0x1a, 0x02, 0xf9, 0xd4, 0xc4, 0x7c, 0x81, 0xda, 0x15, 0xc0, 0xd4, 0x25, 0xdc, 0x17, 0xa6, 0x0d, 0x90, 0x55, 0xf2, 0x10, 0xf8, 0xa7, 0x71, 0x9b, 0xed, 0xdf, 0xdf, 0xa1, 0xe4, 0xb9, 0x12, 0x6b, 0x05, 0x3e, 0x83, 0x99, 0x49, 0xbf, 0x66, 0xbb, 0xf6, 0x76, 0xd3, 0xa9, 0x24, 0x61, 0x8c, 0x25, 0x49, 0xd0, 0xf7, 0x83, 0x44, 0xfb, 0x27, 0xe2, 0x7d, 0x69, 0x6d, 0x34, 0x67, 0xed, 0x39, 0x89, 0x02, 0xcb, 0x2f, 0x33, 0x3c, 0xcd, 0x12, 0x42, 0x8f, 0x86, 0x7d, 0xda, 0x3f, 0xd7, 0x26, 0x62, 0x9c, 0x1f, 0x2e, 0xa8, 0xc3, 0x85, 0xf1, 0x73, 0xe5, 0x2c, 0x11, 0xde, 0x98, 0xc8, 0xb0, 0x10, 0x17, 0x55, 0xf5, 0x32, 0x52, 0x67, 0xca, 0x64, 0x50, 0x28, 0x9a, 0x24, 0x92, 0xa1, 0x97, 0x57, 0x81, 0xaf, 0xca, 0x1e, 0xc0, 0xa4, 0x71, 0x2d, 0x2a, 0xec, 0xc9, 0x23, 0x6a, 0x0c, 0x1d, 0x54, 0x15, 0x2a, 0x56, 0x42, 0x0a, 0x83, 0xff, 0x28, 0xba, 0xe7, 0x68, 0x38, 0xf5, 0x32, 0xa9, 0xb7, 0xe7, 0x70, 0x32, 0xa8, 0x79, 0x5e, 0x46, 0x1d, 0xec, 0x29, 0x8a, 0xde, 0x41, 0x94, 0x94, 0x26, 0x79, 0xc2, 0x52, 0x23, 0xe0, 0xa1, 0x1d, 0x65, 0x0c, 0xbe, 0x1b, 0x87, 0x2a, 0x21, 0x53, 0x2f, 0x35, 0x56, 0xe8, 0xd1, 0x7b, 0xb8, 0x23, 0x75, 0x56, 0xc7, 0x08, 0x9d, 0x13, 0xf0, 0x8f, 0x80, 0x38, 0xe9, 0x92, 0xf7, 0x16, 0xc2, 0xf3, 0x74, 0xa7, 0x92, 0xf5, 0x49, 0x7d, 0x09, 0x41, 0xbc, 0x07, 0x61, 0x1f, 0xe6, 0xa0, 0xd8, 0xa6, 0xe3, 0x72, 0xa4, 0x59, 0x4a, 0xd9, 0x33, 0x40, 0x80, 0x3a, 0x3a, 0xb3, 0xa0, 0x96, 0xca, 0x56, 0x98, 0xbd, 0x1f, 0x80, 0x86, 0x6c, 0xe1, 0x09, 0x64, 0x1b, 0x1a, 0xc9, 0x52, 0xaa, 0xd1, 0x39, 0xea, 0x4b, 0x6a, 0x3e, 0x4e, 0xa4, 0xea, 0x00, 0xde, 0x07, 0x0b, 0x23, 0xbc, 0x40, 0xc4, 0xd2, 0xd9, 0xf6, 0xda, 0x8e, 0x22, 0x36, 0xbe, 0x5e, 0x65, 0x6e, 0xbe, 0xc8, 0xb0, 0x07, 0xa2, 0x2d, 0xe9, 0x4b, 0x73, 0x54, 0xe6, 0x0a, 0xf2, 0xd3, 0x83, 0x8b, 0x27, 0x4c, 0xcc, 0x0c, 0x8a, 0xd4, 0x2b, 0xb8, 0x95, 0x2e, 0x42, 0x64, 0x29, 0xc1, 0xe0, 0x6b, 0x92, 0xab, 0xfe, 0x53, 0x06, 0x96, 0x4a, 0x8c, 0x5d, 0x7c, 0x51, 0x74, 0xd0, 0x1e, 0x37, 0x35, 0x9c, 0x1e, 0x69, 0x8f, 0x68, 0x18, 0xd9, 0xbe, 0xaf, 0x81, 0x9b, 0x7e, 0xd8, 0x71, 0x9d, 0xb6, 0x50, 0x43, 0x78, 0x85, 0x7d, 0x65, 0x93, 0x45, 0xb4, 0x02, 0xd0, 0x5c, 0x36, 0xe2, 0x62, 0x3f, 0x40, 0x33, 0xee, 0x91, 0xe5, 0x3f, 0x67, 0x39, 0x2f, 0x1b, 0x89, 0x9f, 0x04, 0x9d, 0x46, 0x3e, 0x70, 0x92, 0x9e, 0x8c, 0xf5 }; uint8_t s0s1s2[] = { 0x03, 0xac, 0x44, 0x29, 0x53, 0x04, 0x05, 0x00, 0x01, 0x6e, 0x65, 0x69, 0x2d, 0x69, 0x2d, 0x69, 0x73, 0x6e, 0x69, 0x73, 0x6c, 0x65, 0x72, 0x69, 0x72, 0x76, 0x65, 0x72, 0x69, 0x77, 0x74, 0x2e, 0x6e, 0x72, 0x76, 0x72, 0x65, 0x72, 0x70, 0x72, 0x69, 0x69, 0x70, 0x72, 0x73, 0x6e, 0x65, 0x72, 0x72, 0x6e, 0x2d, 0x65, 0x74, 0x72, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x40, 0x69, 0x69, 0x76, 0x77, 0x2d, 0x73, 0x65, 0x72, 0x72, 0x76, 0x73, 0x72, 0x2e, 0x2d, 0x76, 0x65, 0x31, 0x65, 0x6d, 0x6d, 0x73, 0x69, 0x73, 0x74, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x72, 0x65, 0x2d, 0x74, 0x69, 0x31, 0x65, 0x2d, 0x6f, 0x77, 0x2e, 0x76, 0x77, 0x2d, 0x77, 0x72, 0x65, 0x65, 0x31, 0x74, 0x73, 0x70, 0x74, 0x6e, 0x72, 0x6e, 0x73, 0x6d, 0x2e, 0x69, 0x72, 0x2d, 0x65, 0x69, 0x77, 0x69, 0x76, 0x72, 0x77, 0x72, 0x32, 0x6e, 0x65, 0x6c, 0x2e, 0x2d, 0x6e, 0x69, 0x6d, 0x6c, 0x73, 0x65, 0x73, 0x70, 0x2d, 0x65, 0x72, 0x40, 0x72, 0x74, 0x6e, 0x6e, 0x6d, 0x6f, 0x70, 0x74, 0x73, 0x2d, 0x63, 0x69, 0x32, 0x31, 0x2d, 0x40, 0x69, 0x70, 0x2d, 0x2d, 0x72, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x69, 0x65, 0x6e, 0x32, 0x6f, 0x6c, 0x6e, 0x72, 0x73, 0x77, 0x65, 0x65, 0x72, 0x32, 0x6d, 0x65, 0x6c, 0x2d, 0x72, 0x6e, 0x65, 0x6d, 0x31, 0x65, 0x74, 0x2d, 0x6f, 0x72, 0x65, 0x63, 0x69, 0x40, 0x70, 0x2d, 0x65, 0x6d, 0x2d, 0x77, 0x63, 0x63, 0x74, 0x40, 0x36, 0x2d, 0x72, 0x65, 0x70, 0x2d, 0x6e, 0x69, 0x6d, 0x65, 0x74, 0x70, 0x76, 0x40, 0x76, 0x72, 0x72, 0x69, 0x77, 0x76, 0x69, 0x74, 0x74, 0x65, 0x31, 0x6d, 0x2e, 0x6f, 0x72, 0x73, 0x73, 0x6c, 0x40, 0x36, 0x72, 0x70, 0x72, 0x70, 0x72, 0x69, 0x32, 0x6c, 0x77, 0x70, 0x76, 0x65, 0x72, 0x76, 0x63, 0x65, 0x65, 0x77, 0x72, 0x6e, 0x2e, 0x76, 0x69, 0x69, 0x2e, 0x40, 0x72, 0x2e, 0x2e, 0x72, 0x73, 0x6e, 0x72, 0x72, 0x6e, 0x70, 0x40, 0x77, 0x65, 0x77, 0x65, 0x70, 0x63, 0x74, 0x2d, 0x70, 0x72, 0x2d, 0x74, 0x72, 0x31, 0x65, 0x6e, 0x2d, 0x76, 0x2d, 0x2d, 0x2d, 0x74, 0x76, 0x2d, 0x74, 0x65, 0x2e, 0x2d, 0x6c, 0x76, 0x2d, 0x6c, 0x70, 0x73, 0x6d, 0x65, 0x72, 0x31, 0x31, 0x36, 0x76, 0x73, 0x73, 0x6e, 0x2d, 0x6e, 0x73, 0x72, 0x2d, 0x6f, 0x6c, 0x65, 0x74, 0x77, 0x65, 0x69, 0x72, 0x69, 0x65, 0x6d, 0x76, 0x31, 0x65, 0x73, 0x72, 0x6c, 0x72, 0x77, 0x65, 0x76, 0x74, 0x72, 0x69, 0x72, 0x76, 0x32, 0x73, 0x6d, 0x72, 0x2d, 0x6d, 0x40, 0x69, 0x40, 0x69, 0x31, 0x69, 0x6f, 0x6e, 0x6d, 0x69, 0x73, 0x70, 0x72, 0x77, 0x6f, 0x6f, 0x65, 0x77, 0x76, 0x70, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x32, 0x36, 0x6c, 0x74, 0x6e, 0x72, 0x74, 0x2d, 0x6e, 0x6c, 0x72, 0x72, 0x2d, 0x74, 0x65, 0x73, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x65, 0x2d, 0x6e, 0x70, 0x6e, 0x40, 0x65, 0x6e, 0x6e, 0x74, 0x65, 0x6e, 0x72, 0x6e, 0xfe, 0x5a, 0x38, 0x79, 0x81, 0xe8, 0x49, 0xee, 0x93, 0xbb, 0xa0, 0x59, 0x4a, 0xa0, 0xcc, 0x31, 0xbf, 0x0d, 0x86, 0xc0, 0x3f, 0xae, 0x2a, 0x16, 0xfa, 0xf0, 0x4e, 0x0f, 0xa3, 0x01, 0x06, 0xa0, 0x0e, 0xa5, 0x8c, 0xa4, 0xca, 0xd2, 0x01, 0xa5, 0x90, 0xbd, 0x55, 0xd1, 0x42, 0x2b, 0xd4, 0xb3, 0xbb, 0x06, 0xb1, 0x3a, 0x94, 0x41, 0x76, 0x1d, 0xa5, 0x23, 0x6e, 0x1e, 0x59, 0x73, 0x63, 0x34, 0x60, 0xd3, 0x48, 0xc0, 0x3b, 0xcf, 0xf1, 0xa8, 0x38, 0xd6, 0xf3, 0x5e, 0x6d, 0xcb, 0xea, 0xfc, 0x9c, 0x52, 0xae, 0x9a, 0x89, 0xdb, 0x24, 0x1b, 0x92, 0x4a, 0x85, 0x97, 0x3c, 0xd8, 0x4c, 0x31, 0xad, 0xfd, 0x00, 0xef, 0xc5, 0x17, 0xa5, 0x22, 0xc0, 0xf1, 0x94, 0x18, 0xec, 0xf6, 0x49, 0xe5, 0x05, 0x11, 0x12, 0x67, 0x6c, 0x71, 0xc0, 0x84, 0x6d, 0x50, 0xf8, 0x23, 0x01, 0x57, 0xc4, 0xfc, 0x73, 0x65, 0x69, 0x6e, 0x65, 0x72, 0x6d, 0x6f, 0x69, 0x2d, 0x65, 0x65, 0x69, 0x63, 0x63, 0x69, 0x2d, 0x72, 0x2d, 0x69, 0x2d, 0x2d, 0x77, 0x72, 0x76, 0x72, 0x72, 0x2d, 0x76, 0x70, 0x63, 0x69, 0x74, 0x73, 0x6d, 0x65, 0x6c, 0x2d, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x77, 0x69, 0x63, 0x69, 0x70, 0x31, 0x40, 0x72, 0x69, 0x2d, 0x2d, 0x2d, 0x72, 0x72, 0x6c, 0x72, 0x63, 0x72, 0x77, 0x6e, 0x6c, 0x2d, 0x72, 0x2e, 0x76, 0x72, 0x65, 0x6d, 0x76, 0x36, 0x6d, 0x72, 0x77, 0x72, 0x65, 0x65, 0x69, 0x72, 0x76, 0x6d, 0x76, 0x74, 0x76, 0x72, 0x65, 0x69, 0x72, 0x6e, 0x6d, 0x77, 0x6c, 0x40, 0x32, 0x70, 0x65, 0x65, 0x69, 0x72, 0x31, 0x2e, 0x70, 0x36, 0x31, 0x65, 0x70, 0x72, 0x72, 0x73, 0x72, 0x6e, 0x6e, 0x73, 0x32, 0x2d, 0x2d, 0x2d, 0x69, 0x65, 0x31, 0x74, 0x6e, 0x65, 0x74, 0x65, 0x76, 0x69, 0x6d, 0x6c, 0x6e, 0x70, 0x74, 0x73, 0x72, 0x6d, 0x72, 0x72, 0x69, 0x65, 0x74, 0x65, 0x65, 0x2d, 0x70, 0x74, 0x6e, 0x74, 0x65, 0x6f, 0x72, 0x69, 0x76, 0x40, 0x31, 0x69, 0x72, 0x6d, 0x6d, 0x77, 0x69, 0x72, 0x65, 0x6e, 0x40, 0x63, 0x40, 0x65, 0x65, 0x69, 0x2d, 0x72, 0x65, 0x40, 0x69, 0x32, 0x74, 0x73, 0x6e, 0x36, 0x2d, 0x70, 0x65, 0x6c, 0x70, 0x6e, 0x72, 0x69, 0x32, 0x65, 0x74, 0x76, 0x77, 0x73, 0x6f, 0x77, 0x65, 0x72, 0x2d, 0x6e, 0x73, 0x65, 0x65, 0x70, 0x65, 0x2d, 0x65, 0x73, 0x2d, 0x65, 0x2e, 0x73, 0x69, 0x67, 0x45, 0x8b, 0x6b, 0x3b, 0xc9, 0x5f, 0x09, 0x65, 0x65, 0x72, 0x6c, 0x73, 0x6d, 0x70, 0x70, 0x73, 0x63, 0x70, 0x40, 0x72, 0x76, 0x65, 0x6e, 0x6f, 0x6c, 0x69, 0x2e, 0x72, 0x73, 0x76, 0x69, 0x77, 0x72, 0x2d, 0x69, 0x6e, 0x69, 0x65, 0x77, 0x73, 0x69, 0x70, 0x77, 0x63, 0x65, 0x74, 0x72, 0x73, 0x31, 0x65, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x6d, 0x65, 0x36, 0x6e, 0x6e, 0x69, 0x6d, 0x6e, 0x70, 0x77, 0x72, 0x65, 0x31, 0x65, 0x6e, 0x6e, 0x65, 0x2d, 0x65, 0x65, 0x2e, 0x77, 0x6e, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x6c, 0x31, 0x76, 0x65, 0x72, 0x2d, 0x36, 0x6c, 0x70, 0x6f, 0x65, 0x72, 0x73, 0x63, 0x72, 0x77, 0x73, 0x72, 0x65, 0x65, 0x65, 0x6c, 0x76, 0x72, 0x65, 0x6e, 0x65, 0x2e, 0x6f, 0x2d, 0x72, 0x70, 0x65, 0x74, 0x72, 0x77, 0x69, 0x69, 0x72, 0x65, 0x77, 0x6c, 0x72, 0x2d, 0x69, 0x72, 0x31, 0x6e, 0x65, 0x70, 0x72, 0x74, 0x76, 0x6c, 0x2e, 0x72, 0x65, 0x72, 0x6c, 0x73, 0x6c, 0x2e, 0x2e, 0x72, 0x2d, 0x6e, 0x63, 0x32, 0x2e, 0x65, 0x2d, 0x65, 0x69, 0x2d, 0x65, 0x70, 0x6e, 0x72, 0x72, 0x32, 0x2e, 0x73, 0x70, 0x77, 0x65, 0x73, 0x77, 0x73, 0x40, 0x40, 0x73, 0x63, 0x2e, 0x65, 0x76, 0x70, 0x65, 0x69, 0x65, 0x70, 0x73, 0x40, 0x65, 0x73, 0x2d, 0x2d, 0x2e, 0x2e, 0x73, 0x65, 0x6f, 0x65, 0x65, 0x6d, 0x76, 0x70, 0x6d, 0x69, 0x70, 0x70, 0x69, 0x2e, 0x76, 0x6e, 0x72, 0x72, 0x72, 0x6d, 0x73, 0x6f, 0x73, 0x72, 0x72, 0x72, 0x77, 0x70, 0x65, 0x69, 0x72, 0x73, 0x6e, 0x69, 0x65, 0x65, 0x74, 0x65, 0x69, 0x40, 0x63, 0x69, 0x70, 0x6c, 0x6e, 0x2d, 0x65, 0x69, 0x72, 0x63, 0x6c, 0x72, 0x2e, 0x36, 0x69, 0x72, 0x6c, 0x6c, 0x2d, 0x6f, 0x76, 0x69, 0x6f, 0x2d, 0x6d, 0x6c, 0x72, 0x72, 0x2e, 0x70, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x69, 0x65, 0x65, 0x2d, 0x6d, 0x76, 0x6e, 0x69, 0x73, 0x73, 0x73, 0x74, 0x63, 0x65, 0x76, 0x2e, 0x77, 0x2d, 0x36, 0x73, 0x69, 0x2d, 0x72, 0x72, 0x6c, 0x36, 0x74, 0x72, 0x6d, 0x65, 0x2d, 0x65, 0x2e, 0x6d, 0x31, 0x72, 0x6f, 0x74, 0x76, 0x31, 0x65, 0x6d, 0x69, 0x72, 0x69, 0x69, 0x2d, 0x72, 0x73, 0x72, 0x72, 0x76, 0x31, 0x6e, 0x2d, 0x69, 0x6e, 0x77, 0x70, 0x69, 0x72, 0x6e, 0x76, 0x74, 0x6f, 0x65, 0x63, 0x6f, 0x73, 0x65, 0x73, 0x72, 0x69, 0x69, 0x40, 0x6e, 0x65, 0x65, 0x65, 0x65, 0x77, 0x70, 0x70, 0x6e, 0x72, 0x6e, 0x65, 0x72, 0x32, 0x65, 0x2d, 0x77, 0x69, 0x6e, 0x70, 0x69, 0x6f, 0x76, 0x77, 0x72, 0x74, 0x77, 0x6e, 0x72, 0xfe, 0x98, 0xf3, 0xb4, 0xff, 0x3f, 0x2e, 0xdb, 0x59, 0xbd, 0x32, 0x02, 0x6a, 0x44, 0x03, 0x67, 0x9e, 0xe1, 0x98, 0x97, 0xed, 0x67, 0x6d, 0xb0, 0x8f, 0xa9, 0xb6, 0xf8, 0x4d, 0x92, 0x35, 0x19, 0x72, 0x72, 0x65, 0x74, 0x73, 0x6e, 0x65, 0x65, 0x69, 0x36, 0x72, 0x73, 0x2d, 0x70, 0x2d, 0x2d, 0x69, 0x6e, 0x72, 0x65, 0x32, 0x72, 0x77, 0x72, 0x73, 0x77, 0x73, 0x70, 0x2d, 0x2d, 0x69, 0x6c, 0x70, 0x74, 0x65, 0x69, 0x72, 0x74, 0x6e, 0x76, 0x65, 0x76, 0x76, 0x69, 0x69, 0x65, 0x70, 0x6e, 0x73, 0x6e, 0x36, 0x76, 0x70, 0x76, 0x6c, 0x6c, 0x70, 0x6e, 0x6e, 0x74, 0x2e, 0x6f, 0x32, 0x74, 0x76, 0x74, 0x40, 0x72, 0x6e, 0x72, 0x74, 0x74, 0x2d, 0x6f, 0x72, 0x73, 0x32, 0x72, 0x32, 0x72, 0x70, 0x65, 0x65, 0x6e, 0x72, 0x70, 0x73, 0x72, 0x69, 0x74, 0x74, 0x6e, 0x72, 0x6c, 0x31, 0x74, 0x77, 0x31, 0x63, 0x63, 0x74, 0x69, 0x72, 0x69, 0x72, 0x70, 0x31, 0x74, 0x72, 0x76, 0x65, 0x72, 0x65, 0x6c, 0x76, 0x6d, 0x72, 0x6c, 0x69, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x69, 0x6c, 0x74, 0x6e, 0x65, 0x69, 0x77, 0x73, 0x70, 0x69, 0x72, 0x2d, 0x65, 0x74, 0x2e, 0x65, 0x65, 0x6d, 0x72, 0x31, 0x2d, 0x72, 0x36, 0x65, 0x2d, 0x69, 0x6d, 0x36, 0x6e, 0x72, 0x6d, 0x6c, 0x72, 0x72, 0x65, 0x65, 0x6e, 0x31, 0x6e, 0x40, 0x72, 0x40, 0x6f, 0x73, 0x6d, 0x36, 0x2e, 0x72, 0x65, 0x36, 0x74, 0x77, 0x65, 0x65, 0x73, 0x36, 0x76, 0x6c, 0x6f, 0x2d, 0x36, 0x6d, 0x36, 0x70, 0x32, 0x74, 0x6d, 0x65, 0x6d, 0x69, 0x65, 0x65, 0x69, 0x76, 0x69, 0x74, 0x2d, 0x63, 0x2d, 0x6e, 0x32, 0x72, 0x63, 0x2d, 0x77, 0x72, 0x74, 0x72, 0x70, 0x6e, 0x76, 0x6f, 0x72, 0x40, 0x65, 0x65, 0x6d, 0x77, 0x2d, 0x2d, 0x74, 0x6e, 0x73, 0x76, 0x65, 0x69, 0x69, 0x72, 0x6f, 0x65, 0x70, 0x69, 0x6d, 0x76, 0x69, 0x65, 0x72, 0x2d, 0x74, 0x2d, 0x69, 0x65, 0x72, 0x69, 0x6f, 0x72, 0x72, 0x69, 0x76, 0x72, 0x77, 0x69, 0x2e, 0x77, 0x69, 0x70, 0x69, 0x6d, 0x36, 0x72, 0x76, 0x65, 0x76, 0x73, 0x6e, 0x72, 0x65, 0x2e, 0x76, 0x2d, 0x76, 0x6f, 0x2d, 0x65, 0x73, 0x72, 0x74, 0x36, 0x2d, 0x6f, 0x70, 0x73, 0x74, 0x74, 0x77, 0x6c, 0x2d, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x72, 0x32, 0x2d, 0x72, 0x69, 0x6d, 0x6e, 0x72, 0x6c, 0x6f, 0x65, 0x36, 0x31, 0x65, 0x65, 0x69, 0x73, 0x31, 0x74, 0x69, 0x69, 0x65, 0x40, 0x69, 0x6e, 0x2d, 0x63, 0x40, 0x31, 0x70, 0x65, 0x6e, 0x2d, 0x69, 0x72, 0x65, 0x65, 0x76, 0x65, 0x70, 0x72, 0x6c, 0x2d, 0x6e, 0x73, 0x69, 0x65, 0x65, 0x6e, 0x2e, 0x63, 0x6c, 0x72, 0x65, 0x2d, 0x2e, 0x6d, 0x72, 0x76, 0x70, 0x69, 0x6d, 0x40, 0x32, 0x77, 0x72, 0x6e, 0x72, 0x6c, 0x36, 0x72, 0x31, 0x2d, 0x73, 0x74, 0x2d, 0x69, 0x63, 0x40, 0x70, 0x32, 0x65, 0x31, 0x69, 0x69, 0x65, 0x72, 0x63, 0x74, 0x72, 0x74, 0x77, 0x6e, 0x69, 0x72, 0x65, 0x76, 0x65, 0x77, 0x69, 0x69, 0x73, 0x6e, 0x77, 0x77, 0x73, 0x6f, 0x69, 0x70, 0x73, 0x2d, 0x65, 0x65, 0x73, 0x65, 0x77, 0x2d, 0x73, 0x72, 0x6d, 0x65, 0x32, 0x6e, 0x73, 0x36, 0x65, 0x72, 0x77, 0x70, 0x65, 0x69, 0x2d, 0x2d, 0x74, 0x6f, 0x6f, 0x36, 0x63, 0x74, 0x72, 0x63, 0x77, 0x69, 0x2e, 0x31, 0x6c, 0x65, 0x77, 0x72, 0x65, 0x76, 0x74, 0x2d, 0x77, 0x2e, 0x76, 0x72, 0x6e, 0x36, 0x70, 0x69, 0x2e, 0x6e, 0x72, 0x77, 0x69, 0x65, 0x74, 0x2d, 0x6e, 0x63, 0x6e, 0x70, 0x2d, 0x6e, 0x2e, 0x6d, 0x69, 0x65, 0x63, 0x65, 0x2d, 0x76, 0x70, 0x73, 0x31, 0x73, 0x2d, 0x76, 0x6e, 0x6e, 0x6c, 0x2d, 0x6c, 0x2d, 0x65, 0x6e, 0x73, 0x6c, 0x65, 0x74, 0x70, 0x65, 0x2d, 0x6e, 0x77, 0x76, 0x40, 0x69, 0x40, 0x63, 0x6f, 0x72, 0x32, 0x6d, 0x31, 0x72, 0x36, 0x69, 0x73, 0x72, 0x70, 0x65, 0x2d, 0x6c, 0x2e, 0x72, 0x74, 0x74, 0x65, 0x69, 0x6f, 0x69, 0x2d, 0x2d, 0x65, 0x6f, 0x65, 0x74, 0x72, 0x69, 0x76, 0x72, 0x72, 0x65, 0x69, 0x76, 0x69, 0x69, 0x6e, 0x31, 0x65, 0x76, 0x72, 0x73, 0x77, 0x72, 0x2d, 0x69, 0x65, 0x69, 0x70, 0x65, 0x6e, 0x6e, 0x65, 0x65, 0x6e, 0x2d, 0x72, 0x76, 0x72, 0x6c, 0x2e, 0x70, 0x76, 0x6e, 0x69, 0x72, 0x70, 0x73, 0x2d, 0x69, 0x74, 0x76, 0x72, 0x70, 0x65, 0x63, 0x72, 0x70, 0x6e, 0x36, 0x6c, 0x74, 0x72, 0x72, 0x72, 0x73, 0x65, 0x40, 0x63, 0x6d, 0x63, 0x32, 0x65, 0x32, 0x69, 0x6e, 0x77, 0x65, 0x74, 0x72, 0x77, 0x40, 0x69, 0x65, 0x70, 0x31, 0x36, 0x72, 0x73, 0x2d, 0x72, 0x72, 0x32, 0x72, 0x6c, 0x77, 0x6e, 0x6f, 0x77, 0x6c, 0x74, 0x72, 0x2d, 0x6e, 0x65, 0x70, 0x6c, 0x72, 0x6f, 0x69, 0x2d, 0x2d, 0x69, 0x36, 0x69, 0x69, 0x76, 0x69, 0x69, 0x6d, 0x72, 0x73, 0x6f, 0x6d, 0x74, 0x70, 0x76, 0x6d, 0x6d, 0x69, 0x72, 0x70, 0x70, 0x2d, 0x31, 0x63, 0x6c, 0x65, 0x65, 0x6e, 0x2d, 0x77, 0x74, 0x73, 0x6c, 0x72, 0x6e, 0x65, 0x65, 0x2d, 0x6c, 0x69, 0x2d, 0x6e, 0x74, 0x70, 0x72, 0x77, 0x77, 0x65, 0x65, 0x65, 0x2d, 0x76, 0x6e, 0x72, 0x69, 0x69, 0x73, 0x65, 0x74, 0x73, 0x76, 0x72, 0x72, 0x72, 0x69, 0x72, 0x73, 0x72, 0x6f, 0x2e, 0x77, 0x2d, 0x2d, 0x6c, 0x6e, 0x65, 0x65, 0x6d, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x40, 0x69, 0x32, 0x69, 0x32, 0x6e, 0x65, 0x32, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x36, 0x6e, 0x72, 0x32, 0x6e, 0x65, 0x69, 0x32, 0x6f, 0x70, 0x72, 0x72, 0x65, 0x72, 0x72, 0x69, 0x6e, 0x6d, 0x69, 0x70, 0x6c, 0x6c, 0x65, 0x31, 0x72, 0x72, 0x73, 0x72, 0x70, 0x73, 0x72, 0x65, 0x65, 0x6e, 0x76, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x31, 0x74, 0x74, 0x72, 0x63, 0x2e, 0x69, 0x65, 0x2d, 0x6d, 0x72, 0x70, 0x6e, 0x6c, 0x65, 0x31, 0x73, 0x73, 0x40, 0x74, 0x72, 0x73, 0x2e, 0x74, 0x6e, 0x77, 0x6c, 0x6f, 0x70, 0x77, 0x76, 0x73, 0x72, 0x69, 0x77, 0x69, 0x6e, 0x69, 0x2d, 0x72, 0x70, 0x70, 0x73, 0x2e, 0x76, 0x73, 0x65, 0x72, 0x72, 0x74, 0x2d, 0x72, 0x65, 0x76, 0x69, 0x77, 0x72, 0x65, 0x2d, 0x72, 0x69, 0x36, 0x77, 0x77, 0x77, 0x40, 0x2d, 0x6d, 0x69, 0x74, 0x72, 0x2d, 0x32, 0x6f, 0x76, 0x72, 0x2d, 0x2d, 0x65, 0x2e, 0x2e, 0x72, 0x6e, 0x32, 0x74, 0x6c, 0x6e, 0x6c, 0x2e, 0x6d, 0x2d, 0x6f, 0x65, 0x72, 0x2d, 0x6e, 0x65, 0x65, 0x69, 0x40, 0x69, 0x77, 0x65, 0x6c, 0x2d, 0x69, 0x69, 0x65, 0x72, 0x72, 0x32, 0x40, 0x73, 0x65, 0x36, 0x76, 0x73, 0x72, 0x69, 0x63, 0x77, 0x72, 0x6c, 0x72, 0x6e, 0x74, 0x2d, 0x65, 0x69, 0x72, 0x70, 0x6d, 0x65, 0x6c, 0x73, 0x65, 0x6c, 0x32, 0x2d, 0x73, 0x70, 0x2d, 0x31, 0x72, 0x74, 0x2e, 0x65, 0x74, 0x72, 0x74, 0x72, 0x70, 0x69, 0x40, 0x36, 0x2d, 0x74, 0x72, 0x6c, 0x2d, 0x6e, 0x72, 0x6e, 0x6d, 0x63, 0x76, 0x74, 0x6d, 0x70, 0x32, 0x70, 0x69, 0x69, 0x2d, 0x73, 0x72, 0x74, 0x65, 0x74, 0x74, 0x70, 0x2d, 0x31, 0x6c, 0x77, 0x65, 0x72, 0x70, 0x73, 0x36, 0x6c, 0x72, 0x72, 0x65, 0x65, 0x76, 0x69, 0x2e, 0x6e, 0x72, 0x72, 0x36, 0x65, 0x69, 0x72, 0x69, 0x40, 0x6c, 0x74, 0x6c, 0x72, 0x2d, 0x70, 0x74, 0x76, 0x74, 0x6f, 0x72, 0x31, 0x73, 0x70, 0x65, 0x74, 0x69, 0x6e, 0x69, 0x6c, 0x70, 0x72, 0x65, 0x70, 0x72, 0x73, 0x69, 0x2d, 0x6d, 0x63, 0x2d, 0x72, 0x2d, 0x36, 0x73, 0x6e, 0x2d, 0x6d, 0x69, 0x76, 0x76, 0x6d, 0x74, 0x72, 0x77, 0x74, 0x2e, 0x6d, 0x65, 0x2d, 0x65, 0x6d, 0x2e, 0x6c, 0x73, 0x6e, 0x6f, 0x76, 0x31, 0x74, 0x65, 0x65, 0x31, 0x69, 0x65, 0x32, 0x2d, 0x74, 0x2d, 0x77, 0x77, 0x77, 0x2e, 0x70, 0x65, 0x6e, 0x2d, 0x69, 0x32, 0x72, 0x73, 0x74, 0x65, 0x65, 0x69, 0x73, 0x77, 0x77, 0x2e, 0x6e, 0x72, 0x65, 0x70, 0x76, 0x40, 0x77, 0x65, 0x2d, 0x70, 0x36, 0x2d, 0x74, 0x65, 0x2d, 0x69, 0x74, 0x76, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x73, 0x31, 0x36, 0x69, 0x31, 0x74, 0x76, 0x65, 0x77, 0x6c, 0x6e, 0x6c, 0x32, 0x6e, 0x70, 0x73, 0x69, 0x69, 0x65, 0x72, 0x2d, 0x6e, 0x2d, 0x65, 0x65, 0x6c, 0x32, 0x77, 0x72, 0x69, 0x70, 0x76, 0x32, 0x65, 0x6c, 0x36, 0x65, 0x69, 0x31, 0x6e, 0x72, 0x6c, 0x6d, 0x65, 0x65, 0x77, 0x6e, 0x2d, 0x32, 0x77, 0x69, 0x65, 0x6d, 0x74, 0x77, 0x40, 0x65, 0x6e, 0x77, 0x73, 0x65, 0x72, 0x6c, 0x40, 0x65, 0x65, 0x72, 0x72, 0x74, 0x6e, 0x6c, 0x6d, 0x73, 0x69, 0x76, 0x72, 0x31, 0x2d, 0x65, 0x36, 0x72, 0x2d, 0x70, 0x69, 0x6e, 0x63, 0x31, 0x2d, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x2e, 0x77, 0x2d, 0x72, 0x76, 0x63, 0x69, 0x2d, 0x6d, 0x70, 0x2d, 0x6c, 0x69, 0x63, 0x69, 0x77, 0x6e, 0x69, 0x77, 0x36, 0x72, 0x69, 0x72, 0x2e, 0x74, 0x72, 0x6e, 0x65, 0x6f, 0x73, 0x2d, 0x2e, 0x72, 0x63, 0x76, 0x74, 0x36, 0x65, 0x72, 0x65, 0x6d, 0x32, 0x72, 0x70, 0x40, 0x65, 0x74, 0x6e, 0x32, 0x70, 0x2d, 0x31, 0x40, 0x6c, 0x65, 0x6c, 0x76, 0x69, 0x69, 0x76, 0x76, 0x73, 0x31, 0x6e, 0x65, 0x74, 0x65, 0x6d, 0x69, 0x2d, 0x72, 0x74, 0x74, 0x6c, 0x31, 0x74, 0x6e, 0x6e, 0x65, 0x77, 0x36, 0x69, 0x69, 0x72, 0x6e, 0x2d, 0x2d, 0x2d, 0x72, 0x73, 0x76, 0x72, 0x72, 0x65, 0x72, 0x65, 0x72, 0x2d, 0x6c, 0x76, 0x77, 0x63, 0x77, 0x72, 0x6d, 0x72, 0x2e, 0x65, 0x73, 0x32, 0x72, 0x36, 0x77, 0x72, 0x72, 0x6d, 0x74, 0x2d, 0x72, 0x2e, 0x73, 0x73, 0x65, 0x77, 0x6e, 0x65, 0x69, 0x65, 0x2d, 0x65, 0x77, 0x6f, 0x74, 0x72, 0x32, 0x40, 0x6e, 0x72, 0x69, 0x6e, 0x32, 0x70, 0x73, 0x72, 0x40, 0x2d, 0x65, 0x69, 0x65, 0x77, 0x65, 0x70, 0x40, 0x36, 0x72, 0x6c, 0x6d, 0x73, 0x69, 0x72, 0x72, 0x74, 0x36, 0x6c, 0x76, 0x65, 0x76, 0x2d, 0x74, 0x6c, 0x72, 0x72, 0x74, 0x6e, 0x73, 0x74, 0x69, 0x72, 0x6d, 0x40, 0x2d, 0x6e, 0x70, 0x73, 0x2d, 0x6d, 0x72, 0x72, 0x70, 0x65, 0x65, 0x36, 0x6e, 0x77, 0x2d, 0x69, 0x2d, 0x32, 0x72, 0x6d, 0x72, 0x6c, 0x32, 0x6c, 0x73, 0x6d, 0x65, 0x36, 0x69, 0x69, 0x72, 0x77, 0x74, 0x6f, 0x72, 0x6d, 0x6d, 0x69, 0x65, 0x73, 0x63, 0x65, 0x74, 0x74, 0x72, 0x65, 0x72, 0x2e, 0x6e, 0x73, 0x65, 0x76, 0x6c, 0x76, 0x77, 0x72, 0x6e, 0x6c, 0x32, 0x2d, 0x73, 0x65, 0x73, 0x2e, 0x76, 0x72, 0x65, 0x2d, 0x72, 0x77, 0x2d, 0x77, 0x70, 0x65, 0x6c, 0x72, 0x6e, 0x2e, 0x31, 0x73, 0x2e, 0x72, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x6d, 0x32, 0x70, 0x76, 0x76, 0x31, 0x76, 0x77, 0x65, 0x6e, 0x73, 0x63, 0x2e, 0x2d, 0x69, 0x6e, 0x69, 0x77, 0x6e, 0x65, 0x6d, 0x2d, 0x72, 0x6e, 0x74, 0x6e, 0x40, 0x73, 0x2d, 0x74, 0x74, 0x65, 0x72, 0x2d, 0x2d, 0x69, 0x73, 0x70, 0x69, 0x6c, 0x72, 0x76, 0x6d, 0x74, 0x6e, 0x73, 0x74, 0x72, 0x65, 0x63, 0x69, 0x65, 0x65, 0x72, 0x6f, 0x6e, 0x72, 0x72, 0x6c, 0x6e, 0x6e, 0x65, 0x6d, 0x74, 0x6c, 0x74, 0x65, 0x69, 0x2d, 0x6f, 0x69, 0x2e, 0x6e, 0x63, 0x65, 0x6c, 0x40, 0x70, 0x2d, 0x2d, 0x74, 0x73, 0x74, 0x40, 0x72, 0x74, 0x6c, 0x72, 0x6e, 0x6f, 0x73, 0x65, 0x74, 0x6d, 0x69, 0x32, 0x72, 0x65, 0x77, 0x6e, 0x76, 0x74, 0x73, 0x2d, 0x72, 0x6e, 0x69, 0x73, 0x40, 0x36, 0x2d, 0x6d, 0x2e, 0x65, 0x6d, 0x40, 0x69, 0x72, 0x72, 0x70, 0x65, 0x72, 0x76, 0x6c, 0x65, 0x76, 0x72, 0x65, 0x69, 0x65, 0x69, 0x6e, 0x72, 0x2d, 0x63, 0x72, 0x69, 0x6e, 0x72, 0x69, 0x6e, 0x69, 0x70, 0x6e, 0x2d, 0x69, 0x6c, 0x72, 0x2d, 0x65, 0x2d, 0x72, 0x6f, 0x65, 0x6e, 0x76, 0x6e, 0x40, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x6f, 0x72, 0x6c, 0x65, 0x74, 0x73, 0x72, 0x70, 0x77, 0x69, 0x69, 0x6d, 0x6c, 0x6d, 0x6e, 0x2d, 0x65, 0x65, 0x65, 0x74, 0x6c, 0x2d, 0x74, 0x6f, 0x2d, 0x74, 0x70, 0x72, 0x6e, 0x73, 0x72, 0x69, 0x72, 0x2e, 0x6d, 0x69, 0x65, 0x65, 0x32, 0x70, 0x6c, 0x6c, 0x65, 0x77, 0x2d, 0x72, 0x6f, 0x70, 0x76, 0x65, 0x2d, 0x72, 0x69, 0x6d, 0x72, 0x36, 0x40, 0x6d, 0x72, 0x6c, 0x6d, 0x77, 0x6c, 0x6e, 0x69, 0x72, 0x6d, 0x76, 0x73, 0x2e, 0x73, 0x72, 0x77, 0x73, 0x76, 0x2d, 0x73, 0x76, 0x6d, 0x76, 0x65, 0x69, 0x76, 0x63, 0x65, 0x72, 0x31, 0x72, 0x69, 0x76, 0x72, 0x65, 0x65, 0x2d, 0x73, 0x6d, 0x31, 0x72, 0x6e, 0x72, 0x2d, 0x2d, 0x36, 0x72, 0x73, 0x77, 0x2d, 0x77, 0x36, 0x76, 0x72, 0x6d, 0x65, 0x2d, 0x72, 0x70, 0x2d, 0x74, 0x32, 0x6c, 0x63, 0x6d, 0x6f, 0x6e, 0x2e, 0x2d, 0x69, 0x65, 0x73, 0x6d, 0x65, 0x73, 0x6e, 0x6d, 0x6c, 0x65, 0x6e, 0x72, 0x72, 0x72, 0x32, 0x70, 0x65, 0x73, 0x6c, 0x6d, 0x70, 0x6d, 0x72, 0x6f, 0x65, 0x6c, 0x76, 0x73, 0x63, 0x73, 0x65, 0x6c, 0x2d, 0x6e, 0x72, 0x65, 0x65, 0x72, 0x2d, 0x70, 0x6d, 0x69, 0x69, 0x65, 0x2d, 0x6c, 0x72, 0x69, 0x6c, 0x2d, 0x74, 0x65, 0x65, 0x69, 0x31, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x74, 0x73, 0x65, 0x32, 0x2d, 0x6f, 0x2d, 0x70, 0x72, 0x6f, 0x65, 0x69, 0x73, 0x32, 0x6d, 0x65, 0x2d, 0x65, 0x74, 0x6d, 0x6d, 0x73, 0x76, 0x6c, 0x69, 0x65, 0x2d, 0x73, 0x74, 0x65, 0x65, 0x72, 0x72, 0x74, 0x31, 0x2d, 0x76, 0x73, 0x2e, 0x2d, 0x2d, 0x72, 0x76, 0x77, 0x65, 0x72, 0x72, 0x40, 0x6e, 0x6c, 0x6d, 0x72, 0x74, 0x73, 0x72, 0x72, 0x65, 0x65, 0x2d, 0x6f, 0x74, 0x70, 0x63, 0xb8, 0xa1, 0x11, 0x6e, 0xd7, 0x74, 0x16, 0x7f, 0xb4, 0xba, 0x40, 0x93, 0x98, 0x00, 0x71, 0xcc, 0x42, 0xa7, 0x2f, 0x28, 0x69, 0xe7, 0x31, 0x48, 0x22, 0xa0, 0xe1, 0x45, 0xe3, 0xf7, 0x7f, 0x3a }; uint8_t c2[] = { 0x5b, 0x52, 0xf1, 0x2d, 0x94, 0xcb, 0xb0, 0x86, 0xd8, 0xd3, 0xe3, 0x20, 0x88, 0x47, 0xcf, 0x5a, 0x49, 0xd2, 0x11, 0x30, 0x92, 0x17, 0x8d, 0xf4, 0x99, 0xf7, 0x6c, 0x8a, 0xbc, 0xe7, 0x5c, 0x58, 0x6a, 0x65, 0xed, 0x81, 0xdc, 0xdd, 0xcf, 0x83, 0xcd, 0xa4, 0xed, 0xa2, 0x5e, 0x63, 0xd9, 0x98, 0xf6, 0x2e, 0x15, 0x76, 0x9a, 0xc8, 0x8c, 0x42, 0x54, 0x44, 0xf4, 0x47, 0xf5, 0x96, 0xc9, 0x6e, 0x23, 0x09, 0x1a, 0x0d, 0xe3, 0x04, 0xe6, 0xed, 0x48, 0x49, 0x62, 0x31, 0xe8, 0x36, 0x04, 0xed, 0xb9, 0xe7, 0xa6, 0x35, 0x4d, 0xcd, 0xe3, 0xfa, 0xa0, 0xc8, 0x34, 0xbd, 0x62, 0x7b, 0xbc, 0xbe, 0x1c, 0x5b, 0x69, 0x1f, 0x9c, 0x30, 0x20, 0x48, 0x52, 0xd1, 0xb6, 0x5e, 0xa2, 0x6e, 0x06, 0x94, 0x72, 0x10, 0x56, 0x7c, 0x94, 0xa5, 0xc0, 0xaa, 0xea, 0x48, 0x61, 0x03, 0x14, 0x94, 0x09, 0x77, 0xd9, 0xa7, 0xfe, 0x78, 0x17, 0x95, 0x4f, 0x7e, 0xb0, 0x32, 0x63, 0x02, 0x17, 0x47, 0x1e, 0x7d, 0xb2, 0x7d, 0xb5, 0xcb, 0x9f, 0x61, 0x65, 0xed, 0x03, 0xd2, 0xdb, 0xd1, 0xb3, 0xd6, 0x1a, 0xf5, 0x67, 0x0b, 0x8b, 0x6b, 0x44, 0xf2, 0x62, 0x42, 0xc2, 0x4d, 0xe1, 0x5c, 0xfe, 0xc6, 0x19, 0x2b, 0xfb, 0x03, 0x0f, 0x1b, 0x89, 0x08, 0x86, 0x40, 0xca, 0x45, 0x15, 0xda, 0x65, 0xcc, 0x73, 0x00, 0x49, 0x4e, 0x48, 0x21, 0x25, 0xc6, 0xde, 0x26, 0x21, 0x1d, 0xea, 0x3c, 0x11, 0xac, 0xef, 0x34, 0x4c, 0x96, 0xcc, 0x5e, 0x26, 0xf3, 0xcd, 0x70, 0x0d, 0x62, 0xea, 0x09, 0x35, 0x2b, 0x1e, 0x60, 0xe4, 0x76, 0xd3, 0x65, 0x01, 0x8c, 0xab, 0xd4, 0x89, 0xad, 0x81, 0x9d, 0x04, 0x01, 0xd5, 0x55, 0x3c, 0xcb, 0x32, 0xe1, 0xb5, 0xd4, 0xda, 0xb4, 0xa9, 0x01, 0xb2, 0x10, 0xc7, 0xb1, 0xa9, 0x54, 0x66, 0x1d, 0xcc, 0xff, 0x54, 0x0b, 0x84, 0x37, 0xe0, 0x3a, 0xa5, 0x68, 0x80, 0x87, 0xbc, 0x3c, 0x0f, 0xda, 0x7e, 0x3c, 0x23, 0xfc, 0xd8, 0xc5, 0x52, 0xf7, 0x22, 0x12, 0x05, 0x9c, 0x68, 0x39, 0xb1, 0xed, 0x26, 0x24, 0x2b, 0x7e, 0x0b, 0xaf, 0x9e, 0x97, 0x45, 0x7b, 0xa9, 0xbc, 0x48, 0x0e, 0x66, 0x93, 0x32, 0x0d, 0x6b, 0xd6, 0xf0, 0x4f, 0x54, 0x18, 0xcd, 0xc9, 0x8c, 0xce, 0xc4, 0xa2, 0xff, 0x1e, 0x69, 0x17, 0x7e, 0xf4, 0x99, 0x09, 0x68, 0xa1, 0x9e, 0x1f, 0xbf, 0x90, 0xdc, 0x77, 0x5d, 0x50, 0x2b, 0x0e, 0xff, 0x96, 0xdc, 0x21, 0x2e, 0x74, 0x22, 0x28, 0x88, 0xa0, 0x00, 0x32, 0x15, 0xb0, 0xfd, 0xb1, 0xc9, 0x75, 0xb3, 0x3c, 0xbd, 0x89, 0xc5, 0xa4, 0x48, 0x17, 0xa9, 0xc9, 0x50, 0x61, 0x0c, 0x35, 0x31, 0x55, 0x11, 0xe3, 0x23, 0xe9, 0x3e, 0x78, 0x25, 0xdc, 0x50, 0xe8, 0x23, 0x5f, 0xb7, 0x3f, 0xc7, 0xae, 0xf0, 0x82, 0x35, 0x46, 0x34, 0x63, 0xcc, 0x5d, 0x96, 0xb8, 0x6a, 0x7a, 0x7f, 0x54, 0x27, 0x1a, 0xa4, 0x63, 0xdd, 0xb0, 0xb6, 0x17, 0x08, 0xa1, 0x2e, 0x95, 0x9e, 0xd4, 0x9b, 0x71, 0x83, 0x81, 0x6c, 0xea, 0xab, 0x00, 0x2e, 0xca, 0x60, 0xc1, 0x4b, 0x83, 0xa7, 0xab, 0x47, 0xe8, 0x1b, 0x5a, 0x78, 0x4f, 0xec, 0xbd, 0x62, 0x94, 0x25, 0x75, 0x2e, 0x64, 0xe7, 0x70, 0x13, 0xac, 0xe9, 0x89, 0x4f, 0x1e, 0x79, 0xbc, 0x15, 0x0c, 0x8d, 0x40, 0xe8, 0x16, 0x31, 0x7c, 0xb8, 0xa5, 0xd7, 0x21, 0x39, 0x93, 0x9b, 0xe6, 0x05, 0x81, 0xb6, 0x20, 0xa8, 0x5d, 0x73, 0x58, 0x8b, 0x66, 0x92, 0xac, 0x23, 0xa0, 0xf4, 0x8c, 0xab, 0x58, 0xae, 0xb6, 0x9c, 0x3c, 0x4d, 0x77, 0x5f, 0xae, 0xe2, 0x57, 0x89, 0x8f, 0xe4, 0x68, 0x81, 0x24, 0x7d, 0x3b, 0x99, 0x46, 0x9f, 0x7b, 0x9d, 0xa6, 0xdd, 0x99, 0xcf, 0xc1, 0x79, 0x04, 0x95, 0xce, 0x96, 0x7a, 0xd9, 0xb5, 0x6e, 0xcf, 0xd1, 0x72, 0x18, 0x97, 0x76, 0xe2, 0xb7, 0x38, 0x1e, 0x24, 0x0b, 0x09, 0x00, 0x8b, 0x28, 0x5d, 0xf8, 0xd0, 0x50, 0x7f, 0xeb, 0x3b, 0x37, 0x61, 0x0b, 0xd3, 0xff, 0x65, 0x7d, 0x88, 0x1e, 0x1d, 0xbb, 0x6c, 0xf5, 0xf8, 0xf3, 0x2b, 0x51, 0xd9, 0x6d, 0xc9, 0xbe, 0xbe, 0xd1, 0x94, 0x0e, 0x58, 0x2a, 0x0a, 0xe4, 0xf8, 0x28, 0x26, 0xc3, 0x74, 0x87, 0xd3, 0x81, 0x48, 0x6e, 0x9b, 0xd5, 0xa1, 0x60, 0x87, 0xfc, 0x1b, 0x06, 0x33, 0x0d, 0x87, 0xfa, 0x9b, 0xf9, 0x73, 0x6b, 0x0c, 0xdf, 0xea, 0xee, 0x32, 0x78, 0xe0, 0xf8, 0x18, 0x3f, 0xc3, 0x3b, 0x12, 0x88, 0x0b, 0xb2, 0x4a, 0x52, 0x64, 0x4e, 0x58, 0x54, 0x82, 0x52, 0x61, 0x54, 0x28, 0x1b, 0xf7, 0x99, 0x06, 0xa2, 0xad, 0x04, 0x19, 0x9f, 0x2e, 0x34, 0xe6, 0xf0, 0xee, 0xeb, 0x93, 0x9a, 0x9c, 0x73, 0x86, 0x23, 0x6d, 0x5d, 0xae, 0x64, 0xec, 0x6f, 0xf9, 0x7c, 0xc7, 0x46, 0x96, 0xdb, 0x44, 0xf4, 0xab, 0xc9, 0x67, 0x61, 0xb8, 0xec, 0xf0, 0x99, 0xe0, 0x4d, 0x45, 0xed, 0xa3, 0x1c, 0xe9, 0x68, 0x31, 0x85, 0xa5, 0xa1, 0xba, 0x08, 0xdb, 0x3f, 0x84, 0x75, 0x70, 0x24, 0xcd, 0x49, 0xd4, 0x07, 0xa8, 0xaa, 0x52, 0xd9, 0x55, 0x68, 0x8f, 0x78, 0xd2, 0x5d, 0x46, 0x23, 0x60, 0x76, 0xe1, 0x22, 0xdc, 0x2a, 0xeb, 0xac, 0xbc, 0xeb, 0xd6, 0x4c, 0x0f, 0xb5, 0xcb, 0x47, 0xce, 0x43, 0x59, 0x1d, 0x3e, 0xfc, 0x7f, 0x7c, 0x93, 0x9e, 0xef, 0xcd, 0x79, 0x5c, 0x08, 0x8e, 0xeb, 0xa8, 0x98, 0x3e, 0x95, 0xd1, 0x36, 0x42, 0x57, 0xfd, 0x6d, 0xdc, 0xe0, 0xa3, 0x3f, 0x46, 0x32, 0xb7, 0xff, 0x00, 0x4f, 0x7b, 0x23, 0x4d, 0xd0, 0xe5, 0xdd, 0x40, 0xab, 0xb2, 0xcb, 0x45, 0x92, 0x76, 0x7c, 0x5b, 0x98, 0xc7, 0xc0, 0x54, 0x34, 0x94, 0x8e, 0xbb, 0x28, 0xcf, 0xba, 0xd9, 0xa0, 0xe6, 0xf3, 0x65, 0x61, 0xd7, 0x10, 0xd3, 0xeb, 0xce, 0x21, 0x6a, 0xca, 0x61, 0xe7, 0x81, 0x15, 0x18, 0x4e, 0x71, 0xb0, 0x99, 0x62, 0xd9, 0xeb, 0xd0, 0x8b, 0xe9, 0xdf, 0x6a, 0x6d, 0x59, 0x0b, 0x45, 0x93, 0x38, 0xfe, 0xe6, 0x6a, 0xd1, 0x5f, 0xb6, 0xe9, 0x86, 0x01, 0x38, 0xab, 0x59, 0x5c, 0xd7, 0xb7, 0xfa, 0x81, 0x8a, 0xbe, 0xdc, 0xeb, 0x50, 0x7d, 0x81, 0xfa, 0x1b, 0x8f, 0xce, 0x53, 0x38, 0xe4, 0x8a, 0x82, 0xbe, 0x7d, 0xdc, 0xd8, 0x57, 0x5a, 0x48, 0xa3, 0x38, 0x74, 0x8a, 0xac, 0xf2, 0xfd, 0xbf, 0xcc, 0xd8, 0x08, 0x4d, 0x3e, 0xae, 0xa9, 0x00, 0x66, 0x06, 0xcb, 0xf3, 0x50, 0xcc, 0x52, 0xc7, 0x4b, 0x16, 0x33, 0xa5, 0xde, 0x20, 0xed, 0x6a, 0xa7, 0x58, 0x5e, 0x4e, 0x7e, 0x29, 0xab, 0xb9, 0x65, 0x9d, 0x17, 0xe0, 0x1e, 0x79, 0x77, 0xf6, 0x1e, 0xa0, 0xcb, 0x0c, 0xf7, 0xc0, 0xe4, 0xf6, 0x3b, 0x60, 0x81, 0xfe, 0xed, 0xd9, 0x42, 0xa9, 0x61, 0x9d, 0xa8, 0xd7, 0xe8, 0xaa, 0x97, 0xad, 0xbb, 0xba, 0x13, 0x6e, 0x05, 0xa5, 0xce, 0x7a, 0x65, 0x6f, 0x55, 0xe3, 0xcf, 0xbc, 0x67, 0x14, 0x64, 0x57, 0x9c, 0x46, 0x14, 0xd6, 0x1d, 0x39, 0x1c, 0xd3, 0xe8, 0x98, 0x20, 0x5a, 0x1a, 0x05, 0x3b, 0x27, 0xd5, 0x84, 0xca, 0xd4, 0x0b, 0xc4, 0x1e, 0xd8, 0x46, 0x29, 0x48, 0x95, 0xdb, 0xe5, 0x58, 0x8a, 0x51, 0xc7, 0x74, 0x7f, 0x53, 0xa8, 0xbb, 0x58, 0xc0, 0x5b, 0xe1, 0xa7, 0x27, 0x36, 0x6c, 0xa6, 0x70, 0xec, 0x88, 0xcd, 0x9a, 0x70, 0xe1, 0xa0, 0xc7, 0xdd, 0x60, 0x71, 0xf4, 0x2a, 0x51, 0x98, 0x8e, 0xab, 0xb8, 0x13, 0x03, 0x48, 0x5f, 0x44, 0xf8, 0x88, 0xd9, 0x7d, 0xd3, 0xf1, 0x5f, 0xc4, 0x2b, 0x44, 0x15, 0x57, 0x31, 0xa4, 0xa1, 0xdb, 0x6d, 0x2a, 0x5a, 0x5a, 0xf7, 0xde, 0xd5, 0x23, 0x38, 0x00, 0xe5, 0x5c, 0x55, 0xe7, 0x37, 0x9c, 0xcb, 0x8b, 0xc0, 0x33, 0x42, 0x68, 0x23, 0x84, 0x7d, 0x89, 0x9d, 0xae, 0x59, 0x18, 0xae, 0xea, 0x46, 0x3f, 0xac, 0x57, 0x0d, 0x5d, 0x49, 0x14, 0x50, 0xe5, 0x70, 0x17, 0x73, 0x09, 0x11, 0x93, 0x6b, 0x02, 0x22, 0xb7, 0x63, 0xc9, 0xe6, 0xa4, 0xe3, 0xb1, 0xf7, 0xa6, 0x58, 0x8d, 0x14, 0xa1, 0xda, 0x6a, 0xb9, 0x38, 0xf9, 0x20, 0x45, 0x8c, 0xe6, 0x32, 0x23, 0x9d, 0x5f, 0xba, 0xcb, 0xb4, 0x95, 0xf9, 0xa9, 0x5c, 0x60, 0x03, 0x5a, 0x8c, 0xa7, 0xb9, 0x65, 0xa8, 0x84, 0x38, 0xc0, 0x25, 0xe6, 0xa7, 0xc0, 0x3b, 0xbc, 0x11, 0xed, 0x0e, 0x9a, 0x6f, 0xfe, 0x61, 0x79, 0x86, 0x92, 0x3a, 0xce, 0xe0, 0xb7, 0x70, 0xad, 0xe0, 0xcc, 0x88, 0x47, 0xd9, 0x2a, 0x3d, 0x41, 0x06, 0x77, 0x41, 0xbe, 0x3f, 0x55, 0x31, 0x54, 0x10, 0x14, 0x5b, 0xdf, 0x88, 0xb2, 0x9f, 0xff, 0x11, 0xb8, 0x11, 0xdc, 0x5e, 0x64, 0xf9, 0x97, 0x8a, 0x26, 0x6a, 0x44, 0xb4, 0x83, 0x83, 0x9b, 0x81, 0xaa, 0xfd, 0xb5, 0x8b, 0x16, 0x18, 0x2e, 0x5c, 0xe4, 0x5b, 0x8f, 0xdd, 0x7c, 0x1f, 0x33, 0x2f, 0xef, 0x57, 0x8c, 0x6a, 0x3f, 0x3c, 0x19, 0x5e, 0x73, 0x64, 0xc5, 0xaf, 0x1d, 0xa1, 0xb4, 0x11, 0xee, 0x6b, 0x7e, 0x66, 0xfb, 0xaa, 0x03, 0x17, 0xe4, 0xc9, 0x90, 0x4b, 0xf2, 0x50, 0x55, 0x71, 0xad, 0x31, 0x71, 0x49, 0xd7, 0x80, 0xd1, 0xa5, 0x9f, 0x6d, 0x71, 0x28, 0x2b, 0x65, 0xcf, 0x8d, 0xb1, 0x2a, 0x33, 0xdc, 0x93, 0xff, 0x86, 0xd7, 0xa6, 0xd0, 0x46, 0x66, 0x32, 0x3d, 0x18, 0x8c, 0xd3, 0xda, 0xf6, 0x1b, 0xa0, 0x2d, 0x29, 0xfd, 0x8d, 0x57, 0x2c, 0x82, 0xed, 0x38, 0x4a, 0x6f, 0xc4, 0x3c, 0x9a, 0x61, 0xcb, 0xe5, 0xcf, 0xd3, 0x83, 0xa1, 0x91, 0x93, 0x0d, 0x75, 0xfd, 0x4e, 0x2c, 0x83, 0xa0, 0x85, 0x27, 0x13, 0x5a, 0x24, 0xbd, 0x08, 0x1e, 0xe9, 0xab, 0x92, 0x41, 0xc2, 0x3a, 0xa0, 0xe1, 0xfd, 0x00, 0xb9, 0xf8, 0xca, 0x0b, 0x1a, 0x8e, 0xf6, 0x27, 0x9f, 0x5a, 0xf0, 0x23, 0x07, 0xc8, 0xbf, 0xf6, 0x74, 0xe7, 0xf8, 0x67, 0xfc, 0x28, 0x4e, 0x6a, 0x6c, 0xc6, 0x83, 0xe3, 0xf0, 0x01, 0xe0, 0x0f, 0x2d, 0xdf, 0x9e, 0x4b, 0x8b, 0x06, 0x15, 0x4c, 0x9f, 0xdf, 0x55, 0x14, 0x44, 0xde, 0x34, 0x35, 0x5a, 0xcb, 0xe5, 0xa7, 0xb5, 0x7e, 0x00, 0x31, 0x98, 0x5f, 0x51, 0x11, 0x37, 0xe1, 0xd2, 0x99, 0x8f, 0x70, 0x13, 0x40, 0xa0, 0xbe, 0xf8, 0xde, 0xac, 0x37, 0x06, 0xb6, 0x26, 0xf3, 0xb1, 0x97, 0x0b, 0x85, 0x68, 0x09, 0xa4, 0xc8, 0x34, 0x0a, 0x41, 0x6e, 0xac, 0x1a, 0x5b, 0xe0, 0x91, 0x6f, 0xa3, 0x0a, 0xf6, 0x05, 0x37, 0x32, 0xe1, 0x8e, 0xd8, 0xed, 0x55, 0xa3, 0x54, 0x3f, 0x62, 0x95, 0x82, 0xcf, 0x0a, 0x19, 0xb4, 0x9f, 0x04, 0xcc, 0x86, 0x7e, 0xf1, 0xe5, 0x8b, 0x67, 0x73, 0xa2, 0x46, 0x4e, 0xf2, 0x98, 0x94, 0xb5, 0xeb, 0xa5, 0xbd, 0xcb, 0x66, 0x82, 0xe9, 0x87, 0xe9, 0xe3, 0x50, 0x55, 0x4b, 0xd6, 0x67, 0x30, 0xe1, 0x7c, 0x15, 0x77, 0x29, 0xfd, 0x85, 0x67, 0x5a, 0xc4, 0xd5, 0x69, 0xfa, 0xc7, 0x66, 0x66, 0x49, 0xf7, 0x5a, 0xcd, 0xd1, 0x81, 0x5c, 0x74, 0x8d, 0xbf, 0xc5, 0xc2, 0xff, 0x4d, 0x90, 0xe8, 0x8e, 0x05, 0x00, 0xff, 0x7a, 0xd7, 0xb2, 0x7a, 0xad, 0x8b, 0xd6, 0x4b, 0x52, 0x09, 0x50, 0x4b }; SrsHandshakeBytes bytes; if (true) { ASSERT_EQ(ERROR_SUCCESS, bytes.create_c0c1()); memcpy(bytes.c0c1, c0c1, 1537); ASSERT_EQ(ERROR_SUCCESS, bytes.create_s0s1s2()); memcpy(bytes.s0s1s2, s0s1s2, 3073); ASSERT_EQ(ERROR_SUCCESS, bytes.create_c2()); memcpy(bytes.c2, c2, 1536); } SrsHandshakeBytes* hs_bytes = &bytes; if (true) { bool is_valid; c1s1 c1; ASSERT_EQ(ERROR_SUCCESS, c1.parse(hs_bytes->c0c1 + 1, 1536, srs_schema0)); ASSERT_EQ(ERROR_SUCCESS, c1.c1_validate_digest(is_valid)); ASSERT_TRUE(is_valid); c1s1 s1; ASSERT_EQ(ERROR_SUCCESS, s1.parse(hs_bytes->s0s1s2 + 1, 1536, c1.schema())); ASSERT_EQ(ERROR_SUCCESS, s1.s1_validate_digest(is_valid)); ASSERT_TRUE(is_valid); c2s2 c2; c2.parse(hs_bytes->c2, 1536); ASSERT_EQ(ERROR_SUCCESS, c2.c2_validate(&s1, is_valid)); ASSERT_TRUE(is_valid); c2s2 s2; s2.parse(hs_bytes->s0s1s2 + 1 + 1536, 1536); ASSERT_EQ(ERROR_SUCCESS, s2.s2_validate(&c1, is_valid)); ASSERT_TRUE(is_valid); } if (true) { MockBufferIO io; io.append(s0s1s2, 3073); SrsRtmpClient r(&io); HELPER_EXPECT_SUCCESS(r.handshake()); } if (true) { MockBufferIO io; io.append(s0s1s2, 3073); SrsRtmpClient r(&io); HELPER_EXPECT_SUCCESS(r.complex_handshake()); } if (true) { MockBufferIO io; io.append(c0c1, 1537); io.append(c2, 1536); SrsRtmpServer r(&io); HELPER_EXPECT_SUCCESS(r.handshake()); } } VOID TEST(ProtocolHandshakeTest, SimpleHandshake) { srs_error_t err; uint8_t c0c1[] = { 0x03, 0x01, 0x14, 0xf7, 0x4e, 0x80, 0x00, 0x07, 0x02, 0xac, 0x14, 0x98, 0x57, 0x0a, 0x07, 0x58, 0x44, 0x96, 0x47, 0xb5, 0x9a, 0x73, 0xf6, 0x07, 0x0f, 0x49, 0x0d, 0x72, 0xb8, 0x16, 0xbb, 0xb2, 0xb7, 0x61, 0x17, 0x79, 0xa0, 0xe9, 0x98, 0xca, 0xb2, 0x86, 0x64, 0x5f, 0x65, 0x3e, 0xfc, 0x4d, 0xc0, 0x0e, 0x4c, 0xfa, 0x91, 0xc7, 0x0f, 0x2e, 0x57, 0x31, 0x4b, 0x96, 0xef, 0xc9, 0x81, 0x02, 0x00, 0x54, 0x25, 0x2b, 0xb2, 0x0d, 0x7c, 0xee, 0xba, 0xdb, 0xe4, 0x06, 0x78, 0xcd, 0x70, 0x2c, 0x54, 0x5a, 0x3a, 0x03, 0x13, 0x2e, 0xe7, 0x4b, 0x87, 0x40, 0x77, 0x0b, 0x9f, 0xd2, 0xab, 0x32, 0x07, 0x6f, 0x1e, 0x75, 0x74, 0xe9, 0xc7, 0x44, 0xd9, 0x76, 0x53, 0xba, 0xe2, 0x52, 0xfa, 0xcc, 0xef, 0x34, 0xd5, 0x14, 0x61, 0xac, 0xcc, 0x63, 0xfd, 0x2b, 0x2d, 0xb3, 0xb8, 0xdd, 0x8a, 0x51, 0x9a, 0x2d, 0x0e, 0xfa, 0x84, 0x25, 0x55, 0xb2, 0xb7, 0x94, 0x54, 0x68, 0xfb, 0x94, 0xdf, 0xd8, 0xeb, 0x43, 0xd0, 0x11, 0x70, 0x8f, 0xf5, 0x48, 0xfc, 0x69, 0x4d, 0x5b, 0xc6, 0x53, 0x8a, 0x22, 0xea, 0x62, 0x84, 0x89, 0x6b, 0xfe, 0x4e, 0xab, 0x51, 0x98, 0xf4, 0x4f, 0xae, 0xf8, 0xdf, 0xac, 0x43, 0xed, 0x5a, 0x04, 0x97, 0xc4, 0xbe, 0x44, 0x5b, 0x99, 0x20, 0x68, 0x67, 0x0f, 0xe3, 0xfa, 0x4c, 0x9d, 0xe7, 0x0b, 0x3f, 0x80, 0x7c, 0x4c, 0x35, 0xf6, 0xdd, 0x20, 0x05, 0xfd, 0x0f, 0x39, 0xb7, 0x36, 0x45, 0x4c, 0xb7, 0x62, 0x92, 0x35, 0x2a, 0xcd, 0xb9, 0x49, 0xea, 0x12, 0x0b, 0x5f, 0x39, 0xae, 0x3b, 0x49, 0x29, 0xe6, 0x30, 0xc7, 0x7c, 0x77, 0xaf, 0x00, 0x43, 0x4d, 0x06, 0x45, 0x72, 0x73, 0x25, 0x71, 0x5e, 0x35, 0x04, 0xbd, 0xe9, 0x48, 0x23, 0x64, 0x4d, 0x15, 0x0b, 0xc5, 0x3f, 0x6e, 0x3a, 0xd5, 0xd5, 0xa6, 0xae, 0x3b, 0x4c, 0x66, 0x6a, 0x70, 0x8b, 0xf3, 0x6a, 0x43, 0xc4, 0xb9, 0xbd, 0xa0, 0x09, 0x72, 0xbc, 0xce, 0x7a, 0xea, 0x49, 0xf2, 0x86, 0xa7, 0xd8, 0x4a, 0x87, 0x28, 0xca, 0x2c, 0x53, 0xee, 0x96, 0x0b, 0xbe, 0x15, 0x14, 0xa8, 0x00, 0xca, 0x76, 0x08, 0x4d, 0x0f, 0xef, 0x78, 0x4b, 0xf6, 0x47, 0x60, 0xfc, 0x16, 0x00, 0x7c, 0x6b, 0x49, 0x39, 0x64, 0x36, 0xee, 0x45, 0x3a, 0x9a, 0xa5, 0xbf, 0xfb, 0x7b, 0xe7, 0xcf, 0x42, 0x82, 0x48, 0x1b, 0x30, 0xfe, 0x0d, 0xba, 0x10, 0xb8, 0xe1, 0x40, 0xcc, 0x6f, 0x36, 0x1c, 0x94, 0x5d, 0x50, 0x9e, 0x21, 0x08, 0xc9, 0xd5, 0xb0, 0x32, 0x51, 0x6a, 0x8f, 0xfa, 0x57, 0x8d, 0x45, 0xd7, 0xd2, 0xd0, 0xd6, 0x6c, 0x78, 0x95, 0xe9, 0xe1, 0x20, 0x97, 0x1a, 0x43, 0x40, 0xa3, 0xb5, 0xcc, 0x4b, 0x12, 0x84, 0x1e, 0x0e, 0xd3, 0x32, 0xca, 0x99, 0xc3, 0x2b, 0x78, 0x17, 0x24, 0x6b, 0xc7, 0xbc, 0x9d, 0x05, 0xc6, 0xaf, 0x8f, 0x19, 0x75, 0x3c, 0x08, 0xa6, 0x08, 0x26, 0x5b, 0xf4, 0x10, 0x40, 0xaa, 0x6a, 0x7e, 0xb9, 0xde, 0x0b, 0x23, 0x3f, 0x53, 0x5a, 0x20, 0x13, 0x62, 0xec, 0x53, 0x86, 0x81, 0x1f, 0xf6, 0x8e, 0xe3, 0xd1, 0xaa, 0xb5, 0x41, 0x87, 0x62, 0xd2, 0xb7, 0x09, 0x12, 0x71, 0x01, 0x2c, 0xac, 0x6d, 0x9d, 0x37, 0x46, 0x5b, 0xdc, 0x76, 0x2c, 0x96, 0x61, 0x88, 0x55, 0x5a, 0x20, 0xc2, 0x84, 0x95, 0xbd, 0x72, 0xc4, 0xb7, 0x22, 0xae, 0xeb, 0x49, 0x0e, 0x16, 0xf1, 0xf1, 0xbf, 0xc5, 0xc7, 0xa8, 0x8d, 0xfb, 0xe1, 0x08, 0x6c, 0xc4, 0x79, 0x81, 0x13, 0xe8, 0x39, 0xbf, 0x6e, 0x5c, 0xa1, 0x62, 0xfb, 0x32, 0x2a, 0x62, 0xf0, 0x12, 0x07, 0x31, 0x93, 0x40, 0xf3, 0xc0, 0xea, 0x1d, 0xd8, 0x65, 0xba, 0x12, 0xb3, 0x9b, 0xf5, 0x59, 0x9c, 0x4e, 0xf6, 0xb9, 0xf7, 0x85, 0xa1, 0xd9, 0x2f, 0x7c, 0x8b, 0xd0, 0xfc, 0x53, 0x3b, 0xed, 0x85, 0xa4, 0xd2, 0x5e, 0x69, 0x61, 0x02, 0x53, 0xb6, 0x19, 0xc7, 0x82, 0xea, 0x8a, 0x45, 0x01, 0x5d, 0x4b, 0xb3, 0x06, 0x86, 0x7f, 0x4b, 0x2f, 0xe7, 0xa8, 0xd0, 0x28, 0x62, 0x02, 0xe8, 0xf3, 0x9e, 0x1e, 0x72, 0x82, 0x07, 0x9f, 0xdd, 0xd2, 0x83, 0x7d, 0x89, 0x73, 0x1b, 0x6f, 0x35, 0x20, 0xb7, 0x88, 0x15, 0x92, 0xa7, 0x11, 0xfe, 0x81, 0x68, 0xed, 0x14, 0x07, 0xdf, 0x4a, 0x06, 0x9c, 0x5e, 0x7e, 0x34, 0x3a, 0x2a, 0x8a, 0xd3, 0xe8, 0xf8, 0xd4, 0xdb, 0xe3, 0xe9, 0x73, 0xbf, 0xa7, 0xe9, 0x73, 0x62, 0xf2, 0x9d, 0xc1, 0xf7, 0x51, 0xeb, 0xff, 0xb7, 0xe6, 0xd9, 0xac, 0x46, 0x06, 0x74, 0xe2, 0x25, 0x3f, 0x46, 0x43, 0xce, 0x49, 0x52, 0x25, 0x1b, 0xf9, 0x24, 0x5c, 0xda, 0xfd, 0x7f, 0xf6, 0xef, 0xb3, 0xd5, 0xe9, 0x6e, 0x35, 0xb8, 0xd1, 0x0e, 0x2c, 0xc1, 0x48, 0x5a, 0x27, 0x0a, 0x81, 0x01, 0x0f, 0xe4, 0x51, 0xcf, 0x89, 0x36, 0xd3, 0xe8, 0x5e, 0x05, 0xb9, 0x83, 0x42, 0xf3, 0xa5, 0x94, 0x67, 0x6d, 0x6a, 0x6e, 0xad, 0xf8, 0x90, 0xb1, 0x1d, 0x63, 0x18, 0x52, 0xc1, 0xbf, 0xbc, 0xad, 0xf4, 0xd2, 0xc5, 0xef, 0xca, 0x4c, 0xfe, 0xa1, 0xda, 0x15, 0x92, 0x4c, 0x42, 0x3d, 0xfc, 0x80, 0x7e, 0x49, 0x13, 0x4e, 0xf6, 0xe1, 0xee, 0x70, 0xca, 0xd9, 0x0a, 0xde, 0x9b, 0xea, 0xcd, 0xf9, 0x90, 0xfd, 0xae, 0x09, 0xce, 0xb6, 0xa0, 0xf7, 0xd1, 0xe6, 0x0c, 0x55, 0x1e, 0x3f, 0xbb, 0x1e, 0xff, 0x3d, 0xdb, 0xdd, 0x27, 0x80, 0x06, 0x53, 0x7e, 0x0b, 0x2a, 0x80, 0x24, 0x51, 0x5c, 0x6a, 0xab, 0x32, 0x5d, 0x37, 0x8a, 0xf4, 0xb7, 0x11, 0xa7, 0xc1, 0x9e, 0x05, 0x2c, 0x16, 0xc2, 0x08, 0xe2, 0xac, 0x1a, 0xeb, 0x60, 0xf8, 0xd2, 0xea, 0x39, 0x01, 0x1c, 0x64, 0xbd, 0x22, 0x80, 0x19, 0x20, 0xc9, 0x6f, 0xdd, 0x5c, 0x73, 0x8c, 0xa1, 0x53, 0x48, 0x2e, 0x99, 0x1d, 0xc0, 0x8f, 0x28, 0xf1, 0xe3, 0xc5, 0xc5, 0x65, 0x53, 0xf2, 0x44, 0x44, 0x24, 0xb9, 0xe2, 0x73, 0xe4, 0x76, 0x14, 0x56, 0xb8, 0x82, 0xe3, 0xb4, 0xfd, 0x68, 0x31, 0xed, 0x40, 0x10, 0x99, 0xd3, 0x3d, 0xe5, 0x6b, 0x14, 0x61, 0x66, 0x9a, 0xf6, 0x33, 0x98, 0xc5, 0x4d, 0x11, 0xbb, 0xf8, 0x56, 0xf8, 0x8f, 0xd7, 0xb9, 0xda, 0xa3, 0x56, 0x1a, 0xe0, 0x9e, 0xbe, 0x5f, 0x56, 0xe5, 0xb9, 0xd8, 0xf3, 0xbc, 0x19, 0xf5, 0xe9, 0x1f, 0xd2, 0xea, 0xf4, 0x5a, 0xde, 0xed, 0xd4, 0x9e, 0xc8, 0xf5, 0x54, 0x83, 0x8b, 0x8c, 0x2d, 0x24, 0x0e, 0x30, 0xb1, 0x84, 0xa2, 0xbe, 0x2c, 0x86, 0xe6, 0x42, 0x82, 0xaa, 0x37, 0x64, 0x55, 0x51, 0xbc, 0xde, 0xc0, 0x63, 0x88, 0xf6, 0x31, 0x71, 0x52, 0xd5, 0x34, 0x0f, 0x8e, 0xcb, 0x28, 0x65, 0x93, 0x1a, 0x66, 0x3b, 0x21, 0x00, 0xaa, 0x7a, 0xda, 0x2d, 0xf6, 0x7e, 0xb5, 0x27, 0x79, 0xf4, 0x50, 0x3b, 0x10, 0x6b, 0x3c, 0xd7, 0x99, 0x9d, 0xf6, 0xc5, 0x01, 0x91, 0xa0, 0xd5, 0x4f, 0xd3, 0x76, 0x54, 0xa8, 0x5c, 0x35, 0x1d, 0xe2, 0x35, 0x6a, 0x68, 0x67, 0x03, 0xc4, 0x1f, 0xe9, 0x60, 0xb8, 0x49, 0xb1, 0x9a, 0x40, 0xd9, 0x3c, 0x4c, 0x73, 0xaa, 0x88, 0x63, 0xaf, 0xfe, 0xe8, 0xa8, 0x0c, 0x96, 0xbe, 0xb4, 0x65, 0x7c, 0x27, 0xfb, 0xc1, 0x27, 0x24, 0x58, 0xab, 0x4b, 0xa0, 0x5a, 0x7d, 0xc7, 0xca, 0x2d, 0xa5, 0x22, 0xa7, 0xed, 0x26, 0x87, 0xd5, 0x44, 0x1a, 0xc7, 0xdd, 0xfb, 0x60, 0xfc, 0xe5, 0x50, 0xd9, 0x8d, 0xa7, 0xdb, 0x78, 0xb6, 0x9d, 0x80, 0x0f, 0xb9, 0x5f, 0xa7, 0x53, 0x92, 0x5d, 0x18, 0xce, 0x89, 0xc2, 0x69, 0xee, 0xcf, 0xb6, 0x66, 0xe5, 0x66, 0xd2, 0xe3, 0x35, 0x74, 0x0b, 0x83, 0xb6, 0xde, 0xf1, 0xfb, 0xb4, 0x1d, 0x4b, 0x94, 0x95, 0x06, 0x82, 0xe7, 0x1c, 0xf8, 0xc5, 0xe6, 0xd0, 0xf2, 0x17, 0x37, 0x44, 0xfe, 0x99, 0x43, 0x82, 0xbb, 0x88, 0xe4, 0x43, 0x67, 0xcc, 0x4d, 0x5f, 0xa6, 0x26, 0xd7, 0x53, 0xd6, 0x45, 0x96, 0x2b, 0x63, 0xd1, 0x2a, 0xa1, 0x2c, 0x41, 0x59, 0x8b, 0xb8, 0xc1, 0x89, 0x03, 0x3a, 0x61, 0x13, 0xc4, 0x2c, 0x37, 0xa5, 0xbf, 0xd7, 0xdb, 0xd8, 0x53, 0x5f, 0xa1, 0xdb, 0xdb, 0xa5, 0x73, 0xb6, 0xf7, 0x74, 0xa0, 0xf8, 0x93, 0xf5, 0x61, 0xee, 0x3c, 0xe7, 0x00, 0x01, 0x98, 0xe0, 0xa1, 0x22, 0xb6, 0x9a, 0x83, 0x44, 0xa1, 0xe6, 0x70, 0x56, 0x65, 0x92, 0x1e, 0xf0, 0xbc, 0x73, 0xa5, 0x7a, 0xc1, 0x1a, 0x02, 0xf9, 0xd4, 0xc4, 0x7c, 0x81, 0xda, 0x15, 0xc0, 0xd4, 0x25, 0xdc, 0x17, 0xa6, 0x0d, 0x90, 0x55, 0xf2, 0x10, 0xf8, 0xa7, 0x71, 0x9b, 0xed, 0xdf, 0xdf, 0xa1, 0xe4, 0xb9, 0x12, 0x6b, 0x05, 0x3e, 0x83, 0x99, 0x49, 0xbf, 0x66, 0xbb, 0xf6, 0x76, 0xd3, 0xa9, 0x24, 0x61, 0x8c, 0x25, 0x49, 0xd0, 0xf7, 0x83, 0x44, 0xfb, 0x27, 0xe2, 0x7d, 0x69, 0x6d, 0x34, 0x67, 0xed, 0x39, 0x89, 0x02, 0xcb, 0x2f, 0x33, 0x3c, 0xcd, 0x12, 0x42, 0x8f, 0x86, 0x7d, 0xda, 0x3f, 0xd7, 0x26, 0x62, 0x9c, 0x1f, 0x2e, 0xa8, 0xc3, 0x85, 0xf1, 0x73, 0xe5, 0x2c, 0x11, 0xde, 0x98, 0xc8, 0xb0, 0x10, 0x17, 0x55, 0xf5, 0x32, 0x52, 0x67, 0xca, 0x64, 0x50, 0x28, 0x9a, 0x24, 0x92, 0xa1, 0x97, 0x57, 0x81, 0xaf, 0xca, 0x1e, 0xc0, 0xa4, 0x71, 0x2d, 0x2a, 0xec, 0xc9, 0x23, 0x6a, 0x0c, 0x1d, 0x54, 0x15, 0x2a, 0x56, 0x42, 0x0a, 0x83, 0xff, 0x28, 0xba, 0xe7, 0x68, 0x38, 0xf5, 0x32, 0xa9, 0xb7, 0xe7, 0x70, 0x32, 0xa8, 0x79, 0x5e, 0x46, 0x1d, 0xec, 0x29, 0x8a, 0xde, 0x41, 0x94, 0x94, 0x26, 0x79, 0xc2, 0x52, 0x23, 0xe0, 0xa1, 0x1d, 0x65, 0x0c, 0xbe, 0x1b, 0x87, 0x2a, 0x21, 0x53, 0x2f, 0x35, 0x56, 0xe8, 0xd1, 0x7b, 0xb8, 0x23, 0x75, 0x56, 0xc7, 0x08, 0x9d, 0x13, 0xf0, 0x8f, 0x80, 0x38, 0xe9, 0x92, 0xf7, 0x16, 0xc2, 0xf3, 0x74, 0xa7, 0x92, 0xf5, 0x49, 0x7d, 0x09, 0x41, 0xbc, 0x07, 0x61, 0x1f, 0xe6, 0xa0, 0xd8, 0xa6, 0xe3, 0x72, 0xa4, 0x59, 0x4a, 0xd9, 0x33, 0x40, 0x80, 0x3a, 0x3a, 0xb3, 0xa0, 0x96, 0xca, 0x56, 0x98, 0xbd, 0x1f, 0x80, 0x86, 0x6c, 0xe1, 0x09, 0x64, 0x1b, 0x1a, 0xc9, 0x52, 0xaa, 0xd1, 0x39, 0xea, 0x4b, 0x6a, 0x3e, 0x4e, 0xa4, 0xea, 0x00, 0xde, 0x07, 0x0b, 0x23, 0xbc, 0x40, 0xc4, 0xd2, 0xd9, 0xf6, 0xda, 0x8e, 0x22, 0x36, 0xbe, 0x5e, 0x65, 0x6e, 0xbe, 0xc8, 0xb0, 0x07, 0xa2, 0x2d, 0xe9, 0x4b, 0x73, 0x54, 0xe6, 0x0a, 0xf2, 0xd3, 0x83, 0x8b, 0x27, 0x4c, 0xcc, 0x0c, 0x8a, 0xd4, 0x2b, 0xb8, 0x95, 0x2e, 0x42, 0x64, 0x29, 0xc1, 0xe0, 0x6b, 0x92, 0xab, 0xfe, 0x53, 0x06, 0x96, 0x4a, 0x8c, 0x5d, 0x7c, 0x51, 0x74, 0xd0, 0x1e, 0x37, 0x35, 0x9c, 0x1e, 0x69, 0x8f, 0x68, 0x18, 0xd9, 0xbe, 0xaf, 0x81, 0x9b, 0x7e, 0xd8, 0x71, 0x9d, 0xb6, 0x50, 0x43, 0x78, 0x85, 0x7d, 0x65, 0x93, 0x45, 0xb4, 0x02, 0xd0, 0x5c, 0x36, 0xe2, 0x62, 0x3f, 0x40, 0x33, 0xee, 0x91, 0xe5, 0x3f, 0x67, 0x39, 0x2f, 0x1b, 0x89, 0x9f, 0x04, 0x9d, 0x46, 0x3e, 0x70, 0x92, 0x9e, 0x8c, 0xf5 }; uint8_t s0s1s2[] = { 0x03, 0xac, 0x44, 0x29, 0x53, 0x04, 0x05, 0x00, 0x01, 0x6e, 0x65, 0x69, 0x2d, 0x69, 0x2d, 0x69, 0x73, 0x6e, 0x69, 0x73, 0x6c, 0x65, 0x72, 0x69, 0x72, 0x76, 0x65, 0x72, 0x69, 0x77, 0x74, 0x2e, 0x6e, 0x72, 0x76, 0x72, 0x65, 0x72, 0x70, 0x72, 0x69, 0x69, 0x70, 0x72, 0x73, 0x6e, 0x65, 0x72, 0x72, 0x6e, 0x2d, 0x65, 0x74, 0x72, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x40, 0x69, 0x69, 0x76, 0x77, 0x2d, 0x73, 0x65, 0x72, 0x72, 0x76, 0x73, 0x72, 0x2e, 0x2d, 0x76, 0x65, 0x31, 0x65, 0x6d, 0x6d, 0x73, 0x69, 0x73, 0x74, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x72, 0x65, 0x2d, 0x74, 0x69, 0x31, 0x65, 0x2d, 0x6f, 0x77, 0x2e, 0x76, 0x77, 0x2d, 0x77, 0x72, 0x65, 0x65, 0x31, 0x74, 0x73, 0x70, 0x74, 0x6e, 0x72, 0x6e, 0x73, 0x6d, 0x2e, 0x69, 0x72, 0x2d, 0x65, 0x69, 0x77, 0x69, 0x76, 0x72, 0x77, 0x72, 0x32, 0x6e, 0x65, 0x6c, 0x2e, 0x2d, 0x6e, 0x69, 0x6d, 0x6c, 0x73, 0x65, 0x73, 0x70, 0x2d, 0x65, 0x72, 0x40, 0x72, 0x74, 0x6e, 0x6e, 0x6d, 0x6f, 0x70, 0x74, 0x73, 0x2d, 0x63, 0x69, 0x32, 0x31, 0x2d, 0x40, 0x69, 0x70, 0x2d, 0x2d, 0x72, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x69, 0x65, 0x6e, 0x32, 0x6f, 0x6c, 0x6e, 0x72, 0x73, 0x77, 0x65, 0x65, 0x72, 0x32, 0x6d, 0x65, 0x6c, 0x2d, 0x72, 0x6e, 0x65, 0x6d, 0x31, 0x65, 0x74, 0x2d, 0x6f, 0x72, 0x65, 0x63, 0x69, 0x40, 0x70, 0x2d, 0x65, 0x6d, 0x2d, 0x77, 0x63, 0x63, 0x74, 0x40, 0x36, 0x2d, 0x72, 0x65, 0x70, 0x2d, 0x6e, 0x69, 0x6d, 0x65, 0x74, 0x70, 0x76, 0x40, 0x76, 0x72, 0x72, 0x69, 0x77, 0x76, 0x69, 0x74, 0x74, 0x65, 0x31, 0x6d, 0x2e, 0x6f, 0x72, 0x73, 0x73, 0x6c, 0x40, 0x36, 0x72, 0x70, 0x72, 0x70, 0x72, 0x69, 0x32, 0x6c, 0x77, 0x70, 0x76, 0x65, 0x72, 0x76, 0x63, 0x65, 0x65, 0x77, 0x72, 0x6e, 0x2e, 0x76, 0x69, 0x69, 0x2e, 0x40, 0x72, 0x2e, 0x2e, 0x72, 0x73, 0x6e, 0x72, 0x72, 0x6e, 0x70, 0x40, 0x77, 0x65, 0x77, 0x65, 0x70, 0x63, 0x74, 0x2d, 0x70, 0x72, 0x2d, 0x74, 0x72, 0x31, 0x65, 0x6e, 0x2d, 0x76, 0x2d, 0x2d, 0x2d, 0x74, 0x76, 0x2d, 0x74, 0x65, 0x2e, 0x2d, 0x6c, 0x76, 0x2d, 0x6c, 0x70, 0x73, 0x6d, 0x65, 0x72, 0x31, 0x31, 0x36, 0x76, 0x73, 0x73, 0x6e, 0x2d, 0x6e, 0x73, 0x72, 0x2d, 0x6f, 0x6c, 0x65, 0x74, 0x77, 0x65, 0x69, 0x72, 0x69, 0x65, 0x6d, 0x76, 0x31, 0x65, 0x73, 0x72, 0x6c, 0x72, 0x77, 0x65, 0x76, 0x74, 0x72, 0x69, 0x72, 0x76, 0x32, 0x73, 0x6d, 0x72, 0x2d, 0x6d, 0x40, 0x69, 0x40, 0x69, 0x31, 0x69, 0x6f, 0x6e, 0x6d, 0x69, 0x73, 0x70, 0x72, 0x77, 0x6f, 0x6f, 0x65, 0x77, 0x76, 0x70, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x32, 0x36, 0x6c, 0x74, 0x6e, 0x72, 0x74, 0x2d, 0x6e, 0x6c, 0x72, 0x72, 0x2d, 0x74, 0x65, 0x73, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x65, 0x2d, 0x6e, 0x70, 0x6e, 0x40, 0x65, 0x6e, 0x6e, 0x74, 0x65, 0x6e, 0x72, 0x6e, 0xfe, 0x5a, 0x38, 0x79, 0x81, 0xe8, 0x49, 0xee, 0x93, 0xbb, 0xa0, 0x59, 0x4a, 0xa0, 0xcc, 0x31, 0xbf, 0x0d, 0x86, 0xc0, 0x3f, 0xae, 0x2a, 0x16, 0xfa, 0xf0, 0x4e, 0x0f, 0xa3, 0x01, 0x06, 0xa0, 0x0e, 0xa5, 0x8c, 0xa4, 0xca, 0xd2, 0x01, 0xa5, 0x90, 0xbd, 0x55, 0xd1, 0x42, 0x2b, 0xd4, 0xb3, 0xbb, 0x06, 0xb1, 0x3a, 0x94, 0x41, 0x76, 0x1d, 0xa5, 0x23, 0x6e, 0x1e, 0x59, 0x73, 0x63, 0x34, 0x60, 0xd3, 0x48, 0xc0, 0x3b, 0xcf, 0xf1, 0xa8, 0x38, 0xd6, 0xf3, 0x5e, 0x6d, 0xcb, 0xea, 0xfc, 0x9c, 0x52, 0xae, 0x9a, 0x89, 0xdb, 0x24, 0x1b, 0x92, 0x4a, 0x85, 0x97, 0x3c, 0xd8, 0x4c, 0x31, 0xad, 0xfd, 0x00, 0xef, 0xc5, 0x17, 0xa5, 0x22, 0xc0, 0xf1, 0x94, 0x18, 0xec, 0xf6, 0x49, 0xe5, 0x05, 0x11, 0x12, 0x67, 0x6c, 0x71, 0xc0, 0x84, 0x6d, 0x50, 0xf8, 0x23, 0x01, 0x57, 0xc4, 0xfc, 0x73, 0x65, 0x69, 0x6e, 0x65, 0x72, 0x6d, 0x6f, 0x69, 0x2d, 0x65, 0x65, 0x69, 0x63, 0x63, 0x69, 0x2d, 0x72, 0x2d, 0x69, 0x2d, 0x2d, 0x77, 0x72, 0x76, 0x72, 0x72, 0x2d, 0x76, 0x70, 0x63, 0x69, 0x74, 0x73, 0x6d, 0x65, 0x6c, 0x2d, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x77, 0x69, 0x63, 0x69, 0x70, 0x31, 0x40, 0x72, 0x69, 0x2d, 0x2d, 0x2d, 0x72, 0x72, 0x6c, 0x72, 0x63, 0x72, 0x77, 0x6e, 0x6c, 0x2d, 0x72, 0x2e, 0x76, 0x72, 0x65, 0x6d, 0x76, 0x36, 0x6d, 0x72, 0x77, 0x72, 0x65, 0x65, 0x69, 0x72, 0x76, 0x6d, 0x76, 0x74, 0x76, 0x72, 0x65, 0x69, 0x72, 0x6e, 0x6d, 0x77, 0x6c, 0x40, 0x32, 0x70, 0x65, 0x65, 0x69, 0x72, 0x31, 0x2e, 0x70, 0x36, 0x31, 0x65, 0x70, 0x72, 0x72, 0x73, 0x72, 0x6e, 0x6e, 0x73, 0x32, 0x2d, 0x2d, 0x2d, 0x69, 0x65, 0x31, 0x74, 0x6e, 0x65, 0x74, 0x65, 0x76, 0x69, 0x6d, 0x6c, 0x6e, 0x70, 0x74, 0x73, 0x72, 0x6d, 0x72, 0x72, 0x69, 0x65, 0x74, 0x65, 0x65, 0x2d, 0x70, 0x74, 0x6e, 0x74, 0x65, 0x6f, 0x72, 0x69, 0x76, 0x40, 0x31, 0x69, 0x72, 0x6d, 0x6d, 0x77, 0x69, 0x72, 0x65, 0x6e, 0x40, 0x63, 0x40, 0x65, 0x65, 0x69, 0x2d, 0x72, 0x65, 0x40, 0x69, 0x32, 0x74, 0x73, 0x6e, 0x36, 0x2d, 0x70, 0x65, 0x6c, 0x70, 0x6e, 0x72, 0x69, 0x32, 0x65, 0x74, 0x76, 0x77, 0x73, 0x6f, 0x77, 0x65, 0x72, 0x2d, 0x6e, 0x73, 0x65, 0x65, 0x70, 0x65, 0x2d, 0x65, 0x73, 0x2d, 0x65, 0x2e, 0x73, 0x69, 0x67, 0x45, 0x8b, 0x6b, 0x3b, 0xc9, 0x5f, 0x09, 0x65, 0x65, 0x72, 0x6c, 0x73, 0x6d, 0x70, 0x70, 0x73, 0x63, 0x70, 0x40, 0x72, 0x76, 0x65, 0x6e, 0x6f, 0x6c, 0x69, 0x2e, 0x72, 0x73, 0x76, 0x69, 0x77, 0x72, 0x2d, 0x69, 0x6e, 0x69, 0x65, 0x77, 0x73, 0x69, 0x70, 0x77, 0x63, 0x65, 0x74, 0x72, 0x73, 0x31, 0x65, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x6d, 0x65, 0x36, 0x6e, 0x6e, 0x69, 0x6d, 0x6e, 0x70, 0x77, 0x72, 0x65, 0x31, 0x65, 0x6e, 0x6e, 0x65, 0x2d, 0x65, 0x65, 0x2e, 0x77, 0x6e, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x6c, 0x31, 0x76, 0x65, 0x72, 0x2d, 0x36, 0x6c, 0x70, 0x6f, 0x65, 0x72, 0x73, 0x63, 0x72, 0x77, 0x73, 0x72, 0x65, 0x65, 0x65, 0x6c, 0x76, 0x72, 0x65, 0x6e, 0x65, 0x2e, 0x6f, 0x2d, 0x72, 0x70, 0x65, 0x74, 0x72, 0x77, 0x69, 0x69, 0x72, 0x65, 0x77, 0x6c, 0x72, 0x2d, 0x69, 0x72, 0x31, 0x6e, 0x65, 0x70, 0x72, 0x74, 0x76, 0x6c, 0x2e, 0x72, 0x65, 0x72, 0x6c, 0x73, 0x6c, 0x2e, 0x2e, 0x72, 0x2d, 0x6e, 0x63, 0x32, 0x2e, 0x65, 0x2d, 0x65, 0x69, 0x2d, 0x65, 0x70, 0x6e, 0x72, 0x72, 0x32, 0x2e, 0x73, 0x70, 0x77, 0x65, 0x73, 0x77, 0x73, 0x40, 0x40, 0x73, 0x63, 0x2e, 0x65, 0x76, 0x70, 0x65, 0x69, 0x65, 0x70, 0x73, 0x40, 0x65, 0x73, 0x2d, 0x2d, 0x2e, 0x2e, 0x73, 0x65, 0x6f, 0x65, 0x65, 0x6d, 0x76, 0x70, 0x6d, 0x69, 0x70, 0x70, 0x69, 0x2e, 0x76, 0x6e, 0x72, 0x72, 0x72, 0x6d, 0x73, 0x6f, 0x73, 0x72, 0x72, 0x72, 0x77, 0x70, 0x65, 0x69, 0x72, 0x73, 0x6e, 0x69, 0x65, 0x65, 0x74, 0x65, 0x69, 0x40, 0x63, 0x69, 0x70, 0x6c, 0x6e, 0x2d, 0x65, 0x69, 0x72, 0x63, 0x6c, 0x72, 0x2e, 0x36, 0x69, 0x72, 0x6c, 0x6c, 0x2d, 0x6f, 0x76, 0x69, 0x6f, 0x2d, 0x6d, 0x6c, 0x72, 0x72, 0x2e, 0x70, 0x73, 0x6d, 0x6f, 0x2e, 0x6e, 0x69, 0x65, 0x65, 0x2d, 0x6d, 0x76, 0x6e, 0x69, 0x73, 0x73, 0x73, 0x74, 0x63, 0x65, 0x76, 0x2e, 0x77, 0x2d, 0x36, 0x73, 0x69, 0x2d, 0x72, 0x72, 0x6c, 0x36, 0x74, 0x72, 0x6d, 0x65, 0x2d, 0x65, 0x2e, 0x6d, 0x31, 0x72, 0x6f, 0x74, 0x76, 0x31, 0x65, 0x6d, 0x69, 0x72, 0x69, 0x69, 0x2d, 0x72, 0x73, 0x72, 0x72, 0x76, 0x31, 0x6e, 0x2d, 0x69, 0x6e, 0x77, 0x70, 0x69, 0x72, 0x6e, 0x76, 0x74, 0x6f, 0x65, 0x63, 0x6f, 0x73, 0x65, 0x73, 0x72, 0x69, 0x69, 0x40, 0x6e, 0x65, 0x65, 0x65, 0x65, 0x77, 0x70, 0x70, 0x6e, 0x72, 0x6e, 0x65, 0x72, 0x32, 0x65, 0x2d, 0x77, 0x69, 0x6e, 0x70, 0x69, 0x6f, 0x76, 0x77, 0x72, 0x74, 0x77, 0x6e, 0x72, 0xfe, 0x98, 0xf3, 0xb4, 0xff, 0x3f, 0x2e, 0xdb, 0x59, 0xbd, 0x32, 0x02, 0x6a, 0x44, 0x03, 0x67, 0x9e, 0xe1, 0x98, 0x97, 0xed, 0x67, 0x6d, 0xb0, 0x8f, 0xa9, 0xb6, 0xf8, 0x4d, 0x92, 0x35, 0x19, 0x72, 0x72, 0x65, 0x74, 0x73, 0x6e, 0x65, 0x65, 0x69, 0x36, 0x72, 0x73, 0x2d, 0x70, 0x2d, 0x2d, 0x69, 0x6e, 0x72, 0x65, 0x32, 0x72, 0x77, 0x72, 0x73, 0x77, 0x73, 0x70, 0x2d, 0x2d, 0x69, 0x6c, 0x70, 0x74, 0x65, 0x69, 0x72, 0x74, 0x6e, 0x76, 0x65, 0x76, 0x76, 0x69, 0x69, 0x65, 0x70, 0x6e, 0x73, 0x6e, 0x36, 0x76, 0x70, 0x76, 0x6c, 0x6c, 0x70, 0x6e, 0x6e, 0x74, 0x2e, 0x6f, 0x32, 0x74, 0x76, 0x74, 0x40, 0x72, 0x6e, 0x72, 0x74, 0x74, 0x2d, 0x6f, 0x72, 0x73, 0x32, 0x72, 0x32, 0x72, 0x70, 0x65, 0x65, 0x6e, 0x72, 0x70, 0x73, 0x72, 0x69, 0x74, 0x74, 0x6e, 0x72, 0x6c, 0x31, 0x74, 0x77, 0x31, 0x63, 0x63, 0x74, 0x69, 0x72, 0x69, 0x72, 0x70, 0x31, 0x74, 0x72, 0x76, 0x65, 0x72, 0x65, 0x6c, 0x76, 0x6d, 0x72, 0x6c, 0x69, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x69, 0x6c, 0x74, 0x6e, 0x65, 0x69, 0x77, 0x73, 0x70, 0x69, 0x72, 0x2d, 0x65, 0x74, 0x2e, 0x65, 0x65, 0x6d, 0x72, 0x31, 0x2d, 0x72, 0x36, 0x65, 0x2d, 0x69, 0x6d, 0x36, 0x6e, 0x72, 0x6d, 0x6c, 0x72, 0x72, 0x65, 0x65, 0x6e, 0x31, 0x6e, 0x40, 0x72, 0x40, 0x6f, 0x73, 0x6d, 0x36, 0x2e, 0x72, 0x65, 0x36, 0x74, 0x77, 0x65, 0x65, 0x73, 0x36, 0x76, 0x6c, 0x6f, 0x2d, 0x36, 0x6d, 0x36, 0x70, 0x32, 0x74, 0x6d, 0x65, 0x6d, 0x69, 0x65, 0x65, 0x69, 0x76, 0x69, 0x74, 0x2d, 0x63, 0x2d, 0x6e, 0x32, 0x72, 0x63, 0x2d, 0x77, 0x72, 0x74, 0x72, 0x70, 0x6e, 0x76, 0x6f, 0x72, 0x40, 0x65, 0x65, 0x6d, 0x77, 0x2d, 0x2d, 0x74, 0x6e, 0x73, 0x76, 0x65, 0x69, 0x69, 0x72, 0x6f, 0x65, 0x70, 0x69, 0x6d, 0x76, 0x69, 0x65, 0x72, 0x2d, 0x74, 0x2d, 0x69, 0x65, 0x72, 0x69, 0x6f, 0x72, 0x72, 0x69, 0x76, 0x72, 0x77, 0x69, 0x2e, 0x77, 0x69, 0x70, 0x69, 0x6d, 0x36, 0x72, 0x76, 0x65, 0x76, 0x73, 0x6e, 0x72, 0x65, 0x2e, 0x76, 0x2d, 0x76, 0x6f, 0x2d, 0x65, 0x73, 0x72, 0x74, 0x36, 0x2d, 0x6f, 0x70, 0x73, 0x74, 0x74, 0x77, 0x6c, 0x2d, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x72, 0x32, 0x2d, 0x72, 0x69, 0x6d, 0x6e, 0x72, 0x6c, 0x6f, 0x65, 0x36, 0x31, 0x65, 0x65, 0x69, 0x73, 0x31, 0x74, 0x69, 0x69, 0x65, 0x40, 0x69, 0x6e, 0x2d, 0x63, 0x40, 0x31, 0x70, 0x65, 0x6e, 0x2d, 0x69, 0x72, 0x65, 0x65, 0x76, 0x65, 0x70, 0x72, 0x6c, 0x2d, 0x6e, 0x73, 0x69, 0x65, 0x65, 0x6e, 0x2e, 0x63, 0x6c, 0x72, 0x65, 0x2d, 0x2e, 0x6d, 0x72, 0x76, 0x70, 0x69, 0x6d, 0x40, 0x32, 0x77, 0x72, 0x6e, 0x72, 0x6c, 0x36, 0x72, 0x31, 0x2d, 0x73, 0x74, 0x2d, 0x69, 0x63, 0x40, 0x70, 0x32, 0x65, 0x31, 0x69, 0x69, 0x65, 0x72, 0x63, 0x74, 0x72, 0x74, 0x77, 0x6e, 0x69, 0x72, 0x65, 0x76, 0x65, 0x77, 0x69, 0x69, 0x73, 0x6e, 0x77, 0x77, 0x73, 0x6f, 0x69, 0x70, 0x73, 0x2d, 0x65, 0x65, 0x73, 0x65, 0x77, 0x2d, 0x73, 0x72, 0x6d, 0x65, 0x32, 0x6e, 0x73, 0x36, 0x65, 0x72, 0x77, 0x70, 0x65, 0x69, 0x2d, 0x2d, 0x74, 0x6f, 0x6f, 0x36, 0x63, 0x74, 0x72, 0x63, 0x77, 0x69, 0x2e, 0x31, 0x6c, 0x65, 0x77, 0x72, 0x65, 0x76, 0x74, 0x2d, 0x77, 0x2e, 0x76, 0x72, 0x6e, 0x36, 0x70, 0x69, 0x2e, 0x6e, 0x72, 0x77, 0x69, 0x65, 0x74, 0x2d, 0x6e, 0x63, 0x6e, 0x70, 0x2d, 0x6e, 0x2e, 0x6d, 0x69, 0x65, 0x63, 0x65, 0x2d, 0x76, 0x70, 0x73, 0x31, 0x73, 0x2d, 0x76, 0x6e, 0x6e, 0x6c, 0x2d, 0x6c, 0x2d, 0x65, 0x6e, 0x73, 0x6c, 0x65, 0x74, 0x70, 0x65, 0x2d, 0x6e, 0x77, 0x76, 0x40, 0x69, 0x40, 0x63, 0x6f, 0x72, 0x32, 0x6d, 0x31, 0x72, 0x36, 0x69, 0x73, 0x72, 0x70, 0x65, 0x2d, 0x6c, 0x2e, 0x72, 0x74, 0x74, 0x65, 0x69, 0x6f, 0x69, 0x2d, 0x2d, 0x65, 0x6f, 0x65, 0x74, 0x72, 0x69, 0x76, 0x72, 0x72, 0x65, 0x69, 0x76, 0x69, 0x69, 0x6e, 0x31, 0x65, 0x76, 0x72, 0x73, 0x77, 0x72, 0x2d, 0x69, 0x65, 0x69, 0x70, 0x65, 0x6e, 0x6e, 0x65, 0x65, 0x6e, 0x2d, 0x72, 0x76, 0x72, 0x6c, 0x2e, 0x70, 0x76, 0x6e, 0x69, 0x72, 0x70, 0x73, 0x2d, 0x69, 0x74, 0x76, 0x72, 0x70, 0x65, 0x63, 0x72, 0x70, 0x6e, 0x36, 0x6c, 0x74, 0x72, 0x72, 0x72, 0x73, 0x65, 0x40, 0x63, 0x6d, 0x63, 0x32, 0x65, 0x32, 0x69, 0x6e, 0x77, 0x65, 0x74, 0x72, 0x77, 0x40, 0x69, 0x65, 0x70, 0x31, 0x36, 0x72, 0x73, 0x2d, 0x72, 0x72, 0x32, 0x72, 0x6c, 0x77, 0x6e, 0x6f, 0x77, 0x6c, 0x74, 0x72, 0x2d, 0x6e, 0x65, 0x70, 0x6c, 0x72, 0x6f, 0x69, 0x2d, 0x2d, 0x69, 0x36, 0x69, 0x69, 0x76, 0x69, 0x69, 0x6d, 0x72, 0x73, 0x6f, 0x6d, 0x74, 0x70, 0x76, 0x6d, 0x6d, 0x69, 0x72, 0x70, 0x70, 0x2d, 0x31, 0x63, 0x6c, 0x65, 0x65, 0x6e, 0x2d, 0x77, 0x74, 0x73, 0x6c, 0x72, 0x6e, 0x65, 0x65, 0x2d, 0x6c, 0x69, 0x2d, 0x6e, 0x74, 0x70, 0x72, 0x77, 0x77, 0x65, 0x65, 0x65, 0x2d, 0x76, 0x6e, 0x72, 0x69, 0x69, 0x73, 0x65, 0x74, 0x73, 0x76, 0x72, 0x72, 0x72, 0x69, 0x72, 0x73, 0x72, 0x6f, 0x2e, 0x77, 0x2d, 0x2d, 0x6c, 0x6e, 0x65, 0x65, 0x6d, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x40, 0x69, 0x32, 0x69, 0x32, 0x6e, 0x65, 0x32, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x36, 0x6e, 0x72, 0x32, 0x6e, 0x65, 0x69, 0x32, 0x6f, 0x70, 0x72, 0x72, 0x65, 0x72, 0x72, 0x69, 0x6e, 0x6d, 0x69, 0x70, 0x6c, 0x6c, 0x65, 0x31, 0x72, 0x72, 0x73, 0x72, 0x70, 0x73, 0x72, 0x65, 0x65, 0x6e, 0x76, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x31, 0x74, 0x74, 0x72, 0x63, 0x2e, 0x69, 0x65, 0x2d, 0x6d, 0x72, 0x70, 0x6e, 0x6c, 0x65, 0x31, 0x73, 0x73, 0x40, 0x74, 0x72, 0x73, 0x2e, 0x74, 0x6e, 0x77, 0x6c, 0x6f, 0x70, 0x77, 0x76, 0x73, 0x72, 0x69, 0x77, 0x69, 0x6e, 0x69, 0x2d, 0x72, 0x70, 0x70, 0x73, 0x2e, 0x76, 0x73, 0x65, 0x72, 0x72, 0x74, 0x2d, 0x72, 0x65, 0x76, 0x69, 0x77, 0x72, 0x65, 0x2d, 0x72, 0x69, 0x36, 0x77, 0x77, 0x77, 0x40, 0x2d, 0x6d, 0x69, 0x74, 0x72, 0x2d, 0x32, 0x6f, 0x76, 0x72, 0x2d, 0x2d, 0x65, 0x2e, 0x2e, 0x72, 0x6e, 0x32, 0x74, 0x6c, 0x6e, 0x6c, 0x2e, 0x6d, 0x2d, 0x6f, 0x65, 0x72, 0x2d, 0x6e, 0x65, 0x65, 0x69, 0x40, 0x69, 0x77, 0x65, 0x6c, 0x2d, 0x69, 0x69, 0x65, 0x72, 0x72, 0x32, 0x40, 0x73, 0x65, 0x36, 0x76, 0x73, 0x72, 0x69, 0x63, 0x77, 0x72, 0x6c, 0x72, 0x6e, 0x74, 0x2d, 0x65, 0x69, 0x72, 0x70, 0x6d, 0x65, 0x6c, 0x73, 0x65, 0x6c, 0x32, 0x2d, 0x73, 0x70, 0x2d, 0x31, 0x72, 0x74, 0x2e, 0x65, 0x74, 0x72, 0x74, 0x72, 0x70, 0x69, 0x40, 0x36, 0x2d, 0x74, 0x72, 0x6c, 0x2d, 0x6e, 0x72, 0x6e, 0x6d, 0x63, 0x76, 0x74, 0x6d, 0x70, 0x32, 0x70, 0x69, 0x69, 0x2d, 0x73, 0x72, 0x74, 0x65, 0x74, 0x74, 0x70, 0x2d, 0x31, 0x6c, 0x77, 0x65, 0x72, 0x70, 0x73, 0x36, 0x6c, 0x72, 0x72, 0x65, 0x65, 0x76, 0x69, 0x2e, 0x6e, 0x72, 0x72, 0x36, 0x65, 0x69, 0x72, 0x69, 0x40, 0x6c, 0x74, 0x6c, 0x72, 0x2d, 0x70, 0x74, 0x76, 0x74, 0x6f, 0x72, 0x31, 0x73, 0x70, 0x65, 0x74, 0x69, 0x6e, 0x69, 0x6c, 0x70, 0x72, 0x65, 0x70, 0x72, 0x73, 0x69, 0x2d, 0x6d, 0x63, 0x2d, 0x72, 0x2d, 0x36, 0x73, 0x6e, 0x2d, 0x6d, 0x69, 0x76, 0x76, 0x6d, 0x74, 0x72, 0x77, 0x74, 0x2e, 0x6d, 0x65, 0x2d, 0x65, 0x6d, 0x2e, 0x6c, 0x73, 0x6e, 0x6f, 0x76, 0x31, 0x74, 0x65, 0x65, 0x31, 0x69, 0x65, 0x32, 0x2d, 0x74, 0x2d, 0x77, 0x77, 0x77, 0x2e, 0x70, 0x65, 0x6e, 0x2d, 0x69, 0x32, 0x72, 0x73, 0x74, 0x65, 0x65, 0x69, 0x73, 0x77, 0x77, 0x2e, 0x6e, 0x72, 0x65, 0x70, 0x76, 0x40, 0x77, 0x65, 0x2d, 0x70, 0x36, 0x2d, 0x74, 0x65, 0x2d, 0x69, 0x74, 0x76, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x73, 0x31, 0x36, 0x69, 0x31, 0x74, 0x76, 0x65, 0x77, 0x6c, 0x6e, 0x6c, 0x32, 0x6e, 0x70, 0x73, 0x69, 0x69, 0x65, 0x72, 0x2d, 0x6e, 0x2d, 0x65, 0x65, 0x6c, 0x32, 0x77, 0x72, 0x69, 0x70, 0x76, 0x32, 0x65, 0x6c, 0x36, 0x65, 0x69, 0x31, 0x6e, 0x72, 0x6c, 0x6d, 0x65, 0x65, 0x77, 0x6e, 0x2d, 0x32, 0x77, 0x69, 0x65, 0x6d, 0x74, 0x77, 0x40, 0x65, 0x6e, 0x77, 0x73, 0x65, 0x72, 0x6c, 0x40, 0x65, 0x65, 0x72, 0x72, 0x74, 0x6e, 0x6c, 0x6d, 0x73, 0x69, 0x76, 0x72, 0x31, 0x2d, 0x65, 0x36, 0x72, 0x2d, 0x70, 0x69, 0x6e, 0x63, 0x31, 0x2d, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x2e, 0x77, 0x2d, 0x72, 0x76, 0x63, 0x69, 0x2d, 0x6d, 0x70, 0x2d, 0x6c, 0x69, 0x63, 0x69, 0x77, 0x6e, 0x69, 0x77, 0x36, 0x72, 0x69, 0x72, 0x2e, 0x74, 0x72, 0x6e, 0x65, 0x6f, 0x73, 0x2d, 0x2e, 0x72, 0x63, 0x76, 0x74, 0x36, 0x65, 0x72, 0x65, 0x6d, 0x32, 0x72, 0x70, 0x40, 0x65, 0x74, 0x6e, 0x32, 0x70, 0x2d, 0x31, 0x40, 0x6c, 0x65, 0x6c, 0x76, 0x69, 0x69, 0x76, 0x76, 0x73, 0x31, 0x6e, 0x65, 0x74, 0x65, 0x6d, 0x69, 0x2d, 0x72, 0x74, 0x74, 0x6c, 0x31, 0x74, 0x6e, 0x6e, 0x65, 0x77, 0x36, 0x69, 0x69, 0x72, 0x6e, 0x2d, 0x2d, 0x2d, 0x72, 0x73, 0x76, 0x72, 0x72, 0x65, 0x72, 0x65, 0x72, 0x2d, 0x6c, 0x76, 0x77, 0x63, 0x77, 0x72, 0x6d, 0x72, 0x2e, 0x65, 0x73, 0x32, 0x72, 0x36, 0x77, 0x72, 0x72, 0x6d, 0x74, 0x2d, 0x72, 0x2e, 0x73, 0x73, 0x65, 0x77, 0x6e, 0x65, 0x69, 0x65, 0x2d, 0x65, 0x77, 0x6f, 0x74, 0x72, 0x32, 0x40, 0x6e, 0x72, 0x69, 0x6e, 0x32, 0x70, 0x73, 0x72, 0x40, 0x2d, 0x65, 0x69, 0x65, 0x77, 0x65, 0x70, 0x40, 0x36, 0x72, 0x6c, 0x6d, 0x73, 0x69, 0x72, 0x72, 0x74, 0x36, 0x6c, 0x76, 0x65, 0x76, 0x2d, 0x74, 0x6c, 0x72, 0x72, 0x74, 0x6e, 0x73, 0x74, 0x69, 0x72, 0x6d, 0x40, 0x2d, 0x6e, 0x70, 0x73, 0x2d, 0x6d, 0x72, 0x72, 0x70, 0x65, 0x65, 0x36, 0x6e, 0x77, 0x2d, 0x69, 0x2d, 0x32, 0x72, 0x6d, 0x72, 0x6c, 0x32, 0x6c, 0x73, 0x6d, 0x65, 0x36, 0x69, 0x69, 0x72, 0x77, 0x74, 0x6f, 0x72, 0x6d, 0x6d, 0x69, 0x65, 0x73, 0x63, 0x65, 0x74, 0x74, 0x72, 0x65, 0x72, 0x2e, 0x6e, 0x73, 0x65, 0x76, 0x6c, 0x76, 0x77, 0x72, 0x6e, 0x6c, 0x32, 0x2d, 0x73, 0x65, 0x73, 0x2e, 0x76, 0x72, 0x65, 0x2d, 0x72, 0x77, 0x2d, 0x77, 0x70, 0x65, 0x6c, 0x72, 0x6e, 0x2e, 0x31, 0x73, 0x2e, 0x72, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x6d, 0x32, 0x70, 0x76, 0x76, 0x31, 0x76, 0x77, 0x65, 0x6e, 0x73, 0x63, 0x2e, 0x2d, 0x69, 0x6e, 0x69, 0x77, 0x6e, 0x65, 0x6d, 0x2d, 0x72, 0x6e, 0x74, 0x6e, 0x40, 0x73, 0x2d, 0x74, 0x74, 0x65, 0x72, 0x2d, 0x2d, 0x69, 0x73, 0x70, 0x69, 0x6c, 0x72, 0x76, 0x6d, 0x74, 0x6e, 0x73, 0x74, 0x72, 0x65, 0x63, 0x69, 0x65, 0x65, 0x72, 0x6f, 0x6e, 0x72, 0x72, 0x6c, 0x6e, 0x6e, 0x65, 0x6d, 0x74, 0x6c, 0x74, 0x65, 0x69, 0x2d, 0x6f, 0x69, 0x2e, 0x6e, 0x63, 0x65, 0x6c, 0x40, 0x70, 0x2d, 0x2d, 0x74, 0x73, 0x74, 0x40, 0x72, 0x74, 0x6c, 0x72, 0x6e, 0x6f, 0x73, 0x65, 0x74, 0x6d, 0x69, 0x32, 0x72, 0x65, 0x77, 0x6e, 0x76, 0x74, 0x73, 0x2d, 0x72, 0x6e, 0x69, 0x73, 0x40, 0x36, 0x2d, 0x6d, 0x2e, 0x65, 0x6d, 0x40, 0x69, 0x72, 0x72, 0x70, 0x65, 0x72, 0x76, 0x6c, 0x65, 0x76, 0x72, 0x65, 0x69, 0x65, 0x69, 0x6e, 0x72, 0x2d, 0x63, 0x72, 0x69, 0x6e, 0x72, 0x69, 0x6e, 0x69, 0x70, 0x6e, 0x2d, 0x69, 0x6c, 0x72, 0x2d, 0x65, 0x2d, 0x72, 0x6f, 0x65, 0x6e, 0x76, 0x6e, 0x40, 0x2d, 0x65, 0x72, 0x72, 0x6f, 0x6f, 0x72, 0x6c, 0x65, 0x74, 0x73, 0x72, 0x70, 0x77, 0x69, 0x69, 0x6d, 0x6c, 0x6d, 0x6e, 0x2d, 0x65, 0x65, 0x65, 0x74, 0x6c, 0x2d, 0x74, 0x6f, 0x2d, 0x74, 0x70, 0x72, 0x6e, 0x73, 0x72, 0x69, 0x72, 0x2e, 0x6d, 0x69, 0x65, 0x65, 0x32, 0x70, 0x6c, 0x6c, 0x65, 0x77, 0x2d, 0x72, 0x6f, 0x70, 0x76, 0x65, 0x2d, 0x72, 0x69, 0x6d, 0x72, 0x36, 0x40, 0x6d, 0x72, 0x6c, 0x6d, 0x77, 0x6c, 0x6e, 0x69, 0x72, 0x6d, 0x76, 0x73, 0x2e, 0x73, 0x72, 0x77, 0x73, 0x76, 0x2d, 0x73, 0x76, 0x6d, 0x76, 0x65, 0x69, 0x76, 0x63, 0x65, 0x72, 0x31, 0x72, 0x69, 0x76, 0x72, 0x65, 0x65, 0x2d, 0x73, 0x6d, 0x31, 0x72, 0x6e, 0x72, 0x2d, 0x2d, 0x36, 0x72, 0x73, 0x77, 0x2d, 0x77, 0x36, 0x76, 0x72, 0x6d, 0x65, 0x2d, 0x72, 0x70, 0x2d, 0x74, 0x32, 0x6c, 0x63, 0x6d, 0x6f, 0x6e, 0x2e, 0x2d, 0x69, 0x65, 0x73, 0x6d, 0x65, 0x73, 0x6e, 0x6d, 0x6c, 0x65, 0x6e, 0x72, 0x72, 0x72, 0x32, 0x70, 0x65, 0x73, 0x6c, 0x6d, 0x70, 0x6d, 0x72, 0x6f, 0x65, 0x6c, 0x76, 0x73, 0x63, 0x73, 0x65, 0x6c, 0x2d, 0x6e, 0x72, 0x65, 0x65, 0x72, 0x2d, 0x70, 0x6d, 0x69, 0x69, 0x65, 0x2d, 0x6c, 0x72, 0x69, 0x6c, 0x2d, 0x74, 0x65, 0x65, 0x69, 0x31, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x74, 0x73, 0x65, 0x32, 0x2d, 0x6f, 0x2d, 0x70, 0x72, 0x6f, 0x65, 0x69, 0x73, 0x32, 0x6d, 0x65, 0x2d, 0x65, 0x74, 0x6d, 0x6d, 0x73, 0x76, 0x6c, 0x69, 0x65, 0x2d, 0x73, 0x74, 0x65, 0x65, 0x72, 0x72, 0x74, 0x31, 0x2d, 0x76, 0x73, 0x2e, 0x2d, 0x2d, 0x72, 0x76, 0x77, 0x65, 0x72, 0x72, 0x40, 0x6e, 0x6c, 0x6d, 0x72, 0x74, 0x73, 0x72, 0x72, 0x65, 0x65, 0x2d, 0x6f, 0x74, 0x70, 0x63, 0xb8, 0xa1, 0x11, 0x6e, 0xd7, 0x74, 0x16, 0x7f, 0xb4, 0xba, 0x40, 0x93, 0x98, 0x00, 0x71, 0xcc, 0x42, 0xa7, 0x2f, 0x28, 0x69, 0xe7, 0x31, 0x48, 0x22, 0xa0, 0xe1, 0x45, 0xe3, 0xf7, 0x7f, 0x3a }; uint8_t c2[] = { 0x5b, 0x52, 0xf1, 0x2d, 0x94, 0xcb, 0xb0, 0x86, 0xd8, 0xd3, 0xe3, 0x20, 0x88, 0x47, 0xcf, 0x5a, 0x49, 0xd2, 0x11, 0x30, 0x92, 0x17, 0x8d, 0xf4, 0x99, 0xf7, 0x6c, 0x8a, 0xbc, 0xe7, 0x5c, 0x58, 0x6a, 0x65, 0xed, 0x81, 0xdc, 0xdd, 0xcf, 0x83, 0xcd, 0xa4, 0xed, 0xa2, 0x5e, 0x63, 0xd9, 0x98, 0xf6, 0x2e, 0x15, 0x76, 0x9a, 0xc8, 0x8c, 0x42, 0x54, 0x44, 0xf4, 0x47, 0xf5, 0x96, 0xc9, 0x6e, 0x23, 0x09, 0x1a, 0x0d, 0xe3, 0x04, 0xe6, 0xed, 0x48, 0x49, 0x62, 0x31, 0xe8, 0x36, 0x04, 0xed, 0xb9, 0xe7, 0xa6, 0x35, 0x4d, 0xcd, 0xe3, 0xfa, 0xa0, 0xc8, 0x34, 0xbd, 0x62, 0x7b, 0xbc, 0xbe, 0x1c, 0x5b, 0x69, 0x1f, 0x9c, 0x30, 0x20, 0x48, 0x52, 0xd1, 0xb6, 0x5e, 0xa2, 0x6e, 0x06, 0x94, 0x72, 0x10, 0x56, 0x7c, 0x94, 0xa5, 0xc0, 0xaa, 0xea, 0x48, 0x61, 0x03, 0x14, 0x94, 0x09, 0x77, 0xd9, 0xa7, 0xfe, 0x78, 0x17, 0x95, 0x4f, 0x7e, 0xb0, 0x32, 0x63, 0x02, 0x17, 0x47, 0x1e, 0x7d, 0xb2, 0x7d, 0xb5, 0xcb, 0x9f, 0x61, 0x65, 0xed, 0x03, 0xd2, 0xdb, 0xd1, 0xb3, 0xd6, 0x1a, 0xf5, 0x67, 0x0b, 0x8b, 0x6b, 0x44, 0xf2, 0x62, 0x42, 0xc2, 0x4d, 0xe1, 0x5c, 0xfe, 0xc6, 0x19, 0x2b, 0xfb, 0x03, 0x0f, 0x1b, 0x89, 0x08, 0x86, 0x40, 0xca, 0x45, 0x15, 0xda, 0x65, 0xcc, 0x73, 0x00, 0x49, 0x4e, 0x48, 0x21, 0x25, 0xc6, 0xde, 0x26, 0x21, 0x1d, 0xea, 0x3c, 0x11, 0xac, 0xef, 0x34, 0x4c, 0x96, 0xcc, 0x5e, 0x26, 0xf3, 0xcd, 0x70, 0x0d, 0x62, 0xea, 0x09, 0x35, 0x2b, 0x1e, 0x60, 0xe4, 0x76, 0xd3, 0x65, 0x01, 0x8c, 0xab, 0xd4, 0x89, 0xad, 0x81, 0x9d, 0x04, 0x01, 0xd5, 0x55, 0x3c, 0xcb, 0x32, 0xe1, 0xb5, 0xd4, 0xda, 0xb4, 0xa9, 0x01, 0xb2, 0x10, 0xc7, 0xb1, 0xa9, 0x54, 0x66, 0x1d, 0xcc, 0xff, 0x54, 0x0b, 0x84, 0x37, 0xe0, 0x3a, 0xa5, 0x68, 0x80, 0x87, 0xbc, 0x3c, 0x0f, 0xda, 0x7e, 0x3c, 0x23, 0xfc, 0xd8, 0xc5, 0x52, 0xf7, 0x22, 0x12, 0x05, 0x9c, 0x68, 0x39, 0xb1, 0xed, 0x26, 0x24, 0x2b, 0x7e, 0x0b, 0xaf, 0x9e, 0x97, 0x45, 0x7b, 0xa9, 0xbc, 0x48, 0x0e, 0x66, 0x93, 0x32, 0x0d, 0x6b, 0xd6, 0xf0, 0x4f, 0x54, 0x18, 0xcd, 0xc9, 0x8c, 0xce, 0xc4, 0xa2, 0xff, 0x1e, 0x69, 0x17, 0x7e, 0xf4, 0x99, 0x09, 0x68, 0xa1, 0x9e, 0x1f, 0xbf, 0x90, 0xdc, 0x77, 0x5d, 0x50, 0x2b, 0x0e, 0xff, 0x96, 0xdc, 0x21, 0x2e, 0x74, 0x22, 0x28, 0x88, 0xa0, 0x00, 0x32, 0x15, 0xb0, 0xfd, 0xb1, 0xc9, 0x75, 0xb3, 0x3c, 0xbd, 0x89, 0xc5, 0xa4, 0x48, 0x17, 0xa9, 0xc9, 0x50, 0x61, 0x0c, 0x35, 0x31, 0x55, 0x11, 0xe3, 0x23, 0xe9, 0x3e, 0x78, 0x25, 0xdc, 0x50, 0xe8, 0x23, 0x5f, 0xb7, 0x3f, 0xc7, 0xae, 0xf0, 0x82, 0x35, 0x46, 0x34, 0x63, 0xcc, 0x5d, 0x96, 0xb8, 0x6a, 0x7a, 0x7f, 0x54, 0x27, 0x1a, 0xa4, 0x63, 0xdd, 0xb0, 0xb6, 0x17, 0x08, 0xa1, 0x2e, 0x95, 0x9e, 0xd4, 0x9b, 0x71, 0x83, 0x81, 0x6c, 0xea, 0xab, 0x00, 0x2e, 0xca, 0x60, 0xc1, 0x4b, 0x83, 0xa7, 0xab, 0x47, 0xe8, 0x1b, 0x5a, 0x78, 0x4f, 0xec, 0xbd, 0x62, 0x94, 0x25, 0x75, 0x2e, 0x64, 0xe7, 0x70, 0x13, 0xac, 0xe9, 0x89, 0x4f, 0x1e, 0x79, 0xbc, 0x15, 0x0c, 0x8d, 0x40, 0xe8, 0x16, 0x31, 0x7c, 0xb8, 0xa5, 0xd7, 0x21, 0x39, 0x93, 0x9b, 0xe6, 0x05, 0x81, 0xb6, 0x20, 0xa8, 0x5d, 0x73, 0x58, 0x8b, 0x66, 0x92, 0xac, 0x23, 0xa0, 0xf4, 0x8c, 0xab, 0x58, 0xae, 0xb6, 0x9c, 0x3c, 0x4d, 0x77, 0x5f, 0xae, 0xe2, 0x57, 0x89, 0x8f, 0xe4, 0x68, 0x81, 0x24, 0x7d, 0x3b, 0x99, 0x46, 0x9f, 0x7b, 0x9d, 0xa6, 0xdd, 0x99, 0xcf, 0xc1, 0x79, 0x04, 0x95, 0xce, 0x96, 0x7a, 0xd9, 0xb5, 0x6e, 0xcf, 0xd1, 0x72, 0x18, 0x97, 0x76, 0xe2, 0xb7, 0x38, 0x1e, 0x24, 0x0b, 0x09, 0x00, 0x8b, 0x28, 0x5d, 0xf8, 0xd0, 0x50, 0x7f, 0xeb, 0x3b, 0x37, 0x61, 0x0b, 0xd3, 0xff, 0x65, 0x7d, 0x88, 0x1e, 0x1d, 0xbb, 0x6c, 0xf5, 0xf8, 0xf3, 0x2b, 0x51, 0xd9, 0x6d, 0xc9, 0xbe, 0xbe, 0xd1, 0x94, 0x0e, 0x58, 0x2a, 0x0a, 0xe4, 0xf8, 0x28, 0x26, 0xc3, 0x74, 0x87, 0xd3, 0x81, 0x48, 0x6e, 0x9b, 0xd5, 0xa1, 0x60, 0x87, 0xfc, 0x1b, 0x06, 0x33, 0x0d, 0x87, 0xfa, 0x9b, 0xf9, 0x73, 0x6b, 0x0c, 0xdf, 0xea, 0xee, 0x32, 0x78, 0xe0, 0xf8, 0x18, 0x3f, 0xc3, 0x3b, 0x12, 0x88, 0x0b, 0xb2, 0x4a, 0x52, 0x64, 0x4e, 0x58, 0x54, 0x82, 0x52, 0x61, 0x54, 0x28, 0x1b, 0xf7, 0x99, 0x06, 0xa2, 0xad, 0x04, 0x19, 0x9f, 0x2e, 0x34, 0xe6, 0xf0, 0xee, 0xeb, 0x93, 0x9a, 0x9c, 0x73, 0x86, 0x23, 0x6d, 0x5d, 0xae, 0x64, 0xec, 0x6f, 0xf9, 0x7c, 0xc7, 0x46, 0x96, 0xdb, 0x44, 0xf4, 0xab, 0xc9, 0x67, 0x61, 0xb8, 0xec, 0xf0, 0x99, 0xe0, 0x4d, 0x45, 0xed, 0xa3, 0x1c, 0xe9, 0x68, 0x31, 0x85, 0xa5, 0xa1, 0xba, 0x08, 0xdb, 0x3f, 0x84, 0x75, 0x70, 0x24, 0xcd, 0x49, 0xd4, 0x07, 0xa8, 0xaa, 0x52, 0xd9, 0x55, 0x68, 0x8f, 0x78, 0xd2, 0x5d, 0x46, 0x23, 0x60, 0x76, 0xe1, 0x22, 0xdc, 0x2a, 0xeb, 0xac, 0xbc, 0xeb, 0xd6, 0x4c, 0x0f, 0xb5, 0xcb, 0x47, 0xce, 0x43, 0x59, 0x1d, 0x3e, 0xfc, 0x7f, 0x7c, 0x93, 0x9e, 0xef, 0xcd, 0x79, 0x5c, 0x08, 0x8e, 0xeb, 0xa8, 0x98, 0x3e, 0x95, 0xd1, 0x36, 0x42, 0x57, 0xfd, 0x6d, 0xdc, 0xe0, 0xa3, 0x3f, 0x46, 0x32, 0xb7, 0xff, 0x00, 0x4f, 0x7b, 0x23, 0x4d, 0xd0, 0xe5, 0xdd, 0x40, 0xab, 0xb2, 0xcb, 0x45, 0x92, 0x76, 0x7c, 0x5b, 0x98, 0xc7, 0xc0, 0x54, 0x34, 0x94, 0x8e, 0xbb, 0x28, 0xcf, 0xba, 0xd9, 0xa0, 0xe6, 0xf3, 0x65, 0x61, 0xd7, 0x10, 0xd3, 0xeb, 0xce, 0x21, 0x6a, 0xca, 0x61, 0xe7, 0x81, 0x15, 0x18, 0x4e, 0x71, 0xb0, 0x99, 0x62, 0xd9, 0xeb, 0xd0, 0x8b, 0xe9, 0xdf, 0x6a, 0x6d, 0x59, 0x0b, 0x45, 0x93, 0x38, 0xfe, 0xe6, 0x6a, 0xd1, 0x5f, 0xb6, 0xe9, 0x86, 0x01, 0x38, 0xab, 0x59, 0x5c, 0xd7, 0xb7, 0xfa, 0x81, 0x8a, 0xbe, 0xdc, 0xeb, 0x50, 0x7d, 0x81, 0xfa, 0x1b, 0x8f, 0xce, 0x53, 0x38, 0xe4, 0x8a, 0x82, 0xbe, 0x7d, 0xdc, 0xd8, 0x57, 0x5a, 0x48, 0xa3, 0x38, 0x74, 0x8a, 0xac, 0xf2, 0xfd, 0xbf, 0xcc, 0xd8, 0x08, 0x4d, 0x3e, 0xae, 0xa9, 0x00, 0x66, 0x06, 0xcb, 0xf3, 0x50, 0xcc, 0x52, 0xc7, 0x4b, 0x16, 0x33, 0xa5, 0xde, 0x20, 0xed, 0x6a, 0xa7, 0x58, 0x5e, 0x4e, 0x7e, 0x29, 0xab, 0xb9, 0x65, 0x9d, 0x17, 0xe0, 0x1e, 0x79, 0x77, 0xf6, 0x1e, 0xa0, 0xcb, 0x0c, 0xf7, 0xc0, 0xe4, 0xf6, 0x3b, 0x60, 0x81, 0xfe, 0xed, 0xd9, 0x42, 0xa9, 0x61, 0x9d, 0xa8, 0xd7, 0xe8, 0xaa, 0x97, 0xad, 0xbb, 0xba, 0x13, 0x6e, 0x05, 0xa5, 0xce, 0x7a, 0x65, 0x6f, 0x55, 0xe3, 0xcf, 0xbc, 0x67, 0x14, 0x64, 0x57, 0x9c, 0x46, 0x14, 0xd6, 0x1d, 0x39, 0x1c, 0xd3, 0xe8, 0x98, 0x20, 0x5a, 0x1a, 0x05, 0x3b, 0x27, 0xd5, 0x84, 0xca, 0xd4, 0x0b, 0xc4, 0x1e, 0xd8, 0x46, 0x29, 0x48, 0x95, 0xdb, 0xe5, 0x58, 0x8a, 0x51, 0xc7, 0x74, 0x7f, 0x53, 0xa8, 0xbb, 0x58, 0xc0, 0x5b, 0xe1, 0xa7, 0x27, 0x36, 0x6c, 0xa6, 0x70, 0xec, 0x88, 0xcd, 0x9a, 0x70, 0xe1, 0xa0, 0xc7, 0xdd, 0x60, 0x71, 0xf4, 0x2a, 0x51, 0x98, 0x8e, 0xab, 0xb8, 0x13, 0x03, 0x48, 0x5f, 0x44, 0xf8, 0x88, 0xd9, 0x7d, 0xd3, 0xf1, 0x5f, 0xc4, 0x2b, 0x44, 0x15, 0x57, 0x31, 0xa4, 0xa1, 0xdb, 0x6d, 0x2a, 0x5a, 0x5a, 0xf7, 0xde, 0xd5, 0x23, 0x38, 0x00, 0xe5, 0x5c, 0x55, 0xe7, 0x37, 0x9c, 0xcb, 0x8b, 0xc0, 0x33, 0x42, 0x68, 0x23, 0x84, 0x7d, 0x89, 0x9d, 0xae, 0x59, 0x18, 0xae, 0xea, 0x46, 0x3f, 0xac, 0x57, 0x0d, 0x5d, 0x49, 0x14, 0x50, 0xe5, 0x70, 0x17, 0x73, 0x09, 0x11, 0x93, 0x6b, 0x02, 0x22, 0xb7, 0x63, 0xc9, 0xe6, 0xa4, 0xe3, 0xb1, 0xf7, 0xa6, 0x58, 0x8d, 0x14, 0xa1, 0xda, 0x6a, 0xb9, 0x38, 0xf9, 0x20, 0x45, 0x8c, 0xe6, 0x32, 0x23, 0x9d, 0x5f, 0xba, 0xcb, 0xb4, 0x95, 0xf9, 0xa9, 0x5c, 0x60, 0x03, 0x5a, 0x8c, 0xa7, 0xb9, 0x65, 0xa8, 0x84, 0x38, 0xc0, 0x25, 0xe6, 0xa7, 0xc0, 0x3b, 0xbc, 0x11, 0xed, 0x0e, 0x9a, 0x6f, 0xfe, 0x61, 0x79, 0x86, 0x92, 0x3a, 0xce, 0xe0, 0xb7, 0x70, 0xad, 0xe0, 0xcc, 0x88, 0x47, 0xd9, 0x2a, 0x3d, 0x41, 0x06, 0x77, 0x41, 0xbe, 0x3f, 0x55, 0x31, 0x54, 0x10, 0x14, 0x5b, 0xdf, 0x88, 0xb2, 0x9f, 0xff, 0x11, 0xb8, 0x11, 0xdc, 0x5e, 0x64, 0xf9, 0x97, 0x8a, 0x26, 0x6a, 0x44, 0xb4, 0x83, 0x83, 0x9b, 0x81, 0xaa, 0xfd, 0xb5, 0x8b, 0x16, 0x18, 0x2e, 0x5c, 0xe4, 0x5b, 0x8f, 0xdd, 0x7c, 0x1f, 0x33, 0x2f, 0xef, 0x57, 0x8c, 0x6a, 0x3f, 0x3c, 0x19, 0x5e, 0x73, 0x64, 0xc5, 0xaf, 0x1d, 0xa1, 0xb4, 0x11, 0xee, 0x6b, 0x7e, 0x66, 0xfb, 0xaa, 0x03, 0x17, 0xe4, 0xc9, 0x90, 0x4b, 0xf2, 0x50, 0x55, 0x71, 0xad, 0x31, 0x71, 0x49, 0xd7, 0x80, 0xd1, 0xa5, 0x9f, 0x6d, 0x71, 0x28, 0x2b, 0x65, 0xcf, 0x8d, 0xb1, 0x2a, 0x33, 0xdc, 0x93, 0xff, 0x86, 0xd7, 0xa6, 0xd0, 0x46, 0x66, 0x32, 0x3d, 0x18, 0x8c, 0xd3, 0xda, 0xf6, 0x1b, 0xa0, 0x2d, 0x29, 0xfd, 0x8d, 0x57, 0x2c, 0x82, 0xed, 0x38, 0x4a, 0x6f, 0xc4, 0x3c, 0x9a, 0x61, 0xcb, 0xe5, 0xcf, 0xd3, 0x83, 0xa1, 0x91, 0x93, 0x0d, 0x75, 0xfd, 0x4e, 0x2c, 0x83, 0xa0, 0x85, 0x27, 0x13, 0x5a, 0x24, 0xbd, 0x08, 0x1e, 0xe9, 0xab, 0x92, 0x41, 0xc2, 0x3a, 0xa0, 0xe1, 0xfd, 0x00, 0xb9, 0xf8, 0xca, 0x0b, 0x1a, 0x8e, 0xf6, 0x27, 0x9f, 0x5a, 0xf0, 0x23, 0x07, 0xc8, 0xbf, 0xf6, 0x74, 0xe7, 0xf8, 0x67, 0xfc, 0x28, 0x4e, 0x6a, 0x6c, 0xc6, 0x83, 0xe3, 0xf0, 0x01, 0xe0, 0x0f, 0x2d, 0xdf, 0x9e, 0x4b, 0x8b, 0x06, 0x15, 0x4c, 0x9f, 0xdf, 0x55, 0x14, 0x44, 0xde, 0x34, 0x35, 0x5a, 0xcb, 0xe5, 0xa7, 0xb5, 0x7e, 0x00, 0x31, 0x98, 0x5f, 0x51, 0x11, 0x37, 0xe1, 0xd2, 0x99, 0x8f, 0x70, 0x13, 0x40, 0xa0, 0xbe, 0xf8, 0xde, 0xac, 0x37, 0x06, 0xb6, 0x26, 0xf3, 0xb1, 0x97, 0x0b, 0x85, 0x68, 0x09, 0xa4, 0xc8, 0x34, 0x0a, 0x41, 0x6e, 0xac, 0x1a, 0x5b, 0xe0, 0x91, 0x6f, 0xa3, 0x0a, 0xf6, 0x05, 0x37, 0x32, 0xe1, 0x8e, 0xd8, 0xed, 0x55, 0xa3, 0x54, 0x3f, 0x62, 0x95, 0x82, 0xcf, 0x0a, 0x19, 0xb4, 0x9f, 0x04, 0xcc, 0x86, 0x7e, 0xf1, 0xe5, 0x8b, 0x67, 0x73, 0xa2, 0x46, 0x4e, 0xf2, 0x98, 0x94, 0xb5, 0xeb, 0xa5, 0xbd, 0xcb, 0x66, 0x82, 0xe9, 0x87, 0xe9, 0xe3, 0x50, 0x55, 0x4b, 0xd6, 0x67, 0x30, 0xe1, 0x7c, 0x15, 0x77, 0x29, 0xfd, 0x85, 0x67, 0x5a, 0xc4, 0xd5, 0x69, 0xfa, 0xc7, 0x66, 0x66, 0x49, 0xf7, 0x5a, 0xcd, 0xd1, 0x81, 0x5c, 0x74, 0x8d, 0xbf, 0xc5, 0xc2, 0xff, 0x4d, 0x90, 0xe8, 0x8e, 0x05, 0x00, 0xff, 0x7a, 0xd7, 0xb2, 0x7a, 0xad, 0x8b, 0xd6, 0x4b, 0x52, 0x09, 0x50, 0x4b }; if (true) { SrsHandshakeBytes bytes; ASSERT_EQ(ERROR_SUCCESS, bytes.create_c0c1()); memcpy(bytes.c0c1, c0c1, 1537); ASSERT_EQ(ERROR_SUCCESS, bytes.create_s0s1s2()); memcpy(bytes.s0s1s2, s0s1s2, 3073); ASSERT_EQ(ERROR_SUCCESS, bytes.create_c2()); memcpy(bytes.c2, c2, 1536); MockEmptyIO eio; SrsSimpleHandshake hs; HELPER_EXPECT_SUCCESS(hs.handshake_with_client(&bytes, &eio)); HELPER_EXPECT_SUCCESS(hs.handshake_with_server(&bytes, &eio)); } if (true) { MockBufferIO io; io.append(s0s1s2, 3073); SrsRtmpClient r(&io); HELPER_EXPECT_SUCCESS(r.handshake()); } if (true) { MockBufferIO io; io.append(s0s1s2, 3073); SrsRtmpClient r(&io); HELPER_EXPECT_SUCCESS(r.simple_handshake()); } if (true) { MockBufferIO io; io.append(c0c1, 1537); io.append(c2, 1536); SrsRtmpServer r(&io); HELPER_EXPECT_SUCCESS(r.handshake()); } } /** * bytes equal utility */ VOID TEST(ProtocolHandshakeTest, BytesEqual) { uint8_t a1[] = { 0x01 }; uint8_t b1[] = { 0x02 }; uint8_t a2[] = { 0x01, 0x02 }; uint8_t b2[] = { 0x02, 0x03 }; EXPECT_TRUE(srs_bytes_equals(NULL, NULL, 0)); EXPECT_FALSE(srs_bytes_equals(a1, NULL, 1)); EXPECT_FALSE(srs_bytes_equals(NULL, a1, 1)); EXPECT_FALSE(srs_bytes_equals(a1, b1, 1)); EXPECT_TRUE(srs_bytes_equals(a1, a1, 1)); EXPECT_TRUE(srs_bytes_equals(a1, a2, 1)); EXPECT_FALSE(srs_bytes_equals(a1, b2, 1)); } /** * discovery tcUrl to schema/vhost/host/port/app */ VOID TEST(ProtocolUtilityTest, DiscoveryTcUrl) { std::string tcUrl, schema, ip, vhost, app, stream, param; int port; // general url tcUrl = "rtmp://winlin.cn/live"; stream= "show"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("winlin.cn", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(1935, port); tcUrl = "rtmp://winlin.cn:19351/live"; stream= "show"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("winlin.cn", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(19351, port); tcUrl = "rtmp://winlin.cn/live"; stream= "show?key=abc"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("winlin.cn", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(1935, port); EXPECT_STREQ("?key=abc", param.c_str()); tcUrl = "rtmp://winlin.cn/live"; stream= "show?key=abc&&vhost=demo.com"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("demo.com", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(1935, port); EXPECT_STREQ("?key=abc&&vhost=demo.com", param.c_str()); // vhost in app tcUrl = "rtmp://winlin.cn/live?key=abc"; stream= "show"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("winlin.cn", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(1935, port); EXPECT_STREQ("?key=abc", param.c_str()); tcUrl = "rtmp://winlin.cn/live?key=abc&&vhost=demo.com"; stream= "show"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("demo.com", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(1935, port); EXPECT_STREQ("?key=abc&&vhost=demo.com", param.c_str()); // without stream tcUrl = "rtmp://winlin.cn/live"; stream=""; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("winlin.cn", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("", stream.c_str()); EXPECT_EQ(1935, port); tcUrl = "rtmp://127.0.0.1:1935/live"; stream=""; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", ip.c_str()); EXPECT_STREQ("127.0.0.1", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("", stream.c_str()); EXPECT_EQ(1935, port); tcUrl = "rtmp://127.0.0.1:19351/live"; stream=""; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", ip.c_str()); EXPECT_STREQ("127.0.0.1", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("", stream.c_str()); EXPECT_EQ(19351, port); tcUrl = "rtmp://127.0.0.1:19351/live?vhost=demo"; stream=""; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", ip.c_str()); EXPECT_STREQ("demo", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("", stream.c_str()); EXPECT_EQ(19351, port); // no vhost tcUrl = "rtmp://127.0.0.1:19351/live"; stream= "show"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", ip.c_str()); EXPECT_STREQ("127.0.0.1", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(19351, port); // ip and vhost tcUrl = "rtmp://127.0.0.1:19351/live"; stream= "show?vhost=demo"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", ip.c_str()); EXPECT_STREQ("demo", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(19351, port); // _definst_ at the end of app tcUrl = "rtmp://winlin.cn/live/_definst_"; stream= "show"; srs_discovery_tc_url(tcUrl, schema, ip, vhost, app, stream, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("winlin.cn", ip.c_str()); EXPECT_STREQ("winlin.cn", vhost.c_str()); EXPECT_STREQ("live", app.c_str()); EXPECT_STREQ("show", stream.c_str()); EXPECT_EQ(1935, port); } /** * generate tcUrl from ip/vhost/app/port */ VOID TEST(ProtocolUtilityTest, GenerateTcUrl) { string ip; string vhost; string app; int port; string tcUrl; string param; ip = "127.0.0.1"; vhost = "__defaultVhost__"; app = "live"; port = 1935; tcUrl = srs_generate_tc_url(ip, vhost, app, port); EXPECT_STREQ("rtmp://127.0.0.1/live", tcUrl.c_str()); ip = "127.0.0.1"; vhost = "demo"; app = "live"; port = 1935; tcUrl = srs_generate_tc_url(ip, vhost, app, port); EXPECT_STREQ("rtmp://demo/live", tcUrl.c_str()); ip = "127.0.0.1"; vhost = "demo"; app = "live"; port = 19351; tcUrl = srs_generate_tc_url(ip, vhost, app, port); EXPECT_STREQ("rtmp://demo:19351/live", tcUrl.c_str()); } /** * shared ptr message array test */ VOID TEST(ProtocolMsgArrayTest, MessageArray) { SrsMessageHeader header; SrsSharedPtrMessage msg; char* payload = new char[1024]; EXPECT_TRUE(ERROR_SUCCESS == msg.create(&header, payload, 1024)); EXPECT_EQ(0, msg.count()); if (true) { SrsMessageArray arr(3); arr.msgs[0] = msg.copy(); EXPECT_EQ(1, msg.count()); arr.msgs[1] = msg.copy(); EXPECT_EQ(2, msg.count()); arr.msgs[2] = msg.copy(); EXPECT_EQ(3, msg.count()); } EXPECT_EQ(3, msg.count()); if (true) { SrsMessageArray arr(3); arr.msgs[0] = msg.copy(); EXPECT_EQ(4, msg.count()); arr.msgs[2] = msg.copy(); EXPECT_EQ(5, msg.count()); } EXPECT_EQ(5, msg.count()); } /** * set/get timeout of protocol stack */ VOID TEST(ProtocolStackTest, ProtocolTimeout) { MockBufferIO bio; SrsProtocol proto(&bio); EXPECT_TRUE(SRS_UTIME_NO_TIMEOUT == proto.get_recv_timeout()); EXPECT_TRUE(SRS_UTIME_NO_TIMEOUT == proto.get_send_timeout()); proto.set_recv_timeout(10 * SRS_UTIME_MILLISECONDS); EXPECT_TRUE(10 * SRS_UTIME_MILLISECONDS == proto.get_recv_timeout()); proto.set_send_timeout(10 * SRS_UTIME_MILLISECONDS); EXPECT_TRUE(10 * SRS_UTIME_MILLISECONDS == proto.get_send_timeout()); } /** * get recv/send bytes of protocol stack. */ VOID TEST(ProtocolStackTest, ProtocolBytes) { MockBufferIO bio; SrsProtocol proto(&bio); EXPECT_TRUE(0 == proto.get_recv_bytes()); EXPECT_TRUE(0 == proto.get_send_bytes()); SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); EXPECT_TRUE(0 < proto.get_send_bytes()); } /** * recv a SrsConnectAppPacket packet. */ VOID TEST(ProtocolStackTest, ProtocolRecvMessage) { MockBufferIO bio; SrsProtocol proto(&bio); // packet is SrsConnectAppPacket uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa1, 0x14, 0x00, 0x00, 0x00, 0x00, // 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, 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, 0xC3, /*next chunk.*/ 0x0d, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x62, 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, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x76, 0x68, 0x6f, 0x73, 0x74, 0x3d, 0x64, 0x65, 0x76, 0x26, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3d, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x26, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3d, 0x64, 0x65, 0x76, 0x26, 0x70, 0x6f, 0x72, 0x74, 0xC3, /*next chunk.*/ 0x3d, 0x31, 0x39, 0x33, 0x35, 0x00, 0x0e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }; bio.in_buffer.append((char*)data, sizeof(data)); SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); SrsPacket* pkt = NULL; EXPECT_TRUE(ERROR_SUCCESS == proto.decode_message(msg, &pkt)); SrsAutoFree(SrsPacket, pkt); SrsConnectAppPacket* spkt = dynamic_cast(pkt); ASSERT_TRUE(NULL != spkt); } // for librtmp, if ping, it will send a fresh stream with fmt=1, // 0x42 where: fmt=1, cid=2, protocol contorl user-control message // 0x00 0x00 0x00 where: timestamp=0 // 0x00 0x00 0x06 where: payload_length=6 // 0x04 where: message_type=4(protocol control user-control message) // 0x00 0x06 where: event Ping(0x06) // 0x00 0x00 0x0d 0x0f where: event data 4bytes ping timestamp. // @see: https://github.com/ossrs/srs/issues/98 VOID TEST(ProtocolStackTest, ProtocolRecvMessageBug98) { MockBufferIO bio; SrsProtocol proto(&bio); // packet is SrsConnectAppPacket uint8_t data[] = { 0x42, // 1bytes chunk header 0x00, 0x00, 0x00, // timestamp=0 0x00, 0x00, 0x06, // payload_length=6 0x04, // message_type=4(protocol control user-control message) 0x00, 0x06, // event Ping(0x06) 0x00, 0x00, 0x0d, 0x0f // event data 4bytes ping timestamp. }; bio.in_buffer.append((char*)data, sizeof(data)); SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); SrsPacket* pkt = NULL; EXPECT_TRUE(ERROR_SUCCESS == proto.decode_message(msg, &pkt)); SrsAutoFree(SrsPacket, pkt); SrsUserControlPacket* spkt = dynamic_cast(pkt); ASSERT_TRUE(NULL != spkt); EXPECT_EQ(SrcPCUCPingRequest, spkt->event_type); EXPECT_EQ(0x0d0f, spkt->event_data); } /** * recv a SrsSetWindowAckSizePacket packet. */ VOID TEST(ProtocolStackTest, ProtocolRecvAckSizeMessage) { MockBufferIO bio; SrsProtocol proto(&bio); // packet is SrsSetWindowAckSizePacket uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, // 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); SrsPacket* pkt = NULL; EXPECT_TRUE(ERROR_SUCCESS == proto.decode_message(msg, &pkt)); SrsAutoFree(SrsPacket, pkt); SrsSetWindowAckSizePacket* spkt = dynamic_cast(pkt); ASSERT_TRUE(NULL != spkt); EXPECT_EQ(0x0763, spkt->ackowledgement_window_size); } /** * recv a video message. */ VOID TEST(ProtocolStackTest, ProtocolRecvVMessage) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 0x00, 0x00, 0x00, // timestamp 0x00, 0x00, 0x04, // length 0x09, // message_type 0x00, 0x00, 0x00, 0x00, // stream_id // 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()); } /** * recv a audio message. */ VOID TEST(ProtocolStackTest, ProtocolRecvAMessage) { MockBufferIO bio; SrsProtocol proto(&bio); // audio message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 0x00, 0x00, 0x00, // timestamp 0x00, 0x00, 0x04, // length 0x08, // message_type 0x00, 0x00, 0x00, 0x00, // stream_id // 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_audio()); } /** * recv a video message in 2 chunk packets. */ VOID TEST(ProtocolStackTest, ProtocolRecvVMessage2Trunk) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 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, 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, 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()); } /** * recv video and audio, interlaced in chunks. */ VOID TEST(ProtocolStackTest, ProtocolRecvVAMessage) { 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, 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 }; 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, 0x00, // timestamp 0x00, 0x00, 0x90, // length, 144 0x08, // 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 }; 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)); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_audio()); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_video()); } } /** * recv video and audio, interlaced in chunks. * the continue chunks use fmt=1 header */ VOID TEST(ProtocolStackTest, ProtocolRecvVAFmt1) { 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, 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 }; 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, 0x00, // timestamp 0x00, 0x00, 0x90, // length, 144 0x08, // 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 }; bio.in_buffer.append((char*)data, sizeof(data)); } // video message, chunk#2 if (true) { uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x43, 0x00, 0x00, 0x00, // timestamp 0x00, 0x01, 0x10, // length, 272 0x09, // message_type // msg payload start /*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)); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_audio()); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_video()); } } /** * recv video and audio, interlaced in chunks. * the continue chunks use fmt=2 header */ VOID TEST(ProtocolStackTest, ProtocolRecvVAFmt2) { 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, 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 }; 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, 0x00, // timestamp 0x00, 0x00, 0x90, // length, 144 0x08, // 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 }; bio.in_buffer.append((char*)data, sizeof(data)); } // video message, chunk#2 if (true) { uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x83, 0x00, 0x00, 0x00, // timestamp // msg payload start /*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)); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_audio()); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_video()); } } /** * recv video and audio, interlaced in chunks. * the continue chunks use fmt=3 header */ VOID TEST(ProtocolStackTest, ProtocolRecvVAFmt3) { 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, 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 }; 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, 0x00, // timestamp 0x00, 0x00, 0x90, // length, 144 0x08, // 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 }; bio.in_buffer.append((char*)data, sizeof(data)); } // video message, chunk#2 if (true) { uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0xC3, // msg payload start /*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)); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_audio()); } if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_video()); } } /** * recv video, audio and video, interlaced in chunks. */ VOID TEST(ProtocolStackTest, ProtocolRecvVAVMessage) { 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)); } 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); } } /** * recv video, audio and video, interlaced in chunks. * the continue chunks use fmt=1 header */ VOID TEST(ProtocolStackTest, ProtocolRecvVAVFmt1) { 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, 0x12, // 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)); } 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(0x22, msg->header.timestamp); EXPECT_EQ(0x01, msg->header.stream_id); } } /** * recv video, audio and video, interlaced in chunks. * the continue chunks use fmt=2 header */ VOID TEST(ProtocolStackTest, ProtocolRecvVAVFmt2) { 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, 0x12, // 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)); } 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(0x22, msg->header.timestamp); EXPECT_EQ(0x01, msg->header.stream_id); } } /** * recv video, audio and video, interlaced in chunks. * the continue chunks use fmt=3 header */ VOID TEST(ProtocolStackTest, ProtocolRecvVAVFmt3) { 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)); } 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); } } /** * 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. // @see https://github.com/ossrs/srs/issues/111 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); } /** * a video message, in 2 chunks packet. * use 1B chunk header, cid in 2-63 */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid1BNormal) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x09, 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 0xC9, /*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 0xC9, /*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), cid in 2-63 EXPECT_EQ(0x09, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 1B chunk header, max chunk id is 63. */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid1BMax) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x3F, 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 0xFF, /*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 0xFF, /*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), max is 63 EXPECT_EQ(0x3F, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 2B chunk header, min chunk id is 64. */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid2BMin) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x00, 0x00, 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 0xC0, 0x00, /*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 0xC0, 0x00, /*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()); // 2B cid(8bits), min is 64 EXPECT_EQ(64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 2B chunk header, cid in 64-319 */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid2BNormal) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x00, 0x10, 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 0xC0, 0x10, /*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 0xC0, 0x10, /*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()); // 2B cid(8bits), cid in 64-319 EXPECT_EQ(0x10+64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 2B chunk header, cid in 64-319 */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid2BNormal2) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x00, 0x11, 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 0xC0, 0x11, /*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 0xC0, 0x11, /*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()); // 2B cid(8bits), cid in 64-319 EXPECT_EQ(0x11+64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 2B chunk header, max chunk id is 319. */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid2BMax) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x00, 0xFF, 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 0xC0, 0xFF, /*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 0xC0, 0xFF, /*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()); // 2B cid(68bits), max is 319 EXPECT_EQ(319, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 3B chunk header, min chunk id is 64. */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BMin) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x01, 0x00, 0x00, 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 0xC1, 0x00, 0x00, /*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 0xC1, 0x00, 0x00, /*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()); // 3B cid(16bits), min is 64 EXPECT_EQ(64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 3B chunk header, cid in 64-65599 */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BNormal) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x01, 0x00, 0x10, 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 0xC1, 0x00, 0x10, /*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 0xC1, 0x00, 0x10, /*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()); // 3B cid(16bits), cid in 64-65599 EXPECT_EQ(0x10*256+64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 3B chunk header, cid in 64-65599, greater than 319 */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BNormal2) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x01, 0x01, 0x10, 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 0xC1, 0x01, 0x10, /*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 0xC1, 0x01, 0x10, /*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()); // 3B cid(16bits), cid in 64-65599 EXPECT_EQ(0x01 + (0x10*256) + 64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 3B chunk header, cid in 64-65599, greater than 319 */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BNormal3) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x01, 0xFF, 0x10, 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 0xC1, 0xFF, 0x10, /*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 0xC1, 0xFF, 0x10, /*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()); // 3B cid(16bits), cid in 64-65599 EXPECT_EQ(0xFF + (0x10*256) + 64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 3B chunk header, cid in 64-65599, greater than 319 */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BNormal4) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x01, 0x02, 0x10, 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 0xC1, 0x02, 0x10, /*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 0xC1, 0x02, 0x10, /*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()); // 3B cid(16bits), cid in 64-65599 EXPECT_EQ(0x02 + (0x10*256) + 64, msg->header.perfer_cid); } /** * a video message, in 2 chunks packet. * use 3B chunk header, max chunk id is 65599. */ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BMax) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x01, 0xFF, 0xFF, 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 0xC1, 0xFF, 0xFF, /*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 0xC1, 0xFF, 0xFF, /*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()); // 2B cid(16bits), max is 65599 EXPECT_EQ(65599, msg->header.perfer_cid); } /** * recv a zero length video message. */ VOID TEST(ProtocolStackTest, ProtocolRecvV0LenMessage) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // video #1 // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 0x00, 0x00, 0x00, // timestamp 0x00, 0x00, 0x00, // length 0x09, // message_type 0x00, 0x00, 0x00, 0x00, // stream_id // video #2 // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 0x00, 0x00, 0x00, // timestamp 0x00, 0x00, 0x04, // length 0x09, // message_type 0x00, 0x00, 0x00, 0x00, // stream_id // 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()); // protocol stack will ignore the empty video message. EXPECT_EQ(4, msg->header.payload_length); } /** * send a video message */ VOID TEST(ProtocolStackTest, ProtocolSendVMessage) { MockBufferIO bio; SrsProtocol proto(&bio); uint8_t data[] = {0x01, 0x02, 0x03, 0x04}; SrsCommonMessage* msg = new SrsCommonMessage(); msg->size = sizeof(data); msg->payload = new char[msg->size]; memcpy(msg->payload, data, msg->size); SrsSharedPtrMessage m; ASSERT_TRUE(ERROR_SUCCESS == m.create(msg)); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_message(m.copy(), 0)); EXPECT_EQ(16, bio.out_buffer.length()); } /** * send a SrsCallPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsCallPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); SrsCallPacket* pkt = new SrsCallPacket(); pkt->command_name = "my_call"; pkt->command_object = SrsAmf0Any::null(); pkt->arguments = args; args->set("video_id", SrsAmf0Any::number(100)); args->set("url", SrsAmf0Any::str("http://ossrs.net/api/v1/videos/100")); args->set("date", SrsAmf0Any::str("2014-07-11 16:20:10.2984")); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x07, 0x6d, 0x79, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x08, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x69, 0x64, 0x00, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, 0x6c, 0x02, 0x00, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x73, 0x73, 0x72, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x73, 0x2f, 0x31, 0x30, 0x30, 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x02, 0x00, 0x18, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x37, 0x2d, 0x31, 0x31, 0x20, 0x31, 0x36, 0x3a, 0x32, 0x30, 0x3a, 0x31, 0x30, 0x2e, 0x32, 0x39, 0x38, 0x34, 0x00, 0x00, 0x09 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsCallResPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsCallResPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); SrsCallResPacket* pkt = new SrsCallResPacket(0); pkt->command_name = "_result"; pkt->command_object = SrsAmf0Any::null(); pkt->response = args; args->set("video_id", SrsAmf0Any::number(100)); args->set("url", SrsAmf0Any::str("http://ossrs.net/api/v1/videos/100")); args->set("date", SrsAmf0Any::str("2014-07-11 16:20:10.2984")); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x07, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x08, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x69, 0x64, 0x00, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, 0x6c, 0x02, 0x00, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x73, 0x73, 0x72, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x73, 0x2f, 0x31, 0x30, 0x30, 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x02, 0x00, 0x18, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x37, 0x2d, 0x31, 0x31, 0x20, 0x31, 0x36, 0x3a, 0x32, 0x30, 0x3a, 0x31, 0x30, 0x2e, 0x32, 0x39, 0x38, 0x34, 0x00, 0x00, 0x09 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsCreateStreamPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsCreateStreamPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsCreateStreamPacket* pkt = new SrsCreateStreamPacket(); pkt->command_object = SrsAmf0Any::null(); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsFMLEStartPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsFMLEStartPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsFMLEStartPacket* pkt = new SrsFMLEStartPacket(); pkt->command_name = "FMLEStart"; pkt->command_object = SrsAmf0Any::null(); pkt->stream_name = "livestream"; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x46, 0x4d, 0x4c, 0x45, 0x53, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02, 0x00, 0x0a, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsFMLEStartResPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsFMLEStartResPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(1); pkt->command_name = "FMLEStart"; pkt->command_object = SrsAmf0Any::null(); pkt->args = args; args->set("stream" , SrsAmf0Any::str("livestream")); args->set("start" , SrsAmf0Any::number(0)); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); uint8_t buf[] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x46, 0x4d, 0x4c, 0x45, 0x53, 0x74, 0x61, 0x72, 0x74, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), (char*)buf, sizeof(buf))); } /** * send a SrsPublishPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsPublishPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsPublishPacket* pkt = new SrsPublishPacket(); pkt->command_name = "publish"; pkt->command_object = SrsAmf0Any::null(); pkt->stream_name = "livestream"; pkt->type = "live"; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); uint8_t buf[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x07, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02, 0x00, 0x0a, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x02, 0x00, 0x04, 0x6c, 0x69, 0x76, 0x65 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), (char*)buf, sizeof(buf))); } /** * send a SrsPlayResPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsPlayResPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); SrsPlayResPacket* pkt = new SrsPlayResPacket(); pkt->command_name = "_result"; pkt->command_object = SrsAmf0Any::null(); pkt->desc = args; args->set("stream" , SrsAmf0Any::str("livestream")); args->set("start" , SrsAmf0Any::number(0)); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x07, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x06, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x02, 0x00, 0x0a, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x00, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsOnBWDonePacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsOnBWDonePacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); pkt->command_name = "onBWDone"; pkt->args = SrsAmf0Any::null(); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x6f, 0x6e, 0x42, 0x57, 0x44, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsOnStatusCallPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsOnStatusCallPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); args->set("stream" , SrsAmf0Any::str("livestream")); args->set("start" , SrsAmf0Any::number(0)); SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); pkt->command_name = "onStatus"; pkt->args = SrsAmf0Any::null(); pkt->data = args; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x06, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x02, 0x00, 0x0a, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x00, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsBandwidthPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsBandwidthPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); args->set("stream" , SrsAmf0Any::str("livestream")); args->set("start" , SrsAmf0Any::number(0)); SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); pkt->command_name = "startPublish"; pkt->args = SrsAmf0Any::null(); pkt->data = args; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0c, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x00, 0x06, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x02, 0x00, 0x0a, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x00, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsOnStatusDataPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsOnStatusDataPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); args->set("stream" , SrsAmf0Any::str("livestream")); args->set("start" , SrsAmf0Any::number(0)); SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); pkt->command_name = "onData"; pkt->data = args; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x03, 0x00, 0x06, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x02, 0x00, 0x0a, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x00, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsSampleAccessPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsSampleAccessPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); pkt->command_name = "|RtmpSampleAccess"; pkt->video_sample_access = true; pkt->audio_sample_access = true; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x11, 0x7c, 0x52, 0x74, 0x6d, 0x70, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x01, 0x01, 0x01, 0x01 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsOnMetaDataPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsOnMetaDataPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAmf0Object* args = SrsAmf0Any::object(); args->set("width" , SrsAmf0Any::number(1024)); args->set("height" , SrsAmf0Any::number(576)); SrsOnMetaDataPacket* pkt = new SrsOnMetaDataPacket(); pkt->name = "onMetaData"; pkt->metadata = args; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); uint8_t buf[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x12, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x03, 0x00, 0x05, 0x77, 0x69, 0x64, 0x74, 0x68, 0x00, 0x40, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x40, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), (char*)buf, sizeof(buf))); } /** * send a SrsSetWindowAckSizePacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsSetWindowAckSizePacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); pkt->ackowledgement_window_size = 102400; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); uint8_t buf[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x90, 0x00 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), (char*)buf, sizeof(buf))); } /** * send a SrsAcknowledgementPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsAcknowledgementPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsAcknowledgementPacket* pkt = new SrsAcknowledgementPacket(); pkt->sequence_number = 1024; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsSetChunkSizePacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsSetChunkSizePacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); pkt->chunk_size = 1024; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsSetPeerBandwidthPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsSetPeerBandwidthPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsSetPeerBandwidthPacket* pkt = new SrsSetPeerBandwidthPacket(); pkt->type = SrsPeerBandwidthSoft; pkt->bandwidth = 1024; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); } /** * send a SrsUserControlPacket packet */ VOID TEST(ProtocolStackTest, ProtocolSendSrsUserControlPacket) { MockBufferIO bio; SrsProtocol proto(&bio); SrsUserControlPacket* pkt = new SrsUserControlPacket(); pkt->event_type = SrcPCUCSetBufferLength; pkt->event_data = 0x01; pkt->extra_data = 0x10; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); char buf[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10 }; EXPECT_TRUE(srs_bytes_equals(bio.out_buffer.bytes(), buf, sizeof(buf))); EXPECT_TRUE(true); } /** * recv video message from multiple chunks, * the next chunks must not be fmt=0 which means new msg. */ // when exists cache msg, means got an partial message, // the fmt must not be type0 which means new message. VOID TEST(ProtocolStackTest, ProtocolRecvVMessageFmtInvalid) { MockBufferIO bio; SrsProtocol proto(&bio); // video message uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 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, 0x03, /*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, 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; EXPECT_FALSE(ERROR_SUCCESS == proto.recv_message(&msg)); } /** * when recv bytes archive the ack-size, server must response a acked-size auto. */ VOID TEST(ProtocolStackTest, ProtocolAckSizeFlow) { MockBufferIO bio; SrsProtocol proto(&bio); if (true) { SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); pkt->ackowledgement_window_size = 512; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); } if (true) { SrsCommonMessage* msg = new SrsCommonMessage(); msg->header.payload_length = msg->size = 4096; msg->payload = new char[msg->size]; msg->header.message_type = 9; EXPECT_TRUE(msg->header.is_video()); SrsSharedPtrMessage m; ASSERT_TRUE(ERROR_SUCCESS == m.create(msg)); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_message(m.copy(), 1)); } // copy output to input if (true) { bio.in_buffer.append(bio.out_buffer.bytes(), bio.out_buffer.length()); bio.out_buffer.erase(bio.out_buffer.length()); } // recv SrsSetWindowAckSizePacket if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); ASSERT_TRUE(msg->header.is_window_ackledgement_size()); } // recv video if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); ASSERT_TRUE(msg->header.is_video()); } // copy output to input if (true) { bio.in_buffer.append(bio.out_buffer.bytes(), bio.out_buffer.length()); bio.out_buffer.erase(bio.out_buffer.length()); } // recv auto send acked size. #1 if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); ASSERT_TRUE(msg->header.is_ackledgement()); } // send again if (true) { SrsCommonMessage* msg = new SrsCommonMessage(); msg->header.payload_length = msg->size = 4096; msg->payload = new char[msg->size]; msg->header.message_type = 9; EXPECT_TRUE(msg->header.is_video()); SrsSharedPtrMessage m; ASSERT_TRUE(ERROR_SUCCESS == m.create(msg)); EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_message(m.copy(), 1)); } // copy output to input if (true) { bio.in_buffer.append(bio.out_buffer.bytes(), bio.out_buffer.length()); bio.out_buffer.erase(bio.out_buffer.length()); } // recv video if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); ASSERT_TRUE(msg->header.is_video()); } // copy output to input if (true) { bio.in_buffer.append(bio.out_buffer.bytes(), bio.out_buffer.length()); bio.out_buffer.erase(bio.out_buffer.length()); } // recv auto send acked size. #2 if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); ASSERT_TRUE(msg->header.is_ackledgement()); } } /** * when recv ping message, server will response it auto. */ VOID TEST(ProtocolStackTest, ProtocolPingFlow) { MockBufferIO bio; SrsProtocol proto(&bio); // ping request if (true) { SrsUserControlPacket* pkt = new SrsUserControlPacket(); pkt->event_type = SrcPCUCPingRequest; pkt->event_data = 0x3456; EXPECT_TRUE(ERROR_SUCCESS == proto.send_and_free_packet(pkt, 0)); } // copy output to input if (true) { bio.in_buffer.append(bio.out_buffer.bytes(), bio.out_buffer.length()); bio.out_buffer.erase(bio.out_buffer.length()); } // recv ping if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); EXPECT_TRUE(msg->header.is_user_control_message()); } // recv the server auto send ping response message // copy output to input if (true) { bio.in_buffer.append(bio.out_buffer.bytes(), bio.out_buffer.length()); bio.out_buffer.erase(bio.out_buffer.length()); } // recv ping if (true) { SrsCommonMessage* msg = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg)); SrsAutoFree(SrsCommonMessage, msg); ASSERT_TRUE(msg->header.is_user_control_message()); SrsPacket* pkt = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.decode_message(msg, &pkt)); SrsUserControlPacket* spkt = dynamic_cast(pkt); ASSERT_TRUE(spkt != NULL); EXPECT_TRUE(SrcPCUCPingResponse == spkt->event_type); EXPECT_TRUE(0x3456 == spkt->event_data); } } /** * expect specified message */ VOID TEST(ProtocolStackTest, ProtocolExcpectMessage) { MockBufferIO bio; SrsProtocol proto(&bio); // packet is SrsConnectAppPacket uint8_t data[] = { // 12bytes header, 1byts chunk header, 11bytes msg heder 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa1, 0x14, 0x00, 0x00, 0x00, 0x00, // 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, 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, 0xC3, /*next chunk.*/ 0x0d, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x70, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, 0x02, 0x00, 0x62, 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, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3f, 0x76, 0x68, 0x6f, 0x73, 0x74, 0x3d, 0x64, 0x65, 0x76, 0x26, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3d, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x26, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3d, 0x64, 0x65, 0x76, 0x26, 0x70, 0x6f, 0x72, 0x74, 0xC3, /*next chunk.*/ 0x3d, 0x31, 0x39, 0x33, 0x35, 0x00, 0x0e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }; bio.in_buffer.append((char*)data, sizeof(data)); SrsCommonMessage* msg = NULL; SrsConnectAppPacket* pkt = NULL; ASSERT_TRUE(ERROR_SUCCESS == proto.expect_message(&msg, &pkt)); SrsAutoFree(SrsCommonMessage, msg); SrsAutoFree(SrsConnectAppPacket, pkt); ASSERT_TRUE(NULL != pkt); } VOID TEST(ProtocolRTMPTest, RTMPRequest) { SrsRequest req; std::string param; req.stream = "livestream"; srs_discovery_tc_url("rtmp://std.ossrs.net/live", req.schema, req.host, req.vhost, req.app, req.stream, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str()); EXPECT_STREQ("std.ossrs.net", req.vhost.c_str()); EXPECT_STREQ("live", req.app.c_str()); EXPECT_EQ(1935, req.port); req.stream = "livestream"; srs_discovery_tc_url("rtmp://s td.os srs.n et/li v e", req.schema, req.host, req.vhost, req.app, req.stream, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str()); EXPECT_STREQ("std.ossrs.net", req.vhost.c_str()); EXPECT_STREQ("live", req.app.c_str()); EXPECT_EQ(1935, req.port); req.stream = "livestream"; srs_discovery_tc_url("rtmp://s\ntd.o\rssrs.ne\nt/li\nve", req.schema, req.host, req.vhost, req.app, req.stream, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str()); EXPECT_STREQ("std.ossrs.net", req.vhost.c_str()); EXPECT_STREQ("live", req.app.c_str()); EXPECT_EQ(1935, req.port); req.stream = "livestream"; srs_discovery_tc_url("rtmp://std.ossrs.net/live ", req.schema, req.host, req.vhost, req.app, req.stream, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str()); EXPECT_STREQ("std.ossrs.net", req.vhost.c_str()); EXPECT_STREQ("live", req.app.c_str()); EXPECT_EQ(1935, req.port); EXPECT_TRUE(NULL == req.args); SrsRequest req1; req1.args = SrsAmf0Any::object(); req.update_auth(&req1); EXPECT_TRUE(NULL != req.args); EXPECT_TRUE(req1.args != req.args); } VOID TEST(ProtocolRTMPTest, RTMPHandshakeBytes) { MockBufferIO bio; SrsHandshakeBytes bytes; char hs[3073]; bio.in_buffer.append(hs, sizeof(hs)); bio.in_buffer.append(hs, sizeof(hs)); EXPECT_TRUE(ERROR_SUCCESS == bytes.read_c0c1(&bio)); EXPECT_TRUE(bytes.c0c1 != NULL); EXPECT_TRUE(ERROR_SUCCESS == bytes.read_c2(&bio)); EXPECT_TRUE(bytes.c2 != NULL); EXPECT_TRUE(ERROR_SUCCESS == bytes.read_s0s1s2(&bio)); 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, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(0, parser.parser->nread); EXPECT_EQ(5, 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, parser.parsed); EXPECT_EQ(1, 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, parser.parsed); EXPECT_EQ(0, parser.parser->nread); EXPECT_EQ(5, 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, parser.parsed); EXPECT_EQ(0, parser.parser->nread); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(0, parser.parser->nread); EXPECT_EQ(2, 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, parser.parsed); EXPECT_EQ(1, 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, parser.parsed); EXPECT_EQ(34, 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, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(41, 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, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(48, parser.parser->nread); // size = 27, nparsed = 27, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("\nContent-Length: 5\r\n\r\nHello")); EXPECT_EQ(27, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(68, parser.parser->nread); // size = 7, nparsed = 7, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("\r\nHello")); EXPECT_EQ(7, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(69, parser.parser->nread); // size = 6, nparsed = 6, nread = 0 HELPER_EXPECT_SUCCESS(parser.parse("\nHello")); EXPECT_EQ(6, parser.parsed); EXPECT_EQ(0, 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, parser.parsed); EXPECT_EQ(0, parser.parser->nread); } if (true) { MockParser parser; // nparsed = 2, size = 2, nread = 2 HELPER_EXPECT_SUCCESS(parser.parse("GE")); EXPECT_EQ(2, parser.parsed); EXPECT_EQ(2, parser.parser->nread); // size = 0, nparsed = 1, nread=2 HELPER_EXPECT_FAILED(parser.parse("")); EXPECT_EQ(1, parser.parsed); EXPECT_EQ(2, parser.parser->nread); } if (true) { MockParser parser; // size = 2, nparsed = 2, nread = 2 HELPER_EXPECT_SUCCESS(parser.parse("GE")); EXPECT_EQ(2, parser.parsed); EXPECT_EQ(2, parser.parser->nread); // size = 1, nparsed = 0, nread = 3 HELPER_EXPECT_FAILED(parser.parse("X")); EXPECT_EQ(0, parser.parsed); EXPECT_EQ(3, parser.parser->nread); } if (true) { MockParser parser; // size = 2, nparsed = 2, nread = 2 HELPER_EXPECT_SUCCESS(parser.parse("GE")); EXPECT_EQ(2, parser.parsed); EXPECT_EQ(2, parser.parser->nread); // size = 1, nparsed = 1, nread = 3 HELPER_EXPECT_SUCCESS(parser.parse("T")); EXPECT_EQ(1, parser.parsed); EXPECT_EQ(3, parser.parser->nread); } if (true) { MockParser parser; // size = 3, nparsed = 3, nread = 3 HELPER_EXPECT_SUCCESS(parser.parse("GET")); EXPECT_EQ(3, parser.parsed); EXPECT_EQ(3, parser.parser->nread); } } VOID TEST(ProtocolHTTPTest, ParseHTTPMessage) { if (true) { MockBufferIO bio; SrsHttpParser hp; bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello"); EXPECT_TRUE(0 == hp.initialize(HTTP_REQUEST, false)); ISrsHttpMessage* req = NULL; ASSERT_TRUE(0 == 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 ASSERT_FALSE(0 == hp.parse_message(&bio, &req)); srs_freep(req); } if (true) { MockBufferIO bio; SrsHttpParser hp; bio.append("GET"); EXPECT_TRUE(0 == hp.initialize(HTTP_REQUEST, false)); // Should fail if not completed message. ISrsHttpMessage* req = NULL; ASSERT_FALSE(0 == 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"); ASSERT_TRUE(0 == hp.initialize(HTTP_REQUEST, false)); ISrsHttpMessage* req = NULL; SrsAutoFree(ISrsHttpMessage, req); ASSERT_TRUE(0 == hp.parse_message(&bio, &req)); char v[64] = {0}; EXPECT_TRUE(0 == 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"); ASSERT_TRUE(0 == hp.initialize(HTTP_REQUEST, false)); ISrsHttpMessage* req = NULL; SrsAutoFree(ISrsHttpMessage, req); EXPECT_TRUE(0 == hp.parse_message(&bio, &req)); } if (true) { MockBufferIO bio; SrsHttpParser hp; bio.append("GET /gslb/v1/versions HTTP/1.1\r\n\r\n"); ASSERT_TRUE(0 == hp.initialize(HTTP_REQUEST, false)); ISrsHttpMessage* req = NULL; SrsAutoFree(ISrsHttpMessage, req); EXPECT_TRUE(0 == hp.parse_message(&bio, &req)); } if (true) { MockBufferIO bio; SrsHttpParser hp; bio.append("GET /gslb/v1/versions HTTP/1.1\r\n\r\n"); ASSERT_TRUE(0 == hp.initialize(HTTP_REQUEST, false)); ISrsHttpMessage* req = NULL; SrsAutoFree(ISrsHttpMessage, req); EXPECT_TRUE(0 == hp.parse_message(&bio, &req)); } } 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); 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); SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); SrsAutoFree(SrsKbps, 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); SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); SrsAutoFree(SrsKbps, 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, Delta) { if (true) { MockWallClock* clock = new MockWallClock(); SrsAutoFree(MockWallClock, clock); MockStatistic* io = new MockStatistic(); SrsAutoFree(MockStatistic, io); SrsKbps* conn = new SrsKbps(clock->set_clock(0)); SrsAutoFree(SrsKbps, conn); conn->set_io(io, io); // No data. ISrsKbpsDelta* delta = (ISrsKbpsDelta*)conn; 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); SrsKbps* conn = new SrsKbps(clock->set_clock(0)); SrsAutoFree(SrsKbps, conn); conn->set_io(io, io); // No data. ISrsKbpsDelta* delta = (ISrsKbpsDelta*)conn; 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); kbps->set_io(NULL, NULL); // 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); SrsKbps* conn = new SrsKbps(clock->set_clock(0)); SrsAutoFree(SrsKbps, conn); conn->set_io(io, io); SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); SrsAutoFree(SrsKbps, kbps); kbps->set_io(conn, conn); // 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); SrsKbps* kbps = new SrsKbps(clock->set_clock(0)); SrsAutoFree(SrsKbps, kbps); // No io, no data. kbps->set_io(NULL, NULL); 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); 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); 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); 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); EXPECT_EQ(100 * 1000, kbps->get_recv_bytes()); EXPECT_EQ(100 * 1000, kbps->get_send_bytes()); io->set_in(150 * 1000)->set_out(150 * 1000); EXPECT_EQ(150 * 1000, kbps->get_recv_bytes()); EXPECT_EQ(150 * 1000, kbps->get_send_bytes()); // No io, cached data. kbps->set_io(NULL, NULL); EXPECT_EQ(150 * 1000, kbps->get_recv_bytes()); EXPECT_EQ(150 * 1000, kbps->get_send_bytes()); } }