// 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_connection.h"

#include <string.h>
#include <sys/types.h>

#include <algorithm>
#include <cstdint>
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>

#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/congestion_control/rtt_stats.h"
#include "quiche/quic/core/congestion_control/send_algorithm_interface.h"
#include "quiche/quic/core/crypto/crypto_protocol.h"
#include "quiche/quic/core/crypto/crypto_utils.h"
#include "quiche/quic/core/crypto/quic_decrypter.h"
#include "quiche/quic/core/crypto/quic_encrypter.h"
#include "quiche/quic/core/proto/cached_network_parameters_proto.h"
#include "quiche/quic/core/quic_bandwidth.h"
#include "quiche/quic/core/quic_config.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_packet_creator.h"
#include "quiche/quic/core/quic_packet_writer.h"
#include "quiche/quic/core/quic_packets.h"
#include "quiche/quic/core/quic_path_validator.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"
#include "quiche/quic/platform/api/quic_client_stats.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_hostname_utils.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_server_stats.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/common/platform/api/quiche_flag_utils.h"
#include "quiche/common/quiche_text_utils.h"

namespace quic {

class QuicDecrypter;
class QuicEncrypter;

namespace {

// Maximum number of consecutive sent nonretransmittable packets.
const QuicPacketCount kMaxConsecutiveNonRetransmittablePackets = 19;

// The minimum release time into future in ms.
const int kMinReleaseTimeIntoFutureMs = 1;

// Base class of all alarms owned by a QuicConnection.
class QuicConnectionAlarmDelegate : public QuicAlarm::Delegate {
 public:
  explicit QuicConnectionAlarmDelegate(QuicConnection* connection)
      : connection_(connection) {}
  QuicConnectionAlarmDelegate(const QuicConnectionAlarmDelegate&) = delete;
  QuicConnectionAlarmDelegate& operator=(const QuicConnectionAlarmDelegate&) =
      delete;

  QuicConnectionContext* GetConnectionContext() override {
    return (connection_ == nullptr) ? nullptr : connection_->context();
  }

 protected:
  QuicConnection* connection_;
};

// An alarm that is scheduled to send an ack if a timeout occurs.
class AckAlarmDelegate : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->ack_frame_updated());
    QUICHE_DCHECK(connection_->connected());
    QuicConnection::ScopedPacketFlusher flusher(connection_);
    if (connection_->SupportsMultiplePacketNumberSpaces()) {
      connection_->SendAllPendingAcks();
    } else {
      connection_->SendAck();
    }
  }
};

// This alarm will be scheduled any time a data-bearing packet is sent out.
// When the alarm goes off, the connection checks to see if the oldest packets
// have been acked, and retransmit them if they have not.
class RetransmissionAlarmDelegate : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->connected());
    connection_->OnRetransmissionTimeout();
  }
};

// An alarm that is scheduled when the SentPacketManager requires a delay
// before sending packets and fires when the packet may be sent.
class SendAlarmDelegate : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->connected());
    connection_->WriteIfNotBlocked();
  }
};

class MtuDiscoveryAlarmDelegate : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->connected());
    connection_->DiscoverMtu();
  }
};

class ProcessUndecryptablePacketsAlarmDelegate
    : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->connected());
    QuicConnection::ScopedPacketFlusher flusher(connection_);
    connection_->MaybeProcessUndecryptablePackets();
  }
};

class DiscardPreviousOneRttKeysAlarmDelegate
    : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->connected());
    connection_->DiscardPreviousOneRttKeys();
  }
};

class DiscardZeroRttDecryptionKeysAlarmDelegate
    : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->connected());
    QUIC_DLOG(INFO) << "0-RTT discard alarm fired";
    connection_->RemoveDecrypter(ENCRYPTION_ZERO_RTT);
    connection_->RetireOriginalDestinationConnectionId();
  }
};

class MultiPortProbingAlarmDelegate : public QuicConnectionAlarmDelegate {
 public:
  using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;

  void OnAlarm() override {
    QUICHE_DCHECK(connection_->connected());
    QUIC_DLOG(INFO) << "Alternative path probing alarm fired";
    connection_->MaybeProbeMultiPortPath();
  }
};

// When the clearer goes out of scope, the coalesced packet gets cleared.
class ScopedCoalescedPacketClearer {
 public:
  explicit ScopedCoalescedPacketClearer(QuicCoalescedPacket* coalesced)
      : coalesced_(coalesced) {}
  ~ScopedCoalescedPacketClearer() { coalesced_->Clear(); }

 private:
  QuicCoalescedPacket* coalesced_;  // Unowned.
};

// Whether this incoming packet is allowed to replace our connection ID.
bool PacketCanReplaceServerConnectionId(const QuicPacketHeader& header,
                                        Perspective perspective) {
  return perspective == Perspective::IS_CLIENT &&
         header.form == IETF_QUIC_LONG_HEADER_PACKET &&
         header.version.IsKnown() &&
         header.version.AllowsVariableLengthConnectionIds() &&
         (header.long_packet_type == INITIAL ||
          header.long_packet_type == RETRY);
}

// Due to a lost Initial packet, a Handshake packet might use a new connection
// ID we haven't seen before. We shouldn't update the connection ID based on
// this, but should buffer the packet in case it works out.
bool NewServerConnectionIdMightBeValid(const QuicPacketHeader& header,
                                       Perspective perspective,
                                       bool connection_id_already_replaced) {
  return perspective == Perspective::IS_CLIENT &&
         header.form == IETF_QUIC_LONG_HEADER_PACKET &&
         header.version.IsKnown() &&
         header.version.AllowsVariableLengthConnectionIds() &&
         header.long_packet_type == HANDSHAKE &&
         !connection_id_already_replaced;
}

CongestionControlType GetDefaultCongestionControlType() {
  if (GetQuicReloadableFlag(quic_default_to_bbr_v2)) {
    return kBBRv2;
  }

  if (GetQuicReloadableFlag(quic_default_to_bbr)) {
    return kBBR;
  }

  return kCubicBytes;
}

bool ContainsNonProbingFrame(const SerializedPacket& packet) {
  for (const QuicFrame& frame : packet.nonretransmittable_frames) {
    if (!QuicUtils::IsProbingFrame(frame.type)) {
      return true;
    }
  }
  for (const QuicFrame& frame : packet.retransmittable_frames) {
    if (!QuicUtils::IsProbingFrame(frame.type)) {
      return true;
    }
  }
  return false;
}

}  // namespace

#define ENDPOINT \
  (perspective_ == Perspective::IS_SERVER ? "Server: " : "Client: ")

QuicConnection::QuicConnection(
    QuicConnectionId server_connection_id,
    QuicSocketAddress initial_self_address,
    QuicSocketAddress initial_peer_address,
    QuicConnectionHelperInterface* helper, QuicAlarmFactory* alarm_factory,
    QuicPacketWriter* writer, bool owns_writer, Perspective perspective,
    const ParsedQuicVersionVector& supported_versions,
    ConnectionIdGeneratorInterface& generator)
    : framer_(supported_versions, helper->GetClock()->ApproximateNow(),
              perspective, server_connection_id.length()),
      current_packet_content_(NO_FRAMES_RECEIVED),
      is_current_packet_connectivity_probing_(false),
      has_path_challenge_in_current_packet_(false),
      current_effective_peer_migration_type_(NO_CHANGE),
      helper_(helper),
      alarm_factory_(alarm_factory),
      per_packet_options_(nullptr),
      writer_(writer),
      owns_writer_(owns_writer),
      encryption_level_(ENCRYPTION_INITIAL),
      clock_(helper->GetClock()),
      random_generator_(helper->GetRandomGenerator()),
      client_connection_id_is_set_(false),
      direct_peer_address_(initial_peer_address),
      default_path_(initial_self_address, QuicSocketAddress(),
                    /*client_connection_id=*/EmptyQuicConnectionId(),
                    server_connection_id,
                    /*stateless_reset_token=*/absl::nullopt),
      active_effective_peer_migration_type_(NO_CHANGE),
      support_key_update_for_connection_(false),
      current_packet_data_(nullptr),
      should_last_packet_instigate_acks_(false),
      max_undecryptable_packets_(0),
      max_tracked_packets_(GetQuicFlag(quic_max_tracked_packet_count)),
      idle_timeout_connection_close_behavior_(
          ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET),
      num_rtos_for_blackhole_detection_(0),
      uber_received_packet_manager_(&stats_),
      stop_waiting_count_(0),
      pending_retransmission_alarm_(false),
      defer_send_in_response_to_packets_(false),
      arena_(),
      ack_alarm_(alarm_factory_->CreateAlarm(arena_.New<AckAlarmDelegate>(this),
                                             &arena_)),
      retransmission_alarm_(alarm_factory_->CreateAlarm(
          arena_.New<RetransmissionAlarmDelegate>(this), &arena_)),
      send_alarm_(alarm_factory_->CreateAlarm(
          arena_.New<SendAlarmDelegate>(this), &arena_)),
      mtu_discovery_alarm_(alarm_factory_->CreateAlarm(
          arena_.New<MtuDiscoveryAlarmDelegate>(this), &arena_)),
      process_undecryptable_packets_alarm_(alarm_factory_->CreateAlarm(
          arena_.New<ProcessUndecryptablePacketsAlarmDelegate>(this), &arena_)),
      discard_previous_one_rtt_keys_alarm_(alarm_factory_->CreateAlarm(
          arena_.New<DiscardPreviousOneRttKeysAlarmDelegate>(this), &arena_)),
      discard_zero_rtt_decryption_keys_alarm_(alarm_factory_->CreateAlarm(
          arena_.New<DiscardZeroRttDecryptionKeysAlarmDelegate>(this),
          &arena_)),
      multi_port_probing_alarm_(alarm_factory_->CreateAlarm(
          arena_.New<MultiPortProbingAlarmDelegate>(this), &arena_)),
      visitor_(nullptr),
      debug_visitor_(nullptr),
      packet_creator_(server_connection_id, &framer_, random_generator_, this),
      last_received_packet_info_(clock_->ApproximateNow()),
      sent_packet_manager_(perspective, clock_, random_generator_, &stats_,
                           GetDefaultCongestionControlType()),
      version_negotiated_(false),
      perspective_(perspective),
      connected_(true),
      can_truncate_connection_ids_(perspective == Perspective::IS_SERVER),
      mtu_probe_count_(0),
      previous_validated_mtu_(0),
      peer_max_packet_size_(kDefaultMaxPacketSizeTransportParam),
      largest_received_packet_size_(0),
      write_error_occurred_(false),
      no_stop_waiting_frames_(version().HasIetfInvariantHeader()),
      consecutive_num_packets_with_no_retransmittable_frames_(0),
      max_consecutive_num_packets_with_no_retransmittable_frames_(
          kMaxConsecutiveNonRetransmittablePackets),
      bundle_retransmittable_with_pto_ack_(false),
      last_control_frame_id_(kInvalidControlFrameId),
      is_path_degrading_(false),
      processing_ack_frame_(false),
      supports_release_time_(false),
      release_time_into_future_(QuicTime::Delta::Zero()),
      blackhole_detector_(this, &arena_, alarm_factory_, &context_),
      idle_network_detector_(this, clock_->ApproximateNow(), &arena_,
                             alarm_factory_, &context_),
      path_validator_(alarm_factory_, &arena_, this, random_generator_, clock_,
                      &context_),
      ping_manager_(perspective, this, &arena_, alarm_factory_, &context_),
      multi_port_probing_interval_(kDefaultMultiPortProbingInterval),
      connection_id_generator_(generator) {
  QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
                default_path_.self_address.IsInitialized());

  QUIC_DLOG(INFO) << ENDPOINT << "Created connection with server connection ID "
                  << server_connection_id
                  << " and version: " << ParsedQuicVersionToString(version());

  QUIC_BUG_IF(quic_bug_12714_2, !QuicUtils::IsConnectionIdValidForVersion(
                                    server_connection_id, transport_version()))
      << "QuicConnection: attempted to use server connection ID "
      << server_connection_id << " which is invalid with version " << version();
  framer_.set_visitor(this);
  stats_.connection_creation_time = clock_->ApproximateNow();
  // TODO(ianswett): Supply the NetworkChangeVisitor as a constructor argument
  // and make it required non-null, because it's always used.
  sent_packet_manager_.SetNetworkChangeVisitor(this);
  if (GetQuicRestartFlag(quic_offload_pacing_to_usps2)) {
    sent_packet_manager_.SetPacingAlarmGranularity(QuicTime::Delta::Zero());
    release_time_into_future_ =
        QuicTime::Delta::FromMilliseconds(kMinReleaseTimeIntoFutureMs);
  }
  // Allow the packet writer to potentially reduce the packet size to a value
  // even smaller than kDefaultMaxPacketSize.
  SetMaxPacketLength(perspective_ == Perspective::IS_SERVER
                         ? kDefaultServerMaxPacketSize
                         : kDefaultMaxPacketSize);
  uber_received_packet_manager_.set_max_ack_ranges(255);
  MaybeEnableMultiplePacketNumberSpacesSupport();
  QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
                supported_versions.size() == 1);
  InstallInitialCrypters(default_path_.server_connection_id);

  // On the server side, version negotiation has been done by the dispatcher,
  // and the server connection is created with the right version.
  if (perspective_ == Perspective::IS_SERVER) {
    SetVersionNegotiated();
  }
  if (default_enable_5rto_blackhole_detection_) {
    num_rtos_for_blackhole_detection_ = 5;
    if (GetQuicReloadableFlag(quic_disable_server_blackhole_detection) &&
        perspective_ == Perspective::IS_SERVER) {
      QUIC_RELOADABLE_FLAG_COUNT(quic_disable_server_blackhole_detection);
      blackhole_detection_disabled_ = true;
    }
  }
  if (perspective_ == Perspective::IS_CLIENT) {
    AddKnownServerAddress(initial_peer_address);
  }
  packet_creator_.SetDefaultPeerAddress(initial_peer_address);
}

void QuicConnection::InstallInitialCrypters(QuicConnectionId connection_id) {
  CrypterPair crypters;
  CryptoUtils::CreateInitialObfuscators(perspective_, version(), connection_id,
                                        &crypters);
  SetEncrypter(ENCRYPTION_INITIAL, std::move(crypters.encrypter));
  if (version().KnowsWhichDecrypterToUse()) {
    InstallDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
  } else {
    SetDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
  }
}

QuicConnection::~QuicConnection() {
  QUICHE_DCHECK_GE(stats_.max_egress_mtu, long_term_mtu_);
  if (owns_writer_) {
    delete writer_;
  }
  ClearQueuedPackets();
  if (stats_
          .num_tls_server_zero_rtt_packets_received_after_discarding_decrypter >
      0) {
    QUIC_CODE_COUNT_N(
        quic_server_received_tls_zero_rtt_packet_after_discarding_decrypter, 2,
        3);
  } else {
    QUIC_CODE_COUNT_N(
        quic_server_received_tls_zero_rtt_packet_after_discarding_decrypter, 3,
        3);
  }
}

void QuicConnection::ClearQueuedPackets() { buffered_packets_.clear(); }

bool QuicConnection::ValidateConfigConnectionIds(const QuicConfig& config) {
  QUICHE_DCHECK(config.negotiated());
  if (!version().UsesTls()) {
    // QUIC+TLS is required to transmit connection ID transport parameters.
    return true;
  }
  // This function validates connection IDs as defined in IETF draft-28 and
  // later.

  // Validate initial_source_connection_id.
  QuicConnectionId expected_initial_source_connection_id;
  if (perspective_ == Perspective::IS_CLIENT) {
    expected_initial_source_connection_id = default_path_.server_connection_id;
  } else {
    expected_initial_source_connection_id = default_path_.client_connection_id;
  }
  if (!config.HasReceivedInitialSourceConnectionId() ||
      config.ReceivedInitialSourceConnectionId() !=
          expected_initial_source_connection_id) {
    std::string received_value;
    if (config.HasReceivedInitialSourceConnectionId()) {
      received_value = config.ReceivedInitialSourceConnectionId().ToString();
    } else {
      received_value = "none";
    }
    std::string error_details =
        absl::StrCat("Bad initial_source_connection_id: expected ",
                     expected_initial_source_connection_id.ToString(),
                     ", received ", received_value);
    CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  if (perspective_ == Perspective::IS_CLIENT) {
    // Validate original_destination_connection_id.
    if (!config.HasReceivedOriginalConnectionId() ||
        config.ReceivedOriginalConnectionId() !=
            GetOriginalDestinationConnectionId()) {
      std::string received_value;
      if (config.HasReceivedOriginalConnectionId()) {
        received_value = config.ReceivedOriginalConnectionId().ToString();
      } else {
        received_value = "none";
      }
      std::string error_details =
          absl::StrCat("Bad original_destination_connection_id: expected ",
                       GetOriginalDestinationConnectionId().ToString(),
                       ", received ", received_value);
      CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
                      ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
      return false;
    }
    // Validate retry_source_connection_id.
    if (retry_source_connection_id_.has_value()) {
      // We received a RETRY packet, validate that the retry source
      // connection ID from the config matches the one from the RETRY.
      if (!config.HasReceivedRetrySourceConnectionId() ||
          config.ReceivedRetrySourceConnectionId() !=
              retry_source_connection_id_.value()) {
        std::string received_value;
        if (config.HasReceivedRetrySourceConnectionId()) {
          received_value = config.ReceivedRetrySourceConnectionId().ToString();
        } else {
          received_value = "none";
        }
        std::string error_details =
            absl::StrCat("Bad retry_source_connection_id: expected ",
                         retry_source_connection_id_.value().ToString(),
                         ", received ", received_value);
        CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
        return false;
      }
    } else {
      // We did not receive a RETRY packet, make sure we did not receive the
      // retry_source_connection_id transport parameter.
      if (config.HasReceivedRetrySourceConnectionId()) {
        std::string error_details = absl::StrCat(
            "Bad retry_source_connection_id: did not receive RETRY but "
            "received ",
            config.ReceivedRetrySourceConnectionId().ToString());
        CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION, error_details,
                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
        return false;
      }
    }
  }
  return true;
}

void QuicConnection::SetFromConfig(const QuicConfig& config) {
  if (config.negotiated()) {
    // Handshake complete, set handshake timeout to Infinite.
    SetNetworkTimeouts(QuicTime::Delta::Infinite(),
                       config.IdleNetworkTimeout());
    idle_timeout_connection_close_behavior_ =
        ConnectionCloseBehavior::SILENT_CLOSE;
    if (perspective_ == Perspective::IS_SERVER) {
      idle_timeout_connection_close_behavior_ = ConnectionCloseBehavior::
          SILENT_CLOSE_WITH_CONNECTION_CLOSE_PACKET_SERIALIZED;
    }
    if (config.HasClientRequestedIndependentOption(kNSLC, perspective_)) {
      idle_timeout_connection_close_behavior_ =
          ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET;
    }
    if (!ValidateConfigConnectionIds(config)) {
      return;
    }
    support_key_update_for_connection_ = version().UsesTls();
    framer_.SetKeyUpdateSupportForConnection(
        support_key_update_for_connection_);
  } else {
    SetNetworkTimeouts(config.max_time_before_crypto_handshake(),
                       config.max_idle_time_before_crypto_handshake());
  }

  if (version().HasIetfQuicFrames() &&
      config.HasReceivedPreferredAddressConnectionIdAndToken()) {
    QuicNewConnectionIdFrame frame;
    std::tie(frame.connection_id, frame.stateless_reset_token) =
        config.ReceivedPreferredAddressConnectionIdAndToken();
    frame.sequence_number = 1u;
    frame.retire_prior_to = 0u;
    OnNewConnectionIdFrameInner(frame);
  }

  sent_packet_manager_.SetFromConfig(config);
  if (perspective_ == Perspective::IS_SERVER &&
      config.HasClientSentConnectionOption(kAFF2, perspective_)) {
    send_ack_frequency_on_handshake_completion_ = true;
  }
  if (config.HasReceivedBytesForConnectionId() &&
      can_truncate_connection_ids_) {
    packet_creator_.SetServerConnectionIdLength(
        config.ReceivedBytesForConnectionId());
  }
  max_undecryptable_packets_ = config.max_undecryptable_packets();

  if (!GetQuicReloadableFlag(quic_enable_mtu_discovery_at_server)) {
    if (config.HasClientRequestedIndependentOption(kMTUH, perspective_)) {
      SetMtuDiscoveryTarget(kMtuDiscoveryTargetPacketSizeHigh);
    }
  }
  if (config.HasClientRequestedIndependentOption(kMTUL, perspective_)) {
    SetMtuDiscoveryTarget(kMtuDiscoveryTargetPacketSizeLow);
  }
  if (default_enable_5rto_blackhole_detection_) {
    if (config.HasClientRequestedIndependentOption(kCBHD, perspective_)) {
      QUIC_CODE_COUNT(quic_client_only_blackhole_detection);
      blackhole_detection_disabled_ = true;
    }
    if (config.HasClientSentConnectionOption(kNBHD, perspective_)) {
      blackhole_detection_disabled_ = true;
    }
  }

  if (config.HasClientRequestedIndependentOption(kFIDT, perspective_)) {
    idle_network_detector_.enable_shorter_idle_timeout_on_sent_packet();
  }
  if (perspective_ == Perspective::IS_CLIENT && version().HasIetfQuicFrames()) {
    // Only conduct those experiments in IETF QUIC because random packets may
    // elicit reset and gQUIC PUBLIC_RESET will cause connection close.
    if (config.HasClientRequestedIndependentOption(kROWF, perspective_)) {
      retransmittable_on_wire_behavior_ = SEND_FIRST_FORWARD_SECURE_PACKET;
    }
    if (config.HasClientRequestedIndependentOption(kROWR, perspective_)) {
      retransmittable_on_wire_behavior_ = SEND_RANDOM_BYTES;
    }
  }
  if (config.HasClientRequestedIndependentOption(k3AFF, perspective_)) {
    anti_amplification_factor_ = 3;
  }
  if (config.HasClientRequestedIndependentOption(k10AF, perspective_)) {
    anti_amplification_factor_ = 10;
  }

  if (GetQuicReloadableFlag(quic_enable_server_on_wire_ping) &&
      perspective_ == Perspective::IS_SERVER &&
      config.HasClientSentConnectionOption(kSRWP, perspective_)) {
    QUIC_RELOADABLE_FLAG_COUNT(quic_enable_server_on_wire_ping);
    set_initial_retransmittable_on_wire_timeout(
        QuicTime::Delta::FromMilliseconds(200));
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnSetFromConfig(config);
  }
  uber_received_packet_manager_.SetFromConfig(config, perspective_);
  if (config.HasClientSentConnectionOption(k5RTO, perspective_)) {
    num_rtos_for_blackhole_detection_ = 5;
  }
  if (config.HasClientSentConnectionOption(k6PTO, perspective_) ||
      config.HasClientSentConnectionOption(k7PTO, perspective_) ||
      config.HasClientSentConnectionOption(k8PTO, perspective_)) {
    num_rtos_for_blackhole_detection_ = 5;
  }
  if (config.HasClientSentConnectionOption(kNSTP, perspective_)) {
    no_stop_waiting_frames_ = true;
  }
  if (config.HasReceivedStatelessResetToken()) {
    default_path_.stateless_reset_token = config.ReceivedStatelessResetToken();
  }
  if (config.HasReceivedAckDelayExponent()) {
    framer_.set_peer_ack_delay_exponent(config.ReceivedAckDelayExponent());
  }
  if (config.HasClientSentConnectionOption(kEACK, perspective_)) {
    bundle_retransmittable_with_pto_ack_ = true;
  }
  if (config.HasClientSentConnectionOption(kDFER, perspective_)) {
    defer_send_in_response_to_packets_ = false;
  }

  if (config.HasClientRequestedIndependentOption(kINVC, perspective_)) {
    send_connection_close_for_invalid_version_ = true;
  }
  const bool remove_connection_migration_connection_option =
      GetQuicReloadableFlag(
          quic_remove_connection_migration_connection_option_v2);
  if (remove_connection_migration_connection_option) {
    QUIC_RELOADABLE_FLAG_COUNT(
        quic_remove_connection_migration_connection_option_v2);
  }
  if (framer_.version().HasIetfQuicFrames() &&
      (remove_connection_migration_connection_option ||
       config.HasClientSentConnectionOption(kRVCM, perspective_))) {
    validate_client_addresses_ = true;
  }
  // Having connection_migration_use_new_cid_ depends on the same set of flags
  // and connection option on both client and server sides has the advantage of:
  // 1) Less chance of skew in using new connection ID or not between client
  //    and server in unit tests with random flag combinations.
  // 2) Client side's rollout can be protected by the same connection option.
  connection_migration_use_new_cid_ =
      validate_client_addresses_ &&
      GetQuicReloadableFlag(quic_connection_migration_use_new_cid_v2);

  if (connection_migration_use_new_cid_ &&
      config.HasReceivedPreferredAddressConnectionIdAndToken() &&
      config.HasClientSentConnectionOption(kSPAD, perspective_)) {
    if (self_address().host().IsIPv4() &&
        config.HasReceivedIPv4AlternateServerAddress()) {
      received_server_preferred_address_ =
          config.ReceivedIPv4AlternateServerAddress();
    } else if (self_address().host().IsIPv6() &&
               config.HasReceivedIPv6AlternateServerAddress()) {
      received_server_preferred_address_ =
          config.ReceivedIPv6AlternateServerAddress();
    }
    if (received_server_preferred_address_.IsInitialized()) {
      QUICHE_DLOG(INFO) << ENDPOINT << "Received server preferred address: "
                        << received_server_preferred_address_;
      if (config.HasClientRequestedIndependentOption(kSPA2, perspective_)) {
        accelerated_server_preferred_address_ = true;
        visitor_->OnServerPreferredAddressAvailable(
            received_server_preferred_address_);
      }
    }
  }

  if (config.HasReceivedMaxPacketSize()) {
    peer_max_packet_size_ = config.ReceivedMaxPacketSize();
    packet_creator_.SetMaxPacketLength(
        GetLimitedMaxPacketSize(packet_creator_.max_packet_length()));
  }
  if (config.HasReceivedMaxDatagramFrameSize()) {
    packet_creator_.SetMaxDatagramFrameSize(
        config.ReceivedMaxDatagramFrameSize());
  }

  supports_release_time_ =
      writer_ != nullptr && writer_->SupportsReleaseTime() &&
      !config.HasClientSentConnectionOption(kNPCO, perspective_);

  if (supports_release_time_) {
    UpdateReleaseTimeIntoFuture();
  }

  if (perspective_ == Perspective::IS_CLIENT &&
      connection_migration_use_new_cid_ &&
      config.HasClientRequestedIndependentOption(kMPQC, perspective_)) {
    multi_port_stats_ = std::make_unique<MultiPortStats>();
  }
}

bool QuicConnection::MaybeTestLiveness() {
  QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
  if (liveness_testing_disabled_ ||
      encryption_level_ != ENCRYPTION_FORWARD_SECURE) {
    return false;
  }
  const QuicTime idle_network_deadline =
      idle_network_detector_.GetIdleNetworkDeadline();
  if (!idle_network_deadline.IsInitialized()) {
    return false;
  }
  const QuicTime now = clock_->ApproximateNow();
  if (now > idle_network_deadline) {
    QUIC_DLOG(WARNING) << "Idle network deadline has passed";
    return false;
  }
  const QuicTime::Delta timeout = idle_network_deadline - now;
  if (2 * timeout > idle_network_detector_.idle_network_timeout()) {
    // Do not test liveness if timeout is > half timeout. This is used to
    // prevent an infinite loop for short idle timeout.
    return false;
  }
  if (!sent_packet_manager_.IsLessThanThreePTOs(timeout)) {
    return false;
  }
  QUIC_LOG_EVERY_N_SEC(INFO, 60)
      << "Testing liveness, idle_network_timeout: "
      << idle_network_detector_.idle_network_timeout()
      << ", timeout: " << timeout
      << ", Pto delay: " << sent_packet_manager_.GetPtoDelay()
      << ", smoothed_rtt: "
      << sent_packet_manager_.GetRttStats()->smoothed_rtt()
      << ", mean deviation: "
      << sent_packet_manager_.GetRttStats()->mean_deviation();
  SendConnectivityProbingPacket(writer_, peer_address());
  return true;
}

void QuicConnection::ApplyConnectionOptions(
    const QuicTagVector& connection_options) {
  sent_packet_manager_.ApplyConnectionOptions(connection_options);
}

void QuicConnection::OnSendConnectionState(
    const CachedNetworkParameters& cached_network_params) {
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnSendConnectionState(cached_network_params);
  }
}

void QuicConnection::OnReceiveConnectionState(
    const CachedNetworkParameters& cached_network_params) {
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnReceiveConnectionState(cached_network_params);
  }
}

void QuicConnection::ResumeConnectionState(
    const CachedNetworkParameters& cached_network_params,
    bool max_bandwidth_resumption) {
  sent_packet_manager_.ResumeConnectionState(cached_network_params,
                                             max_bandwidth_resumption);
}

void QuicConnection::SetMaxPacingRate(QuicBandwidth max_pacing_rate) {
  sent_packet_manager_.SetMaxPacingRate(max_pacing_rate);
}

void QuicConnection::AdjustNetworkParameters(
    const SendAlgorithmInterface::NetworkParams& params) {
  sent_packet_manager_.AdjustNetworkParameters(params);
}

void QuicConnection::SetLossDetectionTuner(
    std::unique_ptr<LossDetectionTunerInterface> tuner) {
  sent_packet_manager_.SetLossDetectionTuner(std::move(tuner));
}

void QuicConnection::OnConfigNegotiated() {
  sent_packet_manager_.OnConfigNegotiated();

  if (GetQuicReloadableFlag(quic_enable_mtu_discovery_at_server) &&
      perspective_ == Perspective::IS_SERVER) {
    QUIC_RELOADABLE_FLAG_COUNT(quic_enable_mtu_discovery_at_server);
    SetMtuDiscoveryTarget(kMtuDiscoveryTargetPacketSizeHigh);
  }
}

QuicBandwidth QuicConnection::MaxPacingRate() const {
  return sent_packet_manager_.MaxPacingRate();
}

bool QuicConnection::SelectMutualVersion(
    const ParsedQuicVersionVector& available_versions) {
  // Try to find the highest mutual version by iterating over supported
  // versions, starting with the highest, and breaking out of the loop once we
  // find a matching version in the provided available_versions vector.
  const ParsedQuicVersionVector& supported_versions =
      framer_.supported_versions();
  for (size_t i = 0; i < supported_versions.size(); ++i) {
    const ParsedQuicVersion& version = supported_versions[i];
    if (std::find(available_versions.begin(), available_versions.end(),
                  version) != available_versions.end()) {
      framer_.set_version(version);
      return true;
    }
  }

  return false;
}

void QuicConnection::OnError(QuicFramer* framer) {
  // Packets that we can not or have not decrypted are dropped.
  // TODO(rch): add stats to measure this.
  if (!connected_ || !last_received_packet_info_.decrypted) {
    return;
  }
  CloseConnection(framer->error(), framer->detailed_error(),
                  ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}

void QuicConnection::OnPacket() {
  last_received_packet_info_.decrypted = false;
}

void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) {
  // Check that any public reset packet with a different connection ID that was
  // routed to this QuicConnection has been redirected before control reaches
  // here.  (Check for a bug regression.)
  QUICHE_DCHECK_EQ(default_path_.server_connection_id, packet.connection_id);
  QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
  QUICHE_DCHECK(!version().HasIetfInvariantHeader());
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnPublicResetPacket(packet);
  }
  std::string error_details = "Received public reset.";
  if (perspective_ == Perspective::IS_CLIENT && !packet.endpoint_id.empty()) {
    absl::StrAppend(&error_details, " From ", packet.endpoint_id, ".");
  }
  QUIC_DLOG(INFO) << ENDPOINT << error_details;
  QUIC_CODE_COUNT(quic_tear_down_local_connection_on_public_reset);
  TearDownLocalConnectionState(QUIC_PUBLIC_RESET, NO_IETF_QUIC_ERROR,
                               error_details, ConnectionCloseSource::FROM_PEER);
}

bool QuicConnection::OnProtocolVersionMismatch(
    ParsedQuicVersion received_version) {
  QUIC_DLOG(INFO) << ENDPOINT << "Received packet with mismatched version "
                  << ParsedQuicVersionToString(received_version);
  if (perspective_ == Perspective::IS_CLIENT) {
    const std::string error_details = "Protocol version mismatch.";
    QUIC_BUG(quic_bug_10511_3) << ENDPOINT << error_details;
    CloseConnection(QUIC_INTERNAL_ERROR, error_details,
                    ConnectionCloseBehavior::SILENT_CLOSE);
  }

  // Server drops old packets that were sent by the client before the version
  // was negotiated.
  return false;
}

// Handles version negotiation for client connection.
void QuicConnection::OnVersionNegotiationPacket(
    const QuicVersionNegotiationPacket& packet) {
  // Check that any public reset packet with a different connection ID that was
  // routed to this QuicConnection has been redirected before control reaches
  // here.  (Check for a bug regression.)
  QUICHE_DCHECK_EQ(default_path_.server_connection_id, packet.connection_id);
  if (perspective_ == Perspective::IS_SERVER) {
    const std::string error_details =
        "Server received version negotiation packet.";
    QUIC_BUG(quic_bug_10511_4) << error_details;
    QUIC_CODE_COUNT(quic_tear_down_local_connection_on_version_negotiation);
    CloseConnection(QUIC_INTERNAL_ERROR, error_details,
                    ConnectionCloseBehavior::SILENT_CLOSE);
    return;
  }
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnVersionNegotiationPacket(packet);
  }

  if (version_negotiated_) {
    // Possibly a duplicate version negotiation packet.
    return;
  }

  if (std::find(packet.versions.begin(), packet.versions.end(), version()) !=
      packet.versions.end()) {
    const std::string error_details = absl::StrCat(
        "Server already supports client's version ",
        ParsedQuicVersionToString(version()),
        " and should have accepted the connection instead of sending {",
        ParsedQuicVersionVectorToString(packet.versions), "}.");
    QUIC_DLOG(WARNING) << error_details;
    CloseConnection(QUIC_INVALID_VERSION_NEGOTIATION_PACKET, error_details,
                    ConnectionCloseBehavior::SILENT_CLOSE);
    return;
  }

  server_supported_versions_ = packet.versions;
  CloseConnection(
      QUIC_INVALID_VERSION,
      absl::StrCat(
          "Client may support one of the versions in the server's list, but "
          "it's going to close the connection anyway. Supported versions: {",
          ParsedQuicVersionVectorToString(framer_.supported_versions()),
          "}, peer supported versions: {",
          ParsedQuicVersionVectorToString(packet.versions), "}"),
      send_connection_close_for_invalid_version_
          ? ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET
          : ConnectionCloseBehavior::SILENT_CLOSE);
}

