// 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 "quiche/quic/core/quic_packet_creator.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <optional>
#include <string>
#include <utility>

#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/crypto_protocol.h"
#include "quiche/quic/core/frames/quic_frame.h"
#include "quiche/quic/core/frames/quic_padding_frame.h"
#include "quiche/quic/core/frames/quic_path_challenge_frame.h"
#include "quiche/quic/core/frames/quic_stream_frame.h"
#include "quiche/quic/core/quic_chaos_protector.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/core/quic_data_writer.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
#include "quiche/quic/platform/api/quic_exported_stats.h"
#include "quiche/quic/platform/api/quic_flag_utils.h"
#include "quiche/quic/platform/api/quic_flags.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_server_stats.h"
#include "quiche/common/print_elements.h"

namespace quic {
namespace {

QuicLongHeaderType EncryptionlevelToLongHeaderType(EncryptionLevel level) {
  switch (level) {
    case ENCRYPTION_INITIAL:
      return INITIAL;
    case ENCRYPTION_HANDSHAKE:
      return HANDSHAKE;
    case ENCRYPTION_ZERO_RTT:
      return ZERO_RTT_PROTECTED;
    case ENCRYPTION_FORWARD_SECURE:
      QUIC_BUG(quic_bug_12398_1)
          << "Try to derive long header type for packet with encryption level: "
          << level;
      return INVALID_PACKET_TYPE;
    default:
      QUIC_BUG(quic_bug_10752_1) << level;
      return INVALID_PACKET_TYPE;
  }
}

void LogCoalesceStreamFrameStatus(bool success) {
  QUIC_HISTOGRAM_BOOL("QuicSession.CoalesceStreamFrameStatus", success,
                      "Success rate of coalesing stream frames attempt.");
}

// ScopedPacketContextSwitcher saves |packet|'s states and change states
// during its construction. When the switcher goes out of scope, it restores
// saved states.
class ScopedPacketContextSwitcher {
 public:
  ScopedPacketContextSwitcher(QuicPacketNumber packet_number,
                              QuicPacketNumberLength packet_number_length,
                              EncryptionLevel encryption_level,
                              SerializedPacket* packet)

      : saved_packet_number_(packet->packet_number),
        saved_packet_number_length_(packet->packet_number_length),
        saved_encryption_level_(packet->encryption_level),
        packet_(packet) {
    packet_->packet_number = packet_number,
    packet_->packet_number_length = packet_number_length;
    packet_->encryption_level = encryption_level;
  }

  ~ScopedPacketContextSwitcher() {
    packet_->packet_number = saved_packet_number_;
    packet_->packet_number_length = saved_packet_number_length_;
    packet_->encryption_level = saved_encryption_level_;
  }

