| Index: webrtc/p2p/base/dtlstransportchannel.cc
|
| diff --git a/webrtc/p2p/base/dtlstransportchannel.cc b/webrtc/p2p/base/dtlstransportchannel.cc
|
| index f9baa3756202de01c93ef2da9d130911971430ff..1e3df13493fe4c2a2208c724fb69d1207e0748c6 100644
|
| --- a/webrtc/p2p/base/dtlstransportchannel.cc
|
| +++ b/webrtc/p2p/base/dtlstransportchannel.cc
|
| @@ -37,6 +37,13 @@ static bool IsDtlsPacket(const char* data, size_t len) {
|
| const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
|
| return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
|
| }
|
| +static bool IsDtlsClientHelloPacket(const char* data, size_t len) {
|
| + if (!IsDtlsPacket(data, len)) {
|
| + return false;
|
| + }
|
| + const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
|
| + return len > 17 && u[0] == 22 && u[13] == 1;
|
| +}
|
| static bool IsRtpPacket(const char* data, size_t len) {
|
| const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
|
| return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
|
| @@ -470,15 +477,18 @@ void DtlsTransportChannelWrapper::OnReadPacket(
|
| switch (dtls_state()) {
|
| case DTLS_TRANSPORT_NEW:
|
| if (dtls_) {
|
| - // Drop packets received before DTLS has actually started.
|
| - LOG_J(LS_INFO, this) << "Dropping packet received before DTLS started.";
|
| + LOG_J(LS_INFO, this) << "Packet received before DTLS started.";
|
| + } else {
|
| + LOG_J(LS_WARNING, this) << "Packet received before we know if we are "
|
| + << "doing DTLS or not.";
|
| + }
|
| + // Cache a client hello packet received before DTLS has actually started.
|
| + if (IsDtlsClientHelloPacket(data, size)) {
|
| + LOG_J(LS_INFO, this) << "Caching DTLS ClientHello packet until DTLS is "
|
| + << "started.";
|
| + cached_client_hello_.SetData(data, size);
|
| } else {
|
| - // Currently drop the packet, but we might in future
|
| - // decide to take this as evidence that the other
|
| - // side is ready to do DTLS and start the handshake
|
| - // on our end.
|
| - LOG_J(LS_WARNING, this) << "Received packet before we know if we are "
|
| - << "doing DTLS or not; dropping.";
|
| + LOG_J(LS_INFO, this) << "Not a DTLS ClientHello packet; dropping.";
|
| }
|
| break;
|
|
|
| @@ -577,6 +587,21 @@ bool DtlsTransportChannelWrapper::MaybeStartDtls() {
|
| LOG_J(LS_INFO, this)
|
| << "DtlsTransportChannelWrapper: Started DTLS handshake";
|
| set_dtls_state(DTLS_TRANSPORT_CONNECTING);
|
| + // Now that the handshake has started, we can process a cached ClientHello
|
| + // (if one exists).
|
| + if (cached_client_hello_.size()) {
|
| + if (ssl_role_ == rtc::SSL_SERVER) {
|
| + LOG_J(LS_INFO, this) << "Handling cached DTLS ClientHello packet.";
|
| + if (!HandleDtlsPacket(cached_client_hello_.data<char>(),
|
| + cached_client_hello_.size())) {
|
| + LOG_J(LS_ERROR, this) << "Failed to handle DTLS packet.";
|
| + }
|
| + } else {
|
| + LOG_J(LS_WARNING, this) << "Discarding cached DTLS ClientHello packet "
|
| + << "because we don't have the server role.";
|
| + }
|
| + cached_client_hello_.Clear();
|
| + }
|
| }
|
| return true;
|
| }
|
|
|