xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2012 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 // This file contains some protocol structures for use with SPDY 3 and HTTP 2
6 // The SPDY 3 spec can be found at:
7 // http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3
8 
9 #ifndef QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_
10 #define QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_
11 
12 #include <cstddef>
13 #include <cstdint>
14 #include <cstring>
15 #include <iosfwd>
16 #include <map>
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "absl/strings/string_view.h"
23 #include "absl/types/variant.h"
24 #include "quiche/common/platform/api/quiche_export.h"
25 #include "quiche/common/platform/api/quiche_flags.h"
26 #include "quiche/common/platform/api/quiche_logging.h"
27 #include "quiche/spdy/core/http2_header_block.h"
28 #include "quiche/spdy/core/spdy_alt_svc_wire_format.h"
29 #include "quiche/spdy/core/spdy_bitmasks.h"
30 
31 namespace spdy {
32 
33 // A stream ID is a 31-bit entity.
34 using SpdyStreamId = uint32_t;
35 
36 // A SETTINGS ID is a 16-bit entity.
37 using SpdySettingsId = uint16_t;
38 
39 // Specifies the stream ID used to denote the current session (for
40 // flow control).
41 inline constexpr SpdyStreamId kSessionFlowControlStreamId = 0;
42 
43 // 0 is not a valid stream ID for any other purpose than flow control.
44 inline constexpr SpdyStreamId kInvalidStreamId = 0;
45 
46 // Max stream id.
47 inline constexpr SpdyStreamId kMaxStreamId = 0x7fffffff;
48 
49 // The maximum possible frame payload size allowed by the spec.
50 inline constexpr uint32_t kSpdyMaxFrameSizeLimit = (1 << 24) - 1;
51 
52 // The initial value for the maximum frame payload size as per the spec. This is
53 // the maximum control frame size we accept.
54 inline constexpr uint32_t kHttp2DefaultFramePayloadLimit = 1 << 14;
55 
56 // The maximum size of the control frames that we send, including the size of
57 // the header. This limit is arbitrary. We can enforce it here or at the
58 // application layer. We chose the framing layer, but this can be changed (or
59 // removed) if necessary later down the line.
60 inline constexpr size_t kHttp2MaxControlFrameSendSize =
61     kHttp2DefaultFramePayloadLimit - 1;
62 
63 // Number of octets in the frame header.
64 inline constexpr size_t kFrameHeaderSize = 9;
65 
66 // The initial value for the maximum frame payload size as per the spec. This is
67 // the maximum control frame size we accept.
68 inline constexpr uint32_t kHttp2DefaultFrameSizeLimit =
69     kHttp2DefaultFramePayloadLimit + kFrameHeaderSize;
70 
71 // The initial value for the maximum size of the header list, "unlimited" (max
72 // unsigned 32-bit int) as per the spec.
73 inline constexpr uint32_t kSpdyInitialHeaderListSizeLimit = 0xFFFFFFFF;
74 
75 // Maximum window size for a Spdy stream or session.
76 inline constexpr int32_t kSpdyMaximumWindowSize =
77     0x7FFFFFFF;  // Max signed 32bit int
78 
79 // Maximum padding size in octets for one DATA or HEADERS or PUSH_PROMISE frame.
80 inline constexpr int32_t kPaddingSizePerFrame = 256;
81 
82 // The HTTP/2 connection preface, which must be the first bytes sent by the
83 // client upon starting an HTTP/2 connection, and which must be followed by a
84 // SETTINGS frame.  Note that even though |kHttp2ConnectionHeaderPrefix| is
85 // defined as a string literal with a null terminator, the actual connection
86 // preface is only the first |kHttp2ConnectionHeaderPrefixSize| bytes, which
87 // excludes the null terminator.
88 QUICHE_EXPORT extern const char* const kHttp2ConnectionHeaderPrefix;
89 inline constexpr int kHttp2ConnectionHeaderPrefixSize = 24;
90 
91 // Wire values for HTTP2 frame types.
92 enum class SpdyFrameType : uint8_t {
93   DATA = 0x00,
94   HEADERS = 0x01,
95   PRIORITY = 0x02,
96   RST_STREAM = 0x03,
97   SETTINGS = 0x04,
98   PUSH_PROMISE = 0x05,
99   PING = 0x06,
100   GOAWAY = 0x07,
101   WINDOW_UPDATE = 0x08,
102   CONTINUATION = 0x09,
103   // ALTSVC is a public extension.
104   ALTSVC = 0x0a,
105   PRIORITY_UPDATE = 0x10,
106   ACCEPT_CH = 0x89,
107 };
108 
109 // Flags on data packets.
110 enum SpdyDataFlags {
111   DATA_FLAG_NONE = 0x00,
112   DATA_FLAG_FIN = 0x01,
113   DATA_FLAG_PADDED = 0x08,
114 };
115 
116 // Flags on control packets
117 enum SpdyControlFlags {
118   CONTROL_FLAG_NONE = 0x00,
119   CONTROL_FLAG_FIN = 0x01,
120 };
121 
122 enum SpdyPingFlags {
123   PING_FLAG_ACK = 0x01,
124 };
125 
126 // Used by HEADERS, PUSH_PROMISE, and CONTINUATION.
127 enum SpdyHeadersFlags {
128   HEADERS_FLAG_END_HEADERS = 0x04,
129   HEADERS_FLAG_PADDED = 0x08,
130   HEADERS_FLAG_PRIORITY = 0x20,
131 };
132 
133 enum SpdyPushPromiseFlags {
134   PUSH_PROMISE_FLAG_END_PUSH_PROMISE = 0x04,
135   PUSH_PROMISE_FLAG_PADDED = 0x08,
136 };
137 
138 enum Http2SettingsControlFlags {
139   SETTINGS_FLAG_ACK = 0x01,
140 };
141 
142 // Wire values of HTTP/2 setting identifiers.
143 enum SpdyKnownSettingsId : SpdySettingsId {
144   // HPACK header table maximum size.
145   SETTINGS_HEADER_TABLE_SIZE = 0x1,
146   SETTINGS_MIN = SETTINGS_HEADER_TABLE_SIZE,
147   // Whether or not server push (PUSH_PROMISE) is enabled.
148   SETTINGS_ENABLE_PUSH = 0x2,
149   // The maximum number of simultaneous live streams in each direction.
150   SETTINGS_MAX_CONCURRENT_STREAMS = 0x3,
151   // Initial window size in bytes
152   SETTINGS_INITIAL_WINDOW_SIZE = 0x4,
153   // The size of the largest frame payload that a receiver is willing to accept.
154   SETTINGS_MAX_FRAME_SIZE = 0x5,
155   // The maximum size of header list that the sender is prepared to accept.
156   SETTINGS_MAX_HEADER_LIST_SIZE = 0x6,
157   // Enable Websockets over HTTP/2, see
158   // https://httpwg.org/specs/rfc8441.html
159   SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x8,
160   // Disable HTTP/2 priorities, see
161   // https://tools.ietf.org/html/draft-ietf-httpbis-priority-02.
162   SETTINGS_DEPRECATE_HTTP2_PRIORITIES = 0x9,
163   SETTINGS_MAX = SETTINGS_DEPRECATE_HTTP2_PRIORITIES,
164   // Experimental setting used to configure an alternative write scheduler.
165   SETTINGS_EXPERIMENT_SCHEDULER = 0xFF45,
166 };
167 
168 // This explicit operator is needed, otherwise compiler finds
169 // overloaded operator to be ambiguous.
170 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
171                                        SpdyKnownSettingsId id);
172 
173 // This operator is needed, because SpdyFrameType is an enum class,
174 // therefore implicit conversion to underlying integer type is not allowed.
175 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out,
176                                        SpdyFrameType frame_type);
177 
178 using SettingsMap = std::map<SpdySettingsId, uint32_t>;
179 
180 // HTTP/2 error codes, RFC 7540 Section 7.
181 enum SpdyErrorCode : uint32_t {
182   ERROR_CODE_NO_ERROR = 0x0,
183   ERROR_CODE_PROTOCOL_ERROR = 0x1,
184   ERROR_CODE_INTERNAL_ERROR = 0x2,
185   ERROR_CODE_FLOW_CONTROL_ERROR = 0x3,
186   ERROR_CODE_SETTINGS_TIMEOUT = 0x4,
187   ERROR_CODE_STREAM_CLOSED = 0x5,
188   ERROR_CODE_FRAME_SIZE_ERROR = 0x6,
189   ERROR_CODE_REFUSED_STREAM = 0x7,
190   ERROR_CODE_CANCEL = 0x8,
191   ERROR_CODE_COMPRESSION_ERROR = 0x9,
192   ERROR_CODE_CONNECT_ERROR = 0xa,
193   ERROR_CODE_ENHANCE_YOUR_CALM = 0xb,
194   ERROR_CODE_INADEQUATE_SECURITY = 0xc,
195   ERROR_CODE_HTTP_1_1_REQUIRED = 0xd,
196   ERROR_CODE_MAX = ERROR_CODE_HTTP_1_1_REQUIRED
197 };
198 
199 // Type of priority write scheduler.
200 enum class WriteSchedulerType {
201   LIFO,  // Last added stream has the highest priority.
202   SPDY,  // Uses SPDY priorities described in
203          // https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority.
204   HTTP2,  // Uses HTTP2 (tree-style) priority described in
205           // https://tools.ietf.org/html/rfc7540#section-5.3.
206   FIFO,   // Stream with the smallest stream ID has the highest priority.
207 };
208 
209 // A SPDY priority is a number between 0 and 7 (inclusive).
210 typedef uint8_t SpdyPriority;
211 
212 // Lowest and Highest here refer to SPDY priorities as described in
213 // https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.3.3-Stream-priority
214 inline constexpr SpdyPriority kV3HighestPriority = 0;
215 inline constexpr SpdyPriority kV3LowestPriority = 7;
216 
217 // Returns SPDY 3.x priority value clamped to the valid range of [0, 7].
218 QUICHE_EXPORT SpdyPriority ClampSpdy3Priority(SpdyPriority priority);
219 
220 // HTTP/2 stream weights are integers in range [1, 256], as specified in RFC
221 // 7540 section 5.3.2. Default stream weight is defined in section 5.3.5.
222 inline constexpr int kHttp2MinStreamWeight = 1;
223 inline constexpr int kHttp2MaxStreamWeight = 256;
224 inline constexpr int kHttp2DefaultStreamWeight = 16;
225 
226 // Returns HTTP/2 weight clamped to the valid range of [1, 256].
227 QUICHE_EXPORT int ClampHttp2Weight(int weight);
228 
229 // Maps SPDY 3.x priority value in range [0, 7] to HTTP/2 weight value in range
230 // [1, 256], where priority 0 (i.e. highest precedence) corresponds to maximum
231 // weight 256 and priority 7 (lowest precedence) corresponds to minimum weight
232 // 1.
233 QUICHE_EXPORT int Spdy3PriorityToHttp2Weight(SpdyPriority priority);
234 
235 // Maps HTTP/2 weight value in range [1, 256] to SPDY 3.x priority value in
236 // range [0, 7], where minimum weight 1 corresponds to priority 7 (lowest
237 // precedence) and maximum weight 256 corresponds to priority 0 (highest
238 // precedence).
239 QUICHE_EXPORT SpdyPriority Http2WeightToSpdy3Priority(int weight);
240 
241 // Reserved ID for root stream of HTTP/2 stream dependency tree, as specified
242 // in RFC 7540 section 5.3.1.
243 const unsigned int kHttp2RootStreamId = 0;
244 
245 typedef uint64_t SpdyPingId;
246 
247 // Returns true if a given on-the-wire enumeration of a frame type is defined
248 // in a standardized HTTP/2 specification, false otherwise.
249 QUICHE_EXPORT bool IsDefinedFrameType(uint8_t frame_type_field);
250 
251 // Parses a frame type from an on-the-wire enumeration.
252 // Behavior is undefined for invalid frame type fields; consumers should first
253 // use IsValidFrameType() to verify validity of frame type fields.
254 QUICHE_EXPORT SpdyFrameType ParseFrameType(uint8_t frame_type_field);
255 
256 // Serializes a frame type to the on-the-wire value.
257 QUICHE_EXPORT uint8_t SerializeFrameType(SpdyFrameType frame_type);
258 
259 // (HTTP/2) All standard frame types except WINDOW_UPDATE are
260 // (stream-specific xor connection-level). Returns false iff we know
261 // the given frame type does not align with the given streamID.
262 QUICHE_EXPORT bool IsValidHTTP2FrameStreamId(
263     SpdyStreamId current_frame_stream_id, SpdyFrameType frame_type_field);
264 
265 // Serialize |frame_type| to string for logging/debugging.
266 QUICHE_EXPORT const char* FrameTypeToString(SpdyFrameType frame_type);
267 
268 // If |wire_setting_id| is the on-the-wire representation of a defined SETTINGS
269 // parameter, parse it to |*setting_id| and return true.
270 QUICHE_EXPORT bool ParseSettingsId(SpdySettingsId wire_setting_id,
271                                    SpdyKnownSettingsId* setting_id);
272 
273 // Returns a string representation of the |id| for logging/debugging. Returns
274 // the |id| prefixed with "SETTINGS_UNKNOWN_" for unknown SETTINGS IDs. To parse
275 // the |id| into a SpdyKnownSettingsId (if applicable), use ParseSettingsId().
276 QUICHE_EXPORT std::string SettingsIdToString(SpdySettingsId id);
277 
278 // Parse |wire_error_code| to a SpdyErrorCode.
279 // Treat unrecognized error codes as INTERNAL_ERROR
280 // as recommended by the HTTP/2 specification.
281 QUICHE_EXPORT SpdyErrorCode ParseErrorCode(uint32_t wire_error_code);
282 
283 // Serialize RST_STREAM or GOAWAY frame error code to string
284 // for logging/debugging.
285 QUICHE_EXPORT const char* ErrorCodeToString(SpdyErrorCode error_code);
286 
287 // Serialize |type| to string for logging/debugging.
288 QUICHE_EXPORT const char* WriteSchedulerTypeToString(WriteSchedulerType type);
289 
290 // Minimum size of a frame, in octets.
291 inline constexpr size_t kFrameMinimumSize = kFrameHeaderSize;
292 
293 // Minimum frame size for variable size frame types (includes mandatory fields),
294 // frame size for fixed size frames, in octets.
295 
296 inline constexpr size_t kDataFrameMinimumSize = kFrameHeaderSize;
297 inline constexpr size_t kHeadersFrameMinimumSize = kFrameHeaderSize;
298 // PRIORITY frame has stream_dependency (4 octets) and weight (1 octet) fields.
299 inline constexpr size_t kPriorityFrameSize = kFrameHeaderSize + 5;
300 // RST_STREAM frame has error_code (4 octets) field.
301 inline constexpr size_t kRstStreamFrameSize = kFrameHeaderSize + 4;
302 inline constexpr size_t kSettingsFrameMinimumSize = kFrameHeaderSize;
303 inline constexpr size_t kSettingsOneSettingSize =
304     sizeof(uint32_t) + sizeof(SpdySettingsId);
305 // PUSH_PROMISE frame has promised_stream_id (4 octet) field.
306 inline constexpr size_t kPushPromiseFrameMinimumSize = kFrameHeaderSize + 4;
307 // PING frame has opaque_bytes (8 octet) field.
308 inline constexpr size_t kPingFrameSize = kFrameHeaderSize + 8;
309 // GOAWAY frame has last_stream_id (4 octet) and error_code (4 octet) fields.
310 inline constexpr size_t kGoawayFrameMinimumSize = kFrameHeaderSize + 8;
311 // WINDOW_UPDATE frame has window_size_increment (4 octet) field.
312 inline constexpr size_t kWindowUpdateFrameSize = kFrameHeaderSize + 4;
313 inline constexpr size_t kContinuationFrameMinimumSize = kFrameHeaderSize;
314 // ALTSVC frame has origin_len (2 octets) field.
315 inline constexpr size_t kGetAltSvcFrameMinimumSize = kFrameHeaderSize + 2;
316 // PRIORITY_UPDATE frame has prioritized_stream_id (4 octets) field.
317 inline constexpr size_t kPriorityUpdateFrameMinimumSize = kFrameHeaderSize + 4;
318 // ACCEPT_CH frame may have empty payload.
319 inline constexpr size_t kAcceptChFrameMinimumSize = kFrameHeaderSize;
320 // Each ACCEPT_CH frame entry has a 16-bit origin length and a 16-bit value
321 // length.
322 inline constexpr size_t kAcceptChFramePerEntryOverhead = 4;
323 
324 // Maximum possible configurable size of a frame in octets.
325 inline constexpr size_t kMaxFrameSizeLimit =
326     kSpdyMaxFrameSizeLimit + kFrameHeaderSize;
327 // Size of a header block size field.
328 inline constexpr size_t kSizeOfSizeField = sizeof(uint32_t);
329 // Initial window size for a stream in bytes.
330 inline constexpr int32_t kInitialStreamWindowSize = 64 * 1024 - 1;
331 // Initial window size for a session in bytes.
332 inline constexpr int32_t kInitialSessionWindowSize = 64 * 1024 - 1;
333 // The NPN string for HTTP2, "h2".
334 QUICHE_EXPORT extern const char* const kHttp2Npn;
335 // An estimate of the HPACK overhead for each header field in bytes, intended to
336 // be no smaller than actual overhead, based on the literal header field
337 // representation in RFC 7541 Section 6.2 (with or without indexing):
338 //   - 1 byte for the opcode.
339 //   - 2 bytes for the name length (assuming new name).
340 //   - 3 bytes for the value length.
341 // TODO(b/322146543): Remove the `New` suffix with deprecation of
342 // --gfe2_reloadable_flag_http2_add_hpack_overhead_bytes2.
343 inline constexpr size_t kPerHeaderHpackOverheadNew = 6;
344 // An estimate size of the HPACK overhead for each header field. 1 bytes for
345 // indexed literal, 1 bytes for key literal and length encoding, and 2 bytes for
346 // value literal and length encoding.
347 // TODO(b/322146543): Remove with deprecation of
348 // --gfe2_reloadable_flag_http2_add_hpack_overhead_bytes2.
349 inline constexpr size_t kPerHeaderHpackOverheadOld = 4;
350 
351 // Names of pseudo-headers defined for HTTP/2 requests.
352 QUICHE_EXPORT extern const char* const kHttp2AuthorityHeader;
353 QUICHE_EXPORT extern const char* const kHttp2MethodHeader;
354 QUICHE_EXPORT extern const char* const kHttp2PathHeader;
355 QUICHE_EXPORT extern const char* const kHttp2SchemeHeader;
356 QUICHE_EXPORT extern const char* const kHttp2ProtocolHeader;
357 
358 // Name of pseudo-header defined for HTTP/2 responses.
359 QUICHE_EXPORT extern const char* const kHttp2StatusHeader;
360 
361 QUICHE_EXPORT size_t GetNumberRequiredContinuationFrames(size_t size);
362 
363 // Variant type that is either a SPDY 3.x priority value, or else an HTTP/2
364 // stream dependency tuple {parent stream ID, weight, exclusive bit}. Templated
365 // to allow for use by QUIC code; SPDY and HTTP/2 code should use the concrete
366 // type instantiation SpdyStreamPrecedence.
367 template <typename StreamIdType>
368 class QUICHE_EXPORT StreamPrecedence {
369  public:
370   // Constructs instance that is a SPDY 3.x priority. Clamps priority value to
371   // the valid range [0, 7].
StreamPrecedence(SpdyPriority priority)372   explicit StreamPrecedence(SpdyPriority priority)
373       : precedence_(ClampSpdy3Priority(priority)) {}
374 
375   // Constructs instance that is an HTTP/2 stream weight, parent stream ID, and
376   // exclusive bit. Clamps stream weight to the valid range [1, 256].
StreamPrecedence(StreamIdType parent_id,int weight,bool is_exclusive)377   StreamPrecedence(StreamIdType parent_id, int weight, bool is_exclusive)
378       : precedence_(Http2StreamDependency{parent_id, ClampHttp2Weight(weight),
379                                           is_exclusive}) {}
380 
381   // Intentionally copyable, to support pass by value.
382   StreamPrecedence(const StreamPrecedence& other) = default;
383   StreamPrecedence& operator=(const StreamPrecedence& other) = default;
384 
385   // Returns true if this instance is a SPDY 3.x priority, or false if this
386   // instance is an HTTP/2 stream dependency.
is_spdy3_priority()387   bool is_spdy3_priority() const {
388     return absl::holds_alternative<SpdyPriority>(precedence_);
389   }
390 
391   // Returns SPDY 3.x priority value. If |is_spdy3_priority()| is true, this is
392   // the value provided at construction, clamped to the legal priority
393   // range. Otherwise, it is the HTTP/2 stream weight mapped to a SPDY 3.x
394   // priority value, where minimum weight 1 corresponds to priority 7 (lowest
395   // precedence) and maximum weight 256 corresponds to priority 0 (highest
396   // precedence).
spdy3_priority()397   SpdyPriority spdy3_priority() const {
398     return is_spdy3_priority()
399                ? absl::get<SpdyPriority>(precedence_)
400                : Http2WeightToSpdy3Priority(
401                      absl::get<Http2StreamDependency>(precedence_).weight);
402   }
403 
404   // Returns HTTP/2 parent stream ID. If |is_spdy3_priority()| is false, this is
405   // the value provided at construction, otherwise it is |kHttp2RootStreamId|.
parent_id()406   StreamIdType parent_id() const {
407     return is_spdy3_priority()
408                ? kHttp2RootStreamId
409                : absl::get<Http2StreamDependency>(precedence_).parent_id;
410   }
411 
412   // Returns HTTP/2 stream weight. If |is_spdy3_priority()| is false, this is
413   // the value provided at construction, clamped to the legal weight
414   // range. Otherwise, it is the SPDY 3.x priority value mapped to an HTTP/2
415   // stream weight, where priority 0 (i.e. highest precedence) corresponds to
416   // maximum weight 256 and priority 7 (lowest precedence) corresponds to
417   // minimum weight 1.
weight()418   int weight() const {
419     return is_spdy3_priority()
420                ? Spdy3PriorityToHttp2Weight(
421                      absl::get<SpdyPriority>(precedence_))
422                : absl::get<Http2StreamDependency>(precedence_).weight;
423   }
424 
425   // Returns HTTP/2 parent stream exclusivity. If |is_spdy3_priority()| is
426   // false, this is the value provided at construction, otherwise it is false.
is_exclusive()427   bool is_exclusive() const {
428     return absl::holds_alternative<Http2StreamDependency>(precedence_) &&
429            absl::get<Http2StreamDependency>(precedence_).is_exclusive;
430   }
431 
432   // Facilitates test assertions.
433   bool operator==(const StreamPrecedence& other) const {
434     return precedence_ == other.precedence_;
435   }
436 
437   bool operator!=(const StreamPrecedence& other) const {
438     return !(*this == other);
439   }
440 
441  private:
442   struct QUICHE_EXPORT Http2StreamDependency {
443     StreamIdType parent_id;
444     int weight;
445     bool is_exclusive;
446 
447     bool operator==(const Http2StreamDependency& other) const {
448       return parent_id == other.parent_id && weight == other.weight &&
449              is_exclusive == other.is_exclusive;
450     }
451   };
452 
453   absl::variant<SpdyPriority, Http2StreamDependency> precedence_;
454 };
455 
456 typedef StreamPrecedence<SpdyStreamId> SpdyStreamPrecedence;
457 
458 class SpdyFrameVisitor;
459 
460 // Intermediate representation for HTTP2 frames.
461 class QUICHE_EXPORT SpdyFrameIR {
462  public:
~SpdyFrameIR()463   virtual ~SpdyFrameIR() {}
464 
465   virtual void Visit(SpdyFrameVisitor* visitor) const = 0;
466   virtual SpdyFrameType frame_type() const = 0;
stream_id()467   SpdyStreamId stream_id() const { return stream_id_; }
468   virtual bool fin() const;
469   // Returns an estimate of the size of the serialized frame, without applying
470   // compression. May not be exact, but implementations should return the same
471   // value for a const frame.
472   virtual size_t size() const = 0;
473 
474   // Returns the number of bytes of flow control window that would be consumed
475   // by this frame if written to the wire.
476   virtual int flow_control_window_consumed() const;
477 
478  protected:
SpdyFrameIR()479   SpdyFrameIR() : stream_id_(0) {}
SpdyFrameIR(SpdyStreamId stream_id)480   explicit SpdyFrameIR(SpdyStreamId stream_id) : stream_id_(stream_id) {}
481   SpdyFrameIR(const SpdyFrameIR&) = delete;
482   SpdyFrameIR& operator=(const SpdyFrameIR&) = delete;
483 
484  private:
485   SpdyStreamId stream_id_;
486 };
487 
488 // Abstract class intended to be inherited by IRs that have the option of a FIN
489 // flag.
490 class QUICHE_EXPORT SpdyFrameWithFinIR : public SpdyFrameIR {
491  public:
~SpdyFrameWithFinIR()492   ~SpdyFrameWithFinIR() override {}
493   bool fin() const override;
set_fin(bool fin)494   void set_fin(bool fin) { fin_ = fin; }
495 
496  protected:
SpdyFrameWithFinIR(SpdyStreamId stream_id)497   explicit SpdyFrameWithFinIR(SpdyStreamId stream_id)
498       : SpdyFrameIR(stream_id), fin_(false) {}
499   SpdyFrameWithFinIR(const SpdyFrameWithFinIR&) = delete;
500   SpdyFrameWithFinIR& operator=(const SpdyFrameWithFinIR&) = delete;
501 
502  private:
503   bool fin_;
504 };
505 
506 // Abstract class intended to be inherited by IRs that contain a header
507 // block. Implies SpdyFrameWithFinIR.
508 class QUICHE_EXPORT SpdyFrameWithHeaderBlockIR : public SpdyFrameWithFinIR {
509  public:
510   ~SpdyFrameWithHeaderBlockIR() override;
511 
header_block()512   const Http2HeaderBlock& header_block() const { return header_block_; }
set_header_block(Http2HeaderBlock header_block)513   void set_header_block(Http2HeaderBlock header_block) {
514     // Deep copy.
515     header_block_ = std::move(header_block);
516   }
SetHeader(absl::string_view name,absl::string_view value)517   void SetHeader(absl::string_view name, absl::string_view value) {
518     header_block_[name] = value;
519   }
520 
521  protected:
522   SpdyFrameWithHeaderBlockIR(SpdyStreamId stream_id,
523                              Http2HeaderBlock header_block);
524   SpdyFrameWithHeaderBlockIR(const SpdyFrameWithHeaderBlockIR&) = delete;
525   SpdyFrameWithHeaderBlockIR& operator=(const SpdyFrameWithHeaderBlockIR&) =
526       delete;
527 
528  private:
529   Http2HeaderBlock header_block_;
530 };
531 
532 class QUICHE_EXPORT SpdyDataIR : public SpdyFrameWithFinIR {
533  public:
534   // Performs a deep copy on data.
535   SpdyDataIR(SpdyStreamId stream_id, absl::string_view data);
536 
537   // Performs a deep copy on data.
538   SpdyDataIR(SpdyStreamId stream_id, const char* data);
539 
540   // Moves data into data_store_. Makes a copy if passed a non-movable string.
541   SpdyDataIR(SpdyStreamId stream_id, std::string data);
542 
543   // Use in conjunction with SetDataShallow() for shallow-copy on data.
544   explicit SpdyDataIR(SpdyStreamId stream_id);
545   SpdyDataIR(const SpdyDataIR&) = delete;
546   SpdyDataIR& operator=(const SpdyDataIR&) = delete;
547 
548   ~SpdyDataIR() override;
549 
data()550   const char* data() const { return data_; }
data_len()551   size_t data_len() const { return data_len_; }
552 
padded()553   bool padded() const { return padded_; }
554 
padding_payload_len()555   int padding_payload_len() const { return padding_payload_len_; }
556 
set_padding_len(int padding_len)557   void set_padding_len(int padding_len) {
558     QUICHE_DCHECK_GT(padding_len, 0);
559     QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame);
560     padded_ = true;
561     // The pad field takes one octet on the wire.
562     padding_payload_len_ = padding_len - 1;
563   }
564 
565   // Deep-copy of data (keep private copy).
SetDataDeep(absl::string_view data)566   void SetDataDeep(absl::string_view data) {
567     data_store_ = std::make_unique<std::string>(data.data(), data.size());
568     data_ = data_store_->data();
569     data_len_ = data.size();
570   }
571 
572   // Shallow-copy of data (do not keep private copy).
SetDataShallow(absl::string_view data)573   void SetDataShallow(absl::string_view data) {
574     data_store_.reset();
575     data_ = data.data();
576     data_len_ = data.size();
577   }
578 
579   // Use this method if we don't have a contiguous buffer and only
580   // need a length.
SetDataShallow(size_t len)581   void SetDataShallow(size_t len) {
582     data_store_.reset();
583     data_ = nullptr;
584     data_len_ = len;
585   }
586 
587   void Visit(SpdyFrameVisitor* visitor) const override;
588 
589   SpdyFrameType frame_type() const override;
590 
591   int flow_control_window_consumed() const override;
592 
593   size_t size() const override;
594 
595  private:
596   // Used to store data that this SpdyDataIR should own.
597   std::unique_ptr<std::string> data_store_;
598   const char* data_;
599   size_t data_len_;
600 
601   bool padded_;
602   // padding_payload_len_ = desired padding length - len(padding length field).
603   int padding_payload_len_;
604 };
605 
606 class QUICHE_EXPORT SpdyRstStreamIR : public SpdyFrameIR {
607  public:
608   SpdyRstStreamIR(SpdyStreamId stream_id, SpdyErrorCode error_code);
609   SpdyRstStreamIR(const SpdyRstStreamIR&) = delete;
610   SpdyRstStreamIR& operator=(const SpdyRstStreamIR&) = delete;
611 
612   ~SpdyRstStreamIR() override;
613 
error_code()614   SpdyErrorCode error_code() const { return error_code_; }
set_error_code(SpdyErrorCode error_code)615   void set_error_code(SpdyErrorCode error_code) { error_code_ = error_code; }
616 
617   void Visit(SpdyFrameVisitor* visitor) const override;
618 
619   SpdyFrameType frame_type() const override;
620 
621   size_t size() const override;
622 
623  private:
624   SpdyErrorCode error_code_;
625 };
626 
627 class QUICHE_EXPORT SpdySettingsIR : public SpdyFrameIR {
628  public:
629   SpdySettingsIR();
630   SpdySettingsIR(const SpdySettingsIR&) = delete;
631   SpdySettingsIR& operator=(const SpdySettingsIR&) = delete;
632   ~SpdySettingsIR() override;
633 
634   // Overwrites as appropriate.
values()635   const SettingsMap& values() const { return values_; }
AddSetting(SpdySettingsId id,int32_t value)636   void AddSetting(SpdySettingsId id, int32_t value) { values_[id] = value; }
637 
is_ack()638   bool is_ack() const { return is_ack_; }
set_is_ack(bool is_ack)639   void set_is_ack(bool is_ack) { is_ack_ = is_ack; }
640 
641   void Visit(SpdyFrameVisitor* visitor) const override;
642 
643   SpdyFrameType frame_type() const override;
644 
645   size_t size() const override;
646 
647  private:
648   SettingsMap values_;
649   bool is_ack_;
650 };
651 
652 class QUICHE_EXPORT SpdyPingIR : public SpdyFrameIR {
653  public:
SpdyPingIR(SpdyPingId id)654   explicit SpdyPingIR(SpdyPingId id) : id_(id), is_ack_(false) {}
655   SpdyPingIR(const SpdyPingIR&) = delete;
656   SpdyPingIR& operator=(const SpdyPingIR&) = delete;
id()657   SpdyPingId id() const { return id_; }
658 
is_ack()659   bool is_ack() const { return is_ack_; }
set_is_ack(bool is_ack)660   void set_is_ack(bool is_ack) { is_ack_ = is_ack; }
661 
662   void Visit(SpdyFrameVisitor* visitor) const override;
663 
664   SpdyFrameType frame_type() const override;
665 
666   size_t size() const override;
667 
668  private:
669   SpdyPingId id_;
670   bool is_ack_;
671 };
672 
673 class QUICHE_EXPORT SpdyGoAwayIR : public SpdyFrameIR {
674  public:
675   // References description, doesn't copy it, so description must outlast
676   // this SpdyGoAwayIR.
677   SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code,
678                absl::string_view description);
679 
680   // References description, doesn't copy it, so description must outlast
681   // this SpdyGoAwayIR.
682   SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code,
683                const char* description);
684 
685   // Moves description into description_store_, so caller doesn't need to
686   // keep description live after constructing this SpdyGoAwayIR.
687   SpdyGoAwayIR(SpdyStreamId last_good_stream_id, SpdyErrorCode error_code,
688                std::string description);
689   SpdyGoAwayIR(const SpdyGoAwayIR&) = delete;
690   SpdyGoAwayIR& operator=(const SpdyGoAwayIR&) = delete;
691 
692   ~SpdyGoAwayIR() override;
693 
last_good_stream_id()694   SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; }
set_last_good_stream_id(SpdyStreamId last_good_stream_id)695   void set_last_good_stream_id(SpdyStreamId last_good_stream_id) {
696     QUICHE_DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask);
697     last_good_stream_id_ = last_good_stream_id;
698   }
error_code()699   SpdyErrorCode error_code() const { return error_code_; }
set_error_code(SpdyErrorCode error_code)700   void set_error_code(SpdyErrorCode error_code) {
701     // TODO(hkhalil): Check valid ranges of error_code?
702     error_code_ = error_code;
703   }
704 
description()705   const absl::string_view& description() const { return description_; }
706 
707   void Visit(SpdyFrameVisitor* visitor) const override;
708 
709   SpdyFrameType frame_type() const override;
710 
711   size_t size() const override;
712 
713  private:
714   SpdyStreamId last_good_stream_id_;
715   SpdyErrorCode error_code_;
716   const std::string description_store_;
717   const absl::string_view description_;
718 };
719 
720 class QUICHE_EXPORT SpdyHeadersIR : public SpdyFrameWithHeaderBlockIR {
721  public:
SpdyHeadersIR(SpdyStreamId stream_id)722   explicit SpdyHeadersIR(SpdyStreamId stream_id)
723       : SpdyHeadersIR(stream_id, Http2HeaderBlock()) {}
SpdyHeadersIR(SpdyStreamId stream_id,Http2HeaderBlock header_block)724   SpdyHeadersIR(SpdyStreamId stream_id, Http2HeaderBlock header_block)
725       : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)) {}
726   SpdyHeadersIR(const SpdyHeadersIR&) = delete;
727   SpdyHeadersIR& operator=(const SpdyHeadersIR&) = delete;
728 
729   void Visit(SpdyFrameVisitor* visitor) const override;
730 
731   SpdyFrameType frame_type() const override;
732 
733   size_t size() const override;
734 
has_priority()735   bool has_priority() const { return has_priority_; }
set_has_priority(bool has_priority)736   void set_has_priority(bool has_priority) { has_priority_ = has_priority; }
weight()737   int weight() const { return weight_; }
set_weight(int weight)738   void set_weight(int weight) { weight_ = weight; }
parent_stream_id()739   SpdyStreamId parent_stream_id() const { return parent_stream_id_; }
set_parent_stream_id(SpdyStreamId id)740   void set_parent_stream_id(SpdyStreamId id) { parent_stream_id_ = id; }
exclusive()741   bool exclusive() const { return exclusive_; }
set_exclusive(bool exclusive)742   void set_exclusive(bool exclusive) { exclusive_ = exclusive; }
padded()743   bool padded() const { return padded_; }
padding_payload_len()744   int padding_payload_len() const { return padding_payload_len_; }
set_padding_len(int padding_len)745   void set_padding_len(int padding_len) {
746     QUICHE_DCHECK_GT(padding_len, 0);
747     QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame);
748     padded_ = true;
749     // The pad field takes one octet on the wire.
750     padding_payload_len_ = padding_len - 1;
751   }
752 
753  private:
754   bool has_priority_ = false;
755   int weight_ = kHttp2DefaultStreamWeight;
756   SpdyStreamId parent_stream_id_ = 0;
757   bool exclusive_ = false;
758   bool padded_ = false;
759   int padding_payload_len_ = 0;
760   const bool add_hpack_overhead_bytes_ =
761       GetQuicheReloadableFlag(http2_add_hpack_overhead_bytes2);
762 };
763 
764 class QUICHE_EXPORT SpdyWindowUpdateIR : public SpdyFrameIR {
765  public:
SpdyWindowUpdateIR(SpdyStreamId stream_id,int32_t delta)766   SpdyWindowUpdateIR(SpdyStreamId stream_id, int32_t delta)
767       : SpdyFrameIR(stream_id) {
768     set_delta(delta);
769   }
770   SpdyWindowUpdateIR(const SpdyWindowUpdateIR&) = delete;
771   SpdyWindowUpdateIR& operator=(const SpdyWindowUpdateIR&) = delete;
772 
delta()773   int32_t delta() const { return delta_; }
set_delta(int32_t delta)774   void set_delta(int32_t delta) {
775     QUICHE_DCHECK_LE(0, delta);
776     QUICHE_DCHECK_LE(delta, kSpdyMaximumWindowSize);
777     delta_ = delta;
778   }
779 
780   void Visit(SpdyFrameVisitor* visitor) const override;
781 
782   SpdyFrameType frame_type() const override;
783 
784   size_t size() const override;
785 
786  private:
787   int32_t delta_;
788 };
789 
790 class QUICHE_EXPORT SpdyPushPromiseIR : public SpdyFrameWithHeaderBlockIR {
791  public:
SpdyPushPromiseIR(SpdyStreamId stream_id,SpdyStreamId promised_stream_id)792   SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id)
793       : SpdyPushPromiseIR(stream_id, promised_stream_id, Http2HeaderBlock()) {}
SpdyPushPromiseIR(SpdyStreamId stream_id,SpdyStreamId promised_stream_id,Http2HeaderBlock header_block)794   SpdyPushPromiseIR(SpdyStreamId stream_id, SpdyStreamId promised_stream_id,
795                     Http2HeaderBlock header_block)
796       : SpdyFrameWithHeaderBlockIR(stream_id, std::move(header_block)),
797         promised_stream_id_(promised_stream_id),
798         padded_(false),
799         padding_payload_len_(0) {}
800   SpdyPushPromiseIR(const SpdyPushPromiseIR&) = delete;
801   SpdyPushPromiseIR& operator=(const SpdyPushPromiseIR&) = delete;
promised_stream_id()802   SpdyStreamId promised_stream_id() const { return promised_stream_id_; }
803 
804   void Visit(SpdyFrameVisitor* visitor) const override;
805 
806   SpdyFrameType frame_type() const override;
807 
808   size_t size() const override;
809 
padded()810   bool padded() const { return padded_; }
padding_payload_len()811   int padding_payload_len() const { return padding_payload_len_; }
set_padding_len(int padding_len)812   void set_padding_len(int padding_len) {
813     QUICHE_DCHECK_GT(padding_len, 0);
814     QUICHE_DCHECK_LE(padding_len, kPaddingSizePerFrame);
815     padded_ = true;
816     // The pad field takes one octet on the wire.
817     padding_payload_len_ = padding_len - 1;
818   }
819 
820  private:
821   SpdyStreamId promised_stream_id_;
822 
823   bool padded_;
824   int padding_payload_len_;
825 };
826 
827 class QUICHE_EXPORT SpdyContinuationIR : public SpdyFrameIR {
828  public:
829   explicit SpdyContinuationIR(SpdyStreamId stream_id);
830   SpdyContinuationIR(const SpdyContinuationIR&) = delete;
831   SpdyContinuationIR& operator=(const SpdyContinuationIR&) = delete;
832   ~SpdyContinuationIR() override;
833 
834   void Visit(SpdyFrameVisitor* visitor) const override;
835 
836   SpdyFrameType frame_type() const override;
837 
end_headers()838   bool end_headers() const { return end_headers_; }
set_end_headers(bool end_headers)839   void set_end_headers(bool end_headers) { end_headers_ = end_headers; }
encoding()840   const std::string& encoding() const { return encoding_; }
take_encoding(std::string encoding)841   void take_encoding(std::string encoding) { encoding_ = std::move(encoding); }
842   size_t size() const override;
843 
844  private:
845   std::string encoding_;
846   bool end_headers_;
847 };
848 
849 class QUICHE_EXPORT SpdyAltSvcIR : public SpdyFrameIR {
850  public:
851   explicit SpdyAltSvcIR(SpdyStreamId stream_id);
852   SpdyAltSvcIR(const SpdyAltSvcIR&) = delete;
853   SpdyAltSvcIR& operator=(const SpdyAltSvcIR&) = delete;
854   ~SpdyAltSvcIR() override;
855 
origin()856   std::string origin() const { return origin_; }
altsvc_vector()857   const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector() const {
858     return altsvc_vector_;
859   }
860 
set_origin(std::string origin)861   void set_origin(std::string origin) { origin_ = std::move(origin); }
add_altsvc(const SpdyAltSvcWireFormat::AlternativeService & altsvc)862   void add_altsvc(const SpdyAltSvcWireFormat::AlternativeService& altsvc) {
863     altsvc_vector_.push_back(altsvc);
864   }
865 
866   void Visit(SpdyFrameVisitor* visitor) const override;
867 
868   SpdyFrameType frame_type() const override;
869 
870   size_t size() const override;
871 
872  private:
873   std::string origin_;
874   SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector_;
875 };
876 
877 class QUICHE_EXPORT SpdyPriorityIR : public SpdyFrameIR {
878  public:
SpdyPriorityIR(SpdyStreamId stream_id,SpdyStreamId parent_stream_id,int weight,bool exclusive)879   SpdyPriorityIR(SpdyStreamId stream_id, SpdyStreamId parent_stream_id,
880                  int weight, bool exclusive)
881       : SpdyFrameIR(stream_id),
882         parent_stream_id_(parent_stream_id),
883         weight_(weight),
884         exclusive_(exclusive) {}
885   SpdyPriorityIR(const SpdyPriorityIR&) = delete;
886   SpdyPriorityIR& operator=(const SpdyPriorityIR&) = delete;
parent_stream_id()887   SpdyStreamId parent_stream_id() const { return parent_stream_id_; }
weight()888   int weight() const { return weight_; }
exclusive()889   bool exclusive() const { return exclusive_; }
890 
891   void Visit(SpdyFrameVisitor* visitor) const override;
892 
893   SpdyFrameType frame_type() const override;
894 
895   size_t size() const override;
896 
897  private:
898   SpdyStreamId parent_stream_id_;
899   int weight_;
900   bool exclusive_;
901 };
902 
903 class QUICHE_EXPORT SpdyPriorityUpdateIR : public SpdyFrameIR {
904  public:
SpdyPriorityUpdateIR(SpdyStreamId stream_id,SpdyStreamId prioritized_stream_id,std::string priority_field_value)905   SpdyPriorityUpdateIR(SpdyStreamId stream_id,
906                        SpdyStreamId prioritized_stream_id,
907                        std::string priority_field_value)
908       : SpdyFrameIR(stream_id),
909         prioritized_stream_id_(prioritized_stream_id),
910         priority_field_value_(std::move(priority_field_value)) {}
911   SpdyPriorityUpdateIR(const SpdyPriorityUpdateIR&) = delete;
912   SpdyPriorityUpdateIR& operator=(const SpdyPriorityUpdateIR&) = delete;
prioritized_stream_id()913   SpdyStreamId prioritized_stream_id() const { return prioritized_stream_id_; }
priority_field_value()914   const std::string& priority_field_value() const {
915     return priority_field_value_;
916   }
917 
918   void Visit(SpdyFrameVisitor* visitor) const override;
919 
920   SpdyFrameType frame_type() const override;
921 
922   size_t size() const override;
923 
924  private:
925   SpdyStreamId prioritized_stream_id_;
926   std::string priority_field_value_;
927 };
928 
929 struct QUICHE_EXPORT AcceptChOriginValuePair {
930   std::string origin;
931   std::string value;
932   bool operator==(const AcceptChOriginValuePair& rhs) const {
933     return origin == rhs.origin && value == rhs.value;
934   }
935 };
936 
937 class QUICHE_EXPORT SpdyAcceptChIR : public SpdyFrameIR {
938  public:
SpdyAcceptChIR(std::vector<AcceptChOriginValuePair> entries)939   SpdyAcceptChIR(std::vector<AcceptChOriginValuePair> entries)
940       : entries_(std::move(entries)) {}
941   SpdyAcceptChIR(const SpdyAcceptChIR&) = delete;
942   SpdyAcceptChIR& operator=(const SpdyAcceptChIR&) = delete;
943 
944   void Visit(SpdyFrameVisitor* visitor) const override;
945 
946   SpdyFrameType frame_type() const override;
947 
948   size_t size() const override;
949 
entries()950   const std::vector<AcceptChOriginValuePair>& entries() const {
951     return entries_;
952   }
953 
954  private:
955   std::vector<AcceptChOriginValuePair> entries_;
956 };
957 
958 // Represents a frame of unrecognized type.
959 class QUICHE_EXPORT SpdyUnknownIR : public SpdyFrameIR {
960  public:
SpdyUnknownIR(SpdyStreamId stream_id,uint8_t type,uint8_t flags,std::string payload)961   SpdyUnknownIR(SpdyStreamId stream_id, uint8_t type, uint8_t flags,
962                 std::string payload)
963       : SpdyFrameIR(stream_id),
964         type_(type),
965         flags_(flags),
966         length_(payload.size()),
967         payload_(std::move(payload)) {}
968   SpdyUnknownIR(const SpdyUnknownIR&) = delete;
969   SpdyUnknownIR& operator=(const SpdyUnknownIR&) = delete;
type()970   uint8_t type() const { return type_; }
flags()971   uint8_t flags() const { return flags_; }
length()972   size_t length() const { return length_; }
payload()973   const std::string& payload() const { return payload_; }
974 
975   void Visit(SpdyFrameVisitor* visitor) const override;
976 
977   SpdyFrameType frame_type() const override;
978 
979   int flow_control_window_consumed() const override;
980 
981   size_t size() const override;
982 
983  protected:
984   // Allows subclasses to overwrite the default payload length.
set_length(size_t length)985   void set_length(size_t length) { length_ = length; }
986 
987  private:
988   uint8_t type_;
989   uint8_t flags_;
990   size_t length_;
991   const std::string payload_;
992 };
993 
994 class QUICHE_EXPORT SpdySerializedFrame {
995  public:
SpdySerializedFrame()996   SpdySerializedFrame() : size_(0) {}
997 
998   // Creates a valid SpdySerializedFrame using a pre-created buffer.
SpdySerializedFrame(std::unique_ptr<char[]> data,size_t size)999   SpdySerializedFrame(std::unique_ptr<char[]> data, size_t size)
1000       : frame_(std::move(data)), size_(size) {}
1001 
SpdySerializedFrame(SpdySerializedFrame && other)1002   SpdySerializedFrame(SpdySerializedFrame&& other)
1003       : frame_(std::move(other.frame_)), size_(other.size_) {}
1004 
1005   SpdySerializedFrame(const SpdySerializedFrame&) = delete;
1006   SpdySerializedFrame& operator=(const SpdySerializedFrame&) = delete;
1007 
1008   SpdySerializedFrame& operator=(SpdySerializedFrame&& other) {
1009     // Take over |other|.
1010     frame_ = std::move(other.frame_);
1011     size_ = other.size_;
1012     return *this;
1013   }
1014 
1015   ~SpdySerializedFrame() = default;
1016 
1017   // Provides access to the frame bytes, which is a buffer containing the frame
1018   // packed as expected for sending over the wire.
data()1019   char* data() const { return frame_.get(); }
1020 
1021   // Returns the actual size of the underlying buffer.
size()1022   size_t size() const { return size_; }
1023 
string_view()1024   operator absl::string_view() const {
1025     return absl::string_view{frame_.get(), size_};
1026   }
1027 
1028  private:
1029   std::unique_ptr<char[]> frame_;
1030   size_t size_;
1031 };
1032 
1033 // This interface is for classes that want to process SpdyFrameIRs without
1034 // having to know what type they are.  An instance of this interface can be
1035 // passed to a SpdyFrameIR's Visit method, and the appropriate type-specific
1036 // method of this class will be called.
1037 class QUICHE_EXPORT SpdyFrameVisitor {
1038  public:
SpdyFrameVisitor()1039   SpdyFrameVisitor() {}
1040   SpdyFrameVisitor(const SpdyFrameVisitor&) = delete;
1041   SpdyFrameVisitor& operator=(const SpdyFrameVisitor&) = delete;
~SpdyFrameVisitor()1042   virtual ~SpdyFrameVisitor() {}
1043 
1044   virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) = 0;
1045   virtual void VisitSettings(const SpdySettingsIR& settings) = 0;
1046   virtual void VisitPing(const SpdyPingIR& ping) = 0;
1047   virtual void VisitGoAway(const SpdyGoAwayIR& goaway) = 0;
1048   virtual void VisitHeaders(const SpdyHeadersIR& headers) = 0;
1049   virtual void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) = 0;
1050   virtual void VisitPushPromise(const SpdyPushPromiseIR& push_promise) = 0;
1051   virtual void VisitContinuation(const SpdyContinuationIR& continuation) = 0;
1052   virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) = 0;
1053   virtual void VisitPriority(const SpdyPriorityIR& priority) = 0;
1054   virtual void VisitData(const SpdyDataIR& data) = 0;
1055   virtual void VisitPriorityUpdate(
1056       const SpdyPriorityUpdateIR& priority_update) = 0;
1057   virtual void VisitAcceptCh(const SpdyAcceptChIR& accept_ch) = 0;
VisitUnknown(const SpdyUnknownIR &)1058   virtual void VisitUnknown(const SpdyUnknownIR& /*unknown*/) {
1059     // TODO(birenroy): make abstract.
1060   }
1061 };
1062 
1063 // Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting
1064 // SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in
1065 // order to extract debug/internal information about the SpdyFramer as it
1066 // operates.
1067 //
1068 // Most HTTP2 implementations need not bother with this interface at all.
1069 class QUICHE_EXPORT SpdyFramerDebugVisitorInterface {
1070  public:
~SpdyFramerDebugVisitorInterface()1071   virtual ~SpdyFramerDebugVisitorInterface() {}
1072 
1073   // Called after compressing a frame with a payload of
1074   // a list of name-value pairs.
1075   // |payload_len| is the uncompressed payload size.
1076   // |frame_len| is the compressed frame size.
OnSendCompressedFrame(SpdyStreamId,SpdyFrameType,size_t,size_t)1077   virtual void OnSendCompressedFrame(SpdyStreamId /*stream_id*/,
1078                                      SpdyFrameType /*type*/,
1079                                      size_t /*payload_len*/,
1080                                      size_t /*frame_len*/) {}
1081 
1082   // Called when a frame containing a compressed payload of
1083   // name-value pairs is received.
1084   // |frame_len| is the compressed frame size.
OnReceiveCompressedFrame(SpdyStreamId,SpdyFrameType,size_t)1085   virtual void OnReceiveCompressedFrame(SpdyStreamId /*stream_id*/,
1086                                         SpdyFrameType /*type*/,
1087                                         size_t /*frame_len*/) {}
1088 };
1089 
1090 // Calculates the number of bytes required to serialize a SpdyHeadersIR, not
1091 // including the bytes to be used for the encoded header set.
1092 size_t GetHeaderFrameSizeSansBlock(const SpdyHeadersIR& header_ir);
1093 
1094 // Calculates the number of bytes required to serialize a SpdyPushPromiseIR,
1095 // not including the bytes to be used for the encoded header set.
1096 size_t GetPushPromiseFrameSizeSansBlock(
1097     const SpdyPushPromiseIR& push_promise_ir);
1098 
1099 }  // namespace spdy
1100 
1101 #endif  // QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_
1102