 private:
  const QuicPacketNumber saved_packet_number_;
  const QuicPacketNumberLength saved_packet_number_length_;
  const EncryptionLevel saved_encryption_level_;
  SerializedPacket* packet_;
};

}  // namespace

#define ENDPOINT \
  (framer_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")

QuicPacketCreator::QuicPacketCreator(QuicConnectionId server_connection_id,
                                     QuicFramer* framer,
                                     DelegateInterface* delegate)
    : QuicPacketCreator(server_connection_id, framer, QuicRandom::GetInstance(),
                        delegate) {}

QuicPacketCreator::QuicPacketCreator(QuicConnectionId server_connection_id,
                                     QuicFramer* framer, QuicRandom* random,
                                     DelegateInterface* delegate)
    : delegate_(delegate),
      debug_delegate_(nullptr),
      framer_(framer),
      random_(random),
      have_diversification_nonce_(false),
      max_packet_length_(0),
      next_max_packet_length_(0),
      server_connection_id_included_(CONNECTION_ID_PRESENT),
      packet_size_(0),
      server_connection_id_(server_connection_id),
      client_connection_id_(EmptyQuicConnectionId()),
      packet_(QuicPacketNumber(), PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false,
              false),
      pending_padding_bytes_(0),
      needs_full_padding_(false),
      next_transmission_type_(NOT_RETRANSMISSION),
      flusher_attached_(false),
      fully_pad_crypto_handshake_packets_(true),
      latched_hard_max_packet_length_(0),
      max_datagram_frame_size_(0) {
  SetMaxPacketLength(kDefaultMaxPacketSize);
  if (!framer_->version().UsesTls()) {
    // QUIC+TLS negotiates the maximum datagram frame size via the
    // IETF QUIC max_datagram_frame_size transport parameter.
    // QUIC_CRYPTO however does not negotiate this so we set its value here.
    SetMaxDatagramFrameSize(kMaxAcceptedDatagramFrameSize);
  }
}

QuicPacketCreator::~QuicPacketCreator() {
  DeleteFrames(&packet_.retransmittable_frames);
}

void QuicPacketCreator::SetEncrypter(EncryptionLevel level,
                                     std::unique_ptr<QuicEncrypter> encrypter) {
  framer_->SetEncrypter(level, std::move(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) {
  if (!GetQuicRestartFlag(quic_allow_control_frames_while_procesing)) {
    QUICHE_DCHECK(CanSetMaxPacketLength()) << ENDPOINT;
  } else {
    QUIC_RESTART_FLAG_COUNT_N(quic_allow_control_frames_while_procesing, 2, 3);
    if (!CanSetMaxPacketLength()) {
      QUIC_RESTART_FLAG_COUNT_N(quic_allow_control_frames_while_procesing, 3,
                                3);
      // The new max packet length will be applied to the next packet.
      next_max_packet_length_ = length;
      return;
    }
  }
  // Avoid recomputing |max_plaintext_size_| if the length does not actually
  // change.
  if (length == max_packet_length_) {
    return;
  }
  QUIC_DVLOG(1) << ENDPOINT << "Updating packet creator max packet length from "
                << max_packet_length_ << " to " << length;

  max_packet_length_ = length;
  max_plaintext_size_ = framer_->GetMaxPlaintextSize(max_packet_length_);
  QUIC_BUG_IF(
      quic_bug_12398_2,
      max_plaintext_size_ - PacketHeaderSize() <
          MinPlaintextPacketSize(framer_->version(), GetPacketNumberLength()))
      << ENDPOINT << "Attempted to set max packet length too small";
}

void QuicPacketCreator::SetMaxDatagramFrameSize(
    QuicByteCount max_datagram_frame_size) {
  constexpr QuicByteCount upper_bound =
      std::min<QuicByteCount>(std::numeric_limits<QuicPacketLength>::max(),
                              std::numeric_limits<size_t>::max());
  if (max_datagram_frame_size > upper_bound) {
    // A value of |max_datagram_frame_size| that is equal or greater than
    // 2^16-1 is effectively infinite because QUIC packets cannot be that large.
    // We therefore clamp the value here to allow us to safely cast
    // |max_datagram_frame_size_| to QuicPacketLength or size_t.
    max_datagram_frame_size = upper_bound;
  }
  max_datagram_frame_size_ = max_datagram_frame_size;
}

void QuicPacketCreator::SetSoftMaxPacketLength(QuicByteCount length) {
  QUICHE_DCHECK(CanSetMaxPacketLength()) << ENDPOINT;
  if (length > max_packet_length_) {
    QUIC_BUG(quic_bug_10752_2)
        << ENDPOINT
        << "Try to increase max_packet_length_ in "
           "SetSoftMaxPacketLength, use SetMaxPacketLength instead.";
    return;
  }
  if (framer_->GetMaxPlaintextSize(length) <
      PacketHeaderSize() +
          MinPlaintextPacketSize(framer_->version(), GetPacketNumberLength())) {
    // Please note: this would not guarantee to fit next packet if the size of
    // packet header increases (e.g., encryption level changes).
    QUIC_DLOG(INFO) << ENDPOINT << length
                    << " is too small to fit packet header";
    RemoveSoftMaxPacketLength();
    return;
  }
  QUIC_DVLOG(1) << ENDPOINT << "Setting soft max packet length to: " << length;
  latched_hard_max_packet_length_ = max_packet_length_;
  max_packet_length_ = length;
  max_plaintext_size_ = framer_->GetMaxPlaintextSize(length);
}

void QuicPacketCreator::SetDiversificationNonce(
    const DiversificationNonce& nonce) {
  QUICHE_DCHECK(!have_diversification_nonce_) << ENDPOINT;
  have_diversification_nonce_ = true;
  diversification_nonce_ = nonce;
}

void QuicPacketCreator::UpdatePacketNumberLength(
    QuicPacketNumber least_packet_awaited_by_peer,
    QuicPacketCount max_packets_in_flight) {
  if (!queued_frames_.empty()) {
    // Don't change creator state if there are frames queued.
    QUIC_BUG(quic_bug_10752_3)
        << ENDPOINT << "Called UpdatePacketNumberLength with "
        << queued_frames_.size()
        << " queued_frames.  First frame type:" << queued_frames_.front().type
        << " last frame type:" << queued_frames_.back().type;
    return;
  }

  const QuicPacketNumber next_packet_number = NextSendingPacketNumber();
  QUICHE_DCHECK_LE(least_packet_awaited_by_peer, next_packet_number)
      << ENDPOINT;
  const uint64_t current_delta =
      next_packet_number - least_packet_awaited_by_peer;
  const uint64_t delta = std::max(current_delta, max_packets_in_flight);
  const QuicPacketNumberLength packet_number_length =
      QuicFramer::GetMinPacketNumberLength(QuicPacketNumber(delta * 4));
  if (packet_.packet_number_length == packet_number_length) {
    return;
  }
  QUIC_DVLOG(1) << ENDPOINT << "Updating packet number length from "
                << static_cast<int>(packet_.packet_number_length) << " to "
                << static_cast<int>(packet_number_length)
                << ", least_packet_awaited_by_peer: "
                << least_packet_awaited_by_peer
                << " max_packets_in_flight: " << max_packets_in_flight
                << " next_packet_number: " << next_packet_number;
  packet_.packet_number_length = packet_number_length;
}

void QuicPacketCreator::SkipNPacketNumbers(
    QuicPacketCount count, QuicPacketNumber least_packet_awaited_by_peer,
    QuicPacketCount max_packets_in_flight) {
  if (!queued_frames_.empty()) {
    // Don't change creator state if there are frames queued.
    QUIC_BUG(quic_bug_10752_4)
        << ENDPOINT << "Called SkipNPacketNumbers with "
        << queued_frames_.size()
        << " queued_frames.  First frame type:" << queued_frames_.front().type
        << " last frame type:" << queued_frames_.back().type;
    return;
  }
  if (packet_.packet_number > packet_.packet_number + count) {
    // Skipping count packet numbers causes packet number wrapping around,
    // reject it.
    QUIC_LOG(WARNING) << ENDPOINT << "Skipping " << count
                      << " packet numbers causes packet number wrapping "
                         "around, least_packet_awaited_by_peer: "
                      << least_packet_awaited_by_peer
                      << " packet_number:" << packet_.packet_number;
    return;
  }
  packet_.packet_number += count;
  // Packet number changes, update packet number length if necessary.
  UpdatePacketNumberLength(least_packet_awaited_by_peer, max_packets_in_flight);
}

bool QuicPacketCreator::ConsumeCryptoDataToFillCurrentPacket(
    EncryptionLevel level, size_t write_length, QuicStreamOffset offset,
    bool needs_full_padding, TransmissionType transmission_type,
    QuicFrame* frame) {
  QUIC_DVLOG(2) << ENDPOINT << "ConsumeCryptoDataToFillCurrentPacket " << level
                << " write_length " << write_length << " offset " << offset
                << (needs_full_padding ? " needs_full_padding" : "") << " "
                << transmission_type;
  if (!CreateCryptoFrame(level, write_length, offset, frame)) {
    return false;
  }
  // When crypto data was sent in stream frames, ConsumeData is called with
  // |needs_full_padding = true|. Keep the same behavior here when sending
  // crypto frames.
  //
  // TODO(nharper): Check what the IETF drafts say about padding out initial
  // messages and change this as appropriate.
  if (needs_full_padding) {
    needs_full_padding_ = true;
  }
  return AddFrame(*frame, transmission_type);
}

bool QuicPacketCreator::ConsumeDataToFillCurrentPacket(
    QuicStreamId id, size_t data_size, QuicStreamOffset offset, bool fin,
    bool needs_full_padding, TransmissionType transmission_type,
    QuicFrame* frame) {
  if (!HasRoomForStreamFrame(id, offset, data_size)) {
    return false;
  }
  CreateStreamFrame(id, data_size, offset, fin, frame);
  // Explicitly disallow multi-packet CHLOs.
  if (GetQuicFlag(quic_enforce_single_packet_chlo) &&
      StreamFrameIsClientHello(frame->stream_frame) &&
      frame->stream_frame.data_length < data_size) {
    const std::string error_details =
        "Client hello won't fit in a single packet.";
    QUIC_BUG(quic_bug_10752_5)
        << ENDPOINT << error_details << " Constructed stream frame length: "
        << frame->stream_frame.data_length << " CHLO length: " << data_size;
    delegate_->OnUnrecoverableError(QUIC_CRYPTO_CHLO_TOO_LARGE, error_details);
    return false;
  }
  if (!AddFrame(*frame, transmission_type)) {
    // Fails if we try to write unencrypted stream data.
    return false;
  }
  if (needs_full_padding) {
    needs_full_padding_ = true;
  }

  return true;
}

bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
                                              QuicStreamOffset offset,
                                              size_t data_size) {
  const size_t min_stream_frame_size = QuicFramer::GetMinStreamFrameSize(
      framer_->transport_version(), id, offset, /*last_frame_in_packet=*/true,
      data_size);
  if (BytesFree() > min_stream_frame_size) {
    return true;
  }
  if (!RemoveSoftMaxPacketLength()) {
    return false;
  }
  return BytesFree() > min_stream_frame_size;
}

bool QuicPacketCreator::HasRoomForMessageFrame(QuicByteCount length) {
  const size_t message_frame_size =
      QuicFramer::GetMessageFrameSize(/*last_frame_in_packet=*/true, length);
  if (static_cast<QuicByteCount>(message_frame_size) >
      max_datagram_frame_size_) {
    return false;
  }
  if (BytesFree() >= message_frame_size) {
    return true;
  }
  if (!RemoveSoftMaxPacketLength()) {
    return false;
  }
  return BytesFree() >= message_frame_size;
}

// static
size_t QuicPacketCreator::StreamFramePacketOverhead(
    QuicTransportVersion version, uint8_t destination_connection_id_length,
    uint8_t source_connection_id_length, bool include_version,
    bool include_diversification_nonce,
    QuicPacketNumberLength packet_number_length,
    quiche::QuicheVariableLengthIntegerLength retry_token_length_length,
    quiche::QuicheVariableLengthIntegerLength length_length,
    QuicStreamOffset offset) {
  return GetPacketHeaderSize(version, destination_connection_id_length,
                             source_connection_id_length, include_version,
                             include_diversification_nonce,
                             packet_number_length, retry_token_length_length, 0,
                             length_length) +

         // Assumes a packet with a single stream frame, which omits the length,
         // causing the data length argument to be ignored.
         QuicFramer::GetMinStreamFrameSize(version, 1u, offset, true,
                                           kMaxOutgoingPacketSize /* unused */);
}

void QuicPacketCreator::CreateStreamFrame(QuicStreamId id, size_t data_size,
                                          QuicStreamOffset offset, bool fin,
                                          QuicFrame* frame) {
  // Make sure max_packet_length_ is greater than the largest possible overhead
  // or max_packet_length_ is set to the soft limit.
  QUICHE_DCHECK(
      max_packet_length_ >
          StreamFramePacketOverhead(
              framer_->transport_version(), GetDestinationConnectionIdLength(),
              GetSourceConnectionIdLength(), kIncludeVersion,
              IncludeNonceInPublicHeader(), PACKET_6BYTE_PACKET_NUMBER,
              GetRetryTokenLengthLength(), GetLengthLength(), offset) ||
      latched_hard_max_packet_length_ > 0)
      << ENDPOINT;

  QUIC_BUG_IF(quic_bug_12398_3, !HasRoomForStreamFrame(id, offset, data_size))
      << ENDPOINT << "No room for Stream frame, BytesFree: " << BytesFree()
      << " MinStreamFrameSize: "
      << QuicFramer::GetMinStreamFrameSize(framer_->transport_version(), id,
                                           offset, true, data_size);

  QUIC_BUG_IF(quic_bug_12398_4, data_size == 0 && !fin)
      << ENDPOINT << "Creating a stream frame for stream ID:" << id
      << " with no data or fin.";
  size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
      framer_->transport_version(), id, offset,
      /* last_frame_in_packet= */ true, data_size);
  size_t bytes_consumed =
      std::min<size_t>(BytesFree() - min_frame_size, data_size);

  bool set_fin = fin && bytes_consumed == data_size;  // Last frame.
  *frame = QuicFrame(QuicStreamFrame(id, set_fin, offset, bytes_consumed));
}

bool QuicPacketCreator::CreateCryptoFrame(EncryptionLevel level,
                                          size_t write_length,
                                          QuicStreamOffset offset,
                                          QuicFrame* frame) {
  const size_t min_frame_size =
      QuicFramer::GetMinCryptoFrameSize(write_length, offset);
  if (BytesFree() <= min_frame_size &&
      (!RemoveSoftMaxPacketLength() || BytesFree() <= min_frame_size)) {
    return false;
  }
  size_t max_write_length = BytesFree() - min_frame_size;
  size_t bytes_consumed = std::min<size_t>(max_write_length, write_length);
  *frame = QuicFrame(new QuicCryptoFrame(level, offset, bytes_consumed));
  return true;
}

void QuicPacketCreator::FlushCurrentPacket() {
  if (!HasPendingFrames() && pending_padding_bytes_ == 0) {
    return;
  }

  ABSL_CACHELINE_ALIGNED char stack_buffer[kMaxOutgoingPacketSize];
  QuicOwnedPacketBuffer external_buffer(delegate_->GetPacketBuffer());

  if (external_buffer.buffer == nullptr) {
    external_buffer.buffer = stack_buffer;
    external_buffer.release_buffer = nullptr;
  }

  QUICHE_DCHECK_EQ(nullptr, packet_.encrypted_buffer) << ENDPOINT;
  if (!SerializePacket(std::move(external_buffer), kMaxOutgoingPacketSize,
                       /*allow_padding=*/true)) {
    return;
  }
  OnSerializedPacket();
}

void QuicPacketCreator::OnSerializedPacket() {
  QUIC_BUG_IF(quic_bug_12398_5, packet_.encrypted_buffer == nullptr)
      << ENDPOINT;

  // Clear bytes_not_retransmitted for packets containing only
  // NOT_RETRANSMISSION frames.
  if (packet_.transmission_type == NOT_RETRANSMISSION) {
    packet_.bytes_not_retransmitted.reset();
  }

  SerializedPacket packet(std::move(packet_));
  ClearPacket();
  RemoveSoftMaxPacketLength();
  delegate_->OnSerializedPacket(std::move(packet));
  if (next_max_packet_length_ != 0) {
    QUICHE_DCHECK(CanSetMaxPacketLength()) << ENDPOINT;
    SetMaxPacketLength(next_max_packet_length_);
    next_max_packet_length_ = 0;
  }
}

void QuicPacketCreator::ClearPacket() {
  packet_.has_ack = false;
  packet_.has_stop_waiting = false;
  packet_.has_ack_ecn = false;
  packet_.has_crypto_handshake = NOT_HANDSHAKE;
  packet_.transmission_type = NOT_RETRANSMISSION;
  packet_.encrypted_buffer = nullptr;
  packet_.encrypted_length = 0;
  packet_.has_ack_frequency = false;
  packet_.has_message = false;
  packet_.fate = SEND_TO_WRITER;
  QUIC_BUG_IF(quic_bug_12398_6, packet_.release_encrypted_buffer != nullptr)
      << ENDPOINT << "packet_.release_encrypted_buffer should be empty";
  packet_.release_encrypted_buffer = nullptr;
  QUICHE_DCHECK(packet_.retransmittable_frames.empty()) << ENDPOINT;
  QUICHE_DCHECK(packet_.nonretransmittable_frames.empty()) << ENDPOINT;
  packet_.largest_acked.Clear();
  needs_full_padding_ = false;
  packet_.bytes_not_retransmitted.reset();
  packet_.initial_header.reset();
}

size_t QuicPacketCreator::ReserializeInitialPacketInCoalescedPacket(
    const SerializedPacket& packet, size_t padding_size, char* buffer,
    size_t buffer_len) {
  QUIC_BUG_IF(quic_bug_12398_7, packet.encryption_level != ENCRYPTION_INITIAL);
  QUIC_BUG_IF(quic_bug_12398_8, packet.nonretransmittable_frames.empty() &&
                                    packet.retransmittable_frames.empty())
      << ENDPOINT
      << "Attempt to serialize empty ENCRYPTION_INITIAL packet in coalesced "
         "packet";

  if (HasPendingFrames()) {
    QUIC_BUG(quic_packet_creator_unexpected_queued_frames)
        << "Unexpected queued frames: " << GetPendingFramesInfo();
    return 0;
  }

  ScopedPacketContextSwitcher switcher(
      packet.packet_number -
          1,  // -1 because serialize packet increase packet number.
      packet.packet_number_length, packet.encryption_level, &packet_);
  for (const QuicFrame& frame : packet.nonretransmittable_frames) {
    if (!AddFrame(frame, packet.transmission_type)) {
      QUIC_BUG(quic_bug_10752_6)
          << ENDPOINT << "Failed to serialize frame: " << frame;
      return 0;
    }
  }
  for (const QuicFrame& frame : packet.retransmittable_frames) {
    if (!AddFrame(frame, packet.transmission_type)) {
      QUIC_BUG(quic_bug_10752_7)
          << ENDPOINT << "Failed to serialize frame: " << frame;
      return 0;
    }
  }
  // Add necessary padding.
  if (padding_size > 0) {
    QUIC_DVLOG(2) << ENDPOINT << "Add padding of size: " << padding_size;
    if (!AddFrame(QuicFrame(QuicPaddingFrame(padding_size)),
                  packet.transmission_type)) {
      QUIC_BUG(quic_bug_10752_8)
          << ENDPOINT << "Failed to add padding of size " << padding_size
          << " when serializing ENCRYPTION_INITIAL "
             "packet in coalesced packet";
      return 0;
    }
  }

  if (!SerializePacket(QuicOwnedPacketBuffer(buffer, nullptr), buffer_len,
                       /*allow_padding=*/false)) {
    return 0;
  }
  if (!packet.initial_header.has_value() ||
      !packet_.initial_header.has_value()) {
    QUIC_BUG(missing initial packet header)
        << "initial serialized packet does not have header populated";
  } else if (*packet.initial_header != *packet_.initial_header) {
    QUIC_BUG(initial packet header changed before reserialization)
        << ENDPOINT << "original header: " << *packet.initial_header
        << ", new header: " << *packet_.initial_header;
  }
  const size_t encrypted_length = packet_.encrypted_length;
  // Clear frames in packet_. No need to DeleteFrames since frames are owned by
  // initial_packet.
  packet_.retransmittable_frames.clear();
  packet_.nonretransmittable_frames.clear();
  ClearPacket();
  return encrypted_length;
}

void QuicPacketCreator::CreateAndSerializeStreamFrame(
    QuicStreamId id, size_t write_length, QuicStreamOffset iov_offset,
    QuicStreamOffset stream_offset, bool fin,
    TransmissionType transmission_type, size_t* num_bytes_consumed) {
  // TODO(b/167222597): consider using ScopedSerializationFailureHandler.
  QUICHE_DCHECK(queued_frames_.empty()) << ENDPOINT;
  QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id))
      << ENDPOINT;
  // Write out the packet header
  QuicPacketHeader header;
  FillPacketHeader(&header);
  packet_.fate = delegate_->GetSerializedPacketFate(
      /*is_mtu_discovery=*/false, packet_.encryption_level);
  QUIC_DVLOG(1) << ENDPOINT << "fate of packet " << packet_.packet_number
                << ": " << SerializedPacketFateToString(packet_.fate) << " of "
                << EncryptionLevelToString(packet_.encryption_level);