// Handles retry for client connection.
void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
                                   QuicConnectionId new_connection_id,
                                   absl::string_view retry_token,
                                   absl::string_view retry_integrity_tag,
                                   absl::string_view retry_without_tag) {
  QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
  if (version().UsesTls()) {
    if (!CryptoUtils::ValidateRetryIntegrityTag(
            version(), default_path_.server_connection_id, retry_without_tag,
            retry_integrity_tag)) {
      QUIC_DLOG(ERROR) << "Ignoring RETRY with invalid integrity tag";
      return;
    }
  } else {
    if (original_connection_id != default_path_.server_connection_id) {
      QUIC_DLOG(ERROR) << "Ignoring RETRY with original connection ID "
                       << original_connection_id << " not matching expected "
                       << default_path_.server_connection_id << " token "
                       << absl::BytesToHexString(retry_token);
      return;
    }
  }
  framer_.set_drop_incoming_retry_packets(true);
  stats_.retry_packet_processed = true;
  QUIC_DLOG(INFO) << "Received RETRY, replacing connection ID "
                  << default_path_.server_connection_id << " with "
                  << new_connection_id << ", received token "
                  << absl::BytesToHexString(retry_token);
  if (!original_destination_connection_id_.has_value()) {
    original_destination_connection_id_ = default_path_.server_connection_id;
  }
  QUICHE_DCHECK(!retry_source_connection_id_.has_value())
      << retry_source_connection_id_.value();
  retry_source_connection_id_ = new_connection_id;
  ReplaceInitialServerConnectionId(new_connection_id);
  packet_creator_.SetRetryToken(retry_token);

  // Reinstall initial crypters because the connection ID changed.
  InstallInitialCrypters(default_path_.server_connection_id);

  sent_packet_manager_.MarkInitialPacketsForRetransmission();
}

void QuicConnection::SetOriginalDestinationConnectionId(
    const QuicConnectionId& original_destination_connection_id) {
  QUIC_DLOG(INFO) << "Setting original_destination_connection_id to "
                  << original_destination_connection_id
                  << " on connection with server_connection_id "
                  << default_path_.server_connection_id;
  QUICHE_DCHECK_NE(original_destination_connection_id,
                   default_path_.server_connection_id);
  InstallInitialCrypters(original_destination_connection_id);
  QUICHE_DCHECK(!original_destination_connection_id_.has_value())
      << original_destination_connection_id_.value();
  original_destination_connection_id_ = original_destination_connection_id;
  original_destination_connection_id_replacement_ =
      default_path_.server_connection_id;
}

QuicConnectionId QuicConnection::GetOriginalDestinationConnectionId() const {
  if (original_destination_connection_id_.has_value()) {
    return original_destination_connection_id_.value();
  }
  return default_path_.server_connection_id;
}

void QuicConnection::RetireOriginalDestinationConnectionId() {
  if (original_destination_connection_id_.has_value()) {
    visitor_->OnServerConnectionIdRetired(*original_destination_connection_id_);
    original_destination_connection_id_.reset();
  }
}

bool QuicConnection::ValidateServerConnectionId(
    const QuicPacketHeader& header) const {
  if (perspective_ == Perspective::IS_CLIENT &&
      header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
    return true;
  }

  QuicConnectionId server_connection_id =
      GetServerConnectionIdAsRecipient(header, perspective_);

  if (server_connection_id == default_path_.server_connection_id ||
      server_connection_id == original_destination_connection_id_) {
    return true;
  }

  if (PacketCanReplaceServerConnectionId(header, perspective_)) {
    QUIC_DLOG(INFO) << ENDPOINT << "Accepting packet with new connection ID "
                    << server_connection_id << " instead of "
                    << default_path_.server_connection_id;
    return true;
  }

  if (connection_migration_use_new_cid_ &&
      perspective_ == Perspective::IS_SERVER &&
      self_issued_cid_manager_ != nullptr &&
      self_issued_cid_manager_->IsConnectionIdInUse(server_connection_id)) {
    return true;
  }

  if (NewServerConnectionIdMightBeValid(
          header, perspective_, server_connection_id_replaced_by_initial_)) {
    return true;
  }

  return false;
}

bool QuicConnection::OnUnauthenticatedPublicHeader(
    const QuicPacketHeader& header) {
  last_received_packet_info_.destination_connection_id =
      header.destination_connection_id;
  // If last packet destination connection ID is the original server
  // connection ID chosen by client, replaces it with the connection ID chosen
  // by server.
  if (perspective_ == Perspective::IS_SERVER &&
      original_destination_connection_id_.has_value() &&
      last_received_packet_info_.destination_connection_id ==
          *original_destination_connection_id_) {
    last_received_packet_info_.destination_connection_id =
        original_destination_connection_id_replacement_;
  }

  // As soon as we receive an initial we start ignoring subsequent retries.
  if (header.version_flag && header.long_packet_type == INITIAL) {
    framer_.set_drop_incoming_retry_packets(true);
  }

  if (!ValidateServerConnectionId(header)) {
    ++stats_.packets_dropped;
    QuicConnectionId server_connection_id =
        GetServerConnectionIdAsRecipient(header, perspective_);
    QUIC_DLOG(INFO) << ENDPOINT
                    << "Ignoring packet from unexpected server connection ID "
                    << server_connection_id << " instead of "
                    << default_path_.server_connection_id;
    if (debug_visitor_ != nullptr) {
      debug_visitor_->OnIncorrectConnectionId(server_connection_id);
    }
    QUICHE_DCHECK_NE(Perspective::IS_SERVER, perspective_);
    return false;
  }

  if (!version().SupportsClientConnectionIds()) {
    return true;
  }

  if (perspective_ == Perspective::IS_SERVER &&
      header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
    return true;
  }

  QuicConnectionId client_connection_id =
      GetClientConnectionIdAsRecipient(header, perspective_);

  if (client_connection_id == default_path_.client_connection_id) {
    return true;
  }

  if (!client_connection_id_is_set_ && perspective_ == Perspective::IS_SERVER) {
    QUIC_DLOG(INFO) << ENDPOINT
                    << "Setting client connection ID from first packet to "
                    << client_connection_id;
    set_client_connection_id(client_connection_id);
    return true;
  }

  if (connection_migration_use_new_cid_ &&
      perspective_ == Perspective::IS_CLIENT &&
      self_issued_cid_manager_ != nullptr &&
      self_issued_cid_manager_->IsConnectionIdInUse(client_connection_id)) {
    return true;
  }

  ++stats_.packets_dropped;
  QUIC_DLOG(INFO) << ENDPOINT
                  << "Ignoring packet from unexpected client connection ID "
                  << client_connection_id << " instead of "
                  << default_path_.client_connection_id;
  return false;
}

bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnUnauthenticatedHeader(header);
  }

  // Sanity check on the server connection ID in header.
  QUICHE_DCHECK(ValidateServerConnectionId(header));

  if (packet_creator_.HasPendingFrames()) {
    // Incoming packets may change a queued ACK frame.
    const std::string error_details =
        "Pending frames must be serialized before incoming packets are "
        "processed.";
    QUIC_BUG(quic_pending_frames_not_serialized)
        << error_details << ", received header: " << header;
    CloseConnection(QUIC_INTERNAL_ERROR, error_details,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }

  return true;
}

void QuicConnection::OnSuccessfulVersionNegotiation() {
  visitor_->OnSuccessfulVersionNegotiation(version());
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnSuccessfulVersionNegotiation(version());
  }
}

void QuicConnection::OnSuccessfulMigration(bool is_port_change) {
  QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
  if (IsPathDegrading() && !multi_port_stats_) {
    // If path was previously degrading, and migration is successful after
    // probing, restart the path degrading and blackhole detection.
    // In the case of multi-port, since the alt-path state is inferred from
    // historical data, we can't trust it until we receive data on the new path.
    OnForwardProgressMade();
  }
  if (IsAlternativePath(default_path_.self_address,
                        default_path_.peer_address)) {
    // Reset alternative path state even if it is still under validation.
    alternative_path_.Clear();
  }
  // TODO(b/159074035): notify SentPacketManger with RTT sample from probing.
  if (version().HasIetfQuicFrames() && !is_port_change) {
    sent_packet_manager_.OnConnectionMigration(/*reset_send_algorithm=*/true);
  }
}

void QuicConnection::OnTransportParametersSent(
    const TransportParameters& transport_parameters) const {
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnTransportParametersSent(transport_parameters);
  }
}

void QuicConnection::OnTransportParametersReceived(
    const TransportParameters& transport_parameters) const {
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnTransportParametersReceived(transport_parameters);
  }
}

void QuicConnection::OnTransportParametersResumed(
    const TransportParameters& transport_parameters) const {
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnTransportParametersResumed(transport_parameters);
  }
}

bool QuicConnection::HasPendingAcks() const { return ack_alarm_->IsSet(); }

void QuicConnection::OnUserAgentIdKnown(const std::string& /*user_agent_id*/) {
  sent_packet_manager_.OnUserAgentIdKnown();
}

void QuicConnection::OnDecryptedPacket(size_t /*length*/,
                                       EncryptionLevel level) {
  last_received_packet_info_.decrypted_level = level;
  last_received_packet_info_.decrypted = true;
  if (level == ENCRYPTION_FORWARD_SECURE &&
      !have_decrypted_first_one_rtt_packet_) {
    have_decrypted_first_one_rtt_packet_ = true;
    if (version().UsesTls() && perspective_ == Perspective::IS_SERVER) {
      // Servers MAY temporarily retain 0-RTT keys to allow decrypting reordered
      // packets without requiring their contents to be retransmitted with 1-RTT
      // keys. After receiving a 1-RTT packet, servers MUST discard 0-RTT keys
      // within a short time; the RECOMMENDED time period is three times the
      // Probe Timeout.
      // https://quicwg.org/base-drafts/draft-ietf-quic-tls.html#name-discarding-0-rtt-keys
      discard_zero_rtt_decryption_keys_alarm_->Set(
          clock_->ApproximateNow() + sent_packet_manager_.GetPtoDelay() * 3);
    }
  }
  if (EnforceAntiAmplificationLimit() && !IsHandshakeConfirmed() &&
      (level == ENCRYPTION_HANDSHAKE || level == ENCRYPTION_FORWARD_SECURE)) {
    // Address is validated by successfully processing a HANDSHAKE or 1-RTT
    // packet.
    default_path_.validated = true;
    stats_.address_validated_via_decrypting_packet = true;
  }
  idle_network_detector_.OnPacketReceived(
      last_received_packet_info_.receipt_time);

  visitor_->OnPacketDecrypted(level);
}

QuicSocketAddress QuicConnection::GetEffectivePeerAddressFromCurrentPacket()
    const {
  // By default, the connection is not proxied, and the effective peer address
  // is the packet's source address, i.e. the direct peer address.
  return last_received_packet_info_.source_address;
}

bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnPacketHeader(header, clock_->ApproximateNow(),
                                   last_received_packet_info_.decrypted_level);
  }

  // Will be decremented below if we fall through to return true.
  ++stats_.packets_dropped;

  if (!ProcessValidatedPacket(header)) {
    return false;
  }

  // Initialize the current packet content state.
  current_packet_content_ = NO_FRAMES_RECEIVED;
  is_current_packet_connectivity_probing_ = false;
  has_path_challenge_in_current_packet_ = false;
  current_effective_peer_migration_type_ = NO_CHANGE;

  if (perspective_ == Perspective::IS_CLIENT) {
    if (!GetLargestReceivedPacket().IsInitialized() ||
        header.packet_number > GetLargestReceivedPacket()) {
      if (version().HasIetfQuicFrames()) {
        // Client processes packets from any known server address, but only
        // updates peer address on initialization and/or to validated server
        // preferred address.
      } else {
        // Update direct_peer_address_ and default path peer_address immediately
        // for client connections.
        // TODO(fayang): only change peer addresses in application data packet
        // number space.
        UpdatePeerAddress(last_received_packet_info_.source_address);
        default_path_.peer_address = GetEffectivePeerAddressFromCurrentPacket();
      }
    }
  } else {
    // At server, remember the address change type of effective_peer_address
    // in current_effective_peer_migration_type_. But this variable alone
    // doesn't necessarily starts a migration. A migration will be started
    // later, once the current packet is confirmed to meet the following
    // conditions:
    // 1) current_effective_peer_migration_type_ is not NO_CHANGE.
    // 2) The current packet is not a connectivity probing.
    // 3) The current packet is not reordered, i.e. its packet number is the
    //    largest of this connection so far.
    // Once the above conditions are confirmed, a new migration will start
    // even if there is an active migration underway.
    current_effective_peer_migration_type_ =
        QuicUtils::DetermineAddressChangeType(
            default_path_.peer_address,
            GetEffectivePeerAddressFromCurrentPacket());

    if (connection_migration_use_new_cid_) {
      auto effective_peer_address = GetEffectivePeerAddressFromCurrentPacket();
      // Since server does not send new connection ID to client before handshake
      // completion and source connection ID is omitted in short header packet,
      // the server_connection_id on PathState on the server side does not
      // affect the packets server writes after handshake completion. On the
      // other hand, it is still desirable to have the "correct" server
      // connection ID set on path.
      // 1) If client uses 1 unique server connection ID per path and the packet
      // is received from an existing path, then
      // last_received_packet_info_.destination_connection_id will always be the
      // same as the server connection ID on path. Server side will maintain the
      // 1-to-1 mapping from server connection ID to path. 2) If client uses
      // multiple server connection IDs on the same path, compared to the
      // server_connection_id on path,
      // last_received_packet_info_.destination_connection_id has the advantage
      // that it is still present in the session map since the packet can be
      // routed here regardless of packet reordering.
      if (IsDefaultPath(last_received_packet_info_.destination_address,
                        effective_peer_address)) {
        default_path_.server_connection_id =
            last_received_packet_info_.destination_connection_id;
      } else if (IsAlternativePath(
                     last_received_packet_info_.destination_address,
                     effective_peer_address)) {
        alternative_path_.server_connection_id =
            last_received_packet_info_.destination_connection_id;
      }
    }

    if (last_received_packet_info_.destination_connection_id !=
            default_path_.server_connection_id &&
        (!original_destination_connection_id_.has_value() ||
         last_received_packet_info_.destination_connection_id !=
             *original_destination_connection_id_)) {
      QUIC_CODE_COUNT(quic_connection_id_change);
    }

    QUIC_DLOG_IF(INFO, current_effective_peer_migration_type_ != NO_CHANGE)
        << ENDPOINT << "Effective peer's ip:port changed from "
        << default_path_.peer_address.ToString() << " to "
        << GetEffectivePeerAddressFromCurrentPacket().ToString()
        << ", active_effective_peer_migration_type is "
        << active_effective_peer_migration_type_;
  }

  --stats_.packets_dropped;
  QUIC_DVLOG(1) << ENDPOINT << "Received packet header: " << header;
  last_received_packet_info_.header = header;
  if (!stats_.first_decrypted_packet.IsInitialized()) {
    stats_.first_decrypted_packet =
        last_received_packet_info_.header.packet_number;
  }

  switch (last_received_packet_info_.ecn_codepoint) {
    case ECN_NOT_ECT:
      break;
    case ECN_ECT0:
      stats_.num_ecn_marks_received.ect0++;
      break;
    case ECN_ECT1:
      stats_.num_ecn_marks_received.ect1++;
      break;
    case ECN_CE:
      stats_.num_ecn_marks_received.ce++;
      break;
  }

  // Record packet receipt to populate ack info before processing stream
  // frames, since the processing may result in sending a bundled ack.
  QuicTime receipt_time = idle_network_detector_.time_of_last_received_packet();
  if (SupportsMultiplePacketNumberSpaces()) {
    receipt_time = last_received_packet_info_.receipt_time;
  }
  uber_received_packet_manager_.RecordPacketReceived(
      last_received_packet_info_.decrypted_level,
      last_received_packet_info_.header, receipt_time,
      last_received_packet_info_.ecn_codepoint);
  if (EnforceAntiAmplificationLimit() && !IsHandshakeConfirmed() &&
      !header.retry_token.empty() &&
      visitor_->ValidateToken(header.retry_token)) {
    QUIC_DLOG(INFO) << ENDPOINT << "Address validated via token.";
    QUIC_CODE_COUNT(quic_address_validated_via_token);
    default_path_.validated = true;
    stats_.address_validated_via_token = true;
  }
  QUICHE_DCHECK(connected_);
  return true;
}

bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_3, !connected_)
      << "Processing STREAM frame when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;

  // Since a stream frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(STREAM_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnStreamFrame(frame);
  }
  if (!QuicUtils::IsCryptoStreamId(transport_version(), frame.stream_id) &&
      last_received_packet_info_.decrypted_level == ENCRYPTION_INITIAL) {
    if (MaybeConsiderAsMemoryCorruption(frame)) {
      CloseConnection(QUIC_MAYBE_CORRUPTED_MEMORY,
                      "Received crypto frame on non crypto stream.",
                      ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
      return false;
    }

    QUIC_PEER_BUG(quic_peer_bug_10511_6)
        << ENDPOINT << "Received an unencrypted data frame: closing connection"
        << " packet_number:" << last_received_packet_info_.header.packet_number
        << " stream_id:" << frame.stream_id
        << " received_packets:" << ack_frame();
    CloseConnection(QUIC_UNENCRYPTED_STREAM_DATA,
                    "Unencrypted stream data seen.",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  // TODO(fayang): Consider moving UpdatePacketContent and
  // MaybeUpdateAckTimeout to a stand-alone function instead of calling them for
  // all frames.
  MaybeUpdateAckTimeout();
  visitor_->OnStreamFrame(frame);
  stats_.stream_bytes_received += frame.data_length;
  ping_manager_.reset_consecutive_retransmittable_on_wire_count();
  return connected_;
}

bool QuicConnection::OnCryptoFrame(const QuicCryptoFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_4, !connected_)
      << "Processing CRYPTO frame when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;

  // Since a CRYPTO frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(CRYPTO_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnCryptoFrame(frame);
  }
  MaybeUpdateAckTimeout();
  visitor_->OnCryptoFrame(frame);
  return connected_;
}

bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
                                     QuicTime::Delta ack_delay_time) {
  QUIC_BUG_IF(quic_bug_12714_5, !connected_)
      << "Processing ACK frame start when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;

  if (processing_ack_frame_) {
    CloseConnection(QUIC_INVALID_ACK_DATA,
                    "Received a new ack while processing an ack frame.",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }

  // Since an ack frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(ACK_FRAME)) {
    return false;
  }

  QUIC_DVLOG(1) << ENDPOINT
                << "OnAckFrameStart, largest_acked: " << largest_acked;

  if (GetLargestReceivedPacketWithAck().IsInitialized() &&
      last_received_packet_info_.header.packet_number <=
          GetLargestReceivedPacketWithAck()) {
    QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
    return true;
  }

  if (!sent_packet_manager_.GetLargestSentPacket().IsInitialized() ||
      largest_acked > sent_packet_manager_.GetLargestSentPacket()) {
    QUIC_DLOG(WARNING) << ENDPOINT
                       << "Peer's observed unsent packet:" << largest_acked
                       << " vs " << sent_packet_manager_.GetLargestSentPacket()
                       << ". SupportsMultiplePacketNumberSpaces():"
                       << SupportsMultiplePacketNumberSpaces()
                       << ", last_received_packet_info_.decrypted_level:"
                       << last_received_packet_info_.decrypted_level;
    // We got an ack for data we have not sent.
    CloseConnection(QUIC_INVALID_ACK_DATA, "Largest observed too high.",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  processing_ack_frame_ = true;
  sent_packet_manager_.OnAckFrameStart(
      largest_acked, ack_delay_time,
      idle_network_detector_.time_of_last_received_packet());
  return true;
}

bool QuicConnection::OnAckRange(QuicPacketNumber start, QuicPacketNumber end) {
  QUIC_BUG_IF(quic_bug_12714_6, !connected_)
      << "Processing ACK frame range when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;
  QUIC_DVLOG(1) << ENDPOINT << "OnAckRange: [" << start << ", " << end << ")";

  if (GetLargestReceivedPacketWithAck().IsInitialized() &&
      last_received_packet_info_.header.packet_number <=
          GetLargestReceivedPacketWithAck()) {
    QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
    return true;
  }

  sent_packet_manager_.OnAckRange(start, end);
  return true;
}

bool QuicConnection::OnAckTimestamp(QuicPacketNumber packet_number,
                                    QuicTime timestamp) {
  QUIC_BUG_IF(quic_bug_10511_7, !connected_)
      << "Processing ACK frame time stamp when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;
  QUIC_DVLOG(1) << ENDPOINT << "OnAckTimestamp: [" << packet_number << ", "
                << timestamp.ToDebuggingValue() << ")";

  if (GetLargestReceivedPacketWithAck().IsInitialized() &&
      last_received_packet_info_.header.packet_number <=
          GetLargestReceivedPacketWithAck()) {
    QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
    return true;
  }

  sent_packet_manager_.OnAckTimestamp(packet_number, timestamp);
  return true;
}

void QuicConnection::OnAckEcnCounts(const QuicEcnCounts& ecn_counts) {
  QUIC_DVLOG(1) << ENDPOINT << "OnAckEcnCounts: [" << ecn_counts.ToString()
                << "]";
  PacketNumberSpace space = QuicUtils::GetPacketNumberSpace(
      last_received_packet_info_.decrypted_level);
  peer_ack_ecn_counts_[space] = ecn_counts;
}

bool QuicConnection::OnAckFrameEnd(QuicPacketNumber start) {
  QUIC_BUG_IF(quic_bug_12714_7, !connected_)
      << "Processing ACK frame end when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;
  QUIC_DVLOG(1) << ENDPOINT << "OnAckFrameEnd, start: " << start;

  if (GetLargestReceivedPacketWithAck().IsInitialized() &&
      last_received_packet_info_.header.packet_number <=
          GetLargestReceivedPacketWithAck()) {
    QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
    return true;
  }
  const bool one_rtt_packet_was_acked =
      sent_packet_manager_.one_rtt_packet_acked();
  const bool zero_rtt_packet_was_acked =
      sent_packet_manager_.zero_rtt_packet_acked();
  const AckResult ack_result = sent_packet_manager_.OnAckFrameEnd(
      idle_network_detector_.time_of_last_received_packet(),
      last_received_packet_info_.header.packet_number,
      last_received_packet_info_.decrypted_level);
  if (ack_result != PACKETS_NEWLY_ACKED &&
      ack_result != NO_PACKETS_NEWLY_ACKED) {
    // Error occurred (e.g., this ACK tries to ack packets in wrong packet
    // number space), and this would cause the connection to be closed.
    QUIC_DLOG(ERROR) << ENDPOINT
                     << "Error occurred when processing an ACK frame: "
                     << QuicUtils::AckResultToString(ack_result);
    return false;
  }
  if (SupportsMultiplePacketNumberSpaces() && !one_rtt_packet_was_acked &&
      sent_packet_manager_.one_rtt_packet_acked()) {
    visitor_->OnOneRttPacketAcknowledged();
  }
  if (debug_visitor_ != nullptr && version().UsesTls() &&
      !zero_rtt_packet_was_acked &&
      sent_packet_manager_.zero_rtt_packet_acked()) {
    debug_visitor_->OnZeroRttPacketAcked();
  }
  // Cancel the send alarm because new packets likely have been acked, which
  // may change the congestion window and/or pacing rate.  Canceling the alarm
  // causes CanWrite to recalculate the next send time.
  if (send_alarm_->IsSet()) {
    send_alarm_->Cancel();
  }
  if (supports_release_time_) {
    // Update pace time into future because smoothed RTT is likely updated.
    UpdateReleaseTimeIntoFuture();
  }
  SetLargestReceivedPacketWithAck(
      last_received_packet_info_.header.packet_number);
  // If the incoming ack's packets set expresses missing packets: peer is still
  // waiting for a packet lower than a packet that we are no longer planning to
  // send.
  // If the incoming ack's packets set expresses received packets: peer is still
  // acking packets which we never care about.
  // Send an ack to raise the high water mark.
  const bool send_stop_waiting =
      no_stop_waiting_frames_ ? false : GetLeastUnacked() > start;
  PostProcessAfterAckFrame(send_stop_waiting,
                           ack_result == PACKETS_NEWLY_ACKED);
  processing_ack_frame_ = false;
  return connected_;
}

bool QuicConnection::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_8, !connected_)
      << "Processing STOP_WAITING frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;

  // Since a stop waiting frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(STOP_WAITING_FRAME)) {
    return false;
  }

  if (no_stop_waiting_frames_) {
    return true;
  }
  if (largest_seen_packet_with_stop_waiting_.IsInitialized() &&
      last_received_packet_info_.header.packet_number <=
          largest_seen_packet_with_stop_waiting_) {
    QUIC_DLOG(INFO) << ENDPOINT
                    << "Received an old stop waiting frame: ignoring";
    return true;
  }

  const char* error = ValidateStopWaitingFrame(frame);
  if (error != nullptr) {
    CloseConnection(QUIC_INVALID_STOP_WAITING_DATA, error,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnStopWaitingFrame(frame);
  }

  largest_seen_packet_with_stop_waiting_ =
      last_received_packet_info_.header.packet_number;
  uber_received_packet_manager_.DontWaitForPacketsBefore(
      last_received_packet_info_.decrypted_level, frame.least_unacked);
  return connected_;
}

bool QuicConnection::OnPaddingFrame(const QuicPaddingFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_9, !connected_)
      << "Processing PADDING frame when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;
  if (!UpdatePacketContent(PADDING_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnPaddingFrame(frame);
  }
  return true;
}

bool QuicConnection::OnPingFrame(const QuicPingFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_10, !connected_)
      << "Processing PING frame when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;
  if (!UpdatePacketContent(PING_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    QuicTime::Delta ping_received_delay = QuicTime::Delta::Zero();
    const QuicTime now = clock_->ApproximateNow();
    if (now > stats_.connection_creation_time) {
      ping_received_delay = now - stats_.connection_creation_time;
    }
    debug_visitor_->OnPingFrame(frame, ping_received_delay);
  }
  MaybeUpdateAckTimeout();
  return true;
}

const char* QuicConnection::ValidateStopWaitingFrame(
    const QuicStopWaitingFrame& stop_waiting) {
  const QuicPacketNumber peer_least_packet_awaiting_ack =
      uber_received_packet_manager_.peer_least_packet_awaiting_ack();
  if (peer_least_packet_awaiting_ack.IsInitialized() &&
      stop_waiting.least_unacked < peer_least_packet_awaiting_ack) {
    QUIC_DLOG(ERROR) << ENDPOINT << "Peer's sent low least_unacked: "
                     << stop_waiting.least_unacked << " vs "
                     << peer_least_packet_awaiting_ack;
    // We never process old ack frames, so this number should only increase.
    return "Least unacked too small.";
  }

  if (stop_waiting.least_unacked >
      last_received_packet_info_.header.packet_number) {
    QUIC_DLOG(ERROR) << ENDPOINT
                     << "Peer sent least_unacked:" << stop_waiting.least_unacked
                     << " greater than the enclosing packet number:"
                     << last_received_packet_info_.header.packet_number;
    return "Least unacked too large.";
  }

  return nullptr;
}

bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_11, !connected_)
      << "Processing RST_STREAM frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;

  // Since a reset stream frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(RST_STREAM_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnRstStreamFrame(frame);
  }
  QUIC_DLOG(INFO) << ENDPOINT
                  << "RST_STREAM_FRAME received for stream: " << frame.stream_id
                  << " with error: "
                  << QuicRstStreamErrorCodeToString(frame.error_code);
  MaybeUpdateAckTimeout();
  visitor_->OnRstStream(frame);
  return connected_;
}

bool QuicConnection::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_12, !connected_)
      << "Processing STOP_SENDING frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;

  // Since a reset stream frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(STOP_SENDING_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnStopSendingFrame(frame);
  }

  QUIC_DLOG(INFO) << ENDPOINT << "STOP_SENDING frame received for stream: "
                  << frame.stream_id
                  << " with error: " << frame.ietf_error_code;
  MaybeUpdateAckTimeout();
  visitor_->OnStopSendingFrame(frame);
  return connected_;
}

class ReversePathValidationContext : public QuicPathValidationContext {
 public:
  ReversePathValidationContext(const QuicSocketAddress& self_address,
                               const QuicSocketAddress& peer_address,
                               const QuicSocketAddress& effective_peer_address,
                               QuicConnection* connection)
      : QuicPathValidationContext(self_address, peer_address,
                                  effective_peer_address),
        connection_(connection) {}

  QuicPacketWriter* WriterToUse() override { return connection_->writer(); }

 private:
  QuicConnection* connection_;
};

bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) {
  QUIC_BUG_IF(quic_bug_10511_8, !connected_)
      << "Processing PATH_CHALLENGE frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;
  if (has_path_challenge_in_current_packet_) {
    // Only respond to the 1st PATH_CHALLENGE in the packet.
    return true;
  }
  if (!validate_client_addresses_) {
    return OnPathChallengeFrameInternal(frame);
  }
  {
    // TODO(danzh) inline OnPathChallengeFrameInternal() once
    // validate_client_addresses_ is deprecated.
    if (!OnPathChallengeFrameInternal(frame)) {
      return false;
    }
  }
  return connected_;
}

bool QuicConnection::OnPathChallengeFrameInternal(
    const QuicPathChallengeFrame& frame) {
  should_proactively_validate_peer_address_on_path_challenge_ = false;
  // UpdatePacketContent() may start reverse path validation.
  if (!UpdatePacketContent(PATH_CHALLENGE_FRAME)) {
    return false;
  }
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnPathChallengeFrame(frame);
  }
  // On the server side, send response to the source address of the current
  // incoming packet according to RFC9000.
  // On the client side, send response to the default peer address which should
  // be on an existing path with a pre-assigned a destination CID.
  const QuicSocketAddress effective_peer_address_to_respond =
      perspective_ == Perspective::IS_CLIENT
          ? effective_peer_address()
          : GetEffectivePeerAddressFromCurrentPacket();
  const QuicSocketAddress direct_peer_address_to_respond =
      perspective_ == Perspective::IS_CLIENT
          ? direct_peer_address_
          : last_received_packet_info_.source_address;
  QuicConnectionId client_cid, server_cid;
  FindOnPathConnectionIds(last_received_packet_info_.destination_address,
                          effective_peer_address_to_respond, &client_cid,
                          &server_cid);
  QuicPacketCreator::ScopedPeerAddressContext context(
      &packet_creator_, direct_peer_address_to_respond, client_cid, server_cid,
      connection_migration_use_new_cid_);
  if (should_proactively_validate_peer_address_on_path_challenge_) {
    // Conditions to proactively validate peer address:
    // The perspective is server
    // The PATH_CHALLENGE is received on an unvalidated alternative path.
    // The connection isn't validating migrated peer address, which is of
    // higher prority.
    QUIC_DVLOG(1) << "Proactively validate the effective peer address "
                  << effective_peer_address_to_respond;
    QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 2, 6);
    ValidatePath(std::make_unique<ReversePathValidationContext>(
                     default_path_.self_address, direct_peer_address_to_respond,
                     effective_peer_address_to_respond, this),
                 std::make_unique<ReversePathValidationResultDelegate>(
                     this, peer_address()),
                 PathValidationReason::kReversePathValidation);
  }
  has_path_challenge_in_current_packet_ = true;
  MaybeUpdateAckTimeout();
  // Queue or send PATH_RESPONSE.
  if (!SendPathResponse(frame.data_buffer, direct_peer_address_to_respond,
                        effective_peer_address_to_respond)) {
    QUIC_CODE_COUNT(quic_failed_to_send_path_response);
  }
  // TODO(b/150095588): change the stats to
  // num_valid_path_challenge_received.
  ++stats_.num_connectivity_probing_received;

  // SendPathResponse() might cause connection to be closed.
  return connected_;
}

bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) {
  QUIC_BUG_IF(quic_bug_10511_9, !connected_)
      << "Processing PATH_RESPONSE frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;
  ++stats_.num_path_response_received;
  if (!UpdatePacketContent(PATH_RESPONSE_FRAME)) {
    return false;
  }
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnPathResponseFrame(frame);
  }
  MaybeUpdateAckTimeout();
  path_validator_.OnPathResponse(
      frame.data_buffer, last_received_packet_info_.destination_address);
  return connected_;
}

bool QuicConnection::OnConnectionCloseFrame(
    const QuicConnectionCloseFrame& frame) {
  QUIC_BUG_IF(quic_bug_10511_10, !connected_)
      << "Processing CONNECTION_CLOSE frame when connection is closed. "
         "Received packet info: "
      << last_received_packet_info_;

  // Since a connection close frame was received, this is not a connectivity
  // probe. A probe only contains a PING and full padding.
  if (!UpdatePacketContent(CONNECTION_CLOSE_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnConnectionCloseFrame(frame);
  }
  switch (frame.close_type) {
    case GOOGLE_QUIC_CONNECTION_CLOSE:
      QUIC_DLOG(INFO) << ENDPOINT << "Received ConnectionClose for connection: "
                      << connection_id() << ", with error: "
                      << QuicErrorCodeToString(frame.quic_error_code) << " ("
                      << frame.error_details << ")";
      break;
    case IETF_QUIC_TRANSPORT_CONNECTION_CLOSE:
      QUIC_DLOG(INFO) << ENDPOINT
                      << "Received Transport ConnectionClose for connection: "
                      << connection_id() << ", with error: "
                      << QuicErrorCodeToString(frame.quic_error_code) << " ("
                      << frame.error_details << ")"
                      << ", transport error code: "
                      << QuicIetfTransportErrorCodeString(
                             static_cast<QuicIetfTransportErrorCodes>(
                                 frame.wire_error_code))
                      << ", error frame type: "
                      << frame.transport_close_frame_type;
      break;
    case IETF_QUIC_APPLICATION_CONNECTION_CLOSE:
      QUIC_DLOG(INFO) << ENDPOINT
                      << "Received Application ConnectionClose for connection: "
                      << connection_id() << ", with error: "
                      << QuicErrorCodeToString(frame.quic_error_code) << " ("
                      << frame.error_details << ")"
                      << ", application error code: " << frame.wire_error_code;
      break;
  }

  if (frame.quic_error_code == QUIC_BAD_MULTIPATH_FLAG) {
    QUIC_LOG_FIRST_N(ERROR, 10)
        << "Unexpected QUIC_BAD_MULTIPATH_FLAG error."
        << " last_received_header: " << last_received_packet_info_.header
        << " encryption_level: " << encryption_level_;
  }
  TearDownLocalConnectionState(frame, ConnectionCloseSource::FROM_PEER);
  return connected_;
}

bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_13, !connected_)
      << "Processing MAX_STREAMS frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;
  if (!UpdatePacketContent(MAX_STREAMS_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnMaxStreamsFrame(frame);
  }
  MaybeUpdateAckTimeout();
  return visitor_->OnMaxStreamsFrame(frame) && connected_;
}

bool QuicConnection::OnStreamsBlockedFrame(
    const QuicStreamsBlockedFrame& frame) {
  QUIC_BUG_IF(quic_bug_10511_11, !connected_)
      << "Processing STREAMS_BLOCKED frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;
  if (!UpdatePacketContent(STREAMS_BLOCKED_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnStreamsBlockedFrame(frame);
  }
  MaybeUpdateAckTimeout();
  return visitor_->OnStreamsBlockedFrame(frame) && connected_;
}

bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_14, !connected_)
      << "Processing GOAWAY frame when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;

  // Since a go away frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(GOAWAY_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnGoAwayFrame(frame);
  }
  QUIC_DLOG(INFO) << ENDPOINT << "GOAWAY_FRAME received with last good stream: "
                  << frame.last_good_stream_id
                  << " and error: " << QuicErrorCodeToString(frame.error_code)
                  << " and reason: " << frame.reason_phrase;
  MaybeUpdateAckTimeout();
  visitor_->OnGoAway(frame);
  return connected_;
}

bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
  QUIC_BUG_IF(quic_bug_10511_12, !connected_)
      << "Processing WINDOW_UPDATE frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;

  // Since a window update frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(WINDOW_UPDATE_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnWindowUpdateFrame(
        frame, idle_network_detector_.time_of_last_received_packet());
  }
  QUIC_DVLOG(1) << ENDPOINT << "WINDOW_UPDATE_FRAME received " << frame;
  MaybeUpdateAckTimeout();
  visitor_->OnWindowUpdateFrame(frame);
  return connected_;
}

void QuicConnection::OnClientConnectionIdAvailable() {
  QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
  if (!peer_issued_cid_manager_->HasUnusedConnectionId()) {
    return;
  }
  if (default_path_.client_connection_id.IsEmpty()) {
    // Count client connection ID patched onto the default path.
    QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 3,
                                 6);
    const QuicConnectionIdData* unused_cid_data =
        peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
    QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
                  << unused_cid_data->connection_id << " to default path";
    default_path_.client_connection_id = unused_cid_data->connection_id;
    default_path_.stateless_reset_token =
        unused_cid_data->stateless_reset_token;
    QUICHE_DCHECK(!packet_creator_.HasPendingFrames());
    QUICHE_DCHECK(packet_creator_.GetDestinationConnectionId().IsEmpty());
    packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
    return;
  }
  if (alternative_path_.peer_address.IsInitialized() &&
      alternative_path_.client_connection_id.IsEmpty()) {
    // Count client connection ID patched onto the alternative path.
    QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 4,
                                 6);
    const QuicConnectionIdData* unused_cid_data =
        peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
    QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
                  << unused_cid_data->connection_id << " to alternative path";
    alternative_path_.client_connection_id = unused_cid_data->connection_id;
    alternative_path_.stateless_reset_token =
        unused_cid_data->stateless_reset_token;
  }
}

bool QuicConnection::OnNewConnectionIdFrameInner(
    const QuicNewConnectionIdFrame& frame) {
  if (peer_issued_cid_manager_ == nullptr) {
    CloseConnection(
        IETF_QUIC_PROTOCOL_VIOLATION,
        "Receives NEW_CONNECTION_ID while peer uses zero length connection ID",
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  std::string error_detail;
  QuicErrorCode error =
      peer_issued_cid_manager_->OnNewConnectionIdFrame(frame, &error_detail);
  if (error != QUIC_NO_ERROR) {
    CloseConnection(error, error_detail,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  if (perspective_ == Perspective::IS_SERVER) {
    OnClientConnectionIdAvailable();
  }
  MaybeUpdateAckTimeout();
  return true;
}

bool QuicConnection::OnNewConnectionIdFrame(
    const QuicNewConnectionIdFrame& frame) {
  QUICHE_DCHECK(version().HasIetfQuicFrames());
  QUIC_BUG_IF(quic_bug_10511_13, !connected_)
      << "Processing NEW_CONNECTION_ID frame when connection is closed. "
         "Received packet info: "
      << last_received_packet_info_;
  if (!UpdatePacketContent(NEW_CONNECTION_ID_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnNewConnectionIdFrame(frame);
  }

  if (!OnNewConnectionIdFrameInner(frame)) {
    return false;
  }
  if (multi_port_stats_ != nullptr) {
    MaybeCreateMultiPortPath();
  }
  return true;
}

bool QuicConnection::OnRetireConnectionIdFrame(
    const QuicRetireConnectionIdFrame& frame) {
  QUICHE_DCHECK(version().HasIetfQuicFrames());
  QUIC_BUG_IF(quic_bug_10511_14, !connected_)
      << "Processing RETIRE_CONNECTION_ID frame when connection is closed. "
         "Received packet info: "
      << last_received_packet_info_;
  if (!UpdatePacketContent(RETIRE_CONNECTION_ID_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnRetireConnectionIdFrame(frame);
  }
  if (!connection_migration_use_new_cid_) {
    // Do not respond to RetireConnectionId frame.
    return true;
  }
  if (self_issued_cid_manager_ == nullptr) {
    CloseConnection(
        IETF_QUIC_PROTOCOL_VIOLATION,
        "Receives RETIRE_CONNECTION_ID while new connection ID is never issued",
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  std::string error_detail;
  QuicErrorCode error = self_issued_cid_manager_->OnRetireConnectionIdFrame(
      frame, sent_packet_manager_.GetPtoDelay(), &error_detail);
  if (error != QUIC_NO_ERROR) {
    CloseConnection(error, error_detail,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  // Count successfully received RETIRE_CONNECTION_ID frames.
  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 5, 6);
  MaybeUpdateAckTimeout();
  return true;
}

bool QuicConnection::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_15, !connected_)
      << "Processing NEW_TOKEN frame when connection is closed. Received "
         "packet info: "
      << last_received_packet_info_;
  if (!UpdatePacketContent(NEW_TOKEN_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnNewTokenFrame(frame);
  }
  if (perspective_ == Perspective::IS_SERVER) {
    CloseConnection(QUIC_INVALID_NEW_TOKEN, "Server received new token frame.",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }
  // NEW_TOKEN frame should insitgate ACKs.
  MaybeUpdateAckTimeout();
  visitor_->OnNewTokenReceived(frame.token);
  return true;
}

bool QuicConnection::OnMessageFrame(const QuicMessageFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_16, !connected_)
      << "Processing MESSAGE frame when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;

  // Since a message frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(MESSAGE_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnMessageFrame(frame);
  }
  MaybeUpdateAckTimeout();
  visitor_->OnMessageReceived(
      absl::string_view(frame.data, frame.message_length));
  return connected_;
}

bool QuicConnection::OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) {
  QUIC_BUG_IF(quic_bug_10511_15, !connected_)
      << "Processing HANDSHAKE_DONE frame when connection "
         "is closed. Received packet "
         "info: "
      << last_received_packet_info_;
  if (!version().UsesTls()) {
    CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
                    "Handshake done frame is unsupported",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }

  if (perspective_ == Perspective::IS_SERVER) {
    CloseConnection(IETF_QUIC_PROTOCOL_VIOLATION,
                    "Server received handshake done frame.",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return false;
  }

  // Since a handshake done frame was received, this is not a connectivity
  // probe. A probe only contains a PING and full padding.
  if (!UpdatePacketContent(HANDSHAKE_DONE_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnHandshakeDoneFrame(frame);
  }
  MaybeUpdateAckTimeout();
  visitor_->OnHandshakeDoneReceived();
  return connected_;
}

bool QuicConnection::OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) {
  QUIC_BUG_IF(quic_bug_10511_16, !connected_)
      << "Processing ACK_FREQUENCY frame when connection "
         "is closed. Received packet "
         "info: "
      << last_received_packet_info_;
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnAckFrequencyFrame(frame);
  }
  if (!UpdatePacketContent(ACK_FREQUENCY_FRAME)) {
    return false;
  }

  if (!can_receive_ack_frequency_frame_) {
    QUIC_LOG_EVERY_N_SEC(ERROR, 120) << "Get unexpected AckFrequencyFrame.";
    return false;
  }
  if (auto packet_number_space =
          QuicUtils::GetPacketNumberSpace(
              last_received_packet_info_.decrypted_level) == APPLICATION_DATA) {
    uber_received_packet_manager_.OnAckFrequencyFrame(frame);
  } else {
    QUIC_LOG_EVERY_N_SEC(ERROR, 120)
        << "Get AckFrequencyFrame in packet number space "
        << packet_number_space;
  }
  MaybeUpdateAckTimeout();
  return true;
}

bool QuicConnection::OnBlockedFrame(const QuicBlockedFrame& frame) {
  QUIC_BUG_IF(quic_bug_12714_17, !connected_)
      << "Processing BLOCKED frame when connection is closed. Received packet "
         "info: "
      << last_received_packet_info_;

  // Since a blocked frame was received, this is not a connectivity probe.
  // A probe only contains a PING and full padding.
  if (!UpdatePacketContent(BLOCKED_FRAME)) {
    return false;
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnBlockedFrame(frame);
  }
  QUIC_DLOG(INFO) << ENDPOINT
                  << "BLOCKED_FRAME received for stream: " << frame.stream_id;
  MaybeUpdateAckTimeout();
  visitor_->OnBlockedFrame(frame);
  stats_.blocked_frames_received++;
  return connected_;
}

void QuicConnection::OnPacketComplete() {
  // Don't do anything if this packet closed the connection.
  if (!connected_) {
    ClearLastFrames();
    return;
  }

  if (IsCurrentPacketConnectivityProbing()) {
    QUICHE_DCHECK(!version().HasIetfQuicFrames());
    ++stats_.num_connectivity_probing_received;
  }

  QUIC_DVLOG(1) << ENDPOINT << "Got"
                << (SupportsMultiplePacketNumberSpaces()
                        ? (" " +
                           EncryptionLevelToString(
                               last_received_packet_info_.decrypted_level))
                        : "")
                << " packet " << last_received_packet_info_.header.packet_number
                << " for "
                << GetServerConnectionIdAsRecipient(
                       last_received_packet_info_.header, perspective_);

  QUIC_DLOG_IF(INFO, current_packet_content_ == SECOND_FRAME_IS_PADDING)
      << ENDPOINT << "Received a padded PING packet. is_probing: "
      << IsCurrentPacketConnectivityProbing();

  if (!version().HasIetfQuicFrames()) {
    MaybeRespondToConnectivityProbingOrMigration();
  }

  current_effective_peer_migration_type_ = NO_CHANGE;

  // For IETF QUIC, it is guaranteed that TLS will give connection the
  // corresponding write key before read key. In other words, connection should
  // never process a packet while an ACK for it cannot be encrypted.
  if (!should_last_packet_instigate_acks_) {
    uber_received_packet_manager_.MaybeUpdateAckTimeout(
        should_last_packet_instigate_acks_,
        last_received_packet_info_.decrypted_level,
        last_received_packet_info_.header.packet_number,
        last_received_packet_info_.receipt_time, clock_->ApproximateNow(),
        sent_packet_manager_.GetRttStats());
  }

  ClearLastFrames();
  CloseIfTooManyOutstandingSentPackets();
}

void QuicConnection::MaybeRespondToConnectivityProbingOrMigration() {
  QUICHE_DCHECK(!version().HasIetfQuicFrames());
  if (IsCurrentPacketConnectivityProbing()) {
    visitor_->OnPacketReceived(last_received_packet_info_.destination_address,
                               last_received_packet_info_.source_address,
                               /*is_connectivity_probe=*/true);
    return;
  }
  if (perspective_ == Perspective::IS_CLIENT) {
    // This node is a client, notify that a speculative connectivity probing
    // packet has been received anyway.
    QUIC_DVLOG(1) << ENDPOINT
                  << "Received a speculative connectivity probing packet for "
                  << GetServerConnectionIdAsRecipient(
                         last_received_packet_info_.header, perspective_)
                  << " from ip:port: "
                  << last_received_packet_info_.source_address.ToString()
                  << " to ip:port: "
                  << last_received_packet_info_.destination_address.ToString();
    visitor_->OnPacketReceived(last_received_packet_info_.destination_address,
                               last_received_packet_info_.source_address,
                               /*is_connectivity_probe=*/false);
    return;
  }
}

bool QuicConnection::IsValidStatelessResetToken(
    const StatelessResetToken& token) const {
  QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
  return default_path_.stateless_reset_token.has_value() &&
         QuicUtils::AreStatelessResetTokensEqual(
             token, *default_path_.stateless_reset_token);
}

void QuicConnection::OnAuthenticatedIetfStatelessResetPacket(
    const QuicIetfStatelessResetPacket& /*packet*/) {
  // TODO(fayang): Add OnAuthenticatedIetfStatelessResetPacket to
  // debug_visitor_.
  QUICHE_DCHECK(version().HasIetfInvariantHeader());
  QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);

  if (!IsDefaultPath(last_received_packet_info_.destination_address,
                     last_received_packet_info_.source_address)) {
    // This packet is received on a probing path. Do not close connection.
    if (IsAlternativePath(last_received_packet_info_.destination_address,
                          GetEffectivePeerAddressFromCurrentPacket())) {
      QUIC_BUG_IF(quic_bug_12714_18, alternative_path_.validated)
          << "STATELESS_RESET received on alternate path after it's "
             "validated.";
      path_validator_.CancelPathValidation();
    } else {
      QUIC_BUG(quic_bug_10511_17)
          << "Received Stateless Reset on unknown socket.";
    }
    return;
  }

  const std::string error_details = "Received stateless reset.";
  QUIC_CODE_COUNT(quic_tear_down_local_connection_on_stateless_reset);
  TearDownLocalConnectionState(QUIC_PUBLIC_RESET, NO_IETF_QUIC_ERROR,
                               error_details, ConnectionCloseSource::FROM_PEER);
}

void QuicConnection::OnKeyUpdate(KeyUpdateReason reason) {
  QUICHE_DCHECK(support_key_update_for_connection_);
  QUIC_DLOG(INFO) << ENDPOINT << "Key phase updated for " << reason;

  lowest_packet_sent_in_current_key_phase_.Clear();
  stats_.key_update_count++;

  // If another key update triggers while the previous
  // discard_previous_one_rtt_keys_alarm_ hasn't fired yet, cancel it since the
  // old keys would already be discarded.
  discard_previous_one_rtt_keys_alarm_->Cancel();

  visitor_->OnKeyUpdate(reason);
}

void QuicConnection::OnDecryptedFirstPacketInKeyPhase() {
  QUIC_DLOG(INFO) << ENDPOINT << "OnDecryptedFirstPacketInKeyPhase";
  // An endpoint SHOULD retain old read keys for no more than three times the
  // PTO after having received a packet protected using the new keys. After this
  // period, old read keys and their corresponding secrets SHOULD be discarded.
  //
  // Note that this will cause an unnecessary
  // discard_previous_one_rtt_keys_alarm_ on the first packet in the 1RTT
  // encryption level, but this is harmless.
  discard_previous_one_rtt_keys_alarm_->Set(
      clock_->ApproximateNow() + sent_packet_manager_.GetPtoDelay() * 3);
}

std::unique_ptr<QuicDecrypter>
QuicConnection::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
  QUIC_DLOG(INFO) << ENDPOINT << "AdvanceKeysAndCreateCurrentOneRttDecrypter";
  return visitor_->AdvanceKeysAndCreateCurrentOneRttDecrypter();
}

std::unique_ptr<QuicEncrypter> QuicConnection::CreateCurrentOneRttEncrypter() {
  QUIC_DLOG(INFO) << ENDPOINT << "CreateCurrentOneRttEncrypter";
  return visitor_->CreateCurrentOneRttEncrypter();
}

void QuicConnection::ClearLastFrames() {
  should_last_packet_instigate_acks_ = false;
}

void QuicConnection::CloseIfTooManyOutstandingSentPackets() {
  // This occurs if we don't discard old packets we've seen fast enough. It's
  // possible largest observed is less than leaset unacked.
  const bool should_close =
      sent_packet_manager_.GetLargestSentPacket().IsInitialized() &&
      sent_packet_manager_.GetLargestSentPacket() >
          sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_;

  if (should_close) {
    CloseConnection(
        QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
        absl::StrCat("More than ", max_tracked_packets_,
                     " outstanding, least_unacked: ",
                     sent_packet_manager_.GetLeastUnacked().ToUint64(),
                     ", packets_processed: ", stats_.packets_processed,
                     ", last_decrypted_packet_level: ",
                     EncryptionLevelToString(
                         last_received_packet_info_.decrypted_level)),
        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
  }
}

const QuicFrame QuicConnection::GetUpdatedAckFrame() {
  QUICHE_DCHECK(!uber_received_packet_manager_.IsAckFrameEmpty(
      QuicUtils::GetPacketNumberSpace(encryption_level_)))
      << "Try to retrieve an empty ACK frame";
  return uber_received_packet_manager_.GetUpdatedAckFrame(
      QuicUtils::GetPacketNumberSpace(encryption_level_),
      clock_->ApproximateNow());
}

void QuicConnection::PopulateStopWaitingFrame(
    QuicStopWaitingFrame* stop_waiting) {
  stop_waiting->least_unacked = GetLeastUnacked();
}

QuicPacketNumber QuicConnection::GetLeastUnacked() const {
  return sent_packet_manager_.GetLeastUnacked();
}

bool QuicConnection::HandleWriteBlocked() {
  if (!writer_->IsWriteBlocked()) {
    return false;
  }

  visitor_->OnWriteBlocked();
  return true;
}

void QuicConnection::MaybeSendInResponseToPacket() {
  if (!connected_) {
    return;
  }

  // If the writer is blocked, don't attempt to send packets now or in the send
  // alarm. When the writer unblocks, OnCanWrite() will be called for this
  // connection to send.
  if (HandleWriteBlocked()) {
    return;
  }

  // Now that we have received an ack, we might be able to send packets which
  // are queued locally, or drain streams which are blocked.
  if (defer_send_in_response_to_packets_) {
    send_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero());
  } else {
    WriteIfNotBlocked();
  }
}

size_t QuicConnection::SendCryptoData(EncryptionLevel level,
                                      size_t write_length,
                                      QuicStreamOffset offset) {
  if (write_length == 0) {
    QUIC_BUG(quic_bug_10511_18) << "Attempt to send empty crypto frame";
    return 0;
  }
  ScopedPacketFlusher flusher(this);
  return packet_creator_.ConsumeCryptoData(level, write_length, offset);
}

QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
                                                size_t write_length,
                                                QuicStreamOffset offset,
                                                StreamSendingState state) {
  if (state == NO_FIN && write_length == 0) {
    QUIC_BUG(quic_bug_10511_19) << "Attempt to send empty stream frame";
    return QuicConsumedData(0, false);
  }

  if (perspective_ == Perspective::IS_SERVER &&
      version().CanSendCoalescedPackets() && !IsHandshakeConfirmed()) {
    if (in_probe_time_out_ && coalesced_packet_.NumberOfPackets() == 0u) {
      // PTO fires while handshake is not confirmed. Do not preempt handshake
      // data with stream data.
      QUIC_CODE_COUNT(quic_try_to_send_half_rtt_data_when_pto_fires);
      return QuicConsumedData(0, false);
    }
    if (coalesced_packet_.ContainsPacketOfEncryptionLevel(ENCRYPTION_INITIAL) &&
        coalesced_packet_.NumberOfPackets() == 1u) {
      // Handshake is not confirmed yet, if there is only an initial packet in
      // the coalescer, try to bundle an ENCRYPTION_HANDSHAKE packet before
      // sending stream data.
      sent_packet_manager_.RetransmitDataOfSpaceIfAny(HANDSHAKE_DATA);
    }
  }
  // Opportunistically bundle an ack with every outgoing packet.
  // Particularly, we want to bundle with handshake packets since we don't
  // know which decrypter will be used on an ack packet following a handshake
  // packet (a handshake packet from client to server could result in a REJ or
  // a SHLO from the server, leading to two different decrypters at the
  // server.)
  ScopedPacketFlusher flusher(this);
  return packet_creator_.ConsumeData(id, write_length, offset, state);
}

bool QuicConnection::SendControlFrame(const QuicFrame& frame) {
  if (SupportsMultiplePacketNumberSpaces() &&
      (encryption_level_ == ENCRYPTION_INITIAL ||
       encryption_level_ == ENCRYPTION_HANDSHAKE) &&
      frame.type != PING_FRAME) {
    // Allow PING frame to be sent without APPLICATION key. For example, when
    // anti-amplification limit is used, client needs to send something to avoid
    // handshake deadlock.
    QUIC_DVLOG(1) << ENDPOINT << "Failed to send control frame: " << frame
                  << " at encryption level: " << encryption_level_;
    return false;
  }
  ScopedPacketFlusher flusher(this);
  const bool consumed =
      packet_creator_.ConsumeRetransmittableControlFrame(frame);
  if (!consumed) {
    QUIC_DVLOG(1) << ENDPOINT << "Failed to send control frame: " << frame;
    return false;
  }
  if (frame.type == PING_FRAME) {
    // Flush PING frame immediately.
    packet_creator_.FlushCurrentPacket();
    stats_.ping_frames_sent++;
    if (debug_visitor_ != nullptr) {
      debug_visitor_->OnPingSent();
    }
  }
  if (frame.type == BLOCKED_FRAME) {
    stats_.blocked_frames_sent++;
  }
  return true;
}

void QuicConnection::OnStreamReset(QuicStreamId id,
                                   QuicRstStreamErrorCode error) {
  if (error == QUIC_STREAM_NO_ERROR) {
    // All data for streams which are reset with QUIC_STREAM_NO_ERROR must
    // be received by the peer.
    return;
  }
  // Flush stream frames of reset stream.
  if (packet_creator_.HasPendingStreamFramesOfStream(id)) {
    ScopedPacketFlusher flusher(this);
    packet_creator_.FlushCurrentPacket();
  }
  // TODO(ianswett): Consider checking for 3 RTOs when the last stream is
  // cancelled as well.
}

const QuicConnectionStats& QuicConnection::GetStats() {
  const RttStats* rtt_stats = sent_packet_manager_.GetRttStats();

  // Update rtt and estimated bandwidth.
  QuicTime::Delta min_rtt = rtt_stats->min_rtt();
  if (min_rtt.IsZero()) {
    // If min RTT has not been set, use initial RTT instead.
    min_rtt = rtt_stats->initial_rtt();
  }
  stats_.min_rtt_us = min_rtt.ToMicroseconds();

  QuicTime::Delta srtt = rtt_stats->SmoothedOrInitialRtt();
  stats_.srtt_us = srtt.ToMicroseconds();

  stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
  sent_packet_manager_.GetSendAlgorithm()->PopulateConnectionStats(&stats_);
  stats_.egress_mtu = long_term_mtu_;
  stats_.ingress_mtu = largest_received_packet_size_;
  return stats_;
}

void QuicConnection::OnCoalescedPacket(const QuicEncryptedPacket& packet) {
  QueueCoalescedPacket(packet);
}

void QuicConnection::OnUndecryptablePacket(const QuicEncryptedPacket& packet,
                                           EncryptionLevel decryption_level,
                                           bool has_decryption_key) {
  QUIC_DVLOG(1) << ENDPOINT << "Received undecryptable packet of length "
                << packet.length() << " with"
                << (has_decryption_key ? "" : "out") << " key at level "
                << decryption_level
                << " while connection is at encryption level "
                << encryption_level_;
  QUICHE_DCHECK(EncryptionLevelIsValid(decryption_level));
  if (encryption_level_ != ENCRYPTION_FORWARD_SECURE) {
    ++stats_.undecryptable_packets_received_before_handshake_complete;
  }

  const bool should_enqueue =
      ShouldEnqueueUnDecryptablePacket(decryption_level, has_decryption_key);
  if (should_enqueue) {
    QueueUndecryptablePacket(packet, decryption_level);
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnUndecryptablePacket(decryption_level,
                                          /*dropped=*/!should_enqueue);
  }

  if (has_decryption_key) {
    stats_.num_failed_authentication_packets_received++;
    if (version().UsesTls()) {
      // Should always be non-null if has_decryption_key is true.
      QUICHE_DCHECK(framer_.GetDecrypter(decryption_level));
      const QuicPacketCount integrity_limit =
          framer_.GetDecrypter(decryption_level)->GetIntegrityLimit();
      QUIC_DVLOG(2) << ENDPOINT << "Checking AEAD integrity limits:"
                    << " num_failed_authentication_packets_received="
                    << stats_.num_failed_authentication_packets_received
                    << " integrity_limit=" << integrity_limit;
      if (stats_.num_failed_authentication_packets_received >=
          integrity_limit) {
        const std::string error_details = absl::StrCat(
            "decrypter integrity limit reached:"
            " num_failed_authentication_packets_received=",
            stats_.num_failed_authentication_packets_received,
            " integrity_limit=", integrity_limit);
        CloseConnection(QUIC_AEAD_LIMIT_REACHED, error_details,
                        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
      }
    }
  }

  if (version().UsesTls() && perspective_ == Perspective::IS_SERVER &&
      decryption_level == ENCRYPTION_ZERO_RTT && !has_decryption_key &&
      had_zero_rtt_decrypter_) {
    QUIC_CODE_COUNT_N(
        quic_server_received_tls_zero_rtt_packet_after_discarding_decrypter, 1,
        3);
    stats_
        .num_tls_server_zero_rtt_packets_received_after_discarding_decrypter++;
  }
}

bool QuicConnection::ShouldEnqueueUnDecryptablePacket(
    EncryptionLevel decryption_level, bool has_decryption_key) const {
  if (has_decryption_key) {
    // We already have the key for this decryption level, therefore no
    // future keys will allow it be decrypted.
    return false;
  }
  if (IsHandshakeComplete()) {
    // We do not expect to install any further keys.
    return false;
  }
  if (undecryptable_packets_.size() >= max_undecryptable_packets_) {
    // We do not queue more than max_undecryptable_packets_ packets.
    return false;
  }
  if (version().KnowsWhichDecrypterToUse() &&
      decryption_level == ENCRYPTION_INITIAL) {
    // When the corresponding decryption key is not available, all
    // non-Initial packets should be buffered until the handshake is complete.
    return false;
  }
  if (perspective_ == Perspective::IS_CLIENT && version().UsesTls() &&
      decryption_level == ENCRYPTION_ZERO_RTT) {
    // Only clients send Zero RTT packets in IETF QUIC.
    QUIC_PEER_BUG(quic_peer_bug_client_received_zero_rtt)
        << "Client received a Zero RTT packet, not buffering.";
    return false;
  }
  return true;
}

std::string QuicConnection::UndecryptablePacketsInfo() const {
  std::string info = absl::StrCat(
      "num_undecryptable_packets: ", undecryptable_packets_.size(), " {");
  for (const auto& packet : undecryptable_packets_) {
    absl::StrAppend(&info, "[",
                    EncryptionLevelToString(packet.encryption_level), ", ",
                    packet.packet->length(), "]");
  }
  absl::StrAppend(&info, "}");
  return info;
}

void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
                                      const QuicSocketAddress& peer_address,
                                      const QuicReceivedPacket& packet) {
  if (!connected_) {
    return;
  }
  QUIC_DVLOG(2) << ENDPOINT << "Received encrypted " << packet.length()
                << " bytes:" << std::endl
                << quiche::QuicheTextUtils::HexDump(
                       absl::string_view(packet.data(), packet.length()));
  QUIC_BUG_IF(quic_bug_12714_21, current_packet_data_ != nullptr)
      << "ProcessUdpPacket must not be called while processing a packet.";
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnPacketReceived(self_address, peer_address, packet);
  }
  last_received_packet_info_ =
      ReceivedPacketInfo(self_address, peer_address, packet.receipt_time(),
                         packet.length(), packet.ecn_codepoint());
  current_packet_data_ = packet.data();

  if (!default_path_.self_address.IsInitialized()) {
    default_path_.self_address = last_received_packet_info_.destination_address;
  } else if (default_path_.self_address != self_address &&
             sent_server_preferred_address_.IsInitialized() &&
             self_address.Normalized() ==
                 sent_server_preferred_address_.Normalized()) {
    // If the packet is received at the preferred address, treat it as if it is
    // received on the original server address.
    last_received_packet_info_.destination_address = default_path_.self_address;
    last_received_packet_info_.actual_destination_address = self_address;
  }

  if (!direct_peer_address_.IsInitialized()) {
    if (perspective_ == Perspective::IS_CLIENT) {
      AddKnownServerAddress(last_received_packet_info_.source_address);
    }
    UpdatePeerAddress(last_received_packet_info_.source_address);
  }

  if (!default_path_.peer_address.IsInitialized()) {
    const QuicSocketAddress effective_peer_addr =
        GetEffectivePeerAddressFromCurrentPacket();

    // The default path peer_address must be initialized at the beginning of the
    // first packet processed(here). If effective_peer_addr is uninitialized,
    // just set effective_peer_address_ to the direct peer address.
    default_path_.peer_address = effective_peer_addr.IsInitialized()
                                     ? effective_peer_addr
                                     : direct_peer_address_;
  }

  stats_.bytes_received += packet.length();
  ++stats_.packets_received;
  if (IsDefaultPath(last_received_packet_info_.destination_address,
                    last_received_packet_info_.source_address) &&
      EnforceAntiAmplificationLimit()) {
    last_received_packet_info_.received_bytes_counted = true;
    default_path_.bytes_received_before_address_validation +=
        last_received_packet_info_.length;
  }

  // Ensure the time coming from the packet reader is within 2 minutes of now.
  if (std::abs((packet.receipt_time() - clock_->ApproximateNow()).ToSeconds()) >
      2 * 60) {
    QUIC_BUG(quic_bug_10511_21)
        << "Packet receipt time:" << packet.receipt_time().ToDebuggingValue()
        << " too far from current time:"
        << clock_->ApproximateNow().ToDebuggingValue();
  }
  QUIC_DVLOG(1) << ENDPOINT << "time of last received packet: "
                << packet.receipt_time().ToDebuggingValue() << " from peer "
                << last_received_packet_info_.source_address << ", to "
                << last_received_packet_info_.destination_address;

  ScopedPacketFlusher flusher(this);
  if (!framer_.ProcessPacket(packet)) {
    // If we are unable to decrypt this packet, it might be
    // because the CHLO or SHLO packet was lost.
    QUIC_DVLOG(1) << ENDPOINT
                  << "Unable to process packet.  Last packet processed: "
                  << last_received_packet_info_.header.packet_number;
    current_packet_data_ = nullptr;
    is_current_packet_connectivity_probing_ = false;

    MaybeProcessCoalescedPackets();
    return;
  }

  ++stats_.packets_processed;

  QUIC_DLOG_IF(INFO, active_effective_peer_migration_type_ != NO_CHANGE)
      << "sent_packet_manager_.GetLargestObserved() = "
      << sent_packet_manager_.GetLargestObserved()
      << ", highest_packet_sent_before_effective_peer_migration_ = "
      << highest_packet_sent_before_effective_peer_migration_;
  if (!validate_client_addresses_ &&
      active_effective_peer_migration_type_ != NO_CHANGE &&
      sent_packet_manager_.GetLargestObserved().IsInitialized() &&
      (!highest_packet_sent_before_effective_peer_migration_.IsInitialized() ||
       sent_packet_manager_.GetLargestObserved() >
           highest_packet_sent_before_effective_peer_migration_)) {
    if (perspective_ == Perspective::IS_SERVER) {
      OnEffectivePeerMigrationValidated(/*is_migration_linkable=*/true);
    }
  }

  if (!MaybeProcessCoalescedPackets()) {
    MaybeProcessUndecryptablePackets();
    MaybeSendInResponseToPacket();
  }
  SetPingAlarm();
  RetirePeerIssuedConnectionIdsNoLongerOnPath();
  current_packet_data_ = nullptr;
  is_current_packet_connectivity_probing_ = false;
}

void QuicConnection::OnBlockedWriterCanWrite() {
  writer_->SetWritable();
  OnCanWrite();
}

void QuicConnection::OnCanWrite() {
  if (!connected_) {
    return;
  }
  if (writer_->IsWriteBlocked()) {
    const std::string error_details =
        "Writer is blocked while calling OnCanWrite.";
    QUIC_BUG(quic_bug_10511_22) << ENDPOINT << error_details;
    CloseConnection(QUIC_INTERNAL_ERROR, error_details,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return;
  }

  ScopedPacketFlusher flusher(this);

  WriteQueuedPackets();
  const QuicTime ack_timeout =
      uber_received_packet_manager_.GetEarliestAckTimeout();
  if (ack_timeout.IsInitialized() && ack_timeout <= clock_->ApproximateNow()) {
    // Send an ACK now because either 1) we were write blocked when we last
    // tried to send an ACK, or 2) both ack alarm and send alarm were set to
    // go off together.
    if (SupportsMultiplePacketNumberSpaces()) {
      SendAllPendingAcks();
    } else {
      SendAck();
    }
  }

  // Sending queued packets may have caused the socket to become write blocked,
  // or the congestion manager to prohibit sending.
  if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
    return;
  }

  // Tell the session it can write.
  visitor_->OnCanWrite();

  // After the visitor writes, it may have caused the socket to become write
  // blocked or the congestion manager to prohibit sending, so check again.
  if (visitor_->WillingAndAbleToWrite() && !send_alarm_->IsSet() &&
      CanWrite(HAS_RETRANSMITTABLE_DATA)) {
    // We're not write blocked, but some data wasn't written. Register for
    // 'immediate' resumption so we'll keep writing after other connections.
    send_alarm_->Set(clock_->ApproximateNow());
  }
}

void QuicConnection::WriteIfNotBlocked() {
  if (framer().is_processing_packet()) {
    QUIC_BUG(connection_write_mid_packet_processing)
        << ENDPOINT << "Tried to write in mid of packet processing";
    return;
  }
  if (!HandleWriteBlocked()) {
    OnCanWrite();
  }
}

void QuicConnection::MaybeClearQueuedPacketsOnPathChange() {
  if (connection_migration_use_new_cid_ &&
      peer_issued_cid_manager_ != nullptr && HasQueuedPackets()) {
    // Discard packets serialized with the connection ID on the old code path.
    // It is possible to clear queued packets only if connection ID changes.
    // However, the case where connection ID is unchanged and queued packets are
    // non-empty is quite rare.
    ClearQueuedPackets();
  }
}

void QuicConnection::ReplaceInitialServerConnectionId(
    const QuicConnectionId& new_server_connection_id) {
  QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
  if (version().HasIetfQuicFrames()) {
    if (new_server_connection_id.IsEmpty()) {
      peer_issued_cid_manager_ = nullptr;
    } else {
      if (peer_issued_cid_manager_ != nullptr) {
        QUIC_BUG_IF(quic_bug_12714_22,
                    !peer_issued_cid_manager_->IsConnectionIdActive(
                        default_path_.server_connection_id))
            << "Connection ID replaced header is no longer active. old id: "
            << default_path_.server_connection_id
            << " new_id: " << new_server_connection_id;
        peer_issued_cid_manager_->ReplaceConnectionId(
            default_path_.server_connection_id, new_server_connection_id);
      } else {
        peer_issued_cid_manager_ =
            std::make_unique<QuicPeerIssuedConnectionIdManager>(
                kMinNumOfActiveConnectionIds, new_server_connection_id, clock_,
                alarm_factory_, this, context());
      }
    }
  }
  default_path_.server_connection_id = new_server_connection_id;
  packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
}

void QuicConnection::FindMatchingOrNewClientConnectionIdOrToken(
    const PathState& default_path, const PathState& alternative_path,
    const QuicConnectionId& server_connection_id,
    QuicConnectionId* client_connection_id,
    absl::optional<StatelessResetToken>* stateless_reset_token) {
  QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
  if (peer_issued_cid_manager_ == nullptr ||
      server_connection_id == default_path.server_connection_id) {
    *client_connection_id = default_path.client_connection_id;
    *stateless_reset_token = default_path.stateless_reset_token;
    return;
  }
  if (server_connection_id == alternative_path_.server_connection_id) {
    *client_connection_id = alternative_path.client_connection_id;
    *stateless_reset_token = alternative_path.stateless_reset_token;
    return;
  }
  if (!connection_migration_use_new_cid_) {
    QUIC_BUG(quic_bug_46004) << "Cannot find matching connection ID.";
    return;
  }
  auto* connection_id_data =
      peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
  if (connection_id_data == nullptr) {
    return;
  }
  *client_connection_id = connection_id_data->connection_id;
  *stateless_reset_token = connection_id_data->stateless_reset_token;
}

bool QuicConnection::FindOnPathConnectionIds(
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address,
    QuicConnectionId* client_connection_id,
    QuicConnectionId* server_connection_id) const {
  if (IsDefaultPath(self_address, peer_address)) {
    *client_connection_id = default_path_.client_connection_id,
    *server_connection_id = default_path_.server_connection_id;
    return true;
  }
  if (IsAlternativePath(self_address, peer_address)) {
    *client_connection_id = alternative_path_.client_connection_id,
    *server_connection_id = alternative_path_.server_connection_id;
    return true;
  }
  // Client should only send packets on either default or alternative path, so
  // it shouldn't fail here. If the server fail to find CID to use, no packet
  // will be generated on this path.
  // TODO(danzh) fix SendPathResponse() to respond to probes from a different
  // client port with non-Zero client CID.
  QUIC_BUG_IF(failed to find on path connection ids,
              perspective_ == Perspective::IS_CLIENT)
      << "Fails to find on path connection IDs";
  return false;
}

void QuicConnection::SetDefaultPathState(PathState new_path_state) {
  default_path_ = std::move(new_path_state);
  if (connection_migration_use_new_cid_) {
    packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
    packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
  }
}

bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
  if (perspective_ == Perspective::IS_CLIENT && version().HasIetfQuicFrames() &&
      direct_peer_address_.IsInitialized() &&
      last_received_packet_info_.source_address.IsInitialized() &&
      direct_peer_address_ != last_received_packet_info_.source_address &&
      !IsKnownServerAddress(last_received_packet_info_.source_address)) {
    // Discard packets received from unseen server addresses.
    return false;
  }

  if (perspective_ == Perspective::IS_SERVER &&
      default_path_.self_address.IsInitialized() &&
      last_received_packet_info_.destination_address.IsInitialized() &&
      default_path_.self_address !=
          last_received_packet_info_.destination_address) {
    // Allow change between pure IPv4 and equivalent mapped IPv4 address.
    if (default_path_.self_address.port() !=
            last_received_packet_info_.destination_address.port() ||
        default_path_.self_address.host().Normalized() !=
            last_received_packet_info_.destination_address.host()
                .Normalized()) {
      if (!visitor_->AllowSelfAddressChange()) {
        const std::string error_details = absl::StrCat(
            "Self address migration is not supported at the server, current "
            "address: ",
            default_path_.self_address.ToString(),
            ", server preferred address: ",
            sent_server_preferred_address_.ToString(),
            ", received packet address: ",
            last_received_packet_info_.destination_address.ToString(),
            ", size: ", last_received_packet_info_.length,
            ", packet number: ", header.packet_number.ToString(),
            ", encryption level: ",
            EncryptionLevelToString(
                last_received_packet_info_.decrypted_level));
        QUIC_LOG_EVERY_N_SEC(INFO, 100) << error_details;
        QUIC_CODE_COUNT(quic_dropped_packets_with_changed_server_address);
        return false;
      }
    }
    default_path_.self_address = last_received_packet_info_.destination_address;
  }

  if (perspective_ == Perspective::IS_SERVER &&
      last_received_packet_info_.actual_destination_address.IsInitialized() &&
      !IsHandshakeConfirmed() &&
      GetEffectivePeerAddressFromCurrentPacket() !=
          default_path_.peer_address) {
    // Our client implementation has an optimization to spray packets from
    // different sockets to the server's preferred address before handshake
    // gets confirmed. In this case, do not kick off client address migration
    // detection.
    QUICHE_DCHECK(sent_server_preferred_address_.IsInitialized());
    last_received_packet_info_.source_address = direct_peer_address_;
  }

  if (PacketCanReplaceServerConnectionId(header, perspective_) &&
      default_path_.server_connection_id != header.source_connection_id) {
    QUICHE_DCHECK_EQ(header.long_packet_type, INITIAL);
    if (server_connection_id_replaced_by_initial_) {
      QUIC_DLOG(ERROR) << ENDPOINT << "Refusing to replace connection ID "
                       << default_path_.server_connection_id << " with "
                       << header.source_connection_id;
      return false;
    }
    server_connection_id_replaced_by_initial_ = true;
    QUIC_DLOG(INFO) << ENDPOINT << "Replacing connection ID "
                    << default_path_.server_connection_id << " with "
                    << header.source_connection_id;
    if (!original_destination_connection_id_.has_value()) {
      original_destination_connection_id_ = default_path_.server_connection_id;
    }
    ReplaceInitialServerConnectionId(header.source_connection_id);
  }

  if (!ValidateReceivedPacketNumber(header.packet_number)) {
    return false;
  }

  if (!version_negotiated_) {
    if (perspective_ == Perspective::IS_CLIENT) {
      QUICHE_DCHECK(!header.version_flag || header.form != GOOGLE_QUIC_PACKET);
      if (!version().HasIetfInvariantHeader()) {
        // If the client gets a packet without the version flag from the server
        // it should stop sending version since the version negotiation is done.
        // IETF QUIC stops sending version once encryption level switches to
        // forward secure.
        packet_creator_.StopSendingVersion();
      }
      version_negotiated_ = true;
      OnSuccessfulVersionNegotiation();
    }
  }

  if (last_received_packet_info_.length > largest_received_packet_size_) {
    largest_received_packet_size_ = last_received_packet_info_.length;
  }

  if (perspective_ == Perspective::IS_SERVER &&
      encryption_level_ == ENCRYPTION_INITIAL &&
      last_received_packet_info_.length > packet_creator_.max_packet_length()) {
    if (GetQuicFlag(quic_use_lower_server_response_mtu_for_test)) {
      SetMaxPacketLength(
          std::min(last_received_packet_info_.length, QuicByteCount(1250)));
    } else {
      SetMaxPacketLength(last_received_packet_info_.length);
    }
  }
  return true;
}

bool QuicConnection::ValidateReceivedPacketNumber(
    QuicPacketNumber packet_number) {
  // If this packet has already been seen, or the sender has told us that it
  // will not be retransmitted, then stop processing the packet.
  if (!uber_received_packet_manager_.IsAwaitingPacket(
          last_received_packet_info_.decrypted_level, packet_number)) {
    QUIC_DLOG(INFO) << ENDPOINT << "Packet " << packet_number
                    << " no longer being waited for at level "
                    << static_cast<int>(
                           last_received_packet_info_.decrypted_level)
                    << ".  Discarding.";
    if (debug_visitor_ != nullptr) {
      debug_visitor_->OnDuplicatePacket(packet_number);
    }
    return false;
  }

  return true;
}

void QuicConnection::WriteQueuedPackets() {
  QUICHE_DCHECK(!writer_->IsWriteBlocked());

  QUIC_CLIENT_HISTOGRAM_COUNTS("QuicSession.NumQueuedPacketsBeforeWrite",
                               buffered_packets_.size(), 1, 1000, 50, "");

  while (!buffered_packets_.empty()) {
    if (HandleWriteBlocked()) {
      break;
    }
    const BufferedPacket& packet = buffered_packets_.front();
    WriteResult result = writer_->WritePacket(
        packet.data.get(), packet.length, packet.self_address.host(),
        packet.peer_address, per_packet_options_);
    QUIC_DVLOG(1) << ENDPOINT << "Sending buffered packet, result: " << result;
    if (IsMsgTooBig(writer_, result) && packet.length > long_term_mtu_) {
      // When MSG_TOO_BIG is returned, the system typically knows what the
      // actual MTU is, so there is no need to probe further.
      // TODO(wub): Reduce max packet size to a safe default, or the actual MTU.
      mtu_discoverer_.Disable();
      mtu_discovery_alarm_->Cancel();
      buffered_packets_.pop_front();
      continue;
    }
    if (IsWriteError(result.status)) {
      OnWriteError(result.error_code);
      break;
    }
    if (result.status == WRITE_STATUS_OK ||
        result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
      buffered_packets_.pop_front();
    }
    if (IsWriteBlockedStatus(result.status)) {
      visitor_->OnWriteBlocked();
      break;
    }
  }
}

void QuicConnection::MarkZeroRttPacketsForRetransmission(int reject_reason) {
  sent_packet_manager_.MarkZeroRttPacketsForRetransmission();
  if (debug_visitor_ != nullptr && version().UsesTls()) {
    debug_visitor_->OnZeroRttRejected(reject_reason);
  }
}

void QuicConnection::NeuterUnencryptedPackets() {
  sent_packet_manager_.NeuterUnencryptedPackets();
  // This may have changed the retransmission timer, so re-arm it.
  SetRetransmissionAlarm();
  if (default_enable_5rto_blackhole_detection_) {
    QUIC_RELOADABLE_FLAG_COUNT_N(quic_default_enable_5rto_blackhole_detection2,
                                 1, 3);
    // Consider this as forward progress since this is called when initial key
    // gets discarded (or previous unencrypted data is not needed anymore).
    OnForwardProgressMade();
  }
  if (SupportsMultiplePacketNumberSpaces()) {
    // Stop sending ack of initial packet number space.
    uber_received_packet_manager_.ResetAckStates(ENCRYPTION_INITIAL);
    // Re-arm ack alarm.
    ack_alarm_->Update(uber_received_packet_manager_.GetEarliestAckTimeout(),
                       kAlarmGranularity);
  }
}

bool QuicConnection::ShouldGeneratePacket(
    HasRetransmittableData retransmittable, IsHandshake handshake) {
  QUICHE_DCHECK(handshake != IS_HANDSHAKE ||
                QuicVersionUsesCryptoFrames(transport_version()))
      << ENDPOINT
      << "Handshake in STREAM frames should not check ShouldGeneratePacket";
  if (peer_issued_cid_manager_ != nullptr &&
      packet_creator_.GetDestinationConnectionId().IsEmpty()) {
    QUICHE_DCHECK(version().HasIetfQuicFrames());
    QUIC_CODE_COUNT(quic_generate_packet_blocked_by_no_connection_id);
    QUIC_BUG_IF(quic_bug_90265_1, perspective_ == Perspective::IS_CLIENT);
    QUIC_DLOG(INFO) << ENDPOINT
                    << "There is no destination connection ID available to "
                       "generate packet.";
    return false;
  }
  if (IsDefaultPath(default_path_.self_address,
                    packet_creator_.peer_address())) {
    return CanWrite(retransmittable);
  }
  // This is checking on the alternative path with a different peer address. The
  // self address and the writer used are the same as the default path. In the
  // case of different self address and writer, writing packet would use a
  // differnt code path without checking the states of the default writer.
  return connected_ && !HandleWriteBlocked();
}

const QuicFrames QuicConnection::MaybeBundleAckOpportunistically() {
  if (!ack_frequency_sent_ && sent_packet_manager_.CanSendAckFrequency()) {
    if (packet_creator_.NextSendingPacketNumber() >=
        FirstSendingPacketNumber() + kMinReceivedBeforeAckDecimation) {
      QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 3, 3);
      ack_frequency_sent_ = true;
      auto frame = sent_packet_manager_.GetUpdatedAckFrequencyFrame();
      visitor_->SendAckFrequency(frame);
    }
  }

  QuicFrames frames;
  const bool has_pending_ack =
      uber_received_packet_manager_
          .GetAckTimeout(QuicUtils::GetPacketNumberSpace(encryption_level_))
          .IsInitialized();
  if (!has_pending_ack && stop_waiting_count_ <= 1) {
    // No need to send an ACK.
    return frames;
  }
  ResetAckStates();

  QUIC_DVLOG(1) << ENDPOINT << "Bundle an ACK opportunistically";
  QuicFrame updated_ack_frame = GetUpdatedAckFrame();
  QUIC_BUG_IF(quic_bug_12714_23, updated_ack_frame.ack_frame->packets.Empty())
      << ENDPOINT << "Attempted to opportunistically bundle an empty "
      << encryption_level_ << " ACK, " << (has_pending_ack ? "" : "!")
      << "has_pending_ack, stop_waiting_count_ " << stop_waiting_count_;
  frames.push_back(updated_ack_frame);

  if (!no_stop_waiting_frames_) {
    QuicStopWaitingFrame stop_waiting;
    PopulateStopWaitingFrame(&stop_waiting);
    frames.push_back(QuicFrame(stop_waiting));
  }
  return frames;
}

