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