• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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>
32 #include <string>
33 
34 #include "quiche/http2/http2_constants.h"
35 #include "quiche/common/platform/api/quiche_export.h"
36 #include "quiche/common/platform/api/quiche_logging.h"
37 
38 namespace http2 {
39 
40 struct QUICHE_EXPORT Http2FrameHeader {
Http2FrameHeaderHttp2FrameHeader41   Http2FrameHeader() {}
Http2FrameHeaderHttp2FrameHeader42   Http2FrameHeader(uint32_t payload_length, Http2FrameType type, uint8_t flags,
43                    uint32_t stream_id)
44       : payload_length(payload_length),
45         stream_id(stream_id),
46         type(type),
47         flags(flags) {
48     QUICHE_DCHECK_LT(payload_length, static_cast<uint32_t>(1 << 24))
49         << "Payload Length is only a 24 bit field\n"
50         << ToString();
51   }
52 
EncodedSizeHttp2FrameHeader53   static constexpr size_t EncodedSize() { return 9; }
54 
55   // Keep the current value of those flags that are in
56   // valid_flags, and clear all the others.
RetainFlagsHttp2FrameHeader57   void RetainFlags(uint8_t valid_flags) { flags = (flags & valid_flags); }
58 
59   // Returns true if any of the flags in flag_mask are set,
60   // otherwise false.
HasAnyFlagsHttp2FrameHeader61   bool HasAnyFlags(uint8_t flag_mask) const { return 0 != (flags & flag_mask); }
62 
63   // Is the END_STREAM flag set?
IsEndStreamHttp2FrameHeader64   bool IsEndStream() const {
65     QUICHE_DCHECK(type == Http2FrameType::DATA ||
66                   type == Http2FrameType::HEADERS)
67         << ToString();
68     return (flags & Http2FrameFlag::END_STREAM) != 0;
69   }
70 
71   // Is the ACK flag set?
IsAckHttp2FrameHeader72   bool IsAck() const {
73     QUICHE_DCHECK(type == Http2FrameType::SETTINGS ||
74                   type == Http2FrameType::PING)
75         << ToString();
76     return (flags & Http2FrameFlag::ACK) != 0;
77   }
78 
79   // Is the END_HEADERS flag set?
IsEndHeadersHttp2FrameHeader80   bool IsEndHeaders() const {
81     QUICHE_DCHECK(type == Http2FrameType::HEADERS ||
82                   type == Http2FrameType::PUSH_PROMISE ||
83                   type == Http2FrameType::CONTINUATION)
84         << ToString();
85     return (flags & Http2FrameFlag::END_HEADERS) != 0;
86   }
87 
88   // Is the PADDED flag set?
IsPaddedHttp2FrameHeader89   bool IsPadded() const {
90     QUICHE_DCHECK(type == Http2FrameType::DATA ||
91                   type == Http2FrameType::HEADERS ||
92                   type == Http2FrameType::PUSH_PROMISE)
93         << ToString();
94     return (flags & Http2FrameFlag::PADDED) != 0;
95   }
96 
97   // Is the PRIORITY flag set?
HasPriorityHttp2FrameHeader98   bool HasPriority() const {
99     QUICHE_DCHECK_EQ(type, Http2FrameType::HEADERS) << ToString();
100     return (flags & Http2FrameFlag::PRIORITY) != 0;
101   }
102 
103   // Does the encoding of this header start with "HTTP/", indicating that it
104   // might be from a non-HTTP/2 server.
105   bool IsProbableHttpResponse() const;
106 
107   // Produce strings useful for debugging/logging messages.
108   std::string ToString() const;
109   std::string FlagsToString() const;
110 
111   // 24 bit length of the payload after the header, including any padding.
112   // First field in encoding.
113   uint32_t payload_length;  // 24 bits
114 
115   // 31 bit stream id, with high bit (32nd bit) reserved (must be zero),
116   // and is cleared during decoding.
117   // Fourth field in encoding.
118   uint32_t stream_id;
119 
120   // Type of the frame.
121   // Second field in encoding.
122   Http2FrameType type;
123 
124   // Flag bits, with interpretations that depend upon the frame type.
125   // Flag bits not used by the frame type are cleared.
126   // Third field in encoding.
127   uint8_t flags;
128 };
129 
130 QUICHE_EXPORT bool operator==(const Http2FrameHeader& a,
131                               const Http2FrameHeader& b);
132 QUICHE_EXPORT inline bool operator!=(const Http2FrameHeader& a,
133                                      const Http2FrameHeader& b) {
134   return !(a == b);
135 }
136 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
137                                        const Http2FrameHeader& v);
138 
139 // Http2PriorityFields:
140 
141 struct QUICHE_EXPORT Http2PriorityFields {
Http2PriorityFieldsHttp2PriorityFields142   Http2PriorityFields() {}
Http2PriorityFieldsHttp2PriorityFields143   Http2PriorityFields(uint32_t stream_dependency, uint32_t weight,
144                       bool is_exclusive)
145       : stream_dependency(stream_dependency),
146         weight(weight),
147         is_exclusive(is_exclusive) {
148     // Can't have the high-bit set in the stream id because we need to use
149     // that for the EXCLUSIVE flag bit.
150     QUICHE_DCHECK_EQ(stream_dependency, stream_dependency & StreamIdMask())
151         << "Stream Dependency is only a 31-bit field.\n"
152         << ToString();
153     QUICHE_DCHECK_LE(1u, weight) << "Weight is too small.";
154     QUICHE_DCHECK_LE(weight, 256u) << "Weight is too large.";
155   }
EncodedSizeHttp2PriorityFields156   static constexpr size_t EncodedSize() { return 5; }
157 
158   // Produce strings useful for debugging/logging messages.
159   std::string ToString() const;
160 
161   // A 31-bit stream identifier for the stream that this stream depends on.
162   uint32_t stream_dependency;
163 
164   // Weight (1 to 256) is encoded as a byte in the range 0 to 255, so we
165   // add one when decoding, and store it in a field larger than a byte.
166   uint32_t weight;
167 
168   // A single-bit flag indicating that the stream dependency is exclusive;
169   // extracted from high bit of stream dependency field during decoding.
170   bool is_exclusive;
171 };
172 
173 QUICHE_EXPORT bool operator==(const Http2PriorityFields& a,
174                               const Http2PriorityFields& b);
175 QUICHE_EXPORT inline bool operator!=(const Http2PriorityFields& a,
176                                      const Http2PriorityFields& b) {
177   return !(a == b);
178 }
179 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
180                                        const Http2PriorityFields& v);
181 
182 // Http2RstStreamFields:
183 
184 struct QUICHE_EXPORT Http2RstStreamFields {
EncodedSizeHttp2RstStreamFields185   static constexpr size_t EncodedSize() { return 4; }
IsSupportedErrorCodeHttp2RstStreamFields186   bool IsSupportedErrorCode() const {
187     return IsSupportedHttp2ErrorCode(error_code);
188   }
189 
190   Http2ErrorCode error_code;
191 };
192 
193 QUICHE_EXPORT bool operator==(const Http2RstStreamFields& a,
194                               const Http2RstStreamFields& b);
195 QUICHE_EXPORT inline bool operator!=(const Http2RstStreamFields& a,
196                                      const Http2RstStreamFields& b) {
197   return !(a == b);
198 }
199 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
200                                        const Http2RstStreamFields& v);
201 
202 // Http2SettingFields:
203 
204 struct QUICHE_EXPORT Http2SettingFields {
Http2SettingFieldsHttp2SettingFields205   Http2SettingFields() {}
Http2SettingFieldsHttp2SettingFields206   Http2SettingFields(Http2SettingsParameter parameter, uint32_t value)
207       : parameter(parameter), value(value) {}
EncodedSizeHttp2SettingFields208   static constexpr size_t EncodedSize() { return 6; }
IsSupportedParameterHttp2SettingFields209   bool IsSupportedParameter() const {
210     return IsSupportedHttp2SettingsParameter(parameter);
211   }
212 
213   Http2SettingsParameter parameter;
214   uint32_t value;
215 };
216 
217 QUICHE_EXPORT bool operator==(const Http2SettingFields& a,
218                               const Http2SettingFields& b);
219 QUICHE_EXPORT inline bool operator!=(const Http2SettingFields& a,
220                                      const Http2SettingFields& b) {
221   return !(a == b);
222 }
223 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
224                                        const Http2SettingFields& v);
225 
226 // Http2PushPromiseFields:
227 
228 struct QUICHE_EXPORT Http2PushPromiseFields {
EncodedSizeHttp2PushPromiseFields229   static constexpr size_t EncodedSize() { return 4; }
230 
231   uint32_t promised_stream_id;
232 };
233 
234 QUICHE_EXPORT bool operator==(const Http2PushPromiseFields& a,
235                               const Http2PushPromiseFields& b);
236 QUICHE_EXPORT inline bool operator!=(const Http2PushPromiseFields& a,
237                                      const Http2PushPromiseFields& b) {
238   return !(a == b);
239 }
240 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
241                                        const Http2PushPromiseFields& v);
242 
243 // Http2PingFields:
244 
245 struct QUICHE_EXPORT Http2PingFields {
EncodedSizeHttp2PingFields246   static constexpr size_t EncodedSize() { return 8; }
247 
248   uint8_t opaque_bytes[8];
249 };
250 
251 QUICHE_EXPORT bool operator==(const Http2PingFields& a,
252                               const Http2PingFields& b);
253 QUICHE_EXPORT inline bool operator!=(const Http2PingFields& a,
254                                      const Http2PingFields& b) {
255   return !(a == b);
256 }
257 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
258                                        const Http2PingFields& v);
259 
260 // Http2GoAwayFields:
261 
262 struct QUICHE_EXPORT Http2GoAwayFields {
Http2GoAwayFieldsHttp2GoAwayFields263   Http2GoAwayFields() {}
Http2GoAwayFieldsHttp2GoAwayFields264   Http2GoAwayFields(uint32_t last_stream_id, Http2ErrorCode error_code)
265       : last_stream_id(last_stream_id), error_code(error_code) {}
EncodedSizeHttp2GoAwayFields266   static constexpr size_t EncodedSize() { return 8; }
IsSupportedErrorCodeHttp2GoAwayFields267   bool IsSupportedErrorCode() const {
268     return IsSupportedHttp2ErrorCode(error_code);
269   }
270 
271   uint32_t last_stream_id;
272   Http2ErrorCode error_code;
273 };
274 
275 QUICHE_EXPORT bool operator==(const Http2GoAwayFields& a,
276                               const Http2GoAwayFields& b);
277 QUICHE_EXPORT inline bool operator!=(const Http2GoAwayFields& a,
278                                      const Http2GoAwayFields& b) {
279   return !(a == b);
280 }
281 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
282                                        const Http2GoAwayFields& v);
283 
284 // Http2WindowUpdateFields:
285 
286 struct QUICHE_EXPORT Http2WindowUpdateFields {
EncodedSizeHttp2WindowUpdateFields287   static constexpr size_t EncodedSize() { return 4; }
288 
289   // 31-bit, unsigned increase in the window size (only positive values are
290   // allowed). The high-bit is reserved for the future.
291   uint32_t window_size_increment;
292 };
293 
294 QUICHE_EXPORT bool operator==(const Http2WindowUpdateFields& a,
295                               const Http2WindowUpdateFields& b);
296 QUICHE_EXPORT inline bool operator!=(const Http2WindowUpdateFields& a,
297                                      const Http2WindowUpdateFields& b) {
298   return !(a == b);
299 }
300 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
301                                        const Http2WindowUpdateFields& v);
302 
303 // Http2AltSvcFields:
304 
305 struct QUICHE_EXPORT Http2AltSvcFields {
EncodedSizeHttp2AltSvcFields306   static constexpr size_t EncodedSize() { return 2; }
307 
308   // This is the one fixed size portion of the ALTSVC payload.
309   uint16_t origin_length;
310 };
311 
312 QUICHE_EXPORT bool operator==(const Http2AltSvcFields& a,
313                               const Http2AltSvcFields& b);
314 QUICHE_EXPORT inline bool operator!=(const Http2AltSvcFields& a,
315                                      const Http2AltSvcFields& b) {
316   return !(a == b);
317 }
318 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
319                                        const Http2AltSvcFields& v);
320 
321 // Http2PriorityUpdateFields:
322 
323 struct QUICHE_EXPORT Http2PriorityUpdateFields {
Http2PriorityUpdateFieldsHttp2PriorityUpdateFields324   Http2PriorityUpdateFields() {}
Http2PriorityUpdateFieldsHttp2PriorityUpdateFields325   Http2PriorityUpdateFields(uint32_t prioritized_stream_id)
326       : prioritized_stream_id(prioritized_stream_id) {}
EncodedSizeHttp2PriorityUpdateFields327   static constexpr size_t EncodedSize() { return 4; }
328 
329   // Produce strings useful for debugging/logging messages.
330   std::string ToString() const;
331 
332   // The 31-bit stream identifier of the stream whose priority is updated.
333   uint32_t prioritized_stream_id;
334 };
335 
336 QUICHE_EXPORT bool operator==(const Http2PriorityUpdateFields& a,
337                               const Http2PriorityUpdateFields& b);
338 QUICHE_EXPORT inline bool operator!=(const Http2PriorityUpdateFields& a,
339                                      const Http2PriorityUpdateFields& b) {
340   return !(a == b);
341 }
342 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
343                                        const Http2PriorityUpdateFields& v);
344 
345 }  // namespace http2
346 
347 #endif  // QUICHE_HTTP2_HTTP2_STRUCTURES_H_
348