Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't | 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't |
| 6 // constantly adding and subtracting header sizes; this is ugly and error- | 6 // constantly adding and subtracting header sizes; this is ugly and error- |
| 7 // prone. | 7 // prone. |
| 8 | 8 |
| 9 #include "net/spdy/spdy_framer.h" | 9 #include "net/spdy/spdy_framer.h" |
| 10 | 10 |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/metrics/stats_counters.h" | 12 #include "base/metrics/stats_counters.h" |
| 13 #include "base/third_party/valgrind/memcheck.h" | 13 #include "base/third_party/valgrind/memcheck.h" |
| 14 #include "net/spdy/spdy_frame_builder.h" | 14 #include "net/spdy/spdy_frame_builder.h" |
| 15 #include "net/spdy/spdy_frame_reader.h" | |
| 15 #include "net/spdy/spdy_bitmasks.h" | 16 #include "net/spdy/spdy_bitmasks.h" |
| 16 | 17 |
| 17 #if defined(USE_SYSTEM_ZLIB) | 18 #if defined(USE_SYSTEM_ZLIB) |
| 18 #include <zlib.h> | 19 #include <zlib.h> |
| 19 #else | 20 #else |
| 20 #include "third_party/zlib/zlib.h" | 21 #include "third_party/zlib/zlib.h" |
| 21 #endif | 22 #endif |
| 22 | 23 |
| 23 using std::vector; | 24 using std::vector; |
| 24 | 25 |
| 25 namespace spdy { | 26 namespace spdy { |
| 26 | 27 |
| 27 SpdyCredential::SpdyCredential() : slot(0) { } | |
| 28 SpdyCredential::~SpdyCredential() { } | |
| 29 | |
| 30 // Compute the id of our dictionary so that we know we're using the | 28 // Compute the id of our dictionary so that we know we're using the |
| 31 // right one when asked for it. | 29 // right one when asked for it. |
| 32 uLong CalculateDictionaryId() { | 30 uLong CalculateDictionaryId(const char* dictionary, |
| 31 const size_t dictionary_size) { | |
| 33 uLong initial_value = adler32(0L, Z_NULL, 0); | 32 uLong initial_value = adler32(0L, Z_NULL, 0); |
| 34 return adler32(initial_value, | 33 return adler32(initial_value, |
| 35 reinterpret_cast<const Bytef*>(SpdyFramer::kDictionary), | 34 reinterpret_cast<const Bytef*>(dictionary), |
| 36 SpdyFramer::kDictionarySize); | 35 dictionary_size); |
| 37 } | 36 } |
| 38 | 37 |
| 39 // Adler ID for the SPDY header compressor dictionary. | 38 // Adler ID for the SPDY header compressor dictionaries. |
| 40 const uLong kDictionaryId = CalculateDictionaryId(); | 39 const uLong kV2DictionaryId = CalculateDictionaryId(kV2Dictionary, |
| 41 | 40 kV2DictionarySize); |
| 42 int DecompressHeaderBlockInZStream(z_stream* decompressor) { | 41 const uLong kV3DictionaryId = CalculateDictionaryId(kV3Dictionary, |
| 43 int rv = inflate(decompressor, Z_SYNC_FLUSH); | 42 kV3DictionarySize); |
| 44 if (rv == Z_NEED_DICT) { | |
| 45 // Need to try again with the right dictionary. | |
| 46 if (decompressor->adler == kDictionaryId) { | |
| 47 rv = inflateSetDictionary(decompressor, | |
| 48 (const Bytef*)SpdyFramer::kDictionary, | |
| 49 SpdyFramer::kDictionarySize); | |
| 50 if (rv == Z_OK) | |
| 51 rv = inflate(decompressor, Z_SYNC_FLUSH); | |
| 52 } | |
| 53 } | |
| 54 return rv; | |
| 55 } | |
| 56 | |
| 57 // Retrieve serialized length of SpdyHeaderBlock. | |
| 58 size_t GetSerializedLength(const SpdyHeaderBlock* headers) { | |
| 59 size_t total_length = SpdyControlFrame::kNumNameValuePairsSize; | |
| 60 SpdyHeaderBlock::const_iterator it; | |
| 61 for (it = headers->begin(); it != headers->end(); ++it) { | |
| 62 // We add space for the length of the name and the length of the value as | |
| 63 // well as the length of the name and the length of the value. | |
| 64 total_length += SpdyControlFrame::kLengthOfNameSize + | |
| 65 it->first.size() + | |
| 66 SpdyControlFrame::kLengthOfValueSize + | |
| 67 it->second.size(); | |
| 68 } | |
| 69 return total_length; | |
| 70 } | |
| 71 | |
| 72 // Serializes a SpdyHeaderBlock. | |
| 73 void WriteHeaderBlock(SpdyFrameBuilder* frame, const SpdyHeaderBlock* headers) { | |
| 74 frame->WriteUInt16(headers->size()); // Number of headers. | |
| 75 SpdyHeaderBlock::const_iterator it; | |
| 76 for (it = headers->begin(); it != headers->end(); ++it) { | |
| 77 bool wrote_header; | |
| 78 wrote_header = frame->WriteString(it->first); | |
| 79 wrote_header &= frame->WriteString(it->second); | |
| 80 DCHECK(wrote_header); | |
| 81 } | |
| 82 } | |
| 83 | 43 |
| 84 // Creates a FlagsAndLength. | 44 // Creates a FlagsAndLength. |
| 85 FlagsAndLength CreateFlagsAndLength(SpdyControlFlags flags, size_t length) { | 45 FlagsAndLength CreateFlagsAndLength(SpdyControlFlags flags, size_t length) { |
| 86 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); | 46 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); |
| 87 FlagsAndLength flags_length; | 47 FlagsAndLength flags_length; |
| 88 flags_length.length_ = htonl(static_cast<uint32>(length)); | 48 flags_length.length_ = htonl(static_cast<uint32>(length)); |
| 89 DCHECK_EQ(0, flags & ~kControlFlagsMask); | 49 DCHECK_EQ(0, flags & ~kControlFlagsMask); |
| 90 flags_length.flags_[0] = flags; | 50 flags_length.flags_[0] = flags; |
| 91 return flags_length; | 51 return flags_length; |
| 92 } | 52 } |
| 93 | 53 |
| 94 // By default is compression on or off. | 54 // By default is compression on or off. |
| 95 bool SpdyFramer::compression_default_ = true; | 55 bool SpdyFramer::compression_default_ = true; |
| 96 | 56 |
| 97 // The initial size of the control frame buffer; this is used internally | 57 // The initial size of the control frame buffer; this is used internally |
| 98 // as we parse through control frames. (It is exposed here for unit test | 58 // as we parse through control frames. (It is exposed here for unit test |
| 99 // purposes.) | 59 // purposes.) |
| 100 size_t SpdyFramer::kControlFrameBufferInitialSize = 32 * 1024; | 60 size_t SpdyFramer::kControlFrameBufferInitialSize = 32 * 1024; |
| 101 | 61 |
| 102 // The maximum size of the control frame buffer that we support. | 62 // The maximum size of the control frame buffer that we support. |
| 103 // TODO(mbelshe): We should make this stream-based so there are no limits. | 63 // TODO(mbelshe): We should make this stream-based so there are no limits. |
| 104 size_t SpdyFramer::kControlFrameBufferMaxSize = 64 * 1024; | 64 size_t SpdyFramer::kControlFrameBufferMaxSize = 64 * 1024; |
| 105 | 65 |
| 106 int SpdyFramer::spdy_version_ = kSpdyProtocolVersion; | |
| 107 | |
| 108 const SpdyStreamId SpdyFramer::kInvalidStream = -1; | 66 const SpdyStreamId SpdyFramer::kInvalidStream = -1; |
| 109 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 67 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
| 68 size_t SpdyFramer::kUncompressedControlFrameBufferInitialSize = 18 + 16; | |
|
Ryan Hamilton
2012/03/09 19:09:58
Can you add a comment explaining why this is the r
ramant (doing other things)
2012/03/10 01:14:09
Done.
| |
| 69 | |
| 110 | 70 |
| 111 #ifdef DEBUG_SPDY_STATE_CHANGES | 71 #ifdef DEBUG_SPDY_STATE_CHANGES |
| 112 #define CHANGE_STATE(newstate) \ | 72 #define CHANGE_STATE(newstate) \ |
| 113 { \ | 73 { \ |
| 114 do { \ | 74 do { \ |
| 115 LOG(INFO) << "Changing state from: " \ | 75 LOG(INFO) << "Changing state from: " \ |
| 116 << StateToString(state_) \ | 76 << StateToString(state_) \ |
| 117 << " to " << StateToString(newstate) << "\n"; \ | 77 << " to " << StateToString(newstate) << "\n"; \ |
| 118 state_ = newstate; \ | 78 state_ = newstate; \ |
| 119 } while (false); \ | 79 } while (false); \ |
| 120 } | 80 } |
| 121 #else | 81 #else |
| 122 #define CHANGE_STATE(newstate) (state_ = newstate) | 82 #define CHANGE_STATE(newstate) (state_ = newstate) |
| 123 #endif | 83 #endif |
| 124 | 84 |
| 125 SpdyFramer::SpdyFramer() | 85 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, |
| 86 uint32 wire) { | |
| 87 if (version < 3) { | |
| 88 ConvertFlagsAndIdForSpdy2(&wire); | |
| 89 } | |
| 90 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); | |
| 91 } | |
| 92 | |
| 93 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) | |
| 94 : flags_(flags), id_(id & 0x00ffffff) { | |
| 95 DCHECK_GT(static_cast<uint32>(1 << 24), id); | |
| 96 } | |
| 97 | |
| 98 uint32 SettingsFlagsAndId::GetWireFormat(int version) const { | |
| 99 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); | |
| 100 if (version < 3) { | |
| 101 ConvertFlagsAndIdForSpdy2(&wire); | |
| 102 } | |
| 103 return wire; | |
| 104 } | |
| 105 | |
| 106 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field. | |
| 107 // This method is used to preserve buggy behavior and works on both | |
| 108 // little-endian and big-endian hosts. | |
| 109 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3 | |
| 110 // as well as vice versa). | |
| 111 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) { | |
| 112 uint8* wire_array = reinterpret_cast<uint8*>(val); | |
| 113 std::swap(wire_array[0], wire_array[3]); | |
| 114 std::swap(wire_array[1], wire_array[2]); | |
| 115 } | |
| 116 | |
| 117 SpdyCredential::SpdyCredential() : slot(0) { } | |
| 118 SpdyCredential::~SpdyCredential() { } | |
| 119 | |
| 120 SpdyFramer::SpdyFramer(int version) | |
| 126 : state_(SPDY_RESET), | 121 : state_(SPDY_RESET), |
| 127 error_code_(SPDY_NO_ERROR), | 122 error_code_(SPDY_NO_ERROR), |
| 128 remaining_data_(0), | 123 remaining_data_(0), |
| 129 remaining_control_payload_(0), | 124 remaining_control_payload_(0), |
| 130 remaining_control_header_(0), | 125 remaining_control_header_(0), |
| 131 current_frame_buffer_(NULL), | 126 current_frame_buffer_(NULL), |
| 132 current_frame_len_(0), | 127 current_frame_len_(0), |
| 133 current_frame_capacity_(0), | 128 current_frame_capacity_(0), |
| 134 validate_control_frame_sizes_(true), | 129 validate_control_frame_sizes_(true), |
| 135 enable_compression_(compression_default_), | 130 enable_compression_(compression_default_), |
| 136 visitor_(NULL), | 131 visitor_(NULL), |
| 137 display_protocol_("SPDY") { | 132 display_protocol_("SPDY"), |
| 133 spdy_version_(version), | |
| 134 syn_frame_processed_(false), | |
| 135 probable_http_response_(false) { | |
| 136 DCHECK_GE(3, version); | |
| 137 DCHECK_LE(2, version); | |
| 138 } | 138 } |
| 139 | 139 |
| 140 SpdyFramer::~SpdyFramer() { | 140 SpdyFramer::~SpdyFramer() { |
| 141 if (header_compressor_.get()) { | 141 if (header_compressor_.get()) { |
| 142 deflateEnd(header_compressor_.get()); | 142 deflateEnd(header_compressor_.get()); |
| 143 } | 143 } |
| 144 if (header_decompressor_.get()) { | 144 if (header_decompressor_.get()) { |
| 145 inflateEnd(header_decompressor_.get()); | 145 inflateEnd(header_decompressor_.get()); |
| 146 } | 146 } |
| 147 CleanupStreamCompressorsAndDecompressors(); | 147 CleanupStreamCompressorsAndDecompressors(); |
| 148 delete [] current_frame_buffer_; | 148 delete [] current_frame_buffer_; |
| 149 } | 149 } |
| 150 | 150 |
| 151 void SpdyFramer::Reset() { | 151 void SpdyFramer::Reset() { |
| 152 state_ = SPDY_RESET; | 152 state_ = SPDY_RESET; |
| 153 error_code_ = SPDY_NO_ERROR; | 153 error_code_ = SPDY_NO_ERROR; |
| 154 remaining_data_ = 0; | 154 remaining_data_ = 0; |
| 155 remaining_control_payload_ = 0; | 155 remaining_control_payload_ = 0; |
| 156 remaining_control_header_ = 0; | 156 remaining_control_header_ = 0; |
| 157 current_frame_len_ = 0; | 157 current_frame_len_ = 0; |
| 158 settings_scratch_.Reset(); | |
| 158 // TODO(hkhalil): Remove once initial_size == kControlFrameBufferInitialSize. | 159 // TODO(hkhalil): Remove once initial_size == kControlFrameBufferInitialSize. |
| 159 size_t initial_size = kControlFrameBufferInitialSize; | 160 size_t initial_size = kControlFrameBufferInitialSize; |
| 160 if (!enable_compression_) { | 161 if (!enable_compression_) { |
| 161 initial_size = kUncompressedControlFrameBufferInitialSize; | 162 initial_size = kUncompressedControlFrameBufferInitialSize; |
| 162 } | 163 } |
| 163 if (current_frame_capacity_ != initial_size) { | 164 if (current_frame_capacity_ != initial_size) { |
| 164 delete [] current_frame_buffer_; | 165 delete [] current_frame_buffer_; |
| 165 current_frame_buffer_ = 0; | 166 current_frame_buffer_ = 0; |
| 166 current_frame_capacity_ = 0; | 167 current_frame_capacity_ = 0; |
| 167 ExpandControlFrameBuffer(initial_size); | 168 ExpandControlFrameBuffer(initial_size); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 185 case SPDY_IGNORE_REMAINING_PAYLOAD: | 186 case SPDY_IGNORE_REMAINING_PAYLOAD: |
| 186 return "IGNORE_REMAINING_PAYLOAD"; | 187 return "IGNORE_REMAINING_PAYLOAD"; |
| 187 case SPDY_FORWARD_STREAM_FRAME: | 188 case SPDY_FORWARD_STREAM_FRAME: |
| 188 return "FORWARD_STREAM_FRAME"; | 189 return "FORWARD_STREAM_FRAME"; |
| 189 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: | 190 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: |
| 190 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; | 191 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; |
| 191 case SPDY_CONTROL_FRAME_HEADER_BLOCK: | 192 case SPDY_CONTROL_FRAME_HEADER_BLOCK: |
| 192 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; | 193 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; |
| 193 case SPDY_CREDENTIAL_FRAME_PAYLOAD: | 194 case SPDY_CREDENTIAL_FRAME_PAYLOAD: |
| 194 return "SPDY_CREDENTIAL_FRAME_PAYLOAD"; | 195 return "SPDY_CREDENTIAL_FRAME_PAYLOAD"; |
| 196 case SPDY_SETTINGS_FRAME_PAYLOAD: | |
| 197 return "SPDY_SETTINGS_FRAME_PAYLOAD"; | |
| 195 } | 198 } |
| 196 return "UNKNOWN_STATE"; | 199 return "UNKNOWN_STATE"; |
| 197 } | 200 } |
| 198 | 201 |
| 199 void SpdyFramer::set_error(SpdyError error) { | 202 void SpdyFramer::set_error(SpdyError error) { |
| 200 DCHECK(visitor_); | 203 DCHECK(visitor_); |
| 201 error_code_ = error; | 204 error_code_ = error; |
| 202 CHANGE_STATE(SPDY_ERROR); | 205 CHANGE_STATE(SPDY_ERROR); |
| 203 visitor_->OnError(this); | 206 visitor_->OnError(this); |
| 204 } | 207 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 continue; | 300 continue; |
| 298 } | 301 } |
| 299 | 302 |
| 300 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { | 303 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { |
| 301 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY, | 304 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY, |
| 302 // HEADERS) take a different path through the state machine - they | 305 // HEADERS) take a different path through the state machine - they |
| 303 // will go: | 306 // will go: |
| 304 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK | 307 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK |
| 305 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK | 308 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK |
| 306 // | 309 // |
| 310 // SETTINGS frames take a slightly modified route: | |
| 311 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK | |
| 312 // 2. SPDY_SETTINGS_FRAME_PAYLOAD | |
| 313 // | |
| 307 // All other control frames will use the alternate route directly to | 314 // All other control frames will use the alternate route directly to |
| 308 // SPDY_CONTROL_FRAME_PAYLOAD | 315 // SPDY_CONTROL_FRAME_PAYLOAD |
| 309 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); | 316 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); |
| 310 len -= bytes_read; | 317 len -= bytes_read; |
| 311 data += bytes_read; | 318 data += bytes_read; |
| 312 continue; | 319 continue; |
| 313 } | 320 } |
| 314 | 321 |
| 322 case SPDY_SETTINGS_FRAME_PAYLOAD: { | |
| 323 int bytes_read = ProcessSettingsFramePayload(data, len); | |
| 324 len -= bytes_read; | |
| 325 data += bytes_read; | |
| 326 continue; | |
| 327 } | |
| 328 | |
| 315 case SPDY_CONTROL_FRAME_HEADER_BLOCK: { | 329 case SPDY_CONTROL_FRAME_HEADER_BLOCK: { |
| 316 int bytes_read = ProcessControlFrameHeaderBlock(data, len); | 330 int bytes_read = ProcessControlFrameHeaderBlock(data, len); |
| 317 len -= bytes_read; | 331 len -= bytes_read; |
| 318 data += bytes_read; | 332 data += bytes_read; |
| 319 continue; | 333 continue; |
| 320 } | 334 } |
| 321 | 335 |
| 322 case SPDY_CREDENTIAL_FRAME_PAYLOAD: { | 336 case SPDY_CREDENTIAL_FRAME_PAYLOAD: { |
| 323 size_t bytes_read = ProcessCredentialFramePayload(data, len); | 337 size_t bytes_read = ProcessCredentialFramePayload(data, len); |
| 324 len -= bytes_read; | 338 len -= bytes_read; |
| 325 data += bytes_read; | 339 data += bytes_read; |
| 326 continue; | |
| 327 } | 340 } |
| 328 | 341 |
| 329 case SPDY_CONTROL_FRAME_PAYLOAD: { | 342 case SPDY_CONTROL_FRAME_PAYLOAD: { |
| 330 size_t bytes_read = ProcessControlFramePayload(data, len); | 343 size_t bytes_read = ProcessControlFramePayload(data, len); |
| 331 len -= bytes_read; | 344 len -= bytes_read; |
| 332 data += bytes_read; | 345 data += bytes_read; |
| 333 } | 346 } |
| 334 // intentional fallthrough | 347 // intentional fallthrough |
| 335 case SPDY_IGNORE_REMAINING_PAYLOAD: | 348 case SPDY_IGNORE_REMAINING_PAYLOAD: |
| 336 // control frame has too-large payload | 349 // control frame has too-large payload |
| 337 // intentional fallthrough | 350 // intentional fallthrough |
| 338 case SPDY_FORWARD_STREAM_FRAME: { | 351 case SPDY_FORWARD_STREAM_FRAME: { |
| 339 size_t bytes_read = ProcessDataFramePayload(data, len); | 352 size_t bytes_read = ProcessDataFramePayload(data, len); |
| 340 len -= bytes_read; | 353 len -= bytes_read; |
| 341 data += bytes_read; | 354 data += bytes_read; |
| 342 continue; | 355 continue; |
| 343 } | 356 } |
| 344 default: | 357 default: |
| 358 LOG(ERROR) << "Invalid value for " << display_protocol_ | |
| 359 << " framer state: " << state_; | |
| 345 // This ensures that we don't infinite-loop if state_ gets an | 360 // This ensures that we don't infinite-loop if state_ gets an |
| 346 // invalid value somehow, such as due to a SpdyFramer getting deleted | 361 // invalid value somehow, such as due to a SpdyFramer getting deleted |
| 347 // from a callback it calls. | 362 // from a callback it calls. |
| 348 goto bottom; | 363 goto bottom; |
| 349 } | 364 } |
| 350 } | 365 } |
| 351 bottom: | 366 bottom: |
| 352 return original_len - len; | 367 return original_len - len; |
| 353 } | 368 } |
| 354 | 369 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 376 visitor_->OnDataFrameHeader(&data_frame); | 391 visitor_->OnDataFrameHeader(&data_frame); |
| 377 if (current_frame.flags() & DATA_FLAG_FIN) { | 392 if (current_frame.flags() & DATA_FLAG_FIN) { |
| 378 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0); | 393 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0); |
| 379 } | 394 } |
| 380 CHANGE_STATE(SPDY_AUTO_RESET); | 395 CHANGE_STATE(SPDY_AUTO_RESET); |
| 381 } else { | 396 } else { |
| 382 remaining_data_ = current_frame.length(); | 397 remaining_data_ = current_frame.length(); |
| 383 | 398 |
| 384 // This is just a sanity check for help debugging early frame errors. | 399 // This is just a sanity check for help debugging early frame errors. |
| 385 if (remaining_data_ > 1000000u) { | 400 if (remaining_data_ > 1000000u) { |
| 386 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_ | 401 // The strncmp for 5 is safe because we only hit this point if we |
| 387 << " session is likely corrupt."; | 402 // have SpdyFrame::kHeaderSize (8) bytes |
| 403 if (!syn_frame_processed_ && | |
| 404 strncmp(current_frame_buffer_, "HTTP/", 5) == 0) { | |
| 405 LOG(WARNING) << "Unexpected HTTP response to spdy request"; | |
| 406 probable_http_response_ = true; | |
| 407 } else { | |
| 408 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_ | |
| 409 << " session is likely corrupt."; | |
| 410 } | |
| 388 } | 411 } |
| 389 | 412 |
| 390 // if we're here, then we have the common header all received. | 413 // if we're here, then we have the common header all received. |
| 391 if (!current_frame.is_control_frame()) { | 414 if (!current_frame.is_control_frame()) { |
| 392 SpdyDataFrame data_frame(current_frame_buffer_, false); | 415 SpdyDataFrame data_frame(current_frame_buffer_, false); |
| 393 visitor_->OnDataFrameHeader(&data_frame); | 416 visitor_->OnDataFrameHeader(&data_frame); |
| 394 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); | 417 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); |
| 395 } else { | 418 } else { |
| 396 ProcessControlFrameHeader(); | 419 ProcessControlFrameHeader(); |
| 397 } | 420 } |
| 398 } | 421 } |
| 399 return original_len - len; | 422 return original_len - len; |
| 400 } | 423 } |
| 401 | 424 |
| 402 void SpdyFramer::ProcessControlFrameHeader() { | 425 void SpdyFramer::ProcessControlFrameHeader() { |
| 403 DCHECK_EQ(SPDY_NO_ERROR, error_code_); | 426 DCHECK_EQ(SPDY_NO_ERROR, error_code_); |
| 404 DCHECK_LE(static_cast<size_t>(SpdyFrame::kHeaderSize), current_frame_len_); | 427 DCHECK_LE(static_cast<size_t>(SpdyFrame::kHeaderSize), current_frame_len_); |
| 405 SpdyControlFrame current_control_frame(current_frame_buffer_, false); | 428 SpdyControlFrame current_control_frame(current_frame_buffer_, false); |
| 406 | 429 |
| 407 // We check version before we check validity: version can never be 'invalid', | 430 // We check version before we check validity: version can never be 'invalid', |
| 408 // it can only be unsupported. | 431 // it can only be unsupported. |
| 409 if (current_control_frame.version() != spdy_version_) { | 432 if (current_control_frame.version() != spdy_version_) { |
| 433 DLOG(INFO) << "Unsupported SPDY version " << current_control_frame.version() | |
| 434 << " (expected " << spdy_version_ << ")"; | |
| 410 set_error(SPDY_UNSUPPORTED_VERSION); | 435 set_error(SPDY_UNSUPPORTED_VERSION); |
| 411 return; | 436 return; |
| 412 } | 437 } |
| 413 | 438 |
| 414 // Next up, check to see if we have valid data. This should be after version | 439 // Next up, check to see if we have valid data. This should be after version |
| 415 // checking (otherwise if the the type were out of bounds due to a version | 440 // checking (otherwise if the the type were out of bounds due to a version |
| 416 // upgrade we would misclassify the error) and before checking the type | 441 // upgrade we would misclassify the error) and before checking the type |
| 417 // (type can definitely be out of bounds) | 442 // (type can definitely be out of bounds) |
| 418 if (!current_control_frame.AppearsToBeAValidControlFrame()) { | 443 if (!current_control_frame.AppearsToBeAValidControlFrame()) { |
| 419 set_error(SPDY_INVALID_CONTROL_FRAME); | 444 set_error(SPDY_INVALID_CONTROL_FRAME); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 438 if (current_control_frame.length() < | 463 if (current_control_frame.length() < |
| 439 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize) | 464 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize) |
| 440 set_error(SPDY_INVALID_CONTROL_FRAME); | 465 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 441 break; | 466 break; |
| 442 case RST_STREAM: | 467 case RST_STREAM: |
| 443 if (current_control_frame.length() != | 468 if (current_control_frame.length() != |
| 444 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize) | 469 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize) |
| 445 set_error(SPDY_INVALID_CONTROL_FRAME); | 470 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 446 break; | 471 break; |
| 447 case SETTINGS: | 472 case SETTINGS: |
| 473 // Make sure that we have an integral number of 8-byte key/value pairs, | |
| 474 // plus a 4-byte length field. | |
| 448 if (current_control_frame.length() < | 475 if (current_control_frame.length() < |
| 449 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize) | 476 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize || |
| 477 (current_control_frame.length() % 8 != 4)) { | |
| 478 DLOG(WARNING) << "Invalid length for SETTINGS frame: " | |
| 479 << current_control_frame.length(); | |
| 450 set_error(SPDY_INVALID_CONTROL_FRAME); | 480 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 481 } | |
| 451 break; | 482 break; |
| 452 case GOAWAY: | 483 case GOAWAY: |
| 453 if (current_control_frame.length() != | 484 if (current_control_frame.length() != |
| 454 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize) | 485 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize) |
| 455 set_error(SPDY_INVALID_CONTROL_FRAME); | 486 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 456 break; | 487 break; |
| 457 case HEADERS: | 488 case HEADERS: |
| 458 if (current_control_frame.length() < | 489 if (current_control_frame.length() < |
| 459 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize) | 490 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize) |
| 460 set_error(SPDY_INVALID_CONTROL_FRAME); | 491 set_error(SPDY_INVALID_CONTROL_FRAME); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 478 default: | 509 default: |
| 479 LOG(WARNING) << "Valid " << display_protocol_ | 510 LOG(WARNING) << "Valid " << display_protocol_ |
| 480 << " control frame with unhandled type: " | 511 << " control frame with unhandled type: " |
| 481 << current_control_frame.type(); | 512 << current_control_frame.type(); |
| 482 DCHECK(false); | 513 DCHECK(false); |
| 483 set_error(SPDY_INVALID_CONTROL_FRAME); | 514 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 484 break; | 515 break; |
| 485 } | 516 } |
| 486 } | 517 } |
| 487 | 518 |
| 488 // We only support version 1 of this protocol. | |
| 489 if (current_control_frame.version() != spdy_version_) { | |
| 490 set_error(SPDY_UNSUPPORTED_VERSION); | |
| 491 return; | |
| 492 } | |
| 493 | |
| 494 remaining_control_payload_ = current_control_frame.length(); | 519 remaining_control_payload_ = current_control_frame.length(); |
| 495 if (remaining_control_payload_ > | 520 if (remaining_control_payload_ > |
| 496 kControlFrameBufferMaxSize - SpdyFrame::kHeaderSize) { | 521 kControlFrameBufferMaxSize - SpdyFrame::kHeaderSize) { |
| 497 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 522 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
| 498 return; | 523 return; |
| 499 } | 524 } |
| 500 | 525 |
| 501 if (current_control_frame.type() == CREDENTIAL) { | 526 if (current_control_frame.type() == CREDENTIAL) { |
| 502 visitor_->OnControl(¤t_control_frame); | 527 visitor_->OnControl(¤t_control_frame); |
| 503 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD); | 528 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD); |
| 504 return; | 529 return; |
| 505 } | 530 } |
| 506 | 531 |
| 507 int32 frame_size_without_header_block; | 532 // Determine the frame size without variable-length data. |
| 533 int32 frame_size_without_variable_data; | |
| 508 switch (current_control_frame.type()) { | 534 switch (current_control_frame.type()) { |
| 509 case SYN_STREAM: | 535 case SYN_STREAM: |
| 510 frame_size_without_header_block = SpdySynStreamControlFrame::size(); | 536 syn_frame_processed_ = true; |
| 537 frame_size_without_variable_data = SpdySynStreamControlFrame::size(); | |
| 511 break; | 538 break; |
| 512 case SYN_REPLY: | 539 case SYN_REPLY: |
| 513 frame_size_without_header_block = SpdySynReplyControlFrame::size(); | 540 syn_frame_processed_ = true; |
| 541 frame_size_without_variable_data = SpdySynReplyControlFrame::size(); | |
| 542 // SPDY 2 had two bytes of unused space preceeding payload. | |
| 543 if (spdy_version_ < 3) { | |
| 544 frame_size_without_variable_data += 2; | |
| 545 } | |
| 514 break; | 546 break; |
| 515 case HEADERS: | 547 case HEADERS: |
| 516 frame_size_without_header_block = SpdyHeadersControlFrame::size(); | 548 frame_size_without_variable_data = SpdyHeadersControlFrame::size(); |
| 549 // SPDY 2 had two bytes of unused space preceeding payload. | |
| 550 if (spdy_version_ < 3) { | |
| 551 frame_size_without_variable_data += 2; | |
| 552 } | |
| 553 break; | |
| 554 case SETTINGS: | |
| 555 frame_size_without_variable_data = SpdySettingsControlFrame::size(); | |
| 517 break; | 556 break; |
| 518 default: | 557 default: |
| 519 frame_size_without_header_block = -1; | 558 frame_size_without_variable_data = -1; |
| 520 LOG_IF(DFATAL, remaining_control_payload_ + SpdyFrame::kHeaderSize > | |
| 521 current_frame_capacity_) | |
| 522 << display_protocol_ | |
| 523 << " control frame buffer too small for fixed-length frame."; | |
| 524 ExpandControlFrameBuffer(remaining_control_payload_); | |
| 525 break; | 559 break; |
| 526 } | 560 } |
| 527 | 561 |
| 528 if (frame_size_without_header_block > 0) { | 562 if (frame_size_without_variable_data == -1) { |
| 563 LOG_IF(ERROR, remaining_control_payload_ + SpdyFrame::kHeaderSize > | |
| 564 current_frame_capacity_) | |
| 565 << display_protocol_ | |
| 566 << " control frame buffer too small for fixed-length frame."; | |
| 567 // TODO(hkhalil): Remove ExpandControlFrameBuffer(). | |
| 568 ExpandControlFrameBuffer(remaining_control_payload_); | |
| 569 } | |
| 570 if (frame_size_without_variable_data > 0) { | |
| 529 // We have a control frame with a header block. We need to parse the | 571 // We have a control frame with a header block. We need to parse the |
| 530 // remainder of the control frame's header before we can parse the header | 572 // remainder of the control frame's header before we can parse the header |
| 531 // block. The start of the header block varies with the control type. | 573 // block. The start of the header block varies with the control type. |
| 532 DCHECK_GE(static_cast<uint32>(frame_size_without_header_block), | 574 DCHECK_GE(frame_size_without_variable_data, |
| 533 current_frame_len_); | 575 static_cast<int32>(current_frame_len_)); |
| 534 remaining_control_header_ = frame_size_without_header_block - | 576 remaining_control_header_ = frame_size_without_variable_data - |
| 535 current_frame_len_; | 577 current_frame_len_; |
| 536 remaining_control_payload_ += SpdyFrame::kHeaderSize - | 578 remaining_control_payload_ += SpdyFrame::kHeaderSize - |
| 537 frame_size_without_header_block; | 579 frame_size_without_variable_data; |
| 538 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); | 580 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); |
| 539 return; | 581 return; |
| 540 } | 582 } |
| 541 | 583 |
| 542 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); | 584 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); |
| 543 } | 585 } |
| 544 | 586 |
| 545 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, | 587 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, |
| 546 size_t max_bytes) { | 588 size_t max_bytes) { |
| 547 size_t bytes_to_read = std::min(*len, max_bytes); | 589 size_t bytes_to_read = std::min(*len, max_bytes); |
| 548 DCHECK_GE(current_frame_capacity_, current_frame_len_ + bytes_to_read); | 590 DCHECK_GE(current_frame_capacity_, current_frame_len_ + bytes_to_read); |
| 549 memcpy(¤t_frame_buffer_[current_frame_len_], *data, bytes_to_read); | 591 memcpy(¤t_frame_buffer_[current_frame_len_], *data, bytes_to_read); |
| 550 current_frame_len_ += bytes_to_read; | 592 current_frame_len_ += bytes_to_read; |
| 551 *data += bytes_to_read; | 593 *data += bytes_to_read; |
| 552 *len -= bytes_to_read; | 594 *len -= bytes_to_read; |
| 553 return bytes_to_read; | 595 return bytes_to_read; |
| 554 } | 596 } |
| 555 | 597 |
| 598 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock* headers) const { | |
| 599 const size_t num_name_value_pairs_size | |
| 600 = (spdy_version_ < 3) ? sizeof(uint16) : sizeof(uint32); | |
| 601 const size_t length_of_name_size = num_name_value_pairs_size; | |
| 602 const size_t length_of_value_size = num_name_value_pairs_size; | |
| 603 | |
| 604 size_t total_length = num_name_value_pairs_size; | |
| 605 for (SpdyHeaderBlock::const_iterator it = headers->begin(); | |
| 606 it != headers->end(); | |
| 607 ++it) { | |
| 608 // We add space for the length of the name and the length of the value as | |
| 609 // well as the length of the name and the length of the value. | |
| 610 total_length += length_of_name_size + it->first.size() + | |
| 611 length_of_value_size + it->second.size(); | |
| 612 } | |
| 613 return total_length; | |
| 614 } | |
| 615 | |
| 616 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, | |
| 617 const SpdyHeaderBlock* headers) const { | |
| 618 if (spdy_version_ < 3) { | |
| 619 frame->WriteUInt16(headers->size()); // Number of headers. | |
| 620 } else { | |
| 621 frame->WriteUInt32(headers->size()); // Number of headers. | |
| 622 } | |
| 623 SpdyHeaderBlock::const_iterator it; | |
| 624 for (it = headers->begin(); it != headers->end(); ++it) { | |
| 625 bool wrote_header; | |
| 626 if (spdy_version_ < 3) { | |
| 627 wrote_header = frame->WriteString(it->first); | |
| 628 wrote_header &= frame->WriteString(it->second); | |
| 629 } else { | |
| 630 wrote_header = frame->WriteStringPiece32(it->first); | |
| 631 wrote_header &= frame->WriteStringPiece32(it->second); | |
| 632 } | |
| 633 DCHECK(wrote_header); | |
| 634 } | |
| 635 } | |
| 636 | |
| 637 | |
| 556 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, | 638 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, |
| 557 size_t len) { | 639 size_t len) { |
| 558 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); | 640 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); |
| 559 DCHECK_GT(remaining_control_header_, 0u); | 641 DCHECK_GT(remaining_control_header_, 0u); |
| 560 size_t original_len = len; | 642 size_t original_len = len; |
| 561 | 643 |
| 562 if (remaining_control_header_) { | 644 if (remaining_control_header_) { |
| 563 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, | 645 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, |
| 564 remaining_control_header_); | 646 remaining_control_header_); |
| 565 remaining_control_header_ -= bytes_read; | 647 remaining_control_header_ -= bytes_read; |
| 566 if (remaining_control_header_ == 0) { | 648 if (remaining_control_header_ == 0) { |
| 567 SpdyControlFrame control_frame(current_frame_buffer_, false); | 649 SpdyControlFrame control_frame(current_frame_buffer_, false); |
| 568 DCHECK(control_frame.type() == SYN_STREAM || | 650 DCHECK(control_frame.type() == SYN_STREAM || |
| 569 control_frame.type() == SYN_REPLY || | 651 control_frame.type() == SYN_REPLY || |
| 570 control_frame.type() == HEADERS); | 652 control_frame.type() == HEADERS || |
| 653 control_frame.type() == SETTINGS); | |
| 571 visitor_->OnControl(&control_frame); | 654 visitor_->OnControl(&control_frame); |
| 572 | 655 |
| 573 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | 656 if (control_frame.type() == SETTINGS) { |
| 657 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); | |
| 658 } else { | |
| 659 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | |
| 660 } | |
| 574 } | 661 } |
| 575 } | 662 } |
| 576 return original_len - len; | 663 return original_len - len; |
| 577 } | 664 } |
| 578 | 665 |
| 579 // Does not buffer the control payload. Instead, either passes directly to the | 666 // Does not buffer the control payload. Instead, either passes directly to the |
| 580 // visitor or decompresses and then passes directly to the visitor, via | 667 // visitor or decompresses and then passes directly to the visitor, via |
| 581 // IncrementallyDeliverControlFrameHeaderData() or | 668 // IncrementallyDeliverControlFrameHeaderData() or |
| 582 // IncrementallyDecompressControlFrameHeaderData() respectively. | 669 // IncrementallyDecompressControlFrameHeaderData() respectively. |
| 583 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, | 670 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 618 | 705 |
| 619 // Handle error. | 706 // Handle error. |
| 620 if (!processed_successfully) { | 707 if (!processed_successfully) { |
| 621 return data_len; | 708 return data_len; |
| 622 } | 709 } |
| 623 | 710 |
| 624 // Return amount processed. | 711 // Return amount processed. |
| 625 return process_bytes; | 712 return process_bytes; |
| 626 } | 713 } |
| 627 | 714 |
| 715 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, | |
| 716 size_t data_len) { | |
| 717 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); | |
| 718 SpdyControlFrame control_frame(current_frame_buffer_, false); | |
| 719 DCHECK_EQ(control_frame.type(), SETTINGS); | |
| 720 size_t unprocessed_bytes = std::min(data_len, remaining_control_payload_); | |
| 721 size_t processed_bytes = 0; | |
| 722 DCHECK_GT(unprocessed_bytes, 0u); | |
| 723 | |
| 724 // Loop over our incoming data. | |
| 725 while (unprocessed_bytes > 0) { | |
| 726 // Process up to one setting at a time. | |
| 727 size_t processing = std::min( | |
| 728 unprocessed_bytes, | |
| 729 static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); | |
| 730 | |
| 731 // Check if we have a complete setting in our input. | |
| 732 if (processing == 8) { | |
| 733 // Parse the setting directly out of the input without buffering. | |
| 734 if (!ProcessSetting(data + processed_bytes)) { | |
| 735 set_error(SPDY_INVALID_CONTROL_FRAME); | |
| 736 return processed_bytes; | |
| 737 } | |
| 738 } else { | |
| 739 // Continue updating settings_scratch_.setting_buf. | |
| 740 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len, | |
| 741 data + processed_bytes, | |
| 742 processing); | |
| 743 settings_scratch_.setting_buf_len += processing; | |
| 744 | |
| 745 // Check if we have a complete setting buffered. | |
| 746 if (settings_scratch_.setting_buf_len == 8) { | |
| 747 if (!ProcessSetting(settings_scratch_.setting_buf)) { | |
| 748 set_error(SPDY_INVALID_CONTROL_FRAME); | |
| 749 return processed_bytes; | |
| 750 } | |
| 751 // Reset settings_scratch_.setting_buf for our next setting. | |
| 752 settings_scratch_.setting_buf_len = 0; | |
| 753 } | |
| 754 } | |
| 755 | |
| 756 // Iterate. | |
| 757 unprocessed_bytes -= processing; | |
| 758 processed_bytes += processing; | |
| 759 } | |
| 760 | |
| 761 // Check if we're done handling this SETTINGS frame. | |
| 762 remaining_control_payload_ -= processed_bytes; | |
| 763 if (remaining_control_payload_ == 0) { | |
| 764 CHANGE_STATE(SPDY_AUTO_RESET); | |
| 765 } | |
| 766 | |
| 767 return processed_bytes; | |
| 768 } | |
| 769 | |
| 770 bool SpdyFramer::ProcessSetting(const char* data) { | |
| 771 // Extract fields. | |
| 772 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. | |
| 773 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data)); | |
| 774 SettingsFlagsAndId id_and_flags = | |
| 775 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire); | |
| 776 uint8 flags = id_and_flags.flags(); | |
| 777 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); | |
| 778 | |
| 779 // Validate id. | |
| 780 switch (id_and_flags.id()) { | |
| 781 case SETTINGS_UPLOAD_BANDWIDTH: | |
| 782 case SETTINGS_DOWNLOAD_BANDWIDTH: | |
| 783 case SETTINGS_ROUND_TRIP_TIME: | |
| 784 case SETTINGS_MAX_CONCURRENT_STREAMS: | |
| 785 case SETTINGS_CURRENT_CWND: | |
| 786 case SETTINGS_DOWNLOAD_RETRANS_RATE: | |
| 787 case SETTINGS_INITIAL_WINDOW_SIZE: | |
| 788 // Valid values. | |
| 789 break; | |
| 790 default: | |
| 791 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id(); | |
| 792 return false; | |
| 793 } | |
| 794 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id()); | |
| 795 | |
| 796 // Detect duplciates. | |
| 797 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) { | |
| 798 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id | |
| 799 << " in " << display_protocol_ << " SETTINGS frame " | |
| 800 << "(last settikng id was " | |
| 801 << settings_scratch_.last_setting_id << ")."; | |
| 802 return false; | |
| 803 } | |
| 804 settings_scratch_.last_setting_id = id; | |
| 805 | |
| 806 // Validate flags. | |
| 807 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED; | |
| 808 if ((flags & ~(kFlagsMask)) != 0) { | |
| 809 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": " | |
| 810 << flags; | |
| 811 return false; | |
| 812 } | |
| 813 | |
| 814 // Validation succeeded. Pass on to visitor. | |
| 815 visitor_->OnSetting(id, flags, value); | |
| 816 return true; | |
| 817 } | |
| 818 | |
| 628 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { | 819 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { |
| 629 size_t original_len = len; | 820 size_t original_len = len; |
| 630 if (remaining_control_payload_) { | 821 if (remaining_control_payload_) { |
| 631 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, | 822 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, |
| 632 remaining_control_payload_); | 823 remaining_control_payload_); |
| 633 remaining_control_payload_ -= bytes_read; | 824 remaining_control_payload_ -= bytes_read; |
| 634 remaining_data_ -= bytes_read; | 825 remaining_data_ -= bytes_read; |
| 635 if (remaining_control_payload_ == 0) { | 826 if (remaining_control_payload_ == 0) { |
| 636 SpdyControlFrame control_frame(current_frame_buffer_, false); | 827 SpdyControlFrame control_frame(current_frame_buffer_, false); |
| 637 DCHECK(!control_frame.has_header_block()); | 828 DCHECK(!control_frame.has_header_block()); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 722 DCHECK_LE(alloc_size, kControlFrameBufferMaxSize); | 913 DCHECK_LE(alloc_size, kControlFrameBufferMaxSize); |
| 723 if (alloc_size <= current_frame_capacity_) | 914 if (alloc_size <= current_frame_capacity_) |
| 724 return; | 915 return; |
| 725 char* new_buffer = new char[alloc_size]; | 916 char* new_buffer = new char[alloc_size]; |
| 726 memcpy(new_buffer, current_frame_buffer_, current_frame_len_); | 917 memcpy(new_buffer, current_frame_buffer_, current_frame_len_); |
| 727 delete [] current_frame_buffer_; | 918 delete [] current_frame_buffer_; |
| 728 current_frame_capacity_ = alloc_size; | 919 current_frame_capacity_ = alloc_size; |
| 729 current_frame_buffer_ = new_buffer; | 920 current_frame_buffer_ = new_buffer; |
| 730 } | 921 } |
| 731 | 922 |
| 732 /* static */ | |
| 733 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, | 923 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, |
| 734 size_t header_length, | 924 size_t header_length, |
| 735 SpdyHeaderBlock* block) { | 925 SpdyHeaderBlock* block) { |
| 736 SpdyFrameBuilder builder(header_data, header_length); | 926 SpdyFrameReader reader(header_data, header_length); |
| 737 void* iter = NULL; | 927 |
| 738 uint16 num_headers; | 928 // Read number of headers. |
| 739 if (builder.ReadUInt16(&iter, &num_headers)) { | 929 uint32 num_headers; |
| 740 for (int index = 0; index < num_headers; ++index) { | 930 if (spdy_version_ < 3) { |
| 741 std::string name; | 931 uint16 temp; |
| 742 std::string value; | 932 if (!reader.ReadUInt16(&temp)) { |
| 743 if (!builder.ReadString(&iter, &name)) | 933 DLOG(INFO) << "Unable to read number of headers."; |
| 744 return false; | 934 return false; |
| 745 if (!builder.ReadString(&iter, &value)) | |
| 746 return false; | |
| 747 if (block->find(name) == block->end()) { | |
| 748 (*block)[name] = value; | |
| 749 } else { | |
| 750 return false; | |
| 751 } | |
| 752 } | 935 } |
| 753 return true; | 936 num_headers = temp; |
| 754 } | 937 } else { |
| 755 return false; | 938 if (!reader.ReadUInt32(&num_headers)) { |
| 756 } | 939 DLOG(INFO) << "Unable to read number of headers."; |
| 757 | 940 return false; |
| 758 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame, | 941 } |
| 759 SpdyHeaderBlock* block) { | |
| 760 SpdyControlFrame control_frame(frame->data(), false); | |
| 761 uint32 type = control_frame.type(); | |
| 762 if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS) | |
| 763 return false; | |
| 764 | |
| 765 // Find the header data within the control frame. | |
| 766 scoped_ptr<SpdyFrame> decompressed_frame(DecompressFrame(*frame)); | |
| 767 if (!decompressed_frame.get()) | |
| 768 return false; | |
| 769 | |
| 770 const char *header_data = NULL; | |
| 771 int header_length = 0; | |
| 772 | |
| 773 switch (type) { | |
| 774 case SYN_STREAM: | |
| 775 { | |
| 776 SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false); | |
| 777 header_data = syn_frame.header_block(); | |
| 778 header_length = syn_frame.header_block_len(); | |
| 779 } | |
| 780 break; | |
| 781 case SYN_REPLY: | |
| 782 { | |
| 783 SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false); | |
| 784 header_data = syn_frame.header_block(); | |
| 785 header_length = syn_frame.header_block_len(); | |
| 786 } | |
| 787 break; | |
| 788 case HEADERS: | |
| 789 { | |
| 790 SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false); | |
| 791 header_data = header_frame.header_block(); | |
| 792 header_length = header_frame.header_block_len(); | |
| 793 } | |
| 794 break; | |
| 795 } | 942 } |
| 796 | 943 |
| 797 SpdyFrameBuilder builder(header_data, header_length); | 944 // Read each header. |
| 798 void* iter = NULL; | 945 for (uint32 index = 0; index < num_headers; ++index) { |
| 799 uint16 num_headers; | 946 base::StringPiece temp; |
| 800 if (builder.ReadUInt16(&iter, &num_headers)) { | 947 |
| 801 int index; | 948 // Read header name. |
| 802 for (index = 0; index < num_headers; ++index) { | 949 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) |
| 803 std::string name; | 950 : !reader.ReadStringPiece32(&temp)) { |
| 804 std::string value; | 951 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of " |
| 805 if (!builder.ReadString(&iter, &name)) | 952 << num_headers << ")."; |
| 806 break; | 953 return false; |
| 807 if (!builder.ReadString(&iter, &value)) | |
| 808 break; | |
| 809 if (!name.size() || !value.size()) | |
| 810 return false; | |
| 811 if (block->find(name) == block->end()) { | |
| 812 (*block)[name] = value; | |
| 813 } else { | |
| 814 return false; | |
| 815 } | |
| 816 } | 954 } |
| 817 return index == num_headers && | 955 std::string name; |
| 818 iter == header_data + header_length; | 956 temp.CopyToString(&name); |
| 957 | |
| 958 // Read header value. | |
| 959 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) | |
| 960 : !reader.ReadStringPiece32(&temp)) { | |
| 961 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of " | |
| 962 << num_headers << ")."; | |
| 963 return false; | |
| 964 } | |
| 965 std::string value; | |
| 966 temp.CopyToString(&value); | |
| 967 | |
| 968 // Ensure no duplicates. | |
| 969 if (block->find(name) != block->end()) { | |
| 970 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of " | |
| 971 << num_headers << ")."; | |
| 972 return false; | |
| 973 } | |
| 974 | |
| 975 // Store header. | |
| 976 (*block)[name] = value; | |
| 819 } | 977 } |
| 820 return false; | 978 return true; |
| 821 } | 979 } |
| 822 | 980 |
| 823 /* static */ | 981 /* static */ |
| 824 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, | 982 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, |
| 825 SpdySettings* settings) { | 983 SpdySettings* settings) { |
| 826 DCHECK_EQ(frame->type(), SETTINGS); | 984 DCHECK_EQ(frame->type(), SETTINGS); |
| 827 DCHECK(settings); | 985 DCHECK(settings); |
| 828 | 986 |
| 829 SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len()); | 987 SpdyFrameReader parser(frame->header_block(), frame->header_block_len()); |
| 830 void* iter = NULL; | |
| 831 for (size_t index = 0; index < frame->num_entries(); ++index) { | 988 for (size_t index = 0; index < frame->num_entries(); ++index) { |
| 832 uint32 id; | 989 uint32 id_and_flags_wire; |
| 833 uint32 value; | 990 uint32 value; |
| 834 if (!parser.ReadUInt32(&iter, &id)) | 991 // SettingsFlagsAndId accepts off-the-wire (network byte order) data, so we |
| 992 // use ReadBytes() instead of ReadUInt32() as the latter calls ntohl(). | |
| 993 if (!parser.ReadBytes(&id_and_flags_wire, 4)) { | |
| 835 return false; | 994 return false; |
| 836 if (!parser.ReadUInt32(&iter, &value)) | 995 } |
| 996 if (!parser.ReadUInt32(&value)) | |
| 837 return false; | 997 return false; |
| 838 settings->insert(settings->end(), std::make_pair(id, value)); | 998 SettingsFlagsAndId id_and_flags = |
| 999 SettingsFlagsAndId::FromWireFormat(frame->version(), id_and_flags_wire); | |
| 1000 settings->insert(settings->end(), std::make_pair(id_and_flags, value)); | |
| 839 } | 1001 } |
| 840 return true; | 1002 return true; |
| 841 } | 1003 } |
| 842 | 1004 |
| 843 /* static */ | 1005 /* static */ |
| 844 bool SpdyFramer::ParseCredentialData(const char* data, size_t len, | 1006 bool SpdyFramer::ParseCredentialData(const char* data, size_t len, |
| 845 SpdyCredential* credential) { | 1007 SpdyCredential* credential) { |
| 846 DCHECK(credential); | 1008 DCHECK(credential); |
| 847 | 1009 |
| 848 void* iter = NULL; | 1010 SpdyFrameReader parser(data, len); |
| 849 SpdyFrameBuilder parser(data, len); | 1011 base::StringPiece temp; |
| 850 if (!parser.ReadUInt16(&iter, &credential->slot)) | 1012 if (!parser.ReadUInt16(&credential->slot)) { |
| 851 return false; | 1013 return false; |
| 1014 } | |
| 852 | 1015 |
| 853 uint32 proof_len; | 1016 if (!parser.ReadStringPiece32(&temp)) { |
| 854 const char* proof_data; | |
| 855 if (!parser.ReadReadLen32PrefixedData(&iter, &proof_data, &proof_len)) | |
| 856 return false; | 1017 return false; |
| 857 credential->proof.assign(proof_data, proof_len); | 1018 } |
| 1019 temp.CopyToString(&credential->proof); | |
| 858 | 1020 |
| 859 while (parser.IteratorHasRoomFor(iter, 1)) { | 1021 while (!parser.IsDoneReading()) { |
| 860 uint32 cert_len; | 1022 if (!parser.ReadStringPiece32(&temp)) { |
| 861 const char* cert_data; | |
| 862 if (!parser.ReadReadLen32PrefixedData(&iter, &cert_data, &cert_len)) | |
| 863 return false; | 1023 return false; |
| 864 credential->certs.push_back(""); | 1024 } |
| 865 credential->certs.back().assign(cert_data, cert_len); | 1025 std::string cert; |
| 1026 temp.CopyToString(&cert); | |
| 1027 credential->certs.push_back(cert); | |
| 866 } | 1028 } |
| 867 return true; | 1029 return true; |
| 868 } | 1030 } |
| 869 | 1031 |
| 870 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( | 1032 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( |
| 871 SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority, | 1033 SpdyStreamId stream_id, |
| 872 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { | 1034 SpdyStreamId associated_stream_id, |
| 873 DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0)); | 1035 SpdyPriority priority, |
| 1036 SpdyControlFlags flags, | |
| 1037 bool compressed, | |
| 1038 const SpdyHeaderBlock* headers) { | |
| 874 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1039 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 875 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); | 1040 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); |
| 876 | 1041 |
| 877 // Find our length. | 1042 // Find our length. |
| 878 size_t expected_frame_size = SpdySynStreamControlFrame::size() + | 1043 size_t expected_frame_size = SpdySynStreamControlFrame::size() + |
| 879 GetSerializedLength(headers); | 1044 GetSerializedLength(headers); |
| 880 | 1045 |
| 881 // Create our FlagsAndLength. | 1046 // Create our FlagsAndLength. |
| 882 FlagsAndLength flags_length = CreateFlagsAndLength( | 1047 FlagsAndLength flags_length = CreateFlagsAndLength( |
| 883 flags, | 1048 flags, |
| 884 expected_frame_size - SpdyFrame::kHeaderSize); | 1049 expected_frame_size - SpdyFrame::kHeaderSize); |
| 885 | 1050 |
| 886 SpdyFrameBuilder frame(expected_frame_size); | 1051 SpdyFrameBuilder frame(expected_frame_size); |
| 887 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1052 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 888 frame.WriteUInt16(SYN_STREAM); | 1053 frame.WriteUInt16(SYN_STREAM); |
| 889 frame.WriteBytes(&flags_length, sizeof(flags_length)); | 1054 frame.WriteBytes(&flags_length, sizeof(flags_length)); |
| 890 frame.WriteUInt32(stream_id); | 1055 frame.WriteUInt32(stream_id); |
| 891 frame.WriteUInt32(associated_stream_id); | 1056 frame.WriteUInt32(associated_stream_id); |
| 892 frame.WriteUInt16(ntohs(priority) << 6); // Priority. | 1057 // Cap as appropriate. |
| 1058 if (priority > GetLowestPriority()) { | |
| 1059 DLOG(ERROR) << "Priority out-of-bounds."; | |
| 1060 priority = GetLowestPriority(); | |
| 1061 } | |
| 1062 // Priority is 2 bits for <spdy3, 3 bits otherwise. | |
| 1063 frame.WriteUInt16(ntohs(priority) << (spdy_version_ < 3 ? 6 : 5)); | |
| 893 WriteHeaderBlock(&frame, headers); | 1064 WriteHeaderBlock(&frame, headers); |
| 894 | 1065 |
| 895 scoped_ptr<SpdySynStreamControlFrame> syn_frame( | 1066 scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
| 896 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); | 1067 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); |
| 897 if (compressed) { | 1068 if (compressed) { |
| 898 return reinterpret_cast<SpdySynStreamControlFrame*>( | 1069 return reinterpret_cast<SpdySynStreamControlFrame*>( |
| 899 CompressControlFrame(*syn_frame.get())); | 1070 CompressControlFrame(*syn_frame.get())); |
| 900 } | 1071 } |
| 901 return syn_frame.release(); | 1072 return syn_frame.release(); |
| 902 } | 1073 } |
| 903 | 1074 |
| 904 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id, | 1075 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( |
| 905 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { | 1076 SpdyStreamId stream_id, |
| 1077 SpdyControlFlags flags, | |
| 1078 bool compressed, | |
| 1079 const SpdyHeaderBlock* headers) { | |
| 906 DCHECK_GT(stream_id, 0u); | 1080 DCHECK_GT(stream_id, 0u); |
| 907 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1081 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 908 | 1082 |
| 909 // Find our length. | 1083 // Find our length. |
| 910 size_t expected_frame_size = SpdySynReplyControlFrame::size() + | 1084 size_t expected_frame_size = SpdySynReplyControlFrame::size() + |
| 911 GetSerializedLength(headers); | 1085 GetSerializedLength(headers); |
| 1086 // In SPDY 2, there were 2 unused bytes before payload. | |
| 1087 if (spdy_version_ < 3) { | |
| 1088 expected_frame_size += 2; | |
| 1089 } | |
| 912 | 1090 |
| 913 // Create our FlagsAndLength. | 1091 // Create our FlagsAndLength. |
| 914 FlagsAndLength flags_length = CreateFlagsAndLength( | 1092 FlagsAndLength flags_length = CreateFlagsAndLength( |
| 915 flags, | 1093 flags, |
| 916 expected_frame_size - SpdyFrame::kHeaderSize); | 1094 expected_frame_size - SpdyFrame::kHeaderSize); |
| 917 | 1095 |
| 918 SpdyFrameBuilder frame(expected_frame_size); | 1096 SpdyFrameBuilder frame(expected_frame_size); |
| 919 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1097 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 920 frame.WriteUInt16(SYN_REPLY); | 1098 frame.WriteUInt16(SYN_REPLY); |
| 921 frame.WriteBytes(&flags_length, sizeof(flags_length)); | 1099 frame.WriteBytes(&flags_length, sizeof(flags_length)); |
| 922 frame.WriteUInt32(stream_id); | 1100 frame.WriteUInt32(stream_id); |
| 923 frame.WriteUInt16(0); // Unused | 1101 if (spdy_version_ < 3) { |
| 1102 frame.WriteUInt16(0); // Unused | |
| 1103 } | |
| 924 WriteHeaderBlock(&frame, headers); | 1104 WriteHeaderBlock(&frame, headers); |
| 925 | 1105 |
| 926 scoped_ptr<SpdySynReplyControlFrame> reply_frame( | 1106 scoped_ptr<SpdySynReplyControlFrame> reply_frame( |
| 927 reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); | 1107 reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); |
| 928 if (compressed) { | 1108 if (compressed) { |
| 929 return reinterpret_cast<SpdySynReplyControlFrame*>( | 1109 return reinterpret_cast<SpdySynReplyControlFrame*>( |
| 930 CompressControlFrame(*reply_frame.get())); | 1110 CompressControlFrame(*reply_frame.get())); |
| 931 } | 1111 } |
| 932 return reply_frame.release(); | 1112 return reply_frame.release(); |
| 933 } | 1113 } |
| 934 | 1114 |
| 935 /* static */ | 1115 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream( |
| 936 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id, | 1116 SpdyStreamId stream_id, |
| 937 SpdyStatusCodes status) { | 1117 SpdyStatusCodes status) const { |
| 938 DCHECK_GT(stream_id, 0u); | 1118 DCHECK_GT(stream_id, 0u); |
| 939 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1119 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 940 DCHECK_NE(status, INVALID); | 1120 DCHECK_NE(status, INVALID); |
| 941 DCHECK_LT(status, NUM_STATUS_CODES); | 1121 DCHECK_LT(status, NUM_STATUS_CODES); |
| 942 | 1122 |
| 943 SpdyFrameBuilder frame(SpdyRstStreamControlFrame::size()); | 1123 SpdyFrameBuilder frame(SpdyRstStreamControlFrame::size()); |
| 944 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1124 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 945 frame.WriteUInt16(RST_STREAM); | 1125 frame.WriteUInt16(RST_STREAM); |
| 946 frame.WriteUInt32(8); | 1126 frame.WriteUInt32(8); |
| 947 frame.WriteUInt32(stream_id); | 1127 frame.WriteUInt32(stream_id); |
| 948 frame.WriteUInt32(status); | 1128 frame.WriteUInt32(status); |
| 949 return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take()); | 1129 return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take()); |
| 950 } | 1130 } |
| 951 | 1131 |
| 952 /* static */ | |
| 953 SpdySettingsControlFrame* SpdyFramer::CreateSettings( | 1132 SpdySettingsControlFrame* SpdyFramer::CreateSettings( |
| 954 const SpdySettings& values) { | 1133 const SpdySettings& values) const { |
| 955 SpdyFrameBuilder frame(SpdySettingsControlFrame::size() + 8 * values.size()); | 1134 SpdyFrameBuilder frame(SpdySettingsControlFrame::size() + 8 * values.size()); |
| 956 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1135 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 957 frame.WriteUInt16(SETTINGS); | 1136 frame.WriteUInt16(SETTINGS); |
| 958 size_t settings_size = | 1137 size_t settings_size = |
| 959 SpdySettingsControlFrame::size() - SpdyFrame::kHeaderSize + | 1138 SpdySettingsControlFrame::size() - SpdyFrame::kHeaderSize + |
| 960 8 * values.size(); | 1139 8 * values.size(); |
| 961 frame.WriteUInt32(settings_size); | 1140 frame.WriteUInt32(settings_size); |
| 962 frame.WriteUInt32(values.size()); | 1141 frame.WriteUInt32(values.size()); |
| 963 SpdySettings::const_iterator it = values.begin(); | 1142 SpdySettings::const_iterator it = values.begin(); |
| 964 while (it != values.end()) { | 1143 while (it != values.end()) { |
| 965 frame.WriteUInt32(it->first.id_); | 1144 uint32 id_and_flags_wire = it->first.GetWireFormat(spdy_version_); |
| 1145 frame.WriteBytes(&id_and_flags_wire, 4); | |
| 966 frame.WriteUInt32(it->second); | 1146 frame.WriteUInt32(it->second); |
| 967 ++it; | 1147 ++it; |
| 968 } | 1148 } |
| 969 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); | 1149 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); |
| 970 } | 1150 } |
| 971 | 1151 |
| 972 /* static */ | 1152 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { |
| 973 SpdyNoOpControlFrame* SpdyFramer::CreateNopFrame() { | |
| 974 SpdyFrameBuilder frame(SpdyNoOpControlFrame::size()); | |
| 975 frame.WriteUInt16(kControlFlagMask | spdy_version_); | |
| 976 frame.WriteUInt16(NOOP); | |
| 977 frame.WriteUInt32(0); | |
| 978 return reinterpret_cast<SpdyNoOpControlFrame*>(frame.take()); | |
| 979 } | |
| 980 | |
| 981 /* static */ | |
| 982 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) { | |
| 983 SpdyFrameBuilder frame(SpdyPingControlFrame::size()); | 1153 SpdyFrameBuilder frame(SpdyPingControlFrame::size()); |
| 984 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1154 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 985 frame.WriteUInt16(PING); | 1155 frame.WriteUInt16(PING); |
| 986 size_t ping_size = SpdyPingControlFrame::size() - SpdyFrame::kHeaderSize; | 1156 size_t ping_size = SpdyPingControlFrame::size() - SpdyFrame::kHeaderSize; |
| 987 frame.WriteUInt32(ping_size); | 1157 frame.WriteUInt32(ping_size); |
| 988 frame.WriteUInt32(unique_id); | 1158 frame.WriteUInt32(unique_id); |
| 989 return reinterpret_cast<SpdyPingControlFrame*>(frame.take()); | 1159 return reinterpret_cast<SpdyPingControlFrame*>(frame.take()); |
| 990 } | 1160 } |
| 991 | 1161 |
| 992 /* static */ | |
| 993 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( | 1162 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( |
| 994 SpdyStreamId last_accepted_stream_id) { | 1163 SpdyStreamId last_accepted_stream_id) const { |
| 995 DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); | 1164 DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); |
| 996 | 1165 |
| 997 SpdyFrameBuilder frame(SpdyGoAwayControlFrame::size()); | 1166 SpdyFrameBuilder frame(SpdyGoAwayControlFrame::size()); |
| 998 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1167 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 999 frame.WriteUInt16(GOAWAY); | 1168 frame.WriteUInt16(GOAWAY); |
| 1000 size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize; | 1169 size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize; |
| 1001 frame.WriteUInt32(go_away_size); | 1170 frame.WriteUInt32(go_away_size); |
| 1002 frame.WriteUInt32(last_accepted_stream_id); | 1171 frame.WriteUInt32(last_accepted_stream_id); |
| 1003 return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); | 1172 return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); |
| 1004 } | 1173 } |
| 1005 | 1174 |
| 1006 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id, | 1175 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders( |
| 1007 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { | 1176 SpdyStreamId stream_id, |
| 1177 SpdyControlFlags flags, | |
| 1178 bool compressed, | |
| 1179 const SpdyHeaderBlock* headers) { | |
| 1008 // Basically the same as CreateSynReply(). | 1180 // Basically the same as CreateSynReply(). |
| 1009 DCHECK_GT(stream_id, 0u); | 1181 DCHECK_GT(stream_id, 0u); |
| 1010 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1182 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 1011 | 1183 |
| 1012 // Find our length. | 1184 // Find our length. |
| 1013 size_t expected_frame_size = SpdyHeadersControlFrame::size() + | 1185 size_t expected_frame_size = SpdyHeadersControlFrame::size() + |
| 1014 GetSerializedLength(headers); | 1186 GetSerializedLength(headers); |
| 1187 // In SPDY 2, there were 2 unused bytes before payload. | |
| 1188 if (spdy_version_ < 3) { | |
| 1189 expected_frame_size += 2; | |
| 1190 } | |
| 1015 | 1191 |
| 1016 // Create our FlagsAndLength. | 1192 // Create our FlagsAndLength. |
| 1017 FlagsAndLength flags_length = CreateFlagsAndLength( | 1193 FlagsAndLength flags_length = CreateFlagsAndLength( |
| 1018 flags, | 1194 flags, |
| 1019 expected_frame_size - SpdyFrame::kHeaderSize); | 1195 expected_frame_size - SpdyFrame::kHeaderSize); |
| 1020 | 1196 |
| 1021 SpdyFrameBuilder frame(expected_frame_size); | 1197 SpdyFrameBuilder frame(expected_frame_size); |
| 1022 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1198 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 1023 frame.WriteUInt16(HEADERS); | 1199 frame.WriteUInt16(HEADERS); |
| 1024 frame.WriteBytes(&flags_length, sizeof(flags_length)); | 1200 frame.WriteBytes(&flags_length, sizeof(flags_length)); |
| 1025 frame.WriteUInt32(stream_id); | 1201 frame.WriteUInt32(stream_id); |
| 1026 frame.WriteUInt16(0); // Unused | 1202 if (spdy_version_ < 3) { |
| 1203 frame.WriteUInt16(0); // Unused | |
| 1204 } | |
| 1027 WriteHeaderBlock(&frame, headers); | 1205 WriteHeaderBlock(&frame, headers); |
| 1028 DCHECK_EQ(static_cast<size_t>(frame.length()), expected_frame_size); | 1206 DCHECK_EQ(static_cast<size_t>(frame.length()), expected_frame_size); |
| 1029 | 1207 |
| 1030 scoped_ptr<SpdyHeadersControlFrame> headers_frame( | 1208 scoped_ptr<SpdyHeadersControlFrame> headers_frame( |
| 1031 reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); | 1209 reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); |
| 1032 if (compressed) { | 1210 if (compressed) { |
| 1033 return reinterpret_cast<SpdyHeadersControlFrame*>( | 1211 return reinterpret_cast<SpdyHeadersControlFrame*>( |
| 1034 CompressControlFrame(*headers_frame.get())); | 1212 CompressControlFrame(*headers_frame.get())); |
| 1035 } | 1213 } |
| 1036 return headers_frame.release(); | 1214 return headers_frame.release(); |
| 1037 } | 1215 } |
| 1038 | 1216 |
| 1039 /* static */ | |
| 1040 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( | 1217 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( |
| 1041 SpdyStreamId stream_id, | 1218 SpdyStreamId stream_id, |
| 1042 uint32 delta_window_size) { | 1219 uint32 delta_window_size) const { |
| 1043 DCHECK_GT(stream_id, 0u); | 1220 DCHECK_GT(stream_id, 0u); |
| 1044 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1221 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 1045 DCHECK_GT(delta_window_size, 0u); | 1222 DCHECK_GT(delta_window_size, 0u); |
| 1046 DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize); | 1223 DCHECK_LE(delta_window_size, |
| 1224 static_cast<uint32>(spdy::kSpdyStreamMaximumWindowSize)); | |
| 1047 | 1225 |
| 1048 SpdyFrameBuilder frame(SpdyWindowUpdateControlFrame::size()); | 1226 SpdyFrameBuilder frame(SpdyWindowUpdateControlFrame::size()); |
| 1049 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1227 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 1050 frame.WriteUInt16(WINDOW_UPDATE); | 1228 frame.WriteUInt16(WINDOW_UPDATE); |
| 1051 size_t window_update_size = SpdyWindowUpdateControlFrame::size() - | 1229 size_t window_update_size = SpdyWindowUpdateControlFrame::size() - |
| 1052 SpdyFrame::kHeaderSize; | 1230 SpdyFrame::kHeaderSize; |
| 1053 frame.WriteUInt32(window_update_size); | 1231 frame.WriteUInt32(window_update_size); |
| 1054 frame.WriteUInt32(stream_id); | 1232 frame.WriteUInt32(stream_id); |
| 1055 frame.WriteUInt32(delta_window_size); | 1233 frame.WriteUInt32(delta_window_size); |
| 1056 return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take()); | 1234 return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take()); |
| 1057 } | 1235 } |
| 1058 | 1236 |
| 1059 /* static */ | |
| 1060 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( | 1237 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( |
| 1061 const SpdyCredential& credential) { | 1238 const SpdyCredential& credential) const { |
| 1062 // Calculate the size of the frame by adding the size of the | 1239 // Calculate the size of the frame by adding the size of the |
| 1063 // variable length data to the size of the fixed length data. | 1240 // variable length data to the size of the fixed length data. |
| 1064 size_t frame_size = SpdyCredentialControlFrame::size() + | 1241 size_t frame_size = SpdyCredentialControlFrame::size() + |
| 1065 credential.proof.length(); | 1242 credential.proof.length(); |
| 1066 DCHECK_EQ(SpdyCredentialControlFrame::size(), 14u); | 1243 DCHECK_EQ(SpdyCredentialControlFrame::size(), 14u); |
| 1067 for (vector<std::string>::const_iterator cert = credential.certs.begin(); | 1244 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); |
| 1068 cert != credential.certs.end(); | 1245 cert != credential.certs.end(); |
| 1069 cert++) { | 1246 ++cert) { |
| 1070 frame_size += sizeof(uint32); // size of the cert_length field | 1247 frame_size += sizeof(uint32); // size of the cert_length field |
| 1071 frame_size += cert->length(); // size of the cert_data field | 1248 frame_size += cert->length(); // size of the cert_data field |
| 1072 } | 1249 } |
| 1073 size_t payload_size = frame_size - SpdyFrame::kHeaderSize; | 1250 size_t payload_size = frame_size - SpdyFrame::kHeaderSize; |
| 1074 | 1251 |
| 1075 SpdyFrameBuilder frame(frame_size); | 1252 SpdyFrameBuilder frame(frame_size); |
| 1076 // Create our FlagsAndLength. | 1253 // Create our FlagsAndLength. |
| 1077 SpdyControlFlags flags = spdy::CONTROL_FLAG_NONE; | 1254 SpdyControlFlags flags = CONTROL_FLAG_NONE; |
| 1078 FlagsAndLength flags_length = CreateFlagsAndLength(flags, payload_size); | 1255 FlagsAndLength flags_length = CreateFlagsAndLength(flags, payload_size); |
| 1079 | 1256 |
| 1080 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 1257 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
| 1081 frame.WriteUInt16(CREDENTIAL); | 1258 frame.WriteUInt16(CREDENTIAL); |
| 1082 frame.WriteBytes(&flags_length, sizeof(flags_length)); | 1259 frame.WriteBytes(&flags_length, sizeof(flags_length)); |
| 1083 frame.WriteUInt16(credential.slot); | 1260 frame.WriteUInt16(credential.slot); |
| 1084 frame.WriteUInt32(credential.proof.size()); | 1261 frame.WriteUInt32(credential.proof.size()); |
| 1085 frame.WriteBytes(credential.proof.c_str(), credential.proof.size()); | 1262 frame.WriteBytes(credential.proof.c_str(), credential.proof.size()); |
| 1086 for (vector<std::string>::const_iterator cert = credential.certs.begin(); | 1263 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); |
| 1087 cert != credential.certs.end(); | 1264 cert != credential.certs.end(); |
| 1088 cert++) { | 1265 ++cert) { |
| 1089 frame.WriteUInt32(cert->length()); | 1266 frame.WriteUInt32(cert->length()); |
| 1090 frame.WriteBytes(cert->c_str(), cert->length()); | 1267 frame.WriteBytes(cert->c_str(), cert->length()); |
| 1091 } | 1268 } |
| 1092 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); | 1269 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); |
| 1093 } | 1270 } |
| 1094 | 1271 |
| 1095 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, | 1272 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, |
| 1096 const char* data, | 1273 const char* data, |
| 1097 uint32 len, SpdyDataFlags flags) { | 1274 uint32 len, SpdyDataFlags flags) { |
| 1098 DCHECK_GT(stream_id, 0u); | |
| 1099 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1275 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
| 1100 | 1276 |
| 1101 SpdyFrameBuilder frame(SpdyDataFrame::size() + len); | 1277 SpdyFrameBuilder frame(SpdyDataFrame::size() + len); |
| 1102 frame.WriteUInt32(stream_id); | 1278 frame.WriteUInt32(stream_id); |
| 1103 | 1279 |
| 1104 DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask)); | 1280 DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask)); |
| 1105 FlagsAndLength flags_length; | 1281 FlagsAndLength flags_length; |
| 1106 flags_length.length_ = htonl(len); | 1282 flags_length.length_ = htonl(len); |
| 1107 DCHECK_EQ(0, flags & ~kDataFlagsMask); | 1283 DCHECK_EQ(0, flags & ~kDataFlagsMask); |
| 1108 flags_length.flags_[0] = flags; | 1284 flags_length.flags_[0] = flags; |
| 1109 frame.WriteBytes(&flags_length, sizeof(flags_length)); | 1285 frame.WriteBytes(&flags_length, sizeof(flags_length)); |
| 1110 | 1286 |
| 1111 frame.WriteBytes(data, len); | 1287 frame.WriteBytes(data, len); |
| 1112 scoped_ptr<SpdyFrame> data_frame(frame.take()); | 1288 scoped_ptr<SpdyFrame> data_frame(frame.take()); |
| 1113 SpdyDataFrame* rv; | 1289 SpdyDataFrame* rv; |
| 1114 if (flags & DATA_FLAG_COMPRESSED) { | 1290 if (flags & DATA_FLAG_COMPRESSED) { |
| 1115 rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get())); | 1291 LOG(DFATAL) << "DATA_FLAG_COMPRESSED invalid for " << display_protocol_ |
| 1116 } else { | 1292 << "."; |
| 1117 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release()); | |
| 1118 } | 1293 } |
| 1294 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release()); | |
| 1119 | 1295 |
| 1120 if (flags & DATA_FLAG_FIN) { | 1296 if (flags & DATA_FLAG_FIN) { |
| 1121 CleanupCompressorForStream(stream_id); | 1297 CleanupCompressorForStream(stream_id); |
| 1122 } | 1298 } |
| 1123 | 1299 |
| 1124 return rv; | 1300 return rv; |
| 1125 } | 1301 } |
| 1126 | 1302 |
| 1127 // The following compression setting are based on Brian Olson's analysis. See | 1303 // The following compression setting are based on Brian Olson's analysis. See |
| 1128 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2 | 1304 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2 |
| 1129 // for more details. | 1305 // for more details. |
| 1130 static const int kCompressorLevel = 9; | 1306 static const int kCompressorLevel = 9; |
| 1131 static const int kCompressorWindowSizeInBits = 11; | 1307 static const int kCompressorWindowSizeInBits = 11; |
| 1132 static const int kCompressorMemLevel = 1; | 1308 static const int kCompressorMemLevel = 1; |
| 1133 | 1309 |
| 1134 // This is just a hacked dictionary to use for shrinking HTTP-like headers. | |
| 1135 // TODO(mbelshe): Use a scientific methodology for computing the dictionary. | |
| 1136 const char SpdyFramer::kDictionary[] = | |
| 1137 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" | |
| 1138 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" | |
| 1139 "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" | |
| 1140 "-agent10010120020120220320420520630030130230330430530630740040140240340440" | |
| 1141 "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" | |
| 1142 "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" | |
| 1143 "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" | |
| 1144 "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" | |
| 1145 "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" | |
| 1146 "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" | |
| 1147 "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" | |
| 1148 "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" | |
| 1149 ".1statusversionurl"; | |
| 1150 const int SpdyFramer::kDictionarySize = arraysize(kDictionary); | |
| 1151 | |
| 1152 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) { | 1310 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) { |
| 1153 if (frame.is_control_frame()) { | 1311 if (frame.is_control_frame()) { |
| 1154 return CompressControlFrame( | 1312 return CompressControlFrame( |
| 1155 reinterpret_cast<const SpdyControlFrame&>(frame)); | 1313 reinterpret_cast<const SpdyControlFrame&>(frame)); |
| 1156 } | 1314 } |
| 1157 return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame)); | 1315 return NULL; |
| 1158 } | |
| 1159 | |
| 1160 SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) { | |
| 1161 if (frame.is_control_frame()) { | |
| 1162 return DecompressControlFrame( | |
| 1163 reinterpret_cast<const SpdyControlFrame&>(frame)); | |
| 1164 } | |
| 1165 return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame)); | |
| 1166 } | 1316 } |
| 1167 | 1317 |
| 1168 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const { | 1318 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const { |
| 1169 // The important frames to compress are those which contain large | 1319 // The important frames to compress are those which contain large |
| 1170 // amounts of compressible data - namely the headers in the SYN_STREAM | 1320 // amounts of compressible data - namely the headers in the SYN_STREAM |
| 1171 // and SYN_REPLY. | 1321 // and SYN_REPLY. |
| 1172 // TODO(mbelshe): Reconcile this with the spec when the spec is | |
| 1173 // explicit about which frames compress and which do not. | |
| 1174 if (frame.is_control_frame()) { | 1322 if (frame.is_control_frame()) { |
| 1175 const SpdyControlFrame& control_frame = | 1323 const SpdyControlFrame& control_frame = |
| 1176 reinterpret_cast<const SpdyControlFrame&>(frame); | 1324 reinterpret_cast<const SpdyControlFrame&>(frame); |
| 1177 return control_frame.type() == SYN_STREAM || | 1325 return control_frame.type() == SYN_STREAM || |
| 1178 control_frame.type() == SYN_REPLY; | 1326 control_frame.type() == SYN_REPLY; |
| 1179 } | 1327 } |
| 1180 | 1328 |
| 1181 const SpdyDataFrame& data_frame = | 1329 // We don't compress Data frames. |
| 1182 reinterpret_cast<const SpdyDataFrame&>(frame); | 1330 return false; |
| 1183 return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0; | |
| 1184 } | 1331 } |
| 1185 | 1332 |
| 1186 z_stream* SpdyFramer::GetHeaderCompressor() { | 1333 z_stream* SpdyFramer::GetHeaderCompressor() { |
| 1187 if (header_compressor_.get()) | 1334 if (header_compressor_.get()) |
| 1188 return header_compressor_.get(); // Already initialized. | 1335 return header_compressor_.get(); // Already initialized. |
| 1189 | 1336 |
| 1190 header_compressor_.reset(new z_stream); | 1337 header_compressor_.reset(new z_stream); |
| 1191 memset(header_compressor_.get(), 0, sizeof(z_stream)); | 1338 memset(header_compressor_.get(), 0, sizeof(z_stream)); |
| 1192 | 1339 |
| 1193 int success = deflateInit2(header_compressor_.get(), | 1340 int success = deflateInit2(header_compressor_.get(), |
| 1194 kCompressorLevel, | 1341 kCompressorLevel, |
| 1195 Z_DEFLATED, | 1342 Z_DEFLATED, |
| 1196 kCompressorWindowSizeInBits, | 1343 kCompressorWindowSizeInBits, |
| 1197 kCompressorMemLevel, | 1344 kCompressorMemLevel, |
| 1198 Z_DEFAULT_STRATEGY); | 1345 Z_DEFAULT_STRATEGY); |
| 1199 if (success == Z_OK) | 1346 if (success == Z_OK) { |
| 1347 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary | |
| 1348 : kV3Dictionary; | |
| 1349 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize | |
| 1350 : kV3DictionarySize; | |
| 1200 success = deflateSetDictionary(header_compressor_.get(), | 1351 success = deflateSetDictionary(header_compressor_.get(), |
| 1201 reinterpret_cast<const Bytef*>(kDictionary), | 1352 reinterpret_cast<const Bytef*>(dictionary), |
| 1202 kDictionarySize); | 1353 dictionary_size); |
| 1354 } | |
| 1203 if (success != Z_OK) { | 1355 if (success != Z_OK) { |
| 1204 LOG(WARNING) << "deflateSetDictionary failure: " << success; | 1356 LOG(WARNING) << "deflateSetDictionary failure: " << success; |
| 1205 header_compressor_.reset(NULL); | 1357 header_compressor_.reset(NULL); |
| 1206 return NULL; | 1358 return NULL; |
| 1207 } | 1359 } |
| 1208 return header_compressor_.get(); | 1360 return header_compressor_.get(); |
| 1209 } | 1361 } |
| 1210 | 1362 |
| 1211 z_stream* SpdyFramer::GetHeaderDecompressor() { | 1363 z_stream* SpdyFramer::GetHeaderDecompressor() { |
| 1212 if (header_decompressor_.get()) | 1364 if (header_decompressor_.get()) |
| 1213 return header_decompressor_.get(); // Already initialized. | 1365 return header_decompressor_.get(); // Already initialized. |
| 1214 | 1366 |
| 1215 header_decompressor_.reset(new z_stream); | 1367 header_decompressor_.reset(new z_stream); |
| 1216 memset(header_decompressor_.get(), 0, sizeof(z_stream)); | 1368 memset(header_decompressor_.get(), 0, sizeof(z_stream)); |
| 1217 | 1369 |
| 1218 int success = inflateInit(header_decompressor_.get()); | 1370 int success = inflateInit(header_decompressor_.get()); |
| 1219 if (success != Z_OK) { | 1371 if (success != Z_OK) { |
| 1220 LOG(WARNING) << "inflateInit failure: " << success; | 1372 LOG(WARNING) << "inflateInit failure: " << success; |
| 1221 header_decompressor_.reset(NULL); | 1373 header_decompressor_.reset(NULL); |
| 1222 return NULL; | 1374 return NULL; |
| 1223 } | 1375 } |
| 1224 return header_decompressor_.get(); | 1376 return header_decompressor_.get(); |
| 1225 } | 1377 } |
| 1226 | 1378 |
| 1227 z_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) { | |
| 1228 CompressorMap::iterator it = stream_compressors_.find(stream_id); | |
| 1229 if (it != stream_compressors_.end()) | |
| 1230 return it->second; // Already initialized. | |
| 1231 | |
| 1232 scoped_ptr<z_stream> compressor(new z_stream); | |
| 1233 memset(compressor.get(), 0, sizeof(z_stream)); | |
| 1234 | |
| 1235 int success = deflateInit2(compressor.get(), | |
| 1236 kCompressorLevel, | |
| 1237 Z_DEFLATED, | |
| 1238 kCompressorWindowSizeInBits, | |
| 1239 kCompressorMemLevel, | |
| 1240 Z_DEFAULT_STRATEGY); | |
| 1241 if (success != Z_OK) { | |
| 1242 LOG(WARNING) << "deflateInit failure: " << success; | |
| 1243 return NULL; | |
| 1244 } | |
| 1245 return stream_compressors_[stream_id] = compressor.release(); | |
| 1246 } | |
| 1247 | |
| 1248 z_stream* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id) { | 1379 z_stream* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id) { |
| 1249 CompressorMap::iterator it = stream_decompressors_.find(stream_id); | 1380 CompressorMap::iterator it = stream_decompressors_.find(stream_id); |
| 1250 if (it != stream_decompressors_.end()) | 1381 if (it != stream_decompressors_.end()) |
| 1251 return it->second; // Already initialized. | 1382 return it->second; // Already initialized. |
| 1252 | 1383 |
| 1253 scoped_ptr<z_stream> decompressor(new z_stream); | 1384 scoped_ptr<z_stream> decompressor(new z_stream); |
| 1254 memset(decompressor.get(), 0, sizeof(z_stream)); | 1385 memset(decompressor.get(), 0, sizeof(z_stream)); |
| 1255 | 1386 |
| 1256 int success = inflateInit(decompressor.get()); | 1387 int success = inflateInit(decompressor.get()); |
| 1257 if (success != Z_OK) { | 1388 if (success != Z_OK) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1281 } | 1412 } |
| 1282 break; | 1413 break; |
| 1283 case SYN_REPLY: | 1414 case SYN_REPLY: |
| 1284 { | 1415 { |
| 1285 const SpdySynReplyControlFrame& syn_frame = | 1416 const SpdySynReplyControlFrame& syn_frame = |
| 1286 reinterpret_cast<const SpdySynReplyControlFrame&>(frame); | 1417 reinterpret_cast<const SpdySynReplyControlFrame&>(frame); |
| 1287 frame_size = SpdySynReplyControlFrame::size(); | 1418 frame_size = SpdySynReplyControlFrame::size(); |
| 1288 *payload_length = syn_frame.header_block_len(); | 1419 *payload_length = syn_frame.header_block_len(); |
| 1289 *header_length = frame_size; | 1420 *header_length = frame_size; |
| 1290 *payload = frame.data() + *header_length; | 1421 *payload = frame.data() + *header_length; |
| 1422 // SPDY 2 had two bytes of unused space preceeding payload. | |
| 1423 if (spdy_version_ < 3) { | |
| 1424 *header_length += 2; | |
| 1425 *payload += 2; | |
| 1426 } | |
| 1291 } | 1427 } |
| 1292 break; | 1428 break; |
| 1293 case HEADERS: | 1429 case HEADERS: |
| 1294 { | 1430 { |
| 1295 const SpdyHeadersControlFrame& headers_frame = | 1431 const SpdyHeadersControlFrame& headers_frame = |
| 1296 reinterpret_cast<const SpdyHeadersControlFrame&>(frame); | 1432 reinterpret_cast<const SpdyHeadersControlFrame&>(frame); |
| 1297 frame_size = SpdyHeadersControlFrame::size(); | 1433 frame_size = SpdyHeadersControlFrame::size(); |
| 1298 *payload_length = headers_frame.header_block_len(); | 1434 *payload_length = headers_frame.header_block_len(); |
| 1299 *header_length = frame_size; | 1435 *header_length = frame_size; |
| 1300 *payload = frame.data() + *header_length; | 1436 *payload = frame.data() + *header_length; |
| 1437 // SPDY 2 had two bytes of unused space preceeding payload. | |
| 1438 if (spdy_version_ < 3) { | |
| 1439 *header_length += 2; | |
| 1440 *payload += 2; | |
| 1441 } | |
| 1301 } | 1442 } |
| 1302 break; | 1443 break; |
| 1303 default: | 1444 default: |
| 1304 // TODO(mbelshe): set an error? | 1445 // TODO(mbelshe): set an error? |
| 1305 return false; // We can't compress this frame! | 1446 return false; // We can't compress this frame! |
| 1306 } | 1447 } |
| 1307 } else { | 1448 } else { |
| 1308 frame_size = SpdyFrame::kHeaderSize; | 1449 frame_size = SpdyFrame::kHeaderSize; |
| 1309 *header_length = frame_size; | 1450 *header_length = frame_size; |
| 1310 *payload_length = frame.length(); | 1451 *payload_length = frame.length(); |
| 1311 *payload = frame.data() + SpdyFrame::kHeaderSize; | 1452 *payload = frame.data() + SpdyFrame::kHeaderSize; |
| 1312 } | 1453 } |
| 1313 return true; | 1454 return true; |
| 1314 } | 1455 } |
| 1315 | 1456 |
| 1316 SpdyControlFrame* SpdyFramer::CompressControlFrame( | 1457 SpdyControlFrame* SpdyFramer::CompressControlFrame( |
| 1317 const SpdyControlFrame& frame) { | 1458 const SpdyControlFrame& frame) { |
| 1318 z_stream* compressor = GetHeaderCompressor(); | 1459 z_stream* compressor = GetHeaderCompressor(); |
| 1319 if (!compressor) | 1460 if (!compressor) |
| 1320 return NULL; | 1461 return NULL; |
| 1321 return reinterpret_cast<SpdyControlFrame*>( | |
| 1322 CompressFrameWithZStream(frame, compressor)); | |
| 1323 } | |
| 1324 | 1462 |
| 1325 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) { | |
| 1326 z_stream* compressor = GetStreamCompressor(frame.stream_id()); | |
| 1327 if (!compressor) | |
| 1328 return NULL; | |
| 1329 return reinterpret_cast<SpdyDataFrame*>( | |
| 1330 CompressFrameWithZStream(frame, compressor)); | |
| 1331 } | |
| 1332 | |
| 1333 SpdyControlFrame* SpdyFramer::DecompressControlFrame( | |
| 1334 const SpdyControlFrame& frame) { | |
| 1335 z_stream* decompressor = GetHeaderDecompressor(); | |
| 1336 if (!decompressor) { | |
| 1337 LOG(DFATAL) << "Couldn't get decompressor for handling control frame."; | |
| 1338 set_error(SPDY_DECOMPRESS_FAILURE); | |
| 1339 return NULL; | |
| 1340 } | |
| 1341 return reinterpret_cast<SpdyControlFrame*>( | |
| 1342 DecompressFrameWithZStream(frame, decompressor)); | |
| 1343 } | |
| 1344 | |
| 1345 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) { | |
| 1346 z_stream* decompressor = GetStreamDecompressor(frame.stream_id()); | |
| 1347 if (!decompressor) | |
| 1348 return NULL; | |
| 1349 return reinterpret_cast<SpdyDataFrame*>( | |
| 1350 DecompressFrameWithZStream(frame, decompressor)); | |
| 1351 } | |
| 1352 | |
| 1353 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame, | |
| 1354 z_stream* compressor) { | |
| 1355 int payload_length; | 1463 int payload_length; |
| 1356 int header_length; | 1464 int header_length; |
| 1357 const char* payload; | 1465 const char* payload; |
| 1358 | 1466 |
| 1359 base::StatsCounter compressed_frames("spdy.CompressedFrames"); | 1467 base::StatsCounter compressed_frames("spdy.CompressedFrames"); |
| 1360 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); | 1468 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); |
| 1361 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); | 1469 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); |
| 1362 | 1470 |
| 1363 if (!enable_compression_) | 1471 if (!enable_compression_) |
| 1364 return DuplicateFrame(frame); | 1472 return reinterpret_cast<SpdyControlFrame*>(DuplicateFrame(frame)); |
| 1365 | 1473 |
| 1366 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) | 1474 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) |
| 1367 return NULL; | 1475 return NULL; |
| 1368 | 1476 |
| 1369 // Create an output frame. | 1477 // Create an output frame. |
| 1370 int compressed_max_size = deflateBound(compressor, payload_length); | 1478 int compressed_max_size = deflateBound(compressor, payload_length); |
| 1371 int new_frame_size = header_length + compressed_max_size; | 1479 int new_frame_size = header_length + compressed_max_size; |
| 1372 scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size)); | 1480 if ((frame.type() == SYN_REPLY || frame.type() == HEADERS) && |
| 1481 spdy_version_ < 3) { | |
| 1482 new_frame_size += 2; | |
| 1483 } | |
| 1484 DCHECK_GE(new_frame_size, | |
| 1485 static_cast<int>(frame.length() + SpdyFrame::kHeaderSize)); | |
| 1486 scoped_ptr<SpdyControlFrame> new_frame(new SpdyControlFrame(new_frame_size)); | |
| 1373 memcpy(new_frame->data(), frame.data(), | 1487 memcpy(new_frame->data(), frame.data(), |
| 1374 frame.length() + SpdyFrame::kHeaderSize); | 1488 frame.length() + SpdyFrame::kHeaderSize); |
| 1375 | 1489 |
| 1376 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); | 1490 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); |
| 1377 compressor->avail_in = payload_length; | 1491 compressor->avail_in = payload_length; |
| 1378 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + | 1492 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + |
| 1379 header_length; | 1493 header_length; |
| 1380 compressor->avail_out = compressed_max_size; | 1494 compressor->avail_out = compressed_max_size; |
| 1381 | 1495 |
| 1382 // Data packets have a 'compressed' flag. | 1496 // Data packets have a 'compressed' flag. |
| 1497 // TODO(hkhalil): Remove post code-yellow. It's impossible to execute this | |
| 1498 // branch given that SpdyControlFrame::is_control_frame always returns true. | |
| 1499 DCHECK(new_frame->is_control_frame()); | |
| 1383 if (!new_frame->is_control_frame()) { | 1500 if (!new_frame->is_control_frame()) { |
| 1384 SpdyDataFrame* data_frame = | 1501 SpdyDataFrame* data_frame = |
| 1385 reinterpret_cast<SpdyDataFrame*>(new_frame.get()); | 1502 reinterpret_cast<SpdyDataFrame*>(new_frame.get()); |
| 1386 data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED); | 1503 data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED); |
| 1387 } | 1504 } |
| 1388 | 1505 |
| 1389 // Make sure that all the data we pass to zlib is defined. | 1506 // Make sure that all the data we pass to zlib is defined. |
| 1390 // This way, all Valgrind reports on the compressed data are zlib's fault. | 1507 // This way, all Valgrind reports on the compressed data are zlib's fault. |
| 1391 (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in, | 1508 (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in, |
| 1392 compressor->avail_in); | 1509 compressor->avail_in); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1409 header_length + compressed_size - SpdyFrame::kHeaderSize); | 1526 header_length + compressed_size - SpdyFrame::kHeaderSize); |
| 1410 | 1527 |
| 1411 pre_compress_bytes.Add(payload_length); | 1528 pre_compress_bytes.Add(payload_length); |
| 1412 post_compress_bytes.Add(new_frame->length()); | 1529 post_compress_bytes.Add(new_frame->length()); |
| 1413 | 1530 |
| 1414 compressed_frames.Increment(); | 1531 compressed_frames.Increment(); |
| 1415 | 1532 |
| 1416 return new_frame.release(); | 1533 return new_frame.release(); |
| 1417 } | 1534 } |
| 1418 | 1535 |
| 1419 SpdyFrame* SpdyFramer::DecompressFrameWithZStream(const SpdyFrame& frame, | |
| 1420 z_stream* decompressor) { | |
| 1421 int payload_length; | |
| 1422 int header_length; | |
| 1423 const char* payload; | |
| 1424 | |
| 1425 base::StatsCounter decompressed_frames("spdy.DecompressedFrames"); | |
| 1426 base::StatsCounter pre_decompress_bytes("spdy.PreDeCompressSize"); | |
| 1427 base::StatsCounter post_decompress_bytes("spdy.PostDeCompressSize"); | |
| 1428 | |
| 1429 if (!enable_compression_) | |
| 1430 return DuplicateFrame(frame); | |
| 1431 | |
| 1432 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) | |
| 1433 return NULL; | |
| 1434 | |
| 1435 if (!frame.is_control_frame()) { | |
| 1436 const SpdyDataFrame& data_frame = | |
| 1437 reinterpret_cast<const SpdyDataFrame&>(frame); | |
| 1438 if ((data_frame.flags() & DATA_FLAG_COMPRESSED) == 0) | |
| 1439 return DuplicateFrame(frame); | |
| 1440 } | |
| 1441 | |
| 1442 // Create an output frame. Assume it does not need to be longer than | |
| 1443 // the input data. | |
| 1444 size_t decompressed_max_size = kControlFrameBufferInitialSize; | |
| 1445 int new_frame_size = header_length + decompressed_max_size; | |
| 1446 if (frame.length() > decompressed_max_size) | |
| 1447 return NULL; | |
| 1448 scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size)); | |
| 1449 memcpy(new_frame->data(), frame.data(), | |
| 1450 frame.length() + SpdyFrame::kHeaderSize); | |
| 1451 | |
| 1452 decompressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); | |
| 1453 decompressor->avail_in = payload_length; | |
| 1454 decompressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + | |
| 1455 header_length; | |
| 1456 decompressor->avail_out = decompressed_max_size; | |
| 1457 | |
| 1458 int rv = inflate(decompressor, Z_SYNC_FLUSH); | |
| 1459 if (rv == Z_NEED_DICT) { | |
| 1460 // Need to try again with the right dictionary. | |
| 1461 if (decompressor->adler == kDictionaryId) { | |
| 1462 rv = inflateSetDictionary(decompressor, | |
| 1463 (const Bytef*)SpdyFramer::kDictionary, | |
| 1464 SpdyFramer::kDictionarySize); | |
| 1465 if (rv == Z_OK) | |
| 1466 rv = inflate(decompressor, Z_SYNC_FLUSH); | |
| 1467 } | |
| 1468 } | |
| 1469 if (rv != Z_OK) { // How can we know that it decompressed everything? | |
| 1470 LOG(WARNING) << "inflate failure: " << rv; | |
| 1471 return NULL; | |
| 1472 } | |
| 1473 | |
| 1474 // Unset the compressed flag for data frames. | |
| 1475 if (!new_frame->is_control_frame()) { | |
| 1476 SpdyDataFrame* data_frame = | |
| 1477 reinterpret_cast<SpdyDataFrame*>(new_frame.get()); | |
| 1478 data_frame->set_flags(data_frame->flags() & ~DATA_FLAG_COMPRESSED); | |
| 1479 } | |
| 1480 | |
| 1481 int decompressed_size = decompressed_max_size - decompressor->avail_out; | |
| 1482 new_frame->set_length( | |
| 1483 header_length + decompressed_size - SpdyFrame::kHeaderSize); | |
| 1484 | |
| 1485 // If there is data left, then the frame didn't fully decompress. This | |
| 1486 // means that there is stranded data at the end of this frame buffer which | |
| 1487 // will be ignored. | |
| 1488 DCHECK_EQ(decompressor->avail_in, 0u); | |
| 1489 | |
| 1490 pre_decompress_bytes.Add(frame.length()); | |
| 1491 post_decompress_bytes.Add(new_frame->length()); | |
| 1492 | |
| 1493 decompressed_frames.Increment(); | |
| 1494 | |
| 1495 return new_frame.release(); | |
| 1496 } | |
| 1497 | |
| 1498 // Incrementally decompress the control frame's header block, feeding the | 1536 // Incrementally decompress the control frame's header block, feeding the |
| 1499 // result to the visitor in chunks. Continue this until the visitor | 1537 // result to the visitor in chunks. Continue this until the visitor |
| 1500 // indicates that it cannot process any more data, or (more commonly) we | 1538 // indicates that it cannot process any more data, or (more commonly) we |
| 1501 // run out of data to deliver. | 1539 // run out of data to deliver. |
| 1502 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( | 1540 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( |
| 1503 const SpdyControlFrame* control_frame, | 1541 const SpdyControlFrame* control_frame, |
| 1504 const char* data, | 1542 const char* data, |
| 1505 size_t len) { | 1543 size_t len) { |
| 1506 // Get a decompressor or set error. | 1544 // Get a decompressor or set error. |
| 1507 z_stream* decomp = GetHeaderDecompressor(); | 1545 z_stream* decomp = GetHeaderDecompressor(); |
| 1508 if (decomp == NULL) { | 1546 if (decomp == NULL) { |
| 1509 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; | 1547 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; |
| 1510 set_error(SPDY_DECOMPRESS_FAILURE); | 1548 set_error(SPDY_DECOMPRESS_FAILURE); |
| 1511 return false; | 1549 return false; |
| 1512 } | 1550 } |
| 1513 | 1551 |
| 1514 bool processed_successfully = true; | 1552 bool processed_successfully = true; |
| 1515 char buffer[kHeaderDataChunkMaxSize]; | 1553 char buffer[kHeaderDataChunkMaxSize]; |
| 1516 | 1554 |
| 1517 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); | 1555 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); |
| 1518 decomp->avail_in = len; | 1556 decomp->avail_in = len; |
| 1519 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); | 1557 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); |
| 1520 DCHECK_LT(0u, stream_id); | 1558 DCHECK_LT(0u, stream_id); |
| 1521 while (decomp->avail_in > 0 && processed_successfully) { | 1559 while (decomp->avail_in > 0 && processed_successfully) { |
| 1522 decomp->next_out = reinterpret_cast<Bytef*>(buffer); | 1560 decomp->next_out = reinterpret_cast<Bytef*>(buffer); |
| 1523 decomp->avail_out = arraysize(buffer); | 1561 decomp->avail_out = arraysize(buffer); |
| 1524 int rv = DecompressHeaderBlockInZStream(decomp); | 1562 |
| 1525 if (rv != Z_OK && rv != Z_BUF_ERROR) { | 1563 int rv = inflate(decomp, Z_SYNC_FLUSH); |
| 1526 set_error(SPDY_DECOMPRESS_FAILURE); | 1564 if (rv == Z_NEED_DICT) { |
| 1527 DLOG(WARNING) << "inflate failure: " << rv; | 1565 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary |
| 1528 processed_successfully = false; | 1566 : kV3Dictionary; |
| 1529 } else { | 1567 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize |
| 1568 : kV3DictionarySize; | |
| 1569 const uLong dictionary_id = (spdy_version_ < 3) ? kV2DictionaryId | |
| 1570 : kV3DictionaryId; | |
| 1571 // Need to try again with the right dictionary. | |
| 1572 if (decomp->adler == dictionary_id) { | |
| 1573 rv = inflateSetDictionary(decomp, | |
| 1574 reinterpret_cast<const Bytef*>(dictionary), | |
| 1575 dictionary_size); | |
| 1576 if (rv == Z_OK) | |
| 1577 rv = inflate(decomp, Z_SYNC_FLUSH); | |
| 1578 } | |
| 1579 } | |
| 1580 | |
| 1581 // Inflate will generate a Z_BUF_ERROR if it runs out of input | |
| 1582 // without producing any output. The input is consumed and | |
| 1583 // buffered internally by zlib so we can detect this condition by | |
| 1584 // checking if avail_in is 0 after the call to inflate. | |
| 1585 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); | |
| 1586 if ((rv == Z_OK) || input_exhausted) { | |
| 1530 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; | 1587 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; |
| 1531 if (decompressed_len > 0) { | 1588 if (decompressed_len > 0) { |
| 1532 processed_successfully = visitor_->OnControlFrameHeaderData( | 1589 processed_successfully = visitor_->OnControlFrameHeaderData( |
| 1533 stream_id, buffer, decompressed_len); | 1590 stream_id, buffer, decompressed_len); |
| 1534 } | 1591 } |
| 1535 if (!processed_successfully) { | 1592 if (!processed_successfully) { |
| 1536 // Assume that the problem was the header block was too large for the | 1593 // Assume that the problem was the header block was too large for the |
| 1537 // visitor. | 1594 // visitor. |
| 1538 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 1595 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
| 1539 } | 1596 } |
| 1597 } else { | |
| 1598 DLOG(WARNING) << "inflate failure: " << rv << " " << len; | |
| 1599 set_error(SPDY_DECOMPRESS_FAILURE); | |
| 1600 processed_successfully = false; | |
| 1540 } | 1601 } |
| 1541 } | 1602 } |
| 1542 return processed_successfully; | 1603 return processed_successfully; |
| 1543 } | 1604 } |
| 1544 | 1605 |
| 1545 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( | 1606 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( |
| 1546 const SpdyControlFrame* control_frame, const char* data, size_t len) { | 1607 const SpdyControlFrame* control_frame, const char* data, size_t len) { |
| 1547 bool read_successfully = true; | 1608 bool read_successfully = true; |
| 1548 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); | 1609 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); |
| 1549 DCHECK_LT(0u, stream_id); | |
| 1550 while (read_successfully && len > 0) { | 1610 while (read_successfully && len > 0) { |
| 1551 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); | 1611 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); |
| 1552 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, | 1612 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, |
| 1553 bytes_to_deliver); | 1613 bytes_to_deliver); |
| 1554 data += bytes_to_deliver; | 1614 data += bytes_to_deliver; |
| 1555 len -= bytes_to_deliver; | 1615 len -= bytes_to_deliver; |
| 1556 if (!read_successfully) { | 1616 if (!read_successfully) { |
| 1557 // Assume that the problem was the header block was too large for the | 1617 // Assume that the problem was the header block was too large for the |
| 1558 // visitor. | 1618 // visitor. |
| 1559 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 1619 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1615 switch (type) { | 1675 switch (type) { |
| 1616 case SYN_STREAM: | 1676 case SYN_STREAM: |
| 1617 return SpdySynStreamControlFrame::size(); | 1677 return SpdySynStreamControlFrame::size(); |
| 1618 case SYN_REPLY: | 1678 case SYN_REPLY: |
| 1619 return SpdySynReplyControlFrame::size(); | 1679 return SpdySynReplyControlFrame::size(); |
| 1620 case RST_STREAM: | 1680 case RST_STREAM: |
| 1621 return SpdyRstStreamControlFrame::size(); | 1681 return SpdyRstStreamControlFrame::size(); |
| 1622 case SETTINGS: | 1682 case SETTINGS: |
| 1623 return SpdySettingsControlFrame::size(); | 1683 return SpdySettingsControlFrame::size(); |
| 1624 case NOOP: | 1684 case NOOP: |
| 1625 return SpdyNoOpControlFrame::size(); | 1685 // Even though NOOP is no longer supported, we still correctly report its |
| 1686 // size so that it can be handled correctly as incoming data if | |
| 1687 // implementations so desire. | |
| 1688 return SpdyFrame::kHeaderSize; | |
| 1626 case PING: | 1689 case PING: |
| 1627 return SpdyPingControlFrame::size(); | 1690 return SpdyPingControlFrame::size(); |
| 1628 case GOAWAY: | 1691 case GOAWAY: |
| 1629 return SpdyGoAwayControlFrame::size(); | 1692 return SpdyGoAwayControlFrame::size(); |
| 1630 case HEADERS: | 1693 case HEADERS: |
| 1631 return SpdyHeadersControlFrame::size(); | 1694 return SpdyHeadersControlFrame::size(); |
| 1632 case WINDOW_UPDATE: | 1695 case WINDOW_UPDATE: |
| 1633 return SpdyWindowUpdateControlFrame::size(); | 1696 return SpdyWindowUpdateControlFrame::size(); |
| 1634 case CREDENTIAL: | 1697 case CREDENTIAL: |
| 1635 return SpdyCredentialControlFrame::size(); | 1698 return SpdyCredentialControlFrame::size(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1675 case PING: | 1738 case PING: |
| 1676 case GOAWAY: | 1739 case GOAWAY: |
| 1677 case CREDENTIAL: | 1740 case CREDENTIAL: |
| 1678 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy | 1741 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy |
| 1679 break; | 1742 break; |
| 1680 } | 1743 } |
| 1681 } | 1744 } |
| 1682 return stream_id; | 1745 return stream_id; |
| 1683 } | 1746 } |
| 1684 | 1747 |
| 1685 size_t SpdyFramer::BytesSafeToRead() const { | |
| 1686 switch (state_) { | |
| 1687 case SPDY_ERROR: | |
| 1688 case SPDY_DONE: | |
| 1689 case SPDY_AUTO_RESET: | |
| 1690 case SPDY_RESET: | |
| 1691 return 0; | |
| 1692 case SPDY_READING_COMMON_HEADER: | |
| 1693 DCHECK_LT(current_frame_len_, | |
| 1694 static_cast<size_t>(SpdyFrame::kHeaderSize)); | |
| 1695 return SpdyFrame::kHeaderSize - current_frame_len_; | |
| 1696 // TODO(rtenneti): Add support for SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK | |
| 1697 // and SPDY_CONTROL_FRAME_HEADER_BLOCK. | |
| 1698 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: | |
| 1699 case SPDY_CONTROL_FRAME_HEADER_BLOCK: | |
| 1700 return 0; | |
| 1701 case SPDY_CONTROL_FRAME_PAYLOAD: | |
| 1702 case SPDY_CREDENTIAL_FRAME_PAYLOAD: | |
| 1703 case SPDY_IGNORE_REMAINING_PAYLOAD: | |
| 1704 case SPDY_FORWARD_STREAM_FRAME: | |
| 1705 return remaining_data_; | |
| 1706 } | |
| 1707 // We should never get to here. | |
| 1708 return 0; | |
| 1709 } | |
| 1710 | |
| 1711 void SpdyFramer::set_enable_compression(bool value) { | 1748 void SpdyFramer::set_enable_compression(bool value) { |
| 1712 enable_compression_ = value; | 1749 enable_compression_ = value; |
| 1713 } | 1750 } |
| 1714 | 1751 |
| 1752 void SpdyFramer::set_validate_control_frame_sizes(bool value) { | |
| 1753 validate_control_frame_sizes_ = value; | |
| 1754 } | |
| 1755 | |
| 1715 void SpdyFramer::set_enable_compression_default(bool value) { | 1756 void SpdyFramer::set_enable_compression_default(bool value) { |
| 1716 compression_default_ = value; | 1757 compression_default_ = value; |
| 1717 } | 1758 } |
| 1718 | 1759 |
| 1719 void SpdyFramer::set_validate_control_frame_sizes(bool value) { | |
| 1720 validate_control_frame_sizes_ = value; | |
| 1721 } | |
| 1722 | |
| 1723 } // namespace spdy | 1760 } // namespace spdy |
| OLD | NEW |