gfe-relnote: Send QUIC connection close packets at all available encryption levels.

PiperOrigin-RevId: 275164869
Change-Id: I0a75e528218a6526dbeef2d44df5cf0cb332094e
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 079e14d..7916791 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -2832,13 +2832,13 @@
 
 void QuicConnection::QueueUndecryptablePacket(
     const QuicEncryptedPacket& packet) {
-    for (const auto& saved_packet : undecryptable_packets_) {
-      if (packet.data() == saved_packet->data() &&
-          packet.length() == saved_packet->length()) {
-        QUIC_DVLOG(1) << ENDPOINT << "Not queueing known undecryptable packet";
-        return;
-      }
+  for (const auto& saved_packet : undecryptable_packets_) {
+    if (packet.data() == saved_packet->data() &&
+        packet.length() == saved_packet->length()) {
+      QUIC_DVLOG(1) << ENDPOINT << "Not queueing known undecryptable packet";
+      return;
     }
+  }
   QUIC_DVLOG(1) << ENDPOINT << "Queueing undecryptable packet.";
   undecryptable_packets_.push_back(packet.Clone());
 }
@@ -2942,25 +2942,58 @@
 
 void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
                                                const std::string& details) {
-  QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
-  SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
-  ClearQueuedPackets();
-  // If there was a packet write error, write the smallest close possible.
-  ScopedPacketFlusher flusher(this);
-  // When multiple packet number spaces is supported, an ACK frame will be
-  // bundled when connection is not write blocked.
-  if (!SupportsMultiplePacketNumberSpaces() &&
-      error != QUIC_PACKET_WRITE_ERROR &&
-      !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
-    SendAck();
-  }
-  QuicConnectionCloseFrame* frame;
+  if (!GetQuicReloadableFlag(quic_close_all_encryptions_levels)) {
+    QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
+    SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
+    ClearQueuedPackets();
+    // If there was a packet write error, write the smallest close possible.
+    ScopedPacketFlusher flusher(this);
+    // When multiple packet number spaces is supported, an ACK frame will be
+    // bundled when connection is not write blocked.
+    if (!SupportsMultiplePacketNumberSpaces() &&
+        error != QUIC_PACKET_WRITE_ERROR &&
+        !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
+      SendAck();
+    }
+    QuicConnectionCloseFrame* frame;
 
-  frame = new QuicConnectionCloseFrame(transport_version(), error, details,
-                                       framer_.current_received_frame_type());
-  packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
-  packet_generator_.FlushAllQueuedFrames();
-  ClearQueuedPackets();
+    frame = new QuicConnectionCloseFrame(transport_version(), error, details,
+                                         framer_.current_received_frame_type());
+    packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
+    packet_generator_.FlushAllQueuedFrames();
+    ClearQueuedPackets();
+    return;
+  }
+  const EncryptionLevel current_encryption_level = encryption_level_;
+  ScopedPacketFlusher flusher(this);
+  QUIC_RELOADABLE_FLAG_COUNT(quic_close_all_encryptions_levels);
+  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: "
+                    << EncryptionLevelToString(level);
+    SetDefaultEncryptionLevel(level);
+    ClearQueuedPackets();
+    // If there was a packet write error, write the smallest close possible.
+    // When multiple packet number spaces are supported, an ACK frame will
+    // be bundled by the ScopedPacketFlusher. Otherwise, an ACK must be sent
+    // explicitly.
+    if (!SupportsMultiplePacketNumberSpaces() &&
+        error != QUIC_PACKET_WRITE_ERROR &&
+        !GetUpdatedAckFrame().ack_frame->packets.Empty()) {
+      SendAck();
+    }
+    auto* frame =
+        new QuicConnectionCloseFrame(transport_version(), error, details,
+                                     framer_.current_received_frame_type());
+    packet_generator_.ConsumeRetransmittableControlFrame(QuicFrame(frame));
+    packet_generator_.FlushAllQueuedFrames();
+    ClearQueuedPackets();
+  }
+  SetDefaultEncryptionLevel(current_encryption_level);
 }
 
 void QuicConnection::TearDownLocalConnectionState(
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 20f63f7..d73865c 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -2053,8 +2053,9 @@
   // Regression test for b/74073386.
   {
     InSequence seq;
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
-    EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(1);
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+        .Times(AtLeast(1));
+    EXPECT_CALL(visitor_, OnConnectionClosed(_, _)).Times(AtLeast(1));
   }
 
   set_perspective(Perspective::IS_CLIENT);
@@ -2852,9 +2853,11 @@
   // one.  This should cause a connection error.
   QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 7);
   if (!GetParam().no_stop_waiting) {
-    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+    EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+        .Times(AtLeast(1));
     EXPECT_CALL(visitor_,
-                OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
+                OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
+        .Times(AtLeast(1));
   }
   ProcessStopWaitingPacket(InitStopWaitingFrame(1));
   if (!GetParam().no_stop_waiting) {
@@ -2907,7 +2910,7 @@
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   QuicAckFrame frame = InitAckFrame(1);
   EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
   ProcessAckPacket(&frame);
@@ -5473,7 +5476,7 @@
   // This time, we should time out.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   clock_.AdvanceTime(five_ms);
   EXPECT_EQ(default_timeout + five_ms, clock_.ApproximateNow());
   connection_.GetTimeoutAlarm()->Fire();
@@ -5551,7 +5554,7 @@
   // This time, we should time out.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   clock_.AdvanceTime(final_timeout - clock_.Now());
   EXPECT_EQ(connection_.GetTimeoutAlarm()->deadline(), clock_.Now());
   EXPECT_EQ(final_timeout, clock_.Now());
@@ -5686,7 +5689,7 @@
   // This time, we should time out and send a connection close due to the TLP.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   clock_.AdvanceTime(connection_.GetTimeoutAlarm()->deadline() -
                      clock_.ApproximateNow() + five_ms);
   connection_.GetTimeoutAlarm()->Fire();
@@ -5741,7 +5744,7 @@
   // This time, we should time out and send a connection close due to the TLP.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   clock_.AdvanceTime(connection_.GetTimeoutAlarm()->deadline() -
                      clock_.ApproximateNow() + five_ms);
   connection_.GetTimeoutAlarm()->Fire();
