diff --git a/trunk/src/app/srs_app_rtc_api.cpp b/trunk/src/app/srs_app_rtc_api.cpp index 52c78cf45..a921da8e5 100644 --- a/trunk/src/app/srs_app_rtc_api.cpp +++ b/trunk/src/app/srs_app_rtc_api.cpp @@ -178,16 +178,18 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe 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. 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"); } - if (encrypt.empty()) { - session->set_encrypt(_srs_config->get_rtc_server_encrypt()); - } else { - session->set_encrypt(encrypt != "false"); - } ostringstream os; 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("sessionid", SrsJsonAny::str(session->username().c_str())); - srs_trace("RTC username=%s, offer=%dB, answer=%dB", session->username().c_str(), - remote_sdp_str.length(), local_sdp_str.length()); + srs_trace("RTC username=%s, srtp=%u, offer=%dB, answer=%dB", session->username().c_str(), + 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 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. 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"); } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index fa0a30de2..5f86397dd 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -60,6 +60,14 @@ using namespace std; #define SRS_TICKID_RTCP 0 +ISrsRtcTransport::ISrsRtcTransport() +{ +} + +ISrsRtcTransport::~ISrsRtcTransport() +{ +} + SrsSecurityTransport::SrsSecurityTransport(SrsRtcConnection* 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); } +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() { nn_rtp_pkts = 0; @@ -356,8 +387,8 @@ srs_error_t SrsRtcPlayStream::cycle() // TODO: FIXME: Add cost in ms. 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(), - ::getpid(), cid.c_str(), session_->encrypt, realtime, mw_msgs); + 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(), realtime, mw_msgs); SrsPithyPrint* pprint = SrsPithyPrint::create_rtc_play(); SrsAutoFree(SrsPithyPrint, pprint); @@ -1657,7 +1688,6 @@ SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s, SrsContextId context_id) { req = NULL; is_publisher_ = false; - encrypt = true; cid = context_id; stat_ = new SrsRtcConnectionStatistic(); timer_ = new SrsHourGlass(this, 1000 * SRS_UTIME_MILLISECONDS); @@ -1746,11 +1776,6 @@ vector SrsRtcConnection::peer_addresses() return addresses; } -void SrsRtcConnection::set_encrypt(bool v) -{ - encrypt = v; -} - void SrsRtcConnection::switch_to_context() { _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. -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; @@ -1879,6 +1904,11 @@ srs_error_t SrsRtcConnection::initialize(SrsRtcStream* source, SrsRequest* r, bo is_publisher_ = is_publisher; req = r->copy(); + if (!srtp) { + srs_freep(transport_); + transport_ = new SrsSemiSecurityTransport(this); + } + SrsSessionConfig* cfg = &local_sdp.session_config_; if ((err = transport_->initialize(cfg)) != srs_success) { 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); 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(), - r->get_stream_url().c_str(), cfg->dtls_role.c_str(), cfg->dtls_version.c_str(), srsu2msi(session_timeout)); + 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(), dtls, srtp, cfg->dtls_role.c_str(), cfg->dtls_version.c_str(), srsu2msi(session_timeout)); return err; } @@ -2281,8 +2311,8 @@ srs_error_t SrsRtcConnection::do_send_packets(const std::vector& iov->iov_len = stream.pos(); } - // Whether encrypt the RTP bytes. - if (encrypt) { + // Cipher RTP to SRTP packet. + if (true) { int nn_encrypt = (int)iov->iov_len; if ((err = transport_->protect_rtp2(iov->iov_base, &nn_encrypt)) != srs_success) { return srs_error_wrap(err, "srtp protect"); diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 5826f7579..8900c2990 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -89,8 +89,26 @@ enum SrsRtcConnectionStateType 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. -class SrsSecurityTransport : public ISrsDtlsCallback +class SrsSecurityTransport : public ISrsRtcTransport { private: SrsRtcConnection* session_; @@ -128,6 +146,18 @@ private: 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). class SrsRtcPlayStreamStatistic { @@ -323,7 +353,7 @@ public: private: SrsRtcServer* server_; SrsRtcConnectionStateType state_; - SrsSecurityTransport* transport_; + ISrsRtcTransport* transport_; SrsRtcPlayStream* player_; SrsRtcPublishStream* publisher_; bool is_publisher_; @@ -342,11 +372,6 @@ private: private: // For each RTC session, we use a specified cid for debugging logs. 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; SrsSdp remote_sdp; SrsSdp local_sdp; @@ -374,7 +399,6 @@ public: // Get all addresses client used. std::vector peer_addresses(); public: - void set_encrypt(bool v); void switch_to_context(); SrsContextId context_id(); public: @@ -384,7 +408,7 @@ public: srs_error_t add_player2(SrsRequest* request, SrsSdp& local_sdp); public: // 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. srs_error_t on_stun(SrsUdpMuxSocket* skt, SrsStunPacket* r); srs_error_t on_dtls(char* data, int nb_data); diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index 88f3a2a6a..c24a61a0d 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -378,7 +378,8 @@ srs_error_t SrsRtcServer::listen_api() } 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 ) { 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. 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); return srs_error_wrap(err, "create session"); } @@ -408,8 +409,8 @@ srs_error_t SrsRtcServer::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, - SrsRtcStream* source + SrsRtcConnection* session, SrsRequest* req, const SrsSdp& remote_sdp, SrsSdp& local_sdp, const std::string& mock_eip, + bool publish, bool dtls, bool srtp, SrsRtcStream* source ) { srs_error_t err = srs_success; @@ -477,7 +478,7 @@ srs_error_t SrsRtcServer::do_create_session( session->set_state(WAITING_STUN); // 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"); } @@ -543,7 +544,7 @@ srs_error_t SrsRtcServer::setup_session2(SrsRtcConnection* session, SrsRequest* // TODO: FIXME: Collision detect. 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"); } diff --git a/trunk/src/app/srs_app_rtc_server.hpp b/trunk/src/app/srs_app_rtc_server.hpp index 6ac0106f9..f6eba2a94 100644 --- a/trunk/src/app/srs_app_rtc_server.hpp +++ b/trunk/src/app/srs_app_rtc_server.hpp @@ -102,13 +102,14 @@ public: public: // Peer start offering, we answer it. 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 ); private: srs_error_t do_create_session( 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: // We start offering, create_session2 to generate offer, setup_session2 to handle answer.