1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
|
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_HTTP2_HTTP2_STRUCTURES_H_
#define NET_HTTP2_HTTP2_STRUCTURES_H_
// Defines structs for various fixed sized structures in HTTP/2.
//
// Those structs with multiple fields have constructors that take arguments in
// the same order as their encoding (which may be different from their order
// in the struct). For single field structs, use aggregate initialization if
// desired, e.g.:
//
// Http2RstStreamFields var{Http2ErrorCode::ENHANCE_YOUR_CALM};
// or:
// SomeFunc(Http2RstStreamFields{Http2ErrorCode::ENHANCE_YOUR_CALM});
//
// Each struct includes a static method EncodedSize which returns the number
// of bytes of the encoding.
//
// With the exception of Http2FrameHeader, all the types are named
// Http2<X>Fields, where X is the title-case form of the frame which always
// includes the fields; the "always" is to cover the case of the PRIORITY frame;
// its fields optionally appear in the HEADERS frame, but the struct is called
// Http2PriorityFields.
#include <stddef.h>
#include <stdint.h>
#include <ostream>
#include "base/logging.h"
#include "net/http2/http2_constants.h"
#include "net/http2/platform/api/http2_export.h"
#include "net/http2/platform/api/http2_string.h"
namespace net {
struct HTTP2_EXPORT_PRIVATE Http2FrameHeader {
Http2FrameHeader() {}
Http2FrameHeader(uint32_t payload_length,
Http2FrameType type,
uint8_t flags,
uint32_t stream_id)
: payload_length(payload_length),
stream_id(stream_id),
type(type),
flags(static_cast<Http2FrameFlag>(flags)) {
DCHECK_LT(payload_length, static_cast<uint32_t>(1 << 24))
<< "Payload Length is only a 24 bit field\n"
<< ToString();
}
static constexpr size_t EncodedSize() { return 9; }
// Keep the current value of those flags that are in
// valid_flags, and clear all the others.
void RetainFlags(uint8_t valid_flags) {
flags = static_cast<Http2FrameFlag>(flags & valid_flags);
}
// Returns true if any of the flags in flag_mask are set,
// otherwise false.
bool HasAnyFlags(uint8_t flag_mask) const { return 0 != (flags & flag_mask); }
// Is the END_STREAM flag set?
bool IsEndStream() const {
DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS)
<< ToString();
return (flags & Http2FrameFlag::END_STREAM) != 0;
}
// Is the ACK flag set?
bool IsAck() const {
DCHECK(type == Http2FrameType::SETTINGS || type == Http2FrameType::PING)
<< ToString();
return (flags & Http2FrameFlag::ACK) != 0;
}
// Is the END_HEADERS flag set?
bool IsEndHeaders() const {
DCHECK(type == Http2FrameType::HEADERS ||
type == Http2FrameType::PUSH_PROMISE ||
type == Http2FrameType::CONTINUATION)
<< ToString();
return (flags & Http2FrameFlag::END_HEADERS) != 0;
}
// Is the PADDED flag set?
bool IsPadded() const {
DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS ||
type == Http2FrameType::PUSH_PROMISE)
<< ToString();
return (flags & Http2FrameFlag::PADDED) != 0;
}
// Is the PRIORITY flag set?
bool HasPriority() const {
DCHECK_EQ(type, Http2FrameType::HEADERS) << ToString();
return (flags & Http2FrameFlag::PRIORITY) != 0;
}
// Does the encoding of this header start with "HTTP/", indicating that it
// might be from a non-HTTP/2 server.
bool IsProbableHttpResponse() const;
// Produce strings useful for debugging/logging messages.
Http2String ToString() const;
Http2String FlagsToString() const;
// 24 bit length of the payload after the header, including any padding.
// First field in encoding.
uint32_t payload_length; // 24 bits
// 31 bit stream id, with high bit (32nd bit) reserved (must be zero),
// and is cleared during decoding.
// Fourth field in encoding.
uint32_t stream_id;
// Type of the frame.
// Second field in encoding.
Http2FrameType type;
// Flag bits, with interpretations that depend upon the frame type.
// Flag bits not used by the frame type are cleared.
// Third field in encoding.
Http2FrameFlag flags;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2FrameHeader& a,
const Http2FrameHeader& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2FrameHeader& a,
const Http2FrameHeader& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2FrameHeader& v);
// Http2PriorityFields:
struct HTTP2_EXPORT_PRIVATE Http2PriorityFields {
Http2PriorityFields() {}
Http2PriorityFields(uint32_t stream_dependency,
uint32_t weight,
bool is_exclusive)
: stream_dependency(stream_dependency),
weight(weight),
is_exclusive(is_exclusive) {
// Can't have the high-bit set in the stream id because we need to use
// that for the EXCLUSIVE flag bit.
DCHECK_EQ(stream_dependency, stream_dependency & StreamIdMask())
<< "Stream Dependency is only a 31-bit field.\n"
<< ToString();
DCHECK_LE(1u, weight) << "Weight is too small.";
DCHECK_LE(weight, 256u) << "Weight is too large.";
}
static constexpr size_t EncodedSize() { return 5; }
// Produce strings useful for debugging/logging messages.
Http2String ToString() const;
// A 31-bit stream identifier for the stream that this stream depends on.
uint32_t stream_dependency;
// Weight (1 to 256) is encoded as a byte in the range 0 to 255, so we
// add one when decoding, and store it in a field larger than a byte.
uint32_t weight;
// A single-bit flag indicating that the stream dependency is exclusive;
// extracted from high bit of stream dependency field during decoding.
bool is_exclusive;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2PriorityFields& a,
const Http2PriorityFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PriorityFields& a,
const Http2PriorityFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2PriorityFields& v);
// Http2RstStreamFields:
struct Http2RstStreamFields {
static constexpr size_t EncodedSize() { return 4; }
bool IsSupportedErrorCode() const {
return IsSupportedHttp2ErrorCode(error_code);
}
Http2ErrorCode error_code;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2RstStreamFields& a,
const Http2RstStreamFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2RstStreamFields& a,
const Http2RstStreamFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2RstStreamFields& v);
// Http2SettingFields:
struct Http2SettingFields {
Http2SettingFields() {}
Http2SettingFields(Http2SettingsParameter parameter, uint32_t value)
: parameter(parameter), value(value) {}
static constexpr size_t EncodedSize() { return 6; }
bool IsSupportedParameter() const {
return IsSupportedHttp2SettingsParameter(parameter);
}
Http2SettingsParameter parameter;
uint32_t value;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2SettingFields& a,
const Http2SettingFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2SettingFields& a,
const Http2SettingFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2SettingFields& v);
// Http2PushPromiseFields:
struct Http2PushPromiseFields {
static constexpr size_t EncodedSize() { return 4; }
uint32_t promised_stream_id;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2PushPromiseFields& a,
const Http2PushPromiseFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PushPromiseFields& a,
const Http2PushPromiseFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2PushPromiseFields& v);
// Http2PingFields:
struct Http2PingFields {
static constexpr size_t EncodedSize() { return 8; }
uint8_t opaque_bytes[8];
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2PingFields& a,
const Http2PingFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PingFields& a,
const Http2PingFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2PingFields& v);
// Http2GoAwayFields:
struct Http2GoAwayFields {
Http2GoAwayFields() {}
Http2GoAwayFields(uint32_t last_stream_id, Http2ErrorCode error_code)
: last_stream_id(last_stream_id), error_code(error_code) {}
static constexpr size_t EncodedSize() { return 8; }
bool IsSupportedErrorCode() const {
return IsSupportedHttp2ErrorCode(error_code);
}
uint32_t last_stream_id;
Http2ErrorCode error_code;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2GoAwayFields& a,
const Http2GoAwayFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2GoAwayFields& a,
const Http2GoAwayFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2GoAwayFields& v);
// Http2WindowUpdateFields:
struct Http2WindowUpdateFields {
static constexpr size_t EncodedSize() { return 4; }
// 31-bit, unsigned increase in the window size (only positive values are
// allowed). The high-bit is reserved for the future.
uint32_t window_size_increment;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2WindowUpdateFields& a,
const Http2WindowUpdateFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2WindowUpdateFields& a,
const Http2WindowUpdateFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2WindowUpdateFields& v);
// Http2AltSvcFields:
struct Http2AltSvcFields {
static constexpr size_t EncodedSize() { return 2; }
// This is the one fixed size portion of the ALTSVC payload.
uint16_t origin_length;
};
HTTP2_EXPORT_PRIVATE bool operator==(const Http2AltSvcFields& a,
const Http2AltSvcFields& b);
HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2AltSvcFields& a,
const Http2AltSvcFields& b) {
return !(a == b);
}
HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
const Http2AltSvcFields& v);
} // namespace net
#endif // NET_HTTP2_HTTP2_STRUCTURES_H_
|