Add HttpEncoder method to serialize ACCEPT_CH frame. PiperOrigin-RevId: 345446123 Change-Id: I55e45926e6d94cdcde4022b9620d6d3868475eeb
diff --git a/quic/core/http/http_encoder.cc b/quic/core/http/http_encoder.cc index 4f86d45..0689a77 100644 --- a/quic/core/http/http_encoder.cc +++ b/quic/core/http/http_encoder.cc
@@ -258,6 +258,42 @@ } // static +QuicByteCount HttpEncoder::SerializeAcceptChFrame( + const AcceptChFrame& accept_ch, + std::unique_ptr<char[]>* output) { + QuicByteCount payload_length = 0; + for (const auto& entry : accept_ch.entries) { + payload_length += QuicDataWriter::GetVarInt62Len(entry.origin.size()); + payload_length += entry.origin.size(); + payload_length += QuicDataWriter::GetVarInt62Len(entry.value.size()); + payload_length += entry.value.size(); + } + + QuicByteCount total_length = + GetTotalLength(payload_length, HttpFrameType::ACCEPT_CH); + + output->reset(new char[total_length]); + QuicDataWriter writer(total_length, output->get()); + + if (!WriteFrameHeader(payload_length, HttpFrameType::ACCEPT_CH, &writer)) { + QUIC_DLOG(ERROR) + << "Http encoder failed to serialize ACCEPT_CH frame header."; + return 0; + } + + for (const auto& entry : accept_ch.entries) { + if (!writer.WriteStringPieceVarInt62(entry.origin) || + !writer.WriteStringPieceVarInt62(entry.value)) { + QUIC_DLOG(ERROR) + << "Http encoder failed to serialize ACCEPT_CH frame payload."; + return 0; + } + } + + return total_length; +} + +// static QuicByteCount HttpEncoder::SerializeGreasingFrame( std::unique_ptr<char[]>* output) { uint64_t frame_type;
diff --git a/quic/core/http/http_encoder.h b/quic/core/http/http_encoder.h index 4d6a54a..dfa236a 100644 --- a/quic/core/http/http_encoder.h +++ b/quic/core/http/http_encoder.h
@@ -67,6 +67,11 @@ const PriorityUpdateFrame& priority_update, std::unique_ptr<char[]>* output); + // Serializes an ACCEPT_CH frame into a new buffer stored in |output|. + // Returns the length of the buffer on success, or 0 otherwise. + static QuicByteCount SerializeAcceptChFrame(const AcceptChFrame& accept_ch, + std::unique_ptr<char[]>* output); + // Serializes a frame with reserved frame type specified in // https://tools.ietf.org/html/draft-ietf-quic-http-25#section-7.2.9. static QuicByteCount SerializeGreasingFrame(std::unique_ptr<char[]>* output);
diff --git a/quic/core/http/http_encoder_test.cc b/quic/core/http/http_encoder_test.cc index 2466326..df2b523 100644 --- a/quic/core/http/http_encoder_test.cc +++ b/quic/core/http/http_encoder_test.cc
@@ -184,5 +184,28 @@ ABSL_ARRAYSIZE(output2)); } +TEST(HttpEncoderTest, SerializeAcceptChFrame) { + AcceptChFrame accept_ch; + char output1[] = {0x40, 0x89, // type (ACCEPT_CH) + 0x00}; // length + + std::unique_ptr<char[]> buffer; + uint64_t length = HttpEncoder::SerializeAcceptChFrame(accept_ch, &buffer); + EXPECT_EQ(ABSL_ARRAYSIZE(output1), length); + quiche::test::CompareCharArraysWithHexError("ACCEPT_CH", buffer.get(), length, + output1, ABSL_ARRAYSIZE(output1)); + + accept_ch.entries.push_back({"foo", "bar"}); + char output2[] = {0x40, 0x89, // type (ACCEPT_CH) + 0x08, // payload length + 0x03, 0x66, 0x6f, 0x6f, // length of "foo"; "foo" + 0x03, 0x62, 0x61, 0x72}; // length of "bar"; "bar" + + length = HttpEncoder::SerializeAcceptChFrame(accept_ch, &buffer); + EXPECT_EQ(ABSL_ARRAYSIZE(output2), length); + quiche::test::CompareCharArraysWithHexError("ACCEPT_CH", buffer.get(), length, + output2, ABSL_ARRAYSIZE(output2)); +} + } // namespace test } // namespace quic