Do not send control frames (by session) until encryption gets established.
Protected by FLAGS_quic_reloadable_flag_quic_encrypted_control_frames.
PiperOrigin-RevId: 339672390
Change-Id: I7bcab9157f05d92cbd74b4488957cabc0e7ea6fa
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 36ebf87..714c21d 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -85,6 +85,13 @@
params_->cipher_suite = 1;
}
+ void EstablishZeroRttEncryption() {
+ encryption_established_ = true;
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_ZERO_RTT,
+ std::make_unique<NullEncrypter>(session()->perspective()));
+ }
+
void OnHandshakeMessage(const CryptoHandshakeMessage& /*message*/) override {
encryption_established_ = true;
one_rtt_keys_available_ = true;
@@ -573,6 +580,7 @@
}
TEST_P(QuicSpdySessionTestServer, IsClosedStreamLocallyCreated) {
+ CompleteHandshake();
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id());
QuicSpdyStream* stream4 = session_.CreateOutgoingBidirectionalStream();
@@ -586,6 +594,7 @@
}
TEST_P(QuicSpdySessionTestServer, IsClosedStreamPeerCreated) {
+ CompleteHandshake();
QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0);
QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1);
session_.GetOrCreateStream(stream_id1);
@@ -988,6 +997,7 @@
}
TEST_P(QuicSpdySessionTestServer, OnCanWriteWithClosedStream) {
+ CompleteHandshake();
session_.set_writev_consumes_all_data(true);
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
TestStream* stream4 = session_.CreateOutgoingBidirectionalStream();
@@ -1065,6 +1075,7 @@
}
TEST_P(QuicSpdySessionTestServer, SendGoAway) {
+ CompleteHandshake();
if (VersionHasIetfQuicFrames(transport_version())) {
// HTTP/3 GOAWAY has different semantic and thus has its own test.
return;
@@ -1188,6 +1199,7 @@
}
TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
+ CompleteHandshake();
if (VersionHasIetfQuicFrames(transport_version())) {
// HTTP/3 GOAWAY doesn't have such restriction.
return;
@@ -1400,6 +1412,7 @@
// Ensure that Writev consumes all the data it is given (simulate no socket
// blocking).
+ session_.GetMutableCryptoStream()->EstablishZeroRttEncryption();
session_.set_writev_consumes_all_data(true);
// Create a stream, and send enough data to make it flow control blocked.
@@ -1426,9 +1439,12 @@
TEST_P(QuicSpdySessionTestServer,
HandshakeUnblocksFlowControlBlockedCryptoStream) {
- if (QuicVersionUsesCryptoFrames(transport_version())) {
+ if (QuicVersionUsesCryptoFrames(transport_version()) ||
+ connection_->encrypted_control_frames()) {
// QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
- // test doesn't make sense for those versions.
+ // test doesn't make sense for those versions. With
+ // use_encryption_level_context, control frames can only be sent when
+ // encryption gets established, do not send BLOCKED for crypto streams.
return;
}
// Test that if the crypto stream is flow control blocked, then if the SHLO
@@ -1498,6 +1514,7 @@
// Test that if the header stream is flow control blocked, then if the SHLO
// contains a larger send window offset, the stream becomes unblocked.
+ session_.GetMutableCryptoStream()->EstablishZeroRttEncryption();
session_.set_writev_consumes_all_data(true);
TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
@@ -1614,6 +1631,7 @@
if (!VersionUsesHttp3(transport_version())) {
return;
}
+ session_.GetMutableCryptoStream()->EstablishZeroRttEncryption();
QuicConfigPeer::SetReceivedMaxUnidirectionalStreams(session_.config(), 2u);
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -1629,7 +1647,6 @@
QuicTagVector copt;
copt.push_back(kIFW7);
QuicConfigPeer::SetReceivedConnectionOptions(session_.config(), copt);
-
connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
session_.OnConfigNegotiated();
EXPECT_EQ(192 * 1024u, QuicFlowControllerPeer::ReceiveWindowSize(
@@ -1668,6 +1685,7 @@
// If a buggy/malicious peer creates too many streams that are not ended
// with a FIN or RST then we send an RST to refuse streams for versions other
// than version 99. In version 99 the connection gets closed.
+ CompleteHandshake();
const QuicStreamId kMaxStreams = 5;
if (VersionHasIetfQuicFrames(transport_version())) {
QuicSessionPeer::SetMaxOpenIncomingBidirectionalStreams(&session_,
@@ -1722,6 +1740,7 @@
// Verify that a draining stream (which has received a FIN but not consumed
// it) does not count against the open quota (because it is closed from the
// protocol point of view).
+ CompleteHandshake();
if (VersionHasIetfQuicFrames(transport_version())) {
// Simulate receiving a config. so that MAX_STREAMS/etc frames may
// be transmitted
@@ -1907,6 +1926,7 @@
// Verify that an incoming FIN is recorded in a stream object even if the read
// side has been closed. This prevents an entry from being made in
// locally_closed_streams_highest_offset_ (which will never be deleted).
+ CompleteHandshake();
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
QuicStreamId stream_id = stream->id();
@@ -2111,6 +2131,7 @@
TEST_P(QuicSpdySessionTestServer, DonotRetransmitDataOfClosedStreams) {
// Resetting a stream will send a QPACK Stream Cancellation instruction on the
// decoder stream. For simplicity, ignore writes on this stream.
+ CompleteHandshake();
NoopQpackStreamSenderDelegate qpack_stream_sender_delegate;
if (VersionUsesHttp3(transport_version())) {
session_.qpack_decoder()->set_qpack_stream_sender_delegate(
@@ -2156,6 +2177,7 @@
}
TEST_P(QuicSpdySessionTestServer, RetransmitFrames) {
+ CompleteHandshake();
MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm);
InSequence s;
@@ -2274,7 +2296,7 @@
if (!VersionUsesHttp3(transport_version())) {
return;
}
-
+ CompleteHandshake();
char input[] = {0x04, // type
'a', 'b', 'c'}; // data
absl::string_view payload(input, ABSL_ARRAYSIZE(input));
@@ -2326,7 +2348,7 @@
if (!VersionUsesHttp3(transport_version())) {
return;
}
-
+ CompleteHandshake();
char input[] = {0x04, // type
'a', 'b', 'c'}; // data
absl::string_view payload(input, ABSL_ARRAYSIZE(input));
@@ -2367,7 +2389,7 @@
if (!VersionUsesHttp3(transport_version())) {
return;
}
-
+ CompleteHandshake();
char input[] = {0x41, 0x00, // type (256)
'a', 'b', 'c'}; // data
absl::string_view payload(input, ABSL_ARRAYSIZE(input));
@@ -2479,7 +2501,7 @@
if (!VersionUsesHttp3(transport_version())) {
return;
}
-
+ CompleteHandshake();
session_.qpack_decoder()->OnSetDynamicTableCapacity(1024);
QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
@@ -2546,6 +2568,7 @@
if (!VersionUsesHttp3(transport_version())) {
return;
}
+ CompleteHandshake();
ASSERT_TRUE(session_.UsesPendingStreams());
const QuicStreamId stream_id =
@@ -2592,6 +2615,7 @@
if (!VersionUsesHttp3(transport_version())) {
return;
}
+ CompleteHandshake();
ASSERT_TRUE(session_.UsesPendingStreams());
const QuicStreamId stream_id =