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 |