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

Side by Side Diff: net/quic/core/quic_packet_creator.cc

Issue 2963763003: In QUIC, send data is copied to streams rather than frames. Protected by FLAGS_quic_reloadable_flag… (Closed)
Patch Set: Rebase Created 3 years, 5 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
« no previous file with comments | « net/quic/core/quic_packet_creator.h ('k') | net/quic/core/quic_packet_creator_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/quic/core/quic_packet_creator.h ('k') | net/quic/core/quic_packet_creator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698