AI: Add utest to cover the rtc server.
This commit is contained in:
parent
604f9450fc
commit
c6c6f38ed7
|
|
@ -25,6 +25,7 @@
|
|||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_http_client.hpp>
|
||||
#include <srs_protocol_st.hpp>
|
||||
#include <srs_app_rtc_conn.hpp>
|
||||
|
||||
ISrsAppFactory::ISrsAppFactory()
|
||||
{
|
||||
|
|
@ -165,6 +166,13 @@ ISrsIpListener *SrsAppFactory::create_tcp_listener(ISrsTcpHandler *handler)
|
|||
return new SrsTcpListener(handler);
|
||||
}
|
||||
|
||||
ISrsRtcConnection *SrsAppFactory::create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid)
|
||||
{
|
||||
SrsRtcConnection *session = new SrsRtcConnection(exec, cid);
|
||||
session->assemble();
|
||||
return session;
|
||||
}
|
||||
|
||||
ISrsCoroutine *SrsAppFactory::create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid)
|
||||
{
|
||||
return kernel_factory_->create_coroutine(name, handler, cid);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ class ISrsFragmentedMp4;
|
|||
class SrsFinalFactory;
|
||||
class ISrsIpListener;
|
||||
class ISrsTcpHandler;
|
||||
class ISrsRtcConnection;
|
||||
class ISrsExecRtcAsyncTask;
|
||||
|
||||
// The factory to create app objects.
|
||||
class ISrsAppFactory : public ISrsKernelFactory
|
||||
|
|
@ -74,6 +76,7 @@ public:
|
|||
virtual ISrsFragmentWindow *create_fragment_window() = 0;
|
||||
virtual ISrsFragmentedMp4 *create_fragmented_mp4() = 0;
|
||||
virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler) = 0;
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid) = 0;
|
||||
};
|
||||
|
||||
// The factory to create app objects.
|
||||
|
|
@ -114,6 +117,7 @@ public:
|
|||
virtual ISrsFragmentWindow *create_fragment_window();
|
||||
virtual ISrsFragmentedMp4 *create_fragmented_mp4();
|
||||
virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler);
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid);
|
||||
|
||||
public:
|
||||
virtual ISrsCoroutine *create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid);
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ srs_error_t SrsGoApiRtcPlay::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
}
|
||||
|
||||
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
||||
SrsRtcConnection *session = NULL;
|
||||
ISrsRtcConnection *session = NULL;
|
||||
if ((err = server_->create_rtc_session(ruc, local_sdp, &session)) != srs_success) {
|
||||
return srs_error_wrap(err, "create session, dtls=%u, srtp=%u, eip=%s", ruc->dtls_, ruc->srtp_, ruc->eip_.c_str());
|
||||
}
|
||||
|
|
@ -544,7 +544,7 @@ srs_error_t SrsGoApiRtcPublish::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
|
||||
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
||||
// We must do stat the client before hooks, because hooks depends on it.
|
||||
SrsRtcConnection *session = NULL;
|
||||
ISrsRtcConnection *session = NULL;
|
||||
if ((err = server_->create_rtc_session(ruc, local_sdp, &session)) != srs_success) {
|
||||
return srs_error_wrap(err, "create session");
|
||||
}
|
||||
|
|
@ -672,7 +672,7 @@ srs_error_t SrsGoApiRtcWhip::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa
|
|||
return srs_error_new(ERROR_RTC_INVALID_SESSION, "token empty");
|
||||
}
|
||||
|
||||
SrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
ISrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
if (session && token != session->token()) {
|
||||
return srs_error_new(ERROR_RTC_INVALID_SESSION, "token %s not match", token.c_str());
|
||||
}
|
||||
|
|
@ -847,7 +847,7 @@ srs_error_t SrsGoApiRtcNACK::do_serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe
|
|||
return srs_error_new(ERROR_RTC_INVALID_PARAMS, "invalid drop=%s/%d", dropv.c_str(), drop);
|
||||
}
|
||||
|
||||
SrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
ISrsRtcConnection *session = server_->find_rtc_session_by_username(username);
|
||||
if (!session) {
|
||||
return srs_error_new(ERROR_RTC_NO_SESSION, "no session username=%s", username.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2414,6 +2414,11 @@ bool SrsRtcConnection::is_alive()
|
|||
return last_stun_time_ + session_timeout_ > srs_time_now_cached();
|
||||
}
|
||||
|
||||
bool SrsRtcConnection::is_disposing()
|
||||
{
|
||||
return disposing_;
|
||||
}
|
||||
|
||||
void SrsRtcConnection::alive()
|
||||
{
|
||||
last_stun_time_ = srs_time_now_cached();
|
||||
|
|
|
|||
|
|
@ -579,8 +579,26 @@ public:
|
|||
virtual ISrsRtcNetwork *tcp() = 0;
|
||||
// Keep alive.
|
||||
virtual void alive() = 0;
|
||||
virtual bool is_alive() = 0;
|
||||
virtual bool is_disposing() = 0;
|
||||
// Context switching.
|
||||
virtual void switch_to_context() = 0;
|
||||
// Session management.
|
||||
virtual srs_error_t add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp) = 0;
|
||||
virtual srs_error_t add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp) = 0;
|
||||
virtual void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status) = 0;
|
||||
// SDP management.
|
||||
virtual void set_remote_sdp(const SrsSdp &sdp) = 0;
|
||||
virtual void set_local_sdp(const SrsSdp &sdp) = 0;
|
||||
virtual void set_state_as_waiting_stun() = 0;
|
||||
// Initialization.
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username) = 0;
|
||||
// Username and token access.
|
||||
virtual std::string username() = 0;
|
||||
virtual std::string token() = 0;
|
||||
virtual void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token) = 0;
|
||||
// Simulation for testing.
|
||||
virtual void simulate_nack_drop(int nn) = 0;
|
||||
};
|
||||
|
||||
// A RTC Peer Connection, SDP level object.
|
||||
|
|
@ -721,6 +739,7 @@ public:
|
|||
srs_error_t on_dtls_handshake_done();
|
||||
srs_error_t on_dtls_alert(std::string type, std::string desc);
|
||||
bool is_alive();
|
||||
bool is_disposing();
|
||||
void alive();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public:
|
|||
|
||||
public:
|
||||
virtual srs_error_t initialize() = 0;
|
||||
virtual std::string get_fingerprint() = 0;
|
||||
};
|
||||
|
||||
// The DTLS certificate.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ using namespace std;
|
|||
#include <srs_protocol_log.hpp>
|
||||
#include <srs_protocol_rtc_stun.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
|
||||
extern SrsPps *_srs_pps_rpkts;
|
||||
extern SrsPps *_srs_pps_rstuns;
|
||||
|
|
@ -314,6 +315,11 @@ SrsRtcSessionManager::SrsRtcSessionManager()
|
|||
rtc_async_ = new SrsAsyncCallWorker();
|
||||
|
||||
conn_manager_ = _srs_conn_manager;
|
||||
stream_publish_tokens_ = _srs_stream_publish_tokens;
|
||||
rtc_sources_ = _srs_rtc_sources;
|
||||
dtls_certificate_ = _srs_rtc_dtls_certificate;
|
||||
config_ = _srs_config;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsRtcSessionManager::~SrsRtcSessionManager()
|
||||
|
|
@ -322,6 +328,11 @@ SrsRtcSessionManager::~SrsRtcSessionManager()
|
|||
srs_freep(rtc_async_);
|
||||
|
||||
conn_manager_ = NULL;
|
||||
stream_publish_tokens_ = NULL;
|
||||
rtc_sources_ = NULL;
|
||||
dtls_certificate_ = NULL;
|
||||
config_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcSessionManager::initialize()
|
||||
|
|
@ -335,13 +346,13 @@ srs_error_t SrsRtcSessionManager::initialize()
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsRtcConnection *SrsRtcSessionManager::find_rtc_session_by_username(const std::string &username)
|
||||
ISrsRtcConnection *SrsRtcSessionManager::find_rtc_session_by_username(const std::string &username)
|
||||
{
|
||||
ISrsResource *conn = conn_manager_->find_by_name(username);
|
||||
return dynamic_cast<SrsRtcConnection *>(conn);
|
||||
return dynamic_cast<ISrsRtcConnection *>(conn);
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession)
|
||||
srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -349,7 +360,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
|
||||
// Acquire stream publish token to prevent race conditions across all protocols.
|
||||
SrsStreamPublishToken *publish_token_raw = NULL;
|
||||
if (ruc->publish_ && (err = _srs_stream_publish_tokens->acquire_token(req, publish_token_raw)) != srs_success) {
|
||||
if (ruc->publish_ && (err = stream_publish_tokens_->acquire_token(req, publish_token_raw)) != srs_success) {
|
||||
return srs_error_wrap(err, "acquire stream publish token");
|
||||
}
|
||||
SrsSharedPtr<SrsStreamPublishToken> publish_token(publish_token_raw);
|
||||
|
|
@ -358,7 +369,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
}
|
||||
|
||||
SrsSharedPtr<SrsRtcSource> source;
|
||||
if ((err = _srs_rtc_sources->fetch_or_create(req, source)) != srs_success) {
|
||||
if ((err = rtc_sources_->fetch_or_create(req, source)) != srs_success) {
|
||||
return srs_error_wrap(err, "create source");
|
||||
}
|
||||
|
||||
|
|
@ -368,8 +379,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
|
||||
// TODO: FIXME: add do_create_session to error process.
|
||||
SrsContextId cid = _srs_context->get_id();
|
||||
SrsRtcConnection *session = new SrsRtcConnection(this, cid);
|
||||
session->assemble();
|
||||
ISrsRtcConnection *session = app_factory_->create_rtc_connection(this, cid);
|
||||
|
||||
if ((err = do_create_rtc_session(ruc, local_sdp, session)) != srs_success) {
|
||||
srs_freep(session);
|
||||
|
|
@ -386,7 +396,7 @@ srs_error_t SrsRtcSessionManager::create_rtc_session(SrsRtcUserConfig *ruc, SrsS
|
|||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection *session)
|
||||
srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection *session)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
@ -424,7 +434,7 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
local_sdp.set_ice_ufrag(local_ufrag);
|
||||
local_sdp.set_ice_pwd(local_pwd);
|
||||
local_sdp.set_fingerprint_algo("sha-256");
|
||||
local_sdp.set_fingerprint(_srs_rtc_dtls_certificate->get_fingerprint());
|
||||
local_sdp.set_fingerprint(dtls_certificate_->get_fingerprint());
|
||||
|
||||
// We allows to mock the eip of server.
|
||||
if (true) {
|
||||
|
|
@ -432,21 +442,21 @@ srs_error_t SrsRtcSessionManager::do_create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
int udp_port = 0;
|
||||
if (true) {
|
||||
string udp_host;
|
||||
string udp_hostport = _srs_config->get_rtc_server_listens().at(0);
|
||||
string udp_hostport = config_->get_rtc_server_listens().at(0);
|
||||
srs_net_split_for_listener(udp_hostport, udp_host, udp_port);
|
||||
}
|
||||
|
||||
int tcp_port = 0;
|
||||
if (true) {
|
||||
string tcp_host;
|
||||
string tcp_hostport = _srs_config->get_rtc_server_tcp_listens().at(0);
|
||||
string tcp_hostport = config_->get_rtc_server_tcp_listens().at(0);
|
||||
srs_net_split_for_listener(tcp_hostport, tcp_host, tcp_port);
|
||||
}
|
||||
|
||||
string protocol = _srs_config->get_rtc_server_protocol();
|
||||
string protocol = config_->get_rtc_server_protocol();
|
||||
|
||||
SrsProtocolUtility utility;
|
||||
set<string> candidates = discover_candidates(&utility, _srs_config, ruc);
|
||||
set<string> candidates = discover_candidates(&utility, config_, ruc);
|
||||
for (set<string>::iterator it = candidates.begin(); it != candidates.end(); ++it) {
|
||||
string hostname;
|
||||
int uport = udp_port;
|
||||
|
|
@ -510,9 +520,9 @@ void SrsRtcSessionManager::srs_update_rtc_sessions()
|
|||
|
||||
// Check all sessions and dispose the dead sessions.
|
||||
for (int i = 0; i < (int)conn_manager_->size(); i++) {
|
||||
SrsRtcConnection *session = dynamic_cast<SrsRtcConnection *>(conn_manager_->at(i));
|
||||
ISrsRtcConnection *session = dynamic_cast<ISrsRtcConnection *>(conn_manager_->at(i));
|
||||
// Ignore not session, or already disposing.
|
||||
if (!session || session->disposing_) {
|
||||
if (!session || session->is_disposing()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -564,7 +574,7 @@ srs_error_t SrsRtcSessionManager::on_udp_packet(ISrsUdpMuxSocket *skt)
|
|||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsRtcConnection *session = NULL;
|
||||
ISrsRtcConnection *session = NULL;
|
||||
char *data = skt->data();
|
||||
int size = skt->size();
|
||||
bool is_rtp_or_rtcp = srs_is_rtp_or_rtcp((uint8_t *)data, size);
|
||||
|
|
@ -573,11 +583,11 @@ srs_error_t SrsRtcSessionManager::on_udp_packet(ISrsUdpMuxSocket *skt)
|
|||
uint64_t fast_id = skt->fast_id();
|
||||
// Try fast id first, if not found, search by long peer id.
|
||||
if (fast_id) {
|
||||
session = (SrsRtcConnection *)conn_manager_->find_by_fast_id(fast_id);
|
||||
session = (ISrsRtcConnection *)conn_manager_->find_by_fast_id(fast_id);
|
||||
}
|
||||
if (!session) {
|
||||
string peer_id = skt->peer_id();
|
||||
session = (SrsRtcConnection *)conn_manager_->find_by_id(peer_id);
|
||||
session = (ISrsRtcConnection *)conn_manager_->find_by_id(peer_id);
|
||||
}
|
||||
|
||||
if (session) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
class SrsRtcServer;
|
||||
class SrsHourGlass;
|
||||
class SrsRtcConnection;
|
||||
class ISrsRtcConnection;
|
||||
class ISrsRequest;
|
||||
class SrsSdp;
|
||||
class SrsRtcSource;
|
||||
|
|
@ -30,6 +31,11 @@ class SrsResourceManager;
|
|||
class SrsAsyncCallWorker;
|
||||
class ISrsUdpMuxSocket;
|
||||
class ISrsResourceManager;
|
||||
class ISrsStreamPublishTokenManager;
|
||||
class ISrsRtcSourceManager;
|
||||
class ISrsDtlsCertificate;
|
||||
class ISrsAppConfig;
|
||||
class ISrsAppFactory;
|
||||
|
||||
// The UDP black hole, for developer to use wireshark to catch plaintext packets.
|
||||
// For example, server receive UDP packets at udp://8000, and forward the plaintext packet to black hole,
|
||||
|
|
@ -96,6 +102,11 @@ class SrsRtcSessionManager : public ISrsExecRtcAsyncTask
|
|||
{
|
||||
private:
|
||||
ISrsResourceManager *conn_manager_;
|
||||
ISrsStreamPublishTokenManager *stream_publish_tokens_;
|
||||
ISrsRtcSourceManager *rtc_sources_;
|
||||
ISrsDtlsCertificate *dtls_certificate_;
|
||||
ISrsAppConfig *config_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
private:
|
||||
// WebRTC async call worker for non-blocking operations.
|
||||
|
|
@ -109,11 +120,11 @@ public:
|
|||
virtual srs_error_t initialize();
|
||||
|
||||
public:
|
||||
virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession);
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession);
|
||||
|
||||
private:
|
||||
virtual srs_error_t do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection *session);
|
||||
virtual srs_error_t do_create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection *session);
|
||||
|
||||
public:
|
||||
virtual void srs_update_rtc_sessions();
|
||||
|
|
|
|||
|
|
@ -1418,12 +1418,12 @@ srs_error_t SrsServer::listen_rtc_api()
|
|||
return err;
|
||||
}
|
||||
|
||||
SrsRtcConnection *SrsServer::find_rtc_session_by_username(const std::string &username)
|
||||
ISrsRtcConnection *SrsServer::find_rtc_session_by_username(const std::string &username)
|
||||
{
|
||||
return rtc_session_manager_->find_rtc_session_by_username(username);
|
||||
}
|
||||
|
||||
srs_error_t SrsServer::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession)
|
||||
srs_error_t SrsServer::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class ISrsStatistic;
|
|||
class ISrsHourGlass;
|
||||
class ISrsAppFactory;
|
||||
class ISrsUdpMuxSocket;
|
||||
class ISrsRtcConnection;
|
||||
|
||||
// Initialize global shared variables cross all threads.
|
||||
extern srs_error_t srs_global_initialize();
|
||||
|
|
@ -104,8 +105,8 @@ public:
|
|||
virtual ~ISrsRtcApiServer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession) = 0;
|
||||
virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag) = 0;
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession) = 0;
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag) = 0;
|
||||
};
|
||||
|
||||
// SrsServer is the main server class of SRS (Simple Realtime Server) that provides comprehensive
|
||||
|
|
@ -305,8 +306,8 @@ private:
|
|||
virtual srs_error_t listen_rtc_api();
|
||||
|
||||
public:
|
||||
virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession);
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession);
|
||||
|
||||
private:
|
||||
virtual srs_error_t srs_update_server_statistics();
|
||||
|
|
|
|||
|
|
@ -3244,6 +3244,11 @@ ISrsIpListener *MockDvrAppFactory::create_tcp_listener(ISrsTcpHandler *handler)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ISrsRtcConnection *MockDvrAppFactory::create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsCoroutine *MockDvrAppFactory::create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid)
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -642,6 +642,7 @@ public:
|
|||
virtual ISrsFragmentWindow *create_fragment_window();
|
||||
virtual ISrsFragmentedMp4 *create_fragmented_mp4();
|
||||
virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler);
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid);
|
||||
// ISrsKernelFactory interface methods
|
||||
virtual ISrsCoroutine *create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid);
|
||||
virtual ISrsTime *create_time();
|
||||
|
|
|
|||
|
|
@ -1654,10 +1654,69 @@ void MockRtcConnectionForTcpConn::alive()
|
|||
{
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForTcpConn::is_alive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForTcpConn::is_disposing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConn::switch_to_context()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForTcpConn::add_publisher(SrsRtcUserConfig * /*ruc*/, SrsSdp & /*local_sdp*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForTcpConn::add_player(SrsRtcUserConfig * /*ruc*/, SrsSdp & /*local_sdp*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConn::set_all_tracks_status(std::string /*stream_uri*/, bool /*is_publish*/, bool /*status*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConn::set_remote_sdp(const SrsSdp & /*sdp*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConn::set_local_sdp(const SrsSdp & /*sdp*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConn::set_state_as_waiting_stun()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForTcpConn::initialize(ISrsRequest * /*r*/, bool /*dtls*/, bool /*srtp*/, std::string /*username*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForTcpConn::username()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForTcpConn::token()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConn::set_publish_token(SrsSharedPtr<SrsStreamPublishToken> /*publish_token*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConn::simulate_nack_drop(int /*nn*/)
|
||||
{
|
||||
}
|
||||
|
||||
// Mock ISrsPsPackHandler implementation
|
||||
MockPsPackHandler::MockPsPackHandler()
|
||||
{
|
||||
|
|
@ -2406,6 +2465,11 @@ ISrsIpListener *MockAppFactoryForGbPublish::create_tcp_listener(ISrsTcpHandler *
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ISrsRtcConnection *MockAppFactoryForGbPublish::create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsCoroutine *MockAppFactoryForGbPublish::create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid)
|
||||
{
|
||||
return NULL;
|
||||
|
|
@ -2903,10 +2967,69 @@ void MockRtcConnectionForUdpNetwork::alive()
|
|||
{
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForUdpNetwork::is_alive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForUdpNetwork::is_disposing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::switch_to_context()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUdpNetwork::add_publisher(SrsRtcUserConfig * /*ruc*/, SrsSdp & /*local_sdp*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUdpNetwork::add_player(SrsRtcUserConfig * /*ruc*/, SrsSdp & /*local_sdp*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::set_all_tracks_status(std::string /*stream_uri*/, bool /*is_publish*/, bool /*status*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::set_remote_sdp(const SrsSdp & /*sdp*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::set_local_sdp(const SrsSdp & /*sdp*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::set_state_as_waiting_stun()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUdpNetwork::initialize(ISrsRequest * /*r*/, bool /*dtls*/, bool /*srtp*/, std::string /*username*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForUdpNetwork::username()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForUdpNetwork::token()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::set_publish_token(SrsSharedPtr<SrsStreamPublishToken> /*publish_token*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::simulate_nack_drop(int /*nn*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUdpNetwork::set_on_dtls_alert_error(srs_error_t err)
|
||||
{
|
||||
srs_freep(on_dtls_alert_error_);
|
||||
|
|
@ -4096,11 +4219,70 @@ void MockRtcConnectionForTcpConnHandshake::alive()
|
|||
{
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForTcpConnHandshake::is_alive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForTcpConnHandshake::is_disposing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::switch_to_context()
|
||||
{
|
||||
switch_to_context_called_ = true;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForTcpConnHandshake::add_publisher(SrsRtcUserConfig * /*ruc*/, SrsSdp & /*local_sdp*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForTcpConnHandshake::add_player(SrsRtcUserConfig * /*ruc*/, SrsSdp & /*local_sdp*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::set_all_tracks_status(std::string /*stream_uri*/, bool /*is_publish*/, bool /*status*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::set_remote_sdp(const SrsSdp & /*sdp*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::set_local_sdp(const SrsSdp & /*sdp*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::set_state_as_waiting_stun()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForTcpConnHandshake::initialize(ISrsRequest * /*r*/, bool /*dtls*/, bool /*srtp*/, std::string /*username*/)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForTcpConnHandshake::username()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForTcpConnHandshake::token()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::set_publish_token(SrsSharedPtr<SrsStreamPublishToken> /*publish_token*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::simulate_nack_drop(int /*nn*/)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForTcpConnHandshake::reset()
|
||||
{
|
||||
tcp_network_ = NULL;
|
||||
|
|
|
|||
|
|
@ -157,7 +157,20 @@ public:
|
|||
virtual ISrsRtcNetwork *udp();
|
||||
virtual ISrsRtcNetwork *tcp();
|
||||
virtual void alive();
|
||||
virtual bool is_alive();
|
||||
virtual bool is_disposing();
|
||||
virtual void switch_to_context();
|
||||
virtual srs_error_t add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual srs_error_t add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status);
|
||||
virtual void set_remote_sdp(const SrsSdp &sdp);
|
||||
virtual void set_local_sdp(const SrsSdp &sdp);
|
||||
virtual void set_state_as_waiting_stun();
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username);
|
||||
virtual std::string username();
|
||||
virtual std::string token();
|
||||
virtual void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token);
|
||||
virtual void simulate_nack_drop(int nn);
|
||||
|
||||
public:
|
||||
void set_on_dtls_alert_error(srs_error_t err);
|
||||
|
|
@ -477,7 +490,20 @@ public:
|
|||
virtual ISrsRtcNetwork *udp();
|
||||
virtual ISrsRtcNetwork *tcp();
|
||||
virtual void alive();
|
||||
virtual bool is_alive();
|
||||
virtual bool is_disposing();
|
||||
virtual void switch_to_context();
|
||||
virtual srs_error_t add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual srs_error_t add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status);
|
||||
virtual void set_remote_sdp(const SrsSdp &sdp);
|
||||
virtual void set_local_sdp(const SrsSdp &sdp);
|
||||
virtual void set_state_as_waiting_stun();
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username);
|
||||
virtual std::string username();
|
||||
virtual std::string token();
|
||||
virtual void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token);
|
||||
virtual void simulate_nack_drop(int nn);
|
||||
};
|
||||
|
||||
// Mock ISrsPsPackHandler for testing SrsPackContext
|
||||
|
|
@ -606,6 +632,7 @@ public:
|
|||
virtual ISrsFragmentWindow *create_fragment_window();
|
||||
virtual ISrsFragmentedMp4 *create_fragmented_mp4();
|
||||
virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler);
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid);
|
||||
// ISrsKernelFactory interface methods
|
||||
virtual ISrsCoroutine *create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid);
|
||||
virtual ISrsTime *create_time();
|
||||
|
|
@ -847,7 +874,20 @@ public:
|
|||
virtual ISrsRtcNetwork *udp();
|
||||
virtual ISrsRtcNetwork *tcp();
|
||||
virtual void alive();
|
||||
virtual bool is_alive();
|
||||
virtual bool is_disposing();
|
||||
virtual void switch_to_context();
|
||||
virtual srs_error_t add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual srs_error_t add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status);
|
||||
virtual void set_remote_sdp(const SrsSdp &sdp);
|
||||
virtual void set_local_sdp(const SrsSdp &sdp);
|
||||
virtual void set_state_as_waiting_stun();
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username);
|
||||
virtual std::string username();
|
||||
virtual std::string token();
|
||||
virtual void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token);
|
||||
virtual void simulate_nack_drop(int nn);
|
||||
|
||||
public:
|
||||
void reset();
|
||||
|
|
|
|||
|
|
@ -1774,7 +1774,7 @@ MockRtcApiServer::~MockRtcApiServer()
|
|||
srs_freep(mock_connection_);
|
||||
}
|
||||
|
||||
srs_error_t MockRtcApiServer::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession)
|
||||
srs_error_t MockRtcApiServer::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession)
|
||||
{
|
||||
create_session_called_ = true;
|
||||
|
||||
|
|
@ -1793,7 +1793,7 @@ srs_error_t MockRtcApiServer::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
SrsRtcConnection *MockRtcApiServer::find_rtc_session_by_username(const std::string &ufrag)
|
||||
ISrsRtcConnection *MockRtcApiServer::find_rtc_session_by_username(const std::string &ufrag)
|
||||
{
|
||||
find_username_ = ufrag;
|
||||
// Return NULL to simulate session not found (easier to test than full mock)
|
||||
|
|
@ -2126,7 +2126,7 @@ MockRtcApiServerForPlay::~MockRtcApiServerForPlay()
|
|||
srs_freep(mock_connection_);
|
||||
}
|
||||
|
||||
srs_error_t MockRtcApiServerForPlay::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession)
|
||||
srs_error_t MockRtcApiServerForPlay::create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession)
|
||||
{
|
||||
create_session_called_ = true;
|
||||
|
||||
|
|
@ -2143,7 +2143,7 @@ srs_error_t MockRtcApiServerForPlay::create_rtc_session(SrsRtcUserConfig *ruc, S
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
SrsRtcConnection *MockRtcApiServerForPlay::find_rtc_session_by_username(const std::string &ufrag)
|
||||
ISrsRtcConnection *MockRtcApiServerForPlay::find_rtc_session_by_username(const std::string &ufrag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,8 +290,8 @@ public:
|
|||
virtual ~MockRtcApiServer();
|
||||
|
||||
public:
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession);
|
||||
virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession);
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
};
|
||||
|
||||
// Mock ISrsStatistic for testing RTC API
|
||||
|
|
@ -447,8 +447,8 @@ public:
|
|||
virtual ~MockRtcApiServerForPlay();
|
||||
|
||||
public:
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, SrsRtcConnection **psession);
|
||||
virtual SrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
virtual srs_error_t create_rtc_session(SrsRtcUserConfig *ruc, SrsSdp &local_sdp, ISrsRtcConnection **psession);
|
||||
virtual ISrsRtcConnection *find_rtc_session_by_username(const std::string &ufrag);
|
||||
};
|
||||
|
||||
// Mock ISrsHttpResponseReader for testing SrsHttpHooks
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ using namespace std;
|
|||
#include <srs_kernel_st.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_protocol_utility.hpp>
|
||||
#include <srs_utest_app14.hpp>
|
||||
#include <sstream>
|
||||
|
||||
// Mock ISrsSrtSocket implementation
|
||||
|
|
@ -1855,3 +1856,752 @@ VOID TEST(RtcServerTest, DiscoverCandidates_EipOverride)
|
|||
EXPECT_TRUE(candidates.find("198.51.100.20") != candidates.end());
|
||||
EXPECT_TRUE(candidates.find("192.168.1.100") != candidates.end());
|
||||
}
|
||||
|
||||
// Mock ISrsStreamPublishTokenManager implementation
|
||||
MockStreamPublishTokenManager::MockStreamPublishTokenManager()
|
||||
{
|
||||
acquire_token_error_ = srs_success;
|
||||
acquire_token_count_ = 0;
|
||||
release_token_count_ = 0;
|
||||
token_to_return_ = NULL;
|
||||
}
|
||||
|
||||
MockStreamPublishTokenManager::~MockStreamPublishTokenManager()
|
||||
{
|
||||
srs_freep(acquire_token_error_);
|
||||
// Note: Don't free token_to_return_ because it's managed by SrsSharedPtr in the caller
|
||||
}
|
||||
|
||||
srs_error_t MockStreamPublishTokenManager::acquire_token(ISrsRequest *req, SrsStreamPublishToken *&token)
|
||||
{
|
||||
acquire_token_count_++;
|
||||
if (acquire_token_error_ != srs_success) {
|
||||
token = NULL;
|
||||
return srs_error_copy(acquire_token_error_);
|
||||
}
|
||||
|
||||
// Create a new token if not already created
|
||||
if (!token_to_return_) {
|
||||
token_to_return_ = new SrsStreamPublishToken(req->get_stream_url(), NULL);
|
||||
}
|
||||
token = token_to_return_;
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockStreamPublishTokenManager::release_token(const std::string &stream_url)
|
||||
{
|
||||
release_token_count_++;
|
||||
}
|
||||
|
||||
void MockStreamPublishTokenManager::set_acquire_token_error(srs_error_t err)
|
||||
{
|
||||
srs_freep(acquire_token_error_);
|
||||
acquire_token_error_ = srs_error_copy(err);
|
||||
}
|
||||
|
||||
void MockStreamPublishTokenManager::reset()
|
||||
{
|
||||
srs_freep(acquire_token_error_);
|
||||
// Note: Don't free token_to_return_ here because it may have been freed by SrsSharedPtr
|
||||
// Just set it to NULL
|
||||
acquire_token_error_ = srs_success;
|
||||
acquire_token_count_ = 0;
|
||||
release_token_count_ = 0;
|
||||
token_to_return_ = NULL;
|
||||
}
|
||||
|
||||
// Mock ISrsRtcConnection implementation
|
||||
MockRtcConnectionForSessionManager::MockRtcConnectionForSessionManager()
|
||||
{
|
||||
add_publisher_called_ = false;
|
||||
add_player_called_ = false;
|
||||
set_all_tracks_status_called_ = false;
|
||||
set_publish_token_called_ = false;
|
||||
add_publisher_error_ = srs_success;
|
||||
add_player_error_ = srs_success;
|
||||
username_ = "test-username";
|
||||
token_ = "test-token";
|
||||
}
|
||||
|
||||
MockRtcConnectionForSessionManager::~MockRtcConnectionForSessionManager()
|
||||
{
|
||||
srs_freep(add_publisher_error_);
|
||||
srs_freep(add_player_error_);
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForSessionManager::add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp)
|
||||
{
|
||||
add_publisher_called_ = true;
|
||||
return srs_error_copy(add_publisher_error_);
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForSessionManager::add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp)
|
||||
{
|
||||
add_player_called_ = true;
|
||||
return srs_error_copy(add_player_error_);
|
||||
}
|
||||
|
||||
void MockRtcConnectionForSessionManager::set_all_tracks_status(std::string stream_uri, bool is_publish, bool status)
|
||||
{
|
||||
set_all_tracks_status_called_ = true;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForSessionManager::set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token)
|
||||
{
|
||||
set_publish_token_called_ = true;
|
||||
publish_token_ = publish_token;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForSessionManager::reset()
|
||||
{
|
||||
add_publisher_called_ = false;
|
||||
add_player_called_ = false;
|
||||
set_all_tracks_status_called_ = false;
|
||||
set_publish_token_called_ = false;
|
||||
srs_freep(add_publisher_error_);
|
||||
srs_freep(add_player_error_);
|
||||
add_publisher_error_ = srs_success;
|
||||
add_player_error_ = srs_success;
|
||||
}
|
||||
|
||||
// Mock ISrsAppFactory implementation
|
||||
MockAppFactoryForSessionManager::MockAppFactoryForSessionManager()
|
||||
{
|
||||
mock_connection_ = new MockRtcConnectionForSessionManager();
|
||||
create_rtc_connection_count_ = 0;
|
||||
}
|
||||
|
||||
MockAppFactoryForSessionManager::~MockAppFactoryForSessionManager()
|
||||
{
|
||||
srs_freep(mock_connection_);
|
||||
}
|
||||
|
||||
ISrsRtcConnection *MockAppFactoryForSessionManager::create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid)
|
||||
{
|
||||
create_rtc_connection_count_++;
|
||||
// Create a real SrsRtcConnection object for testing
|
||||
// The test will inject mock_connection_ methods into it
|
||||
SrsRtcConnection *session = new SrsRtcConnection(exec, cid);
|
||||
return session;
|
||||
}
|
||||
|
||||
void MockAppFactoryForSessionManager::reset()
|
||||
{
|
||||
create_rtc_connection_count_ = 0;
|
||||
}
|
||||
|
||||
// Unit test for SrsRtcSessionManager::create_rtc_session
|
||||
// This test verifies the major use scenario: token acquisition and error handling
|
||||
// Note: Full session creation requires complex initialization, so we test the key logic paths
|
||||
VOID TEST(RtcSessionManagerTest, CreateRtcSession_TokenAcquisitionAndErrorHandling)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
// Create mock dependencies
|
||||
MockResourceManagerForBindSession mock_conn_manager;
|
||||
MockStreamPublishTokenManager mock_token_manager;
|
||||
MockRtcSourceManager mock_rtc_sources;
|
||||
|
||||
// Create SrsRtcSessionManager
|
||||
SrsUniquePtr<SrsRtcSessionManager> session_manager(new SrsRtcSessionManager());
|
||||
|
||||
// Inject mock dependencies
|
||||
session_manager->conn_manager_ = &mock_conn_manager;
|
||||
session_manager->stream_publish_tokens_ = &mock_token_manager;
|
||||
session_manager->rtc_sources_ = &mock_rtc_sources;
|
||||
|
||||
// Test 1: Verify error handling when token acquisition fails
|
||||
{
|
||||
// Set token acquisition to fail
|
||||
mock_token_manager.set_acquire_token_error(srs_error_new(ERROR_SYSTEM_STREAM_BUSY, "stream busy"));
|
||||
|
||||
// Create RTC user config for publishing
|
||||
SrsUniquePtr<SrsRtcUserConfig> ruc(new SrsRtcUserConfig());
|
||||
ruc->publish_ = true;
|
||||
ruc->req_ = new MockRtcAsyncCallRequest("test.vhost", "live", "stream1");
|
||||
|
||||
// Create local SDP
|
||||
SrsSdp local_sdp;
|
||||
|
||||
// Test: Create RTC session should fail due to token acquisition error
|
||||
ISrsRtcConnection *session = NULL;
|
||||
HELPER_EXPECT_FAILED(session_manager->create_rtc_session(ruc.get(), local_sdp, &session));
|
||||
|
||||
// Verify: Token acquisition was attempted
|
||||
EXPECT_EQ(mock_token_manager.acquire_token_count_, 1);
|
||||
|
||||
// Verify: RTC source was NOT fetched/created (because token acquisition failed first)
|
||||
EXPECT_EQ(mock_rtc_sources.fetch_or_create_count_, 0);
|
||||
|
||||
// Clean up
|
||||
srs_freep(session);
|
||||
srs_freep(ruc->req_);
|
||||
}
|
||||
|
||||
// Test 2: Verify error handling when source fetch/create fails
|
||||
{
|
||||
mock_token_manager.reset();
|
||||
mock_rtc_sources.reset();
|
||||
|
||||
// Set source fetch/create to fail
|
||||
mock_rtc_sources.set_fetch_or_create_error(srs_error_new(ERROR_SYSTEM_CREATE_PIPE, "create source failed"));
|
||||
|
||||
// Create RTC user config for publishing
|
||||
SrsUniquePtr<SrsRtcUserConfig> ruc2(new SrsRtcUserConfig());
|
||||
ruc2->publish_ = true;
|
||||
ruc2->req_ = new MockRtcAsyncCallRequest("test.vhost", "live", "stream2");
|
||||
|
||||
// Create local SDP
|
||||
SrsSdp local_sdp2;
|
||||
|
||||
// Test: Create RTC session should fail due to source creation error
|
||||
ISrsRtcConnection *session2 = NULL;
|
||||
HELPER_EXPECT_FAILED(session_manager->create_rtc_session(ruc2.get(), local_sdp2, &session2));
|
||||
|
||||
// Verify: Token acquisition was attempted
|
||||
EXPECT_EQ(mock_token_manager.acquire_token_count_, 1);
|
||||
|
||||
// Verify: RTC source fetch/create was attempted
|
||||
EXPECT_EQ(mock_rtc_sources.fetch_or_create_count_, 1);
|
||||
|
||||
// Clean up
|
||||
srs_freep(session2);
|
||||
srs_freep(ruc2->req_);
|
||||
}
|
||||
|
||||
// Test 3: Verify error handling when source cannot publish (stream busy)
|
||||
{
|
||||
mock_token_manager.reset();
|
||||
mock_rtc_sources.reset();
|
||||
|
||||
// Set source to not allow publishing (simulate stream busy)
|
||||
// can_publish() returns !is_created_, so set is_created_ to true
|
||||
mock_rtc_sources.mock_source_->is_created_ = true;
|
||||
|
||||
// Create RTC user config for publishing
|
||||
SrsUniquePtr<SrsRtcUserConfig> ruc3(new SrsRtcUserConfig());
|
||||
ruc3->publish_ = true;
|
||||
ruc3->req_ = new MockRtcAsyncCallRequest("test.vhost", "live", "stream3");
|
||||
|
||||
// Create local SDP
|
||||
SrsSdp local_sdp3;
|
||||
|
||||
// Test: Create RTC session should fail because source is busy
|
||||
ISrsRtcConnection *session3 = NULL;
|
||||
HELPER_EXPECT_FAILED(session_manager->create_rtc_session(ruc3.get(), local_sdp3, &session3));
|
||||
|
||||
// Verify: Token acquisition was attempted
|
||||
EXPECT_EQ(mock_token_manager.acquire_token_count_, 1);
|
||||
|
||||
// Verify: RTC source fetch/create was attempted
|
||||
EXPECT_EQ(mock_rtc_sources.fetch_or_create_count_, 1);
|
||||
|
||||
// Clean up
|
||||
srs_freep(session3);
|
||||
srs_freep(ruc3->req_);
|
||||
}
|
||||
|
||||
// Clean up - set to NULL to avoid double-free
|
||||
session_manager->conn_manager_ = NULL;
|
||||
session_manager->stream_publish_tokens_ = NULL;
|
||||
session_manager->rtc_sources_ = NULL;
|
||||
}
|
||||
|
||||
// Mock ISrsRtcConnection implementation for srs_update_rtc_sessions test
|
||||
MockRtcConnectionForUpdateSessions::MockRtcConnectionForUpdateSessions()
|
||||
{
|
||||
is_alive_ = true;
|
||||
is_disposing_ = false;
|
||||
username_ = "test-user";
|
||||
switch_to_context_called_ = false;
|
||||
alive_called_ = false;
|
||||
udp_network_ = NULL;
|
||||
}
|
||||
|
||||
MockRtcConnectionForUpdateSessions::~MockRtcConnectionForUpdateSessions()
|
||||
{
|
||||
udp_network_ = NULL;
|
||||
}
|
||||
|
||||
const SrsContextId &MockRtcConnectionForUpdateSessions::get_id()
|
||||
{
|
||||
return cid_;
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForUpdateSessions::desc()
|
||||
{
|
||||
return "MockRtcConnection";
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::on_disposing(ISrsResource *c)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::on_before_dispose(ISrsResource *c)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::expire()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::send_rtcp(char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer *rtp_queue, const uint64_t &last_send_systime, const SrsNtp &last_send_ntp)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::send_rtcp_xr_rrtr(uint32_t ssrc)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::check_send_nacks(SrsRtpNackForReceiver *nack, uint32_t ssrc, uint32_t &sent_nacks, uint32_t &timeout_nacks)
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::send_rtcp_fb_pli(uint32_t ssrc, const SrsContextId &cid_of_subscriber)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::do_send_packet(SrsRtpPacket *pkt)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::do_check_send_nacks()
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::on_timer_nack()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::on_dtls_handshake_done()
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::on_dtls_alert(std::string type, std::string desc)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::on_rtp_cipher(char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::on_rtp_plaintext(char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::on_rtcp(char *data, int nb_data)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::on_binding_request(SrsStunPacket *r, std::string &ice_pwd)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
ISrsRtcNetwork *MockRtcConnectionForUpdateSessions::udp()
|
||||
{
|
||||
return udp_network_;
|
||||
}
|
||||
|
||||
ISrsRtcNetwork *MockRtcConnectionForUpdateSessions::tcp()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::alive()
|
||||
{
|
||||
alive_called_ = true;
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForUpdateSessions::is_alive()
|
||||
{
|
||||
return is_alive_;
|
||||
}
|
||||
|
||||
bool MockRtcConnectionForUpdateSessions::is_disposing()
|
||||
{
|
||||
return is_disposing_;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::switch_to_context()
|
||||
{
|
||||
switch_to_context_called_ = true;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::set_all_tracks_status(std::string stream_uri, bool is_publish, bool status)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::set_remote_sdp(const SrsSdp &sdp)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::set_local_sdp(const SrsSdp &sdp)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::set_state_as_waiting_stun()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcConnectionForUpdateSessions::initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForUpdateSessions::username()
|
||||
{
|
||||
return username_;
|
||||
}
|
||||
|
||||
std::string MockRtcConnectionForUpdateSessions::token()
|
||||
{
|
||||
return "test-token";
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::simulate_drop_packet(bool v, int nn)
|
||||
{
|
||||
}
|
||||
|
||||
void MockRtcConnectionForUpdateSessions::simulate_nack_drop(int nn)
|
||||
{
|
||||
}
|
||||
|
||||
// Mock ISrsResourceManager implementation for srs_update_rtc_sessions test
|
||||
MockResourceManagerForUpdateSessions::MockResourceManagerForUpdateSessions()
|
||||
{
|
||||
}
|
||||
|
||||
MockResourceManagerForUpdateSessions::~MockResourceManagerForUpdateSessions()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
srs_error_t MockResourceManagerForUpdateSessions::start()
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
bool MockResourceManagerForUpdateSessions::empty()
|
||||
{
|
||||
return resources_.empty();
|
||||
}
|
||||
|
||||
size_t MockResourceManagerForUpdateSessions::size()
|
||||
{
|
||||
return resources_.size();
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::add(ISrsResource *conn, bool *exists)
|
||||
{
|
||||
resources_.push_back(conn);
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::add_with_id(const std::string &id, ISrsResource *conn)
|
||||
{
|
||||
resources_.push_back(conn);
|
||||
id_map_[id] = conn;
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::add_with_fast_id(uint64_t id, ISrsResource *conn)
|
||||
{
|
||||
resources_.push_back(conn);
|
||||
fast_id_map_[id] = conn;
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::add_with_name(const std::string &name, ISrsResource *conn)
|
||||
{
|
||||
resources_.push_back(conn);
|
||||
name_map_[name] = conn;
|
||||
}
|
||||
|
||||
ISrsResource *MockResourceManagerForUpdateSessions::at(int index)
|
||||
{
|
||||
if (index < 0 || index >= (int)resources_.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return resources_[index];
|
||||
}
|
||||
|
||||
ISrsResource *MockResourceManagerForUpdateSessions::find_by_id(std::string id)
|
||||
{
|
||||
std::map<std::string, ISrsResource *>::iterator it = id_map_.find(id);
|
||||
if (it != id_map_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsResource *MockResourceManagerForUpdateSessions::find_by_fast_id(uint64_t id)
|
||||
{
|
||||
std::map<uint64_t, ISrsResource *>::iterator it = fast_id_map_.find(id);
|
||||
if (it != fast_id_map_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsResource *MockResourceManagerForUpdateSessions::find_by_name(std::string name)
|
||||
{
|
||||
std::map<std::string, ISrsResource *>::iterator it = name_map_.find(name);
|
||||
if (it != name_map_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::remove(ISrsResource *c)
|
||||
{
|
||||
removed_resources_.push_back(c);
|
||||
// Remove from resources_ vector
|
||||
for (std::vector<ISrsResource *>::iterator it = resources_.begin(); it != resources_.end(); ++it) {
|
||||
if (*it == c) {
|
||||
resources_.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::subscribe(ISrsDisposingHandler *h)
|
||||
{
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::unsubscribe(ISrsDisposingHandler *h)
|
||||
{
|
||||
}
|
||||
|
||||
void MockResourceManagerForUpdateSessions::reset()
|
||||
{
|
||||
resources_.clear();
|
||||
removed_resources_.clear();
|
||||
id_map_.clear();
|
||||
fast_id_map_.clear();
|
||||
name_map_.clear();
|
||||
}
|
||||
|
||||
// Unit test for SrsRtcSessionManager::srs_update_rtc_sessions
|
||||
// This test verifies the major use scenario: checking sessions and disposing dead sessions
|
||||
VOID TEST(RtcSessionManagerTest, UpdateRtcSessions_CheckAndDisposeDeadSessions)
|
||||
{
|
||||
// Create mock connection manager
|
||||
SrsUniquePtr<MockResourceManagerForUpdateSessions> mock_conn_manager(new MockResourceManagerForUpdateSessions());
|
||||
|
||||
// Create SrsRtcSessionManager
|
||||
SrsUniquePtr<SrsRtcSessionManager> session_manager(new SrsRtcSessionManager());
|
||||
|
||||
// Inject mock connection manager
|
||||
session_manager->conn_manager_ = mock_conn_manager.get();
|
||||
|
||||
// Test scenario: Multiple sessions with different states
|
||||
// - Session 1: Alive session (should be counted, not removed)
|
||||
// - Session 2: Dead session (not alive, should be removed)
|
||||
// - Session 3: Disposing session (should be ignored)
|
||||
// - Session 4: Alive session (should be counted, not removed)
|
||||
|
||||
// Create mock sessions
|
||||
MockRtcConnectionForUpdateSessions *session1 = new MockRtcConnectionForUpdateSessions();
|
||||
session1->is_alive_ = true;
|
||||
session1->is_disposing_ = false;
|
||||
session1->username_ = "user1";
|
||||
|
||||
MockRtcConnectionForUpdateSessions *session2 = new MockRtcConnectionForUpdateSessions();
|
||||
session2->is_alive_ = false; // Dead session
|
||||
session2->is_disposing_ = false;
|
||||
session2->username_ = "user2";
|
||||
|
||||
MockRtcConnectionForUpdateSessions *session3 = new MockRtcConnectionForUpdateSessions();
|
||||
session3->is_alive_ = false;
|
||||
session3->is_disposing_ = true; // Already disposing
|
||||
session3->username_ = "user3";
|
||||
|
||||
MockRtcConnectionForUpdateSessions *session4 = new MockRtcConnectionForUpdateSessions();
|
||||
session4->is_alive_ = true;
|
||||
session4->is_disposing_ = false;
|
||||
session4->username_ = "user4";
|
||||
|
||||
// Add sessions to mock connection manager
|
||||
mock_conn_manager->add(session1);
|
||||
mock_conn_manager->add(session2);
|
||||
mock_conn_manager->add(session3);
|
||||
mock_conn_manager->add(session4);
|
||||
|
||||
// Verify initial state
|
||||
EXPECT_EQ(mock_conn_manager->size(), 4);
|
||||
EXPECT_EQ(mock_conn_manager->removed_resources_.size(), 0);
|
||||
|
||||
// Call srs_update_rtc_sessions
|
||||
session_manager->srs_update_rtc_sessions();
|
||||
|
||||
// Verify results:
|
||||
// 1. Dead session (session2) should be removed
|
||||
EXPECT_EQ(mock_conn_manager->removed_resources_.size(), 1);
|
||||
EXPECT_EQ(mock_conn_manager->removed_resources_[0], session2);
|
||||
|
||||
// 2. switch_to_context should be called for dead session
|
||||
EXPECT_TRUE(session2->switch_to_context_called_);
|
||||
|
||||
// 3. Alive sessions should NOT be removed
|
||||
EXPECT_FALSE(session1->switch_to_context_called_);
|
||||
EXPECT_FALSE(session4->switch_to_context_called_);
|
||||
|
||||
// 4. Disposing session should be ignored (not removed again)
|
||||
EXPECT_FALSE(session3->switch_to_context_called_);
|
||||
|
||||
// 5. Connection manager should have 3 sessions left (session1, session3, session4)
|
||||
EXPECT_EQ(mock_conn_manager->size(), 3);
|
||||
|
||||
// Clean up - set to NULL to avoid double-free
|
||||
session_manager->conn_manager_ = NULL;
|
||||
|
||||
// Free mock sessions
|
||||
srs_freep(session1);
|
||||
srs_freep(session2);
|
||||
srs_freep(session3);
|
||||
srs_freep(session4);
|
||||
}
|
||||
|
||||
// Mock ISrsRtcNetwork implementation for on_udp_packet tests
|
||||
MockRtcNetworkForUdpNetwork::MockRtcNetworkForUdpNetwork()
|
||||
{
|
||||
on_stun_called_ = false;
|
||||
on_rtp_called_ = false;
|
||||
on_rtcp_called_ = false;
|
||||
on_dtls_called_ = false;
|
||||
}
|
||||
|
||||
MockRtcNetworkForUdpNetwork::~MockRtcNetworkForUdpNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::initialize(SrsSessionConfig *cfg, bool dtls, bool srtp)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcNetworkForUdpNetwork::set_state(SrsRtcNetworkState state)
|
||||
{
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::on_dtls_handshake_done()
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::on_dtls_alert(std::string type, std::string desc)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::on_dtls(char *data, int nb_data)
|
||||
{
|
||||
on_dtls_called_ = true;
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::on_stun(SrsStunPacket *r, char *data, int nb_data)
|
||||
{
|
||||
on_stun_called_ = true;
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::on_rtp(char *data, int nb_data)
|
||||
{
|
||||
on_rtp_called_ = true;
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::on_rtcp(char *data, int nb_data)
|
||||
{
|
||||
on_rtcp_called_ = true;
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::protect_rtp(void *packet, int *nb_cipher)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::protect_rtcp(void *packet, int *nb_cipher)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
bool MockRtcNetworkForUdpNetwork::is_establelished()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcNetworkForUdpNetwork::write(void *buf, size_t size, ssize_t *nwrite)
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
// Test SrsRtcSessionManager::on_udp_packet with no session found (error case)
|
||||
VOID TEST(RtcSessionManagerTest, OnUdpPacket_NoSessionFound)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// Create session manager
|
||||
SrsUniquePtr<SrsRtcSessionManager> session_manager(new SrsRtcSessionManager());
|
||||
|
||||
// Create mock connection manager (empty - no sessions)
|
||||
SrsUniquePtr<MockResourceManagerForUpdateSessions> mock_conn_manager(new MockResourceManagerForUpdateSessions());
|
||||
|
||||
// Inject mock connection manager
|
||||
session_manager->conn_manager_ = mock_conn_manager.get();
|
||||
|
||||
// Create RTP packet (V=2, PT=96 for RTP)
|
||||
char rtp_packet[20];
|
||||
memset(rtp_packet, 0, sizeof(rtp_packet));
|
||||
rtp_packet[0] = (char)0x80; // V=2 (10000000)
|
||||
rtp_packet[1] = 96; // PT=96 (RTP payload type)
|
||||
|
||||
// Create mock UDP socket
|
||||
SrsUniquePtr<MockUdpMuxSocket> mock_socket(new MockUdpMuxSocket());
|
||||
mock_socket->data_ = rtp_packet;
|
||||
mock_socket->size_ = 20;
|
||||
mock_socket->fast_id_ = 12345; // Non-existent session
|
||||
mock_socket->peer_id_ = "192.168.1.100:8000";
|
||||
|
||||
// Call on_udp_packet
|
||||
err = session_manager->on_udp_packet(mock_socket.get());
|
||||
|
||||
// Verify: Should fail when no session is found
|
||||
HELPER_EXPECT_FAILED(err);
|
||||
|
||||
// Clean up
|
||||
session_manager->conn_manager_ = NULL;
|
||||
}
|
||||
|
||||
// Note: The remaining tests for RTP, RTCP, DTLS, and STUN packets require more complex setup
|
||||
// including proper mock UDP networks and session initialization. The above test covers the
|
||||
// basic error path when no session is found, which is a key scenario in on_udp_packet.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
#include <srs_utest_app10.hpp>
|
||||
#include <srs_utest_app11.hpp>
|
||||
#include <srs_utest_app6.hpp>
|
||||
#include <srs_app_stream_token.hpp>
|
||||
#include <srs_app_rtc_conn.hpp>
|
||||
|
||||
// Mock ISrsSrtSocket for testing SrsSrtConnection
|
||||
class MockSrtSocket : public ISrsSrtSocket
|
||||
|
|
@ -252,4 +254,204 @@ public:
|
|||
virtual std::string get_rtc_server_ip_family();
|
||||
};
|
||||
|
||||
// Mock ISrsStreamPublishTokenManager for testing SrsRtcSessionManager
|
||||
class MockStreamPublishTokenManager : public ISrsStreamPublishTokenManager
|
||||
{
|
||||
public:
|
||||
srs_error_t acquire_token_error_;
|
||||
int acquire_token_count_;
|
||||
int release_token_count_;
|
||||
SrsStreamPublishToken *token_to_return_;
|
||||
|
||||
public:
|
||||
MockStreamPublishTokenManager();
|
||||
virtual ~MockStreamPublishTokenManager();
|
||||
|
||||
public:
|
||||
virtual srs_error_t acquire_token(ISrsRequest *req, SrsStreamPublishToken *&token);
|
||||
virtual void release_token(const std::string &stream_url);
|
||||
void set_acquire_token_error(srs_error_t err);
|
||||
void reset();
|
||||
};
|
||||
|
||||
// Mock ISrsRtcConnection for testing SrsRtcSessionManager
|
||||
// Note: This is a simplified mock that only implements the methods needed for testing
|
||||
class MockRtcConnectionForSessionManager
|
||||
{
|
||||
public:
|
||||
bool add_publisher_called_;
|
||||
bool add_player_called_;
|
||||
bool set_all_tracks_status_called_;
|
||||
bool set_publish_token_called_;
|
||||
srs_error_t add_publisher_error_;
|
||||
srs_error_t add_player_error_;
|
||||
std::string username_;
|
||||
std::string token_;
|
||||
SrsSharedPtr<SrsStreamPublishToken> publish_token_;
|
||||
|
||||
public:
|
||||
MockRtcConnectionForSessionManager();
|
||||
virtual ~MockRtcConnectionForSessionManager();
|
||||
|
||||
public:
|
||||
srs_error_t add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
srs_error_t add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status);
|
||||
void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token);
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
// Mock ISrsAppFactory for testing SrsRtcSessionManager
|
||||
class MockAppFactoryForSessionManager : public SrsAppFactory
|
||||
{
|
||||
public:
|
||||
MockRtcConnectionForSessionManager *mock_connection_;
|
||||
int create_rtc_connection_count_;
|
||||
|
||||
public:
|
||||
MockAppFactoryForSessionManager();
|
||||
virtual ~MockAppFactoryForSessionManager();
|
||||
|
||||
public:
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid);
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
// Mock ISrsRtcConnection for testing SrsRtcSessionManager::srs_update_rtc_sessions
|
||||
class MockRtcConnectionForUpdateSessions : public ISrsRtcConnection
|
||||
{
|
||||
public:
|
||||
bool is_alive_;
|
||||
bool is_disposing_;
|
||||
std::string username_;
|
||||
bool switch_to_context_called_;
|
||||
bool alive_called_;
|
||||
SrsContextId cid_;
|
||||
ISrsRtcNetwork *udp_network_;
|
||||
|
||||
public:
|
||||
MockRtcConnectionForUpdateSessions();
|
||||
virtual ~MockRtcConnectionForUpdateSessions();
|
||||
|
||||
public:
|
||||
// ISrsResource interface
|
||||
virtual const SrsContextId &get_id();
|
||||
virtual std::string desc();
|
||||
virtual void on_disposing(ISrsResource *c);
|
||||
|
||||
public:
|
||||
// ISrsDisposingHandler interface
|
||||
virtual void on_before_dispose(ISrsResource *c);
|
||||
|
||||
public:
|
||||
// ISrsExpire interface
|
||||
virtual void expire();
|
||||
|
||||
public:
|
||||
// ISrsRtcPacketSender interface
|
||||
virtual srs_error_t send_rtcp(char *data, int nb_data);
|
||||
virtual srs_error_t send_rtcp_rr(uint32_t ssrc, SrsRtpRingBuffer *rtp_queue, const uint64_t &last_send_systime, const SrsNtp &last_send_ntp);
|
||||
virtual srs_error_t send_rtcp_xr_rrtr(uint32_t ssrc);
|
||||
virtual void check_send_nacks(SrsRtpNackForReceiver *nack, uint32_t ssrc, uint32_t &sent_nacks, uint32_t &timeout_nacks);
|
||||
virtual srs_error_t send_rtcp_fb_pli(uint32_t ssrc, const SrsContextId &cid_of_subscriber);
|
||||
virtual srs_error_t do_send_packet(SrsRtpPacket *pkt);
|
||||
|
||||
public:
|
||||
// ISrsRtcPacketReceiver interface
|
||||
virtual srs_error_t do_check_send_nacks();
|
||||
|
||||
public:
|
||||
// ISrsRtcConnectionNackTimerHandler interface
|
||||
virtual void on_timer_nack();
|
||||
|
||||
public:
|
||||
// ISrsRtcConnection interface
|
||||
virtual srs_error_t on_dtls_handshake_done();
|
||||
virtual srs_error_t on_dtls_alert(std::string type, std::string desc);
|
||||
virtual srs_error_t on_rtp_cipher(char *data, int nb_data);
|
||||
virtual srs_error_t on_rtp_plaintext(char *data, int nb_data);
|
||||
virtual srs_error_t on_rtcp(char *data, int nb_data);
|
||||
virtual srs_error_t on_binding_request(SrsStunPacket *r, std::string &ice_pwd);
|
||||
virtual ISrsRtcNetwork *udp();
|
||||
virtual ISrsRtcNetwork *tcp();
|
||||
virtual void alive();
|
||||
virtual bool is_alive();
|
||||
virtual bool is_disposing();
|
||||
virtual void switch_to_context();
|
||||
virtual srs_error_t add_publisher(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual srs_error_t add_player(SrsRtcUserConfig *ruc, SrsSdp &local_sdp);
|
||||
virtual void set_all_tracks_status(std::string stream_uri, bool is_publish, bool status);
|
||||
virtual void set_remote_sdp(const SrsSdp &sdp);
|
||||
virtual void set_local_sdp(const SrsSdp &sdp);
|
||||
virtual void set_state_as_waiting_stun();
|
||||
virtual srs_error_t initialize(ISrsRequest *r, bool dtls, bool srtp, std::string username);
|
||||
virtual std::string username();
|
||||
virtual std::string token();
|
||||
virtual void set_publish_token(SrsSharedPtr<SrsStreamPublishToken> publish_token);
|
||||
virtual void simulate_drop_packet(bool v, int nn);
|
||||
virtual void simulate_nack_drop(int nn);
|
||||
};
|
||||
|
||||
// Mock ISrsResourceManager for testing SrsRtcSessionManager::srs_update_rtc_sessions
|
||||
class MockResourceManagerForUpdateSessions : public ISrsResourceManager
|
||||
{
|
||||
public:
|
||||
std::vector<ISrsResource *> resources_;
|
||||
std::vector<ISrsResource *> removed_resources_;
|
||||
std::map<std::string, ISrsResource *> id_map_;
|
||||
std::map<uint64_t, ISrsResource *> fast_id_map_;
|
||||
std::map<std::string, ISrsResource *> name_map_;
|
||||
|
||||
public:
|
||||
MockResourceManagerForUpdateSessions();
|
||||
virtual ~MockResourceManagerForUpdateSessions();
|
||||
|
||||
public:
|
||||
virtual srs_error_t start();
|
||||
virtual bool empty();
|
||||
virtual size_t size();
|
||||
virtual void add(ISrsResource *conn, bool *exists = NULL);
|
||||
virtual void add_with_id(const std::string &id, ISrsResource *conn);
|
||||
virtual void add_with_fast_id(uint64_t id, ISrsResource *conn);
|
||||
virtual void add_with_name(const std::string &name, ISrsResource *conn);
|
||||
virtual ISrsResource *at(int index);
|
||||
virtual ISrsResource *find_by_id(std::string id);
|
||||
virtual ISrsResource *find_by_fast_id(uint64_t id);
|
||||
virtual ISrsResource *find_by_name(std::string name);
|
||||
virtual void remove(ISrsResource *c);
|
||||
virtual void subscribe(ISrsDisposingHandler *h);
|
||||
virtual void unsubscribe(ISrsDisposingHandler *h);
|
||||
void reset();
|
||||
};
|
||||
|
||||
// Mock ISrsRtcNetwork for testing SrsRtcSessionManager::on_udp_packet
|
||||
class MockRtcNetworkForUdpNetwork : public ISrsRtcNetwork
|
||||
{
|
||||
public:
|
||||
bool on_stun_called_;
|
||||
bool on_rtp_called_;
|
||||
bool on_rtcp_called_;
|
||||
bool on_dtls_called_;
|
||||
|
||||
public:
|
||||
MockRtcNetworkForUdpNetwork();
|
||||
virtual ~MockRtcNetworkForUdpNetwork();
|
||||
|
||||
public:
|
||||
virtual srs_error_t initialize(SrsSessionConfig *cfg, bool dtls, bool srtp);
|
||||
virtual void set_state(SrsRtcNetworkState state);
|
||||
virtual srs_error_t on_dtls_handshake_done();
|
||||
virtual srs_error_t on_dtls_alert(std::string type, std::string desc);
|
||||
virtual srs_error_t on_dtls(char *data, int nb_data);
|
||||
virtual srs_error_t on_stun(SrsStunPacket *r, char *data, int nb_data);
|
||||
virtual srs_error_t on_rtp(char *data, int nb_data);
|
||||
virtual srs_error_t on_rtcp(char *data, int nb_data);
|
||||
virtual srs_error_t protect_rtp(void *packet, int *nb_cipher);
|
||||
virtual srs_error_t protect_rtcp(void *packet, int *nb_cipher);
|
||||
virtual bool is_establelished();
|
||||
virtual srs_error_t write(void *buf, size_t size, ssize_t *nwrite);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user