Do not ACK when encryption keys are missing
This issue would cause a crash (cl/243903209) which was found during IETF interop. The fix skips the packet number space instead of crashing.
gfe-relnote: protected by quic_use_uber_received_packet_manager
PiperOrigin-RevId: 244273811
Change-Id: I5c2a946310f19ce67bb02dd6540c452f23cfc793
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index cb901ba..fae53e8 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -1502,11 +1502,30 @@
if (received_packet_manager_.decide_when_to_send_acks()) {
if (use_uber_received_packet_manager_) {
- uber_received_packet_manager_.MaybeUpdateAckTimeout(
- should_last_packet_instigate_acks_, last_decrypted_packet_level_,
- last_header_.packet_number, time_of_last_received_packet_,
- clock_->ApproximateNow(), sent_packet_manager_.GetRttStats(),
- sent_packet_manager_.delayed_ack_time());
+ // Some encryption levels share a packet number space, it is therefore
+ // possible for us to want to ack some packets even though we do not yet
+ // have the appropriate keys to encrypt the acks. In this scenario we
+ // do not update the ACK timeout. This can happen for example with
+ // IETF QUIC on the server when we receive 0-RTT packets and do not yet
+ // have 1-RTT keys (0-RTT packets are acked at the 1-RTT level).
+ // Note that this could cause slight performance degradations in the edge
+ // case where one packet is received, then the encrypter is installed,
+ // then a second packet is received; as that could cause the ACK for the
+ // second packet to be delayed instead of immediate. This is currently
+ // considered to be small enough of an edge case to not be optimized for.
+ if (framer_.HasEncrypterOfEncryptionLevel(QuicUtils::GetEncryptionLevel(
+ QuicUtils::GetPacketNumberSpace(last_decrypted_packet_level_)))) {
+ uber_received_packet_manager_.MaybeUpdateAckTimeout(
+ should_last_packet_instigate_acks_, last_decrypted_packet_level_,
+ last_header_.packet_number, time_of_last_received_packet_,
+ clock_->ApproximateNow(), sent_packet_manager_.GetRttStats(),
+ sent_packet_manager_.delayed_ack_time());
+ } else {
+ QUIC_DLOG(INFO) << ENDPOINT << "Not updating ACK timeout for "
+ << QuicUtils::EncryptionLevelToString(
+ last_decrypted_packet_level_)
+ << " as we do not have the corresponding encrypter";
+ }
} else {
received_packet_manager_.MaybeUpdateAckTimeout(
should_last_packet_instigate_acks_, last_header_.packet_number,
@@ -3982,6 +4001,13 @@
ack_timeout > clock_->ApproximateNow()) {
continue;
}
+ if (!framer_.HasEncrypterOfEncryptionLevel(
+ QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i)))) {
+ QUIC_BUG << ENDPOINT << "Cannot send ACKs for packet number space "
+ << static_cast<uint32_t>(i)
+ << " without corresponding encrypter";
+ continue;
+ }
QUIC_DVLOG(1) << ENDPOINT << "Sending ACK of packet number space: "
<< static_cast<uint32_t>(i);
// Switch to the appropriate encryption level.