AI: Add utest to cover heatbeat.
This commit is contained in:
parent
223202f121
commit
44c3dab79e
|
|
@ -43,27 +43,35 @@ SrsCircuitBreaker::SrsCircuitBreaker()
|
||||||
hybrid_high_water_level_ = 0;
|
hybrid_high_water_level_ = 0;
|
||||||
hybrid_critical_water_level_ = 0;
|
hybrid_critical_water_level_ = 0;
|
||||||
hybrid_dying_water_level_ = 0;
|
hybrid_dying_water_level_ = 0;
|
||||||
|
|
||||||
|
host_ = new SrsHost();
|
||||||
|
|
||||||
|
config_ = _srs_config;
|
||||||
|
shared_timer_ = _srs_shared_timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCircuitBreaker::~SrsCircuitBreaker()
|
SrsCircuitBreaker::~SrsCircuitBreaker()
|
||||||
{
|
{
|
||||||
|
srs_freep(host_);
|
||||||
|
|
||||||
|
config_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsCircuitBreaker::initialize()
|
srs_error_t SrsCircuitBreaker::initialize()
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
enabled_ = _srs_config->get_circuit_breaker();
|
enabled_ = config_->get_circuit_breaker();
|
||||||
high_threshold_ = _srs_config->get_high_threshold();
|
high_threshold_ = config_->get_high_threshold();
|
||||||
high_pulse_ = _srs_config->get_high_pulse();
|
high_pulse_ = config_->get_high_pulse();
|
||||||
critical_threshold_ = _srs_config->get_critical_threshold();
|
critical_threshold_ = config_->get_critical_threshold();
|
||||||
critical_pulse_ = _srs_config->get_critical_pulse();
|
critical_pulse_ = config_->get_critical_pulse();
|
||||||
dying_threshold_ = _srs_config->get_dying_threshold();
|
dying_threshold_ = config_->get_dying_threshold();
|
||||||
dying_pulse_ = _srs_config->get_dying_pulse();
|
dying_pulse_ = config_->get_dying_pulse();
|
||||||
|
|
||||||
// Update the water level for circuit breaker.
|
// Update the water level for circuit breaker.
|
||||||
// @see SrsCircuitBreaker::on_timer()
|
// @see SrsCircuitBreaker::on_timer()
|
||||||
_srs_shared_timer->timer1s()->subscribe(this);
|
shared_timer_->timer1s()->subscribe(this);
|
||||||
|
|
||||||
srs_trace("CircuitBreaker: enabled=%d, high=%dx%d, critical=%dx%d, dying=%dx%d", enabled_,
|
srs_trace("CircuitBreaker: enabled=%d, high=%dx%d, critical=%dx%d, dying=%dx%d", enabled_,
|
||||||
high_pulse_, high_threshold_, critical_pulse_, critical_threshold_,
|
high_pulse_, high_threshold_, critical_pulse_, critical_threshold_,
|
||||||
|
|
@ -93,7 +101,7 @@ srs_error_t SrsCircuitBreaker::on_timer(srs_utime_t interval)
|
||||||
|
|
||||||
// Update the CPU usage.
|
// Update the CPU usage.
|
||||||
srs_update_proc_stat();
|
srs_update_proc_stat();
|
||||||
SrsProcSelfStat *stat = srs_get_self_proc_stat();
|
SrsProcSelfStat *stat = host_->self_proc_stat();
|
||||||
|
|
||||||
// Reset the high water-level when CPU is low for N times.
|
// Reset the high water-level when CPU is low for N times.
|
||||||
if (stat->percent_ * 100 > high_threshold_) {
|
if (stat->percent_ * 100 > high_threshold_) {
|
||||||
|
|
@ -117,7 +125,7 @@ srs_error_t SrsCircuitBreaker::on_timer(srs_utime_t interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show statistics for RTC server.
|
// Show statistics for RTC server.
|
||||||
SrsProcSelfStat *u = srs_get_self_proc_stat();
|
SrsProcSelfStat *u = host_->self_proc_stat();
|
||||||
// Resident Set Size: number of pages the process has in real memory.
|
// Resident Set Size: number of pages the process has in real memory.
|
||||||
int memory = (int)(u->rss_ * 4 / 1024);
|
int memory = (int)(u->rss_ * 4 / 1024);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@
|
||||||
|
|
||||||
#include <srs_kernel_hourglass.hpp>
|
#include <srs_kernel_hourglass.hpp>
|
||||||
|
|
||||||
|
class ISrsAppConfig;
|
||||||
|
class ISrsSharedTimer;
|
||||||
|
class ISrsHost;
|
||||||
|
|
||||||
// Interface for circuit breaker functionality to protect server in high load conditions.
|
// Interface for circuit breaker functionality to protect server in high load conditions.
|
||||||
// The circuit breaker monitors CPU usage and enables different levels of protection:
|
// The circuit breaker monitors CPU usage and enables different levels of protection:
|
||||||
// - High water level: Disables some unnecessary features to reduce CPU load
|
// - High water level: Disables some unnecessary features to reduce CPU load
|
||||||
|
|
@ -48,6 +52,12 @@ public:
|
||||||
|
|
||||||
class SrsCircuitBreaker : public ISrsCircuitBreaker, public ISrsFastTimerHandler
|
class SrsCircuitBreaker : public ISrsCircuitBreaker, public ISrsFastTimerHandler
|
||||||
{
|
{
|
||||||
|
// clang-format off
|
||||||
|
SRS_DECLARE_PRIVATE: // clang-format on
|
||||||
|
ISrsAppConfig *config_;
|
||||||
|
ISrsSharedTimer *shared_timer_;
|
||||||
|
ISrsHost *host_;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
SRS_DECLARE_PRIVATE: // clang-format on
|
SRS_DECLARE_PRIVATE: // clang-format on
|
||||||
bool enabled_;
|
bool enabled_;
|
||||||
|
|
|
||||||
|
|
@ -396,6 +396,20 @@ public:
|
||||||
// Heartbeat config
|
// Heartbeat config
|
||||||
virtual bool get_heartbeat_enabled() = 0;
|
virtual bool get_heartbeat_enabled() = 0;
|
||||||
virtual srs_utime_t get_heartbeat_interval() = 0;
|
virtual srs_utime_t get_heartbeat_interval() = 0;
|
||||||
|
virtual std::string get_heartbeat_url() = 0;
|
||||||
|
virtual std::string get_heartbeat_device_id() = 0;
|
||||||
|
virtual bool get_heartbeat_summaries() = 0;
|
||||||
|
virtual bool get_heartbeat_ports() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Circuit breaker config
|
||||||
|
virtual bool get_circuit_breaker() = 0;
|
||||||
|
virtual int get_high_threshold() = 0;
|
||||||
|
virtual int get_high_pulse() = 0;
|
||||||
|
virtual int get_critical_threshold() = 0;
|
||||||
|
virtual int get_critical_pulse() = 0;
|
||||||
|
virtual int get_dying_threshold() = 0;
|
||||||
|
virtual int get_dying_pulse() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// RTMPS config
|
// RTMPS config
|
||||||
|
|
@ -1522,7 +1536,7 @@ public:
|
||||||
virtual std::string get_heartbeat_device_id();
|
virtual std::string get_heartbeat_device_id();
|
||||||
// Whether report with summaries of http api: /api/v1/summaries.
|
// Whether report with summaries of http api: /api/v1/summaries.
|
||||||
virtual bool get_heartbeat_summaries();
|
virtual bool get_heartbeat_summaries();
|
||||||
bool get_heartbeat_ports();
|
virtual bool get_heartbeat_ports();
|
||||||
// stats section
|
// stats section
|
||||||
// clang-format off
|
// clang-format off
|
||||||
SRS_DECLARE_PRIVATE: // clang-format on
|
SRS_DECLARE_PRIVATE: // clang-format on
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_app_config.hpp>
|
#include <srs_app_config.hpp>
|
||||||
|
#include <srs_app_factory.hpp>
|
||||||
#include <srs_app_http_client.hpp>
|
#include <srs_app_http_client.hpp>
|
||||||
#include <srs_app_http_conn.hpp>
|
#include <srs_app_http_conn.hpp>
|
||||||
#include <srs_app_statistic.hpp>
|
#include <srs_app_statistic.hpp>
|
||||||
|
|
@ -23,10 +24,14 @@ using namespace std;
|
||||||
|
|
||||||
SrsHttpHeartbeat::SrsHttpHeartbeat()
|
SrsHttpHeartbeat::SrsHttpHeartbeat()
|
||||||
{
|
{
|
||||||
|
config_ = _srs_config;
|
||||||
|
app_factory_ = _srs_app_factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHttpHeartbeat::~SrsHttpHeartbeat()
|
SrsHttpHeartbeat::~SrsHttpHeartbeat()
|
||||||
{
|
{
|
||||||
|
config_ = NULL;
|
||||||
|
app_factory_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsHttpHeartbeat::heartbeat()
|
void SrsHttpHeartbeat::heartbeat()
|
||||||
|
|
@ -43,7 +48,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
std::string url = _srs_config->get_heartbeat_url();
|
std::string url = config_->get_heartbeat_url();
|
||||||
|
|
||||||
SrsHttpUri uri;
|
SrsHttpUri uri;
|
||||||
if ((err = uri.initialize(url)) != srs_success) {
|
if ((err = uri.initialize(url)) != srs_success) {
|
||||||
|
|
@ -51,7 +56,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
||||||
}
|
}
|
||||||
|
|
||||||
string ip;
|
string ip;
|
||||||
std::string device_id = _srs_config->get_heartbeat_device_id();
|
std::string device_id = config_->get_heartbeat_device_id();
|
||||||
|
|
||||||
// Try to load the ip from the environment variable.
|
// Try to load the ip from the environment variable.
|
||||||
ip = srs_getenv("srs.device.ip"); // SRS_DEVICE_IP
|
ip = srs_getenv("srs.device.ip"); // SRS_DEVICE_IP
|
||||||
|
|
@ -60,7 +65,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
||||||
SrsProtocolUtility utility;
|
SrsProtocolUtility utility;
|
||||||
vector<SrsIPAddress *> &ips = utility.local_ips();
|
vector<SrsIPAddress *> &ips = utility.local_ips();
|
||||||
if (!ips.empty()) {
|
if (!ips.empty()) {
|
||||||
ip = ips[_srs_config->get_stats_network() % (int)ips.size()]->ip_;
|
ip = ips[config_->get_stats_network() % (int)ips.size()]->ip_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,82 +79,82 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
||||||
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
obj->set("service", SrsJsonAny::str(stat->service_id().c_str()));
|
||||||
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
obj->set("pid", SrsJsonAny::str(stat->service_pid().c_str()));
|
||||||
|
|
||||||
if (_srs_config->get_heartbeat_summaries()) {
|
if (config_->get_heartbeat_summaries()) {
|
||||||
SrsJsonObject *summaries = SrsJsonAny::object();
|
SrsJsonObject *summaries = SrsJsonAny::object();
|
||||||
obj->set("summaries", summaries);
|
obj->set("summaries", summaries);
|
||||||
|
|
||||||
srs_api_dump_summaries(summaries);
|
srs_api_dump_summaries(summaries);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_srs_config->get_heartbeat_ports()) {
|
if (config_->get_heartbeat_ports()) {
|
||||||
// For RTMP listen endpoints.
|
// For RTMP listen endpoints.
|
||||||
if (true) {
|
if (true) {
|
||||||
SrsJsonArray *o = SrsJsonAny::array();
|
SrsJsonArray *o = SrsJsonAny::array();
|
||||||
obj->set("rtmp", o);
|
obj->set("rtmp", o);
|
||||||
|
|
||||||
vector<string> endpoints = _srs_config->get_listens();
|
vector<string> endpoints = config_->get_listens();
|
||||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For HTTP Stream listen endpoints.
|
// For HTTP Stream listen endpoints.
|
||||||
if (_srs_config->get_http_stream_enabled()) {
|
if (config_->get_http_stream_enabled()) {
|
||||||
SrsJsonArray *o = SrsJsonAny::array();
|
SrsJsonArray *o = SrsJsonAny::array();
|
||||||
obj->set("http", o);
|
obj->set("http", o);
|
||||||
|
|
||||||
vector<string> endpoints = _srs_config->get_http_stream_listens();
|
vector<string> endpoints = config_->get_http_stream_listens();
|
||||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For HTTP API listen endpoints.
|
// For HTTP API listen endpoints.
|
||||||
if (_srs_config->get_http_api_enabled()) {
|
if (config_->get_http_api_enabled()) {
|
||||||
SrsJsonArray *o = SrsJsonAny::array();
|
SrsJsonArray *o = SrsJsonAny::array();
|
||||||
obj->set("api", o);
|
obj->set("api", o);
|
||||||
|
|
||||||
vector<string> endpoints = _srs_config->get_http_api_listens();
|
vector<string> endpoints = config_->get_http_api_listens();
|
||||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For SRT listen endpoints.
|
// For SRT listen endpoints.
|
||||||
if (_srs_config->get_srt_enabled()) {
|
if (config_->get_srt_enabled()) {
|
||||||
SrsJsonArray *o = SrsJsonAny::array();
|
SrsJsonArray *o = SrsJsonAny::array();
|
||||||
obj->set("srt", o);
|
obj->set("srt", o);
|
||||||
|
|
||||||
vector<string> endpoints = _srs_config->get_srt_listens();
|
vector<string> endpoints = config_->get_srt_listens();
|
||||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For RTSP listen endpoints.
|
// For RTSP listen endpoints.
|
||||||
if (_srs_config->get_rtsp_server_enabled()) {
|
if (config_->get_rtsp_server_enabled()) {
|
||||||
SrsJsonArray *o = SrsJsonAny::array();
|
SrsJsonArray *o = SrsJsonAny::array();
|
||||||
obj->set("rtsp", o);
|
obj->set("rtsp", o);
|
||||||
|
|
||||||
vector<string> endpoints = _srs_config->get_rtsp_server_listens();
|
vector<string> endpoints = config_->get_rtsp_server_listens();
|
||||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||||
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
o->append(SrsJsonAny::str(endpoints.at(i).c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For WebRTC listen endpoints.
|
// For WebRTC listen endpoints.
|
||||||
if (_srs_config->get_rtc_server_enabled()) {
|
if (config_->get_rtc_server_enabled()) {
|
||||||
SrsJsonArray *o = SrsJsonAny::array();
|
SrsJsonArray *o = SrsJsonAny::array();
|
||||||
obj->set("rtc", o);
|
obj->set("rtc", o);
|
||||||
|
|
||||||
vector<string> endpoints = _srs_config->get_rtc_server_listens();
|
vector<string> endpoints = config_->get_rtc_server_listens();
|
||||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||||
string endpoint = srs_fmt_sprintf("udp://%s", endpoints.at(i).c_str());
|
string endpoint = srs_fmt_sprintf("udp://%s", endpoints.at(i).c_str());
|
||||||
o->append(SrsJsonAny::str(endpoint.c_str()));
|
o->append(SrsJsonAny::str(endpoint.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_srs_config->get_rtc_server_tcp_enabled()) {
|
if (config_->get_rtc_server_tcp_enabled()) {
|
||||||
vector<string> endpoints = _srs_config->get_rtc_server_tcp_listens();
|
vector<string> endpoints = config_->get_rtc_server_tcp_listens();
|
||||||
for (int i = 0; i < (int)endpoints.size(); i++) {
|
for (int i = 0; i < (int)endpoints.size(); i++) {
|
||||||
string endpoint = srs_fmt_sprintf("tcp://%s", endpoints.at(i).c_str());
|
string endpoint = srs_fmt_sprintf("tcp://%s", endpoints.at(i).c_str());
|
||||||
o->append(SrsJsonAny::str(endpoint.c_str()));
|
o->append(SrsJsonAny::str(endpoint.c_str()));
|
||||||
|
|
@ -158,14 +163,14 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHttpClient http;
|
SrsUniquePtr<ISrsHttpClient> http(app_factory_->create_http_client());
|
||||||
if ((err = http.initialize(uri.get_schema(), uri.get_host(), uri.get_port())) != srs_success) {
|
if ((err = http->initialize(uri.get_schema(), uri.get_host(), uri.get_port())) != srs_success) {
|
||||||
return srs_error_wrap(err, "init uri=%s", uri.get_url().c_str());
|
return srs_error_wrap(err, "init uri=%s", uri.get_url().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string req = obj->dumps();
|
std::string req = obj->dumps();
|
||||||
ISrsHttpMessage *msg_raw = NULL;
|
ISrsHttpMessage *msg_raw = NULL;
|
||||||
if ((err = http.post(uri.get_path(), req, &msg_raw)) != srs_success) {
|
if ((err = http->post(uri.get_path(), req, &msg_raw)) != srs_success) {
|
||||||
return srs_error_wrap(err, "http post hartbeart uri failed. url=%s, request=%s", url.c_str(), req.c_str());
|
return srs_error_wrap(err, "http post hartbeart uri failed. url=%s, request=%s", url.c_str(), req.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,17 @@
|
||||||
|
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
|
||||||
|
class ISrsAppConfig;
|
||||||
|
class ISrsAppFactory;
|
||||||
|
|
||||||
// The http heartbeat to api-server to notice api that the information of SRS.
|
// The http heartbeat to api-server to notice api that the information of SRS.
|
||||||
class SrsHttpHeartbeat
|
class SrsHttpHeartbeat
|
||||||
{
|
{
|
||||||
|
// clang-format off
|
||||||
|
SRS_DECLARE_PRIVATE: // clang-format on
|
||||||
|
ISrsAppConfig *config_;
|
||||||
|
ISrsAppFactory *app_factory_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SrsHttpHeartbeat();
|
SrsHttpHeartbeat();
|
||||||
virtual ~SrsHttpHeartbeat();
|
virtual ~SrsHttpHeartbeat();
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <srs_app_http_conn.hpp>
|
#include <srs_app_http_conn.hpp>
|
||||||
#include <srs_app_statistic.hpp>
|
#include <srs_app_statistic.hpp>
|
||||||
|
|
||||||
|
#include <srs_app_factory.hpp>
|
||||||
#include <srs_app_utility.hpp>
|
#include <srs_app_utility.hpp>
|
||||||
#include <srs_core_autofree.hpp>
|
#include <srs_core_autofree.hpp>
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
|
|
@ -18,7 +19,6 @@
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
#include <srs_protocol_json.hpp>
|
#include <srs_protocol_json.hpp>
|
||||||
#include <srs_protocol_utility.hpp>
|
#include <srs_protocol_utility.hpp>
|
||||||
#include <srs_app_factory.hpp>
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,27 @@ int64_t SrsProcSystemStat::total()
|
||||||
return user_ + nice_ + sys_ + idle_ + iowait_ + irq_ + softirq_ + steal_ + guest_;
|
return user_ + nice_ + sys_ + idle_ + iowait_ + irq_ + softirq_ + steal_ + guest_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISrsHost::ISrsHost()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsHost::~ISrsHost()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsHost::SrsHost()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsHost::~SrsHost()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsProcSelfStat *SrsHost::self_proc_stat()
|
||||||
|
{
|
||||||
|
return srs_get_self_proc_stat();
|
||||||
|
}
|
||||||
|
|
||||||
SrsProcSelfStat *srs_get_self_proc_stat()
|
SrsProcSelfStat *srs_get_self_proc_stat()
|
||||||
{
|
{
|
||||||
return &_srs_system_cpu_self_stat;
|
return &_srs_system_cpu_self_stat;
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,28 @@ public:
|
||||||
int64_t total();
|
int64_t total();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The host interface.
|
||||||
|
class ISrsHost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ISrsHost();
|
||||||
|
virtual ~ISrsHost();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SrsProcSelfStat *self_proc_stat() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the host info.
|
||||||
|
class SrsHost : public ISrsHost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsHost();
|
||||||
|
virtual ~SrsHost();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SrsProcSelfStat *self_proc_stat();
|
||||||
|
};
|
||||||
|
|
||||||
// Get system cpu stat, use cache to avoid performance problem.
|
// Get system cpu stat, use cache to avoid performance problem.
|
||||||
extern SrsProcSelfStat *srs_get_self_proc_stat();
|
extern SrsProcSelfStat *srs_get_self_proc_stat();
|
||||||
// Get system cpu stat, use cache to avoid performance problem.
|
// Get system cpu stat, use cache to avoid performance problem.
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,18 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_app_caster_flv.hpp>
|
#include <srs_app_caster_flv.hpp>
|
||||||
|
#include <srs_app_circuit_breaker.hpp>
|
||||||
#include <srs_app_encoder.hpp>
|
#include <srs_app_encoder.hpp>
|
||||||
#include <srs_app_ffmpeg.hpp>
|
#include <srs_app_ffmpeg.hpp>
|
||||||
|
#include <srs_app_heartbeat.hpp>
|
||||||
#include <srs_app_http_conn.hpp>
|
#include <srs_app_http_conn.hpp>
|
||||||
#include <srs_app_latest_version.hpp>
|
#include <srs_app_latest_version.hpp>
|
||||||
#include <srs_app_mpegts_udp.hpp>
|
#include <srs_app_mpegts_udp.hpp>
|
||||||
#include <srs_app_ng_exec.hpp>
|
#include <srs_app_ng_exec.hpp>
|
||||||
#include <srs_app_process.hpp>
|
#include <srs_app_process.hpp>
|
||||||
#include <srs_app_recv_thread.hpp>
|
#include <srs_app_recv_thread.hpp>
|
||||||
|
#include <srs_app_refer.hpp>
|
||||||
|
#include <srs_app_utility.hpp>
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
#include <srs_kernel_packet.hpp>
|
#include <srs_kernel_packet.hpp>
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
|
|
@ -3958,3 +3962,696 @@ VOID TEST(NgExecTest, ParseExecPublishWithMultipleArgs)
|
||||||
// Clean up - set to NULL to avoid double-free
|
// Clean up - set to NULL to avoid double-free
|
||||||
ng_exec->config_ = NULL;
|
ng_exec->config_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mock ISrsHttpMessage implementation for SrsHttpHeartbeat
|
||||||
|
MockHttpMessageForHeartbeat::MockHttpMessageForHeartbeat()
|
||||||
|
{
|
||||||
|
status_code_ = 200;
|
||||||
|
body_content_ = "";
|
||||||
|
body_reader_ = new MockBufferReader("");
|
||||||
|
}
|
||||||
|
|
||||||
|
MockHttpMessageForHeartbeat::~MockHttpMessageForHeartbeat()
|
||||||
|
{
|
||||||
|
srs_freep(body_reader_);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MockHttpMessageForHeartbeat::method()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MockHttpMessageForHeartbeat::status_code()
|
||||||
|
{
|
||||||
|
return status_code_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::method_str()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::url()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::host()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::path()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::query()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::ext()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t MockHttpMessageForHeartbeat::body_read_all(std::string &body)
|
||||||
|
{
|
||||||
|
body = body_content_;
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsHttpResponseReader *MockHttpMessageForHeartbeat::body_reader()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t MockHttpMessageForHeartbeat::content_length()
|
||||||
|
{
|
||||||
|
return body_content_.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::query_get(std::string key)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsHttpHeader *MockHttpMessageForHeartbeat::header()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockHttpMessageForHeartbeat::is_jsonp()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockHttpMessageForHeartbeat::is_keep_alive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsRequest *MockHttpMessageForHeartbeat::to_request(std::string vhost)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::parse_rest_id(std::string pattern)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MockHttpMessageForHeartbeat::message_type()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockHttpMessageForHeartbeat::is_http_get()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockHttpMessageForHeartbeat::is_http_put()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockHttpMessageForHeartbeat::is_http_post()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockHttpMessageForHeartbeat::is_http_delete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockHttpMessageForHeartbeat::is_http_options()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockHttpMessageForHeartbeat::uri()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockHttpMessageForHeartbeat::reset()
|
||||||
|
{
|
||||||
|
status_code_ = 200;
|
||||||
|
body_content_ = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock ISrsHttpClient implementation for SrsHttpHeartbeat
|
||||||
|
MockHttpClientForHeartbeat::MockHttpClientForHeartbeat()
|
||||||
|
{
|
||||||
|
initialize_called_ = false;
|
||||||
|
post_called_ = false;
|
||||||
|
port_ = 0;
|
||||||
|
mock_response_ = NULL;
|
||||||
|
initialize_error_ = srs_success;
|
||||||
|
post_error_ = srs_success;
|
||||||
|
should_delete_response_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MockHttpClientForHeartbeat::~MockHttpClientForHeartbeat()
|
||||||
|
{
|
||||||
|
srs_freep(initialize_error_);
|
||||||
|
srs_freep(post_error_);
|
||||||
|
// Don't delete mock_response_ - it's managed by the caller or already deleted
|
||||||
|
mock_response_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t MockHttpClientForHeartbeat::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 MockHttpClientForHeartbeat::get(std::string path, std::string req, ISrsHttpMessage **ppmsg)
|
||||||
|
{
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t MockHttpClientForHeartbeat::post(std::string path, std::string req, ISrsHttpMessage **ppmsg)
|
||||||
|
{
|
||||||
|
post_called_ = true;
|
||||||
|
path_ = path;
|
||||||
|
request_body_ = req;
|
||||||
|
if (ppmsg && mock_response_) {
|
||||||
|
*ppmsg = (ISrsHttpMessage *)mock_response_;
|
||||||
|
}
|
||||||
|
return srs_error_copy(post_error_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockHttpClientForHeartbeat::set_recv_timeout(srs_utime_t tm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockHttpClientForHeartbeat::kbps_sample(const char *label, srs_utime_t age)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockHttpClientForHeartbeat::reset()
|
||||||
|
{
|
||||||
|
initialize_called_ = false;
|
||||||
|
post_called_ = false;
|
||||||
|
port_ = 0;
|
||||||
|
schema_ = "";
|
||||||
|
host_ = "";
|
||||||
|
path_ = "";
|
||||||
|
request_body_ = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock ISrsAppFactory implementation for SrsHttpHeartbeat
|
||||||
|
MockAppFactoryForHeartbeat::MockAppFactoryForHeartbeat()
|
||||||
|
{
|
||||||
|
mock_http_client_ = NULL;
|
||||||
|
create_http_client_called_ = false;
|
||||||
|
should_delete_client_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MockAppFactoryForHeartbeat::~MockAppFactoryForHeartbeat()
|
||||||
|
{
|
||||||
|
if (should_delete_client_) {
|
||||||
|
srs_freep(mock_http_client_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsHttpClient *MockAppFactoryForHeartbeat::create_http_client()
|
||||||
|
{
|
||||||
|
create_http_client_called_ = true;
|
||||||
|
return mock_http_client_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockAppFactoryForHeartbeat::reset()
|
||||||
|
{
|
||||||
|
create_http_client_called_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock ISrsAppConfig implementation for SrsHttpHeartbeat
|
||||||
|
MockAppConfigForHeartbeat::MockAppConfigForHeartbeat()
|
||||||
|
{
|
||||||
|
heartbeat_url_ = "";
|
||||||
|
heartbeat_device_id_ = "";
|
||||||
|
heartbeat_summaries_ = false;
|
||||||
|
heartbeat_ports_ = false;
|
||||||
|
stats_network_ = 0;
|
||||||
|
http_stream_enabled_ = false;
|
||||||
|
http_api_enabled_ = false;
|
||||||
|
srt_enabled_ = false;
|
||||||
|
rtsp_server_enabled_ = false;
|
||||||
|
rtc_server_enabled_ = false;
|
||||||
|
rtc_server_tcp_enabled_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MockAppConfigForHeartbeat::~MockAppConfigForHeartbeat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockAppConfigForHeartbeat::get_heartbeat_url()
|
||||||
|
{
|
||||||
|
return heartbeat_url_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MockAppConfigForHeartbeat::get_heartbeat_device_id()
|
||||||
|
{
|
||||||
|
return heartbeat_device_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_heartbeat_summaries()
|
||||||
|
{
|
||||||
|
return heartbeat_summaries_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_heartbeat_ports()
|
||||||
|
{
|
||||||
|
return heartbeat_ports_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockAppConfigForHeartbeat::get_stats_network()
|
||||||
|
{
|
||||||
|
return stats_network_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MockAppConfigForHeartbeat::get_listens()
|
||||||
|
{
|
||||||
|
return listens_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_http_stream_enabled()
|
||||||
|
{
|
||||||
|
return http_stream_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MockAppConfigForHeartbeat::get_http_stream_listens()
|
||||||
|
{
|
||||||
|
return http_stream_listens_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_http_api_enabled()
|
||||||
|
{
|
||||||
|
return http_api_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MockAppConfigForHeartbeat::get_http_api_listens()
|
||||||
|
{
|
||||||
|
return http_api_listens_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_srt_enabled()
|
||||||
|
{
|
||||||
|
return srt_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MockAppConfigForHeartbeat::get_srt_listens()
|
||||||
|
{
|
||||||
|
return srt_listens_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_rtsp_server_enabled()
|
||||||
|
{
|
||||||
|
return rtsp_server_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MockAppConfigForHeartbeat::get_rtsp_server_listens()
|
||||||
|
{
|
||||||
|
return rtsp_server_listens_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_rtc_server_enabled()
|
||||||
|
{
|
||||||
|
return rtc_server_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MockAppConfigForHeartbeat::get_rtc_server_listens()
|
||||||
|
{
|
||||||
|
return rtc_server_listens_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForHeartbeat::get_rtc_server_tcp_enabled()
|
||||||
|
{
|
||||||
|
return rtc_server_tcp_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MockAppConfigForHeartbeat::get_rtc_server_tcp_listens()
|
||||||
|
{
|
||||||
|
return rtc_server_tcp_listens_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock ISrsAppConfig implementation for SrsCircuitBreaker
|
||||||
|
MockAppConfigForCircuitBreaker::MockAppConfigForCircuitBreaker()
|
||||||
|
{
|
||||||
|
circuit_breaker_enabled_ = true;
|
||||||
|
high_threshold_ = 90;
|
||||||
|
high_pulse_ = 2;
|
||||||
|
critical_threshold_ = 95;
|
||||||
|
critical_pulse_ = 1;
|
||||||
|
dying_threshold_ = 99;
|
||||||
|
dying_pulse_ = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
MockAppConfigForCircuitBreaker::~MockAppConfigForCircuitBreaker()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MockAppConfigForCircuitBreaker::get_circuit_breaker()
|
||||||
|
{
|
||||||
|
return circuit_breaker_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockAppConfigForCircuitBreaker::get_high_threshold()
|
||||||
|
{
|
||||||
|
return high_threshold_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockAppConfigForCircuitBreaker::get_high_pulse()
|
||||||
|
{
|
||||||
|
return high_pulse_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockAppConfigForCircuitBreaker::get_critical_threshold()
|
||||||
|
{
|
||||||
|
return critical_threshold_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockAppConfigForCircuitBreaker::get_critical_pulse()
|
||||||
|
{
|
||||||
|
return critical_pulse_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockAppConfigForCircuitBreaker::get_dying_threshold()
|
||||||
|
{
|
||||||
|
return dying_threshold_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MockAppConfigForCircuitBreaker::get_dying_pulse()
|
||||||
|
{
|
||||||
|
return dying_pulse_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock ISrsFastTimer implementation for SrsCircuitBreaker
|
||||||
|
MockFastTimerForCircuitBreaker::MockFastTimerForCircuitBreaker()
|
||||||
|
{
|
||||||
|
subscribe_called_ = false;
|
||||||
|
subscribed_handler_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MockFastTimerForCircuitBreaker::~MockFastTimerForCircuitBreaker()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t MockFastTimerForCircuitBreaker::start()
|
||||||
|
{
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockFastTimerForCircuitBreaker::subscribe(ISrsFastTimerHandler *handler)
|
||||||
|
{
|
||||||
|
subscribe_called_ = true;
|
||||||
|
subscribed_handler_ = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockFastTimerForCircuitBreaker::unsubscribe(ISrsFastTimerHandler *handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MockFastTimerForCircuitBreaker::reset()
|
||||||
|
{
|
||||||
|
subscribe_called_ = false;
|
||||||
|
subscribed_handler_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock ISrsSharedTimer implementation for SrsCircuitBreaker
|
||||||
|
MockSharedTimerForCircuitBreaker::MockSharedTimerForCircuitBreaker()
|
||||||
|
{
|
||||||
|
timer1s_ = new MockFastTimerForCircuitBreaker();
|
||||||
|
}
|
||||||
|
|
||||||
|
MockSharedTimerForCircuitBreaker::~MockSharedTimerForCircuitBreaker()
|
||||||
|
{
|
||||||
|
srs_freep(timer1s_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsFastTimer *MockSharedTimerForCircuitBreaker::timer20ms()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsFastTimer *MockSharedTimerForCircuitBreaker::timer100ms()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsFastTimer *MockSharedTimerForCircuitBreaker::timer1s()
|
||||||
|
{
|
||||||
|
return timer1s_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsFastTimer *MockSharedTimerForCircuitBreaker::timer5s()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock ISrsHost implementation for SrsCircuitBreaker
|
||||||
|
MockHostForCircuitBreaker::MockHostForCircuitBreaker()
|
||||||
|
{
|
||||||
|
proc_stat_ = new SrsProcSelfStat();
|
||||||
|
proc_stat_->percent_ = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MockHostForCircuitBreaker::~MockHostForCircuitBreaker()
|
||||||
|
{
|
||||||
|
srs_freep(proc_stat_);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsProcSelfStat *MockHostForCircuitBreaker::self_proc_stat()
|
||||||
|
{
|
||||||
|
return proc_stat_;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID TEST(HttpHeartbeatTest, DoHeartbeatWithAllPortsEnabled)
|
||||||
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
// Create mock config with all protocols enabled
|
||||||
|
SrsUniquePtr<MockAppConfigForHeartbeat> mock_config(new MockAppConfigForHeartbeat());
|
||||||
|
mock_config->heartbeat_url_ = "http://127.0.0.1:8080/api/v1/heartbeat";
|
||||||
|
mock_config->heartbeat_device_id_ = "test-device-001";
|
||||||
|
mock_config->heartbeat_summaries_ = false;
|
||||||
|
mock_config->heartbeat_ports_ = true;
|
||||||
|
mock_config->stats_network_ = 0;
|
||||||
|
|
||||||
|
// Configure RTMP listen endpoints
|
||||||
|
mock_config->listens_.push_back("1935");
|
||||||
|
mock_config->listens_.push_back("19350");
|
||||||
|
|
||||||
|
// Configure HTTP stream endpoints
|
||||||
|
mock_config->http_stream_enabled_ = true;
|
||||||
|
mock_config->http_stream_listens_.push_back("8080");
|
||||||
|
|
||||||
|
// Configure HTTP API endpoints
|
||||||
|
mock_config->http_api_enabled_ = true;
|
||||||
|
mock_config->http_api_listens_.push_back("1985");
|
||||||
|
|
||||||
|
// Configure SRT endpoints
|
||||||
|
mock_config->srt_enabled_ = true;
|
||||||
|
mock_config->srt_listens_.push_back("10080");
|
||||||
|
|
||||||
|
// Configure RTSP endpoints
|
||||||
|
mock_config->rtsp_server_enabled_ = true;
|
||||||
|
mock_config->rtsp_server_listens_.push_back("554");
|
||||||
|
|
||||||
|
// Configure WebRTC endpoints
|
||||||
|
mock_config->rtc_server_enabled_ = true;
|
||||||
|
mock_config->rtc_server_listens_.push_back("8000");
|
||||||
|
mock_config->rtc_server_tcp_enabled_ = true;
|
||||||
|
mock_config->rtc_server_tcp_listens_.push_back("8000");
|
||||||
|
|
||||||
|
// Create mock HTTP response
|
||||||
|
MockHttpMessageForHeartbeat *mock_response = new MockHttpMessageForHeartbeat();
|
||||||
|
mock_response->status_code_ = 200;
|
||||||
|
mock_response->body_content_ = "{\"code\":0,\"data\":{}}";
|
||||||
|
|
||||||
|
// Create mock HTTP client
|
||||||
|
MockHttpClientForHeartbeat *mock_http_client = new MockHttpClientForHeartbeat();
|
||||||
|
mock_http_client->mock_response_ = mock_response;
|
||||||
|
mock_http_client->should_delete_response_ = true; // Client will delete response
|
||||||
|
|
||||||
|
// Create mock app factory
|
||||||
|
SrsUniquePtr<MockAppFactoryForHeartbeat> mock_factory(new MockAppFactoryForHeartbeat());
|
||||||
|
mock_factory->mock_http_client_ = mock_http_client;
|
||||||
|
mock_factory->should_delete_client_ = true; // Factory will delete client
|
||||||
|
|
||||||
|
// Create SrsHttpHeartbeat and inject mocks
|
||||||
|
SrsUniquePtr<SrsHttpHeartbeat> heartbeat(new SrsHttpHeartbeat());
|
||||||
|
heartbeat->config_ = mock_config.get();
|
||||||
|
heartbeat->app_factory_ = mock_factory.get();
|
||||||
|
|
||||||
|
// Execute do_heartbeat
|
||||||
|
// Note: This will delete mock_http_client and mock_response via SrsUniquePtr in do_heartbeat()
|
||||||
|
// So we cannot verify mock_http_client fields after this call
|
||||||
|
HELPER_EXPECT_SUCCESS(heartbeat->do_heartbeat());
|
||||||
|
|
||||||
|
// Clean up - set to NULL to avoid double-free
|
||||||
|
heartbeat->config_ = NULL;
|
||||||
|
heartbeat->app_factory_ = NULL;
|
||||||
|
mock_factory->mock_http_client_ = NULL; // Already deleted by do_heartbeat()
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID TEST(ReferTest, CheckReferWithMatchingDomain)
|
||||||
|
{
|
||||||
|
srs_error_t err;
|
||||||
|
|
||||||
|
// Create SrsRefer instance
|
||||||
|
SrsUniquePtr<SrsRefer> refer(new SrsRefer());
|
||||||
|
|
||||||
|
// Create refer directive with allowed domains
|
||||||
|
SrsUniquePtr<SrsConfDirective> refer_conf(new SrsConfDirective());
|
||||||
|
refer_conf->name_ = "refer";
|
||||||
|
refer_conf->args_.push_back("github.com");
|
||||||
|
refer_conf->args_.push_back("github.io");
|
||||||
|
|
||||||
|
// Test 1: Valid page URL matching github.com domain
|
||||||
|
HELPER_EXPECT_SUCCESS(refer->check("http://www.github.com/path", refer_conf.get()));
|
||||||
|
|
||||||
|
// Test 2: Valid page URL matching github.io domain
|
||||||
|
HELPER_EXPECT_SUCCESS(refer->check("https://ossrs.github.io/index.html", refer_conf.get()));
|
||||||
|
|
||||||
|
// Test 3: Valid page URL with port number
|
||||||
|
HELPER_EXPECT_SUCCESS(refer->check("http://api.github.com:8080/api", refer_conf.get()));
|
||||||
|
|
||||||
|
// Test 4: Invalid page URL not matching any allowed domain
|
||||||
|
HELPER_EXPECT_FAILED(refer->check("http://example.com/page", refer_conf.get()));
|
||||||
|
|
||||||
|
// Test 5: NULL refer directive should allow all
|
||||||
|
HELPER_EXPECT_SUCCESS(refer->check("http://any-domain.com/page", NULL));
|
||||||
|
|
||||||
|
// Test 6: Empty refer directive should deny access
|
||||||
|
SrsUniquePtr<SrsConfDirective> empty_refer(new SrsConfDirective());
|
||||||
|
empty_refer->name_ = "refer";
|
||||||
|
HELPER_EXPECT_FAILED(refer->check("http://example.com/page", empty_refer.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test SrsCircuitBreaker - covers the major use scenario:
|
||||||
|
// This test verifies the complete circuit breaker functionality including:
|
||||||
|
// 1. Initialize with configuration (enabled, thresholds, pulses)
|
||||||
|
// 2. Subscribe to timer for periodic CPU monitoring
|
||||||
|
// 3. Simulate CPU load changes via on_timer() callback
|
||||||
|
// 4. Verify water level transitions (high -> critical -> dying)
|
||||||
|
// 5. Verify water level decay when CPU load decreases
|
||||||
|
// 6. Test all three protection levels: high_water_level, critical_water_level, dying_water_level
|
||||||
|
VOID TEST(CircuitBreakerTest, InitializeAndWaterLevelTransitions)
|
||||||
|
{
|
||||||
|
srs_error_t err;
|
||||||
|
|
||||||
|
// Create mock dependencies
|
||||||
|
SrsUniquePtr<MockAppConfigForCircuitBreaker> mock_config(new MockAppConfigForCircuitBreaker());
|
||||||
|
SrsUniquePtr<MockSharedTimerForCircuitBreaker> mock_timer(new MockSharedTimerForCircuitBreaker());
|
||||||
|
MockHostForCircuitBreaker *mock_host = new MockHostForCircuitBreaker();
|
||||||
|
|
||||||
|
// Configure circuit breaker settings
|
||||||
|
mock_config->circuit_breaker_enabled_ = true;
|
||||||
|
mock_config->high_threshold_ = 90; // CPU > 90% triggers high water level
|
||||||
|
mock_config->high_pulse_ = 2; // High level lasts for 2 timer ticks
|
||||||
|
mock_config->critical_threshold_ = 95; // CPU > 95% triggers critical water level
|
||||||
|
mock_config->critical_pulse_ = 1; // Critical level lasts for 1 timer tick
|
||||||
|
mock_config->dying_threshold_ = 99; // CPU > 99% triggers dying water level
|
||||||
|
mock_config->dying_pulse_ = 5; // Dying level requires 5 consecutive ticks
|
||||||
|
|
||||||
|
// Create SrsCircuitBreaker
|
||||||
|
SrsUniquePtr<SrsCircuitBreaker> breaker(new SrsCircuitBreaker());
|
||||||
|
|
||||||
|
// Inject mock dependencies
|
||||||
|
breaker->config_ = mock_config.get();
|
||||||
|
breaker->shared_timer_ = mock_timer.get();
|
||||||
|
breaker->host_ = mock_host;
|
||||||
|
|
||||||
|
// Test 1: Initialize - should load config and subscribe to timer
|
||||||
|
HELPER_EXPECT_SUCCESS(breaker->initialize());
|
||||||
|
|
||||||
|
// Verify timer subscription
|
||||||
|
EXPECT_TRUE(mock_timer->timer1s_->subscribe_called_);
|
||||||
|
EXPECT_EQ(breaker.get(), mock_timer->timer1s_->subscribed_handler_);
|
||||||
|
|
||||||
|
// Test 2: Initially all water levels should be false (CPU is 0%)
|
||||||
|
EXPECT_FALSE(breaker->hybrid_high_water_level());
|
||||||
|
EXPECT_FALSE(breaker->hybrid_critical_water_level());
|
||||||
|
EXPECT_FALSE(breaker->hybrid_dying_water_level());
|
||||||
|
|
||||||
|
// Test 3: Simulate high CPU load (91% > high_threshold 90%)
|
||||||
|
mock_host->proc_stat_->percent_ = 0.91; // 91% CPU
|
||||||
|
HELPER_EXPECT_SUCCESS(breaker->on_timer(1 * SRS_UTIME_SECONDS));
|
||||||
|
|
||||||
|
// After 1 tick with high CPU, high water level should be active
|
||||||
|
EXPECT_TRUE(breaker->hybrid_high_water_level());
|
||||||
|
EXPECT_FALSE(breaker->hybrid_critical_water_level());
|
||||||
|
EXPECT_FALSE(breaker->hybrid_dying_water_level());
|
||||||
|
|
||||||
|
// Test 4: Simulate critical CPU load (96% > critical_threshold 95%)
|
||||||
|
mock_host->proc_stat_->percent_ = 0.96; // 96% CPU
|
||||||
|
HELPER_EXPECT_SUCCESS(breaker->on_timer(1 * SRS_UTIME_SECONDS));
|
||||||
|
|
||||||
|
// After 1 tick with critical CPU, both high and critical should be active
|
||||||
|
EXPECT_TRUE(breaker->hybrid_high_water_level());
|
||||||
|
EXPECT_TRUE(breaker->hybrid_critical_water_level());
|
||||||
|
EXPECT_FALSE(breaker->hybrid_dying_water_level());
|
||||||
|
|
||||||
|
// Test 5: Simulate dying CPU load (99.5% > dying_threshold 99%)
|
||||||
|
// Need 5 consecutive ticks to activate dying level
|
||||||
|
mock_host->proc_stat_->percent_ = 0.995; // 99.5% CPU
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
HELPER_EXPECT_SUCCESS(breaker->on_timer(1 * SRS_UTIME_SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// After 5 consecutive ticks with dying CPU, all levels should be active
|
||||||
|
EXPECT_TRUE(breaker->hybrid_high_water_level());
|
||||||
|
EXPECT_TRUE(breaker->hybrid_critical_water_level());
|
||||||
|
EXPECT_TRUE(breaker->hybrid_dying_water_level());
|
||||||
|
|
||||||
|
// Test 6: Simulate CPU load decrease (back to 50%)
|
||||||
|
mock_host->proc_stat_->percent_ = 0.50; // 50% CPU
|
||||||
|
HELPER_EXPECT_SUCCESS(breaker->on_timer(1 * SRS_UTIME_SECONDS));
|
||||||
|
|
||||||
|
// Dying level should immediately reset to 0 when CPU drops
|
||||||
|
EXPECT_FALSE(breaker->hybrid_dying_water_level());
|
||||||
|
// Critical should also become false (since dying is false and critical_water_level_ will decay)
|
||||||
|
// But high should still be active (high_water_level_ = 2, needs 2 ticks to decay)
|
||||||
|
EXPECT_TRUE(breaker->hybrid_high_water_level());
|
||||||
|
// Critical is false because dying is false and critical_water_level_ decayed from 1 to 0
|
||||||
|
EXPECT_FALSE(breaker->hybrid_critical_water_level());
|
||||||
|
|
||||||
|
// Test 7: Continue with low CPU - high should decay to 0 after 1 more tick
|
||||||
|
HELPER_EXPECT_SUCCESS(breaker->on_timer(1 * SRS_UTIME_SECONDS));
|
||||||
|
EXPECT_FALSE(breaker->hybrid_high_water_level()); // High now false (high_water_level_ = 0)
|
||||||
|
EXPECT_FALSE(breaker->hybrid_critical_water_level());
|
||||||
|
EXPECT_FALSE(breaker->hybrid_dying_water_level());
|
||||||
|
|
||||||
|
// Test 9: Verify disabled circuit breaker returns false for all levels
|
||||||
|
mock_config->circuit_breaker_enabled_ = false;
|
||||||
|
SrsUniquePtr<SrsCircuitBreaker> disabled_breaker(new SrsCircuitBreaker());
|
||||||
|
disabled_breaker->config_ = mock_config.get();
|
||||||
|
disabled_breaker->shared_timer_ = mock_timer.get();
|
||||||
|
disabled_breaker->host_ = mock_host;
|
||||||
|
HELPER_EXPECT_SUCCESS(disabled_breaker->initialize());
|
||||||
|
|
||||||
|
// Even with high CPU, disabled breaker should return false
|
||||||
|
mock_host->proc_stat_->percent_ = 0.99;
|
||||||
|
HELPER_EXPECT_SUCCESS(disabled_breaker->on_timer(1 * SRS_UTIME_SECONDS));
|
||||||
|
EXPECT_FALSE(disabled_breaker->hybrid_high_water_level());
|
||||||
|
EXPECT_FALSE(disabled_breaker->hybrid_critical_water_level());
|
||||||
|
EXPECT_FALSE(disabled_breaker->hybrid_dying_water_level());
|
||||||
|
|
||||||
|
// Clean up - set to NULL to avoid double-free
|
||||||
|
breaker->config_ = NULL;
|
||||||
|
breaker->shared_timer_ = NULL;
|
||||||
|
breaker->host_ = NULL;
|
||||||
|
disabled_breaker->config_ = NULL;
|
||||||
|
disabled_breaker->shared_timer_ = NULL;
|
||||||
|
disabled_breaker->host_ = NULL;
|
||||||
|
srs_freep(mock_host);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,21 @@
|
||||||
#include <srs_utest.hpp>
|
#include <srs_utest.hpp>
|
||||||
|
|
||||||
#include <srs_app_caster_flv.hpp>
|
#include <srs_app_caster_flv.hpp>
|
||||||
|
#include <srs_app_circuit_breaker.hpp>
|
||||||
#include <srs_app_config.hpp>
|
#include <srs_app_config.hpp>
|
||||||
#include <srs_app_factory.hpp>
|
#include <srs_app_factory.hpp>
|
||||||
#include <srs_app_ffmpeg.hpp>
|
#include <srs_app_ffmpeg.hpp>
|
||||||
#include <srs_app_listener.hpp>
|
#include <srs_app_listener.hpp>
|
||||||
#include <srs_app_mpegts_udp.hpp>
|
#include <srs_app_mpegts_udp.hpp>
|
||||||
|
#include <srs_app_utility.hpp>
|
||||||
#include <srs_kernel_pithy_print.hpp>
|
#include <srs_kernel_pithy_print.hpp>
|
||||||
|
#include <srs_protocol_http_client.hpp>
|
||||||
#include <srs_protocol_raw_avc.hpp>
|
#include <srs_protocol_raw_avc.hpp>
|
||||||
#include <srs_protocol_rtmp_conn.hpp>
|
#include <srs_protocol_rtmp_conn.hpp>
|
||||||
#include <srs_protocol_http_client.hpp>
|
|
||||||
#include <srs_utest_app10.hpp>
|
#include <srs_utest_app10.hpp>
|
||||||
#include <srs_utest_app11.hpp>
|
#include <srs_utest_app11.hpp>
|
||||||
#include <srs_utest_app6.hpp>
|
#include <srs_utest_app6.hpp>
|
||||||
|
#include <srs_utest_kernel.hpp>
|
||||||
|
|
||||||
// Mock ISrsAppConfig for testing SrsUdpCasterListener
|
// Mock ISrsAppConfig for testing SrsUdpCasterListener
|
||||||
class MockAppConfigForUdpCaster : public MockAppConfig
|
class MockAppConfigForUdpCaster : public MockAppConfig
|
||||||
|
|
@ -877,4 +880,213 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Mock ISrsHttpMessage for testing SrsHttpHeartbeat
|
||||||
|
class MockHttpMessageForHeartbeat : public ISrsHttpMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int status_code_;
|
||||||
|
std::string body_content_;
|
||||||
|
ISrsReader *body_reader_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockHttpMessageForHeartbeat();
|
||||||
|
virtual ~MockHttpMessageForHeartbeat();
|
||||||
|
|
||||||
|
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 SrsHttpHeader *header();
|
||||||
|
virtual bool is_jsonp();
|
||||||
|
virtual bool is_keep_alive();
|
||||||
|
virtual ISrsRequest *to_request(std::string vhost);
|
||||||
|
virtual std::string parse_rest_id(std::string pattern);
|
||||||
|
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();
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock ISrsHttpClient for testing SrsHttpHeartbeat
|
||||||
|
class MockHttpClientForHeartbeat : public ISrsHttpClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool initialize_called_;
|
||||||
|
bool post_called_;
|
||||||
|
std::string schema_;
|
||||||
|
std::string host_;
|
||||||
|
int port_;
|
||||||
|
std::string path_;
|
||||||
|
std::string request_body_;
|
||||||
|
MockHttpMessageForHeartbeat *mock_response_;
|
||||||
|
srs_error_t initialize_error_;
|
||||||
|
srs_error_t post_error_;
|
||||||
|
bool should_delete_response_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockHttpClientForHeartbeat();
|
||||||
|
virtual ~MockHttpClientForHeartbeat();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual srs_error_t initialize(std::string schema, std::string h, int p, srs_utime_t tm = SRS_HTTP_CLIENT_TIMEOUT);
|
||||||
|
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);
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock ISrsAppFactory for testing SrsHttpHeartbeat
|
||||||
|
class MockAppFactoryForHeartbeat : public SrsAppFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MockHttpClientForHeartbeat *mock_http_client_;
|
||||||
|
bool create_http_client_called_;
|
||||||
|
bool should_delete_client_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockAppFactoryForHeartbeat();
|
||||||
|
virtual ~MockAppFactoryForHeartbeat();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ISrsHttpClient *create_http_client();
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock ISrsAppConfig for testing SrsHttpHeartbeat
|
||||||
|
class MockAppConfigForHeartbeat : public MockAppConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string heartbeat_url_;
|
||||||
|
std::string heartbeat_device_id_;
|
||||||
|
bool heartbeat_summaries_;
|
||||||
|
bool heartbeat_ports_;
|
||||||
|
int stats_network_;
|
||||||
|
bool http_stream_enabled_;
|
||||||
|
bool http_api_enabled_;
|
||||||
|
bool srt_enabled_;
|
||||||
|
bool rtsp_server_enabled_;
|
||||||
|
bool rtc_server_enabled_;
|
||||||
|
bool rtc_server_tcp_enabled_;
|
||||||
|
std::vector<std::string> listens_;
|
||||||
|
std::vector<std::string> http_stream_listens_;
|
||||||
|
std::vector<std::string> http_api_listens_;
|
||||||
|
std::vector<std::string> srt_listens_;
|
||||||
|
std::vector<std::string> rtsp_server_listens_;
|
||||||
|
std::vector<std::string> rtc_server_listens_;
|
||||||
|
std::vector<std::string> rtc_server_tcp_listens_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockAppConfigForHeartbeat();
|
||||||
|
virtual ~MockAppConfigForHeartbeat();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual std::string get_heartbeat_url();
|
||||||
|
virtual std::string get_heartbeat_device_id();
|
||||||
|
virtual bool get_heartbeat_summaries();
|
||||||
|
virtual bool get_heartbeat_ports();
|
||||||
|
virtual int get_stats_network();
|
||||||
|
virtual std::vector<std::string> get_listens();
|
||||||
|
virtual bool get_http_stream_enabled();
|
||||||
|
virtual std::vector<std::string> get_http_stream_listens();
|
||||||
|
virtual bool get_http_api_enabled();
|
||||||
|
virtual std::vector<std::string> get_http_api_listens();
|
||||||
|
virtual bool get_srt_enabled();
|
||||||
|
virtual std::vector<std::string> get_srt_listens();
|
||||||
|
virtual bool get_rtsp_server_enabled();
|
||||||
|
virtual std::vector<std::string> get_rtsp_server_listens();
|
||||||
|
virtual bool get_rtc_server_enabled();
|
||||||
|
virtual std::vector<std::string> get_rtc_server_listens();
|
||||||
|
virtual bool get_rtc_server_tcp_enabled();
|
||||||
|
virtual std::vector<std::string> get_rtc_server_tcp_listens();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock ISrsAppConfig for testing SrsCircuitBreaker
|
||||||
|
class MockAppConfigForCircuitBreaker : public MockAppConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool circuit_breaker_enabled_;
|
||||||
|
int high_threshold_;
|
||||||
|
int high_pulse_;
|
||||||
|
int critical_threshold_;
|
||||||
|
int critical_pulse_;
|
||||||
|
int dying_threshold_;
|
||||||
|
int dying_pulse_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockAppConfigForCircuitBreaker();
|
||||||
|
virtual ~MockAppConfigForCircuitBreaker();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool get_circuit_breaker();
|
||||||
|
virtual int get_high_threshold();
|
||||||
|
virtual int get_high_pulse();
|
||||||
|
virtual int get_critical_threshold();
|
||||||
|
virtual int get_critical_pulse();
|
||||||
|
virtual int get_dying_threshold();
|
||||||
|
virtual int get_dying_pulse();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock ISrsFastTimer for testing SrsCircuitBreaker
|
||||||
|
class MockFastTimerForCircuitBreaker : public ISrsFastTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool subscribe_called_;
|
||||||
|
ISrsFastTimerHandler *subscribed_handler_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockFastTimerForCircuitBreaker();
|
||||||
|
virtual ~MockFastTimerForCircuitBreaker();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual srs_error_t start();
|
||||||
|
virtual void subscribe(ISrsFastTimerHandler *handler);
|
||||||
|
virtual void unsubscribe(ISrsFastTimerHandler *handler);
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock ISrsSharedTimer for testing SrsCircuitBreaker
|
||||||
|
class MockSharedTimerForCircuitBreaker : public ISrsSharedTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MockFastTimerForCircuitBreaker *timer1s_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockSharedTimerForCircuitBreaker();
|
||||||
|
virtual ~MockSharedTimerForCircuitBreaker();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ISrsFastTimer *timer20ms();
|
||||||
|
virtual ISrsFastTimer *timer100ms();
|
||||||
|
virtual ISrsFastTimer *timer1s();
|
||||||
|
virtual ISrsFastTimer *timer5s();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mock ISrsHost for testing SrsCircuitBreaker
|
||||||
|
class MockHostForCircuitBreaker : public ISrsHost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsProcSelfStat *proc_stat_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MockHostForCircuitBreaker();
|
||||||
|
virtual ~MockHostForCircuitBreaker();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual SrsProcSelfStat *self_proc_stat();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -403,6 +403,17 @@ public:
|
||||||
virtual int get_stats_network() { return 0; }
|
virtual int get_stats_network() { return 0; }
|
||||||
virtual bool get_heartbeat_enabled() { return false; }
|
virtual bool get_heartbeat_enabled() { return false; }
|
||||||
virtual srs_utime_t get_heartbeat_interval() { return 0; }
|
virtual srs_utime_t get_heartbeat_interval() { return 0; }
|
||||||
|
virtual std::string get_heartbeat_url() { return ""; }
|
||||||
|
virtual std::string get_heartbeat_device_id() { return ""; }
|
||||||
|
virtual bool get_heartbeat_summaries() { return false; }
|
||||||
|
virtual bool get_heartbeat_ports() { return false; }
|
||||||
|
virtual bool get_circuit_breaker() { return false; }
|
||||||
|
virtual int get_high_threshold() { return 0; }
|
||||||
|
virtual int get_high_pulse() { return 0; }
|
||||||
|
virtual int get_critical_threshold() { return 0; }
|
||||||
|
virtual int get_critical_pulse() { return 0; }
|
||||||
|
virtual int get_dying_threshold() { return 0; }
|
||||||
|
virtual int get_dying_pulse() { return 0; }
|
||||||
virtual std::string get_rtmps_ssl_cert() { return ""; }
|
virtual std::string get_rtmps_ssl_cert() { return ""; }
|
||||||
virtual std::string get_rtmps_ssl_key() { return ""; }
|
virtual std::string get_rtmps_ssl_key() { return ""; }
|
||||||
virtual SrsConfDirective *get_vhost(std::string vhost, bool try_default_vhost = true) { return NULL; }
|
virtual SrsConfDirective *get_vhost(std::string vhost, bool try_default_vhost = true) { return NULL; }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user