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