diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic/core/http')
11 files changed, 175 insertions, 72 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc index 29e6377280b..cad9cacb022 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc @@ -485,8 +485,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { } } - void AddToCache(absl::string_view path, - int response_code, + void AddToCache(absl::string_view path, int response_code, absl::string_view body) { memory_cache_backend_.AddSimpleResponse(server_hostname_, path, response_code, body); @@ -553,12 +552,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { EXPECT_EQ(0u, server_stats.packets_lost); } EXPECT_EQ(0u, server_stats.packets_discarded); - if (!GetQuicReloadableFlag( - quic_ignore_user_agent_transport_parameter)) { - EXPECT_EQ( - server_session->user_agent_id().value_or("MissingUserAgent"), - kTestUserAgentId); - } } else { ADD_FAILURE() << "Missing server connection"; } @@ -657,16 +650,14 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { } bool SendSynchronousRequestAndCheckResponse( - QuicTestClient* client, - const std::string& request, + QuicTestClient* client, const std::string& request, const std::string& expected_response) { std::string received_response = client->SendSynchronousRequest(request); return CheckResponse(client, received_response, expected_response); } bool SendSynchronousRequestAndCheckResponse( - const std::string& request, - const std::string& expected_response) { + const std::string& request, const std::string& expected_response) { return SendSynchronousRequestAndCheckResponse(client_.get(), request, expected_response); } @@ -844,8 +835,7 @@ class EndToEndTest : public QuicTestWithParam<TestParams> { }; // Run all end to end tests with all supported versions. -INSTANTIATE_TEST_SUITE_P(EndToEndTests, - EndToEndTest, +INSTANTIATE_TEST_SUITE_P(EndToEndTests, EndToEndTest, ::testing::ValuesIn(GetTestParams()), ::testing::PrintToStringParamName()); @@ -3210,8 +3200,7 @@ TEST_P(EndToEndTest, ConnectionMigrationNewTokenForNewIp) { class DuplicatePacketWithSpoofedSelfAddressWriter : public QuicPacketWriterWrapper { public: - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { @@ -3246,7 +3235,8 @@ TEST_P(EndToEndTest, ClientAddressSpoofedForSomePeriod) { ASSERT_TRUE(QuicConnectionPeer::HasUnusedPeerIssuedConnectionId( GetClientConnection())); - QuicIpAddress real_host = TestLoopback(1); + QuicIpAddress real_host = + client_->client()->session()->connection()->self_address().host(); ASSERT_TRUE(client_->MigrateSocket(real_host)); SendSynchronousFooRequestAndCheckResponse(); EXPECT_EQ( @@ -4384,13 +4374,10 @@ TEST_P(EndToEndTest, CanceledStreamDoesNotBecomeZombie) { class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream { public: ServerStreamWithErrorResponseBody( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend, std::string response_body) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend), response_body_(std::move(response_body)) {} @@ -4419,8 +4406,7 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory { ~StreamWithErrorFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamWithErrorResponseBody( id, session, quic_simple_server_backend, response_body_); @@ -4433,12 +4419,9 @@ class StreamWithErrorFactory : public QuicTestServer::StreamFactory { // A test server stream that drops all received body. class ServerStreamThatDropsBody : public QuicSimpleServerStream { public: - ServerStreamThatDropsBody(QuicStreamId id, - QuicSpdySession* session, + ServerStreamThatDropsBody(QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend) {} ~ServerStreamThatDropsBody() override = default; @@ -4480,8 +4463,7 @@ class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory { ~ServerStreamThatDropsBodyFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamThatDropsBody(id, session, quic_simple_server_backend); @@ -4492,13 +4474,9 @@ class ServerStreamThatDropsBodyFactory : public QuicTestServer::StreamFactory { class ServerStreamThatSendsHugeResponse : public QuicSimpleServerStream { public: ServerStreamThatSendsHugeResponse( - QuicStreamId id, - QuicSpdySession* session, - QuicSimpleServerBackend* quic_simple_server_backend, - int64_t body_bytes) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + QuicStreamId id, QuicSpdySession* session, + QuicSimpleServerBackend* quic_simple_server_backend, int64_t body_bytes) + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend), body_bytes_(body_bytes) {} @@ -4528,8 +4506,7 @@ class ServerStreamThatSendsHugeResponseFactory ~ServerStreamThatSendsHugeResponseFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamThatSendsHugeResponse( id, session, quic_simple_server_backend, body_bytes_); @@ -5254,8 +5231,7 @@ TEST_P(EndToEndPacketReorderingTest, ReorderedConnectivityProbing) { // called. class PacketHoldingWriter : public QuicPacketWriterWrapper { public: - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { @@ -5533,11 +5509,13 @@ TEST_P(EndToEndPacketReorderingTest, MigrateAgainAfterPathValidationFailure) { } TEST_P(EndToEndPacketReorderingTest, - MigrateAgainAfterPathValidationFailureWithNonZeroClientConnectionId) { + MigrateAgainAfterPathValidationFailureWithNonZeroClientCid) { if (!version_.SupportsClientConnectionIds()) { ASSERT_TRUE(Initialize()); return; } + SetQuicReloadableFlag(quic_retire_cid_on_reverse_path_validation_failure, + true); override_client_connection_id_length_ = kQuicDefaultConnectionIdLength; ASSERT_TRUE(Initialize()); if (!GetClientConnection()->connection_migration_use_new_cid()) { @@ -5707,8 +5685,7 @@ class BadShloPacketWriter : public QuicPacketWriterWrapper { : error_returned_(false), version_(version) {} ~BadShloPacketWriter() override {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, quic::PerPacketOptions* options) override { @@ -5725,6 +5702,9 @@ class BadShloPacketWriter : public QuicPacketWriterWrapper { } bool TypeByteIsServerHello(uint8_t type_byte) { + if (version_.UsesV2PacketTypes()) { + return ((type_byte & 0x30) >> 4) == 3; + } if (version_.UsesQuicCrypto()) { // ENCRYPTION_ZERO_RTT packet. return ((type_byte & 0x30) >> 4) == 1; @@ -5781,21 +5761,23 @@ TEST_P(EndToEndTest, ConnectionCloseBeforeHandshakeComplete) { class BadShloPacketWriter2 : public QuicPacketWriterWrapper { public: - BadShloPacketWriter2() : error_returned_(false) {} + BadShloPacketWriter2(ParsedQuicVersion version) + : error_returned_(false), version_(version) {} ~BadShloPacketWriter2() override {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, quic::PerPacketOptions* options) override { const uint8_t type_byte = buffer[0]; - if ((type_byte & FLAGS_LONG_HEADER) && - (((type_byte & 0x30) >> 4) == 1 || (type_byte & 0x7F) == 0x7C)) { - QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet"; - return WriteResult(WRITE_STATUS_OK, buf_len); - } - if (!error_returned_ && !(type_byte & FLAGS_LONG_HEADER)) { + + if (type_byte & FLAGS_LONG_HEADER) { + if (((type_byte & 0x30 >> 4) == (version_.UsesV2PacketTypes() ? 2 : 1)) || + ((type_byte & 0x7F) == 0x7C)) { + QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet"; + return WriteResult(WRITE_STATUS_OK, buf_len); + } + } else if (!error_returned_) { QUIC_DVLOG(1) << "Return write error for short header packet"; error_returned_ = true; return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE); @@ -5806,6 +5788,7 @@ class BadShloPacketWriter2 : public QuicPacketWriterWrapper { private: bool error_returned_; + ParsedQuicVersion version_; }; TEST_P(EndToEndTest, ForwardSecureConnectionClose) { @@ -5836,7 +5819,7 @@ TEST_P(EndToEndTest, ForwardSecureConnectionClose) { dispatcher, // This causes the all server sent ZERO_RTT_PROTECTED packets to be // dropped, and first short header packet causes write error. - new BadShloPacketWriter2()); + new BadShloPacketWriter2(version_)); server_thread_->Resume(); client_.reset(CreateQuicClient(client_writer_)); EXPECT_EQ("", client_->SendSynchronousRequest("/foo")); @@ -5913,10 +5896,6 @@ TEST_P(EndToEndTest, CustomTransportParameters) { QuicConfig* server_config = nullptr; if (server_session != nullptr) { server_config = server_session->config(); - if (!GetQuicReloadableFlag(quic_ignore_user_agent_transport_parameter)) { - EXPECT_EQ(server_session->user_agent_id().value_or("MissingUserAgent"), - kTestUserAgentId); - } } else { ADD_FAILURE() << "Missing server session"; } @@ -6025,8 +6004,7 @@ class CopyingPacketWriter : public PacketDroppingTestWriter { public: explicit CopyingPacketWriter(int num_packets_to_copy) : num_packets_to_copy_(num_packets_to_copy) {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc index 42fef63c978..3a44f79a1d1 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_headers_stream_test.cc @@ -50,7 +50,6 @@ using spdy::SpdyGoAwayIR; using spdy::SpdyHeaderBlock; using spdy::SpdyHeadersHandlerInterface; using spdy::SpdyHeadersIR; -using spdy::SpdyKnownSettingsId; using spdy::SpdyPingId; using spdy::SpdyPingIR; using spdy::SpdyPriority; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc index 30c4178feca..2d144d2465c 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base_test.cc @@ -45,7 +45,6 @@ using testing::_; using testing::StrictMock; using testing::AtLeast; -using testing::Return; namespace quic { namespace test { diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc index 5a859271e6e..cfc47296417 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc @@ -43,7 +43,6 @@ using spdy::SpdyFrameType; using spdy::SpdyHeaderBlock; using spdy::SpdyHeadersHandlerInterface; using spdy::SpdyHeadersIR; -using spdy::SpdyKnownSettingsId; using spdy::SpdyPingId; using spdy::SpdyPriority; using spdy::SpdyPriorityIR; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc index 5db1aab4e91..45506211f9d 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc @@ -153,7 +153,6 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { } void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> /*application_state*/) override {} - bool KeyUpdateSupportedLocally() const override { return false; } std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override { return nullptr; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc index 8147ce00dcc..5317137d7e0 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc @@ -185,6 +185,8 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session, headers_payload_length_(0), trailers_decompressed_(false), trailers_consumed_(false), + qpack_decoded_headers_accumulator_reset_reason_( + QpackDecodedHeadersAccumulatorResetReason::kUnSet), http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)), decoder_(http_decoder_visitor_.get(), HttpDecoderOptionsForBidiStream(spdy_session)), @@ -225,6 +227,8 @@ QuicSpdyStream::QuicSpdyStream(PendingStream* pending, headers_payload_length_(0), trailers_decompressed_(false), trailers_consumed_(false), + qpack_decoded_headers_accumulator_reset_reason_( + QpackDecodedHeadersAccumulatorResetReason::kUnSet), http_decoder_visitor_(std::make_unique<HttpDecoderVisitor>(this)), decoder_(http_decoder_visitor_.get()), sequencer_offset_(sequencer()->NumBytesConsumed()), @@ -563,6 +567,8 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers, bool header_list_size_limit_exceeded) { header_list_size_limit_exceeded_ = header_list_size_limit_exceeded; qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnHeadersDecoded; QuicSpdySession::LogHeaderCompressionRatioHistogram( /* using_qpack = */ true, @@ -592,6 +598,8 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers, void QuicSpdyStream::OnHeaderDecodingError(QuicErrorCode error_code, absl::string_view error_message) { qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnHeaderDecodingError; std::string connection_close_error_message = absl::StrCat( "Error decoding ", headers_decompressed_ ? "trailers" : "headers", @@ -756,6 +764,8 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { if (GetQuicReloadableFlag(quic_abort_qpack_on_stream_reset)) { QUIC_RELOADABLE_FLAG_COUNT_N(quic_abort_qpack_on_stream_reset, 1, 2); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnStreamReset1; } } @@ -769,6 +779,8 @@ void QuicSpdyStream::OnStreamReset(const QuicRstStreamFrame& frame) { if (!fin_received() && spdy_session_->qpack_decoder()) { spdy_session_->qpack_decoder()->OnStreamReset(id()); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnStreamReset2; } QuicStream::OnStreamReset(frame); @@ -791,6 +803,8 @@ void QuicSpdyStream::ResetWithError(QuicResetStreamError error) { if (GetQuicReloadableFlag(quic_abort_qpack_on_stream_reset)) { QUIC_RELOADABLE_FLAG_COUNT_N(quic_abort_qpack_on_stream_reset, 2, 2); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInResetWithError; } } @@ -893,6 +907,8 @@ void QuicSpdyStream::OnClose() { QuicStream::OnClose(); qpack_decoded_headers_accumulator_.reset(); + qpack_decoded_headers_accumulator_reset_reason_ = + QpackDecodedHeadersAccumulatorResetReason::kResetInOnClose; if (visitor_) { Visitor* visitor = visitor_; @@ -1088,7 +1104,14 @@ bool QuicSpdyStream::OnHeadersFrameStart(QuicByteCount header_length, bool QuicSpdyStream::OnHeadersFramePayload(absl::string_view payload) { QUICHE_DCHECK(VersionUsesHttp3(transport_version())); - QUICHE_DCHECK(qpack_decoded_headers_accumulator_); + + if (!qpack_decoded_headers_accumulator_) { + QUIC_BUG(b215142466_OnHeadersFramePayload) + << static_cast<int>(qpack_decoded_headers_accumulator_reset_reason_); + OnHeaderDecodingError(QUIC_INTERNAL_ERROR, + "qpack_decoded_headers_accumulator_ is nullptr"); + return false; + } qpack_decoded_headers_accumulator_->Decode(payload); @@ -1103,7 +1126,14 @@ bool QuicSpdyStream::OnHeadersFramePayload(absl::string_view payload) { bool QuicSpdyStream::OnHeadersFrameEnd() { QUICHE_DCHECK(VersionUsesHttp3(transport_version())); - QUICHE_DCHECK(qpack_decoded_headers_accumulator_); + + if (!qpack_decoded_headers_accumulator_) { + QUIC_BUG(b215142466_OnHeadersFrameEnd) + << static_cast<int>(qpack_decoded_headers_accumulator_reset_reason_); + OnHeaderDecodingError(QUIC_INTERNAL_ERROR, + "qpack_decoded_headers_accumulator_ is nullptr"); + return false; + } qpack_decoded_headers_accumulator_->EndHeaderBlock(); @@ -1244,9 +1274,7 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() { std::string protocol; absl::optional<QuicDatagramStreamId> flow_id; bool version_indicated = false; - for (const auto& header : header_list_) { - const std::string& header_name = header.first; - const std::string& header_value = header.second; + for (const auto& [header_name, header_value] : header_list_) { if (header_name == ":method") { if (!method.empty() || header_value.empty()) { return; diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h index 8ec56d58f06..14ac2f2f585 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h @@ -391,6 +391,20 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream WebTransportStreamAdapter adapter; }; + // Reason codes for `qpack_decoded_headers_accumulator_` being nullptr. + enum class QpackDecodedHeadersAccumulatorResetReason { + // `qpack_decoded_headers_accumulator_` was default constructed to nullptr. + kUnSet = 0, + // `qpack_decoded_headers_accumulator_` was reset in the corresponding + // method. + kResetInOnHeadersDecoded = 1, + kResetInOnHeaderDecodingError = 2, + kResetInOnStreamReset1 = 3, + kResetInOnStreamReset2 = 4, + kResetInResetWithError = 5, + kResetInOnClose = 6, + }; + // Called by HttpDecoderVisitor. bool OnDataFrameStart(QuicByteCount header_length, QuicByteCount payload_length); @@ -462,6 +476,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream // Headers accumulator for decoding HEADERS frame payload. std::unique_ptr<QpackDecodedHeadersAccumulator> qpack_decoded_headers_accumulator_; + // Reason for `qpack_decoded_headers_accumulator_` being nullptr. + QpackDecodedHeadersAccumulatorResetReason + qpack_decoded_headers_accumulator_reset_reason_; // Visitor of the HttpDecoder. std::unique_ptr<HttpDecoderVisitor> http_decoder_visitor_; // HttpDecoder for processing raw incoming stream frames. diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc index 3bad6efe6ee..c8146e1c5a1 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc @@ -136,7 +136,6 @@ class TestCryptoStream : public QuicCryptoStream, public QuicCryptoHandshaker { } void SetServerApplicationStateForResumption( std::unique_ptr<ApplicationState> /*application_state*/) override {} - bool KeyUpdateSupportedLocally() const override { return true; } std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() override { return nullptr; @@ -3424,6 +3423,32 @@ TEST_P(QuicSpdyStreamTest, GetMaxDatagramSize) { EXPECT_EQ(size - 1, size_with_context); } +TEST_P(QuicSpdyStreamTest, + QUIC_TEST_DISABLED_IN_CHROME(HeadersAccumulatorNullptr)) { + if (!UsesHttp3()) { + return; + } + + Initialize(kShouldProcessData); + + // Creates QpackDecodedHeadersAccumulator in + // `qpack_decoded_headers_accumulator_`. + std::string headers = HeadersFrame({std::make_pair("foo", "bar")}); + stream_->OnStreamFrame(QuicStreamFrame(stream_->id(), false, 0, headers)); + + // Resets `qpack_decoded_headers_accumulator_`. + stream_->OnHeadersDecoded({}, false); + + // This private method should never be called when + // `qpack_decoded_headers_accumulator_` is nullptr. The number 1 identifies + // the site where `qpack_decoded_headers_accumulator_` was last reset. + EXPECT_CALL(*connection_, CloseConnection(_, _, _)); + bool result = true; + EXPECT_QUIC_BUG(result = QuicSpdyStreamPeer::OnHeadersFrameEnd(stream_), + "b215142466_OnHeadersFrameEnd.: 1$"); + EXPECT_FALSE(result); +} + } // namespace } // namespace test } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc index 74c9c53a72d..5b744077402 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc @@ -13,6 +13,7 @@ #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "quic/core/quic_versions.h" #include "quic/platform/api/quic_flag_utils.h" #include "quic/platform/api/quic_flags.h" #include "quic/platform/api/quic_logging.h" @@ -194,4 +195,23 @@ void SpdyUtils::AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers, (*headers)["datagram-flow-id"] = absl::StrCat(flow_id); } +// static +ParsedQuicVersion SpdyUtils::ExtractQuicVersionFromAltSvcEntry( + const spdy::SpdyAltSvcWireFormat::AlternativeService& + alternative_service_entry, + const ParsedQuicVersionVector& supported_versions) { + for (const ParsedQuicVersion& version : supported_versions) { + if (version.AlpnDeferToRFCv1()) { + // Versions with share an ALPN with v1 are currently unable to be + // advertised with Alt-Svc. + continue; + } + if (AlpnForVersion(version) == alternative_service_entry.protocol_id) { + return version; + } + } + + return ParsedQuicVersion::Unsupported(); +} + } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h index 01fae4f17a7..85099ab15e7 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h +++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h @@ -14,6 +14,7 @@ #include "quic/core/http/quic_header_list.h" #include "quic/core/quic_packets.h" #include "quic/platform/api/quic_export.h" +#include "spdy/core/spdy_alt_svc_wire_format.h" #include "spdy/core/spdy_header_block.h" namespace quic { @@ -61,6 +62,14 @@ class QUIC_EXPORT_PRIVATE SpdyUtils { // Adds the "datagram-flow-id" header. static void AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers, QuicDatagramStreamId flow_id); + + // Returns the advertised QUIC version from the specified alternative service + // advertisement, or ParsedQuicVersion::Unsupported() if no supported version + // is advertised. + static ParsedQuicVersion ExtractQuicVersionFromAltSvcEntry( + const spdy::SpdyAltSvcWireFormat::AlternativeService& + alternative_service_entry, + const ParsedQuicVersionVector& supported_versions); }; } // namespace quic diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc index 918739d6f90..85c5ceccd57 100644 --- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "quic/core/http/spdy_utils.h" + #include <memory> #include <string> #include "absl/base/macros.h" #include "absl/strings/string_view.h" -#include "quic/core/http/spdy_utils.h" +#include "quic/core/quic_versions.h" #include "quic/platform/api/quic_test.h" using spdy::SpdyHeaderBlock; @@ -408,5 +410,33 @@ TEST_F(DatagramFlowIdTest, DatagramFlowId) { ValidateDatagramFlowId("44; ecn-ect0, 42, 48; ecn-ce, 46; ecn-ect1", 42); } +using ExtractQuicVersionFromAltSvcEntry = QuicTest; + +TEST_F(ExtractQuicVersionFromAltSvcEntry, SupportedVersion) { + ParsedQuicVersionVector supported_versions = AllSupportedVersions(); + spdy::SpdyAltSvcWireFormat::AlternativeService entry; + for (const ParsedQuicVersion& version : supported_versions) { + entry.protocol_id = AlpnForVersion(version); + ParsedQuicVersion expected_version = version; + // Versions with share an ALPN with v1 are currently unable to be + // advertised with Alt-Svc. + if (entry.protocol_id == AlpnForVersion(ParsedQuicVersion::RFCv1()) && + version != ParsedQuicVersion::RFCv1()) { + expected_version = ParsedQuicVersion::RFCv1(); + } + EXPECT_EQ(expected_version, SpdyUtils::ExtractQuicVersionFromAltSvcEntry( + entry, supported_versions)) + << "version: " << version; + } +} + +TEST_F(ExtractQuicVersionFromAltSvcEntry, UnsupportedVersion) { + spdy::SpdyAltSvcWireFormat::AlternativeService entry; + entry.protocol_id = "quic"; + EXPECT_EQ(ParsedQuicVersion::Unsupported(), + SpdyUtils::ExtractQuicVersionFromAltSvcEntry( + entry, AllSupportedVersions())); +} + } // namespace test } // namespace quic |