blob: a60ac89f0d5f0c1ae1feacee05ca8f3a0f4c64ad [file] [log] [blame]
QUICHE teamfd50a402018-12-07 22:54:05 -05001// Copyright 2016 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#ifndef QUICHE_HTTP2_HTTP2_STRUCTURES_H_
6#define QUICHE_HTTP2_HTTP2_STRUCTURES_H_
7
8// Defines structs for various fixed sized structures in HTTP/2.
9//
10// Those structs with multiple fields have constructors that take arguments in
11// the same order as their encoding (which may be different from their order
12// in the struct). For single field structs, use aggregate initialization if
13// desired, e.g.:
14//
15// Http2RstStreamFields var{Http2ErrorCode::ENHANCE_YOUR_CALM};
16// or:
17// SomeFunc(Http2RstStreamFields{Http2ErrorCode::ENHANCE_YOUR_CALM});
18//
19// Each struct includes a static method EncodedSize which returns the number
20// of bytes of the encoding.
21//
22// With the exception of Http2FrameHeader, all the types are named
23// Http2<X>Fields, where X is the title-case form of the frame which always
24// includes the fields; the "always" is to cover the case of the PRIORITY frame;
25// its fields optionally appear in the HEADERS frame, but the struct is called
26// Http2PriorityFields.
27
28#include <stddef.h>
29
30#include <cstdint>
31#include <ostream>
bnc47904002019-08-16 11:49:48 -070032#include <string>
QUICHE teamfd50a402018-12-07 22:54:05 -050033
QUICHE teamfd50a402018-12-07 22:54:05 -050034#include "net/third_party/quiche/src/http2/http2_constants.h"
QUICHE team61940b42019-03-07 23:32:27 -050035#include "net/third_party/quiche/src/http2/platform/api/http2_logging.h"
bnc641ace72020-01-21 12:24:57 -080036#include "net/third_party/quiche/src/common/platform/api/quiche_export.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050037
38namespace http2 {
39
bnc641ace72020-01-21 12:24:57 -080040struct QUICHE_EXPORT_PRIVATE Http2FrameHeader {
QUICHE teamfd50a402018-12-07 22:54:05 -050041 Http2FrameHeader() {}
42 Http2FrameHeader(uint32_t payload_length,
43 Http2FrameType type,
44 uint8_t flags,
45 uint32_t stream_id)
46 : payload_length(payload_length),
47 stream_id(stream_id),
48 type(type),
49 flags(static_cast<Http2FrameFlag>(flags)) {
50 DCHECK_LT(payload_length, static_cast<uint32_t>(1 << 24))
51 << "Payload Length is only a 24 bit field\n"
52 << ToString();
53 }
54
55 static constexpr size_t EncodedSize() { return 9; }
56
57 // Keep the current value of those flags that are in
58 // valid_flags, and clear all the others.
59 void RetainFlags(uint8_t valid_flags) {
60 flags = static_cast<Http2FrameFlag>(flags & valid_flags);
61 }
62
63 // Returns true if any of the flags in flag_mask are set,
64 // otherwise false.
65 bool HasAnyFlags(uint8_t flag_mask) const { return 0 != (flags & flag_mask); }
66
67 // Is the END_STREAM flag set?
68 bool IsEndStream() const {
69 DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS)
70 << ToString();
71 return (flags & Http2FrameFlag::END_STREAM) != 0;
72 }
73
74 // Is the ACK flag set?
75 bool IsAck() const {
76 DCHECK(type == Http2FrameType::SETTINGS || type == Http2FrameType::PING)
77 << ToString();
78 return (flags & Http2FrameFlag::ACK) != 0;
79 }
80
81 // Is the END_HEADERS flag set?
82 bool IsEndHeaders() const {
83 DCHECK(type == Http2FrameType::HEADERS ||
84 type == Http2FrameType::PUSH_PROMISE ||
85 type == Http2FrameType::CONTINUATION)
86 << ToString();
87 return (flags & Http2FrameFlag::END_HEADERS) != 0;
88 }
89
90 // Is the PADDED flag set?
91 bool IsPadded() const {
92 DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
93 type == Http2FrameType::PUSH_PROMISE)
94 << ToString();
95 return (flags & Http2FrameFlag::PADDED) != 0;
96 }
97
98 // Is the PRIORITY flag set?
99 bool HasPriority() const {
100 DCHECK_EQ(type, Http2FrameType::HEADERS) << ToString();
101 return (flags & Http2FrameFlag::PRIORITY) != 0;
102 }
103
104 // Does the encoding of this header start with "HTTP/", indicating that it
105 // might be from a non-HTTP/2 server.
106 bool IsProbableHttpResponse() const;
107
108 // Produce strings useful for debugging/logging messages.
bnc47904002019-08-16 11:49:48 -0700109 std::string ToString() const;
110 std::string FlagsToString() const;
QUICHE teamfd50a402018-12-07 22:54:05 -0500111
112 // 24 bit length of the payload after the header, including any padding.
113 // First field in encoding.
114 uint32_t payload_length; // 24 bits
115
116 // 31 bit stream id, with high bit (32nd bit) reserved (must be zero),
117 // and is cleared during decoding.
118 // Fourth field in encoding.
119 uint32_t stream_id;
120
121 // Type of the frame.
122 // Second field in encoding.
123 Http2FrameType type;
124
125 // Flag bits, with interpretations that depend upon the frame type.
126 // Flag bits not used by the frame type are cleared.
127 // Third field in encoding.
128 Http2FrameFlag flags;
129};
130
bnc641ace72020-01-21 12:24:57 -0800131QUICHE_EXPORT_PRIVATE bool operator==(const Http2FrameHeader& a,
132 const Http2FrameHeader& b);
133QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2FrameHeader& a,
134 const Http2FrameHeader& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500135 return !(a == b);
136}
bnc641ace72020-01-21 12:24:57 -0800137QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
138 const Http2FrameHeader& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500139
140// Http2PriorityFields:
141
bnc641ace72020-01-21 12:24:57 -0800142struct QUICHE_EXPORT_PRIVATE Http2PriorityFields {
QUICHE teamfd50a402018-12-07 22:54:05 -0500143 Http2PriorityFields() {}
144 Http2PriorityFields(uint32_t stream_dependency,
145 uint32_t weight,
146 bool is_exclusive)
147 : stream_dependency(stream_dependency),
148 weight(weight),
149 is_exclusive(is_exclusive) {
150 // Can't have the high-bit set in the stream id because we need to use
151 // that for the EXCLUSIVE flag bit.
152 DCHECK_EQ(stream_dependency, stream_dependency & StreamIdMask())
153 << "Stream Dependency is only a 31-bit field.\n"
154 << ToString();
155 DCHECK_LE(1u, weight) << "Weight is too small.";
156 DCHECK_LE(weight, 256u) << "Weight is too large.";
157 }
158 static constexpr size_t EncodedSize() { return 5; }
159
160 // Produce strings useful for debugging/logging messages.
bnc47904002019-08-16 11:49:48 -0700161 std::string ToString() const;
QUICHE teamfd50a402018-12-07 22:54:05 -0500162
163 // A 31-bit stream identifier for the stream that this stream depends on.
164 uint32_t stream_dependency;
165
166 // Weight (1 to 256) is encoded as a byte in the range 0 to 255, so we
167 // add one when decoding, and store it in a field larger than a byte.
168 uint32_t weight;
169
170 // A single-bit flag indicating that the stream dependency is exclusive;
171 // extracted from high bit of stream dependency field during decoding.
172 bool is_exclusive;
173};
174
bnc641ace72020-01-21 12:24:57 -0800175QUICHE_EXPORT_PRIVATE bool operator==(const Http2PriorityFields& a,
176 const Http2PriorityFields& b);
177QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2PriorityFields& a,
178 const Http2PriorityFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500179 return !(a == b);
180}
bnc641ace72020-01-21 12:24:57 -0800181QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
182 const Http2PriorityFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500183
184// Http2RstStreamFields:
185
186struct Http2RstStreamFields {
187 static constexpr size_t EncodedSize() { return 4; }
188 bool IsSupportedErrorCode() const {
189 return IsSupportedHttp2ErrorCode(error_code);
190 }
191
192 Http2ErrorCode error_code;
193};
194
bnc641ace72020-01-21 12:24:57 -0800195QUICHE_EXPORT_PRIVATE bool operator==(const Http2RstStreamFields& a,
196 const Http2RstStreamFields& b);
197QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2RstStreamFields& a,
198 const Http2RstStreamFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500199 return !(a == b);
200}
bnc641ace72020-01-21 12:24:57 -0800201QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
202 const Http2RstStreamFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500203
204// Http2SettingFields:
205
206struct Http2SettingFields {
207 Http2SettingFields() {}
208 Http2SettingFields(Http2SettingsParameter parameter, uint32_t value)
209 : parameter(parameter), value(value) {}
210 static constexpr size_t EncodedSize() { return 6; }
211 bool IsSupportedParameter() const {
212 return IsSupportedHttp2SettingsParameter(parameter);
213 }
214
215 Http2SettingsParameter parameter;
216 uint32_t value;
217};
218
bnc641ace72020-01-21 12:24:57 -0800219QUICHE_EXPORT_PRIVATE bool operator==(const Http2SettingFields& a,
220 const Http2SettingFields& b);
221QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2SettingFields& a,
222 const Http2SettingFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500223 return !(a == b);
224}
bnc641ace72020-01-21 12:24:57 -0800225QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
226 const Http2SettingFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500227
228// Http2PushPromiseFields:
229
230struct Http2PushPromiseFields {
231 static constexpr size_t EncodedSize() { return 4; }
232
233 uint32_t promised_stream_id;
234};
235
bnc641ace72020-01-21 12:24:57 -0800236QUICHE_EXPORT_PRIVATE bool operator==(const Http2PushPromiseFields& a,
237 const Http2PushPromiseFields& b);
238QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2PushPromiseFields& a,
239 const Http2PushPromiseFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500240 return !(a == b);
241}
bnc641ace72020-01-21 12:24:57 -0800242QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
243 const Http2PushPromiseFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500244
245// Http2PingFields:
246
247struct Http2PingFields {
248 static constexpr size_t EncodedSize() { return 8; }
249
250 uint8_t opaque_bytes[8];
251};
252
bnc641ace72020-01-21 12:24:57 -0800253QUICHE_EXPORT_PRIVATE bool operator==(const Http2PingFields& a,
254 const Http2PingFields& b);
255QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2PingFields& a,
256 const Http2PingFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500257 return !(a == b);
258}
bnc641ace72020-01-21 12:24:57 -0800259QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
260 const Http2PingFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500261
262// Http2GoAwayFields:
263
264struct Http2GoAwayFields {
265 Http2GoAwayFields() {}
266 Http2GoAwayFields(uint32_t last_stream_id, Http2ErrorCode error_code)
267 : last_stream_id(last_stream_id), error_code(error_code) {}
268 static constexpr size_t EncodedSize() { return 8; }
269 bool IsSupportedErrorCode() const {
270 return IsSupportedHttp2ErrorCode(error_code);
271 }
272
273 uint32_t last_stream_id;
274 Http2ErrorCode error_code;
275};
276
bnc641ace72020-01-21 12:24:57 -0800277QUICHE_EXPORT_PRIVATE bool operator==(const Http2GoAwayFields& a,
278 const Http2GoAwayFields& b);
279QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2GoAwayFields& a,
280 const Http2GoAwayFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500281 return !(a == b);
282}
bnc641ace72020-01-21 12:24:57 -0800283QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
284 const Http2GoAwayFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500285
286// Http2WindowUpdateFields:
287
288struct Http2WindowUpdateFields {
289 static constexpr size_t EncodedSize() { return 4; }
290
291 // 31-bit, unsigned increase in the window size (only positive values are
292 // allowed). The high-bit is reserved for the future.
293 uint32_t window_size_increment;
294};
295
bnc641ace72020-01-21 12:24:57 -0800296QUICHE_EXPORT_PRIVATE bool operator==(const Http2WindowUpdateFields& a,
297 const Http2WindowUpdateFields& b);
298QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2WindowUpdateFields& a,
299 const Http2WindowUpdateFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500300 return !(a == b);
301}
bnc641ace72020-01-21 12:24:57 -0800302QUICHE_EXPORT_PRIVATE std::ostream& operator<<(
303 std::ostream& out,
304 const Http2WindowUpdateFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500305
306// Http2AltSvcFields:
307
308struct Http2AltSvcFields {
309 static constexpr size_t EncodedSize() { return 2; }
310
311 // This is the one fixed size portion of the ALTSVC payload.
312 uint16_t origin_length;
313};
314
bnc641ace72020-01-21 12:24:57 -0800315QUICHE_EXPORT_PRIVATE bool operator==(const Http2AltSvcFields& a,
316 const Http2AltSvcFields& b);
317QUICHE_EXPORT_PRIVATE inline bool operator!=(const Http2AltSvcFields& a,
318 const Http2AltSvcFields& b) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500319 return !(a == b);
320}
bnc641ace72020-01-21 12:24:57 -0800321QUICHE_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
322 const Http2AltSvcFields& v);
QUICHE teamfd50a402018-12-07 22:54:05 -0500323
324} // namespace http2
325
326#endif // QUICHE_HTTP2_HTTP2_STRUCTURES_H_