  ABSL_CACHELINE_ALIGNED char stack_buffer[kMaxOutgoingPacketSize];
  QuicOwnedPacketBuffer packet_buffer(delegate_->GetPacketBuffer());

  if (packet_buffer.buffer == nullptr) {
    packet_buffer.buffer = stack_buffer;
    packet_buffer.release_buffer = nullptr;
  }

  char* encrypted_buffer = packet_buffer.buffer;

  QuicDataWriter writer(kMaxOutgoingPacketSize, encrypted_buffer);
  size_t length_field_offset = 0;
  if (!framer_->AppendIetfPacketHeader(header, &writer, &length_field_offset)) {
    QUIC_BUG(quic_bug_10752_9) << ENDPOINT << "AppendPacketHeader failed";
    return;
  }

  // Create a Stream frame with the remaining space.
  QUIC_BUG_IF(quic_bug_12398_9, iov_offset == write_length && !fin)
      << ENDPOINT << "Creating a stream frame with no data or fin.";
  const size_t remaining_data_size = write_length - iov_offset;
  size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
      framer_->transport_version(), id, stream_offset,
      /* last_frame_in_packet= */ true, remaining_data_size);
  size_t available_size =
      max_plaintext_size_ - writer.length() - min_frame_size;
  size_t bytes_consumed = std::min<size_t>(available_size, remaining_data_size);
  size_t plaintext_bytes_written = min_frame_size + bytes_consumed;
  bool needs_padding = false;
  const size_t min_plaintext_size =
      MinPlaintextPacketSize(framer_->version(), GetPacketNumberLength());
  if (plaintext_bytes_written < min_plaintext_size) {
    needs_padding = true;
  }

  const bool set_fin = fin && (bytes_consumed == remaining_data_size);
  QuicStreamFrame frame(id, set_fin, stream_offset, bytes_consumed);
  if (debug_delegate_ != nullptr) {
    debug_delegate_->OnFrameAddedToPacket(QuicFrame(frame));
  }
  QUIC_DVLOG(1) << ENDPOINT << "Adding frame: " << frame;

  QUIC_DVLOG(2) << ENDPOINT << "Serializing stream packet " << header << frame;

  // TODO(ianswett): AppendTypeByte and AppendStreamFrame could be optimized
  // into one method that takes a QuicStreamFrame, if warranted.
  if (needs_padding) {
    if (!writer.WritePaddingBytes(min_plaintext_size -
                                  plaintext_bytes_written)) {
      QUIC_BUG(quic_bug_10752_12) << ENDPOINT << "Unable to add padding bytes";
      return;
    }
    needs_padding = false;
  }
  bool omit_frame_length = !needs_padding;
  if (!framer_->AppendTypeByte(QuicFrame(frame), omit_frame_length, &writer)) {
    QUIC_BUG(quic_bug_10752_10) << ENDPOINT << "AppendTypeByte failed";
    return;
  }
  if (!framer_->AppendStreamFrame(frame, omit_frame_length, &writer)) {
    QUIC_BUG(quic_bug_10752_11) << ENDPOINT << "AppendStreamFrame failed";
    return;
  }
  if (needs_padding && plaintext_bytes_written < min_plaintext_size &&
      !writer.WritePaddingBytes(min_plaintext_size - plaintext_bytes_written)) {
    QUIC_BUG(quic_bug_10752_12) << ENDPOINT << "Unable to add padding bytes";
    return;
  }

  if (!framer_->WriteIetfLongHeaderLength(header, &writer, length_field_offset,
                                          packet_.encryption_level)) {
    return;
  }

  packet_.transmission_type = transmission_type;

  QUICHE_DCHECK(packet_.encryption_level == ENCRYPTION_FORWARD_SECURE ||
                packet_.encryption_level == ENCRYPTION_ZERO_RTT)
      << ENDPOINT << packet_.encryption_level;
  size_t encrypted_length = framer_->EncryptInPlace(
      packet_.encryption_level, packet_.packet_number,
      GetStartOfEncryptedData(framer_->transport_version(), header),
      writer.length(), kMaxOutgoingPacketSize, encrypted_buffer);
  if (encrypted_length == 0) {
    QUIC_BUG(quic_bug_10752_13)
        << ENDPOINT << "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_.encrypted_buffer = encrypted_buffer;
  packet_.encrypted_length = encrypted_length;

  packet_buffer.buffer = nullptr;
  packet_.release_encrypted_buffer = std::move(packet_buffer).release_buffer;

  packet_.retransmittable_frames.push_back(QuicFrame(frame));
  OnSerializedPacket();
}

bool QuicPacketCreator::HasPendingFrames() const {
  return !queued_frames_.empty();
}

std::string QuicPacketCreator::GetPendingFramesInfo() const {
  return QuicFramesToString(queued_frames_);
}

bool QuicPacketCreator::HasPendingRetransmittableFrames() const {
  return !packet_.retransmittable_frames.empty();
}

bool QuicPacketCreator::HasPendingStreamFramesOfStream(QuicStreamId id) const {
  for (const auto& frame : packet_.retransmittable_frames) {
    if (frame.type == STREAM_FRAME && frame.stream_frame.stream_id == id) {
      return true;
    }
  }
  return false;
}

size_t QuicPacketCreator::ExpansionOnNewFrame() const {
  // If the last frame in the packet is a message frame, then it will expand to
  // include the varint message length when a new frame is added.
  if (queued_frames_.empty()) {
    return 0;
  }
  return ExpansionOnNewFrameWithLastFrame(queued_frames_.back(),
                                          framer_->transport_version());
}

// static
size_t QuicPacketCreator::ExpansionOnNewFrameWithLastFrame(
    const QuicFrame& last_frame, QuicTransportVersion version) {
  if (last_frame.type == MESSAGE_FRAME) {
    return QuicDataWriter::GetVarInt62Len(
        last_frame.message_frame->message_length);
  }
  if (last_frame.type != STREAM_FRAME) {
    return 0;
  }
  if (VersionHasIetfQuicFrames(version)) {
    return QuicDataWriter::GetVarInt62Len(last_frame.stream_frame.data_length);
  }
  return kQuicStreamPayloadLengthSize;
}

size_t QuicPacketCreator::BytesFree() const {
  return max_plaintext_size_ -
         std::min(max_plaintext_size_, PacketSize() + ExpansionOnNewFrame());
}

size_t QuicPacketCreator::BytesFreeForPadding() const {
  size_t consumed = PacketSize();
  return max_plaintext_size_ - std::min(max_plaintext_size_, consumed);
}

size_t QuicPacketCreator::PacketSize() const {
  return queued_frames_.empty() ? PacketHeaderSize() : packet_size_;
}

bool QuicPacketCreator::AddPaddedSavedFrame(
    const QuicFrame& frame, TransmissionType transmission_type) {
  if (AddFrame(frame, transmission_type)) {
    needs_full_padding_ = true;
    return true;
  }
  return false;
}

std::optional<size_t>
QuicPacketCreator::MaybeBuildDataPacketWithChaosProtection(
    const QuicPacketHeader& header, char* buffer) {
  if (!GetQuicFlag(quic_enable_chaos_protection) ||
      framer_->perspective() != Perspective::IS_CLIENT ||
      packet_.encryption_level != ENCRYPTION_INITIAL ||
      !framer_->version().UsesCryptoFrames() || queued_frames_.size() != 2u ||
      queued_frames_[0].type != CRYPTO_FRAME ||
      queued_frames_[1].type != PADDING_FRAME ||
      // Do not perform chaos protection if we do not have a known number of
      // padding bytes to work with.
      queued_frames_[1].padding_frame.num_padding_bytes <= 0 ||
      // Chaos protection relies on the framer using a crypto data producer,
      // which is always the case in practice.
      framer_->data_producer() == nullptr) {
    return std::nullopt;
  }
  const QuicCryptoFrame& crypto_frame = *queued_frames_[0].crypto_frame;
  if (packet_.encryption_level != crypto_frame.level) {
    QUIC_BUG(chaos frame level)
        << ENDPOINT << packet_.encryption_level << " != " << crypto_frame.level;
    return std::nullopt;
  }
  QuicChaosProtector chaos_protector(
      crypto_frame, queued_frames_[1].padding_frame.num_padding_bytes,
      packet_size_, framer_, random_);
  return chaos_protector.BuildDataPacket(header, buffer);
}

bool QuicPacketCreator::SerializePacket(QuicOwnedPacketBuffer encrypted_buffer,
                                        size_t encrypted_buffer_len,
                                        bool allow_padding) {
  if (packet_.encrypted_buffer != nullptr) {
    const std::string error_details =
        "Packet's encrypted buffer is not empty before serialization";
    QUIC_BUG(quic_bug_10752_14) << ENDPOINT << error_details;
    delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
                                    error_details);
    return false;
  }
  ScopedSerializationFailureHandler handler(this);

  QUICHE_DCHECK_LT(0u, encrypted_buffer_len) << ENDPOINT;
  QUIC_BUG_IF(quic_bug_12398_10,
              queued_frames_.empty() && pending_padding_bytes_ == 0)
      << ENDPOINT << "Attempt to serialize empty packet";
  QuicPacketHeader header;
  // FillPacketHeader increments packet_number_.
  FillPacketHeader(&header);
  if (packet_.encryption_level == ENCRYPTION_INITIAL) {
    packet_.initial_header = header;
  }
  if (delegate_ != nullptr) {
    packet_.fate = delegate_->GetSerializedPacketFate(
        /*is_mtu_discovery=*/QuicUtils::ContainsFrameType(queued_frames_,
                                                          MTU_DISCOVERY_FRAME),
        packet_.encryption_level);
    QUIC_DVLOG(1) << ENDPOINT << "fate of packet " << packet_.packet_number
                  << ": " << SerializedPacketFateToString(packet_.fate)
                  << " of "
                  << EncryptionLevelToString(packet_.encryption_level);
  }

  if (allow_padding) {
    MaybeAddPadding();
  }

  QUIC_DVLOG(2) << ENDPOINT << "Serializing packet " << header
                << QuicFramesToString(queued_frames_) << " at encryption_level "
                << packet_.encryption_level
                << ", allow_padding:" << allow_padding;

  if (!framer_->HasEncrypterOfEncryptionLevel(packet_.encryption_level)) {
    // TODO(fayang): Use QUIC_MISSING_WRITE_KEYS for serialization failures due
    // to missing keys.
    QUIC_BUG(quic_bug_10752_15)
        << ENDPOINT << "Attempting to serialize " << header
        << QuicFramesToString(queued_frames_) << " at missing encryption_level "
        << packet_.encryption_level << " using " << framer_->version();
    return false;
  }

  QUICHE_DCHECK_GE(max_plaintext_size_, packet_size_) << ENDPOINT;
  // Use the packet_size_ instead of the buffer size to ensure smaller
  // packet sizes are properly used.

  size_t length;
  std::optional<size_t> length_with_chaos_protection =
      MaybeBuildDataPacketWithChaosProtection(header, encrypted_buffer.buffer);
  if (length_with_chaos_protection.has_value()) {
    length = *length_with_chaos_protection;
  } else {
    length = framer_->BuildDataPacket(header, queued_frames_,
                                      encrypted_buffer.buffer, packet_size_,
                                      packet_.encryption_level);
  }

  if (length == 0) {
    QUIC_BUG(quic_bug_10752_16)
        << ENDPOINT << "Failed to serialize "
        << QuicFramesToString(queued_frames_)
        << " at encryption_level: " << packet_.encryption_level
        << ", needs_full_padding_: " << needs_full_padding_
        << ", pending_padding_bytes_: " << pending_padding_bytes_
        << ", latched_hard_max_packet_length_: "
        << latched_hard_max_packet_length_
        << ", max_packet_length_: " << max_packet_length_
        << ", header: " << header;
    return false;
  }

  // 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) {
    QUICHE_DCHECK_EQ(packet_size_, length) << ENDPOINT;
  }
  const size_t encrypted_length = framer_->EncryptInPlace(
      packet_.encryption_level, packet_.packet_number,
      GetStartOfEncryptedData(framer_->transport_version(), header), length,
      encrypted_buffer_len, encrypted_buffer.buffer);
  if (encrypted_length == 0) {
    QUIC_BUG(quic_bug_10752_17)
        << ENDPOINT << "Failed to encrypt packet number "
        << packet_.packet_number;
    return false;
  }

  packet_size_ = 0;
  packet_.encrypted_buffer = encrypted_buffer.buffer;
  packet_.encrypted_length = encrypted_length;

  encrypted_buffer.buffer = nullptr;
  packet_.release_encrypted_buffer = std::move(encrypted_buffer).release_buffer;
  return true;
}

std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializeConnectivityProbingPacket() {
  QUIC_BUG_IF(quic_bug_12398_11,
              VersionHasIetfQuicFrames(framer_->transport_version()))
      << ENDPOINT
      << "Must not be version 99 to serialize padded ping connectivity probe";
  RemoveSoftMaxPacketLength();
  QuicPacketHeader header;
  // FillPacketHeader increments packet_number_.
  FillPacketHeader(&header);

  QUIC_DVLOG(2) << ENDPOINT << "Serializing connectivity probing packet "
                << header;

  std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
  size_t length = BuildConnectivityProbingPacket(
      header, buffer.get(), max_plaintext_size_, packet_.encryption_level);
  QUICHE_DCHECK(length) << ENDPOINT;

  QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE)
      << ENDPOINT;
  const size_t encrypted_length = framer_->EncryptInPlace(
      packet_.encryption_level, packet_.packet_number,
      GetStartOfEncryptedData(framer_->transport_version(), header), length,
      kMaxOutgoingPacketSize, buffer.get());
  QUICHE_DCHECK(encrypted_length) << ENDPOINT;

  std::unique_ptr<SerializedPacket> serialize_packet(new SerializedPacket(
      header.packet_number, header.packet_number_length, buffer.release(),
      encrypted_length, /*has_ack=*/false, /*has_stop_waiting=*/false));

  serialize_packet->release_encrypted_buffer = [](const char* p) {
    delete[] p;
  };
  serialize_packet->encryption_level = packet_.encryption_level;
  serialize_packet->transmission_type = NOT_RETRANSMISSION;

  return serialize_packet;
}

std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializePathChallengeConnectivityProbingPacket(
    const QuicPathFrameBuffer& payload) {
  QUIC_BUG_IF(quic_bug_12398_12,
              !VersionHasIetfQuicFrames(framer_->transport_version()))
      << ENDPOINT
      << "Must be version 99 to serialize path challenge connectivity probe, "
         "is version "
      << framer_->transport_version();
  RemoveSoftMaxPacketLength();
  QuicPacketHeader header;
  // FillPacketHeader increments packet_number_.
  FillPacketHeader(&header);

  QUIC_DVLOG(2) << ENDPOINT << "Serializing path challenge packet " << header;

  std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
  size_t length =
      BuildPaddedPathChallengePacket(header, buffer.get(), max_plaintext_size_,
                                     payload, packet_.encryption_level);
  QUICHE_DCHECK(length) << ENDPOINT;

  QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE)
      << ENDPOINT;
  const size_t encrypted_length = framer_->EncryptInPlace(
      packet_.encryption_level, packet_.packet_number,
      GetStartOfEncryptedData(framer_->transport_version(), header), length,
      kMaxOutgoingPacketSize, buffer.get());
  QUICHE_DCHECK(encrypted_length) << ENDPOINT;

  std::unique_ptr<SerializedPacket> serialize_packet(
      new SerializedPacket(header.packet_number, header.packet_number_length,
                           buffer.release(), encrypted_length,
                           /*has_ack=*/false, /*has_stop_waiting=*/false));

  serialize_packet->release_encrypted_buffer = [](const char* p) {
    delete[] p;
  };
  serialize_packet->encryption_level = packet_.encryption_level;
  serialize_packet->transmission_type = NOT_RETRANSMISSION;

  return serialize_packet;
}

std::unique_ptr<SerializedPacket>
QuicPacketCreator::SerializePathResponseConnectivityProbingPacket(
    const quiche::QuicheCircularDeque<QuicPathFrameBuffer>& payloads,
    const bool is_padded) {
  QUIC_BUG_IF(quic_bug_12398_13,
              !VersionHasIetfQuicFrames(framer_->transport_version()))
      << ENDPOINT
      << "Must be version 99 to serialize path response connectivity probe, is "
         "version "
      << framer_->transport_version();
  RemoveSoftMaxPacketLength();
  QuicPacketHeader header;
  // FillPacketHeader increments packet_number_.
  FillPacketHeader(&header);

  QUIC_DVLOG(2) << ENDPOINT << "Serializing path response packet " << header;

  std::unique_ptr<char[]> buffer(new char[kMaxOutgoingPacketSize]);
  size_t length =
      BuildPathResponsePacket(header, buffer.get(), max_plaintext_size_,
                              payloads, is_padded, packet_.encryption_level);
  QUICHE_DCHECK(length) << ENDPOINT;

  QUICHE_DCHECK_EQ(packet_.encryption_level, ENCRYPTION_FORWARD_SECURE)
      << ENDPOINT;
  const size_t encrypted_length = framer_->EncryptInPlace(
      packet_.encryption_level, packet_.packet_number,
      GetStartOfEncryptedData(framer_->transport_version(), header), length,
      kMaxOutgoingPacketSize, buffer.get());
  QUICHE_DCHECK(encrypted_length) << ENDPOINT;

  std::unique_ptr<SerializedPacket> serialize_packet(
      new SerializedPacket(header.packet_number, header.packet_number_length,
                           buffer.release(), encrypted_length,
                           /*has_ack=*/false, /*has_stop_waiting=*/false));

  serialize_packet->release_encrypted_buffer = [](const char* p) {
    delete[] p;
  };
  serialize_packet->encryption_level = packet_.encryption_level;
  serialize_packet->transmission_type = NOT_RETRANSMISSION;

  return serialize_packet;
}

size_t QuicPacketCreator::BuildPaddedPathChallengePacket(
    const QuicPacketHeader& header, char* buffer, size_t packet_length,
    const QuicPathFrameBuffer& payload, EncryptionLevel level) {
  QUICHE_DCHECK(VersionHasIetfQuicFrames(framer_->transport_version()))
      << ENDPOINT;
  QuicFrames frames;

  // Write a PATH_CHALLENGE frame, which has a random 8-byte payload
  frames.push_back(QuicFrame(QuicPathChallengeFrame(0, payload)));

  if (debug_delegate_ != nullptr) {
    debug_delegate_->OnFrameAddedToPacket(frames.back());
  }

  // Add padding to the rest of the packet in order to assess Path MTU
  // characteristics.
  QuicPaddingFrame padding_frame;
  frames.push_back(QuicFrame(padding_frame));

  return framer_->BuildDataPacket(header, frames, buffer, packet_length, level);
}

size_t QuicPacketCreator::BuildPathResponsePacket(
    const QuicPacketHeader& header, char* buffer, size_t packet_length,
    const quiche::QuicheCircularDeque<QuicPathFrameBuffer>& payloads,
    const bool is_padded, EncryptionLevel level) {
  if (payloads.empty()) {
    QUIC_BUG(quic_bug_12398_14)
        << ENDPOINT
        << "Attempt to generate connectivity response with no request payloads";
    return 0;
  }
  QUICHE_DCHECK(VersionHasIetfQuicFrames(framer_->transport_version()))
      << ENDPOINT;

  QuicFrames frames;
  for (const QuicPathFrameBuffer& payload : payloads) {
    // Note that the control frame ID can be 0 since this is not retransmitted.
    frames.push_back(QuicFrame(QuicPathResponseFrame(0, payload)));
    if (debug_delegate_ != nullptr) {
      debug_delegate_->OnFrameAddedToPacket(frames.back());
    }
  }

  if (is_padded) {
    // Add padding to the rest of the packet in order to assess Path MTU
    // characteristics.
    QuicPaddingFrame padding_frame;
    frames.push_back(QuicFrame(padding_frame));
  }

  return framer_->BuildDataPacket(header, frames, buffer, packet_length, level);
}

size_t QuicPacketCreator::BuildConnectivityProbingPacket(
    const QuicPacketHeader& header, char* buffer, size_t packet_length,
    EncryptionLevel level) {
  QuicFrames frames;

  // Write a PING frame, which has no data payload.
  QuicPingFrame ping_frame;
  frames.push_back(QuicFrame(ping_frame));

  // Add padding to the rest of the packet.
  QuicPaddingFrame padding_frame;
  frames.push_back(QuicFrame(padding_frame));

  return framer_->BuildDataPacket(header, frames, buffer, packet_length, level);
}

size_t QuicPacketCreator::SerializeCoalescedPacket(
    const QuicCoalescedPacket& coalesced, char* buffer, size_t buffer_len) {
  if (HasPendingFrames()) {
    QUIC_BUG(quic_bug_10752_18)
        << ENDPOINT << "Try to serialize coalesced packet with pending frames";
    return 0;
  }
  RemoveSoftMaxPacketLength();
  QUIC_BUG_IF(quic_bug_12398_15, coalesced.length() == 0)
      << ENDPOINT << "Attempt to serialize empty coalesced packet";
  size_t packet_length = 0;
  size_t initial_length = 0;
  size_t padding_size = 0;
  if (coalesced.initial_packet() != nullptr) {
    // Padding coalesced packet containing initial packet to full.
    padding_size = coalesced.max_packet_length() - coalesced.length();
    if (framer_->perspective() == Perspective::IS_SERVER &&
        QuicUtils::ContainsFrameType(
            coalesced.initial_packet()->retransmittable_frames,
            CONNECTION_CLOSE_FRAME)) {
      // Do not pad server initial connection close packet.
      padding_size = 0;
    }
    initial_length = ReserializeInitialPacketInCoalescedPacket(
        *coalesced.initial_packet(), padding_size, buffer, buffer_len);
    if (initial_length == 0) {
      QUIC_BUG(quic_bug_10752_19)
          << ENDPOINT
          << "Failed to reserialize ENCRYPTION_INITIAL packet in "
             "coalesced packet";
      return 0;
    }
    QUIC_BUG_IF(quic_reserialize_initial_packet_unexpected_size,
                coalesced.initial_packet()->encrypted_length + padding_size !=
                    initial_length)
        << "Reserialize initial packet in coalescer has unexpected size, "
           "original_length: "
        << coalesced.initial_packet()->encrypted_length
        << ", coalesced.max_packet_length: " << coalesced.max_packet_length()
        << ", coalesced.length: " << coalesced.length()
        << ", padding_size: " << padding_size
        << ", serialized_length: " << initial_length
        << ", retransmittable frames: "
        << QuicFramesToString(
               coalesced.initial_packet()->retransmittable_frames)
        << ", nonretransmittable frames: "
        << QuicFramesToString(
               coalesced.initial_packet()->nonretransmittable_frames);
    buffer += initial_length;
    buffer_len -= initial_length;
    packet_length += initial_length;
  }
  size_t length_copied = 0;
  if (!coalesced.CopyEncryptedBuffers(buffer, buffer_len, &length_copied)) {
    QUIC_BUG(quic_serialize_coalesced_packet_copy_failure)
        << "SerializeCoalescedPacket failed. buffer_len:" << buffer_len
        << ", initial_length:" << initial_length
        << ", padding_size: " << padding_size
        << ", length_copied:" << length_copied
        << ", coalesced.length:" << coalesced.length()
        << ", coalesced.max_packet_length:" << coalesced.max_packet_length()
        << ", coalesced.packet_lengths:"
        << absl::StrJoin(coalesced.packet_lengths(), ":");
    return 0;
  }
  packet_length += length_copied;
  QUIC_DVLOG(1) << ENDPOINT
                << "Successfully serialized coalesced packet of length: "
                << packet_length;
  return packet_length;
}

// TODO(b/74062209): Make this a public method of framer?
SerializedPacket QuicPacketCreator::NoPacket() {
  return SerializedPacket(QuicPacketNumber(), PACKET_1BYTE_PACKET_NUMBER,
                          nullptr, 0, false, false);
}

QuicConnectionId QuicPacketCreator::GetDestinationConnectionId() const {
  if (framer_->perspective() == Perspective::IS_SERVER) {
    return client_connection_id_;
  }
  return server_connection_id_;
}

QuicConnectionId QuicPacketCreator::GetSourceConnectionId() const {
  if (framer_->perspective() == Perspective::IS_CLIENT) {
    return client_connection_id_;
  }
  return server_connection_id_;
}

QuicConnectionIdIncluded QuicPacketCreator::GetDestinationConnectionIdIncluded()
    const {
  // In versions that do not support client connection IDs, the destination
  // connection ID is only sent from client to server.
  return (framer_->perspective() == Perspective::IS_CLIENT ||
          framer_->version().SupportsClientConnectionIds())
             ? CONNECTION_ID_PRESENT
             : CONNECTION_ID_ABSENT;
}

QuicConnectionIdIncluded QuicPacketCreator::GetSourceConnectionIdIncluded()
    const {
  // Long header packets sent by server include source connection ID.
  // Ones sent by the client only include source connection ID if the version
  // supports client connection IDs.
  if (HasIetfLongHeader() &&
      (framer_->perspective() == Perspective::IS_SERVER ||
       framer_->version().SupportsClientConnectionIds())) {
    return CONNECTION_ID_PRESENT;
  }
  if (framer_->perspective() == Perspective::IS_SERVER) {
    return server_connection_id_included_;
  }
  return CONNECTION_ID_ABSENT;
}

uint8_t QuicPacketCreator::GetDestinationConnectionIdLength() const {
  QUICHE_DCHECK(QuicUtils::IsConnectionIdValidForVersion(server_connection_id_,
                                                         transport_version()))
      << ENDPOINT;
  return GetDestinationConnectionIdIncluded() == CONNECTION_ID_PRESENT
             ? GetDestinationConnectionId().length()
             : 0;
}

uint8_t QuicPacketCreator::GetSourceConnectionIdLength() const {
  QUICHE_DCHECK(QuicUtils::IsConnectionIdValidForVersion(server_connection_id_,
                                                         transport_version()))
      << ENDPOINT;
  return GetSourceConnectionIdIncluded() == CONNECTION_ID_PRESENT
             ? GetSourceConnectionId().length()
             : 0;
}

QuicPacketNumberLength QuicPacketCreator::GetPacketNumberLength() const {
  if (HasIetfLongHeader() &&
      !framer_->version().SendsVariableLengthPacketNumberInLongHeader()) {
    return PACKET_4BYTE_PACKET_NUMBER;
  }
  return packet_.packet_number_length;
}

size_t QuicPacketCreator::PacketHeaderSize() const {
  return GetPacketHeaderSize(
      framer_->transport_version(), GetDestinationConnectionIdLength(),
      GetSourceConnectionIdLength(), IncludeVersionInHeader(),
      IncludeNonceInPublicHeader(), GetPacketNumberLength(),
      GetRetryTokenLengthLength(), GetRetryToken().length(), GetLengthLength());
}

quiche::QuicheVariableLengthIntegerLength
QuicPacketCreator::GetRetryTokenLengthLength() const {
  if (QuicVersionHasLongHeaderLengths(framer_->transport_version()) &&
      HasIetfLongHeader() &&
      EncryptionlevelToLongHeaderType(packet_.encryption_level) == INITIAL) {
    return QuicDataWriter::GetVarInt62Len(GetRetryToken().length());
  }
  return quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
}

absl::string_view QuicPacketCreator::GetRetryToken() const {
  if (QuicVersionHasLongHeaderLengths(framer_->transport_version()) &&
      HasIetfLongHeader() &&
      EncryptionlevelToLongHeaderType(packet_.encryption_level) == INITIAL) {
    return retry_token_;
  }
  return absl::string_view();
}

void QuicPacketCreator::SetRetryToken(absl::string_view retry_token) {
  retry_token_ = std::string(retry_token);
}

bool QuicPacketCreator::ConsumeRetransmittableControlFrame(
    const QuicFrame& frame) {
  QUIC_BUG_IF(quic_bug_12398_16, IsControlFrame(frame.type) &&
                                     !GetControlFrameId(frame) &&
                                     frame.type != PING_FRAME)
      << ENDPOINT
      << "Adding a control frame with no control frame id: " << frame;
  QUICHE_DCHECK(QuicUtils::IsRetransmittableFrame(frame.type))
      << ENDPOINT << frame;
  MaybeBundleOpportunistically();
  if (HasPendingFrames()) {
    if (AddFrame(frame, next_transmission_type_)) {
      // There is pending frames and current frame fits.
      return true;
    }
  }
  QUICHE_DCHECK(!HasPendingFrames()) << ENDPOINT;
  if (frame.type != PING_FRAME && frame.type != CONNECTION_CLOSE_FRAME &&
      !delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
                                       NOT_HANDSHAKE)) {
    // Do not check congestion window for ping or connection close frames.
    return false;
  }
  const bool success = AddFrame(frame, next_transmission_type_);
  QUIC_BUG_IF(quic_bug_10752_20, !success)
      << ENDPOINT << "Failed to add frame:" << frame
      << " transmission_type:" << next_transmission_type_;
  return success;
}

void QuicPacketCreator::MaybeBundleOpportunistically() {
  if (!GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data3)) {
    delegate_->MaybeBundleOpportunistically();
    return;
  }

  // delegate_->MaybeBundleOpportunistically() may change
  // next_transmission_type_ for the bundled data.
  const TransmissionType next_transmission_type = next_transmission_type_;
  delegate_->MaybeBundleOpportunistically();
  next_transmission_type_ = next_transmission_type;
}

QuicConsumedData QuicPacketCreator::ConsumeData(QuicStreamId id,
                                                size_t write_length,
                                                QuicStreamOffset offset,
                                                StreamSendingState state) {
  QUIC_BUG_IF(quic_bug_10752_21, !flusher_attached_)
      << ENDPOINT
      << "Packet flusher is not attached when "
         "generator tries to write stream data.";
  bool has_handshake = QuicUtils::IsCryptoStreamId(transport_version(), id);
  const TransmissionType next_transmission_type = next_transmission_type_;
  MaybeBundleOpportunistically();
  // TODO(wub): Remove this QUIC_BUG when deprecating
  // quic_opport_bundle_qpack_decoder_data3.
  QUIC_BUG_IF(quic_packet_creator_change_transmission_type,
              next_transmission_type != next_transmission_type_)
      << ENDPOINT
      << "Transmission type changed by bundled data. old transmission type:"
      << next_transmission_type
      << ", new transmission type:" << next_transmission_type_;
  // If the data being consumed is subject to flow control, check the flow
  // control send window to see if |write_length| exceeds the send window after
  // bundling opportunistic data, if so, reduce |write_length| to the send
  // window size.
  // The data being consumed is subject to flow control iff
  // - It is not a retransmission. We check next_transmission_type_ for that.
  // - And it's not handshake data. This is always true for ConsumeData because
  //   the function is not called for handshake data.
  if (GetQuicRestartFlag(quic_opport_bundle_qpack_decoder_data3) &&
      next_transmission_type_ == NOT_RETRANSMISSION) {
    if (QuicByteCount send_window = delegate_->GetFlowControlSendWindowSize(id);
        write_length > send_window) {
      QUIC_RESTART_FLAG_COUNT_N(quic_opport_bundle_qpack_decoder_data3, 4, 4);
      QUIC_DLOG(INFO) << ENDPOINT
                      << "After bundled data, reducing (old) write_length:"
                      << write_length << "to (new) send_window:" << send_window;
      write_length = send_window;
      state = NO_FIN;
    }
  }
  bool fin = state != NO_FIN;
  QUIC_BUG_IF(quic_bug_12398_17, has_handshake && fin)
      << ENDPOINT << "Handshake packets should never send a fin";
  // To make reasoning about crypto frames easier, we don't combine them with
  // other retransmittable frames in a single packet.
  if (has_handshake && HasPendingRetransmittableFrames()) {
    FlushCurrentPacket();
  }

  size_t total_bytes_consumed = 0;
  bool fin_consumed = false;

  if (!HasRoomForStreamFrame(id, offset, write_length)) {
    FlushCurrentPacket();
  }

  if (!fin && (write_length == 0)) {
    QUIC_BUG(quic_bug_10752_22)
        << ENDPOINT
        << "Attempt to consume empty data without FIN. old transmission type:"
        << next_transmission_type
        << ", new transmission type:" << next_transmission_type_;
    return QuicConsumedData(0, false);
  }
  // We determine if we can enter the fast path before executing
  // the slow path loop.
  bool run_fast_path =
      !has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
      write_length - total_bytes_consumed > kMaxOutgoingPacketSize &&
      latched_hard_max_packet_length_ == 0;

  while (!run_fast_path &&
         (has_handshake || delegate_->ShouldGeneratePacket(
                               HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE))) {
    QuicFrame frame;
    bool needs_full_padding =
        has_handshake && fully_pad_crypto_handshake_packets_;

    if (!ConsumeDataToFillCurrentPacket(id, write_length - total_bytes_consumed,
                                        offset + total_bytes_consumed, fin,
                                        needs_full_padding,
                                        next_transmission_type_, &frame)) {
      // The creator is always flushed if there's not enough room for a new
      // stream frame before ConsumeData, so ConsumeData should always succeed.
      QUIC_BUG(quic_bug_10752_23)
          << ENDPOINT << "Failed to ConsumeData, stream:" << id;
      return QuicConsumedData(0, false);
    }

    // A stream frame is created and added.
    size_t bytes_consumed = frame.stream_frame.data_length;
    total_bytes_consumed += bytes_consumed;
    fin_consumed = fin && total_bytes_consumed == write_length;
    if (fin_consumed && state == FIN_AND_PADDING) {
      AddRandomPadding();
    }
    QUICHE_DCHECK(total_bytes_consumed == write_length ||
                  (bytes_consumed > 0 && HasPendingFrames()))
        << ENDPOINT;

    if (total_bytes_consumed == write_length) {
      // We're done writing the data. Exit the loop.
      // We don't make this a precondition because we could have 0 bytes of data
      // if we're simply writing a fin.
      break;
    }
    FlushCurrentPacket();

    run_fast_path =
        !has_handshake && state != FIN_AND_PADDING && !HasPendingFrames() &&
        write_length - total_bytes_consumed > kMaxOutgoingPacketSize &&
        latched_hard_max_packet_length_ == 0;
  }

  if (run_fast_path) {
    return ConsumeDataFastPath(id, write_length, offset, state != NO_FIN,
                               total_bytes_consumed);
  }

  // Don't allow the handshake to be bundled with other retransmittable frames.
  if (has_handshake) {
    FlushCurrentPacket();
  }

  return QuicConsumedData(total_bytes_consumed, fin_consumed);
}

QuicConsumedData QuicPacketCreator::ConsumeDataFastPath(
    QuicStreamId id, size_t write_length, QuicStreamOffset offset, bool fin,
    size_t total_bytes_consumed) {
  QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id))
      << ENDPOINT;
  if (AttemptingToSendUnencryptedStreamData()) {
    return QuicConsumedData(total_bytes_consumed,
                            fin && (total_bytes_consumed == write_length));
  }

  while (total_bytes_consumed < write_length &&
         delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
                                         NOT_HANDSHAKE)) {
    // Serialize and encrypt the packet.
    size_t bytes_consumed = 0;
    CreateAndSerializeStreamFrame(id, write_length, total_bytes_consumed,
                                  offset + total_bytes_consumed, fin,
                                  next_transmission_type_, &bytes_consumed);
    if (bytes_consumed == 0) {
      const std::string error_details =
          "Failed in CreateAndSerializeStreamFrame.";
      QUIC_BUG(quic_bug_10752_24) << ENDPOINT << error_details;
      delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
                                      error_details);
      break;
    }
    total_bytes_consumed += bytes_consumed;
  }

  return QuicConsumedData(total_bytes_consumed,
                          fin && (total_bytes_consumed == write_length));
}

size_t QuicPacketCreator::ConsumeCryptoData(EncryptionLevel level,
                                            size_t write_length,
                                            QuicStreamOffset offset) {
  QUIC_DVLOG(2) << ENDPOINT << "ConsumeCryptoData " << level << " write_length "
                << write_length << " offset " << offset;
  QUIC_BUG_IF(quic_bug_10752_25, !flusher_attached_)
      << ENDPOINT
      << "Packet flusher is not attached when "
         "generator tries to write crypto data.";
  MaybeBundleOpportunistically();
  // To make reasoning about crypto frames easier, we don't combine them with
  // other retransmittable frames in a single packet.
  // TODO(nharper): Once we have separate packet number spaces, everything
  // should be driven by encryption level, and we should stop flushing in this
  // spot.
  if (HasPendingRetransmittableFrames()) {
    FlushCurrentPacket();
  }

  size_t total_bytes_consumed = 0;

  while (
      total_bytes_consumed < write_length &&
      delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA, IS_HANDSHAKE)) {
    QuicFrame frame;
    if (!ConsumeCryptoDataToFillCurrentPacket(
            level, write_length - total_bytes_consumed,
            offset + total_bytes_consumed, fully_pad_crypto_handshake_packets_,
            next_transmission_type_, &frame)) {
      // The only pending data in the packet is non-retransmittable frames.
      // I'm assuming here that they won't occupy so much of the packet that a
      // CRYPTO frame won't fit.
      QUIC_BUG_IF(quic_bug_10752_26, !HasSoftMaxPacketLength()) << absl::StrCat(
          ENDPOINT, "Failed to ConsumeCryptoData at level ", level,
          ", pending_frames: ", GetPendingFramesInfo(),
          ", has_soft_max_packet_length: ", HasSoftMaxPacketLength(),
          ", max_packet_length: ", max_packet_length_, ", transmission_type: ",
          TransmissionTypeToString(next_transmission_type_),
          ", packet_number: ", packet_number().ToString());
      return 0;
    }
    total_bytes_consumed += frame.crypto_frame->data_length;
    FlushCurrentPacket();
  }

  // Don't allow the handshake to be bundled with other retransmittable frames.
  FlushCurrentPacket();

  return total_bytes_consumed;
}

void QuicPacketCreator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
  // MTU discovery frames must be sent by themselves.
  if (!CanSetMaxPacketLength()) {
    QUIC_BUG(quic_bug_10752_27)
        << ENDPOINT
        << "MTU discovery packets should only be sent when no other "
        << "frames needs to be sent.";
    return;
  }
  const QuicByteCount current_mtu = max_packet_length();

  // The MTU discovery frame is allocated on the stack, since it is going to be
  // serialized within this function.
  QuicMtuDiscoveryFrame mtu_discovery_frame;
  QuicFrame frame(mtu_discovery_frame);

  // Send the probe packet with the new length.
  SetMaxPacketLength(target_mtu);
  const bool success = AddPaddedSavedFrame(frame, next_transmission_type_);
  FlushCurrentPacket();
  // The only reason AddFrame can fail is that the packet is too full to fit in
  // a ping.  This is not possible for any sane MTU.
  QUIC_BUG_IF(quic_bug_10752_28, !success)
      << ENDPOINT << "Failed to send path MTU target_mtu:" << target_mtu
      << " transmission_type:" << next_transmission_type_;

  // Reset the packet length back.
  SetMaxPacketLength(current_mtu);
}

bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
  QUIC_BUG_IF(quic_bug_10752_30, !flusher_attached_)
      << ENDPOINT
      << "Packet flusher is not attached when "
         "generator tries to send ACK frame.";
  // delegate_->MaybeBundleOpportunistically could be called nestedly when
  // sending a control frame causing another control frame to be sent.
  QUIC_BUG_IF(quic_bug_12398_18, !frames.empty() && has_ack())
      << ENDPOINT << "Trying to flush " << quiche::PrintElements(frames)
      << " when there is ACK queued";
  for (const auto& frame : frames) {
    QUICHE_DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME)
        << ENDPOINT;
    if (HasPendingFrames()) {
      if (AddFrame(frame, next_transmission_type_)) {
        // There is pending frames and current frame fits.
        continue;
      }
    }
    QUICHE_DCHECK(!HasPendingFrames()) << ENDPOINT;
    // There is no pending frames, consult the delegate whether a packet can be
    // generated.
    if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
                                         NOT_HANDSHAKE)) {
      return false;
    }
    const bool success = AddFrame(frame, next_transmission_type_);
    QUIC_BUG_IF(quic_bug_10752_31, !success)
        << ENDPOINT << "Failed to flush " << frame;
  }
  return true;
}

void QuicPacketCreator::AddRandomPadding() {
  AddPendingPadding(random_->RandUint64() % kMaxNumRandomPaddingBytes + 1);
}

void QuicPacketCreator::AttachPacketFlusher() {
  flusher_attached_ = true;
  if (!write_start_packet_number_.IsInitialized()) {
    write_start_packet_number_ = NextSendingPacketNumber();
  }
}

void QuicPacketCreator::Flush() {
  FlushCurrentPacket();
  SendRemainingPendingPadding();
  flusher_attached_ = false;
  if (GetQuicFlag(quic_export_write_path_stats_at_server)) {
    if (!write_start_packet_number_.IsInitialized()) {
      QUIC_BUG(quic_bug_10752_32)
          << ENDPOINT << "write_start_packet_number is not initialized";
      return;
    }
    QUIC_SERVER_HISTOGRAM_COUNTS(
        "quic_server_num_written_packets_per_write",
        NextSendingPacketNumber() - write_start_packet_number_, 1, 200, 50,
        "Number of QUIC packets written per write operation");
  }
  write_start_packet_number_.Clear();
}

void QuicPacketCreator::SendRemainingPendingPadding() {
  while (
      pending_padding_bytes() > 0 && !HasPendingFrames() &&
      delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)) {
    FlushCurrentPacket();
  }
}

void QuicPacketCreator::SetServerConnectionIdLength(uint32_t length) {
  if (length == 0) {
    SetServerConnectionIdIncluded(CONNECTION_ID_ABSENT);
  } else {
    SetServerConnectionIdIncluded(CONNECTION_ID_PRESENT);
  }
}

void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
  next_transmission_type_ = type;
}

MessageStatus QuicPacketCreator::AddMessageFrame(
    QuicMessageId message_id, absl::Span<quiche::QuicheMemSlice> message) {
  QUIC_BUG_IF(quic_bug_10752_33, !flusher_attached_)
      << ENDPOINT
      << "Packet flusher is not attached when "
         "generator tries to add message frame.";
  MaybeBundleOpportunistically();
  const QuicByteCount message_length = MemSliceSpanTotalSize(message);
  if (message_length > GetCurrentLargestMessagePayload()) {
    return MESSAGE_STATUS_TOO_LARGE;
  }
  if (!HasRoomForMessageFrame(message_length)) {
    FlushCurrentPacket();
  }
  QuicMessageFrame* frame = new QuicMessageFrame(message_id, message);
  const bool success = AddFrame(QuicFrame(frame), next_transmission_type_);
  if (!success) {
    QUIC_BUG(quic_bug_10752_34)
        << ENDPOINT << "Failed to send message " << message_id;
    delete frame;
    return MESSAGE_STATUS_INTERNAL_ERROR;
  }
  QUICHE_DCHECK_EQ(MemSliceSpanTotalSize(message),
                   0u);  // Ensure the old slices are empty.
  return MESSAGE_STATUS_SUCCESS;
}

quiche::QuicheVariableLengthIntegerLength QuicPacketCreator::GetLengthLength()
    const {
  if (QuicVersionHasLongHeaderLengths(framer_->transport_version()) &&
      HasIetfLongHeader()) {
    QuicLongHeaderType long_header_type =
        EncryptionlevelToLongHeaderType(packet_.encryption_level);
    if (long_header_type == INITIAL || long_header_type == ZERO_RTT_PROTECTED ||
        long_header_type == HANDSHAKE) {
      return quiche::VARIABLE_LENGTH_INTEGER_LENGTH_2;
    }
  }
  return quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
}

void QuicPacketCreator::FillPacketHeader(QuicPacketHeader* header) {
  header->destination_connection_id = GetDestinationConnectionId();
  header->destination_connection_id_included =
      GetDestinationConnectionIdIncluded();
  header->source_connection_id = GetSourceConnectionId();
  header->source_connection_id_included = GetSourceConnectionIdIncluded();
  header->reset_flag = false;
  header->version_flag = IncludeVersionInHeader();
  if (IncludeNonceInPublicHeader()) {
    QUICHE_DCHECK_EQ(Perspective::IS_SERVER, framer_->perspective())
        << ENDPOINT;
    header->nonce = &diversification_nonce_;
  } else {
    header->nonce = nullptr;
  }
  packet_.packet_number = NextSendingPacketNumber();
  header->packet_number = packet_.packet_number;
  header->packet_number_length = GetPacketNumberLength();
  header->retry_token_length_length = GetRetryTokenLengthLength();
  header->retry_token = GetRetryToken();
  header->length_length = GetLengthLength();
  header->remaining_packet_length = 0;
  if (!HasIetfLongHeader()) {
    return;
  }
  header->long_packet_type =
      EncryptionlevelToLongHeaderType(packet_.encryption_level);
}

size_t QuicPacketCreator::GetSerializedFrameLength(const QuicFrame& frame) {
  size_t serialized_frame_length = framer_->GetSerializedFrameLength(
      frame, BytesFree(), queued_frames_.empty(),
      /* last_frame_in_packet= */ true, GetPacketNumberLength());
  if (!framer_->version().HasHeaderProtection() ||
      serialized_frame_length == 0) {
    return serialized_frame_length;
  }
  // Calculate frame bytes and bytes free with this frame added.
  const size_t frame_bytes = PacketSize() - PacketHeaderSize() +
                             ExpansionOnNewFrame() + serialized_frame_length;
  if (frame_bytes >=
      MinPlaintextPacketSize(framer_->version(), GetPacketNumberLength())) {
    // No extra bytes is needed.
    return serialized_frame_length;
  }
  if (BytesFree() < serialized_frame_length) {
    QUIC_BUG(quic_bug_10752_35) << ENDPOINT << "Frame does not fit: " << frame;
    return 0;
  }
  // Please note bytes_free does not take |frame|'s expansion into account.
  size_t bytes_free = BytesFree() - serialized_frame_length;
  // Extra bytes needed (this is NOT padding needed) should be at least 1
  // padding + expansion.
  const size_t extra_bytes_needed = std::max(
      1 + ExpansionOnNewFrameWithLastFrame(frame, framer_->transport_version()),
      MinPlaintextPacketSize(framer_->version(), GetPacketNumberLength()) -
          frame_bytes);
  if (bytes_free < extra_bytes_needed) {
    // This frame does not fit.
    return 0;
  }
  return serialized_frame_length;
}

bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
                                 TransmissionType transmission_type) {
  QUIC_DVLOG(1) << ENDPOINT << "Adding frame with transmission type "
                << transmission_type << ": " << frame;
  if (frame.type == STREAM_FRAME &&
      !QuicUtils::IsCryptoStreamId(framer_->transport_version(),
                                   frame.stream_frame.stream_id) &&
      AttemptingToSendUnencryptedStreamData()) {
    return false;
  }

  // Sanity check to ensure we don't send frames at the wrong encryption level.
  QUICHE_DCHECK(
      packet_.encryption_level == ENCRYPTION_ZERO_RTT ||
      packet_.encryption_level == ENCRYPTION_FORWARD_SECURE ||
      (frame.type != GOAWAY_FRAME && frame.type != WINDOW_UPDATE_FRAME &&
       frame.type != HANDSHAKE_DONE_FRAME &&
       frame.type != NEW_CONNECTION_ID_FRAME &&
       frame.type != MAX_STREAMS_FRAME && frame.type != STREAMS_BLOCKED_FRAME &&
       frame.type != PATH_RESPONSE_FRAME &&
       frame.type != PATH_CHALLENGE_FRAME && frame.type != STOP_SENDING_FRAME &&
       frame.type != MESSAGE_FRAME && frame.type != NEW_TOKEN_FRAME &&
       frame.type != RETIRE_CONNECTION_ID_FRAME &&
       frame.type != ACK_FREQUENCY_FRAME))
      << ENDPOINT << frame.type << " not allowed at "
      << packet_.encryption_level;

  if (frame.type == STREAM_FRAME) {
    if (MaybeCoalesceStreamFrame(frame.stream_frame)) {
      LogCoalesceStreamFrameStatus(true);
      return true;
    } else {
      LogCoalesceStreamFrameStatus(false);
    }
  }

  // If this is an ACK frame, validate that it is non-empty and that
  // largest_acked matches the max packet number.
  QUICHE_DCHECK(frame.type != ACK_FRAME || (!frame.ack_frame->packets.Empty() &&
                                            frame.ack_frame->packets.Max() ==
                                                frame.ack_frame->largest_acked))
      << ENDPOINT << "Invalid ACK frame: " << frame;

  size_t frame_len = GetSerializedFrameLength(frame);
  if (frame_len == 0 && RemoveSoftMaxPacketLength()) {
    // Remove soft max_packet_length and retry.
    frame_len = GetSerializedFrameLength(frame);
  }
  if (frame_len == 0) {
    QUIC_DVLOG(1) << ENDPOINT
                  << "Flushing because current open packet is full when adding "
                  << frame;
    FlushCurrentPacket();
    return false;
  }
  if (queued_frames_.empty()) {
    packet_size_ = PacketHeaderSize();
  }
  QUICHE_DCHECK_LT(0u, packet_size_) << ENDPOINT;

  packet_size_ += ExpansionOnNewFrame() + frame_len;

  if (QuicUtils::IsRetransmittableFrame(frame.type)) {
    packet_.retransmittable_frames.push_back(frame);
    queued_frames_.push_back(frame);
    if (QuicUtils::IsHandshakeFrame(frame, framer_->transport_version())) {
      packet_.has_crypto_handshake = IS_HANDSHAKE;
    }
  } else {
    if (frame.type == PADDING_FRAME &&
        frame.padding_frame.num_padding_bytes == -1) {
      // Populate the actual length of full padding frame, such that one can
      // know how much padding is actually added.
      packet_.nonretransmittable_frames.push_back(
          QuicFrame(QuicPaddingFrame(frame_len)));
    } else {
      packet_.nonretransmittable_frames.push_back(frame);
    }
    queued_frames_.push_back(frame);
  }

  if (frame.type == ACK_FRAME) {
    packet_.has_ack = true;
    packet_.largest_acked = LargestAcked(*frame.ack_frame);
    if (frame.ack_frame->ecn_counters.has_value()) {
      packet_.has_ack_ecn = true;
    }
  } else if (frame.type == STOP_WAITING_FRAME) {
    packet_.has_stop_waiting = true;
  } else if (frame.type == ACK_FREQUENCY_FRAME) {
    packet_.has_ack_frequency = true;
  } else if (frame.type == MESSAGE_FRAME) {
    packet_.has_message = true;
  }
  if (debug_delegate_ != nullptr) {
    debug_delegate_->OnFrameAddedToPacket(frame);
  }

  if (transmission_type == NOT_RETRANSMISSION) {
    packet_.bytes_not_retransmitted.emplace(
        packet_.bytes_not_retransmitted.value_or(0) + frame_len);
  } else if (QuicUtils::IsRetransmittableFrame(frame.type)) {
    // Packet transmission type is determined by the last added retransmittable
    // frame of a retransmission type. If a packet has no retransmittable
    // retransmission frames, it has type NOT_RETRANSMISSION.
    packet_.transmission_type = transmission_type;
  }
  return true;
}

void QuicPacketCreator::MaybeAddExtraPaddingForHeaderProtection() {
  if (!framer_->version().HasHeaderProtection() || needs_full_padding_) {
    return;
  }
  const size_t frame_bytes = PacketSize() - PacketHeaderSize();
  if (frame_bytes >=
      MinPlaintextPacketSize(framer_->version(), GetPacketNumberLength())) {
    return;
  }
  QuicByteCount min_header_protection_padding =
      MinPlaintextPacketSize(framer_->version(), GetPacketNumberLength()) -
      frame_bytes;
  // Update pending_padding_bytes_.
  pending_padding_bytes_ =
      std::max(pending_padding_bytes_, min_header_protection_padding);
}

bool QuicPacketCreator::MaybeCoalesceStreamFrame(const QuicStreamFrame& frame) {
  if (queued_frames_.empty() || queued_frames_.back().type != STREAM_FRAME) {
    return false;
  }
  QuicStreamFrame* candidate = &queued_frames_.back().stream_frame;
  if (candidate->stream_id != frame.stream_id ||
      candidate->offset + candidate->data_length != frame.offset ||
      frame.data_length > BytesFree()) {
    return false;
  }
  candidate->data_length += frame.data_length;
  candidate->fin = frame.fin;

  // The back of retransmittable frames must be the same as the original
  // queued frames' back.
  QUICHE_DCHECK_EQ(packet_.retransmittable_frames.back().type, STREAM_FRAME)
      << ENDPOINT;
  QuicStreamFrame* retransmittable =
      &packet_.retransmittable_frames.back().stream_frame;
  QUICHE_DCHECK_EQ(retransmittable->stream_id, frame.stream_id) << ENDPOINT;
  QUICHE_DCHECK_EQ(retransmittable->offset + retransmittable->data_length,
                   frame.offset)
      << ENDPOINT;
  retransmittable->data_length = candidate->data_length;
  retransmittable->fin = candidate->fin;
  packet_size_ += frame.data_length;
  if (debug_delegate_ != nullptr) {
    debug_delegate_->OnStreamFrameCoalesced(*candidate);
  }
  return true;
}

bool QuicPacketCreator::RemoveSoftMaxPacketLength() {
  if (latched_hard_max_packet_length_ == 0) {
    return false;
  }
  if (!CanSetMaxPacketLength()) {
    return false;
  }
  QUIC_DVLOG(1) << ENDPOINT << "Restoring max packet length to: "
                << latched_hard_max_packet_length_;
  SetMaxPacketLength(latched_hard_max_packet_length_);
  // Reset latched_max_packet_length_.
  latched_hard_max_packet_length_ = 0;
  return true;
}

void QuicPacketCreator::MaybeAddPadding() {
  // The current packet should have no padding bytes because padding is only
  // added when this method is called just before the packet is serialized.
  if (BytesFreeForPadding() == 0) {
    // Don't pad full packets.
    return;
  }

  if (packet_.fate == COALESCE) {
    // Do not add full padding if the packet is going to be coalesced.
    needs_full_padding_ = false;
  }

  // Header protection requires a minimum plaintext packet size.
  MaybeAddExtraPaddingForHeaderProtection();

  QUIC_DVLOG(3) << "MaybeAddPadding for " << packet_.packet_number
                << ": transmission_type:" << packet_.transmission_type
                << ", fate:" << packet_.fate
                << ", needs_full_padding_:" << needs_full_padding_
                << ", pending_padding_bytes_:" << pending_padding_bytes_
                << ", BytesFree:" << BytesFree();

  if (!needs_full_padding_ && pending_padding_bytes_ == 0) {
    // Do not need padding.
    return;
  }

  int padding_bytes = -1;
  if (!needs_full_padding_) {
    padding_bytes =
        std::min<int16_t>(pending_padding_bytes_, BytesFreeForPadding());
    pending_padding_bytes_ -= padding_bytes;
  }

  if (!queued_frames_.empty()) {
    // Insert PADDING before the other frames to avoid adding a length field
    // to any trailing STREAM frame.
    if (needs_full_padding_) {
      padding_bytes = BytesFreeForPadding();
    }
    // AddFrame cannot be used here because it adds the frame to the end of the
    // packet.
    QuicFrame frame{QuicPaddingFrame(padding_bytes)};
    queued_frames_.insert(queued_frames_.begin(), frame);
    packet_size_ += padding_bytes;
    packet_.nonretransmittable_frames.push_back(frame);
    if (packet_.transmission_type == NOT_RETRANSMISSION) {
      packet_.bytes_not_retransmitted.emplace(
          packet_.bytes_not_retransmitted.value_or(0) + padding_bytes);
    }
  } else {
    bool success = AddFrame(QuicFrame(QuicPaddingFrame(padding_bytes)),
                            packet_.transmission_type);
    QUIC_BUG_IF(quic_bug_10752_36, !success)
        << ENDPOINT << "Failed to add padding_bytes: " << padding_bytes
        << " transmission_type: " << packet_.transmission_type;
  }
}

bool QuicPacketCreator::IncludeNonceInPublicHeader() const {
  return have_diversification_nonce_ &&
         packet_.encryption_level == ENCRYPTION_ZERO_RTT;
}

bool QuicPacketCreator::IncludeVersionInHeader() const {
  return packet_.encryption_level < ENCRYPTION_FORWARD_SECURE;
}

void QuicPacketCreator::AddPendingPadding(QuicByteCount size) {
  pending_padding_bytes_ += size;
  QUIC_DVLOG(3) << "After AddPendingPadding(" << size
                << "), pending_padding_bytes_:" << pending_padding_bytes_;
}

bool QuicPacketCreator::StreamFrameIsClientHello(
    const QuicStreamFrame& frame) const {
  if (framer_->perspective() == Perspective::IS_SERVER ||
      !QuicUtils::IsCryptoStreamId(framer_->transport_version(),
                                   frame.stream_id)) {
    return false;
  }
  // The ClientHello is always sent with INITIAL encryption.
  return packet_.encryption_level == ENCRYPTION_INITIAL;
}

