| 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 |