Index: pc/dtlssrtptransport.cc |
diff --git a/pc/dtlssrtptransport.cc b/pc/dtlssrtptransport.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3b89b5b2eb665a8876dd1c475a79edcc7eb33ca8 |
--- /dev/null |
+++ b/pc/dtlssrtptransport.cc |
@@ -0,0 +1,238 @@ |
+/* |
+ * Copyright 2017 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include "pc/dtlssrtptransport.h" |
+ |
+#include <memory> |
+#include <string> |
+#include <utility> |
+ |
+#include "media/base/rtputils.h" |
+#include "rtc_base/sslstreamadapter.h" |
+ |
+namespace { |
+// Value specified in RFC 5764. |
+static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp"; |
+} // namespace |
+ |
+namespace webrtc { |
+ |
+DtlsSrtpTransport::DtlsSrtpTransport( |
+ std::unique_ptr<webrtc::SrtpTransport> transport) |
+ : srtp_transport_(std::move(transport)) { |
+ ConnectToSrtpTransport(); |
+} |
+ |
+void DtlsSrtpTransport::ConnectToSrtpTransport() { |
+ RTC_DCHECK(srtp_transport_); |
+ srtp_transport_->SignalPacketReceived.connect( |
+ this, &DtlsSrtpTransport::OnPacketReceived); |
+ srtp_transport_->SignalReadyToSend.connect(this, |
+ &DtlsSrtpTransport::OnReadyToSend); |
+} |
+ |
+void DtlsSrtpTransport::OnPacketReceived(bool rtcp, |
+ rtc::CopyOnWriteBuffer* packet, |
+ const rtc::PacketTime& packet_time) { |
+ SignalPacketReceived(rtcp, packet, packet_time); |
+} |
+ |
+void DtlsSrtpTransport::OnReadyToSend(bool ready) { |
+ SignalReadyToSend(ready); |
+} |
+ |
+bool DtlsSrtpTransport::SetupDtlsSrtp(bool rtcp) { |
+ bool ret = false; |
+ |
+ cricket::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 " |
+ << cricket::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 (!IsActive()) { |
+ 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())); |
+ } |
+ |
+ if (!ret) { |
+ LOG(LS_WARNING) << "DTLS-SRTP key installation failed"; |
+ } |
+ active_ = ret; |
+ return ret; |
+} |
+ |
+void DtlsSrtpTransport::SetSendEncryptedHeaderExtensionIds( |
Taylor Brandstetter
2017/09/27 23:54:48
In a previous code review I mentioned that it may
|
+ const std::vector<int>& send_extension_ids) { |
+ RTC_DCHECK(srtp_transport_); |
Taylor Brandstetter
2017/09/27 23:54:48
nit: I don't know if adding these DCHECKS everywhe
|
+ srtp_transport_->SetSendEncryptedHeaderExtensionIds(send_extension_ids); |
+} |
+ |
+void DtlsSrtpTransport::SetRecvEncryptedHeaderExtensionIds( |
+ const std::vector<int>& recv_extension_ids) { |
+ RTC_DCHECK(srtp_transport_); |
+ srtp_transport_->SetRecvEncryptedHeaderExtensionIds(recv_extension_ids); |
+} |
+ |
+void DtlsSrtpTransport::SetRtcpMuxEnabled(bool enable) { |
+ RTC_DCHECK(srtp_transport_); |
+ srtp_transport_->SetRtcpMuxEnabled(enable); |
+} |
+ |
+rtc::PacketTransportInternal* DtlsSrtpTransport::rtp_packet_transport() const { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->rtp_packet_transport(); |
+} |
+ |
+void DtlsSrtpTransport::SetRtpPacketTransport( |
+ rtc::PacketTransportInternal* rtp) { |
+ RTC_DCHECK(srtp_transport_); |
+ srtp_transport_->SetRtpPacketTransport(rtp); |
+} |
+ |
+PacketTransportInterface* DtlsSrtpTransport::GetRtpPacketTransport() const { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->GetRtpPacketTransport(); |
+} |
+ |
+rtc::PacketTransportInternal* DtlsSrtpTransport::rtcp_packet_transport() const { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->rtcp_packet_transport(); |
+} |
+ |
+void DtlsSrtpTransport::SetRtcpPacketTransport( |
+ rtc::PacketTransportInternal* rtcp) { |
+ RTC_DCHECK(srtp_transport_); |
+ srtp_transport_->SetRtcpPacketTransport(rtcp); |
+} |
+ |
+PacketTransportInterface* DtlsSrtpTransport::GetRtcpPacketTransport() const { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->GetRtcpPacketTransport(); |
+} |
+ |
+bool DtlsSrtpTransport::IsWritable(bool rtcp) const { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->IsWritable(rtcp); |
+} |
+ |
+bool DtlsSrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet, |
+ const rtc::PacketOptions& options, |
+ int flags) { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->SendRtpPacket(packet, options, flags); |
+} |
+ |
+bool DtlsSrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet, |
+ const rtc::PacketOptions& options, |
+ int flags) { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->SendRtcpPacket(packet, options, flags); |
+} |
+ |
+bool DtlsSrtpTransport::HandlesPayloadType(int payload_type) const { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->HandlesPayloadType(payload_type); |
+} |
+ |
+void DtlsSrtpTransport::AddHandledPayloadType(int payload_type) { |
+ RTC_DCHECK(srtp_transport_); |
+ srtp_transport_->AddHandledPayloadType(payload_type); |
+} |
+ |
+void DtlsSrtpTransport::ResetParams() { |
+ active_ = false; |
+ if (srtp_transport_) { |
Taylor Brandstetter
2017/09/27 23:54:48
When will it be null?
|
+ srtp_transport_->ResetParams(); |
+ } |
+} |
+ |
+RTCError DtlsSrtpTransport::SetParameters( |
+ const RtpTransportParameters& parameters) { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->SetParameters(parameters); |
+} |
+ |
+RtpTransportParameters DtlsSrtpTransport::GetParameters() const { |
+ RTC_DCHECK(srtp_transport_); |
+ return srtp_transport_->GetParameters(); |
+} |
+ |
+} // namespace webrtc |