Notify debug_visitor once any 0-RTT packet gets acknowledged. Client only (server + TLS does not send 0-RTT packets).

PiperOrigin-RevId: 333813151
Change-Id: I468d0da1bd9df984bc7c3f836dcff58e5329e547
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 15298fe..642ebc7 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -1319,6 +1319,8 @@
   }
   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_header_.packet_number, last_decrypted_packet_level_);
@@ -1335,6 +1337,11 @@
       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.
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index c9d903e..e72ffb8 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -377,6 +377,9 @@
   // Called for QUIC+TLS versions when 0-RTT is rejected.
   virtual void OnZeroRttRejected(int /*reject_reason*/) {}
 
+  // Called for QUIC+TLS versions when 0-RTT packet gets acked.
+  virtual void OnZeroRttPacketAcked() {}
+
   // Called on peer address change.
   virtual void OnPeerAddressChange(AddressChangeType /*type*/,
                                    QuicTime::Delta /*connection_time*/) {}
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index c26cdc8..ea73382 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -12174,6 +12174,53 @@
       {{2, frames1, ENCRYPTION_INITIAL}, {3, frames2, ENCRYPTION_HANDSHAKE}});
 }
 
+TEST_P(QuicConnectionTest, OnZeroRttPacketAcked) {
+  if (!connection_.version().UsesTls()) {
+    return;
+  }
+  MockQuicConnectionDebugVisitor debug_visitor;
+  connection_.set_debug_visitor(&debug_visitor);
+  use_tagging_decrypter();
+  connection_.SetEncrypter(ENCRYPTION_INITIAL,
+                           std::make_unique<TaggingEncrypter>(0x01));
+  connection_.SendCryptoStreamData();
+  // Send 0-RTT packet.
+  connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
+                           std::make_unique<TaggingEncrypter>(0x02));
+  connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+  connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN);
+  connection_.SendStreamDataWithString(4, "bar", 0, NO_FIN);
+  // Received ACK for packet 1, HANDSHAKE packet and 1-RTT ACK.
+  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _))
+      .Times(AnyNumber());
+  QuicFrames frames1;
+  QuicAckFrame ack_frame1 = InitAckFrame(1);
+  frames1.push_back(QuicFrame(&ack_frame1));
+
+  QuicFrames frames2;
+  QuicCryptoFrame crypto_frame(ENCRYPTION_HANDSHAKE, 0,
+                               quiche::QuicheStringPiece(data1));
+  frames2.push_back(QuicFrame(&crypto_frame));
+  EXPECT_CALL(debug_visitor, OnZeroRttPacketAcked()).Times(0);
+  EXPECT_CALL(visitor_, OnCryptoFrame(_)).Times(1);
+  ProcessCoalescedPacket(
+      {{1, frames1, ENCRYPTION_INITIAL}, {2, frames2, ENCRYPTION_HANDSHAKE}});
+
+  QuicFrames frames3;
+  QuicAckFrame ack_frame2 =
+      InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
+  frames3.push_back(QuicFrame(&ack_frame2));
+  EXPECT_CALL(debug_visitor, OnZeroRttPacketAcked()).Times(1);
+  ProcessCoalescedPacket({{3, frames3, ENCRYPTION_FORWARD_SECURE}});
+
+  QuicFrames frames4;
+  QuicAckFrame ack_frame3 =
+      InitAckFrame({{QuicPacketNumber(3), QuicPacketNumber(4)}});
+  frames4.push_back(QuicFrame(&ack_frame3));
+  EXPECT_CALL(debug_visitor, OnZeroRttPacketAcked()).Times(0);
+  ProcessCoalescedPacket({{4, frames4, ENCRYPTION_FORWARD_SECURE}});
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index f453619..4dc2582 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -105,6 +105,7 @@
       pto_rttvar_multiplier_(4),
       num_tlp_timeout_ptos_(0),
       handshake_packet_acked_(false),
+      zero_rtt_packet_acked_(false),
       one_rtt_packet_acked_(false),
       one_rtt_packet_sent_(false),
       first_pto_srtt_multiplier_(0),
@@ -1475,8 +1476,9 @@
     last_ack_frame_.packets.Add(acked_packet.packet_number);
     if (info->encryption_level == ENCRYPTION_HANDSHAKE) {
       handshake_packet_acked_ = true;
-    }
-    if (info->encryption_level == ENCRYPTION_FORWARD_SECURE) {
+    } else if (info->encryption_level == ENCRYPTION_ZERO_RTT) {
+      zero_rtt_packet_acked_ = true;
+    } else if (info->encryption_level == ENCRYPTION_FORWARD_SECURE) {
       one_rtt_packet_acked_ = true;
     }
     largest_packet_peer_knows_is_acked_.UpdateMax(info->largest_acked);
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index 3420140..6e36da9 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -436,6 +436,8 @@
     return skip_packet_number_for_pto_;
   }
 
+  bool zero_rtt_packet_acked() const { return zero_rtt_packet_acked_; }
+
   bool one_rtt_packet_acked() const { return one_rtt_packet_acked_; }
 
   void OnUserAgentIdKnown() { loss_algorithm_->OnUserAgentIdKnown(); }
@@ -697,6 +699,9 @@
   // True if any ENCRYPTION_HANDSHAKE packet gets acknowledged.
   bool handshake_packet_acked_;
 
+  // True if any 0-RTT packet gets acknowledged.
+  bool zero_rtt_packet_acked_;
+
   // True if any 1-RTT packet gets acknowledged.
   bool one_rtt_packet_acked_;
 
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index a47bdd1..cd87b5b 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -1482,6 +1482,7 @@
               (override));
 
   MOCK_METHOD(void, OnZeroRttRejected, (int), (override));
+  MOCK_METHOD(void, OnZeroRttPacketAcked, (), (override));
 };
 
 class MockReceivedPacketManager : public QuicReceivedPacketManager {