From 265b70863c750570432396e3bf0c80d1febe737e Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 18:37:20 +0800 Subject: [PATCH 1/8] Improve test coverage for service TCP/UDP. --- trunk/src/service/srs_service_st.cpp | 89 ++++++---- trunk/src/utest/srs_utest_service.cpp | 237 ++++++++++++++++++++++++++ trunk/src/utest/srs_utest_service.hpp | 2 + 3 files changed, 292 insertions(+), 36 deletions(-) diff --git a/trunk/src/service/srs_service_st.cpp b/trunk/src/service/srs_service_st.cpp index 512ec563c..30f8b120c 100644 --- a/trunk/src/service/srs_service_st.cpp +++ b/trunk/src/service/srs_service_st.cpp @@ -187,6 +187,43 @@ srs_error_t srs_tcp_connect(string server, int port, srs_utime_t tm, srs_netfd_t return srs_success; } +srs_error_t do_srs_tcp_listen(int fd, addrinfo* r, srs_netfd_t* pfd) +{ + srs_error_t err = srs_success; + + // Detect alive for TCP connection. + // @see https://github.com/ossrs/srs/issues/1044 + if ((err = srs_fd_keepalive(fd)) != srs_success) { + return srs_error_wrap(err, "set keepalive"); + } + + if ((err = srs_fd_closeexec(fd)) != srs_success) { + return srs_error_wrap(err, "set closeexec"); + } + + if ((err = srs_fd_reuseaddr(fd)) != srs_success) { + return srs_error_wrap(err, "set reuseaddr"); + } + + if ((err = srs_fd_reuseport(fd)) != srs_success) { + return srs_error_wrap(err, "set reuseport"); + } + + if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) { + return srs_error_new(ERROR_SOCKET_BIND, "bind"); + } + + if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) { + return srs_error_new(ERROR_SOCKET_LISTEN, "listen"); + } + + if ((*pfd = srs_netfd_open_socket(fd)) == NULL){ + return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open"); + } + + return err; +} + srs_error_t srs_tcp_listen(std::string ip, int port, srs_netfd_t* pfd) { srs_error_t err = srs_success; @@ -213,41 +250,41 @@ srs_error_t srs_tcp_listen(std::string ip, int port, srs_netfd_t* pfd) r->ai_family, r->ai_socktype, r->ai_protocol); } - // Detect alive for TCP connection. - // @see https://github.com/ossrs/srs/issues/1044 - if ((err = srs_fd_keepalive(fd)) != srs_success) { + if ((err = do_srs_tcp_listen(fd, r, pfd)) != srs_success) { ::close(fd); - return srs_error_wrap(err, "set keepalive fd=%d", fd); + return srs_error_wrap(err, "fd=%d", fd); } + return err; +} + +srs_error_t do_srs_udp_listen(int fd, addrinfo* r, srs_netfd_t* pfd) +{ + srs_error_t err = srs_success; + if ((err = srs_fd_closeexec(fd)) != srs_success) { ::close(fd); - return srs_error_wrap(err, "set closeexec fd=%d", fd); + return srs_error_wrap(err, "set closeexec"); } if ((err = srs_fd_reuseaddr(fd)) != srs_success) { ::close(fd); - return srs_error_wrap(err, "set reuseaddr fd=%d", fd); + return srs_error_wrap(err, "set reuseaddr"); } if ((err = srs_fd_reuseport(fd)) != srs_success) { ::close(fd); - return srs_error_wrap(err, "set reuseport fd=%d", fd); + return srs_error_wrap(err, "set reuseport"); } if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) { ::close(fd); - return srs_error_new(ERROR_SOCKET_BIND, "bind fd=%d", fd); - } - - if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) { - ::close(fd); - return srs_error_new(ERROR_SOCKET_LISTEN, "listen fd=%d", fd); + return srs_error_new(ERROR_SOCKET_BIND, "bind"); } if ((*pfd = srs_netfd_open_socket(fd)) == NULL){ ::close(fd); - return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open fd=%d", fd); + return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open"); } return err; @@ -279,29 +316,9 @@ srs_error_t srs_udp_listen(std::string ip, int port, srs_netfd_t* pfd) r->ai_family, r->ai_socktype, r->ai_protocol); } - if ((err = srs_fd_closeexec(fd)) != srs_success) { + if ((err = do_srs_udp_listen(fd, r, pfd)) != srs_success) { ::close(fd); - return srs_error_wrap(err, "set closeexec fd=%d", fd); - } - - if ((err = srs_fd_reuseaddr(fd)) != srs_success) { - ::close(fd); - return srs_error_wrap(err, "set reuseaddr fd=%d", fd); - } - - if ((err = srs_fd_reuseport(fd)) != srs_success) { - ::close(fd); - return srs_error_wrap(err, "set reuseport fd=%d", fd); - } - - if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) { - ::close(fd); - return srs_error_new(ERROR_SOCKET_BIND, "bind fd=%d", fd); - } - - if ((*pfd = srs_netfd_open_socket(fd)) == NULL){ - ::close(fd); - return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open fd=%d", fd); + return srs_error_wrap(err, "fd=%d", fd); } return err; diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index 9307ab48f..d42abd43d 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -679,3 +679,240 @@ VOID TEST(TCPServerTest, MessageWritev) } } +VOID TEST(TCPServerTest, TCPListen) +{ + srs_error_t err; + + // Failed for invalid ip. + if (true) { + srs_netfd_t pfd = NULL; + HELPER_EXPECT_FAILED(srs_tcp_listen("10.0.0.abc", 1935, &pfd)); + srs_close_stfd(pfd); + } + + // If listen multiple times, should success for we already set the REUSEPORT. + if (true) { + srs_netfd_t pfd = NULL; + HELPER_ASSERT_SUCCESS(srs_tcp_listen("127.0.0.1", 1935, &pfd)); + + srs_netfd_t pfd2 = NULL; + srs_error_t err2 = srs_tcp_listen("127.0.0.1", 1935, &pfd2); + + srs_close_stfd(pfd); + srs_close_stfd(pfd2); + HELPER_EXPECT_SUCCESS(err2); + } + + // Typical listen. + if (true) { + srs_netfd_t pfd = NULL; + HELPER_ASSERT_SUCCESS(srs_tcp_listen("127.0.0.1", 1935, &pfd)); + srs_close_stfd(pfd); + } +} + +VOID TEST(TCPServerTest, UDPListen) +{ + srs_error_t err; + + // Failed for invalid ip. + if (true) { + srs_netfd_t pfd = NULL; + HELPER_EXPECT_FAILED(srs_udp_listen("10.0.0.abc", 1935, &pfd)); + srs_close_stfd(pfd); + } + + // If listen multiple times, should success for we already set the REUSEPORT. + if (true) { + srs_netfd_t pfd = NULL; + HELPER_ASSERT_SUCCESS(srs_udp_listen("127.0.0.1", 1935, &pfd)); + + srs_netfd_t pfd2 = NULL; + srs_error_t err2 = srs_udp_listen("127.0.0.1", 1935, &pfd2); + + srs_close_stfd(pfd); + srs_close_stfd(pfd2); + HELPER_EXPECT_SUCCESS(err2); + } + + // Typical listen. + if (true) { + srs_netfd_t pfd = NULL; + HELPER_ASSERT_SUCCESS(srs_udp_listen("127.0.0.1", 1935, &pfd)); + srs_close_stfd(pfd); + } +} + +class MockOnCycleThread : public ISrsCoroutineHandler +{ +public: + SrsSTCoroutine trd; + srs_cond_t cond; + MockOnCycleThread() : trd("mock", this, 0) { + cond = srs_cond_new(); + }; + virtual ~MockOnCycleThread() { + srs_cond_destroy(cond); + } + virtual srs_error_t cycle() { + srs_error_t err = srs_success; + + for (;;) { + srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_cond_signal(cond); + // If no one waiting on the cond, directly return event signal more than one time. + // If someone waiting, signal them more than one time. + srs_cond_signal(cond); + + if ((err = trd.pull()) != srs_success) { + return err; + } + } + + return err; + } +}; + +VOID TEST(TCPServerTest, ThreadCondWait) +{ + MockOnCycleThread trd; + trd.trd.start(); + + srs_usleep(20 * SRS_UTIME_MILLISECONDS); + srs_cond_wait(trd.cond); + trd.trd.stop(); +} + +class MockOnCycleThread2 : public ISrsCoroutineHandler +{ +public: + SrsSTCoroutine trd; + srs_mutex_t lock; + MockOnCycleThread2() : trd("mock", this, 0) { + lock = srs_mutex_new(); + }; + virtual ~MockOnCycleThread2() { + srs_mutex_destroy(lock); + } + virtual srs_error_t cycle() { + srs_error_t err = srs_success; + + for (;;) { + srs_mutex_lock(lock); + srs_usleep(10 * SRS_UTIME_MILLISECONDS); + srs_mutex_unlock(lock); + + srs_error_t err = trd.pull(); + if (err != srs_success) { + return err; + } + } + + return err; + } +}; + +VOID TEST(TCPServerTest, ThreadMutexWait) +{ + MockOnCycleThread2 trd; + trd.trd.start(); + + srs_usleep(20 * SRS_UTIME_MILLISECONDS); + + srs_mutex_lock(trd.lock); + trd.trd.stop(); + srs_mutex_unlock(trd.lock); +} + +class MockOnCycleThread3 : public ISrsCoroutineHandler +{ +public: + SrsSTCoroutine trd; + srs_netfd_t fd; + MockOnCycleThread3() : trd("mock", this, 0) { + }; + virtual ~MockOnCycleThread3() { + trd.stop(); + srs_close_stfd(fd); + } + virtual srs_error_t start(string ip, int port) { + srs_error_t err = srs_success; + if ((err = srs_tcp_listen(ip, port, &fd)) != srs_success) { + return err; + } + + return trd.start(); + } + virtual srs_error_t do_cycle(srs_netfd_t cfd) { + srs_error_t err = srs_success; + + SrsStSocket skt; + if ((err = skt.initialize(cfd)) != srs_success) { + return err; + } + + skt.set_recv_timeout(1 * SRS_UTIME_SECONDS); + skt.set_send_timeout(1 * SRS_UTIME_SECONDS); + + while (true) { + if ((err = trd.pull()) != srs_success) { + return err; + } + + char buf[5]; + if ((err = skt.read_fully(buf, 5, NULL)) != srs_success) { + return err; + } + if ((err = skt.write(buf, 5, NULL)) != srs_success) { + return err; + } + } + + return err; + } + virtual srs_error_t cycle() { + srs_error_t err = srs_success; + + srs_netfd_t cfd = srs_accept(fd, NULL, NULL, SRS_UTIME_NO_TIMEOUT); + if (cfd == NULL) { + return err; + } + + err = do_cycle(cfd); + srs_close_stfd(cfd); + srs_freep(err); + + return err; + } +}; + +VOID TEST(TCPServerTest, TCPClientServer) +{ + srs_error_t err; + + MockOnCycleThread3 trd; + HELPER_ASSERT_SUCCESS(trd.start("127.0.0.1", 1935)); + + SrsTcpClient c("127.0.0.1", 1935, 1 * SRS_UTIME_SECONDS); + HELPER_ASSERT_SUCCESS(c.connect()); + + c.set_recv_timeout(1 * SRS_UTIME_SECONDS); + c.set_send_timeout(1 * SRS_UTIME_SECONDS); + + if (true) { + HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL)); + + char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0); + HELPER_ASSERT_SUCCESS(c.read(buf, 5, NULL)); + EXPECT_STREQ("Hello", buf); + } + + if (true) { + HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL)); + + char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0); + HELPER_ASSERT_SUCCESS(c.read_fully(buf, 5, NULL)); + EXPECT_STREQ("Hello", buf); + } +} + diff --git a/trunk/src/utest/srs_utest_service.hpp b/trunk/src/utest/srs_utest_service.hpp index 819272dc6..995b75e83 100644 --- a/trunk/src/utest/srs_utest_service.hpp +++ b/trunk/src/utest/srs_utest_service.hpp @@ -29,5 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +#include + #endif From 02c1bd0946fe44119d51187602f3d1e6a9a0698c Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 18:42:37 +0800 Subject: [PATCH 2/8] Improve test coverage for service TCP/UDP. --- trunk/src/service/srs_service_st.cpp | 5 ----- trunk/src/utest/srs_utest_service.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/trunk/src/service/srs_service_st.cpp b/trunk/src/service/srs_service_st.cpp index 30f8b120c..00d1b4380 100644 --- a/trunk/src/service/srs_service_st.cpp +++ b/trunk/src/service/srs_service_st.cpp @@ -263,27 +263,22 @@ srs_error_t do_srs_udp_listen(int fd, addrinfo* r, srs_netfd_t* pfd) srs_error_t err = srs_success; if ((err = srs_fd_closeexec(fd)) != srs_success) { - ::close(fd); return srs_error_wrap(err, "set closeexec"); } if ((err = srs_fd_reuseaddr(fd)) != srs_success) { - ::close(fd); return srs_error_wrap(err, "set reuseaddr"); } if ((err = srs_fd_reuseport(fd)) != srs_success) { - ::close(fd); return srs_error_wrap(err, "set reuseport"); } if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) { - ::close(fd); return srs_error_new(ERROR_SOCKET_BIND, "bind"); } if ((*pfd = srs_netfd_open_socket(fd)) == NULL){ - ::close(fd); return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open"); } diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index d42abd43d..f573ccc12 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -914,5 +914,13 @@ VOID TEST(TCPServerTest, TCPClientServer) HELPER_ASSERT_SUCCESS(c.read_fully(buf, 5, NULL)); EXPECT_STREQ("Hello", buf); } + + if (true) { + HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL)); + + char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0); + HELPER_ASSERT_SUCCESS(srs_read(c.stfd, buf, 5, NULL)); + EXPECT_STREQ("Hello", buf); + } } From 42ee6570a79dfa0afbb8c088bf56184ef3a8b775 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 18:43:23 +0800 Subject: [PATCH 3/8] Improve test coverage for service TCP/UDP. --- trunk/src/utest/srs_utest_service.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index f573ccc12..099f7e7ea 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -919,7 +919,7 @@ VOID TEST(TCPServerTest, TCPClientServer) HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL)); char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0); - HELPER_ASSERT_SUCCESS(srs_read(c.stfd, buf, 5, NULL)); + HELPER_ASSERT_SUCCESS(srs_read(c.stfd, buf, 5, 1*SRS_UTIME_SECONDS)); EXPECT_STREQ("Hello", buf); } } From 498f3c5df97e17ddee604ff29cba2e5370f768f0 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 18:44:07 +0800 Subject: [PATCH 4/8] Improve test coverage for service TCP/UDP. --- trunk/src/utest/srs_utest_service.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index 099f7e7ea..d58638105 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -919,7 +919,7 @@ VOID TEST(TCPServerTest, TCPClientServer) HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL)); char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0); - HELPER_ASSERT_SUCCESS(srs_read(c.stfd, buf, 5, 1*SRS_UTIME_SECONDS)); + ASSERT_EQ(5, srs_read(c.stfd, buf, 5, 1*SRS_UTIME_SECONDS)); EXPECT_STREQ("Hello", buf); } } From bc6c61e546c5f4976703c8e5e2cead57f7e44721 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 20:06:25 +0800 Subject: [PATCH 5/8] Fix #1543, use getpeername to retrieve client ip. 3.0.92 --- README.md | 2 + trunk/src/app/srs_app_utility.cpp | 2 +- trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_utility.cpp | 2 +- trunk/src/utest/srs_utest_service.cpp | 58 +++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 75e58cbbd..d755bd761 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2020-01-05, For [#1543][bug #1543], use getpeername to retrieve client ip. 3.0.92 * v3.0, 2020-01-02, For [#1042][bug #1042], improve test coverage for config. 3.0.91 * v3.0, 2019-12-30, Fix mp4 security issue, check buffer when required size is variable. * v3.0, 2019-12-29, [3.0 alpha7(3.0.90)][r3.0a7] released. 116356 lines. @@ -1581,6 +1582,7 @@ Winlin [bug #1105]: https://github.com/ossrs/srs/issues/1105 [bug #1544]: https://github.com/ossrs/srs/issues/1544 [bug #1255]: https://github.com/ossrs/srs/issues/1255 +[bug #1543]: https://github.com/ossrs/srs/issues/1543 [bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index 9374f4e4b..d82dfdf6a 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -1142,7 +1142,7 @@ string srs_get_peer_ip(int fd) // discovery client information sockaddr_storage addr; socklen_t addrlen = sizeof(addr); - if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) { + if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) { return ""; } diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 06f93f5cb..10dbe06ca 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -27,7 +27,7 @@ // The version config. #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_REVISION 91 +#define VERSION_REVISION 92 // The macros generated by configure script. #include diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 1a38c7e1e..1cab2c969 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -183,11 +183,11 @@ string srs_dns_resolve(string host, int& family) char* h = (char*)saddr; socklen_t nbh = sizeof(saddr); const int r0 = getnameinfo(r->ai_addr, r->ai_addrlen, h, nbh, NULL, 0, NI_NUMERICHOST); - if(!r0) { family = r->ai_family; return string(saddr); } + return ""; } diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index d58638105..c4dda4dd6 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -35,6 +35,7 @@ using namespace std; #include #include #include +#include class MockSrsConnection : public ISrsConnection { @@ -924,3 +925,60 @@ VOID TEST(TCPServerTest, TCPClientServer) } } +VOID TEST(TCPServerTest, CoverUtility) +{ + EXPECT_TRUE(srs_string_is_http("http://")); + EXPECT_TRUE(srs_string_is_http("https://")); + EXPECT_TRUE(srs_string_is_http("http://localhost")); + EXPECT_TRUE(srs_string_is_http("https://localhost")); + EXPECT_FALSE(srs_string_is_http("ftp://")); + EXPECT_FALSE(srs_string_is_http("ftps://")); + EXPECT_FALSE(srs_string_is_http("http:")); + EXPECT_FALSE(srs_string_is_http("https:")); + EXPECT_TRUE(srs_string_is_rtmp("rtmp://")); + EXPECT_TRUE(srs_string_is_rtmp("rtmp://localhost")); + EXPECT_FALSE(srs_string_is_rtmp("http://")); + EXPECT_FALSE(srs_string_is_rtmp("rtmp:")); + + if (true) { + sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + } + + EXPECT_FALSE(srs_net_device_is_internet("eth0")); + + if (true) { + sockaddr_in addr; + addr.sin_family = AF_INET; + + addr.sin_addr.s_addr = htonl(0x12000000); + EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0x7f000000); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0x7f000001); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0x0a000000); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0x0a000001); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0x0affffff); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0xc0a80000); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0xc0a80001); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + + addr.sin_addr.s_addr = htonl(0xc0a8ffff); + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + } +} + From 76d92792b78ecd9afbcc9d33be75a35e069156e4 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 21:25:51 +0800 Subject: [PATCH 6/8] For #460, fix ipv6 intranet address filter bug. 3.0.93 --- README.md | 1 + trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_mp4.hpp | 4 +- trunk/src/kernel/srs_kernel_utility.cpp | 19 ++-- trunk/src/service/srs_service_st.cpp | 2 +- trunk/src/service/srs_service_utility.cpp | 24 ++++- trunk/src/utest/srs_utest_kernel.cpp | 8 ++ trunk/src/utest/srs_utest_service.cpp | 105 +++++++++++++++++++++- 8 files changed, 144 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index d755bd761..629d93211 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 intranet address filter bug. 3.0.93 * v3.0, 2020-01-05, For [#1543][bug #1543], use getpeername to retrieve client ip. 3.0.92 * v3.0, 2020-01-02, For [#1042][bug #1042], improve test coverage for config. 3.0.91 * v3.0, 2019-12-30, Fix mp4 security issue, check buffer when required size is variable. diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 10dbe06ca..2ddb51420 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -27,7 +27,7 @@ // The version config. #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_REVISION 92 +#define VERSION_REVISION 93 // The macros generated by configure script. #include diff --git a/trunk/src/kernel/srs_kernel_mp4.hpp b/trunk/src/kernel/srs_kernel_mp4.hpp index 6d06ea106..161f2c032 100644 --- a/trunk/src/kernel/srs_kernel_mp4.hpp +++ b/trunk/src/kernel/srs_kernel_mp4.hpp @@ -2169,7 +2169,7 @@ std::stringstream& srs_dumps_array(std::vector&arr, std::stringstream& ss, Sr pfn(elem, ss, dc); - if (i < limit - 1) { + if ((int)i < limit - 1) { delimiter(ss, dc); } } @@ -2192,7 +2192,7 @@ std::stringstream& srs_dumps_array(T* arr, int size, std::stringstream& ss, SrsM pfn(elem, ss, dc); - if (i < limit - 1) { + if ((int)i < limit - 1) { delimiter(ss, dc); } } diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 1cab2c969..1d091338e 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -170,25 +170,22 @@ string srs_dns_resolve(string host, int& family) { addrinfo hints; memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; + hints.ai_family = family; addrinfo* r = NULL; SrsAutoFree(addrinfo, r); - - if(getaddrinfo(host.c_str(), NULL, NULL, &r)) { + if(getaddrinfo(host.c_str(), NULL, &hints, &r)) { return ""; } - char saddr[64]; - char* h = (char*)saddr; - socklen_t nbh = sizeof(saddr); - const int r0 = getnameinfo(r->ai_addr, r->ai_addrlen, h, nbh, NULL, 0, NI_NUMERICHOST); - if(!r0) { - family = r->ai_family; - return string(saddr); + char shost[64]; + memset(shost, 0, sizeof(shost)); + if (getnameinfo(r->ai_addr, r->ai_addrlen, shost, sizeof(shost), NULL, 0, NI_NUMERICHOST)) { + return ""; } - return ""; + family = r->ai_family; + return string(shost); } void srs_parse_hostport(const string& hostport, string& host, int& port) diff --git a/trunk/src/service/srs_service_st.cpp b/trunk/src/service/srs_service_st.cpp index 00d1b4380..6cd04ba93 100644 --- a/trunk/src/service/srs_service_st.cpp +++ b/trunk/src/service/srs_service_st.cpp @@ -157,7 +157,7 @@ srs_error_t srs_tcp_connect(string server, int port, srs_utime_t tm, srs_netfd_t addrinfo hints; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; addrinfo* r = NULL; diff --git a/trunk/src/service/srs_service_utility.cpp b/trunk/src/service/srs_service_utility.cpp index cc3eade17..4d19133f4 100644 --- a/trunk/src/service/srs_service_utility.cpp +++ b/trunk/src/service/srs_service_utility.cpp @@ -115,8 +115,28 @@ bool srs_net_device_is_internet(const sockaddr* addr) } } else if(addr->sa_family == AF_INET6) { const sockaddr_in6* a6 = (const sockaddr_in6*)addr; - if ((IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr)) || - (IN6_IS_ADDR_SITELOCAL(&a6->sin6_addr))) { + + // IPv6 loopback is ::1 + if (IN6_IS_ADDR_LOOPBACK(&a6->sin6_addr)) { + return false; + } + + // IPv6 unspecified is :: + if (IN6_IS_ADDR_UNSPECIFIED(&a6->sin6_addr)) { + return false; + } + + // From IPv4, you might know APIPA (Automatic Private IP Addressing) or AutoNet. + // Whenever automatic IP configuration through DHCP fails. + // The prefix of a site-local address is FE80::/10. + if (IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr)) { + return false; + } + + // Site-local addresses are equivalent to private IP addresses in IPv4. + // The prefix of a site-local address is FEC0::/10. + // https://4sysops.com/archives/ipv6-tutorial-part-6-site-local-addresses-and-link-local-addresses/ + if (IN6_IS_ADDR_SITELOCAL(&a6->sin6_addr)) { return false; } } diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 8f62186cc..9868749d5 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -4253,6 +4253,14 @@ VOID TEST(KernelUtilityTest, CoverTimeUtilityAll) _srs_system_time_us_cache -= 300*1000 * 1000 + 1; EXPECT_TRUE(srs_update_system_time() > 0); + + if (true) { + string host; + int port = 8080; + srs_parse_hostport("3ffe:dead:beef::1", host, port); + EXPECT_EQ(8080, port); + EXPECT_STREQ("3ffe:dead:beef::1", host.c_str()); + } if (true) { string host; diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index c4dda4dd6..e75f7285d 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -36,6 +36,8 @@ using namespace std; #include #include #include +#include +#include class MockSrsConnection : public ISrsConnection { @@ -940,11 +942,30 @@ VOID TEST(TCPServerTest, CoverUtility) EXPECT_FALSE(srs_string_is_rtmp("http://")); EXPECT_FALSE(srs_string_is_rtmp("rtmp:")); + // ipv4 loopback if (true) { - sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("127.0.0.1", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // ipv4 intranet + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("192.168.0.1", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); } EXPECT_FALSE(srs_net_device_is_internet("eth0")); @@ -980,5 +1001,81 @@ VOID TEST(TCPServerTest, CoverUtility) addr.sin_addr.s_addr = htonl(0xc0a8ffff); EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr)); } + + // Normal ipv6 address. + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("2001:da8:6000:291:21f:d0ff:fed4:928c", NULL, &hints, &r)); + + EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("3ffe:dead:beef::1", NULL, &hints, &r)); + + EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_UNSPECIFIED + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("::", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_SITELOCAL + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("fec0::", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_LINKLOCAL + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("FE80::", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } + + // IN6_IS_ADDR_LINKLOCAL + if (true) { + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + + addrinfo* r = NULL; + SrsAutoFree(addrinfo, r); + ASSERT_TRUE(!getaddrinfo("::1", NULL, &hints, &r)); + + EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr)); + } } From b794c9e4ecab4c4362d4675ce1b01e1ad4f5cb53 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 22:16:21 +0800 Subject: [PATCH 7/8] For #460, fix ipv6 hostport parsing bug. 3.0.94 --- README.md | 1 + trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_utility.cpp | 49 +++++++++++++++++-------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 629d93211..561c0165b 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 hostport parsing bug. 3.0.94 * v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 intranet address filter bug. 3.0.93 * v3.0, 2020-01-05, For [#1543][bug #1543], use getpeername to retrieve client ip. 3.0.92 * v3.0, 2020-01-02, For [#1042][bug #1042], improve test coverage for config. 3.0.91 diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 2ddb51420..b4b9edbd5 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -27,7 +27,7 @@ // The version config. #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_REVISION 93 +#define VERSION_REVISION 94 // The macros generated by configure script. #include diff --git a/trunk/src/kernel/srs_kernel_utility.cpp b/trunk/src/kernel/srs_kernel_utility.cpp index 1d091338e..861be3610 100644 --- a/trunk/src/kernel/srs_kernel_utility.cpp +++ b/trunk/src/kernel/srs_kernel_utility.cpp @@ -188,23 +188,42 @@ string srs_dns_resolve(string host, int& family) return string(shost); } -void srs_parse_hostport(const string& hostport, string& host, int& port) +void srs_parse_hostport(string hostport, string& host, int& port) { - const size_t pos = hostport.rfind(":"); // Look for ":" from the end, to work with IPv6. - if (pos != std::string::npos) { - const string p = hostport.substr(pos + 1); - if ((pos >= 1) && - (hostport[0] == '[') && - (hostport[pos - 1] == ']')) { - // Handle IPv6 in RFC 2732 format, e.g. [3ffe:dead:beef::1]:1935 - host = hostport.substr(1, pos - 2); - } else { - // Handle IP address - host = hostport.substr(0, pos); - } - port = ::atoi(p.c_str()); - } else { + // No host or port. + if (hostport.empty()) { + return; + } + + size_t pos = string::npos; + + // Host only for ipv4. + if ((pos = hostport.rfind(":")) == string::npos) { host = hostport; + return; + } + + // For ipv4(only one colon), host:port. + if (hostport.find(":") == pos) { + host = hostport.substr(0, pos); + string p = hostport.substr(pos + 1); + if (!p.empty()) { + port = ::atoi(p.c_str()); + } + return; + } + + // Host only for ipv6. + if (hostport.at(0) != '[' || (pos = hostport.rfind("]:")) == string::npos) { + host = hostport; + return; + } + + // For ipv6, [host]:port. + host = hostport.substr(1, pos - 1); + string p = hostport.substr(pos + 2); + if (!p.empty()) { + port = ::atoi(p.c_str()); } } From 10464a5fbe77e753f5e9452afc9bf93e6bbfac03 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 22:17:15 +0800 Subject: [PATCH 8/8] Always use string instance to avoid crash risk. 3.0.95 --- README.md | 1 + trunk/src/app/srs_app_config.cpp | 2 +- trunk/src/app/srs_app_config.hpp | 2 +- trunk/src/app/srs_app_st.cpp | 2 +- trunk/src/app/srs_app_st.hpp | 2 +- trunk/src/app/srs_app_utility.cpp | 2 +- trunk/src/app/srs_app_utility.hpp | 2 +- trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_mp4.cpp | 4 +- trunk/src/kernel/srs_kernel_utility.hpp | 2 +- trunk/src/protocol/srs_protocol_json.cpp | 2 +- trunk/src/protocol/srs_protocol_json.hpp | 2 +- trunk/src/service/srs_service_utility.cpp | 2 +- trunk/src/service/srs_service_utility.hpp | 2 +- trunk/src/utest/srs_utest_kernel.cpp | 104 ++++++++++++++++++++++ 15 files changed, 119 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 561c0165b..99fd8ac6b 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* v3.0, 2020-01-05, Always use string instance to avoid crash risk. 3.0.95 * v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 hostport parsing bug. 3.0.94 * v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 intranet address filter bug. 3.0.93 * v3.0, 2020-01-05, For [#1543][bug #1543], use getpeername to retrieve client ip. 3.0.92 diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 026ac8801..a0277f3c9 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -296,7 +296,7 @@ bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req) return false; } -string srs_config_bool2switch(const string& sbool) +string srs_config_bool2switch(string sbool) { return sbool == "true"? "on":"off"; } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 6bc0b4cf2..c9c03e24f 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -123,7 +123,7 @@ extern bool srs_stream_caster_is_flv(std::string caster); extern bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req); // Convert bool in str to on/off -extern std::string srs_config_bool2switch(const std::string& sbool); +extern std::string srs_config_bool2switch(std::string sbool); // Parse loaded vhost directives to compatible mode. // For exmaple, SRS1/2 use the follow refer style: diff --git a/trunk/src/app/srs_app_st.cpp b/trunk/src/app/srs_app_st.cpp index 1e6ae4371..831a0613a 100755 --- a/trunk/src/app/srs_app_st.cpp +++ b/trunk/src/app/srs_app_st.cpp @@ -81,7 +81,7 @@ int SrsDummyCoroutine::cid() _ST_THREAD_CREATE_PFN _pfn_st_thread_create = (_ST_THREAD_CREATE_PFN)st_thread_create; -SrsSTCoroutine::SrsSTCoroutine(const string& n, ISrsCoroutineHandler* h, int cid) +SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h, int cid) { name = n; handler = h; diff --git a/trunk/src/app/srs_app_st.hpp b/trunk/src/app/srs_app_st.hpp index 131ec697c..956e00b42 100644 --- a/trunk/src/app/srs_app_st.hpp +++ b/trunk/src/app/srs_app_st.hpp @@ -132,7 +132,7 @@ private: public: // Create a thread with name n and handler h. // @remark User can specify a cid for thread to use, or we will allocate a new one. - SrsSTCoroutine(const std::string& n, ISrsCoroutineHandler* h, int cid = 0); + SrsSTCoroutine(std::string n, ISrsCoroutineHandler* h, int cid = 0); virtual ~SrsSTCoroutine(); public: // Start the thread. diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index d82dfdf6a..2dc149ddc 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -1157,7 +1157,7 @@ string srs_get_peer_ip(int fd) return std::string(saddr); } -bool srs_is_boolean(const string& str) +bool srs_is_boolean(string str) { return str == "true" || str == "false"; } diff --git a/trunk/src/app/srs_app_utility.hpp b/trunk/src/app/srs_app_utility.hpp index 26da0106d..be7cbced6 100644 --- a/trunk/src/app/srs_app_utility.hpp +++ b/trunk/src/app/srs_app_utility.hpp @@ -644,7 +644,7 @@ extern std::string srs_get_peer_ip(int fd); // is_bool("true") == true // is_bool("false") == true // otherwise, false. -extern bool srs_is_boolean(const std::string& str); +extern bool srs_is_boolean(std::string str); // Dump summaries for /api/v1/summaries. extern void srs_api_dump_summaries(SrsJsonObject* obj); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index b4b9edbd5..0eb763b92 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -27,7 +27,7 @@ // The version config. #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_REVISION 94 +#define VERSION_REVISION 95 // The macros generated by configure script. #include diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index 1845a87b2..5cfc5ac9f 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -110,12 +110,12 @@ void srs_mp4_delimiter_newline(stringstream& ss, SrsMp4DumpContext dc) srs_mp4_padding(ss, dc); } -int srs_mp4_string_length(const string& v) +int srs_mp4_string_length(string v) { return (int)v.length()+1; } -void srs_mp4_string_write(SrsBuffer* buf, const string& v) +void srs_mp4_string_write(SrsBuffer* buf, string v) { if (!v.empty()) { buf->write_bytes((char*)v.data(), (int)v.length()); diff --git a/trunk/src/kernel/srs_kernel_utility.hpp b/trunk/src/kernel/srs_kernel_utility.hpp index 765a86546..04d386298 100644 --- a/trunk/src/kernel/srs_kernel_utility.hpp +++ b/trunk/src/kernel/srs_kernel_utility.hpp @@ -56,7 +56,7 @@ extern std::string srs_dns_resolve(std::string host, int& family); // Split the host:port to host and port. // @remark the hostport format in , where port is optional. -extern void srs_parse_hostport(const std::string& hostport, std::string& host, int& port); +extern void srs_parse_hostport(std::string hostport, std::string& host, int& port); // Parse the endpoint to ip and port. // @remark The hostport format in <[ip:]port>, where ip is default to "0.0.0.0". diff --git a/trunk/src/protocol/srs_protocol_json.cpp b/trunk/src/protocol/srs_protocol_json.cpp index 82f099114..c742bb158 100644 --- a/trunk/src/protocol/srs_protocol_json.cpp +++ b/trunk/src/protocol/srs_protocol_json.cpp @@ -1731,7 +1731,7 @@ SrsJsonAny* srs_json_parse_tree(json_value* node) } } -SrsJsonAny* SrsJsonAny::loads(const string& str) +SrsJsonAny* SrsJsonAny::loads(string str) { if (str.empty()) { return NULL; diff --git a/trunk/src/protocol/srs_protocol_json.hpp b/trunk/src/protocol/srs_protocol_json.hpp index cac07a8d5..273b237dc 100644 --- a/trunk/src/protocol/srs_protocol_json.hpp +++ b/trunk/src/protocol/srs_protocol_json.hpp @@ -107,7 +107,7 @@ public: public: // Read json tree from string. // @return json object. NULL if error. - static SrsJsonAny* loads(const std::string& str); + static SrsJsonAny* loads(std::string str); }; class SrsJsonObject : public SrsJsonAny diff --git a/trunk/src/service/srs_service_utility.cpp b/trunk/src/service/srs_service_utility.cpp index 4d19133f4..108240bdb 100644 --- a/trunk/src/service/srs_service_utility.cpp +++ b/trunk/src/service/srs_service_utility.cpp @@ -51,7 +51,7 @@ bool srs_string_is_rtmp(string url) return srs_string_starts_with(url, "rtmp://"); } -bool srs_is_digit_number(const string& str) +bool srs_is_digit_number(string str) { if (str.empty()) { return false; diff --git a/trunk/src/service/srs_service_utility.hpp b/trunk/src/service/srs_service_utility.hpp index c41a86215..ce1acc3ed 100644 --- a/trunk/src/service/srs_service_utility.hpp +++ b/trunk/src/service/srs_service_utility.hpp @@ -48,7 +48,7 @@ extern bool srs_string_is_rtmp(std::string url); // is_digit("10e3") === false // is_digit("!1234567890") === false // is_digit("") === false -extern bool srs_is_digit_number(const std::string& str); +extern bool srs_is_digit_number(std::string str); // Get local ip, fill to @param ips extern std::vector& srs_get_local_ips(); diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 9868749d5..181bc58b1 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -4254,6 +4254,110 @@ VOID TEST(KernelUtilityTest, CoverTimeUtilityAll) _srs_system_time_us_cache -= 300*1000 * 1000 + 1; EXPECT_TRUE(srs_update_system_time() > 0); + if (true) { + string host = "127.0.0.1:1935"; + int port = 0; + srs_parse_hostport(host, host, port); + EXPECT_EQ(1935, port); + EXPECT_STREQ("127.0.0.1", host.c_str()); + } + + if (true) { + string host; + int port = 8080; + srs_parse_hostport("::1", host, port); + EXPECT_EQ(8080, port); + EXPECT_STREQ("::1", host.c_str()); + } + + if (true) { + string host; + int port = 8080; + srs_parse_hostport("::", host, port); + EXPECT_EQ(8080, port); + EXPECT_STREQ("::", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("3ffe:dead:beef::1", host, port); + EXPECT_EQ(0, port); + EXPECT_STREQ("3ffe:dead:beef::1", host.c_str()); + } + + if (true) { + string host; + int port = 10; + srs_parse_hostport("2001:da8:6000:291:21f:d0ff:fed4:928c", host, port); + EXPECT_EQ(10, port); + EXPECT_STREQ("2001:da8:6000:291:21f:d0ff:fed4:928c", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("[2001:da8:6000:291:21f:d0ff:fed4:928c]:167", host, port); + EXPECT_EQ(167, port); + EXPECT_STREQ("2001:da8:6000:291:21f:d0ff:fed4:928c", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("[::A.B.C.D]:167", host, port); + EXPECT_EQ(167, port); + EXPECT_STREQ("::A.B.C.D", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("::A.B.C.D", host, port); + EXPECT_EQ(0, port); + EXPECT_STREQ("::A.B.C.D", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("[::FFFF:A.B.C.D]:167", host, port); + EXPECT_EQ(167, port); + EXPECT_STREQ("::FFFF:A.B.C.D", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("[ff00::]:167", host, port); + EXPECT_EQ(167, port); + EXPECT_STREQ("ff00::", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("[fe80::a00:27ff:fe84:be2%eth0]:167", host, port); + EXPECT_EQ(167, port); + EXPECT_STREQ("fe80::a00:27ff:fe84:be2%eth0", host.c_str()); + } + + if (true) { + string host; + int port = 0; + srs_parse_hostport("::FFFF:A.B.C.D", host, port); + EXPECT_EQ(0, port); + EXPECT_STREQ("::FFFF:A.B.C.D", host.c_str()); + } + + if (true) { + string host; + int port = 8080; + srs_parse_hostport("", host, port); + EXPECT_EQ(8080, port); + EXPECT_STREQ("", host.c_str()); + } + if (true) { string host; int port = 8080;