| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/core/quic_packet_creator.h" | 5 #include "net/quic/core/quic_packet_creator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstdint> | 8 #include <cstdint> |
| 9 | 9 |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "net/quic/core/crypto/crypto_protocol.h" | 11 #include "net/quic/core/crypto/crypto_protocol.h" |
| 12 #include "net/quic/core/quic_data_writer.h" | 12 #include "net/quic/core/quic_data_writer.h" |
| 13 #include "net/quic/core/quic_utils.h" | 13 #include "net/quic/core/quic_utils.h" |
| 14 #include "net/quic/platform/api/quic_aligned.h" | 14 #include "net/quic/platform/api/quic_aligned.h" |
| 15 #include "net/quic/platform/api/quic_bug_tracker.h" | 15 #include "net/quic/platform/api/quic_bug_tracker.h" |
| 16 #include "net/quic/platform/api/quic_flag_utils.h" | 16 #include "net/quic/platform/api/quic_flag_utils.h" |
| 17 #include "net/quic/platform/api/quic_flags.h" | 17 #include "net/quic/platform/api/quic_flags.h" |
| 18 #include "net/quic/platform/api/quic_logging.h" | 18 #include "net/quic/platform/api/quic_logging.h" |
| 19 #include "net/quic/platform/api/quic_ptr_util.h" |
| 19 #include "net/quic/platform/api/quic_string_piece.h" | 20 #include "net/quic/platform/api/quic_string_piece.h" |
| 20 | 21 |
| 21 using std::string; | 22 using std::string; |
| 22 | 23 |
| 23 // If true, enforce that QUIC CHLOs fit in one packet. | 24 // If true, enforce that QUIC CHLOs fit in one packet. |
| 24 bool FLAGS_quic_enforce_single_packet_chlo = true; | 25 bool FLAGS_quic_enforce_single_packet_chlo = true; |
| 25 | 26 |
| 26 namespace net { | 27 namespace net { |
| 27 | 28 |
| 28 #define ENDPOINT \ | 29 #define ENDPOINT \ |
| (...skipping 11 matching lines...) Expand all Loading... |
| 40 next_packet_number_length_(PACKET_1BYTE_PACKET_NUMBER), | 41 next_packet_number_length_(PACKET_1BYTE_PACKET_NUMBER), |
| 41 have_diversification_nonce_(false), | 42 have_diversification_nonce_(false), |
| 42 max_packet_length_(0), | 43 max_packet_length_(0), |
| 43 connection_id_length_(PACKET_8BYTE_CONNECTION_ID), | 44 connection_id_length_(PACKET_8BYTE_CONNECTION_ID), |
| 44 packet_size_(0), | 45 packet_size_(0), |
| 45 connection_id_(connection_id), | 46 connection_id_(connection_id), |
| 46 packet_(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false, false), | 47 packet_(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false, false), |
| 47 latched_flag_no_stop_waiting_frames_( | 48 latched_flag_no_stop_waiting_frames_( |
| 48 FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames), | 49 FLAGS_quic_reloadable_flag_quic_no_stop_waiting_frames), |
| 49 pending_padding_bytes_(0), | 50 pending_padding_bytes_(0), |
| 50 needs_full_padding_(false) { | 51 needs_full_padding_(false), |
| 52 delegate_saves_data_(false) { |
| 51 SetMaxPacketLength(kDefaultMaxPacketSize); | 53 SetMaxPacketLength(kDefaultMaxPacketSize); |
| 52 } | 54 } |
| 53 | 55 |
| 54 QuicPacketCreator::~QuicPacketCreator() { | 56 QuicPacketCreator::~QuicPacketCreator() { |
| 55 DeleteFrames(&packet_.retransmittable_frames); | 57 DeleteFrames(&packet_.retransmittable_frames); |
| 56 } | 58 } |
| 57 | 59 |
| 58 void QuicPacketCreator::SetEncrypter(EncryptionLevel level, | 60 void QuicPacketCreator::SetEncrypter(EncryptionLevel level, |
| 59 QuicEncrypter* encrypter) { | 61 QuicEncrypter* encrypter) { |
| 60 framer_->SetEncrypter(level, encrypter); | 62 framer_->SetEncrypter(level, encrypter); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 size_t iov_offset, | 125 size_t iov_offset, |
| 124 QuicStreamOffset offset, | 126 QuicStreamOffset offset, |
| 125 bool fin, | 127 bool fin, |
| 126 bool needs_full_padding, | 128 bool needs_full_padding, |
| 127 QuicFrame* frame) { | 129 QuicFrame* frame) { |
| 128 if (!HasRoomForStreamFrame(id, offset)) { | 130 if (!HasRoomForStreamFrame(id, offset)) { |
| 129 return false; | 131 return false; |
| 130 } | 132 } |
| 131 CreateStreamFrame(id, iov, iov_offset, offset, fin, frame); | 133 CreateStreamFrame(id, iov, iov_offset, offset, fin, frame); |
| 132 // Explicitly disallow multi-packet CHLOs. | 134 // Explicitly disallow multi-packet CHLOs. |
| 133 if (id == kCryptoStreamId && | 135 if (StreamFrameStartsWithChlo(iov, iov_offset, *frame->stream_frame) && |
| 134 frame->stream_frame->data_length >= sizeof(kCHLO) && | 136 FLAGS_quic_enforce_single_packet_chlo && |
| 135 strncmp(frame->stream_frame->data_buffer, | 137 frame->stream_frame->data_length < iov.iov->iov_len) { |
| 136 reinterpret_cast<const char*>(&kCHLO), sizeof(kCHLO)) == 0) { | 138 const string error_details = "Client hello won't fit in a single packet."; |
| 137 DCHECK_EQ(0u, iov_offset); | 139 QUIC_BUG << error_details << " Constructed stream frame length: " |
| 138 if (FLAGS_quic_enforce_single_packet_chlo && | 140 << frame->stream_frame->data_length |
| 139 frame->stream_frame->data_length < iov.iov->iov_len) { | 141 << " CHLO length: " << iov.iov->iov_len; |
| 140 const string error_details = "Client hello won't fit in a single packet."; | 142 delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details, |
| 141 QUIC_BUG << error_details << " Constructed stream frame length: " | 143 ConnectionCloseSource::FROM_SELF); |
| 142 << frame->stream_frame->data_length | 144 delete frame->stream_frame; |
| 143 << " CHLO length: " << iov.iov->iov_len; | 145 return false; |
| 144 delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details, | |
| 145 ConnectionCloseSource::FROM_SELF); | |
| 146 delete frame->stream_frame; | |
| 147 return false; | |
| 148 } | |
| 149 } | 146 } |
| 150 if (!AddFrame(*frame, /*save_retransmittable_frames=*/true)) { | 147 if (!AddFrame(*frame, /*save_retransmittable_frames=*/true)) { |
| 151 // Fails if we try to write unencrypted stream data. | 148 // Fails if we try to write unencrypted stream data. |
| 152 delete frame->stream_frame; | 149 delete frame->stream_frame; |
| 153 return false; | 150 return false; |
| 154 } | 151 } |
| 155 if (needs_full_padding) { | 152 if (needs_full_padding) { |
| 156 needs_full_padding_ = true; | 153 needs_full_padding_ = true; |
| 157 } | 154 } |
| 158 | 155 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 return; | 201 return; |
| 205 } | 202 } |
| 206 | 203 |
| 207 const size_t data_size = iov.total_length - iov_offset; | 204 const size_t data_size = iov.total_length - iov_offset; |
| 208 size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( | 205 size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( |
| 209 id, offset, /* last_frame_in_packet= */ true); | 206 id, offset, /* last_frame_in_packet= */ true); |
| 210 size_t bytes_consumed = | 207 size_t bytes_consumed = |
| 211 std::min<size_t>(BytesFree() - min_frame_size, data_size); | 208 std::min<size_t>(BytesFree() - min_frame_size, data_size); |
| 212 | 209 |
| 213 bool set_fin = fin && bytes_consumed == data_size; // Last frame. | 210 bool set_fin = fin && bytes_consumed == data_size; // Last frame. |
| 211 if (delegate_saves_data_) { |
| 212 *frame = |
| 213 QuicFrame(new QuicStreamFrame(id, set_fin, offset, bytes_consumed)); |
| 214 if (bytes_consumed > 0) { |
| 215 delegate_->SaveStreamData(id, iov, iov_offset, offset, bytes_consumed); |
| 216 } |
| 217 return; |
| 218 } |
| 214 UniqueStreamBuffer buffer = | 219 UniqueStreamBuffer buffer = |
| 215 NewStreamBuffer(buffer_allocator_, bytes_consumed); | 220 NewStreamBuffer(buffer_allocator_, bytes_consumed); |
| 216 QuicUtils::CopyToBuffer(iov, iov_offset, bytes_consumed, buffer.get()); | 221 QuicUtils::CopyToBuffer(iov, iov_offset, bytes_consumed, buffer.get()); |
| 217 *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, bytes_consumed, | 222 *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, bytes_consumed, |
| 218 std::move(buffer))); | 223 std::move(buffer))); |
| 219 } | 224 } |
| 220 | 225 |
| 221 void QuicPacketCreator::ReserializeAllFrames( | 226 void QuicPacketCreator::ReserializeAllFrames( |
| 222 const QuicPendingRetransmission& retransmission, | 227 const QuicPendingRetransmission& retransmission, |
| 223 char* buffer, | 228 char* buffer, |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 << "Creating a stream frame with no data or fin."; | 330 << "Creating a stream frame with no data or fin."; |
| 326 const size_t remaining_data_size = iov.total_length - iov_offset; | 331 const size_t remaining_data_size = iov.total_length - iov_offset; |
| 327 const size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( | 332 const size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( |
| 328 id, stream_offset, /* last_frame_in_packet= */ true); | 333 id, stream_offset, /* last_frame_in_packet= */ true); |
| 329 const size_t available_size = | 334 const size_t available_size = |
| 330 max_plaintext_size_ - writer.length() - min_frame_size; | 335 max_plaintext_size_ - writer.length() - min_frame_size; |
| 331 const size_t bytes_consumed = | 336 const size_t bytes_consumed = |
| 332 std::min<size_t>(available_size, remaining_data_size); | 337 std::min<size_t>(available_size, remaining_data_size); |
| 333 | 338 |
| 334 const bool set_fin = fin && (bytes_consumed == remaining_data_size); | 339 const bool set_fin = fin && (bytes_consumed == remaining_data_size); |
| 335 UniqueStreamBuffer stream_buffer = | 340 std::unique_ptr<QuicStreamFrame> frame; |
| 336 NewStreamBuffer(buffer_allocator_, bytes_consumed); | 341 if (delegate_saves_data_) { |
| 337 QuicUtils::CopyToBuffer(iov, iov_offset, bytes_consumed, stream_buffer.get()); | 342 frame = QuicMakeUnique<QuicStreamFrame>(id, set_fin, stream_offset, |
| 338 std::unique_ptr<QuicStreamFrame> frame(new QuicStreamFrame( | 343 bytes_consumed); |
| 339 id, set_fin, stream_offset, bytes_consumed, std::move(stream_buffer))); | 344 if (bytes_consumed > 0) { |
| 345 delegate_->SaveStreamData(id, iov, iov_offset, stream_offset, |
| 346 bytes_consumed); |
| 347 } |
| 348 } else { |
| 349 UniqueStreamBuffer stream_buffer = |
| 350 NewStreamBuffer(buffer_allocator_, bytes_consumed); |
| 351 QuicUtils::CopyToBuffer(iov, iov_offset, bytes_consumed, |
| 352 stream_buffer.get()); |
| 353 frame = QuicMakeUnique<QuicStreamFrame>( |
| 354 id, set_fin, stream_offset, bytes_consumed, std::move(stream_buffer)); |
| 355 } |
| 340 QUIC_DVLOG(1) << ENDPOINT << "Adding frame: " << *frame; | 356 QUIC_DVLOG(1) << ENDPOINT << "Adding frame: " << *frame; |
| 341 | 357 |
| 342 // TODO(ianswett): AppendTypeByte and AppendStreamFrame could be optimized | 358 // TODO(ianswett): AppendTypeByte and AppendStreamFrame could be optimized |
| 343 // into one method that takes a QuicStreamFrame, if warranted. | 359 // into one method that takes a QuicStreamFrame, if warranted. |
| 344 if (!framer_->AppendTypeByte(QuicFrame(frame.get()), | 360 if (!framer_->AppendTypeByte(QuicFrame(frame.get()), |
| 345 /* no stream frame length */ true, &writer)) { | 361 /* no stream frame length */ true, &writer)) { |
| 346 QUIC_BUG << "AppendTypeByte failed"; | 362 QUIC_BUG << "AppendTypeByte failed"; |
| 347 return; | 363 return; |
| 348 } | 364 } |
| 349 if (!framer_->AppendStreamFrame(*frame, /* no stream frame length */ true, | 365 if (!framer_->AppendStreamFrame(*frame, /* no stream frame length */ true, |
| 350 &writer)) { | 366 &writer, |
| 367 delegate_saves_data_ ? delegate_ : nullptr)) { |
| 351 QUIC_BUG << "AppendStreamFrame failed"; | 368 QUIC_BUG << "AppendStreamFrame failed"; |
| 352 return; | 369 return; |
| 353 } | 370 } |
| 354 | 371 |
| 355 size_t encrypted_length = framer_->EncryptInPlace( | 372 size_t encrypted_length = framer_->EncryptInPlace( |
| 356 packet_.encryption_level, packet_.packet_number, | 373 packet_.encryption_level, packet_.packet_number, |
| 357 GetStartOfEncryptedData(framer_->version(), header), writer.length(), | 374 GetStartOfEncryptedData(framer_->version(), header), writer.length(), |
| 358 arraysize(encrypted_buffer), encrypted_buffer); | 375 arraysize(encrypted_buffer), encrypted_buffer); |
| 359 if (encrypted_length == 0) { | 376 if (encrypted_length == 0) { |
| 360 QUIC_BUG << "Failed to encrypt packet number " << header.packet_number; | 377 QUIC_BUG << "Failed to encrypt packet number " << header.packet_number; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 << "Attempt to serialize empty packet"; | 448 << "Attempt to serialize empty packet"; |
| 432 QuicPacketHeader header; | 449 QuicPacketHeader header; |
| 433 // FillPacketHeader increments packet_number_. | 450 // FillPacketHeader increments packet_number_. |
| 434 FillPacketHeader(&header); | 451 FillPacketHeader(&header); |
| 435 | 452 |
| 436 MaybeAddPadding(); | 453 MaybeAddPadding(); |
| 437 | 454 |
| 438 DCHECK_GE(max_plaintext_size_, packet_size_); | 455 DCHECK_GE(max_plaintext_size_, packet_size_); |
| 439 // Use the packet_size_ instead of the buffer size to ensure smaller | 456 // Use the packet_size_ instead of the buffer size to ensure smaller |
| 440 // packet sizes are properly used. | 457 // packet sizes are properly used. |
| 441 size_t length = framer_->BuildDataPacket(header, queued_frames_, | 458 size_t length = framer_->BuildDataPacket( |
| 442 encrypted_buffer, packet_size_); | 459 header, queued_frames_, encrypted_buffer, packet_size_, |
| 460 delegate_saves_data_ ? delegate_ : nullptr); |
| 443 if (length == 0) { | 461 if (length == 0) { |
| 444 QUIC_BUG << "Failed to serialize " << queued_frames_.size() << " frames."; | 462 QUIC_BUG << "Failed to serialize " << queued_frames_.size() << " frames."; |
| 445 return; | 463 return; |
| 446 } | 464 } |
| 447 | 465 |
| 448 // ACK Frames will be truncated due to length only if they're the only frame | 466 // ACK Frames will be truncated due to length only if they're the only frame |
| 449 // in the packet, and if packet_size_ was set to max_plaintext_size_. If | 467 // in the packet, and if packet_size_ was set to max_plaintext_size_. If |
| 450 // truncation due to length occurred, then GetSerializedFrameLength will have | 468 // truncation due to length occurred, then GetSerializedFrameLength will have |
| 451 // returned all bytes free. | 469 // returned all bytes free. |
| 452 bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ && | 470 bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ && |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 | 620 |
| 603 bool QuicPacketCreator::IncludeNonceInPublicHeader() { | 621 bool QuicPacketCreator::IncludeNonceInPublicHeader() { |
| 604 return have_diversification_nonce_ && | 622 return have_diversification_nonce_ && |
| 605 packet_.encryption_level == ENCRYPTION_INITIAL; | 623 packet_.encryption_level == ENCRYPTION_INITIAL; |
| 606 } | 624 } |
| 607 | 625 |
| 608 void QuicPacketCreator::AddPendingPadding(QuicByteCount size) { | 626 void QuicPacketCreator::AddPendingPadding(QuicByteCount size) { |
| 609 pending_padding_bytes_ += size; | 627 pending_padding_bytes_ += size; |
| 610 } | 628 } |
| 611 | 629 |
| 630 bool QuicPacketCreator::StreamFrameStartsWithChlo( |
| 631 QuicIOVector iov, |
| 632 size_t iov_offset, |
| 633 const QuicStreamFrame& frame) const { |
| 634 if (!delegate_saves_data_) { |
| 635 return frame.stream_id == kCryptoStreamId && |
| 636 frame.data_length >= sizeof(kCHLO) && |
| 637 strncmp(frame.data_buffer, reinterpret_cast<const char*>(&kCHLO), |
| 638 sizeof(kCHLO)) == 0; |
| 639 } |
| 640 |
| 641 if (framer_->perspective() == Perspective::IS_SERVER || |
| 642 frame.stream_id != kCryptoStreamId || iov_offset != 0 || |
| 643 frame.data_length < sizeof(kCHLO)) { |
| 644 return false; |
| 645 } |
| 646 |
| 647 if (iov.iov[0].iov_len < sizeof(kCHLO)) { |
| 648 QUIC_BUG << "iov length " << iov.iov[0].iov_len << " is less than " |
| 649 << sizeof(kCHLO); |
| 650 return false; |
| 651 } |
| 652 return strncmp(reinterpret_cast<const char*>(iov.iov[0].iov_base), |
| 653 reinterpret_cast<const char*>(&kCHLO), sizeof(kCHLO)) == 0; |
| 654 } |
| 655 |
| 612 } // namespace net | 656 } // namespace net |
| OLD | NEW |