Index: pc/channel.cc |
diff --git a/pc/channel.cc b/pc/channel.cc |
index 7ddf5de7dd91bf304bf5b0e2dc10f5c55d7dcc57..11bf78261630c7dbbc715df3c6cb60123273707d 100644 |
--- a/pc/channel.cc |
+++ b/pc/channel.cc |
@@ -63,9 +63,6 @@ enum { |
MSG_FIRSTPACKETRECEIVED, |
}; |
-// Value specified in RFC 5764. |
-static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp"; |
- |
static const int kAgcMinus10db = -10; |
static void SafeSetError(const std::string& message, std::string* error_desc) { |
@@ -155,18 +152,7 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread, |
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_transport_->EnableExternalAuth(); |
-#endif |
- } else { |
- rtp_transport_ = rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required); |
- srtp_transport_ = nullptr; |
- } |
+ rtp_transport_ = rtc::MakeUnique<webrtc::RtpTransport>(rtcp_mux_required); |
rtp_transport_->SignalReadyToSend.connect( |
this, &BaseChannel::OnTransportReadyToSend); |
// TODO(zstein): RtpTransport::SignalPacketReceived will probably be replaced |
@@ -318,9 +304,8 @@ void BaseChannel::SetTransports_n( |
// Set |writable_| to false such that UpdateWritableState_w can set up |
// DTLS-SRTP when |writable_| becomes true again. |
writable_ = false; |
- dtls_active_ = false; |
- if (srtp_transport_) { |
- srtp_transport_->ResetParams(); |
+ if (dtls_srtp_transport_) { |
+ dtls_srtp_transport_->ResetParams(); |
} |
} |
@@ -384,6 +369,10 @@ void BaseChannel::SetTransport_n( |
if (new_dtls_transport) { |
ConnectToDtlsTransport(new_dtls_transport); |
+ if (dtls_srtp_transport_) { |
+ rtcp ? dtls_srtp_transport_->SetRtcpDtlsTransport(new_dtls_transport) |
+ : dtls_srtp_transport_->SetRtpDtlsTransport(new_dtls_transport); |
+ } |
} else { |
ConnectToPacketTransport(new_packet_transport); |
} |
@@ -587,9 +576,8 @@ void BaseChannel::OnDtlsState(DtlsTransportInternal* transport, |
// TransportChannel) or when TransportChannel is attached after DTLS is |
// negotiated. |
if (state != DTLS_TRANSPORT_CONNECTED) { |
- dtls_active_ = false; |
- if (srtp_transport_) { |
- srtp_transport_->ResetParams(); |
+ if (dtls_srtp_transport_) { |
+ dtls_srtp_transport_->ResetParams(); |
} |
} |
} |
@@ -683,11 +671,22 @@ bool BaseChannel::SendPacket(bool rtcp, |
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()); |
+ |
+ if (dtls_srtp_transport_) { |
+ RTC_DCHECK(!sdes_transport_); |
+ RTC_DCHECK(dtls_srtp_transport_->IsActive()); |
+ // Bon voyage. |
+ return rtcp ? dtls_srtp_transport_->SendRtcpPacket(packet, options, |
+ PF_SRTP_BYPASS) |
+ : dtls_srtp_transport_->SendRtpPacket(packet, options, |
+ PF_SRTP_BYPASS); |
+ } |
+ |
+ RTC_DCHECK(sdes_transport_); |
+ RTC_DCHECK(sdes_transport_->IsActive()); |
// Bon voyage. |
- return rtcp ? srtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS) |
- : srtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS); |
+ return rtcp ? sdes_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS) |
+ : sdes_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS); |
} |
bool BaseChannel::HandlesPayloadType(int packet_type) const { |
@@ -811,102 +810,6 @@ bool BaseChannel::ShouldSetupDtlsSrtp_n() const { |
return rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive(); |
} |
-// This function returns true if either DTLS-SRTP is not in use |
-// *or* DTLS-SRTP is successfully set up. |
-bool BaseChannel::SetupDtlsSrtp_n(bool rtcp) { |
- RTC_DCHECK(network_thread_->IsCurrent()); |
- bool ret = false; |
- |
- DtlsTransportInternal* transport = |
- rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_; |
- RTC_DCHECK(transport); |
- RTC_DCHECK(transport->IsDtlsActive()); |
- |
- int selected_crypto_suite; |
- |
- if (!transport->GetSrtpCryptoSuite(&selected_crypto_suite)) { |
- LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite"; |
- return false; |
- } |
- |
- LOG(LS_INFO) << "Installing keys from DTLS-SRTP on " << content_name() << " " |
- << RtpRtcpStringLiteral(rtcp); |
- |
- int key_len; |
- int salt_len; |
- if (!rtc::GetSrtpKeyAndSaltLengths(selected_crypto_suite, &key_len, |
- &salt_len)) { |
- LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite" << selected_crypto_suite; |
- return false; |
- } |
- |
- // OK, we're now doing DTLS (RFC 5764) |
- std::vector<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2); |
- |
- // RFC 5705 exporter using the RFC 5764 parameters |
- if (!transport->ExportKeyingMaterial(kDtlsSrtpExporterLabel, NULL, 0, false, |
- &dtls_buffer[0], dtls_buffer.size())) { |
- LOG(LS_WARNING) << "DTLS-SRTP key export failed"; |
- RTC_NOTREACHED(); // This should never happen |
- return false; |
- } |
- |
- // Sync up the keys with the DTLS-SRTP interface |
- std::vector<unsigned char> client_write_key(key_len + salt_len); |
- std::vector<unsigned char> server_write_key(key_len + salt_len); |
- size_t offset = 0; |
- memcpy(&client_write_key[0], &dtls_buffer[offset], key_len); |
- offset += key_len; |
- memcpy(&server_write_key[0], &dtls_buffer[offset], key_len); |
- offset += key_len; |
- memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len); |
- offset += salt_len; |
- memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len); |
- |
- std::vector<unsigned char> *send_key, *recv_key; |
- rtc::SSLRole role; |
- if (!transport->GetSslRole(&role)) { |
- LOG(LS_WARNING) << "GetSslRole failed"; |
- return false; |
- } |
- |
- if (role == rtc::SSL_SERVER) { |
- send_key = &server_write_key; |
- recv_key = &client_write_key; |
- } else { |
- send_key = &client_write_key; |
- recv_key = &server_write_key; |
- } |
- |
- 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 { |
- // 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 { |
- 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 { |
- UpdateTransportOverhead(); |
- } |
- return ret; |
-} |
- |
void BaseChannel::MaybeSetupDtlsSrtp_n() { |
if (dtls_active()) { |
return; |
@@ -916,17 +819,17 @@ void BaseChannel::MaybeSetupDtlsSrtp_n() { |
return; |
} |
- if (!srtp_transport_) { |
- EnableSrtpTransport_n(); |
+ if (!dtls_srtp_transport_) { |
+ EnableDtlsSrtp_n(); |
} |
- if (!SetupDtlsSrtp_n(false)) { |
+ if (!dtls_srtp_transport_->SetupDtlsSrtp(false)) { |
SignalDtlsSrtpSetupFailure_n(false); |
return; |
} |
if (rtcp_dtls_transport_) { |
- if (!SetupDtlsSrtp_n(true)) { |
+ if (!dtls_srtp_transport_->SetupDtlsSrtp(true)) { |
SignalDtlsSrtpSetupFailure_n(true); |
return; |
} |
@@ -1003,21 +906,72 @@ 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); |
+void BaseChannel::EnableSdes_n() { |
+ if (sdes_transport_) { |
+ return; |
+ } |
+ // DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same |
+ // time. |
+ RTC_DCHECK(!dtls_srtp_transport_); |
+ rtp_transport_->SignalReadyToSend.disconnect(this); |
+ rtp_transport_->SignalPacketReceived.disconnect(this); |
+ |
+ auto transport = rtc::MakeUnique<webrtc::SrtpTransport>( |
+ std::move(rtp_transport_), content_name_); |
+ sdes_transport_ = transport.get(); |
+#if defined(ENABLE_EXTERNAL_AUTH) |
+ sdes_transport_->EnableExternalAuth(); |
+#endif |
+ 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."; |
+} |
+ |
+void BaseChannel::EnableDtlsSrtp_n() { |
+ if (dtls_srtp_transport_) { |
+ return; |
+ } |
+ // DtlsSrtpTransport and SrtpTransport shouldn't be enabled at the same |
+ // time. |
+ RTC_DCHECK(!sdes_transport_); |
+ rtp_transport_->SignalReadyToSend.disconnect(this); |
+ rtp_transport_->SignalPacketReceived.disconnect(this); |
+ |
+ std::unique_ptr<webrtc::SrtpTransport> srtp_transport = |
+ rtc::MakeUnique<webrtc::SrtpTransport>(std::move(rtp_transport_), |
+ content_name_); |
+ srtp_transport->SetSendEncryptedHeaderExtensionIds( |
+ send_encrypted_header_extension_ids_); |
+ srtp_transport->SetRecvEncryptedHeaderExtensionIds( |
+ recv_encrypted_header_extension_ids_); |
+#if defined(ENABLE_EXTERNAL_AUTH) |
+ srtp_transport->EnableExternalAuth(); |
+#endif |
+ std::unique_ptr<webrtc::DtlsSrtpTransport> transport = |
+ rtc::MakeUnique<webrtc::DtlsSrtpTransport>(std::move(srtp_transport)); |
+ dtls_srtp_transport_ = transport.get(); |
+ dtls_srtp_transport_->SetRtcpDtlsTransport(rtcp_dtls_transport_); |
+ dtls_srtp_transport_->SetRtpDtlsTransport(rtp_dtls_transport_); |
- auto transport = rtc::MakeUnique<webrtc::SrtpTransport>( |
- std::move(rtp_transport_), content_name_); |
- srtp_transport_ = transport.get(); |
- rtp_transport_ = std::move(transport); |
+ rtp_transport_ = std::move(transport); |
+ rtp_transport_->SignalReadyToSend.connect( |
+ this, &BaseChannel::OnTransportReadyToSend); |
+ rtp_transport_->SignalPacketReceived.connect(this, |
+ &BaseChannel::OnPacketReceived); |
+ LOG(LS_INFO) << "Wrapping SrtpTransport in DtlsSrtpTransport."; |
+} |
- rtp_transport_->SignalReadyToSend.connect( |
- this, &BaseChannel::OnTransportReadyToSend); |
- rtp_transport_->SignalPacketReceived.connect( |
- this, &BaseChannel::OnPacketReceived); |
- LOG(LS_INFO) << "Wrapping RtpTransport in SrtpTransport."; |
+void BaseChannel::CacheEncryptedHeaderExtensionIds( |
+ cricket::ContentSource source, |
+ const std::vector<int>& extension_ids) { |
+ if (source == cricket::CS_LOCAL) { |
+ recv_encrypted_header_extension_ids_ = extension_ids; |
+ } else { |
+ send_encrypted_header_extension_ids_ = extension_ids; |
} |
} |
@@ -1037,37 +991,56 @@ bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos, |
if (!ret) { |
return false; |
} |
+ // Cache the encrypted extension ids. |SetSrtp_n| could happen before the |
+ // certficate is ready and the |rtp_dtls_transport_| is active. The |
Taylor Brandstetter
2017/09/27 23:54:48
certificate
|
+ // |dtls_srtp_transport_| is not enabled until the |rtp_dtls_transport_| is |
+ // active. |
+ CacheEncryptedHeaderExtensionIds(src, encrypted_extension_ids); |
+ |
+ if (!dtls) { |
+ ret = SetSdesSrtp_n(cryptos, action, src, encrypted_extension_ids); |
+ } else { |
+ ret = SetDtlsSrtp_n(src, encrypted_extension_ids); |
+ } |
+ |
+ if (!ret) { |
+ SafeSetError("Failed to setup SRTP.", error_desc); |
+ return false; |
+ } |
+ return true; |
+} |
+bool BaseChannel::SetSdesSrtp_n( |
+ const std::vector<CryptoParams>& cryptos, |
+ ContentAction action, |
+ ContentSource src, |
+ const std::vector<int>& encrypted_extension_ids) { |
+ if (cryptos.empty()) { |
+ return true; |
+ } |
// 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 (!sdes_transport_) { |
+ EnableSdes_n(); |
} |
- if (srtp_transport_) { |
- srtp_transport_->SetEncryptedHeaderExtensionIds(src, |
- encrypted_extension_ids); |
+ if (sdes_transport_) { |
+ src == cricket::CS_LOCAL |
+ ? sdes_transport_->SetRecvEncryptedHeaderExtensionIds( |
+ encrypted_extension_ids) |
+ : sdes_transport_->SetSendEncryptedHeaderExtensionIds( |
+ encrypted_extension_ids); |
} |
+ |
+ bool ret = true; |
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 = sdes_negotiator_.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 = sdes_negotiator_.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 = sdes_negotiator_.SetAnswer(cryptos, src); |
- } |
+ ret = sdes_negotiator_.SetAnswer(cryptos, src); |
break; |
default: |
break; |
@@ -1075,10 +1048,10 @@ bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos, |
// If setting an SDES answer succeeded, apply the negotiated parameters |
// to the SRTP transport. |
- if ((action == CA_PRANSWER || action == CA_ANSWER) && !dtls && ret) { |
+ if ((action == CA_PRANSWER || action == CA_ANSWER) && ret) { |
if (sdes_negotiator_.send_cipher_suite() && |
sdes_negotiator_.recv_cipher_suite()) { |
- ret = srtp_transport_->SetRtpParams( |
+ ret = sdes_transport_->SetRtpParams( |
*(sdes_negotiator_.send_cipher_suite()), |
sdes_negotiator_.send_key().data(), |
static_cast<int>(sdes_negotiator_.send_key().size()), |
@@ -1087,28 +1060,41 @@ bool BaseChannel::SetSrtp_n(const std::vector<CryptoParams>& cryptos, |
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 |
+ if (action == CA_ANSWER && sdes_transport_) { |
+ // Explicitly reset the |sdes_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(); |
+ sdes_transport_->ResetParams(); |
} |
} |
} |
+ return ret; |
+} |
- // 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_active() && rtp_dtls_transport_ && |
- rtp_dtls_transport_->dtls_state() == DTLS_TRANSPORT_CONNECTED) { |
+bool BaseChannel::SetDtlsSrtp_n( |
+ ContentSource src, |
+ const std::vector<int>& encrypted_extension_ids) { |
+ bool ret = true; |
+ if (!dtls_srtp_transport_) { |
+ EnableDtlsSrtp_n(); |
+ } |
+ // Update the DtlsSrtpTransport if using DTLS. |
+ // TODO(zhihuang): Only update if encrypted extension ids have changed. |
+ else { |
+ src == cricket::CS_LOCAL |
+ ? dtls_srtp_transport_->SetRecvEncryptedHeaderExtensionIds( |
+ encrypted_extension_ids) |
+ : dtls_srtp_transport_->SetSendEncryptedHeaderExtensionIds( |
+ encrypted_extension_ids); |
+ } |
+ |
+ if (dtls_active() && dtls_srtp_transport_->rtp_dtls_transport() && |
+ dtls_srtp_transport_->rtp_dtls_transport()->dtls_state() == |
+ DTLS_TRANSPORT_CONNECTED) { |
bool rtcp = false; |
- ret = SetupDtlsSrtp_n(rtcp); |
- } |
- if (!ret) { |
- SafeSetError("Failed to setup SRTP filter.", error_desc); |
- return false; |
+ ret = dtls_srtp_transport_->SetupDtlsSrtp(rtcp); |
} |
- return true; |
+ return ret; |
} |
bool BaseChannel::SetRtcpMux_n(bool enable, |
@@ -1371,8 +1357,8 @@ void BaseChannel::MaybeCacheRtpAbsSendTimeHeaderExtension_w( |
void BaseChannel::CacheRtpAbsSendTimeHeaderExtension_n( |
int rtp_abs_sendtime_extn_id) { |
- if (srtp_transport_) { |
- srtp_transport_->CacheRtpAbsSendTimeHeaderExtension( |
+ if (sdes_transport_) { |
+ sdes_transport_->CacheRtpAbsSendTimeHeaderExtension( |
rtp_abs_sendtime_extn_id); |
} else { |
LOG(LS_WARNING) << "Trying to cache the Absolute Send Time extension id " |
@@ -1663,7 +1649,7 @@ int BaseChannel::GetTransportOverheadPerPacket() const { |
if (sdes_active()) { |
int srtp_overhead = 0; |
- if (srtp_transport_->GetSrtpOverhead(&srtp_overhead)) |
+ if (sdes_transport_->GetSrtpOverhead(&srtp_overhead)) |
transport_overhead_per_packet += srtp_overhead; |
} |