@@ -5792,7 +5795,7 @@
   // This time, we should time out.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   clock_.AdvanceTime(five_ms);
   EXPECT_EQ(default_timeout + five_ms, clock_.ApproximateNow());
   connection_.GetTimeoutAlarm()->Fire();
@@ -5895,7 +5898,7 @@
   // This time, we should time out.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   connection_.GetRetransmissionAlarm()->Fire();
   EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
   EXPECT_FALSE(connection_.connected());
@@ -7407,7 +7410,7 @@
   EXPECT_EQ(1u, writer_->packets_write_attempts());
 
   TriggerConnectionClose();
-  EXPECT_EQ(2u, writer_->packets_write_attempts());
+  EXPECT_LE(2u, writer_->packets_write_attempts());
 }
 
 TEST_P(QuicConnectionTest, ConnectionCloseGettingWriteBlocked) {
@@ -8813,6 +8816,8 @@
   use_tagging_decrypter();
   connection_.SetEncrypter(ENCRYPTION_INITIAL,
                            std::make_unique<TaggingEncrypter>(0x01));
+  connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+                           std::make_unique<TaggingEncrypter>(0x01));
 
   connection_.SendCryptoStreamData();
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -8834,7 +8839,7 @@
       InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(4)}});
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   ProcessFramePacketAtLevel(300, QuicFrame(&invalid_ack), ENCRYPTION_INITIAL);
   TestConnectionCloseQuicErrorCode(QUIC_INVALID_ACK_DATA);
 }
@@ -9317,7 +9322,7 @@
       0, FIN, nullptr);
 
   // 5PTO + 1 connection close.
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(6));
 
   // Fire the retransmission alarm 5 times.
   for (int i = 0; i < 5; ++i) {
@@ -9371,7 +9376,7 @@
   // Closes connection on 7th PTO.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   connection_.GetRetransmissionAlarm()->Fire();
   EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
   EXPECT_FALSE(connection_.connected());
@@ -9411,7 +9416,7 @@
   // Closes connection on 8th PTO.
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
-  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+  EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(AtLeast(1));
   connection_.GetRetransmissionAlarm()->Fire();
   EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
   EXPECT_FALSE(connection_.connected());