bool QuicConnection::CanWrite(HasRetransmittableData retransmittable) {
  if (!connected_) {
    return false;
  }

  if (version().CanSendCoalescedPackets() &&
      framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL) &&
      framer_.is_processing_packet()) {
    // While we still have initial keys, suppress sending in mid of packet
    // processing.
    // TODO(fayang): always suppress sending while in the mid of packet
    // processing.
    QUIC_DVLOG(1) << ENDPOINT
                  << "Suppress sending in the mid of packet processing";
    return false;
  }

  if (fill_coalesced_packet_) {
    // Try to coalesce packet, only allow to write when creator is on soft max
    // packet length. Given the next created packet is going to fill current
    // coalesced packet, do not check amplification factor.
    return packet_creator_.HasSoftMaxPacketLength();
  }

  if (sent_packet_manager_.pending_timer_transmission_count() > 0) {
    // Allow sending if there are pending tokens, which occurs when:
    // 1) firing PTO,
    // 2) bundling CRYPTO data with ACKs,
    // 3) coalescing CRYPTO data of higher space.
    return true;
  }

  if (LimitedByAmplificationFactor(packet_creator_.max_packet_length())) {
    // Server is constrained by the amplification restriction.
    QUIC_CODE_COUNT(quic_throttled_by_amplification_limit);
    QUIC_DVLOG(1) << ENDPOINT
                  << "Constrained by amplification restriction to peer address "
                  << default_path_.peer_address << " bytes received "
                  << default_path_.bytes_received_before_address_validation
                  << ", bytes sent"
                  << default_path_.bytes_sent_before_address_validation;
    ++stats_.num_amplification_throttling;
    return false;
  }

  if (HandleWriteBlocked()) {
    return false;
  }

  // Allow acks and probing frames to be sent immediately.
  if (retransmittable == NO_RETRANSMITTABLE_DATA) {
    return true;
  }
  // If the send alarm is set, wait for it to fire.
  if (send_alarm_->IsSet()) {
    return false;
  }

  QuicTime now = clock_->Now();
  QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend(now);
  if (delay.IsInfinite()) {
    send_alarm_->Cancel();
    return false;
  }

  // Scheduler requires a delay.
  if (!delay.IsZero()) {
    if (delay <= release_time_into_future_) {
      // Required delay is within pace time into future, send now.
      return true;
    }
    // Cannot send packet now because delay is too far in the future.
    send_alarm_->Update(now + delay, kAlarmGranularity);
    QUIC_DVLOG(1) << ENDPOINT << "Delaying sending " << delay.ToMilliseconds()
                  << "ms";
    return false;
  }
  return true;
}

QuicTime QuicConnection::CalculatePacketSentTime() {
  const QuicTime now = clock_->Now();
  if (!supports_release_time_ || per_packet_options_ == nullptr) {
    // Don't change the release delay.
    return now;
  }

  auto next_release_time_result = sent_packet_manager_.GetNextReleaseTime();

  // Release before |now| is impossible.
  QuicTime next_release_time =
      std::max(now, next_release_time_result.release_time);
  per_packet_options_->release_time_delay = next_release_time - now;
  per_packet_options_->allow_burst = next_release_time_result.allow_burst;
  return next_release_time;
}

bool QuicConnection::WritePacket(SerializedPacket* packet) {
  if (sent_packet_manager_.GetLargestSentPacket().IsInitialized() &&
      packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) {
    QUIC_BUG(quic_bug_10511_23)
        << "Attempt to write packet:" << packet->packet_number
        << " after:" << sent_packet_manager_.GetLargestSentPacket();
    CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return true;
  }
  const bool is_mtu_discovery = QuicUtils::ContainsFrameType(
      packet->nonretransmittable_frames, MTU_DISCOVERY_FRAME);
  const SerializedPacketFate fate = packet->fate;
  // Termination packets are encrypted and saved, so don't exit early.
  QuicErrorCode error_code = QUIC_NO_ERROR;
  const bool is_termination_packet = IsTerminationPacket(*packet, &error_code);
  QuicPacketNumber packet_number = packet->packet_number;
  QuicPacketLength encrypted_length = packet->encrypted_length;
  // Termination packets are eventually owned by TimeWaitListManager.
  // Others are deleted at the end of this call.
  if (is_termination_packet) {
    if (termination_packets_ == nullptr) {
      termination_packets_.reset(
          new std::vector<std::unique_ptr<QuicEncryptedPacket>>);
    }
    // Copy the buffer so it's owned in the future.
    char* buffer_copy = CopyBuffer(*packet);
    termination_packets_->emplace_back(
        new QuicEncryptedPacket(buffer_copy, encrypted_length, true));
    if (error_code == QUIC_SILENT_IDLE_TIMEOUT) {
      QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective_);
      // TODO(fayang): populate histogram indicating the time elapsed from this
      // connection gets closed to following client packets get received.
      QUIC_DVLOG(1) << ENDPOINT
                    << "Added silent connection close to termination packets, "
                       "num of termination packets: "
                    << termination_packets_->size();
      return true;
    }
  }

  QUICHE_DCHECK_LE(encrypted_length, kMaxOutgoingPacketSize);
  QUICHE_DCHECK(is_mtu_discovery ||
                encrypted_length <= packet_creator_.max_packet_length())
      << " encrypted_length=" << encrypted_length
      << " > packet_creator max_packet_length="
      << packet_creator_.max_packet_length();
  QUIC_DVLOG(1) << ENDPOINT << "Sending packet " << packet_number << " : "
                << (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
                        ? "data bearing "
                        : " ack or probing only ")
                << ", encryption level: " << packet->encryption_level
                << ", encrypted length:" << encrypted_length
                << ", fate: " << fate << " to peer " << packet->peer_address;
  QUIC_DVLOG(2) << ENDPOINT << packet->encryption_level << " packet number "
                << packet_number << " of length " << encrypted_length << ": "
                << std::endl
                << quiche::QuicheTextUtils::HexDump(absl::string_view(
                       packet->encrypted_buffer, encrypted_length));

  // Measure the RTT from before the write begins to avoid underestimating the
  // min_rtt_, especially in cases where the thread blocks or gets swapped out
  // during the WritePacket below.
  QuicTime packet_send_time = CalculatePacketSentTime();
  WriteResult result(WRITE_STATUS_OK, encrypted_length);
  QuicSocketAddress send_to_address = packet->peer_address;
  // Self address is always the default self address on this code path.
  const bool send_on_current_path = send_to_address == peer_address();
  if (!send_on_current_path) {
    QUIC_BUG_IF(quic_send_non_probing_frames_on_alternative_path,
                ContainsNonProbingFrame(*packet))
        << "Packet " << packet->packet_number
        << " with non-probing frames was sent on alternative path: "
           "nonretransmittable_frames: "
        << QuicFramesToString(packet->nonretransmittable_frames)
        << " retransmittable_frames: "
        << QuicFramesToString(packet->retransmittable_frames);
  }
  switch (fate) {
    case DISCARD:
      ++stats_.packets_discarded;
      if (debug_visitor_ != nullptr) {
        debug_visitor_->OnPacketDiscarded(*packet);
      }
      return true;
    case COALESCE:
      QUIC_BUG_IF(quic_bug_12714_24,
                  !version().CanSendCoalescedPackets() || coalescing_done_);
      if (!coalesced_packet_.MaybeCoalescePacket(
              *packet, self_address(), send_to_address,
              helper_->GetStreamSendBufferAllocator(),
              packet_creator_.max_packet_length())) {
        // Failed to coalesce packet, flush current coalesced packet.
        if (!FlushCoalescedPacket()) {
          QUIC_BUG_IF(quic_connection_connected_after_flush_coalesced_failure,
                      connected_)
              << "QUIC connection is still connected after failing to flush "
                 "coalesced packet.";
          // Failed to flush coalesced packet, write error has been handled.
          return false;
        }
        if (!coalesced_packet_.MaybeCoalescePacket(
                *packet, self_address(), send_to_address,
                helper_->GetStreamSendBufferAllocator(),
                packet_creator_.max_packet_length())) {
          // Failed to coalesce packet even it is the only packet, raise a write
          // error.
          QUIC_DLOG(ERROR) << ENDPOINT << "Failed to coalesce packet";
          result.error_code = WRITE_STATUS_FAILED_TO_COALESCE_PACKET;
          break;
        }
      }
      if (coalesced_packet_.length() < coalesced_packet_.max_packet_length()) {
        QUIC_DVLOG(1) << ENDPOINT << "Trying to set soft max packet length to "
                      << coalesced_packet_.max_packet_length() -
                             coalesced_packet_.length();
        packet_creator_.SetSoftMaxPacketLength(
            coalesced_packet_.max_packet_length() - coalesced_packet_.length());
      }
      break;
    case BUFFER:
      QUIC_DVLOG(1) << ENDPOINT << "Adding packet: " << packet->packet_number
                    << " to buffered packets";
      buffered_packets_.emplace_back(*packet, self_address(), send_to_address);
      break;
    case SEND_TO_WRITER:
      // Stop using coalescer from now on.
      coalescing_done_ = true;
      // At this point, packet->release_encrypted_buffer is either nullptr,
      // meaning |packet->encrypted_buffer| is a stack buffer, or not-nullptr,
      /// meaning it's a writer-allocated buffer. Note that connectivity probing
      // packets do not use this function, so setting release_encrypted_buffer
      // to nullptr will not cause probing packets to be leaked.
      //
      // writer_->WritePacket transfers buffer ownership back to the writer.
      packet->release_encrypted_buffer = nullptr;
      result = writer_->WritePacket(packet->encrypted_buffer, encrypted_length,
                                    self_address().host(), send_to_address,
                                    per_packet_options_);
      // This is a work around for an issue with linux UDP GSO batch writers.
      // When sending a GSO packet with 2 segments, if the first segment is
      // larger than the path MTU, instead of EMSGSIZE, the linux kernel returns
      // EINVAL, which translates to WRITE_STATUS_ERROR and causes conneciton to
      // be closed. By manually flush the writer here, the MTU probe is sent in
      // a normal(non-GSO) packet, so the kernel can return EMSGSIZE and we will
      // not close the connection.
      if (is_mtu_discovery && writer_->IsBatchMode()) {
        result = writer_->Flush();
      }
      break;
    default:
      QUICHE_DCHECK(false);
      break;
  }

  QUIC_HISTOGRAM_ENUM(
      "QuicConnection.WritePacketStatus", result.status,
      WRITE_STATUS_NUM_VALUES,
      "Status code returned by writer_->WritePacket() in QuicConnection.");

  if (IsWriteBlockedStatus(result.status)) {
    // Ensure the writer is still write blocked, otherwise QUIC may continue
    // trying to write when it will not be able to.
    QUICHE_DCHECK(writer_->IsWriteBlocked());
    visitor_->OnWriteBlocked();
    // If the socket buffers the data, then the packet should not
    // be queued and sent again, which would result in an unnecessary
    // duplicate packet being sent.  The helper must call OnCanWrite
    // when the write completes, and OnWriteError if an error occurs.
    if (result.status != WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
      QUIC_DVLOG(1) << ENDPOINT << "Adding packet: " << packet->packet_number
                    << " to buffered packets";
      buffered_packets_.emplace_back(*packet, self_address(), send_to_address);
    }
  }

  // In some cases, an MTU probe can cause EMSGSIZE. This indicates that the
  // MTU discovery is permanently unsuccessful.
  if (IsMsgTooBig(writer_, result)) {
    if (is_mtu_discovery) {
      // When MSG_TOO_BIG is returned, the system typically knows what the
      // actual MTU is, so there is no need to probe further.
      // TODO(wub): Reduce max packet size to a safe default, or the actual MTU.
      QUIC_DVLOG(1) << ENDPOINT
                    << " MTU probe packet too big, size:" << encrypted_length
                    << ", long_term_mtu_:" << long_term_mtu_;
      mtu_discoverer_.Disable();
      mtu_discovery_alarm_->Cancel();
      // The write failed, but the writer is not blocked, so return true.
      return true;
    }
    if (!send_on_current_path) {
      // Only handle MSG_TOO_BIG as error on current path.
      return true;
    }
  }

  if (IsWriteError(result.status)) {
    QUIC_LOG_FIRST_N(ERROR, 10)
        << ENDPOINT << "Failed writing packet " << packet_number << " of "
        << encrypted_length << " bytes from " << self_address().host() << " to "
        << send_to_address << ", with error code " << result.error_code
        << ". long_term_mtu_:" << long_term_mtu_
        << ", previous_validated_mtu_:" << previous_validated_mtu_
        << ", max_packet_length():" << max_packet_length()
        << ", is_mtu_discovery:" << is_mtu_discovery;
    if (MaybeRevertToPreviousMtu()) {
      return true;
    }

    OnWriteError(result.error_code);
    return false;
  }

  if (result.status == WRITE_STATUS_OK) {
    // packet_send_time is the ideal send time, if allow_burst is true, writer
    // may have sent it earlier than that.
    packet_send_time = packet_send_time + result.send_time_offset;
  }

  if (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA &&
      !is_termination_packet) {
    // Start blackhole/path degrading detections if the sent packet is not
    // termination packet and contains retransmittable data.
    // Do not restart detection if detection is in progress indicating no
    // forward progress has been made since last event (i.e., packet was sent
    // or new packets were acknowledged).
    if (!blackhole_detector_.IsDetectionInProgress()) {
      // Try to start detections if no detection in progress. This could
      // because either both detections are inactive when sending last packet
      // or this connection just gets out of quiescence.
      blackhole_detector_.RestartDetection(GetPathDegradingDeadline(),
                                           GetNetworkBlackholeDeadline(),
                                           GetPathMtuReductionDeadline());
    }
    idle_network_detector_.OnPacketSent(packet_send_time,
                                        sent_packet_manager_.GetPtoDelay());
  }

  MaybeSetMtuAlarm(packet_number);
  QUIC_DVLOG(1) << ENDPOINT << "time we began writing last sent packet: "
                << packet_send_time.ToDebuggingValue();

  if (IsDefaultPath(default_path_.self_address, send_to_address)) {
    if (EnforceAntiAmplificationLimit()) {
      // Include bytes sent even if they are not in flight.
      default_path_.bytes_sent_before_address_validation += encrypted_length;
    }
  } else {
    MaybeUpdateBytesSentToAlternativeAddress(send_to_address, encrypted_length);
  }

  // Do not measure rtt of this packet if it's not sent on current path.
  QUIC_DLOG_IF(INFO, !send_on_current_path)
      << ENDPOINT << " Sent packet " << packet->packet_number
      << " on a different path with remote address " << send_to_address
      << " while current path has peer address " << peer_address();
  const bool in_flight = sent_packet_manager_.OnPacketSent(
      packet, packet_send_time, packet->transmission_type,
      IsRetransmittable(*packet), /*measure_rtt=*/send_on_current_path);
  QUIC_BUG_IF(quic_bug_12714_25,
              perspective_ == Perspective::IS_SERVER &&
                  default_enable_5rto_blackhole_detection_ &&
                  blackhole_detector_.IsDetectionInProgress() &&
                  !sent_packet_manager_.HasInFlightPackets())
      << ENDPOINT
      << "Trying to start blackhole detection without no bytes in flight";

  if (debug_visitor_ != nullptr) {
    if (sent_packet_manager_.unacked_packets().empty()) {
      QUIC_BUG(quic_bug_10511_25)
          << "Unacked map is empty right after packet is sent";
    } else {
      debug_visitor_->OnPacketSent(
          packet->packet_number, packet->encrypted_length,
          packet->has_crypto_handshake, packet->transmission_type,
          packet->encryption_level,
          sent_packet_manager_.unacked_packets()
              .rbegin()
              ->retransmittable_frames,
          packet->nonretransmittable_frames, packet_send_time);
    }
  }
  if (packet->encryption_level == ENCRYPTION_HANDSHAKE) {
    handshake_packet_sent_ = true;
  }

  if (packet->encryption_level == ENCRYPTION_FORWARD_SECURE) {
    if (!lowest_packet_sent_in_current_key_phase_.IsInitialized()) {
      QUIC_DLOG(INFO) << ENDPOINT
                      << "lowest_packet_sent_in_current_key_phase_ = "
                      << packet_number;
      lowest_packet_sent_in_current_key_phase_ = packet_number;
    }
    if (!is_termination_packet &&
        MaybeHandleAeadConfidentialityLimits(*packet)) {
      return true;
    }
  }
  if (in_flight || !retransmission_alarm_->IsSet()) {
    SetRetransmissionAlarm();
  }
  SetPingAlarm();
  RetirePeerIssuedConnectionIdsNoLongerOnPath();

  // The packet number length must be updated after OnPacketSent, because it
  // may change the packet number length in packet.
  packet_creator_.UpdatePacketNumberLength(
      sent_packet_manager_.GetLeastPacketAwaitedByPeer(encryption_level_),
      sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));

  stats_.bytes_sent += encrypted_length;
  ++stats_.packets_sent;
  if (packet->has_ack_ecn) {
    stats_.num_ack_frames_sent_with_ecn++;
  }

  QuicByteCount bytes_not_retransmitted =
      packet->bytes_not_retransmitted.value_or(0);
  if (packet->transmission_type != NOT_RETRANSMISSION) {
    if (static_cast<uint64_t>(encrypted_length) < bytes_not_retransmitted) {
      QUIC_BUG(quic_packet_bytes_written_lt_bytes_not_retransmitted)
          << "Total bytes written to the packet should be larger than the "
             "bytes in not-retransmitted frames. Bytes written: "
          << encrypted_length
          << ", bytes not retransmitted: " << bytes_not_retransmitted;
    } else {
      // bytes_retransmitted includes packet's headers and encryption
      // overhead.
      stats_.bytes_retransmitted +=
          (encrypted_length - bytes_not_retransmitted);
    }
    ++stats_.packets_retransmitted;
  }

  return true;
}

