gfe-relnote: In QUIC, add OnOneRttPacketAckowledged to TLS handshaker, and this is used to allow client mark handshake confirmed when handshake done frame is not supported. Not affecting prod, not protected.
PiperOrigin-RevId: 291363354
Change-Id: I2aa500244b1e443e17bc4585e983c666d5782afa
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 1522118..1082633 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -131,6 +131,7 @@
return QuicCryptoHandshaker::crypto_message_parser();
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
void OnHandshakeDoneReceived() override {}
MOCK_METHOD0(OnCanWrite, void());
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 2c3e43c..38b1dfb 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -1032,6 +1032,8 @@
QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
+ const bool one_rtt_packet_was_acked =
+ sent_packet_manager_.one_rtt_packet_acked();
const AckResult ack_result = sent_packet_manager_.OnAckFrameEnd(
time_of_last_received_packet_, last_header_.packet_number,
last_decrypted_packet_level_);
@@ -1044,6 +1046,10 @@
<< QuicUtils::AckResultToString(ack_result);
return false;
}
+ if (SupportsMultiplePacketNumberSpaces() && !one_rtt_packet_was_acked &&
+ sent_packet_manager_.one_rtt_packet_acked()) {
+ visitor_->OnOneRttPacketAcknowledged();
+ }
// 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 7fc528f..b060f87 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -175,6 +175,9 @@
// Called when a packet of encryption |level| has been successfully decrypted.
virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
+
+ // Called when a 1RTT packet has been acknowledged.
+ virtual void OnOneRttPacketAcknowledged() = 0;
};
// Interface which gets callbacks from the QuicConnection at interesting
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 0cb109e..4a041d1 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -1071,7 +1071,8 @@
EXPECT_CALL(visitor_, OnPacketReceived(_, _, _)).Times(AnyNumber());
EXPECT_CALL(visitor_, OnForwardProgressConfirmed()).Times(AnyNumber());
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber());
-
+ EXPECT_CALL(visitor_, OnOneRttPacketAcknowledged())
+ .Times(testing::AtMost(1));
EXPECT_CALL(*loss_algorithm_, GetLossTimeout())
.WillRepeatedly(Return(QuicTime::Zero()));
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
@@ -2669,10 +2670,16 @@
QuicAckFrame ack1 = InitAckFrame(1);
QuicAckFrame ack2 = InitAckFrame(2);
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+ if (connection_.SupportsMultiplePacketNumberSpaces()) {
+ EXPECT_CALL(visitor_, OnOneRttPacketAcknowledged()).Times(1);
+ }
ProcessAckPacket(2, &ack2);
// Should ack immediately since we have missing packets.
EXPECT_EQ(2u, writer_->packets_write_attempts());
+ if (connection_.SupportsMultiplePacketNumberSpaces()) {
+ EXPECT_CALL(visitor_, OnOneRttPacketAcknowledged()).Times(0);
+ }
ProcessAckPacket(1, &ack1);
// Should not ack an ack filling a missing packet.
EXPECT_EQ(2u, writer_->packets_write_attempts());
diff --git a/quic/core/quic_crypto_client_handshaker.h b/quic/core/quic_crypto_client_handshaker.h
index dc799fb..be3907d 100644
--- a/quic/core/quic_crypto_client_handshaker.h
+++ b/quic/core/quic_crypto_client_handshaker.h
@@ -47,6 +47,7 @@
CryptoMessageParser* crypto_message_parser() override;
HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
+ void OnOneRttPacketAcknowledged() override {}
void OnHandshakeDoneReceived() override;
// From QuicCryptoHandshaker
diff --git a/quic/core/quic_crypto_client_stream.cc b/quic/core/quic_crypto_client_stream.cc
index 92d396f..aa8c1b5 100644
--- a/quic/core/quic_crypto_client_stream.cc
+++ b/quic/core/quic_crypto_client_stream.cc
@@ -99,6 +99,10 @@
return handshaker_->chlo_hash();
}
+void QuicCryptoClientStream::OnOneRttPacketAcknowledged() {
+ handshaker_->OnOneRttPacketAcknowledged();
+}
+
void QuicCryptoClientStream::OnHandshakeDoneReceived() {
handshaker_->OnHandshakeDoneReceived();
}
diff --git a/quic/core/quic_crypto_client_stream.h b/quic/core/quic_crypto_client_stream.h
index fd81259..01f9612 100644
--- a/quic/core/quic_crypto_client_stream.h
+++ b/quic/core/quic_crypto_client_stream.h
@@ -121,6 +121,9 @@
// Returns current handshake state.
virtual HandshakeState GetHandshakeState() const = 0;
+ // Called when a 1RTT packet has been acknowledged.
+ virtual void OnOneRttPacketAcknowledged() = 0;
+
// Called when handshake done has been received.
virtual void OnHandshakeDoneReceived() = 0;
};
@@ -168,6 +171,7 @@
const override;
CryptoMessageParser* crypto_message_parser() override;
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override;
void OnHandshakeDoneReceived() override;
HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
diff --git a/quic/core/quic_crypto_server_stream.h b/quic/core/quic_crypto_server_stream.h
index 9f8d08d..3150036 100644
--- a/quic/core/quic_crypto_server_stream.h
+++ b/quic/core/quic_crypto_server_stream.h
@@ -175,6 +175,7 @@
const override;
CryptoMessageParser* crypto_message_parser() override;
void OnPacketDecrypted(EncryptionLevel level) override;
+ void OnOneRttPacketAcknowledged() override {}
void OnHandshakeDoneReceived() override;
HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
diff --git a/quic/core/quic_crypto_stream.h b/quic/core/quic_crypto_stream.h
index 66bd461..17474a8 100644
--- a/quic/core/quic_crypto_stream.h
+++ b/quic/core/quic_crypto_stream.h
@@ -85,6 +85,9 @@
// Called when a packet of encryption |level| has been successfully decrypted.
virtual void OnPacketDecrypted(EncryptionLevel level) = 0;
+ // Called when a 1RTT packet has been acknowledged.
+ virtual void OnOneRttPacketAcknowledged() = 0;
+
// Called when a handshake done frame has been received.
virtual void OnHandshakeDoneReceived() = 0;
diff --git a/quic/core/quic_crypto_stream_test.cc b/quic/core/quic_crypto_stream_test.cc
index dfbc6ef..1e1967c 100644
--- a/quic/core/quic_crypto_stream_test.cc
+++ b/quic/core/quic_crypto_stream_test.cc
@@ -57,6 +57,7 @@
return QuicCryptoHandshaker::crypto_message_parser();
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
void OnHandshakeDoneReceived() override {}
HandshakeState GetHandshakeState() const override { return HANDSHAKE_START; }
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index f4b7973..d9f501c 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -106,6 +106,7 @@
pto_exponential_backoff_start_point_(0),
pto_rttvar_multiplier_(4),
num_tlp_timeout_ptos_(0),
+ one_rtt_packet_acked_(false),
sanitize_ack_delay_(GetQuicReloadableFlag(quic_sanitize_ack_delay)) {
SetSendAlgorithm(congestion_control_type);
}
@@ -1233,6 +1234,9 @@
return PACKETS_ACKED_IN_WRONG_PACKET_NUMBER_SPACE;
}
last_ack_frame_.packets.Add(acked_packet.packet_number);
+ if (info->encryption_level == ENCRYPTION_FORWARD_SECURE) {
+ one_rtt_packet_acked_ = true;
+ }
largest_packet_peer_knows_is_acked_.UpdateMax(info->largest_acked);
if (supports_multiple_packet_number_spaces()) {
largest_packets_peer_knows_is_acked_[packet_number_space].UpdateMax(
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index fdbd697..d6c9b83 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -402,6 +402,8 @@
return skip_packet_number_for_pto_;
}
+ bool one_rtt_packet_acked() const { return one_rtt_packet_acked_; }
+
private:
friend class test::QuicConnectionPeer;
friend class test::QuicSentPacketManagerPeer;
@@ -639,6 +641,9 @@
// Number of PTOs similar to TLPs.
size_t num_tlp_timeout_ptos_;
+ // True if any 1-RTT packet gets acknowledged.
+ bool one_rtt_packet_acked_;
+
// Latched value of quic_sanitize_ack_delay.
const bool sanitize_ack_delay_;
};
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index e3dbf73..4ab9f6c 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -299,6 +299,10 @@
GetMutableCryptoStream()->OnPacketDecrypted(level);
}
+void QuicSession::OnOneRttPacketAcknowledged() {
+ GetMutableCryptoStream()->OnOneRttPacketAcknowledged();
+}
+
void QuicSession::PendingStreamOnRstStream(const QuicRstStreamFrame& frame) {
DCHECK(VersionUsesHttp3(transport_version()));
QuicStreamId stream_id = frame.stream_id;
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index bd19714..d951912 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -135,6 +135,7 @@
bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
void OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
void OnPacketDecrypted(EncryptionLevel level) override;
+ void OnOneRttPacketAcknowledged() override;
// QuicStreamFrameDataProducer
WriteStreamDataResult WriteStreamData(QuicStreamId id,
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 23cd87b..a287f55 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -115,6 +115,7 @@
return QuicCryptoHandshaker::crypto_message_parser();
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
void OnHandshakeDoneReceived() override {}
HandshakeState GetHandshakeState() const override {
return one_rtt_keys_available() ? HANDSHAKE_COMPLETE : HANDSHAKE_START;
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h
index 42dc050..fd49da2 100644
--- a/quic/core/quic_types.h
+++ b/quic/core/quic_types.h
@@ -736,10 +736,9 @@
// has both 1-RTT send and receive keys.
HANDSHAKE_COMPLETE,
// Only used in IETF QUIC with TLS handshake. State proceeds to
- // HANDSHAKE_CONFIRMED if a client receives HANDSHAKE_DONE frame or server has
+ // HANDSHAKE_CONFIRMED if 1) a client receives HANDSHAKE_DONE frame or
+ // acknowledgment for 1-RTT packet or 2) server has
// 1-RTT send and receive keys.
- // TODO(fayang): on the client side, proceed state to HANDSHAKE_CONFIRMED once
- // 1-RTT packet gets acknowledged..
HANDSHAKE_CONFIRMED,
};
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc
index 45d1849..42955ce 100644
--- a/quic/core/tls_client_handshaker.cc
+++ b/quic/core/tls_client_handshaker.cc
@@ -257,12 +257,21 @@
return TlsHandshaker::BufferSizeLimitForLevel(level);
}
+void TlsClientHandshaker::OnOneRttPacketAcknowledged() {
+ OnHandshakeConfirmed();
+}
+
void TlsClientHandshaker::OnHandshakeDoneReceived() {
if (!one_rtt_keys_available_) {
CloseConnection(QUIC_HANDSHAKE_FAILED,
"Unexpected handshake done received");
return;
}
+ OnHandshakeConfirmed();
+}
+
+void TlsClientHandshaker::OnHandshakeConfirmed() {
+ DCHECK(one_rtt_keys_available_);
if (handshake_confirmed_) {
return;
}
diff --git a/quic/core/tls_client_handshaker.h b/quic/core/tls_client_handshaker.h
index 4c7028a..5c5390f 100644
--- a/quic/core/tls_client_handshaker.h
+++ b/quic/core/tls_client_handshaker.h
@@ -51,6 +51,7 @@
CryptoMessageParser* crypto_message_parser() override;
HandshakeState GetHandshakeState() const override;
size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
+ void OnOneRttPacketAcknowledged() override;
void OnHandshakeDoneReceived() override;
// Override to drop initial keys if trying to write ENCRYPTION_HANDSHAKE data.
@@ -107,6 +108,10 @@
bool ProcessTransportParameters(std::string* error_details);
void FinishHandshake();
+ // Called when server completes handshake (i.e., either handshake done is
+ // received or 1-RTT packet gets acknowledged).
+ void OnHandshakeConfirmed();
+
void InsertSession(bssl::UniquePtr<SSL_SESSION> session) override;
QuicSession* session() { return session_; }
diff --git a/quic/core/tls_handshaker_test.cc b/quic/core/tls_handshaker_test.cc
index 12b3299..03a899f 100644
--- a/quic/core/tls_handshaker_test.cc
+++ b/quic/core/tls_handshaker_test.cc
@@ -181,6 +181,7 @@
}
void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
+ void OnOneRttPacketAcknowledged() override {}
HandshakeState GetHandshakeState() const override {
return handshaker()->GetHandshakeState();
diff --git a/quic/core/tls_server_handshaker.h b/quic/core/tls_server_handshaker.h
index 8215bb7..d377f4d 100644
--- a/quic/core/tls_server_handshaker.h
+++ b/quic/core/tls_server_handshaker.h
@@ -47,6 +47,7 @@
void SetPreviousCachedNetworkParams(
CachedNetworkParameters cached_network_params) override;
void OnPacketDecrypted(EncryptionLevel level) override;
+ void OnOneRttPacketAcknowledged() override {}
void OnHandshakeDoneReceived() override;
bool ShouldSendExpectCTHeader() const override;