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