OLD | NEW |
| (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 | |
OLD | NEW |