mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
RTC: Support semi security transport
This commit is contained in:
parent
47c43e47b6
commit
d2264ba6f9
5 changed files with 97 additions and 39 deletions
|
@ -178,16 +178,18 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe
|
||||||
server_enabled, rtc_enabled, request.vhost.c_str());
|
server_enabled, rtc_enabled, request.vhost.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool srtp_enabled = true;
|
||||||
|
if (encrypt.empty()) {
|
||||||
|
srtp_enabled = _srs_config->get_rtc_server_encrypt();
|
||||||
|
} else {
|
||||||
|
srtp_enabled = (encrypt != "false");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
||||||
SrsRtcConnection* session = NULL;
|
SrsRtcConnection* session = NULL;
|
||||||
if ((err = server_->create_session(&request, remote_sdp, local_sdp, eip, false, &session)) != srs_success) {
|
if ((err = server_->create_session(&request, remote_sdp, local_sdp, eip, false, true, srtp_enabled, &session)) != srs_success) {
|
||||||
return srs_error_wrap(err, "create session");
|
return srs_error_wrap(err, "create session");
|
||||||
}
|
}
|
||||||
if (encrypt.empty()) {
|
|
||||||
session->set_encrypt(_srs_config->get_rtc_server_encrypt());
|
|
||||||
} else {
|
|
||||||
session->set_encrypt(encrypt != "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
ostringstream os;
|
ostringstream os;
|
||||||
if ((err = local_sdp.encode(os)) != srs_success) {
|
if ((err = local_sdp.encode(os)) != srs_success) {
|
||||||
|
@ -206,8 +208,8 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe
|
||||||
res->set("sdp", SrsJsonAny::str(local_sdp_str.c_str()));
|
res->set("sdp", SrsJsonAny::str(local_sdp_str.c_str()));
|
||||||
res->set("sessionid", SrsJsonAny::str(session->username().c_str()));
|
res->set("sessionid", SrsJsonAny::str(session->username().c_str()));
|
||||||
|
|
||||||
srs_trace("RTC username=%s, offer=%dB, answer=%dB", session->username().c_str(),
|
srs_trace("RTC username=%s, srtp=%u, offer=%dB, answer=%dB", session->username().c_str(),
|
||||||
remote_sdp_str.length(), local_sdp_str.length());
|
srtp_enabled, remote_sdp_str.length(), local_sdp_str.length());
|
||||||
srs_trace("RTC remote offer: %s", srs_string_replace(remote_sdp_str.c_str(), "\r\n", "\\r\\n").c_str());
|
srs_trace("RTC remote offer: %s", srs_string_replace(remote_sdp_str.c_str(), "\r\n", "\\r\\n").c_str());
|
||||||
srs_trace("RTC local answer: %s", local_sdp_str.c_str());
|
srs_trace("RTC local answer: %s", local_sdp_str.c_str());
|
||||||
|
|
||||||
|
@ -537,7 +539,7 @@ srs_error_t SrsGoApiRtcPublish::do_serve_http(ISrsHttpResponseWriter* w, ISrsHtt
|
||||||
|
|
||||||
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
// TODO: FIXME: When server enabled, but vhost disabled, should report error.
|
||||||
SrsRtcConnection* session = NULL;
|
SrsRtcConnection* session = NULL;
|
||||||
if ((err = server_->create_session(&request, remote_sdp, local_sdp, eip, true, &session)) != srs_success) {
|
if ((err = server_->create_session(&request, remote_sdp, local_sdp, eip, true, true, true, &session)) != srs_success) {
|
||||||
return srs_error_wrap(err, "create session");
|
return srs_error_wrap(err, "create session");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,14 @@ using namespace std;
|
||||||
|
|
||||||
#define SRS_TICKID_RTCP 0
|
#define SRS_TICKID_RTCP 0
|
||||||
|
|
||||||
|
ISrsRtcTransport::ISrsRtcTransport()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsRtcTransport::~ISrsRtcTransport()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SrsSecurityTransport::SrsSecurityTransport(SrsRtcConnection* s)
|
SrsSecurityTransport::SrsSecurityTransport(SrsRtcConnection* s)
|
||||||
{
|
{
|
||||||
session_ = s;
|
session_ = s;
|
||||||
|
@ -182,6 +190,29 @@ srs_error_t SrsSecurityTransport::unprotect_rtcp(const char* cipher, char* plain
|
||||||
return srtp_->unprotect_rtcp(cipher, plaintext, nb_plaintext);
|
return srtp_->unprotect_rtcp(cipher, plaintext, nb_plaintext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsSemiSecurityTransport::SrsSemiSecurityTransport(SrsRtcConnection* s) : SrsSecurityTransport(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSemiSecurityTransport::~SrsSemiSecurityTransport()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsSemiSecurityTransport::protect_rtp(const char* plaintext, char* cipher, int& nb_cipher)
|
||||||
|
{
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsSemiSecurityTransport::protect_rtcp(const char* plaintext, char* cipher, int& nb_cipher)
|
||||||
|
{
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsSemiSecurityTransport::protect_rtp2(void* rtp_hdr, int* len_ptr)
|
||||||
|
{
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtcPlayStreamStatistic::SrsRtcPlayStreamStatistic()
|
SrsRtcPlayStreamStatistic::SrsRtcPlayStreamStatistic()
|
||||||
{
|
{
|
||||||
nn_rtp_pkts = 0;
|
nn_rtp_pkts = 0;
|
||||||
|
@ -356,8 +387,8 @@ srs_error_t SrsRtcPlayStream::cycle()
|
||||||
|
|
||||||
// TODO: FIXME: Add cost in ms.
|
// TODO: FIXME: Add cost in ms.
|
||||||
SrsContextId cid = source->source_id();
|
SrsContextId cid = source->source_id();
|
||||||
srs_trace("RTC: start play url=%s, source_id=[%d][%s], encrypt=%d, realtime=%d, mw_msgs=%d", req_->get_stream_url().c_str(),
|
srs_trace("RTC: start play url=%s, source_id=[%d][%s], realtime=%d, mw_msgs=%d", req_->get_stream_url().c_str(),
|
||||||
::getpid(), cid.c_str(), session_->encrypt, realtime, mw_msgs);
|
::getpid(), cid.c_str(), realtime, mw_msgs);
|
||||||
|
|
||||||
SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play();
|
SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play();
|
||||||
SrsAutoFree(SrsPithyPrint, pprint);
|
SrsAutoFree(SrsPithyPrint, pprint);
|
||||||
|
@ -1657,7 +1688,6 @@ SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s, SrsContextId context_id)
|
||||||
{
|
{
|
||||||
req = NULL;
|
req = NULL;
|
||||||
is_publisher_ = false;
|
is_publisher_ = false;
|
||||||
encrypt = true;
|
|
||||||
cid = context_id;
|
cid = context_id;
|
||||||
stat_ = new SrsRtcConnectionStatistic();
|
stat_ = new SrsRtcConnectionStatistic();
|
||||||
timer_ = new SrsHourGlass(this, 1000 * SRS_UTIME_MILLISECONDS);
|
timer_ = new SrsHourGlass(this, 1000 * SRS_UTIME_MILLISECONDS);
|
||||||
|
@ -1746,11 +1776,6 @@ vector<SrsUdpMuxSocket*> SrsRtcConnection::peer_addresses()
|
||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsRtcConnection::set_encrypt(bool v)
|
|
||||||
{
|
|
||||||
encrypt = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SrsRtcConnection::switch_to_context()
|
void SrsRtcConnection::switch_to_context()
|
||||||
{
|
{
|
||||||
_srs_context->set_id(cid);
|
_srs_context->set_id(cid);
|
||||||
|
@ -1871,7 +1896,7 @@ srs_error_t SrsRtcConnection::add_player2(SrsRequest* req, SrsSdp& local_sdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIXME: Remove unused source.
|
// TODO: FIXME: Remove unused source.
|
||||||
srs_error_t SrsRtcConnection::initialize(SrsRtcStream* source, SrsRequest* r, bool is_publisher, string username)
|
srs_error_t SrsRtcConnection::initialize(SrsRtcStream* source, SrsRequest* r, bool is_publisher, bool dtls, bool srtp, string username)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
@ -1879,6 +1904,11 @@ srs_error_t SrsRtcConnection::initialize(SrsRtcStream* source, SrsRequest* r, bo
|
||||||
is_publisher_ = is_publisher;
|
is_publisher_ = is_publisher;
|
||||||
req = r->copy();
|
req = r->copy();
|
||||||
|
|
||||||
|
if (!srtp) {
|
||||||
|
srs_freep(transport_);
|
||||||
|
transport_ = new SrsSemiSecurityTransport(this);
|
||||||
|
}
|
||||||
|
|
||||||
SrsSessionConfig* cfg = &local_sdp.session_config_;
|
SrsSessionConfig* cfg = &local_sdp.session_config_;
|
||||||
if ((err = transport_->initialize(cfg)) != srs_success) {
|
if ((err = transport_->initialize(cfg)) != srs_success) {
|
||||||
return srs_error_wrap(err, "init");
|
return srs_error_wrap(err, "init");
|
||||||
|
@ -1892,8 +1922,8 @@ srs_error_t SrsRtcConnection::initialize(SrsRtcStream* source, SrsRequest* r, bo
|
||||||
session_timeout = _srs_config->get_rtc_stun_timeout(req->vhost);
|
session_timeout = _srs_config->get_rtc_stun_timeout(req->vhost);
|
||||||
last_stun_time = srs_get_system_time();
|
last_stun_time = srs_get_system_time();
|
||||||
|
|
||||||
srs_trace("RTC init session, user=%s, url=%s, DTLS(role=%s, version=%s), timeout=%dms", username.c_str(),
|
srs_trace("RTC init session, user=%s, url=%s, encrypt=%u/%u, DTLS(role=%s, version=%s), timeout=%dms", username.c_str(),
|
||||||
r->get_stream_url().c_str(), cfg->dtls_role.c_str(), cfg->dtls_version.c_str(), srsu2msi(session_timeout));
|
r->get_stream_url().c_str(), dtls, srtp, cfg->dtls_role.c_str(), cfg->dtls_version.c_str(), srsu2msi(session_timeout));
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -2281,8 +2311,8 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector<SrsRtpPacket2*>&
|
||||||
iov->iov_len = stream.pos();
|
iov->iov_len = stream.pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether encrypt the RTP bytes.
|
// Cipher RTP to SRTP packet.
|
||||||
if (encrypt) {
|
if (true) {
|
||||||
int nn_encrypt = (int)iov->iov_len;
|
int nn_encrypt = (int)iov->iov_len;
|
||||||
if ((err = transport_->protect_rtp2(iov->iov_base, &nn_encrypt)) != srs_success) {
|
if ((err = transport_->protect_rtp2(iov->iov_base, &nn_encrypt)) != srs_success) {
|
||||||
return srs_error_wrap(err, "srtp protect");
|
return srs_error_wrap(err, "srtp protect");
|
||||||
|
|
|
@ -89,8 +89,26 @@ enum SrsRtcConnectionStateType
|
||||||
CLOSED = 5,
|
CLOSED = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The transport for RTC connection.
|
||||||
|
class ISrsRtcTransport : public ISrsDtlsCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ISrsRtcTransport();
|
||||||
|
virtual ~ISrsRtcTransport();
|
||||||
|
public:
|
||||||
|
virtual srs_error_t initialize(SrsSessionConfig* cfg) = 0;
|
||||||
|
virtual srs_error_t start_active_handshake() = 0;
|
||||||
|
virtual srs_error_t on_dtls(char* data, int nb_data) = 0;
|
||||||
|
public:
|
||||||
|
virtual srs_error_t protect_rtp(const char* plaintext, char* cipher, int& nb_cipher) = 0;
|
||||||
|
virtual srs_error_t protect_rtcp(const char* plaintext, char* cipher, int& nb_cipher) = 0;
|
||||||
|
virtual srs_error_t protect_rtp2(void* rtp_hdr, int* len_ptr) = 0;
|
||||||
|
virtual srs_error_t unprotect_rtp(const char* cipher, char* plaintext, int& nb_plaintext) = 0;
|
||||||
|
virtual srs_error_t unprotect_rtcp(const char* cipher, char* plaintext, int& nb_plaintext) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// The security transport, use DTLS/SRTP to protect the data.
|
// The security transport, use DTLS/SRTP to protect the data.
|
||||||
class SrsSecurityTransport : public ISrsDtlsCallback
|
class SrsSecurityTransport : public ISrsRtcTransport
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsRtcConnection* session_;
|
SrsRtcConnection* session_;
|
||||||
|
@ -128,6 +146,18 @@ private:
|
||||||
srs_error_t srtp_initialize();
|
srs_error_t srtp_initialize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Semi security transport, setup DTLS and SRTP, with SRTP decrypt, without SRTP encrypt.
|
||||||
|
class SrsSemiSecurityTransport : public SrsSecurityTransport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsSemiSecurityTransport(SrsRtcConnection* s);
|
||||||
|
virtual ~SrsSemiSecurityTransport();
|
||||||
|
public:
|
||||||
|
virtual srs_error_t protect_rtp(const char* plaintext, char* cipher, int& nb_cipher);
|
||||||
|
virtual srs_error_t protect_rtcp(const char* plaintext, char* cipher, int& nb_cipher);
|
||||||
|
virtual srs_error_t protect_rtp2(void* rtp_hdr, int* len_ptr);
|
||||||
|
};
|
||||||
|
|
||||||
// A group of RTP packets for outgoing(send to players).
|
// A group of RTP packets for outgoing(send to players).
|
||||||
class SrsRtcPlayStreamStatistic
|
class SrsRtcPlayStreamStatistic
|
||||||
{
|
{
|
||||||
|
@ -323,7 +353,7 @@ public:
|
||||||
private:
|
private:
|
||||||
SrsRtcServer* server_;
|
SrsRtcServer* server_;
|
||||||
SrsRtcConnectionStateType state_;
|
SrsRtcConnectionStateType state_;
|
||||||
SrsSecurityTransport* transport_;
|
ISrsRtcTransport* transport_;
|
||||||
SrsRtcPlayStream* player_;
|
SrsRtcPlayStream* player_;
|
||||||
SrsRtcPublishStream* publisher_;
|
SrsRtcPublishStream* publisher_;
|
||||||
bool is_publisher_;
|
bool is_publisher_;
|
||||||
|
@ -342,11 +372,6 @@ private:
|
||||||
private:
|
private:
|
||||||
// For each RTC session, we use a specified cid for debugging logs.
|
// For each RTC session, we use a specified cid for debugging logs.
|
||||||
SrsContextId cid;
|
SrsContextId cid;
|
||||||
// For each RTC session, whether requires encrypt.
|
|
||||||
// Read config value, rtc_server.encrypt, default to on.
|
|
||||||
// Sepcifies by HTTP API, query encrypt, optional.
|
|
||||||
// TODO: FIXME: Support reload.
|
|
||||||
bool encrypt;
|
|
||||||
SrsRequest* req;
|
SrsRequest* req;
|
||||||
SrsSdp remote_sdp;
|
SrsSdp remote_sdp;
|
||||||
SrsSdp local_sdp;
|
SrsSdp local_sdp;
|
||||||
|
@ -374,7 +399,6 @@ public:
|
||||||
// Get all addresses client used.
|
// Get all addresses client used.
|
||||||
std::vector<SrsUdpMuxSocket*> peer_addresses();
|
std::vector<SrsUdpMuxSocket*> peer_addresses();
|
||||||
public:
|
public:
|
||||||
void set_encrypt(bool v);
|
|
||||||
void switch_to_context();
|
void switch_to_context();
|
||||||
SrsContextId context_id();
|
SrsContextId context_id();
|
||||||
public:
|
public:
|
||||||
|
@ -384,7 +408,7 @@ public:
|
||||||
srs_error_t add_player2(SrsRequest* request, SrsSdp& local_sdp);
|
srs_error_t add_player2(SrsRequest* request, SrsSdp& local_sdp);
|
||||||
public:
|
public:
|
||||||
// Before initialize, user must set the local SDP, which is used to inititlize DTLS.
|
// Before initialize, user must set the local SDP, which is used to inititlize DTLS.
|
||||||
srs_error_t initialize(SrsRtcStream* source, SrsRequest* r, bool is_publisher, std::string username);
|
srs_error_t initialize(SrsRtcStream* source, SrsRequest* r, bool is_publisher, bool dtls, bool srtp, std::string username);
|
||||||
// The peer address may change, we can identify that by STUN messages.
|
// The peer address may change, we can identify that by STUN messages.
|
||||||
srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* r);
|
srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* r);
|
||||||
srs_error_t on_dtls(char* data, int nb_data);
|
srs_error_t on_dtls(char* data, int nb_data);
|
||||||
|
|
|
@ -378,7 +378,8 @@ srs_error_t SrsRtcServer::listen_api()
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsRtcServer::create_session(
|
srs_error_t SrsRtcServer::create_session(
|
||||||
SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip, bool publish,
|
SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip,
|
||||||
|
bool publish, bool dtls, bool srtp,
|
||||||
SrsRtcConnection** psession
|
SrsRtcConnection** psession
|
||||||
) {
|
) {
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
@ -397,7 +398,7 @@ srs_error_t SrsRtcServer::create_session(
|
||||||
|
|
||||||
// TODO: FIXME: add do_create_session to error process.
|
// TODO: FIXME: add do_create_session to error process.
|
||||||
SrsRtcConnection* session = new SrsRtcConnection(this, cid);
|
SrsRtcConnection* session = new SrsRtcConnection(this, cid);
|
||||||
if ((err = do_create_session(session, req, remote_sdp, local_sdp, mock_eip, publish, source)) != srs_success) {
|
if ((err = do_create_session(session, req, remote_sdp, local_sdp, mock_eip, publish, dtls, srtp, source)) != srs_success) {
|
||||||
srs_freep(session);
|
srs_freep(session);
|
||||||
return srs_error_wrap(err, "create session");
|
return srs_error_wrap(err, "create session");
|
||||||
}
|
}
|
||||||
|
@ -408,8 +409,8 @@ srs_error_t SrsRtcServer::create_session(
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsRtcServer::do_create_session(
|
srs_error_t SrsRtcServer::do_create_session(
|
||||||
SrsRtcConnection* session, SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip, bool publish,
|
SrsRtcConnection* session, SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip,
|
||||||
SrsRtcStream* source
|
bool publish, bool dtls, bool srtp, SrsRtcStream* source
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
@ -477,7 +478,7 @@ srs_error_t SrsRtcServer::do_create_session(
|
||||||
session->set_state(WAITING_STUN);
|
session->set_state(WAITING_STUN);
|
||||||
|
|
||||||
// Before session initialize, we must setup the local SDP.
|
// Before session initialize, we must setup the local SDP.
|
||||||
if ((err = session->initialize(source, req, publish, username)) != srs_success) {
|
if ((err = session->initialize(source, req, publish, dtls, srtp, username)) != srs_success) {
|
||||||
return srs_error_wrap(err, "init");
|
return srs_error_wrap(err, "init");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +544,7 @@ srs_error_t SrsRtcServer::setup_session2(SrsRtcConnection* session, SrsRequest*
|
||||||
// TODO: FIXME: Collision detect.
|
// TODO: FIXME: Collision detect.
|
||||||
string username = session->get_local_sdp()->get_ice_ufrag() + ":" + remote_sdp.get_ice_ufrag();
|
string username = session->get_local_sdp()->get_ice_ufrag() + ":" + remote_sdp.get_ice_ufrag();
|
||||||
|
|
||||||
if ((err = session->initialize(source, req, false, username)) != srs_success) {
|
if ((err = session->initialize(source, req, false, true, true, username)) != srs_success) {
|
||||||
return srs_error_wrap(err, "init");
|
return srs_error_wrap(err, "init");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,13 +102,14 @@ public:
|
||||||
public:
|
public:
|
||||||
// Peer start offering, we answer it.
|
// Peer start offering, we answer it.
|
||||||
srs_error_t create_session(
|
srs_error_t create_session(
|
||||||
SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip, bool publish,
|
SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip,
|
||||||
|
bool publish, bool dtls, bool srtp,
|
||||||
SrsRtcConnection** psession
|
SrsRtcConnection** psession
|
||||||
);
|
);
|
||||||
private:
|
private:
|
||||||
srs_error_t do_create_session(
|
srs_error_t do_create_session(
|
||||||
SrsRtcConnection* session, SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp,
|
SrsRtcConnection* session, SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp,
|
||||||
const std::string& mock_eip, bool publish, SrsRtcStream* source
|
const std::string& mock_eip, bool publish, bool dtls, bool srtp, SrsRtcStream* source
|
||||||
);
|
);
|
||||||
public:
|
public:
|
||||||
// We start offering, create_session2 to generate offer, setup_session2 to handle answer.
|
// We start offering, create_session2 to generate offer, setup_session2 to handle answer.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue