mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 11:51:57 +00:00
Merge branch '3.0release' into develop
This commit is contained in:
commit
e13a0c3ab4
9 changed files with 487 additions and 67 deletions
|
@ -49,4 +49,5 @@ CONTRIBUTORS ordered by first contribution.
|
||||||
* qiang.li<qiang.li@verycdn.com.cn>
|
* qiang.li<qiang.li@verycdn.com.cn>
|
||||||
* HungMingWu<u9089000@gmail.com>
|
* HungMingWu<u9089000@gmail.com>
|
||||||
* Himer<xishizhaohua@qq.com>
|
* Himer<xishizhaohua@qq.com>
|
||||||
* xialixin<xlx0625@163.com>
|
* xialixin<xlx0625@163.com>
|
||||||
|
* alphonsetai<tyh_123@163.com>
|
|
@ -148,6 +148,7 @@ For previous versions, please read:
|
||||||
|
|
||||||
## V3 changes
|
## 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-30, Fix mp4 security issue, check buffer when required size is variable.
|
||||||
* <strong>v3.0, 2019-12-29, [3.0 alpha7(3.0.90)][r3.0a7] released. 116356 lines.</strong>
|
* <strong>v3.0, 2019-12-29, [3.0 alpha7(3.0.90)][r3.0a7] released. 116356 lines.</strong>
|
||||||
* v3.0, 2019-12-29, For [#1255][bug #1255], support vhost/domain in query string for HTTP streaming. 3.0.90
|
* v3.0, 2019-12-29, For [#1255][bug #1255], support vhost/domain in query string for HTTP streaming. 3.0.90
|
||||||
|
@ -269,6 +270,7 @@ For previous versions, please read:
|
||||||
|
|
||||||
## V2 changes
|
## V2 changes
|
||||||
|
|
||||||
|
* 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-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 #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
|
* 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
|
||||||
|
@ -1546,6 +1548,7 @@ Winlin
|
||||||
[bug #1304]: https://github.com/ossrs/srs/pull/1304
|
[bug #1304]: https://github.com/ossrs/srs/pull/1304
|
||||||
[bug #1524]: https://github.com/ossrs/srs/issues/1524
|
[bug #1524]: https://github.com/ossrs/srs/issues/1524
|
||||||
[bug #1488]: https://github.com/ossrs/srs/issues/1488
|
[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
|
[bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx
|
||||||
|
|
||||||
[bug #735]: https://github.com/ossrs/srs/issues/735
|
[bug #735]: https://github.com/ossrs/srs/issues/735
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
// The version config.
|
// The version config.
|
||||||
#define VERSION_MAJOR 3
|
#define VERSION_MAJOR 3
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 90
|
#define VERSION_REVISION 91
|
||||||
|
|
||||||
// The macros generated by configure script.
|
// The macros generated by configure script.
|
||||||
#include <srs_auto_headers.hpp>
|
#include <srs_auto_headers.hpp>
|
||||||
|
|
|
@ -159,7 +159,7 @@ void SrsRtpPacket::copy(SrsRtpPacket* src)
|
||||||
|
|
||||||
chunked = src->chunked;
|
chunked = src->chunked;
|
||||||
completed = src->completed;
|
completed = src->completed;
|
||||||
|
|
||||||
srs_freep(audio);
|
srs_freep(audio);
|
||||||
audio = new SrsAudioFrame();
|
audio = new SrsAudioFrame();
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** p
|
||||||
msg->set_header(header, http_should_keep_alive(&hp_header));
|
msg->set_header(header, http_should_keep_alive(&hp_header));
|
||||||
if ((err = msg->set_url(url, jsonp)) != srs_success) {
|
if ((err = msg->set_url(url, jsonp)) != srs_success) {
|
||||||
srs_freep(msg);
|
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.
|
// parse ok, return the msg.
|
||||||
|
@ -296,9 +296,13 @@ SrsHttpMessage::SrsHttpMessage(ISrsReader* reader, SrsFastStream* buffer) : ISrs
|
||||||
|
|
||||||
jsonp = false;
|
jsonp = false;
|
||||||
|
|
||||||
_method = 0;
|
// As 0 is DELETE, so we use GET as default.
|
||||||
_status = 0;
|
_method = SRS_CONSTS_HTTP_GET;
|
||||||
|
// 200 is ok.
|
||||||
|
_status = SRS_CONSTS_HTTP_OK;
|
||||||
|
// -1 means infinity chunked mode.
|
||||||
_content_length = -1;
|
_content_length = -1;
|
||||||
|
// From HTTP/1.1, default to keep alive.
|
||||||
_keep_alive = true;
|
_keep_alive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,18 +342,21 @@ srs_error_t SrsHttpMessage::set_url(string url, bool allow_jsonp)
|
||||||
|
|
||||||
_url = url;
|
_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
|
// parse uri from schema/server:port/path?query
|
||||||
std::string uri = _url;
|
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) {
|
if ((err = _uri->initialize(uri)) != srs_success) {
|
||||||
return srs_error_wrap(err, "init uri %s", uri.c_str());
|
return srs_error_wrap(err, "init uri %s", uri.c_str());
|
||||||
}
|
}
|
||||||
|
@ -627,7 +634,7 @@ SrsRequest* SrsHttpMessage::to_request(string vhost)
|
||||||
|
|
||||||
std::string query = _uri->get_query();
|
std::string query = _uri->get_query();
|
||||||
if (!query.empty()) {
|
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);
|
srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->stream, req->port, req->param);
|
||||||
|
@ -781,9 +788,8 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
||||||
if (!header_wrote || content_length != -1) {
|
if (!header_wrote || content_length != -1) {
|
||||||
ssize_t nwrite = 0;
|
ssize_t nwrite = 0;
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
const iovec* piovc = iov + i;
|
nwrite += iov[i].iov_len;
|
||||||
nwrite += piovc->iov_len;
|
if ((err = write((char*)iov[i].iov_base, (int)iov[i].iov_len)) != srs_success) {
|
||||||
if ((err = write((char*)piovc->iov_base, (int)piovc->iov_len)) != srs_success) {
|
|
||||||
return srs_error_wrap(err, "writev");
|
return srs_error_wrap(err, "writev");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -799,6 +805,11 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
||||||
if (iovcnt <= 0) {
|
if (iovcnt <= 0) {
|
||||||
return err;
|
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.
|
// send in chunked encoding.
|
||||||
int nb_iovss = 3 + iovcnt;
|
int nb_iovss = 3 + iovcnt;
|
||||||
|
@ -809,9 +820,7 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
||||||
iovss = iovss_cache = new iovec[nb_iovss];
|
iovss = iovss_cache = new iovec[nb_iovss];
|
||||||
}
|
}
|
||||||
|
|
||||||
// send in chunked encoding.
|
// Send all iovs in one chunk, the size is the total size of iovs.
|
||||||
|
|
||||||
// chunk size.
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
const iovec* data_iov = iov + i;
|
const iovec* data_iov = iov + i;
|
||||||
|
@ -821,29 +830,23 @@ srs_error_t SrsHttpResponseWriter::writev(const iovec* iov, int iovcnt, ssize_t*
|
||||||
|
|
||||||
// chunk header
|
// chunk header
|
||||||
int nb_size = snprintf(header_cache, SRS_HTTP_HEADER_CACHE_SIZE, "%x", size);
|
int nb_size = snprintf(header_cache, SRS_HTTP_HEADER_CACHE_SIZE, "%x", size);
|
||||||
iovec* iovs = iovss;
|
iovss[0].iov_base = (char*)header_cache;
|
||||||
iovs[0].iov_base = (char*)header_cache;
|
iovss[0].iov_len = (int)nb_size;
|
||||||
iovs[0].iov_len = (int)nb_size;
|
|
||||||
iovs++;
|
|
||||||
|
|
||||||
// chunk header eof.
|
// chunk header eof.
|
||||||
iovs[0].iov_base = (char*)SRS_HTTP_CRLF;
|
iovss[1].iov_base = (char*)SRS_HTTP_CRLF;
|
||||||
iovs[0].iov_len = 2;
|
iovss[1].iov_len = 2;
|
||||||
iovs++;
|
|
||||||
|
|
||||||
// chunk body.
|
// chunk body.
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
const iovec* data_iov = iov + i;
|
iovss[2+i].iov_base = (char*)iov[i].iov_base;
|
||||||
iovs[0].iov_base = (char*)data_iov->iov_base;
|
iovss[2+i].iov_len = (int)iov[i].iov_len;
|
||||||
iovs[0].iov_len = (int)data_iov->iov_len;
|
|
||||||
iovs++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// chunk body eof.
|
// chunk body eof.
|
||||||
iovs[0].iov_base = (char*)SRS_HTTP_CRLF;
|
iovss[2+iovcnt].iov_base = (char*)SRS_HTTP_CRLF;
|
||||||
iovs[0].iov_len = 2;
|
iovss[2+iovcnt].iov_len = 2;
|
||||||
iovs++;
|
|
||||||
|
|
||||||
// sendout all ioves.
|
// sendout all ioves.
|
||||||
ssize_t nwrite;
|
ssize_t nwrite;
|
||||||
if ((err = srs_write_large_iovs(skt, iovss, nb_iovss, &nwrite)) != srs_success) {
|
if ((err = srs_write_large_iovs(skt, iovss, nb_iovss, &nwrite)) != srs_success) {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,24 +89,6 @@ srs_error_t MockMSegmentsReader::read(void* buf, size_t size, ssize_t* nread)
|
||||||
return err;
|
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()
|
MockResponseWriter::MockResponseWriter()
|
||||||
{
|
{
|
||||||
w = new SrsHttpResponseWriter(&io);
|
w = new SrsHttpResponseWriter(&io);
|
||||||
|
@ -221,12 +203,6 @@ bool _mock_srs_path_not_exists(std::string /*path*/)
|
||||||
return false;
|
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)
|
VOID TEST(ProtocolHTTPTest, StatusCode2Text)
|
||||||
{
|
{
|
||||||
EXPECT_STREQ(SRS_CONSTS_HTTP_OK_str, srs_generate_http_status_text(SRS_CONSTS_HTTP_OK).c_str());
|
EXPECT_STREQ(SRS_CONSTS_HTTP_OK_str, srs_generate_http_status_text(SRS_CONSTS_HTTP_OK).c_str());
|
||||||
|
|
|
@ -30,6 +30,38 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_utest.hpp>
|
#include <srs_utest.hpp>
|
||||||
|
|
||||||
#include <srs_utest_protocol.hpp>
|
#include <srs_utest_protocol.hpp>
|
||||||
|
#include <srs_http_stack.hpp>
|
||||||
|
#include <srs_service_http_conn.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,24 @@ using namespace std;
|
||||||
#include <srs_service_st.hpp>
|
#include <srs_service_st.hpp>
|
||||||
#include <srs_service_utility.hpp>
|
#include <srs_service_utility.hpp>
|
||||||
|
|
||||||
// Disable coroutine test for OSX.
|
|
||||||
#if !defined(SRS_OSX)
|
|
||||||
|
|
||||||
#include <srs_service_st.hpp>
|
#include <srs_service_st.hpp>
|
||||||
|
#include <srs_service_http_conn.hpp>
|
||||||
|
#include <srs_rtmp_stack.hpp>
|
||||||
|
#include <srs_core_autofree.hpp>
|
||||||
|
#include <srs_utest_protocol.hpp>
|
||||||
|
#include <srs_utest_http.hpp>
|
||||||
|
|
||||||
|
class MockSrsConnection : public ISrsConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MockSrsConnection() {
|
||||||
|
}
|
||||||
|
virtual ~MockSrsConnection() {
|
||||||
|
}
|
||||||
|
virtual std::string remote_ip() {
|
||||||
|
return "127.0.0.1";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
VOID TEST(ServiceTimeTest, TimeUnit)
|
VOID TEST(ServiceTimeTest, TimeUnit)
|
||||||
{
|
{
|
||||||
|
@ -376,6 +390,7 @@ VOID TEST(TCPServerTest, StringIsHex)
|
||||||
VOID TEST(TCPServerTest, WritevIOVC)
|
VOID TEST(TCPServerTest, WritevIOVC)
|
||||||
{
|
{
|
||||||
srs_error_t err;
|
srs_error_t err;
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
MockTcpHandler h;
|
MockTcpHandler h;
|
||||||
SrsTcpListener l(&h, _srs_tmp_host, _srs_tmp_port);
|
SrsTcpListener l(&h, _srs_tmp_host, _srs_tmp_port);
|
||||||
|
@ -431,4 +446,236 @@ 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()); 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.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_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_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_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_TRUE(m.is_jsonp());
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
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<SrsHttpMessage*>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue