Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/quic_packet_generator.cc b/quic/core/quic_packet_generator.cc
new file mode 100644
index 0000000..fd18064
--- /dev/null
+++ b/quic/core/quic_packet_generator.cc
@@ -0,0 +1,538 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
+
+#include <cstdint>
+
+#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
+                                         QuicFramer* framer,
+                                         QuicRandom* random_generator,
+                                         DelegateInterface* delegate)
+    : delegate_(delegate),
+      packet_creator_(connection_id, framer, random_generator, delegate),
+      next_transmission_type_(NOT_RETRANSMISSION),
+      flusher_attached_(false),
+      should_send_ack_(false),
+      should_send_stop_waiting_(false),
+      random_generator_(random_generator),
+      fully_pad_crypto_handshake_packets_(true),
+      deprecate_ack_bundling_mode_(
+          GetQuicReloadableFlag(quic_deprecate_ack_bundling_mode)) {}
+
+QuicPacketGenerator::~QuicPacketGenerator() {
+  DeleteFrames(&queued_control_frames_);
+}
+
+void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) {
+  DCHECK(!deprecate_ack_bundling_mode_);
+  if (packet_creator_.has_ack()) {
+    // Ack already queued, nothing to do.
+    return;
+  }
+
+  if (also_send_stop_waiting && packet_creator_.has_stop_waiting()) {
+    QUIC_BUG << "Should only ever be one pending stop waiting frame.";
+    return;
+  }
+
+  should_send_ack_ = true;
+  should_send_stop_waiting_ = also_send_stop_waiting;
+  SendQueuedFrames(/*flush=*/false);
+}
+
+void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
+  QUIC_BUG_IF(IsControlFrame(frame.type) && !GetControlFrameId(frame))
+      << "Adding a control frame with no control frame id: " << frame;
+  if (deprecate_ack_bundling_mode_) {
+    MaybeBundleAckOpportunistically();
+  }
+  queued_control_frames_.push_back(frame);
+  SendQueuedFrames(/*flush=*/false);
+}
+
+size_t QuicPacketGenerator::ConsumeCryptoData(EncryptionLevel level,
+                                              size_t write_length,
+                                              QuicStreamOffset offset) {
+  QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
+                                     "generator tries to write crypto data.";
+  if (deprecate_ack_bundling_mode_) {
+    MaybeBundleAckOpportunistically();
+  }
+  // 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.
+  const bool flush = packet_creator_.HasPendingRetransmittableFrames();
+  SendQueuedFrames(flush);
+
+  size_t total_bytes_consumed = 0;
+
+  while (total_bytes_consumed < write_length) {
+    QuicFrame frame;
+    if (!packet_creator_.ConsumeCryptoData(
+            level, write_length - total_bytes_consumed,
+            offset + total_bytes_consumed, 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 << "Failed to ConsumeCryptoData at level " << level;
+      return 0;
+    }
+    total_bytes_consumed += frame.crypto_frame->data_length;
+
+    // TODO(ianswett): Move to having the creator flush itself when it's full.
+    packet_creator_.Flush();
+  }
+
+  // Don't allow the handshake to be bundled with other retransmittable frames.
+  SendQueuedFrames(/*flush=*/true);
+
+  return total_bytes_consumed;
+}
+
+QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
+                                                  size_t write_length,
+                                                  QuicStreamOffset offset,
+                                                  StreamSendingState state) {
+  QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
+                                     "generator tries to write stream data.";
+  bool has_handshake =
+      (id == QuicUtils::GetCryptoStreamId(packet_creator_.transport_version()));
+  if (deprecate_ack_bundling_mode_) {
+    MaybeBundleAckOpportunistically();
+  }
+  bool fin = state != NO_FIN;
+  QUIC_BUG_IF(has_handshake && fin)
+      << "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.
+  const bool flush =
+      has_handshake && packet_creator_.HasPendingRetransmittableFrames();
+  SendQueuedFrames(flush);
+
+  size_t total_bytes_consumed = 0;
+  bool fin_consumed = false;
+
+  if (!packet_creator_.HasRoomForStreamFrame(id, offset, write_length)) {
+    packet_creator_.Flush();
+  }
+
+  if (!fin && (write_length == 0)) {
+    QUIC_BUG << "Attempt to consume empty data without FIN.";
+    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 &&
+                       !HasQueuedFrames() &&
+                       write_length - total_bytes_consumed > kMaxPacketSize;
+
+  while (!run_fast_path && delegate_->ShouldGeneratePacket(
+                               HAS_RETRANSMITTABLE_DATA,
+                               has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) {
+    QuicFrame frame;
+    bool needs_full_padding =
+        has_handshake && fully_pad_crypto_handshake_packets_;
+
+    if (!packet_creator_.ConsumeData(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 << "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();
+    }
+    DCHECK(total_bytes_consumed == write_length ||
+           (bytes_consumed > 0 && packet_creator_.HasPendingFrames()));
+
+    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;
+    }
+    // TODO(ianswett): Move to having the creator flush itself when it's full.
+    packet_creator_.Flush();
+
+    run_fast_path = !has_handshake && state != FIN_AND_PADDING &&
+                    !HasQueuedFrames() &&
+                    write_length - total_bytes_consumed > kMaxPacketSize;
+  }
+
+  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) {
+    SendQueuedFrames(/*flush=*/true);
+  }
+
+  return QuicConsumedData(total_bytes_consumed, fin_consumed);
+}
+
+QuicConsumedData QuicPacketGenerator::ConsumeDataFastPath(
+    QuicStreamId id,
+    size_t write_length,
+    QuicStreamOffset offset,
+    bool fin,
+    size_t total_bytes_consumed) {
+  DCHECK_NE(id,
+            QuicUtils::GetCryptoStreamId(packet_creator_.transport_version()));
+
+  while (total_bytes_consumed < write_length &&
+         delegate_->ShouldGeneratePacket(HAS_RETRANSMITTABLE_DATA,
+                                         NOT_HANDSHAKE)) {
+    // Serialize and encrypt the packet.
+    size_t bytes_consumed = 0;
+    packet_creator_.CreateAndSerializeStreamFrame(
+        id, write_length, total_bytes_consumed, offset + total_bytes_consumed,
+        fin, next_transmission_type_, &bytes_consumed);
+    total_bytes_consumed += bytes_consumed;
+  }
+
+  return QuicConsumedData(total_bytes_consumed,
+                          fin && (total_bytes_consumed == write_length));
+}
+
+void QuicPacketGenerator::GenerateMtuDiscoveryPacket(QuicByteCount target_mtu) {
+  // MTU discovery frames must be sent by themselves.
+  if (!packet_creator_.CanSetMaxPacketLength()) {
+    QUIC_BUG << "MTU discovery packets should only be sent when no other "
+             << "frames needs to be sent.";
+    return;
+  }
+  const QuicByteCount current_mtu = GetCurrentMaxPacketLength();
+
+  // 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 =
+      packet_creator_.AddPaddedSavedFrame(frame, next_transmission_type_);
+  packet_creator_.Flush();
+  // 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.
+  DCHECK(success);
+
+  // Reset the packet length back.
+  SetMaxPacketLength(current_mtu);
+}
+
+bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
+  DCHECK(HasPendingFrames() || packet_creator_.pending_padding_bytes() > 0);
+  HasRetransmittableData retransmittable =
+      (should_send_ack_ || should_send_stop_waiting_ ||
+       packet_creator_.pending_padding_bytes() > 0)
+          ? NO_RETRANSMITTABLE_DATA
+          : HAS_RETRANSMITTABLE_DATA;
+  if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
+    DCHECK(!queued_control_frames_.empty());  // These are retransmittable.
+  }
+  return delegate_->ShouldGeneratePacket(retransmittable, NOT_HANDSHAKE);
+}
+
+void QuicPacketGenerator::SendQueuedFrames(bool flush) {
+  // Only add pending frames if we are SURE we can then send the whole packet.
+  while (HasPendingFrames() &&
+         (flush || CanSendWithNextPendingFrameAddition())) {
+    bool first_frame = packet_creator_.CanSetMaxPacketLength();
+    if (!AddNextPendingFrame() && first_frame) {
+      // A single frame cannot fit into the packet, tear down the connection.
+      QUIC_BUG << "A single frame cannot fit into packet."
+               << " should_send_ack: " << should_send_ack_
+               << " should_send_stop_waiting: " << should_send_stop_waiting_
+               << " number of queued_control_frames: "
+               << queued_control_frames_.size();
+      if (!queued_control_frames_.empty()) {
+        QUIC_LOG(INFO) << queued_control_frames_[0];
+      }
+      delegate_->OnUnrecoverableError(QUIC_FAILED_TO_SERIALIZE_PACKET,
+                                      "Single frame cannot fit into a packet",
+                                      ConnectionCloseSource::FROM_SELF);
+      return;
+    }
+  }
+  if (flush) {
+    packet_creator_.Flush();
+  }
+}
+
+bool QuicPacketGenerator::PacketFlusherAttached() const {
+  return flusher_attached_;
+}
+
+void QuicPacketGenerator::AttachPacketFlusher() {
+  flusher_attached_ = true;
+}
+
+void QuicPacketGenerator::Flush() {
+  SendQueuedFrames(/*flush=*/false);
+  packet_creator_.Flush();
+  SendRemainingPendingPadding();
+  flusher_attached_ = false;
+}
+
+void QuicPacketGenerator::FlushAllQueuedFrames() {
+  SendQueuedFrames(/*flush=*/true);
+}
+
+bool QuicPacketGenerator::HasQueuedFrames() const {
+  return packet_creator_.HasPendingFrames() || HasPendingFrames();
+}
+
+bool QuicPacketGenerator::IsPendingPacketEmpty() const {
+  return !packet_creator_.HasPendingFrames();
+}
+
+bool QuicPacketGenerator::HasPendingFrames() const {
+  return should_send_ack_ || should_send_stop_waiting_ ||
+         !queued_control_frames_.empty();
+}
+
+bool QuicPacketGenerator::AddNextPendingFrame() {
+  QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
+                                     "generator tries to write control frames.";
+  if (should_send_ack_) {
+    should_send_ack_ = !packet_creator_.AddSavedFrame(
+        delegate_->GetUpdatedAckFrame(), next_transmission_type_);
+    return !should_send_ack_;
+  }
+
+  if (should_send_stop_waiting_) {
+    delegate_->PopulateStopWaitingFrame(&pending_stop_waiting_frame_);
+    // If we can't this add the frame now, then we still need to do so later.
+    should_send_stop_waiting_ = !packet_creator_.AddSavedFrame(
+        QuicFrame(pending_stop_waiting_frame_), next_transmission_type_);
+    // Return success if we have cleared out this flag (i.e., added the frame).
+    // If we still need to send, then the frame is full, and we have failed.
+    return !should_send_stop_waiting_;
+  }
+
+  QUIC_BUG_IF(queued_control_frames_.empty())
+      << "AddNextPendingFrame called with no queued control frames.";
+
+  if (!packet_creator_.AddSavedFrame(queued_control_frames_.back(),
+                                     next_transmission_type_)) {
+    // Packet was full.
+    return false;
+  }
+  queued_control_frames_.pop_back();
+  return true;
+}
+
+void QuicPacketGenerator::StopSendingVersion() {
+  packet_creator_.StopSendingVersion();
+}
+
+void QuicPacketGenerator::SetDiversificationNonce(
+    const DiversificationNonce& nonce) {
+  packet_creator_.SetDiversificationNonce(nonce);
+}
+
+QuicPacketNumber QuicPacketGenerator::packet_number() const {
+  return packet_creator_.packet_number();
+}
+
+QuicByteCount QuicPacketGenerator::GetCurrentMaxPacketLength() const {
+  return packet_creator_.max_packet_length();
+}
+
+void QuicPacketGenerator::SetMaxPacketLength(QuicByteCount length) {
+  DCHECK(packet_creator_.CanSetMaxPacketLength());
+  packet_creator_.SetMaxPacketLength(length);
+}
+
+std::unique_ptr<QuicEncryptedPacket>
+QuicPacketGenerator::SerializeVersionNegotiationPacket(
+    bool ietf_quic,
+    const ParsedQuicVersionVector& supported_versions) {
+  return packet_creator_.SerializeVersionNegotiationPacket(ietf_quic,
+                                                           supported_versions);
+}
+
+OwningSerializedPacketPointer
+QuicPacketGenerator::SerializeConnectivityProbingPacket() {
+  return packet_creator_.SerializeConnectivityProbingPacket();
+}
+
+OwningSerializedPacketPointer
+QuicPacketGenerator::SerializePathChallengeConnectivityProbingPacket(
+    QuicPathFrameBuffer* payload) {
+  return packet_creator_.SerializePathChallengeConnectivityProbingPacket(
+      payload);
+}
+
+OwningSerializedPacketPointer
+QuicPacketGenerator::SerializePathResponseConnectivityProbingPacket(
+    const QuicDeque<QuicPathFrameBuffer>& payloads,
+    const bool is_padded) {
+  return packet_creator_.SerializePathResponseConnectivityProbingPacket(
+      payloads, is_padded);
+}
+
+void QuicPacketGenerator::ReserializeAllFrames(
+    const QuicPendingRetransmission& retransmission,
+    char* buffer,
+    size_t buffer_len) {
+  packet_creator_.ReserializeAllFrames(retransmission, buffer, buffer_len);
+}
+
+void QuicPacketGenerator::UpdatePacketNumberLength(
+    QuicPacketNumber least_packet_awaited_by_peer,
+    QuicPacketCount max_packets_in_flight) {
+  return packet_creator_.UpdatePacketNumberLength(least_packet_awaited_by_peer,
+                                                  max_packets_in_flight);
+}
+
+void QuicPacketGenerator::SetConnectionIdLength(uint32_t length) {
+  if (length == 0) {
+    packet_creator_.SetConnectionIdIncluded(CONNECTION_ID_ABSENT);
+  } else {
+    packet_creator_.SetConnectionIdIncluded(CONNECTION_ID_PRESENT);
+  }
+}
+
+void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) {
+  packet_creator_.set_encryption_level(level);
+}
+
+void QuicPacketGenerator::SetEncrypter(
+    EncryptionLevel level,
+    std::unique_ptr<QuicEncrypter> encrypter) {
+  packet_creator_.SetEncrypter(level, std::move(encrypter));
+}
+
+void QuicPacketGenerator::AddRandomPadding() {
+  packet_creator_.AddPendingPadding(
+      random_generator_->RandUint64() % kMaxNumRandomPaddingBytes + 1);
+}
+
+void QuicPacketGenerator::SendRemainingPendingPadding() {
+  while (packet_creator_.pending_padding_bytes() > 0 && !HasQueuedFrames() &&
+         CanSendWithNextPendingFrameAddition()) {
+    packet_creator_.Flush();
+  }
+}
+
+bool QuicPacketGenerator::HasRetransmittableFrames() const {
+  return !queued_control_frames_.empty() ||
+         packet_creator_.HasPendingRetransmittableFrames();
+}
+
+bool QuicPacketGenerator::HasPendingStreamFramesOfStream(
+    QuicStreamId id) const {
+  return packet_creator_.HasPendingStreamFramesOfStream(id);
+}
+
+void QuicPacketGenerator::SetTransmissionType(TransmissionType type) {
+  packet_creator_.SetTransmissionType(type);
+  if (packet_creator_.ShouldSetTransmissionTypeForNextFrame()) {
+    next_transmission_type_ = type;
+  }
+}
+
+void QuicPacketGenerator::SetCanSetTransmissionType(
+    bool can_set_transmission_type) {
+  packet_creator_.set_can_set_transmission_type(can_set_transmission_type);
+}
+
+MessageStatus QuicPacketGenerator::AddMessageFrame(QuicMessageId message_id,
+                                                   QuicMemSliceSpan message) {
+  QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
+                                     "generator tries to add message frame.";
+  if (deprecate_ack_bundling_mode_) {
+    MaybeBundleAckOpportunistically();
+  }
+  const QuicByteCount message_length = message.total_length();
+  if (message_length > GetLargestMessagePayload()) {
+    return MESSAGE_STATUS_TOO_LARGE;
+  }
+  SendQueuedFrames(/*flush=*/false);
+  if (!packet_creator_.HasRoomForMessageFrame(message_length)) {
+    packet_creator_.Flush();
+  }
+  QuicMessageFrame* frame = new QuicMessageFrame(message_id);
+  message.SaveMemSlicesAsMessageData(frame);
+  const bool success =
+      packet_creator_.AddSavedFrame(QuicFrame(frame), next_transmission_type_);
+  if (!success) {
+    QUIC_BUG << "Failed to send message " << message_id;
+    delete frame;
+    return MESSAGE_STATUS_INTERNAL_ERROR;
+  }
+  return MESSAGE_STATUS_SUCCESS;
+}
+
+void QuicPacketGenerator::MaybeBundleAckOpportunistically() {
+  DCHECK(deprecate_ack_bundling_mode_);
+  if (packet_creator_.has_ack()) {
+    // Ack already queued, nothing to do.
+    return;
+  }
+  if (!delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
+                                       NOT_HANDSHAKE)) {
+    return;
+  }
+  const bool flushed =
+      FlushAckFrame(delegate_->MaybeBundleAckOpportunistically());
+  DCHECK(flushed);
+}
+
+bool QuicPacketGenerator::FlushAckFrame(const QuicFrames& frames) {
+  QUIC_BUG_IF(!flusher_attached_) << "Packet flusher is not attached when "
+                                     "generator tries to send ACK frame.";
+  for (const auto& frame : frames) {
+    DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME);
+    if (packet_creator_.HasPendingFrames()) {
+      if (packet_creator_.AddSavedFrame(frame, next_transmission_type_)) {
+        // There is pending frames and current frame fits.
+        continue;
+      }
+    }
+    DCHECK(!packet_creator_.HasPendingFrames());
+    // 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 =
+        packet_creator_.AddSavedFrame(frame, next_transmission_type_);
+    QUIC_BUG_IF(!success) << "Failed to flush " << frame;
+  }
+  return true;
+}
+
+QuicPacketLength QuicPacketGenerator::GetLargestMessagePayload() const {
+  return packet_creator_.GetLargestMessagePayload();
+}
+
+}  // namespace quic