Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1772)

Unified Diff: webrtc/pc/channel.cc

Issue 2997983002: Completed the functionalities of SrtpTransport. (Closed)
Patch Set: Fix the chromimum issue. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/pc/channel.h ('k') | webrtc/pc/channel_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/pc/channel.cc
diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc
index 59f0869431ae59aef1e26b3dbc555b0c897e7e14..d99a1058683f0e6c51a00e862463edfcce6f9c05 100644
--- a/webrtc/pc/channel.cc
+++ b/webrtc/pc/channel.cc
@@ -158,18 +158,22 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread,
signaling_thread_(signaling_thread),
content_name_(content_name),
rtcp_mux_required_(rtcp_mux_required),
- rtp_transport_(
- srtp_required
- ? rtc::WrapUnique<webrtc::RtpTransportInternal>(
- new webrtc::SrtpTransport(rtcp_mux_required, content_name))
- : rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required)),
srtp_required_(srtp_required),
media_channel_(media_channel),
selected_candidate_pair_(nullptr) {
RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
+ if (srtp_required) {
+ auto transport =
+ rtc::MakeUnique<webrtc::SrtpTransport>(rtcp_mux_required, content_name);
+ srtp_transport_ = transport.get();
+ rtp_transport_ = std::move(transport);
#if defined(ENABLE_EXTERNAL_AUTH)
- srtp_filter_.EnableExternalAuth();
+ srtp_transport_->EnableExternalAuth();
#endif
+ } else {
+ rtp_transport_ = rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required);
+ srtp_transport_ = nullptr;
+ }
rtp_transport_->SignalReadyToSend.connect(
this, &BaseChannel::OnTransportReadyToSend);
// TODO(zstein): RtpTransport::SignalPacketReceived will probably be replaced
@@ -314,14 +318,17 @@ void BaseChannel::SetTransports_n(
return;
}
- // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
- // changes and wait until the DTLS handshake is complete to set the newly
- // negotiated parameters.
+ // When using DTLS-SRTP, we must reset the SrtpTransport every time the
+ // DtlsTransport changes and wait until the DTLS handshake is complete to set
+ // the newly negotiated parameters.
if (ShouldSetupDtlsSrtp_n()) {
// Set |writable_| to false such that UpdateWritableState_w can set up
// DTLS-SRTP when |writable_| becomes true again.
writable_ = false;
- srtp_filter_.ResetParams();
+ dtls_active_ = false;
+ if (srtp_transport_) {
+ srtp_transport_->ResetParams();
+ }
}
// If this BaseChannel doesn't require RTCP mux and we haven't fully
@@ -377,8 +384,8 @@ void BaseChannel::SetTransport_n(
}
if (rtcp && new_dtls_transport) {
- RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
- << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
+ RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_active()))
+ << "Setting RTCP for DTLS/SRTP after the DTLS is active "
<< "should never happen.";
}
@@ -529,8 +536,7 @@ bool BaseChannel::IsReadyToSendMedia_n() const {
// and we have had some form of connectivity.
return enabled() && IsReceiveContentDirection(remote_content_direction_) &&
IsSendContentDirection(local_content_direction_) &&
- was_ever_writable() &&
- (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp_n());
+ was_ever_writable() && (srtp_active() || !ShouldSetupDtlsSrtp_n());
}
bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
@@ -582,13 +588,16 @@ void BaseChannel::OnDtlsState(DtlsTransportInternal* transport,
return;
}
- // Reset the srtp filter if it's not the CONNECTED state. For the CONNECTED
+ // Reset the SrtpTransport if it's not the CONNECTED state. For the CONNECTED
// state, setting up DTLS-SRTP context is deferred to ChannelWritable_w to
// cover other scenarios like the whole transport is writable (not just this
// TransportChannel) or when TransportChannel is attached after DTLS is
// negotiated.
if (state != DTLS_TRANSPORT_CONNECTED) {
- srtp_filter_.ResetParams();
+ dtls_active_ = false;
+ if (srtp_transport_) {
+ srtp_transport_->ResetParams();
+ }
}
}
@@ -662,91 +671,30 @@ bool BaseChannel::SendPacket(bool rtcp,
return false;
}
- rtc::PacketOptions updated_options;
- updated_options = options;
- // Protect if needed.
- if (srtp_filter_.IsActive()) {
- TRACE_EVENT0("webrtc", "SRTP Encode");
- bool res;
- uint8_t* data = packet->data();
- int len = static_cast<int>(packet->size());
- if (!rtcp) {
- // If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
- // inside libsrtp for a RTP packet. A external HMAC module will be writing
- // a fake HMAC value. This is ONLY done for a RTP packet.
- // Socket layer will update rtp sendtime extension header if present in
- // packet with current time before updating the HMAC.
-#if !defined(ENABLE_EXTERNAL_AUTH)
- res = srtp_filter_.ProtectRtp(
- data, len, static_cast<int>(packet->capacity()), &len);
-#else
- if (!srtp_filter_.IsExternalAuthActive()) {
- res = srtp_filter_.ProtectRtp(
- data, len, static_cast<int>(packet->capacity()), &len);
- } else {
- updated_options.packet_time_params.rtp_sendtime_extension_id =
- rtp_abs_sendtime_extn_id_;
- res = srtp_filter_.ProtectRtp(
- data, len, static_cast<int>(packet->capacity()), &len,
- &updated_options.packet_time_params.srtp_packet_index);
- // If protection succeeds, let's get auth params from srtp.
- if (res) {
- uint8_t* auth_key = NULL;
- int key_len;
- res = srtp_filter_.GetRtpAuthParams(
- &auth_key, &key_len,
- &updated_options.packet_time_params.srtp_auth_tag_len);
- if (res) {
- updated_options.packet_time_params.srtp_auth_key.resize(key_len);
- updated_options.packet_time_params.srtp_auth_key.assign(
- auth_key, auth_key + key_len);
- }
- }
- }
-#endif
- if (!res) {
- int seq_num = -1;
- uint32_t ssrc = 0;
- GetRtpSeqNum(data, len, &seq_num);
- GetRtpSsrc(data, len, &ssrc);
- LOG(LS_ERROR) << "Failed to protect " << content_name_
- << " RTP packet: size=" << len
- << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
- return false;
- }
- } else {
- res = srtp_filter_.ProtectRtcp(data, len,
- static_cast<int>(packet->capacity()),
- &len);
- if (!res) {
- int type = -1;
- GetRtcpType(data, len, &type);
- LOG(LS_ERROR) << "Failed to protect " << content_name_
- << " RTCP packet: size=" << len << ", type=" << type;
+ if (!srtp_active()) {
+ if (srtp_required_) {
+ // The audio/video engines may attempt to send RTCP packets as soon as the
+ // streams are created, so don't treat this as an error for RTCP.
+ // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
+ if (rtcp) {
return false;
}
- }
-
- // Update the length of the packet now that we've added the auth tag.
- packet->SetSize(len);
- } else if (srtp_required_) {
- // The audio/video engines may attempt to send RTCP packets as soon as the
- // streams are created, so don't treat this as an error for RTCP.
- // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
- if (rtcp) {
+ // However, there shouldn't be any RTP packets sent before SRTP is set up
+ // (and SetSend(true) is called).
+ LOG(LS_ERROR) << "Can't send outgoing RTP packet when SRTP is inactive"
+ << " and crypto is required";
+ RTC_NOTREACHED();
return false;
}
- // However, there shouldn't be any RTP packets sent before SRTP is set up
- // (and SetSend(true) is called).
- LOG(LS_ERROR) << "Can't send outgoing RTP packet when SRTP is inactive"
- << " and crypto is required";
- RTC_NOTREACHED();
- return false;
+ // Bon voyage.
+ return rtcp ? rtp_transport_->SendRtcpPacket(packet, options, PF_NORMAL)
+ : rtp_transport_->SendRtpPacket(packet, options, PF_NORMAL);
}
-
+ RTC_DCHECK(srtp_transport_);
+ RTC_DCHECK(srtp_transport_->IsActive());
// Bon voyage.
- int flags = (secure() && secure_dtls()) ? PF_SRTP_BYPASS : PF_NORMAL;
- return rtp_transport_->SendPacket(rtcp, packet, updated_options, flags);
+ return rtcp ? srtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
+ : srtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
}
bool BaseChannel::HandlesPayloadType(int packet_type) const {
@@ -761,37 +709,7 @@ void BaseChannel::OnPacketReceived(bool rtcp,
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FIRSTPACKETRECEIVED);
}
- // Unprotect the packet, if needed.
- if (srtp_filter_.IsActive()) {
- TRACE_EVENT0("webrtc", "SRTP Decode");
- char* data = packet->data<char>();
- int len = static_cast<int>(packet->size());
- bool res;
- if (!rtcp) {
- res = srtp_filter_.UnprotectRtp(data, len, &len);
- if (!res) {
- int seq_num = -1;
- uint32_t ssrc = 0;
- GetRtpSeqNum(data, len, &seq_num);
- GetRtpSsrc(data, len, &ssrc);
- LOG(LS_ERROR) << "Failed to unprotect " << content_name_
- << " RTP packet: size=" << len << ", seqnum=" << seq_num
- << ", SSRC=" << ssrc;
- return;
- }
- } else {
- res = srtp_filter_.UnprotectRtcp(data, len, &len);
- if (!res) {
- int type = -1;
- GetRtcpType(data, len, &type);
- LOG(LS_ERROR) << "Failed to unprotect " << content_name_
- << " RTCP packet: size=" << len << ", type=" << type;
- return;
- }
- }
-
- packet->SetSize(len);
- } else if (srtp_required_) {
+ if (!srtp_active() && srtp_required_) {
// Our session description indicates that SRTP is required, but we got a
// packet before our SRTP filter is active. This means either that
// a) we got SRTP packets before we received the SDES keys, in which case
@@ -995,43 +913,37 @@ bool BaseChannel::SetupDtlsSrtp_n(bool rtcp) {
recv_key = &server_write_key;
}
- if (!srtp_filter_.IsActive()) {
- if (rtcp) {
- ret = srtp_filter_.SetRtcpParams(selected_crypto_suite, &(*send_key)[0],
- static_cast<int>(send_key->size()),
- selected_crypto_suite, &(*recv_key)[0],
- static_cast<int>(recv_key->size()));
+ if (rtcp) {
+ if (!dtls_active()) {
+ RTC_DCHECK(srtp_transport_);
+ ret = srtp_transport_->SetRtcpParams(
+ selected_crypto_suite, &(*send_key)[0],
+ static_cast<int>(send_key->size()), selected_crypto_suite,
+ &(*recv_key)[0], static_cast<int>(recv_key->size()));
} else {
- ret = srtp_filter_.SetRtpParams(selected_crypto_suite, &(*send_key)[0],
- static_cast<int>(send_key->size()),
- selected_crypto_suite, &(*recv_key)[0],
- static_cast<int>(recv_key->size()));
- }
- } else {
- if (rtcp) {
- // RTCP doesn't need to be updated because UpdateRtpParams is only used
- // to update the set of encrypted RTP header extension IDs.
+ // RTCP doesn't need to call SetRtpParam because it is only used
+ // to make the updated encrypted RTP header extension IDs take effect.
ret = true;
- } else {
- ret = srtp_filter_.UpdateRtpParams(
- selected_crypto_suite,
- &(*send_key)[0], static_cast<int>(send_key->size()),
- selected_crypto_suite,
- &(*recv_key)[0], static_cast<int>(recv_key->size()));
}
+ } else {
+ RTC_DCHECK(srtp_transport_);
+ ret = srtp_transport_->SetRtpParams(selected_crypto_suite, &(*send_key)[0],
+ static_cast<int>(send_key->size()),
+ selected_crypto_suite, &(*recv_key)[0],
+ static_cast<int>(recv_key->size()));
+ dtls_active_ = ret;
}
if (!ret) {
LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
} else {
- dtls_keyed_ = true;
UpdateTransportOverhead();
}
return ret;
}
void BaseChannel::MaybeSetupDtlsSrtp_n() {
- if (srtp_filter_.IsActive()) {
+ if (dtls_active()) {
return;
}
@@ -1039,6 +951,10 @@ void BaseChannel::MaybeSetupDtlsSrtp_n() {
return;
}
+ if (!srtp_transport_) {
+ EnableSrtpTransport_n();
+ }
+
if (!SetupDtlsSrtp_n(false)) {
SignalDtlsSrtpSetupFailure_n(false);
return;
@@ -1122,6 +1038,24 @@ bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
return true;
}
+void BaseChannel::EnableSrtpTransport_n() {
+ if (srtp_transport_ == nullptr) {
+ rtp_transport_->SignalReadyToSend.disconnect(this);
+ rtp_transport_->SignalPacketReceived.disconnect(this);
+
+ auto transport = rtc::MakeUnique<webrtc::SrtpTransport>(
+ std::move(rtp_transport_), content_name_);
+ srtp_transport_ = transport.get();
+ rtp_transport_ = std::move(transport);
+
+ rtp_transport_->SignalReadyToSend.connect(
+ this, &BaseChannel::OnTransportReadyToSend);
+ rtp_transport_->SignalPacketReceived.connect(
+ this, &BaseChannel::OnPacketReceived);
+ LOG(LS_INFO) << "Wrapping RtpTransport in SrtpTransport.";
+ }
+}
+
bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
ContentAction action,
ContentSource src,
@@ -1138,36 +1072,69 @@ bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos,
if (!ret) {
return false;
}
- srtp_filter_.SetEncryptedHeaderExtensionIds(src, encrypted_extension_ids);
+
+ // If SRTP was not required, but we're setting a description that uses SDES,
+ // we need to upgrade to an SrtpTransport.
+ if (!srtp_transport_ && !dtls && !cryptos.empty()) {
+ EnableSrtpTransport_n();
+ }
+ if (srtp_transport_) {
+ srtp_transport_->SetEncryptedHeaderExtensionIds(src,
+ encrypted_extension_ids);
+ }
switch (action) {
case CA_OFFER:
// If DTLS is already active on the channel, we could be renegotiating
// here. We don't update the srtp filter.
if (!dtls) {
- ret = srtp_filter_.SetOffer(cryptos, src);
+ ret = sdes_negotiator_.SetOffer(cryptos, src);
}
break;
case CA_PRANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters.
if (!dtls) {
- ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
+ ret = sdes_negotiator_.SetProvisionalAnswer(cryptos, src);
}
break;
case CA_ANSWER:
// If we're doing DTLS-SRTP, we don't want to update the filter
// with an answer, because we already have SRTP parameters.
if (!dtls) {
- ret = srtp_filter_.SetAnswer(cryptos, src);
+ ret = sdes_negotiator_.SetAnswer(cryptos, src);
}
break;
default:
break;
}
+
+ // If setting an SDES answer succeeded, apply the negotiated parameters
+ // to the SRTP transport.
+ if ((action == CA_PRANSWER || action == CA_ANSWER) && !dtls && ret) {
+ if (sdes_negotiator_.send_cipher_suite() &&
+ sdes_negotiator_.recv_cipher_suite()) {
+ ret = srtp_transport_->SetRtpParams(
+ *(sdes_negotiator_.send_cipher_suite()),
+ sdes_negotiator_.send_key().data(),
+ static_cast<int>(sdes_negotiator_.send_key().size()),
+ *(sdes_negotiator_.recv_cipher_suite()),
+ sdes_negotiator_.recv_key().data(),
+ static_cast<int>(sdes_negotiator_.recv_key().size()));
+ } else {
+ LOG(LS_INFO) << "No crypto keys are provided for SDES.";
+ if (action == CA_ANSWER && srtp_transport_) {
+ // Explicitly reset the |srtp_transport_| if no crypto param is
+ // provided in the answer. No need to call |ResetParams()| for
+ // |sdes_negotiator_| because it resets the params inside |SetAnswer|.
+ srtp_transport_->ResetParams();
+ }
+ }
+ }
+
// Only update SRTP filter if using DTLS. SDES is handled internally
// by the SRTP filter.
// TODO(jbauch): Only update if encrypted extension ids have changed.
- if (ret && dtls_keyed_ && rtp_dtls_transport_ &&
+ if (ret && dtls_active() && rtp_dtls_transport_ &&
rtp_dtls_transport_->dtls_state() == DTLS_TRANSPORT_CONNECTED) {
bool rtcp = false;
ret = SetupDtlsSrtp_n(rtcp);
@@ -1211,7 +1178,6 @@ bool BaseChannel::SetRtcpMux_n(bool enable,
transport_name_.empty()
? rtp_transport_->rtp_packet_transport()->debug_name()
: transport_name_;
- ;
LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
<< "; no longer need RTCP transport for " << debug_name;
if (rtp_transport_->rtcp_packet_transport()) {
@@ -1440,7 +1406,13 @@ void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w(
void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n(
int rtp_abs_sendtime_extn_id) {
- rtp_abs_sendtime_extn_id_ = rtp_abs_sendtime_extn_id;
+ if (srtp_transport_) {
+ srtp_transport_->CacheRtpAbsSendTimeHeaderExtension(
+ rtp_abs_sendtime_extn_id);
+ } else {
+ LOG(LS_WARNING) << "Trying to cache the Absolute Send Time extension id "
+ "but the SRTP is not active.";
+ }
}
void BaseChannel::OnMessage(rtc::Message *pmsg) {
@@ -1724,9 +1696,9 @@ int BaseChannel::GetTransportOverheadPerPacket() const {
? kTcpOverhaed
: kUdpOverhaed;
- if (secure()) {
+ if (sdes_active()) {
int srtp_overhead = 0;
- if (srtp_filter_.GetSrtpOverhead(&srtp_overhead))
+ if (srtp_transport_->GetSrtpOverhead(&srtp_overhead))
transport_overhead_per_packet += srtp_overhead;
}
« no previous file with comments | « webrtc/pc/channel.h ('k') | webrtc/pc/channel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698