From fa7fd85ca6e6e12bfa804d728203e4f5c9cc1721 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 2 Jan 2020 11:08:18 +0800 Subject: [PATCH 1/7] Improve test coverage for config. --- trunk/src/utest/srs_utest_config.cpp | 158 +++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index 0466c1538..32ee0950c 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -3478,3 +3478,161 @@ VOID TEST(ConfigMainTest, CheckVhostConfig4) } } +VOID TEST(ConfigMainTest, CheckVhostConfig5) +{ + srs_error_t err; + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{exec{enabled on;publish xxx;}}")); + EXPECT_TRUE(conf.get_exec("ossrs.net") != NULL); + EXPECT_TRUE(conf.get_exec_enabled("ossrs.net")); + EXPECT_EQ(1, conf.get_exec_publishs("ossrs.net").size()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{ingest xxx{enabled on;ffmpeg xxx2;input{type xxx3;url xxx4;}}}")); + EXPECT_EQ(1, conf.get_ingesters("ossrs.net").size()); + ASSERT_TRUE(conf.get_ingest_by_id("ossrs.net", "xxx") != NULL); + EXPECT_TRUE(conf.get_ingest_enabled(conf.get_ingest_by_id("ossrs.net", "xxx"))); + EXPECT_STREQ("xxx2", conf.get_ingest_ffmpeg(conf.get_ingest_by_id("ossrs.net", "xxx")).c_str()); + EXPECT_STREQ("xxx3", conf.get_ingest_input_type(conf.get_ingest_by_id("ossrs.net", "xxx")).c_str()); + EXPECT_STREQ("xxx4", conf.get_ingest_input_url(conf.get_ingest_by_id("ossrs.net", "xxx")).c_str()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "srs_log_tank xxx;srs_log_level xxx2;srs_log_file xxx3;ff_log_dir xxx4;")); + EXPECT_TRUE(conf.get_log_tank_file()); + EXPECT_STREQ("xxx2", conf.get_log_level().c_str()); + EXPECT_STREQ("xxx3", conf.get_log_file().c_str()); + EXPECT_STREQ("xxx4", conf.get_ffmpeg_log_dir().c_str()); + EXPECT_TRUE(conf.get_ffmpeg_log_enabled()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{dash{enabled on;dash_fragment 10;dash_update_period 10;dash_timeshift 10;dash_path xxx;dash_mpd_file xxx2;}}")); + EXPECT_TRUE(conf.get_dash_enabled("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_dash_fragment("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_dash_update_period("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_dash_timeshift("ossrs.net")); + EXPECT_STREQ("xxx", conf.get_dash_path("ossrs.net").c_str()); + EXPECT_STREQ("xxx2", conf.get_dash_mpd_file("ossrs.net").c_str()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{hls{enabled on;hls_entry_prefix xxx;hls_path xxx2;hls_m3u8_file xxx3;hls_ts_file xxx4;hls_ts_floor on;hls_fragment 10;}}")); + EXPECT_TRUE(conf.get_hls_enabled("ossrs.net")); + EXPECT_STREQ("xxx", conf.get_hls_entry_prefix("ossrs.net").c_str()); + EXPECT_STREQ("xxx2", conf.get_hls_path("ossrs.net").c_str()); + EXPECT_STREQ("xxx3", conf.get_hls_m3u8_file("ossrs.net").c_str()); + EXPECT_STREQ("xxx4", conf.get_hls_ts_file("ossrs.net").c_str()); + EXPECT_TRUE(conf.get_hls_ts_floor("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_hls_fragment("ossrs.net")); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{hls{hls_td_ratio 2.1;hls_aof_ratio 3.1;hls_window 10;hls_on_error xxx;hls_acodec xxx2;hls_vcodec xxx3;hls_nb_notify 5;hls_dts_directly off;hls_cleanup off;hls_dispose 10;hls_wait_keyframe off;}}")); + EXPECT_EQ(2.1, conf.get_hls_td_ratio("ossrs.net")); + EXPECT_EQ(3.1, conf.get_hls_aof_ratio("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_hls_window("ossrs.net")); + EXPECT_STREQ("xxx", conf.get_hls_on_error("ossrs.net").c_str()); + EXPECT_STREQ("xxx2", conf.get_hls_acodec("ossrs.net").c_str()); + EXPECT_STREQ("xxx3", conf.get_hls_vcodec("ossrs.net").c_str()); + EXPECT_EQ(5, conf.get_vhost_hls_nb_notify("ossrs.net")); + EXPECT_FALSE(conf.get_vhost_hls_dts_directly("ossrs.net")); + EXPECT_FALSE(conf.get_hls_cleanup("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_hls_dispose("ossrs.net")); + EXPECT_FALSE(conf.get_hls_wait_keyframe("ossrs.net")); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{hls{hls_keys on;hls_fragments_per_key 5;hls_key_file xxx;hls_key_file_path xxx2;hls_key_url xxx3;}}")); + EXPECT_TRUE(conf.get_hls_keys("ossrs.net")); + EXPECT_EQ(5, conf.get_hls_fragments_per_key("ossrs.net")); + EXPECT_STREQ("xxx", conf.get_hls_key_file("ossrs.net").c_str()); + EXPECT_STREQ("xxx2", conf.get_hls_key_file_path("ossrs.net").c_str()); + EXPECT_STREQ("xxx3", conf.get_hls_key_url("ossrs.net").c_str()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{hds{enabled on;hds_path xxx;hds_fragment 10;hds_window 10;}}")); + EXPECT_TRUE(conf.get_hds_enabled("ossrs.net")); + EXPECT_STREQ("xxx", conf.get_hds_path("ossrs.net").c_str()); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_hds_fragment("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_hds_window("ossrs.net")); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{dvr{enabled on;dvr_apply all;dvr_path xxx;dvr_plan xxx2;dvr_duration 10;time_jitter full;}}")); + EXPECT_TRUE(conf.get_dvr_enabled("ossrs.net")); + EXPECT_TRUE(conf.get_dvr_apply("ossrs.net") != NULL); + EXPECT_STREQ("xxx", conf.get_dvr_path("ossrs.net").c_str()); + EXPECT_STREQ("xxx2", conf.get_dvr_plan("ossrs.net").c_str()); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_dvr_duration("ossrs.net")); + EXPECT_TRUE(conf.get_dvr_wait_keyframe("ossrs.net")); + EXPECT_EQ(1, conf.get_dvr_time_jitter("ossrs.net")); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "http_api{enabled on;listen xxx;crossdomain off;raw_api {enabled on;allow_reload on;allow_query on;allow_update on;}}")); + EXPECT_TRUE(conf.get_http_api_enabled()); + EXPECT_STREQ("xxx", conf.get_http_api_listen().c_str()); + EXPECT_FALSE(conf.get_http_api_crossdomain()); + EXPECT_TRUE(conf.get_raw_api()); + EXPECT_TRUE(conf.get_raw_api_allow_reload()); + EXPECT_TRUE(conf.get_raw_api_allow_query()); + EXPECT_TRUE(conf.get_raw_api_allow_update()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "http_server{enabled on;listen xxx;dir xxx2;crossdomain on;}")); + EXPECT_TRUE(conf.get_http_stream_enabled()); + EXPECT_STREQ("xxx", conf.get_http_stream_listen().c_str()); + EXPECT_STREQ("xxx2", conf.get_http_stream_dir().c_str()); + EXPECT_TRUE(conf.get_http_stream_crossdomain()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{http_static{enabled on;mount xxx;dir xxx2;}}")); + EXPECT_TRUE(conf.get_vhost_http_enabled("ossrs.net")); + EXPECT_STREQ("xxx", conf.get_vhost_http_mount("ossrs.net").c_str()); + EXPECT_STREQ("xxx2", conf.get_vhost_http_dir("ossrs.net").c_str()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "vhost ossrs.net{http_remux{enabled on;fast_cache 10;mount xxx;}}")); + EXPECT_TRUE(conf.get_vhost_http_remux_enabled("ossrs.net")); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_vhost_http_remux_fast_cache("ossrs.net")); + EXPECT_STREQ("xxx", conf.get_vhost_http_remux_mount("ossrs.net").c_str()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "heartbeat{enabled on;interval 10;url xxx;device_id xxx2;summaries on;}")); + EXPECT_TRUE(conf.get_heartbeat_enabled()); + EXPECT_EQ(10*SRS_UTIME_SECONDS, conf.get_heartbeat_interval()); + EXPECT_STREQ("xxx", conf.get_heartbeat_url().c_str()); + EXPECT_STREQ("xxx2", conf.get_heartbeat_device_id().c_str()); + EXPECT_TRUE(conf.get_heartbeat_summaries()); + } + + if (true) { + MockSrsConfig conf; + HELPER_ASSERT_SUCCESS(conf.parse(_MIN_OK_CONF "stats{network 0;disk xxx;}")); + EXPECT_EQ(0, conf.get_stats_network()); + EXPECT_TRUE(conf.get_stats_disk_device() != NULL); + } +} + From 646eeb05e935441720e01da77021578a670cdb74 Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 2 Jan 2020 11:18:45 +0800 Subject: [PATCH 2/7] For #1042, improve test coverage for config. 3.0.91 --- README.md | 1 + trunk/src/core/srs_core.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9cb037a28..5a422d707 100755 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For previous versions, please read: ## V3 changes +* 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. * v3.0, 2019-12-29, For [#1255][bug #1255], support vhost/domain in query string for HTTP streaming. 3.0.90 diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index fe7692e58..06f93f5cb 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 90 +#define VERSION_REVISION 91 // The macros generated by configure script. #include From 79314f7d4a5aafe397711b260f806eee2bfa22e1 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 3 Jan 2020 13:31:08 +0800 Subject: [PATCH 3/7] Improve test coverage for HTTP service --- trunk/src/service/srs_service_http_conn.cpp | 29 +++++---- trunk/src/utest/srs_utest_service.cpp | 70 +++++++++++++++++++-- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/trunk/src/service/srs_service_http_conn.cpp b/trunk/src/service/srs_service_http_conn.cpp index 08eca160f..0f2f32717 100644 --- a/trunk/src/service/srs_service_http_conn.cpp +++ b/trunk/src/service/srs_service_http_conn.cpp @@ -296,9 +296,13 @@ SrsHttpMessage::SrsHttpMessage(ISrsReader* reader, SrsFastStream* buffer) : ISrs jsonp = false; - _method = 0; - _status = 0; + // As 0 is DELETE, so we use GET as default. + _method = SRS_CONSTS_HTTP_GET; + // 200 is ok. + _status = SRS_CONSTS_HTTP_OK; + // -1 means infinity chunked mode. _content_length = -1; + // From HTTP/1.1, default to keep alive. _keep_alive = true; } @@ -338,18 +342,21 @@ srs_error_t SrsHttpMessage::set_url(string url, bool allow_jsonp) _url = url; - // use server public ip when host not specified. - // to make telnet happy. - std::string host = _header.get("Host"); - if (host.empty()) { - host= srs_get_public_internet_address(); - } - // parse uri from schema/server:port/path?query std::string uri = _url; - if (!host.empty()) { - uri = "http://" + host + _url; + + if (!srs_string_contains(uri, "://")) { + // use server public ip when host not specified. + // to make telnet happy. + std::string host = _header.get("Host"); + if (host.empty()) { + host= srs_get_public_internet_address(); + } + if (!host.empty()) { + uri = "http://" + host + _url; + } } + if ((err = _uri->initialize(uri)) != srs_success) { return srs_error_wrap(err, "init uri %s", uri.c_str()); } diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index 77218d982..44ed22d07 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -29,10 +29,20 @@ using namespace std; #include #include -// Disable coroutine test for OSX. -#if !defined(SRS_OSX) - #include +#include + +class MockSrsConnection : public ISrsConnection +{ +public: + MockSrsConnection() { + } + virtual ~MockSrsConnection() { + } + virtual std::string remote_ip() { + return "127.0.0.1"; + } +}; VOID TEST(ServiceTimeTest, TimeUnit) { @@ -376,6 +386,7 @@ VOID TEST(TCPServerTest, StringIsHex) VOID TEST(TCPServerTest, WritevIOVC) { srs_error_t err; + if (true) { MockTcpHandler h; SrsTcpListener l(&h, _srs_tmp_host, _srs_tmp_port); @@ -431,4 +442,55 @@ VOID TEST(TCPServerTest, WritevIOVC) } } -#endif +VOID TEST(TCPServerTest, MessageConnection) +{ + srs_error_t err; + + if (true) { + MockSrsConnection conn; + SrsHttpMessage m; + m.set_connection(&conn); + EXPECT_TRUE(&conn == m.connection()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=POST", true)); + EXPECT_TRUE(m.jsonp); EXPECT_STREQ("POST", m.jsonp_method.c_str()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=GET", true)); + EXPECT_EQ(SRS_CONSTS_HTTP_GET, m.method()); EXPECT_STREQ("GET", m.method_str().c_str()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=PUT", true)); + EXPECT_EQ(SRS_CONSTS_HTTP_PUT, m.method()); EXPECT_STREQ("PUT", m.method_str().c_str()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=POST", true)); + EXPECT_EQ(SRS_CONSTS_HTTP_POST, m.method()); EXPECT_STREQ("POST", m.method_str().c_str()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=DELETE", true)); + EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str()); + } + + if (true) { + SrsHttpMessage m; + m.set_basic(100, 0, 0); EXPECT_STREQ("OTHER", m.method_str().c_str()); + m.set_basic(SRS_CONSTS_HTTP_GET, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_GET, m.method()); EXPECT_STREQ("GET", m.method_str().c_str()); + m.set_basic(SRS_CONSTS_HTTP_PUT, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_PUT, m.method()); EXPECT_STREQ("PUT", m.method_str().c_str()); + m.set_basic(SRS_CONSTS_HTTP_POST, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_POST, m.method()); EXPECT_STREQ("POST", m.method_str().c_str()); + m.set_basic(SRS_CONSTS_HTTP_DELETE, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str()); + m.set_basic(SRS_CONSTS_HTTP_OPTIONS, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_OPTIONS, m.method()); EXPECT_STREQ("OPTIONS", m.method_str().c_str()); + } +} + From 763c06976a481d16890c6c015026f4fb0731f930 Mon Sep 17 00:00:00 2001 From: alphonsetai Date: Thu, 2 Jan 2020 14:05:06 +0800 Subject: [PATCH 4/7] fix memory leak --- trunk/src/protocol/srs_rtsp_stack.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trunk/src/protocol/srs_rtsp_stack.cpp b/trunk/src/protocol/srs_rtsp_stack.cpp index b939d7178..4d3487ebd 100644 --- a/trunk/src/protocol/srs_rtsp_stack.cpp +++ b/trunk/src/protocol/srs_rtsp_stack.cpp @@ -161,6 +161,8 @@ void SrsRtpPacket::copy(SrsRtpPacket* src) chunked = src->chunked; completed = src->completed; + + srs_freep(audio_samples); audio_samples = new SrsCodecSample(); } From b5f4b96060b332d9ad8695f4ef572475b617d1ad Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 14:41:31 +0800 Subject: [PATCH 5/7] Merge #1551, fix memory leak in RTSP stack. 2.0.270 --- README.md | 2 ++ trunk/src/core/srs_core.hpp | 2 +- trunk/src/protocol/srs_rtsp_stack.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf04a3a46..ca203c440 100755 --- a/README.md +++ b/README.md @@ -338,6 +338,7 @@ Remark: ## History +* v2.0, 2020-01-05, Merge [#1551][bug #1551], fix memory leak in RTSP stack. 2.0.270 * v2.0, 2019-12-26, For [#1488][bug #1488], pass client ip to http callback. 2.0.269 * v2.0, 2019-12-23, Fix [srs-librtmp #22](https://github.com/ossrs/srs-librtmp/issues/22), parse vhost splited by single seperator. 2.0.268 * v2.0, 2019-12-23, Fix [srs-librtmp #25](https://github.com/ossrs/srs-librtmp/issues/25), build srs-librtmp on windows. 2.0.267 @@ -1359,6 +1360,7 @@ Winlin [bug #1312]: https://github.com/ossrs/srs/pull/1312 [bug #1304]: https://github.com/ossrs/srs/pull/1304 [bug #1488]: https://github.com/ossrs/srs/issues/1488 +[bug #1551]: https://github.com/ossrs/srs/pull/1551 [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index bb1461400..11ff88418 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 269 +#define VERSION_REVISION 270 // generated by configure, only macros. #include diff --git a/trunk/src/protocol/srs_rtsp_stack.cpp b/trunk/src/protocol/srs_rtsp_stack.cpp index 4d3487ebd..5552d4771 100644 --- a/trunk/src/protocol/srs_rtsp_stack.cpp +++ b/trunk/src/protocol/srs_rtsp_stack.cpp @@ -162,7 +162,7 @@ void SrsRtpPacket::copy(SrsRtpPacket* src) chunked = src->chunked; completed = src->completed; - srs_freep(audio_samples); + srs_freep(audio_samples); audio_samples = new SrsCodecSample(); } From 9bd8b363b32f082526d6bd29021a42e15383ccf7 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 17:02:57 +0800 Subject: [PATCH 6/7] Improve test coverage for http service. --- trunk/src/service/srs_service_http_conn.cpp | 46 +++-- trunk/src/utest/srs_utest_http.cpp | 24 --- trunk/src/utest/srs_utest_http.hpp | 32 ++++ trunk/src/utest/srs_utest_service.cpp | 197 +++++++++++++++++++- 4 files changed, 244 insertions(+), 55 deletions(-) diff --git a/trunk/src/service/srs_service_http_conn.cpp b/trunk/src/service/srs_service_http_conn.cpp index 0f2f32717..cff5b26a3 100644 --- a/trunk/src/service/srs_service_http_conn.cpp +++ b/trunk/src/service/srs_service_http_conn.cpp @@ -103,7 +103,7 @@ srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** p msg->set_header(header, http_should_keep_alive(&hp_header)); if ((err = msg->set_url(url, jsonp)) != srs_success) { srs_freep(msg); - return srs_error_wrap(err, "update message"); + return srs_error_wrap(err, "set url=%s, jsonp=%d", url.c_str(), jsonp); } // parse ok, return the msg. @@ -634,7 +634,7 @@ SrsRequest* SrsHttpMessage::to_request(string vhost) std::string query = _uri->get_query(); if (!query.empty()) { - req->tcUrl = req->tcUrl + "?" + query; + req->param = "?" + query; } srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->stream, req->port, req->param); @@ -788,9 +788,8 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t* if (!header_wrote || content_length != -1) { ssize_t nwrite = 0; for (int i = 0; i < iovcnt; i++) { - const iovec* piovc = iov + i; - nwrite += piovc->iov_len; - if ((err = write((char*)piovc->iov_base, (int)piovc->iov_len)) != srs_success) { + nwrite += iov[i].iov_len; + if ((err = write((char*)iov[i].iov_base, (int)iov[i].iov_len)) != srs_success) { return srs_error_wrap(err, "writev"); } } @@ -806,6 +805,11 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t* if (iovcnt <= 0) { return err; } + + // whatever header is wrote, we should try to send header. + if ((err = send_header(NULL, 0)) != srs_success) { + return srs_error_wrap(err, "send header"); + } // send in chunked encoding. int nb_iovss = 3 + iovcnt; @@ -816,9 +820,7 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t* iovss = iovss_cache = new iovec[nb_iovss]; } - // send in chunked encoding. - - // chunk size. + // Send all iovs in one chunk, the size is the total size of iovs. int size = 0; for (int i = 0; i < iovcnt; i++) { const iovec* data_iov = iov + i; @@ -828,29 +830,23 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t* // chunk header int nb_size = snprintf(header_cache, SRS_HTTP_HEADER_CACHE_SIZE, "%x", size); - iovec* iovs = iovss; - iovs[0].iov_base = (char*)header_cache; - iovs[0].iov_len = (int)nb_size; - iovs++; - + iovss[0].iov_base = (char*)header_cache; + iovss[0].iov_len = (int)nb_size; + // chunk header eof. - iovs[0].iov_base = (char*)SRS_HTTP_CRLF; - iovs[0].iov_len = 2; - iovs++; - + iovss[1].iov_base = (char*)SRS_HTTP_CRLF; + iovss[1].iov_len = 2; + // chunk body. for (int i = 0; i < iovcnt; i++) { - const iovec* data_iov = iov + i; - iovs[0].iov_base = (char*)data_iov->iov_base; - iovs[0].iov_len = (int)data_iov->iov_len; - iovs++; + iovss[2+i].iov_base = (char*)iov[i].iov_base; + iovss[2+i].iov_len = (int)iov[i].iov_len; } // chunk body eof. - iovs[0].iov_base = (char*)SRS_HTTP_CRLF; - iovs[0].iov_len = 2; - iovs++; - + iovss[2+iovcnt].iov_base = (char*)SRS_HTTP_CRLF; + iovss[2+iovcnt].iov_len = 2; + // sendout all ioves. ssize_t nwrite; if ((err = srs_write_large_iovs(skt, iovss, nb_iovss, &nwrite)) != srs_success) { diff --git a/trunk/src/utest/srs_utest_http.cpp b/trunk/src/utest/srs_utest_http.cpp index 69b78177e..60f91a04a 100644 --- a/trunk/src/utest/srs_utest_http.cpp +++ b/trunk/src/utest/srs_utest_http.cpp @@ -89,24 +89,6 @@ srs_error_t MockMSegmentsReader::read(void* buf, size_t size, ssize_t* nread) return err; } -class MockResponseWriter : virtual public ISrsHttpResponseWriter, virtual public ISrsHttpHeaderFilter -{ -public: - SrsHttpResponseWriter* w; - MockBufferIO io; -public: - MockResponseWriter(); - virtual ~MockResponseWriter(); -public: - virtual srs_error_t final_request(); - virtual SrsHttpHeader* header(); - virtual srs_error_t write(char* data, int size); - virtual srs_error_t writev(const iovec* iov, int iovcnt, ssize_t* pnwrite); - virtual void write_header(int code); -public: - virtual srs_error_t filter(SrsHttpHeader* h); -}; - MockResponseWriter::MockResponseWriter() { w = new SrsHttpResponseWriter(&io); @@ -221,12 +203,6 @@ bool _mock_srs_path_not_exists(std::string /*path*/) return false; } -#define __MOCK_HTTP_EXPECT_STREQ(status, text, w) \ - EXPECT_STREQ(mock_http_response(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str()) - -#define __MOCK_HTTP_EXPECT_STREQ2(status, text, w) \ - EXPECT_STREQ(mock_http_response2(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str()) - VOID TEST(ProtocolHTTPTest, StatusCode2Text) { EXPECT_STREQ(SRS_CONSTS_HTTP_OK_str, srs_generate_http_status_text(SRS_CONSTS_HTTP_OK).c_str()); diff --git a/trunk/src/utest/srs_utest_http.hpp b/trunk/src/utest/srs_utest_http.hpp index 0ca97496f..bb7f576a0 100644 --- a/trunk/src/utest/srs_utest_http.hpp +++ b/trunk/src/utest/srs_utest_http.hpp @@ -30,6 +30,38 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include +#include + +#include +using namespace std; + +class MockResponseWriter : virtual public ISrsHttpResponseWriter, virtual public ISrsHttpHeaderFilter +{ +public: + SrsHttpResponseWriter* w; + MockBufferIO io; +public: + MockResponseWriter(); + virtual ~MockResponseWriter(); +public: + virtual srs_error_t final_request(); + virtual SrsHttpHeader* header(); + virtual srs_error_t write(char* data, int size); + virtual srs_error_t writev(const iovec* iov, int iovcnt, ssize_t* pnwrite); + virtual void write_header(int code); +public: + virtual srs_error_t filter(SrsHttpHeader* h); +}; + +string mock_http_response(int status, string content); +string mock_http_response2(int status, string content); + +#define __MOCK_HTTP_EXPECT_STREQ(status, text, w) \ + EXPECT_STREQ(mock_http_response(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str()) + +#define __MOCK_HTTP_EXPECT_STREQ2(status, text, w) \ + EXPECT_STREQ(mock_http_response2(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str()) #endif diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp index 44ed22d07..9307ab48f 100644 --- a/trunk/src/utest/srs_utest_service.cpp +++ b/trunk/src/utest/srs_utest_service.cpp @@ -31,6 +31,10 @@ using namespace std; #include #include +#include +#include +#include +#include class MockSrsConnection : public ISrsConnection { @@ -450,37 +454,37 @@ VOID TEST(TCPServerTest, MessageConnection) MockSrsConnection conn; SrsHttpMessage m; m.set_connection(&conn); - EXPECT_TRUE(&conn == m.connection()); + EXPECT_TRUE(&conn == m.connection()); EXPECT_FALSE(m.is_jsonp()); } if (true) { SrsHttpMessage m; HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=POST", true)); - EXPECT_TRUE(m.jsonp); EXPECT_STREQ("POST", m.jsonp_method.c_str()); + EXPECT_TRUE(m.jsonp); EXPECT_STREQ("POST", m.jsonp_method.c_str()); EXPECT_TRUE(m.is_jsonp()); } if (true) { SrsHttpMessage m; HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=GET", true)); - EXPECT_EQ(SRS_CONSTS_HTTP_GET, m.method()); EXPECT_STREQ("GET", m.method_str().c_str()); + EXPECT_EQ(SRS_CONSTS_HTTP_GET, m.method()); EXPECT_STREQ("GET", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp()); } if (true) { SrsHttpMessage m; HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=PUT", true)); - EXPECT_EQ(SRS_CONSTS_HTTP_PUT, m.method()); EXPECT_STREQ("PUT", m.method_str().c_str()); + EXPECT_EQ(SRS_CONSTS_HTTP_PUT, m.method()); EXPECT_STREQ("PUT", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp()); } if (true) { SrsHttpMessage m; HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=POST", true)); - EXPECT_EQ(SRS_CONSTS_HTTP_POST, m.method()); EXPECT_STREQ("POST", m.method_str().c_str()); + EXPECT_EQ(SRS_CONSTS_HTTP_POST, m.method()); EXPECT_STREQ("POST", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp()); } if (true) { SrsHttpMessage m; HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?callback=fn&method=DELETE", true)); - EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str()); + EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str()); EXPECT_TRUE(m.is_jsonp()); } if (true) { @@ -492,5 +496,186 @@ VOID TEST(TCPServerTest, MessageConnection) m.set_basic(SRS_CONSTS_HTTP_DELETE, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_DELETE, m.method()); EXPECT_STREQ("DELETE", m.method_str().c_str()); m.set_basic(SRS_CONSTS_HTTP_OPTIONS, 0, 0); EXPECT_EQ(SRS_CONSTS_HTTP_OPTIONS, m.method()); EXPECT_STREQ("OPTIONS", m.method_str().c_str()); } + + if (true) { + SrsHttpMessage m; + EXPECT_TRUE(m.is_keep_alive()); + EXPECT_FALSE(m.is_infinite_chunked()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv", false)); + EXPECT_STREQ("http://127.0.0.1/live/livestream.flv", m.uri().c_str()); EXPECT_FALSE(m.is_jsonp()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?domain=ossrs.net", false)); + EXPECT_STREQ("ossrs.net", m.host().c_str()); EXPECT_FALSE(m.is_jsonp()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv", false)); + EXPECT_STREQ(".flv", m.ext().c_str()); EXPECT_FALSE(m.is_jsonp()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.set_url("http://127.0.0.1/v1/streams/100", false)); + EXPECT_EQ(100, m.parse_rest_id("/v1/streams/")); EXPECT_FALSE(m.is_jsonp()); + } +} + +VOID TEST(TCPServerTest, MessageInfinityChunked) +{ + srs_error_t err; + + if (true) { + SrsHttpMessage m; + EXPECT_FALSE(m.is_infinite_chunked()); + HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked()); + EXPECT_TRUE(m.is_infinite_chunked()); + } + + if (true) { + SrsHttpMessage m; + HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked()); + HELPER_EXPECT_SUCCESS(m.enter_infinite_chunked()); + EXPECT_TRUE(m.is_infinite_chunked()); + } + + if (true) { + SrsHttpMessage m; + SrsHttpHeader hdr; + hdr.set("Transfer-Encoding", "chunked"); + m.set_header(&hdr, false); + HELPER_EXPECT_FAILED(m.enter_infinite_chunked()); + } + + if (true) { + SrsHttpMessage m; + SrsHttpHeader hdr; + hdr.set("Content-Length", "100"); + m.set_header(&hdr, false); + HELPER_EXPECT_FAILED(m.enter_infinite_chunked()); + } +} + +VOID TEST(TCPServerTest, MessageTurnRequest) +{ + srs_error_t err; + + if (true) { + SrsHttpMessage m; + HELPER_ASSERT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv", false)); + SrsRequest* r = m.to_request("ossrs.net"); + EXPECT_STREQ("live", r->app.c_str()); + EXPECT_STREQ("livestream", r->stream.c_str()); + EXPECT_STREQ("rtmp://ossrs.net/live", r->tcUrl.c_str()); + srs_freep(r); + } + + if (true) { + SrsHttpMessage m; + HELPER_ASSERT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?token=key", false)); + SrsRequest* r = m.to_request("ossrs.net"); + EXPECT_STREQ("rtmp://ossrs.net/live", r->tcUrl.c_str()); + EXPECT_STREQ("?token=key", r->param.c_str()); + srs_freep(r); + } + + if (true) { + MockSrsConnection conn; + SrsHttpMessage m; + m.set_connection(&conn); + + SrsRequest* r = m.to_request("ossrs.net"); + EXPECT_STREQ("127.0.0.1", r->ip.c_str()); + srs_freep(r); + } + + if (true) { + MockSrsConnection conn; + SrsHttpMessage m; + m.set_connection(&conn); + + SrsHttpHeader hdr; + hdr.set("X-Real-IP", "10.11.12.13"); + m.set_header(&hdr, false); + + SrsRequest* r = m.to_request("ossrs.net"); + EXPECT_STREQ("10.11.12.13", r->ip.c_str()); + srs_freep(r); + } +} + +VOID TEST(TCPServerTest, MessageWritev) +{ + srs_error_t err; + + // For infinite chunked mode, all data is content. + if (true) { + MockBufferIO io; + io.append("HTTP/1.1 200 OK\r\n\r\n"); + + SrsHttpParser hp; HELPER_ASSERT_SUCCESS(hp.initialize(HTTP_RESPONSE, false)); + ISrsHttpMessage* msg = NULL; HELPER_ASSERT_SUCCESS(hp.parse_message(&io, &msg)); + + if (true) { + SrsHttpMessage* hm = dynamic_cast(msg); + ASSERT_TRUE(hm != NULL); + hm->enter_infinite_chunked(); + } + + char buf[32]; ssize_t nread = 0; + ISrsHttpResponseReader* r = msg->body_reader(); + + io.append("Hello"); + HELPER_ARRAY_INIT(buf, sizeof(buf), 0); + HELPER_ASSERT_SUCCESS(r->read(buf, 5, &nread)); + EXPECT_EQ(5, nread); + EXPECT_STREQ("Hello", buf); + + io.append("\r\nWorld!"); + HELPER_ARRAY_INIT(buf, sizeof(buf), 0); + HELPER_ASSERT_SUCCESS(r->read(buf, 8, &nread)); + EXPECT_EQ(8, nread); + EXPECT_STREQ("\r\nWorld!", buf); + } + + // Directly writev, merge to one chunk. + if (true) { + MockResponseWriter w; + w.write_header(SRS_CONSTS_HTTP_OK); + + iovec iovs[] = { + {(char*)"Hello", 5}, + {(char*)"World", 5}, + {(char*)"!", 1}, + }; + HELPER_ASSERT_SUCCESS(w.writev(iovs, 3, NULL)); + + __MOCK_HTTP_EXPECT_STREQ2(200, "b\r\nHelloWorld!\r\n", w); + } + + // Use writev to send one iov, should also be ok. + if (true) { + MockResponseWriter w; + + char data[] = "Hello, world!"; + iovec iovs[] = {{(char*)data, (int)(sizeof(data) - 1)}}; + HELPER_ASSERT_SUCCESS(w.writev(iovs, 1, NULL)); + + __MOCK_HTTP_EXPECT_STREQ(200, "Hello, world!", w); + } + + // Write header multiple times, should be ok. + if (true) { + MockResponseWriter w; + w.write_header(SRS_CONSTS_HTTP_OK); + w.write_header(SRS_CONSTS_HTTP_OK); + } } From f5a8810f15a2479528e7e39a1ba61c9942556d1d Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 5 Jan 2020 17:14:32 +0800 Subject: [PATCH 7/7] Update author for #1551. --- AUTHORS.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index e705ff820..ae8a9f800 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -49,4 +49,5 @@ CONTRIBUTORS ordered by first contribution. * qiang.li * HungMingWu * Himer -* xialixin \ No newline at end of file +* xialixin +* alphonsetai \ No newline at end of file