Fix original issue of QNZR by only forcing the first CHLO to be inchoate.
Also replace the connection option with QNZ2.
Manually tested with netlog at https://drive.google.com/file/d/1WDFHBZJGy9ZM6hXwriyH3GEjvgdUVy4W/view?usp=sharing
Protected by client connection option QNZ2.
PiperOrigin-RevId: 338360564
Change-Id: I1cac9589006b59ff32dbd325e97ca77d70e2b6cb
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index b5ed5c7..50fa103 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -27,7 +27,8 @@
typedef std::string ServerConfigID;
// The following tags have been deprecated and should not be reused:
-// "1CON", "BBQ4", "NCON", "RCID", "SREJ", "TBKP", "TB10", "SCLS", "SMHL"
+// "1CON", "BBQ4", "NCON", "RCID", "SREJ", "TBKP", "TB10", "SCLS", "SMHL",
+// "QNZR"
// clang-format off
const QuicTag kCHLO = TAG('C', 'H', 'L', 'O'); // Client hello
@@ -369,7 +370,8 @@
const QuicTag kXLCT = TAG('X', 'L', 'C', 'T'); // Expected leaf certificate.
const QuicTag kQLVE = TAG('Q', 'L', 'V', 'E'); // Legacy Version
// Encapsulation.
-const QuicTag kQNZR = TAG('Q', 'N', 'Z', 'R'); // Turn off QUIC crypto 0-RTT.
+
+const QuicTag kQNZ2 = TAG('Q', 'N', 'Z', '2'); // Turn off QUIC crypto 0-RTT.
const QuicTag kQNSP = TAG('Q', 'N', 'S', 'P'); // Turn off server push in
// gQUIC.
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 3335b4a..6d579f5 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -2185,6 +2185,41 @@
server_thread_->Resume();
}
+// Regression test for b/171378845
+TEST_P(EndToEndTest, ClientDisablesGQuicZeroRtt) {
+ if (version_.UsesTls()) {
+ // This feature is gQUIC only.
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ QuicTagVector options;
+ options.push_back(kQNZ2);
+ client_config_.SetClientConnectionOptions(options);
+
+ ASSERT_TRUE(Initialize());
+
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+ QuicSpdyClientSession* client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_FALSE(client_session->EarlyDataAccepted());
+ EXPECT_FALSE(client_session->ReceivedInchoateReject());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->ReceivedInchoateReject());
+
+ client_->Disconnect();
+
+ // Make sure that the request succeeds but 0-RTT was not used.
+ client_->Connect();
+ EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable());
+ ASSERT_TRUE(client_->client()->connected());
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+
+ client_session = GetClientSession();
+ ASSERT_TRUE(client_session);
+ EXPECT_FALSE(client_session->EarlyDataAccepted());
+ EXPECT_FALSE(client_->client()->EarlyDataAccepted());
+}
+
TEST_P(EndToEndTest, MaxInitialRTT) {
// Client tries to suggest twice the server's max initial rtt and the server
// uses the max.
diff --git a/quic/core/quic_crypto_client_handshaker.cc b/quic/core/quic_crypto_client_handshaker.cc
index 784a451..f744153 100644
--- a/quic/core/quic_crypto_client_handshaker.cc
+++ b/quic/core/quic_crypto_client_handshaker.cc
@@ -317,7 +317,8 @@
early_data_reason_ = ssl_early_data_no_session_offered;
fill_inchoate_client_hello = true;
} else if (session()->config()->HasClientRequestedIndependentOption(
- kQNZR, session()->perspective())) {
+ kQNZ2, session()->perspective()) &&
+ num_client_hellos_ == 1) {
early_data_reason_ = ssl_early_data_disabled;
fill_inchoate_client_hello = true;
}
diff --git a/quic/core/quic_crypto_client_stream_test.cc b/quic/core/quic_crypto_client_stream_test.cc
index eef6b49..86fa3b8 100644
--- a/quic/core/quic_crypto_client_stream_test.cc
+++ b/quic/core/quic_crypto_client_stream_test.cc
@@ -69,7 +69,8 @@
void CompleteCryptoHandshake() {
int proof_verify_details_calls = 1;
if (stream()->handshake_protocol() != PROTOCOL_TLS1_3) {
- EXPECT_CALL(*session_, OnProofValid(testing::_));
+ EXPECT_CALL(*session_, OnProofValid(testing::_))
+ .Times(testing::AtLeast(1));
proof_verify_details_calls = 0;
}
EXPECT_CALL(*session_, OnProofVerifyDetailsAvailable(testing::_))
@@ -172,14 +173,13 @@
// Set connection option.
QuicTagVector options;
- options.push_back(kQNZR);
+ options.push_back(kQNZ2);
session_->config()->SetClientConnectionOptions(options);
- EXPECT_CALL(*session_, OnProofValid(testing::_));
- stream()->CryptoConnect();
- // Check that a client hello was sent.
- ASSERT_EQ(1u, connection_->encrypted_packets_.size());
- EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
+ CompleteCryptoHandshake();
+ // Check that two client hellos were sent, one inchoate and one normal.
+ EXPECT_EQ(2, stream()->num_sent_client_hellos());
+ EXPECT_FALSE(stream()->EarlyDataAccepted());
EXPECT_EQ(stream()->EarlyDataReason(), ssl_early_data_disabled);
}