xref: /aosp_15_r20/external/webrtc/pc/dtls_transport.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 "absl/types/optional.h"
16 #include "api/dtls_transport_interface.h"
17 #include "api/make_ref_counted.h"
18 #include "api/sequence_checker.h"
19 #include "pc/ice_transport.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/logging.h"
22 #include "rtc_base/ssl_stream_adapter.h"
23 
24 namespace webrtc {
25 
26 // Implementation of DtlsTransportInterface
DtlsTransport(std::unique_ptr<cricket::DtlsTransportInternal> internal)27 DtlsTransport::DtlsTransport(
28     std::unique_ptr<cricket::DtlsTransportInternal> internal)
29     : owner_thread_(rtc::Thread::Current()),
30       info_(DtlsTransportState::kNew),
31       internal_dtls_transport_(std::move(internal)),
32       ice_transport_(rtc::make_ref_counted<IceTransportWithPointer>(
33           internal_dtls_transport_->ice_transport())) {
34   RTC_DCHECK(internal_dtls_transport_.get());
35   internal_dtls_transport_->SubscribeDtlsTransportState(
36       [this](cricket::DtlsTransportInternal* transport,
37              DtlsTransportState state) {
38         OnInternalDtlsState(transport, state);
39       });
40   UpdateInformation();
41 }
42 
~DtlsTransport()43 DtlsTransport::~DtlsTransport() {
44   // We depend on the signaling thread to call Clear() before dropping
45   // its last reference to this object.
46   RTC_DCHECK(owner_thread_->IsCurrent() || !internal_dtls_transport_);
47 }
48 
Information()49 DtlsTransportInformation DtlsTransport::Information() {
50   MutexLock lock(&lock_);
51   return info_;
52 }
53 
RegisterObserver(DtlsTransportObserverInterface * observer)54 void DtlsTransport::RegisterObserver(DtlsTransportObserverInterface* observer) {
55   RTC_DCHECK_RUN_ON(owner_thread_);
56   RTC_DCHECK(observer);
57   observer_ = observer;
58 }
59 
UnregisterObserver()60 void DtlsTransport::UnregisterObserver() {
61   RTC_DCHECK_RUN_ON(owner_thread_);
62   observer_ = nullptr;
63 }
64 
ice_transport()65 rtc::scoped_refptr<IceTransportInterface> DtlsTransport::ice_transport() {
66   return ice_transport_;
67 }
68 
69 // Internal functions
Clear()70 void DtlsTransport::Clear() {
71   RTC_DCHECK_RUN_ON(owner_thread_);
72   RTC_DCHECK(internal());
73   bool must_send_event =
74       (internal()->dtls_state() != DtlsTransportState::kClosed);
75   // The destructor of cricket::DtlsTransportInternal calls back
76   // into DtlsTransport, so we can't hold the lock while releasing.
77   std::unique_ptr<cricket::DtlsTransportInternal> transport_to_release;
78   {
79     MutexLock lock(&lock_);
80     transport_to_release = std::move(internal_dtls_transport_);
81     ice_transport_->Clear();
82   }
83   UpdateInformation();
84   if (observer_ && must_send_event) {
85     observer_->OnStateChange(Information());
86   }
87 }
88 
OnInternalDtlsState(cricket::DtlsTransportInternal * transport,DtlsTransportState state)89 void DtlsTransport::OnInternalDtlsState(
90     cricket::DtlsTransportInternal* transport,
91     DtlsTransportState state) {
92   RTC_DCHECK_RUN_ON(owner_thread_);
93   RTC_DCHECK(transport == internal());
94   RTC_DCHECK(state == internal()->dtls_state());
95   UpdateInformation();
96   if (observer_) {
97     observer_->OnStateChange(Information());
98   }
99 }
100 
UpdateInformation()101 void DtlsTransport::UpdateInformation() {
102   RTC_DCHECK_RUN_ON(owner_thread_);
103   MutexLock lock(&lock_);
104   if (internal_dtls_transport_) {
105     if (internal_dtls_transport_->dtls_state() ==
106         DtlsTransportState::kConnected) {
107       bool success = true;
108       rtc::SSLRole internal_role;
109       absl::optional<DtlsTransportTlsRole> role;
110       int ssl_cipher_suite;
111       int tls_version;
112       int srtp_cipher;
113       success &= internal_dtls_transport_->GetDtlsRole(&internal_role);
114       if (success) {
115         switch (internal_role) {
116           case rtc::SSL_CLIENT:
117             role = DtlsTransportTlsRole::kClient;
118             break;
119           case rtc::SSL_SERVER:
120             role = DtlsTransportTlsRole::kServer;
121             break;
122         }
123       }
124       success &= internal_dtls_transport_->GetSslVersionBytes(&tls_version);
125       success &= internal_dtls_transport_->GetSslCipherSuite(&ssl_cipher_suite);
126       success &= internal_dtls_transport_->GetSrtpCryptoSuite(&srtp_cipher);
127       if (success) {
128         info_ = DtlsTransportInformation(
129             internal_dtls_transport_->dtls_state(), role, tls_version,
130             ssl_cipher_suite, srtp_cipher,
131             internal_dtls_transport_->GetRemoteSSLCertChain());
132       } else {
133         RTC_LOG(LS_ERROR) << "DtlsTransport in connected state has incomplete "
134                              "TLS information";
135         info_ = DtlsTransportInformation(
136             internal_dtls_transport_->dtls_state(), role, absl::nullopt,
137             absl::nullopt, absl::nullopt,
138             internal_dtls_transport_->GetRemoteSSLCertChain());
139       }
140     } else {
141       info_ = DtlsTransportInformation(internal_dtls_transport_->dtls_state());
142     }
143   } else {
144     info_ = DtlsTransportInformation(DtlsTransportState::kClosed);
145   }
146 }
147 
148 }  // namespace webrtc
149