• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "pc/dtls_transport.h"
12 
13 #include <utility>
14 
15 #include "pc/ice_transport.h"
16 
17 namespace webrtc {
18 
19 namespace {
20 
TranslateState(cricket::DtlsTransportState internal_state)21 DtlsTransportState TranslateState(cricket::DtlsTransportState internal_state) {
22   switch (internal_state) {
23     case cricket::DTLS_TRANSPORT_NEW:
24       return DtlsTransportState::kNew;
25     case cricket::DTLS_TRANSPORT_CONNECTING:
26       return DtlsTransportState::kConnecting;
27     case cricket::DTLS_TRANSPORT_CONNECTED:
28       return DtlsTransportState::kConnected;
29     case cricket::DTLS_TRANSPORT_CLOSED:
30       return DtlsTransportState::kClosed;
31     case cricket::DTLS_TRANSPORT_FAILED:
32       return DtlsTransportState::kFailed;
33   }
34 }
35 
36 }  // namespace
37 
38 // Implementation of DtlsTransportInterface
DtlsTransport(std::unique_ptr<cricket::DtlsTransportInternal> internal)39 DtlsTransport::DtlsTransport(
40     std::unique_ptr<cricket::DtlsTransportInternal> internal)
41     : owner_thread_(rtc::Thread::Current()),
42       info_(DtlsTransportState::kNew),
43       internal_dtls_transport_(std::move(internal)),
44       ice_transport_(new rtc::RefCountedObject<IceTransportWithPointer>(
45           internal_dtls_transport_->ice_transport())) {
46   RTC_DCHECK(internal_dtls_transport_.get());
47   internal_dtls_transport_->SignalDtlsState.connect(
48       this, &DtlsTransport::OnInternalDtlsState);
49   UpdateInformation();
50 }
51 
~DtlsTransport()52 DtlsTransport::~DtlsTransport() {
53   // We depend on the signaling thread to call Clear() before dropping
54   // its last reference to this object.
55   RTC_DCHECK(owner_thread_->IsCurrent() || !internal_dtls_transport_);
56 }
57 
Information()58 DtlsTransportInformation DtlsTransport::Information() {
59   MutexLock lock(&lock_);
60   return info_;
61 }
62 
RegisterObserver(DtlsTransportObserverInterface * observer)63 void DtlsTransport::RegisterObserver(DtlsTransportObserverInterface* observer) {
64   RTC_DCHECK_RUN_ON(owner_thread_);
65   RTC_DCHECK(observer);
66   observer_ = observer;
67 }
68 
UnregisterObserver()69 void DtlsTransport::UnregisterObserver() {
70   RTC_DCHECK_RUN_ON(owner_thread_);
71   observer_ = nullptr;
72 }
73 
ice_transport()74 rtc::scoped_refptr<IceTransportInterface> DtlsTransport::ice_transport() {
75   return ice_transport_;
76 }
77 
78 // Internal functions
Clear()79 void DtlsTransport::Clear() {
80   RTC_DCHECK_RUN_ON(owner_thread_);
81   RTC_DCHECK(internal());
82   bool must_send_event =
83       (internal()->dtls_state() != cricket::DTLS_TRANSPORT_CLOSED);
84   // The destructor of cricket::DtlsTransportInternal calls back
85   // into DtlsTransport, so we can't hold the lock while releasing.
86   std::unique_ptr<cricket::DtlsTransportInternal> transport_to_release;
87   {
88     MutexLock lock(&lock_);
89     transport_to_release = std::move(internal_dtls_transport_);
90     ice_transport_->Clear();
91   }
92   UpdateInformation();
93   if (observer_ && must_send_event) {
94     observer_->OnStateChange(Information());
95   }
96 }
97 
OnInternalDtlsState(cricket::DtlsTransportInternal * transport,cricket::DtlsTransportState state)98 void DtlsTransport::OnInternalDtlsState(
99     cricket::DtlsTransportInternal* transport,
100     cricket::DtlsTransportState state) {
101   RTC_DCHECK_RUN_ON(owner_thread_);
102   RTC_DCHECK(transport == internal());
103   RTC_DCHECK(state == internal()->dtls_state());
104   UpdateInformation();
105   if (observer_) {
106     observer_->OnStateChange(Information());
107   }
108 }
109 
UpdateInformation()110 void DtlsTransport::UpdateInformation() {
111   RTC_DCHECK_RUN_ON(owner_thread_);
112   MutexLock lock(&lock_);
113   if (internal_dtls_transport_) {
114     if (internal_dtls_transport_->dtls_state() ==
115         cricket::DTLS_TRANSPORT_CONNECTED) {
116       bool success = true;
117       int ssl_cipher_suite;
118       int tls_version;
119       int srtp_cipher;
120       success &= internal_dtls_transport_->GetSslVersionBytes(&tls_version);
121       success &= internal_dtls_transport_->GetSslCipherSuite(&ssl_cipher_suite);
122       success &= internal_dtls_transport_->GetSrtpCryptoSuite(&srtp_cipher);
123       if (success) {
124         info_ = DtlsTransportInformation(
125             TranslateState(internal_dtls_transport_->dtls_state()), tls_version,
126             ssl_cipher_suite, srtp_cipher,
127             internal_dtls_transport_->GetRemoteSSLCertChain());
128       } else {
129         RTC_LOG(LS_ERROR) << "DtlsTransport in connected state has incomplete "
130                              "TLS information";
131         info_ = DtlsTransportInformation(
132             TranslateState(internal_dtls_transport_->dtls_state()),
133             absl::nullopt, absl::nullopt, absl::nullopt,
134             internal_dtls_transport_->GetRemoteSSLCertChain());
135       }
136     } else {
137       info_ = DtlsTransportInformation(
138           TranslateState(internal_dtls_transport_->dtls_state()));
139     }
140   } else {
141     info_ = DtlsTransportInformation(DtlsTransportState::kClosed);
142   }
143 }
144 
145 }  // namespace webrtc
146