blob: 46f0f9952015963658b5d37138838d2384620a12 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2011 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
zhihuangca6d3b62017-08-23 18:05:50 -070011#include <algorithm>
jbauch555604a2016-04-26 03:13:22 -070012#include <memory>
kwiberg0eb15ed2015-12-17 03:04:15 -080013#include <utility>
14
Steve Anton10542f22019-01-11 09:11:00 -080015#include "p2p/base/dtls_transport.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000016
Zach Steinc64078f2018-11-27 15:53:01 -080017#include "absl/memory/memory.h"
18#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
Zach Stein846dfdf2018-11-29 14:12:17 -080019#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
Zach Steinc64078f2018-11-27 15:53:01 -080020#include "logging/rtc_event_log/rtc_event_log.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "p2p/base/packet_transport_internal.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "rtc_base/buffer.h"
23#include "rtc_base/checks.h"
24#include "rtc_base/dscp.h"
Jonas Olssond7d762d2018-03-28 09:47:51 +020025#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/message_queue.h"
27#include "rtc_base/rtc_certificate.h"
28#include "rtc_base/ssl_stream_adapter.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "rtc_base/stream.h"
30#include "rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000031
32namespace cricket {
33
34// We don't pull the RTP constants from rtputils.h, to avoid a layer violation.
35static const size_t kDtlsRecordHeaderLen = 13;
36static const size_t kMaxDtlsPacketLen = 2048;
37static const size_t kMinRtpPacketLen = 12;
38
Joachim Bauch6f2ef742015-05-21 17:52:01 +020039// Maximum number of pending packets in the queue. Packets are read immediately
40// after they have been written, so a capacity of "1" is sufficient.
41static const size_t kMaxPendingPackets = 1;
42
skvladd0309122017-02-02 17:18:37 -080043// Minimum and maximum values for the initial DTLS handshake timeout. We'll pick
44// an initial timeout based on ICE RTT estimates, but clamp it to this range.
45static const int kMinHandshakeTimeout = 50;
46static const int kMaxHandshakeTimeout = 3000;
47
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000048static bool IsDtlsPacket(const char* data, size_t len) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020049 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000050 return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
51}
deadbeefe84cd2e2016-05-04 17:16:34 -070052static bool IsDtlsClientHelloPacket(const char* data, size_t len) {
53 if (!IsDtlsPacket(data, len)) {
54 return false;
55 }
56 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
57 return len > 17 && u[0] == 22 && u[13] == 1;
58}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000059static bool IsRtpPacket(const char* data, size_t len) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020060 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000061 return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
62}
63
zhihuangb2cdd932017-01-19 16:54:25 -080064StreamInterfaceChannel::StreamInterfaceChannel(
65 IceTransportInternal* ice_transport)
66 : ice_transport_(ice_transport),
Joachim Bauch6f2ef742015-05-21 17:52:01 +020067 state_(rtc::SS_OPEN),
zhihuangd06adf62017-01-12 15:58:31 -080068 packets_(kMaxPendingPackets, kMaxDtlsPacketLen) {}
Joachim Bauch6f2ef742015-05-21 17:52:01 +020069
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000070rtc::StreamResult StreamInterfaceChannel::Read(void* buffer,
zhihuangca6d3b62017-08-23 18:05:50 -070071 size_t buffer_len,
72 size_t* read,
73 int* error) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000074 if (state_ == rtc::SS_CLOSED)
75 return rtc::SR_EOS;
76 if (state_ == rtc::SS_OPENING)
77 return rtc::SR_BLOCK;
78
Joachim Bauch6f2ef742015-05-21 17:52:01 +020079 if (!packets_.ReadFront(buffer, buffer_len, read)) {
80 return rtc::SR_BLOCK;
81 }
82
83 return rtc::SR_SUCCESS;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000084}
85
86rtc::StreamResult StreamInterfaceChannel::Write(const void* data,
zhihuangca6d3b62017-08-23 18:05:50 -070087 size_t data_len,
88 size_t* written,
89 int* error) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000090 // Always succeeds, since this is an unreliable transport anyway.
zhihuangb2cdd932017-01-19 16:54:25 -080091 // TODO(zhihuang): Should this block if ice_transport_'s temporarily
92 // unwritable?
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000093 rtc::PacketOptions packet_options;
zhihuangb2cdd932017-01-19 16:54:25 -080094 ice_transport_->SendPacket(static_cast<const char*>(data), data_len,
95 packet_options);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000096 if (written) {
97 *written = data_len;
98 }
99 return rtc::SR_SUCCESS;
100}
101
102bool StreamInterfaceChannel::OnPacketReceived(const char* data, size_t size) {
Joachim Bauch6f2ef742015-05-21 17:52:01 +0200103 // We force a read event here to ensure that we don't overflow our queue.
104 bool ret = packets_.WriteBack(data, size, NULL);
henrikg91d6ede2015-09-17 00:24:34 -0700105 RTC_CHECK(ret) << "Failed to write packet to queue.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000106 if (ret) {
107 SignalEvent(this, rtc::SE_READ, 0);
108 }
109 return ret;
110}
111
Steve Anton33f69db2017-10-30 10:01:15 -0700112rtc::StreamState StreamInterfaceChannel::GetState() const {
113 return state_;
114}
115
guoweis4cc9f982016-02-24 11:10:06 -0800116void StreamInterfaceChannel::Close() {
117 packets_.Clear();
118 state_ = rtc::SS_CLOSED;
119}
120
Zhi Huange818b6e2018-02-22 15:26:27 -0800121DtlsTransport::DtlsTransport(
122 std::unique_ptr<IceTransportInternal> ice_transport,
Zach Steinc64078f2018-11-27 15:53:01 -0800123 const webrtc::CryptoOptions& crypto_options,
124 webrtc::RtcEventLog* event_log)
Zhi Huange818b6e2018-02-22 15:26:27 -0800125 : transport_name_(ice_transport->transport_name()),
126 component_(ice_transport->component()),
Harald Alvestrand00dfe932018-11-22 11:34:47 +0100127 ice_transport_(std::move(ice_transport)),
Zhi Huange818b6e2018-02-22 15:26:27 -0800128 downward_(NULL),
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700129 srtp_ciphers_(crypto_options.GetSupportedDtlsSrtpCryptoSuites()),
Zhi Huange818b6e2018-02-22 15:26:27 -0800130 ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_12),
Zach Steinc64078f2018-11-27 15:53:01 -0800131 crypto_options_(crypto_options),
132 event_log_(event_log) {
Harald Alvestrand00dfe932018-11-22 11:34:47 +0100133 RTC_DCHECK(ice_transport_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800134 ConnectToIceTransport();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000135}
136
Steve Anton33f69db2017-10-30 10:01:15 -0700137DtlsTransport::~DtlsTransport() = default;
138
Benjamin Wrighta54daf12018-10-11 15:33:17 -0700139const webrtc::CryptoOptions& DtlsTransport::crypto_options() const {
Steve Anton33f69db2017-10-30 10:01:15 -0700140 return crypto_options_;
141}
142
143DtlsTransportState DtlsTransport::dtls_state() const {
144 return dtls_state_;
145}
146
147const std::string& DtlsTransport::transport_name() const {
148 return transport_name_;
149}
150
151int DtlsTransport::component() const {
152 return component_;
153}
154
155bool DtlsTransport::IsDtlsActive() const {
156 return dtls_active_;
157}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000158
zhihuangb2cdd932017-01-19 16:54:25 -0800159bool DtlsTransport::SetLocalCertificate(
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200160 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
deadbeef2b558672015-10-26 17:23:29 -0700161 if (dtls_active_) {
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200162 if (certificate == local_certificate_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000163 // This may happen during renegotiation.
Yves Gerey665174f2018-06-19 15:03:05 +0200164 RTC_LOG(LS_INFO) << ToString() << ": Ignoring identical DTLS identity";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000165 return true;
166 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200167 RTC_LOG(LS_ERROR) << ToString()
168 << ": Can't change DTLS local identity in this state";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000169 return false;
170 }
171 }
172
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200173 if (certificate) {
174 local_certificate_ = certificate;
deadbeef2b558672015-10-26 17:23:29 -0700175 dtls_active_ = true;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000176 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200177 RTC_LOG(LS_INFO) << ToString()
178 << ": NULL DTLS identity supplied. Not doing DTLS";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000179 }
180
181 return true;
182}
183
zhihuangb2cdd932017-01-19 16:54:25 -0800184rtc::scoped_refptr<rtc::RTCCertificate> DtlsTransport::GetLocalCertificate()
185 const {
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200186 return local_certificate_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000187}
188
zhihuangb2cdd932017-01-19 16:54:25 -0800189bool DtlsTransport::SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) {
deadbeef2b558672015-10-26 17:23:29 -0700190 if (dtls_active_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100191 RTC_LOG(LS_ERROR) << "Not changing max. protocol version "
Jonas Olssond7d762d2018-03-28 09:47:51 +0200192 "while DTLS is negotiating";
Joachim Bauch04e5b492015-05-29 09:40:39 +0200193 return false;
Joachim Bauch831c5582015-05-20 12:48:41 +0200194 }
195
196 ssl_max_version_ = version;
Joachim Bauch04e5b492015-05-29 09:40:39 +0200197 return true;
Joachim Bauch831c5582015-05-20 12:48:41 +0200198}
199
Zhi Huange818b6e2018-02-22 15:26:27 -0800200bool DtlsTransport::SetDtlsRole(rtc::SSLRole role) {
deadbeef89824f62016-09-30 11:55:43 -0700201 if (dtls_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800202 RTC_DCHECK(dtls_role_);
203 if (*dtls_role_ != role) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100204 RTC_LOG(LS_ERROR)
205 << "SSL Role can't be reversed after the session is setup.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000206 return false;
207 }
208 return true;
209 }
210
Mirko Bonadei05cf6be2019-01-31 21:38:12 +0100211 dtls_role_ = role;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000212 return true;
213}
214
Zhi Huange818b6e2018-02-22 15:26:27 -0800215bool DtlsTransport::GetDtlsRole(rtc::SSLRole* role) const {
216 if (!dtls_role_) {
217 return false;
218 }
219 *role = *dtls_role_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000220 return true;
221}
222
zhihuangb2cdd932017-01-19 16:54:25 -0800223bool DtlsTransport::GetSslCipherSuite(int* cipher) {
deadbeef2b558672015-10-26 17:23:29 -0700224 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000225 return false;
226 }
227
Guo-wei Shieh456696a2015-09-30 21:48:54 -0700228 return dtls_->GetSslCipherSuite(cipher);
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000229}
230
zhihuangb2cdd932017-01-19 16:54:25 -0800231bool DtlsTransport::SetRemoteFingerprint(const std::string& digest_alg,
232 const uint8_t* digest,
233 size_t digest_len) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000234 rtc::Buffer remote_fingerprint_value(digest, digest_len);
235
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800236 // Once we have the local certificate, the same remote fingerprint can be set
237 // multiple times.
deadbeef2b558672015-10-26 17:23:29 -0700238 if (dtls_active_ && remote_fingerprint_value_ == remote_fingerprint_value &&
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000239 !digest_alg.empty()) {
240 // This may happen during renegotiation.
Jonas Olssond7d762d2018-03-28 09:47:51 +0200241 RTC_LOG(LS_INFO) << ToString()
242 << ": Ignoring identical remote DTLS fingerprint";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000243 return true;
244 }
245
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800246 // If the other side doesn't support DTLS, turn off |dtls_active_|.
Taylor Brandstetter74cefe12017-12-14 15:38:57 -0800247 // TODO(deadbeef): Remove this. It's dangerous, because it relies on higher
248 // level code to ensure DTLS is actually used, but there are tests that
249 // depend on it, for the case where an m= section is rejected. In that case
250 // SetRemoteFingerprint shouldn't even be called though.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000251 if (digest_alg.empty()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800252 RTC_DCHECK(!digest_len);
Yves Gerey665174f2018-06-19 15:03:05 +0200253 RTC_LOG(LS_INFO) << ToString() << ": Other side didn't support DTLS.";
deadbeef2b558672015-10-26 17:23:29 -0700254 dtls_active_ = false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000255 return true;
256 }
257
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800258 // Otherwise, we must have a local certificate before setting remote
259 // fingerprint.
260 if (!dtls_active_) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200261 RTC_LOG(LS_ERROR) << ToString()
262 << ": Can't set DTLS remote settings in this state.";
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800263 return false;
264 }
265
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000266 // At this point we know we are doing DTLS
deadbeef89824f62016-09-30 11:55:43 -0700267 bool fingerprint_changing = remote_fingerprint_value_.size() > 0u;
kwiberg0eb15ed2015-12-17 03:04:15 -0800268 remote_fingerprint_value_ = std::move(remote_fingerprint_value);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000269 remote_fingerprint_algorithm_ = digest_alg;
270
deadbeef89824f62016-09-30 11:55:43 -0700271 if (dtls_ && !fingerprint_changing) {
272 // This can occur if DTLS is set up before a remote fingerprint is
273 // received. For instance, if we set up DTLS due to receiving an early
274 // ClientHello.
275 rtc::SSLPeerCertificateDigestError err;
276 if (!dtls_->SetPeerCertificateDigest(
277 remote_fingerprint_algorithm_,
278 reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
279 remote_fingerprint_value_.size(), &err)) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200280 RTC_LOG(LS_ERROR) << ToString()
281 << ": Couldn't set DTLS certificate digest.";
deadbeef89824f62016-09-30 11:55:43 -0700282 set_dtls_state(DTLS_TRANSPORT_FAILED);
283 // If the error is "verification failed", don't return false, because
284 // this means the fingerprint was formatted correctly but didn't match
285 // the certificate from the DTLS handshake. Thus the DTLS state should go
286 // to "failed", but SetRemoteDescription shouldn't fail.
287 return err == rtc::SSLPeerCertificateDigestError::VERIFICATION_FAILED;
288 }
289 return true;
290 }
291
292 // If the fingerprint is changing, we'll tear down the DTLS association and
293 // create a new one, resetting our state.
294 if (dtls_ && fingerprint_changing) {
deadbeef367efdc2016-07-13 12:10:17 -0700295 dtls_.reset(nullptr);
296 set_dtls_state(DTLS_TRANSPORT_NEW);
297 set_writable(false);
298 }
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800299
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000300 if (!SetupDtls()) {
deadbeef2b558672015-10-26 17:23:29 -0700301 set_dtls_state(DTLS_TRANSPORT_FAILED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000302 return false;
303 }
304
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000305 return true;
306}
307
Zhi Huang70b820f2018-01-27 14:16:15 -0800308std::unique_ptr<rtc::SSLCertChain> DtlsTransport::GetRemoteSSLCertChain()
309 const {
310 if (!dtls_) {
311 return nullptr;
312 }
313
314 return dtls_->GetPeerSSLCertChain();
315}
316
Steve Anton33f69db2017-10-30 10:01:15 -0700317bool DtlsTransport::ExportKeyingMaterial(const std::string& label,
318 const uint8_t* context,
319 size_t context_len,
320 bool use_context,
321 uint8_t* result,
322 size_t result_len) {
323 return (dtls_.get())
324 ? dtls_->ExportKeyingMaterial(label, context, context_len,
325 use_context, result, result_len)
326 : false;
327}
328
zhihuangb2cdd932017-01-19 16:54:25 -0800329bool DtlsTransport::SetupDtls() {
Zhi Huange818b6e2018-02-22 15:26:27 -0800330 RTC_DCHECK(dtls_role_);
Harald Alvestrand00dfe932018-11-22 11:34:47 +0100331 StreamInterfaceChannel* downward =
332 new StreamInterfaceChannel(ice_transport_.get());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000333
334 dtls_.reset(rtc::SSLStreamAdapter::Create(downward));
335 if (!dtls_) {
Yves Gerey665174f2018-06-19 15:03:05 +0200336 RTC_LOG(LS_ERROR) << ToString() << ": Failed to create DTLS adapter.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000337 delete downward;
338 return false;
339 }
340
341 downward_ = downward;
342
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200343 dtls_->SetIdentity(local_certificate_->identity()->GetReference());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000344 dtls_->SetMode(rtc::SSL_MODE_DTLS);
Joachim Bauch831c5582015-05-20 12:48:41 +0200345 dtls_->SetMaxProtocolVersion(ssl_max_version_);
Zhi Huange818b6e2018-02-22 15:26:27 -0800346 dtls_->SetServerRole(*dtls_role_);
zhihuangb2cdd932017-01-19 16:54:25 -0800347 dtls_->SignalEvent.connect(this, &DtlsTransport::OnDtlsEvent);
348 dtls_->SignalSSLHandshakeError.connect(this,
349 &DtlsTransport::OnDtlsHandshakeError);
deadbeef89824f62016-09-30 11:55:43 -0700350 if (remote_fingerprint_value_.size() &&
351 !dtls_->SetPeerCertificateDigest(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000352 remote_fingerprint_algorithm_,
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000353 reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
deadbeef81f6f4f2016-09-19 17:20:52 -0700354 remote_fingerprint_value_.size())) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200355 RTC_LOG(LS_ERROR) << ToString()
356 << ": Couldn't set DTLS certificate digest.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000357 return false;
358 }
359
360 // Set up DTLS-SRTP, if it's been enabled.
361 if (!srtp_ciphers_.empty()) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800362 if (!dtls_->SetDtlsSrtpCryptoSuites(srtp_ciphers_)) {
Yves Gerey665174f2018-06-19 15:03:05 +0200363 RTC_LOG(LS_ERROR) << ToString() << ": Couldn't set DTLS-SRTP ciphers.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000364 return false;
365 }
366 } else {
Yves Gerey665174f2018-06-19 15:03:05 +0200367 RTC_LOG(LS_INFO) << ToString() << ": Not using DTLS-SRTP.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000368 }
369
Jonas Olssond7d762d2018-03-28 09:47:51 +0200370 RTC_LOG(LS_INFO) << ToString() << ": DTLS setup complete.";
deadbeef367efdc2016-07-13 12:10:17 -0700371
zhihuangb2cdd932017-01-19 16:54:25 -0800372 // If the underlying ice_transport is already writable at this point, we may
373 // be able to start DTLS right away.
deadbeef367efdc2016-07-13 12:10:17 -0700374 MaybeStartDtls();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000375 return true;
376}
377
zhihuangb2cdd932017-01-19 16:54:25 -0800378bool DtlsTransport::GetSrtpCryptoSuite(int* cipher) {
deadbeef2b558672015-10-26 17:23:29 -0700379 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000380 return false;
381 }
382
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800383 return dtls_->GetDtlsSrtpCryptoSuite(cipher);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000384}
385
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000386// Called from upper layers to send a media packet.
zhihuangb2cdd932017-01-19 16:54:25 -0800387int DtlsTransport::SendPacket(const char* data,
388 size_t size,
389 const rtc::PacketOptions& options,
390 int flags) {
deadbeef2b558672015-10-26 17:23:29 -0700391 if (!dtls_active_) {
392 // Not doing DTLS.
zhihuangb2cdd932017-01-19 16:54:25 -0800393 return ice_transport_->SendPacket(data, size, options);
deadbeef2b558672015-10-26 17:23:29 -0700394 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000395
deadbeef2b558672015-10-26 17:23:29 -0700396 switch (dtls_state()) {
397 case DTLS_TRANSPORT_NEW:
398 // Can't send data until the connection is active.
399 // TODO(ekr@rtfm.com): assert here if dtls_ is NULL?
400 return -1;
401 case DTLS_TRANSPORT_CONNECTING:
402 // Can't send data until the connection is active.
403 return -1;
404 case DTLS_TRANSPORT_CONNECTED:
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000405 if (flags & PF_SRTP_BYPASS) {
nisseede5da42017-01-12 05:15:36 -0800406 RTC_DCHECK(!srtp_ciphers_.empty());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000407 if (!IsRtpPacket(data, size)) {
deadbeef2b558672015-10-26 17:23:29 -0700408 return -1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000409 }
410
zhihuangb2cdd932017-01-19 16:54:25 -0800411 return ice_transport_->SendPacket(data, size, options);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000412 } else {
deadbeef2b558672015-10-26 17:23:29 -0700413 return (dtls_->WriteAll(data, size, NULL, NULL) == rtc::SR_SUCCESS)
414 ? static_cast<int>(size)
415 : -1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000416 }
deadbeef2b558672015-10-26 17:23:29 -0700417 case DTLS_TRANSPORT_FAILED:
418 case DTLS_TRANSPORT_CLOSED:
419 // Can't send anything when we're closed.
420 return -1;
421 default:
nissec80e7412017-01-11 05:56:46 -0800422 RTC_NOTREACHED();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000423 return -1;
424 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000425}
426
Steve Anton33f69db2017-10-30 10:01:15 -0700427IceTransportInternal* DtlsTransport::ice_transport() {
Harald Alvestrand00dfe932018-11-22 11:34:47 +0100428 return ice_transport_.get();
Steve Anton33f69db2017-10-30 10:01:15 -0700429}
430
zhihuangb2cdd932017-01-19 16:54:25 -0800431bool DtlsTransport::IsDtlsConnected() {
deadbeef89824f62016-09-30 11:55:43 -0700432 return dtls_ && dtls_->IsTlsConnected();
433}
434
Steve Anton33f69db2017-10-30 10:01:15 -0700435bool DtlsTransport::receiving() const {
436 return receiving_;
437}
438
439bool DtlsTransport::writable() const {
440 return writable_;
441}
442
443int DtlsTransport::GetError() {
444 return ice_transport_->GetError();
445}
446
Danil Chapovalov00c71832018-06-15 15:58:38 +0200447absl::optional<rtc::NetworkRoute> DtlsTransport::network_route() const {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800448 return ice_transport_->network_route();
449}
450
Steve Anton33f69db2017-10-30 10:01:15 -0700451bool DtlsTransport::GetOption(rtc::Socket::Option opt, int* value) {
452 return ice_transport_->GetOption(opt, value);
453}
454
455int DtlsTransport::SetOption(rtc::Socket::Option opt, int value) {
456 return ice_transport_->SetOption(opt, value);
457}
458
Zhi Huange818b6e2018-02-22 15:26:27 -0800459void DtlsTransport::ConnectToIceTransport() {
460 RTC_DCHECK(ice_transport_);
461 ice_transport_->SignalWritableState.connect(this,
462 &DtlsTransport::OnWritableState);
463 ice_transport_->SignalReadPacket.connect(this, &DtlsTransport::OnReadPacket);
464 ice_transport_->SignalSentPacket.connect(this, &DtlsTransport::OnSentPacket);
465 ice_transport_->SignalReadyToSend.connect(this,
466 &DtlsTransport::OnReadyToSend);
467 ice_transport_->SignalReceivingState.connect(
468 this, &DtlsTransport::OnReceivingState);
469 ice_transport_->SignalNetworkRouteChanged.connect(
470 this, &DtlsTransport::OnNetworkRouteChanged);
471}
472
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000473// The state transition logic here is as follows:
474// (1) If we're not doing DTLS-SRTP, then the state is just the
475// state of the underlying impl()
476// (2) If we're doing DTLS-SRTP:
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700477// - Prior to the DTLS handshake, the state is neither receiving nor
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000478// writable
479// - When the impl goes writable for the first time we
480// start the DTLS handshake
481// - Once the DTLS handshake completes, the state is that of the
482// impl again
deadbeef5bd5ca32017-02-10 11:31:50 -0800483void DtlsTransport::OnWritableState(rtc::PacketTransportInternal* transport) {
Steve Antonf7a64ec2018-07-19 15:42:17 -0700484 RTC_DCHECK_RUN_ON(&thread_checker_);
Harald Alvestrand00dfe932018-11-22 11:34:47 +0100485 RTC_DCHECK(transport == ice_transport_.get());
Yves Gerey665174f2018-06-19 15:03:05 +0200486 RTC_LOG(LS_VERBOSE) << ToString()
487 << ": ice_transport writable state changed to "
488 << ice_transport_->writable();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000489
deadbeef2b558672015-10-26 17:23:29 -0700490 if (!dtls_active_) {
491 // Not doing DTLS.
492 // Note: SignalWritableState fired by set_writable.
zhihuangb2cdd932017-01-19 16:54:25 -0800493 set_writable(ice_transport_->writable());
deadbeef2b558672015-10-26 17:23:29 -0700494 return;
495 }
496
497 switch (dtls_state()) {
498 case DTLS_TRANSPORT_NEW:
deadbeef367efdc2016-07-13 12:10:17 -0700499 MaybeStartDtls();
deadbeef2b558672015-10-26 17:23:29 -0700500 break;
501 case DTLS_TRANSPORT_CONNECTED:
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000502 // Note: SignalWritableState fired by set_writable.
zhihuangb2cdd932017-01-19 16:54:25 -0800503 set_writable(ice_transport_->writable());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000504 break;
deadbeef2b558672015-10-26 17:23:29 -0700505 case DTLS_TRANSPORT_CONNECTING:
506 // Do nothing.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000507 break;
deadbeef2b558672015-10-26 17:23:29 -0700508 case DTLS_TRANSPORT_FAILED:
509 case DTLS_TRANSPORT_CLOSED:
510 // Should not happen. Do nothing.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000511 break;
512 }
513}
514
deadbeef5bd5ca32017-02-10 11:31:50 -0800515void DtlsTransport::OnReceivingState(rtc::PacketTransportInternal* transport) {
Steve Antonf7a64ec2018-07-19 15:42:17 -0700516 RTC_DCHECK_RUN_ON(&thread_checker_);
Harald Alvestrand00dfe932018-11-22 11:34:47 +0100517 RTC_DCHECK(transport == ice_transport_.get());
Jonas Olssond7d762d2018-03-28 09:47:51 +0200518 RTC_LOG(LS_VERBOSE) << ToString()
519 << ": ice_transport "
520 "receiving state changed to "
521 << ice_transport_->receiving();
deadbeef2b558672015-10-26 17:23:29 -0700522 if (!dtls_active_ || dtls_state() == DTLS_TRANSPORT_CONNECTED) {
Peter Thatcher54360512015-07-08 11:08:35 -0700523 // Note: SignalReceivingState fired by set_receiving.
zhihuangb2cdd932017-01-19 16:54:25 -0800524 set_receiving(ice_transport_->receiving());
Peter Thatcher54360512015-07-08 11:08:35 -0700525 }
526}
527
deadbeef5bd5ca32017-02-10 11:31:50 -0800528void DtlsTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
zhihuangb2cdd932017-01-19 16:54:25 -0800529 const char* data,
530 size_t size,
Niels Möllere6933812018-11-05 13:01:41 +0100531 const int64_t& packet_time_us,
zhihuangb2cdd932017-01-19 16:54:25 -0800532 int flags) {
Steve Antonf7a64ec2018-07-19 15:42:17 -0700533 RTC_DCHECK_RUN_ON(&thread_checker_);
Harald Alvestrand00dfe932018-11-22 11:34:47 +0100534 RTC_DCHECK(transport == ice_transport_.get());
nisseede5da42017-01-12 05:15:36 -0800535 RTC_DCHECK(flags == 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000536
deadbeef2b558672015-10-26 17:23:29 -0700537 if (!dtls_active_) {
538 // Not doing DTLS.
Niels Möllere6933812018-11-05 13:01:41 +0100539 SignalReadPacket(this, data, size, packet_time_us, 0);
deadbeef2b558672015-10-26 17:23:29 -0700540 return;
541 }
542
543 switch (dtls_state()) {
544 case DTLS_TRANSPORT_NEW:
545 if (dtls_) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200546 RTC_LOG(LS_INFO) << ToString()
547 << ": Packet received before DTLS started.";
deadbeef2b558672015-10-26 17:23:29 -0700548 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200549 RTC_LOG(LS_WARNING) << ToString()
550 << ": Packet received before we know if we are "
551 "doing DTLS or not.";
deadbeefe84cd2e2016-05-04 17:16:34 -0700552 }
553 // Cache a client hello packet received before DTLS has actually started.
554 if (IsDtlsClientHelloPacket(data, size)) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200555 RTC_LOG(LS_INFO) << ToString()
556 << ": Caching DTLS ClientHello packet until DTLS is "
557 "started.";
deadbeefe84cd2e2016-05-04 17:16:34 -0700558 cached_client_hello_.SetData(data, size);
deadbeef89824f62016-09-30 11:55:43 -0700559 // If we haven't started setting up DTLS yet (because we don't have a
560 // remote fingerprint/role), we can use the client hello as a clue that
561 // the peer has chosen the client role, and proceed with the handshake.
562 // The fingerprint will be verified when it's set.
563 if (!dtls_ && local_certificate_) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800564 SetDtlsRole(rtc::SSL_SERVER);
deadbeef89824f62016-09-30 11:55:43 -0700565 SetupDtls();
566 }
deadbeefe84cd2e2016-05-04 17:16:34 -0700567 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200568 RTC_LOG(LS_INFO) << ToString()
569 << ": Not a DTLS ClientHello packet; dropping.";
deadbeef2b558672015-10-26 17:23:29 -0700570 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000571 break;
572
deadbeef2b558672015-10-26 17:23:29 -0700573 case DTLS_TRANSPORT_CONNECTING:
574 case DTLS_TRANSPORT_CONNECTED:
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000575 // We should only get DTLS or SRTP packets; STUN's already been demuxed.
576 // Is this potentially a DTLS packet?
577 if (IsDtlsPacket(data, size)) {
578 if (!HandleDtlsPacket(data, size)) {
Yves Gerey665174f2018-06-19 15:03:05 +0200579 RTC_LOG(LS_ERROR) << ToString() << ": Failed to handle DTLS packet.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000580 return;
581 }
582 } else {
583 // Not a DTLS packet; our handshake should be complete by now.
deadbeef2b558672015-10-26 17:23:29 -0700584 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200585 RTC_LOG(LS_ERROR) << ToString()
586 << ": Received non-DTLS packet before DTLS "
587 "complete.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000588 return;
589 }
590
591 // And it had better be a SRTP packet.
592 if (!IsRtpPacket(data, size)) {
Yves Gerey665174f2018-06-19 15:03:05 +0200593 RTC_LOG(LS_ERROR)
594 << ToString() << ": Received unexpected non-DTLS packet.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000595 return;
596 }
597
598 // Sanity check.
nisseede5da42017-01-12 05:15:36 -0800599 RTC_DCHECK(!srtp_ciphers_.empty());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000600
601 // Signal this upwards as a bypass packet.
Niels Möllere6933812018-11-05 13:01:41 +0100602 SignalReadPacket(this, data, size, packet_time_us, PF_SRTP_BYPASS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000603 }
604 break;
deadbeef2b558672015-10-26 17:23:29 -0700605 case DTLS_TRANSPORT_FAILED:
606 case DTLS_TRANSPORT_CLOSED:
607 // This shouldn't be happening. Drop the packet.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000608 break;
609 }
610}
611
deadbeef5bd5ca32017-02-10 11:31:50 -0800612void DtlsTransport::OnSentPacket(rtc::PacketTransportInternal* transport,
zhihuangb2cdd932017-01-19 16:54:25 -0800613 const rtc::SentPacket& sent_packet) {
Steve Antonf7a64ec2018-07-19 15:42:17 -0700614 RTC_DCHECK_RUN_ON(&thread_checker_);
stefanc1aeaf02015-10-15 07:26:07 -0700615 SignalSentPacket(this, sent_packet);
616}
617
deadbeef5bd5ca32017-02-10 11:31:50 -0800618void DtlsTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
Steve Antonf7a64ec2018-07-19 15:42:17 -0700619 RTC_DCHECK_RUN_ON(&thread_checker_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000620 if (writable()) {
621 SignalReadyToSend(this);
622 }
623}
624
zhihuangb2cdd932017-01-19 16:54:25 -0800625void DtlsTransport::OnDtlsEvent(rtc::StreamInterface* dtls, int sig, int err) {
Steve Antonf7a64ec2018-07-19 15:42:17 -0700626 RTC_DCHECK_RUN_ON(&thread_checker_);
nisseede5da42017-01-12 05:15:36 -0800627 RTC_DCHECK(dtls == dtls_.get());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000628 if (sig & rtc::SE_OPEN) {
629 // This is the first time.
Yves Gerey665174f2018-06-19 15:03:05 +0200630 RTC_LOG(LS_INFO) << ToString() << ": DTLS handshake complete.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000631 if (dtls_->GetState() == rtc::SS_OPEN) {
632 // The check for OPEN shouldn't be necessary but let's make
633 // sure we don't accidentally frob the state if it's closed.
deadbeef2b558672015-10-26 17:23:29 -0700634 set_dtls_state(DTLS_TRANSPORT_CONNECTED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000635 set_writable(true);
636 }
637 }
638 if (sig & rtc::SE_READ) {
639 char buf[kMaxDtlsPacketLen];
640 size_t read;
deadbeef89824f62016-09-30 11:55:43 -0700641 int read_error;
jbauch7d0a77e2017-07-07 13:44:07 -0700642 rtc::StreamResult ret;
643 // The underlying DTLS stream may have received multiple DTLS records in
644 // one packet, so read all of them.
645 do {
646 ret = dtls_->Read(buf, sizeof(buf), &read, &read_error);
647 if (ret == rtc::SR_SUCCESS) {
Niels Möller15ca5a92018-11-01 14:32:47 +0100648 SignalReadPacket(this, buf, read, rtc::TimeMicros(), 0);
jbauch7d0a77e2017-07-07 13:44:07 -0700649 } else if (ret == rtc::SR_EOS) {
650 // Remote peer shut down the association with no error.
Yves Gerey665174f2018-06-19 15:03:05 +0200651 RTC_LOG(LS_INFO) << ToString() << ": DTLS transport closed";
jbauch7d0a77e2017-07-07 13:44:07 -0700652 set_writable(false);
653 set_dtls_state(DTLS_TRANSPORT_CLOSED);
654 } else if (ret == rtc::SR_ERROR) {
655 // Remote peer shut down the association with an error.
Jonas Olssond7d762d2018-03-28 09:47:51 +0200656 RTC_LOG(LS_INFO) << ToString()
657 << ": DTLS transport error, code=" << read_error;
jbauch7d0a77e2017-07-07 13:44:07 -0700658 set_writable(false);
659 set_dtls_state(DTLS_TRANSPORT_FAILED);
660 }
661 } while (ret == rtc::SR_SUCCESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000662 }
663 if (sig & rtc::SE_CLOSE) {
nisseede5da42017-01-12 05:15:36 -0800664 RTC_DCHECK(sig == rtc::SE_CLOSE); // SE_CLOSE should be by itself.
deadbeef2b558672015-10-26 17:23:29 -0700665 set_writable(false);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000666 if (!err) {
Yves Gerey665174f2018-06-19 15:03:05 +0200667 RTC_LOG(LS_INFO) << ToString() << ": DTLS transport closed";
deadbeef2b558672015-10-26 17:23:29 -0700668 set_dtls_state(DTLS_TRANSPORT_CLOSED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000669 } else {
Yves Gerey665174f2018-06-19 15:03:05 +0200670 RTC_LOG(LS_INFO) << ToString() << ": DTLS transport error, code=" << err;
deadbeef2b558672015-10-26 17:23:29 -0700671 set_dtls_state(DTLS_TRANSPORT_FAILED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000672 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000673 }
674}
675
Zhi Huang942bc2e2017-11-13 13:26:07 -0800676void DtlsTransport::OnNetworkRouteChanged(
Danil Chapovalov00c71832018-06-15 15:58:38 +0200677 absl::optional<rtc::NetworkRoute> network_route) {
Steve Antonf7a64ec2018-07-19 15:42:17 -0700678 RTC_DCHECK_RUN_ON(&thread_checker_);
Zhi Huang942bc2e2017-11-13 13:26:07 -0800679 SignalNetworkRouteChanged(network_route);
680}
681
zhihuangb2cdd932017-01-19 16:54:25 -0800682void DtlsTransport::MaybeStartDtls() {
683 if (dtls_ && ice_transport_->writable()) {
skvladd0309122017-02-02 17:18:37 -0800684 ConfigureHandshakeTimeout();
685
Taylor Brandstetterc8762a82016-08-11 12:01:49 -0700686 if (dtls_->StartSSL()) {
deadbeef367efdc2016-07-13 12:10:17 -0700687 // This should never fail:
688 // Because we are operating in a nonblocking mode and all
689 // incoming packets come in via OnReadPacket(), which rejects
690 // packets in this state, the incoming queue must be empty. We
691 // ignore write errors, thus any errors must be because of
692 // configuration and therefore are our fault.
nisseeb4ca4e2017-01-12 02:24:27 -0800693 RTC_NOTREACHED() << "StartSSL failed.";
Yves Gerey665174f2018-06-19 15:03:05 +0200694 RTC_LOG(LS_ERROR) << ToString() << ": Couldn't start DTLS handshake";
deadbeef2b558672015-10-26 17:23:29 -0700695 set_dtls_state(DTLS_TRANSPORT_FAILED);
deadbeef367efdc2016-07-13 12:10:17 -0700696 return;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000697 }
Yves Gerey665174f2018-06-19 15:03:05 +0200698 RTC_LOG(LS_INFO) << ToString() << ": DtlsTransport: Started DTLS handshake";
deadbeef2b558672015-10-26 17:23:29 -0700699 set_dtls_state(DTLS_TRANSPORT_CONNECTING);
deadbeefe84cd2e2016-05-04 17:16:34 -0700700 // Now that the handshake has started, we can process a cached ClientHello
701 // (if one exists).
702 if (cached_client_hello_.size()) {
Zhi Huange818b6e2018-02-22 15:26:27 -0800703 if (*dtls_role_ == rtc::SSL_SERVER) {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200704 RTC_LOG(LS_INFO) << ToString()
705 << ": Handling cached DTLS ClientHello packet.";
deadbeefe84cd2e2016-05-04 17:16:34 -0700706 if (!HandleDtlsPacket(cached_client_hello_.data<char>(),
707 cached_client_hello_.size())) {
Yves Gerey665174f2018-06-19 15:03:05 +0200708 RTC_LOG(LS_ERROR) << ToString() << ": Failed to handle DTLS packet.";
deadbeefe84cd2e2016-05-04 17:16:34 -0700709 }
710 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200711 RTC_LOG(LS_WARNING) << ToString()
712 << ": Discarding cached DTLS ClientHello packet "
713 "because we don't have the server role.";
deadbeefe84cd2e2016-05-04 17:16:34 -0700714 }
715 cached_client_hello_.Clear();
716 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000717 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000718}
719
720// Called from OnReadPacket when a DTLS packet is received.
zhihuangb2cdd932017-01-19 16:54:25 -0800721bool DtlsTransport::HandleDtlsPacket(const char* data, size_t size) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000722 // Sanity check we're not passing junk that
723 // just looks like DTLS.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200724 const uint8_t* tmp_data = reinterpret_cast<const uint8_t*>(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000725 size_t tmp_size = size;
726 while (tmp_size > 0) {
727 if (tmp_size < kDtlsRecordHeaderLen)
728 return false; // Too short for the header
729
730 size_t record_len = (tmp_data[11] << 8) | (tmp_data[12]);
731 if ((record_len + kDtlsRecordHeaderLen) > tmp_size)
732 return false; // Body too short
733
734 tmp_data += record_len + kDtlsRecordHeaderLen;
735 tmp_size -= record_len + kDtlsRecordHeaderLen;
736 }
737
738 // Looks good. Pass to the SIC which ends up being passed to
739 // the DTLS stack.
740 return downward_->OnPacketReceived(data, size);
741}
742
zhihuangb2cdd932017-01-19 16:54:25 -0800743void DtlsTransport::set_receiving(bool receiving) {
744 if (receiving_ == receiving) {
745 return;
746 }
747 receiving_ = receiving;
748 SignalReceivingState(this);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000749}
750
zhihuangb2cdd932017-01-19 16:54:25 -0800751void DtlsTransport::set_writable(bool writable) {
752 if (writable_ == writable) {
753 return;
754 }
Zach Stein846dfdf2018-11-29 14:12:17 -0800755 if (event_log_) {
756 event_log_->Log(
757 absl::make_unique<webrtc::RtcEventDtlsWritableState>(writable));
758 }
Yves Gerey665174f2018-06-19 15:03:05 +0200759 RTC_LOG(LS_VERBOSE) << ToString() << ": set_writable to: " << writable;
zhihuangb2cdd932017-01-19 16:54:25 -0800760 writable_ = writable;
761 if (writable_) {
762 SignalReadyToSend(this);
763 }
764 SignalWritableState(this);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000765}
766
zhihuangb2cdd932017-01-19 16:54:25 -0800767void DtlsTransport::set_dtls_state(DtlsTransportState state) {
768 if (dtls_state_ == state) {
769 return;
770 }
Zach Steinc64078f2018-11-27 15:53:01 -0800771 if (event_log_) {
772 event_log_->Log(absl::make_unique<webrtc::RtcEventDtlsTransportState>(
773 ConvertDtlsTransportState(state)));
774 }
Yves Gerey665174f2018-06-19 15:03:05 +0200775 RTC_LOG(LS_VERBOSE) << ToString() << ": set_dtls_state from:" << dtls_state_
776 << " to " << state;
zhihuangb2cdd932017-01-19 16:54:25 -0800777 dtls_state_ = state;
778 SignalDtlsState(this, state);
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700779}
780
zhihuangb2cdd932017-01-19 16:54:25 -0800781void DtlsTransport::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
zhihuangd82eee02016-08-26 11:25:05 -0700782 SignalDtlsHandshakeError(error);
783}
784
skvladd0309122017-02-02 17:18:37 -0800785void DtlsTransport::ConfigureHandshakeTimeout() {
786 RTC_DCHECK(dtls_);
Danil Chapovalov00c71832018-06-15 15:58:38 +0200787 absl::optional<int> rtt = ice_transport_->GetRttEstimate();
skvladd0309122017-02-02 17:18:37 -0800788 if (rtt) {
789 // Limit the timeout to a reasonable range in case the ICE RTT takes
790 // extreme values.
791 int initial_timeout = std::max(kMinHandshakeTimeout,
zhihuangca6d3b62017-08-23 18:05:50 -0700792 std::min(kMaxHandshakeTimeout, 2 * (*rtt)));
Yves Gerey665174f2018-06-19 15:03:05 +0200793 RTC_LOG(LS_INFO) << ToString() << ": configuring DTLS handshake timeout "
Jonas Olssond7d762d2018-03-28 09:47:51 +0200794 << initial_timeout << " based on ICE RTT " << *rtt;
skvladd0309122017-02-02 17:18:37 -0800795
796 dtls_->SetInitialRetransmissionTimeout(initial_timeout);
797 } else {
Jonas Olssond7d762d2018-03-28 09:47:51 +0200798 RTC_LOG(LS_INFO)
799 << ToString()
800 << ": no RTT estimate - using default DTLS handshake timeout";
skvladd0309122017-02-02 17:18:37 -0800801 }
802}
803
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000804} // namespace cricket