diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 2f01c3ae7..507367477 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -288,6 +288,8 @@ public: virtual srs_error_t persistence() = 0; virtual std::string config() = 0; virtual SrsConfDirective *get_root() = 0; + // Get the current work directory. + virtual std::string cwd() = 0; public: // Global server config diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp index 95eb936f6..d7c09755d 100644 --- a/trunk/src/app/srs_app_dvr.cpp +++ b/trunk/src/app/srs_app_dvr.cpp @@ -775,7 +775,7 @@ void SrsDvrSessionPlan::on_unpublish() // ignore error. srs_error_t err = segment_->close(); if (err != srs_success) { - srs_warn("ignore flv close error %s", srs_error_desc(err).c_str()); + srs_warn("ignore dvr segment close failed. ret=%d", srs_error_code(err)); srs_freep(err); } diff --git a/trunk/src/app/srs_app_http_hooks.cpp b/trunk/src/app/srs_app_http_hooks.cpp index 96b256501..f725d342c 100644 --- a/trunk/src/app/srs_app_http_hooks.cpp +++ b/trunk/src/app/srs_app_http_hooks.cpp @@ -48,11 +48,15 @@ ISrsHttpHooks::~ISrsHttpHooks() SrsHttpHooks::SrsHttpHooks() { factory_ = _srs_app_factory; + stat_ = _srs_stat; + config_ = _srs_config; } SrsHttpHooks::~SrsHttpHooks() { factory_ = NULL; + stat_ = NULL; + config_ = NULL; } srs_error_t SrsHttpHooks::on_connect(string url, ISrsRequest *req) @@ -60,7 +64,7 @@ srs_error_t SrsHttpHooks::on_connect(string url, ISrsRequest *req) srs_error_t err = srs_success; SrsContextId cid = _srs_context->get_id(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -96,7 +100,7 @@ void SrsHttpHooks::on_close(string url, ISrsRequest *req, int64_t send_bytes, in srs_error_t err = srs_success; SrsContextId cid = _srs_context->get_id(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -133,7 +137,7 @@ srs_error_t SrsHttpHooks::on_publish(string url, ISrsRequest *req) srs_error_t err = srs_success; SrsContextId cid = _srs_context->get_id(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -174,7 +178,7 @@ void SrsHttpHooks::on_unpublish(string url, ISrsRequest *req) srs_error_t err = srs_success; SrsContextId cid = _srs_context->get_id(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -218,7 +222,7 @@ srs_error_t SrsHttpHooks::on_play(string url, ISrsRequest *req) srs_error_t err = srs_success; SrsContextId cid = _srs_context->get_id(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -260,7 +264,7 @@ void SrsHttpHooks::on_stop(string url, ISrsRequest *req) srs_error_t err = srs_success; SrsContextId cid = _srs_context->get_id(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -304,9 +308,9 @@ srs_error_t SrsHttpHooks::on_dvr(SrsContextId c, string url, ISrsRequest *req, s srs_error_t err = srs_success; SrsContextId cid = c; - std::string cwd = _srs_config->cwd(); + std::string cwd = config_->cwd(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -349,7 +353,7 @@ srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, ISrsRequest *req, s srs_error_t err = srs_success; SrsContextId cid = c; - std::string cwd = _srs_config->cwd(); + std::string cwd = config_->cwd(); // the ts_url is under the same dir of m3u8_url. SrsPath path; @@ -358,7 +362,7 @@ srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, ISrsRequest *req, s ts_url = prefix + "/" + ts_url; } - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("server_id", SrsJsonAny::str(stat->server_id().c_str())); @@ -405,13 +409,13 @@ srs_error_t SrsHttpHooks::on_hls_notify(SrsContextId c, std::string url, ISrsReq srs_error_t err = srs_success; SrsContextId cid = c; - std::string cwd = _srs_config->cwd(); + std::string cwd = config_->cwd(); if (srs_net_url_is_http(ts_url)) { url = ts_url; } - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; url = srs_strings_replace(url, "[server_id]", stat->server_id().c_str()); url = srs_strings_replace(url, "[service_id]", stat->service_id().c_str()); @@ -530,7 +534,7 @@ srs_error_t SrsHttpHooks::on_forward_backend(string url, ISrsRequest *req, std:: SrsContextId cid = _srs_context->get_id(); - SrsStatistic *stat = _srs_stat; + ISrsStatistic *stat = stat_; SrsUniquePtr obj(SrsJsonAny::object()); obj->set("action", SrsJsonAny::str("on_forward")); diff --git a/trunk/src/app/srs_app_http_hooks.hpp b/trunk/src/app/srs_app_http_hooks.hpp index f1ba06c37..11af2521c 100644 --- a/trunk/src/app/srs_app_http_hooks.hpp +++ b/trunk/src/app/srs_app_http_hooks.hpp @@ -19,6 +19,8 @@ class SrsHttpParser; class SrsHttpClient; class ISrsAppFactory; class ISrsHttpClient; +class ISrsStatistic; +class ISrsAppConfig; // HTTP hooks interface for SRS server event callbacks. // @@ -153,6 +155,8 @@ class SrsHttpHooks : public ISrsHttpHooks { private: ISrsAppFactory *factory_; + ISrsStatistic *stat_; + ISrsAppConfig *config_; public: SrsHttpHooks(); diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp index 5ccc89b32..609b473e3 100644 --- a/trunk/src/app/srs_app_statistic.hpp +++ b/trunk/src/app/srs_app_statistic.hpp @@ -161,6 +161,8 @@ public: virtual SrsStatisticVhost *find_vhost_by_id(std::string vid) = 0; // Find stream by id. virtual SrsStatisticStream *find_stream(std::string sid) = 0; + // Find stream by url. + virtual SrsStatisticStream *find_stream_by_url(std::string url) = 0; // Find client by id. virtual SrsStatisticClient *find_client(std::string client_id) = 0; // Dumps the vhosts to json array. diff --git a/trunk/src/kernel/srs_kernel_mp4.cpp b/trunk/src/kernel/srs_kernel_mp4.cpp index 9a5d0e91e..17add458f 100644 --- a/trunk/src/kernel/srs_kernel_mp4.cpp +++ b/trunk/src/kernel/srs_kernel_mp4.cpp @@ -6649,7 +6649,7 @@ srs_error_t SrsMp4Encoder::flush() srs_error_t err = srs_success; if (!nb_audios_ && !nb_videos_) { - return srs_error_new(ERROR_MP4_ILLEGAL_MOOV, "Missing audio and video track"); + return srs_error_new(ERROR_MP4_ILLEGAL_MOOV, "Missing audio and video track, nb_audios=%d, nb_videos=%d", nb_audios_, nb_videos_); } // Write moov. @@ -6943,6 +6943,7 @@ srs_error_t SrsMp4Encoder::copy_sequence_header(SrsFormat *format, bool vsh, uin pavcc_ = std::vector(sample, sample + nb_sample); } if (format && format->vcodec_) { + vcodec_ = format->vcodec_->id_; width_ = format->vcodec_->width_; height_ = format->vcodec_->height_; } diff --git a/trunk/src/utest/srs_utest_app10.cpp b/trunk/src/utest/srs_utest_app10.cpp index ddb2c1000..7a67d698c 100644 --- a/trunk/src/utest/srs_utest_app10.cpp +++ b/trunk/src/utest/srs_utest_app10.cpp @@ -819,6 +819,11 @@ SrsStatisticStream *MockStatisticForResampleKbps::find_stream(std::string sid) return NULL; } +SrsStatisticStream *MockStatisticForResampleKbps::find_stream_by_url(std::string url) +{ + return NULL; +} + SrsStatisticClient *MockStatisticForResampleKbps::find_client(std::string client_id) { return NULL; diff --git a/trunk/src/utest/srs_utest_app10.hpp b/trunk/src/utest/srs_utest_app10.hpp index b896bd024..8307fa82e 100644 --- a/trunk/src/utest/srs_utest_app10.hpp +++ b/trunk/src/utest/srs_utest_app10.hpp @@ -268,6 +268,7 @@ public: virtual std::string service_pid(); virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); virtual SrsStatisticClient *find_client(std::string client_id); virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count); diff --git a/trunk/src/utest/srs_utest_app11.cpp b/trunk/src/utest/srs_utest_app11.cpp index 2c9c2fd90..2e08cb984 100644 --- a/trunk/src/utest/srs_utest_app11.cpp +++ b/trunk/src/utest/srs_utest_app11.cpp @@ -1050,6 +1050,11 @@ SrsStatisticStream *MockStatisticForLiveStream::find_stream(std::string sid) return NULL; } +SrsStatisticStream *MockStatisticForLiveStream::find_stream_by_url(std::string url) +{ + return NULL; +} + SrsStatisticClient *MockStatisticForLiveStream::find_client(std::string client_id) { return NULL; diff --git a/trunk/src/utest/srs_utest_app11.hpp b/trunk/src/utest/srs_utest_app11.hpp index 36d3454c4..08b85f0ee 100644 --- a/trunk/src/utest/srs_utest_app11.hpp +++ b/trunk/src/utest/srs_utest_app11.hpp @@ -255,6 +255,7 @@ public: virtual std::string service_pid(); virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); virtual SrsStatisticClient *find_client(std::string client_id); virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count); diff --git a/trunk/src/utest/srs_utest_app12.cpp b/trunk/src/utest/srs_utest_app12.cpp index 146840763..1c62ac6eb 100644 --- a/trunk/src/utest/srs_utest_app12.cpp +++ b/trunk/src/utest/srs_utest_app12.cpp @@ -1280,6 +1280,11 @@ SrsStatisticStream *MockSrtStatistic::find_stream(std::string sid) return NULL; } +SrsStatisticStream *MockSrtStatistic::find_stream_by_url(std::string url) +{ + return NULL; +} + SrsStatisticClient *MockSrtStatistic::find_client(std::string client_id) { return NULL; diff --git a/trunk/src/utest/srs_utest_app12.hpp b/trunk/src/utest/srs_utest_app12.hpp index bed8d5d8f..2ec8a79ab 100644 --- a/trunk/src/utest/srs_utest_app12.hpp +++ b/trunk/src/utest/srs_utest_app12.hpp @@ -60,6 +60,7 @@ public: virtual std::string service_pid(); virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); virtual SrsStatisticClient *find_client(std::string client_id); virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count); diff --git a/trunk/src/utest/srs_utest_app13.cpp b/trunk/src/utest/srs_utest_app13.cpp index 488d641d9..2f1d667be 100644 --- a/trunk/src/utest/srs_utest_app13.cpp +++ b/trunk/src/utest/srs_utest_app13.cpp @@ -1668,6 +1668,11 @@ SrsStatisticStream *MockStatisticForRtspPlayStream::find_stream(std::string sid) return NULL; } +SrsStatisticStream *MockStatisticForRtspPlayStream::find_stream_by_url(std::string url) +{ + return NULL; +} + SrsStatisticClient *MockStatisticForRtspPlayStream::find_client(std::string client_id) { return NULL; diff --git a/trunk/src/utest/srs_utest_app13.hpp b/trunk/src/utest/srs_utest_app13.hpp index 393f86f17..886506218 100644 --- a/trunk/src/utest/srs_utest_app13.hpp +++ b/trunk/src/utest/srs_utest_app13.hpp @@ -377,6 +377,7 @@ public: virtual std::string service_pid(); virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); virtual SrsStatisticClient *find_client(std::string client_id); virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count); diff --git a/trunk/src/utest/srs_utest_app15.cpp b/trunk/src/utest/srs_utest_app15.cpp index 6f32c8076..4130399ff 100644 --- a/trunk/src/utest/srs_utest_app15.cpp +++ b/trunk/src/utest/srs_utest_app15.cpp @@ -10,6 +10,7 @@ using namespace std; #include #include +#include #include #include #include @@ -1877,6 +1878,11 @@ SrsStatisticStream *MockStatisticForRtcApi::find_stream(std::string sid) return NULL; } +SrsStatisticStream *MockStatisticForRtcApi::find_stream_by_url(std::string url) +{ + return NULL; +} + SrsStatisticClient *MockStatisticForRtcApi::find_client(std::string client_id) { return NULL; @@ -3403,3 +3409,860 @@ VOID TEST(StatisticTest, DumpsMetrics) // nerrs should be 2 (client1 and client2 disconnected with errors) EXPECT_EQ(2, nerrs); } + +// Mock ISrsHttpResponseReader implementation for SrsHttpHooks testing +MockHttpResponseReaderForHooks::MockHttpResponseReaderForHooks() +{ + content_ = ""; + read_pos_ = 0; + eof_ = false; +} + +MockHttpResponseReaderForHooks::~MockHttpResponseReaderForHooks() +{ +} + +srs_error_t MockHttpResponseReaderForHooks::read(void *buf, size_t size, ssize_t *nread) +{ + if (eof_ || read_pos_ >= content_.length()) { + eof_ = true; + return srs_error_new(-1, "EOF"); + } + + size_t remaining = content_.length() - read_pos_; + size_t to_read = srs_min(size, remaining); + memcpy(buf, content_.data() + read_pos_, to_read); + read_pos_ += to_read; + if (nread) { + *nread = to_read; + } + + if (read_pos_ >= content_.length()) { + eof_ = true; + } + + return srs_success; +} + +bool MockHttpResponseReaderForHooks::eof() +{ + return eof_; +} + +// Mock ISrsHttpMessage implementation for SrsHttpHooks testing +MockHttpMessageForHooks::MockHttpMessageForHooks() +{ + status_code_ = 200; + body_content_ = "{\"code\":0}"; + body_reader_ = NULL; +} + +MockHttpMessageForHooks::~MockHttpMessageForHooks() +{ + srs_freep(body_reader_); +} + +uint8_t MockHttpMessageForHooks::method() +{ + return 0; +} + +uint16_t MockHttpMessageForHooks::status_code() +{ + return status_code_; +} + +std::string MockHttpMessageForHooks::method_str() +{ + return "POST"; +} + +std::string MockHttpMessageForHooks::url() +{ + return ""; +} + +std::string MockHttpMessageForHooks::host() +{ + return ""; +} + +std::string MockHttpMessageForHooks::path() +{ + return ""; +} + +std::string MockHttpMessageForHooks::query() +{ + return ""; +} + +std::string MockHttpMessageForHooks::ext() +{ + return ""; +} + +srs_error_t MockHttpMessageForHooks::body_read_all(std::string &body) +{ + body = body_content_; + return srs_success; +} + +ISrsHttpResponseReader *MockHttpMessageForHooks::body_reader() +{ + return body_reader_; +} + +int64_t MockHttpMessageForHooks::content_length() +{ + return 0; +} + +std::string MockHttpMessageForHooks::query_get(std::string key) +{ + return ""; +} + +int MockHttpMessageForHooks::request_header_count() +{ + return 0; +} + +std::string MockHttpMessageForHooks::request_header_key_at(int index) +{ + return ""; +} + +std::string MockHttpMessageForHooks::request_header_value_at(int index) +{ + return ""; +} + +std::string MockHttpMessageForHooks::get_request_header(std::string name) +{ + return ""; +} + +ISrsRequest *MockHttpMessageForHooks::to_request(std::string vhost) +{ + return NULL; +} + +bool MockHttpMessageForHooks::is_chunked() +{ + return false; +} + +bool MockHttpMessageForHooks::is_keep_alive() +{ + return false; +} + +bool MockHttpMessageForHooks::is_jsonp() +{ + return false; +} + +std::string MockHttpMessageForHooks::jsonp() +{ + return ""; +} + +bool MockHttpMessageForHooks::require_crossdomain() +{ + return false; +} + +srs_error_t MockHttpMessageForHooks::enter_infinite_chunked() +{ + return srs_success; +} + +srs_error_t MockHttpMessageForHooks::end_infinite_chunked() +{ + return srs_success; +} + +uint8_t MockHttpMessageForHooks::message_type() +{ + return 0; +} + +bool MockHttpMessageForHooks::is_http_get() +{ + return false; +} + +bool MockHttpMessageForHooks::is_http_put() +{ + return false; +} + +bool MockHttpMessageForHooks::is_http_post() +{ + return true; +} + +bool MockHttpMessageForHooks::is_http_delete() +{ + return false; +} + +bool MockHttpMessageForHooks::is_http_options() +{ + return false; +} + +std::string MockHttpMessageForHooks::uri() +{ + return ""; +} + +std::string MockHttpMessageForHooks::parse_rest_id(std::string pattern) +{ + return ""; +} + +SrsHttpHeader *MockHttpMessageForHooks::header() +{ + return NULL; +} + +// Mock ISrsHttpClient implementation for SrsHttpHooks testing +MockHttpClientForHooks::MockHttpClientForHooks() +{ + initialize_called_ = false; + post_called_ = false; + get_called_ = false; + port_ = 0; + mock_response_ = NULL; + initialize_error_ = srs_success; + post_error_ = srs_success; + get_error_ = srs_success; +} + +MockHttpClientForHooks::~MockHttpClientForHooks() +{ +} + +srs_error_t MockHttpClientForHooks::initialize(std::string schema, std::string h, int p, srs_utime_t tm) +{ + initialize_called_ = true; + schema_ = schema; + host_ = h; + port_ = p; + return srs_error_copy(initialize_error_); +} + +srs_error_t MockHttpClientForHooks::get(std::string path, std::string req, ISrsHttpMessage **ppmsg) +{ + get_called_ = true; + path_ = path; + request_body_ = req; + if (ppmsg && mock_response_) { + *ppmsg = mock_response_; + } + return srs_error_copy(get_error_); +} + +srs_error_t MockHttpClientForHooks::post(std::string path, std::string req, ISrsHttpMessage **ppmsg) +{ + post_called_ = true; + path_ = path; + request_body_ = req; + if (ppmsg && mock_response_) { + *ppmsg = mock_response_; + } + return srs_error_copy(post_error_); +} + +void MockHttpClientForHooks::set_recv_timeout(srs_utime_t tm) +{ +} + +void MockHttpClientForHooks::kbps_sample(const char *label, srs_utime_t age) +{ +} + +// Mock ISrsAppFactory implementation for SrsHttpHooks testing +MockAppFactoryForHooks::MockAppFactoryForHooks() +{ + mock_http_client_ = NULL; +} + +MockAppFactoryForHooks::~MockAppFactoryForHooks() +{ +} + +ISrsHttpClient *MockAppFactoryForHooks::create_http_client() +{ + return mock_http_client_; +} + +// Mock ISrsStatistic implementation for SrsHttpHooks testing +MockStatisticForHooks::MockStatisticForHooks() +{ + server_id_ = "test_server_id"; + service_id_ = "test_service_id"; +} + +MockStatisticForHooks::~MockStatisticForHooks() +{ +} + +void MockStatisticForHooks::on_disconnect(std::string id, srs_error_t err) +{ +} + +srs_error_t MockStatisticForHooks::on_client(std::string id, ISrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type) +{ + return srs_success; +} + +srs_error_t MockStatisticForHooks::on_video_info(ISrsRequest *req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height) +{ + return srs_success; +} + +srs_error_t MockStatisticForHooks::on_audio_info(ISrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate, + SrsAudioChannels asound_type, SrsAacObjectType aac_object) +{ + return srs_success; +} + +void MockStatisticForHooks::on_stream_publish(ISrsRequest *req, std::string publisher_id) +{ +} + +void MockStatisticForHooks::on_stream_close(ISrsRequest *req) +{ +} + +void MockStatisticForHooks::kbps_add_delta(std::string id, ISrsKbpsDelta *delta) +{ +} + +void MockStatisticForHooks::kbps_sample() +{ +} + +srs_error_t MockStatisticForHooks::on_video_frames(ISrsRequest *req, int nb_frames) +{ + return srs_success; +} + +std::string MockStatisticForHooks::server_id() +{ + return server_id_; +} + +std::string MockStatisticForHooks::service_id() +{ + return service_id_; +} + +std::string MockStatisticForHooks::service_pid() +{ + return "test_pid"; +} + +SrsStatisticVhost *MockStatisticForHooks::find_vhost_by_id(std::string vid) +{ + return NULL; +} + +SrsStatisticStream *MockStatisticForHooks::find_stream(std::string sid) +{ + return NULL; +} + +SrsStatisticStream *MockStatisticForHooks::find_stream_by_url(std::string url) +{ + return NULL; +} + +SrsStatisticClient *MockStatisticForHooks::find_client(std::string client_id) +{ + return NULL; +} + +srs_error_t MockStatisticForHooks::dumps_vhosts(SrsJsonArray *arr) +{ + return srs_success; +} + +srs_error_t MockStatisticForHooks::dumps_streams(SrsJsonArray *arr, int start, int count) +{ + return srs_success; +} + +srs_error_t MockStatisticForHooks::dumps_clients(SrsJsonArray *arr, int start, int count) +{ + return srs_success; +} + +srs_error_t MockStatisticForHooks::dumps_metrics(int64_t &send_bytes, int64_t &recv_bytes, int64_t &nstreams, int64_t &nclients, int64_t &total_nclients, int64_t &nerrs) +{ + return srs_success; +} + +// Mock factory that tracks HTTP client calls +class MockAppFactoryForHooksTest : public SrsAppFactory +{ +public: + bool initialize_called_; + bool post_called_; + std::string schema_; + std::string host_; + int port_; + std::string path_; + std::string request_body_; + MockHttpClientForHooks *mock_http_client_; + +public: + MockAppFactoryForHooksTest() + { + initialize_called_ = false; + post_called_ = false; + port_ = 0; + mock_http_client_ = NULL; + } + + virtual ~MockAppFactoryForHooksTest() + { + } + + virtual ISrsHttpClient *create_http_client() + { + // If a specific mock client is set, return it + if (mock_http_client_) { + return mock_http_client_; + } + + // Create a mock HTTP client that saves call information to the factory + MockHttpClientForHooks *client = new MockHttpClientForHooks(); + + // Create mock response + MockHttpMessageForHooks *msg = new MockHttpMessageForHooks(); + msg->status_code_ = 200; + msg->body_content_ = "{\"code\":0}"; + + // Create mock body reader for GET requests (e.g., on_hls_notify) + MockHttpResponseReaderForHooks *reader = new MockHttpResponseReaderForHooks(); + reader->content_ = "OK"; // Simple response body + msg->body_reader_ = reader; + + client->mock_response_ = msg; + + return client; + } +}; + +VOID TEST(HttpHooksTest, OnConnectSuccess) +{ + srs_error_t err; + + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->pageUrl_ = "http://example.com/player.html"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + + // Test on_connect with successful response + std::string url = "http://127.0.0.1:8085/api/v1/clients"; + HELPER_EXPECT_SUCCESS(hooks->on_connect(url, req.get())); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; +} + +VOID TEST(HttpHooksTest, OnCloseSuccess) +{ + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->vhost_ = "test.vhost"; + req->app_ = "live"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + + // Test on_close with successful response + std::string url = "http://127.0.0.1:8085/api/v1/clients"; + int64_t send_bytes = 1024000; + int64_t recv_bytes = 512000; + hooks->on_close(url, req.get(), send_bytes, recv_bytes); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; +} + +VOID TEST(HttpHooksTest, OnPublishSuccess) +{ + srs_error_t err; + + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + + // Test on_publish with successful response - major use scenario + std::string url = "http://127.0.0.1:8085/api/v1/streams"; + HELPER_EXPECT_SUCCESS(hooks->on_publish(url, req.get())); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; +} + +VOID TEST(HttpHooksTest, OnUnpublishSuccess) +{ + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + + // Test on_unpublish with successful response - major use scenario + std::string url = "http://127.0.0.1:8085/api/v1/streams"; + hooks->on_unpublish(url, req.get()); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; +} + +VOID TEST(HttpHooksTest, OnPlaySuccess) +{ + srs_error_t err; + + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->param_ = "?token=abc123"; + req->pageUrl_ = "http://example.com/player.html"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + + // Test on_play with successful response - major use scenario + std::string url = "http://127.0.0.1:8085/api/v1/sessions"; + HELPER_EXPECT_SUCCESS(hooks->on_play(url, req.get())); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; +} + +VOID TEST(HttpHooksTest, OnStopSuccess) +{ + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->vhost_ = "test.vhost"; + req->app_ = "live"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + + // Test on_stop with successful response - major use scenario + std::string url = "http://127.0.0.1:8085/api/v1/sessions"; + hooks->on_stop(url, req.get()); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; +} + +VOID TEST(HttpHooksTest, OnDvrSuccess) +{ + srs_error_t err; + + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + mock_stat->server_id_ = "server-123"; + mock_stat->service_id_ = "service-456"; + + // Create mock config + SrsUniquePtr mock_config(new MockAppConfig()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + hooks->config_ = mock_config.get(); + + // Test on_dvr with successful response - major use scenario + // This covers DVR recording notification with file path + SrsContextId cid; + cid.set_value("client-789"); + std::string url = "http://127.0.0.1:8085/api/v1/dvrs"; + std::string file = "/data/dvr/test.vhost/live/stream1/2025-01-15/recording.flv"; + HELPER_EXPECT_SUCCESS(hooks->on_dvr(cid, url, req.get(), file)); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; + hooks->config_ = NULL; +} + +VOID TEST(HttpHooksTest, OnHlsSuccess) +{ + srs_error_t err; + + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + mock_stat->server_id_ = "server-123"; + mock_stat->service_id_ = "service-456"; + + // Create mock config + SrsUniquePtr mock_config(new MockAppConfig()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + hooks->config_ = mock_config.get(); + + // Test on_hls with successful response - major use scenario + // This covers HLS segment notification with all typical parameters + SrsContextId cid; + cid.set_value("client-789"); + std::string url = "http://127.0.0.1:8085/api/v1/hls"; + std::string file = "/data/hls/test.vhost/live/stream1/segment-123.ts"; + std::string ts_url = "segment-123.ts"; + std::string m3u8 = "/data/hls/test.vhost/live/stream1/playlist.m3u8"; + std::string m3u8_url = "http://127.0.0.1:8080/live/stream1/playlist.m3u8"; + int sn = 123; + srs_utime_t duration = 10 * SRS_UTIME_SECONDS; // 10 seconds + + HELPER_EXPECT_SUCCESS(hooks->on_hls(cid, url, req.get(), file, ts_url, m3u8, m3u8_url, sn, duration)); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; + hooks->config_ = NULL; +} + +VOID TEST(HttpHooksTest, OnHlsNotifySuccess) +{ + srs_error_t err; + + // Create mock factory that will track calls + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + mock_stat->server_id_ = "server-123"; + mock_stat->service_id_ = "service-456"; + + // Create mock config + SrsUniquePtr mock_config(new MockAppConfig()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->app_ = "live"; + req->stream_ = "stream1"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + hooks->config_ = mock_config.get(); + + // Test on_hls_notify with successful response - major use scenario + // This covers HLS segment notification with URL template variable replacement + SrsContextId cid; + cid.set_value("client-789"); + std::string url = "http://127.0.0.1:8085/api/v1/hls/notify?server=[server_id]&service=[service_id]&app=[app]&stream=[stream]&ts=[ts_url]¶m=[param]"; + std::string ts_url = "segment-123.ts"; + int nb_notify = 1024; // Read up to 1KB from response + + HELPER_EXPECT_SUCCESS(hooks->on_hls_notify(cid, url, req.get(), ts_url, nb_notify)); + + // Clean up - set injected fields to NULL to avoid double-free + hooks->factory_ = NULL; + hooks->stat_ = NULL; + hooks->config_ = NULL; +} + +VOID TEST(HttpHooksTest, DiscoverCoWorkersSuccess) +{ + srs_error_t err; + + // Create mock factory that returns HTTP client with cluster discovery response + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create SrsHttpHooks and inject mock factory + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + + // Override the mock HTTP client response to return cluster discovery JSON + // The response should contain: {"data": {"origin": {"ip": "192.168.1.10", "port": 1935}}} + MockHttpClientForHooks *mock_client = new MockHttpClientForHooks(); + MockHttpMessageForHooks *msg = new MockHttpMessageForHooks(); + msg->status_code_ = 200; + msg->body_content_ = "{\"code\":0,\"data\":{\"origin\":{\"ip\":\"192.168.1.10\",\"port\":1935}}}"; + + MockHttpResponseReaderForHooks *reader = new MockHttpResponseReaderForHooks(); + reader->content_ = msg->body_content_; + msg->body_reader_ = reader; + + mock_client->mock_response_ = msg; + mock_factory->mock_http_client_ = mock_client; + + // Test discover_co_workers with successful response - major use scenario + // This covers origin cluster discovery with host and port extraction + std::string url = "http://127.0.0.1:8085/api/v1/clusters"; + std::string host; + int port = 0; + + HELPER_EXPECT_SUCCESS(hooks->discover_co_workers(url, host, port)); + + // Verify the parsed host and port + EXPECT_STREQ("192.168.1.10", host.c_str()); + EXPECT_EQ(1935, port); + + // Clean up - set injected fields to NULL to avoid double-free + // Note: mock_client is already freed by SrsUniquePtr in discover_co_workers + hooks->factory_ = NULL; + mock_factory->mock_http_client_ = NULL; +} + +VOID TEST(HttpHooksTest, OnForwardBackendSuccess) +{ + srs_error_t err; + + // Create mock factory that returns HTTP client with forward backend response + SrsUniquePtr mock_factory(new MockAppFactoryForHooksTest()); + + // Create mock statistic + SrsUniquePtr mock_stat(new MockStatisticForHooks()); + + // Create mock request + SrsUniquePtr req(new MockSrsRequest("test.vhost", "live", "stream1")); + req->ip_ = "192.168.1.100"; + req->tcUrl_ = "rtmp://test.vhost/live"; + req->param_ = "?token=abc123"; + + // Create SrsHttpHooks and inject mocks + SrsUniquePtr hooks(new SrsHttpHooks()); + hooks->factory_ = mock_factory.get(); + hooks->stat_ = mock_stat.get(); + + // Override the mock HTTP client response to return forward backend JSON with RTMP URLs + // The response should contain: {"data": {"urls": ["rtmp://origin1/live/stream1", "rtmp://origin2/live/stream1"]}} + MockHttpClientForHooks *mock_client = new MockHttpClientForHooks(); + MockHttpMessageForHooks *msg = new MockHttpMessageForHooks(); + msg->status_code_ = 200; + msg->body_content_ = "{\"code\":0,\"data\":{\"urls\":[\"rtmp://192.168.1.10:1935/live/stream1\",\"rtmp://192.168.1.11:1935/live/stream1\"]}}"; + + MockHttpResponseReaderForHooks *reader = new MockHttpResponseReaderForHooks(); + reader->content_ = msg->body_content_; + msg->body_reader_ = reader; + + mock_client->mock_response_ = msg; + mock_factory->mock_http_client_ = mock_client; + + // Test on_forward_backend with successful response - major use scenario + // This covers forward backend discovery with RTMP URL extraction + std::string url = "http://127.0.0.1:8085/api/v1/forward"; + std::vector rtmp_urls; + + HELPER_EXPECT_SUCCESS(hooks->on_forward_backend(url, req.get(), rtmp_urls)); + + // Verify the parsed RTMP URLs + EXPECT_EQ(2, (int)rtmp_urls.size()); + EXPECT_STREQ("rtmp://192.168.1.10:1935/live/stream1", rtmp_urls[0].c_str()); + EXPECT_STREQ("rtmp://192.168.1.11:1935/live/stream1", rtmp_urls[1].c_str()); + + // Clean up - set injected fields to NULL to avoid double-free + // Note: mock_client is already freed by SrsUniquePtr in on_forward_backend + hooks->factory_ = NULL; + hooks->stat_ = NULL; + mock_factory->mock_http_client_ = NULL; +} + diff --git a/trunk/src/utest/srs_utest_app15.hpp b/trunk/src/utest/srs_utest_app15.hpp index f3ec6e5f2..5bda71b1f 100644 --- a/trunk/src/utest/srs_utest_app15.hpp +++ b/trunk/src/utest/srs_utest_app15.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -321,6 +322,7 @@ public: virtual std::string service_pid(); virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); virtual SrsStatisticClient *find_client(std::string client_id); virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count); @@ -449,4 +451,147 @@ public: virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag); }; +// Mock ISrsHttpResponseReader for testing SrsHttpHooks +class MockHttpResponseReaderForHooks : public ISrsHttpResponseReader +{ +public: + std::string content_; + size_t read_pos_; + bool eof_; + +public: + MockHttpResponseReaderForHooks(); + virtual ~MockHttpResponseReaderForHooks(); + +public: + virtual srs_error_t read(void *buf, size_t size, ssize_t *nread); + virtual bool eof(); +}; + +// Mock ISrsHttpMessage for testing SrsHttpHooks::on_connect +class MockHttpMessageForHooks : public ISrsHttpMessage +{ +public: + int status_code_; + std::string body_content_; + MockHttpResponseReaderForHooks *body_reader_; + +public: + MockHttpMessageForHooks(); + virtual ~MockHttpMessageForHooks(); + +public: + virtual uint8_t method(); + virtual uint16_t status_code(); + virtual std::string method_str(); + virtual std::string url(); + virtual std::string host(); + virtual std::string path(); + virtual std::string query(); + virtual std::string ext(); + virtual srs_error_t body_read_all(std::string &body); + virtual ISrsHttpResponseReader *body_reader(); + virtual int64_t content_length(); + virtual std::string query_get(std::string key); + virtual int request_header_count(); + virtual std::string request_header_key_at(int index); + virtual std::string request_header_value_at(int index); + virtual std::string get_request_header(std::string name); + virtual ISrsRequest *to_request(std::string vhost); + virtual bool is_chunked(); + virtual bool is_keep_alive(); + virtual bool is_jsonp(); + virtual std::string jsonp(); + virtual bool require_crossdomain(); + virtual srs_error_t enter_infinite_chunked(); + virtual srs_error_t end_infinite_chunked(); + virtual uint8_t message_type(); + virtual bool is_http_get(); + virtual bool is_http_put(); + virtual bool is_http_post(); + virtual bool is_http_delete(); + virtual bool is_http_options(); + virtual std::string uri(); + virtual std::string parse_rest_id(std::string pattern); + virtual SrsHttpHeader *header(); +}; + +// Mock ISrsHttpClient for testing SrsHttpHooks::on_connect +class MockHttpClientForHooks : public ISrsHttpClient +{ +public: + bool initialize_called_; + bool post_called_; + bool get_called_; + std::string schema_; + std::string host_; + int port_; + std::string path_; + std::string request_body_; + MockHttpMessageForHooks *mock_response_; + srs_error_t initialize_error_; + srs_error_t post_error_; + srs_error_t get_error_; + +public: + MockHttpClientForHooks(); + virtual ~MockHttpClientForHooks(); + +public: + virtual srs_error_t initialize(std::string schema, std::string h, int p, srs_utime_t tm); + virtual srs_error_t get(std::string path, std::string req, ISrsHttpMessage **ppmsg); + virtual srs_error_t post(std::string path, std::string req, ISrsHttpMessage **ppmsg); + virtual void set_recv_timeout(srs_utime_t tm); + virtual void kbps_sample(const char *label, srs_utime_t age); +}; + +// Mock ISrsAppFactory for testing SrsHttpHooks::on_connect +class MockAppFactoryForHooks : public SrsAppFactory +{ +public: + MockHttpClientForHooks *mock_http_client_; + +public: + MockAppFactoryForHooks(); + virtual ~MockAppFactoryForHooks(); + +public: + virtual ISrsHttpClient *create_http_client(); +}; + +// Mock ISrsStatistic for testing SrsHttpHooks::on_connect +class MockStatisticForHooks : public ISrsStatistic +{ +public: + std::string server_id_; + std::string service_id_; + +public: + MockStatisticForHooks(); + virtual ~MockStatisticForHooks(); + +public: + virtual void on_disconnect(std::string id, srs_error_t err); + virtual srs_error_t on_client(std::string id, ISrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type); + virtual srs_error_t on_video_info(ISrsRequest *req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height); + virtual srs_error_t on_audio_info(ISrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate, + SrsAudioChannels asound_type, SrsAacObjectType aac_object); + virtual void on_stream_publish(ISrsRequest *req, std::string publisher_id); + virtual void on_stream_close(ISrsRequest *req); + virtual void kbps_add_delta(std::string id, ISrsKbpsDelta *delta); + virtual void kbps_sample(); + virtual srs_error_t on_video_frames(ISrsRequest *req, int nb_frames); + virtual std::string server_id(); + virtual std::string service_id(); + virtual std::string service_pid(); + virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); + virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); + virtual SrsStatisticClient *find_client(std::string client_id); + virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); + virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count); + virtual srs_error_t dumps_clients(SrsJsonArray *arr, int start, int count); + virtual srs_error_t dumps_metrics(int64_t &send_bytes, int64_t &recv_bytes, int64_t &nstreams, int64_t &nclients, int64_t &total_nclients, int64_t &nerrs); +}; + #endif diff --git a/trunk/src/utest/srs_utest_app6.cpp b/trunk/src/utest/srs_utest_app6.cpp index e18176ebc..2fb1c68f0 100644 --- a/trunk/src/utest/srs_utest_app6.cpp +++ b/trunk/src/utest/srs_utest_app6.cpp @@ -2776,6 +2776,11 @@ SrsStatisticStream *MockRtcStatistic::find_stream(std::string sid) return NULL; } +SrsStatisticStream *MockRtcStatistic::find_stream_by_url(std::string url) +{ + return NULL; +} + SrsStatisticClient *MockRtcStatistic::find_client(std::string client_id) { return NULL; diff --git a/trunk/src/utest/srs_utest_app6.hpp b/trunk/src/utest/srs_utest_app6.hpp index 2943cec60..7a38d4658 100644 --- a/trunk/src/utest/srs_utest_app6.hpp +++ b/trunk/src/utest/srs_utest_app6.hpp @@ -257,6 +257,7 @@ public: virtual srs_error_t persistence() { return srs_success; } virtual std::string config() { return ""; } virtual SrsConfDirective *get_root() { return NULL; } + virtual std::string cwd() { return "./"; } virtual int get_max_connections() { return 1000; } virtual std::string get_pid_file() { return ""; } virtual bool empty_ip_ok() { return false; } @@ -517,6 +518,7 @@ public: virtual std::string service_pid(); virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); virtual SrsStatisticClient *find_client(std::string client_id); virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count); diff --git a/trunk/src/utest/srs_utest_app9.cpp b/trunk/src/utest/srs_utest_app9.cpp index 4bc454087..ed07eaf6c 100644 --- a/trunk/src/utest/srs_utest_app9.cpp +++ b/trunk/src/utest/srs_utest_app9.cpp @@ -1985,6 +1985,11 @@ SrsStatisticStream *MockStatisticForOriginHub::find_stream(std::string sid) return NULL; } +SrsStatisticStream *MockStatisticForOriginHub::find_stream_by_url(std::string url) +{ + return NULL; +} + SrsStatisticClient *MockStatisticForOriginHub::find_client(std::string client_id) { return NULL; diff --git a/trunk/src/utest/srs_utest_app9.hpp b/trunk/src/utest/srs_utest_app9.hpp index 3d43e18cd..5d8d33951 100644 --- a/trunk/src/utest/srs_utest_app9.hpp +++ b/trunk/src/utest/srs_utest_app9.hpp @@ -215,6 +215,7 @@ public: virtual std::string service_pid(); virtual SrsStatisticVhost *find_vhost_by_id(std::string vid); virtual SrsStatisticStream *find_stream(std::string sid); + virtual SrsStatisticStream *find_stream_by_url(std::string url); virtual SrsStatisticClient *find_client(std::string client_id); virtual srs_error_t dumps_vhosts(SrsJsonArray *arr); virtual srs_error_t dumps_streams(SrsJsonArray *arr, int start, int count);