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