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