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