Close connection on QPACK encoder or decoder stream errors.
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 268434745
Change-Id: Ie69e360cacd7b431373fddf1e5221304ec522000
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index 53ec3cc..a2bb509 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -402,18 +402,22 @@
2 * max_inbound_header_list_size_);
}
-void QuicSpdySession::OnDecoderStreamError(QuicStringPiece /*error_message*/) {
+void QuicSpdySession::OnDecoderStreamError(QuicStringPiece error_message) {
DCHECK(VersionUsesQpack(transport_version()));
- // TODO(112770235): Signal connection error on decoder stream errors.
- QUIC_NOTREACHED();
+ // TODO(b/124216424): Use HTTP_QPACK_DECODER_STREAM_ERROR.
+ CloseConnectionWithDetails(
+ QUIC_DECOMPRESSION_FAILURE,
+ QuicStrCat("Decoder stream error: ", error_message));
}
-void QuicSpdySession::OnEncoderStreamError(QuicStringPiece /*error_message*/) {
+void QuicSpdySession::OnEncoderStreamError(QuicStringPiece error_message) {
DCHECK(VersionUsesQpack(transport_version()));
- // TODO(112770235): Signal connection error on encoder stream errors.
- QUIC_NOTREACHED();
+ // TODO(b/124216424): Use HTTP_QPACK_ENCODER_STREAM_ERROR.
+ CloseConnectionWithDetails(
+ QUIC_DECOMPRESSION_FAILURE,
+ QuicStrCat("Encoder stream error: ", error_message));
}
void QuicSpdySession::OnStreamHeadersPriority(
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index e5d50b2..f5bab97 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -2473,6 +2473,48 @@
"Received a duplicate QPACK decoder stream: Closing connection.");
}
+TEST_P(QuicSpdySessionTestClient, EncoderStreamError) {
+ if (!VersionUsesQpack(transport_version())) {
+ return;
+ }
+
+ std::string data = QuicTextUtils::HexDecode(
+ "02" // Encoder stream.
+ "00"); // Duplicate entry 0, but no entries exist.
+
+ QuicStreamId stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
+
+ QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0, data);
+
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_DECOMPRESSION_FAILURE,
+ "Encoder stream error: Invalid relative index.", _));
+ session_.OnStreamFrame(frame);
+}
+
+TEST_P(QuicSpdySessionTestClient, DecoderStreamError) {
+ if (!VersionUsesQpack(transport_version())) {
+ return;
+ }
+
+ std::string data = QuicTextUtils::HexDecode(
+ "03" // Decoder stream.
+ "00"); // Insert Count Increment with forbidden increment value of zero.
+
+ QuicStreamId stream_id =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
+
+ QuicStreamFrame frame(stream_id, /* fin = */ false, /* offset = */ 0, data);
+
+ EXPECT_CALL(
+ *connection_,
+ CloseConnection(QUIC_DECOMPRESSION_FAILURE,
+ "Decoder stream error: Invalid increment value 0.", _));
+ session_.OnStreamFrame(frame);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/tools/quic_simple_client_session.cc b/quic/tools/quic_simple_client_session.cc
index b7743f8..f39d8fa 100644
--- a/quic/tools/quic_simple_client_session.cc
+++ b/quic/tools/quic_simple_client_session.cc
@@ -8,6 +8,27 @@
namespace quic {
+QuicSimpleClientSession::QuicSimpleClientSession(
+ const QuicConfig& config,
+ const ParsedQuicVersionVector& supported_versions,
+ QuicConnection* connection,
+ const QuicServerId& server_id,
+ QuicCryptoClientConfig* crypto_config,
+ QuicClientPushPromiseIndex* push_promise_index,
+ bool drop_response_body)
+ : QuicSpdyClientSession(config,
+ supported_versions,
+ connection,
+ server_id,
+ crypto_config,
+ push_promise_index),
+ drop_response_body_(drop_response_body) {
+ // Do not use the QPACK dynamic table in tests to avoid flakiness due to the
+ // uncertain order of receiving the SETTINGS frame and sending headers.
+ set_qpack_maximum_dynamic_table_capacity(0);
+ set_qpack_maximum_blocked_streams(0);
+}
+
std::unique_ptr<QuicSpdyClientStream>
QuicSimpleClientSession::CreateClientStream() {
return std::make_unique<QuicSimpleClientStream>(
diff --git a/quic/tools/quic_simple_client_session.h b/quic/tools/quic_simple_client_session.h
index 1a17f3d..0ebca98 100644
--- a/quic/tools/quic_simple_client_session.h
+++ b/quic/tools/quic_simple_client_session.h
@@ -18,14 +18,7 @@
const QuicServerId& server_id,
QuicCryptoClientConfig* crypto_config,
QuicClientPushPromiseIndex* push_promise_index,
- bool drop_response_body)
- : QuicSpdyClientSession(config,
- supported_versions,
- connection,
- server_id,
- crypto_config,
- push_promise_index),
- drop_response_body_(drop_response_body) {}
+ bool drop_response_body);
std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override;
diff --git a/quic/tools/quic_simple_server_session.cc b/quic/tools/quic_simple_server_session.cc
index 8298122..1a03ab5 100644
--- a/quic/tools/quic_simple_server_session.cc
+++ b/quic/tools/quic_simple_server_session.cc
@@ -36,6 +36,11 @@
QuicUtils::GetInvalidStreamId(connection->transport_version())),
quic_simple_server_backend_(quic_simple_server_backend) {
DCHECK(quic_simple_server_backend_);
+
+ // Do not use the QPACK dynamic table in tests to avoid flakiness due to the
+ // uncertain order of receiving the SETTINGS frame and sending headers.
+ set_qpack_maximum_dynamic_table_capacity(0);
+ set_qpack_maximum_blocked_streams(0);
}
QuicSimpleServerSession::~QuicSimpleServerSession() {