/* * 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 #include "pc/ice_transport.h" namespace webrtc { namespace { DtlsTransportState TranslateState(cricket::DtlsTransportState internal_state) { switch (internal_state) { case cricket::DTLS_TRANSPORT_NEW: return DtlsTransportState::kNew; case cricket::DTLS_TRANSPORT_CONNECTING: return DtlsTransportState::kConnecting; case cricket::DTLS_TRANSPORT_CONNECTED: return DtlsTransportState::kConnected; case cricket::DTLS_TRANSPORT_CLOSED: return DtlsTransportState::kClosed; case cricket::DTLS_TRANSPORT_FAILED: return DtlsTransportState::kFailed; } RTC_CHECK_NOTREACHED(); } } // namespace // Implementation of DtlsTransportInterface DtlsTransport::DtlsTransport( std::unique_ptr internal) : owner_thread_(rtc::Thread::Current()), info_(DtlsTransportState::kNew), internal_dtls_transport_(std::move(internal)), ice_transport_(new rtc::RefCountedObject( internal_dtls_transport_->ice_transport())) { RTC_DCHECK(internal_dtls_transport_.get()); internal_dtls_transport_->SignalDtlsState.connect( this, &DtlsTransport::OnInternalDtlsState); 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 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() != cricket::DTLS_TRANSPORT_CLOSED); // The destructor of cricket::DtlsTransportInternal calls back // into DtlsTransport, so we can't hold the lock while releasing. std::unique_ptr 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, cricket::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() == cricket::DTLS_TRANSPORT_CONNECTED) { bool success = true; int ssl_cipher_suite; int tls_version; int srtp_cipher; 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( TranslateState(internal_dtls_transport_->dtls_state()), 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( TranslateState(internal_dtls_transport_->dtls_state()), absl::nullopt, absl::nullopt, absl::nullopt, internal_dtls_transport_->GetRemoteSSLCertChain()); } } else { info_ = DtlsTransportInformation( TranslateState(internal_dtls_transport_->dtls_state())); } } else { info_ = DtlsTransportInformation(DtlsTransportState::kClosed); } } } // namespace webrtc