xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/http/http_encoder.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/http/http_encoder.h"
6 
7 #include <cstdint>
8 #include <memory>
9 
10 #include "quiche/quic/core/crypto/quic_random.h"
11 #include "quiche/quic/core/quic_data_writer.h"
12 #include "quiche/quic/core/quic_types.h"
13 #include "quiche/quic/platform/api/quic_bug_tracker.h"
14 #include "quiche/quic/platform/api/quic_flag_utils.h"
15 #include "quiche/quic/platform/api/quic_flags.h"
16 #include "quiche/quic/platform/api/quic_logging.h"
17 
18 namespace quic {
19 
20 namespace {
21 
WriteFrameHeader(QuicByteCount length,HttpFrameType type,QuicDataWriter * writer)22 bool WriteFrameHeader(QuicByteCount length, HttpFrameType type,
23                       QuicDataWriter* writer) {
24   return writer->WriteVarInt62(static_cast<uint64_t>(type)) &&
25          writer->WriteVarInt62(length);
26 }
27 
GetTotalLength(QuicByteCount payload_length,HttpFrameType type)28 QuicByteCount GetTotalLength(QuicByteCount payload_length, HttpFrameType type) {
29   return QuicDataWriter::GetVarInt62Len(payload_length) +
30          QuicDataWriter::GetVarInt62Len(static_cast<uint64_t>(type)) +
31          payload_length;
32 }
33 
34 }  // namespace
35 
GetDataFrameHeaderLength(QuicByteCount payload_length)36 QuicByteCount HttpEncoder::GetDataFrameHeaderLength(
37     QuicByteCount payload_length) {
38   QUICHE_DCHECK_NE(0u, payload_length);
39   return QuicDataWriter::GetVarInt62Len(payload_length) +
40          QuicDataWriter::GetVarInt62Len(
41              static_cast<uint64_t>(HttpFrameType::DATA));
42 }
43 
SerializeDataFrameHeader(QuicByteCount payload_length,quiche::QuicheBufferAllocator * allocator)44 quiche::QuicheBuffer HttpEncoder::SerializeDataFrameHeader(
45     QuicByteCount payload_length, quiche::QuicheBufferAllocator* allocator) {
46   QUICHE_DCHECK_NE(0u, payload_length);
47   QuicByteCount header_length = GetDataFrameHeaderLength(payload_length);
48 
49   quiche::QuicheBuffer header(allocator, header_length);
50   QuicDataWriter writer(header.size(), header.data());
51 
52   if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
53     return header;
54   }
55   QUIC_DLOG(ERROR)
56       << "Http encoder failed when attempting to serialize data frame header.";
57   return quiche::QuicheBuffer();
58 }
59 
SerializeHeadersFrameHeader(QuicByteCount payload_length)60 std::string HttpEncoder::SerializeHeadersFrameHeader(
61     QuicByteCount payload_length) {
62   QUICHE_DCHECK_NE(0u, payload_length);
63   QuicByteCount header_length =
64       QuicDataWriter::GetVarInt62Len(payload_length) +
65       QuicDataWriter::GetVarInt62Len(
66           static_cast<uint64_t>(HttpFrameType::HEADERS));
67 
68   std::string frame;
69   frame.resize(header_length);
70   QuicDataWriter writer(header_length, frame.data());
71 
72   if (WriteFrameHeader(payload_length, HttpFrameType::HEADERS, &writer)) {
73     return frame;
74   }
75   QUIC_DLOG(ERROR)
76       << "Http encoder failed when attempting to serialize headers "
77          "frame header.";
78   return {};
79 }
80 
SerializeSettingsFrame(const SettingsFrame & settings)81 std::string HttpEncoder::SerializeSettingsFrame(const SettingsFrame& settings) {
82   QuicByteCount payload_length = 0;
83   std::vector<std::pair<uint64_t, uint64_t>> ordered_settings{
84       settings.values.begin(), settings.values.end()};
85   std::sort(ordered_settings.begin(), ordered_settings.end());
86   // Calculate the payload length.
87   for (const auto& p : ordered_settings) {
88     payload_length += QuicDataWriter::GetVarInt62Len(p.first);
89     payload_length += QuicDataWriter::GetVarInt62Len(p.second);
90   }
91 
92   QuicByteCount total_length =
93       GetTotalLength(payload_length, HttpFrameType::SETTINGS);
94 
95   std::string frame;
96   frame.resize(total_length);
97   QuicDataWriter writer(total_length, frame.data());
98 
99   if (!WriteFrameHeader(payload_length, HttpFrameType::SETTINGS, &writer)) {
100     QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
101                         "settings frame header.";
102     return {};
103   }
104 
105   for (const auto& p : ordered_settings) {
106     if (!writer.WriteVarInt62(p.first) || !writer.WriteVarInt62(p.second)) {
107       QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
108                           "settings frame payload.";
109       return {};
110     }
111   }
112 
113   return frame;
114 }
115 
SerializeGoAwayFrame(const GoAwayFrame & goaway)116 std::string HttpEncoder::SerializeGoAwayFrame(const GoAwayFrame& goaway) {
117   QuicByteCount payload_length = QuicDataWriter::GetVarInt62Len(goaway.id);
118   QuicByteCount total_length =
119       GetTotalLength(payload_length, HttpFrameType::GOAWAY);
120 
121   std::string frame;
122   frame.resize(total_length);
123   QuicDataWriter writer(total_length, frame.data());
124 
125   if (WriteFrameHeader(payload_length, HttpFrameType::GOAWAY, &writer) &&
126       writer.WriteVarInt62(goaway.id)) {
127     return frame;
128   }
129   QUIC_DLOG(ERROR)
130       << "Http encoder failed when attempting to serialize goaway frame.";
131   return {};
132 }
133 
SerializePriorityUpdateFrame(const PriorityUpdateFrame & priority_update)134 std::string HttpEncoder::SerializePriorityUpdateFrame(
135     const PriorityUpdateFrame& priority_update) {
136   QuicByteCount payload_length =
137       QuicDataWriter::GetVarInt62Len(priority_update.prioritized_element_id) +
138       priority_update.priority_field_value.size();
139   QuicByteCount total_length = GetTotalLength(
140       payload_length, HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM);
141 
142   std::string frame;
143   frame.resize(total_length);
144   QuicDataWriter writer(total_length, frame.data());
145 
146   if (WriteFrameHeader(payload_length,
147                        HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM,
148                        &writer) &&
149       writer.WriteVarInt62(priority_update.prioritized_element_id) &&
150       writer.WriteBytes(priority_update.priority_field_value.data(),
151                         priority_update.priority_field_value.size())) {
152     return frame;
153   }
154 
155   QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
156                       "PRIORITY_UPDATE frame.";
157   return {};
158 }
159 
SerializeAcceptChFrame(const AcceptChFrame & accept_ch)160 std::string HttpEncoder::SerializeAcceptChFrame(
161     const AcceptChFrame& accept_ch) {
162   QuicByteCount payload_length = 0;
163   for (const auto& entry : accept_ch.entries) {
164     payload_length += QuicDataWriter::GetVarInt62Len(entry.origin.size());
165     payload_length += entry.origin.size();
166     payload_length += QuicDataWriter::GetVarInt62Len(entry.value.size());
167     payload_length += entry.value.size();
168   }
169 
170   QuicByteCount total_length =
171       GetTotalLength(payload_length, HttpFrameType::ACCEPT_CH);
172 
173   std::string frame;
174   frame.resize(total_length);
175   QuicDataWriter writer(total_length, frame.data());
176 
177   if (!WriteFrameHeader(payload_length, HttpFrameType::ACCEPT_CH, &writer)) {
178     QUIC_DLOG(ERROR)
179         << "Http encoder failed to serialize ACCEPT_CH frame header.";
180     return {};
181   }
182 
183   for (const auto& entry : accept_ch.entries) {
184     if (!writer.WriteStringPieceVarInt62(entry.origin) ||
185         !writer.WriteStringPieceVarInt62(entry.value)) {
186       QUIC_DLOG(ERROR)
187           << "Http encoder failed to serialize ACCEPT_CH frame payload.";
188       return {};
189     }
190   }
191 
192   return frame;
193 }
194 
SerializeGreasingFrame()195 std::string HttpEncoder::SerializeGreasingFrame() {
196   uint64_t frame_type;
197   QuicByteCount payload_length;
198   std::string payload;
199   if (!GetQuicFlag(quic_enable_http3_grease_randomness)) {
200     frame_type = 0x40;
201     payload_length = 1;
202     payload = "a";
203   } else {
204     uint32_t result;
205     QuicRandom::GetInstance()->RandBytes(&result, sizeof(result));
206     frame_type = 0x1fULL * static_cast<uint64_t>(result) + 0x21ULL;
207 
208     // The payload length is random but within [0, 3];
209     payload_length = result % 4;
210 
211     if (payload_length > 0) {
212       payload.resize(payload_length);
213       QuicRandom::GetInstance()->RandBytes(payload.data(), payload_length);
214     }
215   }
216   QuicByteCount total_length = QuicDataWriter::GetVarInt62Len(frame_type) +
217                                QuicDataWriter::GetVarInt62Len(payload_length) +
218                                payload_length;
219 
220   std::string frame;
221   frame.resize(total_length);
222   QuicDataWriter writer(total_length, frame.data());
223 
224   bool success =
225       writer.WriteVarInt62(frame_type) && writer.WriteVarInt62(payload_length);
226 
227   if (payload_length > 0) {
228     success &= writer.WriteBytes(payload.data(), payload_length);
229   }
230 
231   if (success) {
232     return frame;
233   }
234 
235   QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
236                       "greasing frame.";
237   return {};
238 }
239 
SerializeWebTransportStreamFrameHeader(WebTransportSessionId session_id)240 std::string HttpEncoder::SerializeWebTransportStreamFrameHeader(
241     WebTransportSessionId session_id) {
242   uint64_t stream_type =
243       static_cast<uint64_t>(HttpFrameType::WEBTRANSPORT_STREAM);
244   QuicByteCount header_length = QuicDataWriter::GetVarInt62Len(stream_type) +
245                                 QuicDataWriter::GetVarInt62Len(session_id);
246 
247   std::string frame;
248   frame.resize(header_length);
249   QuicDataWriter writer(header_length, frame.data());
250 
251   bool success =
252       writer.WriteVarInt62(stream_type) && writer.WriteVarInt62(session_id);
253   if (success && writer.remaining() == 0) {
254     return frame;
255   }
256 
257   QUIC_DLOG(ERROR) << "Http encoder failed when attempting to serialize "
258                       "WEBTRANSPORT_STREAM frame header.";
259   return {};
260 }
261 
SerializeMetadataFrameHeader(QuicByteCount payload_length)262 std::string HttpEncoder::SerializeMetadataFrameHeader(
263     QuicByteCount payload_length) {
264   QUICHE_DCHECK_NE(0u, payload_length);
265   QuicByteCount header_length =
266       QuicDataWriter::GetVarInt62Len(payload_length) +
267       QuicDataWriter::GetVarInt62Len(
268           static_cast<uint64_t>(HttpFrameType::METADATA));
269 
270   std::string frame;
271   frame.resize(header_length);
272   QuicDataWriter writer(header_length, frame.data());
273 
274   if (WriteFrameHeader(payload_length, HttpFrameType::METADATA, &writer)) {
275     return frame;
276   }
277   QUIC_DLOG(ERROR)
278       << "Http encoder failed when attempting to serialize METADATA "
279          "frame header.";
280   return {};
281 }
282 
283 }  // namespace quic
284