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_client_promised_info_test.cc b/quic/core/http/quic_client_promised_info_test.cc index 1a1ec69..9e21f41 100644 --- a/quic/core/http/quic_client_promised_info_test.cc +++ b/quic/core/http/quic_client_promised_info_test.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h" #include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" @@ -52,6 +53,11 @@ void set_authorized(bool authorized) { authorized_ = authorized; } + MOCK_METHOD(bool, + WriteControlFrame, + (const QuicFrame& frame, TransmissionType type), + (override)); + private: QuicCryptoClientConfig crypto_config_; @@ -73,6 +79,9 @@ promise_id_( QuicUtils::GetInvalidStreamId(connection_->transport_version())) { connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); + connection_->SetEncrypter( + ENCRYPTION_FORWARD_SECURE, + std::make_unique<NullEncrypter>(connection_->perspective())); session_.Initialize(); headers_[":status"] = "200"; @@ -142,7 +151,7 @@ ASSERT_NE(promised, nullptr); // Fire the alarm that will cancel the promised stream. - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_PUSH_STREAM_TIMED_OUT)); alarm_factory_.FireAlarm(QuicClientPromisedInfoPeer::GetAlarm(promised)); @@ -156,7 +165,7 @@ // Promise with an unsafe method push_promise_[":method"] = "PUT"; - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_METHOD)); ReceivePromise(promise_id_); @@ -170,7 +179,7 @@ // Promise with a missing method push_promise_.erase(":method"); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_METHOD)); ReceivePromise(promise_id_); @@ -184,7 +193,7 @@ // Remove required header field to make URL invalid push_promise_.erase(":authority"); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_INVALID_PROMISE_URL)); ReceivePromise(promise_id_); @@ -197,7 +206,7 @@ TEST_F(QuicClientPromisedInfoTest, PushPromiseUnauthorizedUrl) { session_.set_authorized(false); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_UNAUTHORIZED_PROMISE_URL)); @@ -222,7 +231,7 @@ headers); TestPushPromiseDelegate delegate(/*match=*/false); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_PROMISE_VARY_MISMATCH)); @@ -300,7 +309,7 @@ session_.GetOrCreateStream(promise_id_); // Cancel the promised stream. - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_STREAM_CANCELLED)); promised->Cancel(); @@ -323,7 +332,7 @@ promise_stream->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), headers); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(promise_id_, QUIC_STREAM_PEER_GOING_AWAY)); session_.ResetStream(promise_id_, QUIC_STREAM_PEER_GOING_AWAY);
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc index 8cfa01b..4abde42 100644 --- a/quic/core/http/quic_server_session_base_test.cc +++ b/quic/core/http/quic_server_session_base_test.cc
@@ -71,6 +71,11 @@ ~TestServerSession() override { DeleteConnection(); } + MOCK_METHOD(bool, + WriteControlFrame, + (const QuicFrame& frame, TransmissionType type), + (override)); + protected: QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override { if (!ShouldCreateIncomingStream(id)) { @@ -147,6 +152,9 @@ connection_ = new StrictMock<MockQuicConnection>( &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions); connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); + connection_->SetEncrypter( + ENCRYPTION_FORWARD_SECURE, + std::make_unique<NullEncrypter>(connection_->perspective())); session_ = std::make_unique<TestServerSession>( config_, connection_, &owner_, &stream_helper_, &crypto_config_, &compressed_certs_cache_, &memory_cache_backend_); @@ -193,7 +201,7 @@ EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1); // Expect the RESET_STREAM that is generated in response to receiving a // STOP_SENDING. - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_ERROR_PROCESSING_STREAM)); session_->OnStopSendingFrame(stop_sending); @@ -249,7 +257,7 @@ if (!VersionHasIetfQuicFrames(transport_version())) { // For non-version 99, the RESET_STREAM will do the full close. // Set up expects accordingly. - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); @@ -278,7 +286,7 @@ if (!VersionHasIetfQuicFrames(transport_version())) { // For non-version 99, the RESET_STREAM will do the full close. // Set up expects accordingly. - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); @@ -318,7 +326,7 @@ if (!VersionHasIetfQuicFrames(transport_version())) { // For non-version 99, the RESET_STREAM will do the full close. // Set up expects accordingly. - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); @@ -348,9 +356,6 @@ // streams. For versions other than version 99, the server accepts slightly // more than the negotiated stream limit to deal with rare cases where a // client FIN/RST is lost. - connection_->SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypter>(session_->perspective())); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); session_->OnConfigNegotiated(); if (!VersionHasIetfQuicFrames(transport_version())) { @@ -387,7 +392,7 @@ // For non-version 99, QUIC responds to an attempt to exceed the stream // limit by resetting the stream. EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(stream_id, QUIC_REFUSED_STREAM)); } else { // In version 99 QUIC responds to an attempt to exceed the stream limit by @@ -403,9 +408,6 @@ // Test that the server closes the connection if a client makes too many data // streams available. The server accepts slightly more than the negotiated // stream limit to deal with rare cases where a client FIN/RST is lost. - connection_->SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypter>(session_->perspective())); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); session_->OnConfigNegotiated(); const size_t kAvailableStreamLimit = @@ -512,9 +514,6 @@ QuicTagVector copt; copt.push_back(kBWRE); QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); - connection_->SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypter>(session_->perspective())); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); session_->OnConfigNegotiated(); EXPECT_TRUE( @@ -706,9 +705,6 @@ QuicTagVector copt; copt.push_back(kBWMX); QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); - connection_->SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypter>(session_->perspective())); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); session_->OnConfigNegotiated(); EXPECT_TRUE( @@ -718,9 +714,6 @@ TEST_P(QuicServerSessionBaseTest, NoBandwidthResumptionByDefault) { EXPECT_FALSE( QuicServerSessionBasePeer::IsBandwidthResumptionEnabled(session_.get())); - connection_->SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypter>(session_->perspective())); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); session_->OnConfigNegotiated(); EXPECT_FALSE( @@ -736,9 +729,6 @@ QuicTagVector copt; copt.push_back(kQNSP); QuicConfigPeer::SetReceivedConnectionOptions(session_->config(), copt); - connection_->SetEncrypter( - ENCRYPTION_FORWARD_SECURE, - std::make_unique<NullEncrypter>(session_->perspective())); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); session_->OnConfigNegotiated(); EXPECT_FALSE(session_->server_push_enabled());
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc index 18e8712..c8bae78 100644 --- a/quic/core/http/quic_spdy_client_session_test.cc +++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -766,6 +766,7 @@ } TEST_P(QuicSpdyClientSessionTest, ReceivingPromiseEnhanceYourCalm) { + CompleteCryptoHandshake(); for (size_t i = 0u; i < session_->get_max_promises(); i++) { push_promise_[":path"] = quiche::QuicheStringPrintf("/bar%zu", i);
diff --git a/quic/core/http/quic_spdy_client_stream_test.cc b/quic/core/http/quic_spdy_client_stream_test.cc index c8653ed..90d4ee1 100644 --- a/quic/core/http/quic_spdy_client_stream_test.cc +++ b/quic/core/http/quic_spdy_client_stream_test.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" #include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h" #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" @@ -46,6 +47,11 @@ delete; ~MockQuicSpdyClientSession() override = default; + MOCK_METHOD(bool, + WriteControlFrame, + (const QuicFrame& frame, TransmissionType type), + (override)); + using QuicSession::ActivateStream; private: @@ -68,7 +74,9 @@ body_("hello world") { session_.Initialize(); connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); - + connection_->SetEncrypter( + ENCRYPTION_FORWARD_SECURE, + std::make_unique<NullEncrypter>(connection_->perspective())); headers_[":status"] = "200"; headers_["content-length"] = "11"; @@ -109,7 +117,7 @@ TEST_P(QuicSpdyClientStreamTest, TestReceivingIllegalResponseStatusCode) { headers_[":status"] = "200 ok"; - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD)); auto headers = AsHeaderList(headers_); @@ -200,7 +208,7 @@ // 101 "Switching Protocols" is forbidden in HTTP/3 as per the // "HTTP Upgrade" section of draft-ietf-quic-http. headers_[":status"] = "101"; - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD)); auto headers = AsHeaderList(headers_); @@ -246,7 +254,7 @@ std::string data = VersionUsesHttp3(connection_->transport_version()) ? header + large_body : large_body; - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(session_, WriteControlFrame(_, _)); EXPECT_CALL(*connection_, OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD));
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 =
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index f493598..db6facf 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -349,7 +349,10 @@ clock_->ApproximateNow(), &arena_, alarm_factory_), - support_handshake_done_(version().HasHandshakeDone()) { + support_handshake_done_(version().HasHandshakeDone()), + encrypted_control_frames_( + GetQuicReloadableFlag(quic_encrypted_control_frames) && + packet_creator_.let_connection_handle_pings()) { QUIC_BUG_IF(!start_peer_migration_earlier_ && send_path_response_); if (GetQuicReloadableFlag(quic_connection_set_initial_self_address)) { DCHECK(perspective_ == Perspective::IS_CLIENT || @@ -1840,8 +1843,8 @@ if (!should_last_packet_instigate_acks_) { uber_received_packet_manager_.MaybeUpdateAckTimeout( should_last_packet_instigate_acks_, last_decrypted_packet_level_, - last_header_.packet_number, - clock_->ApproximateNow(), sent_packet_manager_.GetRttStats()); + last_header_.packet_number, clock_->ApproximateNow(), + sent_packet_manager_.GetRttStats()); } ClearLastFrames(); @@ -5342,8 +5345,8 @@ should_last_packet_instigate_acks_ = true; uber_received_packet_manager_.MaybeUpdateAckTimeout( /*should_last_packet_instigate_acks=*/true, last_decrypted_packet_level_, - last_header_.packet_number, - clock_->ApproximateNow(), sent_packet_manager_.GetRttStats()); + last_header_.packet_number, clock_->ApproximateNow(), + sent_packet_manager_.GetRttStats()); } QuicTime QuicConnection::GetPathDegradingDeadline() const {
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h index 45eb1cb..681a64a 100644 --- a/quic/core/quic_connection.h +++ b/quic/core/quic_connection.h
@@ -1127,6 +1127,8 @@ bool is_processing_packet() const { return framer_.is_processing_packet(); } + bool encrypted_control_frames() const { return encrypted_control_frames_; } + protected: // Calls cancel() on all the alarms owned by this connection. void CancelAllAlarms(); @@ -1926,6 +1928,8 @@ const bool check_keys_before_writing_ = GetQuicReloadableFlag(quic_check_keys_before_writing); + + bool encrypted_control_frames_; }; } // namespace quic
diff --git a/quic/core/quic_control_frame_manager_test.cc b/quic/core/quic_control_frame_manager_test.cc index cf90e90..68658bb 100644 --- a/quic/core/quic_control_frame_manager_test.cc +++ b/quic/core/quic_control_frame_manager_test.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" #include "net/third_party/quiche/src/quic/core/frames/quic_ack_frequency_frame.h" #include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" @@ -37,7 +38,7 @@ class QuicControlFrameManagerTest : public QuicTest { public: - bool SaveControlFrame(const QuicFrame& frame) { + bool SaveControlFrame(const QuicFrame& frame, TransmissionType /*type*/) { frame_ = frame; return true; } @@ -54,13 +55,16 @@ void Initialize() { connection_ = new MockQuicConnection(&helper_, &alarm_factory_, Perspective::IS_SERVER); + connection_->SetEncrypter( + ENCRYPTION_FORWARD_SECURE, + std::make_unique<NullEncrypter>(connection_->perspective())); session_ = std::make_unique<StrictMock<MockQuicSession>>(connection_); manager_ = std::make_unique<QuicControlFrameManager>(session_.get()); EXPECT_EQ(0u, QuicControlFrameManagerPeer::QueueSize(manager_.get())); EXPECT_FALSE(manager_->HasPendingRetransmission()); EXPECT_FALSE(manager_->WillingToWrite()); - EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); manager_->WriteOrBufferRstStream(kTestStreamId, QUIC_STREAM_CANCELLED, 0); manager_->WriteOrBufferGoAway(QUIC_PEER_GOING_AWAY, kTestStreamId, "Going away."); @@ -103,10 +107,10 @@ TEST_F(QuicControlFrameManagerTest, OnControlFrameAcked) { Initialize(); InSequence s; - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(3) - .WillRepeatedly(Invoke(&ClearControlFrame)); - EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); // Send control frames 1, 2, 3. manager_->OnCanWrite(); EXPECT_TRUE(manager_->IsControlFrameOutstanding(QuicFrame(&rst_stream_))); @@ -139,8 +143,8 @@ EXPECT_TRUE(manager_->WillingToWrite()); // Send control frames 4, 5. - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillRepeatedly(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); manager_->WritePing(); EXPECT_FALSE(manager_->WillingToWrite()); @@ -149,10 +153,10 @@ TEST_F(QuicControlFrameManagerTest, OnControlFrameLost) { Initialize(); InSequence s; - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(3) - .WillRepeatedly(Invoke(&ClearControlFrame)); - EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); // Send control frames 1, 2, 3. manager_->OnCanWrite(); @@ -166,17 +170,17 @@ manager_->OnControlFrameAcked(QuicFrame(&goaway_)); // Retransmit control frames 1, 3. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(2) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); EXPECT_FALSE(manager_->HasPendingRetransmission()); EXPECT_TRUE(manager_->WillingToWrite()); // Send control frames 4, 5, and 6. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(number_of_frames_ - 2u) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); manager_->WritePing(); EXPECT_FALSE(manager_->WillingToWrite()); @@ -186,26 +190,26 @@ Initialize(); InSequence s; // Send control frames 1, 2, 3, 4. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(number_of_frames_) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); // Ack control frame 2. manager_->OnControlFrameAcked(QuicFrame(&goaway_)); - // Do not retransmit an acked frame. - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0); + // Do not retransmit an acked frame + EXPECT_CALL(*session_, WriteControlFrame(_, _)).Times(0); EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&goaway_), PTO_RETRANSMISSION)); // Retransmit control frame 3. - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&window_update_), PTO_RETRANSMISSION)); // Retransmit control frame 4, and connection is write blocked. - EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); EXPECT_FALSE(manager_->RetransmitControlFrame(QuicFrame(&window_update_), PTO_RETRANSMISSION)); } @@ -213,9 +217,9 @@ TEST_F(QuicControlFrameManagerTest, DonotSendPingWithBufferedFrames) { Initialize(); InSequence s; - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); - EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); // Send control frame 1. manager_->OnCanWrite(); EXPECT_FALSE(manager_->HasPendingRetransmission()); @@ -224,9 +228,9 @@ // Send PING when there is buffered frames. manager_->WritePing(); // Verify only the buffered frames are sent. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(number_of_frames_ - 1) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); EXPECT_FALSE(manager_->HasPendingRetransmission()); EXPECT_FALSE(manager_->WillingToWrite()); @@ -236,10 +240,10 @@ Initialize(); InSequence s; // Send Non-AckFrequency frame 1-5. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(5) - .WillRepeatedly(Invoke(&ClearControlFrame)); - EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); manager_->OnCanWrite(); // Send AckFrequencyFrame as frame 6. @@ -247,8 +251,8 @@ frame_to_send.packet_tolerance = 10; frame_to_send.max_ack_delay = QuicTime::Delta::FromMilliseconds(24); manager_->WriteOrBufferAckFrequency(frame_to_send); - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); // Ack AckFrequencyFrame. @@ -270,8 +274,8 @@ 300); InSequence s; // Flush all buffered control frames. - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillRepeatedly(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); // Mark all 3 window updates as lost. @@ -282,7 +286,7 @@ EXPECT_TRUE(manager_->WillingToWrite()); // Verify only the latest window update gets retransmitted. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .WillOnce(Invoke(this, &QuicControlFrameManagerTest::SaveControlFrame)); manager_->OnCanWrite(); EXPECT_EQ(number_of_frames_ + 2u, @@ -302,8 +306,8 @@ QuicWindowUpdateFrame window_update3(6, kTestStreamId + 4, 300); InSequence s; // Flush all buffered control frames. - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillRepeatedly(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); // Mark all 3 window updates as lost. @@ -314,9 +318,9 @@ EXPECT_TRUE(manager_->WillingToWrite()); // Verify all 3 window updates get retransmitted. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(3) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); manager_->OnCanWrite(); EXPECT_FALSE(manager_->HasPendingRetransmission()); EXPECT_FALSE(manager_->WillingToWrite()); @@ -324,13 +328,13 @@ TEST_F(QuicControlFrameManagerTest, TooManyBufferedControlFrames) { Initialize(); - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(5) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); // Flush buffered frames. manager_->OnCanWrite(); // Write 995 control frames. - EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).WillOnce(Return(false)); for (size_t i = 0; i < 995; ++i) { manager_->WriteOrBufferRstStream(kTestStreamId, QUIC_STREAM_CANCELLED, 0); }
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h index 0526112..e06a766 100644 --- a/quic/core/quic_flags_list.h +++ b/quic/core/quic_flags_list.h
@@ -4,80 +4,81 @@ // This file is autogenerated by the QUICHE Copybara export script. -QUIC_FLAG(FLAGS_quic_reloadable_flag_send_quic_fallback_server_config_on_leto_error, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reject_spdy_settings, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_fast_huffman_encoder, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_false, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_true, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_goaway_with_connection_close, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_timestamps, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reject_spdy_frames, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_split_up_send_rst, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_stop_sending_uses_ietf_error_code, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_version_negotiation_for_short_connection_ids, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_record_received_min_ack_delay, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_start_peer_migration_earlier, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_process_undecryptable_packets_after_async_decrypt_callback, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_let_connection_handle_pings, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_granular_qpack_error_codes, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_key_update_supported, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_http3_new_default_urgency_value, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_out_of_order_sending2, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_undecryptable_packets2, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_missing_initial_keys2, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_arm_pto_for_application_data, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_give_sent_packet_to_debug_visitor_after_sent, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_aead_limits, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_pto_pending_timer_count, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_willing_and_able_to_write2, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_http3_goaway_stream_id, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_do_not_clip_received_error_code, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_address_validation, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q043, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_27, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q050, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_t051, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_29, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_t050, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q046, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_server_blackhole_detection, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_delay_initial_ack, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_copy_bbr_cwnd_to_bbr2, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr_v2, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_deallocate_message_right_after_sent, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_2_rttvar, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_in_on_can_write_with_blocked_writer, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_on_pto, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_use_tcp_inflight_hi_headroom, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_check_keys_before_writing, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_support_max_bootstrap_cwnd, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_set_initial_self_address, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_clean_up_spdy_session_destructor, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_use_post_inflight_to_detect_queuing, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_no_exit_startup_on_loss_with_bw_growth, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_startup_loss_exit_use_max_delivered, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fewer_startup_round_trips, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_limit_inflight_hi, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ack_delay_alarm_granularity, false) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true) -QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_close, true) -QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_true, true) QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_false, false) QUIC_FLAG(FLAGS_quic_restart_flag_quic_support_release_time_for_gso, false) QUIC_FLAG(FLAGS_quic_restart_flag_quic_session_tickets_always_enabled, false) QUIC_FLAG(FLAGS_quic_restart_flag_quic_enable_zero_rtt_for_tls_v2, true) +QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_true, true) QUIC_FLAG(FLAGS_quic_restart_flag_quic_offload_pacing_to_usps2, false) QUIC_FLAG(FLAGS_quic_restart_flag_dont_fetch_quic_private_keys_from_leto, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_pto_pending_timer_count, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_out_of_order_sending2, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_split_up_send_rst, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_missing_initial_keys2, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_goaway_with_connection_close, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_send_quic_fallback_server_config_on_leto_error, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_true, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_stop_sending_uses_ietf_error_code, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_fast_huffman_encoder, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_start_peer_migration_earlier, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_version_negotiation_for_short_connection_ids, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_timestamps, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_false, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reject_spdy_frames, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_process_undecryptable_packets_after_async_decrypt_callback, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_record_received_min_ack_delay, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reject_spdy_settings, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_close, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_let_connection_handle_pings, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_key_update_supported, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_http3_new_default_urgency_value, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_willing_and_able_to_write2, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_granular_qpack_error_codes, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_give_sent_packet_to_debug_visitor_after_sent, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_undecryptable_packets2, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_http3_goaway_stream_id, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_arm_pto_for_application_data, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_address_validation, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_encrypted_control_frames, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_aead_limits, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_do_not_clip_received_error_code, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_t051, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_t050, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q050, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q046, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q043, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_29, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_27, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr_v2, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_server_blackhole_detection, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_delay_initial_ack, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_2_rttvar, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_on_pto, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_deallocate_message_right_after_sent, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_copy_bbr_cwnd_to_bbr2, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_set_initial_self_address, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_in_on_can_write_with_blocked_writer, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_clean_up_spdy_session_destructor, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_check_keys_before_writing, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_use_tcp_inflight_hi_headroom, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_use_post_inflight_to_detect_queuing, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_support_max_bootstrap_cwnd, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_startup_loss_exit_use_max_delivered, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_limit_inflight_hi, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_no_exit_startup_on_loss_with_bw_growth, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fewer_startup_round_trips, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, false) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true) +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ack_delay_alarm_granularity, false)
diff --git a/quic/core/quic_flow_controller_test.cc b/quic/core/quic_flow_controller_test.cc index 29a9ba3..5a27570 100644 --- a/quic/core/quic_flow_controller_test.cc +++ b/quic/core/quic_flow_controller_test.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h" @@ -39,6 +40,9 @@ void Initialize() { connection_ = new MockQuicConnection(&helper_, &alarm_factory_, Perspective::IS_CLIENT); + connection_->SetEncrypter( + ENCRYPTION_FORWARD_SECURE, + std::make_unique<NullEncrypter>(connection_->perspective())); session_ = std::make_unique<MockQuicSession>(connection_); flow_controller_ = std::make_unique<QuicFlowController>( session_.get(), stream_id_, /*is_connection_flow_controller*/ false, @@ -115,7 +119,7 @@ QuicFlowControllerPeer::ReceiveWindowSize(flow_controller_.get())); // Consume enough bytes to send a WINDOW_UPDATE frame. - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).Times(1); flow_controller_->AddBytesConsumed(1 + receive_window_ / 2); @@ -185,7 +189,7 @@ should_auto_tune_receive_window_ = true; Initialize(); // This test will generate two WINDOW_UPDATE frames. - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).Times(1); EXPECT_TRUE(flow_controller_->auto_tune_receive_window()); // Make sure clock is inititialized. @@ -237,9 +241,9 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesFastNoAutoTune) { Initialize(); // This test will generate two WINDOW_UPDATE frames. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(2) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); EXPECT_FALSE(flow_controller_->auto_tune_receive_window()); // Make sure clock is inititialized. @@ -292,7 +296,7 @@ should_auto_tune_receive_window_ = true; Initialize(); // This test will generate two WINDOW_UPDATE frames. - EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1); + EXPECT_CALL(*session_, WriteControlFrame(_, _)).Times(1); EXPECT_TRUE(flow_controller_->auto_tune_receive_window()); // Make sure clock is inititialized. @@ -347,9 +351,9 @@ TEST_F(QuicFlowControllerTest, ReceivingBytesNormalNoAutoTune) { Initialize(); // This test will generate two WINDOW_UPDATE frames. - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(2) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); EXPECT_FALSE(flow_controller_->auto_tune_receive_window()); // Make sure clock is inititialized.
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index 5079b46..5f1c5ef 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -804,6 +804,14 @@ TransmissionType type) { DCHECK(connection()->connected()) << ENDPOINT << "Try to write control frames when connection is closed."; + if (connection_->encrypted_control_frames()) { + QUIC_RELOADABLE_FLAG_COUNT(quic_encrypted_control_frames); + if (!IsEncryptionEstablished()) { + QUIC_BUG << ENDPOINT << "Tried to send control frame " << frame + << " before encryption is established."; + return false; + } + } SetTransmissionType(type); return connection_->SendControlFrame(frame); }
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc index 738ee0b..129c937 100644 --- a/quic/core/quic_session_test.cc +++ b/quic/core/quic_session_test.cc
@@ -70,6 +70,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; @@ -715,6 +722,7 @@ } TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamLocallyCreated) { + CompleteHandshake(); TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); EXPECT_EQ(GetNthServerInitiatedBidirectionalId(0), stream2->id()); TestStream* stream4 = session_.CreateOutgoingBidirectionalStream(); @@ -728,6 +736,7 @@ } TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamLocallyCreated) { + CompleteHandshake(); TestStream* stream2 = session_.CreateOutgoingUnidirectionalStream(); EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(0), stream2->id()); TestStream* stream4 = session_.CreateOutgoingUnidirectionalStream(); @@ -741,6 +750,7 @@ } TEST_P(QuicSessionTestServer, IsClosedBidirectionalStreamPeerCreated) { + CompleteHandshake(); QuicStreamId stream_id1 = GetNthClientInitiatedBidirectionalId(0); QuicStreamId stream_id2 = GetNthClientInitiatedBidirectionalId(1); session_.GetOrCreateStream(stream_id1); @@ -761,6 +771,7 @@ } TEST_P(QuicSessionTestServer, IsClosedUnidirectionalStreamPeerCreated) { + CompleteHandshake(); QuicStreamId stream_id1 = GetNthClientInitiatedUnidirectionalId(0); QuicStreamId stream_id2 = GetNthClientInitiatedUnidirectionalId(1); session_.GetOrCreateStream(stream_id1); @@ -923,6 +934,7 @@ } TEST_P(QuicSessionTestServer, DebugDFatalIfMarkingClosedStreamWriteBlocked) { + CompleteHandshake(); TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); QuicStreamId closed_stream_id = stream2->id(); // Close the stream. @@ -1278,6 +1290,7 @@ if (!VersionHasIetfQuicFrames(transport_version())) { return; } + CompleteHandshake(); for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; ++i) { ASSERT_TRUE(session_.CanOpenNextOutgoingBidirectionalStream()); session_.GetNextOutgoingBidirectionalStreamId(); @@ -1363,6 +1376,7 @@ } TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) { + CompleteHandshake(); session_.set_writev_consumes_all_data(true); TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); TestStream* stream4 = session_.CreateOutgoingBidirectionalStream(); @@ -1432,6 +1446,7 @@ // In IETF QUIC, GOAWAY lives up in the HTTP layer. return; } + CompleteHandshake(); connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); MockPacketWriter* writer = static_cast<MockPacketWriter*>( QuicConnectionPeer::GetWriter(session_.connection())); @@ -1453,6 +1468,7 @@ } TEST_P(QuicSessionTestServer, DoNotSendGoAwayTwice) { + CompleteHandshake(); if (VersionHasIetfQuicFrames(transport_version())) { // In IETF QUIC, GOAWAY lives up in the HTTP layer. return; @@ -1554,12 +1570,7 @@ TEST_P(QuicSessionTestServer, IncreasedTimeoutAfterCryptoHandshake) { EXPECT_EQ(kInitialIdleTimeoutSecs + 3, QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); - if (connection_->version().HasHandshakeDone()) { - EXPECT_CALL(*connection_, SendControlFrame(_)); - } - CryptoHandshakeMessage msg; - connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); + CompleteHandshake(); EXPECT_EQ(kMaximumIdleTimeoutSecs + 3, QuicConnectionPeer::GetNetworkTimeout(connection_).ToSeconds()); } @@ -1621,6 +1632,7 @@ // Ensure that Writev consumes all the data it is given (simulate no socket // blocking). session_.set_writev_consumes_all_data(true); + session_.GetMutableCryptoStream()->EstablishZeroRttEncryption(); // Create a stream, and send enough data to make it flow control blocked. TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); @@ -1636,8 +1648,7 @@ // Now complete the crypto handshake, resulting in an increased flow control // send window. - CryptoHandshakeMessage msg; - session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); + CompleteHandshake(); EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(&session_, stream2->id())); // Stream is now unblocked. EXPECT_FALSE(stream2->IsFlowControlBlocked()); @@ -1646,7 +1657,8 @@ } TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) { - if (QuicVersionUsesCryptoFrames(GetParam().transport_version)) { + if (QuicVersionUsesCryptoFrames(GetParam().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 since CRYPTO frames aren't // flow controlled. @@ -1684,8 +1696,7 @@ // Now complete the crypto handshake, resulting in an increased flow control // send window. - CryptoHandshakeMessage msg; - session_.GetMutableCryptoStream()->OnHandshakeMessage(msg); + CompleteHandshake(); EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked( &session_, QuicUtils::GetCryptoStreamId(connection_->transport_version()))); @@ -1696,6 +1707,7 @@ } TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) { + CompleteHandshake(); // Test that when we receive an out of order stream RST we correctly adjust // our connection level flow control receive window. // On close, the stream should mark as consumed all bytes between the highest @@ -1725,6 +1737,7 @@ } TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAndLocalReset) { + CompleteHandshake(); // Test the situation where we receive a FIN on a stream, and before we fully // consume all the data from the sequencer buffer we locally RST the stream. // The bytes between highest consumed byte, and the final byte offset that we @@ -1751,6 +1764,7 @@ } TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingFinAfterRst) { + CompleteHandshake(); // Test that when we RST the stream (and tear down stream state), and then // receive a FIN from the peer, we correctly adjust our connection level flow // control receive window. @@ -1790,6 +1804,7 @@ } TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstAfterRst) { + CompleteHandshake(); // Test that when we RST the stream (and tear down stream state), and then // receive a RST from the peer, we correctly adjust our connection level flow // control receive window. @@ -1855,6 +1870,7 @@ } TEST_P(QuicSessionTestServer, FlowControlWithInvalidFinalOffset) { + CompleteHandshake(); // Test that if we receive a stream RST with a highest byte offset that // violates flow control, that we close the connection. const uint64_t kLargeOffset = kInitialSessionFlowControlWindowForTest + 1; @@ -1877,6 +1893,7 @@ } TEST_P(QuicSessionTestServer, TooManyUnfinishedStreamsCauseServerRejectStream) { + CompleteHandshake(); // 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 IETF QUIC the // connection is closed. @@ -1919,6 +1936,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(); TestStream* stream = session_.CreateOutgoingBidirectionalStream(); QuicStreamId stream_id = stream->id(); QuicStreamFrame data1(stream_id, true, 0, absl::string_view("HT")); @@ -2030,6 +2048,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())) { // On IETF QUIC, we will expect to see a MAX_STREAMS go out when there are // not enough streams to create the next one. @@ -2186,6 +2205,7 @@ } TEST_P(QuicSessionTestClient, RecordFinAfterReadSideClosed) { + CompleteHandshake(); // 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). @@ -2291,6 +2311,7 @@ } TEST_P(QuicSessionTestServer, ZombieStreams) { + CompleteHandshake(); TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); QuicStreamPeer::SetStreamBytesWritten(3, stream2); EXPECT_TRUE(stream2->IsWaitingForAcks()); @@ -2304,6 +2325,7 @@ } TEST_P(QuicSessionTestServer, RstStreamReceivedAfterRstStreamSent) { + CompleteHandshake(); TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); QuicStreamPeer::SetStreamBytesWritten(3, stream2); EXPECT_TRUE(stream2->IsWaitingForAcks()); @@ -2323,6 +2345,7 @@ // Regression test of b/71548958. TEST_P(QuicSessionTestServer, TestZombieStreams) { + CompleteHandshake(); session_.set_writev_consumes_all_data(true); TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); @@ -2455,6 +2478,7 @@ } TEST_P(QuicSessionTestServer, DonotRetransmitDataOfClosedStreams) { + CompleteHandshake(); InSequence s; TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); @@ -2494,6 +2518,7 @@ } TEST_P(QuicSessionTestServer, RetransmitFrames) { + CompleteHandshake(); MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>; QuicConnectionPeer::SetSendAlgorithm(session_.connection(), send_algorithm); InSequence s; @@ -2530,6 +2555,7 @@ // Regression test of b/110082001. TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) { + CompleteHandshake(); // This test mimics the scenario when a dynamic stream retransmits lost data // and causes connection close. TestStream* stream = session_.CreateOutgoingBidirectionalStream(); @@ -2568,13 +2594,7 @@ MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(), "", &storage))); - // Finish handshake. - if (connection_->version().HasHandshakeDone()) { - EXPECT_CALL(*connection_, SendControlFrame(_)); - } - CryptoHandshakeMessage handshake_message; - connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - session_.GetMutableCryptoStream()->OnHandshakeMessage(handshake_message); + CompleteHandshake(); EXPECT_TRUE(session_.OneRttKeysAvailable()); absl::string_view message; @@ -2615,6 +2635,7 @@ // Regression test of b/115323618. TEST_P(QuicSessionTestServer, LocallyResetZombieStreams) { + CompleteHandshake(); session_.set_writev_consumes_all_data(true); TestStream* stream2 = session_.CreateOutgoingBidirectionalStream(); std::string body(100, '.'); @@ -2644,6 +2665,7 @@ } TEST_P(QuicSessionTestServer, CleanUpClosedStreamsAlarm) { + CompleteHandshake(); EXPECT_FALSE( QuicSessionPeer::GetCleanUpClosedStreamsAlarm(&session_)->IsSet()); @@ -2916,7 +2938,7 @@ if (!VersionHasIetfQuicFrames(transport_version())) { return; } - + CompleteHandshake(); TestStream* stream = session_.CreateOutgoingBidirectionalStream(); QuicStreamId stream_id = stream->id(); CloseStream(stream_id); @@ -2943,6 +2965,7 @@ // If a STOP_SENDING is received for a peer initiated stream, the new stream // will be created. TEST_P(QuicSessionTestServer, OnStopSendingNewStream) { + CompleteHandshake(); if (!VersionHasIetfQuicFrames(transport_version())) { return; } @@ -2962,6 +2985,7 @@ // For a valid stream, ensure that all works TEST_P(QuicSessionTestServer, OnStopSendingInputValidStream) { + CompleteHandshake(); if (!VersionHasIetfQuicFrames(transport_version())) { // Applicable only to IETF QUIC return; @@ -3027,6 +3051,7 @@ } TEST_P(QuicSessionTestServer, ResetForIETFStreamTypes) { + CompleteHandshake(); if (!VersionHasIetfQuicFrames(transport_version())) { return; }
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc index d6ad3f8..563a7fd 100644 --- a/quic/core/quic_stream_test.cc +++ b/quic/core/quic_stream_test.cc
@@ -621,9 +621,9 @@ EXPECT_CALL(*connection_, CloseConnection(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA, _, _)) .Times(0); - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(AtLeast(1)) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); std::string data(1000, 'x'); for (QuicStreamOffset offset = 0; @@ -951,9 +951,9 @@ EXPECT_TRUE(session_->HasUnackedStreamData()); EXPECT_CALL(*connection_, OnStreamReset(stream_->id(), QUIC_STREAM_CANCELLED)); - EXPECT_CALL(*connection_, SendControlFrame(_)) + EXPECT_CALL(*session_, WriteControlFrame(_, _)) .Times(AtLeast(1)) - .WillRepeatedly(Invoke(&ClearControlFrame)); + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); if (!session_->split_up_send_rst()) { EXPECT_CALL(*session_, SendRstStream(stream_->id(), QUIC_STREAM_CANCELLED, 9, _)) @@ -1475,8 +1475,8 @@ EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); std::string data(1024, '.'); stream->WriteOrBufferData(data, false, nullptr); EXPECT_FALSE(HasWriteBlockedStreams()); @@ -1509,8 +1509,8 @@ std::string data(100, '.'); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) .WillRepeatedly(Invoke(session_.get(), &MockQuicSession::ConsumeData)); - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); stream->WriteOrBufferData(data, false, nullptr); EXPECT_FALSE(HasWriteBlockedStreams());
diff --git a/quic/test_tools/quic_connection_peer.cc b/quic/test_tools/quic_connection_peer.cc index d6395d0..30ed4fd 100644 --- a/quic/test_tools/quic_connection_peer.cc +++ b/quic/test_tools/quic_connection_peer.cc
@@ -394,5 +394,10 @@ connection->connected_ = false; } +// static +void QuicConnectionPeer::SendPing(QuicConnection* connection) { + connection->SendPingAtLevel(connection->encryption_level()); +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_connection_peer.h b/quic/test_tools/quic_connection_peer.h index ecc98c5..8859a58 100644 --- a/quic/test_tools/quic_connection_peer.h +++ b/quic/test_tools/quic_connection_peer.h
@@ -162,6 +162,8 @@ pending_path_challenge_payloads(QuicConnection* connection); static void SetConnectionClose(QuicConnection* connection); + + static void SendPing(QuicConnection* connection); }; } // namespace test
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc index 0357ee2..8bf49d9 100644 --- a/quic/test_tools/quic_test_utils.cc +++ b/quic/test_tools/quic_test_utils.cc
@@ -214,6 +214,11 @@ return true; } +bool ClearControlFrameWithTransmissionType(const QuicFrame& frame, + TransmissionType /*type*/) { + return ClearControlFrame(frame); +} + uint64_t SimpleRandom::RandUint64() { uint64_t result; RandBytes(&result, sizeof(result));
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index 0224235..f05859d 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -254,6 +254,8 @@ // Delete |frame| and return true. bool ClearControlFrame(const QuicFrame& frame); +bool ClearControlFrameWithTransmissionType(const QuicFrame& frame, + TransmissionType type); // Simple random number generator used to compute random numbers suitable // for pseudo-randomly dropping packets in tests. @@ -840,6 +842,10 @@ TransmissionType type, absl::optional<EncryptionLevel> level), (override)); + MOCK_METHOD(bool, + WriteControlFrame, + (const QuicFrame& frame, TransmissionType type), + (override)); MOCK_METHOD(void, SendRstStream,
diff --git a/quic/tools/quic_simple_server_session_test.cc b/quic/tools/quic_simple_server_session_test.cc index 8cd89f4..28e8899 100644 --- a/quic/tools/quic_simple_server_session_test.cc +++ b/quic/tools/quic_simple_server_session_test.cc
@@ -9,6 +9,7 @@ #include <utility> #include "absl/strings/string_view.h" +#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" #include "net/third_party/quiche/src/quic/core/http/http_encoder.h" @@ -203,6 +204,10 @@ ()); MOCK_METHOD(void, SendBlocked, (QuicStreamId), (override)); + MOCK_METHOD(bool, + WriteControlFrame, + (const QuicFrame& frame, TransmissionType type), + (override)); }; class QuicSimpleServerSessionTest @@ -256,6 +261,9 @@ connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>( &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions); connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); + connection_->SetEncrypter( + ENCRYPTION_FORWARD_SECURE, + std::make_unique<NullEncrypter>(connection_->perspective())); session_ = std::make_unique<MockQuicSimpleServerSession>( config_, connection_, &owner_, &stream_helper_, &crypto_config_, &compressed_certs_cache_, &memory_cache_backend_); @@ -266,9 +274,8 @@ session_->Initialize(); if (VersionHasIetfQuicFrames(transport_version())) { - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillRepeatedly(Invoke( - this, &QuicSimpleServerSessionTest::ClearMaxStreamsControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); } session_->OnConfigNegotiated(); } @@ -335,7 +342,8 @@ GetNthClientInitiatedBidirectionalId(0), QUIC_ERROR_PROCESSING_STREAM, 0); EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); + if (!VersionHasIetfQuicFrames(transport_version())) { // For version 99, this is covered in InjectStopSending() EXPECT_CALL(*connection_, @@ -365,7 +373,7 @@ QUIC_ERROR_PROCESSING_STREAM, 0); EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); if (!VersionHasIetfQuicFrames(transport_version())) { - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); // For version 99, this is covered in InjectStopSending() EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedBidirectionalId(0), @@ -406,7 +414,7 @@ QUIC_ERROR_PROCESSING_STREAM, 0); EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); if (!VersionHasIetfQuicFrames(transport_version())) { - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); // For version 99, this is covered in InjectStopSending() EXPECT_CALL(*connection_, OnStreamReset(GetNthClientInitiatedBidirectionalId(0), @@ -622,6 +630,9 @@ ParsedQuicVersionVector supported_versions = SupportedVersions(GetParam()); connection_ = new StrictMock<MockQuicConnectionWithSendStreamData>( &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions); + connection_->SetEncrypter( + ENCRYPTION_FORWARD_SECURE, + std::make_unique<NullEncrypter>(connection_->perspective())); session_ = std::make_unique<MockQuicSimpleServerSession>( config_, connection_, &owner_, &stream_helper_, &crypto_config_, &compressed_certs_cache_, &memory_cache_backend_); @@ -629,9 +640,8 @@ // Needed to make new session flow control window and server push work. if (VersionHasIetfQuicFrames(transport_version())) { - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillRepeatedly(Invoke(this, &QuicSimpleServerSessionServerPushTest:: - ClearMaxStreamsControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillRepeatedly(Invoke(&ClearControlFrameWithTransmissionType)); } session_->OnConfigNegotiated(); @@ -881,8 +891,8 @@ // V99 will send out a STREAMS_BLOCKED frame when it tries to exceed the // limit. This will clear the frames so that they do not block the later // rst-stream frame. - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); } QuicByteCount data_frame_header_length = PromisePushResources(num_resources); @@ -898,8 +908,8 @@ QuicRstStreamFrame rst(kInvalidControlFrameId, stream_got_reset, QUIC_STREAM_CANCELLED, 0); EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); EXPECT_CALL(*connection_, OnStreamReset(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT)); session_->OnRstStream(rst); @@ -968,8 +978,8 @@ // V99 will send out a stream-id-blocked frame when the we desired to exceed // the limit. This will clear the frames so that they do not block the later // rst-stream frame. - EXPECT_CALL(*connection_, SendControlFrame(_)) - .WillOnce(Invoke(&ClearControlFrame)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)) + .WillOnce(Invoke(&ClearControlFrameWithTransmissionType)); } QuicByteCount data_frame_header_length = PromisePushResources(num_resources); QuicStreamId stream_to_open; @@ -983,7 +993,7 @@ // Resetting an open stream will close the stream and give space for extra // stream to be opened. QuicStreamId stream_got_reset = GetNthServerInitiatedUnidirectionalId(3); - EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL(*session_, WriteControlFrame(_, _)); if (!VersionHasIetfQuicFrames(transport_version())) { EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1); // For version 99, this is covered in InjectStopSending()