Add HttpEncoder::SerializeMetadataFrameHeader().

Add HTTP/3 SETTING_ENABLE_METADATA.
Add HTTP/3 METADATA frame type.
Add HttpEncoder::SerializeMetadataFrameHeader() method to serialize METADATA frame header.

Setting identifier and frame type match HTTP/2 ones, see
quiche/spdy/core/metadata_extension.cc.

See https://github.com/envoyproxy/envoy/issues/2394 and design document linked
therein for HTTP/2 METADATA.  HTTP/3 implementation will be very similar.

PiperOrigin-RevId: 457048873
diff --git a/quiche/quic/core/http/http_constants.cc b/quiche/quic/core/http/http_constants.cc
index a22620d..e429678 100644
--- a/quiche/quic/core/http/http_constants.cc
+++ b/quiche/quic/core/http/http_constants.cc
@@ -21,6 +21,7 @@
     RETURN_STRING_LITERAL(SETTINGS_H3_DATAGRAM_DRAFT09);
     RETURN_STRING_LITERAL(SETTINGS_WEBTRANS_DRAFT00);
     RETURN_STRING_LITERAL(SETTINGS_ENABLE_CONNECT_PROTOCOL);
+    RETURN_STRING_LITERAL(SETTINGS_ENABLE_METADATA);
   }
   return absl::StrCat("UNSUPPORTED_SETTINGS_TYPE(", identifier, ")");
 }
diff --git a/quiche/quic/core/http/http_constants.h b/quiche/quic/core/http/http_constants.h
index 9e1a696..b5dc19b 100644
--- a/quiche/quic/core/http/http_constants.h
+++ b/quiche/quic/core/http/http_constants.h
@@ -46,6 +46,7 @@
   SETTINGS_WEBTRANS_DRAFT00 = 0x2b603742,
   // draft-ietf-httpbis-h3-websockets
   SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08,
+  SETTINGS_ENABLE_METADATA = 0x4d44,
 };
 
 // Returns HTTP/3 SETTINGS identifier as a string.
diff --git a/quiche/quic/core/http/http_encoder.cc b/quiche/quic/core/http/http_encoder.cc
index 66de89e..8091a20 100644
--- a/quiche/quic/core/http/http_encoder.cc
+++ b/quiche/quic/core/http/http_encoder.cc
@@ -261,4 +261,24 @@
   return 0;
 }
 
+QuicByteCount HttpEncoder::SerializeMetadataFrameHeader(
+    QuicByteCount payload_length, std::unique_ptr<char[]>* output) {
+  QUICHE_DCHECK_NE(0u, payload_length);
+  QuicByteCount header_length =
+      QuicDataWriter::GetVarInt62Len(payload_length) +
+      QuicDataWriter::GetVarInt62Len(
+          static_cast<uint64_t>(HttpFrameType::METADATA));
+
+  *output = std::make_unique<char[]>(header_length);
+  QuicDataWriter writer(header_length, output->get());
+
+  if (WriteFrameHeader(payload_length, HttpFrameType::METADATA, &writer)) {
+    return header_length;
+  }
+  QUIC_DLOG(ERROR)
+      << "Http encoder failed when attempting to serialize METADATA "
+         "frame header.";
+  return 0;
+}
+
 }  // namespace quic
diff --git a/quiche/quic/core/http/http_encoder.h b/quiche/quic/core/http/http_encoder.h
index fc5987f..0d03e69 100644
--- a/quiche/quic/core/http/http_encoder.h
+++ b/quiche/quic/core/http/http_encoder.h
@@ -65,6 +65,11 @@
   // https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-00.html#name-client-initiated-bidirectio
   static QuicByteCount SerializeWebTransportStreamFrameHeader(
       WebTransportSessionId session_id, std::unique_ptr<char[]>* output);
+
+  // Serializes a METADATA frame header into a new buffer stored in |output|.
+  // Returns the length of the buffer on success, or 0 otherwise.
+  static QuicByteCount SerializeMetadataFrameHeader(
+      QuicByteCount payload_length, std::unique_ptr<char[]>* output);
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/http/http_encoder_test.cc b/quiche/quic/core/http/http_encoder_test.cc
index b6d8844..7394ab8 100644
--- a/quiche/quic/core/http/http_encoder_test.cc
+++ b/quiche/quic/core/http/http_encoder_test.cc
@@ -123,5 +123,16 @@
       "WEBTRANSPORT_STREAM", buffer.get(), length, output, sizeof(output));
 }
 
+TEST(HttpEncoderTest, SerializeMetadataFrameHeader) {
+  std::unique_ptr<char[]> buffer;
+  uint64_t length = HttpEncoder::SerializeMetadataFrameHeader(
+      /* payload_length = */ 7, &buffer);
+  char output[] = {0x40, 0x4d,  // type (METADATA, 0x4d, varint encoded)
+                   0x07};       // length
+  EXPECT_EQ(ABSL_ARRAYSIZE(output), length);
+  quiche::test::CompareCharArraysWithHexError("METADATA", buffer.get(), length,
+                                              output, ABSL_ARRAYSIZE(output));
+}
+
 }  // namespace test
 }  // namespace quic
diff --git a/quiche/quic/core/http/http_frames.h b/quiche/quic/core/http/http_frames.h
index b96c5fb..f55881a 100644
--- a/quiche/quic/core/http/http_frames.h
+++ b/quiche/quic/core/http/http_frames.h
@@ -34,6 +34,7 @@
   PRIORITY_UPDATE_REQUEST_STREAM = 0xF0700,
   // https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-00.html
   WEBTRANSPORT_STREAM = 0x41,
+  METADATA = 0x4d,
 };
 
 // 7.2.1.  DATA