Align OnRetransmissionTimeout more closely with RFC9002. When both Initial and Handshake keys are available at the client, switches to sending a PING in Handshake to remove the server's amplification limit and allow it to drop Initial keys, as specified by RFC9002. PiperOrigin-RevId: 382177508
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index cd4e6be..3b3069b 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -4322,27 +4322,28 @@ << retransmission_mode << ", send PING"; QUICHE_DCHECK_LT(0u, sent_packet_manager_.pending_timer_transmission_count()); - EncryptionLevel level = encryption_level_; - PacketNumberSpace packet_number_space = NUM_PACKET_NUMBER_SPACES; 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()) { - level = QuicUtils::GetEncryptionLevel(packet_number_space); - } - if (level == ENCRYPTION_ZERO_RTT) { + SendPingAtLevel(QuicUtils::GetEncryptionLevel(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_); - // Do not send 0-RTT PING since it will only elicit (unprocessable) - // 1-RTT acknowledgement from server, which does not speed up recovery. - if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL)) { - level = ENCRYPTION_INITIAL; - } else if (framer_.HasEncrypterOfEncryptionLevel( - ENCRYPTION_HANDSHAKE)) { - level = ENCRYPTION_HANDSHAKE; + 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_); } - SendPingAtLevel(level); } if (retransmission_mode == QuicSentPacketManager::PTO_MODE) { sent_packet_manager_.AdjustPendingTimerTransmissions();