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