| Index: net/quic/quic_packet_creator.cc
|
| diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
|
| deleted file mode 100644
|
| index 07815219fd5d5931b9e583084b09d99f865a9c25..0000000000000000000000000000000000000000
|
| --- a/net/quic/quic_packet_creator.cc
|
| +++ /dev/null
|
| @@ -1,726 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/quic/quic_packet_creator.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/macros.h"
|
| -#include "net/quic/crypto/crypto_protocol.h"
|
| -#include "net/quic/crypto/quic_random.h"
|
| -#include "net/quic/quic_bug_tracker.h"
|
| -#include "net/quic/quic_data_writer.h"
|
| -#include "net/quic/quic_flags.h"
|
| -#include "net/quic/quic_utils.h"
|
| -
|
| -using base::StringPiece;
|
| -using std::make_pair;
|
| -using std::max;
|
| -using std::min;
|
| -using std::pair;
|
| -using std::string;
|
| -using std::vector;
|
| -
|
| -namespace net {
|
| -
|
| -QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
|
| - QuicFramer* framer,
|
| - QuicRandom* random_generator,
|
| - QuicBufferAllocator* buffer_allocator,
|
| - DelegateInterface* delegate)
|
| - : delegate_(delegate),
|
| - debug_delegate_(nullptr),
|
| - framer_(framer),
|
| - random_bool_source_(random_generator),
|
| - buffer_allocator_(buffer_allocator),
|
| - send_version_in_packet_(framer->perspective() == Perspective::IS_CLIENT),
|
| - send_path_id_in_packet_(false),
|
| - next_packet_number_length_(PACKET_1BYTE_PACKET_NUMBER),
|
| - have_diversification_nonce_(false),
|
| - max_packet_length_(0),
|
| - connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
|
| - packet_size_(0),
|
| - connection_id_(connection_id),
|
| - packet_(kDefaultPathId,
|
| - 0,
|
| - PACKET_1BYTE_PACKET_NUMBER,
|
| - nullptr,
|
| - 0,
|
| - 0,
|
| - false,
|
| - false) {
|
| - SetMaxPacketLength(kDefaultMaxPacketSize);
|
| -}
|
| -
|
| -QuicPacketCreator::~QuicPacketCreator() {
|
| - QuicUtils::DeleteFrames(&packet_.retransmittable_frames);
|
| -}
|
| -
|
| -void QuicPacketCreator::SetEncrypter(EncryptionLevel level,
|
| - QuicEncrypter* encrypter) {
|
| - framer_->SetEncrypter(level, encrypter);
|
| - max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
|
| -}
|
| -
|
| -bool QuicPacketCreator::CanSetMaxPacketLength() const {
|
| - // |max_packet_length_| should not be changed mid-packet.
|
| - return queued_frames_.empty();
|
| -}
|
| -
|
| -void QuicPacketCreator::SetMaxPacketLength(QuicByteCount length) {
|
| - DCHECK(CanSetMaxPacketLength());
|
| -
|
| - // Avoid recomputing |max_plaintext_size_| if the length does not actually
|
| - // change.
|
| - if (length == max_packet_length_) {
|
| - return;
|
| - }
|
| -
|
| - max_packet_length_ = length;
|
| - max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
|
| -}
|
| -
|
| -void QuicPacketCreator::MaybeUpdatePacketNumberLength() {
|
| - DCHECK(!FLAGS_quic_simple_packet_number_length);
|
| - if (!queued_frames_.empty()) {
|
| - // Don't change creator state if there are frames queued.
|
| - return;
|
| - }
|
| -
|
| - // Update packet number length only on packet boundary.
|
| - packet_.packet_number_length = next_packet_number_length_;
|
| -}
|
| -
|
| -// Stops serializing version of the protocol in packets sent after this call.
|
| -// A packet that is already open might send kQuicVersionSize bytes less than the
|
| -// maximum packet size if we stop sending version before it is serialized.
|
| -void QuicPacketCreator::StopSendingVersion() {
|
| - DCHECK(send_version_in_packet_);
|
| - send_version_in_packet_ = false;
|
| - if (packet_size_ > 0) {
|
| - DCHECK_LT(kQuicVersionSize, packet_size_);
|
| - packet_size_ -= kQuicVersionSize;
|
| - }
|
| -}
|
| -
|
| -void QuicPacketCreator::SetDiversificationNonce(
|
| - const DiversificationNonce nonce) {
|
| - DCHECK(!have_diversification_nonce_);
|
| - have_diversification_nonce_ = true;
|
| - memcpy(&diversification_nonce_, nonce, sizeof(diversification_nonce_));
|
| -}
|
| -
|
| -void QuicPacketCreator::UpdatePacketNumberLength(
|
| - QuicPacketNumber least_packet_awaited_by_peer,
|
| - QuicPacketCount max_packets_in_flight) {
|
| - if (FLAGS_quic_simple_packet_number_length && !queued_frames_.empty()) {
|
| - // Don't change creator state if there are frames queued.
|
| - QUIC_BUG << "Called UpdatePacketNumberLength with " << queued_frames_.size()
|
| - << " queued_frames. First frame type:"
|
| - << queued_frames_.front().type
|
| - << " last frame type:" << queued_frames_.back().type;
|
| - return;
|
| - }
|
| -
|
| - DCHECK_LE(least_packet_awaited_by_peer, packet_.packet_number + 1);
|
| - const QuicPacketNumber current_delta =
|
| - packet_.packet_number + 1 - least_packet_awaited_by_peer;
|
| - const uint64_t delta = max(current_delta, max_packets_in_flight);
|
| - if (FLAGS_quic_simple_packet_number_length) {
|
| - packet_.packet_number_length =
|
| - QuicFramer::GetMinSequenceNumberLength(delta * 4);
|
| - } else {
|
| - next_packet_number_length_ =
|
| - QuicFramer::GetMinSequenceNumberLength(delta * 4);
|
| - }
|
| -}
|
| -
|
| -bool QuicPacketCreator::ConsumeData(QuicStreamId id,
|
| - QuicIOVector iov,
|
| - size_t iov_offset,
|
| - QuicStreamOffset offset,
|
| - bool fin,
|
| - bool needs_full_padding,
|
| - QuicFrame* frame) {
|
| - if (!HasRoomForStreamFrame(id, offset)) {
|
| - return false;
|
| - }
|
| - CreateStreamFrame(id, iov, iov_offset, offset, fin, frame);
|
| - // Explicitly disallow multi-packet CHLOs.
|
| - if (id == kCryptoStreamId &&
|
| - frame->stream_frame->data_length >= sizeof(kCHLO) &&
|
| - strncmp(frame->stream_frame->data_buffer,
|
| - reinterpret_cast<const char*>(&kCHLO), sizeof(kCHLO)) == 0) {
|
| - DCHECK_EQ(static_cast<size_t>(0), iov_offset);
|
| - if (frame->stream_frame->data_length < iov.iov->iov_len) {
|
| - const string error_details = "Client hello won't fit in a single packet.";
|
| - QUIC_BUG << error_details << " Constructed stream frame length: "
|
| - << frame->stream_frame->data_length
|
| - << " CHLO length: " << iov.iov->iov_len;
|
| - delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details,
|
| - ConnectionCloseSource::FROM_SELF);
|
| - delete frame->stream_frame;
|
| - return false;
|
| - }
|
| - }
|
| - if (!AddFrame(*frame, /*save_retransmittable_frames=*/true)) {
|
| - // Fails if we try to write unencrypted stream data.
|
| - delete frame->stream_frame;
|
| - return false;
|
| - }
|
| - if (needs_full_padding) {
|
| - packet_.num_padding_bytes = -1;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
|
| - QuicStreamOffset offset) {
|
| - return BytesFree() > QuicFramer::GetMinStreamFrameSize(id, offset, true);
|
| -}
|
| -
|
| -// static
|
| -size_t QuicPacketCreator::StreamFramePacketOverhead(
|
| - QuicVersion version,
|
| - QuicConnectionIdLength connection_id_length,
|
| - bool include_version,
|
| - bool include_path_id,
|
| - bool include_diversification_nonce,
|
| - QuicPacketNumberLength packet_number_length,
|
| - QuicStreamOffset offset) {
|
| - return GetPacketHeaderSize(version, connection_id_length, include_version,
|
| - include_path_id, include_diversification_nonce,
|
| - packet_number_length) +
|
| - // Assumes this is a stream with a single lone packet.
|
| - QuicFramer::GetMinStreamFrameSize(1u, offset, true);
|
| -}
|
| -
|
| -void QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
|
| - QuicIOVector iov,
|
| - size_t iov_offset,
|
| - QuicStreamOffset offset,
|
| - bool fin,
|
| - QuicFrame* frame) {
|
| - DCHECK_GT(max_packet_length_,
|
| - StreamFramePacketOverhead(framer_->version(), connection_id_length_,
|
| - kIncludeVersion, kIncludePathId,
|
| - IncludeNonceInPublicHeader(),
|
| - PACKET_6BYTE_PACKET_NUMBER, offset));
|
| -
|
| - if (!FLAGS_quic_simple_packet_number_length) {
|
| - MaybeUpdatePacketNumberLength();
|
| - }
|
| - QUIC_BUG_IF(!HasRoomForStreamFrame(id, offset))
|
| - << "No room for Stream frame, BytesFree: " << BytesFree()
|
| - << " MinStreamFrameSize: "
|
| - << QuicFramer::GetMinStreamFrameSize(id, offset, true);
|
| -
|
| - if (iov_offset == iov.total_length) {
|
| - QUIC_BUG_IF(!fin) << "Creating a stream frame with no data or fin.";
|
| - // Create a new packet for the fin, if necessary.
|
| - *frame = QuicFrame(new QuicStreamFrame(id, true, offset, StringPiece()));
|
| - return;
|
| - }
|
| -
|
| - const size_t data_size = iov.total_length - iov_offset;
|
| - size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
|
| - id, offset, /* last_frame_in_packet= */ true);
|
| - size_t bytes_consumed = min<size_t>(BytesFree() - min_frame_size, data_size);
|
| -
|
| - bool set_fin = fin && bytes_consumed == data_size; // Last frame.
|
| - UniqueStreamBuffer buffer =
|
| - NewStreamBuffer(buffer_allocator_, bytes_consumed);
|
| - CopyToBuffer(iov, iov_offset, bytes_consumed, buffer.get());
|
| - *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, bytes_consumed,
|
| - std::move(buffer)));
|
| -}
|
| -
|
| -// static
|
| -void QuicPacketCreator::CopyToBuffer(QuicIOVector iov,
|
| - size_t iov_offset,
|
| - size_t length,
|
| - char* buffer) {
|
| - int iovnum = 0;
|
| - while (iovnum < iov.iov_count && iov_offset >= iov.iov[iovnum].iov_len) {
|
| - iov_offset -= iov.iov[iovnum].iov_len;
|
| - ++iovnum;
|
| - }
|
| - DCHECK_LE(iovnum, iov.iov_count);
|
| - DCHECK_LE(iov_offset, iov.iov[iovnum].iov_len);
|
| - if (iovnum >= iov.iov_count || length == 0) {
|
| - return;
|
| - }
|
| -
|
| - // Unroll the first iteration that handles iov_offset.
|
| - const size_t iov_available = iov.iov[iovnum].iov_len - iov_offset;
|
| - size_t copy_len = min(length, iov_available);
|
| -
|
| - // Try to prefetch the next iov if there is at least one more after the
|
| - // current. Otherwise, it looks like an irregular access that the hardware
|
| - // prefetcher won't speculatively prefetch. Only prefetch one iov because
|
| - // generally, the iov_offset is not 0, input iov consists of 2K buffers and
|
| - // the output buffer is ~1.4K.
|
| - if (copy_len == iov_available && iovnum + 1 < iov.iov_count) {
|
| - // TODO(ckrasic) - this is unused without prefetch()
|
| - // char* next_base = static_cast<char*>(iov.iov[iovnum + 1].iov_base);
|
| - // char* next_base = static_cast<char*>(iov.iov[iovnum + 1].iov_base);
|
| - // Prefetch 2 cachelines worth of data to get the prefetcher started; leave
|
| - // it to the hardware prefetcher after that.
|
| - // TODO(ckrasic) - investigate what to do about prefetch directives.
|
| - // prefetch(next_base, PREFETCH_HINT_T0);
|
| - if (iov.iov[iovnum + 1].iov_len >= 64) {
|
| - // TODO(ckrasic) - investigate what to do about prefetch directives.
|
| - // prefetch(next_base + CACHELINE_SIZE, PREFETCH_HINT_T0);
|
| - }
|
| - }
|
| -
|
| - const char* src = static_cast<char*>(iov.iov[iovnum].iov_base) + iov_offset;
|
| - while (true) {
|
| - memcpy(buffer, src, copy_len);
|
| - length -= copy_len;
|
| - buffer += copy_len;
|
| - if (length == 0 || ++iovnum >= iov.iov_count) {
|
| - break;
|
| - }
|
| - src = static_cast<char*>(iov.iov[iovnum].iov_base);
|
| - copy_len = min(length, iov.iov[iovnum].iov_len);
|
| - }
|
| - QUIC_BUG_IF(length > 0) << "Failed to copy entire length to buffer.";
|
| -}
|
| -
|
| -void QuicPacketCreator::ReserializeAllFrames(
|
| - const PendingRetransmission& retransmission,
|
| - char* buffer,
|
| - size_t buffer_len) {
|
| - DCHECK(queued_frames_.empty());
|
| - DCHECK_EQ(0, packet_.num_padding_bytes);
|
| - QUIC_BUG_IF(retransmission.retransmittable_frames.empty())
|
| - << "Attempt to serialize empty packet";
|
| - const QuicPacketNumberLength saved_length = packet_.packet_number_length;
|
| - const QuicPacketNumberLength saved_next_length = next_packet_number_length_;
|
| - const EncryptionLevel default_encryption_level = packet_.encryption_level;
|
| -
|
| - // Temporarily set the packet number length and change the encryption level.
|
| - packet_.packet_number_length = retransmission.packet_number_length;
|
| - if (!FLAGS_quic_simple_packet_number_length) {
|
| - next_packet_number_length_ = retransmission.packet_number_length;
|
| - }
|
| - packet_.num_padding_bytes = retransmission.num_padding_bytes;
|
| - // Only preserve the original encryption level if it's a handshake packet or
|
| - // if we haven't gone forward secure.
|
| - if (retransmission.has_crypto_handshake ||
|
| - packet_.encryption_level != ENCRYPTION_FORWARD_SECURE) {
|
| - packet_.encryption_level = retransmission.encryption_level;
|
| - }
|
| -
|
| - // Serialize the packet and restore packet number length state.
|
| - for (const QuicFrame& frame : retransmission.retransmittable_frames) {
|
| - bool success = AddFrame(frame, false);
|
| - LOG_IF(DFATAL, !success)
|
| - << " Failed to add frame of type:" << frame.type
|
| - << " num_frames:" << retransmission.retransmittable_frames.size()
|
| - << " retransmission.packet_number_length:"
|
| - << retransmission.packet_number_length
|
| - << " packet_.packet_number_length:" << packet_.packet_number_length;
|
| - }
|
| - SerializePacket(buffer, buffer_len);
|
| - packet_.original_path_id = retransmission.path_id;
|
| - packet_.original_packet_number = retransmission.packet_number;
|
| - packet_.transmission_type = retransmission.transmission_type;
|
| - OnSerializedPacket();
|
| - // Restore old values.
|
| - if (!FLAGS_quic_simple_packet_number_length) {
|
| - // OnSerializedPacket updates the packet_number_length, so it's incorrect to
|
| - // restore it here.
|
| - packet_.packet_number_length = saved_length;
|
| - next_packet_number_length_ = saved_next_length;
|
| - }
|
| - packet_.encryption_level = default_encryption_level;
|
| -}
|
| -
|
| -void QuicPacketCreator::Flush() {
|
| - if (!HasPendingFrames()) {
|
| - return;
|
| - }
|
| -
|
| - // TODO(rtenneti): Change the default 64 alignas value (used the default
|
| - // value from CACHELINE_SIZE).
|
| - ALIGNAS(64) char seralized_packet_buffer[kMaxPacketSize];
|
| - SerializePacket(seralized_packet_buffer, kMaxPacketSize);
|
| - OnSerializedPacket();
|
| -}
|
| -
|
| -void QuicPacketCreator::OnSerializedPacket() {
|
| - if (packet_.encrypted_buffer == nullptr) {
|
| - const string error_details = "Failed to SerializePacket.";
|
| - QUIC_BUG << error_details;
|
| - delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
|
| - error_details,
|
| - ConnectionCloseSource::FROM_SELF);
|
| - return;
|
| - }
|
| -
|
| - delegate_->OnSerializedPacket(&packet_);
|
| - ClearPacket();
|
| - // Maximum packet size may be only enacted while no packet is currently being
|
| - // constructed, so here we have a good opportunity to actually change it.
|
| - if (CanSetMaxPacketLength()) {
|
| - SetMaxPacketLength(max_packet_length_);
|
| - }
|
| -}
|
| -
|
| -void QuicPacketCreator::ClearPacket() {
|
| - packet_.has_ack = false;
|
| - packet_.has_stop_waiting = false;
|
| - packet_.has_crypto_handshake = NOT_HANDSHAKE;
|
| - packet_.num_padding_bytes = 0;
|
| - packet_.original_path_id = kInvalidPathId;
|
| - packet_.original_packet_number = 0;
|
| - packet_.transmission_type = NOT_RETRANSMISSION;
|
| - packet_.encrypted_buffer = nullptr;
|
| - packet_.encrypted_length = 0;
|
| - DCHECK(packet_.retransmittable_frames.empty());
|
| - packet_.listeners.clear();
|
| -}
|
| -
|
| -void QuicPacketCreator::CreateAndSerializeStreamFrame(
|
| - QuicStreamId id,
|
| - const QuicIOVector& iov,
|
| - QuicStreamOffset iov_offset,
|
| - QuicStreamOffset stream_offset,
|
| - bool fin,
|
| - QuicAckListenerInterface* listener,
|
| - char* encrypted_buffer,
|
| - size_t encrypted_buffer_len,
|
| - size_t* num_bytes_consumed) {
|
| - DCHECK(queued_frames_.empty());
|
| - // Write out the packet header
|
| - QuicPacketHeader header;
|
| - FillPacketHeader(&header);
|
| - QuicDataWriter writer(kMaxPacketSize, encrypted_buffer);
|
| - if (!framer_->AppendPacketHeader(header, &writer)) {
|
| - QUIC_BUG << "AppendPacketHeader failed";
|
| - return;
|
| - }
|
| -
|
| - // Create a Stream frame with the remaining space.
|
| - QUIC_BUG_IF(iov_offset == iov.total_length && !fin)
|
| - << "Creating a stream frame with no data or fin.";
|
| - const size_t remaining_data_size = iov.total_length - iov_offset;
|
| - const size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
|
| - id, stream_offset, /* last_frame_in_packet= */ true);
|
| - const size_t available_size =
|
| - max_plaintext_size_ - writer.length() - min_frame_size;
|
| - const size_t bytes_consumed =
|
| - min<size_t>(available_size, remaining_data_size);
|
| -
|
| - const bool set_fin = fin && (bytes_consumed == remaining_data_size);
|
| - UniqueStreamBuffer stream_buffer =
|
| - NewStreamBuffer(buffer_allocator_, bytes_consumed);
|
| - CopyToBuffer(iov, iov_offset, bytes_consumed, stream_buffer.get());
|
| - std::unique_ptr<QuicStreamFrame> frame(new QuicStreamFrame(
|
| - id, set_fin, stream_offset, bytes_consumed, std::move(stream_buffer)));
|
| -
|
| - // TODO(ianswett): AppendTypeByte and AppendStreamFrame could be optimized
|
| - // into one method that takes a QuicStreamFrame, if warranted.
|
| - if (!framer_->AppendTypeByte(QuicFrame(frame.get()),
|
| - /* no stream frame length */ true, &writer)) {
|
| - QUIC_BUG << "AppendTypeByte failed";
|
| - return;
|
| - }
|
| - if (!framer_->AppendStreamFrame(*frame, /* no stream frame length */ true,
|
| - &writer)) {
|
| - QUIC_BUG << "AppendStreamFrame failed";
|
| - return;
|
| - }
|
| -
|
| - size_t encrypted_length = framer_->EncryptInPlace(
|
| - packet_.encryption_level, packet_.path_id, packet_.packet_number,
|
| - GetStartOfEncryptedData(framer_->version(), header), writer.length(),
|
| - encrypted_buffer_len, encrypted_buffer);
|
| - if (encrypted_length == 0) {
|
| - QUIC_BUG << "Failed to encrypt packet number " << header.packet_number;
|
| - return;
|
| - }
|
| - // TODO(ianswett): Optimize the storage so RetransmitableFrames can be
|
| - // unioned with a QuicStreamFrame and a UniqueStreamBuffer.
|
| - *num_bytes_consumed = bytes_consumed;
|
| - packet_size_ = 0;
|
| - packet_.entropy_hash = QuicFramer::GetPacketEntropyHash(header);
|
| - packet_.encrypted_buffer = encrypted_buffer;
|
| - packet_.encrypted_length = encrypted_length;
|
| - if (listener != nullptr) {
|
| - packet_.listeners.emplace_back(listener, bytes_consumed);
|
| - }
|
| - packet_.retransmittable_frames.push_back(QuicFrame(frame.release()));
|
| - OnSerializedPacket();
|
| -}
|
| -
|
| -bool QuicPacketCreator::HasPendingFrames() const {
|
| - return !queued_frames_.empty();
|
| -}
|
| -
|
| -bool QuicPacketCreator::HasPendingRetransmittableFrames() const {
|
| - return !packet_.retransmittable_frames.empty();
|
| -}
|
| -
|
| -size_t QuicPacketCreator::ExpansionOnNewFrame() const {
|
| - // If the last frame in the packet is a stream frame, then it will expand to
|
| - // include the stream_length field when a new frame is added.
|
| - bool has_trailing_stream_frame =
|
| - !queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME;
|
| - return has_trailing_stream_frame ? kQuicStreamPayloadLengthSize : 0;
|
| -}
|
| -
|
| -size_t QuicPacketCreator::BytesFree() {
|
| - DCHECK_GE(max_plaintext_size_, PacketSize());
|
| - return max_plaintext_size_ -
|
| - min(max_plaintext_size_, PacketSize() + ExpansionOnNewFrame());
|
| -}
|
| -
|
| -size_t QuicPacketCreator::PacketSize() {
|
| - if (!queued_frames_.empty()) {
|
| - return packet_size_;
|
| - }
|
| - // Update packet number length on packet boundary.
|
| - if (!FLAGS_quic_simple_packet_number_length) {
|
| - packet_.packet_number_length = next_packet_number_length_;
|
| - }
|
| - packet_size_ = GetPacketHeaderSize(
|
| - framer_->version(), connection_id_length_, send_version_in_packet_,
|
| - send_path_id_in_packet_, IncludeNonceInPublicHeader(),
|
| - packet_.packet_number_length);
|
| - return packet_size_;
|
| -}
|
| -
|
| -bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) {
|
| - return AddFrame(frame, /*save_retransmittable_frames=*/true);
|
| -}
|
| -
|
| -bool QuicPacketCreator::AddPaddedSavedFrame(const QuicFrame& frame) {
|
| - if (AddFrame(frame, /*save_retransmittable_frames=*/true)) {
|
| - packet_.num_padding_bytes = -1;
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -void QuicPacketCreator::AddAckListener(QuicAckListenerInterface* listener,
|
| - QuicPacketLength length) {
|
| - DCHECK(!queued_frames_.empty());
|
| - packet_.listeners.emplace_back(listener, length);
|
| -}
|
| -
|
| -void QuicPacketCreator::SerializePacket(char* encrypted_buffer,
|
| - size_t encrypted_buffer_len) {
|
| - DCHECK_LT(0u, encrypted_buffer_len);
|
| - QUIC_BUG_IF(queued_frames_.empty()) << "Attempt to serialize empty packet";
|
| - QuicPacketHeader header;
|
| - // FillPacketHeader increments packet_number_.
|
| - FillPacketHeader(&header);
|
| -
|
| - MaybeAddPadding();
|
| -
|
| - DCHECK_GE(max_plaintext_size_, packet_size_);
|
| - // Use the packet_size_ instead of the buffer size to ensure smaller
|
| - // packet sizes are properly used.
|
| - size_t length = framer_->BuildDataPacket(header, queued_frames_,
|
| - encrypted_buffer, packet_size_);
|
| - if (length == 0) {
|
| - QUIC_BUG << "Failed to serialize " << queued_frames_.size() << " frames.";
|
| - return;
|
| - }
|
| -
|
| - // ACK Frames will be truncated due to length only if they're the only frame
|
| - // in the packet, and if packet_size_ was set to max_plaintext_size_. If
|
| - // truncation due to length occurred, then GetSerializedFrameLength will have
|
| - // returned all bytes free.
|
| - bool possibly_truncated_by_length = packet_size_ == max_plaintext_size_ &&
|
| - queued_frames_.size() == 1 &&
|
| - queued_frames_.back().type == ACK_FRAME;
|
| - // Because of possible truncation, we can't be confident that our
|
| - // packet size calculation worked correctly.
|
| - if (!possibly_truncated_by_length) {
|
| - DCHECK_EQ(packet_size_, length);
|
| - }
|
| - const size_t encrypted_length = framer_->EncryptInPlace(
|
| - packet_.encryption_level, packet_.path_id, packet_.packet_number,
|
| - GetStartOfEncryptedData(framer_->version(), header), length,
|
| - encrypted_buffer_len, encrypted_buffer);
|
| - if (encrypted_length == 0) {
|
| - QUIC_BUG << "Failed to encrypt packet number " << packet_.packet_number;
|
| - return;
|
| - }
|
| -
|
| - packet_size_ = 0;
|
| - queued_frames_.clear();
|
| - packet_.entropy_hash = QuicFramer::GetPacketEntropyHash(header);
|
| - packet_.encrypted_buffer = encrypted_buffer;
|
| - packet_.encrypted_length = encrypted_length;
|
| -}
|
| -
|
| -QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
|
| - const QuicVersionVector& supported_versions) {
|
| - DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
|
| - QuicEncryptedPacket* encrypted = QuicFramer::BuildVersionNegotiationPacket(
|
| - connection_id_, supported_versions);
|
| - DCHECK(encrypted);
|
| - DCHECK_GE(max_packet_length_, encrypted->length());
|
| - return encrypted;
|
| -}
|
| -
|
| -// TODO(jri): Make this a public method of framer?
|
| -SerializedPacket QuicPacketCreator::NoPacket() {
|
| - return SerializedPacket(kInvalidPathId, 0, PACKET_1BYTE_PACKET_NUMBER,
|
| - nullptr, 0, 0, false, false);
|
| -}
|
| -
|
| -void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
|
| - header->public_header.connection_id = connection_id_;
|
| - header->public_header.connection_id_length = connection_id_length_;
|
| - header->public_header.multipath_flag = send_path_id_in_packet_;
|
| - header->public_header.reset_flag = false;
|
| - header->public_header.version_flag = send_version_in_packet_;
|
| - if (IncludeNonceInPublicHeader()) {
|
| - DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective());
|
| - header->public_header.nonce = &diversification_nonce_;
|
| - } else {
|
| - header->public_header.nonce = nullptr;
|
| - }
|
| - header->path_id = packet_.path_id;
|
| - header->packet_number = ++packet_.packet_number;
|
| - header->public_header.packet_number_length = packet_.packet_number_length;
|
| - header->entropy_flag = random_bool_source_.RandBool();
|
| -}
|
| -
|
| -bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
|
| - switch (frame.type) {
|
| - case ACK_FRAME:
|
| - case PADDING_FRAME:
|
| - case STOP_WAITING_FRAME:
|
| - case MTU_DISCOVERY_FRAME:
|
| - return false;
|
| - default:
|
| - return true;
|
| - }
|
| -}
|
| -
|
| -bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
|
| - bool save_retransmittable_frames) {
|
| - DVLOG(1) << "Adding frame: " << frame;
|
| - if (FLAGS_quic_never_write_unencrypted_data && frame.type == STREAM_FRAME &&
|
| - frame.stream_frame->stream_id != kCryptoStreamId &&
|
| - packet_.encryption_level == ENCRYPTION_NONE) {
|
| - const string error_details = "Cannot send stream data without encryption.";
|
| - QUIC_BUG << error_details;
|
| - delegate_->OnUnrecoverableError(
|
| - QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA, error_details,
|
| - ConnectionCloseSource::FROM_SELF);
|
| - return false;
|
| - }
|
| - if (!FLAGS_quic_simple_packet_number_length) {
|
| - MaybeUpdatePacketNumberLength();
|
| - }
|
| - size_t frame_len = framer_->GetSerializedFrameLength(
|
| - frame, BytesFree(), queued_frames_.empty(), true,
|
| - packet_.packet_number_length);
|
| - if (frame_len == 0) {
|
| - // Current open packet is full.
|
| - Flush();
|
| - return false;
|
| - }
|
| - DCHECK_LT(0u, packet_size_);
|
| - packet_size_ += ExpansionOnNewFrame() + frame_len;
|
| -
|
| - if (save_retransmittable_frames && ShouldRetransmit(frame)) {
|
| - if (packet_.retransmittable_frames.empty()) {
|
| - packet_.retransmittable_frames.reserve(2);
|
| - }
|
| - packet_.retransmittable_frames.push_back(frame);
|
| - queued_frames_.push_back(frame);
|
| - if (frame.type == STREAM_FRAME &&
|
| - frame.stream_frame->stream_id == kCryptoStreamId) {
|
| - packet_.has_crypto_handshake = IS_HANDSHAKE;
|
| - }
|
| - } else {
|
| - queued_frames_.push_back(frame);
|
| - }
|
| -
|
| - if (frame.type == ACK_FRAME) {
|
| - packet_.has_ack = true;
|
| - }
|
| - if (frame.type == STOP_WAITING_FRAME) {
|
| - packet_.has_stop_waiting = true;
|
| - }
|
| - if (debug_delegate_ != nullptr) {
|
| - debug_delegate_->OnFrameAddedToPacket(frame);
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void QuicPacketCreator::MaybeAddPadding() {
|
| - if (packet_.num_padding_bytes == 0) {
|
| - return;
|
| - }
|
| -
|
| - if (BytesFree() == 0) {
|
| - // Don't pad full packets.
|
| - return;
|
| - }
|
| -
|
| - bool success =
|
| - AddFrame(QuicFrame(QuicPaddingFrame(packet_.num_padding_bytes)), false);
|
| - DCHECK(success);
|
| -}
|
| -
|
| -void QuicPacketCreator::SetCurrentPath(
|
| - QuicPathId path_id,
|
| - QuicPacketNumber least_packet_awaited_by_peer,
|
| - QuicPacketCount max_packets_in_flight) {
|
| - if (packet_.path_id == path_id) {
|
| - return;
|
| - }
|
| -
|
| - if (HasPendingFrames()) {
|
| - QUIC_BUG << "Unable to change paths when a packet is under construction.";
|
| - return;
|
| - }
|
| - // Save current packet number and load switching path's packet number.
|
| - multipath_packet_number_[packet_.path_id] = packet_.packet_number;
|
| - std::unordered_map<QuicPathId, QuicPacketNumber>::iterator it =
|
| - multipath_packet_number_.find(path_id);
|
| - // If path_id is not in the map, it's a new path. Set packet_number to 0.
|
| - packet_.packet_number = it == multipath_packet_number_.end() ? 0 : it->second;
|
| - packet_.path_id = path_id;
|
| - DCHECK(packet_.path_id != kInvalidPathId);
|
| - // Send path in packet if current path is not the default path.
|
| - send_path_id_in_packet_ = packet_.path_id != kDefaultPathId ? true : false;
|
| - // Switching path needs to update packet number length.
|
| - UpdatePacketNumberLength(least_packet_awaited_by_peer, max_packets_in_flight);
|
| -}
|
| -
|
| -bool QuicPacketCreator::IncludeNonceInPublicHeader() {
|
| - return have_diversification_nonce_ &&
|
| - packet_.encryption_level == ENCRYPTION_INITIAL;
|
| -}
|
| -
|
| -QuicPacketCreator::QuicRandomBoolSource::QuicRandomBoolSource(
|
| - QuicRandom* random)
|
| - : random_(random), bit_bucket_(0), bit_mask_(0) {}
|
| -
|
| -QuicPacketCreator::QuicRandomBoolSource::~QuicRandomBoolSource() {}
|
| -
|
| -bool QuicPacketCreator::QuicRandomBoolSource::RandBool() {
|
| - if (bit_mask_ == 0) {
|
| - bit_bucket_ = random_->RandUint64();
|
| - bit_mask_ = 1;
|
| - }
|
| - bool result = ((bit_bucket_ & bit_mask_) != 0);
|
| - bit_mask_ <<= 1;
|
| - return result;
|
| -}
|
| -
|
| -} // namespace net
|
|
|