Index: webrtc/pc/dtlssrtptransport.cc |
diff --git a/webrtc/pc/dtlssrtptransport.cc b/webrtc/pc/dtlssrtptransport.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c0876ab82b172fd5f532e68dfcfcfcbd476a9372 |
--- /dev/null |
+++ b/webrtc/pc/dtlssrtptransport.cc |
@@ -0,0 +1,241 @@ |
+/* |
+ * 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 "webrtc/pc/dtlssrtptransport.h" |
+ |
+#include <memory> |
+#include <string> |
+#include <utility> |
+ |
+#include "webrtc/media/base/rtputils.h" |
+#include "webrtc/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, |
+ const std::string& content_name) |
+ : srtp_transport_(std::move(transport)), content_name_(content_name) { |
+ 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 " << content_name_ << " " |
pthatcher
2017/09/12 00:24:44
I don't think it's worth passing in the content_na
Zhi Huang
2017/09/27 00:46:32
Ok. I'll remove it then.
|
+ << 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::SetDtlsTransport( |
+ bool rtcp, |
+ cricket::DtlsTransportInternal* dtls_transport) { |
+ rtcp ? rtcp_dtls_transport_ = dtls_transport |
+ : rtp_dtls_transport_ = dtls_transport; |
+} |
+ |
+void DtlsSrtpTransport::SetEncryptedHeaderExtensionIds( |
+ cricket::ContentSource source, |
+ const std::vector<int>& extension_ids) { |
+ RTC_DCHECK(srtp_transport_); |
+ srtp_transport_->SetEncryptedHeaderExtensionIds(source, 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_) { |
+ 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 |