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");
     }
   }
 }