Add QuicFramer::PotentialPeerKeyUpdateAttemptCount() method.
Returns the count of packets received that appeared to attempt a key
update but failed decryption which have been received since the last
successfully decrypted packet.
PiperOrigin-RevId: 338710571
Change-Id: Iaae901269d6bffaf441a31a4a51540aa94c84b73
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 71bb8be..a7f63dd 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -3721,6 +3721,10 @@
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()) {
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index a3da511..31988d2 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -828,6 +828,11 @@
// none of these packets have been acked.
bool HaveSentPacketsInCurrentKeyPhaseButNoneAcked() const;
+ // Returns the count of packets received that appeared to attempt a key
+ // update but failed decryption that have been received since the last
+ // successfully decrypted packet.
+ QuicPacketCount PotentialPeerKeyUpdateAttemptCount() const;
+
// Increment the key phase. It is a bug to call this when IsKeyUpdateAllowed()
// is false. Returns false on error.
bool InitiateKeyUpdate(KeyUpdateReason reason);
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 39be55e..cfa56c2 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -414,6 +414,7 @@
last_timestamp_(QuicTime::Delta::Zero()),
support_key_update_for_connection_(false),
current_key_phase_bit_(false),
+ potential_peer_key_update_attempt_count_(0),
first_sending_packet_number_(FirstSendingPacketNumber()),
data_producer_(nullptr),
infer_packet_header_type_from_version_(perspective ==
@@ -4282,6 +4283,10 @@
return true;
}
+QuicPacketCount QuicFramer::PotentialPeerKeyUpdateAttemptCount() const {
+ return potential_peer_key_update_attempt_count_;
+}
+
const QuicDecrypter* QuicFramer::GetDecrypter(EncryptionLevel level) const {
DCHECK(version_.KnowsWhichDecrypterToUse());
return decrypter_[level].get();
@@ -4717,6 +4722,7 @@
QUIC_DVLOG(1) << ENDPOINT << "packet " << header.packet_number
<< " attempt_key_update=true";
attempt_key_update = true;
+ potential_peer_key_update_attempt_count_++;
decrypter = next_decrypter_.get();
} else {
if (previous_decrypter_) {
@@ -4752,6 +4758,7 @@
if (success) {
visitor_->OnDecryptedPacket(level);
*decrypted_level = level;
+ potential_peer_key_update_attempt_count_ = 0;
if (attempt_key_update) {
if (!DoKeyUpdate(KeyUpdateReason::kRemote)) {
set_detailed_error("Key update failed due to internal error");
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h
index 5d9bf46..86c8882 100644
--- a/quic/core/quic_framer.h
+++ b/quic/core/quic_framer.h
@@ -547,6 +547,10 @@
void DiscardPreviousOneRttKeys();
// Update the key phase.
bool DoKeyUpdate(KeyUpdateReason reason);
+ // Returns the count of packets received that appeared to attempt a key
+ // update but failed decryption which have been received since the last
+ // successfully decrypted packet.
+ QuicPacketCount PotentialPeerKeyUpdateAttemptCount() const;
const QuicDecrypter* GetDecrypter(EncryptionLevel level) const;
const QuicDecrypter* decrypter() const;
@@ -1104,6 +1108,10 @@
// locally initiated key update but before the first packet from the peer in
// the new key phase is received.
QuicPacketNumber current_key_phase_first_received_packet_number_;
+ // Counts the number of packets received that might have been failed key
+ // update attempts. Reset to zero every time a packet is successfully
+ // decrypted.
+ QuicPacketCount potential_peer_key_update_attempt_count_;
// Decrypter for the previous key phase. Will be null if in the first key
// phase or previous keys have been discarded.
std::unique_ptr<QuicDecrypter> previous_decrypter_;
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index ab61814..2fbab61 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -14925,6 +14925,7 @@
EXPECT_EQ(0u, visitor_.key_update_count());
EXPECT_EQ(0, visitor_.derive_next_key_count_);
EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_);
+ EXPECT_EQ(0u, framer_.PotentialPeerKeyUpdateAttemptCount());
header.packet_number += 1;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
@@ -14940,6 +14941,7 @@
EXPECT_EQ(0u, visitor_.key_update_count());
EXPECT_EQ(1, visitor_.derive_next_key_count_);
EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_);
+ EXPECT_EQ(1u, framer_.PotentialPeerKeyUpdateAttemptCount());
header.packet_number += 1;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
@@ -14954,6 +14956,7 @@
EXPECT_EQ(0u, visitor_.key_update_count());
EXPECT_EQ(1, visitor_.derive_next_key_count_);
EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_);
+ EXPECT_EQ(2u, framer_.PotentialPeerKeyUpdateAttemptCount());
header.packet_number += 1;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
@@ -14968,6 +14971,22 @@
EXPECT_EQ(0u, visitor_.key_update_count());
EXPECT_EQ(1, visitor_.derive_next_key_count_);
EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_);
+ EXPECT_EQ(2u, framer_.PotentialPeerKeyUpdateAttemptCount());
+
+ header.packet_number += 1;
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
+ data = BuildDataPacket(header, frames);
+ ASSERT_TRUE(data != nullptr);
+ encrypted = EncryptPacketWithTagAndPhase(*data, 0, false);
+ ASSERT_TRUE(encrypted);
+ QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
+ // Packet with phase=0 and key=0, should process and reset
+ // potential_peer_key_update_attempt_count_.
+ EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+ EXPECT_EQ(0u, visitor_.key_update_count());
+ EXPECT_EQ(1, visitor_.derive_next_key_count_);
+ EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_);
+ EXPECT_EQ(0u, framer_.PotentialPeerKeyUpdateAttemptCount());
}
TEST_P(QuicFramerTest, KeyUpdateReceivedWhenNotEnabled) {