bool QuicConnection::MaybeHandleAeadConfidentialityLimits(
    const SerializedPacket& packet) {
  if (!version().UsesTls()) {
    return false;
  }

  if (packet.encryption_level != ENCRYPTION_FORWARD_SECURE) {
    QUIC_BUG(quic_bug_12714_26)
        << "MaybeHandleAeadConfidentialityLimits called on non 1-RTT packet";
    return false;
  }
  if (!lowest_packet_sent_in_current_key_phase_.IsInitialized()) {
    QUIC_BUG(quic_bug_10511_26)
        << "lowest_packet_sent_in_current_key_phase_ must be initialized "
           "before calling MaybeHandleAeadConfidentialityLimits";
    return false;
  }

  // Calculate the number of packets encrypted from the packet number, which is
  // simpler than keeping another counter. The packet number space may be
  // sparse, so this might overcount, but doing a key update earlier than
  // necessary would only improve security and has negligible cost.
  if (packet.packet_number < lowest_packet_sent_in_current_key_phase_) {
    const std::string error_details =
        absl::StrCat("packet_number(", packet.packet_number.ToString(),
                     ") < lowest_packet_sent_in_current_key_phase_ (",
                     lowest_packet_sent_in_current_key_phase_.ToString(), ")");
    QUIC_BUG(quic_bug_10511_27) << error_details;
    CloseConnection(QUIC_INTERNAL_ERROR, error_details,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return true;
  }
  const QuicPacketCount num_packets_encrypted_in_current_key_phase =
      packet.packet_number - lowest_packet_sent_in_current_key_phase_ + 1;

  const QuicPacketCount confidentiality_limit =
      framer_.GetOneRttEncrypterConfidentialityLimit();

  // Attempt to initiate a key update before reaching the AEAD
  // confidentiality limit when the number of packets sent in the current
  // key phase gets within |kKeyUpdateConfidentialityLimitOffset| packets of
  // the limit, unless overridden by
  // FLAGS_quic_key_update_confidentiality_limit.
  constexpr QuicPacketCount kKeyUpdateConfidentialityLimitOffset = 1000;
  QuicPacketCount key_update_limit = 0;
  if (confidentiality_limit > kKeyUpdateConfidentialityLimitOffset) {
    key_update_limit =
        confidentiality_limit - kKeyUpdateConfidentialityLimitOffset;
  }
  const QuicPacketCount key_update_limit_override =
      GetQuicFlag(quic_key_update_confidentiality_limit);
  if (key_update_limit_override) {
    key_update_limit = key_update_limit_override;
  }

  QUIC_DVLOG(2) << ENDPOINT << "Checking AEAD confidentiality limits: "
                << "num_packets_encrypted_in_current_key_phase="
                << num_packets_encrypted_in_current_key_phase
                << " key_update_limit=" << key_update_limit
                << " confidentiality_limit=" << confidentiality_limit
                << " IsKeyUpdateAllowed()=" << IsKeyUpdateAllowed();

  if (num_packets_encrypted_in_current_key_phase >= confidentiality_limit) {
    // Reached the confidentiality limit without initiating a key update,
    // must close the connection.
    const std::string error_details = absl::StrCat(
        "encrypter confidentiality limit reached: "
        "num_packets_encrypted_in_current_key_phase=",
        num_packets_encrypted_in_current_key_phase,
        " key_update_limit=", key_update_limit,
        " confidentiality_limit=", confidentiality_limit,
        " IsKeyUpdateAllowed()=", IsKeyUpdateAllowed());
    CloseConnection(QUIC_AEAD_LIMIT_REACHED, error_details,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return true;
  }

  if (IsKeyUpdateAllowed() &&
      num_packets_encrypted_in_current_key_phase >= key_update_limit) {
    // Approaching the confidentiality limit, initiate key update so that
    // the next set of keys will be ready for the next packet before the
    // limit is reached.
    KeyUpdateReason reason = KeyUpdateReason::kLocalAeadConfidentialityLimit;
    if (key_update_limit_override) {
      QUIC_DLOG(INFO) << ENDPOINT
                      << "reached FLAGS_quic_key_update_confidentiality_limit, "
                         "initiating key update: "
                      << "num_packets_encrypted_in_current_key_phase="
                      << num_packets_encrypted_in_current_key_phase
                      << " key_update_limit=" << key_update_limit
                      << " confidentiality_limit=" << confidentiality_limit;
      reason = KeyUpdateReason::kLocalKeyUpdateLimitOverride;
    } else {
      QUIC_DLOG(INFO) << ENDPOINT
                      << "approaching AEAD confidentiality limit, "
                         "initiating key update: "
                      << "num_packets_encrypted_in_current_key_phase="
                      << num_packets_encrypted_in_current_key_phase
                      << " key_update_limit=" << key_update_limit
                      << " confidentiality_limit=" << confidentiality_limit;
    }
    InitiateKeyUpdate(reason);
  }

  return false;
}

void QuicConnection::FlushPackets() {
  if (!connected_) {
    return;
  }

  if (!writer_->IsBatchMode()) {
    return;
  }

  if (HandleWriteBlocked()) {
    QUIC_DLOG(INFO) << ENDPOINT << "FlushPackets called while blocked.";
    return;
  }

  WriteResult result = writer_->Flush();

  QUIC_HISTOGRAM_ENUM("QuicConnection.FlushPacketStatus", result.status,
                      WRITE_STATUS_NUM_VALUES,
                      "Status code returned by writer_->Flush() in "
                      "QuicConnection::FlushPackets.");

  if (HandleWriteBlocked()) {
    QUICHE_DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status)
        << "Unexpected flush result:" << result;
    QUIC_DLOG(INFO) << ENDPOINT << "Write blocked in FlushPackets.";
    return;
  }

  if (IsWriteError(result.status) && !MaybeRevertToPreviousMtu()) {
    OnWriteError(result.error_code);
  }
}

bool QuicConnection::IsMsgTooBig(const QuicPacketWriter* writer,
                                 const WriteResult& result) {
  absl::optional<int> writer_error_code = writer->MessageTooBigErrorCode();
  return (result.status == WRITE_STATUS_MSG_TOO_BIG) ||
         (writer_error_code.has_value() && IsWriteError(result.status) &&
          result.error_code == *writer_error_code);
}

bool QuicConnection::ShouldDiscardPacket(EncryptionLevel encryption_level) {
  if (!connected_) {
    QUIC_DLOG(INFO) << ENDPOINT
                    << "Not sending packet as connection is disconnected.";
    return true;
  }

  if (encryption_level_ == ENCRYPTION_FORWARD_SECURE &&
      encryption_level == ENCRYPTION_INITIAL) {
    // Drop packets that are NULL encrypted since the peer won't accept them
    // anymore.
    QUIC_DLOG(INFO) << ENDPOINT
                    << "Dropping NULL encrypted packet since the connection is "
                       "forward secure.";
    return true;
  }

  return false;
}

QuicTime QuicConnection::GetPathMtuReductionDeadline() const {
  if (previous_validated_mtu_ == 0) {
    return QuicTime::Zero();
  }
  QuicTime::Delta delay = sent_packet_manager_.GetMtuReductionDelay(
      num_rtos_for_blackhole_detection_);
  if (delay.IsZero()) {
    return QuicTime::Zero();
  }
  return clock_->ApproximateNow() + delay;
}

bool QuicConnection::MaybeRevertToPreviousMtu() {
  if (previous_validated_mtu_ == 0) {
    return false;
  }

  SetMaxPacketLength(previous_validated_mtu_);
  mtu_discoverer_.Disable();
  mtu_discovery_alarm_->Cancel();
  previous_validated_mtu_ = 0;
  return true;
}

void QuicConnection::OnWriteError(int error_code) {
  if (write_error_occurred_) {
    // A write error already occurred. The connection is being closed.
    return;
  }
  write_error_occurred_ = true;

  const std::string error_details = absl::StrCat(
      "Write failed with error: ", error_code, " (", strerror(error_code), ")");
  QUIC_LOG_FIRST_N(ERROR, 2) << ENDPOINT << error_details;
  absl::optional<int> writer_error_code = writer_->MessageTooBigErrorCode();
  if (writer_error_code.has_value() && error_code == *writer_error_code) {
    CloseConnection(QUIC_PACKET_WRITE_ERROR, error_details,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return;
  }
  // We can't send an error as the socket is presumably borked.
  if (version().HasIetfInvariantHeader()) {
    QUIC_CODE_COUNT(quic_tear_down_local_connection_on_write_error_ietf);
  } else {
    QUIC_CODE_COUNT(quic_tear_down_local_connection_on_write_error_non_ietf);
  }
  CloseConnection(QUIC_PACKET_WRITE_ERROR, error_details,
                  ConnectionCloseBehavior::SILENT_CLOSE);
}

QuicPacketBuffer QuicConnection::GetPacketBuffer() {
  if (version().CanSendCoalescedPackets() && !coalescing_done_) {
    // Do not use writer's packet buffer for coalesced packets which may
    // contain multiple QUIC packets.
    return {nullptr, nullptr};
  }
  return writer_->GetNextWriteLocation(self_address().host(), peer_address());
}

void QuicConnection::OnSerializedPacket(SerializedPacket serialized_packet) {
  if (serialized_packet.encrypted_buffer == nullptr) {
    // We failed to serialize the packet, so close the connection.
    // Specify that the close is silent, that no packet be sent, so no infinite
    // loop here.
    // TODO(ianswett): This is actually an internal error, not an
    // encryption failure.
    if (version().HasIetfInvariantHeader()) {
      QUIC_CODE_COUNT(
          quic_tear_down_local_connection_on_serialized_packet_ietf);
    } else {
      QUIC_CODE_COUNT(
          quic_tear_down_local_connection_on_serialized_packet_non_ietf);
    }
    CloseConnection(QUIC_ENCRYPTION_FAILURE,
                    "Serialized packet does not have an encrypted buffer.",
                    ConnectionCloseBehavior::SILENT_CLOSE);
    return;
  }

  if (serialized_packet.retransmittable_frames.empty()) {
    // Increment consecutive_num_packets_with_no_retransmittable_frames_ if
    // this packet is a new transmission with no retransmittable frames.
    ++consecutive_num_packets_with_no_retransmittable_frames_;
  } else {
    consecutive_num_packets_with_no_retransmittable_frames_ = 0;
  }
  if (retransmittable_on_wire_behavior_ == SEND_FIRST_FORWARD_SECURE_PACKET &&
      first_serialized_one_rtt_packet_ == nullptr &&
      serialized_packet.encryption_level == ENCRYPTION_FORWARD_SECURE) {
    first_serialized_one_rtt_packet_ = std::make_unique<BufferedPacket>(
        serialized_packet, self_address(), peer_address());
  }
  SendOrQueuePacket(std::move(serialized_packet));
}

void QuicConnection::OnUnrecoverableError(QuicErrorCode error,
                                          const std::string& error_details) {
  // The packet creator or generator encountered an unrecoverable error: tear
  // down local connection state immediately.
  if (version().HasIetfInvariantHeader()) {
    QUIC_CODE_COUNT(
        quic_tear_down_local_connection_on_unrecoverable_error_ietf);
  } else {
    QUIC_CODE_COUNT(
        quic_tear_down_local_connection_on_unrecoverable_error_non_ietf);
  }
  CloseConnection(error, error_details, ConnectionCloseBehavior::SILENT_CLOSE);
}

void QuicConnection::OnCongestionChange() {
  visitor_->OnCongestionWindowChange(clock_->ApproximateNow());

  // Uses the connection's smoothed RTT. If zero, uses initial_rtt.
  QuicTime::Delta rtt = sent_packet_manager_.GetRttStats()->smoothed_rtt();
  if (rtt.IsZero()) {
    rtt = sent_packet_manager_.GetRttStats()->initial_rtt();
  }

  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnRttChanged(rtt);
  }
}

void QuicConnection::OnPathMtuIncreased(QuicPacketLength packet_size) {
  if (packet_size > max_packet_length()) {
    previous_validated_mtu_ = max_packet_length();
    SetMaxPacketLength(packet_size);
    mtu_discoverer_.OnMaxPacketLengthUpdated(previous_validated_mtu_,
                                             max_packet_length());
  }
}

std::unique_ptr<QuicSelfIssuedConnectionIdManager>
QuicConnection::MakeSelfIssuedConnectionIdManager() {
  QUICHE_DCHECK((perspective_ == Perspective::IS_CLIENT &&
                 !default_path_.client_connection_id.IsEmpty()) ||
                (perspective_ == Perspective::IS_SERVER &&
                 !default_path_.server_connection_id.IsEmpty()));
  return std::make_unique<QuicSelfIssuedConnectionIdManager>(
      kMinNumOfActiveConnectionIds,
      perspective_ == Perspective::IS_CLIENT
          ? default_path_.client_connection_id
          : default_path_.server_connection_id,
      clock_, alarm_factory_, this, context(), connection_id_generator_);
}

void QuicConnection::MaybeSendConnectionIdToClient() {
  if (perspective_ == Perspective::IS_CLIENT) {
    return;
  }
  QUICHE_DCHECK(self_issued_cid_manager_ != nullptr);
  self_issued_cid_manager_->MaybeSendNewConnectionIds();
}

void QuicConnection::OnHandshakeComplete() {
  sent_packet_manager_.SetHandshakeConfirmed();
  if (connection_migration_use_new_cid_ &&
      perspective_ == Perspective::IS_SERVER &&
      self_issued_cid_manager_ != nullptr) {
    self_issued_cid_manager_->MaybeSendNewConnectionIds();
  }
  if (send_ack_frequency_on_handshake_completion_ &&
      sent_packet_manager_.CanSendAckFrequency()) {
    QUIC_RELOADABLE_FLAG_COUNT_N(quic_can_send_ack_frequency, 2, 3);
    auto ack_frequency_frame =
        sent_packet_manager_.GetUpdatedAckFrequencyFrame();
    // This AckFrequencyFrame is meant to only update the max_ack_delay. Set
    // packet tolerance to the default value for now.
    ack_frequency_frame.packet_tolerance =
        kDefaultRetransmittablePacketsBeforeAck;
    visitor_->SendAckFrequency(ack_frequency_frame);
    if (!connected_) {
      return;
    }
  }
  // This may have changed the retransmission timer, so re-arm it.
  SetRetransmissionAlarm();
  if (default_enable_5rto_blackhole_detection_) {
    QUIC_RELOADABLE_FLAG_COUNT_N(quic_default_enable_5rto_blackhole_detection2,
                                 2, 3);
    OnForwardProgressMade();
  }
  if (!SupportsMultiplePacketNumberSpaces()) {
    // The client should immediately ack the SHLO to confirm the handshake is
    // complete with the server.
    if (perspective_ == Perspective::IS_CLIENT && ack_frame_updated()) {
      ack_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero());
    }
    return;
  }
  // Stop sending ack of handshake packet number space.
  uber_received_packet_manager_.ResetAckStates(ENCRYPTION_HANDSHAKE);
  // Re-arm ack alarm.
  ack_alarm_->Update(uber_received_packet_manager_.GetEarliestAckTimeout(),
                     kAlarmGranularity);
  if (!accelerated_server_preferred_address_ &&
      received_server_preferred_address_.IsInitialized()) {
    QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
    visitor_->OnServerPreferredAddressAvailable(
        received_server_preferred_address_);
  }
}

void QuicConnection::MaybeCreateMultiPortPath() {
  QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
  if (path_validator_.HasPendingPathValidation()) {
    QUIC_CLIENT_HISTOGRAM_ENUM("QuicConnection.MultiPortPathCreationCancelled",
                               path_validator_.GetPathValidationReason(),
                               PathValidationReason::kMaxValue,
                               "Reason for cancelled multi port path creation");
    return;
  }
  if (multi_port_stats_->num_multi_port_paths_created >=
      kMaxNumMultiPortPaths) {
    return;
  }
  auto path_context = visitor_->CreateContextForMultiPortPath();
  if (!path_context) {
    return;
  }
  auto multi_port_validation_result_delegate =
      std::make_unique<MultiPortPathValidationResultDelegate>(this);
  multi_port_probing_alarm_->Cancel();
  multi_port_path_context_ = nullptr;
  multi_port_stats_->num_multi_port_paths_created++;
  ValidatePath(std::move(path_context),
               std::move(multi_port_validation_result_delegate),
               PathValidationReason::kMultiPort);
}

void QuicConnection::SendOrQueuePacket(SerializedPacket packet) {
  // The caller of this function is responsible for checking CanWrite().
  WritePacket(&packet);
}

void QuicConnection::SendAck() {
  QUICHE_DCHECK(!SupportsMultiplePacketNumberSpaces());
  QUIC_DVLOG(1) << ENDPOINT << "Sending an ACK proactively";
  QuicFrames frames;
  frames.push_back(GetUpdatedAckFrame());
  if (!no_stop_waiting_frames_) {
    QuicStopWaitingFrame stop_waiting;
    PopulateStopWaitingFrame(&stop_waiting);
    frames.push_back(QuicFrame(stop_waiting));
  }
  if (!packet_creator_.FlushAckFrame(frames)) {
    return;
  }
  ResetAckStates();
  if (!ShouldBundleRetransmittableFrameWithAck()) {
    return;
  }
  consecutive_num_packets_with_no_retransmittable_frames_ = 0;
  if (packet_creator_.HasPendingRetransmittableFrames() ||
      visitor_->WillingAndAbleToWrite()) {
    // There are pending retransmittable frames.
    return;
  }

  visitor_->OnAckNeedsRetransmittableFrame();
}

EncryptionLevel QuicConnection::GetEncryptionLevelToSendPingForSpace(
    PacketNumberSpace space) const {
  switch (space) {
    case INITIAL_DATA:
      return ENCRYPTION_INITIAL;
    case HANDSHAKE_DATA:
      return ENCRYPTION_HANDSHAKE;
    case APPLICATION_DATA:
      return framer_.GetEncryptionLevelToSendApplicationData();
    default:
      QUICHE_DCHECK(false);
      return NUM_ENCRYPTION_LEVELS;
  }
}

bool QuicConnection::IsKnownServerAddress(
    const QuicSocketAddress& address) const {
  QUICHE_DCHECK(address.IsInitialized());
  return std::find(known_server_addresses_.cbegin(),
                   known_server_addresses_.cend(),
                   address) != known_server_addresses_.cend();
}

void QuicConnection::OnRetransmissionTimeout() {
  ScopedRetransmissionTimeoutIndicator indicator(this);
#ifndef NDEBUG
  if (sent_packet_manager_.unacked_packets().empty()) {
    QUICHE_DCHECK(sent_packet_manager_.handshake_mode_disabled());
    QUICHE_DCHECK(!IsHandshakeComplete());
  }
#endif
  if (!connected_) {
    return;
  }

  QuicPacketNumber previous_created_packet_number =
      packet_creator_.packet_number();
  const auto retransmission_mode =
      sent_packet_manager_.OnRetransmissionTimeout();
  if (retransmission_mode == QuicSentPacketManager::PTO_MODE) {
    // Skip a packet number when PTO fires to elicit an immediate ACK.
    const QuicPacketCount num_packet_numbers_to_skip = 1;
    packet_creator_.SkipNPacketNumbers(
        num_packet_numbers_to_skip,
        sent_packet_manager_.GetLeastPacketAwaitedByPeer(encryption_level_),
        sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
    previous_created_packet_number += num_packet_numbers_to_skip;
    if (debug_visitor_ != nullptr) {
      debug_visitor_->OnNPacketNumbersSkipped(num_packet_numbers_to_skip,
                                              clock_->Now());
    }
  }
  if (default_enable_5rto_blackhole_detection_ &&
      !sent_packet_manager_.HasInFlightPackets() &&
      blackhole_detector_.IsDetectionInProgress()) {
    // Stop detection in quiescence.
    QUICHE_DCHECK_EQ(QuicSentPacketManager::LOSS_MODE, retransmission_mode);
    blackhole_detector_.StopDetection(/*permanent=*/false);
  }
  WriteIfNotBlocked();

  // A write failure can result in the connection being closed, don't attempt to
  // write further packets, or to set alarms.
  if (!connected_) {
    return;
  }
  // When PTO fires, the SentPacketManager gives the connection the opportunity
  // to send new data before retransmitting.
  sent_packet_manager_.MaybeSendProbePacket();

  if (packet_creator_.packet_number() == previous_created_packet_number &&
      retransmission_mode == QuicSentPacketManager::PTO_MODE &&
      !visitor_->WillingAndAbleToWrite()) {
    // Send PING if timer fires in PTO mode but there is no data to send.
    QUIC_DLOG(INFO) << ENDPOINT
                    << "No packet gets sent when timer fires in mode "
                    << retransmission_mode << ", send PING";
    QUICHE_DCHECK_LT(0u,
                     sent_packet_manager_.pending_timer_transmission_count());
    if (SupportsMultiplePacketNumberSpaces()) {
      // Based on https://datatracker.ietf.org/doc/html/rfc9002#appendix-A.9
      PacketNumberSpace packet_number_space;
      if (sent_packet_manager_
              .GetEarliestPacketSentTimeForPto(&packet_number_space)
              .IsInitialized()) {
        SendPingAtLevel(
            GetEncryptionLevelToSendPingForSpace(packet_number_space));
      } else {
        // The client must PTO when there is nothing in flight if the server
        // could be blocked from sending by the amplification limit
        QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
        if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_HANDSHAKE)) {
          SendPingAtLevel(ENCRYPTION_HANDSHAKE);
        } else if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL)) {
          SendPingAtLevel(ENCRYPTION_INITIAL);
        } else {
          QUIC_BUG(quic_bug_no_pto) << "PTO fired but nothing was sent.";
        }
      }
    } else {
      SendPingAtLevel(encryption_level_);
    }
  }
  if (retransmission_mode == QuicSentPacketManager::PTO_MODE) {
    // When timer fires in PTO mode, ensure 1) at least one packet is created,
    // or there is data to send and available credit (such that packets will be
    // sent eventually).
    QUIC_BUG_IF(
        quic_bug_12714_27,
        packet_creator_.packet_number() == previous_created_packet_number &&
            (!visitor_->WillingAndAbleToWrite() ||
             sent_packet_manager_.pending_timer_transmission_count() == 0u))
        << "retransmission_mode: " << retransmission_mode
        << ", packet_number: " << packet_creator_.packet_number()
        << ", session has data to write: " << visitor_->WillingAndAbleToWrite()
        << ", writer is blocked: " << writer_->IsWriteBlocked()
        << ", pending_timer_transmission_count: "
        << sent_packet_manager_.pending_timer_transmission_count();
  }

  // Ensure the retransmission alarm is always set if there are unacked packets
  // and nothing waiting to be sent.
  // This happens if the loss algorithm invokes a timer based loss, but the
  // packet doesn't need to be retransmitted.
  if (!HasQueuedData() && !retransmission_alarm_->IsSet()) {
    SetRetransmissionAlarm();
  }
}

void QuicConnection::SetEncrypter(EncryptionLevel level,
                                  std::unique_ptr<QuicEncrypter> encrypter) {
  packet_creator_.SetEncrypter(level, std::move(encrypter));
}

void QuicConnection::RemoveEncrypter(EncryptionLevel level) {
  framer_.RemoveEncrypter(level);
}

void QuicConnection::SetDiversificationNonce(
    const DiversificationNonce& nonce) {
  QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective_);
  packet_creator_.SetDiversificationNonce(nonce);
}

void QuicConnection::SetDefaultEncryptionLevel(EncryptionLevel level) {
  QUIC_DVLOG(1) << ENDPOINT << "Setting default encryption level from "
                << encryption_level_ << " to " << level;
  const bool changing_level = level != encryption_level_;
  if (changing_level && packet_creator_.HasPendingFrames()) {
    // Flush all queued frames when encryption level changes.
    ScopedPacketFlusher flusher(this);
    packet_creator_.FlushCurrentPacket();
  }
  encryption_level_ = level;
  packet_creator_.set_encryption_level(level);
  QUIC_BUG_IF(quic_bug_12714_28, !framer_.HasEncrypterOfEncryptionLevel(level))
      << ENDPOINT << "Trying to set encryption level to "
      << EncryptionLevelToString(level) << " while the key is missing";

  if (!changing_level) {
    return;
  }
  // The least packet awaited by the peer depends on the encryption level so
  // we recalculate it here.
  packet_creator_.UpdatePacketNumberLength(
      sent_packet_manager_.GetLeastPacketAwaitedByPeer(encryption_level_),
      sent_packet_manager_.EstimateMaxPacketsInFlight(max_packet_length()));
}

void QuicConnection::SetDecrypter(EncryptionLevel level,
                                  std::unique_ptr<QuicDecrypter> decrypter) {
  framer_.SetDecrypter(level, std::move(decrypter));

  if (!undecryptable_packets_.empty() &&
      !process_undecryptable_packets_alarm_->IsSet()) {
    process_undecryptable_packets_alarm_->Set(clock_->ApproximateNow());
  }
}

void QuicConnection::SetAlternativeDecrypter(
    EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter,
    bool latch_once_used) {
  framer_.SetAlternativeDecrypter(level, std::move(decrypter), latch_once_used);

  if (!undecryptable_packets_.empty() &&
      !process_undecryptable_packets_alarm_->IsSet()) {
    process_undecryptable_packets_alarm_->Set(clock_->ApproximateNow());
  }
}

void QuicConnection::InstallDecrypter(
    EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter) {
  if (level == ENCRYPTION_ZERO_RTT) {
    had_zero_rtt_decrypter_ = true;
  }
  framer_.InstallDecrypter(level, std::move(decrypter));
  if (!undecryptable_packets_.empty() &&
      !process_undecryptable_packets_alarm_->IsSet()) {
    process_undecryptable_packets_alarm_->Set(clock_->ApproximateNow());
  }
}

void QuicConnection::RemoveDecrypter(EncryptionLevel level) {
  framer_.RemoveDecrypter(level);
}

void QuicConnection::DiscardPreviousOneRttKeys() {
  framer_.DiscardPreviousOneRttKeys();
}

bool QuicConnection::IsKeyUpdateAllowed() const {
  return support_key_update_for_connection_ &&
         GetLargestAckedPacket().IsInitialized() &&
         lowest_packet_sent_in_current_key_phase_.IsInitialized() &&
         GetLargestAckedPacket() >= lowest_packet_sent_in_current_key_phase_;
}

bool QuicConnection::HaveSentPacketsInCurrentKeyPhaseButNoneAcked() const {
  return lowest_packet_sent_in_current_key_phase_.IsInitialized() &&
         (!GetLargestAckedPacket().IsInitialized() ||
          GetLargestAckedPacket() < lowest_packet_sent_in_current_key_phase_);
}

QuicPacketCount QuicConnection::PotentialPeerKeyUpdateAttemptCount() const {
  return framer_.PotentialPeerKeyUpdateAttemptCount();
}

bool QuicConnection::InitiateKeyUpdate(KeyUpdateReason reason) {
  QUIC_DLOG(INFO) << ENDPOINT << "InitiateKeyUpdate";
  if (!IsKeyUpdateAllowed()) {
    QUIC_BUG(quic_bug_10511_28) << "key update not allowed";
    return false;
  }
  return framer_.DoKeyUpdate(reason);
}

const QuicDecrypter* QuicConnection::decrypter() const {
  return framer_.decrypter();
}

const QuicDecrypter* QuicConnection::alternative_decrypter() const {
  return framer_.alternative_decrypter();
}

void QuicConnection::QueueUndecryptablePacket(
    const QuicEncryptedPacket& packet, EncryptionLevel decryption_level) {
  for (const auto& saved_packet : undecryptable_packets_) {
    if (packet.data() == saved_packet.packet->data() &&
        packet.length() == saved_packet.packet->length()) {
      QUIC_DVLOG(1) << ENDPOINT << "Not queueing known undecryptable packet";
      return;
    }
  }
  QUIC_DVLOG(1) << ENDPOINT << "Queueing undecryptable packet.";
  undecryptable_packets_.emplace_back(packet, decryption_level,
                                      last_received_packet_info_);
  if (perspective_ == Perspective::IS_CLIENT) {
    SetRetransmissionAlarm();
  }
}

void QuicConnection::MaybeProcessUndecryptablePackets() {
  process_undecryptable_packets_alarm_->Cancel();

  if (undecryptable_packets_.empty() ||
      encryption_level_ == ENCRYPTION_INITIAL) {
    return;
  }

  auto iter = undecryptable_packets_.begin();
  while (connected_ && iter != undecryptable_packets_.end()) {
    // Making sure there is no pending frames when processing next undecrypted
    // packet because the queued ack frame may change.
    packet_creator_.FlushCurrentPacket();
    if (!connected_) {
      return;
    }
    UndecryptablePacket* undecryptable_packet = &*iter;
    QUIC_DVLOG(1) << ENDPOINT << "Attempting to process undecryptable packet";
    if (debug_visitor_ != nullptr) {
      debug_visitor_->OnAttemptingToProcessUndecryptablePacket(
          undecryptable_packet->encryption_level);
    }
    last_received_packet_info_ = undecryptable_packet->packet_info;
    current_packet_data_ = undecryptable_packet->packet->data();
    const bool processed = framer_.ProcessPacket(*undecryptable_packet->packet);
    current_packet_data_ = nullptr;

    if (processed) {
      QUIC_DVLOG(1) << ENDPOINT << "Processed undecryptable packet!";
      iter = undecryptable_packets_.erase(iter);
      ++stats_.packets_processed;
      continue;
    }
    const bool has_decryption_key = version().KnowsWhichDecrypterToUse() &&
                                    framer_.HasDecrypterOfEncryptionLevel(
                                        undecryptable_packet->encryption_level);
    if (framer_.error() == QUIC_DECRYPTION_FAILURE &&
        ShouldEnqueueUnDecryptablePacket(undecryptable_packet->encryption_level,
                                         has_decryption_key)) {
      QUIC_DVLOG(1)
          << ENDPOINT
          << "Need to attempt to process this undecryptable packet later";
      ++iter;
      continue;
    }
    iter = undecryptable_packets_.erase(iter);
  }

  // Once handshake is complete, there will be no new keys installed and hence
  // any undecryptable packets will never be able to be decrypted.
  if (IsHandshakeComplete()) {
    if (debug_visitor_ != nullptr) {
      for (const auto& undecryptable_packet : undecryptable_packets_) {
        debug_visitor_->OnUndecryptablePacket(
            undecryptable_packet.encryption_level, /*dropped=*/true);
      }
    }
    undecryptable_packets_.clear();
  }
  if (perspective_ == Perspective::IS_CLIENT) {
    SetRetransmissionAlarm();
  }
}

void QuicConnection::QueueCoalescedPacket(const QuicEncryptedPacket& packet) {
  QUIC_DVLOG(1) << ENDPOINT << "Queueing coalesced packet.";
  received_coalesced_packets_.push_back(packet.Clone());
  ++stats_.num_coalesced_packets_received;
}

bool QuicConnection::MaybeProcessCoalescedPackets() {
  bool processed = false;
  while (connected_ && !received_coalesced_packets_.empty()) {
    // Making sure there are no pending frames when processing the next
    // coalesced packet because the queued ack frame may change.
    packet_creator_.FlushCurrentPacket();
    if (!connected_) {
      return processed;
    }

    std::unique_ptr<QuicEncryptedPacket> packet =
        std::move(received_coalesced_packets_.front());
    received_coalesced_packets_.pop_front();

    QUIC_DVLOG(1) << ENDPOINT << "Processing coalesced packet";
    if (framer_.ProcessPacket(*packet)) {
      processed = true;
      ++stats_.num_coalesced_packets_processed;
    } else {
      // If we are unable to decrypt this packet, it might be
      // because the CHLO or SHLO packet was lost.
    }
  }
  if (processed) {
    MaybeProcessUndecryptablePackets();
    MaybeSendInResponseToPacket();
  }
  return processed;
}

void QuicConnection::CloseConnection(
    QuicErrorCode error, const std::string& details,
    ConnectionCloseBehavior connection_close_behavior) {
  CloseConnection(error, NO_IETF_QUIC_ERROR, details,
                  connection_close_behavior);
}

void QuicConnection::CloseConnection(
    QuicErrorCode error, QuicIetfTransportErrorCodes ietf_error,
    const std::string& error_details,
    ConnectionCloseBehavior connection_close_behavior) {
  QUICHE_DCHECK(!error_details.empty());
  if (!connected_) {
    QUIC_DLOG(INFO) << "Connection is already closed.";
    return;
  }

  if (ietf_error != NO_IETF_QUIC_ERROR) {
    QUIC_DLOG(INFO) << ENDPOINT << "Closing connection: " << connection_id()
                    << ", with wire error: " << ietf_error
                    << ", error: " << QuicErrorCodeToString(error)
                    << ", and details:  " << error_details;
  } else {
    QUIC_DLOG(INFO) << ENDPOINT << "Closing connection: " << connection_id()
                    << ", with error: " << QuicErrorCodeToString(error) << " ("
                    << error << "), and details:  " << error_details;
  }

  if (connection_close_behavior != ConnectionCloseBehavior::SILENT_CLOSE) {
    SendConnectionClosePacket(error, ietf_error, error_details);
  }

  TearDownLocalConnectionState(error, ietf_error, error_details,
                               ConnectionCloseSource::FROM_SELF);
}

void QuicConnection::SendConnectionClosePacket(
    QuicErrorCode error, QuicIetfTransportErrorCodes ietf_error,
    const std::string& details) {
  // Always use the current path to send CONNECTION_CLOSE.
  QuicPacketCreator::ScopedPeerAddressContext context(
      &packet_creator_, peer_address(), default_path_.client_connection_id,
      default_path_.server_connection_id, connection_migration_use_new_cid_);
  if (!SupportsMultiplePacketNumberSpaces()) {
    QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
    ScopedEncryptionLevelContext context(this,
                                         GetConnectionCloseEncryptionLevel());
    if (version().CanSendCoalescedPackets()) {
      coalesced_packet_.Clear();
    }
    ClearQueuedPackets();
    // If there was a packet write error, write the smallest close possible.
    ScopedPacketFlusher flusher(this);
    // Always bundle an ACK with connection close for debugging purpose.
    if (error != QUIC_PACKET_WRITE_ERROR &&
        !uber_received_packet_manager_.IsAckFrameEmpty(
            QuicUtils::GetPacketNumberSpace(encryption_level_)) &&
        !packet_creator_.has_ack()) {
      SendAck();
    }
    QuicConnectionCloseFrame* frame;

    frame = new QuicConnectionCloseFrame(transport_version(), error, ietf_error,
                                         details,
                                         framer_.current_received_frame_type());
    packet_creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
    packet_creator_.FlushCurrentPacket();
    if (version().CanSendCoalescedPackets()) {
      FlushCoalescedPacket();
    }
    ClearQueuedPackets();
    return;
  }
  ScopedPacketFlusher flusher(this);

  // Now that the connection is being closed, discard any unsent packets
  // so the only packets to be sent will be connection close packets.
  if (version().CanSendCoalescedPackets()) {
    coalesced_packet_.Clear();
  }
  ClearQueuedPackets();

  for (EncryptionLevel level :
       {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT,
        ENCRYPTION_FORWARD_SECURE}) {
    if (!framer_.HasEncrypterOfEncryptionLevel(level)) {
      continue;
    }
    QUIC_DLOG(INFO) << ENDPOINT
                    << "Sending connection close packet at level: " << level;
    ScopedEncryptionLevelContext context(this, level);
    // Bundle an ACK of the corresponding packet number space for debugging
    // purpose.
    if (error != QUIC_PACKET_WRITE_ERROR &&
        !uber_received_packet_manager_.IsAckFrameEmpty(
            QuicUtils::GetPacketNumberSpace(encryption_level_)) &&
        !packet_creator_.has_ack()) {
      QuicFrames frames;
      frames.push_back(GetUpdatedAckFrame());
      packet_creator_.FlushAckFrame(frames);
    }

    if (level == ENCRYPTION_FORWARD_SECURE &&
        perspective_ == Perspective::IS_SERVER) {
      visitor_->BeforeConnectionCloseSent();
    }

    auto* frame = new QuicConnectionCloseFrame(
        transport_version(), error, ietf_error, details,
        framer_.current_received_frame_type());
    packet_creator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
    packet_creator_.FlushCurrentPacket();
  }
  if (version().CanSendCoalescedPackets()) {
    FlushCoalescedPacket();
  }
  // Since the connection is closing, if the connection close packets were not
  // sent, then they should be discarded.
  ClearQueuedPackets();
}

void QuicConnection::TearDownLocalConnectionState(
    QuicErrorCode error, QuicIetfTransportErrorCodes ietf_error,
    const std::string& error_details, ConnectionCloseSource source) {
  QuicConnectionCloseFrame frame(transport_version(), error, ietf_error,
                                 error_details,
                                 framer_.current_received_frame_type());
  return TearDownLocalConnectionState(frame, source);
}

void QuicConnection::TearDownLocalConnectionState(
    const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
  if (!connected_) {
    QUIC_DLOG(INFO) << "Connection is already closed.";
    return;
  }

  // If we are using a batch writer, flush packets queued in it, if any.
  FlushPackets();
  connected_ = false;
  QUICHE_DCHECK(visitor_ != nullptr);
  visitor_->OnConnectionClosed(frame, source);
  // LossDetectionTunerInterface::Finish() may be called from
  // sent_packet_manager_.OnConnectionClosed. Which may require the session to
  // finish its business first.
  sent_packet_manager_.OnConnectionClosed();
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnConnectionClosed(frame, source);
  }
  // Cancel the alarms so they don't trigger any action now that the
  // connection is closed.
  CancelAllAlarms();
  CancelPathValidation();

  peer_issued_cid_manager_.reset();
  self_issued_cid_manager_.reset();
}

void QuicConnection::CancelAllAlarms() {
  QUIC_DVLOG(1) << "Cancelling all QuicConnection alarms.";

  ack_alarm_->PermanentCancel();
  ping_manager_.Stop();
  retransmission_alarm_->PermanentCancel();
  send_alarm_->PermanentCancel();
  mtu_discovery_alarm_->PermanentCancel();
  process_undecryptable_packets_alarm_->PermanentCancel();
  discard_previous_one_rtt_keys_alarm_->PermanentCancel();
  discard_zero_rtt_decryption_keys_alarm_->PermanentCancel();
  multi_port_probing_alarm_->PermanentCancel();
  blackhole_detector_.StopDetection(/*permanent=*/true);
  idle_network_detector_.StopDetection();
}

QuicByteCount QuicConnection::max_packet_length() const {
  return packet_creator_.max_packet_length();
}

void QuicConnection::SetMaxPacketLength(QuicByteCount length) {
  long_term_mtu_ = length;
  stats_.max_egress_mtu = std::max(stats_.max_egress_mtu, long_term_mtu_);
  packet_creator_.SetMaxPacketLength(GetLimitedMaxPacketSize(length));
}

bool QuicConnection::HasQueuedData() const {
  return packet_creator_.HasPendingFrames() || !buffered_packets_.empty();
}

void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
                                        QuicTime::Delta idle_timeout) {
  QUIC_BUG_IF(quic_bug_12714_29, idle_timeout > handshake_timeout)
      << "idle_timeout:" << idle_timeout.ToMilliseconds()
      << " handshake_timeout:" << handshake_timeout.ToMilliseconds();
  // Adjust the idle timeout on client and server to prevent clients from
  // sending requests to servers which have already closed the connection.
  if (perspective_ == Perspective::IS_SERVER) {
    idle_timeout = idle_timeout + QuicTime::Delta::FromSeconds(3);
  } else if (idle_timeout > QuicTime::Delta::FromSeconds(1)) {
    idle_timeout = idle_timeout - QuicTime::Delta::FromSeconds(1);
  }
  idle_network_detector_.SetTimeouts(handshake_timeout, idle_timeout);
}

void QuicConnection::SetPingAlarm() {
  if (!connected_) {
    return;
  }
  ping_manager_.SetAlarm(clock_->ApproximateNow(),
                         visitor_->ShouldKeepConnectionAlive(),
                         sent_packet_manager_.HasInFlightPackets());
}

