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 #ifndef NET_SPDY_SPDY_FRAMER_H_ 6 #define NET_SPDY_SPDY_FRAMER_H_ 7 8 #include <list> 9 #include <map> 10 #include <memory> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "base/basictypes.h" 16 #include "base/gtest_prod_util.h" 17 #include "base/memory/scoped_ptr.h" 18 #include "base/strings/string_piece.h" 19 #include "base/sys_byteorder.h" 20 #include "net/base/net_export.h" 21 #include "net/spdy/hpack_decoder.h" 22 #include "net/spdy/hpack_encoder.h" 23 #include "net/spdy/spdy_header_block.h" 24 #include "net/spdy/spdy_protocol.h" 25 26 // TODO(akalin): Remove support for CREDENTIAL frames. 27 28 typedef struct z_stream_s z_stream; // Forward declaration for zlib. 29 30 namespace net { 31 32 class HttpProxyClientSocketPoolTest; 33 class HttpNetworkLayer; 34 class HttpNetworkTransactionTest; 35 class SpdyHttpStreamTest; 36 class SpdyNetworkTransactionTest; 37 class SpdyProxyClientSocketTest; 38 class SpdySessionTest; 39 class SpdyStreamTest; 40 class SpdyWebSocketStreamTest; 41 class WebSocketJobTest; 42 43 class SpdyFramer; 44 class SpdyFrameBuilder; 45 class SpdyFramerTest; 46 47 namespace test { 48 49 class TestSpdyVisitor; 50 51 } // namespace test 52 53 // A datastructure for holding a set of headers from a HEADERS, PUSH_PROMISE, 54 // SYN_STREAM, or SYN_REPLY frame. 55 typedef std::map<std::string, std::string> SpdyHeaderBlock; 56 57 // A datastructure for holding the ID and flag fields for SETTINGS. 58 // Conveniently handles converstion to/from wire format. 59 class NET_EXPORT_PRIVATE SettingsFlagsAndId { 60 public: 61 static SettingsFlagsAndId FromWireFormat(SpdyMajorVersion version, 62 uint32 wire); 63 SettingsFlagsAndId()64 SettingsFlagsAndId() : flags_(0), id_(0) {} 65 66 // TODO(hkhalil): restrict to enums instead of free-form ints. 67 SettingsFlagsAndId(uint8 flags, uint32 id); 68 69 uint32 GetWireFormat(SpdyMajorVersion version) const; 70 id()71 uint32 id() const { return id_; } flags()72 uint8 flags() const { return flags_; } 73 74 private: 75 static void ConvertFlagsAndIdForSpdy2(uint32* val); 76 77 uint8 flags_; 78 uint32 id_; 79 }; 80 81 // SettingsMap has unique (flags, value) pair for given SpdySettingsIds ID. 82 typedef std::pair<SpdySettingsFlags, uint32> SettingsFlagsAndValue; 83 typedef std::map<SpdySettingsIds, SettingsFlagsAndValue> SettingsMap; 84 85 // Scratch space necessary for processing SETTINGS frames. 86 struct NET_EXPORT_PRIVATE SpdySettingsScratch { SpdySettingsScratchSpdySettingsScratch87 SpdySettingsScratch() { Reset(); } 88 ResetSpdySettingsScratch89 void Reset() { 90 setting_buf_len = 0; 91 last_setting_id = -1; 92 } 93 94 // Buffer contains up to one complete key/value pair. 95 char setting_buf[8]; 96 97 // The amount of the buffer that is filled with valid data. 98 size_t setting_buf_len; 99 100 // The ID of the last setting that was processed in the current SETTINGS 101 // frame. Used for detecting out-of-order or duplicate keys within a settings 102 // frame. Set to -1 before first key/value pair is processed. 103 int last_setting_id; 104 }; 105 106 // Scratch space necessary for processing ALTSVC frames. 107 struct NET_EXPORT_PRIVATE SpdyAltSvcScratch { 108 SpdyAltSvcScratch(); 109 ~SpdyAltSvcScratch(); 110 ResetSpdyAltSvcScratch111 void Reset() { 112 max_age = 0; 113 port = 0; 114 pid_len = 0; 115 host_len = 0; 116 origin_len = 0; 117 pid_buf_len = 0; 118 host_buf_len = 0; 119 origin_buf_len = 0; 120 protocol_id.reset(); 121 host.reset(); 122 origin.reset(); 123 } 124 125 uint32 max_age; 126 uint16 port; 127 uint8 pid_len; 128 uint8 host_len; 129 size_t origin_len; 130 size_t pid_buf_len; 131 size_t host_buf_len; 132 size_t origin_buf_len; 133 scoped_ptr<char[]> protocol_id; 134 scoped_ptr<char[]> host; 135 scoped_ptr<char[]> origin; 136 }; 137 138 // SpdyFramerVisitorInterface is a set of callbacks for the SpdyFramer. 139 // Implement this interface to receive event callbacks as frames are 140 // decoded from the framer. 141 // 142 // Control frames that contain SPDY header blocks (SYN_STREAM, SYN_REPLY, 143 // HEADER, and PUSH_PROMISE) are processed in fashion that allows the 144 // decompressed header block to be delivered in chunks to the visitor. 145 // The following steps are followed: 146 // 1. OnSynStream, OnSynReply, OnHeaders, or OnPushPromise is called. 147 // 2. Repeated: OnControlFrameHeaderData is called with chunks of the 148 // decompressed header block. In each call the len parameter is greater 149 // than zero. 150 // 3. OnControlFrameHeaderData is called with len set to zero, indicating 151 // that the full header block has been delivered for the control frame. 152 // During step 2 the visitor may return false, indicating that the chunk of 153 // header data could not be handled by the visitor (typically this indicates 154 // resource exhaustion). If this occurs the framer will discontinue 155 // delivering chunks to the visitor, set a SPDY_CONTROL_PAYLOAD_TOO_LARGE 156 // error, and clean up appropriately. Note that this will cause the header 157 // decompressor to lose synchronization with the sender's header compressor, 158 // making the SPDY session unusable for future work. The visitor's OnError 159 // function should deal with this condition by closing the SPDY connection. 160 class NET_EXPORT_PRIVATE SpdyFramerVisitorInterface { 161 public: ~SpdyFramerVisitorInterface()162 virtual ~SpdyFramerVisitorInterface() {} 163 164 // Called if an error is detected in the SpdyFrame protocol. 165 virtual void OnError(SpdyFramer* framer) = 0; 166 167 // Called when a data frame header is received. The frame's data 168 // payload will be provided via subsequent calls to 169 // OnStreamFrameData(). 170 virtual void OnDataFrameHeader(SpdyStreamId stream_id, 171 size_t length, 172 bool fin) = 0; 173 174 // Called when data is received. 175 // |stream_id| The stream receiving data. 176 // |data| A buffer containing the data received. 177 // |len| The length of the data buffer. 178 // When the other side has finished sending data on this stream, 179 // this method will be called with a zero-length buffer. 180 virtual void OnStreamFrameData(SpdyStreamId stream_id, 181 const char* data, 182 size_t len, 183 bool fin) = 0; 184 185 // Called when a chunk of header data is available. This is called 186 // after OnSynStream, OnSynReply, OnHeaders(), or OnPushPromise. 187 // |stream_id| The stream receiving the header data. 188 // |header_data| A buffer containing the header data chunk received. 189 // |len| The length of the header data buffer. A length of zero indicates 190 // that the header data block has been completely sent. 191 // When this function returns true the visitor indicates that it accepted 192 // all of the data. Returning false indicates that that an unrecoverable 193 // error has occurred, such as bad header data or resource exhaustion. 194 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id, 195 const char* header_data, 196 size_t len) = 0; 197 198 // Called when a SYN_STREAM frame is received. 199 // Note that header block data is not included. See 200 // OnControlFrameHeaderData(). 201 virtual void OnSynStream(SpdyStreamId stream_id, 202 SpdyStreamId associated_stream_id, 203 SpdyPriority priority, 204 bool fin, 205 bool unidirectional) = 0; 206 207 // Called when a SYN_REPLY frame is received. 208 // Note that header block data is not included. See 209 // OnControlFrameHeaderData(). 210 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) = 0; 211 212 // Called when a RST_STREAM frame has been parsed. 213 virtual void OnRstStream(SpdyStreamId stream_id, 214 SpdyRstStreamStatus status) = 0; 215 216 // Called when a SETTINGS frame is received. 217 // |clear_persisted| True if the respective flag is set on the SETTINGS frame. OnSettings(bool clear_persisted)218 virtual void OnSettings(bool clear_persisted) {} 219 220 // Called when a complete setting within a SETTINGS frame has been parsed and 221 // validated. 222 virtual void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) = 0; 223 224 // Called when a SETTINGS frame is received with the ACK flag set. OnSettingsAck()225 virtual void OnSettingsAck() {} 226 227 // Called before and after parsing SETTINGS id and value tuples. 228 virtual void OnSettingsEnd() = 0; 229 230 // Called when a PING frame has been parsed. 231 virtual void OnPing(SpdyPingId unique_id, bool is_ack) = 0; 232 233 // Called when a GOAWAY frame has been parsed. 234 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id, 235 SpdyGoAwayStatus status) = 0; 236 237 // Called when a HEADERS frame is received. 238 // Note that header block data is not included. See 239 // OnControlFrameHeaderData(). 240 virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) = 0; 241 242 // Called when a WINDOW_UPDATE frame has been parsed. 243 virtual void OnWindowUpdate(SpdyStreamId stream_id, 244 uint32 delta_window_size) = 0; 245 246 // Called when a goaway frame opaque data is available. 247 // |goaway_data| A buffer containing the opaque GOAWAY data chunk received. 248 // |len| The length of the header data buffer. A length of zero indicates 249 // that the header data block has been completely sent. 250 // When this function returns true the visitor indicates that it accepted 251 // all of the data. Returning false indicates that that an error has 252 // occurred while processing the data. Default implementation returns true. 253 virtual bool OnGoAwayFrameData(const char* goaway_data, size_t len); 254 255 // Called when rst_stream frame opaque data is available. 256 // |rst_stream_data| A buffer containing the opaque RST_STREAM 257 // data chunk received. 258 // |len| The length of the header data buffer. A length of zero indicates 259 // that the opaque data has been completely sent. 260 // When this function returns true the visitor indicates that it accepted 261 // all of the data. Returning false indicates that that an error has 262 // occurred while processing the data. Default implementation returns true. 263 virtual bool OnRstStreamFrameData(const char* rst_stream_data, size_t len); 264 265 // Called when a BLOCKED frame has been parsed. OnBlocked(SpdyStreamId stream_id)266 virtual void OnBlocked(SpdyStreamId stream_id) {} 267 268 // Called when a PUSH_PROMISE frame is received. 269 // Note that header block data is not included. See 270 // OnControlFrameHeaderData(). 271 virtual void OnPushPromise(SpdyStreamId stream_id, 272 SpdyStreamId promised_stream_id, 273 bool end) = 0; 274 275 // Called when a CONTINUATION frame is received. 276 // Note that header block data is not included. See 277 // OnControlFrameHeaderData(). 278 virtual void OnContinuation(SpdyStreamId stream_id, bool end) = 0; 279 280 // Called when an ALTSVC frame has been parsed. OnAltSvc(SpdyStreamId stream_id,uint32 max_age,uint16 port,base::StringPiece protocol_id,base::StringPiece host,base::StringPiece origin)281 virtual void OnAltSvc(SpdyStreamId stream_id, 282 uint32 max_age, 283 uint16 port, 284 base::StringPiece protocol_id, 285 base::StringPiece host, 286 base::StringPiece origin) {} 287 288 // Called when a PRIORITY frame is received. OnPriority(SpdyStreamId stream_id,SpdyStreamId parent_stream_id,uint8 weight,bool exclusive)289 virtual void OnPriority(SpdyStreamId stream_id, 290 SpdyStreamId parent_stream_id, 291 uint8 weight, 292 bool exclusive) {} 293 294 // Called when a frame type we don't recognize is received. 295 // Return true if this appears to be a valid extension frame, false otherwise. 296 // We distinguish between extension frames and nonsense by checking 297 // whether the stream id is valid. 298 virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) = 0; 299 }; 300 301 // Optionally, and in addition to SpdyFramerVisitorInterface, a class supporting 302 // SpdyFramerDebugVisitorInterface may be used in conjunction with SpdyFramer in 303 // order to extract debug/internal information about the SpdyFramer as it 304 // operates. 305 // 306 // Most SPDY implementations need not bother with this interface at all. 307 class NET_EXPORT_PRIVATE SpdyFramerDebugVisitorInterface { 308 public: ~SpdyFramerDebugVisitorInterface()309 virtual ~SpdyFramerDebugVisitorInterface() {} 310 311 // Called after compressing a frame with a payload of 312 // a list of name-value pairs. 313 // |payload_len| is the uncompressed payload size. 314 // |frame_len| is the compressed frame size. OnSendCompressedFrame(SpdyStreamId stream_id,SpdyFrameType type,size_t payload_len,size_t frame_len)315 virtual void OnSendCompressedFrame(SpdyStreamId stream_id, 316 SpdyFrameType type, 317 size_t payload_len, 318 size_t frame_len) {} 319 320 // Called when a frame containing a compressed payload of 321 // name-value pairs is received. 322 // |frame_len| is the compressed frame size. OnReceiveCompressedFrame(SpdyStreamId stream_id,SpdyFrameType type,size_t frame_len)323 virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id, 324 SpdyFrameType type, 325 size_t frame_len) {} 326 }; 327 328 class NET_EXPORT_PRIVATE SpdyFramer { 329 public: 330 // SPDY states. 331 // TODO(mbelshe): Can we move these into the implementation 332 // and avoid exposing through the header. (Needed for test) 333 enum SpdyState { 334 SPDY_ERROR, 335 SPDY_RESET, 336 SPDY_AUTO_RESET, 337 SPDY_READING_COMMON_HEADER, 338 SPDY_CONTROL_FRAME_PAYLOAD, 339 SPDY_READ_PADDING_LENGTH, 340 SPDY_CONSUME_PADDING, 341 SPDY_IGNORE_REMAINING_PAYLOAD, 342 SPDY_FORWARD_STREAM_FRAME, 343 SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, 344 SPDY_CONTROL_FRAME_HEADER_BLOCK, 345 SPDY_GOAWAY_FRAME_PAYLOAD, 346 SPDY_RST_STREAM_FRAME_PAYLOAD, 347 SPDY_SETTINGS_FRAME_PAYLOAD, 348 SPDY_ALTSVC_FRAME_PAYLOAD, 349 }; 350 351 // SPDY error codes. 352 enum SpdyError { 353 SPDY_NO_ERROR, 354 SPDY_INVALID_CONTROL_FRAME, // Control frame is mal-formatted. 355 SPDY_CONTROL_PAYLOAD_TOO_LARGE, // Control frame payload was too large. 356 SPDY_ZLIB_INIT_FAILURE, // The Zlib library could not initialize. 357 SPDY_UNSUPPORTED_VERSION, // Control frame has unsupported version. 358 SPDY_DECOMPRESS_FAILURE, // There was an error decompressing. 359 SPDY_COMPRESS_FAILURE, // There was an error compressing. 360 SPDY_GOAWAY_FRAME_CORRUPT, // GOAWAY frame could not be parsed. 361 SPDY_RST_STREAM_FRAME_CORRUPT, // RST_STREAM frame could not be parsed. 362 SPDY_INVALID_DATA_FRAME_FLAGS, // Data frame has invalid flags. 363 SPDY_INVALID_CONTROL_FRAME_FLAGS, // Control frame has invalid flags. 364 SPDY_UNEXPECTED_FRAME, // Frame received out of order. 365 366 LAST_ERROR, // Must be the last entry in the enum. 367 }; 368 369 // Constant for invalid (or unknown) stream IDs. 370 static const SpdyStreamId kInvalidStream; 371 372 // The maximum size of header data chunks delivered to the framer visitor 373 // through OnControlFrameHeaderData. (It is exposed here for unit test 374 // purposes.) 375 static const size_t kHeaderDataChunkMaxSize; 376 377 // Serializes a SpdyHeaderBlock. 378 static void WriteHeaderBlock(SpdyFrameBuilder* frame, 379 const SpdyMajorVersion spdy_version, 380 const SpdyHeaderBlock* headers); 381 382 // Retrieve serialized length of SpdyHeaderBlock. 383 // TODO(hkhalil): Remove, or move to quic code. 384 static size_t GetSerializedLength( 385 const SpdyMajorVersion spdy_version, 386 const SpdyHeaderBlock* headers); 387 388 // Create a new Framer, provided a SPDY version. 389 explicit SpdyFramer(SpdyMajorVersion version); 390 virtual ~SpdyFramer(); 391 392 // Set callbacks to be called from the framer. A visitor must be set, or 393 // else the framer will likely crash. It is acceptable for the visitor 394 // to do nothing. If this is called multiple times, only the last visitor 395 // will be used. set_visitor(SpdyFramerVisitorInterface * visitor)396 void set_visitor(SpdyFramerVisitorInterface* visitor) { 397 visitor_ = visitor; 398 } 399 400 // Set debug callbacks to be called from the framer. The debug visitor is 401 // completely optional and need not be set in order for normal operation. 402 // If this is called multiple times, only the last visitor will be used. set_debug_visitor(SpdyFramerDebugVisitorInterface * debug_visitor)403 void set_debug_visitor(SpdyFramerDebugVisitorInterface* debug_visitor) { 404 debug_visitor_ = debug_visitor; 405 } 406 407 // Pass data into the framer for parsing. 408 // Returns the number of bytes consumed. It is safe to pass more bytes in 409 // than may be consumed. 410 size_t ProcessInput(const char* data, size_t len); 411 412 // Resets the framer state after a frame has been successfully decoded. 413 // TODO(mbelshe): can we make this private? 414 void Reset(); 415 416 // Check the state of the framer. error_code()417 SpdyError error_code() const { return error_code_; } state()418 SpdyState state() const { return state_; } HasError()419 bool HasError() const { return state_ == SPDY_ERROR; } 420 421 // Given a buffer containing a decompressed header block in SPDY 422 // serialized format, parse out a SpdyHeaderBlock, putting the results 423 // in the given header block. 424 // Returns number of bytes consumed if successfully parsed, 0 otherwise. 425 size_t ParseHeaderBlockInBuffer(const char* header_data, 426 size_t header_length, 427 SpdyHeaderBlock* block) const; 428 429 // Serialize a data frame. 430 SpdySerializedFrame* SerializeData(const SpdyDataIR& data) const; 431 // Serializes the data frame header and optionally padding length fields, 432 // excluding actual data payload and padding. 433 SpdySerializedFrame* SerializeDataFrameHeaderWithPaddingLengthField( 434 const SpdyDataIR& data) const; 435 436 // Serializes a SYN_STREAM frame. 437 SpdySerializedFrame* SerializeSynStream(const SpdySynStreamIR& syn_stream); 438 439 // Serialize a SYN_REPLY SpdyFrame. 440 SpdySerializedFrame* SerializeSynReply(const SpdySynReplyIR& syn_reply); 441 442 SpdySerializedFrame* SerializeRstStream( 443 const SpdyRstStreamIR& rst_stream) const; 444 445 // Serializes a SETTINGS frame. The SETTINGS frame is 446 // used to communicate name/value pairs relevant to the communication channel. 447 SpdySerializedFrame* SerializeSettings(const SpdySettingsIR& settings) const; 448 449 // Serializes a PING frame. The unique_id is used to 450 // identify the ping request/response. 451 SpdySerializedFrame* SerializePing(const SpdyPingIR& ping) const; 452 453 // Serializes a GOAWAY frame. The GOAWAY frame is used 454 // prior to the shutting down of the TCP connection, and includes the 455 // stream_id of the last stream the sender of the frame is willing to process 456 // to completion. 457 SpdySerializedFrame* SerializeGoAway(const SpdyGoAwayIR& goaway) const; 458 459 // Serializes a HEADERS frame. The HEADERS frame is used 460 // for sending additional headers outside of a SYN_STREAM/SYN_REPLY. 461 SpdySerializedFrame* SerializeHeaders(const SpdyHeadersIR& headers); 462 463 // Serializes a WINDOW_UPDATE frame. The WINDOW_UPDATE 464 // frame is used to implement per stream flow control in SPDY. 465 SpdySerializedFrame* SerializeWindowUpdate( 466 const SpdyWindowUpdateIR& window_update) const; 467 468 // Serializes a BLOCKED frame. The BLOCKED frame is used to 469 // indicate to the remote endpoint that this endpoint believes itself to be 470 // flow-control blocked but otherwise ready to send data. The BLOCKED frame 471 // is purely advisory and optional. 472 SpdySerializedFrame* SerializeBlocked(const SpdyBlockedIR& blocked) const; 473 474 // Serializes a PUSH_PROMISE frame. The PUSH_PROMISE frame is used 475 // to inform the client that it will be receiving an additional stream 476 // in response to the original request. The frame includes synthesized 477 // headers to explain the upcoming data. 478 SpdySerializedFrame* SerializePushPromise( 479 const SpdyPushPromiseIR& push_promise); 480 481 // Serializes a CONTINUATION frame. The CONTINUATION frame is used 482 // to continue a sequence of header block fragments. 483 // TODO(jgraettinger): This implementation is incorrect. The continuation 484 // frame continues a previously-begun HPACK encoding; it doesn't begin a 485 // new one. Figure out whether it makes sense to keep SerializeContinuation(). 486 SpdySerializedFrame* SerializeContinuation( 487 const SpdyContinuationIR& continuation); 488 489 // Serializes an ALTSVC frame. The ALTSVC frame advertises the 490 // availability of an alternative service to the client. 491 SpdySerializedFrame* SerializeAltSvc(const SpdyAltSvcIR& altsvc); 492 493 // Serializes a PRIORITY frame. The PRIORITY frame advises a change in 494 // the relative priority of the given stream. 495 SpdySerializedFrame* SerializePriority(const SpdyPriorityIR& priority); 496 497 // Serialize a frame of unknown type. 498 SpdySerializedFrame* SerializeFrame(const SpdyFrameIR& frame); 499 500 // NOTES about frame compression. 501 // We want spdy to compress headers across the entire session. As long as 502 // the session is over TCP, frames are sent serially. The client & server 503 // can each compress frames in the same order and then compress them in that 504 // order, and the remote can do the reverse. However, we ultimately want 505 // the creation of frames to be less sensitive to order so that they can be 506 // placed over a UDP based protocol and yet still benefit from some 507 // compression. We don't know of any good compression protocol which does 508 // not build its state in a serial (stream based) manner.... For now, we're 509 // using zlib anyway. 510 511 // Compresses a SpdyFrame. 512 // On success, returns a new SpdyFrame with the payload compressed. 513 // Compression state is maintained as part of the SpdyFramer. 514 // Returned frame must be freed with "delete". 515 // On failure, returns NULL. 516 SpdyFrame* CompressFrame(const SpdyFrame& frame); 517 518 // For ease of testing and experimentation we can tweak compression on/off. set_enable_compression(bool value)519 void set_enable_compression(bool value) { 520 enable_compression_ = value; 521 } 522 523 // Used only in log messages. set_display_protocol(const std::string & protocol)524 void set_display_protocol(const std::string& protocol) { 525 display_protocol_ = protocol; 526 } 527 528 // Returns the (minimum) size of frames (sans variable-length portions). 529 size_t GetDataFrameMinimumSize() const; 530 size_t GetControlFrameHeaderSize() const; 531 size_t GetSynStreamMinimumSize() const; 532 size_t GetSynReplyMinimumSize() const; 533 size_t GetRstStreamMinimumSize() const; 534 size_t GetSettingsMinimumSize() const; 535 size_t GetPingSize() const; 536 size_t GetGoAwayMinimumSize() const; 537 size_t GetHeadersMinimumSize() const; 538 size_t GetWindowUpdateSize() const; 539 size_t GetBlockedSize() const; 540 size_t GetPushPromiseMinimumSize() const; 541 size_t GetContinuationMinimumSize() const; 542 size_t GetAltSvcMinimumSize() const; 543 size_t GetPrioritySize() const; 544 545 // Returns the minimum size a frame can be (data or control). 546 size_t GetFrameMinimumSize() const; 547 548 // Returns the maximum size a frame can be (data or control). 549 size_t GetFrameMaximumSize() const; 550 551 // Returns the maximum size that a control frame can be. 552 size_t GetControlFrameMaximumSize() const; 553 554 // Returns the maximum payload size of a DATA frame. 555 size_t GetDataFrameMaximumPayload() const; 556 557 // Returns the prefix length for the given frame type. 558 size_t GetPrefixLength(SpdyFrameType type) const; 559 560 // For debugging. 561 static const char* StateToString(int state); 562 static const char* ErrorCodeToString(int error_code); 563 static const char* StatusCodeToString(int status_code); 564 static const char* FrameTypeToString(SpdyFrameType type); 565 protocol_version()566 SpdyMajorVersion protocol_version() const { return spdy_version_; } 567 probable_http_response()568 bool probable_http_response() const { return probable_http_response_; } 569 expect_continuation()570 SpdyStreamId expect_continuation() const { return expect_continuation_; } 571 GetLowestPriority()572 SpdyPriority GetLowestPriority() const { 573 return spdy_version_ < SPDY3 ? 3 : 7; 574 } 575 GetHighestPriority()576 SpdyPriority GetHighestPriority() const { return 0; } 577 578 // Interpolates SpdyPriority values into SPDY4/HTTP2 priority weights, 579 // and vice versa. 580 uint8 MapPriorityToWeight(SpdyPriority priority); 581 SpdyPriority MapWeightToPriority(uint8 weight); 582 583 // Deliver the given control frame's compressed headers block to the visitor 584 // in decompressed form, in chunks. Returns true if the visitor has 585 // accepted all of the chunks. 586 bool IncrementallyDecompressControlFrameHeaderData( 587 SpdyStreamId stream_id, 588 const char* data, 589 size_t len); 590 591 protected: 592 // TODO(jgraettinger): Switch to test peer pattern. 593 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, BasicCompression); 594 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameSizesAreValidated); 595 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HeaderCompression); 596 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, DecompressUncompressedFrame); 597 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ExpandBuffer_HeapSmash); 598 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, HugeHeaderBlock); 599 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, UnclosedStreamDataCompressors); 600 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, 601 UnclosedStreamDataCompressorsOneByteAtATime); 602 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, 603 UncompressLargerThanFrameBufferInitialSize); 604 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ReadLargeSettingsFrame); 605 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, 606 ReadLargeSettingsFrameInSmallChunks); 607 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameAtMaxSizeLimit); 608 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, ControlFrameTooLarge); 609 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, 610 TooLargeHeadersFrameUsesContinuation); 611 FRIEND_TEST_ALL_PREFIXES(SpdyFramerTest, 612 TooLargePushPromiseFrameUsesContinuation); 613 friend class net::HttpNetworkLayer; // This is temporary for the server. 614 friend class net::HttpNetworkTransactionTest; 615 friend class net::HttpProxyClientSocketPoolTest; 616 friend class net::SpdyHttpStreamTest; 617 friend class net::SpdyNetworkTransactionTest; 618 friend class net::SpdyProxyClientSocketTest; 619 friend class net::SpdySessionTest; 620 friend class net::SpdyStreamTest; 621 friend class net::SpdyWebSocketStreamTest; 622 friend class net::WebSocketJobTest; 623 friend class test::TestSpdyVisitor; 624 625 private: 626 // Internal breakouts from ProcessInput. Each returns the number of bytes 627 // consumed from the data. 628 size_t ProcessCommonHeader(const char* data, size_t len); 629 size_t ProcessControlFramePayload(const char* data, size_t len); 630 size_t ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len); 631 // HPACK data is re-encoded as SPDY3 and re-entrantly delivered through 632 // |ProcessControlFrameHeaderBlock()|. |is_hpack_header_block| controls 633 // whether data is treated as HPACK- vs SPDY3-encoded. 634 size_t ProcessControlFrameHeaderBlock(const char* data, 635 size_t len, 636 bool is_hpack_header_block); 637 size_t ProcessFramePaddingLength(const char* data, size_t len); 638 size_t ProcessFramePadding(const char* data, size_t len); 639 size_t ProcessDataFramePayload(const char* data, size_t len); 640 size_t ProcessGoAwayFramePayload(const char* data, size_t len); 641 size_t ProcessRstStreamFramePayload(const char* data, size_t len); 642 size_t ProcessSettingsFramePayload(const char* data, size_t len); 643 size_t ProcessAltSvcFramePayload(const char* data, size_t len); 644 size_t ProcessIgnoredControlFramePayload(/*const char* data,*/ size_t len); 645 646 // TODO(jgraettinger): To be removed with migration to 647 // SpdyHeadersHandlerInterface. 648 // Serializes the last-processed header block of |hpack_decoder_| as 649 // a SPDY3 format block, and delivers it to the visitor via reentrant 650 // call to ProcessControlFrameHeaderBlock(). 651 void DeliverHpackBlockAsSpdy3Block(); 652 653 // Helpers for above internal breakouts from ProcessInput. 654 void ProcessControlFrameHeader(uint16 control_frame_type_field); 655 // Always passed exactly 1 setting's worth of data. 656 bool ProcessSetting(const char* data); 657 658 // Retrieve serialized length of SpdyHeaderBlock. If compression is enabled, a 659 // maximum estimate is returned. 660 size_t GetSerializedLength(const SpdyHeaderBlock& headers); 661 662 // Get (and lazily initialize) the ZLib state. 663 z_stream* GetHeaderCompressor(); 664 z_stream* GetHeaderDecompressor(); 665 666 // Get (and lazily initialize) the HPACK state. 667 HpackEncoder* GetHpackEncoder(); 668 HpackDecoder* GetHpackDecoder(); 669 670 size_t GetNumberRequiredContinuationFrames(size_t size); 671 672 void WritePayloadWithContinuation(SpdyFrameBuilder* builder, 673 const std::string& hpack_encoding, 674 SpdyStreamId stream_id, 675 SpdyFrameType type); 676 677 private: 678 // Deliver the given control frame's uncompressed headers block to the 679 // visitor in chunks. Returns true if the visitor has accepted all of the 680 // chunks. 681 bool IncrementallyDeliverControlFrameHeaderData(SpdyStreamId stream_id, 682 const char* data, 683 size_t len); 684 685 // Utility to copy the given data block to the current frame buffer, up 686 // to the given maximum number of bytes, and update the buffer 687 // data (pointer and length). Returns the number of bytes 688 // read, and: 689 // *data is advanced the number of bytes read. 690 // *len is reduced by the number of bytes read. 691 size_t UpdateCurrentFrameBuffer(const char** data, size_t* len, 692 size_t max_bytes); 693 694 void WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, 695 z_stream* out) const; 696 697 void SerializeNameValueBlockWithoutCompression( 698 SpdyFrameBuilder* builder, 699 const SpdyNameValueBlock& name_value_block) const; 700 701 // Compresses automatically according to enable_compression_. 702 void SerializeNameValueBlock( 703 SpdyFrameBuilder* builder, 704 const SpdyFrameWithNameValueBlockIR& frame); 705 706 // Set the error code and moves the framer into the error state. 707 void set_error(SpdyError error); 708 709 // The maximum size of the control frames that we support. 710 // This limit is arbitrary. We can enforce it here or at the application 711 // layer. We chose the framing layer, but this can be changed (or removed) 712 // if necessary later down the line. GetControlFrameBufferMaxSize()713 size_t GetControlFrameBufferMaxSize() const { 714 // The theoretical maximum for SPDY3 and earlier is (2^24 - 1) + 715 // 8, since the length field does not count the size of the 716 // header. 717 if (spdy_version_ == SPDY2) { 718 return 64 * 1024; 719 } 720 if (spdy_version_ == SPDY3) { 721 return 16 * 1024 * 1024; 722 } 723 // Absolute maximum size of HTTP2 frame payload (section 4.2 "Frame size"). 724 return (1<<14) - 1; 725 } 726 727 // TODO(jgraettinger): For h2-13 interop testing coverage, 728 // fragment at smaller payload boundaries. GetHeaderFragmentMaxSize()729 size_t GetHeaderFragmentMaxSize() const { 730 return GetControlFrameBufferMaxSize() >> 4; // 1023 bytes. 731 } 732 733 // The size of the control frame buffer. 734 // Since this is only used for control frame headers, the maximum control 735 // frame header size (SYN_STREAM) is sufficient; all remaining control 736 // frame data is streamed to the visitor. 737 static const size_t kControlFrameBufferSize; 738 739 SpdyState state_; 740 SpdyState previous_state_; 741 SpdyError error_code_; 742 743 // Note that for DATA frame, remaining_data_length_ is sum of lengths of 744 // frame header, padding length field (optional), data payload (optional) and 745 // padding payload (optional). 746 size_t remaining_data_length_; 747 748 // The length (in bytes) of the padding payload to be processed. 749 size_t remaining_padding_payload_length_; 750 751 // The number of bytes remaining to read from the current control frame's 752 // headers. Note that header data blocks (for control types that have them) 753 // are part of the frame's payload, and not the frame's headers. 754 size_t remaining_control_header_; 755 756 scoped_ptr<char[]> current_frame_buffer_; 757 // Number of bytes read into the current_frame_buffer_. 758 size_t current_frame_buffer_length_; 759 760 // The type of the frame currently being read. 761 SpdyFrameType current_frame_type_; 762 763 // The flags field of the frame currently being read. 764 uint8 current_frame_flags_; 765 766 // The total length of the frame currently being read, including frame header. 767 uint32 current_frame_length_; 768 769 // The stream ID field of the frame currently being read, if applicable. 770 SpdyStreamId current_frame_stream_id_; 771 772 // Scratch space for handling SETTINGS frames. 773 // TODO(hkhalil): Unify memory for this scratch space with 774 // current_frame_buffer_. 775 SpdySettingsScratch settings_scratch_; 776 777 SpdyAltSvcScratch altsvc_scratch_; 778 779 bool enable_compression_; // Controls all compression 780 // SPDY header compressors. 781 scoped_ptr<z_stream> header_compressor_; 782 scoped_ptr<z_stream> header_decompressor_; 783 784 scoped_ptr<HpackEncoder> hpack_encoder_; 785 scoped_ptr<HpackDecoder> hpack_decoder_; 786 787 SpdyFramerVisitorInterface* visitor_; 788 SpdyFramerDebugVisitorInterface* debug_visitor_; 789 790 std::string display_protocol_; 791 792 // The major SPDY version to be spoken/understood by this framer. 793 const SpdyMajorVersion spdy_version_; 794 795 // Tracks if we've ever gotten far enough in framing to see a control frame of 796 // type SYN_STREAM or SYN_REPLY. 797 // 798 // If we ever get something which looks like a data frame before we've had a 799 // SYN, we explicitly check to see if it looks like we got an HTTP response 800 // to a SPDY request. This boolean lets us do that. 801 bool syn_frame_processed_; 802 803 // If we ever get a data frame before a SYN frame, we check to see if it 804 // starts with HTTP. If it does, we likely have an HTTP response. This 805 // isn't guaranteed though: we could have gotten a settings frame and then 806 // corrupt data that just looks like HTTP, but deterministic checking requires 807 // a lot more state. 808 bool probable_http_response_; 809 810 // Set this to the current stream when we receive a HEADERS, PUSH_PROMISE, or 811 // CONTINUATION frame without the END_HEADERS(0x4) bit set. These frames must 812 // be followed by a CONTINUATION frame, or else we throw a PROTOCOL_ERROR. 813 // A value of 0 indicates that we are not expecting a CONTINUATION frame. 814 SpdyStreamId expect_continuation_; 815 816 // If a HEADERS frame is followed by a CONTINUATION frame, the FIN/END_STREAM 817 // flag is still carried in the HEADERS frame. If it's set, flip this so that 818 // we know to terminate the stream when the entire header block has been 819 // processed. 820 bool end_stream_when_done_; 821 }; 822 823 } // namespace net 824 825 #endif // NET_SPDY_SPDY_FRAMER_H_ 826