| 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 | |
| 6 // constantly adding and subtracting header sizes; this is ugly and error- | |
| 7 // prone. | |
| 8 | |
| 9 #include "net/spdy/spdy_framer.h" | 5 #include "net/spdy/spdy_framer.h" |
| 10 | 6 |
| 11 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 12 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/metrics/stats_counters.h" | 9 #include "base/metrics/stats_counters.h" |
| 14 #include "base/third_party/valgrind/memcheck.h" | 10 #include "base/third_party/valgrind/memcheck.h" |
| 15 #include "net/spdy/spdy_frame_builder.h" | 11 #include "net/spdy/spdy_frame_builder.h" |
| 16 #include "net/spdy/spdy_frame_reader.h" | 12 #include "net/spdy/spdy_frame_reader.h" |
| 17 #include "net/spdy/spdy_bitmasks.h" | 13 #include "net/spdy/spdy_bitmasks.h" |
| 18 #include "third_party/zlib/zlib.h" | 14 #include "third_party/zlib/zlib.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 #else | 69 #else |
| 74 #define CHANGE_STATE(newstate) \ | 70 #define CHANGE_STATE(newstate) \ |
| 75 do { \ | 71 do { \ |
| 76 DCHECK(state_ != SPDY_ERROR); \ | 72 DCHECK(state_ != SPDY_ERROR); \ |
| 77 DCHECK_EQ(previous_state_, state_); \ | 73 DCHECK_EQ(previous_state_, state_); \ |
| 78 previous_state_ = state_; \ | 74 previous_state_ = state_; \ |
| 79 state_ = newstate; \ | 75 state_ = newstate; \ |
| 80 } while (false) | 76 } while (false) |
| 81 #endif | 77 #endif |
| 82 | 78 |
| 83 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, | 79 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat( |
| 84 uint32 wire) { | 80 SpdyMajorVersion version, uint32 wire) { |
| 85 if (version < 3) { | 81 if (version < SPDY3) { |
| 86 ConvertFlagsAndIdForSpdy2(&wire); | 82 ConvertFlagsAndIdForSpdy2(&wire); |
| 87 } | 83 } |
| 88 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); | 84 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); |
| 89 } | 85 } |
| 90 | 86 |
| 91 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) | 87 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) |
| 92 : flags_(flags), id_(id & 0x00ffffff) { | 88 : flags_(flags), id_(id & 0x00ffffff) { |
| 93 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id; | 89 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id; |
| 94 } | 90 } |
| 95 | 91 |
| 96 uint32 SettingsFlagsAndId::GetWireFormat(int version) const { | 92 uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version) |
| 93 const { |
| 97 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); | 94 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); |
| 98 if (version < 3) { | 95 if (version < SPDY3) { |
| 99 ConvertFlagsAndIdForSpdy2(&wire); | 96 ConvertFlagsAndIdForSpdy2(&wire); |
| 100 } | 97 } |
| 101 return wire; | 98 return wire; |
| 102 } | 99 } |
| 103 | 100 |
| 104 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field. | 101 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field. |
| 105 // This method is used to preserve buggy behavior and works on both | 102 // This method is used to preserve buggy behavior and works on both |
| 106 // little-endian and big-endian hosts. | 103 // little-endian and big-endian hosts. |
| 107 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3 | 104 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3 |
| 108 // as well as vice versa). | 105 // as well as vice versa). |
| (...skipping 10 matching lines...) Expand all Loading... |
| 119 | 116 |
| 120 bool SpdyFramerVisitorInterface::OnRstStreamFrameData( | 117 bool SpdyFramerVisitorInterface::OnRstStreamFrameData( |
| 121 const char* rst_stream_data, | 118 const char* rst_stream_data, |
| 122 size_t len) { | 119 size_t len) { |
| 123 return true; | 120 return true; |
| 124 } | 121 } |
| 125 | 122 |
| 126 SpdyFramer::SpdyFramer(SpdyMajorVersion version) | 123 SpdyFramer::SpdyFramer(SpdyMajorVersion version) |
| 127 : current_frame_buffer_(new char[kControlFrameBufferSize]), | 124 : current_frame_buffer_(new char[kControlFrameBufferSize]), |
| 128 enable_compression_(true), | 125 enable_compression_(true), |
| 126 hpack_encoder_(ObtainHpackHuffmanTable()), |
| 129 hpack_decoder_(ObtainHpackHuffmanTable()), | 127 hpack_decoder_(ObtainHpackHuffmanTable()), |
| 130 visitor_(NULL), | 128 visitor_(NULL), |
| 131 debug_visitor_(NULL), | 129 debug_visitor_(NULL), |
| 132 display_protocol_("SPDY"), | 130 display_protocol_("SPDY"), |
| 133 spdy_version_(version), | 131 spdy_version_(version), |
| 134 syn_frame_processed_(false), | 132 syn_frame_processed_(false), |
| 135 probable_http_response_(false), | 133 probable_http_response_(false), |
| 136 expect_continuation_(0), | 134 expect_continuation_(0), |
| 137 end_stream_when_done_(false) { | 135 end_stream_when_done_(false) { |
| 138 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); | 136 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 159 current_frame_type_ = DATA; | 157 current_frame_type_ = DATA; |
| 160 current_frame_flags_ = 0; | 158 current_frame_flags_ = 0; |
| 161 current_frame_length_ = 0; | 159 current_frame_length_ = 0; |
| 162 current_frame_stream_id_ = kInvalidStream; | 160 current_frame_stream_id_ = kInvalidStream; |
| 163 settings_scratch_.Reset(); | 161 settings_scratch_.Reset(); |
| 164 remaining_padding_payload_length_ = 0; | 162 remaining_padding_payload_length_ = 0; |
| 165 remaining_padding_length_fields_ = 0; | 163 remaining_padding_length_fields_ = 0; |
| 166 } | 164 } |
| 167 | 165 |
| 168 size_t SpdyFramer::GetDataFrameMinimumSize() const { | 166 size_t SpdyFramer::GetDataFrameMinimumSize() const { |
| 169 // Size, in bytes, of the data frame header. Future versions of SPDY | 167 return SpdyConstants::GetDataFrameMinimumSize(); |
| 170 // will likely vary this, so we allow for the flexibility of a function call | |
| 171 // for this value as opposed to a constant. | |
| 172 return 8; | |
| 173 } | 168 } |
| 174 | 169 |
| 175 // Size, in bytes, of the control frame header. | 170 // Size, in bytes, of the control frame header. |
| 176 size_t SpdyFramer::GetControlFrameHeaderSize() const { | 171 size_t SpdyFramer::GetControlFrameHeaderSize() const { |
| 177 switch (protocol_version()) { | 172 return SpdyConstants::GetControlFrameHeaderSize(protocol_version()); |
| 178 case SPDY2: | |
| 179 case SPDY3: | |
| 180 case SPDY4: | |
| 181 return 8; | |
| 182 } | |
| 183 LOG(DFATAL) << "Unhandled SPDY version."; | |
| 184 return 0; | |
| 185 } | 173 } |
| 186 | 174 |
| 187 size_t SpdyFramer::GetSynStreamMinimumSize() const { | 175 size_t SpdyFramer::GetSynStreamMinimumSize() const { |
| 188 // Size, in bytes, of a SYN_STREAM frame not including the variable-length | 176 // Size, in bytes, of a SYN_STREAM frame not including the variable-length |
| 189 // name-value block. | 177 // name-value block. |
| 190 if (protocol_version() <= SPDY3) { | 178 if (protocol_version() <= SPDY3) { |
| 191 // Calculated as: | 179 // Calculated as: |
| 192 // control frame header + 2 * 4 (stream IDs) + 1 (priority) | 180 // control frame header + 2 * 4 (stream IDs) + 1 (priority) |
| 193 // + 1 (unused, was credential slot) | 181 // + 1 (unused, was credential slot) |
| 194 return GetControlFrameHeaderSize() + 10; | 182 return GetControlFrameHeaderSize() + 10; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 | 244 |
| 257 size_t SpdyFramer::GetGoAwayMinimumSize() const { | 245 size_t SpdyFramer::GetGoAwayMinimumSize() const { |
| 258 // Size, in bytes, of this GOAWAY frame. Calculated as: | 246 // Size, in bytes, of this GOAWAY frame. Calculated as: |
| 259 // 1. Control frame header size | 247 // 1. Control frame header size |
| 260 size_t size = GetControlFrameHeaderSize(); | 248 size_t size = GetControlFrameHeaderSize(); |
| 261 | 249 |
| 262 // 2. Last good stream id (4 bytes) | 250 // 2. Last good stream id (4 bytes) |
| 263 size += 4; | 251 size += 4; |
| 264 | 252 |
| 265 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes) | 253 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes) |
| 266 if (protocol_version() >= 3) { | 254 if (protocol_version() >= SPDY3) { |
| 267 size += 4; | 255 size += 4; |
| 268 } | 256 } |
| 269 | 257 |
| 270 return size; | 258 return size; |
| 271 } | 259 } |
| 272 | 260 |
| 273 size_t SpdyFramer::GetHeadersMinimumSize() const { | 261 size_t SpdyFramer::GetHeadersMinimumSize() const { |
| 274 // Size, in bytes, of a HEADERS frame not including the variable-length | 262 // Size, in bytes, of a HEADERS frame not including the variable-length |
| 275 // name-value block. | 263 // name-value block. |
| 276 size_t size = GetControlFrameHeaderSize(); | 264 size_t size = GetControlFrameHeaderSize(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 295 // control frame header + 4 (stream id) + 4 (delta) | 283 // control frame header + 4 (stream id) + 4 (delta) |
| 296 return GetControlFrameHeaderSize() + 8; | 284 return GetControlFrameHeaderSize() + 8; |
| 297 } else { | 285 } else { |
| 298 // Calculated as: | 286 // Calculated as: |
| 299 // frame prefix + 4 (delta) | 287 // frame prefix + 4 (delta) |
| 300 return GetControlFrameHeaderSize() + 4; | 288 return GetControlFrameHeaderSize() + 4; |
| 301 } | 289 } |
| 302 } | 290 } |
| 303 | 291 |
| 304 size_t SpdyFramer::GetBlockedSize() const { | 292 size_t SpdyFramer::GetBlockedSize() const { |
| 305 DCHECK_LE(4, protocol_version()); | 293 DCHECK_LT(SPDY3, protocol_version()); |
| 306 // Size, in bytes, of a BLOCKED frame. | 294 // Size, in bytes, of a BLOCKED frame. |
| 307 // The BLOCKED frame has no payload beyond the control frame header. | 295 // The BLOCKED frame has no payload beyond the control frame header. |
| 308 return GetControlFrameHeaderSize(); | 296 return GetControlFrameHeaderSize(); |
| 309 } | 297 } |
| 310 | 298 |
| 311 size_t SpdyFramer::GetPushPromiseMinimumSize() const { | 299 size_t SpdyFramer::GetPushPromiseMinimumSize() const { |
| 312 DCHECK_LE(4, protocol_version()); | 300 DCHECK_LT(SPDY3, protocol_version()); |
| 313 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block. | 301 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block. |
| 314 // Calculated as frame prefix + 4 (promised stream id). | 302 // Calculated as frame prefix + 4 (promised stream id). |
| 315 return GetControlFrameHeaderSize() + 4; | 303 return GetControlFrameHeaderSize() + 4; |
| 316 } | 304 } |
| 317 | 305 |
| 318 size_t SpdyFramer::GetContinuationMinimumSize() const { | 306 size_t SpdyFramer::GetContinuationMinimumSize() const { |
| 319 // Size, in bytes, of a CONTINUATION frame not including the variable-length | 307 // Size, in bytes, of a CONTINUATION frame not including the variable-length |
| 320 // headers fragments. | 308 // headers fragments. |
| 321 return GetControlFrameHeaderSize(); | 309 return GetControlFrameHeaderSize(); |
| 322 } | 310 } |
| 323 | 311 |
| 324 size_t SpdyFramer::GetFrameMinimumSize() const { | 312 size_t SpdyFramer::GetFrameMinimumSize() const { |
| 325 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); | 313 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); |
| 326 } | 314 } |
| 327 | 315 |
| 328 size_t SpdyFramer::GetFrameMaximumSize() const { | 316 size_t SpdyFramer::GetFrameMaximumSize() const { |
| 329 if (protocol_version() <= SPDY3) { | 317 return SpdyConstants::GetFrameMaximumSize(protocol_version()); |
| 330 // 24-bit length field plus eight-byte frame header. | |
| 331 return ((1<<24) - 1) + 8; | |
| 332 } else { | |
| 333 // 14-bit length field. | |
| 334 return (1<<14) - 1; | |
| 335 } | |
| 336 } | 318 } |
| 337 | 319 |
| 338 size_t SpdyFramer::GetDataFrameMaximumPayload() const { | 320 size_t SpdyFramer::GetDataFrameMaximumPayload() const { |
| 339 return GetFrameMaximumSize() - GetDataFrameMinimumSize(); | 321 return GetFrameMaximumSize() - GetDataFrameMinimumSize(); |
| 340 } | 322 } |
| 341 | 323 |
| 324 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const { |
| 325 return SpdyConstants::GetPrefixLength(type, protocol_version()); |
| 326 } |
| 327 |
| 342 const char* SpdyFramer::StateToString(int state) { | 328 const char* SpdyFramer::StateToString(int state) { |
| 343 switch (state) { | 329 switch (state) { |
| 344 case SPDY_ERROR: | 330 case SPDY_ERROR: |
| 345 return "ERROR"; | 331 return "ERROR"; |
| 346 case SPDY_AUTO_RESET: | 332 case SPDY_AUTO_RESET: |
| 347 return "AUTO_RESET"; | 333 return "AUTO_RESET"; |
| 348 case SPDY_RESET: | 334 case SPDY_RESET: |
| 349 return "RESET"; | 335 return "RESET"; |
| 350 case SPDY_READING_COMMON_HEADER: | 336 case SPDY_READING_COMMON_HEADER: |
| 351 return "READING_COMMON_HEADER"; | 337 return "READING_COMMON_HEADER"; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 case RST_STREAM_FLOW_CONTROL_ERROR: | 417 case RST_STREAM_FLOW_CONTROL_ERROR: |
| 432 return "FLOW_CONTROL_ERROR"; | 418 return "FLOW_CONTROL_ERROR"; |
| 433 case RST_STREAM_STREAM_IN_USE: | 419 case RST_STREAM_STREAM_IN_USE: |
| 434 return "STREAM_IN_USE"; | 420 return "STREAM_IN_USE"; |
| 435 case RST_STREAM_STREAM_ALREADY_CLOSED: | 421 case RST_STREAM_STREAM_ALREADY_CLOSED: |
| 436 return "STREAM_ALREADY_CLOSED"; | 422 return "STREAM_ALREADY_CLOSED"; |
| 437 case RST_STREAM_INVALID_CREDENTIALS: | 423 case RST_STREAM_INVALID_CREDENTIALS: |
| 438 return "INVALID_CREDENTIALS"; | 424 return "INVALID_CREDENTIALS"; |
| 439 case RST_STREAM_FRAME_TOO_LARGE: | 425 case RST_STREAM_FRAME_TOO_LARGE: |
| 440 return "FRAME_TOO_LARGE"; | 426 return "FRAME_TOO_LARGE"; |
| 427 case RST_STREAM_CONNECT_ERROR: |
| 428 return "CONNECT_ERROR"; |
| 429 case RST_STREAM_ENHANCE_YOUR_CALM: |
| 430 return "ENHANCE_YOUR_CALM"; |
| 441 } | 431 } |
| 442 return "UNKNOWN_STATUS"; | 432 return "UNKNOWN_STATUS"; |
| 443 } | 433 } |
| 444 | 434 |
| 445 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) { | 435 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) { |
| 446 switch (type) { | 436 switch (type) { |
| 447 case DATA: | 437 case DATA: |
| 448 return "DATA"; | 438 return "DATA"; |
| 449 case SYN_STREAM: | 439 case SYN_STREAM: |
| 450 return "SYN_STREAM"; | 440 return "SYN_STREAM"; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 break; | 555 break; |
| 566 } | 556 } |
| 567 | 557 |
| 568 case SPDY_CONSUME_PADDING: { | 558 case SPDY_CONSUME_PADDING: { |
| 569 size_t bytes_read = ProcessFramePadding(data, len); | 559 size_t bytes_read = ProcessFramePadding(data, len); |
| 570 len -= bytes_read; | 560 len -= bytes_read; |
| 571 data += bytes_read; | 561 data += bytes_read; |
| 572 break; | 562 break; |
| 573 } | 563 } |
| 574 | 564 |
| 575 case SPDY_IGNORE_REMAINING_PAYLOAD: | 565 case SPDY_IGNORE_REMAINING_PAYLOAD: { |
| 576 // control frame has too-large payload | 566 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len); |
| 577 // intentional fallthrough | 567 len -= bytes_read; |
| 568 data += bytes_read; |
| 569 break; |
| 570 } |
| 571 |
| 578 case SPDY_FORWARD_STREAM_FRAME: { | 572 case SPDY_FORWARD_STREAM_FRAME: { |
| 579 size_t bytes_read = ProcessDataFramePayload(data, len); | 573 size_t bytes_read = ProcessDataFramePayload(data, len); |
| 580 len -= bytes_read; | 574 len -= bytes_read; |
| 581 data += bytes_read; | 575 data += bytes_read; |
| 582 break; | 576 break; |
| 583 } | 577 } |
| 578 |
| 584 default: | 579 default: |
| 585 LOG(DFATAL) << "Invalid value for " << display_protocol_ | 580 LOG(DFATAL) << "Invalid value for " << display_protocol_ |
| 586 << " framer state: " << state_; | 581 << " framer state: " << state_; |
| 587 // This ensures that we don't infinite-loop if state_ gets an | 582 // This ensures that we don't infinite-loop if state_ gets an |
| 588 // invalid value somehow, such as due to a SpdyFramer getting deleted | 583 // invalid value somehow, such as due to a SpdyFramer getting deleted |
| 589 // from a callback it calls. | 584 // from a callback it calls. |
| 590 goto bottom; | 585 goto bottom; |
| 591 } | 586 } |
| 592 } while (state_ != previous_state_); | 587 } while (state_ != previous_state_); |
| 593 bottom: | 588 bottom: |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 | 627 |
| 633 uint16 control_frame_type_field = DATA; | 628 uint16 control_frame_type_field = DATA; |
| 634 // ProcessControlFrameHeader() will set current_frame_type_ to the | 629 // ProcessControlFrameHeader() will set current_frame_type_ to the |
| 635 // correct value if this is a valid control frame. | 630 // correct value if this is a valid control frame. |
| 636 current_frame_type_ = DATA; | 631 current_frame_type_ = DATA; |
| 637 if (protocol_version() <= SPDY3) { | 632 if (protocol_version() <= SPDY3) { |
| 638 bool successful_read = reader->ReadUInt16(&version); | 633 bool successful_read = reader->ReadUInt16(&version); |
| 639 DCHECK(successful_read); | 634 DCHECK(successful_read); |
| 640 is_control_frame = (version & kControlFlagMask) != 0; | 635 is_control_frame = (version & kControlFlagMask) != 0; |
| 641 version &= ~kControlFlagMask; // Only valid for control frames. | 636 version &= ~kControlFlagMask; // Only valid for control frames. |
| 642 | |
| 643 if (is_control_frame) { | 637 if (is_control_frame) { |
| 638 // We check version before we check validity: version can never be |
| 639 // 'invalid', it can only be unsupported. |
| 640 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) || |
| 641 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) || |
| 642 SpdyConstants::ParseMajorVersion(version) != protocol_version()) { |
| 643 // Version does not match the version the framer was initialized with. |
| 644 DVLOG(1) << "Unsupported SPDY version " |
| 645 << version |
| 646 << " (expected " << protocol_version() << ")"; |
| 647 set_error(SPDY_UNSUPPORTED_VERSION); |
| 648 return 0; |
| 649 } else { |
| 650 // Convert version from wire format to SpdyMajorVersion. |
| 651 version = SpdyConstants::ParseMajorVersion(version); |
| 652 } |
| 644 // We check control_frame_type_field's validity in | 653 // We check control_frame_type_field's validity in |
| 645 // ProcessControlFrameHeader(). | 654 // ProcessControlFrameHeader(). |
| 646 successful_read = reader->ReadUInt16(&control_frame_type_field); | 655 successful_read = reader->ReadUInt16(&control_frame_type_field); |
| 647 } else { | 656 } else { |
| 648 reader->Rewind(); | 657 reader->Rewind(); |
| 649 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); | 658 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); |
| 650 } | 659 } |
| 651 DCHECK(successful_read); | 660 DCHECK(successful_read); |
| 652 | 661 |
| 653 successful_read = reader->ReadUInt8(¤t_frame_flags_); | 662 successful_read = reader->ReadUInt8(¤t_frame_flags_); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); | 758 CHANGE_STATE(SPDY_READ_PADDING_LENGTH); |
| 750 } else { | 759 } else { |
| 751 // Empty data frame. | 760 // Empty data frame. |
| 752 if (current_frame_flags_ & DATA_FLAG_FIN) { | 761 if (current_frame_flags_ & DATA_FLAG_FIN) { |
| 753 visitor_->OnStreamFrameData( | 762 visitor_->OnStreamFrameData( |
| 754 current_frame_stream_id_, NULL, 0, true); | 763 current_frame_stream_id_, NULL, 0, true); |
| 755 } | 764 } |
| 756 CHANGE_STATE(SPDY_AUTO_RESET); | 765 CHANGE_STATE(SPDY_AUTO_RESET); |
| 757 } | 766 } |
| 758 } | 767 } |
| 759 } else if (version != protocol_version()) { | |
| 760 // We check version before we check validity: version can never be | |
| 761 // 'invalid', it can only be unsupported. | |
| 762 DVLOG(1) << "Unsupported SPDY version " << version | |
| 763 << " (expected " << protocol_version() << ")"; | |
| 764 set_error(SPDY_UNSUPPORTED_VERSION); | |
| 765 } else { | 768 } else { |
| 766 ProcessControlFrameHeader(control_frame_type_field); | 769 ProcessControlFrameHeader(control_frame_type_field); |
| 767 } | 770 } |
| 768 | 771 |
| 769 return original_len - len; | 772 return original_len - len; |
| 770 } | 773 } |
| 771 | 774 |
| 772 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { | 775 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { |
| 773 DCHECK_EQ(SPDY_NO_ERROR, error_code_); | 776 DCHECK_EQ(SPDY_NO_ERROR, error_code_); |
| 774 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); | 777 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 if (current_frame_length_ < GetPushPromiseMinimumSize()) { | 923 if (current_frame_length_ < GetPushPromiseMinimumSize()) { |
| 921 set_error(SPDY_INVALID_CONTROL_FRAME); | 924 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 922 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { | 925 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { |
| 923 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 926 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 924 } else if (protocol_version() > SPDY3 && current_frame_flags_ & | 927 } else if (protocol_version() > SPDY3 && current_frame_flags_ & |
| 925 ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE) { | 928 ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE) { |
| 926 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 929 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 927 } | 930 } |
| 928 break; | 931 break; |
| 929 case CONTINUATION: | 932 case CONTINUATION: |
| 930 if (current_frame_length_ < GetContinuationMinimumSize()) { | 933 if (current_frame_length_ < GetContinuationMinimumSize() || |
| 934 protocol_version() <= SPDY3) { |
| 931 set_error(SPDY_INVALID_CONTROL_FRAME); | 935 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 932 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) { | 936 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) { |
| 933 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); | 937 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
| 934 } | 938 } |
| 935 break; | 939 break; |
| 936 default: | 940 default: |
| 937 LOG(WARNING) << "Valid " << display_protocol_ | 941 LOG(WARNING) << "Valid " << display_protocol_ |
| 938 << " control frame with unhandled type: " | 942 << " control frame with unhandled type: " |
| 939 << current_frame_type_; | 943 << current_frame_type_; |
| 940 // This branch should be unreachable because of the frame type bounds | 944 // This branch should be unreachable because of the frame type bounds |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1036 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_, | 1040 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_, |
| 1037 *data, | 1041 *data, |
| 1038 bytes_to_read); | 1042 bytes_to_read); |
| 1039 current_frame_buffer_length_ += bytes_to_read; | 1043 current_frame_buffer_length_ += bytes_to_read; |
| 1040 *data += bytes_to_read; | 1044 *data += bytes_to_read; |
| 1041 *len -= bytes_to_read; | 1045 *len -= bytes_to_read; |
| 1042 } | 1046 } |
| 1043 return bytes_to_read; | 1047 return bytes_to_read; |
| 1044 } | 1048 } |
| 1045 | 1049 |
| 1046 size_t SpdyFramer::GetSerializedLength(const int spdy_version, | 1050 size_t SpdyFramer::GetSerializedLength( |
| 1047 const SpdyHeaderBlock* headers) { | 1051 const SpdyMajorVersion spdy_version, |
| 1052 const SpdyHeaderBlock* headers) { |
| 1048 const size_t num_name_value_pairs_size | 1053 const size_t num_name_value_pairs_size |
| 1049 = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32); | 1054 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32); |
| 1050 const size_t length_of_name_size = num_name_value_pairs_size; | 1055 const size_t length_of_name_size = num_name_value_pairs_size; |
| 1051 const size_t length_of_value_size = num_name_value_pairs_size; | 1056 const size_t length_of_value_size = num_name_value_pairs_size; |
| 1052 | 1057 |
| 1053 size_t total_length = num_name_value_pairs_size; | 1058 size_t total_length = num_name_value_pairs_size; |
| 1054 for (SpdyHeaderBlock::const_iterator it = headers->begin(); | 1059 for (SpdyHeaderBlock::const_iterator it = headers->begin(); |
| 1055 it != headers->end(); | 1060 it != headers->end(); |
| 1056 ++it) { | 1061 ++it) { |
| 1057 // We add space for the length of the name and the length of the value as | 1062 // We add space for the length of the name and the length of the value as |
| 1058 // well as the length of the name and the length of the value. | 1063 // well as the length of the name and the length of the value. |
| 1059 total_length += length_of_name_size + it->first.size() + | 1064 total_length += length_of_name_size + it->first.size() + |
| 1060 length_of_value_size + it->second.size(); | 1065 length_of_value_size + it->second.size(); |
| 1061 } | 1066 } |
| 1062 return total_length; | 1067 return total_length; |
| 1063 } | 1068 } |
| 1064 | 1069 |
| 1065 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, | 1070 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, |
| 1066 const int spdy_version, | 1071 const SpdyMajorVersion spdy_version, |
| 1067 const SpdyHeaderBlock* headers) { | 1072 const SpdyHeaderBlock* headers) { |
| 1068 if (spdy_version < 3) { | 1073 if (spdy_version < SPDY3) { |
| 1069 frame->WriteUInt16(headers->size()); // Number of headers. | 1074 frame->WriteUInt16(headers->size()); // Number of headers. |
| 1070 } else { | 1075 } else { |
| 1071 frame->WriteUInt32(headers->size()); // Number of headers. | 1076 frame->WriteUInt32(headers->size()); // Number of headers. |
| 1072 } | 1077 } |
| 1073 SpdyHeaderBlock::const_iterator it; | 1078 SpdyHeaderBlock::const_iterator it; |
| 1074 for (it = headers->begin(); it != headers->end(); ++it) { | 1079 for (it = headers->begin(); it != headers->end(); ++it) { |
| 1075 if (spdy_version < 3) { | 1080 if (spdy_version < SPDY3) { |
| 1076 frame->WriteString(it->first); | 1081 frame->WriteString(it->first); |
| 1077 frame->WriteString(it->second); | 1082 frame->WriteString(it->second); |
| 1078 } else { | 1083 } else { |
| 1079 frame->WriteStringPiece32(it->first); | 1084 frame->WriteStringPiece32(it->first); |
| 1080 frame->WriteStringPiece32(it->second); | 1085 frame->WriteStringPiece32(it->second); |
| 1081 } | 1086 } |
| 1082 } | 1087 } |
| 1083 } | 1088 } |
| 1084 | 1089 |
| 1085 // TODO(phajdan.jr): Clean up after we no longer need | 1090 // TODO(phajdan.jr): Clean up after we no longer need |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 DCHECK_LT(SPDY3, protocol_version()); | 1595 DCHECK_LT(SPDY3, protocol_version()); |
| 1591 DCHECK_EQ(0u, remaining_data_length_); | 1596 DCHECK_EQ(0u, remaining_data_length_); |
| 1592 | 1597 |
| 1593 const SpdyNameValueBlock& block = hpack_decoder_.decoded_block(); | 1598 const SpdyNameValueBlock& block = hpack_decoder_.decoded_block(); |
| 1594 if (block.empty()) { | 1599 if (block.empty()) { |
| 1595 // Special-case this to make tests happy. | 1600 // Special-case this to make tests happy. |
| 1596 ProcessControlFrameHeaderBlock(NULL, 0, false); | 1601 ProcessControlFrameHeaderBlock(NULL, 0, false); |
| 1597 return; | 1602 return; |
| 1598 } | 1603 } |
| 1599 SpdyFrameBuilder builder( | 1604 SpdyFrameBuilder builder( |
| 1600 GetSerializedLength(protocol_version(), &block)); | 1605 GetSerializedLength(protocol_version(), &block), |
| 1606 SPDY3); |
| 1601 | 1607 |
| 1602 SerializeNameValueBlockWithoutCompression(&builder, block); | 1608 SerializeNameValueBlockWithoutCompression(&builder, block); |
| 1603 scoped_ptr<SpdyFrame> frame(builder.take()); | 1609 scoped_ptr<SpdyFrame> frame(builder.take()); |
| 1604 | 1610 |
| 1605 remaining_data_length_ = frame->size(); | 1611 remaining_data_length_ = frame->size(); |
| 1606 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); | 1612 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); |
| 1607 } | 1613 } |
| 1608 | 1614 |
| 1609 bool SpdyFramer::ProcessSetting(const char* data) { | 1615 bool SpdyFramer::ProcessSetting(const char* data) { |
| 1610 int id_field; | 1616 int id_field; |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1743 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. | 1749 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. |
| 1744 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); | 1750 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
| 1745 DCHECK(successful_read); | 1751 DCHECK(successful_read); |
| 1746 | 1752 |
| 1747 // In SPDYv3 and up, frames also specify a status code - parse it out. | 1753 // In SPDYv3 and up, frames also specify a status code - parse it out. |
| 1748 SpdyGoAwayStatus status = GOAWAY_OK; | 1754 SpdyGoAwayStatus status = GOAWAY_OK; |
| 1749 if (protocol_version() >= SPDY3) { | 1755 if (protocol_version() >= SPDY3) { |
| 1750 uint32 status_raw = GOAWAY_OK; | 1756 uint32 status_raw = GOAWAY_OK; |
| 1751 successful_read = reader.ReadUInt32(&status_raw); | 1757 successful_read = reader.ReadUInt32(&status_raw); |
| 1752 DCHECK(successful_read); | 1758 DCHECK(successful_read); |
| 1753 // We've read an unsigned integer, so it's enough to only check | 1759 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(), |
| 1754 // upper bound to ensure the value is in valid range. | 1760 status_raw)) { |
| 1755 if (status_raw < GOAWAY_NUM_STATUS_CODES) { | 1761 status = SpdyConstants::ParseGoAwayStatus(protocol_version(), |
| 1756 status = static_cast<SpdyGoAwayStatus>(status_raw); | 1762 status_raw); |
| 1757 } else { | 1763 } else { |
| 1758 // TODO(hkhalil): Probably best to OnError here, depending on | |
| 1759 // our interpretation of the spec. Keeping with existing liberal | |
| 1760 // behavior for now. | |
| 1761 DCHECK(false); | 1764 DCHECK(false); |
| 1765 // Throw an error for SPDY4+, keep liberal behavior |
| 1766 // for earlier versions. |
| 1767 if (protocol_version() > SPDY3) { |
| 1768 DLOG(WARNING) << "Invalid GO_AWAY status " << status_raw; |
| 1769 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 1770 return 0; |
| 1771 } |
| 1762 } | 1772 } |
| 1763 } | 1773 } |
| 1764 // Finished parsing the GOAWAY header, call frame handler. | 1774 // Finished parsing the GOAWAY header, call frame handler. |
| 1765 visitor_->OnGoAway(current_frame_stream_id_, status); | 1775 visitor_->OnGoAway(current_frame_stream_id_, status); |
| 1766 } | 1776 } |
| 1767 } | 1777 } |
| 1768 | 1778 |
| 1769 // Handle remaining data as opaque. | 1779 // Handle remaining data as opaque. |
| 1770 bool processed_successfully = true; | 1780 bool processed_successfully = true; |
| 1771 if (len > 0) { | 1781 if (len > 0) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1809 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. | 1819 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. |
| 1810 if (protocol_version() <= SPDY3) { | 1820 if (protocol_version() <= SPDY3) { |
| 1811 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); | 1821 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
| 1812 DCHECK(successful_read); | 1822 DCHECK(successful_read); |
| 1813 } | 1823 } |
| 1814 | 1824 |
| 1815 SpdyRstStreamStatus status = RST_STREAM_INVALID; | 1825 SpdyRstStreamStatus status = RST_STREAM_INVALID; |
| 1816 uint32 status_raw = status; | 1826 uint32 status_raw = status; |
| 1817 bool successful_read = reader.ReadUInt32(&status_raw); | 1827 bool successful_read = reader.ReadUInt32(&status_raw); |
| 1818 DCHECK(successful_read); | 1828 DCHECK(successful_read); |
| 1819 // We've read an unsigned integer, so it's enough to only check | 1829 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(), |
| 1820 // upper bound to ensure the value is in valid range. | 1830 status_raw)) { |
| 1821 if (status_raw > RST_STREAM_INVALID && | |
| 1822 status_raw < RST_STREAM_NUM_STATUS_CODES) { | |
| 1823 status = static_cast<SpdyRstStreamStatus>(status_raw); | 1831 status = static_cast<SpdyRstStreamStatus>(status_raw); |
| 1824 } else { | 1832 } else { |
| 1825 // TODO(hkhalil): Probably best to OnError here, depending on | 1833 // Throw an error for SPDY4+, keep liberal behavior |
| 1826 // our interpretation of the spec. Keeping with existing liberal | 1834 // for earlier versions. |
| 1827 // behavior for now. | 1835 if (protocol_version() > SPDY3) { |
| 1836 DLOG(WARNING) << "Invalid RST_STREAM status " << status_raw; |
| 1837 set_error(SPDY_INVALID_CONTROL_FRAME); |
| 1838 return 0; |
| 1839 } |
| 1828 } | 1840 } |
| 1829 // Finished parsing the RST_STREAM header, call frame handler. | 1841 // Finished parsing the RST_STREAM header, call frame handler. |
| 1830 visitor_->OnRstStream(current_frame_stream_id_, status); | 1842 visitor_->OnRstStream(current_frame_stream_id_, status); |
| 1831 } | 1843 } |
| 1832 } | 1844 } |
| 1833 | 1845 |
| 1834 // Handle remaining data as opaque. | 1846 // Handle remaining data as opaque. |
| 1835 bool processed_successfully = true; | 1847 bool processed_successfully = true; |
| 1836 if (len > 0) { | 1848 if (len > 0) { |
| 1837 processed_successfully = visitor_->OnRstStreamFrameData(data, len); | 1849 processed_successfully = visitor_->OnRstStreamFrameData(data, len); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1848 } | 1860 } |
| 1849 | 1861 |
| 1850 size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) { | 1862 size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) { |
| 1851 DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_); | 1863 DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_); |
| 1852 | 1864 |
| 1853 size_t original_len = len; | 1865 size_t original_len = len; |
| 1854 if (remaining_padding_length_fields_ == 0) { | 1866 if (remaining_padding_length_fields_ == 0) { |
| 1855 DCHECK_EQ(remaining_padding_payload_length_, 0u); | 1867 DCHECK_EQ(remaining_padding_payload_length_, 0u); |
| 1856 bool pad_low = false; | 1868 bool pad_low = false; |
| 1857 bool pad_high = false; | 1869 bool pad_high = false; |
| 1858 if (current_frame_flags_ & net::DATA_FLAG_PAD_LOW) { | 1870 if (current_frame_flags_ & DATA_FLAG_PAD_LOW) { |
| 1859 pad_low = true; | 1871 pad_low = true; |
| 1860 ++remaining_padding_length_fields_; | 1872 ++remaining_padding_length_fields_; |
| 1861 } | 1873 } |
| 1862 if (current_frame_flags_ & net::DATA_FLAG_PAD_HIGH) { | 1874 if (current_frame_flags_ & DATA_FLAG_PAD_HIGH) { |
| 1863 pad_high = true; | 1875 pad_high = true; |
| 1864 ++remaining_padding_length_fields_; | 1876 ++remaining_padding_length_fields_; |
| 1865 } | 1877 } |
| 1866 if ((pad_high && !pad_low) || | 1878 if ((pad_high && !pad_low) || |
| 1867 remaining_data_length_ < remaining_padding_length_fields_) { | 1879 remaining_data_length_ < remaining_padding_length_fields_) { |
| 1868 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); | 1880 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); |
| 1869 return 0; | 1881 return 0; |
| 1870 } | 1882 } |
| 1871 } | 1883 } |
| 1872 | 1884 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1902 // Communicate the padding to the visitor through a NULL data pointer, with | 1914 // Communicate the padding to the visitor through a NULL data pointer, with |
| 1903 // a nonzero size. | 1915 // a nonzero size. |
| 1904 if (amount_to_discard) { | 1916 if (amount_to_discard) { |
| 1905 visitor_->OnStreamFrameData( | 1917 visitor_->OnStreamFrameData( |
| 1906 current_frame_stream_id_, NULL, amount_to_discard, false); | 1918 current_frame_stream_id_, NULL, amount_to_discard, false); |
| 1907 } | 1919 } |
| 1908 data += amount_to_discard; | 1920 data += amount_to_discard; |
| 1909 len -= amount_to_discard; | 1921 len -= amount_to_discard; |
| 1910 remaining_padding_payload_length_ -= amount_to_discard; | 1922 remaining_padding_payload_length_ -= amount_to_discard; |
| 1911 remaining_data_length_ -= amount_to_discard; | 1923 remaining_data_length_ -= amount_to_discard; |
| 1912 | |
| 1913 // If the FIN flag is set, and there is no more data in this data | |
| 1914 // frame, inform the visitor of EOF via a 0-length data frame. | |
| 1915 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) { | |
| 1916 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); | |
| 1917 } | |
| 1918 } | 1924 } |
| 1919 | 1925 |
| 1920 if (remaining_data_length_ == 0) { | 1926 if (remaining_data_length_ == 0) { |
| 1927 // If the FIN flag is set, and there is no more data in this data frame, |
| 1928 // inform the visitor of EOF via a 0-length data frame. |
| 1929 if (current_frame_flags_ & DATA_FLAG_FIN) { |
| 1930 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); |
| 1931 } |
| 1932 |
| 1921 CHANGE_STATE(SPDY_AUTO_RESET); | 1933 CHANGE_STATE(SPDY_AUTO_RESET); |
| 1922 } | 1934 } |
| 1923 return original_len - len; | 1935 return original_len - len; |
| 1924 } | 1936 } |
| 1925 | 1937 |
| 1926 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { | 1938 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { |
| 1927 size_t original_len = len; | 1939 size_t original_len = len; |
| 1928 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) { | 1940 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) { |
| 1929 size_t amount_to_forward = std::min( | 1941 size_t amount_to_forward = std::min( |
| 1930 remaining_data_length_ - remaining_padding_payload_length_, len); | 1942 remaining_data_length_ - remaining_padding_payload_length_, len); |
| 1931 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { | 1943 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { |
| 1932 // Only inform the visitor if there is data. | 1944 // Only inform the visitor if there is data. |
| 1933 if (amount_to_forward) { | 1945 if (amount_to_forward) { |
| 1934 visitor_->OnStreamFrameData( | 1946 visitor_->OnStreamFrameData( |
| 1935 current_frame_stream_id_, data, amount_to_forward, false); | 1947 current_frame_stream_id_, data, amount_to_forward, false); |
| 1936 } | 1948 } |
| 1937 } | 1949 } |
| 1938 data += amount_to_forward; | 1950 data += amount_to_forward; |
| 1939 len -= amount_to_forward; | 1951 len -= amount_to_forward; |
| 1940 remaining_data_length_ -= amount_to_forward; | 1952 remaining_data_length_ -= amount_to_forward; |
| 1941 | |
| 1942 // If the FIN flag is set, and there is no more data in this data | |
| 1943 // frame, inform the visitor of EOF via a 0-length data frame. | |
| 1944 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) { | |
| 1945 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); | |
| 1946 } | |
| 1947 } | 1953 } |
| 1948 | 1954 |
| 1949 if (remaining_data_length_ == remaining_padding_payload_length_) { | 1955 if (remaining_data_length_ == remaining_padding_payload_length_) { |
| 1950 CHANGE_STATE(SPDY_CONSUME_PADDING); | 1956 CHANGE_STATE(SPDY_CONSUME_PADDING); |
| 1951 } | 1957 } |
| 1952 return original_len - len; | 1958 return original_len - len; |
| 1953 } | 1959 } |
| 1954 | 1960 |
| 1961 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/ |
| 1962 size_t len) { |
| 1963 size_t original_len = len; |
| 1964 if (remaining_data_length_ > 0) { |
| 1965 size_t amount_to_ignore = std::min(remaining_data_length_, len); |
| 1966 len -= amount_to_ignore; |
| 1967 remaining_data_length_ -= amount_to_ignore; |
| 1968 } |
| 1969 |
| 1970 if (remaining_data_length_ == 0) { |
| 1971 CHANGE_STATE(SPDY_AUTO_RESET); |
| 1972 } |
| 1973 return original_len - len; |
| 1974 } |
| 1975 |
| 1955 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, | 1976 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, |
| 1956 size_t header_length, | 1977 size_t header_length, |
| 1957 SpdyHeaderBlock* block) const { | 1978 SpdyHeaderBlock* block) const { |
| 1958 SpdyFrameReader reader(header_data, header_length); | 1979 SpdyFrameReader reader(header_data, header_length); |
| 1959 | 1980 |
| 1960 // Read number of headers. | 1981 // Read number of headers. |
| 1961 uint32 num_headers; | 1982 uint32 num_headers; |
| 1962 if (protocol_version() <= SPDY2) { | 1983 if (protocol_version() <= SPDY2) { |
| 1963 uint16 temp; | 1984 uint16 temp; |
| 1964 if (!reader.ReadUInt16(&temp)) { | 1985 if (!reader.ReadUInt16(&temp)) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 << num_headers << ")."; | 2022 << num_headers << ")."; |
| 2002 return 0; | 2023 return 0; |
| 2003 } | 2024 } |
| 2004 | 2025 |
| 2005 // Store header. | 2026 // Store header. |
| 2006 (*block)[name] = value; | 2027 (*block)[name] = value; |
| 2007 } | 2028 } |
| 2008 return reader.GetBytesConsumed(); | 2029 return reader.GetBytesConsumed(); |
| 2009 } | 2030 } |
| 2010 | 2031 |
| 2011 SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& datair) const { | 2032 SpdySerializedFrame* SpdyFramer::SerializeData( |
| 2033 const SpdyDataIR& data_ir) const { |
| 2012 uint8 flags = DATA_FLAG_NONE; | 2034 uint8 flags = DATA_FLAG_NONE; |
| 2013 if (datair.fin()) { | 2035 if (data_ir.fin()) { |
| 2014 flags = DATA_FLAG_FIN; | 2036 flags = DATA_FLAG_FIN; |
| 2015 } | 2037 } |
| 2016 | 2038 |
| 2017 if (protocol_version() > SPDY3) { | 2039 if (protocol_version() > SPDY3) { |
| 2018 int num_padding_fields = 0; | 2040 int num_padding_fields = 0; |
| 2019 if (datair.pad_low()) { | 2041 if (data_ir.pad_low()) { |
| 2020 flags |= DATA_FLAG_PAD_LOW; | 2042 flags |= DATA_FLAG_PAD_LOW; |
| 2021 ++num_padding_fields; | 2043 ++num_padding_fields; |
| 2022 } | 2044 } |
| 2023 if (datair.pad_high()) { | 2045 if (data_ir.pad_high()) { |
| 2024 flags |= DATA_FLAG_PAD_HIGH; | 2046 flags |= DATA_FLAG_PAD_HIGH; |
| 2025 ++num_padding_fields; | 2047 ++num_padding_fields; |
| 2026 } | 2048 } |
| 2027 | 2049 |
| 2028 const size_t size_with_padding = num_padding_fields + | 2050 const size_t size_with_padding = num_padding_fields + |
| 2029 datair.data().length() + datair.padding_payload_len() + | 2051 data_ir.data().length() + data_ir.padding_payload_len() + |
| 2030 GetDataFrameMinimumSize(); | 2052 GetDataFrameMinimumSize(); |
| 2031 SpdyFrameBuilder builder(size_with_padding); | 2053 SpdyFrameBuilder builder(size_with_padding, protocol_version()); |
| 2032 builder.WriteDataFrameHeader(*this, datair.stream_id(), flags); | 2054 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); |
| 2033 if (datair.pad_high()) { | 2055 if (data_ir.pad_high()) { |
| 2034 builder.WriteUInt8(datair.padding_payload_len() >> 8); | 2056 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); |
| 2035 } | 2057 } |
| 2036 if (datair.pad_low()) { | 2058 if (data_ir.pad_low()) { |
| 2037 builder.WriteUInt8(datair.padding_payload_len() & 0xff); | 2059 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); |
| 2038 } | 2060 } |
| 2039 builder.WriteBytes(datair.data().data(), datair.data().length()); | 2061 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); |
| 2040 if (datair.padding_payload_len() > 0) { | 2062 if (data_ir.padding_payload_len() > 0) { |
| 2041 string padding = string(datair.padding_payload_len(), '0'); | 2063 string padding = string(data_ir.padding_payload_len(), '0'); |
| 2042 builder.WriteBytes(padding.data(), padding.length()); | 2064 builder.WriteBytes(padding.data(), padding.length()); |
| 2043 } | 2065 } |
| 2044 DCHECK_EQ(size_with_padding, builder.length()); | 2066 DCHECK_EQ(size_with_padding, builder.length()); |
| 2045 return builder.take(); | 2067 return builder.take(); |
| 2046 } else { | 2068 } else { |
| 2047 const size_t size = GetDataFrameMinimumSize() + datair.data().length(); | 2069 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length(); |
| 2048 SpdyFrameBuilder builder(size); | 2070 SpdyFrameBuilder builder(size, protocol_version()); |
| 2049 builder.WriteDataFrameHeader(*this, datair.stream_id(), flags); | 2071 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); |
| 2050 builder.WriteBytes(datair.data().data(), datair.data().length()); | 2072 builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); |
| 2051 DCHECK_EQ(size, builder.length()); | 2073 DCHECK_EQ(size, builder.length()); |
| 2052 return builder.take(); | 2074 return builder.take(); |
| 2053 } | 2075 } |
| 2054 } | 2076 } |
| 2055 | 2077 |
| 2056 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader( | 2078 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( |
| 2057 const SpdyDataIR& data) const { | 2079 const SpdyDataIR& data_ir) const { |
| 2058 const size_t kSize = GetDataFrameMinimumSize(); | |
| 2059 | |
| 2060 uint8 flags = DATA_FLAG_NONE; | 2080 uint8 flags = DATA_FLAG_NONE; |
| 2061 if (data.fin()) { | 2081 if (data_ir.fin()) { |
| 2062 flags = DATA_FLAG_FIN; | 2082 flags = DATA_FLAG_FIN; |
| 2063 } | 2083 } |
| 2084 |
| 2085 size_t frame_size = GetDataFrameMinimumSize(); |
| 2086 size_t num_padding_fields = 0; |
| 2064 if (protocol_version() > SPDY3) { | 2087 if (protocol_version() > SPDY3) { |
| 2065 if (data.pad_low()) { | 2088 if (data_ir.pad_low()) { |
| 2066 flags |= DATA_FLAG_PAD_LOW; | 2089 flags |= DATA_FLAG_PAD_LOW; |
| 2090 ++num_padding_fields; |
| 2067 } | 2091 } |
| 2068 if (data.pad_high()) { | 2092 if (data_ir.pad_high()) { |
| 2069 flags |= DATA_FLAG_PAD_HIGH; | 2093 flags |= DATA_FLAG_PAD_HIGH; |
| 2094 ++num_padding_fields; |
| 2070 } | 2095 } |
| 2096 frame_size += num_padding_fields; |
| 2071 } | 2097 } |
| 2072 | 2098 |
| 2073 SpdyFrameBuilder builder(kSize); | 2099 SpdyFrameBuilder builder(frame_size, protocol_version()); |
| 2074 builder.WriteDataFrameHeader(*this, data.stream_id(), flags); | 2100 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); |
| 2075 builder.OverwriteLength(*this, data.data().length()); | 2101 if (protocol_version() > SPDY3) { |
| 2076 DCHECK_EQ(kSize, builder.length()); | 2102 if (data_ir.pad_high()) { |
| 2103 builder.WriteUInt8(data_ir.padding_payload_len() >> 8); |
| 2104 } |
| 2105 if (data_ir.pad_low()) { |
| 2106 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); |
| 2107 } |
| 2108 builder.OverwriteLength(*this, num_padding_fields + |
| 2109 data_ir.data().length() + data_ir.padding_payload_len()); |
| 2110 } else { |
| 2111 builder.OverwriteLength(*this, data_ir.data().length()); |
| 2112 } |
| 2113 DCHECK_EQ(frame_size, builder.length()); |
| 2077 return builder.take(); | 2114 return builder.take(); |
| 2078 } | 2115 } |
| 2079 | 2116 |
| 2080 SpdySerializedFrame* SpdyFramer::SerializeSynStream( | 2117 SpdySerializedFrame* SpdyFramer::SerializeSynStream( |
| 2081 const SpdySynStreamIR& syn_stream) { | 2118 const SpdySynStreamIR& syn_stream) { |
| 2082 uint8 flags = 0; | 2119 uint8 flags = 0; |
| 2083 if (syn_stream.fin()) { | 2120 if (syn_stream.fin()) { |
| 2084 flags |= CONTROL_FLAG_FIN; | 2121 flags |= CONTROL_FLAG_FIN; |
| 2085 } | 2122 } |
| 2086 if (syn_stream.unidirectional()) { | 2123 if (syn_stream.unidirectional()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2099 if (priority > GetLowestPriority()) { | 2136 if (priority > GetLowestPriority()) { |
| 2100 DLOG(DFATAL) << "Priority out-of-bounds."; | 2137 DLOG(DFATAL) << "Priority out-of-bounds."; |
| 2101 priority = GetLowestPriority(); | 2138 priority = GetLowestPriority(); |
| 2102 } | 2139 } |
| 2103 | 2140 |
| 2104 // The size of this frame, including variable-length name-value block. | 2141 // The size of this frame, including variable-length name-value block. |
| 2105 size_t size = GetSynStreamMinimumSize(); | 2142 size_t size = GetSynStreamMinimumSize(); |
| 2106 | 2143 |
| 2107 string hpack_encoding; | 2144 string hpack_encoding; |
| 2108 if (protocol_version() > SPDY3) { | 2145 if (protocol_version() > SPDY3) { |
| 2109 hpack_encoder_.EncodeHeaderSet(syn_stream.name_value_block(), | 2146 if (enable_compression_) { |
| 2110 &hpack_encoding); | 2147 hpack_encoder_.EncodeHeaderSet( |
| 2148 syn_stream.name_value_block(), &hpack_encoding); |
| 2149 } else { |
| 2150 hpack_encoder_.EncodeHeaderSetWithoutCompression( |
| 2151 syn_stream.name_value_block(), &hpack_encoding); |
| 2152 } |
| 2111 size += hpack_encoding.size(); | 2153 size += hpack_encoding.size(); |
| 2112 } else { | 2154 } else { |
| 2113 size += GetSerializedLength(syn_stream.name_value_block()); | 2155 size += GetSerializedLength(syn_stream.name_value_block()); |
| 2114 } | 2156 } |
| 2115 | 2157 |
| 2116 SpdyFrameBuilder builder(size); | 2158 SpdyFrameBuilder builder(size, protocol_version()); |
| 2117 if (protocol_version() <= SPDY3) { | 2159 if (protocol_version() <= SPDY3) { |
| 2118 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); | 2160 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); |
| 2119 builder.WriteUInt32(syn_stream.stream_id()); | 2161 builder.WriteUInt32(syn_stream.stream_id()); |
| 2120 builder.WriteUInt32(syn_stream.associated_to_stream_id()); | 2162 builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
| 2121 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); | 2163 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); |
| 2122 builder.WriteUInt8(0); // Unused byte where credential slot used to be. | 2164 builder.WriteUInt8(0); // Unused byte where credential slot used to be. |
| 2123 } else { | 2165 } else { |
| 2124 builder.WriteFramePrefix(*this, | 2166 builder.BeginNewFrame(*this, |
| 2125 HEADERS, | 2167 HEADERS, |
| 2126 flags, | 2168 flags, |
| 2127 syn_stream.stream_id()); | 2169 syn_stream.stream_id()); |
| 2128 builder.WriteUInt32(priority); | 2170 builder.WriteUInt32(priority); |
| 2129 } | 2171 } |
| 2130 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); | 2172 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); |
| 2131 if (protocol_version() > SPDY3) { | 2173 if (protocol_version() > SPDY3) { |
| 2132 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2174 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
| 2133 } else { | 2175 } else { |
| 2134 SerializeNameValueBlock(&builder, syn_stream); | 2176 SerializeNameValueBlock(&builder, syn_stream); |
| 2135 } | 2177 } |
| 2136 | 2178 |
| 2137 if (debug_visitor_) { | 2179 if (debug_visitor_) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2159 // we never expect to have to overflow into a CONTINUATION frame. | 2201 // we never expect to have to overflow into a CONTINUATION frame. |
| 2160 if (protocol_version() > SPDY3) { | 2202 if (protocol_version() > SPDY3) { |
| 2161 flags |= HEADERS_FLAG_END_HEADERS; | 2203 flags |= HEADERS_FLAG_END_HEADERS; |
| 2162 } | 2204 } |
| 2163 | 2205 |
| 2164 // The size of this frame, including variable-length name-value block. | 2206 // The size of this frame, including variable-length name-value block. |
| 2165 size_t size = GetSynReplyMinimumSize(); | 2207 size_t size = GetSynReplyMinimumSize(); |
| 2166 | 2208 |
| 2167 string hpack_encoding; | 2209 string hpack_encoding; |
| 2168 if (protocol_version() > SPDY3) { | 2210 if (protocol_version() > SPDY3) { |
| 2169 hpack_encoder_.EncodeHeaderSet(syn_reply.name_value_block(), | 2211 if (enable_compression_) { |
| 2170 &hpack_encoding); | 2212 hpack_encoder_.EncodeHeaderSet( |
| 2213 syn_reply.name_value_block(), &hpack_encoding); |
| 2214 } else { |
| 2215 hpack_encoder_.EncodeHeaderSetWithoutCompression( |
| 2216 syn_reply.name_value_block(), &hpack_encoding); |
| 2217 } |
| 2171 size += hpack_encoding.size(); | 2218 size += hpack_encoding.size(); |
| 2172 } else { | 2219 } else { |
| 2173 size += GetSerializedLength(syn_reply.name_value_block()); | 2220 size += GetSerializedLength(syn_reply.name_value_block()); |
| 2174 } | 2221 } |
| 2175 | 2222 |
| 2176 SpdyFrameBuilder builder(size); | 2223 SpdyFrameBuilder builder(size, protocol_version()); |
| 2177 if (protocol_version() <= SPDY3) { | 2224 if (protocol_version() <= SPDY3) { |
| 2178 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); | 2225 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); |
| 2179 builder.WriteUInt32(syn_reply.stream_id()); | 2226 builder.WriteUInt32(syn_reply.stream_id()); |
| 2180 } else { | 2227 } else { |
| 2181 builder.WriteFramePrefix(*this, | 2228 builder.BeginNewFrame(*this, |
| 2182 HEADERS, | 2229 HEADERS, |
| 2183 flags, | 2230 flags, |
| 2184 syn_reply.stream_id()); | 2231 syn_reply.stream_id()); |
| 2185 } | 2232 } |
| 2186 if (protocol_version() < SPDY3) { | 2233 if (protocol_version() < SPDY3) { |
| 2187 builder.WriteUInt16(0); // Unused. | 2234 builder.WriteUInt16(0); // Unused. |
| 2188 } | 2235 } |
| 2189 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); | 2236 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); |
| 2190 if (protocol_version() > SPDY3) { | 2237 if (protocol_version() > SPDY3) { |
| 2191 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2238 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
| 2192 } else { | 2239 } else { |
| 2193 SerializeNameValueBlock(&builder, syn_reply); | 2240 SerializeNameValueBlock(&builder, syn_reply); |
| 2194 } | 2241 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2211 const SpdyRstStreamIR& rst_stream) const { | 2258 const SpdyRstStreamIR& rst_stream) const { |
| 2212 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM | 2259 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM |
| 2213 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, | 2260 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, |
| 2214 // which doesn't currently include RST_STREAM payloads. GFE flags have been | 2261 // which doesn't currently include RST_STREAM payloads. GFE flags have been |
| 2215 // commented but left in place to simplify future patching. | 2262 // commented but left in place to simplify future patching. |
| 2216 // Compute the output buffer size, taking opaque data into account. | 2263 // Compute the output buffer size, taking opaque data into account. |
| 2217 uint16 expected_length = GetRstStreamMinimumSize(); | 2264 uint16 expected_length = GetRstStreamMinimumSize(); |
| 2218 if (protocol_version() > SPDY3) { | 2265 if (protocol_version() > SPDY3) { |
| 2219 expected_length += rst_stream.description().size(); | 2266 expected_length += rst_stream.description().size(); |
| 2220 } | 2267 } |
| 2221 SpdyFrameBuilder builder(expected_length); | 2268 SpdyFrameBuilder builder(expected_length, protocol_version()); |
| 2222 | 2269 |
| 2223 // Serialize the RST_STREAM frame. | 2270 // Serialize the RST_STREAM frame. |
| 2224 if (protocol_version() <= SPDY3) { | 2271 if (protocol_version() <= SPDY3) { |
| 2225 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); | 2272 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); |
| 2226 builder.WriteUInt32(rst_stream.stream_id()); | 2273 builder.WriteUInt32(rst_stream.stream_id()); |
| 2227 } else { | 2274 } else { |
| 2228 builder.WriteFramePrefix(*this, RST_STREAM, 0, rst_stream.stream_id()); | 2275 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); |
| 2229 } | 2276 } |
| 2230 | 2277 |
| 2231 builder.WriteUInt32(rst_stream.status()); | 2278 builder.WriteUInt32(rst_stream.status()); |
| 2232 | 2279 |
| 2233 // In SPDY4 and up, RST_STREAM frames may also specify opaque data. | 2280 // In SPDY4 and up, RST_STREAM frames may also specify opaque data. |
| 2234 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) { | 2281 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) { |
| 2235 builder.WriteBytes(rst_stream.description().data(), | 2282 builder.WriteBytes(rst_stream.description().data(), |
| 2236 rst_stream.description().size()); | 2283 rst_stream.description().size()); |
| 2237 } | 2284 } |
| 2238 | 2285 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2252 if (settings.is_ack()) { | 2299 if (settings.is_ack()) { |
| 2253 flags |= SETTINGS_FLAG_ACK; | 2300 flags |= SETTINGS_FLAG_ACK; |
| 2254 } | 2301 } |
| 2255 } | 2302 } |
| 2256 const SpdySettingsIR::ValueMap* values = &(settings.values()); | 2303 const SpdySettingsIR::ValueMap* values = &(settings.values()); |
| 2257 | 2304 |
| 2258 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5); | 2305 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5); |
| 2259 // Size, in bytes, of this SETTINGS frame. | 2306 // Size, in bytes, of this SETTINGS frame. |
| 2260 const size_t size = GetSettingsMinimumSize() + | 2307 const size_t size = GetSettingsMinimumSize() + |
| 2261 (values->size() * setting_size); | 2308 (values->size() * setting_size); |
| 2262 SpdyFrameBuilder builder(size); | 2309 SpdyFrameBuilder builder(size, protocol_version()); |
| 2263 if (protocol_version() <= SPDY3) { | 2310 if (protocol_version() <= SPDY3) { |
| 2264 builder.WriteControlFrameHeader(*this, SETTINGS, flags); | 2311 builder.WriteControlFrameHeader(*this, SETTINGS, flags); |
| 2265 } else { | 2312 } else { |
| 2266 builder.WriteFramePrefix(*this, SETTINGS, flags, 0); | 2313 builder.BeginNewFrame(*this, SETTINGS, flags, 0); |
| 2267 } | 2314 } |
| 2268 | 2315 |
| 2269 // If this is an ACK, payload should be empty. | 2316 // If this is an ACK, payload should be empty. |
| 2270 if (protocol_version() > SPDY3 && settings.is_ack()) { | 2317 if (protocol_version() > SPDY3 && settings.is_ack()) { |
| 2271 return builder.take(); | 2318 return builder.take(); |
| 2272 } | 2319 } |
| 2273 | 2320 |
| 2274 if (protocol_version() <= SPDY3) { | 2321 if (protocol_version() <= SPDY3) { |
| 2275 builder.WriteUInt32(values->size()); | 2322 builder.WriteUInt32(values->size()); |
| 2276 } | 2323 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2294 } else { | 2341 } else { |
| 2295 builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(), | 2342 builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(), |
| 2296 it->first)); | 2343 it->first)); |
| 2297 } | 2344 } |
| 2298 builder.WriteUInt32(it->second.value); | 2345 builder.WriteUInt32(it->second.value); |
| 2299 } | 2346 } |
| 2300 DCHECK_EQ(size, builder.length()); | 2347 DCHECK_EQ(size, builder.length()); |
| 2301 return builder.take(); | 2348 return builder.take(); |
| 2302 } | 2349 } |
| 2303 | 2350 |
| 2304 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { | |
| 2305 DCHECK_LT(SPDY3, protocol_version()); | |
| 2306 SpdyFrameBuilder builder(GetBlockedSize()); | |
| 2307 builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id()); | |
| 2308 return builder.take(); | |
| 2309 } | |
| 2310 | |
| 2311 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { | 2351 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
| 2312 SpdyFrameBuilder builder(GetPingSize()); | 2352 SpdyFrameBuilder builder(GetPingSize(), protocol_version()); |
| 2313 if (protocol_version() <= SPDY3) { | 2353 if (protocol_version() <= SPDY3) { |
| 2314 builder.WriteControlFrameHeader(*this, PING, kNoFlags); | 2354 builder.WriteControlFrameHeader(*this, PING, kNoFlags); |
| 2315 builder.WriteUInt32(static_cast<uint32>(ping.id())); | 2355 builder.WriteUInt32(static_cast<uint32>(ping.id())); |
| 2316 } else { | 2356 } else { |
| 2317 uint8 flags = 0; | 2357 uint8 flags = 0; |
| 2318 if (ping.is_ack()) { | 2358 if (ping.is_ack()) { |
| 2319 flags |= PING_FLAG_ACK; | 2359 flags |= PING_FLAG_ACK; |
| 2320 } | 2360 } |
| 2321 builder.WriteFramePrefix(*this, PING, flags, 0); | 2361 builder.BeginNewFrame(*this, PING, flags, 0); |
| 2322 builder.WriteUInt64(ping.id()); | 2362 builder.WriteUInt64(ping.id()); |
| 2323 } | 2363 } |
| 2324 DCHECK_EQ(GetPingSize(), builder.length()); | 2364 DCHECK_EQ(GetPingSize(), builder.length()); |
| 2325 return builder.take(); | 2365 return builder.take(); |
| 2326 } | 2366 } |
| 2327 | 2367 |
| 2328 SpdySerializedFrame* SpdyFramer::SerializeGoAway( | 2368 SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
| 2329 const SpdyGoAwayIR& goaway) const { | 2369 const SpdyGoAwayIR& goaway) const { |
| 2330 | 2370 |
| 2331 // Compute the output buffer size, take opaque data into account. | 2371 // Compute the output buffer size, take opaque data into account. |
| 2332 uint16 expected_length = GetGoAwayMinimumSize(); | 2372 uint16 expected_length = GetGoAwayMinimumSize(); |
| 2333 if (protocol_version() > SPDY3) { | 2373 if (protocol_version() > SPDY3) { |
| 2334 expected_length += goaway.description().size(); | 2374 expected_length += goaway.description().size(); |
| 2335 } | 2375 } |
| 2336 SpdyFrameBuilder builder(expected_length); | 2376 SpdyFrameBuilder builder(expected_length, protocol_version()); |
| 2337 | 2377 |
| 2338 // Serialize the GOAWAY frame. | 2378 // Serialize the GOAWAY frame. |
| 2339 if (protocol_version() <= SPDY3) { | 2379 if (protocol_version() <= SPDY3) { |
| 2340 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); | 2380 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); |
| 2341 } else { | 2381 } else { |
| 2342 builder.WriteFramePrefix(*this, GOAWAY, 0, 0); | 2382 builder.BeginNewFrame(*this, GOAWAY, 0, 0); |
| 2343 } | 2383 } |
| 2344 | 2384 |
| 2345 // GOAWAY frames specify the last good stream id for all SPDY versions. | 2385 // GOAWAY frames specify the last good stream id for all SPDY versions. |
| 2346 builder.WriteUInt32(goaway.last_good_stream_id()); | 2386 builder.WriteUInt32(goaway.last_good_stream_id()); |
| 2347 | 2387 |
| 2348 // In SPDY3 and up, GOAWAY frames also specify the error status code. | 2388 // In SPDY3 and up, GOAWAY frames also specify the error status code. |
| 2349 if (protocol_version() >= SPDY3) { | 2389 if (protocol_version() >= SPDY3) { |
| 2350 builder.WriteUInt32(goaway.status()); | 2390 builder.WriteUInt32(goaway.status()); |
| 2351 } | 2391 } |
| 2352 | 2392 |
| 2353 // In SPDY4 and up, GOAWAY frames may also specify opaque data. | 2393 // In SPDY4 and up, GOAWAY frames may also specify opaque data. |
| 2354 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) { | 2394 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) { |
| 2355 builder.WriteBytes(goaway.description().data(), | 2395 builder.WriteBytes(goaway.description().data(), |
| 2356 goaway.description().size()); | 2396 goaway.description().size()); |
| 2357 } | 2397 } |
| 2358 | 2398 |
| 2359 DCHECK_EQ(expected_length, builder.length()); | 2399 DCHECK_EQ(expected_length, builder.length()); |
| 2360 return builder.take(); | 2400 return builder.take(); |
| 2361 } | 2401 } |
| 2362 | 2402 |
| 2363 SpdySerializedFrame* SpdyFramer::SerializeHeaders( | 2403 SpdySerializedFrame* SpdyFramer::SerializeHeaders( |
| 2364 const SpdyHeadersIR& headers) { | 2404 const SpdyHeadersIR& headers) { |
| 2365 uint8 flags = 0; | 2405 uint8 flags = 0; |
| 2366 if (headers.fin()) { | 2406 if (headers.fin()) { |
| 2367 flags |= CONTROL_FLAG_FIN; | 2407 flags |= CONTROL_FLAG_FIN; |
| 2368 } | 2408 } |
| 2369 if (protocol_version() > SPDY3) { | 2409 if (protocol_version() > SPDY3) { |
| 2410 // TODO(mlavan): If we overflow into a CONTINUATION frame, this will |
| 2411 // get overwritten below, so we should probably just get rid of the |
| 2412 // end_headers field. |
| 2370 if (headers.end_headers()) { | 2413 if (headers.end_headers()) { |
| 2371 flags |= HEADERS_FLAG_END_HEADERS; | 2414 flags |= HEADERS_FLAG_END_HEADERS; |
| 2372 } | 2415 } |
| 2373 if (headers.has_priority()) { | 2416 if (headers.has_priority()) { |
| 2374 flags |= HEADERS_FLAG_PRIORITY; | 2417 flags |= HEADERS_FLAG_PRIORITY; |
| 2375 } | 2418 } |
| 2376 } | 2419 } |
| 2377 | 2420 |
| 2378 // The size of this frame, including variable-length name-value block. | 2421 // The size of this frame, including variable-length name-value block. |
| 2379 size_t size = GetHeadersMinimumSize(); | 2422 size_t size = GetHeadersMinimumSize(); |
| 2380 | 2423 |
| 2381 uint32 priority = headers.priority(); | 2424 uint32 priority = headers.priority(); |
| 2382 if (headers.has_priority()) { | 2425 if (headers.has_priority()) { |
| 2383 if (priority > GetLowestPriority()) { | 2426 if (priority > GetLowestPriority()) { |
| 2384 DLOG(DFATAL) << "Priority out-of-bounds."; | 2427 DLOG(DFATAL) << "Priority out-of-bounds."; |
| 2385 priority = GetLowestPriority(); | 2428 priority = GetLowestPriority(); |
| 2386 } | 2429 } |
| 2387 size += 4; | 2430 size += 4; |
| 2388 } | 2431 } |
| 2389 | 2432 |
| 2390 string hpack_encoding; | 2433 string hpack_encoding; |
| 2391 if (protocol_version() > SPDY3) { | 2434 if (protocol_version() > SPDY3) { |
| 2392 hpack_encoder_.EncodeHeaderSet(headers.name_value_block(), &hpack_encoding); | 2435 if (enable_compression_) { |
| 2436 hpack_encoder_.EncodeHeaderSet( |
| 2437 headers.name_value_block(), &hpack_encoding); |
| 2438 } else { |
| 2439 hpack_encoder_.EncodeHeaderSetWithoutCompression( |
| 2440 headers.name_value_block(), &hpack_encoding); |
| 2441 } |
| 2393 size += hpack_encoding.size(); | 2442 size += hpack_encoding.size(); |
| 2443 if (size > GetControlFrameBufferMaxSize()) { |
| 2444 size += GetNumberRequiredContinuationFrames(size) * |
| 2445 GetContinuationMinimumSize(); |
| 2446 flags &= ~HEADERS_FLAG_END_HEADERS; |
| 2447 } |
| 2394 } else { | 2448 } else { |
| 2395 size += GetSerializedLength(headers.name_value_block()); | 2449 size += GetSerializedLength(headers.name_value_block()); |
| 2396 } | 2450 } |
| 2397 | 2451 |
| 2398 SpdyFrameBuilder builder(size); | 2452 SpdyFrameBuilder builder(size, protocol_version()); |
| 2399 if (protocol_version() <= SPDY3) { | 2453 if (protocol_version() <= SPDY3) { |
| 2400 builder.WriteControlFrameHeader(*this, HEADERS, flags); | 2454 builder.WriteControlFrameHeader(*this, HEADERS, flags); |
| 2401 builder.WriteUInt32(headers.stream_id()); | 2455 builder.WriteUInt32(headers.stream_id()); |
| 2402 } else { | 2456 } else { |
| 2403 builder.WriteFramePrefix(*this, | 2457 builder.BeginNewFrame(*this, |
| 2404 HEADERS, | 2458 HEADERS, |
| 2405 flags, | 2459 flags, |
| 2406 headers.stream_id()); | 2460 headers.stream_id()); |
| 2407 if (headers.has_priority()) { | 2461 if (headers.has_priority()) { |
| 2408 builder.WriteUInt32(priority); | 2462 builder.WriteUInt32(priority); |
| 2409 } | 2463 } |
| 2410 } | 2464 } |
| 2411 if (protocol_version() <= SPDY2) { | 2465 if (protocol_version() <= SPDY2) { |
| 2412 builder.WriteUInt16(0); // Unused. | 2466 builder.WriteUInt16(0); // Unused. |
| 2413 } | 2467 } |
| 2414 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); | 2468 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); |
| 2415 | 2469 |
| 2416 if (protocol_version() > SPDY3) { | 2470 if (protocol_version() > SPDY3) { |
| 2417 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2471 WritePayloadWithContinuation(&builder, |
| 2472 hpack_encoding, |
| 2473 headers.stream_id(), |
| 2474 HEADERS); |
| 2418 } else { | 2475 } else { |
| 2419 SerializeNameValueBlock(&builder, headers); | 2476 SerializeNameValueBlock(&builder, headers); |
| 2420 } | 2477 } |
| 2421 | 2478 |
| 2422 if (debug_visitor_) { | 2479 if (debug_visitor_) { |
| 2423 const size_t payload_len = protocol_version() > SPDY3 ? | 2480 const size_t payload_len = protocol_version() > SPDY3 ? |
| 2424 hpack_encoding.size() : | 2481 hpack_encoding.size() : |
| 2425 GetSerializedLength(protocol_version(), | 2482 GetSerializedLength(protocol_version(), |
| 2426 &(headers.name_value_block())); | 2483 &(headers.name_value_block())); |
| 2427 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), | 2484 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), |
| 2428 HEADERS, | 2485 HEADERS, |
| 2429 payload_len, | 2486 payload_len, |
| 2430 builder.length()); | 2487 builder.length()); |
| 2431 } | 2488 } |
| 2432 | 2489 |
| 2433 return builder.take(); | 2490 return builder.take(); |
| 2434 } | 2491 } |
| 2435 | 2492 |
| 2436 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( | 2493 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( |
| 2437 const SpdyWindowUpdateIR& window_update) const { | 2494 const SpdyWindowUpdateIR& window_update) const { |
| 2438 SpdyFrameBuilder builder(GetWindowUpdateSize()); | 2495 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version()); |
| 2439 if (protocol_version() <= SPDY3) { | 2496 if (protocol_version() <= SPDY3) { |
| 2440 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); | 2497 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); |
| 2441 builder.WriteUInt32(window_update.stream_id()); | 2498 builder.WriteUInt32(window_update.stream_id()); |
| 2442 } else { | 2499 } else { |
| 2443 builder.WriteFramePrefix(*this, | 2500 builder.BeginNewFrame(*this, |
| 2444 WINDOW_UPDATE, | 2501 WINDOW_UPDATE, |
| 2445 kNoFlags, | 2502 kNoFlags, |
| 2446 window_update.stream_id()); | 2503 window_update.stream_id()); |
| 2447 } | 2504 } |
| 2448 builder.WriteUInt32(window_update.delta()); | 2505 builder.WriteUInt32(window_update.delta()); |
| 2449 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); | 2506 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); |
| 2450 return builder.take(); | 2507 return builder.take(); |
| 2451 } | 2508 } |
| 2452 | 2509 |
| 2510 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { |
| 2511 DCHECK_LT(SPDY3, protocol_version()); |
| 2512 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version()); |
| 2513 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); |
| 2514 return builder.take(); |
| 2515 } |
| 2516 |
| 2453 SpdyFrame* SpdyFramer::SerializePushPromise( | 2517 SpdyFrame* SpdyFramer::SerializePushPromise( |
| 2454 const SpdyPushPromiseIR& push_promise) { | 2518 const SpdyPushPromiseIR& push_promise) { |
| 2455 DCHECK_LT(SPDY3, protocol_version()); | 2519 DCHECK_LT(SPDY3, protocol_version()); |
| 2456 uint8 flags = 0; | 2520 uint8 flags = 0; |
| 2521 // TODO(mlavan): If we overflow into a CONTINUATION frame, this will |
| 2522 // get overwritten below, so we should probably just get rid of the |
| 2523 // end_push_promise field. |
| 2457 if (push_promise.end_push_promise()) { | 2524 if (push_promise.end_push_promise()) { |
| 2458 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2525 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
| 2459 } | 2526 } |
| 2460 // The size of this frame, including variable-length name-value block. | 2527 // The size of this frame, including variable-length name-value block. |
| 2461 size_t size = GetPushPromiseMinimumSize(); | 2528 size_t size = GetPushPromiseMinimumSize(); |
| 2462 | 2529 |
| 2463 string hpack_encoding; | 2530 string hpack_encoding; |
| 2464 if (protocol_version() > SPDY3) { | 2531 if (protocol_version() > SPDY3) { |
| 2465 hpack_encoder_.EncodeHeaderSet(push_promise.name_value_block(), | 2532 if (enable_compression_) { |
| 2466 &hpack_encoding); | 2533 hpack_encoder_.EncodeHeaderSet( |
| 2534 push_promise.name_value_block(), &hpack_encoding); |
| 2535 } else { |
| 2536 hpack_encoder_.EncodeHeaderSetWithoutCompression( |
| 2537 push_promise.name_value_block(), &hpack_encoding); |
| 2538 } |
| 2467 size += hpack_encoding.size(); | 2539 size += hpack_encoding.size(); |
| 2540 if (size > GetControlFrameBufferMaxSize()) { |
| 2541 size += GetNumberRequiredContinuationFrames(size) * |
| 2542 GetContinuationMinimumSize(); |
| 2543 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
| 2544 } |
| 2468 } else { | 2545 } else { |
| 2469 size += GetSerializedLength(push_promise.name_value_block()); | 2546 size += GetSerializedLength(push_promise.name_value_block()); |
| 2470 } | 2547 } |
| 2471 | 2548 |
| 2472 SpdyFrameBuilder builder(size); | 2549 SpdyFrameBuilder builder(size, protocol_version()); |
| 2473 builder.WriteFramePrefix(*this, PUSH_PROMISE, flags, | 2550 builder.BeginNewFrame(*this, |
| 2474 push_promise.stream_id()); | 2551 PUSH_PROMISE, |
| 2552 flags, |
| 2553 push_promise.stream_id()); |
| 2475 builder.WriteUInt32(push_promise.promised_stream_id()); | 2554 builder.WriteUInt32(push_promise.promised_stream_id()); |
| 2476 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); | 2555 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); |
| 2477 | 2556 |
| 2478 if (protocol_version() > SPDY3) { | 2557 if (protocol_version() > SPDY3) { |
| 2479 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2558 WritePayloadWithContinuation(&builder, |
| 2559 hpack_encoding, |
| 2560 push_promise.stream_id(), |
| 2561 PUSH_PROMISE); |
| 2480 } else { | 2562 } else { |
| 2481 SerializeNameValueBlock(&builder, push_promise); | 2563 SerializeNameValueBlock(&builder, push_promise); |
| 2482 } | 2564 } |
| 2483 | 2565 |
| 2484 if (debug_visitor_) { | 2566 if (debug_visitor_) { |
| 2485 const size_t payload_len = protocol_version() > SPDY3 ? | 2567 const size_t payload_len = protocol_version() > SPDY3 ? |
| 2486 hpack_encoding.size() : | 2568 hpack_encoding.size() : |
| 2487 GetSerializedLength(protocol_version(), | 2569 GetSerializedLength(protocol_version(), |
| 2488 &(push_promise.name_value_block())); | 2570 &(push_promise.name_value_block())); |
| 2489 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), | 2571 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2500 const SpdyContinuationIR& continuation) { | 2582 const SpdyContinuationIR& continuation) { |
| 2501 CHECK_LT(SPDY3, protocol_version()); | 2583 CHECK_LT(SPDY3, protocol_version()); |
| 2502 uint8 flags = 0; | 2584 uint8 flags = 0; |
| 2503 if (continuation.end_headers()) { | 2585 if (continuation.end_headers()) { |
| 2504 flags |= HEADERS_FLAG_END_HEADERS; | 2586 flags |= HEADERS_FLAG_END_HEADERS; |
| 2505 } | 2587 } |
| 2506 | 2588 |
| 2507 // The size of this frame, including variable-length name-value block. | 2589 // The size of this frame, including variable-length name-value block. |
| 2508 size_t size = GetContinuationMinimumSize(); | 2590 size_t size = GetContinuationMinimumSize(); |
| 2509 string hpack_encoding; | 2591 string hpack_encoding; |
| 2510 hpack_encoder_.EncodeHeaderSet(continuation.name_value_block(), | 2592 if (enable_compression_) { |
| 2511 &hpack_encoding); | 2593 hpack_encoder_.EncodeHeaderSet( |
| 2594 continuation.name_value_block(), &hpack_encoding); |
| 2595 } else { |
| 2596 hpack_encoder_.EncodeHeaderSetWithoutCompression( |
| 2597 continuation.name_value_block(), &hpack_encoding); |
| 2598 } |
| 2512 size += hpack_encoding.size(); | 2599 size += hpack_encoding.size(); |
| 2513 | 2600 |
| 2514 SpdyFrameBuilder builder(size); | 2601 SpdyFrameBuilder builder(size, protocol_version()); |
| 2515 builder.WriteFramePrefix(*this, CONTINUATION, flags, | 2602 builder.BeginNewFrame(*this, CONTINUATION, flags, |
| 2516 continuation.stream_id()); | 2603 continuation.stream_id()); |
| 2517 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); | 2604 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); |
| 2518 | 2605 |
| 2519 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2606 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
| 2520 | 2607 |
| 2521 if (debug_visitor_) { | 2608 if (debug_visitor_) { |
| 2522 const size_t payload_len = hpack_encoding.size(); | 2609 const size_t payload_len = hpack_encoding.size(); |
| 2523 debug_visitor_->OnSendCompressedFrame(continuation.stream_id(), | 2610 debug_visitor_->OnSendCompressedFrame(continuation.stream_id(), |
| 2524 CONTINUATION, payload_len, builder.length()); | 2611 CONTINUATION, payload_len, builder.length()); |
| 2525 } | 2612 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2595 GetSerializedLength(protocol_version(), &headers); | 2682 GetSerializedLength(protocol_version(), &headers); |
| 2596 if (!enable_compression_) { | 2683 if (!enable_compression_) { |
| 2597 return uncompressed_length; | 2684 return uncompressed_length; |
| 2598 } | 2685 } |
| 2599 z_stream* compressor = GetHeaderCompressor(); | 2686 z_stream* compressor = GetHeaderCompressor(); |
| 2600 // Since we'll be performing lots of flushes when compressing the data, | 2687 // Since we'll be performing lots of flushes when compressing the data, |
| 2601 // zlib's lower bounds may be insufficient. | 2688 // zlib's lower bounds may be insufficient. |
| 2602 return 2 * deflateBound(compressor, uncompressed_length); | 2689 return 2 * deflateBound(compressor, uncompressed_length); |
| 2603 } | 2690 } |
| 2604 | 2691 |
| 2692 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { |
| 2693 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize(); |
| 2694 DCHECK_GT(protocol_version(), SPDY3); |
| 2695 DCHECK_GT(size, kMaxControlFrameSize); |
| 2696 size_t overflow = size - kMaxControlFrameSize; |
| 2697 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; |
| 2698 } |
| 2699 |
| 2700 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, |
| 2701 const string& hpack_encoding, |
| 2702 SpdyStreamId stream_id, |
| 2703 SpdyFrameType type) { |
| 2704 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize(); |
| 2705 |
| 2706 // In addition to the prefix, fixed_field_size includes the size of |
| 2707 // any fields that come before the variable-length name/value block. |
| 2708 size_t fixed_field_size = 0; |
| 2709 uint8 end_flag = 0; |
| 2710 uint8 flags = 0; |
| 2711 if (type == HEADERS) { |
| 2712 fixed_field_size = GetHeadersMinimumSize(); |
| 2713 end_flag = HEADERS_FLAG_END_HEADERS; |
| 2714 } else if (type == PUSH_PROMISE) { |
| 2715 fixed_field_size = GetPushPromiseMinimumSize(); |
| 2716 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
| 2717 } else { |
| 2718 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " |
| 2719 << FrameTypeToString(type); |
| 2720 } |
| 2721 |
| 2722 // Write as much of the payload as possible into the initial frame. |
| 2723 size_t bytes_remaining = hpack_encoding.size() - |
| 2724 std::min(hpack_encoding.size(), |
| 2725 kMaxControlFrameSize - fixed_field_size); |
| 2726 builder->WriteBytes(&hpack_encoding[0], |
| 2727 hpack_encoding.size() - bytes_remaining); |
| 2728 |
| 2729 if (bytes_remaining > 0) { |
| 2730 builder->OverwriteLength(*this, |
| 2731 kMaxControlFrameSize - GetControlFrameHeaderSize()); |
| 2732 } |
| 2733 |
| 2734 // Tack on CONTINUATION frames for the overflow. |
| 2735 while (bytes_remaining > 0) { |
| 2736 size_t bytes_to_write = std::min(bytes_remaining, |
| 2737 kMaxControlFrameSize - |
| 2738 GetContinuationMinimumSize()); |
| 2739 // Write CONTINUATION frame prefix. |
| 2740 if (bytes_remaining == bytes_to_write) { |
| 2741 flags |= end_flag; |
| 2742 } |
| 2743 builder->BeginNewFrame(*this, |
| 2744 CONTINUATION, |
| 2745 flags, |
| 2746 stream_id); |
| 2747 // Write payload fragment. |
| 2748 builder->WriteBytes(&hpack_encoding[hpack_encoding.size() - |
| 2749 bytes_remaining], |
| 2750 bytes_to_write); |
| 2751 bytes_remaining -= bytes_to_write; |
| 2752 } |
| 2753 } |
| 2754 |
| 2605 // The following compression setting are based on Brian Olson's analysis. See | 2755 // The following compression setting are based on Brian Olson's analysis. See |
| 2606 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 | 2756 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 |
| 2607 // for more details. | 2757 // for more details. |
| 2608 #if defined(USE_SYSTEM_ZLIB) | 2758 #if defined(USE_SYSTEM_ZLIB) |
| 2609 // System zlib is not expected to have workaround for http://crbug.com/139744, | 2759 // System zlib is not expected to have workaround for http://crbug.com/139744, |
| 2610 // so disable compression in that case. | 2760 // so disable compression in that case. |
| 2611 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. | 2761 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. |
| 2612 static const int kCompressorLevel = 0; | 2762 static const int kCompressorLevel = 0; |
| 2613 #else // !defined(USE_SYSTEM_ZLIB) | 2763 #else // !defined(USE_SYSTEM_ZLIB) |
| 2614 static const int kCompressorLevel = 9; | 2764 static const int kCompressorLevel = 9; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2782 const SpdyFrameWithNameValueBlockIR& frame) { | 2932 const SpdyFrameWithNameValueBlockIR& frame) { |
| 2783 CHECK_GE(SPDY3, protocol_version()); | 2933 CHECK_GE(SPDY3, protocol_version()); |
| 2784 if (!enable_compression_) { | 2934 if (!enable_compression_) { |
| 2785 return SerializeNameValueBlockWithoutCompression(builder, | 2935 return SerializeNameValueBlockWithoutCompression(builder, |
| 2786 frame.name_value_block()); | 2936 frame.name_value_block()); |
| 2787 } | 2937 } |
| 2788 | 2938 |
| 2789 // First build an uncompressed version to be fed into the compressor. | 2939 // First build an uncompressed version to be fed into the compressor. |
| 2790 const size_t uncompressed_len = GetSerializedLength( | 2940 const size_t uncompressed_len = GetSerializedLength( |
| 2791 protocol_version(), &(frame.name_value_block())); | 2941 protocol_version(), &(frame.name_value_block())); |
| 2792 SpdyFrameBuilder uncompressed_builder(uncompressed_len); | 2942 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version()); |
| 2793 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, | 2943 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, |
| 2794 frame.name_value_block()); | 2944 frame.name_value_block()); |
| 2795 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); | 2945 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); |
| 2796 | 2946 |
| 2797 z_stream* compressor = GetHeaderCompressor(); | 2947 z_stream* compressor = GetHeaderCompressor(); |
| 2798 if (!compressor) { | 2948 if (!compressor) { |
| 2799 LOG(DFATAL) << "Could not obtain compressor."; | 2949 LOG(DFATAL) << "Could not obtain compressor."; |
| 2800 return; | 2950 return; |
| 2801 } | 2951 } |
| 2802 | 2952 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2841 builder->Seek(compressed_size); | 2991 builder->Seek(compressed_size); |
| 2842 builder->RewriteLength(*this); | 2992 builder->RewriteLength(*this); |
| 2843 | 2993 |
| 2844 pre_compress_bytes.Add(uncompressed_len); | 2994 pre_compress_bytes.Add(uncompressed_len); |
| 2845 post_compress_bytes.Add(compressed_size); | 2995 post_compress_bytes.Add(compressed_size); |
| 2846 | 2996 |
| 2847 compressed_frames.Increment(); | 2997 compressed_frames.Increment(); |
| 2848 } | 2998 } |
| 2849 | 2999 |
| 2850 } // namespace net | 3000 } // namespace net |
| OLD | NEW |