Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: webrtc/p2p/base/dtlstransportchannel.cc

Issue 3004503002: Renamed dtlstransportchannel.h/.cc/_unittest.cc. (Closed)
Patch Set: Rename dtlstransportchannel.h/.cc/_unittest.cc. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
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
11 #include <memory>
12 #include <utility>
13
14 #include "webrtc/p2p/base/dtlstransportchannel.h"
15
16 #include "webrtc/p2p/base/common.h"
17 #include "webrtc/p2p/base/packettransportinternal.h"
18 #include "webrtc/rtc_base/buffer.h"
19 #include "webrtc/rtc_base/checks.h"
20 #include "webrtc/rtc_base/dscp.h"
21 #include "webrtc/rtc_base/messagequeue.h"
22 #include "webrtc/rtc_base/sslstreamadapter.h"
23 #include "webrtc/rtc_base/stream.h"
24 #include "webrtc/rtc_base/thread.h"
25
26 namespace cricket {
27
28 // We don't pull the RTP constants from rtputils.h, to avoid a layer violation.
29 static const size_t kDtlsRecordHeaderLen = 13;
30 static const size_t kMaxDtlsPacketLen = 2048;
31 static const size_t kMinRtpPacketLen = 12;
32
33 // Maximum number of pending packets in the queue. Packets are read immediately
34 // after they have been written, so a capacity of "1" is sufficient.
35 static const size_t kMaxPendingPackets = 1;
36
37 // Minimum and maximum values for the initial DTLS handshake timeout. We'll pick
38 // an initial timeout based on ICE RTT estimates, but clamp it to this range.
39 static const int kMinHandshakeTimeout = 50;
40 static const int kMaxHandshakeTimeout = 3000;
41
42 static bool IsDtlsPacket(const char* data, size_t len) {
43 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
44 return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
45 }
46 static bool IsDtlsClientHelloPacket(const char* data, size_t len) {
47 if (!IsDtlsPacket(data, len)) {
48 return false;
49 }
50 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
51 return len > 17 && u[0] == 22 && u[13] == 1;
52 }
53 static bool IsRtpPacket(const char* data, size_t len) {
54 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
55 return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
56 }
57
58 StreamInterfaceChannel::StreamInterfaceChannel(
59 IceTransportInternal* ice_transport)
60 : ice_transport_(ice_transport),
61 state_(rtc::SS_OPEN),
62 packets_(kMaxPendingPackets, kMaxDtlsPacketLen) {}
63
64 rtc::StreamResult StreamInterfaceChannel::Read(void* buffer,
65 size_t buffer_len,
66 size_t* read,
67 int* error) {
68 if (state_ == rtc::SS_CLOSED)
69 return rtc::SR_EOS;
70 if (state_ == rtc::SS_OPENING)
71 return rtc::SR_BLOCK;
72
73 if (!packets_.ReadFront(buffer, buffer_len, read)) {
74 return rtc::SR_BLOCK;
75 }
76
77 return rtc::SR_SUCCESS;
78 }
79
80 rtc::StreamResult StreamInterfaceChannel::Write(const void* data,
81 size_t data_len,
82 size_t* written,
83 int* error) {
84 // Always succeeds, since this is an unreliable transport anyway.
85 // TODO(zhihuang): Should this block if ice_transport_'s temporarily
86 // unwritable?
87 rtc::PacketOptions packet_options;
88 ice_transport_->SendPacket(static_cast<const char*>(data), data_len,
89 packet_options);
90 if (written) {
91 *written = data_len;
92 }
93 return rtc::SR_SUCCESS;
94 }
95
96 bool StreamInterfaceChannel::OnPacketReceived(const char* data, size_t size) {
97 // We force a read event here to ensure that we don't overflow our queue.
98 bool ret = packets_.WriteBack(data, size, NULL);
99 RTC_CHECK(ret) << "Failed to write packet to queue.";
100 if (ret) {
101 SignalEvent(this, rtc::SE_READ, 0);
102 }
103 return ret;
104 }
105
106 void StreamInterfaceChannel::Close() {
107 packets_.Clear();
108 state_ = rtc::SS_CLOSED;
109 }
110
111 DtlsTransport::DtlsTransport(IceTransportInternal* ice_transport,
112 const rtc::CryptoOptions& crypto_options)
113 : transport_name_(ice_transport->transport_name()),
114 component_(ice_transport->component()),
115 network_thread_(rtc::Thread::Current()),
116 ice_transport_(ice_transport),
117 downward_(NULL),
118 srtp_ciphers_(GetSupportedDtlsSrtpCryptoSuites(crypto_options)),
119 ssl_role_(rtc::SSL_CLIENT),
120 ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_12),
121 crypto_options_(crypto_options) {
122 ice_transport_->SignalWritableState.connect(this,
123 &DtlsTransport::OnWritableState);
124 ice_transport_->SignalReadPacket.connect(this, &DtlsTransport::OnReadPacket);
125 ice_transport_->SignalSentPacket.connect(this, &DtlsTransport::OnSentPacket);
126 ice_transport_->SignalReadyToSend.connect(this,
127 &DtlsTransport::OnReadyToSend);
128 ice_transport_->SignalReceivingState.connect(
129 this, &DtlsTransport::OnReceivingState);
130 }
131
132 DtlsTransport::~DtlsTransport() {}
133
134 bool DtlsTransport::SetLocalCertificate(
135 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
136 if (dtls_active_) {
137 if (certificate == local_certificate_) {
138 // This may happen during renegotiation.
139 LOG_J(LS_INFO, this) << "Ignoring identical DTLS identity";
140 return true;
141 } else {
142 LOG_J(LS_ERROR, this) << "Can't change DTLS local identity in this state";
143 return false;
144 }
145 }
146
147 if (certificate) {
148 local_certificate_ = certificate;
149 dtls_active_ = true;
150 } else {
151 LOG_J(LS_INFO, this) << "NULL DTLS identity supplied. Not doing DTLS";
152 }
153
154 return true;
155 }
156
157 rtc::scoped_refptr<rtc::RTCCertificate> DtlsTransport::GetLocalCertificate()
158 const {
159 return local_certificate_;
160 }
161
162 bool DtlsTransport::SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) {
163 if (dtls_active_) {
164 LOG(LS_ERROR) << "Not changing max. protocol version "
165 << "while DTLS is negotiating";
166 return false;
167 }
168
169 ssl_max_version_ = version;
170 return true;
171 }
172
173 bool DtlsTransport::SetSslRole(rtc::SSLRole role) {
174 if (dtls_) {
175 if (ssl_role_ != role) {
176 LOG(LS_ERROR) << "SSL Role can't be reversed after the session is setup.";
177 return false;
178 }
179 return true;
180 }
181
182 ssl_role_ = role;
183 return true;
184 }
185
186 bool DtlsTransport::GetSslRole(rtc::SSLRole* role) const {
187 *role = ssl_role_;
188 return true;
189 }
190
191 bool DtlsTransport::GetSslCipherSuite(int* cipher) {
192 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
193 return false;
194 }
195
196 return dtls_->GetSslCipherSuite(cipher);
197 }
198
199 bool DtlsTransport::SetRemoteFingerprint(const std::string& digest_alg,
200 const uint8_t* digest,
201 size_t digest_len) {
202 rtc::Buffer remote_fingerprint_value(digest, digest_len);
203
204 // Once we have the local certificate, the same remote fingerprint can be set
205 // multiple times.
206 if (dtls_active_ && remote_fingerprint_value_ == remote_fingerprint_value &&
207 !digest_alg.empty()) {
208 // This may happen during renegotiation.
209 LOG_J(LS_INFO, this) << "Ignoring identical remote DTLS fingerprint";
210 return true;
211 }
212
213 // If the other side doesn't support DTLS, turn off |dtls_active_|.
214 if (digest_alg.empty()) {
215 RTC_DCHECK(!digest_len);
216 LOG_J(LS_INFO, this) << "Other side didn't support DTLS.";
217 dtls_active_ = false;
218 return true;
219 }
220
221 // Otherwise, we must have a local certificate before setting remote
222 // fingerprint.
223 if (!dtls_active_) {
224 LOG_J(LS_ERROR, this) << "Can't set DTLS remote settings in this state.";
225 return false;
226 }
227
228 // At this point we know we are doing DTLS
229 bool fingerprint_changing = remote_fingerprint_value_.size() > 0u;
230 remote_fingerprint_value_ = std::move(remote_fingerprint_value);
231 remote_fingerprint_algorithm_ = digest_alg;
232
233 if (dtls_ && !fingerprint_changing) {
234 // This can occur if DTLS is set up before a remote fingerprint is
235 // received. For instance, if we set up DTLS due to receiving an early
236 // ClientHello.
237 rtc::SSLPeerCertificateDigestError err;
238 if (!dtls_->SetPeerCertificateDigest(
239 remote_fingerprint_algorithm_,
240 reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
241 remote_fingerprint_value_.size(), &err)) {
242 LOG_J(LS_ERROR, this) << "Couldn't set DTLS certificate digest.";
243 set_dtls_state(DTLS_TRANSPORT_FAILED);
244 // If the error is "verification failed", don't return false, because
245 // this means the fingerprint was formatted correctly but didn't match
246 // the certificate from the DTLS handshake. Thus the DTLS state should go
247 // to "failed", but SetRemoteDescription shouldn't fail.
248 return err == rtc::SSLPeerCertificateDigestError::VERIFICATION_FAILED;
249 }
250 return true;
251 }
252
253 // If the fingerprint is changing, we'll tear down the DTLS association and
254 // create a new one, resetting our state.
255 if (dtls_ && fingerprint_changing) {
256 dtls_.reset(nullptr);
257 set_dtls_state(DTLS_TRANSPORT_NEW);
258 set_writable(false);
259 }
260
261 if (!SetupDtls()) {
262 set_dtls_state(DTLS_TRANSPORT_FAILED);
263 return false;
264 }
265
266 return true;
267 }
268
269 std::unique_ptr<rtc::SSLCertificate> DtlsTransport::GetRemoteSSLCertificate()
270 const {
271 if (!dtls_) {
272 return nullptr;
273 }
274
275 return dtls_->GetPeerCertificate();
276 }
277
278 bool DtlsTransport::SetupDtls() {
279 StreamInterfaceChannel* downward = new StreamInterfaceChannel(ice_transport_);
280
281 dtls_.reset(rtc::SSLStreamAdapter::Create(downward));
282 if (!dtls_) {
283 LOG_J(LS_ERROR, this) << "Failed to create DTLS adapter.";
284 delete downward;
285 return false;
286 }
287
288 downward_ = downward;
289
290 dtls_->SetIdentity(local_certificate_->identity()->GetReference());
291 dtls_->SetMode(rtc::SSL_MODE_DTLS);
292 dtls_->SetMaxProtocolVersion(ssl_max_version_);
293 dtls_->SetServerRole(ssl_role_);
294 dtls_->SignalEvent.connect(this, &DtlsTransport::OnDtlsEvent);
295 dtls_->SignalSSLHandshakeError.connect(this,
296 &DtlsTransport::OnDtlsHandshakeError);
297 if (remote_fingerprint_value_.size() &&
298 !dtls_->SetPeerCertificateDigest(
299 remote_fingerprint_algorithm_,
300 reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
301 remote_fingerprint_value_.size())) {
302 LOG_J(LS_ERROR, this) << "Couldn't set DTLS certificate digest.";
303 return false;
304 }
305
306 // Set up DTLS-SRTP, if it's been enabled.
307 if (!srtp_ciphers_.empty()) {
308 if (!dtls_->SetDtlsSrtpCryptoSuites(srtp_ciphers_)) {
309 LOG_J(LS_ERROR, this) << "Couldn't set DTLS-SRTP ciphers.";
310 return false;
311 }
312 } else {
313 LOG_J(LS_INFO, this) << "Not using DTLS-SRTP.";
314 }
315
316 LOG_J(LS_INFO, this) << "DTLS setup complete.";
317
318 // If the underlying ice_transport is already writable at this point, we may
319 // be able to start DTLS right away.
320 MaybeStartDtls();
321 return true;
322 }
323
324 bool DtlsTransport::GetSrtpCryptoSuite(int* cipher) {
325 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
326 return false;
327 }
328
329 return dtls_->GetDtlsSrtpCryptoSuite(cipher);
330 }
331
332
333 // Called from upper layers to send a media packet.
334 int DtlsTransport::SendPacket(const char* data,
335 size_t size,
336 const rtc::PacketOptions& options,
337 int flags) {
338 if (!dtls_active_) {
339 // Not doing DTLS.
340 return ice_transport_->SendPacket(data, size, options);
341 }
342
343 switch (dtls_state()) {
344 case DTLS_TRANSPORT_NEW:
345 // Can't send data until the connection is active.
346 // TODO(ekr@rtfm.com): assert here if dtls_ is NULL?
347 return -1;
348 case DTLS_TRANSPORT_CONNECTING:
349 // Can't send data until the connection is active.
350 return -1;
351 case DTLS_TRANSPORT_CONNECTED:
352 if (flags & PF_SRTP_BYPASS) {
353 RTC_DCHECK(!srtp_ciphers_.empty());
354 if (!IsRtpPacket(data, size)) {
355 return -1;
356 }
357
358 return ice_transport_->SendPacket(data, size, options);
359 } else {
360 return (dtls_->WriteAll(data, size, NULL, NULL) == rtc::SR_SUCCESS)
361 ? static_cast<int>(size)
362 : -1;
363 }
364 case DTLS_TRANSPORT_FAILED:
365 case DTLS_TRANSPORT_CLOSED:
366 // Can't send anything when we're closed.
367 return -1;
368 default:
369 RTC_NOTREACHED();
370 return -1;
371 }
372 }
373
374 bool DtlsTransport::IsDtlsConnected() {
375 return dtls_ && dtls_->IsTlsConnected();
376 }
377
378 // The state transition logic here is as follows:
379 // (1) If we're not doing DTLS-SRTP, then the state is just the
380 // state of the underlying impl()
381 // (2) If we're doing DTLS-SRTP:
382 // - Prior to the DTLS handshake, the state is neither receiving nor
383 // writable
384 // - When the impl goes writable for the first time we
385 // start the DTLS handshake
386 // - Once the DTLS handshake completes, the state is that of the
387 // impl again
388 void DtlsTransport::OnWritableState(rtc::PacketTransportInternal* transport) {
389 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
390 RTC_DCHECK(transport == ice_transport_);
391 LOG_J(LS_VERBOSE, this)
392 << "DTLSTransportChannelWrapper: ice_transport writable state changed to "
393 << ice_transport_->writable();
394
395 if (!dtls_active_) {
396 // Not doing DTLS.
397 // Note: SignalWritableState fired by set_writable.
398 set_writable(ice_transport_->writable());
399 return;
400 }
401
402 switch (dtls_state()) {
403 case DTLS_TRANSPORT_NEW:
404 MaybeStartDtls();
405 break;
406 case DTLS_TRANSPORT_CONNECTED:
407 // Note: SignalWritableState fired by set_writable.
408 set_writable(ice_transport_->writable());
409 break;
410 case DTLS_TRANSPORT_CONNECTING:
411 // Do nothing.
412 break;
413 case DTLS_TRANSPORT_FAILED:
414 case DTLS_TRANSPORT_CLOSED:
415 // Should not happen. Do nothing.
416 break;
417 }
418 }
419
420 void DtlsTransport::OnReceivingState(rtc::PacketTransportInternal* transport) {
421 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
422 RTC_DCHECK(transport == ice_transport_);
423 LOG_J(LS_VERBOSE, this) << "DTLSTransportChannelWrapper: ice_transport "
424 "receiving state changed to "
425 << ice_transport_->receiving();
426 if (!dtls_active_ || dtls_state() == DTLS_TRANSPORT_CONNECTED) {
427 // Note: SignalReceivingState fired by set_receiving.
428 set_receiving(ice_transport_->receiving());
429 }
430 }
431
432 void DtlsTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
433 const char* data,
434 size_t size,
435 const rtc::PacketTime& packet_time,
436 int flags) {
437 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
438 RTC_DCHECK(transport == ice_transport_);
439 RTC_DCHECK(flags == 0);
440
441 if (!dtls_active_) {
442 // Not doing DTLS.
443 SignalReadPacket(this, data, size, packet_time, 0);
444 return;
445 }
446
447 switch (dtls_state()) {
448 case DTLS_TRANSPORT_NEW:
449 if (dtls_) {
450 LOG_J(LS_INFO, this) << "Packet received before DTLS started.";
451 } else {
452 LOG_J(LS_WARNING, this) << "Packet received before we know if we are "
453 << "doing DTLS or not.";
454 }
455 // Cache a client hello packet received before DTLS has actually started.
456 if (IsDtlsClientHelloPacket(data, size)) {
457 LOG_J(LS_INFO, this) << "Caching DTLS ClientHello packet until DTLS is "
458 << "started.";
459 cached_client_hello_.SetData(data, size);
460 // If we haven't started setting up DTLS yet (because we don't have a
461 // remote fingerprint/role), we can use the client hello as a clue that
462 // the peer has chosen the client role, and proceed with the handshake.
463 // The fingerprint will be verified when it's set.
464 if (!dtls_ && local_certificate_) {
465 SetSslRole(rtc::SSL_SERVER);
466 SetupDtls();
467 }
468 } else {
469 LOG_J(LS_INFO, this) << "Not a DTLS ClientHello packet; dropping.";
470 }
471 break;
472
473 case DTLS_TRANSPORT_CONNECTING:
474 case DTLS_TRANSPORT_CONNECTED:
475 // We should only get DTLS or SRTP packets; STUN's already been demuxed.
476 // Is this potentially a DTLS packet?
477 if (IsDtlsPacket(data, size)) {
478 if (!HandleDtlsPacket(data, size)) {
479 LOG_J(LS_ERROR, this) << "Failed to handle DTLS packet.";
480 return;
481 }
482 } else {
483 // Not a DTLS packet; our handshake should be complete by now.
484 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
485 LOG_J(LS_ERROR, this) << "Received non-DTLS packet before DTLS "
486 << "complete.";
487 return;
488 }
489
490 // And it had better be a SRTP packet.
491 if (!IsRtpPacket(data, size)) {
492 LOG_J(LS_ERROR, this) << "Received unexpected non-DTLS packet.";
493 return;
494 }
495
496 // Sanity check.
497 RTC_DCHECK(!srtp_ciphers_.empty());
498
499 // Signal this upwards as a bypass packet.
500 SignalReadPacket(this, data, size, packet_time, PF_SRTP_BYPASS);
501 }
502 break;
503 case DTLS_TRANSPORT_FAILED:
504 case DTLS_TRANSPORT_CLOSED:
505 // This shouldn't be happening. Drop the packet.
506 break;
507 }
508 }
509
510 void DtlsTransport::OnSentPacket(rtc::PacketTransportInternal* transport,
511 const rtc::SentPacket& sent_packet) {
512 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
513
514 SignalSentPacket(this, sent_packet);
515 }
516
517 void DtlsTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
518 if (writable()) {
519 SignalReadyToSend(this);
520 }
521 }
522
523 void DtlsTransport::OnDtlsEvent(rtc::StreamInterface* dtls, int sig, int err) {
524 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
525 RTC_DCHECK(dtls == dtls_.get());
526 if (sig & rtc::SE_OPEN) {
527 // This is the first time.
528 LOG_J(LS_INFO, this) << "DTLS handshake complete.";
529 if (dtls_->GetState() == rtc::SS_OPEN) {
530 // The check for OPEN shouldn't be necessary but let's make
531 // sure we don't accidentally frob the state if it's closed.
532 set_dtls_state(DTLS_TRANSPORT_CONNECTED);
533 set_writable(true);
534 }
535 }
536 if (sig & rtc::SE_READ) {
537 char buf[kMaxDtlsPacketLen];
538 size_t read;
539 int read_error;
540 rtc::StreamResult ret;
541 // The underlying DTLS stream may have received multiple DTLS records in
542 // one packet, so read all of them.
543 do {
544 ret = dtls_->Read(buf, sizeof(buf), &read, &read_error);
545 if (ret == rtc::SR_SUCCESS) {
546 SignalReadPacket(this, buf, read, rtc::CreatePacketTime(0), 0);
547 } else if (ret == rtc::SR_EOS) {
548 // Remote peer shut down the association with no error.
549 LOG_J(LS_INFO, this) << "DTLS transport closed";
550 set_writable(false);
551 set_dtls_state(DTLS_TRANSPORT_CLOSED);
552 } else if (ret == rtc::SR_ERROR) {
553 // Remote peer shut down the association with an error.
554 LOG_J(LS_INFO, this) << "DTLS transport error, code=" << read_error;
555 set_writable(false);
556 set_dtls_state(DTLS_TRANSPORT_FAILED);
557 }
558 } while (ret == rtc::SR_SUCCESS);
559 }
560 if (sig & rtc::SE_CLOSE) {
561 RTC_DCHECK(sig == rtc::SE_CLOSE); // SE_CLOSE should be by itself.
562 set_writable(false);
563 if (!err) {
564 LOG_J(LS_INFO, this) << "DTLS transport closed";
565 set_dtls_state(DTLS_TRANSPORT_CLOSED);
566 } else {
567 LOG_J(LS_INFO, this) << "DTLS transport error, code=" << err;
568 set_dtls_state(DTLS_TRANSPORT_FAILED);
569 }
570 }
571 }
572
573 void DtlsTransport::MaybeStartDtls() {
574 if (dtls_ && ice_transport_->writable()) {
575 ConfigureHandshakeTimeout();
576
577 if (dtls_->StartSSL()) {
578 // This should never fail:
579 // Because we are operating in a nonblocking mode and all
580 // incoming packets come in via OnReadPacket(), which rejects
581 // packets in this state, the incoming queue must be empty. We
582 // ignore write errors, thus any errors must be because of
583 // configuration and therefore are our fault.
584 RTC_NOTREACHED() << "StartSSL failed.";
585 LOG_J(LS_ERROR, this) << "Couldn't start DTLS handshake";
586 set_dtls_state(DTLS_TRANSPORT_FAILED);
587 return;
588 }
589 LOG_J(LS_INFO, this) << "DtlsTransport: Started DTLS handshake";
590 set_dtls_state(DTLS_TRANSPORT_CONNECTING);
591 // Now that the handshake has started, we can process a cached ClientHello
592 // (if one exists).
593 if (cached_client_hello_.size()) {
594 if (ssl_role_ == rtc::SSL_SERVER) {
595 LOG_J(LS_INFO, this) << "Handling cached DTLS ClientHello packet.";
596 if (!HandleDtlsPacket(cached_client_hello_.data<char>(),
597 cached_client_hello_.size())) {
598 LOG_J(LS_ERROR, this) << "Failed to handle DTLS packet.";
599 }
600 } else {
601 LOG_J(LS_WARNING, this) << "Discarding cached DTLS ClientHello packet "
602 << "because we don't have the server role.";
603 }
604 cached_client_hello_.Clear();
605 }
606 }
607 }
608
609 // Called from OnReadPacket when a DTLS packet is received.
610 bool DtlsTransport::HandleDtlsPacket(const char* data, size_t size) {
611 // Sanity check we're not passing junk that
612 // just looks like DTLS.
613 const uint8_t* tmp_data = reinterpret_cast<const uint8_t*>(data);
614 size_t tmp_size = size;
615 while (tmp_size > 0) {
616 if (tmp_size < kDtlsRecordHeaderLen)
617 return false; // Too short for the header
618
619 size_t record_len = (tmp_data[11] << 8) | (tmp_data[12]);
620 if ((record_len + kDtlsRecordHeaderLen) > tmp_size)
621 return false; // Body too short
622
623 tmp_data += record_len + kDtlsRecordHeaderLen;
624 tmp_size -= record_len + kDtlsRecordHeaderLen;
625 }
626
627 // Looks good. Pass to the SIC which ends up being passed to
628 // the DTLS stack.
629 return downward_->OnPacketReceived(data, size);
630 }
631
632 void DtlsTransport::set_receiving(bool receiving) {
633 if (receiving_ == receiving) {
634 return;
635 }
636 receiving_ = receiving;
637 SignalReceivingState(this);
638 }
639
640 void DtlsTransport::set_writable(bool writable) {
641 if (writable_ == writable) {
642 return;
643 }
644 LOG_J(LS_VERBOSE, this) << "set_writable from:" << writable_ << " to "
645 << writable;
646 writable_ = writable;
647 if (writable_) {
648 SignalReadyToSend(this);
649 }
650 SignalWritableState(this);
651 }
652
653 void DtlsTransport::set_dtls_state(DtlsTransportState state) {
654 if (dtls_state_ == state) {
655 return;
656 }
657 LOG_J(LS_VERBOSE, this) << "set_dtls_state from:" << dtls_state_ << " to "
658 << state;
659 dtls_state_ = state;
660 SignalDtlsState(this, state);
661 }
662
663 void DtlsTransport::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
664 SignalDtlsHandshakeError(error);
665 }
666
667 void DtlsTransport::ConfigureHandshakeTimeout() {
668 RTC_DCHECK(dtls_);
669 rtc::Optional<int> rtt = ice_transport_->GetRttEstimate();
670 if (rtt) {
671 // Limit the timeout to a reasonable range in case the ICE RTT takes
672 // extreme values.
673 int initial_timeout = std::max(kMinHandshakeTimeout,
674 std::min(kMaxHandshakeTimeout,
675 2 * (*rtt)));
676 LOG_J(LS_INFO, this) << "configuring DTLS handshake timeout "
677 << initial_timeout << " based on ICE RTT " << *rtt;
678
679 dtls_->SetInitialRetransmissionTimeout(initial_timeout);
680 } else {
681 LOG_J(LS_INFO, this)
682 << "no RTT estimate - using default DTLS handshake timeout";
683 }
684 }
685
686
687 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/base/dtlstransportchannel.h ('k') | webrtc/p2p/base/dtlstransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698