AI: Improve coverage for app rtmp module.
This commit is contained in:
parent
fc6a851d5f
commit
702a58df6a
|
|
@ -363,6 +363,71 @@ code_patterns:
|
|||
- pattern: "#ifdef SRS_VALGRIND"
|
||||
description: "Valgrind support"
|
||||
|
||||
dependency_injection_for_testing:
|
||||
- pattern: "assemble() method pattern"
|
||||
description: "MANDATORY pattern for making classes testable by separating construction from initialization - applies ONLY to production code, NOT to unit test code or mock classes"
|
||||
purpose: "Enables dependency injection for unit testing by deferring subscription/registration operations that depend on global state or external dependencies"
|
||||
|
||||
usage: |
|
||||
WRONG: Direct dependency in constructor (not testable)
|
||||
class SrsOriginHub {
|
||||
public:
|
||||
SrsOriginHub() {
|
||||
_srs_config->subscribe(this); // Hard dependency on global config
|
||||
}
|
||||
~SrsOriginHub() {
|
||||
_srs_config->unsubscribe(this);
|
||||
}
|
||||
};
|
||||
|
||||
CORRECT: Separate construction from initialization with assemble()
|
||||
class SrsOriginHub {
|
||||
private:
|
||||
SrsConfig* config_;
|
||||
public:
|
||||
SrsOriginHub() {
|
||||
config_ = _srs_config; // Store reference only
|
||||
}
|
||||
void assemble() {
|
||||
config_->subscribe(this); // Actual initialization
|
||||
}
|
||||
~SrsOriginHub() {
|
||||
config_->unsubscribe(this);
|
||||
config_ = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// Production code usage
|
||||
hub_ = new SrsOriginHub();
|
||||
hub_->assemble(); // Call immediately after construction
|
||||
|
||||
// Unit test usage
|
||||
SrsOriginHub* hub = new SrsOriginHub();
|
||||
hub->config_ = mock_config; // Inject mock dependency
|
||||
hub->assemble(); // Now uses mock config
|
||||
// Or skip assemble() entirely to avoid side effects
|
||||
|
||||
scope: "Applies ONLY to production code in trunk/src/app/, trunk/src/protocol/, trunk/src/kernel/, trunk/src/core/ - does NOT apply to unit test code or mock classes"
|
||||
|
||||
when_to_use:
|
||||
- "When constructor needs to invoke functions (e.g., subscribe(), register(), initialize() on dependencies)"
|
||||
- "Exception: Simple object creation functions like srs_mutex_new() can remain in constructor - no need to extract to assemble()"
|
||||
- "Rule: If constructor calls methods on dependencies, move those calls to assemble()"
|
||||
|
||||
when_not_to_use:
|
||||
- "In unit test code (trunk/src/utest/) - tests can use direct construction"
|
||||
- "In mock classes (Mock* classes in utest files) - mocks are designed for testing"
|
||||
- "For simple value initialization without external dependencies"
|
||||
- "When the class is already easily testable without this pattern"
|
||||
|
||||
benefits:
|
||||
- "Enables dependency injection for unit testing"
|
||||
- "Allows mocking of global dependencies"
|
||||
- "Separates object construction from initialization side effects"
|
||||
- "Makes code more testable without changing production behavior"
|
||||
|
||||
rationale: "This pattern enables unit testing by allowing mock dependencies to be injected before initialization, while maintaining clean production code that calls assemble() immediately after construction. Unit test code and mock classes don't need this pattern because they are already designed for testing purposes."
|
||||
|
||||
codec_handling:
|
||||
enhanced_rtmp:
|
||||
description: |
|
||||
|
|
|
|||
4
trunk/configure
vendored
4
trunk/configure
vendored
|
|
@ -382,8 +382,8 @@ if [[ $SRS_UTEST == YES ]]; then
|
|||
"srs_utest_st" "srs_utest_rtc2" "srs_utest_rtc3" "srs_utest_fmp4" "srs_utest_source_lock"
|
||||
"srs_utest_stream_token" "srs_utest_rtc_recv_track" "srs_utest_st2" "srs_utest_hevc_structs"
|
||||
"srs_utest_coworkers" "srs_utest_pithy_print" "srs_utest_kernel3" "srs_utest_protocol4"
|
||||
"srs_utest_protocol3" "srs_utest_app" "srs_utest_app2" "srs_utest_app3" "srs_utest_app4"
|
||||
"srs_utest_app5" "srs_utest_app6" "srs_utest_app7" "srs_utest_app8")
|
||||
"srs_utest_protocol3" "srs_utest_app" "srs_utest_app2" "srs_utest_app3" "srs_utest_app4"
|
||||
"srs_utest_app5" "srs_utest_app6" "srs_utest_app7" "srs_utest_app8" "srs_utest_app9")
|
||||
# Always include SRT utest
|
||||
MODULE_FILES+=("srs_utest_srt")
|
||||
if [[ $SRS_GB28181 == YES ]]; then
|
||||
|
|
|
|||
|
|
@ -172,10 +172,11 @@ srs_error_t SrsAppCasterFlv::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
SrsDynamicHttpConn *dconn = dynamic_cast<SrsDynamicHttpConn *>(hconn->handler());
|
||||
srs_assert(dconn);
|
||||
|
||||
std::string app = srs_path_filepath_dir(r->path());
|
||||
SrsPath path;
|
||||
std::string app = path.filepath_dir(r->path());
|
||||
app = srs_strings_trim_start(app, "/");
|
||||
|
||||
std::string stream = srs_path_filepath_base(r->path());
|
||||
std::string stream = path.filepath_base(r->path());
|
||||
stream = srs_strings_trim_start(stream, "/");
|
||||
|
||||
std::string o = output_;
|
||||
|
|
|
|||
|
|
@ -1576,7 +1576,8 @@ srs_error_t SrsConfig::parse_options(int argc, char **argv)
|
|||
}
|
||||
|
||||
// Make sure config file exists.
|
||||
if (!env_only_ && !srs_path_exists(config_file_)) {
|
||||
SrsPath path;
|
||||
if (!env_only_ && !path.exists(config_file_)) {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "no config file at %s", config_file_.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -1677,13 +1678,15 @@ srs_error_t SrsConfig::persistence()
|
|||
|
||||
// do persistence to writer.
|
||||
if ((err = do_persistence(&fw)) != srs_success) {
|
||||
::unlink(path.c_str());
|
||||
SrsPath p;
|
||||
p.unlink(path);
|
||||
return srs_error_wrap(err, "persistence");
|
||||
}
|
||||
|
||||
// rename the config file.
|
||||
if (::rename(path.c_str(), config_file_.c_str()) < 0) {
|
||||
::unlink(path.c_str());
|
||||
SrsPath p;
|
||||
p.unlink(path);
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_PERSISTENCE, "rename %s=>%s", path.c_str(), config_file_.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -2032,7 +2035,8 @@ srs_error_t SrsConfig::check_normal_config()
|
|||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "invalid stats.network=%d", get_stats_network());
|
||||
}
|
||||
if (true) {
|
||||
vector<SrsIPAddress *> ips = srs_get_local_ips();
|
||||
SrsProtocolUtility utility;
|
||||
vector<SrsIPAddress *> ips = utility.local_ips();
|
||||
int index = get_stats_network();
|
||||
if (index >= (int)ips.size()) {
|
||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "invalid stats.network=%d of %d",
|
||||
|
|
|
|||
|
|
@ -281,6 +281,88 @@ public:
|
|||
ISrsAppConfig();
|
||||
virtual ~ISrsAppConfig();
|
||||
|
||||
public:
|
||||
virtual void subscribe(ISrsReloadHandler *handler) = 0;
|
||||
virtual void unsubscribe(ISrsReloadHandler *handler) = 0;
|
||||
virtual srs_error_t reload(SrsReloadState *pstate) = 0;
|
||||
virtual srs_error_t persistence() = 0;
|
||||
virtual std::string config() = 0;
|
||||
|
||||
public:
|
||||
// Global server config
|
||||
virtual int get_max_connections() = 0;
|
||||
virtual std::string get_pid_file() = 0;
|
||||
virtual bool empty_ip_ok() = 0;
|
||||
virtual bool get_asprocess() = 0;
|
||||
virtual srs_utime_t get_grace_start_wait() = 0;
|
||||
virtual srs_utime_t get_grace_final_wait() = 0;
|
||||
virtual bool is_force_grace_quit() = 0;
|
||||
virtual bool inotify_auto_reload() = 0;
|
||||
virtual bool auto_reload_for_docker() = 0;
|
||||
|
||||
public:
|
||||
// RTMP config
|
||||
virtual std::vector<std::string> get_listens() = 0;
|
||||
virtual bool get_rtmps_enabled() = 0;
|
||||
virtual std::vector<std::string> get_rtmps_listen() = 0;
|
||||
|
||||
public:
|
||||
// HTTP API config
|
||||
virtual bool get_http_api_enabled() = 0;
|
||||
virtual std::vector<std::string> get_http_api_listens() = 0;
|
||||
virtual bool get_https_api_enabled() = 0;
|
||||
virtual std::vector<std::string> get_https_api_listens() = 0;
|
||||
virtual std::string get_https_api_ssl_key() = 0;
|
||||
virtual std::string get_https_api_ssl_cert() = 0;
|
||||
|
||||
public:
|
||||
// HTTP Server config
|
||||
virtual bool get_http_stream_enabled() = 0;
|
||||
virtual std::vector<std::string> get_http_stream_listens() = 0;
|
||||
virtual bool get_https_stream_enabled() = 0;
|
||||
virtual std::vector<std::string> get_https_stream_listens() = 0;
|
||||
virtual std::string get_https_stream_ssl_key() = 0;
|
||||
virtual std::string get_https_stream_ssl_cert() = 0;
|
||||
virtual std::string get_http_stream_dir() = 0;
|
||||
|
||||
public:
|
||||
// WebRTC config
|
||||
virtual bool get_rtc_server_enabled() = 0;
|
||||
virtual bool get_rtc_server_tcp_enabled() = 0;
|
||||
virtual std::vector<std::string> get_rtc_server_tcp_listens() = 0;
|
||||
virtual std::string get_rtc_server_protocol() = 0;
|
||||
virtual std::vector<std::string> get_rtc_server_listens() = 0;
|
||||
virtual int get_rtc_server_reuseport() = 0;
|
||||
|
||||
public:
|
||||
// RTSP config
|
||||
virtual bool get_rtsp_server_enabled() = 0;
|
||||
virtual std::vector<std::string> get_rtsp_server_listens() = 0;
|
||||
|
||||
public:
|
||||
// SRT config
|
||||
virtual std::vector<std::string> get_srt_listens() = 0;
|
||||
|
||||
public:
|
||||
// Stream caster config
|
||||
virtual std::vector<SrsConfDirective *> get_stream_casters() = 0;
|
||||
virtual bool get_stream_caster_enabled(SrsConfDirective *conf) = 0;
|
||||
virtual std::string get_stream_caster_engine(SrsConfDirective *conf) = 0;
|
||||
|
||||
public:
|
||||
// Exporter config
|
||||
virtual bool get_exporter_enabled() = 0;
|
||||
virtual std::string get_exporter_listen() = 0;
|
||||
|
||||
public:
|
||||
// Stats config
|
||||
virtual bool get_stats_enabled() = 0;
|
||||
|
||||
public:
|
||||
// Heartbeat config
|
||||
virtual bool get_heartbeat_enabled() = 0;
|
||||
virtual srs_utime_t get_heartbeat_interval() = 0;
|
||||
|
||||
public:
|
||||
virtual bool get_vhost_http_hooks_enabled(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_vhost_on_stop(std::string vhost) = 0;
|
||||
|
|
@ -326,6 +408,18 @@ public:
|
|||
virtual bool get_hls_ctx_enabled(std::string vhost) = 0;
|
||||
virtual bool get_hls_ts_ctx_enabled(std::string vhost) = 0;
|
||||
virtual bool get_hls_recover(std::string vhost) = 0;
|
||||
virtual bool get_forward_enabled(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_forwards(std::string vhost) = 0;
|
||||
virtual srs_utime_t get_queue_length(std::string vhost) = 0;
|
||||
virtual SrsConfDirective *get_forward_backend(std::string vhost) = 0;
|
||||
virtual bool get_atc(std::string vhost) = 0;
|
||||
virtual int get_time_jitter(std::string vhost) = 0;
|
||||
virtual bool get_mix_correct(std::string vhost) = 0;
|
||||
virtual bool try_annexb_first(std::string vhost) = 0;
|
||||
virtual bool get_vhost_is_edge(std::string vhost) = 0;
|
||||
virtual bool get_atc_auto(std::string vhost) = 0;
|
||||
virtual bool get_reduce_sequence_header(std::string vhost) = 0;
|
||||
virtual bool get_parse_sps(std::string vhost) = 0;
|
||||
};
|
||||
|
||||
// The config service provider.
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ SrsJsonAny *SrsCoWorkers::dumps(string vhost, string coworker, string app, strin
|
|||
service_ip = coworker_host;
|
||||
}
|
||||
if (service_ip.empty()) {
|
||||
service_ip = srs_get_public_internet_address();
|
||||
SrsProtocolUtility utility;
|
||||
service_ip = utility.public_internet_address();
|
||||
}
|
||||
|
||||
// The backend API endpoint.
|
||||
|
|
|
|||
|
|
@ -179,8 +179,11 @@ void SrsMpdWriter::dispose()
|
|||
if (req_) {
|
||||
string mpd_path = srs_path_build_stream(mpd_file_, req_->vhost_, req_->app_, req_->stream_);
|
||||
string full_path = home_ + "/" + mpd_path;
|
||||
if (unlink(full_path.c_str()) < 0) {
|
||||
srs_warn("ignore remove mpd failed, %s", full_path.c_str());
|
||||
SrsPath path;
|
||||
srs_error_t err = path.unlink(full_path);
|
||||
if (err != srs_success) {
|
||||
srs_warn("ignore remove mpd failed, %s, %s", full_path.c_str(), srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -207,8 +210,9 @@ srs_error_t SrsMpdWriter::on_publish()
|
|||
home_ = _srs_config->get_dash_path(r->vhost_);
|
||||
mpd_file_ = _srs_config->get_dash_mpd_file(r->vhost_);
|
||||
|
||||
SrsPath path;
|
||||
string mpd_path = srs_path_build_stream(mpd_file_, req_->vhost_, req_->app_, req_->stream_);
|
||||
fragment_home_ = srs_path_filepath_dir(mpd_path) + "/" + req_->stream_;
|
||||
fragment_home_ = path.filepath_dir(mpd_path) + "/" + req_->stream_;
|
||||
window_size_ = _srs_config->get_dash_window_size(r->vhost_);
|
||||
|
||||
srs_trace("DASH: Config fragment=%dms, period=%dms, window=%d, timeshit=%dms, home=%s, mpd=%s",
|
||||
|
|
@ -230,13 +234,14 @@ srs_error_t SrsMpdWriter::write(SrsFormat *format, SrsFragmentWindow *afragments
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsPath path;
|
||||
string mpd_path = srs_path_build_stream(mpd_file_, req_->vhost_, req_->app_, req_->stream_);
|
||||
string full_path = home_ + "/" + mpd_path;
|
||||
string full_home = srs_path_filepath_dir(full_path);
|
||||
string full_home = path.filepath_dir(full_path);
|
||||
|
||||
fragment_home_ = srs_path_filepath_dir(mpd_path) + "/" + req_->stream_;
|
||||
fragment_home_ = path.filepath_dir(mpd_path) + "/" + req_->stream_;
|
||||
|
||||
if ((err = srs_os_mkdir_all(full_home)) != srs_success) {
|
||||
if ((err = path.mkdir_all(full_home)) != srs_success) {
|
||||
return srs_error_wrap(err, "Create MPD home failed, home=%s", full_home.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -650,8 +655,9 @@ srs_error_t SrsDashController::refresh_init_mp4(SrsMediaPacket *msg, SrsFormat *
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsPath path_util;
|
||||
string full_home = home_ + "/" + req_->app_ + "/" + req_->stream_;
|
||||
if ((err = srs_os_mkdir_all(full_home)) != srs_success) {
|
||||
if ((err = path_util.mkdir_all(full_home)) != srs_success) {
|
||||
return srs_error_wrap(err, "Create media home failed, home=%s", full_home.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -680,6 +686,14 @@ srs_error_t SrsDashController::refresh_init_mp4(SrsMediaPacket *msg, SrsFormat *
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsDash::ISrsDash()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsDash::~ISrsDash()
|
||||
{
|
||||
}
|
||||
|
||||
SrsDash::SrsDash()
|
||||
{
|
||||
hub_ = NULL;
|
||||
|
|
|
|||
|
|
@ -162,8 +162,28 @@ private:
|
|||
virtual srs_error_t refresh_init_mp4(SrsMediaPacket *msg, SrsFormat *format);
|
||||
};
|
||||
|
||||
// The DASH interface.
|
||||
class ISrsDash
|
||||
{
|
||||
public:
|
||||
ISrsDash();
|
||||
virtual ~ISrsDash();
|
||||
|
||||
public:
|
||||
virtual void dispose() = 0;
|
||||
virtual srs_error_t cycle() = 0;
|
||||
virtual srs_utime_t cleanup_delay() = 0;
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
};
|
||||
|
||||
// The MPEG-DASH encoder, transmux RTMP to DASH.
|
||||
class SrsDash
|
||||
class SrsDash : public ISrsDash
|
||||
{
|
||||
private:
|
||||
bool enabled_;
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ srs_error_t SrsDvrSegmenter::open()
|
|||
}
|
||||
|
||||
string path = generate_path();
|
||||
if (srs_path_exists(path)) {
|
||||
SrsPath path_util;
|
||||
if (path_util.exists(path)) {
|
||||
return srs_error_new(ERROR_DVR_CANNOT_APPEND, "DVR can't append to exists path=%s", path.c_str());
|
||||
}
|
||||
fragment_->set_path(path);
|
||||
|
|
@ -903,6 +904,14 @@ srs_error_t SrsDvrSegmentPlan::update_duration(SrsMediaPacket *msg)
|
|||
return err;
|
||||
}
|
||||
|
||||
ISrsDvr::ISrsDvr()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsDvr::~ISrsDvr()
|
||||
{
|
||||
}
|
||||
|
||||
SrsDvr::SrsDvr()
|
||||
{
|
||||
hub_ = NULL;
|
||||
|
|
|
|||
|
|
@ -233,8 +233,24 @@ private:
|
|||
virtual srs_error_t update_duration(SrsMediaPacket *msg);
|
||||
};
|
||||
|
||||
// The DVR interface.
|
||||
class ISrsDvr
|
||||
{
|
||||
public:
|
||||
ISrsDvr();
|
||||
virtual ~ISrsDvr();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_publish(ISrsRequest *r) = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *metadata) = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
|
||||
};
|
||||
|
||||
// DVR(Digital Video Recorder) to record RTMP stream to flv/mp4 file.
|
||||
class SrsDvr : public ISrsReloadHandler
|
||||
class SrsDvr : public ISrsReloadHandler, public ISrsDvr
|
||||
{
|
||||
private:
|
||||
SrsOriginHub *hub_;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,14 @@ using namespace std;
|
|||
// for encoder to detect the dead loop
|
||||
static std::vector<std::string> _transcoded_url;
|
||||
|
||||
ISrsMediaEncoder::ISrsMediaEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsMediaEncoder::~ISrsMediaEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
SrsEncoder::SrsEncoder()
|
||||
{
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
|
|
|
|||
|
|
@ -19,9 +19,24 @@ class ISrsRequest;
|
|||
class SrsPithyPrint;
|
||||
class SrsFFMPEG;
|
||||
|
||||
// The encoder interface.
|
||||
class ISrsMediaEncoder
|
||||
{
|
||||
public:
|
||||
ISrsMediaEncoder();
|
||||
virtual ~ISrsMediaEncoder();
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_publish(ISrsRequest *req) = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
// Interface ISrsReusableThreadHandler.
|
||||
public:
|
||||
virtual srs_error_t cycle() = 0;
|
||||
};
|
||||
|
||||
// The encoder for a stream, may use multiple
|
||||
// ffmpegs to transcode the specified stream.
|
||||
class SrsEncoder : public ISrsCoroutineHandler
|
||||
class SrsEncoder : public ISrsCoroutineHandler, public ISrsMediaEncoder
|
||||
{
|
||||
private:
|
||||
std::string input_stream_name_;
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
#include <srs_app_factory.hpp>
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_rtmp_source.hpp>
|
||||
#include <srs_app_st.hpp>
|
||||
#include <srs_kernel_file.hpp>
|
||||
#include <srs_protocol_st.hpp>
|
||||
#include <srs_kernel_ts.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_st.hpp>
|
||||
|
||||
SrsAppFactory::SrsAppFactory()
|
||||
{
|
||||
|
|
@ -41,6 +42,18 @@ SrsPath *SrsAppFactory::create_path()
|
|||
return new SrsPath();
|
||||
}
|
||||
|
||||
SrsLiveSource *SrsAppFactory::create_live_source()
|
||||
{
|
||||
return new SrsLiveSource();
|
||||
}
|
||||
|
||||
ISrsOriginHub *SrsAppFactory::create_origin_hub()
|
||||
{
|
||||
SrsOriginHub *hub = new SrsOriginHub();
|
||||
hub->assemble();
|
||||
return hub;
|
||||
}
|
||||
|
||||
SrsFinalFactory::SrsFinalFactory()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
class ISrsFileWriter;
|
||||
class ISrsFileReader;
|
||||
class SrsPath;
|
||||
class SrsLiveSource;
|
||||
class ISrsOriginHub;
|
||||
|
||||
// The factory to create app objects.
|
||||
class SrsAppFactory
|
||||
|
|
@ -27,6 +29,8 @@ public:
|
|||
virtual ISrsFileWriter *create_enc_file_writer();
|
||||
virtual ISrsFileReader *create_file_reader();
|
||||
virtual SrsPath *create_path();
|
||||
virtual SrsLiveSource *create_live_source();
|
||||
virtual ISrsOriginHub *create_origin_hub();
|
||||
};
|
||||
|
||||
extern SrsAppFactory *_srs_app_factory;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,14 @@ using namespace std;
|
|||
#include <srs_protocol_rtmp_stack.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
ISrsForwarder::ISrsForwarder()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsForwarder::~ISrsForwarder()
|
||||
{
|
||||
}
|
||||
|
||||
SrsForwarder::SrsForwarder(SrsOriginHub *h)
|
||||
{
|
||||
hub_ = h;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,25 @@ class SrsOriginHub;
|
|||
class SrsKbps;
|
||||
class SrsSimpleRtmpClient;
|
||||
|
||||
// The forward interface.
|
||||
class ISrsForwarder
|
||||
{
|
||||
public:
|
||||
ISrsForwarder();
|
||||
virtual ~ISrsForwarder();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(ISrsRequest *r, std::string ep) = 0;
|
||||
virtual void set_queue_size(srs_utime_t queue_size) = 0;
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata) = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio) = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video) = 0;
|
||||
};
|
||||
|
||||
// Forward the stream to other servers.
|
||||
class SrsForwarder : public ISrsCoroutineHandler
|
||||
class SrsForwarder : public ISrsCoroutineHandler, public ISrsForwarder
|
||||
{
|
||||
private:
|
||||
// The ep to forward, server[:port].
|
||||
|
|
|
|||
|
|
@ -81,8 +81,9 @@ srs_error_t SrsFragment::unlink_file()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (::unlink(filepath_.c_str()) < 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_FRAGMENT_UNLINK, "unlink %s", filepath_.c_str());
|
||||
SrsPath path;
|
||||
if ((err = path.unlink(filepath_)) != srs_success) {
|
||||
return srs_error_wrap(err, "unlink %s", filepath_.c_str());
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
@ -92,9 +93,10 @@ srs_error_t SrsFragment::create_dir()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
std::string segment_dir = srs_path_filepath_dir(filepath_);
|
||||
SrsPath path;
|
||||
std::string segment_dir = path.filepath_dir(filepath_);
|
||||
|
||||
if ((err = srs_os_mkdir_all(segment_dir)) != srs_success) {
|
||||
if ((err = path.mkdir_all(segment_dir)) != srs_success) {
|
||||
return srs_error_wrap(err, "create %s", segment_dir.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -113,8 +115,9 @@ srs_error_t SrsFragment::unlink_tmpfile()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
string filepath = tmppath();
|
||||
if (::unlink(filepath.c_str()) < 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_FRAGMENT_UNLINK, "unlink tmp file %s", filepath.c_str());
|
||||
SrsPath path;
|
||||
if ((err = path.unlink(filepath)) != srs_success) {
|
||||
return srs_error_wrap(err, "unlink tmp file %s", filepath.c_str());
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -232,6 +232,14 @@ private:
|
|||
string path_;
|
||||
};
|
||||
|
||||
ISrsHds::ISrsHds()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHds::~ISrsHds()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHds::SrsHds()
|
||||
: currentSegment_(NULL), fragment_index_(1), video_sh_(NULL), audio_sh_(NULL), hds_req_(NULL), hds_enabled_(false)
|
||||
{
|
||||
|
|
@ -407,8 +415,9 @@ srs_error_t SrsHds::flush_mainfest()
|
|||
"</manifest>",
|
||||
hds_req_->stream_.c_str(), hds_req_->stream_.c_str(), hds_req_->stream_.c_str());
|
||||
|
||||
SrsPath path_util;
|
||||
string dir = _srs_config->get_hds_path(hds_req_->vhost_) + "/" + hds_req_->app_;
|
||||
if ((err = srs_os_mkdir_all(dir)) != srs_success) {
|
||||
if ((err = path_util.mkdir_all(dir)) != srs_success) {
|
||||
return srs_error_wrap(err, "hds create dir failed");
|
||||
}
|
||||
string path = dir + "/" + hds_req_->stream_ + ".f4m";
|
||||
|
|
@ -689,7 +698,8 @@ void SrsHds::adjust_windows()
|
|||
double windows_size_limit = srsu2ms(_srs_config->get_hds_window(hds_req_->vhost_));
|
||||
if (windows_size > windows_size_limit) {
|
||||
SrsHdsFragment *fragment = fragments_.front();
|
||||
unlink(fragment->fragment_path().c_str());
|
||||
SrsPath path;
|
||||
path.unlink(fragment->fragment_path());
|
||||
fragments_.erase(fragments_.begin());
|
||||
srs_freep(fragment);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,22 @@ class SrsMediaPacket;
|
|||
class SrsHdsFragment;
|
||||
class SrsLiveSource;
|
||||
|
||||
// The HDS interface.
|
||||
class ISrsHds
|
||||
{
|
||||
public:
|
||||
ISrsHds();
|
||||
virtual ~ISrsHds();
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_publish(ISrsRequest *req) = 0;
|
||||
virtual srs_error_t on_unpublish() = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *msg) = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *msg) = 0;
|
||||
};
|
||||
|
||||
// Mux RTMP to Adobe HDS streaming.
|
||||
class SrsHds
|
||||
class SrsHds : public ISrsHds
|
||||
{
|
||||
public:
|
||||
SrsHds();
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
|||
ip = srs_getenv("srs.device.ip"); // SRS_DEVICE_IP
|
||||
if (ip.empty()) {
|
||||
// Use the local ip address specified by the stats.network config.
|
||||
vector<SrsIPAddress *> &ips = srs_get_local_ips();
|
||||
SrsProtocolUtility utility;
|
||||
vector<SrsIPAddress *> &ips = utility.local_ips();
|
||||
if (!ips.empty()) {
|
||||
ip = ips[_srs_config->get_stats_network() % (int)ips.size()]->ip_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -527,17 +527,18 @@ srs_error_t SrsHlsFmp4Muxer::write_init_mp4(SrsFormat *format, bool has_video, b
|
|||
init_file = srs_path_build_stream(init_file, vhost, app, stream);
|
||||
|
||||
std::string hls_path = config_->get_hls_path(vhost);
|
||||
std::string path = hls_path + "/" + init_file;
|
||||
std::string filepath = hls_path + "/" + init_file;
|
||||
|
||||
// Create directory for the init file
|
||||
std::string init_dir = srs_path_filepath_dir(path);
|
||||
if ((err = srs_os_mkdir_all(init_dir)) != srs_success) {
|
||||
SrsPath path;
|
||||
std::string init_dir = path.filepath_dir(filepath);
|
||||
if ((err = path.mkdir_all(init_dir)) != srs_success) {
|
||||
return srs_error_wrap(err, "Create init mp4 dir failed, dir=%s", init_dir.c_str());
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsInitMp4Segment> init_mp4(new SrsInitMp4Segment(writer_));
|
||||
|
||||
init_mp4->set_path(path);
|
||||
init_mp4->set_path(filepath);
|
||||
|
||||
if (hls_keys_) {
|
||||
init_mp4->config_cipher(kid_, iv_, 16);
|
||||
|
|
@ -578,7 +579,7 @@ srs_error_t SrsHlsFmp4Muxer::write_init_mp4(SrsFormat *format, bool has_video, b
|
|||
init_mp4_uri += "/";
|
||||
|
||||
// add the http dir to uri.
|
||||
string http_dir = srs_path_filepath_dir(m3u8_url_);
|
||||
string http_dir = path.filepath_dir(m3u8_url_);
|
||||
if (!http_dir.empty()) {
|
||||
init_mp4_uri += http_dir + "/";
|
||||
}
|
||||
|
|
@ -587,7 +588,7 @@ srs_error_t SrsHlsFmp4Muxer::write_init_mp4(SrsFormat *format, bool has_video, b
|
|||
|
||||
// Convert to relative URI for m3u8 playlist.
|
||||
// TODO: Need to resolve the relative URI from m3u8 and init file.
|
||||
init_mp4_uri_ = srs_path_filepath_base(init_file);
|
||||
init_mp4_uri_ = path.filepath_base(init_file);
|
||||
|
||||
// use async to call the http hooks, for it will cause thread switch.
|
||||
if ((err = async_->execute(new SrsDvrAsyncCallOnHls(_srs_context->get_id(), req_, init_mp4->fullpath(),
|
||||
|
|
@ -708,16 +709,17 @@ srs_error_t SrsHlsFmp4Muxer::update_config(ISrsRequest *r)
|
|||
max_td_ = hls_fragment_ * hls_td_ratio;
|
||||
|
||||
// create m3u8 dir once.
|
||||
m3u8_dir_ = srs_path_filepath_dir(m3u8_);
|
||||
if ((err = srs_os_mkdir_all(m3u8_dir_)) != srs_success) {
|
||||
SrsPath path;
|
||||
m3u8_dir_ = path.filepath_dir(m3u8_);
|
||||
if ((err = path.mkdir_all(m3u8_dir_)) != srs_success) {
|
||||
return srs_error_wrap(err, "create dir");
|
||||
}
|
||||
|
||||
if (hls_keys_ && (hls_path_ != hls_key_file_path_)) {
|
||||
string key_file = srs_path_build_stream(hls_key_file_, vhost, app, stream);
|
||||
string key_url = hls_key_file_path_ + "/" + key_file;
|
||||
string key_dir = srs_path_filepath_dir(key_url);
|
||||
if ((err = srs_os_mkdir_all(key_dir)) != srs_success) {
|
||||
string key_dir = path.filepath_dir(key_url);
|
||||
if ((err = path.mkdir_all(key_dir)) != srs_success) {
|
||||
return srs_error_wrap(err, "create dir");
|
||||
}
|
||||
}
|
||||
|
|
@ -806,7 +808,8 @@ srs_error_t SrsHlsFmp4Muxer::segment_open(srs_utime_t basetime)
|
|||
current_->uri_ += "/";
|
||||
|
||||
// add the http dir to uri.
|
||||
string http_dir = srs_path_filepath_dir(m3u8_url_);
|
||||
SrsPath path;
|
||||
string http_dir = path.filepath_dir(m3u8_url_);
|
||||
if (!http_dir.empty()) {
|
||||
current_->uri_ += http_dir + "/";
|
||||
}
|
||||
|
|
@ -1062,6 +1065,7 @@ srs_error_t SrsHlsFmp4Muxer::do_refresh_m3u8(std::string m3u8_file)
|
|||
|
||||
// {file name}\n
|
||||
// TODO get segment name in relative path.
|
||||
SrsPath path;
|
||||
std::string seg_uri = segment->fullpath();
|
||||
if (true) {
|
||||
std::stringstream stemp;
|
||||
|
|
@ -1069,7 +1073,7 @@ srs_error_t SrsHlsFmp4Muxer::do_refresh_m3u8(std::string m3u8_file)
|
|||
seg_uri = srs_strings_replace(seg_uri, "[duration]", stemp.str());
|
||||
}
|
||||
// ss << segment->uri << SRS_CONSTS_LF;
|
||||
ss << srs_path_filepath_base(seg_uri) << SRS_CONSTS_LF;
|
||||
ss << path.filepath_base(seg_uri) << SRS_CONSTS_LF;
|
||||
}
|
||||
|
||||
// write m3u8 to writer.
|
||||
|
|
@ -1279,16 +1283,17 @@ srs_error_t SrsHlsMuxer::update_config(ISrsRequest *r, string entry_prefix,
|
|||
max_td_ = fragment * config_->get_hls_td_ratio(r->vhost_);
|
||||
|
||||
// create m3u8 dir once.
|
||||
m3u8_dir_ = srs_path_filepath_dir(m3u8_);
|
||||
if ((err = srs_os_mkdir_all(m3u8_dir_)) != srs_success) {
|
||||
SrsPath path_util;
|
||||
m3u8_dir_ = path_util.filepath_dir(m3u8_);
|
||||
if ((err = path_util.mkdir_all(m3u8_dir_)) != srs_success) {
|
||||
return srs_error_wrap(err, "create dir");
|
||||
}
|
||||
|
||||
if (hls_keys_ && (hls_path_ != hls_key_file_path_)) {
|
||||
string key_file = srs_path_build_stream(hls_key_file_, req_->vhost_, req_->app_, req_->stream_);
|
||||
string key_url = hls_key_file_path_ + "/" + key_file;
|
||||
string key_dir = srs_path_filepath_dir(key_url);
|
||||
if ((err = srs_os_mkdir_all(key_dir)) != srs_success) {
|
||||
string key_dir = path_util.filepath_dir(key_url);
|
||||
if ((err = path_util.mkdir_all(key_dir)) != srs_success) {
|
||||
return srs_error_wrap(err, "create dir");
|
||||
}
|
||||
}
|
||||
|
|
@ -1549,7 +1554,8 @@ srs_error_t SrsHlsMuxer::segment_open()
|
|||
current_->uri_ += "/";
|
||||
|
||||
// add the http dir to uri.
|
||||
string http_dir = srs_path_filepath_dir(m3u8_url_);
|
||||
SrsPath path;
|
||||
string http_dir = path.filepath_dir(m3u8_url_);
|
||||
if (!http_dir.empty()) {
|
||||
current_->uri_ += http_dir + "/";
|
||||
}
|
||||
|
|
@ -2455,6 +2461,14 @@ int SrsHlsMp4Controller::deviation()
|
|||
return muxer_->deviation();
|
||||
}
|
||||
|
||||
ISrsHls::ISrsHls()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHls::~ISrsHls()
|
||||
{
|
||||
}
|
||||
|
||||
SrsHls::SrsHls()
|
||||
{
|
||||
req_ = NULL;
|
||||
|
|
|
|||
|
|
@ -317,6 +317,7 @@ private:
|
|||
public:
|
||||
// HLS recover mode.
|
||||
srs_error_t recover_hls();
|
||||
|
||||
private:
|
||||
virtual srs_error_t do_recover_hls();
|
||||
};
|
||||
|
|
@ -612,9 +613,29 @@ public:
|
|||
virtual int deviation();
|
||||
};
|
||||
|
||||
// The HLS interface.
|
||||
class ISrsHls
|
||||
{
|
||||
public:
|
||||
ISrsHls();
|
||||
virtual ~ISrsHls();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r) = 0;
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format) = 0;
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
|
||||
public:
|
||||
virtual void dispose() = 0;
|
||||
virtual srs_error_t cycle() = 0;
|
||||
virtual srs_utime_t cleanup_delay() = 0;
|
||||
};
|
||||
|
||||
// Transmux RTMP stream to HLS(m3u8 and ts,fmp4).
|
||||
// TODO: FIXME: add utest for hls.
|
||||
class SrsHls
|
||||
class SrsHls : public ISrsHls
|
||||
{
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
|
|
|
|||
|
|
@ -1278,7 +1278,8 @@ srs_error_t SrsGoApiMetrics::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
|
||||
#if defined(__linux__) || defined(SRS_OSX)
|
||||
// Get system info
|
||||
utsname *system_info = srs_get_system_uname_info();
|
||||
SrsProtocolUtility utility;
|
||||
utsname *system_info = utility.system_uname();
|
||||
ss << "# HELP srs_node_uname_info Labeled system information as provided by the uname system call.\n"
|
||||
<< "# TYPE srs_node_uname_info gauge\n"
|
||||
<< "srs_node_uname_info{"
|
||||
|
|
|
|||
|
|
@ -349,7 +349,8 @@ srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, ISrsRequest *req, s
|
|||
std::string cwd = _srs_config->cwd();
|
||||
|
||||
// the ts_url is under the same dir of m3u8_url.
|
||||
string prefix = srs_path_filepath_dir(m3u8_url);
|
||||
SrsPath path;
|
||||
string prefix = path.filepath_dir(m3u8_url);
|
||||
if (!prefix.empty() && !srs_net_url_is_http(ts_url)) {
|
||||
ts_url = prefix + "/" + ts_url;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,8 @@ srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter *w, ISrsHttpMess
|
|||
|
||||
// Correct the app and stream by path, which is created from template.
|
||||
// @remark Be careful that the stream has extension now, might cause identify fail.
|
||||
req->stream_ = srs_path_filepath_base(r->path());
|
||||
SrsPath path;
|
||||
req->stream_ = path.filepath_base(r->path());
|
||||
|
||||
// Served by us.
|
||||
*served = true;
|
||||
|
|
@ -152,9 +153,10 @@ srs_error_t SrsHlsStream::serve_new_session(ISrsHttpResponseWriter *w, ISrsHttpM
|
|||
srs_assert(hr);
|
||||
|
||||
if (ctx.empty()) {
|
||||
SrsRand rand;
|
||||
// make sure unique
|
||||
do {
|
||||
ctx = srs_rand_gen_str(8); // the same as cid
|
||||
ctx = rand.gen_str(8); // the same as cid
|
||||
} while (ctx_is_exist(ctx));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -655,9 +655,10 @@ srs_error_t SrsLiveStream::serve_http_impl(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
|
||||
// Correct the app and stream by path, which is created from template.
|
||||
// @remark Be careful that the stream has extension now, might cause identify fail.
|
||||
req_->stream_ = srs_path_filepath_base(r->path());
|
||||
SrsPath path;
|
||||
req_->stream_ = path.filepath_base(r->path());
|
||||
// remove the extension of stream if have. for instance, test.flv -> test
|
||||
req_->stream_ = srs_path_filepath_filename(req_->stream_);
|
||||
req_->stream_ = path.filepath_filename(req_->stream_);
|
||||
|
||||
// update client ip
|
||||
req_->ip_ = hc->remote_ip();
|
||||
|
|
@ -983,7 +984,8 @@ SrsLiveEntry::SrsLiveEntry(std::string m)
|
|||
|
||||
req_ = NULL;
|
||||
|
||||
std::string ext = srs_path_filepath_ext(m);
|
||||
SrsPath path;
|
||||
std::string ext = path.filepath_ext(m);
|
||||
is_flv_ = (ext == ".flv");
|
||||
is_ts_ = (ext == ".ts");
|
||||
is_mp3_ = (ext == ".mp3");
|
||||
|
|
|
|||
|
|
@ -474,7 +474,8 @@ void SrsIngester::show_ingest_log_message()
|
|||
}
|
||||
|
||||
// random choose one ingester to report.
|
||||
int index = srs_rand_integer() % (int)ingesters_.size();
|
||||
SrsRand rand;
|
||||
int index = rand.integer() % (int)ingesters_.size();
|
||||
SrsIngesterFFMPEG *ingester = ingesters_.at(index);
|
||||
|
||||
// reportable
|
||||
|
|
|
|||
|
|
@ -203,7 +203,8 @@ srs_error_t SrsLatestVersion::cycle()
|
|||
|
||||
if (true) {
|
||||
srs_utime_t first_wait_for_qlv = _srs_config->first_wait_for_qlv();
|
||||
string pip = srs_get_public_internet_address();
|
||||
SrsProtocolUtility utility;
|
||||
string pip = utility.public_internet_address();
|
||||
srs_trace("Startup query id=%s, session=%s, eip=%s, wait=%ds", server_id_.c_str(), session_id_.c_str(), pip.c_str(), srsu2msi(first_wait_for_qlv) / 1000);
|
||||
srs_usleep(first_wait_for_qlv);
|
||||
}
|
||||
|
|
@ -220,8 +221,9 @@ srs_error_t SrsLatestVersion::cycle()
|
|||
srs_freep(err); // Ignore any error.
|
||||
}
|
||||
|
||||
SrsProtocolUtility utility2;
|
||||
srs_trace("Finish query id=%s, session=%s, eip=%s, match=%s, stable=%s, cost=%dms, url=%s",
|
||||
server_id_.c_str(), session_id_.c_str(), srs_get_public_internet_address().c_str(), match_version_.c_str(),
|
||||
server_id_.c_str(), session_id_.c_str(), utility2.public_internet_address().c_str(), match_version_.c_str(),
|
||||
stable_version_.c_str(), srsu2msi(srs_time_now_realtime() - starttime), url.c_str());
|
||||
|
||||
srs_usleep(3600 * SRS_UTIME_SECONDS); // Every an hour.
|
||||
|
|
@ -235,11 +237,12 @@ srs_error_t SrsLatestVersion::query_latest_version(string &url)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// Generate uri and parse to object.
|
||||
SrsProtocolUtility utility3;
|
||||
stringstream ss;
|
||||
ss << "http://api.ossrs.net/service/v1/releases?"
|
||||
<< "version=v" << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION
|
||||
<< "&id=" << server_id_ << "&session=" << session_id_ << "&role=srs"
|
||||
<< "&eip=" << srs_get_public_internet_address()
|
||||
<< "&eip=" << utility3.public_internet_address()
|
||||
<< "&ts=" << srs_time_now_cached()
|
||||
<< "&alive=" << srsu2ms(srs_time_now_cached() - srs_time_since_startup()) / 1000;
|
||||
srs_build_features(ss);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,14 @@ using namespace std;
|
|||
#include <srs_protocol_rtmp_stack.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
|
||||
ISrsNgExec::ISrsNgExec()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsNgExec::~ISrsNgExec()
|
||||
{
|
||||
}
|
||||
|
||||
SrsNgExec::SrsNgExec()
|
||||
{
|
||||
trd_ = new SrsDummyCoroutine();
|
||||
|
|
|
|||
|
|
@ -18,10 +18,23 @@ class ISrsRequest;
|
|||
class SrsPithyPrint;
|
||||
class SrsProcess;
|
||||
|
||||
// The ng-exec interface.
|
||||
class ISrsNgExec
|
||||
{
|
||||
public:
|
||||
ISrsNgExec();
|
||||
virtual ~ISrsNgExec();
|
||||
|
||||
public:
|
||||
virtual srs_error_t on_publish(ISrsRequest *req) = 0;
|
||||
virtual void on_unpublish() = 0;
|
||||
virtual srs_error_t cycle() = 0;
|
||||
};
|
||||
|
||||
// The ng-exec is the exec feature introduced by nginx-rtmp,
|
||||
// @see https://github.com/arut/nginx-rtmp-module/wiki/Directives#exec_push
|
||||
// @see https://github.com/ossrs/srs/issues/367
|
||||
class SrsNgExec : public ISrsCoroutineHandler
|
||||
class SrsNgExec : public ISrsCoroutineHandler, public ISrsNgExec
|
||||
{
|
||||
private:
|
||||
ISrsCoroutine *trd_;
|
||||
|
|
|
|||
|
|
@ -299,7 +299,8 @@ void SrsProcess::stop()
|
|||
// when rewind, upstream will stop publish(unpublish),
|
||||
// unpublish event will stop all ffmpeg encoders,
|
||||
// then publish will start all ffmpeg encoders.
|
||||
srs_error_t err = srs_kill_forced(pid_);
|
||||
SrsAppUtility utility;
|
||||
srs_error_t err = utility.kill(pid_);
|
||||
if (err != srs_success) {
|
||||
srs_warn("ignore kill the process failed, pid=%d. err=%s", pid_, srs_error_desc(err).c_str());
|
||||
srs_freep(err);
|
||||
|
|
|
|||
|
|
@ -2140,7 +2140,8 @@ srs_error_t SrsRtcConnection::initialize(ISrsRequest *r, bool dtls, bool srtp, s
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
username_ = username;
|
||||
token_ = srs_rand_gen_str(9);
|
||||
SrsRand rand;
|
||||
token_ = rand.gen_str(9);
|
||||
req_ = r->copy();
|
||||
|
||||
SrsSessionConfig *cfg = &local_sdp_.session_negotiate_;
|
||||
|
|
@ -3699,7 +3700,8 @@ srs_error_t SrsRtcPlayerNegotiator::generate_play_local_sdp(ISrsRequest *req, Sr
|
|||
|
||||
local_sdp.group_policy_ = "BUNDLE";
|
||||
|
||||
std::string cname = srs_rand_gen_str(16);
|
||||
SrsRand rand;
|
||||
std::string cname = rand.gen_str(16);
|
||||
|
||||
if (audio_before_video) {
|
||||
if ((err = generate_play_local_sdp_for_audio(local_sdp, stream_desc, cname)) != srs_success) {
|
||||
|
|
|
|||
|
|
@ -300,7 +300,8 @@ srs_error_t SrsDtlsCertificate::initialize()
|
|||
X509_NAME *subject = X509_NAME_new();
|
||||
srs_assert(subject);
|
||||
|
||||
int serial = (int)srs_rand_integer();
|
||||
SrsRand rand;
|
||||
int serial = (int)rand.integer();
|
||||
ASN1_INTEGER_set(X509_get_serialNumber(dtls_cert_), serial);
|
||||
|
||||
const std::string &aor = RTMP_SIG_SRS_DOMAIN;
|
||||
|
|
|
|||
|
|
@ -242,7 +242,8 @@ set<string> discover_candidates(SrsRtcUserConfig *ruc)
|
|||
}
|
||||
|
||||
// All automatically detected IP list.
|
||||
vector<SrsIPAddress *> &ips = srs_get_local_ips();
|
||||
SrsProtocolUtility utility;
|
||||
vector<SrsIPAddress *> &ips = utility.local_ips();
|
||||
if (ips.empty()) {
|
||||
return candidate_ips;
|
||||
}
|
||||
|
|
@ -402,8 +403,9 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
// All tracks default as inactive, so we must enable them.
|
||||
session->set_all_tracks_status(req->get_stream_url(), ruc->publish_, true);
|
||||
|
||||
std::string local_pwd = ruc->req_->ice_pwd_.empty() ? srs_rand_gen_str(32) : ruc->req_->ice_pwd_;
|
||||
std::string local_ufrag = ruc->req_->ice_ufrag_.empty() ? srs_rand_gen_str(8) : ruc->req_->ice_ufrag_;
|
||||
SrsRand rand;
|
||||
std::string local_pwd = ruc->req_->ice_pwd_.empty() ? rand.gen_str(32) : ruc->req_->ice_pwd_;
|
||||
std::string local_ufrag = ruc->req_->ice_ufrag_.empty() ? rand.gen_str(8) : ruc->req_->ice_ufrag_;
|
||||
// TODO: FIXME: Rename for a better name, it's not an username.
|
||||
std::string username = "";
|
||||
while (true) {
|
||||
|
|
@ -413,7 +415,7 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
}
|
||||
|
||||
// Username conflict, regenerate a new one.
|
||||
local_ufrag = srs_rand_gen_str(8);
|
||||
local_ufrag = rand.gen_str(8);
|
||||
}
|
||||
|
||||
local_sdp.set_ice_ufrag(local_ufrag);
|
||||
|
|
|
|||
|
|
@ -489,13 +489,15 @@ void SrsRtcSource::init_for_play_before_publishing()
|
|||
|
||||
SrsUniquePtr<SrsRtcSourceDescription> stream_desc(new SrsRtcSourceDescription());
|
||||
|
||||
SrsRand rand;
|
||||
|
||||
// audio track description
|
||||
if (true) {
|
||||
SrsRtcTrackDescription *audio_track_desc = new SrsRtcTrackDescription();
|
||||
stream_desc->audio_track_desc_ = audio_track_desc;
|
||||
|
||||
audio_track_desc->type_ = "audio";
|
||||
audio_track_desc->id_ = "audio-" + srs_rand_gen_str(8);
|
||||
audio_track_desc->id_ = "audio-" + rand.gen_str(8);
|
||||
|
||||
uint32_t audio_ssrc = SrsRtcSSRCGenerator::instance()->generate_ssrc();
|
||||
audio_track_desc->ssrc_ = audio_ssrc;
|
||||
|
|
@ -512,7 +514,7 @@ void SrsRtcSource::init_for_play_before_publishing()
|
|||
stream_desc->video_track_descs_.push_back(h264_track_desc);
|
||||
|
||||
h264_track_desc->type_ = "video";
|
||||
h264_track_desc->id_ = "video-h264-" + srs_rand_gen_str(8);
|
||||
h264_track_desc->id_ = "video-h264-" + rand.gen_str(8);
|
||||
|
||||
uint32_t h264_ssrc = SrsRtcSSRCGenerator::instance()->generate_ssrc();
|
||||
h264_track_desc->ssrc_ = h264_ssrc;
|
||||
|
|
@ -530,7 +532,7 @@ void SrsRtcSource::init_for_play_before_publishing()
|
|||
stream_desc->video_track_descs_.push_back(h265_track_desc);
|
||||
|
||||
h265_track_desc->type_ = "video";
|
||||
h265_track_desc->id_ = "video-h265-" + srs_rand_gen_str(8);
|
||||
h265_track_desc->id_ = "video-h265-" + rand.gen_str(8);
|
||||
|
||||
uint32_t h265_ssrc = SrsRtcSSRCGenerator::instance()->generate_ssrc();
|
||||
h265_track_desc->ssrc_ = h265_ssrc;
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ public:
|
|||
};
|
||||
|
||||
// The RTC source manager.
|
||||
class SrsRtcSourceManager : public ISrsRtcSourceManager, public ISrsHourGlass
|
||||
class SrsRtcSourceManager : public ISrsRtcSourceManager, public ISrsHourGlassHandler
|
||||
{
|
||||
private:
|
||||
srs_mutex_t lock_;
|
||||
|
|
@ -183,7 +183,7 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// interface ISrsHourGlass
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ SrsSimpleRtmpClient::~SrsSimpleRtmpClient()
|
|||
|
||||
srs_error_t SrsSimpleRtmpClient::connect_app()
|
||||
{
|
||||
std::vector<SrsIPAddress *> &ips = srs_get_local_ips();
|
||||
SrsProtocolUtility utility;
|
||||
std::vector<SrsIPAddress *> &ips = utility.local_ips();
|
||||
srs_assert(_srs_config->get_stats_network() < (int)ips.size());
|
||||
SrsIPAddress *local_ip = ips[_srs_config->get_stats_network()];
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ using namespace std;
|
|||
#include <srs_app_dvr.hpp>
|
||||
#include <srs_app_edge.hpp>
|
||||
#include <srs_app_encoder.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_forward.hpp>
|
||||
#include <srs_app_hds.hpp>
|
||||
#include <srs_app_hls.hpp>
|
||||
|
|
@ -403,7 +404,7 @@ ISrsWakable::~ISrsWakable()
|
|||
{
|
||||
}
|
||||
|
||||
SrsLiveConsumer::SrsLiveConsumer(SrsLiveSource *s)
|
||||
SrsLiveConsumer::SrsLiveConsumer(ISrsLiveSource *s)
|
||||
{
|
||||
source_ = s;
|
||||
paused_ = false;
|
||||
|
|
@ -817,6 +818,14 @@ SrsMediaPacket *SrsMixQueue::pop()
|
|||
return msg;
|
||||
}
|
||||
|
||||
ISrsOriginHub::ISrsOriginHub()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsOriginHub::~ISrsOriginHub()
|
||||
{
|
||||
}
|
||||
|
||||
SrsOriginHub::SrsOriginHub()
|
||||
{
|
||||
source_ = NULL;
|
||||
|
|
@ -832,17 +841,24 @@ SrsOriginHub::SrsOriginHub()
|
|||
#endif
|
||||
ng_exec_ = new SrsNgExec();
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
config_ = _srs_config;
|
||||
stat_ = _srs_stat;
|
||||
hooks_ = _srs_hooks;
|
||||
}
|
||||
|
||||
void SrsOriginHub::assemble()
|
||||
{
|
||||
config_->subscribe(this);
|
||||
}
|
||||
|
||||
SrsOriginHub::~SrsOriginHub()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
if (true) {
|
||||
std::vector<SrsForwarder *>::iterator it;
|
||||
std::vector<ISrsForwarder *>::iterator it;
|
||||
for (it = forwarders_.begin(); it != forwarders_.end(); ++it) {
|
||||
SrsForwarder *forwarder = *it;
|
||||
ISrsForwarder *forwarder = *it;
|
||||
srs_freep(forwarder);
|
||||
}
|
||||
forwarders_.clear();
|
||||
|
|
@ -856,6 +872,10 @@ SrsOriginHub::~SrsOriginHub()
|
|||
#ifdef SRS_HDS
|
||||
srs_freep(hds_);
|
||||
#endif
|
||||
|
||||
config_ = NULL;
|
||||
stat_ = NULL;
|
||||
hooks_ = NULL;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
|
|
@ -926,9 +946,9 @@ srs_error_t SrsOriginHub::on_meta_data(SrsMediaPacket *shared_metadata, SrsOnMet
|
|||
|
||||
// copy to all forwarders
|
||||
if (true) {
|
||||
std::vector<SrsForwarder *>::iterator it;
|
||||
std::vector<ISrsForwarder *>::iterator it;
|
||||
for (it = forwarders_.begin(); it != forwarders_.end(); ++it) {
|
||||
SrsForwarder *forwarder = *it;
|
||||
ISrsForwarder *forwarder = *it;
|
||||
if ((err = forwarder->on_meta_data(shared_metadata)) != srs_success) {
|
||||
return srs_error_wrap(err, "Forwarder consume metadata");
|
||||
}
|
||||
|
|
@ -947,7 +967,7 @@ srs_error_t SrsOriginHub::on_audio(SrsMediaPacket *shared_audio)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsMediaPacket *msg = shared_audio;
|
||||
SrsRtmpFormat *format = source_->format_;
|
||||
SrsRtmpFormat *format = source_->format();
|
||||
|
||||
// Handle the metadata when got sequence header.
|
||||
if (format->is_aac_sequence_header() || format->is_mp3_sequence_header()) {
|
||||
|
|
@ -958,8 +978,7 @@ srs_error_t SrsOriginHub::on_audio(SrsMediaPacket *shared_audio)
|
|||
static int flv_sound_types[] = {1, 2, 0};
|
||||
|
||||
// when got audio stream info.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
if ((err = stat->on_audio_info(req_, format->acodec_->id_, c->sound_rate_, c->sound_type_, c->aac_object_)) != srs_success) {
|
||||
if ((err = stat_->on_audio_info(req_, format->acodec_->id_, c->sound_rate_, c->sound_type_, c->aac_object_)) != srs_success) {
|
||||
return srs_error_wrap(err, "stat audio");
|
||||
}
|
||||
|
||||
|
|
@ -978,13 +997,13 @@ srs_error_t SrsOriginHub::on_audio(SrsMediaPacket *shared_audio)
|
|||
|
||||
if ((err = hls_->on_audio(msg, format)) != srs_success) {
|
||||
// apply the error strategy for hls.
|
||||
std::string hls_error_strategy = _srs_config->get_hls_on_error(req_->vhost_);
|
||||
std::string hls_error_strategy = config_->get_hls_on_error(req_->vhost_);
|
||||
if (srs_config_hls_is_on_error_ignore(hls_error_strategy)) {
|
||||
srs_warn("hls: ignore audio error %s", srs_error_desc(err).c_str());
|
||||
hls_->on_unpublish();
|
||||
srs_freep(err);
|
||||
} else if (srs_config_hls_is_on_error_continue(hls_error_strategy)) {
|
||||
if (srs_hls_can_continue(srs_error_code(err), source_->meta_->ash(), msg)) {
|
||||
if (srs_hls_can_continue(srs_error_code(err), source_->meta()->ash(), msg)) {
|
||||
srs_freep(err);
|
||||
} else {
|
||||
return srs_error_wrap(err, "hls: audio");
|
||||
|
|
@ -1016,9 +1035,9 @@ srs_error_t SrsOriginHub::on_audio(SrsMediaPacket *shared_audio)
|
|||
|
||||
// copy to all forwarders.
|
||||
if (true) {
|
||||
std::vector<SrsForwarder *>::iterator it;
|
||||
std::vector<ISrsForwarder *>::iterator it;
|
||||
for (it = forwarders_.begin(); it != forwarders_.end(); ++it) {
|
||||
SrsForwarder *forwarder = *it;
|
||||
ISrsForwarder *forwarder = *it;
|
||||
if ((err = forwarder->on_audio(msg)) != srs_success) {
|
||||
return srs_error_wrap(err, "forward: audio");
|
||||
}
|
||||
|
|
@ -1033,7 +1052,7 @@ srs_error_t SrsOriginHub::on_video(SrsMediaPacket *shared_video, bool is_sequenc
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
SrsMediaPacket *msg = shared_video;
|
||||
SrsRtmpFormat *format = source_->format_;
|
||||
SrsRtmpFormat *format = source_->format();
|
||||
|
||||
// cache the sequence header if h264
|
||||
// donot cache the sequence header to gop_cache, return here.
|
||||
|
|
@ -1042,15 +1061,13 @@ srs_error_t SrsOriginHub::on_video(SrsMediaPacket *shared_video, bool is_sequenc
|
|||
srs_assert(c);
|
||||
|
||||
// when got video stream info.
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
|
||||
if (c->id_ == SrsVideoCodecIdAVC) {
|
||||
err = stat->on_video_info(req_, c->id_, c->avc_profile_, c->avc_level_, c->width_, c->height_);
|
||||
err = stat_->on_video_info(req_, c->id_, c->avc_profile_, c->avc_level_, c->width_, c->height_);
|
||||
srs_trace("%dB video sh, codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %.1ffps, %.1fs)",
|
||||
msg->size(), c->id_, srs_avc_profile2str(c->avc_profile_).c_str(), srs_avc_level2str(c->avc_level_).c_str(),
|
||||
c->width_, c->height_, c->video_data_rate_ / 1000, c->frame_rate_, c->duration_);
|
||||
} else if (c->id_ == SrsVideoCodecIdHEVC) {
|
||||
err = stat->on_video_info(req_, c->id_, c->hevc_profile_, c->hevc_level_, c->width_, c->height_);
|
||||
err = stat_->on_video_info(req_, c->id_, c->hevc_profile_, c->hevc_level_, c->width_, c->height_);
|
||||
srs_trace("%dB video sh, codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %.1ffps, %.1fs)",
|
||||
msg->size(), c->id_, srs_hevc_profile2str(c->hevc_profile_).c_str(), srs_hevc_level2str(c->hevc_level_).c_str(),
|
||||
c->width_, c->height_, c->video_data_rate_ / 1000, c->frame_rate_, c->duration_);
|
||||
|
|
@ -1069,13 +1086,13 @@ srs_error_t SrsOriginHub::on_video(SrsMediaPacket *shared_video, bool is_sequenc
|
|||
if ((err = hls_->on_video(msg, format)) != srs_success) {
|
||||
// TODO: We should support more strategies.
|
||||
// apply the error strategy for hls.
|
||||
std::string hls_error_strategy = _srs_config->get_hls_on_error(req_->vhost_);
|
||||
std::string hls_error_strategy = config_->get_hls_on_error(req_->vhost_);
|
||||
if (srs_config_hls_is_on_error_ignore(hls_error_strategy)) {
|
||||
srs_warn("hls: ignore video error %s", srs_error_desc(err).c_str());
|
||||
hls_->on_unpublish();
|
||||
srs_freep(err);
|
||||
} else if (srs_config_hls_is_on_error_continue(hls_error_strategy)) {
|
||||
if (srs_hls_can_continue(srs_error_code(err), source_->meta_->vsh(), msg)) {
|
||||
if (srs_hls_can_continue(srs_error_code(err), source_->meta()->vsh(), msg)) {
|
||||
srs_freep(err);
|
||||
} else {
|
||||
return srs_error_wrap(err, "hls: video");
|
||||
|
|
@ -1107,9 +1124,9 @@ srs_error_t SrsOriginHub::on_video(SrsMediaPacket *shared_video, bool is_sequenc
|
|||
|
||||
// copy to all forwarders.
|
||||
if (!forwarders_.empty()) {
|
||||
std::vector<SrsForwarder *>::iterator it;
|
||||
std::vector<ISrsForwarder *>::iterator it;
|
||||
for (it = forwarders_.begin(); it != forwarders_.end(); ++it) {
|
||||
SrsForwarder *forwarder = *it;
|
||||
ISrsForwarder *forwarder = *it;
|
||||
if ((err = forwarder->on_video(msg)) != srs_success) {
|
||||
return srs_error_wrap(err, "forward video");
|
||||
}
|
||||
|
|
@ -1186,9 +1203,9 @@ srs_error_t SrsOriginHub::on_forwarder_start(SrsForwarder *forwarder)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsMediaPacket *cache_metadata = source_->meta_->data();
|
||||
SrsMediaPacket *cache_sh_video = source_->meta_->vsh();
|
||||
SrsMediaPacket *cache_sh_audio = source_->meta_->ash();
|
||||
SrsMediaPacket *cache_metadata = source_->meta()->data();
|
||||
SrsMediaPacket *cache_sh_video = source_->meta()->vsh();
|
||||
SrsMediaPacket *cache_sh_audio = source_->meta()->ash();
|
||||
|
||||
// feed the forwarder the metadata/sequence header,
|
||||
// when reload to enable the forwarder.
|
||||
|
|
@ -1209,9 +1226,9 @@ srs_error_t SrsOriginHub::on_dvr_request_sh()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsMediaPacket *cache_metadata = source_->meta_->data();
|
||||
SrsMediaPacket *cache_sh_video = source_->meta_->vsh();
|
||||
SrsMediaPacket *cache_sh_audio = source_->meta_->ash();
|
||||
SrsMediaPacket *cache_metadata = source_->meta()->data();
|
||||
SrsMediaPacket *cache_sh_video = source_->meta()->vsh();
|
||||
SrsMediaPacket *cache_sh_audio = source_->meta()->ash();
|
||||
|
||||
// feed the dvr the metadata/sequence header,
|
||||
// when reload to start dvr, dvr will never get the sequence header in stream,
|
||||
|
|
@ -1221,13 +1238,13 @@ srs_error_t SrsOriginHub::on_dvr_request_sh()
|
|||
}
|
||||
|
||||
if (cache_sh_video) {
|
||||
if ((err = dvr_->on_video(cache_sh_video, source_->meta_->vsh_format())) != srs_success) {
|
||||
if ((err = dvr_->on_video(cache_sh_video, source_->meta()->vsh_format())) != srs_success) {
|
||||
return srs_error_wrap(err, "dvr video");
|
||||
}
|
||||
}
|
||||
|
||||
if (cache_sh_audio) {
|
||||
if ((err = dvr_->on_audio(cache_sh_audio, source_->meta_->ash_format())) != srs_success) {
|
||||
if ((err = dvr_->on_audio(cache_sh_audio, source_->meta()->ash_format())) != srs_success) {
|
||||
return srs_error_wrap(err, "dvr audio");
|
||||
}
|
||||
}
|
||||
|
|
@ -1239,16 +1256,16 @@ srs_error_t SrsOriginHub::on_hls_request_sh()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsMediaPacket *cache_sh_video = source_->meta_->vsh();
|
||||
SrsMediaPacket *cache_sh_video = source_->meta()->vsh();
|
||||
if (cache_sh_video) {
|
||||
if ((err = hls_->on_video(cache_sh_video, source_->meta_->vsh_format())) != srs_success) {
|
||||
if ((err = hls_->on_video(cache_sh_video, source_->meta()->vsh_format())) != srs_success) {
|
||||
return srs_error_wrap(err, "hls video");
|
||||
}
|
||||
}
|
||||
|
||||
SrsMediaPacket *cache_sh_audio = source_->meta_->ash();
|
||||
SrsMediaPacket *cache_sh_audio = source_->meta()->ash();
|
||||
if (cache_sh_audio) {
|
||||
if ((err = hls_->on_audio(cache_sh_audio, source_->meta_->ash_format())) != srs_success) {
|
||||
if ((err = hls_->on_audio(cache_sh_audio, source_->meta()->ash_format())) != srs_success) {
|
||||
return srs_error_wrap(err, "hls audio");
|
||||
}
|
||||
}
|
||||
|
|
@ -1260,7 +1277,7 @@ srs_error_t SrsOriginHub::create_forwarders()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_forward_enabled(req_->vhost_)) {
|
||||
if (!config_->get_forward_enabled(req_->vhost_)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1277,11 +1294,11 @@ srs_error_t SrsOriginHub::create_forwarders()
|
|||
}
|
||||
|
||||
// For destanition config
|
||||
SrsConfDirective *conf = _srs_config->get_forwards(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_forwards(req_->vhost_);
|
||||
for (int i = 0; conf && i < (int)conf->args_.size(); i++) {
|
||||
std::string forward_server = conf->args_.at(i);
|
||||
|
||||
SrsForwarder *forwarder = new SrsForwarder(this);
|
||||
ISrsForwarder *forwarder = new SrsForwarder(this);
|
||||
forwarders_.push_back(forwarder);
|
||||
|
||||
// initialize the forwarder with request.
|
||||
|
|
@ -1289,7 +1306,7 @@ srs_error_t SrsOriginHub::create_forwarders()
|
|||
return srs_error_wrap(err, "init forwarder");
|
||||
}
|
||||
|
||||
srs_utime_t queue_size = _srs_config->get_queue_length(req_->vhost_);
|
||||
srs_utime_t queue_size = config_->get_queue_length(req_->vhost_);
|
||||
forwarder->set_queue_size(queue_size);
|
||||
|
||||
if ((err = forwarder->on_publish()) != srs_success) {
|
||||
|
|
@ -1308,7 +1325,7 @@ srs_error_t SrsOriginHub::create_backend_forwarders(bool &applied)
|
|||
// default not configure backend service
|
||||
applied = false;
|
||||
|
||||
SrsConfDirective *conf = _srs_config->get_forward_backend(req_->vhost_);
|
||||
SrsConfDirective *conf = config_->get_forward_backend(req_->vhost_);
|
||||
if (!conf || conf->arg0().empty()) {
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1321,7 +1338,7 @@ srs_error_t SrsOriginHub::create_backend_forwarders(bool &applied)
|
|||
|
||||
// get urls on forward backend
|
||||
std::vector<std::string> urls;
|
||||
if ((err = _srs_hooks->on_forward_backend(backend_url, req_, urls)) != srs_success) {
|
||||
if ((err = hooks_->on_forward_backend(backend_url, req_, urls)) != srs_success) {
|
||||
return srs_error_wrap(err, "get forward backend failed, backend=%s", backend_url.c_str());
|
||||
}
|
||||
|
||||
|
|
@ -1336,7 +1353,7 @@ srs_error_t SrsOriginHub::create_backend_forwarders(bool &applied)
|
|||
srs_net_url_parse_tcurl(req->tcUrl_, req->schema_, req->host_, req->vhost_, req->app_, req->stream_, req->port_, req->param_);
|
||||
|
||||
// create forwarder
|
||||
SrsForwarder *forwarder = new SrsForwarder(this);
|
||||
ISrsForwarder *forwarder = new SrsForwarder(this);
|
||||
forwarders_.push_back(forwarder);
|
||||
|
||||
std::stringstream forward_server;
|
||||
|
|
@ -1347,7 +1364,7 @@ srs_error_t SrsOriginHub::create_backend_forwarders(bool &applied)
|
|||
return srs_error_wrap(err, "init backend forwarder failed, forward-to=%s", forward_server.str().c_str());
|
||||
}
|
||||
|
||||
srs_utime_t queue_size = _srs_config->get_queue_length(req_->vhost_);
|
||||
srs_utime_t queue_size = config_->get_queue_length(req_->vhost_);
|
||||
forwarder->set_queue_size(queue_size);
|
||||
|
||||
if ((err = forwarder->on_publish()) != srs_success) {
|
||||
|
|
@ -1361,9 +1378,9 @@ srs_error_t SrsOriginHub::create_backend_forwarders(bool &applied)
|
|||
|
||||
void SrsOriginHub::destroy_forwarders()
|
||||
{
|
||||
std::vector<SrsForwarder *>::iterator it;
|
||||
std::vector<ISrsForwarder *>::iterator it;
|
||||
for (it = forwarders_.begin(); it != forwarders_.end(); ++it) {
|
||||
SrsForwarder *forwarder = *it;
|
||||
ISrsForwarder *forwarder = *it;
|
||||
forwarder->on_unpublish();
|
||||
srs_freep(forwarder);
|
||||
}
|
||||
|
|
@ -1564,12 +1581,16 @@ SrsLiveSourceManager::SrsLiveSourceManager()
|
|||
{
|
||||
lock_ = srs_mutex_new();
|
||||
timer_ = new SrsHourGlass("sources", this, 1 * SRS_UTIME_SECONDS);
|
||||
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsLiveSourceManager::~SrsLiveSourceManager()
|
||||
{
|
||||
srs_mutex_destroy(lock_);
|
||||
srs_freep(timer_);
|
||||
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsLiveSourceManager::initialize()
|
||||
|
|
@ -1596,7 +1617,7 @@ srs_error_t SrsLiveSourceManager::fetch_or_create(ISrsRequest *r, SrsSharedPtr<S
|
|||
SrsSharedPtr<SrsLiveSource> &source = it->second;
|
||||
pps = source;
|
||||
} else {
|
||||
SrsSharedPtr<SrsLiveSource> source = new SrsLiveSource();
|
||||
SrsSharedPtr<SrsLiveSource> source = app_factory_->create_live_source();
|
||||
srs_trace("new live source, stream_url=%s", stream_url.c_str());
|
||||
pps = source;
|
||||
|
||||
|
|
@ -1703,6 +1724,14 @@ void SrsLiveSourceManager::destroy()
|
|||
pool_.clear();
|
||||
}
|
||||
|
||||
ISrsLiveSource::ISrsLiveSource()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsLiveSource::~ISrsLiveSource()
|
||||
{
|
||||
}
|
||||
|
||||
SrsLiveSource::SrsLiveSource()
|
||||
{
|
||||
req_ = NULL;
|
||||
|
|
@ -1726,13 +1755,22 @@ SrsLiveSource::SrsLiveSource()
|
|||
is_monotonically_increase_ = false;
|
||||
last_packet_time_ = 0;
|
||||
|
||||
_srs_config->subscribe(this);
|
||||
atc_ = false;
|
||||
|
||||
config_ = _srs_config;
|
||||
stat_ = _srs_stat;
|
||||
handler_ = _srs_server;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
void SrsLiveSource::assemble()
|
||||
{
|
||||
config_->subscribe(this);
|
||||
}
|
||||
|
||||
SrsLiveSource::~SrsLiveSource()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
// never free the consumers,
|
||||
// for all consumers are auto free.
|
||||
|
|
@ -1754,6 +1792,11 @@ SrsLiveSource::~SrsLiveSource()
|
|||
if (cid.empty())
|
||||
cid = _pre_source_id;
|
||||
srs_trace("free live source id=[%s]", cid.c_str());
|
||||
|
||||
config_ = NULL;
|
||||
stat_ = NULL;
|
||||
handler_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
void SrsLiveSource::dispose()
|
||||
|
|
@ -1815,6 +1858,16 @@ bool SrsLiveSource::publisher_is_idle_for(srs_utime_t timeout)
|
|||
return false;
|
||||
}
|
||||
|
||||
SrsMetaCache *SrsLiveSource::meta()
|
||||
{
|
||||
return meta_;
|
||||
}
|
||||
|
||||
SrsRtmpFormat *SrsLiveSource::format()
|
||||
{
|
||||
return format_;
|
||||
}
|
||||
|
||||
// CRITICAL: This method is called AFTER the source has been added to the source pool
|
||||
// in the fetch_or_create pattern (see PR 4449).
|
||||
//
|
||||
|
|
@ -1834,17 +1887,17 @@ srs_error_t SrsLiveSource::initialize(SrsSharedPtr<SrsLiveSource> wrapper, ISrsR
|
|||
srs_assert(!req_);
|
||||
|
||||
req_ = r->copy();
|
||||
atc_ = _srs_config->get_atc(req_->vhost_);
|
||||
atc_ = config_->get_atc(req_->vhost_);
|
||||
|
||||
jitter_algorithm_ = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(req_->vhost_);
|
||||
mix_correct_ = _srs_config->get_mix_correct(req_->vhost_);
|
||||
jitter_algorithm_ = (SrsRtmpJitterAlgorithm)config_->get_time_jitter(req_->vhost_);
|
||||
mix_correct_ = config_->get_mix_correct(req_->vhost_);
|
||||
|
||||
if ((err = format_->initialize()) != srs_success) {
|
||||
return srs_error_wrap(err, "format initialize");
|
||||
}
|
||||
|
||||
// Setup the SPS/PPS parsing strategy.
|
||||
format_->try_annexb_first_ = _srs_config->try_annexb_first(r->vhost_);
|
||||
format_->try_annexb_first_ = config_->try_annexb_first(r->vhost_);
|
||||
|
||||
if ((err = play_edge_->initialize(wrapper, req_)) != srs_success) {
|
||||
return srs_error_wrap(err, "edge(play)");
|
||||
|
|
@ -1853,14 +1906,14 @@ srs_error_t SrsLiveSource::initialize(SrsSharedPtr<SrsLiveSource> wrapper, ISrsR
|
|||
return srs_error_wrap(err, "edge(publish)");
|
||||
}
|
||||
|
||||
srs_utime_t queue_size = _srs_config->get_queue_length(req_->vhost_);
|
||||
srs_utime_t queue_size = config_->get_queue_length(req_->vhost_);
|
||||
publish_edge_->set_queue_size(queue_size);
|
||||
|
||||
// Create and initialize origin hub only for origin servers, not edge servers
|
||||
bool edge = _srs_config->get_vhost_is_edge(req_->vhost_);
|
||||
bool edge = config_->get_vhost_is_edge(req_->vhost_);
|
||||
if (!edge) {
|
||||
srs_freep(hub_);
|
||||
hub_ = new SrsOriginHub();
|
||||
hub_ = app_factory_->create_origin_hub();
|
||||
} else {
|
||||
srs_warn("disable OriginHub creation for edge vhost=%s", req_->vhost_.c_str());
|
||||
}
|
||||
|
|
@ -1942,8 +1995,8 @@ srs_error_t SrsLiveSource::on_meta_data(SrsRtmpCommonMessage *msg, SrsOnMetaData
|
|||
|
||||
// if allow atc_auto and bravo-atc detected, open atc for vhost.
|
||||
SrsAmf0Any *prop = NULL;
|
||||
atc_ = _srs_config->get_atc(req_->vhost_);
|
||||
if (_srs_config->get_atc_auto(req_->vhost_)) {
|
||||
atc_ = config_->get_atc(req_->vhost_);
|
||||
if (config_->get_atc_auto(req_->vhost_)) {
|
||||
if ((prop = metadata->metadata_->get_property("bravo_atc")) != NULL) {
|
||||
if (prop->is_string() && prop->to_str() == "true") {
|
||||
atc_ = true;
|
||||
|
|
@ -1962,7 +2015,7 @@ srs_error_t SrsLiveSource::on_meta_data(SrsRtmpCommonMessage *msg, SrsOnMetaData
|
|||
|
||||
// when already got metadata, drop when reduce sequence header.
|
||||
bool drop_for_reduce = false;
|
||||
if (meta_->data() && _srs_config->get_reduce_sequence_header(req_->vhost_)) {
|
||||
if (meta_->data() && config_->get_reduce_sequence_header(req_->vhost_)) {
|
||||
drop_for_reduce = true;
|
||||
srs_warn("drop for reduce sh metadata, size=%d", msg->size());
|
||||
}
|
||||
|
|
@ -2060,7 +2113,7 @@ srs_error_t SrsLiveSource::on_audio_imp(SrsMediaPacket *msg)
|
|||
|
||||
// whether consumer should drop for the duplicated sequence header.
|
||||
bool drop_for_reduce = false;
|
||||
if (is_sequence_header && meta_->previous_ash() && _srs_config->get_reduce_sequence_header(req_->vhost_)) {
|
||||
if (is_sequence_header && meta_->previous_ash() && config_->get_reduce_sequence_header(req_->vhost_)) {
|
||||
if (meta_->previous_ash()->size() == msg->size()) {
|
||||
drop_for_reduce = srs_bytes_equal(meta_->previous_ash()->payload(), msg->payload(), msg->size());
|
||||
srs_warn("drop for reduce sh audio, size=%d", msg->size());
|
||||
|
|
@ -2160,7 +2213,7 @@ srs_error_t SrsLiveSource::on_video_imp(SrsMediaPacket *msg)
|
|||
// user can disable the sps parse to workaround when parse sps failed.
|
||||
// @see https://github.com/ossrs/srs/issues/474
|
||||
if (is_sequence_header) {
|
||||
format_->avc_parse_sps_ = _srs_config->get_parse_sps(req_->vhost_);
|
||||
format_->avc_parse_sps_ = config_->get_parse_sps(req_->vhost_);
|
||||
}
|
||||
|
||||
if ((err = format_->on_video(msg)) != srs_success) {
|
||||
|
|
@ -2175,7 +2228,7 @@ srs_error_t SrsLiveSource::on_video_imp(SrsMediaPacket *msg)
|
|||
|
||||
// whether consumer should drop for the duplicated sequence header.
|
||||
bool drop_for_reduce = false;
|
||||
if (is_sequence_header && meta_->previous_vsh() && _srs_config->get_reduce_sequence_header(req_->vhost_)) {
|
||||
if (is_sequence_header && meta_->previous_vsh() && config_->get_reduce_sequence_header(req_->vhost_)) {
|
||||
if (meta_->previous_vsh()->size() == msg->size()) {
|
||||
drop_for_reduce = srs_bytes_equal(meta_->previous_vsh()->payload(), msg->payload(), msg->size());
|
||||
srs_warn("drop for reduce sh video, size=%d", msg->size());
|
||||
|
|
@ -2350,9 +2403,8 @@ srs_error_t SrsLiveSource::on_publish()
|
|||
}
|
||||
|
||||
// notify the handler.
|
||||
ISrsLiveSourceHandler *handler = _srs_server;
|
||||
srs_assert(handler);
|
||||
if ((err = handler->on_publish(req_)) != srs_success) {
|
||||
srs_assert(handler_);
|
||||
if ((err = handler_->on_publish(req_)) != srs_success) {
|
||||
return srs_error_wrap(err, "handle publish");
|
||||
}
|
||||
|
||||
|
|
@ -2360,8 +2412,7 @@ srs_error_t SrsLiveSource::on_publish()
|
|||
return srs_error_wrap(err, "bridge publish");
|
||||
}
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->on_stream_publish(req_, _source_id.c_str());
|
||||
stat_->on_stream_publish(req_, _source_id.c_str());
|
||||
|
||||
// When no players, the publisher is idle now.
|
||||
if (consumers_.empty()) {
|
||||
|
|
@ -2401,13 +2452,10 @@ void SrsLiveSource::on_unpublish()
|
|||
_source_id = SrsContextId();
|
||||
|
||||
// notify the handler.
|
||||
ISrsLiveSourceHandler *handler = _srs_server;
|
||||
srs_assert(handler);
|
||||
stat_->on_stream_close(req_);
|
||||
|
||||
SrsStatistic *stat = _srs_stat;
|
||||
stat->on_stream_close(req_);
|
||||
|
||||
handler->on_unpublish(req_);
|
||||
srs_assert(handler_);
|
||||
handler_->on_unpublish(req_);
|
||||
|
||||
if (rtmp_bridge_) {
|
||||
rtmp_bridge_->on_unpublish();
|
||||
|
|
@ -2430,7 +2478,7 @@ srs_error_t SrsLiveSource::create_consumer(SrsLiveConsumer *&consumer)
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// for edge, when play edge stream, check the state
|
||||
if (_srs_config->get_vhost_is_edge(req_->vhost_)) {
|
||||
if (config_->get_vhost_is_edge(req_->vhost_)) {
|
||||
// notice edge to start for the first client.
|
||||
if ((err = play_edge_->on_client_play()) != srs_success) {
|
||||
return srs_error_wrap(err, "play edge");
|
||||
|
|
@ -2451,7 +2499,7 @@ srs_error_t SrsLiveSource::consumer_dumps(SrsLiveConsumer *consumer, bool ds, bo
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
srs_utime_t queue_size = _srs_config->get_queue_length(req_->vhost_);
|
||||
srs_utime_t queue_size = config_->get_queue_length(req_->vhost_);
|
||||
consumer->set_queue_size(queue_size);
|
||||
|
||||
// if atc, update the sequence header to gop cache time.
|
||||
|
|
@ -2509,7 +2557,7 @@ void SrsLiveSource::on_consumer_destroy(SrsLiveConsumer *consumer)
|
|||
|
||||
// For edge server, the stream die when the last player quit, because the edge stream is created by player
|
||||
// activities, so it should die when all players quit.
|
||||
if (_srs_config->get_vhost_is_edge(req_->vhost_)) {
|
||||
if (config_->get_vhost_is_edge(req_->vhost_)) {
|
||||
stream_die_at_ = srs_time_now_cached();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,20 @@ class SrsBuffer;
|
|||
#ifdef SRS_HDS
|
||||
class SrsHds;
|
||||
#endif
|
||||
class ISrsStatistic;
|
||||
class ISrsHttpHooks;
|
||||
class ISrsAppConfig;
|
||||
class ISrsLiveSource;
|
||||
class ISrsHls;
|
||||
class ISrsDash;
|
||||
class ISrsDvr;
|
||||
class ISrsMediaEncoder;
|
||||
#ifdef SRS_HDS
|
||||
class ISrsHds;
|
||||
#endif
|
||||
class ISrsNgExec;
|
||||
class ISrsForwarder;
|
||||
class SrsAppFactory;
|
||||
|
||||
// The time jitter algorithm:
|
||||
// 1. full, to ensure stream start at zero, and ensure stream monotonically increasing.
|
||||
|
|
@ -180,7 +194,7 @@ class SrsLiveConsumer : public ISrsWakable
|
|||
{
|
||||
private:
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
SrsLiveSource *source_;
|
||||
ISrsLiveSource *source_;
|
||||
|
||||
private:
|
||||
SrsRtmpJitter *jitter_;
|
||||
|
|
@ -196,7 +210,7 @@ private:
|
|||
srs_utime_t mw_duration_;
|
||||
#endif
|
||||
public:
|
||||
SrsLiveConsumer(SrsLiveSource *s);
|
||||
SrsLiveConsumer(ISrsLiveSource *s);
|
||||
virtual ~SrsLiveConsumer();
|
||||
|
||||
public:
|
||||
|
|
@ -329,14 +343,48 @@ public:
|
|||
virtual SrsMediaPacket *pop();
|
||||
};
|
||||
|
||||
// The interface for origin hub.
|
||||
class ISrsOriginHub
|
||||
{
|
||||
public:
|
||||
ISrsOriginHub();
|
||||
virtual ~ISrsOriginHub();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, ISrsRequest *r) = 0;
|
||||
virtual void dispose() = 0;
|
||||
virtual srs_error_t cycle() = 0;
|
||||
virtual bool active() = 0;
|
||||
virtual srs_utime_t cleanup_delay() = 0;
|
||||
|
||||
public:
|
||||
// When got a parsed metadata.
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata, SrsOnMetaDataPacket *packet) = 0;
|
||||
// When got a parsed audio packet.
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio) = 0;
|
||||
// When got a parsed video packet.
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, bool is_sequence_header) = 0;
|
||||
|
||||
public:
|
||||
// When start publish stream.
|
||||
virtual srs_error_t on_publish() = 0;
|
||||
// When stop publish stream.
|
||||
virtual void on_unpublish() = 0;
|
||||
};
|
||||
|
||||
// The hub for origin is a collection of utilities for origin only,
|
||||
// For example, DVR, HLS, Forward and Transcode are only available for origin,
|
||||
// they are meanless for edge server.
|
||||
class SrsOriginHub : public ISrsReloadHandler
|
||||
class SrsOriginHub : public ISrsReloadHandler, public ISrsOriginHub
|
||||
{
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsHttpHooks *hooks_;
|
||||
|
||||
private:
|
||||
// Because source references to this object, so we should directly use the source ptr.
|
||||
SrsLiveSource *source_;
|
||||
ISrsLiveSource *source_;
|
||||
|
||||
private:
|
||||
ISrsRequest *req_;
|
||||
|
|
@ -344,24 +392,25 @@ private:
|
|||
|
||||
private:
|
||||
// hls handler.
|
||||
SrsHls *hls_;
|
||||
ISrsHls *hls_;
|
||||
// The DASH encoder.
|
||||
SrsDash *dash_;
|
||||
ISrsDash *dash_;
|
||||
// dvr handler.
|
||||
SrsDvr *dvr_;
|
||||
ISrsDvr *dvr_;
|
||||
// transcoding handler.
|
||||
SrsEncoder *encoder_;
|
||||
ISrsMediaEncoder *encoder_;
|
||||
#ifdef SRS_HDS
|
||||
// adobe hds(http dynamic streaming).
|
||||
SrsHds *hds_;
|
||||
ISrsHds *hds_;
|
||||
#endif
|
||||
// nginx-rtmp exec feature.
|
||||
SrsNgExec *ng_exec_;
|
||||
ISrsNgExec *ng_exec_;
|
||||
// To forward stream to other servers
|
||||
std::vector<SrsForwarder *> forwarders_;
|
||||
std::vector<ISrsForwarder *> forwarders_;
|
||||
|
||||
public:
|
||||
SrsOriginHub();
|
||||
void assemble();
|
||||
virtual ~SrsOriginHub();
|
||||
|
||||
public:
|
||||
|
|
@ -483,12 +532,15 @@ public:
|
|||
};
|
||||
|
||||
// The source manager to create and refresh all stream sources.
|
||||
class SrsLiveSourceManager : public ISrsHourGlass, public ISrsLiveSourceManager
|
||||
class SrsLiveSourceManager : public ISrsHourGlassHandler, public ISrsLiveSourceManager
|
||||
{
|
||||
private:
|
||||
SrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
srs_mutex_t lock_;
|
||||
std::map<std::string, SrsSharedPtr<SrsLiveSource> > pool_;
|
||||
SrsHourGlass *timer_;
|
||||
ISrsHourGlass *timer_;
|
||||
|
||||
public:
|
||||
SrsLiveSourceManager();
|
||||
|
|
@ -509,7 +561,7 @@ public:
|
|||
public:
|
||||
// dispose and cycle all sources.
|
||||
virtual void dispose();
|
||||
// interface ISrsHourGlass
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
|
@ -523,10 +575,29 @@ public:
|
|||
// Global singleton instance.
|
||||
extern SrsLiveSourceManager *_srs_sources;
|
||||
|
||||
// The live streaming source.
|
||||
class SrsLiveSource : public ISrsReloadHandler, public ISrsFrameTarget
|
||||
// The live source interface.
|
||||
class ISrsLiveSource
|
||||
{
|
||||
friend class SrsOriginHub;
|
||||
public:
|
||||
ISrsLiveSource();
|
||||
virtual ~ISrsLiveSource();
|
||||
|
||||
public:
|
||||
virtual void on_consumer_destroy(SrsLiveConsumer *consumer) = 0;
|
||||
virtual SrsContextId source_id() = 0;
|
||||
virtual SrsContextId pre_source_id() = 0;
|
||||
virtual SrsMetaCache *meta() = 0;
|
||||
virtual SrsRtmpFormat *format() = 0;
|
||||
};
|
||||
|
||||
// The live streaming source.
|
||||
class SrsLiveSource : public ISrsReloadHandler, public ISrsFrameTarget, public ISrsLiveSource
|
||||
{
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
ISrsStatistic *stat_;
|
||||
ISrsLiveSourceHandler *handler_;
|
||||
SrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
// For publish, it's the publish client id.
|
||||
|
|
@ -563,7 +634,7 @@ private:
|
|||
// The gop cache for client fast startup.
|
||||
SrsGopCache *gop_cache_;
|
||||
// The hub for origin server.
|
||||
SrsOriginHub *hub_;
|
||||
ISrsOriginHub *hub_;
|
||||
// The metadata cache.
|
||||
SrsMetaCache *meta_;
|
||||
// The format, codec information.
|
||||
|
|
@ -579,6 +650,7 @@ private:
|
|||
|
||||
public:
|
||||
SrsLiveSource();
|
||||
void assemble();
|
||||
virtual ~SrsLiveSource();
|
||||
|
||||
public:
|
||||
|
|
@ -588,6 +660,8 @@ public:
|
|||
virtual bool stream_is_dead();
|
||||
// Whether publisher is idle for a period of timeout.
|
||||
bool publisher_is_idle_for(srs_utime_t timeout);
|
||||
virtual SrsMetaCache *meta();
|
||||
virtual SrsRtmpFormat *format();
|
||||
|
||||
public:
|
||||
// Initialize the hls with handlers.
|
||||
|
|
|
|||
|
|
@ -549,7 +549,8 @@ srs_error_t SrsRtspConnection::do_cycle()
|
|||
} else if (req->is_describe()) {
|
||||
// create session.
|
||||
if (session_id_.empty()) {
|
||||
session_id_ = srs_rand_gen_str(8);
|
||||
SrsRand rand;
|
||||
session_id_ = rand.gen_str(8);
|
||||
}
|
||||
|
||||
SrsUniquePtr<SrsRtspDescribeResponse> res(new SrsRtspDescribeResponse((int)req->seq_));
|
||||
|
|
|
|||
|
|
@ -539,10 +539,12 @@ srs_error_t SrsRtspRtpBuilder::initialize_audio_track(SrsAudioCodecId codec)
|
|||
// RTSP behavior: Build track description from real audio format, not default values
|
||||
// This is different from RTC which uses default track descriptions
|
||||
|
||||
SrsRand rand;
|
||||
|
||||
// Create audio track description from actual format data
|
||||
SrsUniquePtr<SrsRtcTrackDescription> audio_desc(new SrsRtcTrackDescription());
|
||||
audio_desc->type_ = "audio";
|
||||
audio_desc->id_ = "audio-" + srs_rand_gen_str(8);
|
||||
audio_desc->id_ = "audio-" + rand.gen_str(8);
|
||||
audio_desc->direction_ = "recvonly";
|
||||
|
||||
// Generate SSRC for this track
|
||||
|
|
@ -612,10 +614,12 @@ srs_error_t SrsRtspRtpBuilder::initialize_video_track(SrsVideoCodecId codec)
|
|||
|
||||
std::string codec_name = srs_video_codec_id2str(codec);
|
||||
|
||||
SrsRand rand;
|
||||
|
||||
// Create video track description from actual format data
|
||||
SrsUniquePtr<SrsRtcTrackDescription> video_desc(new SrsRtcTrackDescription());
|
||||
video_desc->type_ = "video";
|
||||
video_desc->id_ = "video-" + codec_name + "-" + srs_rand_gen_str(8);
|
||||
video_desc->id_ = "video-" + codec_name + "-" + rand.gen_str(8);
|
||||
video_desc->direction_ = "recvonly";
|
||||
|
||||
// Generate SSRC for this track
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public:
|
|||
void on_stream_change(SrsRtcSourceDescription *desc);
|
||||
};
|
||||
|
||||
class SrsRtspSourceManager : public ISrsHourGlass
|
||||
class SrsRtspSourceManager : public ISrsHourGlassHandler
|
||||
{
|
||||
private:
|
||||
srs_mutex_t lock_;
|
||||
|
|
@ -80,7 +80,7 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// interface ISrsHourGlass
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
|
|
|||
|
|
@ -132,7 +132,11 @@ srs_error_t srs_global_initialize()
|
|||
|
||||
_srs_reload_err = srs_success;
|
||||
_srs_reload_state = SrsReloadStateInit;
|
||||
_srs_reload_id = srs_rand_gen_str(7);
|
||||
SrsRand rand;
|
||||
_srs_reload_id = rand.gen_str(7);
|
||||
|
||||
// Initialize global statistic instance.
|
||||
_srs_stat = new SrsStatistic();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -178,11 +182,10 @@ SrsServer::SrsServer()
|
|||
ingester_ = new SrsIngester();
|
||||
timer_ = NULL;
|
||||
|
||||
// Initialize global statistic instance.
|
||||
_srs_stat = new SrsStatistic();
|
||||
|
||||
// Initialize WebRTC components
|
||||
rtc_session_manager_ = new SrsRtcSessionManager();
|
||||
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsServer::~SrsServer()
|
||||
|
|
@ -234,13 +237,12 @@ SrsServer::~SrsServer()
|
|||
|
||||
srs_freep(rtc_session_manager_);
|
||||
|
||||
// Cleanup global statistic instance.
|
||||
srs_freep(_srs_stat);
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
void SrsServer::dispose()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
// Destroy all listeners.
|
||||
rtmp_listener_->close();
|
||||
|
|
@ -272,11 +274,11 @@ void SrsServer::dispose()
|
|||
|
||||
void SrsServer::gracefully_dispose()
|
||||
{
|
||||
_srs_config->unsubscribe(this);
|
||||
config_->unsubscribe(this);
|
||||
|
||||
// Always wait for a while to start.
|
||||
srs_usleep(_srs_config->get_grace_start_wait());
|
||||
srs_trace("start wait for %dms", srsu2msi(_srs_config->get_grace_start_wait()));
|
||||
srs_usleep(config_->get_grace_start_wait());
|
||||
srs_trace("start wait for %dms", srsu2msi(config_->get_grace_start_wait()));
|
||||
|
||||
// Destroy all listeners.
|
||||
rtmp_listener_->close();
|
||||
|
|
@ -318,8 +320,8 @@ void SrsServer::gracefully_dispose()
|
|||
_srs_sources->dispose();
|
||||
srs_trace("source disposed");
|
||||
|
||||
srs_usleep(_srs_config->get_grace_final_wait());
|
||||
srs_trace("final wait for %dms", srsu2msi(_srs_config->get_grace_final_wait()));
|
||||
srs_usleep(config_->get_grace_final_wait());
|
||||
srs_trace("final wait for %dms", srsu2msi(config_->get_grace_final_wait()));
|
||||
}
|
||||
|
||||
ISrsHttpServeMux *SrsServer::api_server()
|
||||
|
|
@ -365,16 +367,16 @@ srs_error_t SrsServer::initialize()
|
|||
// for the main objects(server, config, log, context),
|
||||
// never subscribe handler in constructor,
|
||||
// instead, subscribe handler in initialize method.
|
||||
srs_assert(_srs_config);
|
||||
_srs_config->subscribe(this);
|
||||
srs_assert(config_);
|
||||
config_->subscribe(this);
|
||||
|
||||
bool stream = _srs_config->get_http_stream_enabled();
|
||||
vector<string> http_listens = _srs_config->get_http_stream_listens();
|
||||
vector<string> https_listens = _srs_config->get_https_stream_listens();
|
||||
bool stream = config_->get_http_stream_enabled();
|
||||
vector<string> http_listens = config_->get_http_stream_listens();
|
||||
vector<string> https_listens = config_->get_https_stream_listens();
|
||||
|
||||
bool rtc = _srs_config->get_rtc_server_enabled();
|
||||
bool rtc_tcp = _srs_config->get_rtc_server_tcp_enabled();
|
||||
vector<string> rtc_listens = _srs_config->get_rtc_server_tcp_listens();
|
||||
bool rtc = config_->get_rtc_server_enabled();
|
||||
bool rtc_tcp = config_->get_rtc_server_tcp_enabled();
|
||||
vector<string> rtc_listens = config_->get_rtc_server_tcp_listens();
|
||||
// If enabled and listen is the same value, resue port for WebRTC over TCP.
|
||||
if (stream && rtc && rtc_tcp && srs_strings_equal(http_listens, rtc_listens)) {
|
||||
srs_trace("WebRTC tcp=%s reuses http=%s server", srs_strings_join(rtc_listens, ",").c_str(), srs_strings_join(http_listens, ",").c_str());
|
||||
|
|
@ -386,9 +388,9 @@ srs_error_t SrsServer::initialize()
|
|||
}
|
||||
|
||||
// If enabled and the listen is the same value, reuse port.
|
||||
bool api = _srs_config->get_http_api_enabled();
|
||||
vector<string> api_listens = _srs_config->get_http_api_listens();
|
||||
vector<string> apis_listens = _srs_config->get_https_api_listens();
|
||||
bool api = config_->get_http_api_enabled();
|
||||
vector<string> api_listens = config_->get_http_api_listens();
|
||||
vector<string> apis_listens = config_->get_https_api_listens();
|
||||
if (stream && api && srs_strings_equal(api_listens, http_listens) && srs_strings_equal(apis_listens, https_listens)) {
|
||||
srs_trace("API reuses http=%s and https=%s server", srs_strings_join(http_listens, ",").c_str(), srs_strings_join(https_listens, ",").c_str());
|
||||
reuse_api_over_server_ = true;
|
||||
|
|
@ -494,7 +496,7 @@ srs_error_t SrsServer::initialize_st()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// check asprocess.
|
||||
bool asprocess = _srs_config->get_asprocess();
|
||||
bool asprocess = config_->get_asprocess();
|
||||
if (asprocess && ppid_ == 1) {
|
||||
return srs_error_new(ERROR_SYSTEM_ASSERT_FAILED, "ppid=%d illegal for asprocess", ppid_);
|
||||
}
|
||||
|
|
@ -526,26 +528,26 @@ srs_error_t SrsServer::listen()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// Create RTMP listeners.
|
||||
rtmp_listener_->add(_srs_config->get_listens())->set_label("RTMP");
|
||||
rtmp_listener_->add(config_->get_listens())->set_label("RTMP");
|
||||
if ((err = rtmp_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtmp listen");
|
||||
}
|
||||
|
||||
// Create RTMPS listeners.
|
||||
if (_srs_config->get_rtmps_enabled()) {
|
||||
rtmps_listener_->add(_srs_config->get_rtmps_listen())->set_label("RTMPS");
|
||||
if (config_->get_rtmps_enabled()) {
|
||||
rtmps_listener_->add(config_->get_rtmps_listen())->set_label("RTMPS");
|
||||
if ((err = rtmps_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtmps listen");
|
||||
}
|
||||
}
|
||||
|
||||
// Create HTTP API listener.
|
||||
if (_srs_config->get_http_api_enabled()) {
|
||||
if (config_->get_http_api_enabled()) {
|
||||
if (reuse_api_over_server_) {
|
||||
vector<string> listens = _srs_config->get_http_stream_listens();
|
||||
vector<string> listens = config_->get_http_stream_listens();
|
||||
srs_trace("HTTP-API: Reuse listen to http server %s", srs_strings_join(listens, ",").c_str());
|
||||
} else {
|
||||
api_listener_->add(_srs_config->get_http_api_listens())->set_label("HTTP-API");
|
||||
api_listener_->add(config_->get_http_api_listens())->set_label("HTTP-API");
|
||||
if ((err = api_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "http api listen");
|
||||
}
|
||||
|
|
@ -553,12 +555,12 @@ srs_error_t SrsServer::listen()
|
|||
}
|
||||
|
||||
// Create HTTPS API listener.
|
||||
if (_srs_config->get_https_api_enabled()) {
|
||||
if (config_->get_https_api_enabled()) {
|
||||
if (reuse_api_over_server_) {
|
||||
vector<string> listens = _srs_config->get_https_stream_listens();
|
||||
vector<string> listens = config_->get_https_stream_listens();
|
||||
srs_trace("HTTPS-API: Reuse listen to http server %s", srs_strings_join(listens, ",").c_str());
|
||||
} else {
|
||||
apis_listener_->add(_srs_config->get_https_api_listens())->set_label("HTTPS-API");
|
||||
apis_listener_->add(config_->get_https_api_listens())->set_label("HTTPS-API");
|
||||
if ((err = apis_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "https api listen");
|
||||
}
|
||||
|
|
@ -566,25 +568,25 @@ srs_error_t SrsServer::listen()
|
|||
}
|
||||
|
||||
// Create HTTP server listener.
|
||||
if (_srs_config->get_http_stream_enabled()) {
|
||||
http_listener_->add(_srs_config->get_http_stream_listens())->set_label("HTTP-Server");
|
||||
if (config_->get_http_stream_enabled()) {
|
||||
http_listener_->add(config_->get_http_stream_listens())->set_label("HTTP-Server");
|
||||
if ((err = http_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "http server listen");
|
||||
}
|
||||
}
|
||||
|
||||
// Create HTTPS server listener.
|
||||
if (_srs_config->get_https_stream_enabled()) {
|
||||
https_listener_->add(_srs_config->get_https_stream_listens())->set_label("HTTPS-Server");
|
||||
if (config_->get_https_stream_enabled()) {
|
||||
https_listener_->add(config_->get_https_stream_listens())->set_label("HTTPS-Server");
|
||||
if ((err = https_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "https server listen");
|
||||
}
|
||||
}
|
||||
|
||||
// Start WebRTC over TCP listener.
|
||||
string protocol = _srs_config->get_rtc_server_protocol();
|
||||
if (!reuse_rtc_over_server_ && protocol != "udp" && _srs_config->get_rtc_server_tcp_enabled()) {
|
||||
webrtc_listener_->add(_srs_config->get_rtc_server_tcp_listens())->set_label("WebRTC");
|
||||
string protocol = config_->get_rtc_server_protocol();
|
||||
if (!reuse_rtc_over_server_ && protocol != "udp" && config_->get_rtc_server_tcp_enabled()) {
|
||||
webrtc_listener_->add(config_->get_rtc_server_tcp_listens())->set_label("WebRTC");
|
||||
if ((err = webrtc_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "webrtc tcp listen");
|
||||
}
|
||||
|
|
@ -592,8 +594,8 @@ srs_error_t SrsServer::listen()
|
|||
|
||||
#ifdef SRS_RTSP
|
||||
// Start RTSP listener. RTC is a critical dependency.
|
||||
if (_srs_config->get_rtsp_server_enabled()) {
|
||||
rtsp_listener_->add(_srs_config->get_rtsp_server_listens())->set_label("RTSP");
|
||||
if (config_->get_rtsp_server_enabled()) {
|
||||
rtsp_listener_->add(config_->get_rtsp_server_listens())->set_label("RTSP");
|
||||
if ((err = rtsp_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtsp listen");
|
||||
}
|
||||
|
|
@ -601,15 +603,15 @@ srs_error_t SrsServer::listen()
|
|||
#endif
|
||||
|
||||
// Start all listeners for stream caster.
|
||||
std::vector<SrsConfDirective *> confs = _srs_config->get_stream_casters();
|
||||
std::vector<SrsConfDirective *> confs = config_->get_stream_casters();
|
||||
for (vector<SrsConfDirective *>::iterator it = confs.begin(); it != confs.end(); ++it) {
|
||||
SrsConfDirective *conf = *it;
|
||||
if (!_srs_config->get_stream_caster_enabled(conf)) {
|
||||
if (!config_->get_stream_caster_enabled(conf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ISrsListener *listener = NULL;
|
||||
std::string caster = _srs_config->get_stream_caster_engine(conf);
|
||||
std::string caster = config_->get_stream_caster_engine(conf);
|
||||
if (srs_stream_caster_is_udp(caster)) {
|
||||
listener = stream_caster_mpegts_;
|
||||
if ((err = stream_caster_mpegts_->initialize(conf)) != srs_success) {
|
||||
|
|
@ -640,8 +642,8 @@ srs_error_t SrsServer::listen()
|
|||
}
|
||||
|
||||
// Create exporter server listener.
|
||||
if (_srs_config->get_exporter_enabled()) {
|
||||
exporter_listener_->set_endpoint(_srs_config->get_exporter_listen())->set_label("Exporter-Server");
|
||||
if (config_->get_exporter_enabled()) {
|
||||
exporter_listener_->set_endpoint(config_->get_exporter_listen())->set_label("Exporter-Server");
|
||||
if ((err = exporter_listener_->listen()) != srs_success) {
|
||||
return srs_error_wrap(err, "exporter server listen");
|
||||
}
|
||||
|
|
@ -778,7 +780,7 @@ srs_error_t SrsServer::http_handle()
|
|||
|
||||
// TODO: FIXME: for console.
|
||||
// TODO: FIXME: support reload.
|
||||
std::string dir = _srs_config->get_http_stream_dir() + "/console";
|
||||
std::string dir = config_->get_http_stream_dir() + "/console";
|
||||
if ((err = http_api_mux_->handle("/console/", new SrsHttpFileServer(dir))) != srs_success) {
|
||||
return srs_error_wrap(err, "handle console at %s", dir.c_str());
|
||||
}
|
||||
|
|
@ -900,7 +902,7 @@ void SrsServer::on_signal(int signo)
|
|||
|
||||
// For K8S, force to gracefully quit for gray release or canary.
|
||||
// @see https://github.com/ossrs/srs/issues/1595#issuecomment-587473037
|
||||
if (signo == SRS_SIGNAL_FAST_QUIT && _srs_config->is_force_grace_quit()) {
|
||||
if (signo == SRS_SIGNAL_FAST_QUIT && config_->is_force_grace_quit()) {
|
||||
srs_trace("force gracefully quit, signo=%d", signo);
|
||||
signo = SRS_SIGNAL_GRACEFULLY_QUIT;
|
||||
}
|
||||
|
|
@ -927,7 +929,7 @@ srs_error_t SrsServer::do_cycle()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// for asprocess.
|
||||
bool asprocess = _srs_config->get_asprocess();
|
||||
bool asprocess = config_->get_asprocess();
|
||||
|
||||
while (true) {
|
||||
// asprocess check.
|
||||
|
|
@ -958,7 +960,7 @@ srs_error_t SrsServer::do_cycle()
|
|||
signal_persistence_config_ = false;
|
||||
srs_info("get signal to persistence config to file.");
|
||||
|
||||
if ((err = _srs_config->persistence()) != srs_success) {
|
||||
if ((err = config_->persistence()) != srs_success) {
|
||||
return srs_error_wrap(err, "config persistence to file");
|
||||
}
|
||||
srs_trace("persistence config to file success.");
|
||||
|
|
@ -972,8 +974,9 @@ srs_error_t SrsServer::do_cycle()
|
|||
SrsReloadState state = SrsReloadStateInit;
|
||||
_srs_reload_state = SrsReloadStateInit;
|
||||
srs_freep(_srs_reload_err);
|
||||
_srs_reload_id = srs_rand_gen_str(7);
|
||||
err = _srs_config->reload(&state);
|
||||
SrsRand rand;
|
||||
_srs_reload_id = rand.gen_str(7);
|
||||
err = config_->reload(&state);
|
||||
_srs_reload_state = state;
|
||||
_srs_reload_err = srs_error_copy(err);
|
||||
if (err != srs_success) {
|
||||
|
|
@ -1006,7 +1009,7 @@ srs_error_t SrsServer::setup_ticks()
|
|||
srs_freep(timer_);
|
||||
timer_ = new SrsHourGlass("srs", this, 1 * SRS_UTIME_SECONDS);
|
||||
|
||||
if (_srs_config->get_stats_enabled()) {
|
||||
if (config_->get_stats_enabled()) {
|
||||
if ((err = timer_->tick(2, 3 * SRS_UTIME_SECONDS)) != srs_success) {
|
||||
return srs_error_wrap(err, "tick");
|
||||
}
|
||||
|
|
@ -1040,8 +1043,8 @@ srs_error_t SrsServer::setup_ticks()
|
|||
}
|
||||
}
|
||||
|
||||
if (_srs_config->get_heartbeat_enabled()) {
|
||||
if ((err = timer_->tick(9, _srs_config->get_heartbeat_interval())) != srs_success) {
|
||||
if (config_->get_heartbeat_enabled()) {
|
||||
if ((err = timer_->tick(9, config_->get_heartbeat_interval())) != srs_success) {
|
||||
return srs_error_wrap(err, "tick");
|
||||
}
|
||||
}
|
||||
|
|
@ -1151,7 +1154,7 @@ srs_error_t SrsServer::listen_srt_mpegts()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_srt_enabled()) {
|
||||
if (!config_->get_srt_enabled()) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1159,7 +1162,7 @@ srs_error_t SrsServer::listen_srt_mpegts()
|
|||
close_srt_listeners();
|
||||
|
||||
// Start listeners for SRT, support multiple addresses including IPv6.
|
||||
vector<string> srt_listens = _srs_config->get_srt_listens();
|
||||
vector<string> srt_listens = config_->get_srt_listens();
|
||||
for (int i = 0; i < (int)srt_listens.size(); i++) {
|
||||
SrsSrtAcceptor *acceptor = new SrsSrtAcceptor(this);
|
||||
|
||||
|
|
@ -1248,18 +1251,18 @@ srs_error_t SrsServer::listen_rtc_udp()
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if (!_srs_config->get_rtc_server_enabled()) {
|
||||
if (!config_->get_rtc_server_enabled()) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Check protocol setting - only create UDP listeners if protocol allows UDP
|
||||
string protocol = _srs_config->get_rtc_server_protocol();
|
||||
string protocol = config_->get_rtc_server_protocol();
|
||||
if (protocol == "tcp") {
|
||||
// When protocol is "tcp", don't create UDP listeners
|
||||
return err;
|
||||
}
|
||||
|
||||
vector<string> rtc_listens = _srs_config->get_rtc_server_listens();
|
||||
vector<string> rtc_listens = config_->get_rtc_server_listens();
|
||||
if (rtc_listens.empty()) {
|
||||
return srs_error_new(ERROR_RTC_PORT, "empty rtc listen");
|
||||
}
|
||||
|
|
@ -1268,7 +1271,7 @@ srs_error_t SrsServer::listen_rtc_udp()
|
|||
srs_assert(rtc_listeners_.empty());
|
||||
|
||||
// For each listen address, create multiple listeners based on reuseport setting
|
||||
int nn_listeners = _srs_config->get_rtc_server_reuseport();
|
||||
int nn_listeners = config_->get_rtc_server_reuseport();
|
||||
for (int j = 0; j < (int)rtc_listens.size(); j++) {
|
||||
string ip;
|
||||
int port;
|
||||
|
|
@ -1397,7 +1400,7 @@ srs_error_t SrsServer::do_on_tcp_client(ISrsListener *listener, srs_netfd_t &stf
|
|||
|
||||
// Ignore if ip is empty, for example, load balancer keepalive.
|
||||
if (ip.empty()) {
|
||||
if (_srs_config->empty_ip_ok())
|
||||
if (config_->empty_ip_ok())
|
||||
return err;
|
||||
return srs_error_new(ERROR_SOCKET_GET_PEER_IP, "ignore empty ip, fd=%d", fd);
|
||||
}
|
||||
|
|
@ -1454,8 +1457,8 @@ srs_error_t SrsServer::do_on_tcp_client(ISrsListener *listener, srs_netfd_t &stf
|
|||
if (nn == 10 && b[0] == 0 && b[2] == 0 && b[3] == 1 && b[1] - b[5] == 20 && b[6] == 0x21 && b[7] == 0x12 && b[8] == 0xa4 && b[9] == 0x42) {
|
||||
resource = new SrsRtcTcpConn(io, ip, port);
|
||||
} else {
|
||||
string key = listener == https_listener_ ? _srs_config->get_https_stream_ssl_key() : "";
|
||||
string cert = listener == https_listener_ ? _srs_config->get_https_stream_ssl_cert() : "";
|
||||
string key = listener == https_listener_ ? config_->get_https_stream_ssl_key() : "";
|
||||
string cert = listener == https_listener_ ? config_->get_https_stream_ssl_cert() : "";
|
||||
resource = new SrsHttpxConn(_srs_conn_manager, io, http_server_, ip, port, key, cert);
|
||||
}
|
||||
}
|
||||
|
|
@ -1469,12 +1472,12 @@ srs_error_t SrsServer::do_on_tcp_client(ISrsListener *listener, srs_netfd_t &stf
|
|||
SrsRtmpTransport *transport = new SrsRtmpsTransport(stfd2);
|
||||
resource = new SrsRtmpConn(this, transport, ip, port);
|
||||
} else if (listener == api_listener_ || listener == apis_listener_) {
|
||||
string key = listener == apis_listener_ ? _srs_config->get_https_api_ssl_key() : "";
|
||||
string cert = listener == apis_listener_ ? _srs_config->get_https_api_ssl_cert() : "";
|
||||
string key = listener == apis_listener_ ? config_->get_https_api_ssl_key() : "";
|
||||
string cert = listener == apis_listener_ ? config_->get_https_api_ssl_cert() : "";
|
||||
resource = new SrsHttpxConn(_srs_conn_manager, new SrsTcpConnection(stfd2), http_api_mux_, ip, port, key, cert);
|
||||
} else if (listener == http_listener_ || listener == https_listener_) {
|
||||
string key = listener == https_listener_ ? _srs_config->get_https_stream_ssl_key() : "";
|
||||
string cert = listener == https_listener_ ? _srs_config->get_https_stream_ssl_cert() : "";
|
||||
string key = listener == https_listener_ ? config_->get_https_stream_ssl_key() : "";
|
||||
string cert = listener == https_listener_ ? config_->get_https_stream_ssl_cert() : "";
|
||||
resource = new SrsHttpxConn(_srs_conn_manager, new SrsTcpConnection(stfd2), http_server_, ip, port, key, cert);
|
||||
} else if (listener == webrtc_listener_) {
|
||||
resource = new SrsRtcTcpConn(new SrsTcpConnection(stfd2), ip, port);
|
||||
|
|
@ -1525,7 +1528,7 @@ srs_error_t SrsServer::on_before_connection(const char *label, int fd, const std
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
// Failed if exceed the connection limitation.
|
||||
int max_connections = _srs_config->get_max_connections();
|
||||
int max_connections = config_->get_max_connections();
|
||||
|
||||
if ((int)_srs_conn_manager->size() >= max_connections) {
|
||||
return srs_error_new(ERROR_EXCEED_CONNECTIONS, "drop %s fd=%d, ip=%s:%d, max=%d, cur=%d for exceed connection limits",
|
||||
|
|
@ -1708,8 +1711,8 @@ srs_error_t SrsInotifyWorker::start()
|
|||
|
||||
#if !defined(SRS_OSX) && !defined(SRS_CYGWIN64)
|
||||
// Whether enable auto reload config.
|
||||
bool auto_reload = _srs_config->inotify_auto_reload();
|
||||
if (!auto_reload && _srs_in_docker && _srs_config->auto_reload_for_docker()) {
|
||||
bool auto_reload = config_->inotify_auto_reload();
|
||||
if (!auto_reload && _srs_in_docker && config_->auto_reload_for_docker()) {
|
||||
srs_warn("enable auto reload for docker");
|
||||
auto_reload = true;
|
||||
}
|
||||
|
|
@ -1766,7 +1769,8 @@ srs_error_t SrsInotifyWorker::start()
|
|||
// #define IN_ONESHOT 0x80000000 /* only send event once */
|
||||
|
||||
// Watch the config directory events.
|
||||
string config_dir = srs_path_filepath_dir(_srs_config->config());
|
||||
SrsPath path_util;
|
||||
string config_dir = path_util.filepath_dir(config_->config());
|
||||
uint32_t mask = IN_MODIFY | IN_CREATE | IN_MOVED_TO;
|
||||
int watch_conf = 0;
|
||||
if ((watch_conf = ::inotify_add_watch(fd, config_dir.c_str(), mask)) < 0) {
|
||||
|
|
@ -1788,8 +1792,9 @@ srs_error_t SrsInotifyWorker::cycle()
|
|||
srs_error_t err = srs_success;
|
||||
|
||||
#if !defined(SRS_OSX) && !defined(SRS_CYGWIN64)
|
||||
string config_path = _srs_config->config();
|
||||
string config_file = srs_path_filepath_base(config_path);
|
||||
SrsPath path;
|
||||
string config_path = config_->config();
|
||||
string config_file = path.filepath_base(config_path);
|
||||
string k8s_file = "..data";
|
||||
|
||||
while (true) {
|
||||
|
|
@ -1821,7 +1826,8 @@ srs_error_t SrsInotifyWorker::cycle()
|
|||
}
|
||||
|
||||
// Notify server to do reload.
|
||||
if (do_reload && srs_path_exists(config_path)) {
|
||||
SrsPath path;
|
||||
if (do_reload && path.exists(config_path)) {
|
||||
server_->on_signal(SRS_SIGNAL_RELOAD);
|
||||
}
|
||||
|
||||
|
|
@ -1835,18 +1841,20 @@ srs_error_t SrsInotifyWorker::cycle()
|
|||
SrsPidFileLocker::SrsPidFileLocker()
|
||||
{
|
||||
pid_fd_ = -1;
|
||||
config_ = _srs_config;
|
||||
}
|
||||
|
||||
SrsPidFileLocker::~SrsPidFileLocker()
|
||||
{
|
||||
close();
|
||||
config_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsPidFileLocker::acquire()
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
pid_file_ = _srs_config->get_pid_file();
|
||||
pid_file_ = config_->get_pid_file();
|
||||
|
||||
// -rw-r--r--
|
||||
// 644
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class SrsSrtAcceptor;
|
|||
class SrsSrtEventLoop;
|
||||
class SrsRtcSessionManager;
|
||||
class SrsPidFileLocker;
|
||||
class ISrsAppConfig;
|
||||
|
||||
// Initialize global shared variables cross all threads.
|
||||
extern srs_error_t srs_global_initialize();
|
||||
|
|
@ -66,10 +67,13 @@ extern srs_error_t srs_global_initialize();
|
|||
class SrsServer : public ISrsReloadHandler, // Reload framework for permormance optimization.
|
||||
public ISrsLiveSourceHandler,
|
||||
public ISrsTcpHandler,
|
||||
public ISrsHourGlass,
|
||||
public ISrsHourGlassHandler,
|
||||
public ISrsSrtClientHandler,
|
||||
public ISrsUdpMuxHandler
|
||||
{
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
ISrsHttpServeMux *http_api_mux_;
|
||||
SrsHttpServer *http_server_;
|
||||
|
|
@ -207,7 +211,7 @@ private:
|
|||
// the cpu/mem/network statistic.
|
||||
virtual srs_error_t do_cycle();
|
||||
|
||||
// interface ISrsHourGlass
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
|
@ -313,6 +317,9 @@ public:
|
|||
// PID file manager for process identification and locking.
|
||||
class SrsPidFileLocker
|
||||
{
|
||||
private:
|
||||
ISrsAppConfig *config_;
|
||||
|
||||
private:
|
||||
int pid_fd_;
|
||||
std::string pid_file_;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public:
|
|||
};
|
||||
|
||||
// The SRT source manager.
|
||||
class SrsSrtSourceManager : public ISrsHourGlass, public ISrsSrtSourceManager
|
||||
class SrsSrtSourceManager : public ISrsHourGlassHandler, public ISrsSrtSourceManager
|
||||
{
|
||||
private:
|
||||
srs_mutex_t lock_;
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize();
|
||||
// interface ISrsHourGlass
|
||||
// interface ISrsHourGlassHandler
|
||||
private:
|
||||
virtual srs_error_t setup_ticks();
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ using namespace std;
|
|||
|
||||
string srs_generate_stat_vid()
|
||||
{
|
||||
return "vid-" + srs_rand_gen_str(7);
|
||||
SrsRand rand;
|
||||
return "vid-" + rand.gen_str(7);
|
||||
}
|
||||
|
||||
SrsStatisticVhost::SrsStatisticVhost()
|
||||
|
|
@ -567,7 +568,8 @@ std::string SrsStatistic::server_id()
|
|||
std::string SrsStatistic::service_id()
|
||||
{
|
||||
if (service_id_.empty()) {
|
||||
service_id_ = srs_rand_gen_str(8);
|
||||
SrsRand rand;
|
||||
service_id_ = rand.gen_str(8);
|
||||
}
|
||||
|
||||
return service_id_;
|
||||
|
|
|
|||
|
|
@ -140,6 +140,11 @@ public:
|
|||
public:
|
||||
virtual void on_disconnect(std::string id, srs_error_t err) = 0;
|
||||
virtual srs_error_t on_client(std::string id, ISrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type) = 0;
|
||||
virtual srs_error_t on_video_info(ISrsRequest *req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height) = 0;
|
||||
virtual srs_error_t on_audio_info(ISrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate,
|
||||
SrsAudioChannels asound_type, SrsAacObjectType aac_object) = 0;
|
||||
virtual void on_stream_publish(ISrsRequest *req, std::string publisher_id) = 0;
|
||||
virtual void on_stream_close(ISrsRequest *req) = 0;
|
||||
};
|
||||
|
||||
// The global statistic instance.
|
||||
|
|
|
|||
|
|
@ -154,7 +154,15 @@ string srs_path_build_timestamp(string template_path)
|
|||
return path;
|
||||
}
|
||||
|
||||
srs_error_t srs_kill_forced(int &pid)
|
||||
SrsAppUtility::SrsAppUtility()
|
||||
{
|
||||
}
|
||||
|
||||
SrsAppUtility::~SrsAppUtility()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t SrsAppUtility::kill(int &pid)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -163,7 +171,7 @@ srs_error_t srs_kill_forced(int &pid)
|
|||
}
|
||||
|
||||
// first, try kill by SIGTERM.
|
||||
if (kill(pid, SIGTERM) < 0) {
|
||||
if (::kill(pid, SIGTERM) < 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_KILL, "kill");
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +198,7 @@ srs_error_t srs_kill_forced(int &pid)
|
|||
}
|
||||
|
||||
// then, try kill by SIGKILL.
|
||||
if (kill(pid, SIGKILL) < 0) {
|
||||
if (::kill(pid, SIGKILL) < 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_KILL, "kill");
|
||||
}
|
||||
|
||||
|
|
@ -1302,7 +1310,8 @@ void srs_api_dump_summaries(SrsJsonObject *obj)
|
|||
n_sample_time = o.sample_time_;
|
||||
|
||||
// stat the intranet bytes.
|
||||
if (inter == "lo" || !srs_net_device_is_internet(inter)) {
|
||||
SrsProtocolUtility utility;
|
||||
if (inter == "lo" || !utility.is_internet(inter)) {
|
||||
nri_bytes += o.rbytes_;
|
||||
nsi_bytes += o.sbytes_;
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -50,11 +50,20 @@ extern std::string srs_path_build_stream(std::string template_path, std::string
|
|||
// @return the replaced path.
|
||||
extern std::string srs_path_build_timestamp(std::string template_path);
|
||||
|
||||
// Kill the pid by SIGINT, then wait to quit,
|
||||
// Kill the pid by SIGKILL again when exceed the timeout.
|
||||
// @param pid the pid to kill. ignore for -1. set to -1 when killed.
|
||||
// @return an int error code.
|
||||
extern srs_error_t srs_kill_forced(int &pid);
|
||||
// The app utility.
|
||||
class SrsAppUtility
|
||||
{
|
||||
public:
|
||||
SrsAppUtility();
|
||||
virtual ~SrsAppUtility();
|
||||
|
||||
public:
|
||||
// Kill the pid by SIGINT, then wait to quit,
|
||||
// Kill the pid by SIGKILL again when exceed the timeout.
|
||||
// @param pid the pid to kill. ignore for -1. set to -1 when killed.
|
||||
// @return an int error code.
|
||||
virtual srs_error_t kill(int &pid);
|
||||
};
|
||||
|
||||
// Current process resource usage.
|
||||
// @see: man getrusage
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@
|
|||
XX(ERROR_NO_SOURCE, 1097, "NoSource", "No source found") \
|
||||
XX(ERROR_STREAM_DISPOSING, 1098, "StreamDisposing", "Stream is disposing") \
|
||||
XX(ERROR_NOT_IMPLEMENTED, 1099, "NotImplemented", "Feature is not implemented") \
|
||||
XX(ERROR_NOT_SUPPORTED, 1100, "NotSupported", "Feature is not supported") \
|
||||
XX(ERROR_NOT_SUPPORTED, 1100, "NotSupported", "Feature is not supported") \
|
||||
XX(ERROR_SYSTEM_FILE_UNLINK, 1101, "FileUnlink", "Failed to unlink file")
|
||||
|
||||
/**************************************************/
|
||||
|
|
|
|||
|
|
@ -30,6 +30,14 @@ extern SrsPps *_srs_pps_clock_80ms;
|
|||
extern SrsPps *_srs_pps_clock_160ms;
|
||||
extern SrsPps *_srs_pps_timer_s;
|
||||
|
||||
ISrsHourGlassHandler::ISrsHourGlassHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHourGlassHandler::~ISrsHourGlassHandler()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsHourGlass::ISrsHourGlass()
|
||||
{
|
||||
}
|
||||
|
|
@ -38,7 +46,7 @@ ISrsHourGlass::~ISrsHourGlass()
|
|||
{
|
||||
}
|
||||
|
||||
SrsHourGlass::SrsHourGlass(string label, ISrsHourGlass *h, srs_utime_t resolution)
|
||||
SrsHourGlass::SrsHourGlass(string label, ISrsHourGlassHandler *h, srs_utime_t resolution)
|
||||
{
|
||||
label_ = label;
|
||||
handler_ = h;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,18 @@
|
|||
class ISrsCoroutine;
|
||||
|
||||
// The handler for the tick.
|
||||
class ISrsHourGlassHandler
|
||||
{
|
||||
public:
|
||||
ISrsHourGlassHandler();
|
||||
virtual ~ISrsHourGlassHandler();
|
||||
|
||||
public:
|
||||
// When time is ticked, this function is called.
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick) = 0;
|
||||
};
|
||||
|
||||
// The interface for hourglass.
|
||||
class ISrsHourGlass
|
||||
{
|
||||
public:
|
||||
|
|
@ -25,8 +37,11 @@ public:
|
|||
virtual ~ISrsHourGlass();
|
||||
|
||||
public:
|
||||
// When time is ticked, this function is called.
|
||||
virtual srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick) = 0;
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual srs_error_t tick(srs_utime_t interval) = 0;
|
||||
virtual srs_error_t tick(int event, srs_utime_t interval) = 0;
|
||||
virtual void untick(int event) = 0;
|
||||
};
|
||||
|
||||
// The hourglass(timer or SrsTimer) for special tasks,
|
||||
|
|
@ -53,12 +68,12 @@ public:
|
|||
//
|
||||
// // The hg will create a thread for timer.
|
||||
// hg->start();
|
||||
class SrsHourGlass : public ISrsCoroutineHandler
|
||||
class SrsHourGlass : public ISrsCoroutineHandler, public ISrsHourGlass
|
||||
{
|
||||
private:
|
||||
std::string label_;
|
||||
ISrsCoroutine *trd_;
|
||||
ISrsHourGlass *handler_;
|
||||
ISrsHourGlassHandler *handler_;
|
||||
srs_utime_t resolution_;
|
||||
ISrsTime *time_;
|
||||
// The ticks:
|
||||
|
|
@ -71,7 +86,7 @@ private:
|
|||
|
||||
public:
|
||||
// TODO: FIMXE: Refine to SrsHourGlass(std::string label);
|
||||
SrsHourGlass(std::string label, ISrsHourGlass *h, srs_utime_t resolution);
|
||||
SrsHourGlass(std::string label, ISrsHourGlassHandler *h, srs_utime_t resolution);
|
||||
virtual ~SrsHourGlass();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -401,7 +401,8 @@ int srs_do_create_dir_recursively(string dir)
|
|||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// stat current dir, if exists, return error.
|
||||
if (srs_path_exists(dir)) {
|
||||
SrsPath path;
|
||||
if (path.exists(dir)) {
|
||||
return ERROR_SYSTEM_DIR_EXISTS;
|
||||
}
|
||||
|
||||
|
|
@ -516,17 +517,6 @@ bool srs_bytes_equal(void *pa, void *pb, int size)
|
|||
return true;
|
||||
}
|
||||
|
||||
srs_error_t srs_os_mkdir_all(string dir)
|
||||
{
|
||||
int ret = srs_do_create_dir_recursively(dir);
|
||||
|
||||
if (ret == ERROR_SYSTEM_DIR_EXISTS || ret == ERROR_SUCCESS) {
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
return srs_error_new(ret, "create dir %s", dir.c_str());
|
||||
}
|
||||
|
||||
SrsPath::SrsPath()
|
||||
{
|
||||
}
|
||||
|
|
@ -536,20 +526,6 @@ SrsPath::~SrsPath()
|
|||
}
|
||||
|
||||
bool SrsPath::exists(std::string path)
|
||||
{
|
||||
return srs_path_exists(path);
|
||||
}
|
||||
|
||||
srs_error_t SrsPath::unlink(std::string path)
|
||||
{
|
||||
if (::unlink(path.c_str()) < 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_FILE_UNLINK, "unlink %s", path.c_str());
|
||||
}
|
||||
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
bool srs_path_exists(std::string path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
|
|
@ -561,7 +537,16 @@ bool srs_path_exists(std::string path)
|
|||
return false;
|
||||
}
|
||||
|
||||
string srs_path_filepath_dir(string path)
|
||||
srs_error_t SrsPath::unlink(std::string path)
|
||||
{
|
||||
if (::unlink(path.c_str()) < 0) {
|
||||
return srs_error_new(ERROR_SYSTEM_FILE_UNLINK, "unlink %s", path.c_str());
|
||||
}
|
||||
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
std::string SrsPath::filepath_dir(std::string path)
|
||||
{
|
||||
std::string dirname = path;
|
||||
|
||||
|
|
@ -581,7 +566,7 @@ string srs_path_filepath_dir(string path)
|
|||
return dirname;
|
||||
}
|
||||
|
||||
string srs_path_filepath_base(string path)
|
||||
string SrsPath::filepath_base(string path)
|
||||
{
|
||||
std::string dirname = path;
|
||||
size_t pos = string::npos;
|
||||
|
|
@ -597,7 +582,7 @@ string srs_path_filepath_base(string path)
|
|||
return dirname;
|
||||
}
|
||||
|
||||
string srs_path_filepath_filename(string path)
|
||||
string SrsPath::filepath_filename(string path)
|
||||
{
|
||||
std::string filename = path;
|
||||
size_t pos = string::npos;
|
||||
|
|
@ -609,7 +594,7 @@ string srs_path_filepath_filename(string path)
|
|||
return filename;
|
||||
}
|
||||
|
||||
string srs_path_filepath_ext(string path)
|
||||
string SrsPath::filepath_ext(string path)
|
||||
{
|
||||
size_t pos = string::npos;
|
||||
|
||||
|
|
@ -620,6 +605,17 @@ string srs_path_filepath_ext(string path)
|
|||
return "";
|
||||
}
|
||||
|
||||
srs_error_t SrsPath::mkdir_all(string dir)
|
||||
{
|
||||
int ret = srs_do_create_dir_recursively(dir);
|
||||
|
||||
if (ret == ERROR_SYSTEM_DIR_EXISTS || ret == ERROR_SUCCESS) {
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
return srs_error_new(ret, "create dir %s", dir.c_str());
|
||||
}
|
||||
|
||||
// fromHexChar converts a hex character into its value and a success flag.
|
||||
uint8_t srs_from_hex_char(uint8_t c)
|
||||
{
|
||||
|
|
@ -691,28 +687,36 @@ int srs_hex_decode_string(uint8_t *data, const char *p, int size)
|
|||
return size / 2;
|
||||
}
|
||||
|
||||
void srs_rand_gen_bytes(char *bytes, int size)
|
||||
SrsRand::SrsRand()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRand::~SrsRand()
|
||||
{
|
||||
}
|
||||
|
||||
void SrsRand::gen_bytes(char *bytes, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
// the common value in [0x0f, 0xf0]
|
||||
bytes[i] = 0x0f + (srs_rand_integer() % (256 - 0x0f - 0x0f));
|
||||
bytes[i] = 0x0f + (integer() % (256 - 0x0f - 0x0f));
|
||||
}
|
||||
}
|
||||
|
||||
std::string srs_rand_gen_str(int len)
|
||||
std::string SrsRand::gen_str(int len)
|
||||
{
|
||||
static string random_table = "01234567890123456789012345678901234567890123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
string ret;
|
||||
ret.reserve(len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
ret.append(1, random_table[srs_rand_integer() % random_table.size()]);
|
||||
ret.append(1, random_table[integer() % random_table.size()]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long srs_rand_integer()
|
||||
long SrsRand::integer()
|
||||
{
|
||||
static bool _random_initialized = false;
|
||||
if (!_random_initialized) {
|
||||
|
|
@ -723,9 +727,9 @@ long srs_rand_integer()
|
|||
return random();
|
||||
}
|
||||
|
||||
long srs_rand_integer(long min, long max)
|
||||
long SrsRand::integer(long min, long max)
|
||||
{
|
||||
return min + (srs_rand_integer() % (max - min + 1));
|
||||
return min + (integer() % (max - min + 1));
|
||||
}
|
||||
|
||||
bool srs_is_digit_number(string str)
|
||||
|
|
|
|||
|
|
@ -126,9 +126,6 @@ bool srs_strings_equal(std::vector<T> &a, std::vector<T> &b)
|
|||
// @return true if completely equal; otherwise, false.
|
||||
extern bool srs_bytes_equal(void *pa, void *pb, int size);
|
||||
|
||||
// Create dir recursively
|
||||
extern srs_error_t srs_os_mkdir_all(std::string dir);
|
||||
|
||||
// The path utility.
|
||||
class SrsPath
|
||||
{
|
||||
|
|
@ -141,18 +138,19 @@ public:
|
|||
virtual bool exists(std::string path);
|
||||
// Remove or unlink file.
|
||||
virtual srs_error_t unlink(std::string path);
|
||||
};
|
||||
// Get the dirname of path, for instance, dirname("/live/livestream")="/live"
|
||||
virtual std::string filepath_dir(std::string path);
|
||||
// Get the basename of path, for instance, basename("/live/livestream")="livestream"
|
||||
virtual std::string filepath_base(std::string path);
|
||||
// Get the filename of path, for instance, filename("livestream.flv")="livestream"
|
||||
virtual std::string filepath_filename(std::string path);
|
||||
// Get the file extension of path, for instance, filext("live.flv")=".flv"
|
||||
virtual std::string filepath_ext(std::string path);
|
||||
|
||||
// Whether path exists.
|
||||
extern bool srs_path_exists(std::string path);
|
||||
// Get the dirname of path, for instance, dirname("/live/livestream")="/live"
|
||||
extern std::string srs_path_filepath_dir(std::string path);
|
||||
// Get the basename of path, for instance, basename("/live/livestream")="livestream"
|
||||
extern std::string srs_path_filepath_base(std::string path);
|
||||
// Get the filename of path, for instance, filename("livestream.flv")="livestream"
|
||||
extern std::string srs_path_filepath_filename(std::string path);
|
||||
// Get the file extension of path, for instance, filext("live.flv")=".flv"
|
||||
extern std::string srs_path_filepath_ext(std::string path);
|
||||
public:
|
||||
// Create dir recursively
|
||||
virtual srs_error_t mkdir_all(std::string dir);
|
||||
};
|
||||
|
||||
// Covert hex string p to uint8 data, for example:
|
||||
// srs_hex_decode_string(data, string("139056E5A0"))
|
||||
|
|
@ -166,15 +164,22 @@ extern char *srs_hex_encode_to_string(char *des, const uint8_t *src, int len);
|
|||
// Output in lowercase, such as string("f33f").
|
||||
extern char *srs_hex_encode_to_string_lowercase(char *des, const uint8_t *src, int len);
|
||||
|
||||
// Generate ramdom data for handshake.
|
||||
extern void srs_rand_gen_bytes(char *bytes, int size);
|
||||
// The random generator.
|
||||
class SrsRand
|
||||
{
|
||||
public:
|
||||
SrsRand();
|
||||
virtual ~SrsRand();
|
||||
|
||||
// Generate random string [0-9a-z] in size of len bytes.
|
||||
extern std::string srs_rand_gen_str(int len);
|
||||
|
||||
// Generate random value, use srandom(now_us) to init seed if not initialized.
|
||||
extern long srs_rand_integer();
|
||||
extern long srs_rand_integer(long min, long max);
|
||||
public:
|
||||
// Generate ramdom data for handshake.
|
||||
virtual void gen_bytes(char *bytes, int size);
|
||||
// Generate random string [0-9a-z] in size of len bytes.
|
||||
virtual std::string gen_str(int len);
|
||||
// Generate random value, use srandom(now_us) to init seed if not initialized.
|
||||
virtual long integer();
|
||||
virtual long integer(long min, long max);
|
||||
};
|
||||
|
||||
// Whether string is digit number
|
||||
// is_digit("0") is true
|
||||
|
|
|
|||
|
|
@ -388,7 +388,8 @@ srs_error_t SrsHttpMessage::set_url(string url, bool allow_jsonp)
|
|||
|
||||
// If no host in header, we use local discovered IP, IPv4 first.
|
||||
if (host.empty()) {
|
||||
host = srs_get_public_internet_address(true);
|
||||
SrsProtocolUtility utility;
|
||||
host = utility.public_internet_address(true);
|
||||
}
|
||||
|
||||
// The url must starts with slash if no schema. For example, SIP request line starts with "sip".
|
||||
|
|
@ -406,7 +407,8 @@ srs_error_t SrsHttpMessage::set_url(string url, bool allow_jsonp)
|
|||
}
|
||||
|
||||
// parse ext.
|
||||
_ext = srs_path_filepath_ext(_uri->get_path());
|
||||
SrsPath path;
|
||||
_ext = path.filepath_ext(_uri->get_path());
|
||||
|
||||
// parse query string.
|
||||
srs_net_url_parse_query(_uri->get_query(), _query);
|
||||
|
|
@ -633,7 +635,8 @@ ISrsRequest *SrsHttpMessage::to_request(string vhost)
|
|||
req->app_ = srs_strings_trim_start(req->app_, "/");
|
||||
|
||||
// remove the extension, for instance, livestream.flv to livestream
|
||||
req->stream_ = srs_path_filepath_filename(req->stream_);
|
||||
SrsPath path;
|
||||
req->stream_ = path.filepath_filename(req->stream_);
|
||||
|
||||
// generate others.
|
||||
req->tcUrl_ = "rtmp://" + vhost + "/" + req->app_;
|
||||
|
|
@ -703,12 +706,14 @@ SrsHttpMessageWriter::SrsHttpMessageWriter(ISrsProtocolReadWriter *io, ISrsHttpF
|
|||
iovss_cache_ = NULL;
|
||||
hf_ = NULL;
|
||||
flw_ = flw;
|
||||
protocol_utility_ = new SrsProtocolUtility();
|
||||
}
|
||||
|
||||
SrsHttpMessageWriter::~SrsHttpMessageWriter()
|
||||
{
|
||||
srs_freep(hdr_);
|
||||
srs_freepa(iovss_cache_);
|
||||
srs_freep(protocol_utility_);
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpMessageWriter::final_request()
|
||||
|
|
@ -874,7 +879,7 @@ srs_error_t SrsHttpMessageWriter::writev(const iovec *iov, int iovcnt, ssize_t *
|
|||
|
||||
// sendout all ioves.
|
||||
ssize_t nwrite = 0;
|
||||
if ((err = srs_write_large_iovs(skt_, iovss, nb_iovss, &nwrite)) != srs_success) {
|
||||
if ((err = protocol_utility_->write_iovs(skt_, iovss, nb_iovss, &nwrite)) != srs_success) {
|
||||
return srs_error_wrap(err, "writev large iovs");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class ISrsRequest;
|
|||
class ISrsReader;
|
||||
class SrsHttpResponseReader;
|
||||
class ISrsProtocolReadWriter;
|
||||
class SrsProtocolUtility;
|
||||
|
||||
// A wrapper for llhttp,
|
||||
// provides HTTP message originted service.
|
||||
|
|
@ -261,6 +262,8 @@ private:
|
|||
// (*response).wroteHeader, which tells only whether it was
|
||||
// logically written.
|
||||
bool header_sent_;
|
||||
// Protocol utility for writing large iovs.
|
||||
SrsProtocolUtility *protocol_utility_;
|
||||
|
||||
public:
|
||||
SrsHttpMessageWriter(ISrsProtocolReadWriter *io, ISrsHttpFirstLineWriter *flw);
|
||||
|
|
|
|||
|
|
@ -532,12 +532,13 @@ SrsHttpFileServer::SrsHttpFileServer(string root_dir)
|
|||
{
|
||||
dir = root_dir;
|
||||
fs_factory = new ISrsFileReaderFactory();
|
||||
_srs_path_exists = srs_path_exists;
|
||||
path_ = new SrsPath();
|
||||
}
|
||||
|
||||
SrsHttpFileServer::~SrsHttpFileServer()
|
||||
{
|
||||
srs_freep(fs_factory);
|
||||
srs_freep(path_);
|
||||
}
|
||||
|
||||
void SrsHttpFileServer::set_fs_factory(ISrsFileReaderFactory *f)
|
||||
|
|
@ -546,9 +547,10 @@ void SrsHttpFileServer::set_fs_factory(ISrsFileReaderFactory *f)
|
|||
fs_factory = f;
|
||||
}
|
||||
|
||||
void SrsHttpFileServer::set_path_check(_pfn_srs_path_exists pfn)
|
||||
void SrsHttpFileServer::set_path(SrsPath *v)
|
||||
{
|
||||
_srs_path_exists = pfn;
|
||||
srs_freep(path_);
|
||||
path_ = v;
|
||||
}
|
||||
|
||||
srs_error_t SrsHttpFileServer::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r)
|
||||
|
|
@ -561,10 +563,11 @@ srs_error_t SrsHttpFileServer::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMes
|
|||
|
||||
string upath = r->path();
|
||||
string fullpath = srs_http_fs_fullpath(dir, entry->pattern, upath);
|
||||
string basename = srs_path_filepath_base(upath);
|
||||
SrsPath path;
|
||||
string basename = path.filepath_base(upath);
|
||||
|
||||
// stat current dir, if exists, return error.
|
||||
if (!_srs_path_exists(fullpath)) {
|
||||
if (!path_->exists(fullpath)) {
|
||||
srs_warn("http miss file=%s, pattern=%s, upath=%s",
|
||||
fullpath.c_str(), entry->pattern.c_str(), upath.c_str());
|
||||
return SrsHttpNotFoundHandler().serve_http(w, r);
|
||||
|
|
@ -640,7 +643,8 @@ srs_error_t SrsHttpFileServer::serve_file(ISrsHttpResponseWriter *w, ISrsHttpMes
|
|||
}
|
||||
|
||||
if (true) {
|
||||
std::string ext = srs_path_filepath_ext(fullpath);
|
||||
SrsPath path;
|
||||
std::string ext = path.filepath_ext(fullpath);
|
||||
|
||||
if (_mime.find(ext) == _mime.end()) {
|
||||
w->header()->set_content_type("application/octet-stream");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <srs_core.hpp>
|
||||
|
||||
#include <srs_kernel_io.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_http_stack_llhttp.hpp>
|
||||
|
||||
#include <map>
|
||||
|
|
@ -327,9 +328,6 @@ public:
|
|||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
};
|
||||
|
||||
// For utest to mock it.
|
||||
typedef bool (*_pfn_srs_path_exists)(std::string path);
|
||||
|
||||
// Build the file path from request r.
|
||||
extern std::string srs_http_fs_fullpath(std::string dir, std::string pattern, std::string upath);
|
||||
|
||||
|
|
@ -348,7 +346,7 @@ protected:
|
|||
|
||||
protected:
|
||||
ISrsFileReaderFactory *fs_factory;
|
||||
_pfn_srs_path_exists _srs_path_exists;
|
||||
SrsPath *path_;
|
||||
|
||||
public:
|
||||
SrsHttpFileServer(std::string root_dir);
|
||||
|
|
@ -357,8 +355,8 @@ public:
|
|||
private:
|
||||
// For utest to mock the fs.
|
||||
virtual void set_fs_factory(ISrsFileReaderFactory *v);
|
||||
// For utest to mock the path check function.
|
||||
virtual void set_path_check(_pfn_srs_path_exists pfn);
|
||||
// For utest to mock the path utility.
|
||||
virtual void set_path(SrsPath *v);
|
||||
|
||||
public:
|
||||
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@ SrsThreadContext::~SrsThreadContext()
|
|||
|
||||
SrsContextId SrsThreadContext::generate_id()
|
||||
{
|
||||
SrsRand rand;
|
||||
SrsContextId cid;
|
||||
return cid.set_value(srs_rand_gen_str(8));
|
||||
return cid.set_value(rand.gen_str(8));
|
||||
}
|
||||
|
||||
static SrsContextId _srs_context_default;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ void SrsBasicRtmpClient::close()
|
|||
|
||||
srs_error_t SrsBasicRtmpClient::connect_app()
|
||||
{
|
||||
return do_connect_app(srs_get_public_internet_address(), false);
|
||||
SrsProtocolUtility utility;
|
||||
return do_connect_app(utility.public_internet_address(), false);
|
||||
}
|
||||
|
||||
srs_error_t SrsBasicRtmpClient::do_connect_app(string local_ip, bool debug)
|
||||
|
|
|
|||
|
|
@ -333,7 +333,8 @@ srs_error_t SrsDH::do_initialize()
|
|||
|
||||
SrsKeyBlock::SrsKeyBlock()
|
||||
{
|
||||
offset_ = (int32_t)srs_rand_integer();
|
||||
SrsRand rand;
|
||||
offset_ = (int32_t)rand.integer();
|
||||
random0_ = NULL;
|
||||
random1_ = NULL;
|
||||
|
||||
|
|
@ -343,16 +344,16 @@ SrsKeyBlock::SrsKeyBlock()
|
|||
random0_size_ = valid_offset;
|
||||
if (random0_size_ > 0) {
|
||||
random0_ = new char[random0_size_];
|
||||
srs_rand_gen_bytes(random0_, random0_size_);
|
||||
rand_.gen_bytes(random0_, random0_size_);
|
||||
snprintf(random0_, random0_size_, "%s", RTMP_SIG_SRS_HANDSHAKE);
|
||||
}
|
||||
|
||||
srs_rand_gen_bytes(key_, sizeof(key_));
|
||||
rand_.gen_bytes(key_, sizeof(key_));
|
||||
|
||||
random1_size_ = 764 - valid_offset - 128 - 4;
|
||||
if (random1_size_ > 0) {
|
||||
random1_ = new char[random1_size_];
|
||||
srs_rand_gen_bytes(random1_, random1_size_);
|
||||
rand_.gen_bytes(random1_, random1_size_);
|
||||
snprintf(random1_, random1_size_, "%s", RTMP_SIG_SRS_HANDSHAKE);
|
||||
}
|
||||
}
|
||||
|
|
@ -415,7 +416,8 @@ int SrsKeyBlock::calc_valid_offset()
|
|||
|
||||
SrsDigestBlock::SrsDigestBlock()
|
||||
{
|
||||
offset_ = (int32_t)srs_rand_integer();
|
||||
SrsRand rand;
|
||||
offset_ = (int32_t)rand.integer();
|
||||
random0_ = NULL;
|
||||
random1_ = NULL;
|
||||
|
||||
|
|
@ -425,16 +427,16 @@ SrsDigestBlock::SrsDigestBlock()
|
|||
random0_size_ = valid_offset;
|
||||
if (random0_size_ > 0) {
|
||||
random0_ = new char[random0_size_];
|
||||
srs_rand_gen_bytes(random0_, random0_size_);
|
||||
rand_.gen_bytes(random0_, random0_size_);
|
||||
snprintf(random0_, random0_size_, "%s", RTMP_SIG_SRS_HANDSHAKE);
|
||||
}
|
||||
|
||||
srs_rand_gen_bytes(digest_, sizeof(digest_));
|
||||
rand_.gen_bytes(digest_, sizeof(digest_));
|
||||
|
||||
random1_size_ = 764 - 4 - valid_offset - 32;
|
||||
if (random1_size_ > 0) {
|
||||
random1_ = new char[random1_size_];
|
||||
srs_rand_gen_bytes(random1_, random1_size_);
|
||||
rand_.gen_bytes(random1_, random1_size_);
|
||||
snprintf(random1_, random1_size_, "%s", RTMP_SIG_SRS_HANDSHAKE);
|
||||
}
|
||||
}
|
||||
|
|
@ -945,13 +947,13 @@ srs_error_t SrsC1S1::s1_validate_digest(bool &is_valid)
|
|||
|
||||
SrsC2S2::SrsC2S2()
|
||||
{
|
||||
srs_rand_gen_bytes(random_, 1504);
|
||||
rand_.gen_bytes(random_, 1504);
|
||||
|
||||
int size = snprintf(random_, 1504, "%s", RTMP_SIG_SRS_HANDSHAKE);
|
||||
srs_assert(size > 0 && size < 1504);
|
||||
snprintf(random_ + 1504 - size, size, "%s", RTMP_SIG_SRS_HANDSHAKE);
|
||||
|
||||
srs_rand_gen_bytes(digest_, 32);
|
||||
rand_.gen_bytes(digest_, 32);
|
||||
}
|
||||
|
||||
SrsC2S2::~SrsC2S2()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#define SRS_PROTOCOL_HANDSHAKE_HPP
|
||||
|
||||
#include <srs_core.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
|
||||
class ISrsProtocolReadWriter;
|
||||
class SrsComplexHandshake;
|
||||
|
|
@ -90,6 +91,9 @@ enum srs_schema_type {
|
|||
// @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
class SrsKeyBlock
|
||||
{
|
||||
private:
|
||||
SrsRand rand_;
|
||||
|
||||
public:
|
||||
// (offset)bytes
|
||||
char *random0_;
|
||||
|
|
@ -129,6 +133,9 @@ private:
|
|||
// @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
class SrsDigestBlock
|
||||
{
|
||||
private:
|
||||
SrsRand rand_;
|
||||
|
||||
public:
|
||||
// 4bytes
|
||||
int32_t offset_;
|
||||
|
|
@ -382,6 +389,9 @@ public:
|
|||
// @see also: http://blog.csdn.net/win_lin/article/details/13006803
|
||||
class SrsC2S2
|
||||
{
|
||||
private:
|
||||
SrsRand rand_;
|
||||
|
||||
public:
|
||||
char random_[1504];
|
||||
char digest_[32];
|
||||
|
|
|
|||
|
|
@ -184,6 +184,8 @@ SrsProtocol::SrsProtocol(ISrsProtocolReadWriter *io)
|
|||
show_debug_info_ = true;
|
||||
in_buffer_length_ = 0;
|
||||
|
||||
protocol_utility_ = new SrsProtocolUtility();
|
||||
|
||||
cs_cache_ = NULL;
|
||||
if (SRS_PERF_CHUNK_STREAM_CACHE > 0) {
|
||||
cs_cache_ = new SrsChunkStream *[SRS_PERF_CHUNK_STREAM_CACHE];
|
||||
|
|
@ -234,6 +236,8 @@ SrsProtocol::~SrsProtocol()
|
|||
srs_freepa(cs_cache_);
|
||||
|
||||
srs_freepa(out_c0c3_caches_);
|
||||
|
||||
srs_freep(protocol_utility_);
|
||||
}
|
||||
|
||||
void SrsProtocol::set_auto_response(bool v)
|
||||
|
|
@ -539,7 +543,7 @@ srs_error_t SrsProtocol::do_send_messages(SrsMediaPacket **msgs, int nb_msgs)
|
|||
|
||||
srs_error_t SrsProtocol::do_iovs_send(iovec *iovs, int size)
|
||||
{
|
||||
return srs_write_large_iovs(skt_, iovs, size);
|
||||
return protocol_utility_->write_iovs(skt_, iovs, size);
|
||||
}
|
||||
|
||||
srs_error_t SrsProtocol::do_send_and_free_packet(SrsRtmpCommand *packet_raw, int stream_id)
|
||||
|
|
@ -1706,7 +1710,7 @@ srs_error_t SrsHandshakeBytes::create_c0c1()
|
|||
}
|
||||
|
||||
c0c1_ = new char[1537];
|
||||
srs_rand_gen_bytes(c0c1_, 1537);
|
||||
rand_.gen_bytes(c0c1_, 1537);
|
||||
|
||||
// plain text required.
|
||||
SrsBuffer stream(c0c1_, 9);
|
||||
|
|
@ -1727,7 +1731,7 @@ srs_error_t SrsHandshakeBytes::create_s0s1s2(const char *c1)
|
|||
}
|
||||
|
||||
s0s1s2_ = new char[3073];
|
||||
srs_rand_gen_bytes(s0s1s2_, 3073);
|
||||
rand_.gen_bytes(s0s1s2_, 3073);
|
||||
|
||||
// plain text required.
|
||||
SrsBuffer stream(s0s1s2_, 9);
|
||||
|
|
@ -1757,7 +1761,7 @@ srs_error_t SrsHandshakeBytes::create_c2()
|
|||
}
|
||||
|
||||
c2_ = new char[1536];
|
||||
srs_rand_gen_bytes(c2_, 1536);
|
||||
rand_.gen_bytes(c2_, 1536);
|
||||
|
||||
// time
|
||||
SrsBuffer stream(c2_, 8);
|
||||
|
|
@ -2387,7 +2391,8 @@ srs_error_t SrsRtmpServer::redirect(ISrsRequest *r, string url, bool &accepted)
|
|||
|
||||
// The redirect is tcUrl while redirect2 is RTMP URL.
|
||||
// https://github.com/ossrs/srs/issues/1575#issuecomment-574999798
|
||||
string tcUrl = srs_path_filepath_dir(url);
|
||||
SrsPath path;
|
||||
string tcUrl = path.filepath_dir(url);
|
||||
ex->set("redirect", SrsAmf0Any::str(tcUrl.c_str()));
|
||||
ex->set("redirect2", SrsAmf0Any::str(url.c_str()));
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_flv.hpp>
|
||||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
|
||||
class SrsFastStream;
|
||||
class SrsBuffer;
|
||||
|
|
@ -33,6 +34,7 @@ class SrsMediaPacket;
|
|||
class SrsProtocol;
|
||||
class ISrsProtocolReader;
|
||||
class ISrsProtocolReadWriter;
|
||||
class SrsProtocolUtility;
|
||||
class SrsCreateStreamPacket;
|
||||
class SrsFMLEStartPacket;
|
||||
class SrsPublishPacket;
|
||||
|
|
@ -197,6 +199,8 @@ private:
|
|||
bool warned_c0c3_cache_dry_;
|
||||
// The output chunk size, default to 128, set by config.
|
||||
int32_t out_chunk_size_;
|
||||
// Protocol utility for writing large iovs.
|
||||
SrsProtocolUtility *protocol_utility_;
|
||||
|
||||
public:
|
||||
SrsProtocol(ISrsProtocolReadWriter *io);
|
||||
|
|
@ -539,6 +543,9 @@ bool srs_client_type_is_publish(SrsRtmpConnType type);
|
|||
// For smart switch between complex and simple handshake.
|
||||
class SrsHandshakeBytes
|
||||
{
|
||||
private:
|
||||
SrsRand rand_;
|
||||
|
||||
public:
|
||||
// For RTMP proxy, the real IP.
|
||||
uint32_t proxy_real_ip_;
|
||||
|
|
|
|||
|
|
@ -551,8 +551,9 @@ srs_error_t SrsRtspStack::do_recv_message(SrsRtspRequest *req)
|
|||
|
||||
// for setup, parse the stream id from uri.
|
||||
if (req->is_setup()) {
|
||||
SrsPath path;
|
||||
size_t pos = string::npos;
|
||||
std::string stream_id = srs_path_filepath_base(req->uri_);
|
||||
std::string stream_id = path.filepath_base(req->uri_);
|
||||
if ((pos = stream_id.find("=")) != string::npos) {
|
||||
stream_id = stream_id.substr(pos + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,12 +79,13 @@ void srs_net_url_parse_tcurl(string tcUrl, string &schema, string &host, string
|
|||
schema = uri.get_schema();
|
||||
host = uri.get_host();
|
||||
port = uri.get_port();
|
||||
stream = srs_path_filepath_base(uri.get_path());
|
||||
SrsPath path;
|
||||
stream = path.filepath_base(uri.get_path());
|
||||
param = uri.get_query().empty() ? "" : "?" + uri.get_query();
|
||||
param += uri.get_fragment().empty() ? "" : "#" + uri.get_fragment();
|
||||
|
||||
// Parse app without the prefix slash.
|
||||
app = srs_path_filepath_dir(uri.get_path());
|
||||
app = path.filepath_dir(uri.get_path());
|
||||
if (!app.empty() && app.at(0) == '/')
|
||||
app = app.substr(1);
|
||||
if (app.empty())
|
||||
|
|
@ -260,7 +261,8 @@ string srs_net_url_encode_sid(string vhost, string app, string stream)
|
|||
}
|
||||
url += "/" + app;
|
||||
// Note that we ignore any extension.
|
||||
url += "/" + srs_path_filepath_filename(stream);
|
||||
SrsPath path;
|
||||
url += "/" + path.filepath_filename(stream);
|
||||
|
||||
return url;
|
||||
}
|
||||
|
|
@ -341,7 +343,15 @@ srs_error_t srs_rtmp_create_msg(char type, uint32_t timestamp, char *data, int s
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t srs_write_large_iovs(ISrsProtocolReadWriter *skt, iovec *iovs, int size, ssize_t *pnwrite)
|
||||
SrsProtocolUtility::SrsProtocolUtility()
|
||||
{
|
||||
}
|
||||
|
||||
SrsProtocolUtility::~SrsProtocolUtility()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t SrsProtocolUtility::write_iovs(ISrsProtocolReadWriter *skt, iovec *iovs, int size, ssize_t *pnwrite)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -379,7 +389,7 @@ srs_error_t srs_write_large_iovs(ISrsProtocolReadWriter *skt, iovec *iovs, int s
|
|||
// value is whether internet, for instance, true.
|
||||
static std::map<std::string, bool> _srs_device_ifs;
|
||||
|
||||
bool srs_net_device_is_internet(string ifname)
|
||||
bool SrsProtocolUtility::is_internet(string ifname)
|
||||
{
|
||||
srs_info("check ifname=%s", ifname.c_str());
|
||||
|
||||
|
|
@ -389,7 +399,7 @@ bool srs_net_device_is_internet(string ifname)
|
|||
return _srs_device_ifs[ifname];
|
||||
}
|
||||
|
||||
bool srs_net_device_is_internet(const sockaddr *addr)
|
||||
bool SrsProtocolUtility::is_internet(const sockaddr *addr)
|
||||
{
|
||||
if (addr->sa_family == AF_INET) {
|
||||
const in_addr inaddr = ((sockaddr_in *)addr)->sin_addr;
|
||||
|
|
@ -465,9 +475,7 @@ bool srs_net_device_is_internet(const sockaddr *addr)
|
|||
return true;
|
||||
}
|
||||
|
||||
vector<SrsIPAddress *> _srs_system_ips;
|
||||
|
||||
void discover_network_iface(ifaddrs *cur, vector<SrsIPAddress *> &ips, stringstream &ss0, stringstream &ss1, bool ipv6, bool loopback)
|
||||
void discover_network_iface(SrsProtocolUtility *utility, ifaddrs *cur, vector<SrsIPAddress *> &ips, stringstream &ss0, stringstream &ss1, bool ipv6, bool loopback)
|
||||
{
|
||||
char saddr[64];
|
||||
char *h = (char *)saddr;
|
||||
|
|
@ -487,7 +495,7 @@ void discover_network_iface(ifaddrs *cur, vector<SrsIPAddress *> &ips, stringstr
|
|||
ip_address->is_ipv4_ = !ipv6;
|
||||
ip_address->is_loopback_ = loopback;
|
||||
ip_address->ifname_ = cur->ifa_name;
|
||||
ip_address->is_internet_ = srs_net_device_is_internet(cur->ifa_addr);
|
||||
ip_address->is_internet_ = utility->is_internet(cur->ifa_addr);
|
||||
ips.push_back(ip_address);
|
||||
|
||||
// set the device internet status.
|
||||
|
|
@ -501,7 +509,9 @@ void discover_network_iface(ifaddrs *cur, vector<SrsIPAddress *> &ips, stringstr
|
|||
ss1 << cur->ifa_name << " " << ip;
|
||||
}
|
||||
|
||||
void retrieve_local_ips()
|
||||
vector<SrsIPAddress *> _srs_system_ips;
|
||||
|
||||
void retrieve_local_ips(SrsProtocolUtility *utility)
|
||||
{
|
||||
vector<SrsIPAddress *> &ips = _srs_system_ips;
|
||||
|
||||
|
|
@ -536,7 +546,7 @@ void retrieve_local_ips()
|
|||
bool ignored = (!cur->ifa_addr) || (cur->ifa_flags & IFF_LOOPBACK) || (cur->ifa_flags & IFF_POINTOPOINT);
|
||||
bool loopback = (cur->ifa_flags & IFF_LOOPBACK);
|
||||
if (ipv4 && ready && !ignored) {
|
||||
discover_network_iface(cur, ips, ss0, ss1, false, loopback);
|
||||
discover_network_iface(utility, cur, ips, ss0, ss1, false, loopback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -557,7 +567,7 @@ void retrieve_local_ips()
|
|||
bool ignored = (!cur->ifa_addr) || (cur->ifa_flags & IFF_POINTOPOINT) || (cur->ifa_flags & IFF_PROMISC) || (cur->ifa_flags & IFF_LOOPBACK);
|
||||
bool loopback = (cur->ifa_flags & IFF_LOOPBACK);
|
||||
if (ipv6 && ready && !ignored) {
|
||||
discover_network_iface(cur, ips, ss0, ss1, true, loopback);
|
||||
discover_network_iface(utility, cur, ips, ss0, ss1, true, loopback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -579,7 +589,7 @@ void retrieve_local_ips()
|
|||
bool ignored = (!cur->ifa_addr) || (cur->ifa_flags & IFF_POINTOPOINT) || (cur->ifa_flags & IFF_PROMISC);
|
||||
bool loopback = (cur->ifa_flags & IFF_LOOPBACK);
|
||||
if (ipv4 && ready && !ignored) {
|
||||
discover_network_iface(cur, ips, ss0, ss1, false, loopback);
|
||||
discover_network_iface(utility, cur, ips, ss0, ss1, false, loopback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -590,10 +600,10 @@ void retrieve_local_ips()
|
|||
freeifaddrs(ifap);
|
||||
}
|
||||
|
||||
vector<SrsIPAddress *> &srs_get_local_ips()
|
||||
vector<SrsIPAddress *> &SrsProtocolUtility::local_ips()
|
||||
{
|
||||
if (_srs_system_ips.empty()) {
|
||||
retrieve_local_ips();
|
||||
retrieve_local_ips(this);
|
||||
}
|
||||
|
||||
return _srs_system_ips;
|
||||
|
|
@ -601,13 +611,13 @@ vector<SrsIPAddress *> &srs_get_local_ips()
|
|||
|
||||
std::string _public_internet_address;
|
||||
|
||||
string srs_get_public_internet_address(bool ipv4_only)
|
||||
string SrsProtocolUtility::public_internet_address(bool ipv4_only)
|
||||
{
|
||||
if (!_public_internet_address.empty()) {
|
||||
return _public_internet_address;
|
||||
}
|
||||
|
||||
std::vector<SrsIPAddress *> &ips = srs_get_local_ips();
|
||||
std::vector<SrsIPAddress *> &ips = local_ips();
|
||||
|
||||
// find the best match public address.
|
||||
for (int i = 0; i < (int)ips.size(); i++) {
|
||||
|
|
@ -678,7 +688,7 @@ string srs_get_original_ip(ISrsHttpMessage *r)
|
|||
|
||||
std::string _srs_system_hostname;
|
||||
|
||||
string srs_get_system_hostname()
|
||||
string SrsProtocolUtility::system_hostname()
|
||||
{
|
||||
if (!_srs_system_hostname.empty()) {
|
||||
return _srs_system_hostname;
|
||||
|
|
@ -695,7 +705,7 @@ string srs_get_system_hostname()
|
|||
}
|
||||
|
||||
#if defined(__linux__) || defined(SRS_OSX)
|
||||
utsname *srs_get_system_uname_info()
|
||||
utsname *SrsProtocolUtility::system_uname()
|
||||
{
|
||||
static utsname *system_info = NULL;
|
||||
|
||||
|
|
@ -838,7 +848,8 @@ bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, ISr
|
|||
request->param_ = stream_with_params.substr(pos + 1);
|
||||
}
|
||||
|
||||
request->host_ = srs_get_public_internet_address();
|
||||
SrsProtocolUtility utility;
|
||||
request->host_ = utility.public_internet_address();
|
||||
if (request->vhost_.empty())
|
||||
request->vhost_ = request->host_;
|
||||
request->tcUrl_ = srs_net_url_encode_tcurl("srt", request->host_, request->vhost_, request->app_, request->port_);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#include <ifaddrs.h>
|
||||
|
||||
class ISrsHttpMessage;
|
||||
|
||||
class SrsMessageHeader;
|
||||
|
|
@ -103,10 +105,6 @@ extern std::string srs_net_url_encode_rtmp_url(std::string server, int port, std
|
|||
*/
|
||||
extern srs_error_t srs_rtmp_create_msg(char type, uint32_t timestamp, char *data, int size, int stream_id, SrsRtmpCommonMessage **ppmsg);
|
||||
|
||||
// write large numbers of iovs.
|
||||
extern srs_error_t srs_write_large_iovs(ISrsProtocolReadWriter *skt, iovec *iovs, int size, ssize_t *pnwrite = NULL);
|
||||
|
||||
// Get local ip, fill to @param ips
|
||||
struct SrsIPAddress {
|
||||
// The network interface name, such as eth0, en0, eth1.
|
||||
std::string ifname_;
|
||||
|
|
@ -119,26 +117,39 @@ struct SrsIPAddress {
|
|||
// Whether the ip is loopback, such as 127.0.0.1
|
||||
bool is_loopback_;
|
||||
};
|
||||
extern std::vector<SrsIPAddress *> &srs_get_local_ips();
|
||||
|
||||
// Get local public ip, empty string if no public internet address found.
|
||||
extern std::string srs_get_public_internet_address(bool ipv4_only = false);
|
||||
// The utility functions for protocol.
|
||||
class SrsProtocolUtility
|
||||
{
|
||||
public:
|
||||
SrsProtocolUtility();
|
||||
virtual ~SrsProtocolUtility();
|
||||
|
||||
// Detect whether specified device is internet public address.
|
||||
extern bool srs_net_device_is_internet(std::string ifname);
|
||||
extern bool srs_net_device_is_internet(const sockaddr *addr);
|
||||
public:
|
||||
// write large numbers of iovs.
|
||||
virtual srs_error_t write_iovs(ISrsProtocolReadWriter *skt, iovec *iovs, int size, ssize_t *pnwrite = NULL);
|
||||
|
||||
public:
|
||||
// Get local ip, fill to @param ips
|
||||
virtual std::vector<SrsIPAddress *> &local_ips();
|
||||
// Get local public ip, empty string if no public internet address found.
|
||||
virtual std::string public_internet_address(bool ipv4_only = false);
|
||||
// Detect whether specified device is internet public address.
|
||||
virtual bool is_internet(std::string ifname);
|
||||
virtual bool is_internet(const sockaddr *addr);
|
||||
|
||||
public:
|
||||
// Get hostname
|
||||
virtual std::string system_hostname(void);
|
||||
#if defined(__linux__) || defined(SRS_OSX)
|
||||
// Get system uname info.
|
||||
virtual utsname *system_uname();
|
||||
#endif
|
||||
};
|
||||
|
||||
// Get the original ip from query and header by proxy.
|
||||
extern std::string srs_get_original_ip(ISrsHttpMessage *r);
|
||||
|
||||
// Get hostname
|
||||
extern std::string srs_get_system_hostname(void);
|
||||
|
||||
#if defined(__linux__) || defined(SRS_OSX)
|
||||
// Get system uname info.
|
||||
extern utsname *srs_get_system_uname_info();
|
||||
#endif
|
||||
|
||||
class ISrsRequest;
|
||||
|
||||
enum SrtMode {
|
||||
|
|
|
|||
|
|
@ -316,7 +316,8 @@ SrsHttpTestServer::SrsHttpTestServer(string response_body) : response_body_(resp
|
|||
fd_ = NULL;
|
||||
ip_ = "127.0.0.1";
|
||||
// Generate random port in range [30000, 60000]
|
||||
port_ = srs_rand_integer(30000, 60000);
|
||||
SrsRand rand;
|
||||
port_ = rand.integer(30000, 60000);
|
||||
}
|
||||
|
||||
SrsHttpTestServer::~SrsHttpTestServer()
|
||||
|
|
@ -339,7 +340,8 @@ srs_error_t SrsHttpTestServer::start()
|
|||
// If this is not the last retry, generate a new random port and try again
|
||||
if (retry < 2) {
|
||||
srs_freep(err);
|
||||
port_ = srs_rand_integer(30000, 60000);
|
||||
SrsRand rand;
|
||||
port_ = rand.integer(30000, 60000);
|
||||
srs_trace("HTTP test server listen failed on %s:%d, retry %d with new port %d",
|
||||
ip_.c_str(), port_, retry + 1, port_);
|
||||
}
|
||||
|
|
@ -421,7 +423,8 @@ SrsHttpsTestServer::SrsHttpsTestServer(string response_body, string key_file, st
|
|||
fd_ = NULL;
|
||||
ip_ = "127.0.0.1";
|
||||
// Generate random port in range [30000, 60000]
|
||||
port_ = srs_rand_integer(30000, 60000);
|
||||
SrsRand rand;
|
||||
port_ = rand.integer(30000, 60000);
|
||||
}
|
||||
|
||||
SrsHttpsTestServer::~SrsHttpsTestServer()
|
||||
|
|
@ -443,7 +446,8 @@ srs_error_t SrsHttpsTestServer::start()
|
|||
// If this is not the last retry, generate a new random port and try again
|
||||
if (retry < 2) {
|
||||
srs_freep(err);
|
||||
port_ = srs_rand_integer(30000, 60000);
|
||||
SrsRand rand;
|
||||
port_ = rand.integer(30000, 60000);
|
||||
srs_trace("HTTPS test server listen failed on %s:%d, retry %d with new port %d",
|
||||
ip_.c_str(), port_, retry + 1, port_);
|
||||
}
|
||||
|
|
@ -544,7 +548,8 @@ SrsRtmpTestServer::SrsRtmpTestServer(string app, string stream) : app_(app), str
|
|||
enable_publish_ = true;
|
||||
enable_play_ = true;
|
||||
// Generate random port in range [30000, 60000]
|
||||
port_ = srs_rand_integer(30000, 60000);
|
||||
SrsRand rand;
|
||||
port_ = rand.integer(30000, 60000);
|
||||
}
|
||||
|
||||
SrsRtmpTestServer::~SrsRtmpTestServer()
|
||||
|
|
@ -567,7 +572,8 @@ srs_error_t SrsRtmpTestServer::start()
|
|||
// If this is not the last retry, generate a new random port and try again
|
||||
if (retry < 2) {
|
||||
srs_freep(err);
|
||||
port_ = srs_rand_integer(30000, 60000);
|
||||
SrsRand rand;
|
||||
port_ = rand.integer(30000, 60000);
|
||||
srs_trace("RTMP test server listen failed on %s:%d, retry %d with new port %d",
|
||||
ip_.c_str(), port_, retry + 1, port_);
|
||||
}
|
||||
|
|
@ -713,7 +719,8 @@ SrsTestTcpServer::SrsTestTcpServer(string ip)
|
|||
conn_ = NULL;
|
||||
ip_ = ip;
|
||||
// Generate random port in range [30000, 60000]
|
||||
port_ = 30000 + (srs_rand_integer() % (60000 - 30000 + 1));
|
||||
SrsRand rand;
|
||||
port_ = 30000 + (rand.integer() % (60000 - 30000 + 1));
|
||||
}
|
||||
|
||||
SrsTestTcpServer::~SrsTestTcpServer()
|
||||
|
|
@ -863,7 +870,8 @@ SrsUdpTestServer::SrsUdpTestServer(string host)
|
|||
socket_ = NULL;
|
||||
started_ = false;
|
||||
// Generate random port in range [30000, 60000]
|
||||
port_ = 30000 + (srs_rand_integer() % (60000 - 30000 + 1));
|
||||
SrsRand rand;
|
||||
port_ = 30000 + (rand.integer() % (60000 - 30000 + 1));
|
||||
}
|
||||
|
||||
SrsUdpTestServer::~SrsUdpTestServer()
|
||||
|
|
@ -890,7 +898,8 @@ srs_error_t SrsUdpTestServer::start()
|
|||
// If this is not the last retry, generate a new random port and try again
|
||||
if (retry < 2) {
|
||||
srs_freep(err);
|
||||
port_ = 30000 + (srs_rand_integer() % (60000 - 30000 + 1));
|
||||
SrsRand rand;
|
||||
port_ = 30000 + (rand.integer() % (60000 - 30000 + 1));
|
||||
srs_trace("UDP test server listen failed on %s:%d, retry %d with new port %d",
|
||||
host_.c_str(), port_, retry + 1, port_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2170,6 +2170,16 @@ std::string MockAppConfig::get_default_app_name()
|
|||
return "live";
|
||||
}
|
||||
|
||||
void MockAppConfig::subscribe(ISrsReloadHandler *handler)
|
||||
{
|
||||
// Do nothing in mock
|
||||
}
|
||||
|
||||
void MockAppConfig::unsubscribe(ISrsReloadHandler *handler)
|
||||
{
|
||||
// Do nothing in mock
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_vhost_http_hooks_enabled(std::string vhost)
|
||||
{
|
||||
return http_hooks_enabled_;
|
||||
|
|
@ -2390,6 +2400,66 @@ bool MockAppConfig::get_hls_recover(std::string vhost)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_forward_enabled(std::string vhost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SrsConfDirective *MockAppConfig::get_forwards(std::string vhost)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
srs_utime_t MockAppConfig::get_queue_length(std::string vhost)
|
||||
{
|
||||
return 30 * SRS_UTIME_SECONDS;
|
||||
}
|
||||
|
||||
SrsConfDirective *MockAppConfig::get_forward_backend(std::string vhost)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_atc(std::string vhost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int MockAppConfig::get_time_jitter(std::string vhost)
|
||||
{
|
||||
return SrsRtmpJitterAlgorithmFULL;
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_mix_correct(std::string vhost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MockAppConfig::try_annexb_first(std::string vhost)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_vhost_is_edge(std::string vhost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_atc_auto(std::string vhost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_reduce_sequence_header(std::string vhost)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MockAppConfig::get_parse_sps(std::string vhost)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MockAppConfig::set_http_hooks_enabled(bool enabled)
|
||||
{
|
||||
http_hooks_enabled_ = enabled;
|
||||
|
|
@ -2600,6 +2670,26 @@ void MockRtcStatistic::reset()
|
|||
last_client_type_ = SrsRtmpConnUnknown;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcStatistic::on_video_info(ISrsRequest *req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcStatistic::on_audio_info(ISrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate, SrsAudioChannels asound_type, SrsAacObjectType aac_object)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcStatistic::on_stream_publish(ISrsRequest *req, std::string publisher_id)
|
||||
{
|
||||
// Do nothing in mock
|
||||
}
|
||||
|
||||
void MockRtcStatistic::on_stream_close(ISrsRequest *req)
|
||||
{
|
||||
// Do nothing in mock
|
||||
}
|
||||
|
||||
// Unit tests for SrsRtcAsyncCallOnStop::call()
|
||||
VOID TEST(RtcAsyncCallOnStopTest, CallWithHttpHooksDisabled)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -243,6 +243,53 @@ public:
|
|||
// ISrsConfig methods
|
||||
virtual srs_utime_t get_pithy_print();
|
||||
virtual std::string get_default_app_name();
|
||||
virtual void subscribe(ISrsReloadHandler *handler);
|
||||
virtual void unsubscribe(ISrsReloadHandler *handler);
|
||||
virtual srs_error_t reload(SrsReloadState *pstate) { return srs_success; }
|
||||
virtual srs_error_t persistence() { return srs_success; }
|
||||
virtual std::string config() { return ""; }
|
||||
virtual int get_max_connections() { return 1000; }
|
||||
virtual std::string get_pid_file() { return ""; }
|
||||
virtual bool empty_ip_ok() { return false; }
|
||||
virtual bool get_asprocess() { return false; }
|
||||
virtual srs_utime_t get_grace_start_wait() { return 0; }
|
||||
virtual srs_utime_t get_grace_final_wait() { return 0; }
|
||||
virtual bool is_force_grace_quit() { return false; }
|
||||
virtual bool inotify_auto_reload() { return false; }
|
||||
virtual bool auto_reload_for_docker() { return false; }
|
||||
virtual std::vector<std::string> get_listens() { return std::vector<std::string>(); }
|
||||
virtual bool get_rtmps_enabled() { return false; }
|
||||
virtual std::vector<std::string> get_rtmps_listen() { return std::vector<std::string>(); }
|
||||
virtual bool get_http_api_enabled() { return false; }
|
||||
virtual std::vector<std::string> get_http_api_listens() { return std::vector<std::string>(); }
|
||||
virtual bool get_https_api_enabled() { return false; }
|
||||
virtual std::vector<std::string> get_https_api_listens() { return std::vector<std::string>(); }
|
||||
virtual std::string get_https_api_ssl_key() { return ""; }
|
||||
virtual std::string get_https_api_ssl_cert() { return ""; }
|
||||
virtual bool get_http_stream_enabled() { return false; }
|
||||
virtual std::vector<std::string> get_http_stream_listens() { return std::vector<std::string>(); }
|
||||
virtual bool get_https_stream_enabled() { return false; }
|
||||
virtual std::vector<std::string> get_https_stream_listens() { return std::vector<std::string>(); }
|
||||
virtual std::string get_https_stream_ssl_key() { return ""; }
|
||||
virtual std::string get_https_stream_ssl_cert() { return ""; }
|
||||
virtual std::string get_http_stream_dir() { return ""; }
|
||||
virtual bool get_rtc_server_enabled() { return false; }
|
||||
virtual bool get_rtc_server_tcp_enabled() { return false; }
|
||||
virtual std::vector<std::string> get_rtc_server_tcp_listens() { return std::vector<std::string>(); }
|
||||
virtual std::string get_rtc_server_protocol() { return "udp"; }
|
||||
virtual std::vector<std::string> get_rtc_server_listens() { return std::vector<std::string>(); }
|
||||
virtual int get_rtc_server_reuseport() { return 1; }
|
||||
virtual bool get_rtsp_server_enabled() { return false; }
|
||||
virtual std::vector<std::string> get_rtsp_server_listens() { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> get_srt_listens() { return std::vector<std::string>(); }
|
||||
virtual std::vector<SrsConfDirective *> get_stream_casters() { return std::vector<SrsConfDirective *>(); }
|
||||
virtual bool get_stream_caster_enabled(SrsConfDirective *conf) { return false; }
|
||||
virtual std::string get_stream_caster_engine(SrsConfDirective *conf) { return ""; }
|
||||
virtual bool get_exporter_enabled() { return false; }
|
||||
virtual std::string get_exporter_listen() { return ""; }
|
||||
virtual bool get_stats_enabled() { return false; }
|
||||
virtual bool get_heartbeat_enabled() { return false; }
|
||||
virtual srs_utime_t get_heartbeat_interval() { return 0; }
|
||||
// ISrsAppConfig methods
|
||||
virtual bool get_vhost_http_hooks_enabled(std::string vhost);
|
||||
virtual SrsConfDirective *get_vhost_on_stop(std::string vhost);
|
||||
|
|
@ -289,6 +336,18 @@ public:
|
|||
virtual bool get_hls_ctx_enabled(std::string vhost);
|
||||
virtual bool get_hls_ts_ctx_enabled(std::string vhost);
|
||||
virtual bool get_hls_recover(std::string vhost);
|
||||
virtual bool get_forward_enabled(std::string vhost);
|
||||
virtual SrsConfDirective *get_forwards(std::string vhost);
|
||||
virtual srs_utime_t get_queue_length(std::string vhost);
|
||||
virtual SrsConfDirective *get_forward_backend(std::string vhost);
|
||||
virtual bool get_atc(std::string vhost);
|
||||
virtual int get_time_jitter(std::string vhost);
|
||||
virtual bool get_mix_correct(std::string vhost);
|
||||
virtual bool try_annexb_first(std::string vhost);
|
||||
virtual bool get_vhost_is_edge(std::string vhost);
|
||||
virtual bool get_atc_auto(std::string vhost);
|
||||
virtual bool get_reduce_sequence_header(std::string vhost);
|
||||
virtual bool get_parse_sps(std::string vhost);
|
||||
void set_http_hooks_enabled(bool enabled);
|
||||
void set_on_stop_urls(const std::vector<std::string> &urls);
|
||||
void clear_on_stop_directive();
|
||||
|
|
@ -358,6 +417,10 @@ public:
|
|||
virtual ~MockRtcStatistic();
|
||||
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);
|
||||
void set_on_client_error(srs_error_t err);
|
||||
void reset();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -932,12 +932,12 @@ VOID TEST(HlsMuxerTest, SegmentOverflowAndPureAudio)
|
|||
// Set up required fields
|
||||
MockHlsRequest mock_request("__defaultVhost__", "live", "test");
|
||||
muxer->req_ = &mock_request;
|
||||
muxer->hls_fragment_ = 10 * SRS_UTIME_SECONDS; // 10 seconds fragment
|
||||
muxer->hls_aof_ratio_ = 2.0; // Absolutely overflow at 2x fragment duration
|
||||
muxer->hls_fragment_ = 10 * SRS_UTIME_SECONDS; // 10 seconds fragment
|
||||
muxer->hls_aof_ratio_ = 2.0; // Absolutely overflow at 2x fragment duration
|
||||
muxer->hls_wait_keyframe_ = true;
|
||||
muxer->hls_ts_floor_ = false; // Disable floor for simpler testing
|
||||
muxer->hls_ts_floor_ = false; // Disable floor for simpler testing
|
||||
muxer->deviation_ts_ = 0;
|
||||
muxer->max_td_ = 10 * SRS_UTIME_SECONDS; // Same as fragment for simplicity
|
||||
muxer->max_td_ = 10 * SRS_UTIME_SECONDS; // Same as fragment for simplicity
|
||||
muxer->latest_acodec_ = SrsAudioCodecIdAAC;
|
||||
muxer->latest_vcodec_ = SrsVideoCodecIdAVC;
|
||||
muxer->writer_ = new MockSrsFileWriter();
|
||||
|
|
@ -953,22 +953,22 @@ VOID TEST(HlsMuxerTest, SegmentOverflowAndPureAudio)
|
|||
|
||||
// Test is_segment_overflow: Segment too small (< 2 * SRS_HLS_SEGMENT_MIN_DURATION)
|
||||
segment->append(0);
|
||||
segment->append(50); // 50ms duration, too small
|
||||
segment->append(50); // 50ms duration, too small
|
||||
EXPECT_FALSE(muxer->is_segment_overflow());
|
||||
|
||||
// Test is_segment_overflow: Segment duration just below threshold
|
||||
segment->append(0);
|
||||
segment->append(9000); // 9 seconds, below 10 seconds threshold
|
||||
segment->append(9000); // 9 seconds, below 10 seconds threshold
|
||||
EXPECT_FALSE(muxer->is_segment_overflow());
|
||||
|
||||
// Test is_segment_overflow: Segment duration at threshold
|
||||
segment->append(0);
|
||||
segment->append(10000); // 10 seconds, at threshold
|
||||
segment->append(10000); // 10 seconds, at threshold
|
||||
EXPECT_TRUE(muxer->is_segment_overflow());
|
||||
|
||||
// Test is_segment_overflow: Segment duration above threshold
|
||||
segment->append(0);
|
||||
segment->append(12000); // 12 seconds, above threshold
|
||||
segment->append(12000); // 12 seconds, above threshold
|
||||
EXPECT_TRUE(muxer->is_segment_overflow());
|
||||
|
||||
// Test wait_keyframe
|
||||
|
|
@ -984,22 +984,22 @@ VOID TEST(HlsMuxerTest, SegmentOverflowAndPureAudio)
|
|||
|
||||
// Test is_segment_absolutely_overflow: Segment too small
|
||||
segment->append(0);
|
||||
segment->append(50); // 50ms duration, too small
|
||||
segment->append(50); // 50ms duration, too small
|
||||
EXPECT_FALSE(muxer->is_segment_absolutely_overflow());
|
||||
|
||||
// Test is_segment_absolutely_overflow: Below absolute overflow threshold (2x fragment)
|
||||
segment->append(0);
|
||||
segment->append(15000); // 15 seconds, below 20 seconds (2x 10s)
|
||||
segment->append(15000); // 15 seconds, below 20 seconds (2x 10s)
|
||||
EXPECT_FALSE(muxer->is_segment_absolutely_overflow());
|
||||
|
||||
// Test is_segment_absolutely_overflow: At absolute overflow threshold
|
||||
segment->append(0);
|
||||
segment->append(20000); // 20 seconds, at 2x threshold
|
||||
segment->append(20000); // 20 seconds, at 2x threshold
|
||||
EXPECT_TRUE(muxer->is_segment_absolutely_overflow());
|
||||
|
||||
// Test is_segment_absolutely_overflow: Above absolute overflow threshold
|
||||
segment->append(0);
|
||||
segment->append(25000); // 25 seconds, above 2x threshold
|
||||
segment->append(25000); // 25 seconds, above 2x threshold
|
||||
EXPECT_TRUE(muxer->is_segment_absolutely_overflow());
|
||||
|
||||
// Test pure_audio: With video codec enabled (not pure audio)
|
||||
|
|
@ -1121,8 +1121,16 @@ VOID TEST(AppHlsTest, HlsControllerWriteAudioTypicalScenario)
|
|||
|
||||
// Create audio payload (AAC raw data) - must be heap allocated for wrap()
|
||||
char *audio_data = new char[10];
|
||||
audio_data[0] = 0x01; audio_data[1] = 0x02; audio_data[2] = 0x03; audio_data[3] = 0x04; audio_data[4] = 0x05;
|
||||
audio_data[5] = 0x06; audio_data[6] = 0x07; audio_data[7] = 0x08; audio_data[8] = 0x09; audio_data[9] = 0x0a;
|
||||
audio_data[0] = 0x01;
|
||||
audio_data[1] = 0x02;
|
||||
audio_data[2] = 0x03;
|
||||
audio_data[3] = 0x04;
|
||||
audio_data[4] = 0x05;
|
||||
audio_data[5] = 0x06;
|
||||
audio_data[6] = 0x07;
|
||||
audio_data[7] = 0x08;
|
||||
audio_data[8] = 0x09;
|
||||
audio_data[9] = 0x0a;
|
||||
audio_packet->wrap(audio_data, 10);
|
||||
|
||||
// Add sample to format->audio_
|
||||
|
|
@ -1150,8 +1158,16 @@ VOID TEST(AppHlsTest, HlsControllerWriteAudioTypicalScenario)
|
|||
|
||||
// Create audio payload - must be heap allocated for wrap()
|
||||
char *audio_data2 = new char[10];
|
||||
audio_data2[0] = 0x0b; audio_data2[1] = 0x0c; audio_data2[2] = 0x0d; audio_data2[3] = 0x0e; audio_data2[4] = 0x0f;
|
||||
audio_data2[5] = 0x10; audio_data2[6] = 0x11; audio_data2[7] = 0x12; audio_data2[8] = 0x13; audio_data2[9] = 0x14;
|
||||
audio_data2[0] = 0x0b;
|
||||
audio_data2[1] = 0x0c;
|
||||
audio_data2[2] = 0x0d;
|
||||
audio_data2[3] = 0x0e;
|
||||
audio_data2[4] = 0x0f;
|
||||
audio_data2[5] = 0x10;
|
||||
audio_data2[6] = 0x11;
|
||||
audio_data2[7] = 0x12;
|
||||
audio_data2[8] = 0x13;
|
||||
audio_data2[9] = 0x14;
|
||||
audio_packet2->wrap(audio_data2, 10);
|
||||
|
||||
format->audio_->nb_samples_ = 1;
|
||||
|
|
@ -1328,19 +1344,19 @@ VOID TEST(AppHlsTest, HlsMuxerDoRefreshM3u8TypicalScenario)
|
|||
segment1->sequence_no_ = 100;
|
||||
segment1->uri_ = "stream1-100.ts";
|
||||
segment1->append(0);
|
||||
segment1->append(10000); // 10 seconds duration
|
||||
segment1->append(10000); // 10 seconds duration
|
||||
|
||||
SrsHlsSegment *segment2 = new SrsHlsSegment(context.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC, fw2.get());
|
||||
segment2->sequence_no_ = 101;
|
||||
segment2->uri_ = "stream1-101.ts";
|
||||
segment2->append(10000);
|
||||
segment2->append(20000); // 10 seconds duration
|
||||
segment2->append(20000); // 10 seconds duration
|
||||
|
||||
SrsHlsSegment *segment3 = new SrsHlsSegment(context.get(), SrsAudioCodecIdAAC, SrsVideoCodecIdAVC, fw3.get());
|
||||
segment3->sequence_no_ = 102;
|
||||
segment3->uri_ = "stream1-102.ts";
|
||||
segment3->append(20000);
|
||||
segment3->append(28000); // 8 seconds duration
|
||||
segment3->append(28000); // 8 seconds duration
|
||||
|
||||
// Add segments to the fragment window (ownership transferred to segments_)
|
||||
muxer->segments_->append(segment1);
|
||||
|
|
@ -1406,7 +1422,7 @@ VOID TEST(AppHlsTest, HlsControllerSelectionTypicalScenario)
|
|||
segment->sequence_no_ = 42;
|
||||
segment->uri_ = "stream1-42.ts";
|
||||
segment->append(0);
|
||||
segment->append(10000); // 10 seconds duration in milliseconds
|
||||
segment->append(10000); // 10 seconds duration in milliseconds
|
||||
|
||||
// Set the current segment in the muxer
|
||||
controller->muxer_->current_ = segment;
|
||||
|
|
@ -1625,7 +1641,6 @@ VOID TEST(AppHlsTest, HlsControllerWriteVideoTypicalScenario)
|
|||
EXPECT_EQ(SrsVideoCodecIdAVC, controller->muxer_->latest_vcodec());
|
||||
}
|
||||
|
||||
|
||||
// Unit test for SrsHlsController::reap_segment typical scenario
|
||||
VOID TEST(AppHlsTest, HlsControllerReapSegmentTypicalScenario)
|
||||
{
|
||||
|
|
@ -1937,8 +1952,16 @@ VOID TEST(AppHlsTest, HlsOnAudioTypicalScenario)
|
|||
|
||||
// Create audio payload (AAC raw data) - must be heap allocated for wrap()
|
||||
char *audio_data = new char[10];
|
||||
audio_data[0] = 0x01; audio_data[1] = 0x02; audio_data[2] = 0x03; audio_data[3] = 0x04; audio_data[4] = 0x05;
|
||||
audio_data[5] = 0x06; audio_data[6] = 0x07; audio_data[7] = 0x08; audio_data[8] = 0x09; audio_data[9] = 0x0a;
|
||||
audio_data[0] = 0x01;
|
||||
audio_data[1] = 0x02;
|
||||
audio_data[2] = 0x03;
|
||||
audio_data[3] = 0x04;
|
||||
audio_data[4] = 0x05;
|
||||
audio_data[5] = 0x06;
|
||||
audio_data[6] = 0x07;
|
||||
audio_data[7] = 0x08;
|
||||
audio_data[8] = 0x09;
|
||||
audio_data[9] = 0x0a;
|
||||
audio_packet->wrap(audio_data, 10);
|
||||
|
||||
// Add sample to format->audio_
|
||||
|
|
|
|||
3310
trunk/src/utest/srs_utest_app9.cpp
Normal file
3310
trunk/src/utest/srs_utest_app9.cpp
Normal file
File diff suppressed because it is too large
Load Diff
333
trunk/src/utest/srs_utest_app9.hpp
Normal file
333
trunk/src/utest/srs_utest_app9.hpp
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
//
|
||||
// Copyright (c) 2013-2025 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_UTEST_APP9_HPP
|
||||
#define SRS_UTEST_APP9_HPP
|
||||
|
||||
/*
|
||||
#include <srs_utest_app9.hpp>
|
||||
*/
|
||||
#include <srs_utest.hpp>
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_dash.hpp>
|
||||
#include <srs_app_dvr.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_forward.hpp>
|
||||
#include <srs_app_hds.hpp>
|
||||
#include <srs_app_hls.hpp>
|
||||
#include <srs_app_ng_exec.hpp>
|
||||
#include <srs_app_rtmp_source.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
#include <srs_kernel_packet.hpp>
|
||||
#include <srs_protocol_rtmp_stack.hpp>
|
||||
#include <srs_utest_app6.hpp>
|
||||
#ifdef SRS_HDS
|
||||
#include <srs_app_hds.hpp>
|
||||
#endif
|
||||
#include <srs_app_factory.hpp>
|
||||
|
||||
// Mock media packet for testing jitter correction
|
||||
class MockMediaPacketForJitter : public SrsMediaPacket
|
||||
{
|
||||
public:
|
||||
MockMediaPacketForJitter(int64_t timestamp, bool is_av);
|
||||
virtual ~MockMediaPacketForJitter();
|
||||
};
|
||||
|
||||
// Mock live source for testing message queue dump_packets
|
||||
class MockLiveSourceForQueue : public SrsLiveSource
|
||||
{
|
||||
public:
|
||||
MockLiveSourceForQueue();
|
||||
virtual ~MockLiveSourceForQueue();
|
||||
virtual void on_consumer_destroy(SrsLiveConsumer *consumer);
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> wrapper, ISrsRequest *r);
|
||||
virtual void update_auth(ISrsRequest *r);
|
||||
};
|
||||
|
||||
// Mock live consumer for testing message queue dump_packets
|
||||
class MockLiveConsumerForQueue : public SrsLiveConsumer
|
||||
{
|
||||
public:
|
||||
int enqueue_count_;
|
||||
std::vector<int64_t> enqueued_timestamps_;
|
||||
|
||||
public:
|
||||
MockLiveConsumerForQueue(MockLiveSourceForQueue *source);
|
||||
virtual ~MockLiveConsumerForQueue();
|
||||
virtual srs_error_t enqueue(SrsMediaPacket *shared_msg, bool atc, SrsRtmpJitterAlgorithm ag);
|
||||
};
|
||||
|
||||
// Mock media packet for testing gop cache with H.264 video
|
||||
class MockH264VideoPacket : public SrsMediaPacket
|
||||
{
|
||||
public:
|
||||
MockH264VideoPacket(bool is_keyframe);
|
||||
virtual ~MockH264VideoPacket();
|
||||
};
|
||||
|
||||
// Mock media packet for testing gop cache with audio
|
||||
class MockAudioPacket : public SrsMediaPacket
|
||||
{
|
||||
public:
|
||||
MockAudioPacket();
|
||||
virtual ~MockAudioPacket();
|
||||
};
|
||||
|
||||
// Mock ISrsHls for testing SrsOriginHub::initialize
|
||||
class MockHlsForOriginHub : public ISrsHls
|
||||
{
|
||||
public:
|
||||
int initialize_count_;
|
||||
srs_error_t initialize_error_;
|
||||
srs_utime_t cleanup_delay_;
|
||||
int on_audio_count_;
|
||||
int on_video_count_;
|
||||
|
||||
public:
|
||||
MockHlsForOriginHub();
|
||||
virtual ~MockHlsForOriginHub();
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
|
||||
virtual srs_error_t on_publish();
|
||||
virtual void on_unpublish();
|
||||
virtual void dispose();
|
||||
virtual srs_error_t cycle();
|
||||
virtual srs_utime_t cleanup_delay();
|
||||
};
|
||||
|
||||
// Mock ISrsDash for testing SrsOriginHub::initialize
|
||||
class MockDashForOriginHub : public ISrsDash
|
||||
{
|
||||
public:
|
||||
int initialize_count_;
|
||||
srs_error_t initialize_error_;
|
||||
srs_utime_t cleanup_delay_;
|
||||
int on_audio_count_;
|
||||
int on_video_count_;
|
||||
|
||||
public:
|
||||
MockDashForOriginHub();
|
||||
virtual ~MockDashForOriginHub();
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
|
||||
virtual srs_error_t on_publish();
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
|
||||
virtual void on_unpublish();
|
||||
virtual void dispose();
|
||||
virtual srs_error_t cycle();
|
||||
virtual srs_utime_t cleanup_delay();
|
||||
};
|
||||
|
||||
// Mock ISrsDvr for testing SrsOriginHub::initialize
|
||||
class MockDvrForOriginHub : public ISrsDvr
|
||||
{
|
||||
public:
|
||||
int initialize_count_;
|
||||
srs_error_t initialize_error_;
|
||||
int on_meta_data_count_;
|
||||
int on_audio_count_;
|
||||
int on_video_count_;
|
||||
|
||||
public:
|
||||
MockDvrForOriginHub();
|
||||
virtual ~MockDvrForOriginHub();
|
||||
virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
|
||||
virtual srs_error_t on_publish(ISrsRequest *r);
|
||||
virtual void on_unpublish();
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *metadata);
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio, SrsFormat *format);
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, SrsFormat *format);
|
||||
};
|
||||
|
||||
// Mock ISrsForwarder for testing SrsOriginHub::on_meta_data
|
||||
class MockForwarderForOriginHub : public ISrsForwarder
|
||||
{
|
||||
public:
|
||||
int on_meta_data_count_;
|
||||
int on_audio_count_;
|
||||
int on_video_count_;
|
||||
|
||||
public:
|
||||
MockForwarderForOriginHub();
|
||||
virtual ~MockForwarderForOriginHub();
|
||||
virtual srs_error_t initialize(ISrsRequest *r, std::string ep);
|
||||
virtual void set_queue_size(srs_utime_t queue_size);
|
||||
virtual srs_error_t on_publish();
|
||||
virtual void on_unpublish();
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata);
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio);
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video);
|
||||
};
|
||||
|
||||
// Mock ISrsLiveSource for testing SrsOriginHub::on_audio
|
||||
class MockLiveSourceForOriginHub : public ISrsLiveSource
|
||||
{
|
||||
private:
|
||||
SrsRtmpFormat *format_;
|
||||
SrsMetaCache *meta_;
|
||||
|
||||
public:
|
||||
MockLiveSourceForOriginHub();
|
||||
virtual ~MockLiveSourceForOriginHub();
|
||||
virtual void on_consumer_destroy(SrsLiveConsumer *consumer);
|
||||
virtual SrsContextId source_id();
|
||||
virtual SrsContextId pre_source_id();
|
||||
virtual SrsMetaCache *meta();
|
||||
virtual SrsRtmpFormat *format();
|
||||
};
|
||||
|
||||
// Mock ISrsStatistic for testing SrsOriginHub::on_video
|
||||
class MockStatisticForOriginHub : public ISrsStatistic
|
||||
{
|
||||
public:
|
||||
int on_video_info_count_;
|
||||
int on_audio_info_count_;
|
||||
|
||||
public:
|
||||
MockStatisticForOriginHub();
|
||||
virtual ~MockStatisticForOriginHub();
|
||||
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);
|
||||
};
|
||||
|
||||
// Mock ISrsNgExec for testing SrsOriginHub::on_publish
|
||||
class MockNgExecForOriginHub : public ISrsNgExec
|
||||
{
|
||||
public:
|
||||
int on_publish_count_;
|
||||
|
||||
public:
|
||||
MockNgExecForOriginHub();
|
||||
virtual ~MockNgExecForOriginHub();
|
||||
virtual srs_error_t on_publish(ISrsRequest *req);
|
||||
virtual void on_unpublish();
|
||||
virtual srs_error_t cycle();
|
||||
};
|
||||
|
||||
#ifdef SRS_HDS
|
||||
// Mock ISrsHds for testing SrsOriginHub::on_publish
|
||||
class MockHdsForOriginHub : public ISrsHds
|
||||
{
|
||||
public:
|
||||
int on_publish_count_;
|
||||
|
||||
public:
|
||||
MockHdsForOriginHub();
|
||||
virtual ~MockHdsForOriginHub();
|
||||
virtual srs_error_t on_publish(ISrsRequest *req);
|
||||
virtual srs_error_t on_unpublish();
|
||||
virtual srs_error_t on_video(SrsMediaPacket *msg);
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *msg);
|
||||
};
|
||||
#endif
|
||||
|
||||
// Mock config for testing SrsOriginHub::create_forwarders
|
||||
class MockAppConfigForForwarder : public MockAppConfig
|
||||
{
|
||||
public:
|
||||
SrsConfDirective *forwards_directive_;
|
||||
SrsConfDirective *backend_directive_;
|
||||
|
||||
public:
|
||||
MockAppConfigForForwarder();
|
||||
virtual ~MockAppConfigForForwarder();
|
||||
virtual bool get_forward_enabled(std::string vhost);
|
||||
virtual SrsConfDirective *get_forwards(std::string vhost);
|
||||
virtual SrsConfDirective *get_forward_backend(std::string vhost);
|
||||
void set_forward_destinations(const std::vector<std::string> &destinations);
|
||||
void set_forward_backend(const std::string &backend_url);
|
||||
};
|
||||
|
||||
// Mock HTTP hooks for testing SrsOriginHub::create_backend_forwarders
|
||||
class MockHttpHooksForBackend : public MockHttpHooks
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> backend_urls_;
|
||||
int on_forward_backend_count_;
|
||||
|
||||
public:
|
||||
MockHttpHooksForBackend();
|
||||
virtual ~MockHttpHooksForBackend();
|
||||
virtual srs_error_t on_forward_backend(std::string url, ISrsRequest *req, std::vector<std::string> &rtmp_urls);
|
||||
void set_backend_urls(const std::vector<std::string> &urls);
|
||||
};
|
||||
|
||||
// Mock ISrsHourGlass for testing SrsLiveSourceManager::setup_ticks
|
||||
class MockHourGlassForSourceManager : public ISrsHourGlass
|
||||
{
|
||||
public:
|
||||
int tick_event_;
|
||||
srs_utime_t tick_interval_;
|
||||
int tick_count_;
|
||||
int start_count_;
|
||||
srs_error_t tick_error_;
|
||||
srs_error_t start_error_;
|
||||
|
||||
public:
|
||||
MockHourGlassForSourceManager();
|
||||
virtual ~MockHourGlassForSourceManager();
|
||||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
virtual srs_error_t tick(srs_utime_t interval);
|
||||
virtual srs_error_t tick(int event, srs_utime_t interval);
|
||||
virtual void untick(int event);
|
||||
};
|
||||
|
||||
// Mock SrsAppFactory for testing SrsLiveSourceManager::fetch_or_create
|
||||
class MockAppFactoryForSourceManager : public SrsAppFactory
|
||||
{
|
||||
public:
|
||||
int create_live_source_count_;
|
||||
|
||||
public:
|
||||
MockAppFactoryForSourceManager();
|
||||
virtual ~MockAppFactoryForSourceManager();
|
||||
virtual SrsLiveSource *create_live_source();
|
||||
};
|
||||
|
||||
// Mock ISrsOriginHub for testing SrsLiveSource::initialize
|
||||
class MockOriginHubForLiveSource : public ISrsOriginHub
|
||||
{
|
||||
public:
|
||||
int initialize_count_;
|
||||
srs_error_t initialize_error_;
|
||||
|
||||
public:
|
||||
MockOriginHubForLiveSource();
|
||||
virtual ~MockOriginHubForLiveSource();
|
||||
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, ISrsRequest *r);
|
||||
virtual void dispose();
|
||||
virtual srs_error_t cycle();
|
||||
virtual bool active();
|
||||
virtual srs_utime_t cleanup_delay();
|
||||
virtual srs_error_t on_meta_data(SrsMediaPacket *shared_metadata, SrsOnMetaDataPacket *packet);
|
||||
virtual srs_error_t on_audio(SrsMediaPacket *shared_audio);
|
||||
virtual srs_error_t on_video(SrsMediaPacket *shared_video, bool is_sequence_header);
|
||||
virtual srs_error_t on_publish();
|
||||
virtual void on_unpublish();
|
||||
};
|
||||
|
||||
// Mock SrsAppFactory for testing SrsLiveSource::initialize
|
||||
class MockAppFactoryForLiveSource : public SrsAppFactory
|
||||
{
|
||||
public:
|
||||
MockOriginHubForLiveSource *mock_hub_;
|
||||
int create_origin_hub_count_;
|
||||
|
||||
public:
|
||||
MockAppFactoryForLiveSource();
|
||||
virtual ~MockAppFactoryForLiveSource();
|
||||
virtual ISrsOriginHub *create_origin_hub();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -202,12 +202,28 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool _mock_srs_path_always_exists(std::string /*path*/)
|
||||
MockSrsPathAlwaysExists::MockSrsPathAlwaysExists()
|
||||
{
|
||||
}
|
||||
|
||||
MockSrsPathAlwaysExists::~MockSrsPathAlwaysExists()
|
||||
{
|
||||
}
|
||||
|
||||
bool MockSrsPathAlwaysExists::exists(std::string /*path*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _mock_srs_path_not_exists(std::string /*path*/)
|
||||
MockSrsPathNotExists::MockSrsPathNotExists()
|
||||
{
|
||||
}
|
||||
|
||||
MockSrsPathNotExists::~MockSrsPathNotExists()
|
||||
{
|
||||
}
|
||||
|
||||
bool MockSrsPathNotExists::exists(std::string /*path*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1463,7 +1479,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory(fs));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1486,7 +1502,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1503,7 +1519,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1521,7 +1537,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1539,7 +1555,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1557,7 +1573,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1575,7 +1591,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1597,7 +1613,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("livestream-13.ts"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1619,7 +1635,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("livestream-13.m4s"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1641,7 +1657,7 @@ VOID TEST(ProtocolHTTPTest, VodStreamHandlers)
|
|||
|
||||
SrsVodStream h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("init.mp4"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1667,7 +1683,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1684,7 +1700,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1701,7 +1717,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1718,7 +1734,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1735,7 +1751,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1752,7 +1768,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1769,7 +1785,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_always_exists);
|
||||
h.set_path(new MockSrsPathAlwaysExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
@ -1786,7 +1802,7 @@ VOID TEST(ProtocolHTTPTest, BasicHandlers)
|
|||
|
||||
SrsHttpFileServer h("/tmp");
|
||||
h.set_fs_factory(new MockFileReaderFactory("Hello, world!"));
|
||||
h.set_path_check(_mock_srs_path_not_exists);
|
||||
h.set_path(new MockSrsPathNotExists());
|
||||
h.entry = &e;
|
||||
|
||||
MockResponseWriter w;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,28 @@ string mock_http_response2(int status, string content);
|
|||
string mock_http_response4(int status, string content);
|
||||
bool is_string_contain(string substr, string str);
|
||||
|
||||
// Mock SrsPath that always returns true for exists()
|
||||
class MockSrsPathAlwaysExists : public SrsPath
|
||||
{
|
||||
public:
|
||||
MockSrsPathAlwaysExists();
|
||||
virtual ~MockSrsPathAlwaysExists();
|
||||
|
||||
public:
|
||||
virtual bool exists(std::string path);
|
||||
};
|
||||
|
||||
// Mock SrsPath that always returns false for exists()
|
||||
class MockSrsPathNotExists : public SrsPath
|
||||
{
|
||||
public:
|
||||
MockSrsPathNotExists();
|
||||
virtual ~MockSrsPathNotExists();
|
||||
|
||||
public:
|
||||
virtual bool exists(std::string path);
|
||||
};
|
||||
|
||||
#define __MOCK_HTTP_EXPECT_STREQ(status, text, w) \
|
||||
EXPECT_STREQ(mock_http_response(status, text).c_str(), HELPER_BUFFER2STR(&w.io.out_buffer).c_str())
|
||||
|
||||
|
|
|
|||
|
|
@ -2861,29 +2861,33 @@ VOID TEST(KernelUtility, BytesUtils)
|
|||
VOID TEST(KernelUtility, PathUtils)
|
||||
{
|
||||
if (true) {
|
||||
EXPECT_TRUE("./" == srs_path_filepath_dir(""));
|
||||
EXPECT_TRUE("/" == srs_path_filepath_dir("/"));
|
||||
EXPECT_TRUE("/" == srs_path_filepath_dir("//"));
|
||||
EXPECT_TRUE("/" == srs_path_filepath_dir("/stream"));
|
||||
EXPECT_TRUE("live" == srs_path_filepath_dir("live/stream"));
|
||||
SrsPath path;
|
||||
EXPECT_TRUE("./" == path.filepath_dir(""));
|
||||
EXPECT_TRUE("/" == path.filepath_dir("/"));
|
||||
EXPECT_TRUE("/" == path.filepath_dir("//"));
|
||||
EXPECT_TRUE("/" == path.filepath_dir("/stream"));
|
||||
EXPECT_TRUE("live" == path.filepath_dir("live/stream"));
|
||||
}
|
||||
|
||||
if (true) {
|
||||
EXPECT_TRUE("" == srs_path_filepath_base(""));
|
||||
EXPECT_TRUE("/" == srs_path_filepath_base("/"));
|
||||
EXPECT_TRUE("stream" == srs_path_filepath_base("/stream"));
|
||||
EXPECT_TRUE("stream" == srs_path_filepath_base("live/stream"));
|
||||
EXPECT_TRUE("stream.flv" == srs_path_filepath_base("live/stream.flv"));
|
||||
SrsPath path;
|
||||
EXPECT_TRUE("" == path.filepath_base(""));
|
||||
EXPECT_TRUE("/" == path.filepath_base("/"));
|
||||
EXPECT_TRUE("stream" == path.filepath_base("/stream"));
|
||||
EXPECT_TRUE("stream" == path.filepath_base("live/stream"));
|
||||
EXPECT_TRUE("stream.flv" == path.filepath_base("live/stream.flv"));
|
||||
}
|
||||
|
||||
if (true) {
|
||||
EXPECT_TRUE("" == srs_path_filepath_filename(""));
|
||||
EXPECT_TRUE("stream" == srs_path_filepath_filename("stream.flv"));
|
||||
SrsPath path;
|
||||
EXPECT_TRUE("" == path.filepath_filename(""));
|
||||
EXPECT_TRUE("stream" == path.filepath_filename("stream.flv"));
|
||||
}
|
||||
|
||||
if (true) {
|
||||
EXPECT_TRUE("" == srs_path_filepath_ext(""));
|
||||
EXPECT_TRUE(".flv" == srs_path_filepath_ext("stream.flv"));
|
||||
SrsPath path;
|
||||
EXPECT_TRUE("" == path.filepath_ext(""));
|
||||
EXPECT_TRUE(".flv" == path.filepath_ext("stream.flv"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5551,7 +5555,8 @@ MockFileRemover::~MockFileRemover()
|
|||
return;
|
||||
if (path_.find(".log") == string::npos)
|
||||
return;
|
||||
::unlink(path_.c_str());
|
||||
SrsPath path;
|
||||
path.unlink(path_);
|
||||
}
|
||||
|
||||
VOID TEST(KernelFileTest, ReadWriteCase)
|
||||
|
|
@ -6164,8 +6169,9 @@ VOID TEST(KernelUtilityTest, CoverTimeUtilityAll)
|
|||
}
|
||||
|
||||
if (true) {
|
||||
EXPECT_TRUE(srs_path_exists("."));
|
||||
HELPER_EXPECT_SUCCESS(srs_os_mkdir_all("."));
|
||||
SrsPath path;
|
||||
EXPECT_TRUE(path.exists("."));
|
||||
HELPER_EXPECT_SUCCESS(path.mkdir_all("."));
|
||||
}
|
||||
|
||||
if (true) {
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ void MockSrsFastTimer::clear()
|
|||
}
|
||||
|
||||
// Tests for srs_kernel_hourglass.hpp
|
||||
VOID TEST(KernelHourglassTest, ISrsHourGlassInterface)
|
||||
VOID TEST(KernelHourglassTest, ISrsHourGlassHandlerInterface)
|
||||
{
|
||||
MockSrsHourGlass handler;
|
||||
|
||||
|
|
@ -4001,7 +4001,7 @@ VOID TEST(KernelHourglassTest, SrsHourGlass_untick)
|
|||
{
|
||||
// Test SrsHourGlass::untick method
|
||||
// Create a mock handler for the hourglass
|
||||
class MockHourGlassHandler : public ISrsHourGlass
|
||||
class MockHourGlassHandler : public ISrsHourGlassHandler
|
||||
{
|
||||
public:
|
||||
srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick)
|
||||
|
|
@ -4037,7 +4037,7 @@ VOID TEST(KernelHourglassTest, SrsHourGlass_stop)
|
|||
{
|
||||
// Test SrsHourGlass::stop method
|
||||
// Create a mock handler for the hourglass
|
||||
class MockHourGlassHandler : public ISrsHourGlass
|
||||
class MockHourGlassHandler : public ISrsHourGlassHandler
|
||||
{
|
||||
public:
|
||||
srs_error_t notify(int event, srs_utime_t interval, srs_utime_t tick)
|
||||
|
|
@ -4141,7 +4141,8 @@ VOID TEST(KernelTSTest, SrsEncFileWriter_write)
|
|||
writer.close();
|
||||
|
||||
// Clean up temp file
|
||||
unlink(temp_file.c_str());
|
||||
SrsPath path;
|
||||
path.unlink(temp_file);
|
||||
}
|
||||
|
||||
VOID TEST(KernelTSTest, SrsEncFileWriter_close)
|
||||
|
|
@ -4184,7 +4185,8 @@ VOID TEST(KernelTSTest, SrsEncFileWriter_close)
|
|||
writer.close();
|
||||
|
||||
// Clean up
|
||||
unlink(temp_file.c_str());
|
||||
SrsPath path;
|
||||
path.unlink(temp_file);
|
||||
}
|
||||
|
||||
VOID TEST(KernelTSTest, SrsTsMessageCache_do_cache_mp3)
|
||||
|
|
@ -4286,7 +4288,8 @@ VOID TEST(KernelTSTest, SrsTsTransmuxer_set_has_video)
|
|||
srs_freep(err);
|
||||
}
|
||||
writer.close();
|
||||
unlink(temp_file.c_str());
|
||||
SrsPath path;
|
||||
path.unlink(temp_file);
|
||||
} else {
|
||||
srs_freep(err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public:
|
|||
};
|
||||
|
||||
// Mock classes for hourglass testing
|
||||
class MockSrsHourGlass : public ISrsHourGlass
|
||||
class MockSrsHourGlass : public ISrsHourGlassHandler
|
||||
{
|
||||
public:
|
||||
std::vector<int> events_;
|
||||
|
|
|
|||
|
|
@ -4630,8 +4630,9 @@ VOID TEST(ProtocolKbpsTest, WriteLargeIOVs)
|
|||
iovs[0].iov_len = 5;
|
||||
|
||||
MockBufferIO io;
|
||||
SrsProtocolUtility utility;
|
||||
ssize_t nn = 0;
|
||||
HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, 1, &nn));
|
||||
HELPER_EXPECT_SUCCESS(utility.write_iovs(&io, iovs, 1, &nn));
|
||||
EXPECT_EQ(5, nn);
|
||||
EXPECT_EQ(5, io.sbytes);
|
||||
}
|
||||
|
|
@ -4645,8 +4646,9 @@ VOID TEST(ProtocolKbpsTest, WriteLargeIOVs)
|
|||
}
|
||||
|
||||
MockBufferIO io;
|
||||
SrsProtocolUtility utility;
|
||||
ssize_t nn = 0;
|
||||
HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn));
|
||||
HELPER_EXPECT_SUCCESS(utility.write_iovs(&io, iovs, nn_iovs, &nn));
|
||||
EXPECT_EQ(5 * nn_iovs, nn);
|
||||
EXPECT_EQ(5 * nn_iovs, io.sbytes);
|
||||
}
|
||||
|
|
@ -4660,8 +4662,9 @@ VOID TEST(ProtocolKbpsTest, WriteLargeIOVs)
|
|||
}
|
||||
|
||||
MockBufferIO io;
|
||||
SrsProtocolUtility utility;
|
||||
ssize_t nn = 0;
|
||||
HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn));
|
||||
HELPER_EXPECT_SUCCESS(utility.write_iovs(&io, iovs, nn_iovs, &nn));
|
||||
EXPECT_EQ(5 * nn_iovs, nn);
|
||||
EXPECT_EQ(5 * nn_iovs, io.sbytes);
|
||||
}
|
||||
|
|
@ -4675,8 +4678,9 @@ VOID TEST(ProtocolKbpsTest, WriteLargeIOVs)
|
|||
}
|
||||
|
||||
MockBufferIO io;
|
||||
SrsProtocolUtility utility;
|
||||
ssize_t nn = 0;
|
||||
HELPER_EXPECT_SUCCESS(srs_write_large_iovs(&io, iovs, nn_iovs, &nn));
|
||||
HELPER_EXPECT_SUCCESS(utility.write_iovs(&io, iovs, nn_iovs, &nn));
|
||||
EXPECT_EQ(5 * nn_iovs, nn);
|
||||
EXPECT_EQ(5 * nn_iovs, io.sbytes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1207,6 +1207,8 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
EXPECT_FALSE(srs_net_url_is_rtmp("http://"));
|
||||
EXPECT_FALSE(srs_net_url_is_rtmp("rtmp:"));
|
||||
|
||||
SrsProtocolUtility utility;
|
||||
|
||||
// ipv4 loopback
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
|
|
@ -1217,7 +1219,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("127.0.0.1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
|
||||
// ipv4 intranet
|
||||
|
|
@ -1230,7 +1232,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("192.168.0.1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
|
||||
if (true) {
|
||||
|
|
@ -1238,31 +1240,31 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
addr.sin_family = AF_INET;
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x12000000);
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_TRUE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x7f000000);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x7f000001);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x0a000000);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x0a000001);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x0affffff);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0xc0a80000);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0xc0a80001);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0xc0a8ffff);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)&addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)&addr));
|
||||
}
|
||||
|
||||
// Normal ipv6 address.
|
||||
|
|
@ -1275,7 +1277,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("2001:da8:6000:291:21f:d0ff:fed4:928c", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_TRUE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
|
|
@ -1286,7 +1288,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("3ffe:dead:beef::1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_TRUE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_UNSPECIFIED
|
||||
|
|
@ -1299,7 +1301,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("::", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_SITELOCAL
|
||||
|
|
@ -1312,7 +1314,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("fec0::", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_LINKLOCAL
|
||||
|
|
@ -1325,7 +1327,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("FE80::", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_LINKLOCAL
|
||||
|
|
@ -1338,7 +1340,7 @@ VOID TEST(TCPServerTest, CoverUtility)
|
|||
ASSERT_TRUE(!getaddrinfo("::1", NULL, &hints, &r_raw));
|
||||
SrsUniquePtr<addrinfo> r(r_raw, freeaddrinfo);
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr *)r->ai_addr));
|
||||
EXPECT_FALSE(utility.is_internet((sockaddr *)r->ai_addr));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -457,12 +457,14 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible)
|
|||
|
||||
VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest)
|
||||
{
|
||||
SrsProtocolUtility utility;
|
||||
|
||||
if (true) {
|
||||
SrtMode mode;
|
||||
SrsRequest req;
|
||||
EXPECT_TRUE(srs_srt_streamid_to_request("#!::r=live/livestream?key1=val1,key2=val2", mode, &req));
|
||||
EXPECT_EQ(mode, SrtModePull);
|
||||
EXPECT_STREQ(req.vhost_.c_str(), srs_get_public_internet_address().c_str());
|
||||
EXPECT_STREQ(req.vhost_.c_str(), utility.public_internet_address().c_str());
|
||||
EXPECT_STREQ(req.app_.c_str(), "live");
|
||||
EXPECT_STREQ(req.stream_.c_str(), "livestream");
|
||||
EXPECT_STREQ(req.param_.c_str(), "key1=val1&key2=val2");
|
||||
|
|
@ -484,7 +486,7 @@ VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest)
|
|||
SrsRequest req;
|
||||
EXPECT_TRUE(srs_srt_streamid_to_request("#!::h=live/livestream?key1=val1,key2=val2", mode, &req));
|
||||
EXPECT_EQ(mode, SrtModePull);
|
||||
EXPECT_STREQ(req.vhost_.c_str(), srs_get_public_internet_address().c_str());
|
||||
EXPECT_STREQ(req.vhost_.c_str(), utility.public_internet_address().c_str());
|
||||
EXPECT_STREQ(req.app_.c_str(), "live");
|
||||
EXPECT_STREQ(req.stream_.c_str(), "livestream");
|
||||
EXPECT_STREQ(req.param_.c_str(), "key1=val1&key2=val2");
|
||||
|
|
|
|||
|
|
@ -502,7 +502,8 @@ VOID TEST(StSocketTest, RandomPortTcpListenAndConnect)
|
|||
srs_error_t err;
|
||||
|
||||
// Generate random port in range [30000, 60000]
|
||||
int random_port = 30000 + (srs_rand_integer() % (60000 - 30000 + 1));
|
||||
SrsRand rand;
|
||||
int random_port = 30000 + (rand.integer() % (60000 - 30000 + 1));
|
||||
EXPECT_GE(random_port, 30000);
|
||||
EXPECT_LE(random_port, 60000);
|
||||
|
||||
|
|
@ -534,7 +535,8 @@ VOID TEST(StSocketTest, RandomPortTcpListenAndConnectIPv6)
|
|||
srs_error_t err;
|
||||
|
||||
// Generate random port in range [30000, 60000]
|
||||
int random_port = 30000 + (srs_rand_integer() % (60000 - 30000 + 1));
|
||||
SrsRand rand;
|
||||
int random_port = 30000 + (rand.integer() % (60000 - 30000 + 1));
|
||||
EXPECT_GE(random_port, 30000);
|
||||
EXPECT_LE(random_port, 60000);
|
||||
|
||||
|
|
@ -565,7 +567,8 @@ VOID TEST(StSocketTest, RandomPortUdpListenIPv4)
|
|||
srs_error_t err;
|
||||
|
||||
// Generate random port in range [30000, 60000]
|
||||
int random_port = 30000 + (srs_rand_integer() % (60000 - 30000 + 1));
|
||||
SrsRand rand;
|
||||
int random_port = 30000 + (rand.integer() % (60000 - 30000 + 1));
|
||||
EXPECT_GE(random_port, 30000);
|
||||
EXPECT_LE(random_port, 60000);
|
||||
|
||||
|
|
@ -597,7 +600,8 @@ VOID TEST(StSocketTest, RandomPortUdpListenIPv6)
|
|||
srs_error_t err;
|
||||
|
||||
// Generate random port in range [30000, 60000]
|
||||
int random_port = 30000 + (srs_rand_integer() % (60000 - 30000 + 1));
|
||||
SrsRand rand;
|
||||
int random_port = 30000 + (rand.integer() % (60000 - 30000 + 1));
|
||||
EXPECT_GE(random_port, 30000);
|
||||
EXPECT_LE(random_port, 60000);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user