diff --git a/trunk/configure b/trunk/configure
index 9bd530793..596d68e0e 100755
--- a/trunk/configure
+++ b/trunk/configure
@@ -439,7 +439,7 @@ if [[ $SRS_UTEST == YES ]]; then
"srs_utest_config" "srs_utest_rtmp" "srs_utest_http" "srs_utest_avc" "srs_utest_reload"
"srs_utest_mp4" "srs_utest_service" "srs_utest_app" "srs_utest_rtc" "srs_utest_config2"
"srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2" "srs_utest_protocol3"
- "srs_utest_st" "srs_utest_rtc2" "srs_utest_rtc3" "srs_utest_fmp4")
+ "srs_utest_st" "srs_utest_rtc2" "srs_utest_rtc3" "srs_utest_fmp4" "srs_utest_source_lock")
if [[ $SRS_SRT == YES ]]; then
MODULE_FILES+=("srs_utest_srt")
fi
diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md
index 96dc15cdf..3133325e4 100644
--- a/trunk/doc/CHANGELOG.md
+++ b/trunk/doc/CHANGELOG.md
@@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 7.0 Changelog
+* v7.0, 2025-08-22, Merge [#4449](https://github.com/ossrs/srs/pull/4449): Refine source lock. v7.0.61 (#4449)
* v7.0, 2025-08-21, Merge [#4447](https://github.com/ossrs/srs/pull/4447): AI: Always enable WebRTC and enforce C++98 compatibility. v7.0.60 (#4447)
* v7.0, 2025-08-20, Merge [#4445](https://github.com/ossrs/srs/pull/4445): AI: Remove multi-threading support and change to single-thread architecture. v7.0.59 (#4445)
* v7.0, 2025-08-19, Merge [#4444](https://github.com/ossrs/srs/pull/4444): AI: Refine hooks from static to instance functions. v7.0.58 (#4444)
diff --git a/trunk/src/app/srs_app_caster_flv.hpp b/trunk/src/app/srs_app_caster_flv.hpp
index 69785009e..65621a36b 100644
--- a/trunk/src/app/srs_app_caster_flv.hpp
+++ b/trunk/src/app/srs_app_caster_flv.hpp
@@ -16,7 +16,7 @@ class SrsConfDirective;
class SrsHttpServeMux;
class SrsRtmpClient;
class SrsStSocket;
-class SrsRequest;
+class ISrsRequest;
class SrsPithyPrint;
class ISrsHttpResponseReader;
class SrsFlvDecoder;
diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp
index b0ba36b52..8518045bc 100644
--- a/trunk/src/app/srs_app_config.cpp
+++ b/trunk/src/app/srs_app_config.cpp
@@ -342,7 +342,7 @@ bool srs_stream_caster_is_gb28181(string caster)
return caster == "gb28181";
}
-bool srs_config_apply_filter(SrsConfDirective *dvr_apply, SrsRequest *req)
+bool srs_config_apply_filter(SrsConfDirective *dvr_apply, ISrsRequest *req)
{
static bool DEFAULT = true;
diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp
index c9a6d5042..83de76990 100644
--- a/trunk/src/app/srs_app_config.hpp
+++ b/trunk/src/app/srs_app_config.hpp
@@ -19,14 +19,13 @@
#include
#include
-class SrsRequest;
+class ISrsRequest;
class SrsFileWriter;
class SrsJsonObject;
class SrsJsonArray;
class SrsJsonAny;
class SrsConfig;
-class SrsRequest;
class SrsJsonArray;
class SrsConfDirective;
@@ -106,7 +105,7 @@ extern bool srs_stream_caster_is_udp(std::string caster);
extern bool srs_stream_caster_is_flv(std::string caster);
extern bool srs_stream_caster_is_gb28181(std::string caster);
// Whether the dvr_apply active the stream specified by req.
-extern bool srs_config_apply_filter(SrsConfDirective *dvr_apply, SrsRequest *req);
+extern bool srs_config_apply_filter(SrsConfDirective *dvr_apply, ISrsRequest *req);
// Convert bool in str to on/off
extern std::string srs_config_bool2switch(std::string sbool);
diff --git a/trunk/src/app/srs_app_coworkers.cpp b/trunk/src/app/srs_app_coworkers.cpp
index 66e19a2da..a79f7217f 100644
--- a/trunk/src/app/srs_app_coworkers.cpp
+++ b/trunk/src/app/srs_app_coworkers.cpp
@@ -24,9 +24,9 @@ SrsCoWorkers::SrsCoWorkers()
SrsCoWorkers::~SrsCoWorkers()
{
- map::iterator it;
+ map::iterator it;
for (it = streams.begin(); it != streams.end(); ++it) {
- SrsRequest *r = it->second;
+ ISrsRequest *r = it->second;
srs_freep(r);
}
streams.clear();
@@ -42,7 +42,7 @@ SrsCoWorkers *SrsCoWorkers::instance()
SrsJsonAny *SrsCoWorkers::dumps(string vhost, string coworker, string app, string stream)
{
- SrsRequest *r = find_stream_info(vhost, app, stream);
+ ISrsRequest *r = find_stream_info(vhost, app, stream);
if (!r) {
// TODO: FIXME: Find stream from our origin util return to the start point.
return SrsJsonAny::null();
@@ -103,7 +103,7 @@ SrsJsonAny *SrsCoWorkers::dumps(string vhost, string coworker, string app, strin
->set("routers", routers);
}
-SrsRequest *SrsCoWorkers::find_stream_info(string vhost, string app, string stream)
+ISrsRequest *SrsCoWorkers::find_stream_info(string vhost, string app, string stream)
{
// First, we should parse the vhost, if not exists, try default vhost instead.
SrsConfDirective *conf = _srs_config->get_vhost(vhost, true);
@@ -113,7 +113,7 @@ SrsRequest *SrsCoWorkers::find_stream_info(string vhost, string app, string stre
// Get stream information from local cache.
string url = srs_generate_stream_url(conf->arg0(), app, stream);
- map::iterator it = streams.find(url);
+ map::iterator it = streams.find(url);
if (it == streams.end()) {
return NULL;
}
@@ -121,14 +121,14 @@ SrsRequest *SrsCoWorkers::find_stream_info(string vhost, string app, string stre
return it->second;
}
-srs_error_t SrsCoWorkers::on_publish(SrsRequest *r)
+srs_error_t SrsCoWorkers::on_publish(ISrsRequest *r)
{
srs_error_t err = srs_success;
string url = r->get_stream_url();
// Delete the previous stream informations.
- map::iterator it = streams.find(url);
+ map::iterator it = streams.find(url);
if (it != streams.end()) {
srs_freep(it->second);
}
@@ -139,11 +139,11 @@ srs_error_t SrsCoWorkers::on_publish(SrsRequest *r)
return err;
}
-void SrsCoWorkers::on_unpublish(SrsRequest *r)
+void SrsCoWorkers::on_unpublish(ISrsRequest *r)
{
string url = r->get_stream_url();
- map::iterator it = streams.find(url);
+ map::iterator it = streams.find(url);
if (it != streams.end()) {
srs_freep(it->second);
streams.erase(it);
diff --git a/trunk/src/app/srs_app_coworkers.hpp b/trunk/src/app/srs_app_coworkers.hpp
index 1ddc9fd55..3bc2257e6 100644
--- a/trunk/src/app/srs_app_coworkers.hpp
+++ b/trunk/src/app/srs_app_coworkers.hpp
@@ -13,7 +13,7 @@
#include
class SrsJsonAny;
-class SrsRequest;
+class ISrsRequest;
class SrsLiveSource;
// For origin cluster.
@@ -23,7 +23,7 @@ private:
static SrsCoWorkers *_instance;
private:
- std::map streams;
+ std::map streams;
private:
SrsCoWorkers();
@@ -36,11 +36,11 @@ public:
virtual SrsJsonAny *dumps(std::string vhost, std::string coworker, std::string app, std::string stream);
private:
- virtual SrsRequest *find_stream_info(std::string vhost, std::string app, std::string stream);
+ virtual ISrsRequest *find_stream_info(std::string vhost, std::string app, std::string stream);
public:
- virtual srs_error_t on_publish(SrsRequest *r);
- virtual void on_unpublish(SrsRequest *r);
+ virtual srs_error_t on_publish(ISrsRequest *r);
+ virtual void on_unpublish(ISrsRequest *r);
};
#endif
diff --git a/trunk/src/app/srs_app_dash.cpp b/trunk/src/app/srs_app_dash.cpp
index 74e368117..9adc4405a 100644
--- a/trunk/src/app/srs_app_dash.cpp
+++ b/trunk/src/app/srs_app_dash.cpp
@@ -79,7 +79,7 @@ SrsFragmentedMp4::~SrsFragmentedMp4()
srs_freep(fw);
}
-srs_error_t SrsFragmentedMp4::initialize(SrsRequest *r, bool video, int64_t time, SrsMpdWriter *mpd, uint32_t tid)
+srs_error_t SrsFragmentedMp4::initialize(ISrsRequest *r, bool video, int64_t time, SrsMpdWriter *mpd, uint32_t tid)
{
srs_error_t err = srs_success;
@@ -185,7 +185,7 @@ void SrsMpdWriter::dispose()
}
}
-srs_error_t SrsMpdWriter::initialize(SrsRequest *r)
+srs_error_t SrsMpdWriter::initialize(ISrsRequest *r)
{
req = r;
return srs_success;
@@ -193,7 +193,7 @@ srs_error_t SrsMpdWriter::initialize(SrsRequest *r)
srs_error_t SrsMpdWriter::on_publish()
{
- SrsRequest *r = req;
+ ISrsRequest *r = req;
fragment = _srs_config->get_dash_fragment(r->vhost);
update_period = _srs_config->get_dash_update_period(r->vhost);
@@ -394,7 +394,7 @@ void SrsDashController::dispose()
srs_trace("gracefully dispose dash %s", req ? req->get_stream_url().c_str() : "");
}
-srs_error_t SrsDashController::initialize(SrsRequest *r)
+srs_error_t SrsDashController::initialize(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -411,7 +411,7 @@ srs_error_t SrsDashController::on_publish()
{
srs_error_t err = srs_success;
- SrsRequest *r = req;
+ ISrsRequest *r = req;
fragment = _srs_config->get_dash_fragment(r->vhost);
home = _srs_config->get_dash_path(r->vhost);
@@ -737,7 +737,7 @@ srs_utime_t SrsDash::cleanup_delay()
return _srs_config->get_dash_dispose(req->vhost) * 1.1;
}
-srs_error_t SrsDash::initialize(SrsOriginHub *h, SrsRequest *r)
+srs_error_t SrsDash::initialize(SrsOriginHub *h, ISrsRequest *r)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_dash.hpp b/trunk/src/app/srs_app_dash.hpp
index e44dd6412..4bcdecfe9 100644
--- a/trunk/src/app/srs_app_dash.hpp
+++ b/trunk/src/app/srs_app_dash.hpp
@@ -14,7 +14,7 @@
#include
-class SrsRequest;
+class ISrsRequest;
class SrsOriginHub;
class SrsSharedPtrMessage;
class SrsFormat;
@@ -52,7 +52,7 @@ public:
public:
// Initialize the fragment, create the home dir, open the file.
- virtual srs_error_t initialize(SrsRequest *r, bool video, int64_t time, SrsMpdWriter *mpd, uint32_t tid);
+ virtual srs_error_t initialize(ISrsRequest *r, bool video, int64_t time, SrsMpdWriter *mpd, uint32_t tid);
// Write media message to fragment.
virtual srs_error_t write(SrsSharedPtrMessage *shared_msg, SrsFormat *format);
// Reap the fragment, close the fd and rename tmp to official file.
@@ -63,7 +63,7 @@ public:
class SrsMpdWriter
{
private:
- SrsRequest *req;
+ ISrsRequest *req;
private:
// The duration of fragment in srs_utime_t.
@@ -97,7 +97,7 @@ public:
virtual void dispose();
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
// Write MPD according to parsed format of stream.
@@ -116,7 +116,7 @@ public:
class SrsDashController
{
private:
- SrsRequest *req;
+ ISrsRequest *req;
SrsFormat *format_;
SrsMpdWriter *mpd;
@@ -151,7 +151,7 @@ public:
virtual void dispose();
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
@@ -171,7 +171,7 @@ private:
srs_utime_t last_update_time_;
private:
- SrsRequest *req;
+ ISrsRequest *req;
SrsOriginHub *hub;
SrsDashController *controller;
@@ -186,7 +186,7 @@ public:
public:
// Initalize the encoder.
- virtual srs_error_t initialize(SrsOriginHub *h, SrsRequest *r);
+ virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
// When stream start publishing.
virtual srs_error_t on_publish();
// When got an shared audio message.
diff --git a/trunk/src/app/srs_app_dvr.cpp b/trunk/src/app/srs_app_dvr.cpp
index dc5c7accd..647baab9b 100644
--- a/trunk/src/app/srs_app_dvr.cpp
+++ b/trunk/src/app/srs_app_dvr.cpp
@@ -51,7 +51,7 @@ SrsDvrSegmenter::~SrsDvrSegmenter()
srs_freep(fs);
}
-srs_error_t SrsDvrSegmenter::initialize(SrsDvrPlan *p, SrsRequest *r)
+srs_error_t SrsDvrSegmenter::initialize(SrsDvrPlan *p, ISrsRequest *r)
{
req = r;
plan = p;
@@ -517,7 +517,7 @@ srs_error_t SrsDvrMp4Segmenter::close_encoder()
return err;
}
-SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(SrsContextId c, SrsRequest *r, string p)
+SrsDvrAsyncCallOnDvr::SrsDvrAsyncCallOnDvr(SrsContextId c, ISrsRequest *r, string p)
{
cid = c;
req = r->copy();
@@ -581,7 +581,7 @@ SrsDvrPlan::~SrsDvrPlan()
srs_freep(req);
}
-srs_error_t SrsDvrPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, SrsRequest *r)
+srs_error_t SrsDvrPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -596,7 +596,7 @@ srs_error_t SrsDvrPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, SrsReque
return err;
}
-srs_error_t SrsDvrPlan::on_publish(SrsRequest *r)
+srs_error_t SrsDvrPlan::on_publish(ISrsRequest *r)
{
// @see https://github.com/ossrs/srs/issues/1613#issuecomment-960623359
srs_freep(req);
@@ -689,7 +689,7 @@ SrsDvrSessionPlan::~SrsDvrSessionPlan()
{
}
-srs_error_t SrsDvrSessionPlan::on_publish(SrsRequest *r)
+srs_error_t SrsDvrSessionPlan::on_publish(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -751,7 +751,7 @@ SrsDvrSegmentPlan::~SrsDvrSegmentPlan()
{
}
-srs_error_t SrsDvrSegmentPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, SrsRequest *r)
+srs_error_t SrsDvrSegmentPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -766,7 +766,7 @@ srs_error_t SrsDvrSegmentPlan::initialize(SrsOriginHub *h, SrsDvrSegmenter *s, S
return srs_success;
}
-srs_error_t SrsDvrSegmentPlan::on_publish(SrsRequest *r)
+srs_error_t SrsDvrSegmentPlan::on_publish(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -932,7 +932,7 @@ SrsDvr::~SrsDvr()
srs_freep(req);
}
-srs_error_t SrsDvr::initialize(SrsOriginHub *h, SrsRequest *r)
+srs_error_t SrsDvr::initialize(SrsOriginHub *h, ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -962,7 +962,7 @@ srs_error_t SrsDvr::initialize(SrsOriginHub *h, SrsRequest *r)
return err;
}
-srs_error_t SrsDvr::on_publish(SrsRequest *r)
+srs_error_t SrsDvr::on_publish(ISrsRequest *r)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_dvr.hpp b/trunk/src/app/srs_app_dvr.hpp
index 9575ea632..69edec222 100644
--- a/trunk/src/app/srs_app_dvr.hpp
+++ b/trunk/src/app/srs_app_dvr.hpp
@@ -14,7 +14,7 @@
class SrsLiveSource;
class SrsOriginHub;
-class SrsRequest;
+class ISrsRequest;
class SrsBuffer;
class SrsRtmpJitter;
class SrsSharedPtrMessage;
@@ -44,7 +44,7 @@ protected:
SrsFragment *fragment;
private:
- SrsRequest *req;
+ ISrsRequest *req;
SrsDvrPlan *plan;
private:
@@ -57,7 +57,7 @@ public:
public:
// Initialize the segment.
- virtual srs_error_t initialize(SrsDvrPlan *p, SrsRequest *r);
+ virtual srs_error_t initialize(SrsDvrPlan *p, ISrsRequest *r);
// Get the current framgnet.
virtual SrsFragment *current();
// Open new segment file.
@@ -157,10 +157,10 @@ class SrsDvrAsyncCallOnDvr : public ISrsAsyncCallTask
private:
SrsContextId cid;
std::string path;
- SrsRequest *req;
+ ISrsRequest *req;
public:
- SrsDvrAsyncCallOnDvr(SrsContextId c, SrsRequest *r, std::string p);
+ SrsDvrAsyncCallOnDvr(SrsContextId c, ISrsRequest *r, std::string p);
virtual ~SrsDvrAsyncCallOnDvr();
public:
@@ -172,7 +172,7 @@ public:
class SrsDvrPlan : public ISrsReloadHandler
{
public:
- SrsRequest *req;
+ ISrsRequest *req;
protected:
SrsOriginHub *hub;
@@ -184,8 +184,8 @@ public:
virtual ~SrsDvrPlan();
public:
- virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, SrsRequest *r);
- virtual srs_error_t on_publish(SrsRequest *r);
+ virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r);
+ virtual srs_error_t on_publish(ISrsRequest *r);
virtual void on_unpublish();
virtual srs_error_t on_meta_data(SrsSharedPtrMessage *shared_metadata);
virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
@@ -207,7 +207,7 @@ public:
virtual ~SrsDvrSessionPlan();
public:
- virtual srs_error_t on_publish(SrsRequest *r);
+ virtual srs_error_t on_publish(ISrsRequest *r);
virtual void on_unpublish();
};
@@ -226,8 +226,8 @@ public:
virtual ~SrsDvrSegmentPlan();
public:
- virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, SrsRequest *r);
- virtual srs_error_t on_publish(SrsRequest *r);
+ virtual srs_error_t initialize(SrsOriginHub *h, SrsDvrSegmenter *s, ISrsRequest *r);
+ virtual srs_error_t on_publish(ISrsRequest *r);
virtual void on_unpublish();
virtual srs_error_t on_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
virtual srs_error_t on_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
@@ -245,7 +245,7 @@ class SrsDvr : public ISrsReloadHandler
private:
SrsOriginHub *hub;
SrsDvrPlan *plan;
- SrsRequest *req;
+ ISrsRequest *req;
private:
// whether the dvr is actived by filter, which is specified by dvr_apply.
@@ -261,11 +261,11 @@ public:
// initialize dvr, create dvr plan.
// when system initialize(encoder publish at first time, or reload),
// initialize the dvr will reinitialize the plan, the whole dvr framework.
- virtual srs_error_t initialize(SrsOriginHub *h, SrsRequest *r);
+ virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
// publish stream event,
// when encoder start to publish RTMP stream.
// @param fetch_sequence_header whether fetch sequence from source.
- virtual srs_error_t on_publish(SrsRequest *r);
+ virtual srs_error_t on_publish(ISrsRequest *r);
// the unpublish event.,
// when encoder stop(unpublish) to publish RTMP stream.
virtual void on_unpublish();
diff --git a/trunk/src/app/srs_app_edge.cpp b/trunk/src/app/srs_app_edge.cpp
index f08920807..c405f01c2 100644
--- a/trunk/src/app/srs_app_edge.cpp
+++ b/trunk/src/app/srs_app_edge.cpp
@@ -62,11 +62,11 @@ SrsEdgeRtmpUpstream::~SrsEdgeRtmpUpstream()
close();
}
-srs_error_t SrsEdgeRtmpUpstream::connect(SrsRequest *r, SrsLbRoundRobin *lb)
+srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, SrsLbRoundRobin *lb)
{
srs_error_t err = srs_success;
- SrsRequest *req = r;
+ ISrsRequest *req = r;
std::string url;
if (true) {
@@ -178,10 +178,10 @@ SrsEdgeFlvUpstream::~SrsEdgeFlvUpstream()
close();
}
-srs_error_t SrsEdgeFlvUpstream::connect(SrsRequest *r, SrsLbRoundRobin *lb)
+srs_error_t SrsEdgeFlvUpstream::connect(ISrsRequest *r, SrsLbRoundRobin *lb)
{
// Because we might modify the r, which cause retry fail, so we must copy it.
- SrsRequest *cp = r->copy();
+ ISrsRequest *cp = r->copy();
// Free the request when close upstream.
srs_freep(req_);
@@ -190,11 +190,11 @@ srs_error_t SrsEdgeFlvUpstream::connect(SrsRequest *r, SrsLbRoundRobin *lb)
return do_connect(cp, lb, 0);
}
-srs_error_t SrsEdgeFlvUpstream::do_connect(SrsRequest *r, SrsLbRoundRobin *lb, int redirect_depth)
+srs_error_t SrsEdgeFlvUpstream::do_connect(ISrsRequest *r, SrsLbRoundRobin *lb, int redirect_depth)
{
srs_error_t err = srs_success;
- SrsRequest *req = r;
+ ISrsRequest *req = r;
if (redirect_depth == 0) {
SrsConfDirective *conf = _srs_config->get_vhost_edge_origin(req->vhost);
@@ -417,7 +417,7 @@ SrsEdgeIngester::~SrsEdgeIngester()
srs_freep(trd);
}
-srs_error_t SrsEdgeIngester::initialize(SrsSharedPtr s, SrsPlayEdge *e, SrsRequest *r)
+srs_error_t SrsEdgeIngester::initialize(SrsSharedPtr s, SrsPlayEdge *e, ISrsRequest *r)
{
// Because source references to this object, so we should directly use the source ptr.
source_ = s.get();
@@ -750,7 +750,7 @@ void SrsEdgeForwarder::set_queue_size(srs_utime_t queue_size)
return queue->set_queue_size(queue_size);
}
-srs_error_t SrsEdgeForwarder::initialize(SrsSharedPtr s, SrsPublishEdge *e, SrsRequest *r)
+srs_error_t SrsEdgeForwarder::initialize(SrsSharedPtr s, SrsPublishEdge *e, ISrsRequest *r)
{
// Because source references to this object, so we should directly use the source ptr.
source_ = s.get();
@@ -965,7 +965,7 @@ SrsPlayEdge::~SrsPlayEdge()
srs_freep(ingester);
}
-srs_error_t SrsPlayEdge::initialize(SrsSharedPtr source, SrsRequest *req)
+srs_error_t SrsPlayEdge::initialize(SrsSharedPtr source, ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -1058,7 +1058,7 @@ void SrsPublishEdge::set_queue_size(srs_utime_t queue_size)
return forwarder->set_queue_size(queue_size);
}
-srs_error_t SrsPublishEdge::initialize(SrsSharedPtr source, SrsRequest *req)
+srs_error_t SrsPublishEdge::initialize(SrsSharedPtr source, ISrsRequest *req)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_edge.hpp b/trunk/src/app/srs_app_edge.hpp
index 0ea205a1e..2f733f4b6 100644
--- a/trunk/src/app/srs_app_edge.hpp
+++ b/trunk/src/app/srs_app_edge.hpp
@@ -17,7 +17,7 @@
class SrsStSocket;
class SrsRtmpServer;
class SrsLiveSource;
-class SrsRequest;
+class ISrsRequest;
class SrsPlayEdge;
class SrsPublishEdge;
class SrsRtmpClient;
@@ -65,7 +65,7 @@ public:
virtual ~SrsEdgeUpstream();
public:
- virtual srs_error_t connect(SrsRequest *r, SrsLbRoundRobin *lb) = 0;
+ virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb) = 0;
virtual srs_error_t recv_message(SrsCommonMessage **pmsg) = 0;
virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsPacket **ppacket) = 0;
virtual void close() = 0;
@@ -95,7 +95,7 @@ public:
virtual ~SrsEdgeRtmpUpstream();
public:
- virtual srs_error_t connect(SrsRequest *r, SrsLbRoundRobin *lb);
+ virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb);
virtual srs_error_t recv_message(SrsCommonMessage **pmsg);
virtual srs_error_t decode_message(SrsCommonMessage *msg, SrsPacket **ppacket);
virtual void close();
@@ -119,7 +119,7 @@ private:
private:
// We might modify the request by HTTP redirect.
- SrsRequest *req_;
+ ISrsRequest *req_;
// Current selected server, the ip:port.
std::string selected_ip;
int selected_port;
@@ -129,10 +129,10 @@ public:
virtual ~SrsEdgeFlvUpstream();
public:
- virtual srs_error_t connect(SrsRequest *r, SrsLbRoundRobin *lb);
+ virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb);
private:
- virtual srs_error_t do_connect(SrsRequest *r, SrsLbRoundRobin *lb, int redirect_depth);
+ virtual srs_error_t do_connect(ISrsRequest *r, SrsLbRoundRobin *lb, int redirect_depth);
public:
virtual srs_error_t recv_message(SrsCommonMessage **pmsg);
@@ -154,7 +154,7 @@ private:
private:
SrsPlayEdge *edge;
- SrsRequest *req;
+ ISrsRequest *req;
SrsCoroutine *trd;
SrsLbRoundRobin *lb;
SrsEdgeUpstream *upstream;
@@ -166,7 +166,7 @@ public:
virtual ~SrsEdgeIngester();
public:
- virtual srs_error_t initialize(SrsSharedPtr s, SrsPlayEdge *e, SrsRequest *r);
+ virtual srs_error_t initialize(SrsSharedPtr s, SrsPlayEdge *e, ISrsRequest *r);
virtual srs_error_t start();
virtual void stop();
virtual std::string get_curr_origin();
@@ -195,7 +195,7 @@ private:
private:
SrsPublishEdge *edge;
- SrsRequest *req;
+ ISrsRequest *req;
SrsCoroutine *trd;
SrsSimpleRtmpClient *sdk;
SrsLbRoundRobin *lb;
@@ -215,7 +215,7 @@ public:
virtual void set_queue_size(srs_utime_t queue_size);
public:
- virtual srs_error_t initialize(SrsSharedPtr s, SrsPublishEdge *e, SrsRequest *r);
+ virtual srs_error_t initialize(SrsSharedPtr s, SrsPublishEdge *e, ISrsRequest *r);
virtual srs_error_t start();
virtual void stop();
// Interface ISrsReusableThread2Handler
@@ -244,7 +244,7 @@ public:
// Always use the req of source,
// For we assume all client to edge is invalid,
// if auth open, edge must valid it from origin, then service it.
- virtual srs_error_t initialize(SrsSharedPtr source, SrsRequest *req);
+ virtual srs_error_t initialize(SrsSharedPtr source, ISrsRequest *req);
// When client play stream on edge.
virtual srs_error_t on_client_play();
// When all client stopped play, disconnect to origin.
@@ -271,7 +271,7 @@ public:
virtual void set_queue_size(srs_utime_t queue_size);
public:
- virtual srs_error_t initialize(SrsSharedPtr source, SrsRequest *req);
+ virtual srs_error_t initialize(SrsSharedPtr source, ISrsRequest *req);
virtual bool can_publish();
// When client publish stream on edge.
virtual srs_error_t on_client_publish();
diff --git a/trunk/src/app/srs_app_encoder.cpp b/trunk/src/app/srs_app_encoder.cpp
index 0ee20aeae..1cc1fa39d 100644
--- a/trunk/src/app/srs_app_encoder.cpp
+++ b/trunk/src/app/srs_app_encoder.cpp
@@ -35,7 +35,7 @@ SrsEncoder::~SrsEncoder()
srs_freep(pprint);
}
-srs_error_t SrsEncoder::on_publish(SrsRequest *req)
+srs_error_t SrsEncoder::on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -155,7 +155,7 @@ SrsFFMPEG *SrsEncoder::at(int index)
return ffmpegs[index];
}
-srs_error_t SrsEncoder::parse_scope_engines(SrsRequest *req)
+srs_error_t SrsEncoder::parse_scope_engines(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -188,7 +188,7 @@ srs_error_t SrsEncoder::parse_scope_engines(SrsRequest *req)
return err;
}
-srs_error_t SrsEncoder::parse_ffmpeg(SrsRequest *req, SrsConfDirective *conf)
+srs_error_t SrsEncoder::parse_ffmpeg(ISrsRequest *req, SrsConfDirective *conf)
{
srs_error_t err = srs_success;
@@ -234,7 +234,7 @@ srs_error_t SrsEncoder::parse_ffmpeg(SrsRequest *req, SrsConfDirective *conf)
return err;
}
-srs_error_t SrsEncoder::initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsRequest *req, SrsConfDirective *engine)
+srs_error_t SrsEncoder::initialize_ffmpeg(SrsFFMPEG *ffmpeg, ISrsRequest *req, SrsConfDirective *engine)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_encoder.hpp b/trunk/src/app/srs_app_encoder.hpp
index 0a4c67fb2..6bbe2d782 100644
--- a/trunk/src/app/srs_app_encoder.hpp
+++ b/trunk/src/app/srs_app_encoder.hpp
@@ -15,7 +15,7 @@
#include
class SrsConfDirective;
-class SrsRequest;
+class ISrsRequest;
class SrsPithyPrint;
class SrsFFMPEG;
@@ -36,7 +36,7 @@ public:
virtual ~SrsEncoder();
public:
- virtual srs_error_t on_publish(SrsRequest *req);
+ virtual srs_error_t on_publish(ISrsRequest *req);
virtual void on_unpublish();
// Interface ISrsReusableThreadHandler.
public:
@@ -48,9 +48,9 @@ private:
private:
virtual void clear_engines();
virtual SrsFFMPEG *at(int index);
- virtual srs_error_t parse_scope_engines(SrsRequest *req);
- virtual srs_error_t parse_ffmpeg(SrsRequest *req, SrsConfDirective *conf);
- virtual srs_error_t initialize_ffmpeg(SrsFFMPEG *ffmpeg, SrsRequest *req, SrsConfDirective *engine);
+ virtual srs_error_t parse_scope_engines(ISrsRequest *req);
+ virtual srs_error_t parse_ffmpeg(ISrsRequest *req, SrsConfDirective *conf);
+ virtual srs_error_t initialize_ffmpeg(SrsFFMPEG *ffmpeg, ISrsRequest *req, SrsConfDirective *engine);
virtual void show_encode_log_message();
};
diff --git a/trunk/src/app/srs_app_forward.cpp b/trunk/src/app/srs_app_forward.cpp
index 4f26a7daf..3bac5177a 100644
--- a/trunk/src/app/srs_app_forward.cpp
+++ b/trunk/src/app/srs_app_forward.cpp
@@ -56,7 +56,7 @@ SrsForwarder::~SrsForwarder()
srs_freep(req);
}
-srs_error_t SrsForwarder::initialize(SrsRequest *r, string ep)
+srs_error_t SrsForwarder::initialize(ISrsRequest *r, string ep)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_forward.hpp b/trunk/src/app/srs_app_forward.hpp
index 833630a16..2dce9a1db 100644
--- a/trunk/src/app/srs_app_forward.hpp
+++ b/trunk/src/app/srs_app_forward.hpp
@@ -19,7 +19,7 @@ class SrsOnMetaDataPacket;
class SrsMessageQueue;
class SrsRtmpJitter;
class SrsRtmpClient;
-class SrsRequest;
+class ISrsRequest;
class SrsLiveSource;
class SrsOriginHub;
class SrsKbps;
@@ -31,7 +31,7 @@ class SrsForwarder : public ISrsCoroutineHandler
private:
// The ep to forward, server[:port].
std::string ep_forward;
- SrsRequest *req;
+ ISrsRequest *req;
private:
// The source or stream context id to bind to.
@@ -54,7 +54,7 @@ public:
virtual ~SrsForwarder();
public:
- virtual srs_error_t initialize(SrsRequest *r, std::string ep);
+ virtual srs_error_t initialize(ISrsRequest *r, std::string ep);
virtual void set_queue_size(srs_utime_t queue_size);
public:
diff --git a/trunk/src/app/srs_app_hds.cpp b/trunk/src/app/srs_app_hds.cpp
index efe511ff1..760f4d9ee 100644
--- a/trunk/src/app/srs_app_hds.cpp
+++ b/trunk/src/app/srs_app_hds.cpp
@@ -70,7 +70,7 @@ string serialFlv(SrsSharedPtrMessage *msg)
class SrsHdsFragment
{
public:
- SrsHdsFragment(SrsRequest *r)
+ SrsHdsFragment(ISrsRequest *r)
: req(r), index(-1), start_time(0), videoSh(NULL), audioSh(NULL)
{
}
@@ -218,7 +218,7 @@ public:
}
private:
- SrsRequest *req;
+ ISrsRequest *req;
list msgs;
/*!
@@ -241,7 +241,7 @@ SrsHds::~SrsHds()
{
}
-srs_error_t SrsHds::on_publish(SrsRequest *req)
+srs_error_t SrsHds::on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_hds.hpp b/trunk/src/app/srs_app_hds.hpp
index ba32d543c..f7037bee9 100644
--- a/trunk/src/app/srs_app_hds.hpp
+++ b/trunk/src/app/srs_app_hds.hpp
@@ -13,7 +13,7 @@
#include
-class SrsRequest;
+class ISrsRequest;
class SrsSharedPtrMessage;
class SrsHdsFragment;
class SrsLiveSource;
@@ -25,7 +25,7 @@ public:
SrsHds();
virtual ~SrsHds();
- srs_error_t on_publish(SrsRequest *req);
+ srs_error_t on_publish(ISrsRequest *req);
srs_error_t on_unpublish();
srs_error_t on_video(SrsSharedPtrMessage *msg);
@@ -43,7 +43,7 @@ private:
SrsSharedPtrMessage *video_sh;
SrsSharedPtrMessage *audio_sh;
- SrsRequest *hds_req;
+ ISrsRequest *hds_req;
bool hds_enabled;
};
diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp
index 995720745..d490ed07f 100644
--- a/trunk/src/app/srs_app_hls.cpp
+++ b/trunk/src/app/srs_app_hls.cpp
@@ -254,7 +254,7 @@ srs_error_t SrsHlsM4sSegment::reap(uint64_t dts)
return err;
}
-SrsDvrAsyncCallOnHls::SrsDvrAsyncCallOnHls(SrsContextId c, SrsRequest *r, string p, string t, string m, string mu, int s, srs_utime_t d)
+SrsDvrAsyncCallOnHls::SrsDvrAsyncCallOnHls(SrsContextId c, ISrsRequest *r, string p, string t, string m, string mu, int s, srs_utime_t d)
{
req = r->copy();
cid = c;
@@ -309,7 +309,7 @@ string SrsDvrAsyncCallOnHls::to_string()
return "on_hls: " + path;
}
-SrsDvrAsyncCallOnHlsNotify::SrsDvrAsyncCallOnHlsNotify(SrsContextId c, SrsRequest *r, string u)
+SrsDvrAsyncCallOnHlsNotify::SrsDvrAsyncCallOnHlsNotify(SrsContextId c, ISrsRequest *r, string u)
{
cid = c;
req = r->copy();
@@ -473,7 +473,7 @@ srs_error_t SrsHlsFmp4Muxer::initialize(int v_tid, int a_tid)
return srs_success;
}
-srs_error_t SrsHlsFmp4Muxer::on_publish(SrsRequest *req)
+srs_error_t SrsHlsFmp4Muxer::on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -632,7 +632,7 @@ srs_error_t SrsHlsFmp4Muxer::on_unpublish()
return srs_success;
}
-srs_error_t SrsHlsFmp4Muxer::update_config(SrsRequest *r)
+srs_error_t SrsHlsFmp4Muxer::update_config(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -1177,7 +1177,7 @@ srs_error_t SrsHlsMuxer::initialize()
return srs_success;
}
-srs_error_t SrsHlsMuxer::on_publish(SrsRequest *req)
+srs_error_t SrsHlsMuxer::on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -1194,7 +1194,7 @@ srs_error_t SrsHlsMuxer::on_unpublish()
return srs_success;
}
-srs_error_t SrsHlsMuxer::update_config(SrsRequest *r, string entry_prefix,
+srs_error_t SrsHlsMuxer::update_config(ISrsRequest *r, string entry_prefix,
string path, string m3u8_file, string ts_file, srs_utime_t fragment, srs_utime_t window,
bool ts_floor, double aof_ratio, bool cleanup, bool wait_keyframe, bool keys,
int fragments_per_key, string key_file, string key_file_path, string key_url)
@@ -1935,7 +1935,7 @@ int SrsHlsController::deviation()
return muxer->deviation();
}
-srs_error_t SrsHlsController::on_publish(SrsRequest *req)
+srs_error_t SrsHlsController::on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -2239,7 +2239,7 @@ void SrsHlsMp4Controller::dispose()
muxer_->dispose();
}
-srs_error_t SrsHlsMp4Controller::on_publish(SrsRequest *req)
+srs_error_t SrsHlsMp4Controller::on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -2514,7 +2514,7 @@ srs_utime_t SrsHls::cleanup_delay()
return _srs_config->get_hls_dispose(req->vhost) * 1.1;
}
-srs_error_t SrsHls::initialize(SrsOriginHub *h, SrsRequest *r)
+srs_error_t SrsHls::initialize(SrsOriginHub *h, ISrsRequest *r)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp
index 8b26dbffa..db0258223 100644
--- a/trunk/src/app/srs_app_hls.hpp
+++ b/trunk/src/app/srs_app_hls.hpp
@@ -23,7 +23,7 @@ class SrsSharedPtrMessage;
class SrsAmf0Object;
class SrsRtmpJitter;
class SrsTsContextWriter;
-class SrsRequest;
+class ISrsRequest;
class SrsPithyPrint;
class SrsLiveSource;
class SrsOriginHub;
@@ -132,12 +132,12 @@ private:
std::string m3u8;
std::string m3u8_url;
int seq_no;
- SrsRequest *req;
+ ISrsRequest *req;
srs_utime_t duration;
public:
// TODO: FIXME: Use TBN 1000.
- SrsDvrAsyncCallOnHls(SrsContextId c, SrsRequest *r, std::string p, std::string t, std::string m, std::string mu, int s, srs_utime_t d);
+ SrsDvrAsyncCallOnHls(SrsContextId c, ISrsRequest *r, std::string p, std::string t, std::string m, std::string mu, int s, srs_utime_t d);
virtual ~SrsDvrAsyncCallOnHls();
public:
@@ -151,10 +151,10 @@ class SrsDvrAsyncCallOnHlsNotify : public ISrsAsyncCallTask
private:
SrsContextId cid;
std::string ts_url;
- SrsRequest *req;
+ ISrsRequest *req;
public:
- SrsDvrAsyncCallOnHlsNotify(SrsContextId c, SrsRequest *r, std::string u);
+ SrsDvrAsyncCallOnHlsNotify(SrsContextId c, ISrsRequest *r, std::string u);
virtual ~SrsDvrAsyncCallOnHlsNotify();
public:
@@ -172,7 +172,7 @@ public:
class SrsHlsMuxer
{
private:
- SrsRequest *req;
+ ISrsRequest *req;
private:
std::string hls_entry_prefix;
@@ -257,10 +257,10 @@ public:
// Initialize the hls muxer.
virtual srs_error_t initialize();
// When publish or unpublish stream.
- virtual srs_error_t on_publish(SrsRequest *req);
+ virtual srs_error_t on_publish(ISrsRequest *req);
virtual srs_error_t on_unpublish();
// When publish, update the config for muxer.
- virtual srs_error_t update_config(SrsRequest *r, std::string entry_prefix,
+ virtual srs_error_t update_config(ISrsRequest *r, std::string entry_prefix,
std::string path, std::string m3u8_file, std::string ts_file,
srs_utime_t fragment, srs_utime_t window, bool ts_floor, double aof_ratio,
bool cleanup, bool wait_keyframe, bool keys, int fragments_per_key,
@@ -308,7 +308,7 @@ public:
class SrsHlsFmp4Muxer
{
private:
- SrsRequest *req_;
+ ISrsRequest *req_;
private:
std::string hls_entry_prefix_;
@@ -406,7 +406,7 @@ public:
// Initialize the hls muxer.
virtual srs_error_t initialize(int v_tid, int a_tid);
// When publish or unpublish stream.
- virtual srs_error_t on_publish(SrsRequest *req);
+ virtual srs_error_t on_publish(ISrsRequest *req);
public:
virtual srs_error_t write_init_mp4(SrsFormat *format, bool has_video, bool has_audio);
@@ -416,7 +416,7 @@ public:
public:
virtual srs_error_t on_unpublish();
// When publish, update the config for muxer.
- virtual srs_error_t update_config(SrsRequest *r);
+ virtual srs_error_t update_config(ISrsRequest *r);
// Open a new segment(a new ts file)
virtual srs_error_t segment_open(srs_utime_t basetime);
virtual srs_error_t on_sequence_header();
@@ -455,7 +455,7 @@ public:
virtual srs_error_t initialize() = 0;
virtual void dispose() = 0;
// When publish or unpublish stream.
- virtual srs_error_t on_publish(SrsRequest *req) = 0;
+ virtual srs_error_t on_publish(ISrsRequest *req) = 0;
virtual srs_error_t on_unpublish() = 0;
public:
@@ -518,7 +518,7 @@ public:
public:
// When publish or unpublish stream.
- virtual srs_error_t on_publish(SrsRequest *req);
+ virtual srs_error_t on_publish(ISrsRequest *req);
virtual srs_error_t on_unpublish();
// When get sequence header,
// must write a #EXT-X-DISCONTINUITY to m3u8.
@@ -557,7 +557,7 @@ private:
uint64_t video_dts_;
private:
- SrsRequest *req_;
+ ISrsRequest *req_;
private:
SrsHlsFmp4Muxer *muxer_;
@@ -570,7 +570,7 @@ public:
virtual srs_error_t initialize();
virtual void dispose();
// When publish or unpublish stream.
- virtual srs_error_t on_publish(SrsRequest *req);
+ virtual srs_error_t on_publish(ISrsRequest *req);
virtual srs_error_t on_unpublish();
virtual srs_error_t write_audio(SrsSharedPtrMessage *shared_audio, SrsFormat *format);
virtual srs_error_t write_video(SrsSharedPtrMessage *shared_video, SrsFormat *format);
@@ -591,7 +591,7 @@ private:
ISrsHlsController *controller;
private:
- SrsRequest *req;
+ ISrsRequest *req;
// Whether the HLS is enabled.
bool enabled;
// Whether the HLS stream is able to be disposed.
@@ -627,7 +627,7 @@ public:
public:
// Initialize the hls by handler and source.
- virtual srs_error_t initialize(SrsOriginHub *h, SrsRequest *r);
+ virtual srs_error_t initialize(SrsOriginHub *h, ISrsRequest *r);
// Publish stream event, continue to write the m3u8,
// for the muxer object not destroyed.
// @param fetch_sequence_header whether fetch sequence from source.
diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp
index 82031a3e3..ff639dd15 100644
--- a/trunk/src/app/srs_app_http_api.hpp
+++ b/trunk/src/app/srs_app_http_api.hpp
@@ -16,7 +16,7 @@ class SrsServer;
class SrsRtcServer;
class SrsJsonObject;
class SrsSdp;
-class SrsRequest;
+class ISrsRequest;
class ISrsHttpResponseWriter;
class SrsHttpConn;
diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp
index 22f7edcb1..fcf41aa59 100644
--- a/trunk/src/app/srs_app_http_conn.cpp
+++ b/trunk/src/app/srs_app_http_conn.cpp
@@ -154,9 +154,9 @@ srs_error_t SrsHttpConn::do_cycle()
}
// process all http messages.
- SrsRequest *last_req_raw = NULL;
+ ISrsRequest *last_req_raw = NULL;
err = process_requests(&last_req_raw);
- SrsUniquePtr last_req(last_req_raw);
+ SrsUniquePtr last_req(last_req_raw);
srs_error_t r0 = srs_success;
if ((r0 = on_disconnect(last_req.get())) != srs_success) {
@@ -167,7 +167,7 @@ srs_error_t SrsHttpConn::do_cycle()
return err;
}
-srs_error_t SrsHttpConn::process_requests(SrsRequest **preq)
+srs_error_t SrsHttpConn::process_requests(ISrsRequest **preq)
{
srs_error_t err = srs_success;
@@ -236,7 +236,7 @@ srs_error_t SrsHttpConn::process_request(ISrsHttpResponseWriter *w, ISrsHttpMess
return err;
}
-srs_error_t SrsHttpConn::on_disconnect(SrsRequest *req)
+srs_error_t SrsHttpConn::on_disconnect(ISrsRequest *req)
{
// TODO: FIXME: Implements it.
return srs_success;
@@ -539,12 +539,12 @@ srs_error_t SrsHttpServer::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage
return http_static->mux.serve_http(w, r);
}
-srs_error_t SrsHttpServer::http_mount(SrsRequest *r)
+srs_error_t SrsHttpServer::http_mount(ISrsRequest *r)
{
return http_stream->http_mount(r);
}
-void SrsHttpServer::http_unmount(SrsRequest *r)
+void SrsHttpServer::http_unmount(ISrsRequest *r)
{
http_stream->http_unmount(r);
}
diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp
index f27011d28..3bb3a6e3b 100644
--- a/trunk/src/app/srs_app_http_conn.hpp
+++ b/trunk/src/app/srs_app_http_conn.hpp
@@ -22,7 +22,7 @@
class SrsServer;
class SrsLiveSource;
-class SrsRequest;
+class ISrsRequest;
class SrsLiveConsumer;
class SrsStSocket;
class SrsHttpParser;
@@ -30,7 +30,6 @@ class ISrsHttpMessage;
class SrsHttpHandler;
class SrsMessageQueue;
class SrsSharedPtrMessage;
-class SrsRequest;
class SrsFastStream;
class SrsHttpUri;
class SrsHttpMessage;
@@ -104,12 +103,12 @@ public:
private:
virtual srs_error_t do_cycle();
- virtual srs_error_t process_requests(SrsRequest **preq);
+ virtual srs_error_t process_requests(ISrsRequest **preq);
virtual srs_error_t process_request(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, int rid);
// When the connection disconnect, call this method.
// e.g. log msg of connection and report to other system.
// @param request: request which is converted by the last http message.
- virtual srs_error_t on_disconnect(SrsRequest *req);
+ virtual srs_error_t on_disconnect(ISrsRequest *req);
public:
// Get the HTTP message handler.
@@ -202,8 +201,8 @@ public:
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
public:
- virtual srs_error_t http_mount(SrsRequest *r);
- virtual void http_unmount(SrsRequest *r);
+ virtual srs_error_t http_mount(ISrsRequest *r);
+ virtual void http_unmount(ISrsRequest *r);
};
#endif
diff --git a/trunk/src/app/srs_app_http_hooks.cpp b/trunk/src/app/srs_app_http_hooks.cpp
index cad37ec60..17ebb473e 100644
--- a/trunk/src/app/srs_app_http_hooks.cpp
+++ b/trunk/src/app/srs_app_http_hooks.cpp
@@ -52,7 +52,7 @@ SrsHttpHooks::~SrsHttpHooks()
{
}
-srs_error_t SrsHttpHooks::on_connect(string url, SrsRequest *req)
+srs_error_t SrsHttpHooks::on_connect(string url, ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -88,7 +88,7 @@ srs_error_t SrsHttpHooks::on_connect(string url, SrsRequest *req)
return err;
}
-void SrsHttpHooks::on_close(string url, SrsRequest *req, int64_t send_bytes, int64_t recv_bytes)
+void SrsHttpHooks::on_close(string url, ISrsRequest *req, int64_t send_bytes, int64_t recv_bytes)
{
srs_error_t err = srs_success;
@@ -125,7 +125,7 @@ void SrsHttpHooks::on_close(string url, SrsRequest *req, int64_t send_bytes, int
return;
}
-srs_error_t SrsHttpHooks::on_publish(string url, SrsRequest *req)
+srs_error_t SrsHttpHooks::on_publish(string url, ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -166,7 +166,7 @@ srs_error_t SrsHttpHooks::on_publish(string url, SrsRequest *req)
return err;
}
-void SrsHttpHooks::on_unpublish(string url, SrsRequest *req)
+void SrsHttpHooks::on_unpublish(string url, ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -210,7 +210,7 @@ void SrsHttpHooks::on_unpublish(string url, SrsRequest *req)
return;
}
-srs_error_t SrsHttpHooks::on_play(string url, SrsRequest *req)
+srs_error_t SrsHttpHooks::on_play(string url, ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -252,7 +252,7 @@ srs_error_t SrsHttpHooks::on_play(string url, SrsRequest *req)
return err;
}
-void SrsHttpHooks::on_stop(string url, SrsRequest *req)
+void SrsHttpHooks::on_stop(string url, ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -296,7 +296,7 @@ void SrsHttpHooks::on_stop(string url, SrsRequest *req)
return;
}
-srs_error_t SrsHttpHooks::on_dvr(SrsContextId c, string url, SrsRequest *req, string file)
+srs_error_t SrsHttpHooks::on_dvr(SrsContextId c, string url, ISrsRequest *req, string file)
{
srs_error_t err = srs_success;
@@ -341,7 +341,7 @@ srs_error_t SrsHttpHooks::on_dvr(SrsContextId c, string url, SrsRequest *req, st
return err;
}
-srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, SrsRequest *req, string file, string ts_url, string m3u8, string m3u8_url, int sn, srs_utime_t duration)
+srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, ISrsRequest *req, string file, string ts_url, string m3u8, string m3u8_url, int sn, srs_utime_t duration)
{
srs_error_t err = srs_success;
@@ -396,7 +396,7 @@ srs_error_t SrsHttpHooks::on_hls(SrsContextId c, string url, SrsRequest *req, st
return err;
}
-srs_error_t SrsHttpHooks::on_hls_notify(SrsContextId c, std::string url, SrsRequest *req, std::string ts_url, int nb_notify)
+srs_error_t SrsHttpHooks::on_hls_notify(SrsContextId c, std::string url, ISrsRequest *req, std::string ts_url, int nb_notify)
{
srs_error_t err = srs_success;
@@ -520,7 +520,7 @@ srs_error_t SrsHttpHooks::discover_co_workers(string url, string &host, int &por
return err;
}
-srs_error_t SrsHttpHooks::on_forward_backend(string url, SrsRequest *req, std::vector &rtmp_urls)
+srs_error_t SrsHttpHooks::on_forward_backend(string url, ISrsRequest *req, std::vector &rtmp_urls)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_http_hooks.hpp b/trunk/src/app/srs_app_http_hooks.hpp
index 78e17ee05..29ec38b40 100644
--- a/trunk/src/app/srs_app_http_hooks.hpp
+++ b/trunk/src/app/srs_app_http_hooks.hpp
@@ -14,7 +14,7 @@
class SrsHttpUri;
class SrsStSocket;
-class SrsRequest;
+class ISrsRequest;
class SrsHttpParser;
class SrsHttpClient;
@@ -41,14 +41,14 @@ public:
// @param url The HTTP callback URL for publish validation. If empty, hook is ignored.
// @param req The publish request information including stream details.
// @return srs_success if publishing is allowed, error otherwise to reject publishing.
- virtual srs_error_t on_publish(std::string url, SrsRequest *req) = 0;
+ virtual srs_error_t on_publish(std::string url, ISrsRequest *req) = 0;
// Stream stop publishing notification hook.
// Called when a client (encoder) stops publishing a stream.
// This is a notification-only hook that cannot prevent the unpublishing.
// @param url The HTTP callback URL for unpublish notification. If empty, hook is ignored.
// @param req The unpublish request information.
- virtual void on_unpublish(std::string url, SrsRequest *req) = 0;
+ virtual void on_unpublish(std::string url, ISrsRequest *req) = 0;
// Stream start playing validation hook.
// Called when a client attempts to start playing/subscribing to a stream.
@@ -56,14 +56,14 @@ public:
// @param url The HTTP callback URL for play validation. If empty, hook is ignored.
// @param req The play request information including stream details.
// @return srs_success if playing is allowed, error otherwise to reject playing.
- virtual srs_error_t on_play(std::string url, SrsRequest *req) = 0;
+ virtual srs_error_t on_play(std::string url, ISrsRequest *req) = 0;
// Stream stop playing notification hook.
// Called when a client stops playing/subscribing to a stream.
// This is a notification-only hook that cannot prevent the stop operation.
// @param url The HTTP callback URL for stop notification. If empty, hook is ignored.
// @param req The stop request information.
- virtual void on_stop(std::string url, SrsRequest *req) = 0;
+ virtual void on_stop(std::string url, ISrsRequest *req) = 0;
public:
// DVR file completion notification hook.
@@ -75,7 +75,7 @@ public:
// @param req The original stream request information.
// @param file The completed DVR file path (can be relative or absolute).
// @return srs_success if processing succeeds, error otherwise (logged but doesn't affect DVR).
- virtual srs_error_t on_dvr(SrsContextId cid, std::string url, SrsRequest *req, std::string file) = 0;
+ virtual srs_error_t on_dvr(SrsContextId cid, std::string url, ISrsRequest *req, std::string file) = 0;
public:
// HLS segment completion notification hook.
@@ -92,7 +92,7 @@ public:
// @param sn The sequence number of the TS segment in the HLS playlist.
// @param duration The segment duration in microseconds (srs_utime_t).
// @return srs_success if processing succeeds, error otherwise (logged but doesn't affect HLS).
- virtual srs_error_t on_hls(SrsContextId cid, std::string url, SrsRequest *req, std::string file, std::string ts_url,
+ virtual srs_error_t on_hls(SrsContextId cid, std::string url, ISrsRequest *req, std::string file, std::string ts_url,
std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration) = 0;
// HLS segment notification hook with custom URL template.
@@ -105,7 +105,7 @@ public:
// @param ts_url The TS segment URL to replace [ts_url] variable in the callback URL.
// @param nb_notify Maximum bytes to read from the notification server response.
// @return srs_success if processing succeeds, error otherwise (logged but doesn't affect HLS).
- virtual srs_error_t on_hls_notify(SrsContextId cid, std::string url, SrsRequest *req, std::string ts_url, int nb_notify) = 0;
+ virtual srs_error_t on_hls_notify(SrsContextId cid, std::string url, ISrsRequest *req, std::string ts_url, int nb_notify) = 0;
public:
// Origin cluster co-worker discovery hook.
@@ -125,7 +125,7 @@ public:
// @param req The publish request information.
// @param rtmp_urls Output parameter to receive the list of RTMP URLs for forwarding.
// @return srs_success if backends are discovered, error otherwise.
- virtual srs_error_t on_forward_backend(std::string url, SrsRequest *req, std::vector &rtmp_urls) = 0;
+ virtual srs_error_t on_forward_backend(std::string url, ISrsRequest *req, std::vector &rtmp_urls) = 0;
// Deprecated hooks.
public:
@@ -135,7 +135,7 @@ public:
// @param url The HTTP callback URL for client validation. If empty, hook is ignored.
// @param req The client request information including IP, vhost, app, stream, etc.
// @return srs_success if connection is allowed, error otherwise to reject connection.
- virtual srs_error_t on_connect(std::string url, SrsRequest *req) = 0;
+ virtual srs_error_t on_connect(std::string url, ISrsRequest *req) = 0;
// Client disconnection notification hook.
// Called when a client disconnects from the SRS server.
@@ -144,7 +144,7 @@ public:
// @param req The client request information.
// @param send_bytes Total bytes sent to the client during the session.
// @param recv_bytes Total bytes received from the client during the session.
- virtual void on_close(std::string url, SrsRequest *req, int64_t send_bytes, int64_t recv_bytes) = 0;
+ virtual void on_close(std::string url, ISrsRequest *req, int64_t send_bytes, int64_t recv_bytes) = 0;
};
class SrsHttpHooks : public ISrsHttpHooks
@@ -154,18 +154,18 @@ public:
virtual ~SrsHttpHooks();
public:
- srs_error_t on_connect(std::string url, SrsRequest *req);
- void on_close(std::string url, SrsRequest *req, int64_t send_bytes, int64_t recv_bytes);
- srs_error_t on_publish(std::string url, SrsRequest *req);
- void on_unpublish(std::string url, SrsRequest *req);
- srs_error_t on_play(std::string url, SrsRequest *req);
- void on_stop(std::string url, SrsRequest *req);
- srs_error_t on_dvr(SrsContextId cid, std::string url, SrsRequest *req, std::string file);
- srs_error_t on_hls(SrsContextId cid, std::string url, SrsRequest *req, std::string file, std::string ts_url,
+ srs_error_t on_connect(std::string url, ISrsRequest *req);
+ void on_close(std::string url, ISrsRequest *req, int64_t send_bytes, int64_t recv_bytes);
+ srs_error_t on_publish(std::string url, ISrsRequest *req);
+ void on_unpublish(std::string url, ISrsRequest *req);
+ srs_error_t on_play(std::string url, ISrsRequest *req);
+ void on_stop(std::string url, ISrsRequest *req);
+ srs_error_t on_dvr(SrsContextId cid, std::string url, ISrsRequest *req, std::string file);
+ srs_error_t on_hls(SrsContextId cid, std::string url, ISrsRequest *req, std::string file, std::string ts_url,
std::string m3u8, std::string m3u8_url, int sn, srs_utime_t duration);
- srs_error_t on_hls_notify(SrsContextId cid, std::string url, SrsRequest *req, std::string ts_url, int nb_notify);
+ srs_error_t on_hls_notify(SrsContextId cid, std::string url, ISrsRequest *req, std::string ts_url, int nb_notify);
srs_error_t discover_co_workers(std::string url, std::string &host, int &port);
- srs_error_t on_forward_backend(std::string url, SrsRequest *req, std::vector &rtmp_urls);
+ srs_error_t on_forward_backend(std::string url, ISrsRequest *req, std::vector &rtmp_urls);
private:
srs_error_t do_post(SrsHttpClient *hc, std::string url, std::string req, int &code, std::string &res);
diff --git a/trunk/src/app/srs_app_http_static.cpp b/trunk/src/app/srs_app_http_static.cpp
index 44c1c0794..8020080a3 100644
--- a/trunk/src/app/srs_app_http_static.cpp
+++ b/trunk/src/app/srs_app_http_static.cpp
@@ -78,7 +78,7 @@ SrsHlsStream::~SrsHlsStream()
srs_freep(security_);
}
-srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsFileReaderFactory *factory, string fullpath, SrsRequest *req, bool *served)
+srs_error_t SrsHlsStream::serve_m3u8_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsFileReaderFactory *factory, string fullpath, ISrsRequest *req, bool *served)
{
srs_error_t err = srs_success;
@@ -144,7 +144,7 @@ void SrsHlsStream::on_serve_ts_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r
SrsStatistic::instance()->kbps_add_delta(ctx, delta);
}
-srs_error_t SrsHlsStream::serve_new_session(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsRequest *req, std::string &ctx)
+srs_error_t SrsHlsStream::serve_new_session(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsRequest *req, std::string &ctx)
{
srs_error_t err = srs_success;
@@ -279,7 +279,7 @@ bool SrsHlsStream::ctx_is_exist(std::string ctx)
return (map_ctx_info_.find(ctx) != map_ctx_info_.end());
}
-void SrsHlsStream::alive(std::string ctx, SrsRequest *req)
+void SrsHlsStream::alive(std::string ctx, ISrsRequest *req)
{
std::map::iterator it = map_ctx_info_.find(ctx);
@@ -308,7 +308,7 @@ void SrsHlsStream::alive(std::string ctx, SrsRequest *req)
}
}
-srs_error_t SrsHlsStream::http_hooks_on_play(SrsRequest *req)
+srs_error_t SrsHlsStream::http_hooks_on_play(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -341,7 +341,7 @@ srs_error_t SrsHlsStream::http_hooks_on_play(SrsRequest *req)
return err;
}
-void SrsHlsStream::http_hooks_on_stop(SrsRequest *req)
+void SrsHlsStream::http_hooks_on_stop(ISrsRequest *req)
{
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
return;
@@ -552,7 +552,7 @@ srs_error_t SrsVodStream::serve_m3u8_ctx(ISrsHttpResponseWriter *w, ISrsHttpMess
SrsHttpMessage *hr = dynamic_cast(r);
srs_assert(hr);
- SrsUniquePtr req(hr->to_request(hr->host())->as_http());
+ SrsUniquePtr req(hr->to_request(hr->host())->as_http());
// discovery vhost, resolve the vhost from config
SrsConfDirective *parsed_vhost = _srs_config->get_vhost(req->vhost);
diff --git a/trunk/src/app/srs_app_http_static.hpp b/trunk/src/app/srs_app_http_static.hpp
index e5334a977..97df3d66a 100644
--- a/trunk/src/app/srs_app_http_static.hpp
+++ b/trunk/src/app/srs_app_http_static.hpp
@@ -18,7 +18,7 @@ class SrsHlsVirtualConn : public ISrsExpire
{
public:
srs_utime_t request_time;
- SrsRequest *req;
+ ISrsRequest *req;
std::string ctx;
bool interrupt;
@@ -42,16 +42,16 @@ public:
virtual ~SrsHlsStream();
public:
- virtual srs_error_t serve_m3u8_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsFileReaderFactory *factory, std::string fullpath, SrsRequest *req, bool *served);
+ virtual srs_error_t serve_m3u8_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsFileReaderFactory *factory, std::string fullpath, ISrsRequest *req, bool *served);
virtual void on_serve_ts_ctx(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
private:
- srs_error_t serve_new_session(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, SrsRequest *req, std::string &ctx);
+ srs_error_t serve_new_session(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsRequest *req, std::string &ctx);
srs_error_t serve_exists_session(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, ISrsFileReaderFactory *factory, std::string fullpath);
bool ctx_is_exist(std::string ctx);
- void alive(std::string ctx, SrsRequest *req);
- srs_error_t http_hooks_on_play(SrsRequest *req);
- void http_hooks_on_stop(SrsRequest *req);
+ void alive(std::string ctx, ISrsRequest *req);
+ srs_error_t http_hooks_on_play(ISrsRequest *req);
+ void http_hooks_on_stop(ISrsRequest *req);
bool is_interrupt(std::string id);
// interface ISrsFastTimer
private:
diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp
index 587ba941b..ecf5bba5e 100644
--- a/trunk/src/app/srs_app_http_stream.cpp
+++ b/trunk/src/app/srs_app_http_stream.cpp
@@ -40,7 +40,7 @@ using namespace std;
#include
#include
-SrsBufferCache::SrsBufferCache(SrsServer *s, SrsRequest *r)
+SrsBufferCache::SrsBufferCache(SrsServer *s, ISrsRequest *r)
{
req = r->copy()->as_http();
queue = new SrsMessageQueue(true);
@@ -59,7 +59,7 @@ SrsBufferCache::~SrsBufferCache()
srs_freep(req);
}
-srs_error_t SrsBufferCache::update_auth(SrsRequest *r)
+srs_error_t SrsBufferCache::update_auth(ISrsRequest *r)
{
srs_freep(req);
req = r->copy();
@@ -133,7 +133,7 @@ srs_error_t SrsBufferCache::cycle()
srs_error_t err = srs_success;
SrsSharedPtr live_source;
- if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) {
+ if ((err = _srs_sources->fetch_or_create(req, live_source)) != srs_success) {
return srs_error_wrap(err, "source create");
}
srs_assert(live_source.get() != NULL);
@@ -596,7 +596,7 @@ srs_error_t SrsBufferWriter::writev(const iovec *iov, int iovcnt, ssize_t *pnwri
return writer->writev(iov, iovcnt, pnwrite);
}
-SrsLiveStream::SrsLiveStream(SrsServer *s, SrsRequest *r, SrsBufferCache *c)
+SrsLiveStream::SrsLiveStream(SrsServer *s, ISrsRequest *r, SrsBufferCache *c)
{
cache = c;
req = r->copy()->as_http();
@@ -613,7 +613,7 @@ SrsLiveStream::~SrsLiveStream()
srs_assert(viewers_.empty());
}
-srs_error_t SrsLiveStream::update_auth(SrsRequest *r)
+srs_error_t SrsLiveStream::update_auth(ISrsRequest *r)
{
srs_freep(req);
req = r->copy()->as_http();
@@ -684,7 +684,7 @@ srs_error_t SrsLiveStream::serve_http_impl(ISrsHttpResponseWriter *w, ISrsHttpMe
// Always try to create the source, because http handler won't create it.
SrsSharedPtr live_source;
- if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) {
+ if ((err = _srs_sources->fetch_or_create(req, live_source)) != srs_success) {
return srs_error_wrap(err, "source create");
}
srs_assert(live_source.get() != NULL);
@@ -887,7 +887,7 @@ srs_error_t SrsLiveStream::http_hooks_on_play(ISrsHttpMessage *r)
// Create request to report for the specified connection.
SrsHttpMessage *hr = dynamic_cast(r);
- SrsUniquePtr nreq(hr->to_request(req->vhost));
+ SrsUniquePtr nreq(hr->to_request(req->vhost));
// the http hooks will cause context switch,
// so we must copy all hooks for the on_connect may freed.
@@ -922,7 +922,7 @@ void SrsLiveStream::http_hooks_on_stop(ISrsHttpMessage *r)
// Create request to report for the specified connection.
SrsHttpMessage *hr = dynamic_cast(r);
- SrsUniquePtr nreq(hr->to_request(req->vhost));
+ SrsUniquePtr nreq(hr->to_request(req->vhost));
// the http hooks will cause context switch,
// so we must copy all hooks for the on_connect may freed.
@@ -1067,7 +1067,7 @@ srs_error_t SrsHttpStreamServer::initialize()
}
// TODO: FIXME: rename for HTTP FLV mount.
-srs_error_t SrsHttpStreamServer::http_mount(SrsRequest *r)
+srs_error_t SrsHttpStreamServer::http_mount(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -1144,7 +1144,7 @@ srs_error_t SrsHttpStreamServer::http_mount(SrsRequest *r)
return err;
}
-void SrsHttpStreamServer::http_unmount(SrsRequest *r)
+void SrsHttpStreamServer::http_unmount(ISrsRequest *r)
{
std::string sid = r->get_stream_url();
@@ -1245,7 +1245,7 @@ srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage *request, ISrsHttpHandle
srs_assert(hreq);
// hijack for entry.
- SrsUniquePtr r(hreq->to_request(vhost->arg0()));
+ SrsUniquePtr r(hreq->to_request(vhost->arg0()));
std::string sid = r->get_stream_url();
// check whether the http remux is enabled,
diff --git a/trunk/src/app/srs_app_http_stream.hpp b/trunk/src/app/srs_app_http_stream.hpp
index 0d3c8f795..352ce4cfa 100644
--- a/trunk/src/app/srs_app_http_stream.hpp
+++ b/trunk/src/app/srs_app_http_stream.hpp
@@ -29,13 +29,13 @@ private:
private:
SrsMessageQueue *queue;
- SrsRequest *req;
+ ISrsRequest *req;
SrsCoroutine *trd;
public:
- SrsBufferCache(SrsServer *s, SrsRequest *r);
+ SrsBufferCache(SrsServer *s, ISrsRequest *r);
virtual ~SrsBufferCache();
- virtual srs_error_t update_auth(SrsRequest *r);
+ virtual srs_error_t update_auth(ISrsRequest *r);
public:
virtual srs_error_t start();
@@ -209,7 +209,7 @@ public:
class SrsLiveStream : public ISrsHttpHandler, public ISrsExpire
{
private:
- SrsRequest *req;
+ ISrsRequest *req;
SrsBufferCache *cache;
SrsSecurity *security_;
SrsServer *server_;
@@ -219,9 +219,9 @@ private:
std::vector viewers_;
public:
- SrsLiveStream(SrsServer *s, SrsRequest *r, SrsBufferCache *c);
+ SrsLiveStream(SrsServer *s, ISrsRequest *r, SrsBufferCache *c);
virtual ~SrsLiveStream();
- virtual srs_error_t update_auth(SrsRequest *r);
+ virtual srs_error_t update_auth(ISrsRequest *r);
public:
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
@@ -252,7 +252,7 @@ private:
public:
// We will free the request.
- SrsRequest *req;
+ ISrsRequest *req;
public:
// For template, the mount contains variables.
@@ -298,8 +298,8 @@ public:
public:
// HTTP flv/ts/mp3/aac stream
- virtual srs_error_t http_mount(SrsRequest *r);
- virtual void http_unmount(SrsRequest *r);
+ virtual srs_error_t http_mount(ISrsRequest *r);
+ virtual void http_unmount(ISrsRequest *r);
// Interface ISrsHttpMatchHijacker
public:
virtual srs_error_t hijack(ISrsHttpMessage *request, ISrsHttpHandler **ph);
diff --git a/trunk/src/app/srs_app_mpegts_udp.hpp b/trunk/src/app/srs_app_mpegts_udp.hpp
index a868cb9bb..c8cd8faee 100644
--- a/trunk/src/app/srs_app_mpegts_udp.hpp
+++ b/trunk/src/app/srs_app_mpegts_udp.hpp
@@ -19,7 +19,7 @@ class SrsConfDirective;
class SrsSimpleStream;
class SrsRtmpClient;
class SrsStSocket;
-class SrsRequest;
+class ISrsRequest;
class SrsRawH264Stream;
class SrsSharedPtrMessage;
class SrsRawAacStream;
diff --git a/trunk/src/app/srs_app_ng_exec.cpp b/trunk/src/app/srs_app_ng_exec.cpp
index 504baf845..b79ba2bed 100644
--- a/trunk/src/app/srs_app_ng_exec.cpp
+++ b/trunk/src/app/srs_app_ng_exec.cpp
@@ -34,7 +34,7 @@ SrsNgExec::~SrsNgExec()
srs_freep(pprint);
}
-srs_error_t SrsNgExec::on_publish(SrsRequest *req)
+srs_error_t SrsNgExec::on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -120,7 +120,7 @@ srs_error_t SrsNgExec::do_cycle()
return err;
}
-srs_error_t SrsNgExec::parse_exec_publish(SrsRequest *req)
+srs_error_t SrsNgExec::parse_exec_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -193,7 +193,7 @@ void SrsNgExec::show_exec_log_message()
}
}
-string SrsNgExec::parse(SrsRequest *req, string tmpl)
+string SrsNgExec::parse(ISrsRequest *req, string tmpl)
{
string output = tmpl;
diff --git a/trunk/src/app/srs_app_ng_exec.hpp b/trunk/src/app/srs_app_ng_exec.hpp
index a9a579008..da0579f8d 100644
--- a/trunk/src/app/srs_app_ng_exec.hpp
+++ b/trunk/src/app/srs_app_ng_exec.hpp
@@ -14,7 +14,7 @@
#include
-class SrsRequest;
+class ISrsRequest;
class SrsPithyPrint;
class SrsProcess;
@@ -34,7 +34,7 @@ public:
virtual ~SrsNgExec();
public:
- virtual srs_error_t on_publish(SrsRequest *req);
+ virtual srs_error_t on_publish(ISrsRequest *req);
virtual void on_unpublish();
// Interface ISrsReusableThreadHandler.
public:
@@ -44,10 +44,10 @@ private:
virtual srs_error_t do_cycle();
private:
- virtual srs_error_t parse_exec_publish(SrsRequest *req);
+ virtual srs_error_t parse_exec_publish(ISrsRequest *req);
virtual void clear_exec_publish();
virtual void show_exec_log_message();
- virtual std::string parse(SrsRequest *req, std::string tmpl);
+ virtual std::string parse(ISrsRequest *req, std::string tmpl);
};
#endif
diff --git a/trunk/src/app/srs_app_recv_thread.cpp b/trunk/src/app/srs_app_recv_thread.cpp
index a148ad412..8f8253000 100644
--- a/trunk/src/app/srs_app_recv_thread.cpp
+++ b/trunk/src/app/srs_app_recv_thread.cpp
@@ -257,7 +257,7 @@ void SrsQueueRecvThread::on_stop()
rtmp->set_auto_response(true);
}
-SrsPublishRecvThread::SrsPublishRecvThread(SrsRtmpServer *rtmp_sdk, SrsRequest *_req,
+SrsPublishRecvThread::SrsPublishRecvThread(SrsRtmpServer *rtmp_sdk, ISrsRequest *_req,
int mr_sock_fd, srs_utime_t tm, SrsRtmpConn *conn, SrsSharedPtr source, SrsContextId parent_cid)
: trd(this, rtmp_sdk, tm, parent_cid)
{
diff --git a/trunk/src/app/srs_app_recv_thread.hpp b/trunk/src/app/srs_app_recv_thread.hpp
index b32ab2d2a..037aa6692 100644
--- a/trunk/src/app/srs_app_recv_thread.hpp
+++ b/trunk/src/app/srs_app_recv_thread.hpp
@@ -22,7 +22,7 @@ class SrsRtmpServer;
class SrsCommonMessage;
class SrsRtmpConn;
class SrsLiveSource;
-class SrsRequest;
+class ISrsRequest;
class SrsLiveConsumer;
class SrsHttpConn;
class SrsHttpxConn;
@@ -141,7 +141,7 @@ private:
uint32_t nn_msgs_for_yield_;
SrsRecvThread trd;
SrsRtmpServer *rtmp;
- SrsRequest *req;
+ ISrsRequest *req;
// The msgs already got.
int64_t _nb_msgs;
// The video frames we got.
@@ -165,7 +165,7 @@ private:
SrsContextId ncid;
public:
- SrsPublishRecvThread(SrsRtmpServer *rtmp_sdk, SrsRequest *_req,
+ SrsPublishRecvThread(SrsRtmpServer *rtmp_sdk, ISrsRequest *_req,
int mr_sock_fd, srs_utime_t tm, SrsRtmpConn *conn, SrsSharedPtr source, SrsContextId parent_cid);
virtual ~SrsPublishRecvThread();
diff --git a/trunk/src/app/srs_app_rtc_api.cpp b/trunk/src/app/srs_app_rtc_api.cpp
index 36e681985..0c6477b8c 100644
--- a/trunk/src/app/srs_app_rtc_api.cpp
+++ b/trunk/src/app/srs_app_rtc_api.cpp
@@ -292,7 +292,7 @@ srs_error_t SrsGoApiRtcPlay::check_remote_sdp(const SrsSdp &remote_sdp)
return err;
}
-srs_error_t SrsGoApiRtcPlay::http_hooks_on_play(SrsRequest *req)
+srs_error_t SrsGoApiRtcPlay::http_hooks_on_play(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -567,7 +567,7 @@ srs_error_t SrsGoApiRtcPublish::check_remote_sdp(const SrsSdp &remote_sdp)
return err;
}
-srs_error_t SrsGoApiRtcPublish::http_hooks_on_publish(SrsRequest *req)
+srs_error_t SrsGoApiRtcPublish::http_hooks_on_publish(ISrsRequest *req)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_rtc_api.hpp b/trunk/src/app/srs_app_rtc_api.hpp
index 24805503c..bc9aea12e 100644
--- a/trunk/src/app/srs_app_rtc_api.hpp
+++ b/trunk/src/app/srs_app_rtc_api.hpp
@@ -12,7 +12,7 @@
#include
class SrsRtcServer;
-class SrsRequest;
+class ISrsRequest;
class SrsSdp;
class SrsRtcUserConfig;
@@ -39,7 +39,7 @@ private:
srs_error_t check_remote_sdp(const SrsSdp &remote_sdp);
private:
- virtual srs_error_t http_hooks_on_play(SrsRequest *req);
+ virtual srs_error_t http_hooks_on_play(ISrsRequest *req);
};
class SrsGoApiRtcPublish : public ISrsHttpHandler
@@ -65,7 +65,7 @@ private:
srs_error_t check_remote_sdp(const SrsSdp &remote_sdp);
private:
- virtual srs_error_t http_hooks_on_publish(SrsRequest *req);
+ virtual srs_error_t http_hooks_on_publish(ISrsRequest *req);
};
// See https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp
index 38ebed95b..e1ddcbe48 100644
--- a/trunk/src/app/srs_app_rtc_conn.cpp
+++ b/trunk/src/app/srs_app_rtc_conn.cpp
@@ -364,7 +364,7 @@ srs_error_t SrsRtcPLIWorker::cycle()
return err;
}
-SrsRtcAsyncCallOnStop::SrsRtcAsyncCallOnStop(SrsContextId c, SrsRequest *r)
+SrsRtcAsyncCallOnStop::SrsRtcAsyncCallOnStop(SrsContextId c, ISrsRequest *r)
{
cid = c;
req = r->copy();
@@ -471,7 +471,7 @@ SrsRtcPlayStream::~SrsRtcPlayStream()
stat->on_disconnect(cid_.c_str(), srs_success);
}
-srs_error_t SrsRtcPlayStream::initialize(SrsRequest *req, std::map sub_relations)
+srs_error_t SrsRtcPlayStream::initialize(ISrsRequest *req, std::map sub_relations)
{
srs_error_t err = srs_success;
@@ -1022,7 +1022,7 @@ srs_error_t SrsRtcPublishTwccTimer::on_timer(srs_utime_t interval)
return err;
}
-SrsRtcAsyncCallOnUnpublish::SrsRtcAsyncCallOnUnpublish(SrsContextId c, SrsRequest *r)
+SrsRtcAsyncCallOnUnpublish::SrsRtcAsyncCallOnUnpublish(SrsContextId c, ISrsRequest *r)
{
cid = c;
req = r->copy();
@@ -1134,7 +1134,7 @@ SrsRtcPublishStream::~SrsRtcPublishStream()
stat->on_disconnect(cid_.c_str(), srs_success);
}
-srs_error_t SrsRtcPublishStream::initialize(SrsRequest *r, SrsRtcSourceDescription *stream_desc)
+srs_error_t SrsRtcPublishStream::initialize(ISrsRequest *r, SrsRtcSourceDescription *stream_desc)
{
srs_error_t err = srs_success;
@@ -1226,7 +1226,7 @@ srs_error_t SrsRtcPublishStream::initialize(SrsRequest *r, SrsRtcSourceDescripti
#if defined(SRS_FFMPEG_FIT)
bool rtc_to_rtmp = _srs_config->get_rtc_to_rtmp(req_->vhost);
if (rtc_to_rtmp) {
- if ((err = _srs_sources->fetch_or_create(r, _srs_hybrid->srs()->instance(), live_source)) != srs_success) {
+ if ((err = _srs_sources->fetch_or_create(r, live_source)) != srs_success) {
return srs_error_wrap(err, "create source");
}
@@ -1937,7 +1937,7 @@ srs_error_t SrsRtcConnection::add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local
{
srs_error_t err = srs_success;
- SrsRequest *req = ruc->req_;
+ ISrsRequest *req = ruc->req_;
SrsUniquePtr stream_desc(new SrsRtcSourceDescription());
@@ -1978,7 +1978,7 @@ srs_error_t SrsRtcConnection::add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sd
{
srs_error_t err = srs_success;
- SrsRequest *req = ruc->req_;
+ ISrsRequest *req = ruc->req_;
std::map play_sub_relations;
if ((err = negotiate_play_capability(ruc, play_sub_relations)) != srs_success) {
@@ -2016,7 +2016,7 @@ srs_error_t SrsRtcConnection::add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sd
return err;
}
-srs_error_t SrsRtcConnection::initialize(SrsRequest *r, bool dtls, bool srtp, string username)
+srs_error_t SrsRtcConnection::initialize(ISrsRequest *r, bool dtls, bool srtp, string username)
{
srs_error_t err = srs_success;
@@ -2654,7 +2654,7 @@ srs_error_t SrsRtcConnection::negotiate_publish_capability(SrsRtcUserConfig *ruc
return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "stream description is NULL");
}
- SrsRequest *req = ruc->req_;
+ ISrsRequest *req = ruc->req_;
const SrsSdp &remote_sdp = ruc->remote_sdp_;
bool nack_enabled = _srs_config->get_rtc_nack_enabled(req->vhost);
@@ -2947,7 +2947,7 @@ srs_error_t SrsRtcConnection::negotiate_publish_capability(SrsRtcUserConfig *ruc
return err;
}
-srs_error_t SrsRtcConnection::generate_publish_local_sdp(SrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video)
+srs_error_t SrsRtcConnection::generate_publish_local_sdp(ISrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video)
{
srs_error_t err = srs_success;
@@ -3086,7 +3086,7 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRtcUserConfig *ruc, s
{
srs_error_t err = srs_success;
- SrsRequest *req = ruc->req_;
+ ISrsRequest *req = ruc->req_;
const SrsSdp &remote_sdp = ruc->remote_sdp_;
bool nack_enabled = _srs_config->get_rtc_nack_enabled(req->vhost);
@@ -3325,7 +3325,7 @@ void video_track_generate_play_offer(SrsRtcTrackDescription *track, string mid,
}
}
-srs_error_t SrsRtcConnection::generate_play_local_sdp(SrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video)
+srs_error_t SrsRtcConnection::generate_play_local_sdp(ISrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video)
{
srs_error_t err = srs_success;
@@ -3479,7 +3479,7 @@ srs_error_t SrsRtcConnection::generate_play_local_sdp_for_video(SrsSdp &local_sd
return err;
}
-srs_error_t SrsRtcConnection::create_player(SrsRequest *req, std::map sub_relations)
+srs_error_t SrsRtcConnection::create_player(ISrsRequest *req, std::map sub_relations)
{
srs_error_t err = srs_success;
@@ -3545,7 +3545,7 @@ srs_error_t SrsRtcConnection::create_player(SrsRequest *req, std::map source_;
// key: publish_ssrc, value: send track to process rtp/rtcp
std::map audio_tracks_;
@@ -266,7 +266,7 @@ public:
virtual ~SrsRtcPlayStream();
public:
- srs_error_t initialize(SrsRequest *request, std::map sub_relations);
+ srs_error_t initialize(ISrsRequest *request, std::map sub_relations);
// Interface ISrsRtcSourceChangeCallback
public:
void on_stream_change(SrsRtcSourceDescription *desc);
@@ -337,10 +337,10 @@ class SrsRtcAsyncCallOnUnpublish : public ISrsAsyncCallTask
{
private:
SrsContextId cid;
- SrsRequest *req;
+ ISrsRequest *req;
public:
- SrsRtcAsyncCallOnUnpublish(SrsContextId c, SrsRequest *r);
+ SrsRtcAsyncCallOnUnpublish(SrsContextId c, ISrsRequest *r);
virtual ~SrsRtcAsyncCallOnUnpublish();
public:
@@ -376,7 +376,7 @@ private:
SrsErrorPithyPrint *pli_epp;
private:
- SrsRequest *req_;
+ ISrsRequest *req_;
SrsSharedPtr source_;
// Simulators.
int nn_simulate_nack_drop;
@@ -399,7 +399,7 @@ public:
virtual ~SrsRtcPublishStream();
public:
- srs_error_t initialize(SrsRequest *req, SrsRtcSourceDescription *stream_desc);
+ srs_error_t initialize(ISrsRequest *req, SrsRtcSourceDescription *stream_desc);
srs_error_t start();
// Directly set the status of track, generally for init to set the default value.
void set_all_tracks_status(bool status);
@@ -516,7 +516,7 @@ private:
private:
// For each RTC session, we use a specified cid for debugging logs.
SrsContextId cid_;
- SrsRequest *req_;
+ ISrsRequest *req_;
SrsSdp remote_sdp;
SrsSdp local_sdp;
@@ -572,7 +572,7 @@ public:
public:
// Before initialize, user must set the local SDP, which is used to inititlize DTLS.
- srs_error_t initialize(SrsRequest *r, bool dtls, bool srtp, std::string username);
+ srs_error_t initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username);
srs_error_t on_rtp_cipher(char *data, int nb_data);
srs_error_t on_rtp_plaintext(char *data, int nb_data);
@@ -623,17 +623,17 @@ public:
private:
// publish media capabilitiy negotiate
srs_error_t negotiate_publish_capability(SrsRtcUserConfig *ruc, SrsRtcSourceDescription *stream_desc);
- srs_error_t generate_publish_local_sdp(SrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video);
+ srs_error_t generate_publish_local_sdp(ISrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video);
srs_error_t generate_publish_local_sdp_for_audio(SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc);
srs_error_t generate_publish_local_sdp_for_video(SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan);
// play media capabilitiy negotiate
// TODO: Use StreamDescription to negotiate and remove first negotiate_play_capability function
srs_error_t negotiate_play_capability(SrsRtcUserConfig *ruc, std::map &sub_relations);
- srs_error_t generate_play_local_sdp(SrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video);
+ srs_error_t generate_play_local_sdp(ISrsRequest *req, SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, bool audio_before_video);
srs_error_t generate_play_local_sdp_for_audio(SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, std::string cname);
srs_error_t generate_play_local_sdp_for_video(SrsSdp &local_sdp, SrsRtcSourceDescription *stream_desc, bool unified_plan, std::string cname);
- srs_error_t create_player(SrsRequest *request, std::map sub_relations);
- srs_error_t create_publisher(SrsRequest *request, SrsRtcSourceDescription *stream_desc);
+ srs_error_t create_player(ISrsRequest *request, std::map sub_relations);
+ srs_error_t create_publisher(ISrsRequest *request, SrsRtcSourceDescription *stream_desc);
};
#endif
diff --git a/trunk/src/app/srs_app_rtc_dtls.hpp b/trunk/src/app/srs_app_rtc_dtls.hpp
index 22b249559..c0316e80e 100644
--- a/trunk/src/app/srs_app_rtc_dtls.hpp
+++ b/trunk/src/app/srs_app_rtc_dtls.hpp
@@ -17,7 +17,7 @@
#include
-class SrsRequest;
+class ISrsRequest;
class SrsDtlsCertificate
{
diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp
index 4b7ddb9c0..d0003da97 100644
--- a/trunk/src/app/srs_app_rtc_server.cpp
+++ b/trunk/src/app/srs_app_rtc_server.cpp
@@ -500,7 +500,7 @@ srs_error_t SrsRtcServer::create_session(SrsRtcUserConfig *ruc, SrsSdp &local_sd
SrsContextId cid = _srs_context->get_id();
- SrsRequest *req = ruc->req_;
+ ISrsRequest *req = ruc->req_;
SrsSharedPtr source;
if ((err = _srs_rtc_sources->fetch_or_create(req, source)) != srs_success) {
@@ -527,7 +527,7 @@ srs_error_t SrsRtcServer::do_create_session(SrsRtcUserConfig *ruc, SrsSdp &local
{
srs_error_t err = srs_success;
- SrsRequest *req = ruc->req_;
+ ISrsRequest *req = ruc->req_;
// first add publisher/player for negotiate sdp media info
if (ruc->publish_) {
diff --git a/trunk/src/app/srs_app_rtc_server.hpp b/trunk/src/app/srs_app_rtc_server.hpp
index 1eda54e14..d1eed212f 100644
--- a/trunk/src/app/srs_app_rtc_server.hpp
+++ b/trunk/src/app/srs_app_rtc_server.hpp
@@ -22,7 +22,7 @@
class SrsRtcServer;
class SrsHourGlass;
class SrsRtcConnection;
-class SrsRequest;
+class ISrsRequest;
class SrsSdp;
class SrsRtcSource;
class SrsResourceManager;
@@ -68,7 +68,7 @@ public:
std::string token_;
// Generated data.
- SrsRequest *req_;
+ ISrsRequest *req_;
bool publish_;
bool dtls_;
bool srtp_;
diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp
index 7d3b7d5d9..8cb977127 100644
--- a/trunk/src/app/srs_app_rtc_source.cpp
+++ b/trunk/src/app/srs_app_rtc_source.cpp
@@ -290,43 +290,49 @@ srs_error_t SrsRtcSourceManager::notify(int event, srs_utime_t interval, srs_uti
return err;
}
-srs_error_t SrsRtcSourceManager::fetch_or_create(SrsRequest *r, SrsSharedPtr &pps)
+srs_error_t SrsRtcSourceManager::fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps)
{
srs_error_t err = srs_success;
- // Use lock to protect coroutine switch.
- // @bug https://github.com/ossrs/srs/issues/1230
- SrsLocker(lock);
+ bool created = false;
+ // Should never invoke any function during the locking.
+ if (true) {
+ // Use lock to protect coroutine switch.
+ // @bug https://github.com/ossrs/srs/issues/1230
+ SrsLocker(lock);
- string stream_url = r->get_stream_url();
- std::map >::iterator it = pool.find(stream_url);
+ string stream_url = r->get_stream_url();
+ std::map >::iterator it = pool.find(stream_url);
- if (it != pool.end()) {
- SrsSharedPtr source = it->second;
+ if (it != pool.end()) {
+ SrsSharedPtr source = it->second;
+ pps = source;
+ } else {
+ SrsSharedPtr source = SrsSharedPtr(new SrsRtcSource());
+ srs_trace("new rtc source, stream_url=%s", stream_url.c_str());
+ pps = source;
- // we always update the request of resource,
- // for origin auth is on, the token in request maybe invalid,
- // and we only need to update the token of request, it's simple.
- source->update_auth(r);
- pps = source;
-
- return err;
+ pool[stream_url] = source;
+ created = true;
+ }
}
- SrsSharedPtr source = SrsSharedPtr(new SrsRtcSource());
- srs_trace("new rtc source, stream_url=%s", stream_url.c_str());
-
- if ((err = source->initialize(r)) != srs_success) {
+ // Initialize source.
+ if (created && (err = pps->initialize(r)) != srs_success) {
return srs_error_wrap(err, "init source %s", r->get_stream_url().c_str());
}
- pool[stream_url] = source;
- pps = source;
+ // we always update the request of resource,
+ // for origin auth is on, the token in request maybe invalid,
+ // and we only need to update the token of request, it's simple.
+ if (!created) {
+ pps->update_auth(r);
+ }
return err;
}
-SrsSharedPtr SrsRtcSourceManager::fetch(SrsRequest *r)
+SrsSharedPtr SrsRtcSourceManager::fetch(ISrsRequest *r)
{
// Use lock to protect coroutine switch.
// @bug https://github.com/ossrs/srs/issues/1230
@@ -399,7 +405,19 @@ SrsRtcSource::~SrsRtcSource()
srs_trace("free rtc source id=[%s]", cid.c_str());
}
-srs_error_t SrsRtcSource::initialize(SrsRequest *r)
+// CRITICAL: This method is called AFTER the source has been added to the source pool
+// in the fetch_or_create pattern (see PR 4449).
+//
+// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches
+// before completing the basic field setup.
+//
+// If context switches occur before all fields are properly initialized, other coroutines
+// accessing this source from the pool may encounter uninitialized state, leading to crashes
+// or undefined behavior.
+//
+// This prevents the race condition where multiple coroutines could create duplicate sources
+// for the same stream when context switches occurred during initialization.
+srs_error_t SrsRtcSource::initialize(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -499,7 +517,7 @@ void SrsRtcSource::init_for_play_before_publishing()
set_stream_desc(stream_desc.get());
}
-void SrsRtcSource::update_auth(SrsRequest *r)
+void SrsRtcSource::update_auth(ISrsRequest *r)
{
req->update_auth(r);
}
@@ -937,7 +955,7 @@ srs_error_t SrsRtcRtpBuilder::initialize_video_track(SrsVideoCodecId codec)
return err;
}
-srs_error_t SrsRtcRtpBuilder::initialize(SrsRequest *r)
+srs_error_t SrsRtcRtpBuilder::initialize(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -1733,7 +1751,7 @@ SrsRtcFrameBuilder::~SrsRtcFrameBuilder()
srs_freep(obs_whip_pps_);
}
-srs_error_t SrsRtcFrameBuilder::initialize(SrsRequest *r, SrsAudioCodecId audio_codec, SrsVideoCodecId video_codec)
+srs_error_t SrsRtcFrameBuilder::initialize(ISrsRequest *r, SrsAudioCodecId audio_codec, SrsVideoCodecId video_codec)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp
index 83107d2f7..8c98fa5ac 100644
--- a/trunk/src/app/srs_app_rtc_source.hpp
+++ b/trunk/src/app/srs_app_rtc_source.hpp
@@ -22,7 +22,7 @@
#include
#include
-class SrsRequest;
+class ISrsRequest;
class SrsMetaCache;
class SrsSharedPtrMessage;
class SrsCommonMessage;
@@ -150,11 +150,11 @@ public:
// create source when fetch from cache failed.
// @param r the client request.
// @param pps the matched source, if success never be NULL.
- virtual srs_error_t fetch_or_create(SrsRequest *r, SrsSharedPtr &pps);
+ virtual srs_error_t fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps);
public:
// Get the exists source, NULL when not exists.
- virtual SrsSharedPtr fetch(SrsRequest *r);
+ virtual SrsSharedPtr fetch(ISrsRequest *r);
};
// Global singleton instance.
@@ -198,7 +198,7 @@ private:
SrsContextId _source_id;
// previous source id.
SrsContextId _pre_source_id;
- SrsRequest *req;
+ ISrsRequest *req;
ISrsRtcPublishStream *publish_stream_;
// Steam description for this steam.
SrsRtcSourceDescription *stream_desc_;
@@ -235,7 +235,7 @@ public:
virtual ~SrsRtcSource();
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
public:
// Whether stream is dead, which is no publisher or player.
@@ -246,7 +246,7 @@ private:
public:
// Update the authentication information in request.
- virtual void update_auth(SrsRequest *r);
+ virtual void update_auth(ISrsRequest *r);
private:
// The stream source changed.
@@ -306,7 +306,7 @@ private:
class SrsRtcRtpBuilder
{
private:
- SrsRequest *req;
+ ISrsRequest *req;
SrsFrameToRtcBridge *bridge_;
// The format, codec information.
SrsRtmpFormat *format;
@@ -343,7 +343,7 @@ private:
srs_error_t initialize_video_track(SrsVideoCodecId codec);
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
@@ -490,7 +490,7 @@ public:
virtual ~SrsRtcFrameBuilder();
public:
- srs_error_t initialize(SrsRequest *r, SrsAudioCodecId audio_codec, SrsVideoCodecId video_codec);
+ srs_error_t initialize(ISrsRequest *r, SrsAudioCodecId audio_codec, SrsVideoCodecId video_codec);
virtual srs_error_t on_publish();
virtual void on_unpublish();
virtual srs_error_t on_rtp(SrsRtpPacket *pkt);
diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp
index d244d7e49..87a880124 100644
--- a/trunk/src/app/srs_app_rtmp_conn.cpp
+++ b/trunk/src/app/srs_app_rtmp_conn.cpp
@@ -300,7 +300,7 @@ srs_error_t SrsRtmpConn::do_cycle()
span_connect_ = _srs_apm->span("connect")->as_child(span_main_);
#endif
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if ((err = rtmp->connect_app(req)) != srs_success) {
return srs_error_wrap(err, "rtmp connect tcUrl");
}
@@ -368,7 +368,7 @@ srs_error_t SrsRtmpConn::on_reload_vhost_removed(string vhost)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (req->vhost != vhost) {
return err;
@@ -390,7 +390,7 @@ srs_error_t SrsRtmpConn::on_reload_vhost_play(string vhost)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (req->vhost != vhost) {
return err;
@@ -416,7 +416,7 @@ srs_error_t SrsRtmpConn::on_reload_vhost_tcp_nodelay(string vhost)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (req->vhost != vhost) {
return err;
@@ -431,7 +431,7 @@ srs_error_t SrsRtmpConn::on_reload_vhost_realtime(string vhost)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (req->vhost != vhost) {
return err;
@@ -454,7 +454,7 @@ srs_error_t SrsRtmpConn::on_reload_vhost_publish(string vhost)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (req->vhost != vhost) {
return err;
@@ -484,7 +484,7 @@ srs_error_t SrsRtmpConn::service_cycle()
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
int out_ack_size = _srs_config->get_out_ack_size(req->vhost);
if (out_ack_size && (err = rtmp->set_window_ack_size(out_ack_size)) != srs_success) {
@@ -579,7 +579,7 @@ srs_error_t SrsRtmpConn::stream_service_cycle()
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if ((err = rtmp->identify_client(info->res->stream_id, info->type, req->stream, req->duration)) != srs_success) {
return srs_error_wrap(err, "rtmp: identify client");
}
@@ -657,7 +657,7 @@ srs_error_t SrsRtmpConn::stream_service_cycle()
// find a source to serve.
SrsSharedPtr live_source;
- if ((err = _srs_sources->fetch_or_create(req, server, live_source)) != srs_success) {
+ if ((err = _srs_sources->fetch_or_create(req, live_source)) != srs_success) {
return srs_error_wrap(err, "rtmp: fetch source");
}
srs_assert(live_source.get() != NULL);
@@ -754,7 +754,7 @@ srs_error_t SrsRtmpConn::check_vhost(bool try_default_vhost)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
srs_assert(req != NULL);
SrsConfDirective *vhost = _srs_config->get_vhost(req->vhost, try_default_vhost);
@@ -789,7 +789,7 @@ srs_error_t SrsRtmpConn::playing(SrsSharedPtr source)
srs_error_t err = srs_success;
// Check page referer of player.
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (_srs_config->get_refer_enabled(req->vhost)) {
if ((err = refer->check(req->pageUrl, _srs_config->get_refer_play(req->vhost))) != srs_success) {
return srs_error_wrap(err, "rtmp: referer check");
@@ -876,7 +876,7 @@ srs_error_t SrsRtmpConn::do_playing(SrsSharedPtr source, SrsLiveC
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
srs_assert(req);
srs_assert(consumer);
@@ -1009,7 +1009,7 @@ srs_error_t SrsRtmpConn::publishing(SrsSharedPtr source)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (_srs_config->get_refer_enabled(req->vhost)) {
if ((err = refer->check(req->pageUrl, _srs_config->get_refer_publish(req->vhost))) != srs_success) {
@@ -1052,7 +1052,7 @@ srs_error_t SrsRtmpConn::do_publishing(SrsSharedPtr source, SrsPu
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
SrsUniquePtr pprint(SrsPithyPrint::create_rtmp_publish());
// start isolate recv thread.
@@ -1151,7 +1151,7 @@ srs_error_t SrsRtmpConn::acquire_publish(SrsSharedPtr source)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
// Check whether RTMP stream is busy.
if (!source->can_publish(info->edge)) {
@@ -1404,7 +1404,7 @@ srs_error_t SrsRtmpConn::process_play_control_msg(SrsLiveConsumer *consumer, Srs
void SrsRtmpConn::set_sock_options()
{
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
bool nvalue = _srs_config->get_tcp_nodelay(req->vhost);
if (nvalue != tcp_nodelay) {
@@ -1422,7 +1422,7 @@ srs_error_t SrsRtmpConn::check_edge_token_traverse_auth()
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
srs_assert(req);
vector args = _srs_config->get_vhost_edge_origin(req->vhost)->args;
@@ -1456,7 +1456,7 @@ srs_error_t SrsRtmpConn::do_token_traverse_auth(SrsRtmpClient *client)
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
srs_assert(client);
client->set_recv_timeout(SRS_CONSTS_RTMP_TIMEOUT);
@@ -1491,7 +1491,7 @@ srs_error_t SrsRtmpConn::http_hooks_on_connect()
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
return err;
@@ -1524,7 +1524,7 @@ srs_error_t SrsRtmpConn::http_hooks_on_connect()
void SrsRtmpConn::http_hooks_on_close()
{
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
return;
@@ -1555,7 +1555,7 @@ srs_error_t SrsRtmpConn::http_hooks_on_publish()
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
return err;
@@ -1588,7 +1588,7 @@ srs_error_t SrsRtmpConn::http_hooks_on_publish()
void SrsRtmpConn::http_hooks_on_unpublish()
{
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
return;
@@ -1619,7 +1619,7 @@ srs_error_t SrsRtmpConn::http_hooks_on_play()
{
srs_error_t err = srs_success;
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
return err;
@@ -1652,7 +1652,7 @@ srs_error_t SrsRtmpConn::http_hooks_on_play()
void SrsRtmpConn::http_hooks_on_stop()
{
- SrsRequest *req = info->req;
+ ISrsRequest *req = info->req;
if (!_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
return;
diff --git a/trunk/src/app/srs_app_rtmp_conn.hpp b/trunk/src/app/srs_app_rtmp_conn.hpp
index 5f54ffc9c..70822e5f1 100644
--- a/trunk/src/app/srs_app_rtmp_conn.hpp
+++ b/trunk/src/app/srs_app_rtmp_conn.hpp
@@ -20,7 +20,7 @@
class SrsServer;
class SrsRtmpServer;
-class SrsRequest;
+class ISrsRequest;
class SrsResponse;
class SrsLiveSource;
class SrsRefer;
@@ -62,7 +62,7 @@ public:
// Whether the client connected at the edge server.
bool edge;
// Original request object from client.
- SrsRequest *req;
+ ISrsRequest *req;
// Response object to client.
SrsResponse *res;
diff --git a/trunk/src/app/srs_app_rtsp_conn.cpp b/trunk/src/app/srs_app_rtsp_conn.cpp
index b91c30c25..19f1fc304 100644
--- a/trunk/src/app/srs_app_rtsp_conn.cpp
+++ b/trunk/src/app/srs_app_rtsp_conn.cpp
@@ -80,7 +80,7 @@ SrsRtspPlayStream::~SrsRtspPlayStream()
stat->on_disconnect(cid_.c_str(), srs_success);
}
-srs_error_t SrsRtspPlayStream::initialize(SrsRequest *req, std::map sub_relations)
+srs_error_t SrsRtspPlayStream::initialize(ISrsRequest *req, std::map sub_relations)
{
srs_error_t err = srs_success;
@@ -850,7 +850,7 @@ srs_error_t SrsRtspConnection::do_teardown()
return srs_success;
}
-srs_error_t SrsRtspConnection::http_hooks_on_play(SrsRequest *req)
+srs_error_t SrsRtspConnection::http_hooks_on_play(ISrsRequest *req)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_rtsp_conn.hpp b/trunk/src/app/srs_app_rtsp_conn.hpp
index 48e330921..a533f9b76 100644
--- a/trunk/src/app/srs_app_rtsp_conn.hpp
+++ b/trunk/src/app/srs_app_rtsp_conn.hpp
@@ -21,7 +21,7 @@
#include
#include
-class SrsRequest;
+class ISrsRequest;
class SrsRtpPacket;
class SrsRtspSource;
class SrsRtspAudioSendTrack;
@@ -42,7 +42,7 @@ private:
SrsRtspConnection *session_;
private:
- SrsRequest *req_;
+ ISrsRequest *req_;
SrsSharedPtr source_;
// key: publish_ssrc, value: send track to process rtp/rtcp
std::map audio_tracks_;
@@ -66,7 +66,7 @@ public:
virtual ~SrsRtspPlayStream();
public:
- srs_error_t initialize(SrsRequest *request, std::map sub_relations);
+ srs_error_t initialize(ISrsRequest *request, std::map sub_relations);
// Interface ISrsRtcSourceChangeCallback
public:
void on_stream_change(SrsRtcSourceDescription *desc);
@@ -101,7 +101,7 @@ private:
// TODO: FIXME: Rename it.
srs_utime_t last_stun_time;
SrsContextId cid_;
- SrsRequest *request_;
+ ISrsRequest *request_;
// The manager object to manage the connection.
ISrsResourceManager *manager_;
// Each connection start a green thread,
@@ -179,7 +179,7 @@ private:
srs_error_t do_cycle();
private:
- srs_error_t http_hooks_on_play(SrsRequest *req);
+ srs_error_t http_hooks_on_play(ISrsRequest *req);
srs_error_t get_ssrc_by_stream_id(uint32_t stream_id, uint32_t *ssrc);
};
diff --git a/trunk/src/app/srs_app_rtsp_source.cpp b/trunk/src/app/srs_app_rtsp_source.cpp
index b1e16319a..42bf2f1f0 100644
--- a/trunk/src/app/srs_app_rtsp_source.cpp
+++ b/trunk/src/app/srs_app_rtsp_source.cpp
@@ -168,43 +168,49 @@ srs_error_t SrsRtspSourceManager::notify(int event, srs_utime_t interval, srs_ut
return err;
}
-srs_error_t SrsRtspSourceManager::fetch_or_create(SrsRequest *r, SrsSharedPtr &pps)
+srs_error_t SrsRtspSourceManager::fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps)
{
srs_error_t err = srs_success;
- // Use lock to protect coroutine switch.
- // @bug https://github.com/ossrs/srs/issues/1230
- SrsLocker(lock);
+ bool created = false;
+ // Should never invoke any function during the locking.
+ if (true) {
+ // Use lock to protect coroutine switch.
+ // @bug https://github.com/ossrs/srs/issues/1230
+ SrsLocker(lock);
- string stream_url = r->get_stream_url();
- std::map >::iterator it = pool.find(stream_url);
+ string stream_url = r->get_stream_url();
+ std::map >::iterator it = pool.find(stream_url);
- if (it != pool.end()) {
- SrsSharedPtr source = it->second;
+ if (it != pool.end()) {
+ SrsSharedPtr source = it->second;
+ pps = source;
+ } else {
+ SrsSharedPtr source = SrsSharedPtr(new SrsRtspSource());
+ srs_trace("new rtsp source, stream_url=%s", stream_url.c_str());
+ pps = source;
- // we always update the request of resource,
- // for origin auth is on, the token in request maybe invalid,
- // and we only need to update the token of request, it's simple.
- source->update_auth(r);
- pps = source;
-
- return err;
+ pool[stream_url] = source;
+ created = true;
+ }
}
- SrsSharedPtr source = SrsSharedPtr(new SrsRtspSource());
- srs_trace("new rtsp source, stream_url=%s", stream_url.c_str());
-
- if ((err = source->initialize(r)) != srs_success) {
+ // Initialize source.
+ if (created && (err = pps->initialize(r)) != srs_success) {
return srs_error_wrap(err, "init source %s", r->get_stream_url().c_str());
}
- pool[stream_url] = source;
- pps = source;
+ // we always update the request of resource,
+ // for origin auth is on, the token in request maybe invalid,
+ // and we only need to update the token of request, it's simple.
+ if (!created) {
+ pps->update_auth(r);
+ }
return err;
}
-SrsSharedPtr SrsRtspSourceManager::fetch(SrsRequest *r)
+SrsSharedPtr SrsRtspSourceManager::fetch(ISrsRequest *r)
{
// Use lock to protect coroutine switch.
// @bug https://github.com/ossrs/srs/issues/1230
@@ -255,7 +261,19 @@ SrsRtspSource::~SrsRtspSource()
srs_trace("free rtc source id=[%s]", cid.c_str());
}
-srs_error_t SrsRtspSource::initialize(SrsRequest *r)
+// CRITICAL: This method is called AFTER the source has been added to the source pool
+// in the fetch_or_create pattern (see PR 4449).
+//
+// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches
+// before completing the basic field setup.
+//
+// If context switches occur before all fields are properly initialized, other coroutines
+// accessing this source from the pool may encounter uninitialized state, leading to crashes
+// or undefined behavior.
+//
+// This prevents the race condition where multiple coroutines could create duplicate sources
+// for the same stream when context switches occurred during initialization.
+srs_error_t SrsRtspSource::initialize(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -285,7 +303,7 @@ bool SrsRtspSource::stream_is_dead()
return true;
}
-void SrsRtspSource::update_auth(SrsRequest *r)
+void SrsRtspSource::update_auth(ISrsRequest *r)
{
req->update_auth(r);
}
@@ -638,7 +656,7 @@ srs_error_t SrsRtspRtpBuilder::initialize_video_track(SrsVideoCodecId codec)
return err;
}
-srs_error_t SrsRtspRtpBuilder::initialize(SrsRequest *r)
+srs_error_t SrsRtspRtpBuilder::initialize(ISrsRequest *r)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_rtsp_source.hpp b/trunk/src/app/srs_app_rtsp_source.hpp
index 338499372..3bb40b209 100644
--- a/trunk/src/app/srs_app_rtsp_source.hpp
+++ b/trunk/src/app/srs_app_rtsp_source.hpp
@@ -17,7 +17,7 @@
#include
#include
-class SrsRequest;
+class ISrsRequest;
class SrsRtpPacket;
class SrsRtspSource;
class SrsRtspConsumer;
@@ -26,6 +26,7 @@ class SrsRtcSourceDescription;
class SrsResourceManager;
class SrsRtspConnection;
class SrsRtpVideoBuilder;
+class SrsFrameToRtspBridge;
// The RTSP stream consumer, consume packets from RTSP stream source.
class SrsRtspConsumer
@@ -89,11 +90,11 @@ public:
// create source when fetch from cache failed.
// @param r the client request.
// @param pps the matched source, if success never be NULL.
- virtual srs_error_t fetch_or_create(SrsRequest *r, SrsSharedPtr &pps);
+ virtual srs_error_t fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps);
public:
// Get the exists source, NULL when not exists.
- virtual SrsSharedPtr fetch(SrsRequest *r);
+ virtual SrsSharedPtr fetch(ISrsRequest *r);
};
// The global RTSP source manager.
@@ -112,7 +113,7 @@ private:
SrsContextId _source_id;
// previous source id.
SrsContextId _pre_source_id;
- SrsRequest *req;
+ ISrsRequest *req;
// Steam description for this steam.
SrsRtcTrackDescription *audio_desc_;
SrsRtcTrackDescription *video_desc_;
@@ -134,7 +135,7 @@ public:
virtual ~SrsRtspSource();
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
public:
// Whether stream is dead, which is no publisher or player.
@@ -142,7 +143,7 @@ public:
public:
// Update the authentication information in request.
- virtual void update_auth(SrsRequest *r);
+ virtual void update_auth(ISrsRequest *r);
private:
// The stream source changed.
@@ -188,7 +189,7 @@ public:
class SrsRtspRtpBuilder
{
private:
- SrsRequest *req;
+ ISrsRequest *req;
SrsFrameToRtspBridge *bridge_;
// The format, codec information.
SrsRtmpFormat *format;
@@ -219,7 +220,7 @@ private:
srs_error_t initialize_video_track(SrsVideoCodecId codec);
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
diff --git a/trunk/src/app/srs_app_security.cpp b/trunk/src/app/srs_app_security.cpp
index ec6c69e7e..2827f1cb2 100644
--- a/trunk/src/app/srs_app_security.cpp
+++ b/trunk/src/app/srs_app_security.cpp
@@ -19,7 +19,7 @@ SrsSecurity::~SrsSecurity()
{
}
-srs_error_t SrsSecurity::check(SrsRtmpConnType type, string ip, SrsRequest *req)
+srs_error_t SrsSecurity::check(SrsRtmpConnType type, string ip, ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -33,7 +33,7 @@ srs_error_t SrsSecurity::check(SrsRtmpConnType type, string ip, SrsRequest *req)
return do_check(rules, type, ip, req);
}
-srs_error_t SrsSecurity::do_check(SrsConfDirective *rules, SrsRtmpConnType type, string ip, SrsRequest *req)
+srs_error_t SrsSecurity::do_check(SrsConfDirective *rules, SrsRtmpConnType type, string ip, ISrsRequest *req)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_security.hpp b/trunk/src/app/srs_app_security.hpp
index f2ecea11d..010f39ea7 100644
--- a/trunk/src/app/srs_app_security.hpp
+++ b/trunk/src/app/srs_app_security.hpp
@@ -28,10 +28,10 @@ public:
// @param type the client type, publish or play.
// @param ip the ip address of client.
// @param req the request object of client.
- virtual srs_error_t check(SrsRtmpConnType type, std::string ip, SrsRequest *req);
+ virtual srs_error_t check(SrsRtmpConnType type, std::string ip, ISrsRequest *req);
private:
- virtual srs_error_t do_check(SrsConfDirective *rules, SrsRtmpConnType type, std::string ip, SrsRequest *req);
+ virtual srs_error_t do_check(SrsConfDirective *rules, SrsRtmpConnType type, std::string ip, ISrsRequest *req);
virtual srs_error_t allow_check(SrsConfDirective *rules, SrsRtmpConnType type, std::string ip);
virtual srs_error_t deny_check(SrsConfDirective *rules, SrsRtmpConnType type, std::string ip);
};
diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp
index bd528d297..c5a39115b 100644
--- a/trunk/src/app/srs_app_server.cpp
+++ b/trunk/src/app/srs_app_server.cpp
@@ -1396,7 +1396,7 @@ srs_error_t SrsServer::on_reload_listen()
return err;
}
-srs_error_t SrsServer::on_publish(SrsRequest *r)
+srs_error_t SrsServer::on_publish(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -1412,7 +1412,7 @@ srs_error_t SrsServer::on_publish(SrsRequest *r)
return err;
}
-void SrsServer::on_unpublish(SrsRequest *r)
+void SrsServer::on_unpublish(ISrsRequest *r)
{
http_server->http_unmount(r);
diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp
index 415e2fd1f..960f7c321 100644
--- a/trunk/src/app/srs_app_server.hpp
+++ b/trunk/src/app/srs_app_server.hpp
@@ -256,8 +256,8 @@ public:
virtual srs_error_t on_reload_listen();
// Interface ISrsLiveSourceHandler
public:
- virtual srs_error_t on_publish(SrsRequest *r);
- virtual void on_unpublish(SrsRequest *r);
+ virtual srs_error_t on_publish(ISrsRequest *r);
+ virtual void on_unpublish(ISrsRequest *r);
};
// The SRS server adapter, the master server.
diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp
index cea23b938..da6da16da 100644
--- a/trunk/src/app/srs_app_source.cpp
+++ b/trunk/src/app/srs_app_source.cpp
@@ -19,8 +19,10 @@ using namespace std;
#include
#include
#include
+#include
#include
#include
+#include
#include
#include
#include
@@ -857,7 +859,7 @@ SrsOriginHub::~SrsOriginHub()
#endif
}
-srs_error_t SrsOriginHub::initialize(SrsSharedPtr s, SrsRequest *r)
+srs_error_t SrsOriginHub::initialize(SrsSharedPtr s, ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -1524,7 +1526,7 @@ srs_error_t SrsOriginHub::create_backend_forwarders(bool &applied)
std::string url = *it;
// create temp Request by url
- SrsUniquePtr req(new SrsRequest());
+ SrsUniquePtr req(new SrsRequest());
srs_parse_rtmp_url(url, req->tcUrl, req->stream);
srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->stream, req->port, req->param);
@@ -1760,42 +1762,53 @@ srs_error_t SrsLiveSourceManager::initialize()
return setup_ticks();
}
-srs_error_t SrsLiveSourceManager::fetch_or_create(SrsRequest *r, ISrsLiveSourceHandler *h, SrsSharedPtr &pps)
+srs_error_t SrsLiveSourceManager::fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps)
{
srs_error_t err = srs_success;
- // Use lock to protect coroutine switch.
- // @bug https://github.com/ossrs/srs/issues/1230
- // TODO: FIXME: Use smaller scope lock.
- SrsLocker(lock);
+ bool created = false;
+ // Should never invoke any function during the locking.
+ if (true) {
+ // Use lock to protect coroutine switch.
+ // @bug https://github.com/ossrs/srs/issues/1230
+ // TODO: FIXME: Use smaller scope lock.
+ SrsLocker(lock);
- string stream_url = r->get_stream_url();
- std::map >::iterator it = pool.find(stream_url);
+ string stream_url = r->get_stream_url();
+ std::map >::iterator it = pool.find(stream_url);
- if (it != pool.end()) {
- SrsSharedPtr &source = it->second;
+ if (it != pool.end()) {
+ SrsSharedPtr &source = it->second;
+ pps = source;
+ } else {
+ SrsSharedPtr source = new SrsLiveSource();
+ srs_trace("new live source, stream_url=%s", stream_url.c_str());
+ pps = source;
- // we always update the request of resource,
- // for origin auth is on, the token in request maybe invalid,
- // and we only need to update the token of request, it's simple.
- source->update_auth(r);
- pps = source;
- return err;
+ // Callback to notify request of source creation
+ r->on_source_created();
+
+ pool[stream_url] = source;
+ created = true;
+ }
}
- SrsSharedPtr source = new SrsLiveSource();
- srs_trace("new live source, stream_url=%s", stream_url.c_str());
-
- if ((err = source->initialize(source, r, h)) != srs_success) {
+ // Initialize source with the wrapper of itself.
+ if (created && (err = pps->initialize(pps, r)) != srs_success) {
return srs_error_wrap(err, "init source %s", r->get_stream_url().c_str());
}
- pool[stream_url] = source;
- pps = source;
+ // we always update the request of resource,
+ // for origin auth is on, the token in request maybe invalid,
+ // and we only need to update the token of request, it's simple.
+ if (!created) {
+ pps->update_auth(r);
+ }
+
return err;
}
-SrsSharedPtr SrsLiveSourceManager::fetch(SrsRequest *r)
+SrsSharedPtr SrsLiveSourceManager::fetch(ISrsRequest *r)
{
// Use lock to protect coroutine switch.
// @bug https://github.com/ossrs/srs/issues/1230
@@ -1886,7 +1899,6 @@ SrsLiveSource::SrsLiveSource()
stream_die_at_ = 0;
publisher_idle_at_ = 0;
- handler = NULL;
bridge_ = NULL;
play_edge = new SrsPlayEdge();
@@ -1985,17 +1997,30 @@ bool SrsLiveSource::publisher_is_idle_for(srs_utime_t timeout)
return false;
}
-srs_error_t SrsLiveSource::initialize(SrsSharedPtr wrapper, SrsRequest *r, ISrsLiveSourceHandler *h)
+// CRITICAL: This method is called AFTER the source has been added to the source pool
+// in the fetch_or_create pattern (see PR 4449).
+//
+// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches
+// before completing the basic field setup.
+//
+// If context switches occur before all fields are properly initialized, other coroutines
+// accessing this source from the pool may encounter uninitialized state, leading to crashes
+// or undefined behavior.
+//
+// This prevents the race condition where multiple coroutines could create duplicate sources
+// for the same stream when context switches occurred during initialization.
+srs_error_t SrsLiveSource::initialize(SrsSharedPtr wrapper, ISrsRequest *r)
{
srs_error_t err = srs_success;
- srs_assert(h);
srs_assert(!req);
- handler = h;
req = r->copy();
atc = _srs_config->get_atc(req->vhost);
+ jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(req->vhost);
+ mix_correct = _srs_config->get_mix_correct(req->vhost);
+
if ((err = format_->initialize()) != srs_success) {
return srs_error_wrap(err, "format initialize");
}
@@ -2003,10 +2028,6 @@ srs_error_t SrsLiveSource::initialize(SrsSharedPtr wrapper, SrsRe
// Setup the SPS/PPS parsing strategy.
format_->try_annexb_first = _srs_config->try_annexb_first(r->vhost);
- if ((err = hub->initialize(wrapper, req)) != srs_success) {
- return srs_error_wrap(err, "hub");
- }
-
if ((err = play_edge->initialize(wrapper, req)) != srs_success) {
return srs_error_wrap(err, "edge(play)");
}
@@ -2017,8 +2038,9 @@ srs_error_t SrsLiveSource::initialize(SrsSharedPtr wrapper, SrsRe
srs_utime_t queue_size = _srs_config->get_queue_length(req->vhost);
publish_edge->set_queue_size(queue_size);
- jitter_algorithm = (SrsRtmpJitterAlgorithm)_srs_config->get_time_jitter(req->vhost);
- mix_correct = _srs_config->get_mix_correct(req->vhost);
+ if ((err = hub->initialize(wrapper, req)) != srs_success) {
+ return srs_error_wrap(err, "hub");
+ }
return err;
}
@@ -2151,7 +2173,7 @@ bool SrsLiveSource::inactive()
return can_publish_;
}
-void SrsLiveSource::update_auth(SrsRequest *r)
+void SrsLiveSource::update_auth(ISrsRequest *r)
{
req->update_auth(r);
}
@@ -2588,6 +2610,7 @@ srs_error_t SrsLiveSource::on_publish()
}
// notify the handler.
+ ISrsLiveSourceHandler *handler = _srs_hybrid->srs()->instance();
srs_assert(handler);
if ((err = handler->on_publish(req)) != srs_success) {
return srs_error_wrap(err, "handle publish");
@@ -2636,7 +2659,9 @@ void SrsLiveSource::on_unpublish()
_source_id = SrsContextId();
// notify the handler.
+ ISrsLiveSourceHandler *handler = _srs_hybrid->srs()->instance();
srs_assert(handler);
+
SrsStatistic *stat = SrsStatistic::instance();
stat->on_stream_close(req);
diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp
index 7fa54b923..11ab13210 100644
--- a/trunk/src/app/srs_app_source.hpp
+++ b/trunk/src/app/srs_app_source.hpp
@@ -31,7 +31,7 @@ class SrsCommonMessage;
class SrsOnMetaDataPacket;
class SrsSharedPtrMessage;
class SrsForwarder;
-class SrsRequest;
+class ISrsRequest;
class SrsStSocket;
class SrsRtmpServer;
class SrsEdgeProxyContext;
@@ -306,9 +306,9 @@ public:
public:
// when stream start publish, mount stream.
- virtual srs_error_t on_publish(SrsRequest *r) = 0;
+ virtual srs_error_t on_publish(ISrsRequest *r) = 0;
// when stream stop publish, unmount stream.
- virtual void on_unpublish(SrsRequest *r) = 0;
+ virtual void on_unpublish(ISrsRequest *r) = 0;
};
// The mix queue to correct the timestamp for mix_correct algorithm.
@@ -339,7 +339,7 @@ private:
SrsLiveSource *source_;
private:
- SrsRequest *req_;
+ ISrsRequest *req_;
bool is_active;
private:
@@ -367,7 +367,7 @@ public:
public:
// Initialize the hub with source and request.
// @param r The request object, managed by source.
- virtual srs_error_t initialize(SrsSharedPtr s, SrsRequest *r);
+ virtual srs_error_t initialize(SrsSharedPtr s, ISrsRequest *r);
// Dispose the hub, release utilities resource,
// For example, delete all HLS pieces.
virtual void dispose();
@@ -492,11 +492,11 @@ public:
// @param r the client request.
// @param h the event handler for source.
// @param pps the matched source, if success never be NULL.
- virtual srs_error_t fetch_or_create(SrsRequest *r, ISrsLiveSourceHandler *h, SrsSharedPtr &pps);
+ virtual srs_error_t fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps);
public:
// Get the exists source, NULL when not exists.
- virtual SrsSharedPtr fetch(SrsRequest *r);
+ virtual SrsSharedPtr fetch(ISrsRequest *r);
public:
// dispose and cycle all sources.
@@ -529,7 +529,7 @@ private:
// previous source id.
SrsContextId _pre_source_id;
// deep copy of client request.
- SrsRequest *req;
+ ISrsRequest *req;
// To delivery stream to clients.
std::vector consumers;
// The time jitter algorithm for vhost.
@@ -547,8 +547,6 @@ private:
bool is_monotonically_increase;
// The time of the packet we just got.
int64_t last_packet_time;
- // The event handler.
- ISrsLiveSourceHandler *handler;
// The source bridge for other source.
ISrsStreamBridge *bridge_;
// The edge control service
@@ -585,7 +583,7 @@ public:
public:
// Initialize the hls with handlers.
- virtual srs_error_t initialize(SrsSharedPtr wrapper, SrsRequest *r, ISrsLiveSourceHandler *h);
+ virtual srs_error_t initialize(SrsSharedPtr wrapper, ISrsRequest *r);
// Bridge to other source, forward packets to it.
void set_bridge(ISrsStreamBridge *v);
// Interface ISrsReloadHandler
@@ -602,7 +600,7 @@ public:
// @remark For edge, it's inactive util stream has been pulled from origin.
virtual bool inactive();
// Update the authentication information in request.
- virtual void update_auth(SrsRequest *r);
+ virtual void update_auth(ISrsRequest *r);
public:
virtual bool can_publish(bool is_edge);
diff --git a/trunk/src/app/srs_app_srt_conn.cpp b/trunk/src/app/srs_app_srt_conn.cpp
index 15173f2fa..9ac18dd4d 100644
--- a/trunk/src/app/srs_app_srt_conn.cpp
+++ b/trunk/src/app/srs_app_srt_conn.cpp
@@ -372,7 +372,7 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish()
return srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "live_source stream %s busy", req_->get_stream_url().c_str());
}
- if ((err = _srs_sources->fetch_or_create(req_, _srs_hybrid->srs()->instance(), live_source)) != srs_success) {
+ if ((err = _srs_sources->fetch_or_create(req_, live_source)) != srs_success) {
return srs_error_wrap(err, "create source");
}
diff --git a/trunk/src/app/srs_app_srt_conn.hpp b/trunk/src/app/srs_app_srt_conn.hpp
index 8dff7d9c6..4d21bf154 100644
--- a/trunk/src/app/srs_app_srt_conn.hpp
+++ b/trunk/src/app/srs_app_srt_conn.hpp
@@ -134,7 +134,7 @@ private:
int port_;
SrsCoroutine *trd_;
- SrsRequest *req_;
+ ISrsRequest *req_;
SrsSharedPtr srt_source_;
SrsSecurity *security_;
};
diff --git a/trunk/src/app/srs_app_srt_source.cpp b/trunk/src/app/srs_app_srt_source.cpp
index 8976cc59d..2ddfa4a18 100644
--- a/trunk/src/app/srs_app_srt_source.cpp
+++ b/trunk/src/app/srs_app_srt_source.cpp
@@ -151,39 +151,63 @@ srs_error_t SrsSrtSourceManager::notify(int event, srs_utime_t interval, srs_uti
return err;
}
-srs_error_t SrsSrtSourceManager::fetch_or_create(SrsRequest *r, SrsSharedPtr &pps)
+srs_error_t SrsSrtSourceManager::fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps)
{
srs_error_t err = srs_success;
+ bool created = false;
+ // Should never invoke any function during the locking.
+ if (true) {
+ // Use lock to protect coroutine switch.
+ // @bug https://github.com/ossrs/srs/issues/1230
+ SrsLocker(lock);
+
+ string stream_url = r->get_stream_url();
+ std::map >::iterator it = pool.find(stream_url);
+ if (it != pool.end()) {
+ SrsSharedPtr source = it->second;
+ pps = source;
+ } else {
+ SrsSharedPtr source(new SrsSrtSource());
+ srs_trace("new srt source, stream_url=%s", stream_url.c_str());
+ pps = source;
+
+ pool[stream_url] = source;
+ created = true;
+ }
+ }
+
+ // Initialize source.
+ if (created && (err = pps->initialize(r)) != srs_success) {
+ return srs_error_wrap(err, "init source %s", r->get_stream_url().c_str());
+ }
+
+ // we always update the request of resource,
+ // for origin auth is on, the token in request maybe invalid,
+ // and we only need to update the token of request, it's simple.
+ if (!created) {
+ pps->update_auth(r);
+ }
+
+ return err;
+}
+
+SrsSharedPtr SrsSrtSourceManager::fetch(ISrsRequest *r)
+{
// Use lock to protect coroutine switch.
// @bug https://github.com/ossrs/srs/issues/1230
SrsLocker(lock);
string stream_url = r->get_stream_url();
std::map >::iterator it = pool.find(stream_url);
- if (it != pool.end()) {
- SrsSharedPtr source = it->second;
- // we always update the request of resource,
- // for origin auth is on, the token in request maybe invalid,
- // and we only need to update the token of request, it's simple.
- source->update_auth(r);
- pps = source;
-
- return err;
+ SrsSharedPtr source;
+ if (it == pool.end()) {
+ return source;
}
- SrsSharedPtr source(new SrsSrtSource());
- srs_trace("new srt source, stream_url=%s", stream_url.c_str());
-
- if ((err = source->initialize(r)) != srs_success) {
- return srs_error_wrap(err, "init source %s", r->get_stream_url().c_str());
- }
-
- pool[stream_url] = source;
- pps = source;
-
- return err;
+ source = it->second;
+ return source;
}
SrsSrtSourceManager *_srs_srt_sources = NULL;
@@ -326,7 +350,7 @@ void SrsSrtFrameBuilder::on_unpublish()
{
}
-srs_error_t SrsSrtFrameBuilder::initialize(SrsRequest *req)
+srs_error_t SrsSrtFrameBuilder::initialize(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -927,7 +951,19 @@ SrsSrtSource::~SrsSrtSource()
srs_trace("free srt source id=[%s]", cid.c_str());
}
-srs_error_t SrsSrtSource::initialize(SrsRequest *r)
+// CRITICAL: This method is called AFTER the source has been added to the source pool
+// in the fetch_or_create pattern (see PR 4449).
+//
+// IMPORTANT: All field initialization in this method MUST NOT cause coroutine context switches
+// before completing the basic field setup.
+//
+// If context switches occur before all fields are properly initialized, other coroutines
+// accessing this source from the pool may encounter uninitialized state, leading to crashes
+// or undefined behavior.
+//
+// This prevents the race condition where multiple coroutines could create duplicate sources
+// for the same stream when context switches occurred during initialization.
+srs_error_t SrsSrtSource::initialize(ISrsRequest *r)
{
srs_error_t err = srs_success;
@@ -990,7 +1026,7 @@ SrsContextId SrsSrtSource::pre_source_id()
return _pre_source_id;
}
-void SrsSrtSource::update_auth(SrsRequest *r)
+void SrsSrtSource::update_auth(ISrsRequest *r)
{
req->update_auth(r);
}
diff --git a/trunk/src/app/srs_app_srt_source.hpp b/trunk/src/app/srs_app_srt_source.hpp
index a501d38a7..25c4b5ee1 100644
--- a/trunk/src/app/srs_app_srt_source.hpp
+++ b/trunk/src/app/srs_app_srt_source.hpp
@@ -19,7 +19,7 @@
#include
class SrsSharedPtrMessage;
-class SrsRequest;
+class ISrsRequest;
class SrsLiveSource;
class SrsSrtSource;
class SrsAlonePithyPrint;
@@ -73,7 +73,11 @@ public:
// create source when fetch from cache failed.
// @param r the client request.
// @param pps the matched source, if success never be NULL.
- virtual srs_error_t fetch_or_create(SrsRequest *r, SrsSharedPtr &pps);
+ virtual srs_error_t fetch_or_create(ISrsRequest *r, SrsSharedPtr &pps);
+
+public:
+ // Get the exists source, NULL when not exists.
+ virtual SrsSharedPtr fetch(ISrsRequest *r);
};
// Global singleton instance.
@@ -117,7 +121,7 @@ public:
virtual ~SrsSrtFrameBuilder();
public:
- srs_error_t initialize(SrsRequest *r);
+ srs_error_t initialize(ISrsRequest *r);
public:
virtual srs_error_t on_publish();
@@ -156,7 +160,7 @@ private:
std::string audio_sh_;
private:
- SrsRequest *req_;
+ ISrsRequest *req_;
private:
// SRT to rtmp, video stream id.
@@ -174,7 +178,7 @@ public:
virtual ~SrsSrtSource();
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
public:
// Whether stream is dead, which is no publisher or player.
@@ -187,7 +191,7 @@ public:
virtual SrsContextId source_id();
virtual SrsContextId pre_source_id();
// Update the authentication information in request.
- virtual void update_auth(SrsRequest *r);
+ virtual void update_auth(ISrsRequest *r);
public:
void set_bridge(ISrsStreamBridge *bridge);
@@ -214,7 +218,7 @@ private:
SrsContextId _source_id;
// previous source id.
SrsContextId _pre_source_id;
- SrsRequest *req;
+ ISrsRequest *req;
// To delivery packets to clients.
std::vector consumers;
bool can_publish_;
diff --git a/trunk/src/app/srs_app_srt_utility.cpp b/trunk/src/app/srs_app_srt_utility.cpp
index 0fed815c1..f50ed67a6 100644
--- a/trunk/src/app/srs_app_srt_utility.cpp
+++ b/trunk/src/app/srs_app_srt_utility.cpp
@@ -112,7 +112,7 @@ bool srs_srt_streamid_info(const std::string &streamid, SrtMode &mode, std::stri
return true;
}
-bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, SrsRequest *request)
+bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, ISrsRequest *request)
{
string url_subpath = "";
bool ret = srs_srt_streamid_info(streamid, mode, request->vhost, url_subpath);
diff --git a/trunk/src/app/srs_app_srt_utility.hpp b/trunk/src/app/srs_app_srt_utility.hpp
index ccd601364..f320805f0 100644
--- a/trunk/src/app/srs_app_srt_utility.hpp
+++ b/trunk/src/app/srs_app_srt_utility.hpp
@@ -14,7 +14,7 @@
#include
#include
-class SrsRequest;
+class ISrsRequest;
enum SrtMode {
SrtModePull = 1,
@@ -25,6 +25,6 @@ enum SrtMode {
extern bool srs_srt_streamid_info(const std::string &streamid, SrtMode &mode, std::string &vhost, std::string &url_subpath);
// SRT streamid to request.
-extern bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, SrsRequest *request);
+extern bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, ISrsRequest *request);
#endif
diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp
index 38a142cb2..ad8c635b6 100644
--- a/trunk/src/app/srs_app_statistic.cpp
+++ b/trunk/src/app/srs_app_statistic.cpp
@@ -345,7 +345,7 @@ SrsStatisticClient *SrsStatistic::find_client(string client_id)
return NULL;
}
-srs_error_t SrsStatistic::on_video_info(SrsRequest *req, SrsVideoCodecId vcodec, int profile, int level, int width, int height)
+srs_error_t SrsStatistic::on_video_info(ISrsRequest *req, SrsVideoCodecId vcodec, int profile, int level, int width, int height)
{
srs_error_t err = srs_success;
@@ -372,7 +372,7 @@ srs_error_t SrsStatistic::on_video_info(SrsRequest *req, SrsVideoCodecId vcodec,
return err;
}
-srs_error_t SrsStatistic::on_audio_info(SrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate, SrsAudioChannels asound_type, SrsAacObjectType aac_object)
+srs_error_t SrsStatistic::on_audio_info(ISrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate, SrsAudioChannels asound_type, SrsAacObjectType aac_object)
{
srs_error_t err = srs_success;
@@ -388,7 +388,7 @@ srs_error_t SrsStatistic::on_audio_info(SrsRequest *req, SrsAudioCodecId acodec,
return err;
}
-srs_error_t SrsStatistic::on_video_frames(SrsRequest *req, int nb_frames)
+srs_error_t SrsStatistic::on_video_frames(ISrsRequest *req, int nb_frames)
{
srs_error_t err = srs_success;
@@ -400,7 +400,7 @@ srs_error_t SrsStatistic::on_video_frames(SrsRequest *req, int nb_frames)
return err;
}
-void SrsStatistic::on_stream_publish(SrsRequest *req, std::string publisher_id)
+void SrsStatistic::on_stream_publish(ISrsRequest *req, std::string publisher_id)
{
SrsStatisticVhost *vhost = create_vhost(req);
SrsStatisticStream *stream = create_stream(vhost, req);
@@ -408,14 +408,14 @@ void SrsStatistic::on_stream_publish(SrsRequest *req, std::string publisher_id)
stream->publish(publisher_id);
}
-void SrsStatistic::on_stream_close(SrsRequest *req)
+void SrsStatistic::on_stream_close(ISrsRequest *req)
{
SrsStatisticVhost *vhost = create_vhost(req);
SrsStatisticStream *stream = create_stream(vhost, req);
stream->close();
}
-srs_error_t SrsStatistic::on_client(std::string id, SrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type)
+srs_error_t SrsStatistic::on_client(std::string id, ISrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type)
{
srs_error_t err = srs_success;
@@ -734,7 +734,7 @@ void SrsStatistic::dumps_cls_streams(SrsClsSugars *sugars)
}
#endif
-SrsStatisticVhost *SrsStatistic::create_vhost(SrsRequest *req)
+SrsStatisticVhost *SrsStatistic::create_vhost(ISrsRequest *req)
{
SrsStatisticVhost *vhost = NULL;
@@ -752,7 +752,7 @@ SrsStatisticVhost *SrsStatistic::create_vhost(SrsRequest *req)
return vhost;
}
-SrsStatisticStream *SrsStatistic::create_stream(SrsStatisticVhost *vhost, SrsRequest *req)
+SrsStatisticStream *SrsStatistic::create_stream(SrsStatisticVhost *vhost, ISrsRequest *req)
{
// To identify a stream, use url without extension, for example, the bellow are the same stream:
// ossrs.io/live/livestream
diff --git a/trunk/src/app/srs_app_statistic.hpp b/trunk/src/app/srs_app_statistic.hpp
index 974ceef7f..f4be0c829 100644
--- a/trunk/src/app/srs_app_statistic.hpp
+++ b/trunk/src/app/srs_app_statistic.hpp
@@ -19,7 +19,7 @@
class SrsKbps;
class SrsWallClock;
-class SrsRequest;
+class ISrsRequest;
class ISrsExpire;
class SrsJsonObject;
class SrsJsonArray;
@@ -113,7 +113,7 @@ public:
public:
SrsStatisticStream *stream;
- SrsRequest *req;
+ ISrsRequest *req;
SrsRtmpConnType type;
std::string id;
srs_utime_t create;
@@ -183,19 +183,19 @@ public:
public:
// When got video info for stream.
- virtual srs_error_t on_video_info(SrsRequest *req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height);
+ virtual srs_error_t on_video_info(ISrsRequest *req, SrsVideoCodecId vcodec, int avc_profile, int avc_level, int width, int height);
// When got audio info for stream.
- virtual srs_error_t on_audio_info(SrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate,
+ virtual srs_error_t on_audio_info(ISrsRequest *req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate,
SrsAudioChannels asound_type, SrsAacObjectType aac_object);
// When got videos, update the frames.
// We only stat the total number of video frames.
- virtual srs_error_t on_video_frames(SrsRequest *req, int nb_frames);
+ virtual srs_error_t on_video_frames(ISrsRequest *req, int nb_frames);
// When publish stream.
// @param req the request object of publish connection.
// @param publisher_id The id of publish connection.
- virtual void on_stream_publish(SrsRequest *req, std::string publisher_id);
+ virtual void on_stream_publish(ISrsRequest *req, std::string publisher_id);
// When close stream.
- virtual void on_stream_close(SrsRequest *req);
+ virtual void on_stream_close(ISrsRequest *req);
public:
// When got a client to publish/play stream,
@@ -203,7 +203,7 @@ public:
// @param req, the client request object.
// @param conn, the physical absract connection object.
// @param type, the type of connection.
- virtual srs_error_t on_client(std::string id, SrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type);
+ virtual srs_error_t on_client(std::string id, ISrsRequest *req, ISrsExpire *conn, SrsRtmpConnType type);
// Client disconnect
// @remark the on_disconnect always call, while the on_client is call when
// only got the request object, so the client specified by id maybe not
@@ -248,8 +248,8 @@ public:
void dumps_cls_streams(SrsClsSugars *sugars);
#endif
private:
- virtual SrsStatisticVhost *create_vhost(SrsRequest *req);
- virtual SrsStatisticStream *create_stream(SrsStatisticVhost *vhost, SrsRequest *req);
+ virtual SrsStatisticVhost *create_vhost(ISrsRequest *req);
+ virtual SrsStatisticStream *create_stream(SrsStatisticVhost *vhost, ISrsRequest *req);
public:
// Dumps exporter metrics.
diff --git a/trunk/src/app/srs_app_stream_bridge.cpp b/trunk/src/app/srs_app_stream_bridge.cpp
index a100f55ea..0b4d39ebd 100644
--- a/trunk/src/app/srs_app_stream_bridge.cpp
+++ b/trunk/src/app/srs_app_stream_bridge.cpp
@@ -37,7 +37,7 @@ SrsFrameToRtmpBridge::~SrsFrameToRtmpBridge()
{
}
-srs_error_t SrsFrameToRtmpBridge::initialize(SrsRequest *r)
+srs_error_t SrsFrameToRtmpBridge::initialize(ISrsRequest *r)
{
return srs_success;
}
@@ -82,7 +82,7 @@ SrsFrameToRtcBridge::~SrsFrameToRtcBridge()
#endif
}
-srs_error_t SrsFrameToRtcBridge::initialize(SrsRequest *r)
+srs_error_t SrsFrameToRtcBridge::initialize(ISrsRequest *r)
{
#ifdef SRS_FFMPEG_FIT
return rtp_builder_->initialize(r);
@@ -148,7 +148,7 @@ SrsFrameToRtspBridge::~SrsFrameToRtspBridge()
srs_freep(rtp_builder_);
}
-srs_error_t SrsFrameToRtspBridge::initialize(SrsRequest *r)
+srs_error_t SrsFrameToRtspBridge::initialize(ISrsRequest *r)
{
return rtp_builder_->initialize(r);
}
@@ -201,7 +201,7 @@ SrsCompositeBridge::~SrsCompositeBridge()
}
}
-srs_error_t SrsCompositeBridge::initialize(SrsRequest *r)
+srs_error_t SrsCompositeBridge::initialize(ISrsRequest *r)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/app/srs_app_stream_bridge.hpp b/trunk/src/app/srs_app_stream_bridge.hpp
index 9f0589c4f..143a08566 100644
--- a/trunk/src/app/srs_app_stream_bridge.hpp
+++ b/trunk/src/app/srs_app_stream_bridge.hpp
@@ -14,7 +14,7 @@
#include
-class SrsRequest;
+class ISrsRequest;
class SrsSharedPtrMessage;
class SrsLiveSource;
class SrsRtcSource;
@@ -35,7 +35,7 @@ public:
virtual ~ISrsStreamBridge();
public:
- virtual srs_error_t initialize(SrsRequest *r) = 0;
+ virtual srs_error_t initialize(ISrsRequest *r) = 0;
virtual srs_error_t on_publish() = 0;
virtual srs_error_t on_frame(SrsSharedPtrMessage *frame) = 0;
virtual void on_unpublish() = 0;
@@ -52,7 +52,7 @@ public:
virtual ~SrsFrameToRtmpBridge();
public:
- srs_error_t initialize(SrsRequest *r);
+ srs_error_t initialize(ISrsRequest *r);
public:
virtual srs_error_t on_publish();
@@ -77,7 +77,7 @@ public:
virtual ~SrsFrameToRtcBridge();
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
@@ -99,7 +99,7 @@ public:
virtual ~SrsFrameToRtspBridge();
public:
- virtual srs_error_t initialize(SrsRequest *r);
+ virtual srs_error_t initialize(ISrsRequest *r);
virtual srs_error_t on_publish();
virtual void on_unpublish();
virtual srs_error_t on_frame(SrsSharedPtrMessage *frame);
@@ -117,7 +117,7 @@ public:
public:
bool empty() { return bridges_.empty(); } // SrsCompositeBridge::empty()
public:
- srs_error_t initialize(SrsRequest *r);
+ srs_error_t initialize(ISrsRequest *r);
public:
virtual srs_error_t on_publish();
diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp
index 36992b251..56b0e01d5 100644
--- a/trunk/src/core/srs_core_version7.hpp
+++ b/trunk/src/core/srs_core_version7.hpp
@@ -9,6 +9,6 @@
#define VERSION_MAJOR 7
#define VERSION_MINOR 0
-#define VERSION_REVISION 60
+#define VERSION_REVISION 61
#endif
\ No newline at end of file
diff --git a/trunk/src/main/srs_main_ingest_hls.cpp b/trunk/src/main/srs_main_ingest_hls.cpp
index bdc1237e6..540702098 100644
--- a/trunk/src/main/srs_main_ingest_hls.cpp
+++ b/trunk/src/main/srs_main_ingest_hls.cpp
@@ -661,7 +661,7 @@ private:
int64_t raw_aac_dts;
private:
- SrsRequest *req;
+ ISrsRequest *req;
SrsBasicRtmpClient *sdk;
private:
diff --git a/trunk/src/protocol/srs_protocol_http_conn.cpp b/trunk/src/protocol/srs_protocol_http_conn.cpp
index 23fc7df5f..bf63c9b3d 100644
--- a/trunk/src/protocol/srs_protocol_http_conn.cpp
+++ b/trunk/src/protocol/srs_protocol_http_conn.cpp
@@ -593,9 +593,9 @@ SrsHttpHeader *SrsHttpMessage::header()
return &_header;
}
-SrsRequest *SrsHttpMessage::to_request(string vhost)
+ISrsRequest *SrsHttpMessage::to_request(string vhost)
{
- SrsRequest *req = new SrsRequest();
+ ISrsRequest *req = new SrsRequest();
// http path, for instance, /live/livestream.flv, parse to
// app: /live
diff --git a/trunk/src/protocol/srs_protocol_http_conn.hpp b/trunk/src/protocol/srs_protocol_http_conn.hpp
index 45d26633f..3f5ade3f2 100644
--- a/trunk/src/protocol/srs_protocol_http_conn.hpp
+++ b/trunk/src/protocol/srs_protocol_http_conn.hpp
@@ -16,7 +16,7 @@
class ISrsConnection;
class SrsFastStream;
-class SrsRequest;
+class ISrsRequest;
class ISrsReader;
class SrsHttpResponseReader;
class ISrsProtocolReadWriter;
@@ -192,7 +192,7 @@ public:
public:
// Convert the http message to a request.
// @remark user must free the return request.
- virtual SrsRequest *to_request(std::string vhost);
+ virtual ISrsRequest *to_request(std::string vhost);
public:
virtual bool is_jsonp();
diff --git a/trunk/src/protocol/srs_protocol_rtmp_conn.hpp b/trunk/src/protocol/srs_protocol_rtmp_conn.hpp
index 9643f4820..981114a92 100644
--- a/trunk/src/protocol/srs_protocol_rtmp_conn.hpp
+++ b/trunk/src/protocol/srs_protocol_rtmp_conn.hpp
@@ -11,7 +11,7 @@
#include
-class SrsRequest;
+class ISrsRequest;
class SrsTcpClient;
class SrsRtmpClient;
class SrsCommonMessage;
@@ -36,7 +36,7 @@ private:
srs_utime_t stream_timeout;
protected:
- SrsRequest *req;
+ ISrsRequest *req;
private:
SrsTcpClient *transport;
diff --git a/trunk/src/protocol/srs_protocol_rtmp_stack.cpp b/trunk/src/protocol/srs_protocol_rtmp_stack.cpp
index 899490b39..3b9f8f292 100644
--- a/trunk/src/protocol/srs_protocol_rtmp_stack.cpp
+++ b/trunk/src/protocol/srs_protocol_rtmp_stack.cpp
@@ -1459,6 +1459,18 @@ SrsChunkStream::~SrsChunkStream()
srs_freep(msg);
}
+ISrsRequest::ISrsRequest()
+{
+}
+
+ISrsRequest::~ISrsRequest()
+{
+}
+
+void ISrsRequest::on_source_created()
+{
+}
+
SrsRequest::SrsRequest()
{
objectEncoding = RTMP_SIG_AMF0_VER;
@@ -1474,7 +1486,7 @@ SrsRequest::~SrsRequest()
srs_freep(args);
}
-SrsRequest *SrsRequest::copy()
+ISrsRequest *SrsRequest::copy()
{
SrsRequest *cp = new SrsRequest();
@@ -1500,7 +1512,7 @@ SrsRequest *SrsRequest::copy()
return cp;
}
-void SrsRequest::update_auth(SrsRequest *req)
+void SrsRequest::update_auth(ISrsRequest *req)
{
pageUrl = req->pageUrl;
swfUrl = req->swfUrl;
@@ -1551,7 +1563,7 @@ void SrsRequest::strip()
stream = srs_string_trim_start(stream, "/");
}
-SrsRequest *SrsRequest::as_http()
+ISrsRequest *SrsRequest::as_http()
{
schema = "http";
tcUrl = srs_generate_tc_url(schema, host, vhost, app, port);
@@ -1883,7 +1895,7 @@ srs_error_t SrsRtmpClient::complex_handshake()
return err;
}
-srs_error_t SrsRtmpClient::connect_app(string app, string tcUrl, SrsRequest *r, bool dsu, SrsServerInfo *si)
+srs_error_t SrsRtmpClient::connect_app(string app, string tcUrl, ISrsRequest *r, bool dsu, SrsServerInfo *si)
{
srs_error_t err = srs_success;
@@ -2256,7 +2268,7 @@ srs_error_t SrsRtmpServer::handshake()
return err;
}
-srs_error_t SrsRtmpServer::connect_app(SrsRequest *req)
+srs_error_t SrsRtmpServer::connect_app(ISrsRequest *req)
{
srs_error_t err = srs_success;
@@ -2331,7 +2343,7 @@ srs_error_t SrsRtmpServer::set_peer_bandwidth(int bandwidth, int type)
return err;
}
-srs_error_t SrsRtmpServer::response_connect_app(SrsRequest *req, const char *server_ip)
+srs_error_t SrsRtmpServer::response_connect_app(ISrsRequest *req, const char *server_ip)
{
srs_error_t err = srs_success;
@@ -2372,7 +2384,7 @@ srs_error_t SrsRtmpServer::response_connect_app(SrsRequest *req, const char *ser
}
#define SRS_RTMP_REDIRECT_TIMEOUT (3 * SRS_UTIME_SECONDS)
-srs_error_t SrsRtmpServer::redirect(SrsRequest *r, string url, bool &accepted)
+srs_error_t SrsRtmpServer::redirect(ISrsRequest *r, string url, bool &accepted)
{
srs_error_t err = srs_success;
@@ -2423,7 +2435,7 @@ srs_error_t SrsRtmpServer::redirect(SrsRequest *r, string url, bool &accepted)
return err;
}
-void SrsRtmpServer::response_connect_reject(SrsRequest * /*req*/, const char *desc)
+void SrsRtmpServer::response_connect_reject(ISrsRequest * /*req*/, const char *desc)
{
srs_error_t err = srs_success;
diff --git a/trunk/src/protocol/srs_protocol_rtmp_stack.hpp b/trunk/src/protocol/srs_protocol_rtmp_stack.hpp
index c129130f0..bff00f86f 100644
--- a/trunk/src/protocol/srs_protocol_rtmp_stack.hpp
+++ b/trunk/src/protocol/srs_protocol_rtmp_stack.hpp
@@ -408,8 +408,7 @@ public:
virtual ~SrsChunkStream();
};
-// The original request from client.
-class SrsRequest
+class ISrsRequest
{
public:
// The client ip.
@@ -457,34 +456,55 @@ public:
// @see https://github.com/ossrs/srs/issues/104
SrsAmf0Object *args;
-public:
- SrsRequest();
- virtual ~SrsRequest();
-
-public:
- // Deep copy the request, for source to use it to support reload,
- // For when initialize the source, the request is valid,
- // When reload it, the request maybe invalid, so need to copy it.
- virtual SrsRequest *copy();
- // update the auth info of request,
- // To keep the current request ptr is ok,
- // For many components use the ptr of request.
- virtual void update_auth(SrsRequest *req);
- // Get the stream identify, vhost/app/stream.
- virtual std::string get_stream_url();
- // To strip url, user must strip when update the url.
- virtual void strip();
-
-public:
- // Transform it as HTTP request.
- virtual SrsRequest *as_http();
-
public:
// The protocol of client:
// rtmp, Adobe RTMP protocol.
// flv, HTTP-FLV protocol.
// flvs, HTTPS-FLV protocol.
std::string protocol;
+
+public:
+ ISrsRequest();
+ virtual ~ISrsRequest();
+
+public:
+ // Deep copy the request, for source to use it to support reload,
+ // For when initialize the source, the request is valid,
+ // When reload it, the request maybe invalid, so need to copy it.
+ virtual ISrsRequest *copy() = 0;
+ // update the auth info of request,
+ // To keep the current request ptr is ok,
+ // For many components use the ptr of request.
+ virtual void update_auth(ISrsRequest *req) = 0;
+ // Get the stream identify, vhost/app/stream.
+ virtual std::string get_stream_url() = 0;
+ // To strip url, user must strip when update the url.
+ virtual void strip() = 0;
+
+public:
+ // Transform it as HTTP request.
+ virtual ISrsRequest *as_http() = 0;
+
+public:
+ // Callback when source is created.
+ virtual void on_source_created();
+};
+
+// The original request from client.
+class SrsRequest : public ISrsRequest
+{
+public:
+ SrsRequest();
+ virtual ~SrsRequest();
+
+public:
+ virtual ISrsRequest *copy();
+ virtual void update_auth(ISrsRequest *req);
+ virtual std::string get_stream_url();
+ virtual void strip();
+
+public:
+ virtual ISrsRequest *as_http();
};
// The response to client.
@@ -601,7 +621,7 @@ public:
// @param req, the optional req object, use the swfUrl/pageUrl if specified. NULL to ignore.
// @param dsu, Whether debug SRS upnode. For edge, set to true to send its info to upnode.
// @param si, The server information, retrieve from response of connect app request. NULL to ignore.
- virtual srs_error_t connect_app(std::string app, std::string tcUrl, SrsRequest *r, bool dsu, SrsServerInfo *si);
+ virtual srs_error_t connect_app(std::string app, std::string tcUrl, ISrsRequest *r, bool dsu, SrsServerInfo *si);
// Create a stream, then play/publish data over this stream.
virtual srs_error_t create_stream(int &stream_id);
// start play stream.
@@ -722,7 +742,7 @@ public:
// Do handshake with client, try complex then simple.
virtual srs_error_t handshake();
// Do connect app with client, to discovery tcUrl.
- virtual srs_error_t connect_app(SrsRequest *req);
+ virtual srs_error_t connect_app(ISrsRequest *req);
// Set output ack size to client, client will send ack-size for each ack window
virtual srs_error_t set_window_ack_size(int ack_size);
// Set the default input ack size value.
@@ -731,13 +751,13 @@ public:
// using the Limit type field.
virtual srs_error_t set_peer_bandwidth(int bandwidth, int type);
// @param server_ip the ip of server.
- virtual srs_error_t response_connect_app(SrsRequest *req, const char *server_ip = NULL);
+ virtual srs_error_t response_connect_app(ISrsRequest *req, const char *server_ip = NULL);
// Redirect the connection to another rtmp server.
// @param a RTMP url to redirect to.
// @param whether the client accept the redirect.
- virtual srs_error_t redirect(SrsRequest *r, std::string url, bool &accepted);
+ virtual srs_error_t redirect(ISrsRequest *r, std::string url, bool &accepted);
// Reject the connect app request.
- virtual void response_connect_reject(SrsRequest *req, const char *desc);
+ virtual void response_connect_reject(ISrsRequest *req, const char *desc);
// Response client the onBWDone message.
virtual srs_error_t on_bw_done();
// Recv some message to identify the client.
diff --git a/trunk/src/utest/srs_utest_rtmp.cpp b/trunk/src/utest/srs_utest_rtmp.cpp
index 5b27baba0..19ca21e7e 100644
--- a/trunk/src/utest/srs_utest_rtmp.cpp
+++ b/trunk/src/utest/srs_utest_rtmp.cpp
@@ -976,7 +976,7 @@ VOID TEST(ProtocolRTMPTest, RecvMessage3)
SrsRequest req;
req.ip = "10.11.12.13";
- SrsRequest *cp = req.copy();
+ ISrsRequest *cp = req.copy();
EXPECT_STREQ("10.11.12.13", cp->ip.c_str());
srs_freep(cp);
}
@@ -989,7 +989,7 @@ VOID TEST(ProtocolRTMPTest, RecvMessage3)
obj->set("id", SrsAmf0Any::str("srs"));
req.args = obj;
- SrsRequest *cp = req.copy();
+ ISrsRequest *cp = req.copy();
EXPECT_STREQ("10.11.12.13", cp->ip.c_str());
SrsAmf0Object *cpa = dynamic_cast(cp->args);
diff --git a/trunk/src/utest/srs_utest_service.cpp b/trunk/src/utest/srs_utest_service.cpp
index d4898b687..bcf78e433 100644
--- a/trunk/src/utest/srs_utest_service.cpp
+++ b/trunk/src/utest/srs_utest_service.cpp
@@ -636,7 +636,7 @@ VOID TEST(HTTPServerTest, MessageTurnRequest)
if (true) {
SrsHttpMessage m;
HELPER_ASSERT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv", false));
- SrsRequest *r = m.to_request("ossrs.net");
+ ISrsRequest *r = m.to_request("ossrs.net");
EXPECT_STREQ("live", r->app.c_str());
EXPECT_STREQ("livestream", r->stream.c_str());
EXPECT_STREQ("rtmp://ossrs.net/live", r->tcUrl.c_str());
@@ -646,7 +646,7 @@ VOID TEST(HTTPServerTest, MessageTurnRequest)
if (true) {
SrsHttpMessage m;
HELPER_ASSERT_SUCCESS(m.set_url("http://127.0.0.1/live/livestream.flv?token=key", false));
- SrsRequest *r = m.to_request("ossrs.net");
+ ISrsRequest *r = m.to_request("ossrs.net");
EXPECT_STREQ("rtmp://ossrs.net/live", r->tcUrl.c_str());
EXPECT_STREQ("?token=key", r->param.c_str());
srs_freep(r);
@@ -657,7 +657,7 @@ VOID TEST(HTTPServerTest, MessageTurnRequest)
SrsHttpMessage m;
m.set_connection(&conn);
- SrsRequest *r = m.to_request("ossrs.net");
+ ISrsRequest *r = m.to_request("ossrs.net");
EXPECT_STREQ("127.0.0.1", r->ip.c_str());
srs_freep(r);
}
@@ -671,7 +671,7 @@ VOID TEST(HTTPServerTest, MessageTurnRequest)
hdr.set("X-Real-IP", "10.11.12.13");
m.set_header(&hdr, false);
- SrsRequest *r = m.to_request("ossrs.net");
+ ISrsRequest *r = m.to_request("ossrs.net");
EXPECT_STREQ("10.11.12.13", r->ip.c_str());
srs_freep(r);
}
diff --git a/trunk/src/utest/srs_utest_source_lock.cpp b/trunk/src/utest/srs_utest_source_lock.cpp
new file mode 100644
index 000000000..9c315b1d8
--- /dev/null
+++ b/trunk/src/utest/srs_utest_source_lock.cpp
@@ -0,0 +1,817 @@
+//
+// Copyright (c) 2013-2025 The SRS Authors
+//
+// SPDX-License-Identifier: MIT
+//
+#include
+
+using namespace std;
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef SRS_RTSP
+#include
+#endif
+
+/**
+ * Unit tests for source lock refinement (PR #4449)
+ *
+ * This file tests the race condition fixes in source managers where multiple
+ * coroutines could create duplicate sources for the same stream. The fix ensures
+ * atomic source creation and pool insertion.
+ *
+ * Template Design:
+ * - MockOtherSourceAsyncCreator: Template for RTC, SRT, RTSP
+ * - MockLiveSourceAsyncCreator: Separate class for Live sources (needs handler parameter)
+ * - Type aliases provide backward compatibility with original class names
+ */
+
+// This mock request always cause context switch in get_stream_url().
+class MockAsyncSrsRequest : public ISrsRequest
+{
+public:
+ string mock_stream_url;
+ bool enable_context_switch;
+
+ MockAsyncSrsRequest(const string &url = "/live/livestream", bool context_switch = false)
+ {
+ mock_stream_url = url;
+ enable_context_switch = context_switch;
+
+ // Initialize all ISrsRequest members to safe defaults
+ objectEncoding = RTMP_SIG_AMF0_VER;
+ duration = -1;
+ port = SRS_CONSTS_RTMP_DEFAULT_PORT;
+ args = NULL; // Initialize to NULL to prevent crashes
+ protocol = "rtmp";
+
+ // Parse the URL to set vhost, app, stream
+ size_t app_pos = url.find('/', 1); // Find second slash
+ if (app_pos != string::npos) {
+ size_t stream_pos = url.find('/', app_pos + 1); // Find third slash
+ if (stream_pos != string::npos) {
+ app = url.substr(app_pos + 1, stream_pos - app_pos - 1);
+ stream = url.substr(stream_pos + 1);
+ } else {
+ app = url.substr(app_pos + 1);
+ stream = "livestream";
+ }
+ } else {
+ app = "live";
+ stream = "livestream";
+ }
+
+ vhost = "localhost";
+ }
+
+ virtual string get_stream_url()
+ {
+ on_source_created();
+ return mock_stream_url;
+ }
+
+ virtual void on_source_created()
+ {
+ // Simulate context switch that could happen during source initialization
+ if (enable_context_switch) {
+ // Force a context switch by yielding to other coroutines
+ // This simulates the original race condition scenario
+ st_usleep(1 * SRS_UTIME_MILLISECONDS); // 1ms sleep to trigger context switch
+ }
+ }
+
+ virtual ISrsRequest *copy()
+ {
+ MockAsyncSrsRequest *cp = new MockAsyncSrsRequest(mock_stream_url, enable_context_switch);
+
+ *cp = *this;
+ if (args) {
+ cp->args = args->copy()->to_object();
+ }
+
+ return cp;
+ }
+
+ virtual void update_auth(ISrsRequest *req)
+ {
+ }
+
+ virtual void strip()
+ {
+ }
+
+ virtual ISrsRequest *as_http()
+ {
+ return this;
+ }
+};
+
+// Template for non-live source async creators (RTC, SRT, RTSP)
+// Since SRS uses C++98, we use a simple template approach
+// Note: MockLiveSourceAsyncCreator is kept separate because it requires an additional
+// ISrsLiveSourceHandler parameter that the other source managers don't need
+template
+class MockOtherSourceAsyncCreator : public ISrsCoroutineHandler
+{
+public:
+ SrsWaitGroup *wg_;
+ ManagerType *manager_;
+ MockAsyncSrsRequest *req_;
+ SrsSharedPtr source_;
+
+ MockOtherSourceAsyncCreator(SrsWaitGroup *w, ManagerType *m, MockAsyncSrsRequest *r)
+ {
+ wg_ = w;
+ manager_ = m;
+ req_ = r;
+ }
+
+ virtual ~MockOtherSourceAsyncCreator()
+ {
+ }
+
+ virtual srs_error_t cycle()
+ {
+ srs_error_t err = do_cycle();
+ wg_->done();
+ return err;
+ }
+
+ srs_error_t do_cycle()
+ {
+ srs_error_t err = srs_success;
+
+ // Test fetch_or_create - should create new source
+ if ((err = manager_->fetch_or_create(req_, source_)) != srs_success) {
+ return srs_error_wrap(err, "fetch or create");
+ }
+
+ return err;
+ }
+};
+
+// Type aliases for convenience (C++98 compatible)
+typedef MockOtherSourceAsyncCreator MockLiveSourceAsyncCreator;
+
+// Test race condition of source managers
+VOID TEST(SourceLockTest, LiveSourceManager_RaceCondition)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/test1", true); // Enable context switch
+ SrsSharedPtr source;
+
+ // Create a coroutine to create source2.
+ SrsWaitGroup wg;
+ MockLiveSourceAsyncCreator creator(&wg, &manager, &req);
+ SrsSTCoroutine trd("test", &creator);
+
+ wg.add(1);
+ HELPER_EXPECT_SUCCESS(trd.start());
+
+ // Test fetch_or_create - should create new source
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Wait for coroutine to finish.
+ wg.wait();
+
+ // The created two sources should be the same instance (no duplicates created)
+ EXPECT_EQ(source.get(), creator.source_.get());
+
+ // Test fetch - should return the same source
+ SrsSharedPtr fetched = manager.fetch(&req);
+ EXPECT_TRUE(fetched.get() != NULL);
+ EXPECT_EQ(source.get(), fetched.get());
+
+ // Test fetch_or_create again - should return existing source
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source.get(), source2.get());
+}
+
+// Type aliases for convenience (C++98 compatible)
+typedef MockOtherSourceAsyncCreator MockRtcSourceAsyncCreator;
+
+// Test race condition of source managers
+VOID TEST(SourceLockTest, RtcSourceManager_RaceCondition)
+{
+ srs_error_t err;
+
+ SrsRtcSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/test1", true); // Enable context switch
+ SrsSharedPtr source;
+
+ // Create a coroutine to create source2.
+ SrsWaitGroup wg;
+ MockRtcSourceAsyncCreator creator(&wg, &manager, &req);
+ SrsSTCoroutine trd("test", &creator);
+
+ wg.add(1);
+ HELPER_EXPECT_SUCCESS(trd.start());
+
+ // Test fetch_or_create - should create new source
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Wait for coroutine to finish.
+ wg.wait();
+
+ // The created two sources should be the same instance (no duplicates created)
+ EXPECT_EQ(source.get(), creator.source_.get());
+
+ // Test fetch - should return the same source
+ SrsSharedPtr fetched = manager.fetch(&req);
+ EXPECT_TRUE(fetched.get() != NULL);
+ EXPECT_EQ(source.get(), fetched.get());
+
+ // Test fetch_or_create again - should return existing source
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source.get(), source2.get());
+}
+
+typedef MockOtherSourceAsyncCreator MockSrtSourceAsyncCreator;
+
+// Test race condition of source managers
+VOID TEST(SourceLockTest, SrtSourceManager_RaceCondition)
+{
+ srs_error_t err;
+
+ SrsSrtSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/test1", true); // Enable context switch
+ SrsSharedPtr source;
+
+ // Create a coroutine to create source2.
+ SrsWaitGroup wg;
+ MockSrtSourceAsyncCreator creator(&wg, &manager, &req);
+ SrsSTCoroutine trd("test", &creator);
+
+ wg.add(1);
+ HELPER_EXPECT_SUCCESS(trd.start());
+
+ // Test fetch_or_create - should create new source
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Wait for coroutine to finish.
+ wg.wait();
+
+ // The created two sources should be the same instance (no duplicates created)
+ EXPECT_EQ(source.get(), creator.source_.get());
+
+ // Test fetch - should return the same source
+ SrsSharedPtr fetched = manager.fetch(&req);
+ EXPECT_TRUE(fetched.get() != NULL);
+ EXPECT_EQ(source.get(), fetched.get());
+
+ // Test fetch_or_create again - should return existing source
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source.get(), source2.get());
+}
+
+// Test basic functionality of source managers
+VOID TEST(SourceLockTest, LiveSourceManager_BasicFunctionality)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/test1");
+ SrsSharedPtr source;
+
+ // Test fetch_or_create - should create new source
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Test fetch - should return the same source
+ SrsSharedPtr fetched = manager.fetch(&req);
+ EXPECT_TRUE(fetched.get() != NULL);
+ EXPECT_EQ(source.get(), fetched.get());
+
+ // Test fetch_or_create again - should return existing source
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source.get(), source2.get());
+}
+
+// Test concurrent access scenarios to verify race condition fixes
+VOID TEST(SourceLockTest, LiveSourceManager_ConcurrentAccess)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/concurrent_test", true); // Enable context switch
+
+ // Simulate multiple concurrent requests for the same stream
+ vector > sources;
+ const int concurrent_requests = 10;
+
+ for (int i = 0; i < concurrent_requests; i++) {
+ SrsSharedPtr source;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ sources.push_back(source);
+ EXPECT_TRUE(source.get() != NULL);
+ }
+
+ // All sources should be the same instance (no duplicates created)
+ for (int i = 1; i < concurrent_requests; i++) {
+ EXPECT_EQ(sources[0].get(), sources[i].get());
+ }
+}
+
+// Test different stream URLs create different sources
+VOID TEST(SourceLockTest, LiveSourceManager_DifferentStreams)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ // Create sources for different streams
+ MockAsyncSrsRequest req1("/live/stream1");
+ MockAsyncSrsRequest req2("/live/stream2");
+ MockAsyncSrsRequest req3("/live/stream3");
+
+ SrsSharedPtr source1, source2, source3;
+
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req1, source1));
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req2, source2));
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req3, source3));
+
+ // All sources should be different instances
+ EXPECT_TRUE(source1.get() != NULL);
+ EXPECT_TRUE(source2.get() != NULL);
+ EXPECT_TRUE(source3.get() != NULL);
+ EXPECT_NE(source1.get(), source2.get());
+ EXPECT_NE(source1.get(), source3.get());
+ EXPECT_NE(source2.get(), source3.get());
+
+ // Fetch should return the same sources
+ SrsSharedPtr fetched1 = manager.fetch(&req1);
+ SrsSharedPtr fetched2 = manager.fetch(&req2);
+ SrsSharedPtr fetched3 = manager.fetch(&req3);
+
+ EXPECT_EQ(source1.get(), fetched1.get());
+ EXPECT_EQ(source2.get(), fetched2.get());
+ EXPECT_EQ(source3.get(), fetched3.get());
+}
+
+// Test fetch for non-existent stream returns NULL
+VOID TEST(SourceLockTest, LiveSourceManager_FetchNonExistent)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/nonexistent");
+
+ // Fetch non-existent source should return NULL
+ SrsSharedPtr source = manager.fetch(&req);
+ EXPECT_TRUE(source.get() == NULL);
+}
+
+// Test that created flag works correctly for initialization
+VOID TEST(SourceLockTest, LiveSourceManager_CreatedFlagLogic)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/created_flag_test");
+
+ // First call should create and initialize
+ SrsSharedPtr source1;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source1));
+ EXPECT_TRUE(source1.get() != NULL);
+
+ // Second call should find existing and only update auth (not initialize again)
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source1.get(), source2.get());
+}
+
+// Test lock protection during source creation
+VOID TEST(SourceLockTest, LiveSourceManager_LockProtection)
+{
+ srs_error_t err;
+
+ // Test that the lock scope is properly limited
+ // This test verifies that no functions are called during locking
+
+ SrsLiveSourceManager live_manager;
+ HELPER_EXPECT_SUCCESS(live_manager.initialize());
+
+ SrsRtcSourceManager rtc_manager;
+ HELPER_EXPECT_SUCCESS(rtc_manager.initialize());
+
+ SrsSrtSourceManager srt_manager;
+ HELPER_EXPECT_SUCCESS(srt_manager.initialize());
+
+ // Test that managers can handle rapid successive calls
+ MockAsyncSrsRequest req("/live/lock_test");
+
+ for (int i = 0; i < 5; i++) {
+ SrsSharedPtr live_source;
+ HELPER_EXPECT_SUCCESS(live_manager.fetch_or_create(&req, live_source));
+ EXPECT_TRUE(live_source.get() != NULL);
+
+ SrsSharedPtr rtc_source;
+ HELPER_EXPECT_SUCCESS(rtc_manager.fetch_or_create(&req, rtc_source));
+ EXPECT_TRUE(rtc_source.get() != NULL);
+
+ SrsSharedPtr srt_source;
+ HELPER_EXPECT_SUCCESS(srt_manager.fetch_or_create(&req, srt_source));
+ EXPECT_TRUE(srt_source.get() != NULL);
+ }
+}
+
+// Test that simulates the original race condition scenario from issue #1230
+// This test verifies that the fix prevents multiple sources for the same stream
+VOID TEST(SourceLockTest, LiveSourceManager_RaceConditionPrevention_Issue1230)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/race_condition_test", true); // Enable context switch
+
+ // Simulate the scenario where multiple coroutines try to create
+ // sources for the same stream simultaneously
+ vector > sources;
+ const int num_attempts = 20;
+
+ // This simulates what would happen if multiple coroutines
+ // called fetch_or_create simultaneously before the fix
+ for (int i = 0; i < num_attempts; i++) {
+ SrsSharedPtr source;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ sources.push_back(source);
+
+ // Verify source is valid
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Verify it's the same source every time (no duplicates)
+ if (i > 0) {
+ EXPECT_EQ(sources[0].get(), source.get())
+ << "Race condition detected: different source instances created for same stream";
+ }
+ }
+
+ // Double-check that all sources are identical
+ for (int i = 1; i < num_attempts; i++) {
+ EXPECT_EQ(sources[0].get(), sources[i].get())
+ << "Source " << i << " differs from source 0";
+ }
+
+ // Verify fetch also returns the same source
+ SrsSharedPtr fetched = manager.fetch(&req);
+ EXPECT_EQ(sources[0].get(), fetched.get());
+}
+
+// Test the atomic nature of source creation and pool insertion
+VOID TEST(SourceLockTest, LiveSourceManager_AtomicSourceCreation)
+{
+ srs_error_t err;
+
+ // Test all source manager types
+ SrsRtcSourceManager rtc_manager;
+ HELPER_EXPECT_SUCCESS(rtc_manager.initialize());
+
+ SrsSrtSourceManager srt_manager;
+ HELPER_EXPECT_SUCCESS(srt_manager.initialize());
+
+ MockAsyncSrsRequest req("/live/atomic_test", true); // Enable context switch
+
+ // Test RTC source manager
+ vector > rtc_sources;
+ for (int i = 0; i < 10; i++) {
+ SrsSharedPtr source;
+ HELPER_EXPECT_SUCCESS(rtc_manager.fetch_or_create(&req, source));
+ rtc_sources.push_back(source);
+ EXPECT_TRUE(source.get() != NULL);
+ if (i > 0) {
+ EXPECT_EQ(rtc_sources[0].get(), source.get());
+ }
+ }
+
+ // Test SRT source manager
+ vector > srt_sources;
+ for (int i = 0; i < 10; i++) {
+ SrsSharedPtr source;
+ HELPER_EXPECT_SUCCESS(srt_manager.fetch_or_create(&req, source));
+ srt_sources.push_back(source);
+ EXPECT_TRUE(source.get() != NULL);
+ if (i > 0) {
+ EXPECT_EQ(srt_sources[0].get(), source.get());
+ }
+ }
+}
+
+// Test that verifies the fix addresses the specific issue mentioned in #1230
+// where DVR and HLS module initialization could cause coroutine switches
+VOID TEST(SourceLockTest, LiveSourceManager_CoroutineSwitchProtection)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ // Test multiple streams to ensure each gets its own source
+ vector stream_urls;
+ stream_urls.push_back("/live/dvr_test1");
+ stream_urls.push_back("/live/dvr_test2");
+ stream_urls.push_back("/live/hls_test1");
+ stream_urls.push_back("/live/hls_test2");
+ stream_urls.push_back("/live/mixed_test");
+
+ map > created_sources;
+
+ // Create sources for each stream
+ for (size_t idx = 0; idx < stream_urls.size(); idx++) {
+ const string &url = stream_urls[idx];
+ MockAsyncSrsRequest req(url, true); // Enable context switch
+ SrsSharedPtr source;
+
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ created_sources[url] = source;
+
+ // Verify subsequent calls return the same source
+ for (int i = 0; i < 3; i++) {
+ SrsSharedPtr same_source;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, same_source));
+ EXPECT_EQ(source.get(), same_source.get())
+ << "Source changed for stream " << url << " on attempt " << i;
+ }
+ }
+
+ // Verify all sources are different from each other
+ vector source_ptrs;
+ for (map >::iterator it = created_sources.begin();
+ it != created_sources.end(); ++it) {
+ source_ptrs.push_back(it->second.get());
+ }
+
+ for (size_t i = 0; i < source_ptrs.size(); i++) {
+ for (size_t j = i + 1; j < source_ptrs.size(); j++) {
+ EXPECT_NE(source_ptrs[i], source_ptrs[j])
+ << "Sources for different streams should be different instances";
+ }
+ }
+}
+
+// Test edge case with empty or invalid stream URLs
+VOID TEST(SourceLockTest, LiveSourceManager_EdgeCases_InvalidUrls)
+{
+ srs_error_t err;
+
+ SrsLiveSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ // Test with various edge case URLs
+ vector edge_case_urls;
+ edge_case_urls.push_back(""); // Empty URL
+ edge_case_urls.push_back("/"); // Root only
+ edge_case_urls.push_back("/live/"); // Trailing slash
+ edge_case_urls.push_back("/live//"); // Double slash
+ edge_case_urls.push_back("/live/test?param=value"); // With parameters
+
+ for (size_t idx = 0; idx < edge_case_urls.size(); idx++) {
+ const string &url = edge_case_urls[idx];
+ MockAsyncSrsRequest req(url);
+ SrsSharedPtr source;
+
+ // Should handle edge cases gracefully
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Verify consistency
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source.get(), source2.get());
+ }
+}
+
+VOID TEST(SourceLockTest, RtcSourceManager_BasicFunctionality)
+{
+ srs_error_t err;
+
+ SrsRtcSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/test2");
+ SrsSharedPtr source;
+
+ // Test fetch_or_create - should create new source
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Test fetch - should return the same source
+ SrsSharedPtr fetched = manager.fetch(&req);
+ EXPECT_TRUE(fetched.get() != NULL);
+ EXPECT_EQ(source.get(), fetched.get());
+
+ // Test fetch_or_create again - should return existing source
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source.get(), source2.get());
+}
+
+VOID TEST(SourceLockTest, SrtSourceManager_BasicFunctionality)
+{
+ srs_error_t err;
+
+ SrsSrtSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/test4");
+ SrsSharedPtr source;
+
+ // Test fetch_or_create - should create new source
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ EXPECT_TRUE(source.get() != NULL);
+
+ // Note: SrsSrtSourceManager doesn't have a fetch method, only fetch_or_create
+ // Test fetch_or_create again - should return existing source
+ SrsSharedPtr source2;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source2));
+ EXPECT_EQ(source.get(), source2.get());
+}
+
+VOID TEST(SourceLockTest, RtcSourceManager_ConcurrentAccess)
+{
+ srs_error_t err;
+
+ SrsRtcSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/rtc_concurrent_test", true); // Enable context switch
+
+ // Simulate multiple concurrent requests for the same stream
+ vector > sources;
+ const int concurrent_requests = 10;
+
+ for (int i = 0; i < concurrent_requests; i++) {
+ SrsSharedPtr source;
+ HELPER_EXPECT_SUCCESS(manager.fetch_or_create(&req, source));
+ sources.push_back(source);
+ EXPECT_TRUE(source.get() != NULL);
+ }
+
+ // All sources should be the same instance (no duplicates created)
+ for (int i = 1; i < concurrent_requests; i++) {
+ EXPECT_EQ(sources[0].get(), sources[i].get());
+ }
+}
+
+VOID TEST(SourceLockTest, RtcSourceManager_FetchNonExistent)
+{
+ srs_error_t err;
+
+ SrsRtcSourceManager manager;
+ HELPER_EXPECT_SUCCESS(manager.initialize());
+
+ MockAsyncSrsRequest req("/live/nonexistent");
+
+ // Fetch non-existent source should return NULL
+ SrsSharedPtr source = manager.fetch(&req);
+ EXPECT_TRUE(source.get() == NULL);
+}
+
+#ifdef SRS_RTSP
+typedef MockOtherSourceAsyncCreator