summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/pc/dtls_transport.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/pc/dtls_transport.cc')
-rw-r--r--third_party/libwebrtc/pc/dtls_transport.cc148
1 files changed, 148 insertions, 0 deletions
diff --git a/third_party/libwebrtc/pc/dtls_transport.cc b/third_party/libwebrtc/pc/dtls_transport.cc
new file mode 100644
index 0000000000..15eed9e47b
--- /dev/null
+++ b/third_party/libwebrtc/pc/dtls_transport.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2018 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/dtls_transport.h"
+
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/dtls_transport_interface.h"
+#include "api/make_ref_counted.h"
+#include "api/sequence_checker.h"
+#include "pc/ice_transport.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/ssl_stream_adapter.h"
+
+namespace webrtc {
+
+// Implementation of DtlsTransportInterface
+DtlsTransport::DtlsTransport(
+ std::unique_ptr<cricket::DtlsTransportInternal> internal)
+ : owner_thread_(rtc::Thread::Current()),
+ info_(DtlsTransportState::kNew),
+ internal_dtls_transport_(std::move(internal)),
+ ice_transport_(rtc::make_ref_counted<IceTransportWithPointer>(
+ internal_dtls_transport_->ice_transport())) {
+ RTC_DCHECK(internal_dtls_transport_.get());
+ internal_dtls_transport_->SubscribeDtlsTransportState(
+ [this](cricket::DtlsTransportInternal* transport,
+ DtlsTransportState state) {
+ OnInternalDtlsState(transport, state);
+ });
+ UpdateInformation();
+}
+
+DtlsTransport::~DtlsTransport() {
+ // We depend on the signaling thread to call Clear() before dropping
+ // its last reference to this object.
+ RTC_DCHECK(owner_thread_->IsCurrent() || !internal_dtls_transport_);
+}
+
+DtlsTransportInformation DtlsTransport::Information() {
+ MutexLock lock(&lock_);
+ return info_;
+}
+
+void DtlsTransport::RegisterObserver(DtlsTransportObserverInterface* observer) {
+ RTC_DCHECK_RUN_ON(owner_thread_);
+ RTC_DCHECK(observer);
+ observer_ = observer;
+}
+
+void DtlsTransport::UnregisterObserver() {
+ RTC_DCHECK_RUN_ON(owner_thread_);
+ observer_ = nullptr;
+}
+
+rtc::scoped_refptr<IceTransportInterface> DtlsTransport::ice_transport() {
+ return ice_transport_;
+}
+
+// Internal functions
+void DtlsTransport::Clear() {
+ RTC_DCHECK_RUN_ON(owner_thread_);
+ RTC_DCHECK(internal());
+ bool must_send_event =
+ (internal()->dtls_state() != DtlsTransportState::kClosed);
+ // The destructor of cricket::DtlsTransportInternal calls back
+ // into DtlsTransport, so we can't hold the lock while releasing.
+ std::unique_ptr<cricket::DtlsTransportInternal> transport_to_release;
+ {
+ MutexLock lock(&lock_);
+ transport_to_release = std::move(internal_dtls_transport_);
+ ice_transport_->Clear();
+ }
+ UpdateInformation();
+ if (observer_ && must_send_event) {
+ observer_->OnStateChange(Information());
+ }
+}
+
+void DtlsTransport::OnInternalDtlsState(
+ cricket::DtlsTransportInternal* transport,
+ DtlsTransportState state) {
+ RTC_DCHECK_RUN_ON(owner_thread_);
+ RTC_DCHECK(transport == internal());
+ RTC_DCHECK(state == internal()->dtls_state());
+ UpdateInformation();
+ if (observer_) {
+ observer_->OnStateChange(Information());
+ }
+}
+
+void DtlsTransport::UpdateInformation() {
+ RTC_DCHECK_RUN_ON(owner_thread_);
+ MutexLock lock(&lock_);
+ if (internal_dtls_transport_) {
+ if (internal_dtls_transport_->dtls_state() ==
+ DtlsTransportState::kConnected) {
+ bool success = true;
+ rtc::SSLRole internal_role;
+ absl::optional<DtlsTransportTlsRole> role;
+ int ssl_cipher_suite;
+ int tls_version;
+ int srtp_cipher;
+ success &= internal_dtls_transport_->GetDtlsRole(&internal_role);
+ if (success) {
+ switch (internal_role) {
+ case rtc::SSL_CLIENT:
+ role = DtlsTransportTlsRole::kClient;
+ break;
+ case rtc::SSL_SERVER:
+ role = DtlsTransportTlsRole::kServer;
+ break;
+ }
+ }
+ success &= internal_dtls_transport_->GetSslVersionBytes(&tls_version);
+ success &= internal_dtls_transport_->GetSslCipherSuite(&ssl_cipher_suite);
+ success &= internal_dtls_transport_->GetSrtpCryptoSuite(&srtp_cipher);
+ if (success) {
+ info_ = DtlsTransportInformation(
+ internal_dtls_transport_->dtls_state(), role, tls_version,
+ ssl_cipher_suite, srtp_cipher,
+ internal_dtls_transport_->GetRemoteSSLCertChain());
+ } else {
+ RTC_LOG(LS_ERROR) << "DtlsTransport in connected state has incomplete "
+ "TLS information";
+ info_ = DtlsTransportInformation(
+ internal_dtls_transport_->dtls_state(), role, absl::nullopt,
+ absl::nullopt, absl::nullopt,
+ internal_dtls_transport_->GetRemoteSSLCertChain());
+ }
+ } else {
+ info_ = DtlsTransportInformation(internal_dtls_transport_->dtls_state());
+ }
+ } else {
+ info_ = DtlsTransportInformation(DtlsTransportState::kClosed);
+ }
+}
+
+} // namespace webrtc