void QuicConnection::SetRetransmissionAlarm() {
  if (!connected_) {
    if (retransmission_alarm_->IsSet()) {
      QUIC_BUG(quic_bug_10511_29)
          << ENDPOINT << "Retransmission alarm is set while disconnected";
      retransmission_alarm_->Cancel();
    }
    return;
  }
  if (packet_creator_.PacketFlusherAttached()) {
    pending_retransmission_alarm_ = true;
    return;
  }
  if (LimitedByAmplificationFactor(packet_creator_.max_packet_length())) {
    // Do not set retransmission timer if connection is anti-amplification limit
    // throttled. Otherwise, nothing can be sent when timer fires.
    retransmission_alarm_->Cancel();
    return;
  }
  PacketNumberSpace packet_number_space;
  if (SupportsMultiplePacketNumberSpaces() && !IsHandshakeConfirmed() &&
      !sent_packet_manager_
           .GetEarliestPacketSentTimeForPto(&packet_number_space)
           .IsInitialized()) {
    // Before handshake gets confirmed, GetEarliestPacketSentTimeForPto
    // returning 0 indicates no packets are in flight or only application data
    // is in flight.
    if (perspective_ == Perspective::IS_SERVER) {
      // No need to arm PTO on server side.
      retransmission_alarm_->Cancel();
      return;
    }
    if (retransmission_alarm_->IsSet() &&
        GetRetransmissionDeadline() > retransmission_alarm_->deadline()) {
      // Do not postpone armed PTO on the client side.
      return;
    }
  }

  retransmission_alarm_->Update(GetRetransmissionDeadline(), kAlarmGranularity);
}

void QuicConnection::MaybeSetMtuAlarm(QuicPacketNumber sent_packet_number) {
  if (mtu_discovery_alarm_->IsSet() ||
      !mtu_discoverer_.ShouldProbeMtu(sent_packet_number)) {
    return;
  }
  mtu_discovery_alarm_->Set(clock_->ApproximateNow());
}

QuicConnection::ScopedPacketFlusher::ScopedPacketFlusher(
    QuicConnection* connection)
    : connection_(connection),
      flush_and_set_pending_retransmission_alarm_on_delete_(false),
      handshake_packet_sent_(connection != nullptr &&
                             connection->handshake_packet_sent_) {
  if (connection_ == nullptr) {
    return;
  }

  if (!connection_->packet_creator_.PacketFlusherAttached()) {
    flush_and_set_pending_retransmission_alarm_on_delete_ = true;
    connection->packet_creator_.AttachPacketFlusher();
  }
}

QuicConnection::ScopedPacketFlusher::~ScopedPacketFlusher() {
  if (connection_ == nullptr || !connection_->connected()) {
    return;
  }

  if (flush_and_set_pending_retransmission_alarm_on_delete_) {
    const QuicTime ack_timeout =
        connection_->uber_received_packet_manager_.GetEarliestAckTimeout();
    if (ack_timeout.IsInitialized()) {
      if (ack_timeout <= connection_->clock_->ApproximateNow() &&
          !connection_->CanWrite(NO_RETRANSMITTABLE_DATA)) {
        // Cancel ACK alarm if connection is write blocked, and ACK will be
        // sent when connection gets unblocked.
        connection_->ack_alarm_->Cancel();
      } else if (!connection_->ack_alarm_->IsSet() ||
                 connection_->ack_alarm_->deadline() > ack_timeout) {
        connection_->ack_alarm_->Update(ack_timeout, QuicTime::Delta::Zero());
      }
    }
    if (connection_->ack_alarm_->IsSet() &&
        connection_->ack_alarm_->deadline() <=
            connection_->clock_->ApproximateNow()) {
      // An ACK needs to be sent right now. This ACK did not get bundled
      // because either there was no data to write or packets were marked as
      // received after frames were queued in the generator.
      if (connection_->send_alarm_->IsSet() &&
          connection_->send_alarm_->deadline() <=
              connection_->clock_->ApproximateNow()) {
        // If send alarm will go off soon, let send alarm send the ACK.
        connection_->ack_alarm_->Cancel();
      } else if (connection_->SupportsMultiplePacketNumberSpaces()) {
        connection_->SendAllPendingAcks();
      } else {
        connection_->SendAck();
      }
    }

    // INITIAL or HANDSHAKE retransmission could cause peer to derive new
    // keys, such that the buffered undecryptable packets may be processed.
    // This endpoint would derive an inflated RTT sample when receiving ACKs
    // of those undecryptable packets. To mitigate this, tries to coalesce as
    // many higher space packets as possible (via for loop inside
    // MaybeCoalescePacketOfHigherSpace) to fill the remaining space in the
    // coalescer.
    if (connection_->version().CanSendCoalescedPackets()) {
      connection_->MaybeCoalescePacketOfHigherSpace();
    }
    connection_->packet_creator_.Flush();
    if (connection_->version().CanSendCoalescedPackets()) {
      connection_->FlushCoalescedPacket();
    }
    connection_->FlushPackets();

    if (!connection_->connected()) {
      return;
    }

    if (!handshake_packet_sent_ && connection_->handshake_packet_sent_) {
      // This would cause INITIAL key to be dropped. Drop keys here to avoid
      // missing the write keys in the middle of writing.
      connection_->visitor_->OnHandshakePacketSent();
    }
    // Reset transmission type.
    connection_->SetTransmissionType(NOT_RETRANSMISSION);

    // Once all transmissions are done, check if there is any outstanding data
    // to send and notify the congestion controller if not.
    //
    // Note that this means that the application limited check will happen as
    // soon as the last flusher gets destroyed, which is typically after a
    // single stream write is finished.  This means that if all the data from a
    // single write goes through the connection, the application-limited signal
    // will fire even if the caller does a write operation immediately after.
    // There are two important approaches to remedy this situation:
    // (1) Instantiate ScopedPacketFlusher before performing multiple subsequent
    //     writes, thus deferring this check until all writes are done.
    // (2) Write data in chunks sufficiently large so that they cause the
    //     connection to be limited by the congestion control.  Typically, this
    //     would mean writing chunks larger than the product of the current
    //     pacing rate and the pacer granularity.  So, for instance, if the
    //     pacing rate of the connection is 1 Gbps, and the pacer granularity is
    //     1 ms, the caller should send at least 125k bytes in order to not
    //     be marked as application-limited.
    connection_->CheckIfApplicationLimited();

    if (connection_->pending_retransmission_alarm_) {
      connection_->SetRetransmissionAlarm();
      connection_->pending_retransmission_alarm_ = false;
    }
  }
  QUICHE_DCHECK_EQ(flush_and_set_pending_retransmission_alarm_on_delete_,
                   !connection_->packet_creator_.PacketFlusherAttached());
}

QuicConnection::ScopedEncryptionLevelContext::ScopedEncryptionLevelContext(
    QuicConnection* connection, EncryptionLevel encryption_level)
    : connection_(connection), latched_encryption_level_(ENCRYPTION_INITIAL) {
  if (connection_ == nullptr) {
    return;
  }
  latched_encryption_level_ = connection_->encryption_level_;
  connection_->SetDefaultEncryptionLevel(encryption_level);
}

QuicConnection::ScopedEncryptionLevelContext::~ScopedEncryptionLevelContext() {
  if (connection_ == nullptr || !connection_->connected_) {
    return;
  }
  connection_->SetDefaultEncryptionLevel(latched_encryption_level_);
}

QuicConnection::BufferedPacket::BufferedPacket(
    const SerializedPacket& packet, const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address)
    : BufferedPacket(packet.encrypted_buffer, packet.encrypted_length,
                     self_address, peer_address) {}

QuicConnection::BufferedPacket::BufferedPacket(
    const char* encrypted_buffer, QuicPacketLength encrypted_length,
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address)
    : length(encrypted_length),
      self_address(self_address),
      peer_address(peer_address) {
  data = std::make_unique<char[]>(encrypted_length);
  memcpy(data.get(), encrypted_buffer, encrypted_length);
}

QuicConnection::BufferedPacket::BufferedPacket(
    QuicRandom& random, QuicPacketLength encrypted_length,
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address)
    : length(encrypted_length),
      self_address(self_address),
      peer_address(peer_address) {
  data = std::make_unique<char[]>(encrypted_length);
  random.RandBytes(data.get(), encrypted_length);
}

QuicConnection::ReceivedPacketInfo::ReceivedPacketInfo(QuicTime receipt_time)
    : receipt_time(receipt_time) {}
QuicConnection::ReceivedPacketInfo::ReceivedPacketInfo(
    const QuicSocketAddress& destination_address,
    const QuicSocketAddress& source_address, QuicTime receipt_time,
    QuicByteCount length, QuicEcnCodepoint ecn_codepoint)
    : destination_address(destination_address),
      source_address(source_address),
      receipt_time(receipt_time),
      length(length),
      ecn_codepoint(ecn_codepoint) {}

std::ostream& operator<<(std::ostream& os,
                         const QuicConnection::ReceivedPacketInfo& info) {
  os << " { destination_address: " << info.destination_address.ToString()
     << ", source_address: " << info.source_address.ToString()
     << ", received_bytes_counted: " << info.received_bytes_counted
     << ", length: " << info.length
     << ", destination_connection_id: " << info.destination_connection_id;
  if (!info.decrypted) {
    os << " }\n";
    return os;
  }
  os << ", decrypted: " << info.decrypted
     << ", decrypted_level: " << EncryptionLevelToString(info.decrypted_level)
     << ", header: " << info.header << ", frames: ";
  for (const auto frame : info.frames) {
    os << frame;
  }
  os << " }\n";
  return os;
}

HasRetransmittableData QuicConnection::IsRetransmittable(
    const SerializedPacket& packet) {
  // Retransmitted packets retransmittable frames are owned by the unacked
  // packet map, but are not present in the serialized packet.
  if (packet.transmission_type != NOT_RETRANSMISSION ||
      !packet.retransmittable_frames.empty()) {
    return HAS_RETRANSMITTABLE_DATA;
  } else {
    return NO_RETRANSMITTABLE_DATA;
  }
}

bool QuicConnection::IsTerminationPacket(const SerializedPacket& packet,
                                         QuicErrorCode* error_code) {
  if (packet.retransmittable_frames.empty()) {
    return false;
  }
  for (const QuicFrame& frame : packet.retransmittable_frames) {
    if (frame.type == CONNECTION_CLOSE_FRAME) {
      *error_code = frame.connection_close_frame->quic_error_code;
      return true;
    }
  }
  return false;
}

void QuicConnection::SetMtuDiscoveryTarget(QuicByteCount target) {
  QUIC_DVLOG(2) << ENDPOINT << "SetMtuDiscoveryTarget: " << target;
  mtu_discoverer_.Disable();
  mtu_discoverer_.Enable(max_packet_length(), GetLimitedMaxPacketSize(target));
}

QuicByteCount QuicConnection::GetLimitedMaxPacketSize(
    QuicByteCount suggested_max_packet_size) {
  if (!peer_address().IsInitialized()) {
    QUIC_BUG(quic_bug_10511_30)
        << "Attempted to use a connection without a valid peer address";
    return suggested_max_packet_size;
  }

  const QuicByteCount writer_limit = writer_->GetMaxPacketSize(peer_address());

  QuicByteCount max_packet_size = suggested_max_packet_size;
  if (max_packet_size > writer_limit) {
    max_packet_size = writer_limit;
  }
  if (max_packet_size > peer_max_packet_size_) {
    max_packet_size = peer_max_packet_size_;
  }
  if (max_packet_size > kMaxOutgoingPacketSize) {
    max_packet_size = kMaxOutgoingPacketSize;
  }
  return max_packet_size;
}

void QuicConnection::SendMtuDiscoveryPacket(QuicByteCount target_mtu) {
  // Currently, this limit is ensured by the caller.
  QUICHE_DCHECK_EQ(target_mtu, GetLimitedMaxPacketSize(target_mtu));

  // Send the probe.
  packet_creator_.GenerateMtuDiscoveryPacket(target_mtu);
}

// TODO(zhongyi): change this method to generate a connectivity probing packet
// and let the caller to call writer to write the packet and handle write
// status.
bool QuicConnection::SendConnectivityProbingPacket(
    QuicPacketWriter* probing_writer, const QuicSocketAddress& peer_address) {
  QUICHE_DCHECK(peer_address.IsInitialized());
  if (!connected_) {
    QUIC_BUG(quic_bug_10511_31)
        << "Not sending connectivity probing packet as connection is "
        << "disconnected.";
    return false;
  }
  if (perspective_ == Perspective::IS_SERVER && probing_writer == nullptr) {
    // Server can use default packet writer to write packet.
    probing_writer = writer_;
  }
  QUICHE_DCHECK(probing_writer);

  if (probing_writer->IsWriteBlocked()) {
    QUIC_DLOG(INFO)
        << ENDPOINT
        << "Writer blocked when sending connectivity probing packet.";
    if (probing_writer == writer_) {
      // Visitor should not be write blocked if the probing writer is not the
      // default packet writer.
      visitor_->OnWriteBlocked();
    }
    return true;
  }

  QUIC_DLOG(INFO) << ENDPOINT
                  << "Sending path probe packet for connection_id = "
                  << default_path_.server_connection_id;

  std::unique_ptr<SerializedPacket> probing_packet;
  if (!version().HasIetfQuicFrames()) {
    // Non-IETF QUIC, generate a padded ping regardless of whether this is a
    // request or a response.
    probing_packet = packet_creator_.SerializeConnectivityProbingPacket();
  } else {
    // IETF QUIC path challenge.
    // Send a path probe request using IETF QUIC PATH_CHALLENGE frame.
    QuicPathFrameBuffer transmitted_connectivity_probe_payload;
    random_generator_->RandBytes(&transmitted_connectivity_probe_payload,
                                 sizeof(QuicPathFrameBuffer));
    probing_packet =
        packet_creator_.SerializePathChallengeConnectivityProbingPacket(
            transmitted_connectivity_probe_payload);
  }
  QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet), NO_RETRANSMITTABLE_DATA);
  return WritePacketUsingWriter(std::move(probing_packet), probing_writer,
                                self_address(), peer_address,
                                /*measure_rtt=*/true);
}

bool QuicConnection::WritePacketUsingWriter(
    std::unique_ptr<SerializedPacket> packet, QuicPacketWriter* writer,
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address, bool measure_rtt) {
  const QuicTime packet_send_time = clock_->Now();
  QUIC_DVLOG(2) << ENDPOINT
                << "Sending path probe packet for server connection ID "
                << default_path_.server_connection_id << std::endl
                << quiche::QuicheTextUtils::HexDump(absl::string_view(
                       packet->encrypted_buffer, packet->encrypted_length));
  WriteResult result = writer->WritePacket(
      packet->encrypted_buffer, packet->encrypted_length, self_address.host(),
      peer_address, per_packet_options_);

  // If using a batch writer and the probing packet is buffered, flush it.
  if (writer->IsBatchMode() && result.status == WRITE_STATUS_OK &&
      result.bytes_written == 0) {
    result = writer->Flush();
  }

  if (IsWriteError(result.status)) {
    // Write error for any connectivity probe should not affect the connection
    // as it is sent on a different path.
    QUIC_DLOG(INFO) << ENDPOINT << "Write probing packet failed with error = "
                    << result.error_code;
    return false;
  }

  // Send in currrent path. Call OnPacketSent regardless of the write result.
  sent_packet_manager_.OnPacketSent(packet.get(), packet_send_time,
                                    packet->transmission_type,
                                    NO_RETRANSMITTABLE_DATA, measure_rtt);

  if (debug_visitor_ != nullptr) {
    if (sent_packet_manager_.unacked_packets().empty()) {
      QUIC_BUG(quic_bug_10511_32)
          << "Unacked map is empty right after packet is sent";
    } else {
      debug_visitor_->OnPacketSent(
          packet->packet_number, packet->encrypted_length,
          packet->has_crypto_handshake, packet->transmission_type,
          packet->encryption_level,
          sent_packet_manager_.unacked_packets()
              .rbegin()
              ->retransmittable_frames,
          packet->nonretransmittable_frames, packet_send_time);
    }
  }

  if (IsWriteBlockedStatus(result.status)) {
    if (writer == writer_) {
      // Visitor should not be write blocked if the probing writer is not the
      // default packet writer.
      visitor_->OnWriteBlocked();
    }
    if (result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
      QUIC_DLOG(INFO) << ENDPOINT << "Write probing packet blocked";
    }
  }

  return true;
}

void QuicConnection::DisableMtuDiscovery() {
  mtu_discoverer_.Disable();
  mtu_discovery_alarm_->Cancel();
}

void QuicConnection::DiscoverMtu() {
  QUICHE_DCHECK(!mtu_discovery_alarm_->IsSet());

  const QuicPacketNumber largest_sent_packet =
      sent_packet_manager_.GetLargestSentPacket();
  if (mtu_discoverer_.ShouldProbeMtu(largest_sent_packet)) {
    ++mtu_probe_count_;
    SendMtuDiscoveryPacket(
        mtu_discoverer_.GetUpdatedMtuProbeSize(largest_sent_packet));
  }
  QUICHE_DCHECK(!mtu_discovery_alarm_->IsSet());
}

void QuicConnection::OnEffectivePeerMigrationValidated(
    bool /*is_migration_linkable*/) {
  if (active_effective_peer_migration_type_ == NO_CHANGE) {
    QUIC_BUG(quic_bug_10511_33) << "No migration underway.";
    return;
  }
  highest_packet_sent_before_effective_peer_migration_.Clear();
  const bool send_address_token =
      active_effective_peer_migration_type_ != PORT_CHANGE;
  active_effective_peer_migration_type_ = NO_CHANGE;
  ++stats_.num_validated_peer_migration;
  if (!validate_client_addresses_) {
    return;
  }
  if (debug_visitor_ != nullptr) {
    const QuicTime now = clock_->ApproximateNow();
    if (now >= stats_.handshake_completion_time) {
      debug_visitor_->OnPeerMigrationValidated(
          now - stats_.handshake_completion_time);
    } else {
      QUIC_BUG(quic_bug_10511_34)
          << "Handshake completion time is larger than current time.";
    }
  }

  // Lift anti-amplification limit.
  default_path_.validated = true;
  alternative_path_.Clear();
  if (send_address_token) {
    visitor_->MaybeSendAddressToken();
  }
}

void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
  // TODO(fayang): Currently, all peer address change type are allowed. Need to
  // add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
  // determine whether |type| is allowed.
  if (!validate_client_addresses_) {
    if (type == NO_CHANGE) {
      QUIC_BUG(quic_bug_10511_35)
          << "EffectivePeerMigration started without address change.";
      return;
    }
    QUIC_DLOG(INFO)
        << ENDPOINT << "Effective peer's ip:port changed from "
        << default_path_.peer_address.ToString() << " to "
        << GetEffectivePeerAddressFromCurrentPacket().ToString()
        << ", address change type is " << type
        << ", migrating connection without validating new client address.";

    highest_packet_sent_before_effective_peer_migration_ =
        sent_packet_manager_.GetLargestSentPacket();
    default_path_.peer_address = GetEffectivePeerAddressFromCurrentPacket();
    active_effective_peer_migration_type_ = type;

    OnConnectionMigration();
    return;
  }

  if (type == NO_CHANGE) {
    UpdatePeerAddress(last_received_packet_info_.source_address);
    QUIC_BUG(quic_bug_10511_36)
        << "EffectivePeerMigration started without address change.";
    return;
  }
  if (GetQuicReloadableFlag(
          quic_flush_pending_frames_and_padding_bytes_on_migration)) {
    QUIC_RELOADABLE_FLAG_COUNT(
        quic_flush_pending_frames_and_padding_bytes_on_migration);
    // There could be pending NEW_TOKEN_FRAME triggered by non-probing
    // PATH_RESPONSE_FRAME in the same packet or pending padding bytes in the
    // packet creator.
    packet_creator_.FlushCurrentPacket();
    packet_creator_.SendRemainingPendingPadding();
    if (!connected_) {
      return;
    }
  } else {
    if (packet_creator_.HasPendingFrames()) {
      packet_creator_.FlushCurrentPacket();
      if (!connected_) {
        return;
      }
    }
  }

  // Action items:
  //   1. Switch congestion controller;
  //   2. Update default_path_ (addresses, validation and bytes accounting);
  //   3. Save previous default path if needed;
  //   4. Kick off reverse path validation if needed.
  // Items 1 and 2 are must-to-do. Items 3 and 4 depends on if the new address
  // is validated or not and which path the incoming packet is on.

  const QuicSocketAddress current_effective_peer_address =
      GetEffectivePeerAddressFromCurrentPacket();
  QUIC_DLOG(INFO) << ENDPOINT << "Effective peer's ip:port changed from "
                  << default_path_.peer_address.ToString() << " to "
                  << current_effective_peer_address.ToString()
                  << ", address change type is " << type
                  << ", migrating connection.";

  const QuicSocketAddress previous_direct_peer_address = direct_peer_address_;
  PathState previous_default_path = std::move(default_path_);
  active_effective_peer_migration_type_ = type;
  MaybeClearQueuedPacketsOnPathChange();
  OnConnectionMigration();

  // Update congestion controller if the address change type is not PORT_CHANGE.
  if (type == PORT_CHANGE) {
    QUICHE_DCHECK(previous_default_path.validated ||
                  (alternative_path_.validated &&
                   alternative_path_.send_algorithm != nullptr));
    // No need to store previous congestion controller because either the new
    // default path is validated or the alternative path is validated and
    // already has associated congestion controller.
  } else {
    previous_default_path.rtt_stats.emplace();
    previous_default_path.rtt_stats->CloneFrom(
        *sent_packet_manager_.GetRttStats());
    // If the new peer address share the same IP with the alternative path, the
    // connection should switch to the congestion controller of the alternative
    // path. Otherwise, the connection should use a brand new one.
    // In order to re-use existing code in sent_packet_manager_, reset
    // congestion controller to initial state first and then change to the one
    // on alternative path.
    // TODO(danzh) combine these two steps into one after deprecating gQUIC.
    previous_default_path.send_algorithm = OnPeerIpAddressChanged();

    if (alternative_path_.peer_address.host() ==
            current_effective_peer_address.host() &&
        alternative_path_.send_algorithm != nullptr) {
      // Update the default path with the congestion controller of the
      // alternative path.
      sent_packet_manager_.SetSendAlgorithm(
          alternative_path_.send_algorithm.release());
      sent_packet_manager_.SetRttStats(
          std::move(alternative_path_.rtt_stats).value());
    }
  }
  // Update to the new peer address.
  UpdatePeerAddress(last_received_packet_info_.source_address);
  // Update the default path.
  if (IsAlternativePath(last_received_packet_info_.destination_address,
                        current_effective_peer_address)) {
    SetDefaultPathState(std::move(alternative_path_));
  } else {
    QuicConnectionId client_connection_id;
    absl::optional<StatelessResetToken> stateless_reset_token;
    FindMatchingOrNewClientConnectionIdOrToken(
        previous_default_path, alternative_path_,
        last_received_packet_info_.destination_connection_id,
        &client_connection_id, &stateless_reset_token);
    SetDefaultPathState(
        PathState(last_received_packet_info_.destination_address,
                  current_effective_peer_address, client_connection_id,
                  last_received_packet_info_.destination_connection_id,
                  stateless_reset_token));
    // The path is considered validated if its peer IP address matches any
    // validated path's peer IP address.
    default_path_.validated =
        (alternative_path_.peer_address.host() ==
             current_effective_peer_address.host() &&
         alternative_path_.validated) ||
        (previous_default_path.validated && type == PORT_CHANGE);
  }
  if (!last_received_packet_info_.received_bytes_counted) {
    // Increment bytes counting on the new default path.
    default_path_.bytes_received_before_address_validation +=
        last_received_packet_info_.length;
    last_received_packet_info_.received_bytes_counted = true;
  }

  if (!previous_default_path.validated) {
    // If the old address is under validation, cancel and fail it. Failing to
    // validate the old path shouldn't take any effect.
    QUIC_DVLOG(1) << "Cancel validation of previous peer address change to "
                  << previous_default_path.peer_address
                  << " upon peer migration to " << default_path_.peer_address;
    path_validator_.CancelPathValidation();
    ++stats_.num_peer_migration_while_validating_default_path;
  }

  // Clear alternative path if the new default path shares the same IP as the
  // alternative path.
  if (alternative_path_.peer_address.host() ==
      default_path_.peer_address.host()) {
    alternative_path_.Clear();
  }

  if (default_path_.validated) {
    QUIC_DVLOG(1) << "Peer migrated to a validated address.";
    // No need to save previous default path, validate new peer address or
    // update bytes sent/received.
    if (!(previous_default_path.validated && type == PORT_CHANGE)) {
      // The alternative path was validated because of proactive reverse path
      // validation.
      ++stats_.num_peer_migration_to_proactively_validated_address;
    }
    OnEffectivePeerMigrationValidated(
        default_path_.server_connection_id ==
        previous_default_path.server_connection_id);
    return;
  }

  // The new default address is not validated yet. Anti-amplification limit is
  // enforced.
  QUICHE_DCHECK(EnforceAntiAmplificationLimit());
  QUIC_DVLOG(1) << "Apply anti-amplification limit to effective peer address "
                << default_path_.peer_address << " with "
                << default_path_.bytes_sent_before_address_validation
                << " bytes sent and "
                << default_path_.bytes_received_before_address_validation
                << " bytes received.";

  QUICHE_DCHECK(!alternative_path_.peer_address.IsInitialized() ||
                alternative_path_.peer_address.host() !=
                    default_path_.peer_address.host());

  // Save previous default path to the altenative path.
  if (previous_default_path.validated) {
    // The old path is a validated path which the connection might revert back
    // to later. Store it as the alternative path.
    alternative_path_ = std::move(previous_default_path);
    QUICHE_DCHECK(alternative_path_.send_algorithm != nullptr);
  }

  // If the new address is not validated and the connection is not already
  // validating that address, a new reverse path validation is needed.
  if (!path_validator_.IsValidatingPeerAddress(
          current_effective_peer_address)) {
    ++stats_.num_reverse_path_validtion_upon_migration;
    ValidatePath(std::make_unique<ReversePathValidationContext>(
                     default_path_.self_address, peer_address(),
                     default_path_.peer_address, this),
                 std::make_unique<ReversePathValidationResultDelegate>(
                     this, previous_direct_peer_address),
                 PathValidationReason::kReversePathValidation);
  } else {
    QUIC_DVLOG(1) << "Peer address " << default_path_.peer_address
                  << " is already under validation, wait for result.";
    ++stats_.num_peer_migration_to_proactively_validated_address;
  }
}

void QuicConnection::OnConnectionMigration() {
  if (debug_visitor_ != nullptr) {
    const QuicTime now = clock_->ApproximateNow();
    if (now >= stats_.handshake_completion_time) {
      debug_visitor_->OnPeerAddressChange(
          active_effective_peer_migration_type_,
          now - stats_.handshake_completion_time);
    }
  }
  visitor_->OnConnectionMigration(active_effective_peer_migration_type_);
  if (active_effective_peer_migration_type_ != PORT_CHANGE &&
      active_effective_peer_migration_type_ != IPV4_SUBNET_CHANGE &&
      !validate_client_addresses_) {
    sent_packet_manager_.OnConnectionMigration(/*reset_send_algorithm=*/false);
  }
}

bool QuicConnection::IsCurrentPacketConnectivityProbing() const {
  return is_current_packet_connectivity_probing_;
}

bool QuicConnection::ack_frame_updated() const {
  return uber_received_packet_manager_.IsAckFrameUpdated();
}

absl::string_view QuicConnection::GetCurrentPacket() {
  if (current_packet_data_ == nullptr) {
    return absl::string_view();
  }
  return absl::string_view(current_packet_data_,
                           last_received_packet_info_.length);
}

bool QuicConnection::MaybeConsiderAsMemoryCorruption(
    const QuicStreamFrame& frame) {
  if (QuicUtils::IsCryptoStreamId(transport_version(), frame.stream_id) ||
      last_received_packet_info_.decrypted_level != ENCRYPTION_INITIAL) {
    return false;
  }

  if (perspective_ == Perspective::IS_SERVER &&
      frame.data_length >= sizeof(kCHLO) &&
      strncmp(frame.data_buffer, reinterpret_cast<const char*>(&kCHLO),
              sizeof(kCHLO)) == 0) {
    return true;
  }

  if (perspective_ == Perspective::IS_CLIENT &&
      frame.data_length >= sizeof(kREJ) &&
      strncmp(frame.data_buffer, reinterpret_cast<const char*>(&kREJ),
              sizeof(kREJ)) == 0) {
    return true;
  }

  return false;
}

void QuicConnection::CheckIfApplicationLimited() {
  if (!connected_) {
    return;
  }

  bool application_limited =
      buffered_packets_.empty() && !visitor_->WillingAndAbleToWrite();

  if (!application_limited) {
    return;
  }

  sent_packet_manager_.OnApplicationLimited();
}

bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
  last_received_packet_info_.frames.push_back(type);
  if (version().HasIetfQuicFrames()) {
    if (perspective_ == Perspective::IS_CLIENT) {
      return connected_;
    }
    if (!QuicUtils::IsProbingFrame(type)) {
      MaybeStartIetfPeerMigration();
      return connected_;
    }
    QuicSocketAddress current_effective_peer_address =
        GetEffectivePeerAddressFromCurrentPacket();
    if (IsDefaultPath(last_received_packet_info_.destination_address,
                      last_received_packet_info_.source_address)) {
      return connected_;
    }
    if (type == PATH_CHALLENGE_FRAME &&
        !IsAlternativePath(last_received_packet_info_.destination_address,
                           current_effective_peer_address)) {
      QUIC_DVLOG(1)
          << "The peer is probing a new path with effective peer address "
          << current_effective_peer_address << ",  self address "
          << last_received_packet_info_.destination_address;
      if (!validate_client_addresses_) {
        QuicConnectionId client_cid;
        absl::optional<StatelessResetToken> stateless_reset_token;
        FindMatchingOrNewClientConnectionIdOrToken(
            default_path_, alternative_path_,
            last_received_packet_info_.destination_connection_id, &client_cid,
            &stateless_reset_token);
        alternative_path_ =
            PathState(last_received_packet_info_.destination_address,
                      current_effective_peer_address, client_cid,
                      last_received_packet_info_.destination_connection_id,
                      stateless_reset_token);
      } else if (!default_path_.validated) {
        // Skip reverse path validation because either handshake hasn't
        // completed or the connection is validating the default path. Using
        // PATH_CHALLENGE to validate alternative client address before
        // handshake gets comfirmed is meaningless because anyone can respond to
        // it. If the connection is validating the default path, this
        // alternative path is currently the only validated path which shouldn't
        // be overridden.
        QUIC_DVLOG(1) << "The connection hasn't finished handshake or is "
                         "validating a recent peer address change.";
        QUIC_BUG_IF(quic_bug_12714_30,
                    IsHandshakeConfirmed() && !alternative_path_.validated)
            << "No validated peer address to send after handshake comfirmed.";
      } else if (!IsReceivedPeerAddressValidated()) {
        QuicConnectionId client_connection_id;
        absl::optional<StatelessResetToken> stateless_reset_token;
        FindMatchingOrNewClientConnectionIdOrToken(
            default_path_, alternative_path_,
            last_received_packet_info_.destination_connection_id,
            &client_connection_id, &stateless_reset_token);
        // Only override alternative path state upon receiving a PATH_CHALLENGE
        // from an unvalidated peer address, and the connection isn't validating
        // a recent peer migration.
        alternative_path_ =
            PathState(last_received_packet_info_.destination_address,
                      current_effective_peer_address, client_connection_id,
                      last_received_packet_info_.destination_connection_id,
                      stateless_reset_token);
        should_proactively_validate_peer_address_on_path_challenge_ = true;
      }
    }
    MaybeUpdateBytesReceivedFromAlternativeAddress(
        last_received_packet_info_.length);
    return connected_;
  }
  // Packet content is tracked to identify connectivity probe in non-IETF
  // version, where a connectivity probe is defined as
  // - a padded PING packet with peer address change received by server,
  // - a padded PING packet on new path received by client.

  if (current_packet_content_ == NOT_PADDED_PING) {
    // We have already learned the current packet is not a connectivity
    // probing packet. Peer migration should have already been started earlier
    // if needed.
    return connected_;
  }

  if (type == PING_FRAME) {
    if (current_packet_content_ == NO_FRAMES_RECEIVED) {
      current_packet_content_ = FIRST_FRAME_IS_PING;
      return connected_;
    }
  }

  // In Google QUIC, we look for a packet with just a PING and PADDING.
  // If the condition is met, mark things as connectivity-probing, causing
  // later processing to generate the correct response.
  if (type == PADDING_FRAME && current_packet_content_ == FIRST_FRAME_IS_PING) {
    current_packet_content_ = SECOND_FRAME_IS_PADDING;
    if (perspective_ == Perspective::IS_SERVER) {
      is_current_packet_connectivity_probing_ =
          current_effective_peer_migration_type_ != NO_CHANGE;
      QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
          << ENDPOINT
          << "Detected connectivity probing packet. "
             "current_effective_peer_migration_type_:"
          << current_effective_peer_migration_type_;
    } else {
      is_current_packet_connectivity_probing_ =
          (last_received_packet_info_.source_address != peer_address()) ||
          (last_received_packet_info_.destination_address !=
           default_path_.self_address);
      QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
          << ENDPOINT
          << "Detected connectivity probing packet. "
             "last_packet_source_address:"
          << last_received_packet_info_.source_address
          << ", peer_address_:" << peer_address()
          << ", last_packet_destination_address:"
          << last_received_packet_info_.destination_address
          << ", default path self_address :" << default_path_.self_address;
    }
    return connected_;
  }

  current_packet_content_ = NOT_PADDED_PING;
  if (GetLargestReceivedPacket().IsInitialized() &&
      last_received_packet_info_.header.packet_number ==
          GetLargestReceivedPacket()) {
    UpdatePeerAddress(last_received_packet_info_.source_address);
    if (current_effective_peer_migration_type_ != NO_CHANGE) {
      // Start effective peer migration immediately when the current packet is
      // confirmed not a connectivity probing packet.
      StartEffectivePeerMigration(current_effective_peer_migration_type_);
    }
  }
  current_effective_peer_migration_type_ = NO_CHANGE;
  return connected_;
}

void QuicConnection::MaybeStartIetfPeerMigration() {
  QUICHE_DCHECK(version().HasIetfQuicFrames());
  if (current_effective_peer_migration_type_ != NO_CHANGE &&
      !IsHandshakeConfirmed()) {
    QUIC_LOG_EVERY_N_SEC(INFO, 60)
        << ENDPOINT << "Effective peer's ip:port changed from "
        << default_path_.peer_address.ToString() << " to "
        << GetEffectivePeerAddressFromCurrentPacket().ToString()
        << " before handshake confirmed, "
           "current_effective_peer_migration_type_: "
        << current_effective_peer_migration_type_;
    // Peer migrated before handshake gets confirmed.
    CloseConnection((current_effective_peer_migration_type_ == PORT_CHANGE
                         ? QUIC_PEER_PORT_CHANGE_HANDSHAKE_UNCONFIRMED
                         : QUIC_CONNECTION_MIGRATION_HANDSHAKE_UNCONFIRMED),
                    "Peer address changed before handshake is confirmed.",
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return;
  }

  if (GetLargestReceivedPacket().IsInitialized() &&
      last_received_packet_info_.header.packet_number ==
          GetLargestReceivedPacket()) {
    if (current_effective_peer_migration_type_ != NO_CHANGE) {
      // Start effective peer migration when the current packet contains a
      // non-probing frame.
      // TODO(fayang): When multiple packet number spaces is supported, only
      // start peer migration for the application data.
      if (!validate_client_addresses_) {
        UpdatePeerAddress(last_received_packet_info_.source_address);
      }
      StartEffectivePeerMigration(current_effective_peer_migration_type_);
    } else {
      UpdatePeerAddress(last_received_packet_info_.source_address);
    }
  }
  current_effective_peer_migration_type_ = NO_CHANGE;
}

void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting,
                                              bool acked_new_packet) {
  if (no_stop_waiting_frames_ && !packet_creator_.has_ack()) {
    uber_received_packet_manager_.DontWaitForPacketsBefore(
        last_received_packet_info_.decrypted_level,
        SupportsMultiplePacketNumberSpaces()
            ? sent_packet_manager_.GetLargestPacketPeerKnowsIsAcked(
                  last_received_packet_info_.decrypted_level)
            : sent_packet_manager_.largest_packet_peer_knows_is_acked());
  }
  // Always reset the retransmission alarm when an ack comes in, since we now
  // have a better estimate of the current rtt than when it was set.
  SetRetransmissionAlarm();
  if (acked_new_packet) {
    OnForwardProgressMade();
  } else if (default_enable_5rto_blackhole_detection_ &&
             !sent_packet_manager_.HasInFlightPackets() &&
             blackhole_detector_.IsDetectionInProgress()) {
    // In case no new packets get acknowledged, it is possible packets are
    // detected lost because of time based loss detection. Cancel blackhole
    // detection if there is no packets in flight.
    blackhole_detector_.StopDetection(/*permanent=*/false);
  }

  if (send_stop_waiting) {
    ++stop_waiting_count_;
  } else {
    stop_waiting_count_ = 0;
  }
}

