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