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