void QuicConnection::SetSessionNotifier(
    SessionNotifierInterface* session_notifier) {
  sent_packet_manager_.SetSessionNotifier(session_notifier);
}

void QuicConnection::SetDataProducer(
    QuicStreamFrameDataProducer* data_producer) {
  framer_.set_data_producer(data_producer);
}

void QuicConnection::SetTransmissionType(TransmissionType type) {
  packet_creator_.SetTransmissionType(type);
}

void QuicConnection::UpdateReleaseTimeIntoFuture() {
  QUICHE_DCHECK(supports_release_time_);

  const QuicTime::Delta prior_max_release_time = release_time_into_future_;
  release_time_into_future_ = std::max(
      QuicTime::Delta::FromMilliseconds(kMinReleaseTimeIntoFutureMs),
      std::min(QuicTime::Delta::FromMilliseconds(
                   GetQuicFlag(quic_max_pace_time_into_future_ms)),
               sent_packet_manager_.GetRttStats()->SmoothedOrInitialRtt() *
                   GetQuicFlag(quic_pace_time_into_future_srtt_fraction)));
  QUIC_DVLOG(3) << "Updated max release time delay from "
                << prior_max_release_time << " to "
                << release_time_into_future_;
}

void QuicConnection::ResetAckStates() {
  ack_alarm_->Cancel();
  stop_waiting_count_ = 0;
  uber_received_packet_manager_.ResetAckStates(encryption_level_);
}

MessageStatus QuicConnection::SendMessage(
    QuicMessageId message_id, absl::Span<quiche::QuicheMemSlice> message,
    bool flush) {
  if (!VersionSupportsMessageFrames(transport_version())) {
    QUIC_BUG(quic_bug_10511_38)
        << "MESSAGE frame is not supported for version " << transport_version();
    return MESSAGE_STATUS_UNSUPPORTED;
  }
  if (MemSliceSpanTotalSize(message) > GetCurrentLargestMessagePayload()) {
    return MESSAGE_STATUS_TOO_LARGE;
  }
  if (!connected_ || (!flush && !CanWrite(HAS_RETRANSMITTABLE_DATA))) {
    return MESSAGE_STATUS_BLOCKED;
  }
  ScopedPacketFlusher flusher(this);
  return packet_creator_.AddMessageFrame(message_id, message);
}

QuicPacketLength QuicConnection::GetCurrentLargestMessagePayload() const {
  return packet_creator_.GetCurrentLargestMessagePayload();
}

QuicPacketLength QuicConnection::GetGuaranteedLargestMessagePayload() const {
  return packet_creator_.GetGuaranteedLargestMessagePayload();
}

uint32_t QuicConnection::cipher_id() const {
  if (version().KnowsWhichDecrypterToUse()) {
    return framer_.GetDecrypter(last_received_packet_info_.decrypted_level)
        ->cipher_id();
  }
  return framer_.decrypter()->cipher_id();
}

EncryptionLevel QuicConnection::GetConnectionCloseEncryptionLevel() const {
  if (perspective_ == Perspective::IS_CLIENT) {
    return encryption_level_;
  }
  if (IsHandshakeComplete()) {
    // A forward secure packet has been received.
    QUIC_BUG_IF(quic_bug_12714_31,
                encryption_level_ != ENCRYPTION_FORWARD_SECURE)
        << ENDPOINT << "Unexpected connection close encryption level "
        << encryption_level_;
    return ENCRYPTION_FORWARD_SECURE;
  }
  if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_ZERO_RTT)) {
    if (encryption_level_ != ENCRYPTION_ZERO_RTT) {
      if (version().HasIetfInvariantHeader()) {
        QUIC_CODE_COUNT(quic_wrong_encryption_level_connection_close_ietf);
      } else {
        QUIC_CODE_COUNT(quic_wrong_encryption_level_connection_close);
      }
    }
    return ENCRYPTION_ZERO_RTT;
  }
  return ENCRYPTION_INITIAL;
}

void QuicConnection::MaybeBundleCryptoDataWithAcks() {
  QUICHE_DCHECK(SupportsMultiplePacketNumberSpaces());
  if (IsHandshakeConfirmed()) {
    return;
  }
  PacketNumberSpace space = HANDSHAKE_DATA;
  if (perspective() == Perspective::IS_SERVER &&
      framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL)) {
    // On the server side, sends INITIAL data with INITIAL ACK if initial key is
    // available.
    space = INITIAL_DATA;
  }
  const QuicTime ack_timeout =
      uber_received_packet_manager_.GetAckTimeout(space);
  if (!ack_timeout.IsInitialized() ||
      (ack_timeout > clock_->ApproximateNow() &&
       ack_timeout > uber_received_packet_manager_.GetEarliestAckTimeout())) {
    // No pending ACK of space.
    return;
  }
  if (coalesced_packet_.length() > 0) {
    // Do not bundle CRYPTO data if the ACK could be coalesced with other
    // packets.
    return;
  }

  if (!framer_.HasAnEncrypterForSpace(space)) {
    QUIC_BUG(quic_bug_10511_39)
        << ENDPOINT
        << "Try to bundle crypto with ACK with missing key of space "
        << PacketNumberSpaceToString(space);
    return;
  }

  sent_packet_manager_.RetransmitDataOfSpaceIfAny(space);
}

void QuicConnection::SendAllPendingAcks() {
  QUICHE_DCHECK(SupportsMultiplePacketNumberSpaces());
  QUIC_DVLOG(1) << ENDPOINT << "Trying to send all pending ACKs";
  ack_alarm_->Cancel();
  QuicTime earliest_ack_timeout =
      uber_received_packet_manager_.GetEarliestAckTimeout();
  QUIC_BUG_IF(quic_bug_12714_32, !earliest_ack_timeout.IsInitialized());
  MaybeBundleCryptoDataWithAcks();
  earliest_ack_timeout = uber_received_packet_manager_.GetEarliestAckTimeout();
  if (!earliest_ack_timeout.IsInitialized()) {
    return;
  }
  for (int8_t i = INITIAL_DATA; i <= APPLICATION_DATA; ++i) {
    const QuicTime ack_timeout = uber_received_packet_manager_.GetAckTimeout(
        static_cast<PacketNumberSpace>(i));
    if (!ack_timeout.IsInitialized()) {
      continue;
    }
    if (!framer_.HasAnEncrypterForSpace(static_cast<PacketNumberSpace>(i))) {
      // The key has been dropped.
      continue;
    }
    if (ack_timeout > clock_->ApproximateNow() &&
        ack_timeout > earliest_ack_timeout) {
      // Always send the earliest ACK to make forward progress in case alarm
      // fires early.
      continue;
    }
    QUIC_DVLOG(1) << ENDPOINT << "Sending ACK of packet number space "
                  << PacketNumberSpaceToString(
                         static_cast<PacketNumberSpace>(i));
    ScopedEncryptionLevelContext context(
        this, QuicUtils::GetEncryptionLevelToSendAckofSpace(
                  static_cast<PacketNumberSpace>(i)));
    QuicFrames frames;
    frames.push_back(uber_received_packet_manager_.GetUpdatedAckFrame(
        static_cast<PacketNumberSpace>(i), clock_->ApproximateNow()));
    const bool flushed = packet_creator_.FlushAckFrame(frames);
    if (!flushed) {
      // Connection is write blocked.
      QUIC_BUG_IF(quic_bug_12714_33,
                  !writer_->IsWriteBlocked() &&
                      !LimitedByAmplificationFactor(
                          packet_creator_.max_packet_length()))
          << "Writer not blocked and not throttled by amplification factor, "
             "but ACK not flushed for packet space:"
          << PacketNumberSpaceToString(static_cast<PacketNumberSpace>(i))
          << ", connected: " << connected_
          << ", fill_coalesced_packet: " << fill_coalesced_packet_
          << ", has_soft_max_packet_length: "
          << packet_creator_.HasSoftMaxPacketLength()
          << ", max_packet_length: " << packet_creator_.max_packet_length()
          << ", pending frames: " << packet_creator_.GetPendingFramesInfo();
      break;
    }
    ResetAckStates();
  }

  const QuicTime timeout =
      uber_received_packet_manager_.GetEarliestAckTimeout();
  if (timeout.IsInitialized()) {
    // If there are ACKs pending, re-arm ack alarm.
    ack_alarm_->Update(timeout, kAlarmGranularity);
  }
  // Only try to bundle retransmittable data with ACK frame if default
  // encryption level is forward secure.
  if (encryption_level_ != ENCRYPTION_FORWARD_SECURE ||
      !ShouldBundleRetransmittableFrameWithAck()) {
    return;
  }
  consecutive_num_packets_with_no_retransmittable_frames_ = 0;
  if (packet_creator_.HasPendingRetransmittableFrames() ||
      visitor_->WillingAndAbleToWrite()) {
    // There are pending retransmittable frames.
    return;
  }

  visitor_->OnAckNeedsRetransmittableFrame();
}

bool QuicConnection::ShouldBundleRetransmittableFrameWithAck() const {
  if (consecutive_num_packets_with_no_retransmittable_frames_ >=
      max_consecutive_num_packets_with_no_retransmittable_frames_) {
    return true;
  }
  if (bundle_retransmittable_with_pto_ack_ &&
      sent_packet_manager_.GetConsecutivePtoCount() > 0) {
    // Bundle a retransmittable frame with an ACK if PTO has fired in order to
    // recover more quickly in cases of temporary network outage.
    return true;
  }
  return false;
}

void QuicConnection::MaybeCoalescePacketOfHigherSpace() {
  if (!connected() || !packet_creator_.HasSoftMaxPacketLength()) {
    return;
  }
  if (fill_coalesced_packet_) {
    // Make sure MaybeCoalescePacketOfHigherSpace is not re-entrant.
    QUIC_BUG(quic_coalesce_packet_reentrant);
    return;
  }
  for (EncryptionLevel retransmission_level :
       {ENCRYPTION_INITIAL, ENCRYPTION_HANDSHAKE}) {
    // Coalesce HANDSHAKE with INITIAL retransmission, and coalesce 1-RTT with
    // HANDSHAKE retransmission.
    const EncryptionLevel coalesced_level =
        retransmission_level == ENCRYPTION_INITIAL ? ENCRYPTION_HANDSHAKE
                                                   : ENCRYPTION_FORWARD_SECURE;
    if (coalesced_packet_.ContainsPacketOfEncryptionLevel(
            retransmission_level) &&
        coalesced_packet_.TransmissionTypeOfPacket(retransmission_level) !=
            NOT_RETRANSMISSION &&
        framer_.HasEncrypterOfEncryptionLevel(coalesced_level) &&
        !coalesced_packet_.ContainsPacketOfEncryptionLevel(coalesced_level)) {
      QUIC_DVLOG(1) << ENDPOINT
                    << "Trying to coalesce packet of encryption level: "
                    << EncryptionLevelToString(coalesced_level);
      fill_coalesced_packet_ = true;
      sent_packet_manager_.RetransmitDataOfSpaceIfAny(
          QuicUtils::GetPacketNumberSpace(coalesced_level));
      fill_coalesced_packet_ = false;
    }
  }
}

bool QuicConnection::FlushCoalescedPacket() {
  ScopedCoalescedPacketClearer clearer(&coalesced_packet_);
  if (!connected_) {
    return false;
  }
  if (!version().CanSendCoalescedPackets()) {
    QUIC_BUG_IF(quic_bug_12714_34, coalesced_packet_.length() > 0);
    return true;
  }
  if (coalesced_packet_.ContainsPacketOfEncryptionLevel(ENCRYPTION_INITIAL) &&
      !framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL)) {
    // Initial packet will be re-serialized. Neuter it in case initial key has
    // been dropped.
    QUIC_BUG(quic_bug_10511_40)
        << ENDPOINT
        << "Coalescer contains initial packet while initial key has "
           "been dropped.";
    coalesced_packet_.NeuterInitialPacket();
  }
  if (coalesced_packet_.length() == 0) {
    return true;
  }

  char buffer[kMaxOutgoingPacketSize];
  const size_t length = packet_creator_.SerializeCoalescedPacket(
      coalesced_packet_, buffer, coalesced_packet_.max_packet_length());
  if (length == 0) {
    if (connected_) {
      CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET,
                      "Failed to serialize coalesced packet.",
                      ConnectionCloseBehavior::SILENT_CLOSE);
    }
    return false;
  }
  if (debug_visitor_ != nullptr) {
    debug_visitor_->OnCoalescedPacketSent(coalesced_packet_, length);
  }
  QUIC_DVLOG(1) << ENDPOINT << "Sending coalesced packet "
                << coalesced_packet_.ToString(length);
  const size_t padding_size =
      length - std::min<size_t>(length, coalesced_packet_.length());
  // Buffer coalesced packet if padding + bytes_sent exceeds amplifcation limit.
  if (!buffered_packets_.empty() || HandleWriteBlocked() ||
      (enforce_strict_amplification_factor_ &&
       LimitedByAmplificationFactor(padding_size))) {
    QUIC_DVLOG(1) << ENDPOINT
                  << "Buffering coalesced packet of len: " << length;
    buffered_packets_.emplace_back(
        buffer, static_cast<QuicPacketLength>(length),
        coalesced_packet_.self_address(), coalesced_packet_.peer_address());
  } else {
    WriteResult result = writer_->WritePacket(
        buffer, length, coalesced_packet_.self_address().host(),
        coalesced_packet_.peer_address(), per_packet_options_);
    if (IsWriteError(result.status)) {
      OnWriteError(result.error_code);
      return false;
    }
    if (IsWriteBlockedStatus(result.status)) {
      visitor_->OnWriteBlocked();
      if (result.status != WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
        QUIC_DVLOG(1) << ENDPOINT
                      << "Buffering coalesced packet of len: " << length;
        buffered_packets_.emplace_back(
            buffer, static_cast<QuicPacketLength>(length),
            coalesced_packet_.self_address(), coalesced_packet_.peer_address());
      }
    }
  }
  if (accelerated_server_preferred_address_ &&
      stats_.num_duplicated_packets_sent_to_server_preferred_address <
          kMaxDuplicatedPacketsSentToServerPreferredAddress) {
    // Send coalesced packets to both addresses while the server preferred
    // address validation is pending.
    QUICHE_DCHECK(received_server_preferred_address_.IsInitialized());
    path_validator_.MaybeWritePacketToAddress(
        buffer, length, received_server_preferred_address_);
    ++stats_.num_duplicated_packets_sent_to_server_preferred_address;
  }
  // Account for added padding.
  if (length > coalesced_packet_.length()) {
    if (IsDefaultPath(coalesced_packet_.self_address(),
                      coalesced_packet_.peer_address())) {
      if (EnforceAntiAmplificationLimit()) {
        // Include bytes sent even if they are not in flight.
        default_path_.bytes_sent_before_address_validation += padding_size;
      }
    } else {
      MaybeUpdateBytesSentToAlternativeAddress(coalesced_packet_.peer_address(),
                                               padding_size);
    }
    stats_.bytes_sent += padding_size;
    if (coalesced_packet_.initial_packet() != nullptr &&
        coalesced_packet_.initial_packet()->transmission_type !=
            NOT_RETRANSMISSION) {
      stats_.bytes_retransmitted += padding_size;
    }
  }
  return true;
}

void QuicConnection::MaybeEnableMultiplePacketNumberSpacesSupport() {
  if (version().handshake_protocol != PROTOCOL_TLS1_3) {
    return;
  }
  QUIC_DVLOG(1) << ENDPOINT << "connection " << connection_id()
                << " supports multiple packet number spaces";
  framer_.EnableMultiplePacketNumberSpacesSupport();
  sent_packet_manager_.EnableMultiplePacketNumberSpacesSupport();
  uber_received_packet_manager_.EnableMultiplePacketNumberSpacesSupport(
      perspective_);
}

bool QuicConnection::SupportsMultiplePacketNumberSpaces() const {
  return sent_packet_manager_.supports_multiple_packet_number_spaces();
}

void QuicConnection::SetLargestReceivedPacketWithAck(
    QuicPacketNumber new_value) {
  if (SupportsMultiplePacketNumberSpaces()) {
    largest_seen_packets_with_ack_[QuicUtils::GetPacketNumberSpace(
        last_received_packet_info_.decrypted_level)] = new_value;
  } else {
    largest_seen_packet_with_ack_ = new_value;
  }
}

void QuicConnection::OnForwardProgressMade() {
  if (!connected_) {
    return;
  }
  if (is_path_degrading_) {
    visitor_->OnForwardProgressMadeAfterPathDegrading();
    is_path_degrading_ = false;
  }
  if (sent_packet_manager_.HasInFlightPackets()) {
    // Restart detections if forward progress has been made.
    blackhole_detector_.RestartDetection(GetPathDegradingDeadline(),
                                         GetNetworkBlackholeDeadline(),
                                         GetPathMtuReductionDeadline());
  } else {
    // Stop detections in quiecense.
    blackhole_detector_.StopDetection(/*permanent=*/false);
  }
  QUIC_BUG_IF(quic_bug_12714_35,
              perspective_ == Perspective::IS_SERVER &&
                  default_enable_5rto_blackhole_detection_ &&
                  blackhole_detector_.IsDetectionInProgress() &&
                  !sent_packet_manager_.HasInFlightPackets())
      << ENDPOINT
      << "Trying to start blackhole detection without no bytes in flight";
}

QuicPacketNumber QuicConnection::GetLargestReceivedPacketWithAck() const {
  if (SupportsMultiplePacketNumberSpaces()) {
    return largest_seen_packets_with_ack_[QuicUtils::GetPacketNumberSpace(
        last_received_packet_info_.decrypted_level)];
  }
  return largest_seen_packet_with_ack_;
}

QuicPacketNumber QuicConnection::GetLargestAckedPacket() const {
  if (SupportsMultiplePacketNumberSpaces()) {
    return sent_packet_manager_.GetLargestAckedPacket(
        last_received_packet_info_.decrypted_level);
  }
  return sent_packet_manager_.GetLargestObserved();
}

QuicPacketNumber QuicConnection::GetLargestReceivedPacket() const {
  return uber_received_packet_manager_.GetLargestObserved(
      last_received_packet_info_.decrypted_level);
}

bool QuicConnection::EnforceAntiAmplificationLimit() const {
  return version().SupportsAntiAmplificationLimit() &&
         perspective_ == Perspective::IS_SERVER && !default_path_.validated;
}

// TODO(danzh) Pass in path object or its reference of some sort to use this
// method to check anti-amplification limit on non-default path.
bool QuicConnection::LimitedByAmplificationFactor(QuicByteCount bytes) const {
  return EnforceAntiAmplificationLimit() &&
         (default_path_.bytes_sent_before_address_validation +
          (enforce_strict_amplification_factor_ ? bytes : 0)) >=
             anti_amplification_factor_ *
                 default_path_.bytes_received_before_address_validation;
}

SerializedPacketFate QuicConnection::GetSerializedPacketFate(
    bool is_mtu_discovery, EncryptionLevel encryption_level) {
  if (ShouldDiscardPacket(encryption_level)) {
    return DISCARD;
  }
  if (version().CanSendCoalescedPackets() && !coalescing_done_ &&
      !is_mtu_discovery) {
    if (!IsHandshakeConfirmed()) {
      // Before receiving ACK for any 1-RTT packets, always try to coalesce
      // packet (except MTU discovery packet).
      return COALESCE;
    }
    if (coalesced_packet_.length() > 0) {
      // If the coalescer is not empty, let this packet go through coalescer
      // to avoid potential out of order sending.
      return COALESCE;
    }
  }
  if (!buffered_packets_.empty() || HandleWriteBlocked()) {
    return BUFFER;
  }
  return SEND_TO_WRITER;
}

bool QuicConnection::IsHandshakeComplete() const {
  return visitor_->GetHandshakeState() >= HANDSHAKE_COMPLETE;
}

bool QuicConnection::IsHandshakeConfirmed() const {
  QUICHE_DCHECK_EQ(PROTOCOL_TLS1_3, version().handshake_protocol);
  return visitor_->GetHandshakeState() == HANDSHAKE_CONFIRMED;
}

size_t QuicConnection::min_received_before_ack_decimation() const {
  return uber_received_packet_manager_.min_received_before_ack_decimation();
}

void QuicConnection::set_min_received_before_ack_decimation(size_t new_value) {
  uber_received_packet_manager_.set_min_received_before_ack_decimation(
      new_value);
}

const QuicAckFrame& QuicConnection::ack_frame() const {
  if (SupportsMultiplePacketNumberSpaces()) {
    return uber_received_packet_manager_.GetAckFrame(
        QuicUtils::GetPacketNumberSpace(
            last_received_packet_info_.decrypted_level));
  }
  return uber_received_packet_manager_.ack_frame();
}

void QuicConnection::set_client_connection_id(
    QuicConnectionId client_connection_id) {
  if (!version().SupportsClientConnectionIds()) {
    QUIC_BUG_IF(quic_bug_12714_36, !client_connection_id.IsEmpty())
        << ENDPOINT << "Attempted to use client connection ID "
        << client_connection_id << " with unsupported version " << version();
    return;
  }
  default_path_.client_connection_id = client_connection_id;

  client_connection_id_is_set_ = true;
  if (version().HasIetfQuicFrames() && !client_connection_id.IsEmpty()) {
    if (perspective_ == Perspective::IS_SERVER) {
      QUICHE_DCHECK(peer_issued_cid_manager_ == nullptr);
      peer_issued_cid_manager_ =
          std::make_unique<QuicPeerIssuedConnectionIdManager>(
              kMinNumOfActiveConnectionIds, client_connection_id, clock_,
              alarm_factory_, this, context());
    } else {
      // Note in Chromium client, set_client_connection_id is not called and
      // thus self_issued_cid_manager_ should be null.
      self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
    }
  }
  QUIC_DLOG(INFO) << ENDPOINT << "setting client connection ID to "
                  << default_path_.client_connection_id
                  << " for connection with server connection ID "
                  << default_path_.server_connection_id;
  packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
  framer_.SetExpectedClientConnectionIdLength(
      default_path_.client_connection_id.length());
}

void QuicConnection::OnPathDegradingDetected() {
  is_path_degrading_ = true;
  visitor_->OnPathDegrading();
  if (multi_port_stats_) {
    multi_port_stats_->num_path_degrading++;
    MaybeMigrateToMultiPortPath();
  }
}

void QuicConnection::MaybeMigrateToMultiPortPath() {
  if (!alternative_path_.validated) {
    QUIC_CLIENT_HISTOGRAM_ENUM(
        "QuicConnection.MultiPortPathStatusWhenMigrating",
        MultiPortStatusOnMigration::kNotValidated,
        MultiPortStatusOnMigration::kMaxValue,
        "Status of the multi port path upon migration");
    return;
  }
  std::unique_ptr<QuicPathValidationContext> context;
  const bool has_pending_validation =
      path_validator_.HasPendingPathValidation();
  if (!has_pending_validation) {
    // The multi-port path should have just finished the recent probe and
    // waiting for the next one.
    context = std::move(multi_port_path_context_);
    multi_port_probing_alarm_->Cancel();
    QUIC_CLIENT_HISTOGRAM_ENUM(
        "QuicConnection.MultiPortPathStatusWhenMigrating",
        MultiPortStatusOnMigration::kWaitingForRefreshValidation,
        MultiPortStatusOnMigration::kMaxValue,
        "Status of the multi port path upon migration");
  } else {
    // The multi-port path is currently under probing.
    context = path_validator_.ReleaseContext();
    QUIC_CLIENT_HISTOGRAM_ENUM(
        "QuicConnection.MultiPortPathStatusWhenMigrating",
        MultiPortStatusOnMigration::kPendingRefreshValidation,
        MultiPortStatusOnMigration::kMaxValue,
        "Status of the multi port path upon migration");
  }
  if (context == nullptr) {
    QUICHE_BUG(quic_bug_12714_90) << "No multi-port context to migrate to";
    return;
  }
  visitor_->MigrateToMultiPortPath(std::move(context));
}

void QuicConnection::OnBlackholeDetected() {
  if (default_enable_5rto_blackhole_detection_ &&
      !sent_packet_manager_.HasInFlightPackets()) {
    QUIC_BUG(quic_bug_10511_41)
        << ENDPOINT
        << "Blackhole detected, but there is no bytes in flight, version: "
        << version();
    // Do not close connection if there is no bytes in flight.
    return;
  }
  CloseConnection(QUIC_TOO_MANY_RTOS, "Network blackhole detected",
                  ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}

void QuicConnection::OnPathMtuReductionDetected() {
  MaybeRevertToPreviousMtu();
}

void QuicConnection::OnHandshakeTimeout() {
  const QuicTime::Delta duration =
      clock_->ApproximateNow() - stats_.connection_creation_time;
  std::string error_details = absl::StrCat(
      "Handshake timeout expired after ", duration.ToDebuggingValue(),
      ". Timeout:",
      idle_network_detector_.handshake_timeout().ToDebuggingValue());
  if (perspective() == Perspective::IS_CLIENT && version().UsesTls()) {
    absl::StrAppend(&error_details, UndecryptablePacketsInfo());
  }
  QUIC_DVLOG(1) << ENDPOINT << error_details;
  CloseConnection(QUIC_HANDSHAKE_TIMEOUT, error_details,
                  ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}

void QuicConnection::OnIdleNetworkDetected() {
  const QuicTime::Delta duration =
      clock_->ApproximateNow() -
      idle_network_detector_.last_network_activity_time();
  std::string error_details = absl::StrCat(
      "No recent network activity after ", duration.ToDebuggingValue(),
      ". Timeout:",
      idle_network_detector_.idle_network_timeout().ToDebuggingValue());
  if (perspective() == Perspective::IS_CLIENT && version().UsesTls() &&
      !IsHandshakeComplete()) {
    absl::StrAppend(&error_details, UndecryptablePacketsInfo());
  }
  QUIC_DVLOG(1) << ENDPOINT << error_details;
  const bool has_consecutive_pto =
      sent_packet_manager_.GetConsecutivePtoCount() > 0;
  if (has_consecutive_pto || visitor_->ShouldKeepConnectionAlive()) {
    if (GetQuicReloadableFlag(quic_add_stream_info_to_idle_close_detail) &&
        !has_consecutive_pto) {
      // Include stream information in error detail if there are open streams.
      QUIC_RELOADABLE_FLAG_COUNT(quic_add_stream_info_to_idle_close_detail);
      absl::StrAppend(&error_details, ", ",
                      visitor_->GetStreamsInfoForLogging());
    }
    CloseConnection(QUIC_NETWORK_IDLE_TIMEOUT, error_details,
                    ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
    return;
  }
  QuicErrorCode error_code = QUIC_NETWORK_IDLE_TIMEOUT;
  if (idle_timeout_connection_close_behavior_ ==
      ConnectionCloseBehavior::
          SILENT_CLOSE_WITH_CONNECTION_CLOSE_PACKET_SERIALIZED) {
    error_code = QUIC_SILENT_IDLE_TIMEOUT;
  }
  CloseConnection(error_code, error_details,
                  idle_timeout_connection_close_behavior_);
}

void QuicConnection::OnBandwidthUpdateTimeout() {
  visitor_->OnBandwidthUpdateTimeout();
}

void QuicConnection::OnKeepAliveTimeout() {
  if (retransmission_alarm_->IsSet() ||
      !visitor_->ShouldKeepConnectionAlive()) {
    return;
  }
  SendPingAtLevel(framer().GetEncryptionLevelToSendApplicationData());
}

void QuicConnection::OnRetransmittableOnWireTimeout() {
  if (retransmission_alarm_->IsSet() ||
      !visitor_->ShouldKeepConnectionAlive()) {
    return;
  }
  bool packet_buffered = false;
  switch (retransmittable_on_wire_behavior_) {
    case DEFAULT:
      break;
    case SEND_FIRST_FORWARD_SECURE_PACKET:
      if (first_serialized_one_rtt_packet_ != nullptr) {
        buffered_packets_.emplace_back(
            first_serialized_one_rtt_packet_->data.get(),
            first_serialized_one_rtt_packet_->length, self_address(),
            peer_address());
        packet_buffered = true;
      }
      break;
    case SEND_RANDOM_BYTES:
      const QuicPacketLength random_bytes_length = std::max<QuicPacketLength>(
          QuicFramer::GetMinStatelessResetPacketLength() + 1,
          random_generator_->RandUint64() %
              packet_creator_.max_packet_length());
      buffered_packets_.emplace_back(*random_generator_, random_bytes_length,
                                     self_address(), peer_address());
      packet_buffered = true;
      break;
  }
  if (packet_buffered) {
    if (!writer_->IsWriteBlocked()) {
      WriteQueuedPackets();
    }
    if (connected_) {
      // Always reset PING alarm with has_in_flight_packets=true. This is used
      // to avoid re-arming the alarm in retransmittable-on-wire mode.
      ping_manager_.SetAlarm(clock_->ApproximateNow(),
                             visitor_->ShouldKeepConnectionAlive(),
                             /*has_in_flight_packets=*/true);
    }
    return;
  }
  SendPingAtLevel(framer().GetEncryptionLevelToSendApplicationData());
}

void QuicConnection::OnPeerIssuedConnectionIdRetired() {
  QUICHE_DCHECK(peer_issued_cid_manager_ != nullptr);
  QuicConnectionId* default_path_cid =
      perspective_ == Perspective::IS_CLIENT
          ? &default_path_.server_connection_id
          : &default_path_.client_connection_id;
  QuicConnectionId* alternative_path_cid =
      perspective_ == Perspective::IS_CLIENT
          ? &alternative_path_.server_connection_id
          : &alternative_path_.client_connection_id;
  bool default_path_and_alternative_path_use_the_same_peer_connection_id =
      *default_path_cid == *alternative_path_cid;
  if (!default_path_cid->IsEmpty() &&
      !peer_issued_cid_manager_->IsConnectionIdActive(*default_path_cid)) {
    *default_path_cid = QuicConnectionId();
  }
  // TODO(haoyuewang) Handle the change for default_path_ & alternatvie_path_
  // via the same helper function.
  if (default_path_cid->IsEmpty()) {
    // Try setting a new connection ID now such that subsequent
    // RetireConnectionId frames can be sent on the default path.
    const QuicConnectionIdData* unused_connection_id_data =
        peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
    if (unused_connection_id_data != nullptr) {
      *default_path_cid = unused_connection_id_data->connection_id;
      default_path_.stateless_reset_token =
          unused_connection_id_data->stateless_reset_token;
      if (perspective_ == Perspective::IS_CLIENT) {
        packet_creator_.SetServerConnectionId(
            unused_connection_id_data->connection_id);
      } else {
        packet_creator_.SetClientConnectionId(
            unused_connection_id_data->connection_id);
      }
    }
  }
  if (default_path_and_alternative_path_use_the_same_peer_connection_id) {
    *alternative_path_cid = *default_path_cid;
    alternative_path_.stateless_reset_token =
        default_path_.stateless_reset_token;
  } else if (!alternative_path_cid->IsEmpty() &&
             !peer_issued_cid_manager_->IsConnectionIdActive(
                 *alternative_path_cid)) {
    *alternative_path_cid = EmptyQuicConnectionId();
    const QuicConnectionIdData* unused_connection_id_data =
        peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
    if (unused_connection_id_data != nullptr) {
      *alternative_path_cid = unused_connection_id_data->connection_id;
      alternative_path_.stateless_reset_token =
          unused_connection_id_data->stateless_reset_token;
    }
  }

  std::vector<uint64_t> retired_cid_sequence_numbers =
      peer_issued_cid_manager_->ConsumeToBeRetiredConnectionIdSequenceNumbers();
  QUICHE_DCHECK(!retired_cid_sequence_numbers.empty());
  for (const auto& sequence_number : retired_cid_sequence_numbers) {
    ++stats_.num_retire_connection_id_sent;
    visitor_->SendRetireConnectionId(sequence_number);
  }
}

bool QuicConnection::SendNewConnectionId(
    const QuicNewConnectionIdFrame& frame) {
  visitor_->SendNewConnectionId(frame);
  ++stats_.num_new_connection_id_sent;
  return connected_;
}

bool QuicConnection::MaybeReserveConnectionId(
    const QuicConnectionId& connection_id) {
  if (perspective_ == Perspective::IS_SERVER) {
    return visitor_->MaybeReserveConnectionId(connection_id);
  }
  return true;
}

void QuicConnection::OnSelfIssuedConnectionIdRetired(
    const QuicConnectionId& connection_id) {
  if (perspective_ == Perspective::IS_SERVER) {
    visitor_->OnServerConnectionIdRetired(connection_id);
  }
}

void QuicConnection::MaybeUpdateAckTimeout() {
  if (should_last_packet_instigate_acks_) {
    return;
  }
  should_last_packet_instigate_acks_ = true;
  uber_received_packet_manager_.MaybeUpdateAckTimeout(
      /*should_last_packet_instigate_acks=*/true,
      last_received_packet_info_.decrypted_level,
      last_received_packet_info_.header.packet_number,
      last_received_packet_info_.receipt_time, clock_->ApproximateNow(),
      sent_packet_manager_.GetRttStats());
}

QuicTime QuicConnection::GetPathDegradingDeadline() const {
  if (!ShouldDetectPathDegrading()) {
    return QuicTime::Zero();
  }
  return clock_->ApproximateNow() +
         sent_packet_manager_.GetPathDegradingDelay();
}

bool QuicConnection::ShouldDetectPathDegrading() const {
  if (!connected_) {
    return false;
  }
  if (GetQuicReloadableFlag(
          quic_no_path_degrading_before_handshake_confirmed) &&
      SupportsMultiplePacketNumberSpaces()) {
    QUIC_RELOADABLE_FLAG_COUNT_N(
        quic_no_path_degrading_before_handshake_confirmed, 1, 2);
    // No path degrading detection before handshake confirmed.
    return perspective_ == Perspective::IS_CLIENT && IsHandshakeConfirmed() &&
           !is_path_degrading_;
  }
  // No path degrading detection before handshake completes.
  if (!idle_network_detector_.handshake_timeout().IsInfinite()) {
    return false;
  }
  return perspective_ == Perspective::IS_CLIENT && !is_path_degrading_;
}

QuicTime QuicConnection::GetNetworkBlackholeDeadline() const {
  if (!ShouldDetectBlackhole()) {
    return QuicTime::Zero();
  }
  QUICHE_DCHECK_LT(0u, num_rtos_for_blackhole_detection_);

  const QuicTime::Delta blackhole_delay =
      sent_packet_manager_.GetNetworkBlackholeDelay(
          num_rtos_for_blackhole_detection_);
  if (!ShouldDetectPathDegrading()) {
    return clock_->ApproximateNow() + blackhole_delay;
  }
  return clock_->ApproximateNow() +
         CalculateNetworkBlackholeDelay(
             blackhole_delay, sent_packet_manager_.GetPathDegradingDelay(),
             sent_packet_manager_.GetPtoDelay());
}

// static
QuicTime::Delta QuicConnection::CalculateNetworkBlackholeDelay(
    QuicTime::Delta blackhole_delay, QuicTime::Delta path_degrading_delay,
    QuicTime::Delta pto_delay) {
  const QuicTime::Delta min_delay = path_degrading_delay + pto_delay * 2;
  if (blackhole_delay < min_delay) {
    QUIC_CODE_COUNT(quic_extending_short_blackhole_delay);
  }
  return std::max(min_delay, blackhole_delay);
}

void QuicConnection::AddKnownServerAddress(const QuicSocketAddress& address) {
  QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
  if (!address.IsInitialized() || IsKnownServerAddress(address)) {
    return;
  }
  known_server_addresses_.push_back(address);
}

absl::optional<QuicNewConnectionIdFrame>
QuicConnection::MaybeIssueNewConnectionIdForPreferredAddress() {
  if (self_issued_cid_manager_ == nullptr) {
    return absl::nullopt;
  }
  return self_issued_cid_manager_
      ->MaybeIssueNewConnectionIdForPreferredAddress();
}

bool QuicConnection::ShouldDetectBlackhole() const {
  if (!connected_ || blackhole_detection_disabled_) {
    return false;
  }
  if (GetQuicReloadableFlag(
          quic_no_path_degrading_before_handshake_confirmed) &&
      SupportsMultiplePacketNumberSpaces() && !IsHandshakeConfirmed()) {
    QUIC_RELOADABLE_FLAG_COUNT_N(
        quic_no_path_degrading_before_handshake_confirmed, 2, 2);
    return false;
  }
  // No blackhole detection before handshake completes.
  if (default_enable_5rto_blackhole_detection_) {
    QUIC_RELOADABLE_FLAG_COUNT_N(quic_default_enable_5rto_blackhole_detection2,
                                 3, 3);
    return IsHandshakeComplete();
  }

  if (!idle_network_detector_.handshake_timeout().IsInfinite()) {
    return false;
  }
  return num_rtos_for_blackhole_detection_ > 0;
}

QuicTime QuicConnection::GetRetransmissionDeadline() const {
  if (perspective_ == Perspective::IS_CLIENT &&
      SupportsMultiplePacketNumberSpaces() && !IsHandshakeConfirmed() &&
      stats_.pto_count == 0 &&
      !framer_.HasDecrypterOfEncryptionLevel(ENCRYPTION_HANDSHAKE) &&
      !undecryptable_packets_.empty()) {
    // Retransmits ClientHello quickly when a Handshake or 1-RTT packet is
    // received prior to having Handshake keys. Adding kAlarmGranulary will
    // avoid spurious retransmissions in the case of small-scale reordering.
    return clock_->ApproximateNow() + kAlarmGranularity;
  }
  return sent_packet_manager_.GetRetransmissionTime();
}

bool QuicConnection::SendPathChallenge(
    const QuicPathFrameBuffer& data_buffer,
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address,
    const QuicSocketAddress& effective_peer_address, QuicPacketWriter* writer) {
  if (!framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_FORWARD_SECURE)) {
    return connected_;
  }
  if (connection_migration_use_new_cid_) {
    QuicConnectionId client_cid, server_cid;
    FindOnPathConnectionIds(self_address, effective_peer_address, &client_cid,
                            &server_cid);
    if (writer == writer_) {
      ScopedPacketFlusher flusher(this);
      {
        QuicPacketCreator::ScopedPeerAddressContext context(
            &packet_creator_, peer_address, client_cid, server_cid,
            connection_migration_use_new_cid_);
        // It's using the default writer, add the PATH_CHALLENGE the same way as
        // other frames. This may cause connection to be closed.
        packet_creator_.AddPathChallengeFrame(data_buffer);
      }
    } else {
      // Switch to the right CID and source/peer addresses.
      QuicPacketCreator::ScopedPeerAddressContext context(
          &packet_creator_, peer_address, client_cid, server_cid,
          connection_migration_use_new_cid_);
      std::unique_ptr<SerializedPacket> probing_packet =
          packet_creator_.SerializePathChallengeConnectivityProbingPacket(
              data_buffer);
      QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet),
                       NO_RETRANSMITTABLE_DATA);
      QUICHE_DCHECK_EQ(self_address, alternative_path_.self_address);
      WritePacketUsingWriter(std::move(probing_packet), writer, self_address,
                             peer_address, /*measure_rtt=*/false);
    }
    return connected_;
  }
  if (writer == writer_) {
    ScopedPacketFlusher flusher(this);
    {
      // It's on current path, add the PATH_CHALLENGE the same way as other
      // frames.
      QuicPacketCreator::ScopedPeerAddressContext context(
          &packet_creator_, peer_address, /*update_connection_id=*/false);
      // This may cause connection to be closed.
      packet_creator_.AddPathChallengeFrame(data_buffer);
    }
    // Return outside of the scope so that the flush result can be reflected.
    return connected_;
  }
  std::unique_ptr<SerializedPacket> probing_packet =
      packet_creator_.SerializePathChallengeConnectivityProbingPacket(
          data_buffer);
  QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet), NO_RETRANSMITTABLE_DATA);
  QUICHE_DCHECK_EQ(self_address, alternative_path_.self_address);
  WritePacketUsingWriter(std::move(probing_packet), writer, self_address,
                         peer_address, /*measure_rtt=*/false);
  return true;
}

