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