diff --git a/quiche/quic/core/http/http_constants.cc b/quiche/quic/core/http/http_constants.cc index a22620d9f..e42967860 100644 --- a/quiche/quic/core/http/http_constants.cc +++ b/quiche/quic/core/http/http_constants.cc @@ -21,6 +21,7 @@ std::string H3SettingsToString(Http3AndQpackSettingsIdentifiers identifier) { 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 9e1a696db..b5dc19b5b 100644 --- a/quiche/quic/core/http/http_constants.h +++ b/quiche/quic/core/http/http_constants.h @@ -46,6 +46,7 @@ enum Http3AndQpackSettingsIdentifiers : uint64_t { 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 66de89ea7..8091a20aa 100644 --- a/quiche/quic/core/http/http_encoder.cc +++ b/quiche/quic/core/http/http_encoder.cc @@ -261,4 +261,24 @@ QuicByteCount HttpEncoder::SerializeWebTransportStreamFrameHeader( return 0; } +QuicByteCount HttpEncoder::SerializeMetadataFrameHeader( + QuicByteCount payload_length, std::unique_ptr* output) { + QUICHE_DCHECK_NE(0u, payload_length); + QuicByteCount header_length = + QuicDataWriter::GetVarInt62Len(payload_length) + + QuicDataWriter::GetVarInt62Len( + static_cast(HttpFrameType::METADATA)); + + *output = std::make_unique(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 fc5987f15..0d03e699f 100644 --- a/quiche/quic/core/http/http_encoder.h +++ b/quiche/quic/core/http/http_encoder.h @@ -65,6 +65,11 @@ class QUIC_EXPORT_PRIVATE HttpEncoder { // 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* 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* output); }; } // namespace quic diff --git a/quiche/quic/core/http/http_encoder_test.cc b/quiche/quic/core/http/http_encoder_test.cc index b6d884454..7394ab8ad 100644 --- a/quiche/quic/core/http/http_encoder_test.cc +++ b/quiche/quic/core/http/http_encoder_test.cc @@ -123,5 +123,16 @@ TEST(HttpEncoderTest, SerializeWebTransportStreamFrameHeader) { "WEBTRANSPORT_STREAM", buffer.get(), length, output, sizeof(output)); } +TEST(HttpEncoderTest, SerializeMetadataFrameHeader) { + std::unique_ptr 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 b96c5fbec..f55881a5f 100644 --- a/quiche/quic/core/http/http_frames.h +++ b/quiche/quic/core/http/http_frames.h @@ -34,6 +34,7 @@ enum class HttpFrameType { 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