QuicTime QuicConnection::GetRetryTimeout(
    const QuicSocketAddress& peer_address_to_use,
    QuicPacketWriter* writer_to_use) const {
  if (writer_to_use == writer_ && peer_address_to_use == peer_address()) {
    return clock_->ApproximateNow() + sent_packet_manager_.GetPtoDelay();
  }
  return clock_->ApproximateNow() +
         QuicTime::Delta::FromMilliseconds(3 * kInitialRttMs);
}

void QuicConnection::ValidatePath(
    std::unique_ptr<QuicPathValidationContext> context,
    std::unique_ptr<QuicPathValidator::ResultDelegate> result_delegate,
    PathValidationReason reason) {
  if (!connection_migration_use_new_cid_ &&
      perspective_ == Perspective::IS_CLIENT &&
      !IsDefaultPath(context->self_address(), context->peer_address())) {
    alternative_path_ = PathState(
        context->self_address(), context->peer_address(),
        default_path_.client_connection_id, default_path_.server_connection_id,
        default_path_.stateless_reset_token);
  }
  if (path_validator_.HasPendingPathValidation()) {
    if (perspective_ == Perspective::IS_CLIENT &&
        IsValidatingServerPreferredAddress()) {
      QUIC_CLIENT_HISTOGRAM_BOOL(
          "QuicSession.ServerPreferredAddressValidationCancelled", true,
          "How often the caller kicked off another validation while there is "
          "an on-going server preferred address validation.");
    }
    // Cancel and fail any earlier validation.
    path_validator_.CancelPathValidation();
  }
  if (connection_migration_use_new_cid_ &&
      perspective_ == Perspective::IS_CLIENT &&
      !IsDefaultPath(context->self_address(), context->peer_address())) {
    if (self_issued_cid_manager_ != nullptr) {
      self_issued_cid_manager_->MaybeSendNewConnectionIds();
      if (!connected_) {
        return;
      }
    }
    if ((self_issued_cid_manager_ != nullptr &&
         !self_issued_cid_manager_->HasConnectionIdToConsume()) ||
        (peer_issued_cid_manager_ != nullptr &&
         !peer_issued_cid_manager_->HasUnusedConnectionId())) {
      QUIC_DVLOG(1) << "Client cannot start new path validation as there is no "
                       "requried connection ID is available.";
      result_delegate->OnPathValidationFailure(std::move(context));
      return;
    }
    QuicConnectionId client_connection_id, server_connection_id;
    absl::optional<StatelessResetToken> stateless_reset_token;
    if (self_issued_cid_manager_ != nullptr) {
      client_connection_id =
          *self_issued_cid_manager_->ConsumeOneConnectionId();
    }
    if (peer_issued_cid_manager_ != nullptr) {
      const auto* connection_id_data =
          peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
      server_connection_id = connection_id_data->connection_id;
      stateless_reset_token = connection_id_data->stateless_reset_token;
    }
    alternative_path_ = PathState(context->self_address(),
                                  context->peer_address(), client_connection_id,
                                  server_connection_id, stateless_reset_token);
  }
  path_validator_.StartPathValidation(std::move(context),
                                      std::move(result_delegate), reason);
  if (perspective_ == Perspective::IS_CLIENT &&
      IsValidatingServerPreferredAddress()) {
    AddKnownServerAddress(received_server_preferred_address_);
  }
}

bool QuicConnection::SendPathResponse(
    const QuicPathFrameBuffer& data_buffer,
    const QuicSocketAddress& peer_address_to_send,
    const QuicSocketAddress& effective_peer_address) {
  if (!framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_FORWARD_SECURE)) {
    return false;
  }
  QuicConnectionId client_cid, server_cid;
  if (connection_migration_use_new_cid_) {
    FindOnPathConnectionIds(last_received_packet_info_.destination_address,
                            effective_peer_address, &client_cid, &server_cid);
  }
  // Send PATH_RESPONSE using the provided peer address. If the creator has been
  // using a different peer address, it will flush before and after serializing
  // the current PATH_RESPONSE.
  QuicPacketCreator::ScopedPeerAddressContext context(
      &packet_creator_, peer_address_to_send, client_cid, server_cid,
      connection_migration_use_new_cid_);
  QUIC_DVLOG(1) << ENDPOINT << "Send PATH_RESPONSE to " << peer_address_to_send;
  if (default_path_.self_address ==
      last_received_packet_info_.destination_address) {
    // The PATH_CHALLENGE is received on the default socket. Respond on the same
    // socket.
    return packet_creator_.AddPathResponseFrame(data_buffer);
  }

  QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
  // This PATH_CHALLENGE is received on an alternative socket which should be
  // used to send PATH_RESPONSE.
  if (!path_validator_.HasPendingPathValidation() ||
      path_validator_.GetContext()->self_address() !=
          last_received_packet_info_.destination_address) {
    // Ignore this PATH_CHALLENGE if it's received from an uninteresting
    // socket.
    return true;
  }
  QuicPacketWriter* writer = path_validator_.GetContext()->WriterToUse();

  std::unique_ptr<SerializedPacket> probing_packet =
      packet_creator_.SerializePathResponseConnectivityProbingPacket(
          {data_buffer}, /*is_padded=*/true);
  QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet), NO_RETRANSMITTABLE_DATA);
  QUIC_DVLOG(1) << ENDPOINT
                << "Send PATH_RESPONSE from alternative socket with address "
                << last_received_packet_info_.destination_address;
  // Ignore the return value to treat write error on the alternative writer as
  // part of network error. If the writer becomes blocked, wait for the peer to
  // send another PATH_CHALLENGE.
  WritePacketUsingWriter(std::move(probing_packet), writer,
                         last_received_packet_info_.destination_address,
                         peer_address_to_send,
                         /*measure_rtt=*/false);
  return true;
}

void QuicConnection::UpdatePeerAddress(QuicSocketAddress peer_address) {
  direct_peer_address_ = peer_address;
  packet_creator_.SetDefaultPeerAddress(peer_address);
}

void QuicConnection::SendPingAtLevel(EncryptionLevel level) {
  ScopedEncryptionLevelContext context(this, level);
  SendControlFrame(QuicFrame(QuicPingFrame()));
}

bool QuicConnection::HasPendingPathValidation() const {
  return path_validator_.HasPendingPathValidation();
}

QuicPathValidationContext* QuicConnection::GetPathValidationContext() const {
  return path_validator_.GetContext();
}

void QuicConnection::CancelPathValidation() {
  path_validator_.CancelPathValidation();
}

bool QuicConnection::UpdateConnectionIdsOnMigration(
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address) {
  QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
  if (IsAlternativePath(self_address, peer_address)) {
    // Client migration is after path validation.
    default_path_.client_connection_id = alternative_path_.client_connection_id;
    default_path_.server_connection_id = alternative_path_.server_connection_id;
    default_path_.stateless_reset_token =
        alternative_path_.stateless_reset_token;
    return true;
  }
  // Client migration is without path validation.
  if (self_issued_cid_manager_ != nullptr) {
    self_issued_cid_manager_->MaybeSendNewConnectionIds();
    if (!connected_) {
      return false;
    }
  }
  if ((self_issued_cid_manager_ != nullptr &&
       !self_issued_cid_manager_->HasConnectionIdToConsume()) ||
      (peer_issued_cid_manager_ != nullptr &&
       !peer_issued_cid_manager_->HasUnusedConnectionId())) {
    return false;
  }
  if (self_issued_cid_manager_ != nullptr) {
    default_path_.client_connection_id =
        *self_issued_cid_manager_->ConsumeOneConnectionId();
  }
  if (peer_issued_cid_manager_ != nullptr) {
    const auto* connection_id_data =
        peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
    default_path_.server_connection_id = connection_id_data->connection_id;
    default_path_.stateless_reset_token =
        connection_id_data->stateless_reset_token;
  }
  return true;
}

void QuicConnection::RetirePeerIssuedConnectionIdsNoLongerOnPath() {
  if (!connection_migration_use_new_cid_ ||
      peer_issued_cid_manager_ == nullptr) {
    return;
  }
  if (perspective_ == Perspective::IS_CLIENT) {
    peer_issued_cid_manager_->MaybeRetireUnusedConnectionIds(
        {default_path_.server_connection_id,
         alternative_path_.server_connection_id});
  } else {
    peer_issued_cid_manager_->MaybeRetireUnusedConnectionIds(
        {default_path_.client_connection_id,
         alternative_path_.client_connection_id});
  }
}

void QuicConnection::RetirePeerIssuedConnectionIdsOnPathValidationFailure() {
  // The alarm to retire connection IDs no longer on paths is scheduled at the
  // end of writing and reading packet. On path validation failure, there could
  // be no packet to write or read. Hence the retirement alarm for the
  // connection ID associated with the failed path needs to be proactively
  // scheduled here.
  if (GetQuicReloadableFlag(
          quic_retire_cid_on_reverse_path_validation_failure) ||
      perspective_ == Perspective::IS_CLIENT) {
    QUIC_RELOADABLE_FLAG_COUNT(
        quic_retire_cid_on_reverse_path_validation_failure);
    RetirePeerIssuedConnectionIdsNoLongerOnPath();
  }
}

bool QuicConnection::MigratePath(const QuicSocketAddress& self_address,
                                 const QuicSocketAddress& peer_address,
                                 QuicPacketWriter* writer, bool owns_writer) {
  QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
  if (!connected_) {
    if (owns_writer) {
      delete writer;
    }
    return false;
  }
  QUICHE_DCHECK(!version().UsesHttp3() || IsHandshakeConfirmed() ||
                accelerated_server_preferred_address_);

  if (connection_migration_use_new_cid_) {
    if (!UpdateConnectionIdsOnMigration(self_address, peer_address)) {
      if (owns_writer) {
        delete writer;
      }
      return false;
    }
    if (packet_creator_.GetServerConnectionId().length() !=
        default_path_.server_connection_id.length()) {
      packet_creator_.FlushCurrentPacket();
    }
    packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
    packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
  }

  const auto self_address_change_type = QuicUtils::DetermineAddressChangeType(
      default_path_.self_address, self_address);
  const auto peer_address_change_type = QuicUtils::DetermineAddressChangeType(
      default_path_.peer_address, peer_address);
  QUICHE_DCHECK(self_address_change_type != NO_CHANGE ||
                peer_address_change_type != NO_CHANGE);
  const bool is_port_change = (self_address_change_type == PORT_CHANGE ||
                               self_address_change_type == NO_CHANGE) &&
                              (peer_address_change_type == PORT_CHANGE ||
                               peer_address_change_type == NO_CHANGE);
  SetSelfAddress(self_address);
  UpdatePeerAddress(peer_address);
  default_path_.peer_address = peer_address;
  if (writer_ != writer) {
    SetQuicPacketWriter(writer, owns_writer);
  }
  MaybeClearQueuedPacketsOnPathChange();
  OnSuccessfulMigration(is_port_change);
  return true;
}

void QuicConnection::OnPathValidationFailureAtClient(
    bool is_multi_port, const QuicPathValidationContext& context) {
  if (connection_migration_use_new_cid_) {
    QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
    alternative_path_.Clear();
  }

  if (is_multi_port && multi_port_stats_ != nullptr) {
    if (is_path_degrading_) {
      multi_port_stats_->num_multi_port_probe_failures_when_path_degrading++;
    } else {
      multi_port_stats_
          ->num_multi_port_probe_failures_when_path_not_degrading++;
    }
  }

  if (context.peer_address() == received_server_preferred_address_ &&
      received_server_preferred_address_ != default_path_.peer_address) {
    QUIC_DLOG(INFO) << "Failed to validate server preferred address : "
                    << received_server_preferred_address_;
    mutable_stats().failed_to_validate_server_preferred_address = true;
  }

  RetirePeerIssuedConnectionIdsOnPathValidationFailure();
}

QuicConnectionId QuicConnection::GetOneActiveServerConnectionId() const {
  if (perspective_ == Perspective::IS_CLIENT ||
      self_issued_cid_manager_ == nullptr) {
    return connection_id();
  }
  auto active_connection_ids = GetActiveServerConnectionIds();
  QUIC_BUG_IF(quic_bug_6944, active_connection_ids.empty());
  if (active_connection_ids.empty() ||
      std::find(active_connection_ids.begin(), active_connection_ids.end(),
                connection_id()) != active_connection_ids.end()) {
    return connection_id();
  }
  QUICHE_CODE_COUNT(connection_id_on_default_path_has_been_retired);
  auto active_connection_id =
      self_issued_cid_manager_->GetOneActiveConnectionId();
  return active_connection_id;
}

std::vector<QuicConnectionId> QuicConnection::GetActiveServerConnectionIds()
    const {
  QUICHE_DCHECK_EQ(Perspective::IS_SERVER, perspective_);
  std::vector<QuicConnectionId> result;
  if (self_issued_cid_manager_ == nullptr) {
    result.push_back(default_path_.server_connection_id);
  } else {
    QUICHE_DCHECK(version().HasIetfQuicFrames());
    result = self_issued_cid_manager_->GetUnretiredConnectionIds();
  }
  if (!original_destination_connection_id_.has_value()) {
    return result;
  }
  // Add the original connection ID
  if (std::find(result.begin(), result.end(),
                original_destination_connection_id_.value()) != result.end()) {
    QUIC_BUG(quic_unexpected_original_destination_connection_id)
        << "original_destination_connection_id: "
        << original_destination_connection_id_.value()
        << " is unexpectedly in active list";
  } else {
    result.insert(result.end(), original_destination_connection_id_.value());
  }
  return result;
}

void QuicConnection::CreateConnectionIdManager() {
  if (!version().HasIetfQuicFrames()) {
    return;
  }

  if (perspective_ == Perspective::IS_CLIENT) {
    if (!default_path_.server_connection_id.IsEmpty()) {
      peer_issued_cid_manager_ =
          std::make_unique<QuicPeerIssuedConnectionIdManager>(
              kMinNumOfActiveConnectionIds, default_path_.server_connection_id,
              clock_, alarm_factory_, this, context());
    }
  } else {
    if (!default_path_.server_connection_id.IsEmpty()) {
      self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
    }
  }
}

void QuicConnection::QuicBugIfHasPendingFrames(QuicStreamId id) const {
  QUIC_BUG_IF(quic_has_pending_frames_unexpectedly,
              connected_ && packet_creator_.HasPendingStreamFramesOfStream(id))
      << "Stream " << id
      << " has pending frames unexpectedly. Received packet info: "
      << last_received_packet_info_;
}

void QuicConnection::SetUnackedMapInitialCapacity() {
  sent_packet_manager_.ReserveUnackedPacketsInitialCapacity(
      GetUnackedMapInitialCapacity());
}

void QuicConnection::SetSourceAddressTokenToSend(absl::string_view token) {
  QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
  if (!packet_creator_.HasRetryToken()) {
    // Ignore received tokens (via NEW_TOKEN frame) from previous connections
    // when a RETRY token has been received.
    packet_creator_.SetRetryToken(std::string(token.data(), token.length()));
  }
}

void QuicConnection::MaybeUpdateBytesSentToAlternativeAddress(
    const QuicSocketAddress& peer_address, QuicByteCount sent_packet_size) {
  if (!version().SupportsAntiAmplificationLimit() ||
      perspective_ != Perspective::IS_SERVER) {
    return;
  }
  QUICHE_DCHECK(!IsDefaultPath(default_path_.self_address, peer_address));
  if (!IsAlternativePath(default_path_.self_address, peer_address)) {
    QUIC_DLOG(INFO) << "Wrote to uninteresting peer address: " << peer_address
                    << " default direct_peer_address_ " << direct_peer_address_
                    << " alternative path peer address "
                    << alternative_path_.peer_address;
    return;
  }
  if (alternative_path_.validated) {
    return;
  }
  if (alternative_path_.bytes_sent_before_address_validation >=
      anti_amplification_factor_ *
          alternative_path_.bytes_received_before_address_validation) {
    QUIC_LOG_FIRST_N(WARNING, 100)
        << "Server sent more data than allowed to unverified alternative "
           "peer address "
        << peer_address << " bytes sent "
        << alternative_path_.bytes_sent_before_address_validation
        << ", bytes received "
        << alternative_path_.bytes_received_before_address_validation;
  }
  alternative_path_.bytes_sent_before_address_validation += sent_packet_size;
}

void QuicConnection::MaybeUpdateBytesReceivedFromAlternativeAddress(
    QuicByteCount received_packet_size) {
  if (!version().SupportsAntiAmplificationLimit() ||
      perspective_ != Perspective::IS_SERVER ||
      !IsAlternativePath(last_received_packet_info_.destination_address,
                         GetEffectivePeerAddressFromCurrentPacket()) ||
      last_received_packet_info_.received_bytes_counted) {
    return;
  }
  // Only update bytes received if this probing frame is received on the most
  // recent alternative path.
  QUICHE_DCHECK(!IsDefaultPath(last_received_packet_info_.destination_address,
                               GetEffectivePeerAddressFromCurrentPacket()));
  if (!alternative_path_.validated) {
    alternative_path_.bytes_received_before_address_validation +=
        received_packet_size;
  }
  last_received_packet_info_.received_bytes_counted = true;
}

bool QuicConnection::IsDefaultPath(
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address) const {
  return direct_peer_address_ == peer_address &&
         default_path_.self_address == self_address;
}

bool QuicConnection::IsAlternativePath(
    const QuicSocketAddress& self_address,
    const QuicSocketAddress& peer_address) const {
  return alternative_path_.peer_address == peer_address &&
         alternative_path_.self_address == self_address;
}

void QuicConnection::PathState::Clear() {
  self_address = QuicSocketAddress();
  peer_address = QuicSocketAddress();
  client_connection_id = {};
  server_connection_id = {};
  validated = false;
  bytes_received_before_address_validation = 0;
  bytes_sent_before_address_validation = 0;
  send_algorithm = nullptr;
  rtt_stats = absl::nullopt;
  stateless_reset_token.reset();
}

QuicConnection::PathState::PathState(PathState&& other) {
  *this = std::move(other);
}

QuicConnection::PathState& QuicConnection::PathState::operator=(
    QuicConnection::PathState&& other) {
  if (this != &other) {
    self_address = other.self_address;
    peer_address = other.peer_address;
    client_connection_id = other.client_connection_id;
    server_connection_id = other.server_connection_id;
    stateless_reset_token = other.stateless_reset_token;
    validated = other.validated;
    bytes_received_before_address_validation =
        other.bytes_received_before_address_validation;
    bytes_sent_before_address_validation =
        other.bytes_sent_before_address_validation;
    send_algorithm = std::move(other.send_algorithm);
    if (other.rtt_stats.has_value()) {
      rtt_stats.emplace();
      rtt_stats->CloneFrom(other.rtt_stats.value());
    } else {
      rtt_stats.reset();
    }
    other.Clear();
  }
  return *this;
}

bool QuicConnection::IsReceivedPeerAddressValidated() const {
  QuicSocketAddress current_effective_peer_address =
      GetEffectivePeerAddressFromCurrentPacket();
  QUICHE_DCHECK(current_effective_peer_address.IsInitialized());
  return (alternative_path_.peer_address.host() ==
              current_effective_peer_address.host() &&
          alternative_path_.validated) ||
         (default_path_.validated && default_path_.peer_address.host() ==
                                         current_effective_peer_address.host());
}

void QuicConnection::OnMultiPortPathProbingSuccess(
    std::unique_ptr<QuicPathValidationContext> context, QuicTime start_time) {
  QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective());
  alternative_path_.validated = true;
  multi_port_path_context_ = std::move(context);
  multi_port_probing_alarm_->Set(clock_->ApproximateNow() +
                                 multi_port_probing_interval_);
  if (multi_port_stats_ != nullptr) {
    auto now = clock_->Now();
    auto time_delta = now - start_time;
    multi_port_stats_->rtt_stats.UpdateRtt(time_delta, QuicTime::Delta::Zero(),
                                           now);
    if (is_path_degrading_) {
      multi_port_stats_->rtt_stats_when_default_path_degrading.UpdateRtt(
          time_delta, QuicTime::Delta::Zero(), now);
    }
  }
}

void QuicConnection::MaybeProbeMultiPortPath() {
  if (!connected_ || path_validator_.HasPendingPathValidation() ||
      !multi_port_path_context_ ||
      alternative_path_.self_address !=
          multi_port_path_context_->self_address() ||
      alternative_path_.peer_address !=
          multi_port_path_context_->peer_address() ||
      !visitor_->ShouldKeepConnectionAlive() ||
      multi_port_probing_alarm_->IsSet()) {
    return;
  }
  auto multi_port_validation_result_delegate =
      std::make_unique<MultiPortPathValidationResultDelegate>(this);
  path_validator_.StartPathValidation(
      std::move(multi_port_path_context_),
      std::move(multi_port_validation_result_delegate),
      PathValidationReason::kMultiPort);
}

QuicConnection::MultiPortPathValidationResultDelegate::
    MultiPortPathValidationResultDelegate(QuicConnection* connection)
    : connection_(connection) {
  QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, connection->perspective());
}

void QuicConnection::MultiPortPathValidationResultDelegate::
    OnPathValidationSuccess(std::unique_ptr<QuicPathValidationContext> context,
                            QuicTime start_time) {
  connection_->OnMultiPortPathProbingSuccess(std::move(context), start_time);
}

void QuicConnection::MultiPortPathValidationResultDelegate::
    OnPathValidationFailure(
        std::unique_ptr<QuicPathValidationContext> context) {
  connection_->OnPathValidationFailureAtClient(/*is_multi_port=*/true,
                                               *context);
}

QuicConnection::ReversePathValidationResultDelegate::
    ReversePathValidationResultDelegate(
        QuicConnection* connection,
        const QuicSocketAddress& direct_peer_address)
    : QuicPathValidator::ResultDelegate(),
      connection_(connection),
      original_direct_peer_address_(direct_peer_address),
      peer_address_default_path_(connection->direct_peer_address_),
      peer_address_alternative_path_(
          connection_->alternative_path_.peer_address),
      active_effective_peer_migration_type_(
          connection_->active_effective_peer_migration_type_) {
  if (connection_->count_reverse_path_validation_stats()) {
    QUIC_CODE_COUNT_N(quic_reverse_path_validation, 1, 4);
  }
}

void QuicConnection::ReversePathValidationResultDelegate::
    OnPathValidationSuccess(std::unique_ptr<QuicPathValidationContext> context,
                            QuicTime start_time) {
  if (connection_->count_reverse_path_validation_stats()) {
    QUIC_CODE_COUNT_N(quic_reverse_path_validation, 2, 4);
  }
  QUIC_DLOG(INFO) << "Successfully validated new path " << *context
                  << ", validation started at " << start_time;
  if (connection_->IsDefaultPath(context->self_address(),
                                 context->peer_address())) {
    QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 3, 6);
    if (connection_->active_effective_peer_migration_type_ == NO_CHANGE) {
      std::string error_detail = absl::StrCat(
          "Reverse path validation on default path from ",
          context->self_address().ToString(), " to ",
          context->peer_address().ToString(),
          " completed without active peer address change: current "
          "peer address on default path ",
          connection_->direct_peer_address_.ToString(),
          ", peer address on default path when the reverse path "
          "validation was kicked off ",
          peer_address_default_path_.ToString(),
          ", peer address on alternative path when the reverse "
          "path validation was kicked off ",
          peer_address_alternative_path_.ToString(),
          ", with active_effective_peer_migration_type_ = ",
          AddressChangeTypeToString(active_effective_peer_migration_type_),
          ". The last received packet number ",
          connection_->last_received_packet_info_.header.packet_number
              .ToString(),
          " Connection is connected: ", connection_->connected_);
      QUIC_BUG(quic_bug_10511_43) << error_detail;
    }
    connection_->OnEffectivePeerMigrationValidated(
        connection_->alternative_path_.server_connection_id ==
        connection_->default_path_.server_connection_id);
  } else {
    QUICHE_DCHECK(connection_->IsAlternativePath(
        context->self_address(), context->effective_peer_address()));
    QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 4, 6);
    QUIC_DVLOG(1) << "Mark alternative peer address "
                  << context->effective_peer_address() << " validated.";
    connection_->alternative_path_.validated = true;
  }
}

void QuicConnection::ReversePathValidationResultDelegate::
    OnPathValidationFailure(
        std::unique_ptr<QuicPathValidationContext> context) {
  if (connection_->count_reverse_path_validation_stats()) {
    QUIC_CODE_COUNT_N(quic_reverse_path_validation, 3, 4);
  }
  if (!connection_->connected()) {
    return;
  }
  QUIC_DLOG(INFO) << "Fail to validate new path " << *context;
  if (connection_->IsDefaultPath(context->self_address(),
                                 context->peer_address())) {
    // Only act upon validation failure on the default path.
    QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 5, 6);
    connection_->RestoreToLastValidatedPath(original_direct_peer_address_);
  } else if (connection_->IsAlternativePath(
                 context->self_address(), context->effective_peer_address())) {
    QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 6, 6);
    connection_->alternative_path_.Clear();
  }
  connection_->RetirePeerIssuedConnectionIdsOnPathValidationFailure();
}

QuicConnection::ScopedRetransmissionTimeoutIndicator::
    ScopedRetransmissionTimeoutIndicator(QuicConnection* connection)
    : connection_(connection) {
  QUICHE_DCHECK(!connection_->in_probe_time_out_)
      << "ScopedRetransmissionTimeoutIndicator is not supposed to be nested";
  connection_->in_probe_time_out_ = true;
}

QuicConnection::ScopedRetransmissionTimeoutIndicator::
    ~ScopedRetransmissionTimeoutIndicator() {
  QUICHE_DCHECK(connection_->in_probe_time_out_);
  connection_->in_probe_time_out_ = false;
}

void QuicConnection::RestoreToLastValidatedPath(
    QuicSocketAddress original_direct_peer_address) {
  QUIC_DLOG(INFO) << "Switch back to use the old peer address "
                  << alternative_path_.peer_address;
  if (!alternative_path_.validated) {
    // If not validated by now, close connection silently so that the following
    // packets received will be rejected.
    CloseConnection(QUIC_INTERNAL_ERROR,
                    "No validated peer address to use after reverse path "
                    "validation failure.",
                    ConnectionCloseBehavior::SILENT_CLOSE);
    return;
  }
  MaybeClearQueuedPacketsOnPathChange();

  // Revert congestion control context to old state.
  OnPeerIpAddressChanged();

  if (alternative_path_.send_algorithm != nullptr) {
    sent_packet_manager_.SetSendAlgorithm(
        alternative_path_.send_algorithm.release());
    sent_packet_manager_.SetRttStats(alternative_path_.rtt_stats.value());
  } else {
    QUIC_BUG(quic_bug_10511_42)
        << "Fail to store congestion controller before migration.";
  }

  UpdatePeerAddress(original_direct_peer_address);
  SetDefaultPathState(std::move(alternative_path_));

  active_effective_peer_migration_type_ = NO_CHANGE;
  ++stats_.num_invalid_peer_migration;
  // The reverse path validation failed because of alarm firing, flush all the
  // pending writes previously throttled by anti-amplification limit.
  WriteIfNotBlocked();
}

std::unique_ptr<SendAlgorithmInterface>
QuicConnection::OnPeerIpAddressChanged() {
  QUICHE_DCHECK(validate_client_addresses_);
  std::unique_ptr<SendAlgorithmInterface> old_send_algorithm =
      sent_packet_manager_.OnConnectionMigration(
          /*reset_send_algorithm=*/true);
  // OnConnectionMigration() should have marked in-flight packets to be
  // retransmitted if there is any.
  QUICHE_DCHECK(!sent_packet_manager_.HasInFlightPackets());
  // OnConnectionMigration() may have changed the retransmission timer, so
  // re-arm it.
  SetRetransmissionAlarm();
  // Stop detections in quiecense.
  blackhole_detector_.StopDetection(/*permanent=*/false);
  return old_send_algorithm;
}

void QuicConnection::set_keep_alive_ping_timeout(
    QuicTime::Delta keep_alive_ping_timeout) {
  ping_manager_.set_keep_alive_timeout(keep_alive_ping_timeout);
}

void QuicConnection::set_initial_retransmittable_on_wire_timeout(
    QuicTime::Delta retransmittable_on_wire_timeout) {
  ping_manager_.set_initial_retransmittable_on_wire_timeout(
      retransmittable_on_wire_timeout);
}

bool QuicConnection::IsValidatingServerPreferredAddress() const {
  QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
  return received_server_preferred_address_.IsInitialized() &&
         received_server_preferred_address_ != default_path_.peer_address &&
         path_validator_.HasPendingPathValidation() &&
         path_validator_.GetContext()->peer_address() ==
             received_server_preferred_address_;
}

void QuicConnection::OnServerPreferredAddressValidated(
    QuicPathValidationContext& context, bool owns_writer) {
  QUIC_DLOG(INFO) << "Server preferred address: " << context.peer_address()
                  << " validated. Migrating path, self_address: "
                  << context.self_address()
                  << ", peer_address: " << context.peer_address();
  mutable_stats().server_preferred_address_validated = true;
  const bool success =
      MigratePath(context.self_address(), context.peer_address(),
                  context.WriterToUse(), owns_writer);
  QUIC_BUG_IF(failed to migrate to server preferred address, !success)
      << "Failed to migrate to server preferred address: "
      << context.peer_address() << " after successful validation";
}

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