void QuicPacketCreator::SetServerConnectionIdIncluded(
    QuicConnectionIdIncluded server_connection_id_included) {
  QUICHE_DCHECK(server_connection_id_included == CONNECTION_ID_PRESENT ||
                server_connection_id_included == CONNECTION_ID_ABSENT)
      << ENDPOINT;
  QUICHE_DCHECK(framer_->perspective() == Perspective::IS_SERVER ||
                server_connection_id_included != CONNECTION_ID_ABSENT)
      << ENDPOINT;
  server_connection_id_included_ = server_connection_id_included;
}

void QuicPacketCreator::SetServerConnectionId(
    QuicConnectionId server_connection_id) {
  server_connection_id_ = server_connection_id;
}

void QuicPacketCreator::SetClientConnectionId(
    QuicConnectionId client_connection_id) {
  QUICHE_DCHECK(client_connection_id.IsEmpty() ||
                framer_->version().SupportsClientConnectionIds())
      << ENDPOINT;
  client_connection_id_ = client_connection_id;
}

QuicPacketLength QuicPacketCreator::GetCurrentLargestMessagePayload() const {
  const size_t packet_header_size = GetPacketHeaderSize(
      framer_->transport_version(), GetDestinationConnectionIdLength(),
      GetSourceConnectionIdLength(), IncludeVersionInHeader(),
      IncludeNonceInPublicHeader(), GetPacketNumberLength(),
      // No Retry token on packets containing application data.
      quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, GetLengthLength());
  // This is the largest possible message payload when the length field is
  // omitted.
  size_t max_plaintext_size =
      latched_hard_max_packet_length_ == 0
          ? max_plaintext_size_
          : framer_->GetMaxPlaintextSize(latched_hard_max_packet_length_);
  size_t largest_frame =
      max_plaintext_size - std::min(max_plaintext_size, packet_header_size);
  if (static_cast<QuicByteCount>(largest_frame) > max_datagram_frame_size_) {
    largest_frame = static_cast<size_t>(max_datagram_frame_size_);
  }
  return largest_frame - std::min(largest_frame, kQuicFrameTypeSize);
}

QuicPacketLength QuicPacketCreator::GetGuaranteedLargestMessagePayload() const {
  // QUIC Crypto server packets may include a diversification nonce.
  const bool may_include_nonce =
      framer_->version().handshake_protocol == PROTOCOL_QUIC_CRYPTO &&
      framer_->perspective() == Perspective::IS_SERVER;
  // IETF QUIC long headers include a length on client 0RTT packets.
  quiche::QuicheVariableLengthIntegerLength length_length =
      quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
  if (framer_->perspective() == Perspective::IS_CLIENT) {
    length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_2;
  }
  if (!QuicVersionHasLongHeaderLengths(framer_->transport_version())) {
    length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
  }
  const size_t packet_header_size = GetPacketHeaderSize(
      framer_->transport_version(), GetDestinationConnectionIdLength(),
      // Assume CID lengths don't change, but version may be present.
      GetSourceConnectionIdLength(), kIncludeVersion, may_include_nonce,
      PACKET_4BYTE_PACKET_NUMBER,
      // No Retry token on packets containing application data.
      quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, length_length);
  // This is the largest possible message payload when the length field is
  // omitted.
  size_t max_plaintext_size =
      latched_hard_max_packet_length_ == 0
          ? max_plaintext_size_
          : framer_->GetMaxPlaintextSize(latched_hard_max_packet_length_);
  size_t largest_frame =
      max_plaintext_size - std::min(max_plaintext_size, packet_header_size);
  if (static_cast<QuicByteCount>(largest_frame) > max_datagram_frame_size_) {
    largest_frame = static_cast<size_t>(max_datagram_frame_size_);
  }
  const QuicPacketLength largest_payload =
      largest_frame - std::min(largest_frame, kQuicFrameTypeSize);
  // This must always be less than or equal to GetCurrentLargestMessagePayload.
  QUICHE_DCHECK_LE(largest_payload, GetCurrentLargestMessagePayload())
      << ENDPOINT;
  return largest_payload;
}

bool QuicPacketCreator::AttemptingToSendUnencryptedStreamData() {
  if (packet_.encryption_level == ENCRYPTION_ZERO_RTT ||
      packet_.encryption_level == ENCRYPTION_FORWARD_SECURE) {
    return false;
  }
  const std::string error_details =
      absl::StrCat("Cannot send stream data with level: ",
                   EncryptionLevelToString(packet_.encryption_level));
  QUIC_BUG(quic_bug_10752_37) << ENDPOINT << error_details;
  delegate_->OnUnrecoverableError(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA,
                                  error_details);
  return true;
}

bool QuicPacketCreator::HasIetfLongHeader() const {
  return packet_.encryption_level < ENCRYPTION_FORWARD_SECURE;
}

// static
size_t QuicPacketCreator::MinPlaintextPacketSize(
    const ParsedQuicVersion& version,
    QuicPacketNumberLength packet_number_length) {
  if (!version.HasHeaderProtection()) {
    return 0;
  }
  // Header protection samples 16 bytes of ciphertext starting 4 bytes after the
  // packet number. In IETF QUIC, all AEAD algorithms have a 16-byte auth tag
  // (i.e. the ciphertext is 16 bytes larger than the plaintext). Since packet
  // numbers could be as small as 1 byte, but the sample starts 4 bytes after
  // the packet number, at least 3 bytes of plaintext are needed to make sure
  // that there is enough ciphertext to sample.
  //
  // Google QUIC crypto uses different AEAD algorithms - in particular the auth
  // tags are only 12 bytes instead of 16 bytes. Since the auth tag is 4 bytes
  // shorter, 4 more bytes of plaintext are needed to guarantee there is enough
  // ciphertext to sample.
  //
  // This method could check for PROTOCOL_TLS1_3 vs PROTOCOL_QUIC_CRYPTO and
  // return 3 when TLS 1.3 is in use (the use of IETF vs Google QUIC crypters is
  // determined based on the handshake protocol used). However, even when TLS
  // 1.3 is used, unittests still use NullEncrypter/NullDecrypter (and other
  // test crypters) which also only use 12 byte tags.
  //
  return (version.UsesTls() ? 4 : 8) - packet_number_length;
}

QuicPacketNumber QuicPacketCreator::NextSendingPacketNumber() const {
  if (!packet_number().IsInitialized()) {
    return framer_->first_sending_packet_number();
  }
  return packet_number() + 1;
}

bool QuicPacketCreator::PacketFlusherAttached() const {
  return flusher_attached_;
}

bool QuicPacketCreator::HasSoftMaxPacketLength() const {
  return latched_hard_max_packet_length_ != 0;
}

void QuicPacketCreator::SetDefaultPeerAddress(QuicSocketAddress address) {
  if (!packet_.peer_address.IsInitialized()) {
    packet_.peer_address = address;
    return;
  }
  if (packet_.peer_address != address) {
    FlushCurrentPacket();
    packet_.peer_address = address;
  }
}

#define ENDPOINT2                                                          \
  (creator_->framer_->perspective() == Perspective::IS_SERVER ? "Server: " \
                                                              : "Client: ")

QuicPacketCreator::ScopedPeerAddressContext::ScopedPeerAddressContext(
    QuicPacketCreator* creator, QuicSocketAddress address,
    const QuicConnectionId& client_connection_id,
    const QuicConnectionId& server_connection_id)
    : creator_(creator),
      old_peer_address_(creator_->packet_.peer_address),
      old_client_connection_id_(creator_->GetClientConnectionId()),
      old_server_connection_id_(creator_->GetServerConnectionId()) {
  QUIC_BUG_IF(quic_bug_12398_19, !old_peer_address_.IsInitialized())
      << ENDPOINT2
      << "Context is used before serialized packet's peer address is "
         "initialized.";
  creator_->SetDefaultPeerAddress(address);
  if (creator_->version().HasIetfQuicFrames()) {
    // Flush current packet if connection ID length changes.
    if (address == old_peer_address_ &&
        ((client_connection_id.length() !=
          old_client_connection_id_.length()) ||
         (server_connection_id.length() !=
          old_server_connection_id_.length()))) {
      creator_->FlushCurrentPacket();
    }
    creator_->SetClientConnectionId(client_connection_id);
    creator_->SetServerConnectionId(server_connection_id);
  }
}

QuicPacketCreator::ScopedPeerAddressContext::~ScopedPeerAddressContext() {
  creator_->SetDefaultPeerAddress(old_peer_address_);
  if (creator_->version().HasIetfQuicFrames()) {
    creator_->SetClientConnectionId(old_client_connection_id_);
    creator_->SetServerConnectionId(old_server_connection_id_);
  }
}

QuicPacketCreator::ScopedSerializationFailureHandler::
    ScopedSerializationFailureHandler(QuicPacketCreator* creator)
    : creator_(creator) {}

QuicPacketCreator::ScopedSerializationFailureHandler::
    ~ScopedSerializationFailureHandler() {
  if (creator_ == nullptr) {
    return;
  }
  // Always clear queued_frames_.
  creator_->queued_frames_.clear();

  if (creator_->packet_.encrypted_buffer == nullptr) {
    const std::string error_details = "Failed to SerializePacket.";
    QUIC_BUG(quic_bug_10752_38) << ENDPOINT2 << error_details;
    creator_->delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
                                              error_details);
  }
}

#undef ENDPOINT2

void QuicPacketCreator::set_encryption_level(EncryptionLevel level) {
  QUICHE_DCHECK(level == packet_.encryption_level || !HasPendingFrames())
      << ENDPOINT << "Cannot update encryption level from "
      << packet_.encryption_level << " to " << level
      << " when we already have pending frames: "
      << QuicFramesToString(queued_frames_);
  packet_.encryption_level = level;
}

void QuicPacketCreator::AddPathChallengeFrame(
    const QuicPathFrameBuffer& payload) {
  // TODO(danzh) Unify similar checks at several entry points into one in
  // AddFrame(). Sort out test helper functions and peer class that don't
  // enforce this check.
  QUIC_BUG_IF(quic_bug_10752_39, !flusher_attached_)
      << ENDPOINT
      << "Packet flusher is not attached when "
         "generator tries to write stream data.";
  // Write a PATH_CHALLENGE frame, which has a random 8-byte payload.
  QuicFrame frame(QuicPathChallengeFrame(0, payload));
  if (AddPaddedFrameWithRetry(frame)) {
    return;
  }
  // Fail silently if the probing packet cannot be written, path validation
  // initiator will retry sending automatically.
  // TODO(danzh) This will consume retry budget, if it causes performance
  // regression, consider to notify the caller about the sending failure and let
  // the caller to decide if it worth retrying.
  QUIC_DVLOG(1) << ENDPOINT << "Can't send PATH_CHALLENGE now";
}

bool QuicPacketCreator::AddPathResponseFrame(
    const QuicPathFrameBuffer& data_buffer) {
  QuicFrame frame(QuicPathResponseFrame(kInvalidControlFrameId, data_buffer));
  if (AddPaddedFrameWithRetry(frame)) {
    return true;
  }

  QUIC_DVLOG(1) << ENDPOINT << "Can't send PATH_RESPONSE now";
  return false;
}

bool QuicPacketCreator::AddPaddedFrameWithRetry(const QuicFrame& frame) {
  if (HasPendingFrames()) {
    if (AddPaddedSavedFrame(frame, NOT_RETRANSMISSION)) {
      // Frame is queued.
      return true;
    }
  }
  // Frame was not queued but queued frames were flushed.
  QUICHE_DCHECK(!HasPendingFrames()) << ENDPOINT;
  if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
                                       NOT_HANDSHAKE)) {
    return false;
  }
  bool success = AddPaddedSavedFrame(frame, NOT_RETRANSMISSION);
  QUIC_BUG_IF(quic_bug_12398_20, !success) << ENDPOINT;
  return true;
}

bool QuicPacketCreator::HasRetryToken() const { return !retry_token_.empty(); }

#undef ENDPOINT  // undef for jumbo builds
}  // namespace quic
