Use IETF QPACK error codes on the wire. gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99. PiperOrigin-RevId: 275232371 Change-Id: Id3bd3819b69167e92de6601f0cd146e084b2bee7
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index 8c724e5..1372df0 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -411,18 +411,16 @@ void QuicSpdySession::OnDecoderStreamError(QuicStringPiece error_message) { DCHECK(VersionUsesHttp3(transport_version())); - // TODO(b/124216424): Use HTTP_QPACK_DECODER_STREAM_ERROR. CloseConnectionWithDetails( - QUIC_DECOMPRESSION_FAILURE, + QUIC_QPACK_DECODER_STREAM_ERROR, QuicStrCat("Decoder stream error: ", error_message)); } void QuicSpdySession::OnEncoderStreamError(QuicStringPiece error_message) { DCHECK(VersionUsesHttp3(transport_version())); - // TODO(b/124216424): Use HTTP_QPACK_ENCODER_STREAM_ERROR. CloseConnectionWithDetails( - QUIC_DECOMPRESSION_FAILURE, + QUIC_QPACK_ENCODER_STREAM_ERROR, QuicStrCat("Encoder stream error: ", error_message)); }
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index 600e342..89f2d04 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -2563,7 +2563,7 @@ EXPECT_CALL( *connection_, - CloseConnection(QUIC_DECOMPRESSION_FAILURE, + CloseConnection(QUIC_QPACK_ENCODER_STREAM_ERROR, "Encoder stream error: Invalid relative index.", _)); session_.OnStreamFrame(frame); } @@ -2584,7 +2584,7 @@ EXPECT_CALL( *connection_, - CloseConnection(QUIC_DECOMPRESSION_FAILURE, + CloseConnection(QUIC_QPACK_DECODER_STREAM_ERROR, "Decoder stream error: Invalid increment value 0.", _)); session_.OnStreamFrame(frame); }
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc index 5dd9f3a..f90f3c7 100644 --- a/quic/core/http/quic_spdy_stream.cc +++ b/quic/core/http/quic_spdy_stream.cc
@@ -544,14 +544,13 @@ } void QuicSpdyStream::OnHeaderDecodingError() { - // TODO(b/124216424): Use HTTP_EXCESSIVE_LOAD or - // HTTP_QPACK_DECOMPRESSION_FAILED error code as indicated by + // TODO(b/124216424): Use HTTP_EXCESSIVE_LOAD instead if indicated by // |qpack_decoded_headers_accumulator_|. std::string error_message = QuicStrCat( "Error during async decoding of ", headers_decompressed_ ? "trailers" : "headers", " on stream ", id(), ": ", qpack_decoded_headers_accumulator_->error_message()); - CloseConnectionWithDetails(QUIC_DECOMPRESSION_FAILURE, error_message); + CloseConnectionWithDetails(QUIC_QPACK_DECOMPRESSION_FAILED, error_message); } void QuicSpdyStream::OnHeadersTooLarge() { @@ -904,11 +903,10 @@ sequencer()->MarkConsumed(body_manager_.OnNonBody(payload.size())); if (!success) { - // TODO(124216424): Use HTTP_QPACK_DECOMPRESSION_FAILED error code. std::string error_message = QuicStrCat("Error decompressing header block on stream ", id(), ": ", qpack_decoded_headers_accumulator_->error_message()); - CloseConnectionWithDetails(QUIC_DECOMPRESSION_FAILURE, error_message); + CloseConnectionWithDetails(QUIC_QPACK_DECOMPRESSION_FAILED, error_message); return false; } return true; @@ -921,11 +919,10 @@ auto result = qpack_decoded_headers_accumulator_->EndHeaderBlock(); if (result == QpackDecodedHeadersAccumulator::Status::kError) { - // TODO(124216424): Use HTTP_QPACK_DECOMPRESSION_FAILED error code. std::string error_message = QuicStrCat("Error decompressing header block on stream ", id(), ": ", qpack_decoded_headers_accumulator_->error_message()); - CloseConnectionWithDetails(QUIC_DECOMPRESSION_FAILURE, error_message); + CloseConnectionWithDetails(QUIC_QPACK_DECOMPRESSION_FAILED, error_message); return false; }
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc index c545265..2db475e 100644 --- a/quic/core/http/quic_spdy_stream_test.cc +++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -1840,7 +1840,7 @@ EXPECT_CALL( *connection_, CloseConnection( - QUIC_DECOMPRESSION_FAILURE, + QUIC_QPACK_DECOMPRESSION_FAILED, MatchesRegex("Error decompressing header block on stream \\d+: " "Incomplete header block."), _)) @@ -1994,7 +1994,7 @@ EXPECT_CALL( *connection_, CloseConnection( - QUIC_DECOMPRESSION_FAILURE, + QUIC_QPACK_DECOMPRESSION_FAILED, MatchesRegex("Error during async decoding of headers on stream \\d+: " "Required Insert Count too large."), ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET)); @@ -2055,7 +2055,7 @@ EXPECT_CALL(*connection_, CloseConnection( - QUIC_DECOMPRESSION_FAILURE, + QUIC_QPACK_DECOMPRESSION_FAILED, MatchesRegex( "Error during async decoding of trailers on stream \\d+: " "Required Insert Count too large."),
diff --git a/quic/core/quic_error_codes.cc b/quic/core/quic_error_codes.cc index b1e8ed2..a603bc1 100644 --- a/quic/core/quic_error_codes.cc +++ b/quic/core/quic_error_codes.cc
@@ -160,6 +160,9 @@ QUIC_WINDOW_UPDATE_RECEIVED_ON_READ_UNIDIRECTIONAL_STREAM); RETURN_STRING_LITERAL(QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES); RETURN_STRING_LITERAL(QUIC_TRANSPORT_INVALID_CLIENT_INDICATION); + RETURN_STRING_LITERAL(QUIC_QPACK_DECOMPRESSION_FAILED); + RETURN_STRING_LITERAL(QUIC_QPACK_ENCODER_STREAM_ERROR); + RETURN_STRING_LITERAL(QUIC_QPACK_DECODER_STREAM_ERROR); RETURN_STRING_LITERAL(QUIC_LAST_ERROR); // Intentionally have no default case, so we'll break the build
diff --git a/quic/core/quic_error_codes.h b/quic/core/quic_error_codes.h index ce5c721..9b3fab2 100644 --- a/quic/core/quic_error_codes.h +++ b/quic/core/quic_error_codes.h
@@ -342,8 +342,13 @@ // QuicTransport received invalid client indication. QUIC_TRANSPORT_INVALID_CLIENT_INDICATION = 125, + // Internal error codes for QPACK errors. + QUIC_QPACK_DECOMPRESSION_FAILED = 126, + QUIC_QPACK_ENCODER_STREAM_ERROR = 127, + QUIC_QPACK_DECODER_STREAM_ERROR = 128, + // No error. Used as bound while iterating. - QUIC_LAST_ERROR = 126, + QUIC_LAST_ERROR = 129, }; // QuicErrorCodes is encoded as four octets on-the-wire when doing Google QUIC, // or a varint62 when doing IETF QUIC. Ensure that its value does not exceed @@ -359,6 +364,14 @@ // Returns the name of the QuicErrorCode as a char* QUIC_EXPORT const char* QuicErrorCodeToString(QuicErrorCode error); +// Wire values for QPACK errors. +// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#error-code-registration +enum QuicHttpQpackErrorCode { + IETF_QUIC_HTTP_QPACK_DECOMPRESSION_FAILED = 0x200, + IETF_QUIC_HTTP_QPACK_ENCODER_STREAM_ERROR = 0x201, + IETF_QUIC_HTTP_QPACK_DECODER_STREAM_ERROR = 0x202 +}; + QUIC_EXPORT_PRIVATE inline std::string HistogramEnumString( QuicErrorCode enum_value) { return QuicErrorCodeToString(enum_value);
diff --git a/quic/core/quic_types.cc b/quic/core/quic_types.cc index db48c5c..e6f95cd 100644 --- a/quic/core/quic_types.cc +++ b/quic/core/quic_types.cc
@@ -413,6 +413,18 @@ {static_cast<uint64_t>(QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES)}}; case QUIC_TRANSPORT_INVALID_CLIENT_INDICATION: return {false, {0u}}; + case QUIC_QPACK_DECOMPRESSION_FAILED: + return { + false, + {static_cast<uint64_t>(IETF_QUIC_HTTP_QPACK_DECOMPRESSION_FAILED)}}; + case QUIC_QPACK_ENCODER_STREAM_ERROR: + return { + false, + {static_cast<uint64_t>(IETF_QUIC_HTTP_QPACK_ENCODER_STREAM_ERROR)}}; + case QUIC_QPACK_DECODER_STREAM_ERROR: + return { + false, + {static_cast<uint64_t>(IETF_QUIC_HTTP_QPACK_DECODER_STREAM_ERROR)}}; case QUIC_LAST_ERROR: return {false, {static_cast<uint64_t>(QUIC_LAST_ERROR)}}; }
diff --git a/quic/core/quic_types_test.cc b/quic/core/quic_types_test.cc index 8b4df89..39989ce 100644 --- a/quic/core/quic_types_test.cc +++ b/quic/core/quic_types_test.cc
@@ -27,10 +27,6 @@ QuicIetfTransportErrorCodeString(mapping.transport_error_code_), QuicStrCat("Unknown Transport Error Code Value: ", static_cast<uint16_t>(mapping.transport_error_code_))); - } else { - // Some QuicErrorCodes are no longer valid. - EXPECT_EQ(QuicIetfTransportErrorCodeString(mapping.transport_error_code_), - "NO_IETF_QUIC_ERROR"); } } }