xref: /aosp_15_r20/external/webrtc/p2p/base/dtls_transport.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/dtls_transport.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
18*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/dtls_transport_interface.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/rtc_event_log/rtc_event_log.h"
22*d9f75844SAndroid Build Coastguard Worker #include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
23*d9f75844SAndroid Build Coastguard Worker #include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
24*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/packet_transport_internal.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/buffer.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/dscp.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rtc_certificate.h"
30*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_stream_adapter.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/stream.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
33*d9f75844SAndroid Build Coastguard Worker 
34*d9f75844SAndroid Build Coastguard Worker namespace cricket {
35*d9f75844SAndroid Build Coastguard Worker 
36*d9f75844SAndroid Build Coastguard Worker // We don't pull the RTP constants from rtputils.h, to avoid a layer violation.
37*d9f75844SAndroid Build Coastguard Worker static const size_t kDtlsRecordHeaderLen = 13;
38*d9f75844SAndroid Build Coastguard Worker static const size_t kMaxDtlsPacketLen = 2048;
39*d9f75844SAndroid Build Coastguard Worker static const size_t kMinRtpPacketLen = 12;
40*d9f75844SAndroid Build Coastguard Worker 
41*d9f75844SAndroid Build Coastguard Worker // Maximum number of pending packets in the queue. Packets are read immediately
42*d9f75844SAndroid Build Coastguard Worker // after they have been written, so a capacity of "1" is sufficient.
43*d9f75844SAndroid Build Coastguard Worker //
44*d9f75844SAndroid Build Coastguard Worker // However, this bug seems to indicate that's not the case: crbug.com/1063834
45*d9f75844SAndroid Build Coastguard Worker // So, temporarily increasing it to 2 to see if that makes a difference.
46*d9f75844SAndroid Build Coastguard Worker static const size_t kMaxPendingPackets = 2;
47*d9f75844SAndroid Build Coastguard Worker 
48*d9f75844SAndroid Build Coastguard Worker // Minimum and maximum values for the initial DTLS handshake timeout. We'll pick
49*d9f75844SAndroid Build Coastguard Worker // an initial timeout based on ICE RTT estimates, but clamp it to this range.
50*d9f75844SAndroid Build Coastguard Worker static const int kMinHandshakeTimeout = 50;
51*d9f75844SAndroid Build Coastguard Worker static const int kMaxHandshakeTimeout = 3000;
52*d9f75844SAndroid Build Coastguard Worker 
IsDtlsPacket(const char * data,size_t len)53*d9f75844SAndroid Build Coastguard Worker static bool IsDtlsPacket(const char* data, size_t len) {
54*d9f75844SAndroid Build Coastguard Worker   const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
55*d9f75844SAndroid Build Coastguard Worker   return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
56*d9f75844SAndroid Build Coastguard Worker }
IsDtlsClientHelloPacket(const char * data,size_t len)57*d9f75844SAndroid Build Coastguard Worker static bool IsDtlsClientHelloPacket(const char* data, size_t len) {
58*d9f75844SAndroid Build Coastguard Worker   if (!IsDtlsPacket(data, len)) {
59*d9f75844SAndroid Build Coastguard Worker     return false;
60*d9f75844SAndroid Build Coastguard Worker   }
61*d9f75844SAndroid Build Coastguard Worker   const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
62*d9f75844SAndroid Build Coastguard Worker   return len > 17 && u[0] == 22 && u[13] == 1;
63*d9f75844SAndroid Build Coastguard Worker }
IsRtpPacket(const char * data,size_t len)64*d9f75844SAndroid Build Coastguard Worker static bool IsRtpPacket(const char* data, size_t len) {
65*d9f75844SAndroid Build Coastguard Worker   const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
66*d9f75844SAndroid Build Coastguard Worker   return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
67*d9f75844SAndroid Build Coastguard Worker }
68*d9f75844SAndroid Build Coastguard Worker 
StreamInterfaceChannel(IceTransportInternal * ice_transport)69*d9f75844SAndroid Build Coastguard Worker StreamInterfaceChannel::StreamInterfaceChannel(
70*d9f75844SAndroid Build Coastguard Worker     IceTransportInternal* ice_transport)
71*d9f75844SAndroid Build Coastguard Worker     : ice_transport_(ice_transport),
72*d9f75844SAndroid Build Coastguard Worker       state_(rtc::SS_OPEN),
73*d9f75844SAndroid Build Coastguard Worker       packets_(kMaxPendingPackets, kMaxDtlsPacketLen) {}
74*d9f75844SAndroid Build Coastguard Worker 
Read(rtc::ArrayView<uint8_t> buffer,size_t & read,int & error)75*d9f75844SAndroid Build Coastguard Worker rtc::StreamResult StreamInterfaceChannel::Read(rtc::ArrayView<uint8_t> buffer,
76*d9f75844SAndroid Build Coastguard Worker                                                size_t& read,
77*d9f75844SAndroid Build Coastguard Worker                                                int& error) {
78*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&sequence_checker_);
79*d9f75844SAndroid Build Coastguard Worker 
80*d9f75844SAndroid Build Coastguard Worker   if (state_ == rtc::SS_CLOSED)
81*d9f75844SAndroid Build Coastguard Worker     return rtc::SR_EOS;
82*d9f75844SAndroid Build Coastguard Worker   if (state_ == rtc::SS_OPENING)
83*d9f75844SAndroid Build Coastguard Worker     return rtc::SR_BLOCK;
84*d9f75844SAndroid Build Coastguard Worker 
85*d9f75844SAndroid Build Coastguard Worker   if (!packets_.ReadFront(buffer.data(), buffer.size(), &read)) {
86*d9f75844SAndroid Build Coastguard Worker     return rtc::SR_BLOCK;
87*d9f75844SAndroid Build Coastguard Worker   }
88*d9f75844SAndroid Build Coastguard Worker 
89*d9f75844SAndroid Build Coastguard Worker   return rtc::SR_SUCCESS;
90*d9f75844SAndroid Build Coastguard Worker }
91*d9f75844SAndroid Build Coastguard Worker 
Write(rtc::ArrayView<const uint8_t> data,size_t & written,int & error)92*d9f75844SAndroid Build Coastguard Worker rtc::StreamResult StreamInterfaceChannel::Write(
93*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const uint8_t> data,
94*d9f75844SAndroid Build Coastguard Worker     size_t& written,
95*d9f75844SAndroid Build Coastguard Worker     int& error) {
96*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&sequence_checker_);
97*d9f75844SAndroid Build Coastguard Worker   // Always succeeds, since this is an unreliable transport anyway.
98*d9f75844SAndroid Build Coastguard Worker   // TODO(zhihuang): Should this block if ice_transport_'s temporarily
99*d9f75844SAndroid Build Coastguard Worker   // unwritable?
100*d9f75844SAndroid Build Coastguard Worker   rtc::PacketOptions packet_options;
101*d9f75844SAndroid Build Coastguard Worker   ice_transport_->SendPacket(reinterpret_cast<const char*>(data.data()),
102*d9f75844SAndroid Build Coastguard Worker                              data.size(), packet_options);
103*d9f75844SAndroid Build Coastguard Worker   written = data.size();
104*d9f75844SAndroid Build Coastguard Worker   return rtc::SR_SUCCESS;
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker 
OnPacketReceived(const char * data,size_t size)107*d9f75844SAndroid Build Coastguard Worker bool StreamInterfaceChannel::OnPacketReceived(const char* data, size_t size) {
108*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&sequence_checker_);
109*d9f75844SAndroid Build Coastguard Worker   if (packets_.size() > 0) {
110*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Packet already in queue.";
111*d9f75844SAndroid Build Coastguard Worker   }
112*d9f75844SAndroid Build Coastguard Worker   bool ret = packets_.WriteBack(data, size, NULL);
113*d9f75844SAndroid Build Coastguard Worker   if (!ret) {
114*d9f75844SAndroid Build Coastguard Worker     // Somehow we received another packet before the SSLStreamAdapter read the
115*d9f75844SAndroid Build Coastguard Worker     // previous one out of our temporary buffer. In this case, we'll log an
116*d9f75844SAndroid Build Coastguard Worker     // error and still signal the read event, hoping that it will read the
117*d9f75844SAndroid Build Coastguard Worker     // packet currently in packets_.
118*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Failed to write packet to queue.";
119*d9f75844SAndroid Build Coastguard Worker   }
120*d9f75844SAndroid Build Coastguard Worker   SignalEvent(this, rtc::SE_READ, 0);
121*d9f75844SAndroid Build Coastguard Worker   return ret;
122*d9f75844SAndroid Build Coastguard Worker }
123*d9f75844SAndroid Build Coastguard Worker 
GetState() const124*d9f75844SAndroid Build Coastguard Worker rtc::StreamState StreamInterfaceChannel::GetState() const {
125*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&sequence_checker_);
126*d9f75844SAndroid Build Coastguard Worker   return state_;
127*d9f75844SAndroid Build Coastguard Worker }
128*d9f75844SAndroid Build Coastguard Worker 
Close()129*d9f75844SAndroid Build Coastguard Worker void StreamInterfaceChannel::Close() {
130*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&sequence_checker_);
131*d9f75844SAndroid Build Coastguard Worker   packets_.Clear();
132*d9f75844SAndroid Build Coastguard Worker   state_ = rtc::SS_CLOSED;
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker 
DtlsTransport(IceTransportInternal * ice_transport,const webrtc::CryptoOptions & crypto_options,webrtc::RtcEventLog * event_log,rtc::SSLProtocolVersion max_version)135*d9f75844SAndroid Build Coastguard Worker DtlsTransport::DtlsTransport(IceTransportInternal* ice_transport,
136*d9f75844SAndroid Build Coastguard Worker                              const webrtc::CryptoOptions& crypto_options,
137*d9f75844SAndroid Build Coastguard Worker                              webrtc::RtcEventLog* event_log,
138*d9f75844SAndroid Build Coastguard Worker                              rtc::SSLProtocolVersion max_version)
139*d9f75844SAndroid Build Coastguard Worker     : component_(ice_transport->component()),
140*d9f75844SAndroid Build Coastguard Worker       ice_transport_(ice_transport),
141*d9f75844SAndroid Build Coastguard Worker       downward_(NULL),
142*d9f75844SAndroid Build Coastguard Worker       srtp_ciphers_(crypto_options.GetSupportedDtlsSrtpCryptoSuites()),
143*d9f75844SAndroid Build Coastguard Worker       ssl_max_version_(max_version),
144*d9f75844SAndroid Build Coastguard Worker       event_log_(event_log) {
145*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ice_transport_);
146*d9f75844SAndroid Build Coastguard Worker   ConnectToIceTransport();
147*d9f75844SAndroid Build Coastguard Worker }
148*d9f75844SAndroid Build Coastguard Worker 
149*d9f75844SAndroid Build Coastguard Worker DtlsTransport::~DtlsTransport() = default;
150*d9f75844SAndroid Build Coastguard Worker 
dtls_state() const151*d9f75844SAndroid Build Coastguard Worker webrtc::DtlsTransportState DtlsTransport::dtls_state() const {
152*d9f75844SAndroid Build Coastguard Worker   return dtls_state_;
153*d9f75844SAndroid Build Coastguard Worker }
154*d9f75844SAndroid Build Coastguard Worker 
transport_name() const155*d9f75844SAndroid Build Coastguard Worker const std::string& DtlsTransport::transport_name() const {
156*d9f75844SAndroid Build Coastguard Worker   return ice_transport_->transport_name();
157*d9f75844SAndroid Build Coastguard Worker }
158*d9f75844SAndroid Build Coastguard Worker 
component() const159*d9f75844SAndroid Build Coastguard Worker int DtlsTransport::component() const {
160*d9f75844SAndroid Build Coastguard Worker   return component_;
161*d9f75844SAndroid Build Coastguard Worker }
162*d9f75844SAndroid Build Coastguard Worker 
IsDtlsActive() const163*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::IsDtlsActive() const {
164*d9f75844SAndroid Build Coastguard Worker   return dtls_active_;
165*d9f75844SAndroid Build Coastguard Worker }
166*d9f75844SAndroid Build Coastguard Worker 
SetLocalCertificate(const rtc::scoped_refptr<rtc::RTCCertificate> & certificate)167*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::SetLocalCertificate(
168*d9f75844SAndroid Build Coastguard Worker     const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
169*d9f75844SAndroid Build Coastguard Worker   if (dtls_active_) {
170*d9f75844SAndroid Build Coastguard Worker     if (certificate == local_certificate_) {
171*d9f75844SAndroid Build Coastguard Worker       // This may happen during renegotiation.
172*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << ToString() << ": Ignoring identical DTLS identity";
173*d9f75844SAndroid Build Coastguard Worker       return true;
174*d9f75844SAndroid Build Coastguard Worker     } else {
175*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
176*d9f75844SAndroid Build Coastguard Worker                         << ": Can't change DTLS local identity in this state";
177*d9f75844SAndroid Build Coastguard Worker       return false;
178*d9f75844SAndroid Build Coastguard Worker     }
179*d9f75844SAndroid Build Coastguard Worker   }
180*d9f75844SAndroid Build Coastguard Worker 
181*d9f75844SAndroid Build Coastguard Worker   if (certificate) {
182*d9f75844SAndroid Build Coastguard Worker     local_certificate_ = certificate;
183*d9f75844SAndroid Build Coastguard Worker     dtls_active_ = true;
184*d9f75844SAndroid Build Coastguard Worker   } else {
185*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString()
186*d9f75844SAndroid Build Coastguard Worker                      << ": NULL DTLS identity supplied. Not doing DTLS";
187*d9f75844SAndroid Build Coastguard Worker   }
188*d9f75844SAndroid Build Coastguard Worker 
189*d9f75844SAndroid Build Coastguard Worker   return true;
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker 
GetLocalCertificate() const192*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<rtc::RTCCertificate> DtlsTransport::GetLocalCertificate()
193*d9f75844SAndroid Build Coastguard Worker     const {
194*d9f75844SAndroid Build Coastguard Worker   return local_certificate_;
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker 
SetDtlsRole(rtc::SSLRole role)197*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::SetDtlsRole(rtc::SSLRole role) {
198*d9f75844SAndroid Build Coastguard Worker   if (dtls_) {
199*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(dtls_role_);
200*d9f75844SAndroid Build Coastguard Worker     if (*dtls_role_ != role) {
201*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR)
202*d9f75844SAndroid Build Coastguard Worker           << "SSL Role can't be reversed after the session is setup.";
203*d9f75844SAndroid Build Coastguard Worker       return false;
204*d9f75844SAndroid Build Coastguard Worker     }
205*d9f75844SAndroid Build Coastguard Worker     return true;
206*d9f75844SAndroid Build Coastguard Worker   }
207*d9f75844SAndroid Build Coastguard Worker 
208*d9f75844SAndroid Build Coastguard Worker   dtls_role_ = role;
209*d9f75844SAndroid Build Coastguard Worker   return true;
210*d9f75844SAndroid Build Coastguard Worker }
211*d9f75844SAndroid Build Coastguard Worker 
GetDtlsRole(rtc::SSLRole * role) const212*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::GetDtlsRole(rtc::SSLRole* role) const {
213*d9f75844SAndroid Build Coastguard Worker   if (!dtls_role_) {
214*d9f75844SAndroid Build Coastguard Worker     return false;
215*d9f75844SAndroid Build Coastguard Worker   }
216*d9f75844SAndroid Build Coastguard Worker   *role = *dtls_role_;
217*d9f75844SAndroid Build Coastguard Worker   return true;
218*d9f75844SAndroid Build Coastguard Worker }
219*d9f75844SAndroid Build Coastguard Worker 
GetSslCipherSuite(int * cipher)220*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::GetSslCipherSuite(int* cipher) {
221*d9f75844SAndroid Build Coastguard Worker   if (dtls_state() != webrtc::DtlsTransportState::kConnected) {
222*d9f75844SAndroid Build Coastguard Worker     return false;
223*d9f75844SAndroid Build Coastguard Worker   }
224*d9f75844SAndroid Build Coastguard Worker 
225*d9f75844SAndroid Build Coastguard Worker   return dtls_->GetSslCipherSuite(cipher);
226*d9f75844SAndroid Build Coastguard Worker }
227*d9f75844SAndroid Build Coastguard Worker 
SetRemoteParameters(absl::string_view digest_alg,const uint8_t * digest,size_t digest_len,absl::optional<rtc::SSLRole> role)228*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError DtlsTransport::SetRemoteParameters(
229*d9f75844SAndroid Build Coastguard Worker     absl::string_view digest_alg,
230*d9f75844SAndroid Build Coastguard Worker     const uint8_t* digest,
231*d9f75844SAndroid Build Coastguard Worker     size_t digest_len,
232*d9f75844SAndroid Build Coastguard Worker     absl::optional<rtc::SSLRole> role) {
233*d9f75844SAndroid Build Coastguard Worker   rtc::Buffer remote_fingerprint_value(digest, digest_len);
234*d9f75844SAndroid Build Coastguard Worker   bool is_dtls_restart =
235*d9f75844SAndroid Build Coastguard Worker       dtls_active_ && remote_fingerprint_value_ != remote_fingerprint_value;
236*d9f75844SAndroid Build Coastguard Worker   // Set SSL role. Role must be set before fingerprint is applied, which
237*d9f75844SAndroid Build Coastguard Worker   // initiates DTLS setup.
238*d9f75844SAndroid Build Coastguard Worker   if (role) {
239*d9f75844SAndroid Build Coastguard Worker     if (is_dtls_restart) {
240*d9f75844SAndroid Build Coastguard Worker       dtls_role_ = *role;
241*d9f75844SAndroid Build Coastguard Worker     } else {
242*d9f75844SAndroid Build Coastguard Worker       if (!SetDtlsRole(*role)) {
243*d9f75844SAndroid Build Coastguard Worker         return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
244*d9f75844SAndroid Build Coastguard Worker                                 "Failed to set SSL role for the transport.");
245*d9f75844SAndroid Build Coastguard Worker       }
246*d9f75844SAndroid Build Coastguard Worker     }
247*d9f75844SAndroid Build Coastguard Worker   }
248*d9f75844SAndroid Build Coastguard Worker   // Apply remote fingerprint.
249*d9f75844SAndroid Build Coastguard Worker   if (!SetRemoteFingerprint(digest_alg, digest, digest_len)) {
250*d9f75844SAndroid Build Coastguard Worker     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
251*d9f75844SAndroid Build Coastguard Worker                             "Failed to apply remote fingerprint.");
252*d9f75844SAndroid Build Coastguard Worker   }
253*d9f75844SAndroid Build Coastguard Worker   return webrtc::RTCError::OK();
254*d9f75844SAndroid Build Coastguard Worker }
255*d9f75844SAndroid Build Coastguard Worker 
SetRemoteFingerprint(absl::string_view digest_alg,const uint8_t * digest,size_t digest_len)256*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::SetRemoteFingerprint(absl::string_view digest_alg,
257*d9f75844SAndroid Build Coastguard Worker                                          const uint8_t* digest,
258*d9f75844SAndroid Build Coastguard Worker                                          size_t digest_len) {
259*d9f75844SAndroid Build Coastguard Worker   rtc::Buffer remote_fingerprint_value(digest, digest_len);
260*d9f75844SAndroid Build Coastguard Worker 
261*d9f75844SAndroid Build Coastguard Worker   // Once we have the local certificate, the same remote fingerprint can be set
262*d9f75844SAndroid Build Coastguard Worker   // multiple times.
263*d9f75844SAndroid Build Coastguard Worker   if (dtls_active_ && remote_fingerprint_value_ == remote_fingerprint_value &&
264*d9f75844SAndroid Build Coastguard Worker       !digest_alg.empty()) {
265*d9f75844SAndroid Build Coastguard Worker     // This may happen during renegotiation.
266*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString()
267*d9f75844SAndroid Build Coastguard Worker                      << ": Ignoring identical remote DTLS fingerprint";
268*d9f75844SAndroid Build Coastguard Worker     return true;
269*d9f75844SAndroid Build Coastguard Worker   }
270*d9f75844SAndroid Build Coastguard Worker 
271*d9f75844SAndroid Build Coastguard Worker   // If the other side doesn't support DTLS, turn off `dtls_active_`.
272*d9f75844SAndroid Build Coastguard Worker   // TODO(deadbeef): Remove this. It's dangerous, because it relies on higher
273*d9f75844SAndroid Build Coastguard Worker   // level code to ensure DTLS is actually used, but there are tests that
274*d9f75844SAndroid Build Coastguard Worker   // depend on it, for the case where an m= section is rejected. In that case
275*d9f75844SAndroid Build Coastguard Worker   // SetRemoteFingerprint shouldn't even be called though.
276*d9f75844SAndroid Build Coastguard Worker   if (digest_alg.empty()) {
277*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!digest_len);
278*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString() << ": Other side didn't support DTLS.";
279*d9f75844SAndroid Build Coastguard Worker     dtls_active_ = false;
280*d9f75844SAndroid Build Coastguard Worker     return true;
281*d9f75844SAndroid Build Coastguard Worker   }
282*d9f75844SAndroid Build Coastguard Worker 
283*d9f75844SAndroid Build Coastguard Worker   // Otherwise, we must have a local certificate before setting remote
284*d9f75844SAndroid Build Coastguard Worker   // fingerprint.
285*d9f75844SAndroid Build Coastguard Worker   if (!dtls_active_) {
286*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << ToString()
287*d9f75844SAndroid Build Coastguard Worker                       << ": Can't set DTLS remote settings in this state.";
288*d9f75844SAndroid Build Coastguard Worker     return false;
289*d9f75844SAndroid Build Coastguard Worker   }
290*d9f75844SAndroid Build Coastguard Worker 
291*d9f75844SAndroid Build Coastguard Worker   // At this point we know we are doing DTLS
292*d9f75844SAndroid Build Coastguard Worker   bool fingerprint_changing = remote_fingerprint_value_.size() > 0u;
293*d9f75844SAndroid Build Coastguard Worker   remote_fingerprint_value_ = std::move(remote_fingerprint_value);
294*d9f75844SAndroid Build Coastguard Worker   remote_fingerprint_algorithm_ = std::string(digest_alg);
295*d9f75844SAndroid Build Coastguard Worker 
296*d9f75844SAndroid Build Coastguard Worker   if (dtls_ && !fingerprint_changing) {
297*d9f75844SAndroid Build Coastguard Worker     // This can occur if DTLS is set up before a remote fingerprint is
298*d9f75844SAndroid Build Coastguard Worker     // received. For instance, if we set up DTLS due to receiving an early
299*d9f75844SAndroid Build Coastguard Worker     // ClientHello.
300*d9f75844SAndroid Build Coastguard Worker     rtc::SSLPeerCertificateDigestError err;
301*d9f75844SAndroid Build Coastguard Worker     if (!dtls_->SetPeerCertificateDigest(
302*d9f75844SAndroid Build Coastguard Worker             remote_fingerprint_algorithm_,
303*d9f75844SAndroid Build Coastguard Worker             reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
304*d9f75844SAndroid Build Coastguard Worker             remote_fingerprint_value_.size(), &err)) {
305*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
306*d9f75844SAndroid Build Coastguard Worker                         << ": Couldn't set DTLS certificate digest.";
307*d9f75844SAndroid Build Coastguard Worker       set_dtls_state(webrtc::DtlsTransportState::kFailed);
308*d9f75844SAndroid Build Coastguard Worker       // If the error is "verification failed", don't return false, because
309*d9f75844SAndroid Build Coastguard Worker       // this means the fingerprint was formatted correctly but didn't match
310*d9f75844SAndroid Build Coastguard Worker       // the certificate from the DTLS handshake. Thus the DTLS state should go
311*d9f75844SAndroid Build Coastguard Worker       // to "failed", but SetRemoteDescription shouldn't fail.
312*d9f75844SAndroid Build Coastguard Worker       return err == rtc::SSLPeerCertificateDigestError::VERIFICATION_FAILED;
313*d9f75844SAndroid Build Coastguard Worker     }
314*d9f75844SAndroid Build Coastguard Worker     return true;
315*d9f75844SAndroid Build Coastguard Worker   }
316*d9f75844SAndroid Build Coastguard Worker 
317*d9f75844SAndroid Build Coastguard Worker   // If the fingerprint is changing, we'll tear down the DTLS association and
318*d9f75844SAndroid Build Coastguard Worker   // create a new one, resetting our state.
319*d9f75844SAndroid Build Coastguard Worker   if (dtls_ && fingerprint_changing) {
320*d9f75844SAndroid Build Coastguard Worker     dtls_.reset(nullptr);
321*d9f75844SAndroid Build Coastguard Worker     set_dtls_state(webrtc::DtlsTransportState::kNew);
322*d9f75844SAndroid Build Coastguard Worker     set_writable(false);
323*d9f75844SAndroid Build Coastguard Worker   }
324*d9f75844SAndroid Build Coastguard Worker 
325*d9f75844SAndroid Build Coastguard Worker   if (!SetupDtls()) {
326*d9f75844SAndroid Build Coastguard Worker     set_dtls_state(webrtc::DtlsTransportState::kFailed);
327*d9f75844SAndroid Build Coastguard Worker     return false;
328*d9f75844SAndroid Build Coastguard Worker   }
329*d9f75844SAndroid Build Coastguard Worker 
330*d9f75844SAndroid Build Coastguard Worker   return true;
331*d9f75844SAndroid Build Coastguard Worker }
332*d9f75844SAndroid Build Coastguard Worker 
GetRemoteSSLCertChain() const333*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SSLCertChain> DtlsTransport::GetRemoteSSLCertChain()
334*d9f75844SAndroid Build Coastguard Worker     const {
335*d9f75844SAndroid Build Coastguard Worker   if (!dtls_) {
336*d9f75844SAndroid Build Coastguard Worker     return nullptr;
337*d9f75844SAndroid Build Coastguard Worker   }
338*d9f75844SAndroid Build Coastguard Worker 
339*d9f75844SAndroid Build Coastguard Worker   return dtls_->GetPeerSSLCertChain();
340*d9f75844SAndroid Build Coastguard Worker }
341*d9f75844SAndroid Build Coastguard Worker 
ExportKeyingMaterial(absl::string_view label,const uint8_t * context,size_t context_len,bool use_context,uint8_t * result,size_t result_len)342*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::ExportKeyingMaterial(absl::string_view label,
343*d9f75844SAndroid Build Coastguard Worker                                          const uint8_t* context,
344*d9f75844SAndroid Build Coastguard Worker                                          size_t context_len,
345*d9f75844SAndroid Build Coastguard Worker                                          bool use_context,
346*d9f75844SAndroid Build Coastguard Worker                                          uint8_t* result,
347*d9f75844SAndroid Build Coastguard Worker                                          size_t result_len) {
348*d9f75844SAndroid Build Coastguard Worker   return (dtls_.get())
349*d9f75844SAndroid Build Coastguard Worker              ? dtls_->ExportKeyingMaterial(label, context, context_len,
350*d9f75844SAndroid Build Coastguard Worker                                            use_context, result, result_len)
351*d9f75844SAndroid Build Coastguard Worker              : false;
352*d9f75844SAndroid Build Coastguard Worker }
353*d9f75844SAndroid Build Coastguard Worker 
SetupDtls()354*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::SetupDtls() {
355*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(dtls_role_);
356*d9f75844SAndroid Build Coastguard Worker   {
357*d9f75844SAndroid Build Coastguard Worker     auto downward = std::make_unique<StreamInterfaceChannel>(ice_transport_);
358*d9f75844SAndroid Build Coastguard Worker     StreamInterfaceChannel* downward_ptr = downward.get();
359*d9f75844SAndroid Build Coastguard Worker 
360*d9f75844SAndroid Build Coastguard Worker     dtls_ = rtc::SSLStreamAdapter::Create(std::move(downward));
361*d9f75844SAndroid Build Coastguard Worker     if (!dtls_) {
362*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString() << ": Failed to create DTLS adapter.";
363*d9f75844SAndroid Build Coastguard Worker       return false;
364*d9f75844SAndroid Build Coastguard Worker     }
365*d9f75844SAndroid Build Coastguard Worker     downward_ = downward_ptr;
366*d9f75844SAndroid Build Coastguard Worker   }
367*d9f75844SAndroid Build Coastguard Worker 
368*d9f75844SAndroid Build Coastguard Worker   dtls_->SetIdentity(local_certificate_->identity()->Clone());
369*d9f75844SAndroid Build Coastguard Worker   dtls_->SetMode(rtc::SSL_MODE_DTLS);
370*d9f75844SAndroid Build Coastguard Worker   dtls_->SetMaxProtocolVersion(ssl_max_version_);
371*d9f75844SAndroid Build Coastguard Worker   dtls_->SetServerRole(*dtls_role_);
372*d9f75844SAndroid Build Coastguard Worker   dtls_->SignalEvent.connect(this, &DtlsTransport::OnDtlsEvent);
373*d9f75844SAndroid Build Coastguard Worker   dtls_->SignalSSLHandshakeError.connect(this,
374*d9f75844SAndroid Build Coastguard Worker                                          &DtlsTransport::OnDtlsHandshakeError);
375*d9f75844SAndroid Build Coastguard Worker   if (remote_fingerprint_value_.size() &&
376*d9f75844SAndroid Build Coastguard Worker       !dtls_->SetPeerCertificateDigest(
377*d9f75844SAndroid Build Coastguard Worker           remote_fingerprint_algorithm_,
378*d9f75844SAndroid Build Coastguard Worker           reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
379*d9f75844SAndroid Build Coastguard Worker           remote_fingerprint_value_.size())) {
380*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << ToString()
381*d9f75844SAndroid Build Coastguard Worker                       << ": Couldn't set DTLS certificate digest.";
382*d9f75844SAndroid Build Coastguard Worker     return false;
383*d9f75844SAndroid Build Coastguard Worker   }
384*d9f75844SAndroid Build Coastguard Worker 
385*d9f75844SAndroid Build Coastguard Worker   // Set up DTLS-SRTP, if it's been enabled.
386*d9f75844SAndroid Build Coastguard Worker   if (!srtp_ciphers_.empty()) {
387*d9f75844SAndroid Build Coastguard Worker     if (!dtls_->SetDtlsSrtpCryptoSuites(srtp_ciphers_)) {
388*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString() << ": Couldn't set DTLS-SRTP ciphers.";
389*d9f75844SAndroid Build Coastguard Worker       return false;
390*d9f75844SAndroid Build Coastguard Worker     }
391*d9f75844SAndroid Build Coastguard Worker   } else {
392*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString() << ": Not using DTLS-SRTP.";
393*d9f75844SAndroid Build Coastguard Worker   }
394*d9f75844SAndroid Build Coastguard Worker 
395*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString() << ": DTLS setup complete.";
396*d9f75844SAndroid Build Coastguard Worker 
397*d9f75844SAndroid Build Coastguard Worker   // If the underlying ice_transport is already writable at this point, we may
398*d9f75844SAndroid Build Coastguard Worker   // be able to start DTLS right away.
399*d9f75844SAndroid Build Coastguard Worker   MaybeStartDtls();
400*d9f75844SAndroid Build Coastguard Worker   return true;
401*d9f75844SAndroid Build Coastguard Worker }
402*d9f75844SAndroid Build Coastguard Worker 
GetSrtpCryptoSuite(int * cipher)403*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::GetSrtpCryptoSuite(int* cipher) {
404*d9f75844SAndroid Build Coastguard Worker   if (dtls_state() != webrtc::DtlsTransportState::kConnected) {
405*d9f75844SAndroid Build Coastguard Worker     return false;
406*d9f75844SAndroid Build Coastguard Worker   }
407*d9f75844SAndroid Build Coastguard Worker 
408*d9f75844SAndroid Build Coastguard Worker   return dtls_->GetDtlsSrtpCryptoSuite(cipher);
409*d9f75844SAndroid Build Coastguard Worker }
410*d9f75844SAndroid Build Coastguard Worker 
GetSslVersionBytes(int * version) const411*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::GetSslVersionBytes(int* version) const {
412*d9f75844SAndroid Build Coastguard Worker   if (dtls_state() != webrtc::DtlsTransportState::kConnected) {
413*d9f75844SAndroid Build Coastguard Worker     return false;
414*d9f75844SAndroid Build Coastguard Worker   }
415*d9f75844SAndroid Build Coastguard Worker 
416*d9f75844SAndroid Build Coastguard Worker   return dtls_->GetSslVersionBytes(version);
417*d9f75844SAndroid Build Coastguard Worker }
418*d9f75844SAndroid Build Coastguard Worker 
419*d9f75844SAndroid Build Coastguard Worker // Called from upper layers to send a media packet.
SendPacket(const char * data,size_t size,const rtc::PacketOptions & options,int flags)420*d9f75844SAndroid Build Coastguard Worker int DtlsTransport::SendPacket(const char* data,
421*d9f75844SAndroid Build Coastguard Worker                               size_t size,
422*d9f75844SAndroid Build Coastguard Worker                               const rtc::PacketOptions& options,
423*d9f75844SAndroid Build Coastguard Worker                               int flags) {
424*d9f75844SAndroid Build Coastguard Worker   if (!dtls_active_) {
425*d9f75844SAndroid Build Coastguard Worker     // Not doing DTLS.
426*d9f75844SAndroid Build Coastguard Worker     return ice_transport_->SendPacket(data, size, options);
427*d9f75844SAndroid Build Coastguard Worker   }
428*d9f75844SAndroid Build Coastguard Worker 
429*d9f75844SAndroid Build Coastguard Worker   switch (dtls_state()) {
430*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kNew:
431*d9f75844SAndroid Build Coastguard Worker       // Can't send data until the connection is active.
432*d9f75844SAndroid Build Coastguard Worker       // TODO([email protected]): assert here if dtls_ is NULL?
433*d9f75844SAndroid Build Coastguard Worker       return -1;
434*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kConnecting:
435*d9f75844SAndroid Build Coastguard Worker       // Can't send data until the connection is active.
436*d9f75844SAndroid Build Coastguard Worker       return -1;
437*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kConnected:
438*d9f75844SAndroid Build Coastguard Worker       if (flags & PF_SRTP_BYPASS) {
439*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(!srtp_ciphers_.empty());
440*d9f75844SAndroid Build Coastguard Worker         if (!IsRtpPacket(data, size)) {
441*d9f75844SAndroid Build Coastguard Worker           return -1;
442*d9f75844SAndroid Build Coastguard Worker         }
443*d9f75844SAndroid Build Coastguard Worker 
444*d9f75844SAndroid Build Coastguard Worker         return ice_transport_->SendPacket(data, size, options);
445*d9f75844SAndroid Build Coastguard Worker       } else {
446*d9f75844SAndroid Build Coastguard Worker         size_t written;
447*d9f75844SAndroid Build Coastguard Worker         int error;
448*d9f75844SAndroid Build Coastguard Worker         return (dtls_->WriteAll(
449*d9f75844SAndroid Build Coastguard Worker                     rtc::MakeArrayView(reinterpret_cast<const uint8_t*>(data),
450*d9f75844SAndroid Build Coastguard Worker                                        size),
451*d9f75844SAndroid Build Coastguard Worker                     written, error) == rtc::SR_SUCCESS)
452*d9f75844SAndroid Build Coastguard Worker                    ? static_cast<int>(size)
453*d9f75844SAndroid Build Coastguard Worker                    : -1;
454*d9f75844SAndroid Build Coastguard Worker       }
455*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kFailed:
456*d9f75844SAndroid Build Coastguard Worker       // Can't send anything when we're failed.
457*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
458*d9f75844SAndroid Build Coastguard Worker                         << ": Couldn't send packet due to "
459*d9f75844SAndroid Build Coastguard Worker                            "webrtc::DtlsTransportState::kFailed.";
460*d9f75844SAndroid Build Coastguard Worker       return -1;
461*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kClosed:
462*d9f75844SAndroid Build Coastguard Worker       // Can't send anything when we're closed.
463*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
464*d9f75844SAndroid Build Coastguard Worker                         << ": Couldn't send packet due to "
465*d9f75844SAndroid Build Coastguard Worker                            "webrtc::DtlsTransportState::kClosed.";
466*d9f75844SAndroid Build Coastguard Worker       return -1;
467*d9f75844SAndroid Build Coastguard Worker     default:
468*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
469*d9f75844SAndroid Build Coastguard Worker       return -1;
470*d9f75844SAndroid Build Coastguard Worker   }
471*d9f75844SAndroid Build Coastguard Worker }
472*d9f75844SAndroid Build Coastguard Worker 
ice_transport()473*d9f75844SAndroid Build Coastguard Worker IceTransportInternal* DtlsTransport::ice_transport() {
474*d9f75844SAndroid Build Coastguard Worker   return ice_transport_;
475*d9f75844SAndroid Build Coastguard Worker }
476*d9f75844SAndroid Build Coastguard Worker 
IsDtlsConnected()477*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::IsDtlsConnected() {
478*d9f75844SAndroid Build Coastguard Worker   return dtls_ && dtls_->IsTlsConnected();
479*d9f75844SAndroid Build Coastguard Worker }
480*d9f75844SAndroid Build Coastguard Worker 
receiving() const481*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::receiving() const {
482*d9f75844SAndroid Build Coastguard Worker   return receiving_;
483*d9f75844SAndroid Build Coastguard Worker }
484*d9f75844SAndroid Build Coastguard Worker 
writable() const485*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::writable() const {
486*d9f75844SAndroid Build Coastguard Worker   return writable_;
487*d9f75844SAndroid Build Coastguard Worker }
488*d9f75844SAndroid Build Coastguard Worker 
GetError()489*d9f75844SAndroid Build Coastguard Worker int DtlsTransport::GetError() {
490*d9f75844SAndroid Build Coastguard Worker   return ice_transport_->GetError();
491*d9f75844SAndroid Build Coastguard Worker }
492*d9f75844SAndroid Build Coastguard Worker 
network_route() const493*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::NetworkRoute> DtlsTransport::network_route() const {
494*d9f75844SAndroid Build Coastguard Worker   return ice_transport_->network_route();
495*d9f75844SAndroid Build Coastguard Worker }
496*d9f75844SAndroid Build Coastguard Worker 
GetOption(rtc::Socket::Option opt,int * value)497*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::GetOption(rtc::Socket::Option opt, int* value) {
498*d9f75844SAndroid Build Coastguard Worker   return ice_transport_->GetOption(opt, value);
499*d9f75844SAndroid Build Coastguard Worker }
500*d9f75844SAndroid Build Coastguard Worker 
SetOption(rtc::Socket::Option opt,int value)501*d9f75844SAndroid Build Coastguard Worker int DtlsTransport::SetOption(rtc::Socket::Option opt, int value) {
502*d9f75844SAndroid Build Coastguard Worker   return ice_transport_->SetOption(opt, value);
503*d9f75844SAndroid Build Coastguard Worker }
504*d9f75844SAndroid Build Coastguard Worker 
ConnectToIceTransport()505*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::ConnectToIceTransport() {
506*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ice_transport_);
507*d9f75844SAndroid Build Coastguard Worker   ice_transport_->SignalWritableState.connect(this,
508*d9f75844SAndroid Build Coastguard Worker                                               &DtlsTransport::OnWritableState);
509*d9f75844SAndroid Build Coastguard Worker   ice_transport_->SignalReadPacket.connect(this, &DtlsTransport::OnReadPacket);
510*d9f75844SAndroid Build Coastguard Worker   ice_transport_->SignalSentPacket.connect(this, &DtlsTransport::OnSentPacket);
511*d9f75844SAndroid Build Coastguard Worker   ice_transport_->SignalReadyToSend.connect(this,
512*d9f75844SAndroid Build Coastguard Worker                                             &DtlsTransport::OnReadyToSend);
513*d9f75844SAndroid Build Coastguard Worker   ice_transport_->SignalReceivingState.connect(
514*d9f75844SAndroid Build Coastguard Worker       this, &DtlsTransport::OnReceivingState);
515*d9f75844SAndroid Build Coastguard Worker   ice_transport_->SignalNetworkRouteChanged.connect(
516*d9f75844SAndroid Build Coastguard Worker       this, &DtlsTransport::OnNetworkRouteChanged);
517*d9f75844SAndroid Build Coastguard Worker }
518*d9f75844SAndroid Build Coastguard Worker 
519*d9f75844SAndroid Build Coastguard Worker // The state transition logic here is as follows:
520*d9f75844SAndroid Build Coastguard Worker // (1) If we're not doing DTLS-SRTP, then the state is just the
521*d9f75844SAndroid Build Coastguard Worker //     state of the underlying impl()
522*d9f75844SAndroid Build Coastguard Worker // (2) If we're doing DTLS-SRTP:
523*d9f75844SAndroid Build Coastguard Worker //     - Prior to the DTLS handshake, the state is neither receiving nor
524*d9f75844SAndroid Build Coastguard Worker //       writable
525*d9f75844SAndroid Build Coastguard Worker //     - When the impl goes writable for the first time we
526*d9f75844SAndroid Build Coastguard Worker //       start the DTLS handshake
527*d9f75844SAndroid Build Coastguard Worker //     - Once the DTLS handshake completes, the state is that of the
528*d9f75844SAndroid Build Coastguard Worker //       impl again
OnWritableState(rtc::PacketTransportInternal * transport)529*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnWritableState(rtc::PacketTransportInternal* transport) {
530*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&thread_checker_);
531*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(transport == ice_transport_);
532*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_VERBOSE) << ToString()
533*d9f75844SAndroid Build Coastguard Worker                       << ": ice_transport writable state changed to "
534*d9f75844SAndroid Build Coastguard Worker                       << ice_transport_->writable();
535*d9f75844SAndroid Build Coastguard Worker 
536*d9f75844SAndroid Build Coastguard Worker   if (!dtls_active_) {
537*d9f75844SAndroid Build Coastguard Worker     // Not doing DTLS.
538*d9f75844SAndroid Build Coastguard Worker     // Note: SignalWritableState fired by set_writable.
539*d9f75844SAndroid Build Coastguard Worker     set_writable(ice_transport_->writable());
540*d9f75844SAndroid Build Coastguard Worker     return;
541*d9f75844SAndroid Build Coastguard Worker   }
542*d9f75844SAndroid Build Coastguard Worker 
543*d9f75844SAndroid Build Coastguard Worker   switch (dtls_state()) {
544*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kNew:
545*d9f75844SAndroid Build Coastguard Worker       MaybeStartDtls();
546*d9f75844SAndroid Build Coastguard Worker       break;
547*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kConnected:
548*d9f75844SAndroid Build Coastguard Worker       // Note: SignalWritableState fired by set_writable.
549*d9f75844SAndroid Build Coastguard Worker       set_writable(ice_transport_->writable());
550*d9f75844SAndroid Build Coastguard Worker       break;
551*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kConnecting:
552*d9f75844SAndroid Build Coastguard Worker       // Do nothing.
553*d9f75844SAndroid Build Coastguard Worker       break;
554*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kFailed:
555*d9f75844SAndroid Build Coastguard Worker       // Should not happen. Do nothing.
556*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
557*d9f75844SAndroid Build Coastguard Worker                         << ": OnWritableState() called in state "
558*d9f75844SAndroid Build Coastguard Worker                            "webrtc::DtlsTransportState::kFailed.";
559*d9f75844SAndroid Build Coastguard Worker       break;
560*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kClosed:
561*d9f75844SAndroid Build Coastguard Worker       // Should not happen. Do nothing.
562*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
563*d9f75844SAndroid Build Coastguard Worker                         << ": OnWritableState() called in state "
564*d9f75844SAndroid Build Coastguard Worker                            "webrtc::DtlsTransportState::kClosed.";
565*d9f75844SAndroid Build Coastguard Worker       break;
566*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kNumValues:
567*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
568*d9f75844SAndroid Build Coastguard Worker       break;
569*d9f75844SAndroid Build Coastguard Worker   }
570*d9f75844SAndroid Build Coastguard Worker }
571*d9f75844SAndroid Build Coastguard Worker 
OnReceivingState(rtc::PacketTransportInternal * transport)572*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnReceivingState(rtc::PacketTransportInternal* transport) {
573*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&thread_checker_);
574*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(transport == ice_transport_);
575*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_VERBOSE) << ToString()
576*d9f75844SAndroid Build Coastguard Worker                       << ": ice_transport "
577*d9f75844SAndroid Build Coastguard Worker                          "receiving state changed to "
578*d9f75844SAndroid Build Coastguard Worker                       << ice_transport_->receiving();
579*d9f75844SAndroid Build Coastguard Worker   if (!dtls_active_ || dtls_state() == webrtc::DtlsTransportState::kConnected) {
580*d9f75844SAndroid Build Coastguard Worker     // Note: SignalReceivingState fired by set_receiving.
581*d9f75844SAndroid Build Coastguard Worker     set_receiving(ice_transport_->receiving());
582*d9f75844SAndroid Build Coastguard Worker   }
583*d9f75844SAndroid Build Coastguard Worker }
584*d9f75844SAndroid Build Coastguard Worker 
OnReadPacket(rtc::PacketTransportInternal * transport,const char * data,size_t size,const int64_t & packet_time_us,int flags)585*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
586*d9f75844SAndroid Build Coastguard Worker                                  const char* data,
587*d9f75844SAndroid Build Coastguard Worker                                  size_t size,
588*d9f75844SAndroid Build Coastguard Worker                                  const int64_t& packet_time_us,
589*d9f75844SAndroid Build Coastguard Worker                                  int flags) {
590*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&thread_checker_);
591*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(transport == ice_transport_);
592*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(flags == 0);
593*d9f75844SAndroid Build Coastguard Worker 
594*d9f75844SAndroid Build Coastguard Worker   if (!dtls_active_) {
595*d9f75844SAndroid Build Coastguard Worker     // Not doing DTLS.
596*d9f75844SAndroid Build Coastguard Worker     SignalReadPacket(this, data, size, packet_time_us, 0);
597*d9f75844SAndroid Build Coastguard Worker     return;
598*d9f75844SAndroid Build Coastguard Worker   }
599*d9f75844SAndroid Build Coastguard Worker 
600*d9f75844SAndroid Build Coastguard Worker   switch (dtls_state()) {
601*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kNew:
602*d9f75844SAndroid Build Coastguard Worker       if (dtls_) {
603*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << ToString()
604*d9f75844SAndroid Build Coastguard Worker                          << ": Packet received before DTLS started.";
605*d9f75844SAndroid Build Coastguard Worker       } else {
606*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING) << ToString()
607*d9f75844SAndroid Build Coastguard Worker                             << ": Packet received before we know if we are "
608*d9f75844SAndroid Build Coastguard Worker                                "doing DTLS or not.";
609*d9f75844SAndroid Build Coastguard Worker       }
610*d9f75844SAndroid Build Coastguard Worker       // Cache a client hello packet received before DTLS has actually started.
611*d9f75844SAndroid Build Coastguard Worker       if (IsDtlsClientHelloPacket(data, size)) {
612*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << ToString()
613*d9f75844SAndroid Build Coastguard Worker                          << ": Caching DTLS ClientHello packet until DTLS is "
614*d9f75844SAndroid Build Coastguard Worker                             "started.";
615*d9f75844SAndroid Build Coastguard Worker         cached_client_hello_.SetData(data, size);
616*d9f75844SAndroid Build Coastguard Worker         // If we haven't started setting up DTLS yet (because we don't have a
617*d9f75844SAndroid Build Coastguard Worker         // remote fingerprint/role), we can use the client hello as a clue that
618*d9f75844SAndroid Build Coastguard Worker         // the peer has chosen the client role, and proceed with the handshake.
619*d9f75844SAndroid Build Coastguard Worker         // The fingerprint will be verified when it's set.
620*d9f75844SAndroid Build Coastguard Worker         if (!dtls_ && local_certificate_) {
621*d9f75844SAndroid Build Coastguard Worker           SetDtlsRole(rtc::SSL_SERVER);
622*d9f75844SAndroid Build Coastguard Worker           SetupDtls();
623*d9f75844SAndroid Build Coastguard Worker         }
624*d9f75844SAndroid Build Coastguard Worker       } else {
625*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << ToString()
626*d9f75844SAndroid Build Coastguard Worker                          << ": Not a DTLS ClientHello packet; dropping.";
627*d9f75844SAndroid Build Coastguard Worker       }
628*d9f75844SAndroid Build Coastguard Worker       break;
629*d9f75844SAndroid Build Coastguard Worker 
630*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kConnecting:
631*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kConnected:
632*d9f75844SAndroid Build Coastguard Worker       // We should only get DTLS or SRTP packets; STUN's already been demuxed.
633*d9f75844SAndroid Build Coastguard Worker       // Is this potentially a DTLS packet?
634*d9f75844SAndroid Build Coastguard Worker       if (IsDtlsPacket(data, size)) {
635*d9f75844SAndroid Build Coastguard Worker         if (!HandleDtlsPacket(data, size)) {
636*d9f75844SAndroid Build Coastguard Worker           RTC_LOG(LS_ERROR) << ToString() << ": Failed to handle DTLS packet.";
637*d9f75844SAndroid Build Coastguard Worker           return;
638*d9f75844SAndroid Build Coastguard Worker         }
639*d9f75844SAndroid Build Coastguard Worker       } else {
640*d9f75844SAndroid Build Coastguard Worker         // Not a DTLS packet; our handshake should be complete by now.
641*d9f75844SAndroid Build Coastguard Worker         if (dtls_state() != webrtc::DtlsTransportState::kConnected) {
642*d9f75844SAndroid Build Coastguard Worker           RTC_LOG(LS_ERROR) << ToString()
643*d9f75844SAndroid Build Coastguard Worker                             << ": Received non-DTLS packet before DTLS "
644*d9f75844SAndroid Build Coastguard Worker                                "complete.";
645*d9f75844SAndroid Build Coastguard Worker           return;
646*d9f75844SAndroid Build Coastguard Worker         }
647*d9f75844SAndroid Build Coastguard Worker 
648*d9f75844SAndroid Build Coastguard Worker         // And it had better be a SRTP packet.
649*d9f75844SAndroid Build Coastguard Worker         if (!IsRtpPacket(data, size)) {
650*d9f75844SAndroid Build Coastguard Worker           RTC_LOG(LS_ERROR)
651*d9f75844SAndroid Build Coastguard Worker               << ToString() << ": Received unexpected non-DTLS packet.";
652*d9f75844SAndroid Build Coastguard Worker           return;
653*d9f75844SAndroid Build Coastguard Worker         }
654*d9f75844SAndroid Build Coastguard Worker 
655*d9f75844SAndroid Build Coastguard Worker         // Sanity check.
656*d9f75844SAndroid Build Coastguard Worker         RTC_DCHECK(!srtp_ciphers_.empty());
657*d9f75844SAndroid Build Coastguard Worker 
658*d9f75844SAndroid Build Coastguard Worker         // Signal this upwards as a bypass packet.
659*d9f75844SAndroid Build Coastguard Worker         SignalReadPacket(this, data, size, packet_time_us, PF_SRTP_BYPASS);
660*d9f75844SAndroid Build Coastguard Worker       }
661*d9f75844SAndroid Build Coastguard Worker       break;
662*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kFailed:
663*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kClosed:
664*d9f75844SAndroid Build Coastguard Worker     case webrtc::DtlsTransportState::kNumValues:
665*d9f75844SAndroid Build Coastguard Worker       // This shouldn't be happening. Drop the packet.
666*d9f75844SAndroid Build Coastguard Worker       break;
667*d9f75844SAndroid Build Coastguard Worker   }
668*d9f75844SAndroid Build Coastguard Worker }
669*d9f75844SAndroid Build Coastguard Worker 
OnSentPacket(rtc::PacketTransportInternal * transport,const rtc::SentPacket & sent_packet)670*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnSentPacket(rtc::PacketTransportInternal* transport,
671*d9f75844SAndroid Build Coastguard Worker                                  const rtc::SentPacket& sent_packet) {
672*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&thread_checker_);
673*d9f75844SAndroid Build Coastguard Worker   SignalSentPacket(this, sent_packet);
674*d9f75844SAndroid Build Coastguard Worker }
675*d9f75844SAndroid Build Coastguard Worker 
OnReadyToSend(rtc::PacketTransportInternal * transport)676*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
677*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&thread_checker_);
678*d9f75844SAndroid Build Coastguard Worker   if (writable()) {
679*d9f75844SAndroid Build Coastguard Worker     SignalReadyToSend(this);
680*d9f75844SAndroid Build Coastguard Worker   }
681*d9f75844SAndroid Build Coastguard Worker }
682*d9f75844SAndroid Build Coastguard Worker 
OnDtlsEvent(rtc::StreamInterface * dtls,int sig,int err)683*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnDtlsEvent(rtc::StreamInterface* dtls, int sig, int err) {
684*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&thread_checker_);
685*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(dtls == dtls_.get());
686*d9f75844SAndroid Build Coastguard Worker   if (sig & rtc::SE_OPEN) {
687*d9f75844SAndroid Build Coastguard Worker     // This is the first time.
688*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString() << ": DTLS handshake complete.";
689*d9f75844SAndroid Build Coastguard Worker     if (dtls_->GetState() == rtc::SS_OPEN) {
690*d9f75844SAndroid Build Coastguard Worker       // The check for OPEN shouldn't be necessary but let's make
691*d9f75844SAndroid Build Coastguard Worker       // sure we don't accidentally frob the state if it's closed.
692*d9f75844SAndroid Build Coastguard Worker       set_dtls_state(webrtc::DtlsTransportState::kConnected);
693*d9f75844SAndroid Build Coastguard Worker       set_writable(true);
694*d9f75844SAndroid Build Coastguard Worker     }
695*d9f75844SAndroid Build Coastguard Worker   }
696*d9f75844SAndroid Build Coastguard Worker   if (sig & rtc::SE_READ) {
697*d9f75844SAndroid Build Coastguard Worker     uint8_t buf[kMaxDtlsPacketLen];
698*d9f75844SAndroid Build Coastguard Worker     size_t read;
699*d9f75844SAndroid Build Coastguard Worker     int read_error;
700*d9f75844SAndroid Build Coastguard Worker     rtc::StreamResult ret;
701*d9f75844SAndroid Build Coastguard Worker     // The underlying DTLS stream may have received multiple DTLS records in
702*d9f75844SAndroid Build Coastguard Worker     // one packet, so read all of them.
703*d9f75844SAndroid Build Coastguard Worker     do {
704*d9f75844SAndroid Build Coastguard Worker       ret = dtls_->Read(buf, read, read_error);
705*d9f75844SAndroid Build Coastguard Worker       if (ret == rtc::SR_SUCCESS) {
706*d9f75844SAndroid Build Coastguard Worker         SignalReadPacket(this, reinterpret_cast<const char*>(buf), read,
707*d9f75844SAndroid Build Coastguard Worker                          rtc::TimeMicros(), 0);
708*d9f75844SAndroid Build Coastguard Worker       } else if (ret == rtc::SR_EOS) {
709*d9f75844SAndroid Build Coastguard Worker         // Remote peer shut down the association with no error.
710*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << ToString() << ": DTLS transport closed by remote";
711*d9f75844SAndroid Build Coastguard Worker         set_writable(false);
712*d9f75844SAndroid Build Coastguard Worker         set_dtls_state(webrtc::DtlsTransportState::kClosed);
713*d9f75844SAndroid Build Coastguard Worker         SignalClosed(this);
714*d9f75844SAndroid Build Coastguard Worker       } else if (ret == rtc::SR_ERROR) {
715*d9f75844SAndroid Build Coastguard Worker         // Remote peer shut down the association with an error.
716*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO)
717*d9f75844SAndroid Build Coastguard Worker             << ToString()
718*d9f75844SAndroid Build Coastguard Worker             << ": Closed by remote with DTLS transport error, code="
719*d9f75844SAndroid Build Coastguard Worker             << read_error;
720*d9f75844SAndroid Build Coastguard Worker         set_writable(false);
721*d9f75844SAndroid Build Coastguard Worker         set_dtls_state(webrtc::DtlsTransportState::kFailed);
722*d9f75844SAndroid Build Coastguard Worker         SignalClosed(this);
723*d9f75844SAndroid Build Coastguard Worker       }
724*d9f75844SAndroid Build Coastguard Worker     } while (ret == rtc::SR_SUCCESS);
725*d9f75844SAndroid Build Coastguard Worker   }
726*d9f75844SAndroid Build Coastguard Worker   if (sig & rtc::SE_CLOSE) {
727*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(sig == rtc::SE_CLOSE);  // SE_CLOSE should be by itself.
728*d9f75844SAndroid Build Coastguard Worker     set_writable(false);
729*d9f75844SAndroid Build Coastguard Worker     if (!err) {
730*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << ToString() << ": DTLS transport closed";
731*d9f75844SAndroid Build Coastguard Worker       set_dtls_state(webrtc::DtlsTransportState::kClosed);
732*d9f75844SAndroid Build Coastguard Worker     } else {
733*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << ToString() << ": DTLS transport error, code=" << err;
734*d9f75844SAndroid Build Coastguard Worker       set_dtls_state(webrtc::DtlsTransportState::kFailed);
735*d9f75844SAndroid Build Coastguard Worker     }
736*d9f75844SAndroid Build Coastguard Worker   }
737*d9f75844SAndroid Build Coastguard Worker }
738*d9f75844SAndroid Build Coastguard Worker 
OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route)739*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnNetworkRouteChanged(
740*d9f75844SAndroid Build Coastguard Worker     absl::optional<rtc::NetworkRoute> network_route) {
741*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(&thread_checker_);
742*d9f75844SAndroid Build Coastguard Worker   SignalNetworkRouteChanged(network_route);
743*d9f75844SAndroid Build Coastguard Worker }
744*d9f75844SAndroid Build Coastguard Worker 
MaybeStartDtls()745*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::MaybeStartDtls() {
746*d9f75844SAndroid Build Coastguard Worker   if (dtls_ && ice_transport_->writable()) {
747*d9f75844SAndroid Build Coastguard Worker     ConfigureHandshakeTimeout();
748*d9f75844SAndroid Build Coastguard Worker 
749*d9f75844SAndroid Build Coastguard Worker     if (dtls_->StartSSL()) {
750*d9f75844SAndroid Build Coastguard Worker       // This should never fail:
751*d9f75844SAndroid Build Coastguard Worker       // Because we are operating in a nonblocking mode and all
752*d9f75844SAndroid Build Coastguard Worker       // incoming packets come in via OnReadPacket(), which rejects
753*d9f75844SAndroid Build Coastguard Worker       // packets in this state, the incoming queue must be empty. We
754*d9f75844SAndroid Build Coastguard Worker       // ignore write errors, thus any errors must be because of
755*d9f75844SAndroid Build Coastguard Worker       // configuration and therefore are our fault.
756*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED() << "StartSSL failed.";
757*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString() << ": Couldn't start DTLS handshake";
758*d9f75844SAndroid Build Coastguard Worker       set_dtls_state(webrtc::DtlsTransportState::kFailed);
759*d9f75844SAndroid Build Coastguard Worker       return;
760*d9f75844SAndroid Build Coastguard Worker     }
761*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString() << ": DtlsTransport: Started DTLS handshake";
762*d9f75844SAndroid Build Coastguard Worker     set_dtls_state(webrtc::DtlsTransportState::kConnecting);
763*d9f75844SAndroid Build Coastguard Worker     // Now that the handshake has started, we can process a cached ClientHello
764*d9f75844SAndroid Build Coastguard Worker     // (if one exists).
765*d9f75844SAndroid Build Coastguard Worker     if (cached_client_hello_.size()) {
766*d9f75844SAndroid Build Coastguard Worker       if (*dtls_role_ == rtc::SSL_SERVER) {
767*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_INFO) << ToString()
768*d9f75844SAndroid Build Coastguard Worker                          << ": Handling cached DTLS ClientHello packet.";
769*d9f75844SAndroid Build Coastguard Worker         if (!HandleDtlsPacket(cached_client_hello_.data<char>(),
770*d9f75844SAndroid Build Coastguard Worker                               cached_client_hello_.size())) {
771*d9f75844SAndroid Build Coastguard Worker           RTC_LOG(LS_ERROR) << ToString() << ": Failed to handle DTLS packet.";
772*d9f75844SAndroid Build Coastguard Worker         }
773*d9f75844SAndroid Build Coastguard Worker       } else {
774*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING) << ToString()
775*d9f75844SAndroid Build Coastguard Worker                             << ": Discarding cached DTLS ClientHello packet "
776*d9f75844SAndroid Build Coastguard Worker                                "because we don't have the server role.";
777*d9f75844SAndroid Build Coastguard Worker       }
778*d9f75844SAndroid Build Coastguard Worker       cached_client_hello_.Clear();
779*d9f75844SAndroid Build Coastguard Worker     }
780*d9f75844SAndroid Build Coastguard Worker   }
781*d9f75844SAndroid Build Coastguard Worker }
782*d9f75844SAndroid Build Coastguard Worker 
783*d9f75844SAndroid Build Coastguard Worker // Called from OnReadPacket when a DTLS packet is received.
HandleDtlsPacket(const char * data,size_t size)784*d9f75844SAndroid Build Coastguard Worker bool DtlsTransport::HandleDtlsPacket(const char* data, size_t size) {
785*d9f75844SAndroid Build Coastguard Worker   // Sanity check we're not passing junk that
786*d9f75844SAndroid Build Coastguard Worker   // just looks like DTLS.
787*d9f75844SAndroid Build Coastguard Worker   const uint8_t* tmp_data = reinterpret_cast<const uint8_t*>(data);
788*d9f75844SAndroid Build Coastguard Worker   size_t tmp_size = size;
789*d9f75844SAndroid Build Coastguard Worker   while (tmp_size > 0) {
790*d9f75844SAndroid Build Coastguard Worker     if (tmp_size < kDtlsRecordHeaderLen)
791*d9f75844SAndroid Build Coastguard Worker       return false;  // Too short for the header
792*d9f75844SAndroid Build Coastguard Worker 
793*d9f75844SAndroid Build Coastguard Worker     size_t record_len = (tmp_data[11] << 8) | (tmp_data[12]);
794*d9f75844SAndroid Build Coastguard Worker     if ((record_len + kDtlsRecordHeaderLen) > tmp_size)
795*d9f75844SAndroid Build Coastguard Worker       return false;  // Body too short
796*d9f75844SAndroid Build Coastguard Worker 
797*d9f75844SAndroid Build Coastguard Worker     tmp_data += record_len + kDtlsRecordHeaderLen;
798*d9f75844SAndroid Build Coastguard Worker     tmp_size -= record_len + kDtlsRecordHeaderLen;
799*d9f75844SAndroid Build Coastguard Worker   }
800*d9f75844SAndroid Build Coastguard Worker 
801*d9f75844SAndroid Build Coastguard Worker   // Looks good. Pass to the SIC which ends up being passed to
802*d9f75844SAndroid Build Coastguard Worker   // the DTLS stack.
803*d9f75844SAndroid Build Coastguard Worker   return downward_->OnPacketReceived(data, size);
804*d9f75844SAndroid Build Coastguard Worker }
805*d9f75844SAndroid Build Coastguard Worker 
set_receiving(bool receiving)806*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::set_receiving(bool receiving) {
807*d9f75844SAndroid Build Coastguard Worker   if (receiving_ == receiving) {
808*d9f75844SAndroid Build Coastguard Worker     return;
809*d9f75844SAndroid Build Coastguard Worker   }
810*d9f75844SAndroid Build Coastguard Worker   receiving_ = receiving;
811*d9f75844SAndroid Build Coastguard Worker   SignalReceivingState(this);
812*d9f75844SAndroid Build Coastguard Worker }
813*d9f75844SAndroid Build Coastguard Worker 
set_writable(bool writable)814*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::set_writable(bool writable) {
815*d9f75844SAndroid Build Coastguard Worker   if (writable_ == writable) {
816*d9f75844SAndroid Build Coastguard Worker     return;
817*d9f75844SAndroid Build Coastguard Worker   }
818*d9f75844SAndroid Build Coastguard Worker   if (event_log_) {
819*d9f75844SAndroid Build Coastguard Worker     event_log_->Log(
820*d9f75844SAndroid Build Coastguard Worker         std::make_unique<webrtc::RtcEventDtlsWritableState>(writable));
821*d9f75844SAndroid Build Coastguard Worker   }
822*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_VERBOSE) << ToString() << ": set_writable to: " << writable;
823*d9f75844SAndroid Build Coastguard Worker   writable_ = writable;
824*d9f75844SAndroid Build Coastguard Worker   if (writable_) {
825*d9f75844SAndroid Build Coastguard Worker     SignalReadyToSend(this);
826*d9f75844SAndroid Build Coastguard Worker   }
827*d9f75844SAndroid Build Coastguard Worker   SignalWritableState(this);
828*d9f75844SAndroid Build Coastguard Worker }
829*d9f75844SAndroid Build Coastguard Worker 
set_dtls_state(webrtc::DtlsTransportState state)830*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::set_dtls_state(webrtc::DtlsTransportState state) {
831*d9f75844SAndroid Build Coastguard Worker   if (dtls_state_ == state) {
832*d9f75844SAndroid Build Coastguard Worker     return;
833*d9f75844SAndroid Build Coastguard Worker   }
834*d9f75844SAndroid Build Coastguard Worker   if (event_log_) {
835*d9f75844SAndroid Build Coastguard Worker     event_log_->Log(
836*d9f75844SAndroid Build Coastguard Worker         std::make_unique<webrtc::RtcEventDtlsTransportState>(state));
837*d9f75844SAndroid Build Coastguard Worker   }
838*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_VERBOSE) << ToString() << ": set_dtls_state from:"
839*d9f75844SAndroid Build Coastguard Worker                       << static_cast<int>(dtls_state_) << " to "
840*d9f75844SAndroid Build Coastguard Worker                       << static_cast<int>(state);
841*d9f75844SAndroid Build Coastguard Worker   dtls_state_ = state;
842*d9f75844SAndroid Build Coastguard Worker   SendDtlsState(this, state);
843*d9f75844SAndroid Build Coastguard Worker }
844*d9f75844SAndroid Build Coastguard Worker 
OnDtlsHandshakeError(rtc::SSLHandshakeError error)845*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
846*d9f75844SAndroid Build Coastguard Worker   SendDtlsHandshakeError(error);
847*d9f75844SAndroid Build Coastguard Worker }
848*d9f75844SAndroid Build Coastguard Worker 
ConfigureHandshakeTimeout()849*d9f75844SAndroid Build Coastguard Worker void DtlsTransport::ConfigureHandshakeTimeout() {
850*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(dtls_);
851*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> rtt = ice_transport_->GetRttEstimate();
852*d9f75844SAndroid Build Coastguard Worker   if (rtt) {
853*d9f75844SAndroid Build Coastguard Worker     // Limit the timeout to a reasonable range in case the ICE RTT takes
854*d9f75844SAndroid Build Coastguard Worker     // extreme values.
855*d9f75844SAndroid Build Coastguard Worker     int initial_timeout = std::max(kMinHandshakeTimeout,
856*d9f75844SAndroid Build Coastguard Worker                                    std::min(kMaxHandshakeTimeout, 2 * (*rtt)));
857*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << ToString() << ": configuring DTLS handshake timeout "
858*d9f75844SAndroid Build Coastguard Worker                      << initial_timeout << " based on ICE RTT " << *rtt;
859*d9f75844SAndroid Build Coastguard Worker 
860*d9f75844SAndroid Build Coastguard Worker     dtls_->SetInitialRetransmissionTimeout(initial_timeout);
861*d9f75844SAndroid Build Coastguard Worker   } else {
862*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO)
863*d9f75844SAndroid Build Coastguard Worker         << ToString()
864*d9f75844SAndroid Build Coastguard Worker         << ": no RTT estimate - using default DTLS handshake timeout";
865*d9f75844SAndroid Build Coastguard Worker   }
866*d9f75844SAndroid Build Coastguard Worker }
867*d9f75844SAndroid Build Coastguard Worker 
868*d9f75844SAndroid Build Coastguard Worker }  // namespace cricket
869