diff --git a/README.md b/README.md index 1efa2d29d..7199fa5a0 100755 --- a/README.md +++ b/README.md @@ -145,6 +145,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2019-12-11, For [#1042][bug #1042], cover RTMP handshake protocol. * v3.0, 2019-12-11, Fix [#1229][bug #1229], fix the security risk in logger. 3.0.69 * v3.0, 2019-12-11, For [#1229][bug #1229], fix the security risk in HDS. 3.0.69 * v3.0, 2019-12-05, Fix [#1506][bug #1501], support directly turn FLV timestamp to TS DTS. 3.0.68 @@ -1513,6 +1514,7 @@ Winlin [bug #1093]: https://github.com/ossrs/srs/issues/1093 [bug #1501]: https://github.com/ossrs/srs/issues/1501 [bug #1229]: https://github.com/ossrs/srs/issues/1229 +[bug #1042]: https://github.com/ossrs/srs/issues/1042 [bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 0099d5791..f2009a477 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -1671,7 +1671,7 @@ void SrsHandshakeBytes::dispose() srs_freepa(c2); } -srs_error_t SrsHandshakeBytes::read_c0c1(ISrsProtocolReadWriter* io) +srs_error_t SrsHandshakeBytes::read_c0c1(ISrsProtocolReader* io) { srs_error_t err = srs_success; @@ -1709,7 +1709,7 @@ srs_error_t SrsHandshakeBytes::read_c0c1(ISrsProtocolReadWriter* io) return err; } -srs_error_t SrsHandshakeBytes::read_s0s1s2(ISrsProtocolReadWriter* io) +srs_error_t SrsHandshakeBytes::read_s0s1s2(ISrsProtocolReader* io) { srs_error_t err = srs_success; @@ -1727,7 +1727,7 @@ srs_error_t SrsHandshakeBytes::read_s0s1s2(ISrsProtocolReadWriter* io) return err; } -srs_error_t SrsHandshakeBytes::read_c2(ISrsProtocolReadWriter* io) +srs_error_t SrsHandshakeBytes::read_c2(ISrsProtocolReader* io) { srs_error_t err = srs_success; diff --git a/trunk/src/protocol/srs_rtmp_stack.hpp b/trunk/src/protocol/srs_rtmp_stack.hpp index db8dce3db..b1ffadebd 100644 --- a/trunk/src/protocol/srs_rtmp_stack.hpp +++ b/trunk/src/protocol/srs_rtmp_stack.hpp @@ -49,6 +49,7 @@ class SrsChunkStream; class SrsSharedPtrMessage; class SrsProtocol; +class ISrsProtocolReader; class ISrsProtocolReadWriter; class SrsCreateStreamPacket; class SrsFMLEStartPacket; @@ -514,9 +515,9 @@ public: public: virtual void dispose(); public: - virtual srs_error_t read_c0c1(ISrsProtocolReadWriter* io); - virtual srs_error_t read_s0s1s2(ISrsProtocolReadWriter* io); - virtual srs_error_t read_c2(ISrsProtocolReadWriter* io); + virtual srs_error_t read_c0c1(ISrsProtocolReader* io); + virtual srs_error_t read_s0s1s2(ISrsProtocolReader* io); + virtual srs_error_t read_c2(ISrsProtocolReader* io); virtual srs_error_t create_c0c1(); virtual srs_error_t create_s0s1s2(const char* c1 = NULL); virtual srs_error_t create_c2(); diff --git a/trunk/src/utest/srs_utest.hpp b/trunk/src/utest/srs_utest.hpp index c18f178ae..9eaf6fc81 100644 --- a/trunk/src/utest/srs_utest.hpp +++ b/trunk/src/utest/srs_utest.hpp @@ -52,6 +52,10 @@ extern srs_utime_t _srs_tmp_timeout; #define HELPER_EXPECT_SUCCESS(x) EXPECT_TRUE(srs_success == (err = x)); srs_freep(err) #define HELPER_EXPECT_FAILED(x) EXPECT_TRUE(srs_success != (err = x)); srs_freep(err) +// For init array data. +#define HELPER_ARRAY_INIT(buf, sz, val) \ + for (int i = 0; i < (int)sz; i++) (buf)[i]=val + // the asserts of gtest: // * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual // * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 diff --git a/trunk/src/utest/srs_utest_core.cpp b/trunk/src/utest/srs_utest_core.cpp index 202ef3362..1c5339a3c 100644 --- a/trunk/src/utest/srs_utest_core.cpp +++ b/trunk/src/utest/srs_utest_core.cpp @@ -64,14 +64,11 @@ VOID TEST(CoreMacroseTest, Check) #endif } -#define _ARRAY_INIT(buf, sz, val) \ - for (int i = 0; i < (int)sz; i++) buf[i]=val - VOID TEST(CoreLogger, CheckVsnprintf) { if (true) { char buf[1024]; - _ARRAY_INIT(buf, sizeof(buf), 0xf); + HELPER_ARRAY_INIT(buf, sizeof(buf), 0xf); // Return the number of characters printed. EXPECT_EQ(6, sprintf(buf, "%s", "Hello!")); @@ -83,7 +80,7 @@ VOID TEST(CoreLogger, CheckVsnprintf) if (true) { char buf[1024]; - _ARRAY_INIT(buf, sizeof(buf), 0xf); + HELPER_ARRAY_INIT(buf, sizeof(buf), 0xf); // Return the number of characters that would have been printed if the size were unlimited. EXPECT_EQ(6, snprintf(buf, 3, "%s", "Hello!")); diff --git a/trunk/src/utest/srs_utest_protocol.cpp b/trunk/src/utest/srs_utest_protocol.cpp index 645e53296..c61649934 100644 --- a/trunk/src/utest/srs_utest_protocol.cpp +++ b/trunk/src/utest/srs_utest_protocol.cpp @@ -108,6 +108,22 @@ MockBufferIO* MockBufferIO::append(string data) return this; } +MockBufferIO* MockBufferIO::append(uint8_t* data, int size) +{ + in_buffer.append((char*)data, size); + return this; +} + +int MockBufferIO::in_length() +{ + return in_buffer.length(); +} + +int MockBufferIO::out_length() +{ + return out_buffer.length(); +} + srs_error_t MockBufferIO::read_fully(void* buf, size_t size, ssize_t* nread) { if (in_err != srs_success) { diff --git a/trunk/src/utest/srs_utest_protocol.hpp b/trunk/src/utest/srs_utest_protocol.hpp index f009e10e6..ed782bd88 100644 --- a/trunk/src/utest/srs_utest_protocol.hpp +++ b/trunk/src/utest/srs_utest_protocol.hpp @@ -88,6 +88,9 @@ public: virtual ~MockBufferIO(); public: virtual MockBufferIO* append(std::string data); + virtual MockBufferIO* append(uint8_t* data, int size); + virtual int in_length(); + virtual int out_length(); // for handshake. public: virtual srs_error_t read_fully(void* buf, size_t size, ssize_t* nread); diff --git a/trunk/src/utest/srs_utest_protostack.cpp b/trunk/src/utest/srs_utest_protostack.cpp index 64a0ce711..9a220e78f 100644 --- a/trunk/src/utest/srs_utest_protostack.cpp +++ b/trunk/src/utest/srs_utest_protostack.cpp @@ -1265,3 +1265,188 @@ VOID TEST(ProtoStackTest, RecvMessage4) } } +VOID TEST(ProtoStackTest, HandshakeC0C1) +{ + srs_error_t err; + + // Fail for empty io. + if (true) { + MockBufferIO io; + SrsHandshakeBytes hs; + HELPER_EXPECT_FAILED(hs.read_c0c1(&io)); + } + + // It's normal c0c1, so it should be ok. + if (true) { + uint8_t buf[1537]; + HELPER_ARRAY_INIT(buf, 1537, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_SUCCESS(hs.read_c0c1(&io)); + } + + // It's extended c0c1 prefixed with ip, which should be ok. + if (true) { + uint8_t buf[1537 + 7] = { + 0xF3, 0x00, 0x04, + 0x01, 0x02, 0x03, 0x04, + }; + HELPER_ARRAY_INIT(buf+7, 1537, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_SUCCESS(hs.read_c0c1(&io)); + EXPECT_EQ(0x01020304, hs.proxy_real_ip); + } + + // It seems a normal c0c1, but it's extended, so it fail. + if (true) { + uint8_t buf[1537] = { + 0xF3, 0x04, 0x01, + 0x01, 0x02, 0x03, 0x04, + }; + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_FAILED(hs.read_c0c1(&io)); + } + + // For extended c0c1, it fail for not enough bytes. + if (true) { + uint8_t buf[7 + 1537 - 1] = { + 0xF3, 0x00, 0x04, + 0x01, 0x02, 0x03, 0x04, + }; + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_FAILED(hs.read_c0c1(&io)); + } + + // Ignore when c0c1 exists. + if (true) { + uint8_t buf[1537]; + HELPER_ARRAY_INIT(buf, 1537, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_SUCCESS(hs.read_c0c1(&io)); + + io.append(buf, sizeof(buf)); + HELPER_EXPECT_SUCCESS(hs.read_c0c1(&io)); + EXPECT_EQ(1537, io.in_length()); + } +} + +VOID TEST(ProtoStackTest, HandshakeS0S1S2) +{ + srs_error_t err; + + // It should be ok for normal s0s1s2. + if (true) { + uint8_t buf[3073]; + HELPER_ARRAY_INIT(buf, 3073, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_SUCCESS(hs.read_s0s1s2(&io)); + } + + // Fail for not enough data. + if (true) { + uint8_t buf[3073-1]; + HELPER_ARRAY_INIT(buf, 3073-1, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_FAILED(hs.read_s0s1s2(&io)); + } + + // Ignore for s0s1s2 exists. + if (true) { + uint8_t buf[3073]; + HELPER_ARRAY_INIT(buf, 3073, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_SUCCESS(hs.read_s0s1s2(&io)); + + io.append(buf, sizeof(buf)); + HELPER_EXPECT_SUCCESS(hs.read_s0s1s2(&io)); + EXPECT_EQ(3073, io.in_length()); + } +} + +VOID TEST(ProtoStackTest, HandshakeC2) +{ + srs_error_t err; + + // It should be ok for normal c2. + if (true) { + uint8_t buf[1536]; + HELPER_ARRAY_INIT(buf, 1536, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_SUCCESS(hs.read_c2(&io)); + } + + // Fail for not enough bytes. + if (true) { + uint8_t buf[1536-1]; + HELPER_ARRAY_INIT(buf, 1536-1, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_FAILED(hs.read_c2(&io)); + } + + // Ignore when c2 exists. + if (true) { + uint8_t buf[1536]; + HELPER_ARRAY_INIT(buf, 1536, 0x00); + + MockBufferIO io; + io.append(buf, sizeof(buf)); + + SrsHandshakeBytes hs; + HELPER_EXPECT_SUCCESS(hs.read_c2(&io)); + + io.append(buf, sizeof(buf)); + HELPER_EXPECT_SUCCESS(hs.read_c2(&io)); + EXPECT_EQ(1536, io.in_buffer.length()); + } +} + +VOID TEST(ProtoStackTest, ServerInfo) +{ + SrsServerInfo si; + EXPECT_EQ(0, si.pid); + EXPECT_EQ(0, si.cid); + EXPECT_EQ(0, si.major); + EXPECT_EQ(0, si.minor); + EXPECT_EQ(0, si.revision); + EXPECT_EQ(0, si.build); +} +