blob: beeef9b6abbd93fa59a6cae4222f91e8d6d49a62 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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
vasilvv872e7a32019-03-12 16:42:44 -07005#include <string>
6
QUICHE teama6ef0a62019-03-07 20:34:33 -05007#include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
8#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
10#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
11#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012
13namespace quic {
14
15namespace {
16
17// Set the first byte of a PRIORITY frame according to its fields.
18uint8_t SetPriorityFields(uint8_t num,
19 PriorityElementType type,
20 bool prioritized) {
21 switch (type) {
22 case REQUEST_STREAM:
23 return num;
24 case PUSH_STREAM:
25 if (prioritized) {
26 return num | (1 << 6);
27 }
28 return num | (1 << 4);
29 case PLACEHOLDER:
30 if (prioritized) {
31 return num | (1 << 7);
32 }
33 return num | (1 << 5);
34 case ROOT_OF_TREE:
35 if (prioritized) {
36 num = num | (1 << 6);
37 return num | (1 << 7);
38 }
39 num = num | (1 << 4);
40 return num | (1 << 5);
41 default:
42 QUIC_NOTREACHED();
43 return num;
44 }
45}
46
47// Length of the type field of a frame.
48static const size_t kFrameTypeLength = 1;
49// Length of the weight field of a priority frame.
50static const size_t kPriorityWeightLength = 1;
51// Length of a priority frame's first byte.
52static const size_t kPriorityFirstByteLength = 1;
53// Length of a key in the map of a settings frame.
54static const size_t kSettingsMapKeyLength = 2;
55
56} // namespace
57
58HttpEncoder::HttpEncoder() {}
59
60HttpEncoder::~HttpEncoder() {}
61
62QuicByteCount HttpEncoder::SerializeDataFrameHeader(
63 QuicByteCount payload_length,
64 std::unique_ptr<char[]>* output) {
65 DCHECK_NE(0u, payload_length);
66 QuicByteCount header_length =
67 QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
68
69 output->reset(new char[header_length]);
70 QuicDataWriter writer(header_length, output->get());
71
72 if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
73 return header_length;
74 }
75 return 0;
76}
77
78QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
79 QuicByteCount payload_length,
80 std::unique_ptr<char[]>* output) {
81 DCHECK_NE(0u, payload_length);
82 QuicByteCount header_length =
83 QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
84
85 output->reset(new char[header_length]);
86 QuicDataWriter writer(header_length, output->get());
87
88 if (WriteFrameHeader(payload_length, HttpFrameType::HEADERS, &writer)) {
89 return header_length;
90 }
91 return 0;
92}
93
94QuicByteCount HttpEncoder::SerializePriorityFrame(
95 const PriorityFrame& priority,
96 std::unique_ptr<char[]>* output) {
97 QuicByteCount payload_length =
98 kPriorityFirstByteLength +
99 QuicDataWriter::GetVarInt62Len(priority.prioritized_element_id) +
100 QuicDataWriter::GetVarInt62Len(priority.element_dependency_id) +
101 kPriorityWeightLength;
102 QuicByteCount total_length = GetTotalLength(payload_length);
103
104 output->reset(new char[total_length]);
105 QuicDataWriter writer(total_length, output->get());
106
107 if (!WriteFrameHeader(payload_length, HttpFrameType::PRIORITY, &writer)) {
108 return 0;
109 }
110
111 // Set the first byte of the payload.
112 uint8_t bits = 0;
113 bits = SetPriorityFields(bits, priority.prioritized_type, true);
114 bits = SetPriorityFields(bits, priority.dependency_type, false);
115 if (priority.exclusive) {
116 bits |= 1;
117 }
118
119 if (writer.WriteUInt8(bits) &&
120 writer.WriteVarInt62(priority.prioritized_element_id) &&
121 writer.WriteVarInt62(priority.element_dependency_id) &&
122 writer.WriteUInt8(priority.weight)) {
123 return total_length;
124 }
125 return 0;
126}
127
128QuicByteCount HttpEncoder::SerializeCancelPushFrame(
129 const CancelPushFrame& cancel_push,
130 std::unique_ptr<char[]>* output) {
131 QuicByteCount payload_length =
132 QuicDataWriter::GetVarInt62Len(cancel_push.push_id);
133 QuicByteCount total_length = GetTotalLength(payload_length);
134
135 output->reset(new char[total_length]);
136 QuicDataWriter writer(total_length, output->get());
137
138 if (WriteFrameHeader(payload_length, HttpFrameType::CANCEL_PUSH, &writer) &&
139 writer.WriteVarInt62(cancel_push.push_id)) {
140 return total_length;
141 }
142 return 0;
143}
144
145QuicByteCount HttpEncoder::SerializeSettingsFrame(
146 const SettingsFrame& settings,
147 std::unique_ptr<char[]>* output) {
148 // Calculate the key sizes.
149 QuicByteCount payload_length = settings.values.size() * kSettingsMapKeyLength;
150 // Calculate the value sizes.
151 for (auto it = settings.values.begin(); it != settings.values.end(); ++it) {
152 payload_length += QuicDataWriter::GetVarInt62Len(it->second);
153 }
154
155 QuicByteCount total_length = GetTotalLength(payload_length);
156
157 output->reset(new char[total_length]);
158 QuicDataWriter writer(total_length, output->get());
159
160 if (!WriteFrameHeader(payload_length, HttpFrameType::SETTINGS, &writer)) {
161 return 0;
162 }
163
164 for (auto it = settings.values.begin(); it != settings.values.end(); ++it) {
165 if (!writer.WriteUInt16(it->first) || !writer.WriteVarInt62(it->second)) {
166 return 0;
167 }
168 }
169
170 return total_length;
171}
172
173QuicByteCount HttpEncoder::SerializePushPromiseFrameWithOnlyPushId(
174 const PushPromiseFrame& push_promise,
175 std::unique_ptr<char[]>* output) {
176 QuicByteCount payload_length =
177 QuicDataWriter::GetVarInt62Len(push_promise.push_id) +
178 push_promise.headers.length();
179 // GetTotalLength() is not used because headers will not be serialized.
180 QuicByteCount total_length =
181 QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength +
182 QuicDataWriter::GetVarInt62Len(push_promise.push_id);
183
184 output->reset(new char[total_length]);
185 QuicDataWriter writer(total_length, output->get());
186
187 if (WriteFrameHeader(payload_length, HttpFrameType::PUSH_PROMISE, &writer) &&
188 writer.WriteVarInt62(push_promise.push_id)) {
189 return total_length;
190 }
191 return 0;
192}
193
194QuicByteCount HttpEncoder::SerializeGoAwayFrame(
195 const GoAwayFrame& goaway,
196 std::unique_ptr<char[]>* output) {
197 QuicByteCount payload_length =
198 QuicDataWriter::GetVarInt62Len(goaway.stream_id);
199 QuicByteCount total_length = GetTotalLength(payload_length);
200
201 output->reset(new char[total_length]);
202 QuicDataWriter writer(total_length, output->get());
203
204 if (WriteFrameHeader(payload_length, HttpFrameType::GOAWAY, &writer) &&
205 writer.WriteVarInt62(goaway.stream_id)) {
206 return total_length;
207 }
208 return 0;
209}
210
211QuicByteCount HttpEncoder::SerializeMaxPushIdFrame(
212 const MaxPushIdFrame& max_push_id,
213 std::unique_ptr<char[]>* output) {
214 QuicByteCount payload_length =
215 QuicDataWriter::GetVarInt62Len(max_push_id.push_id);
216 QuicByteCount total_length = GetTotalLength(payload_length);
217
218 output->reset(new char[total_length]);
219 QuicDataWriter writer(total_length, output->get());
220
221 if (WriteFrameHeader(payload_length, HttpFrameType::MAX_PUSH_ID, &writer) &&
222 writer.WriteVarInt62(max_push_id.push_id)) {
223 return total_length;
224 }
225 return 0;
226}
227
228QuicByteCount HttpEncoder::SerializeDuplicatePushFrame(
229 const DuplicatePushFrame& duplicate_push,
230 std::unique_ptr<char[]>* output) {
231 QuicByteCount payload_length =
232 QuicDataWriter::GetVarInt62Len(duplicate_push.push_id);
233 QuicByteCount total_length = GetTotalLength(payload_length);
234
235 output->reset(new char[total_length]);
236 QuicDataWriter writer(total_length, output->get());
237
238 if (WriteFrameHeader(payload_length, HttpFrameType::DUPLICATE_PUSH,
239 &writer) &&
240 writer.WriteVarInt62(duplicate_push.push_id)) {
241 return total_length;
242 }
243 return 0;
244}
245
246bool HttpEncoder::WriteFrameHeader(QuicByteCount length,
247 HttpFrameType type,
248 QuicDataWriter* writer) {
249 return writer->WriteVarInt62(length) &&
250 writer->WriteUInt8(static_cast<uint8_t>(type));
251}
252
253QuicByteCount HttpEncoder::GetTotalLength(QuicByteCount payload_length) {
254 return QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength +
255 payload_length;
256}
257
258} // namespace quic