| Index: net/spdy/spdy_framer.cc
|
| diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
|
| index 1c0ee752ff3f54f14434aea940fdb287c99332b2..23080accd994ad2c6982d3e639fdaab2a1c28981 100644
|
| --- a/net/spdy/spdy_framer.cc
|
| +++ b/net/spdy/spdy_framer.cc
|
| @@ -90,7 +90,7 @@ SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version,
|
|
|
| SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
|
| : flags_(flags), id_(id & 0x00ffffff) {
|
| - LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large.";
|
| + LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
|
| }
|
|
|
| uint32 SettingsFlagsAndId::GetWireFormat(int version) const {
|
| @@ -161,6 +161,8 @@ void SpdyFramer::Reset() {
|
| current_frame_length_ = 0;
|
| current_frame_stream_id_ = kInvalidStream;
|
| settings_scratch_.Reset();
|
| + remaining_padding_payload_length_ = 0;
|
| + remaining_padding_length_fields_ = 0;
|
| }
|
|
|
| size_t SpdyFramer::GetDataFrameMinimumSize() const {
|
| @@ -185,7 +187,7 @@ size_t SpdyFramer::GetControlFrameHeaderSize() const {
|
| size_t SpdyFramer::GetSynStreamMinimumSize() const {
|
| // Size, in bytes, of a SYN_STREAM frame not including the variable-length
|
| // name-value block.
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // Calculated as:
|
| // control frame header + 2 * 4 (stream IDs) + 1 (priority)
|
| // + 1 (unused, was credential slot)
|
| @@ -201,14 +203,14 @@ size_t SpdyFramer::GetSynReplyMinimumSize() const {
|
| // Size, in bytes, of a SYN_REPLY frame not including the variable-length
|
| // name-value block.
|
| size_t size = GetControlFrameHeaderSize();
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // Calculated as:
|
| // control frame header + 4 (stream IDs)
|
| size += 4;
|
| }
|
|
|
| // In SPDY 2, there were 2 unused bytes before payload.
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() < SPDY3) {
|
| size += 2;
|
| }
|
|
|
| @@ -217,7 +219,7 @@ size_t SpdyFramer::GetSynReplyMinimumSize() const {
|
|
|
| size_t SpdyFramer::GetRstStreamMinimumSize() const {
|
| // Size, in bytes, of a RST_STREAM frame.
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // Calculated as:
|
| // control frame header + 4 (stream id) + 4 (status code)
|
| return GetControlFrameHeaderSize() + 8;
|
| @@ -232,7 +234,7 @@ size_t SpdyFramer::GetSettingsMinimumSize() const {
|
| // Size, in bytes, of a SETTINGS frame not including the IDs and values
|
| // from the variable-length value block. Calculated as:
|
| // control frame header + 4 (number of ID/value pairs)
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| return GetControlFrameHeaderSize() + 4;
|
| } else {
|
| return GetControlFrameHeaderSize();
|
| @@ -241,7 +243,7 @@ size_t SpdyFramer::GetSettingsMinimumSize() const {
|
|
|
| size_t SpdyFramer::GetPingSize() const {
|
| // Size, in bytes, of this PING frame.
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // Calculated as:
|
| // control frame header + 4 (id)
|
| return GetControlFrameHeaderSize() + 4;
|
| @@ -272,14 +274,14 @@ size_t SpdyFramer::GetHeadersMinimumSize() const {
|
| // Size, in bytes, of a HEADERS frame not including the variable-length
|
| // name-value block.
|
| size_t size = GetControlFrameHeaderSize();
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // Calculated as:
|
| // control frame header + 4 (stream IDs)
|
| size += 4;
|
| }
|
|
|
| // In SPDY 2, there were 2 unused bytes before payload.
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() <= SPDY2) {
|
| size += 2;
|
| }
|
|
|
| @@ -288,7 +290,7 @@ size_t SpdyFramer::GetHeadersMinimumSize() const {
|
|
|
| size_t SpdyFramer::GetWindowUpdateSize() const {
|
| // Size, in bytes, of a WINDOW_UPDATE frame.
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // Calculated as:
|
| // control frame header + 4 (stream id) + 4 (delta)
|
| return GetControlFrameHeaderSize() + 8;
|
| @@ -324,7 +326,7 @@ size_t SpdyFramer::GetFrameMinimumSize() const {
|
| }
|
|
|
| size_t SpdyFramer::GetFrameMaximumSize() const {
|
| - if (protocol_version() < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // 24-bit length field plus eight-byte frame header.
|
| return ((1<<24) - 1) + 8;
|
| } else {
|
| @@ -349,6 +351,10 @@ const char* SpdyFramer::StateToString(int state) {
|
| return "READING_COMMON_HEADER";
|
| case SPDY_CONTROL_FRAME_PAYLOAD:
|
| return "CONTROL_FRAME_PAYLOAD";
|
| + case SPDY_READ_PADDING_LENGTH:
|
| + return "SPDY_READ_PADDING_LENGTH";
|
| + case SPDY_CONSUME_PADDING:
|
| + return "SPDY_CONSUME_PADDING";
|
| case SPDY_IGNORE_REMAINING_PAYLOAD:
|
| return "IGNORE_REMAINING_PAYLOAD";
|
| case SPDY_FORWARD_STREAM_FRAME:
|
| @@ -525,7 +531,7 @@ size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
|
|
|
| case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
|
| int bytes_read = ProcessControlFrameHeaderBlock(
|
| - data, len, spdy_version_ >= 4 ? true : false);
|
| + data, len, protocol_version() > SPDY3);
|
| len -= bytes_read;
|
| data += bytes_read;
|
| break;
|
| @@ -552,6 +558,20 @@ size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
|
| break;
|
| }
|
|
|
| + case SPDY_READ_PADDING_LENGTH: {
|
| + size_t bytes_read = ProcessFramePaddingLength(data, len);
|
| + len -= bytes_read;
|
| + data += bytes_read;
|
| + break;
|
| + }
|
| +
|
| + case SPDY_CONSUME_PADDING: {
|
| + size_t bytes_read = ProcessFramePadding(data, len);
|
| + len -= bytes_read;
|
| + data += bytes_read;
|
| + break;
|
| + }
|
| +
|
| case SPDY_IGNORE_REMAINING_PAYLOAD:
|
| // control frame has too-large payload
|
| // intentional fallthrough
|
| @@ -614,7 +634,7 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
|
| // ProcessControlFrameHeader() will set current_frame_type_ to the
|
| // correct value if this is a valid control frame.
|
| current_frame_type_ = DATA;
|
| - if (protocol_version() < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| bool successful_read = reader->ReadUInt16(&version);
|
| DCHECK(successful_read);
|
| is_control_frame = (version & kControlFlagMask) != 0;
|
| @@ -643,7 +663,6 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
|
| uint16 length_field = 0;
|
| bool successful_read = reader->ReadUInt16(&length_field);
|
| DCHECK(successful_read);
|
| - current_frame_length_ = length_field;
|
|
|
| uint8 control_frame_type_field_uint8 = DATA;
|
| successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
|
| @@ -653,6 +672,12 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
|
| control_frame_type_field = control_frame_type_field_uint8;
|
| is_control_frame = (control_frame_type_field != DATA);
|
|
|
| + if (is_control_frame) {
|
| + current_frame_length_ = length_field + GetControlFrameHeaderSize();
|
| + } else {
|
| + current_frame_length_ = length_field + GetDataFrameMinimumSize();
|
| + }
|
| +
|
| successful_read = reader->ReadUInt8(¤t_frame_flags_);
|
| DCHECK(successful_read);
|
|
|
| @@ -663,15 +688,16 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
|
|
|
| // Before we accept a DATA frame, we need to make sure we're not in the
|
| // middle of processing a header block.
|
| - if (expect_continuation_ != 0 && control_frame_type_field != CONTINUATION) {
|
| - DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
|
| - << "frame, but instead received frame type "
|
| - << current_frame_type_;
|
| - set_error(SPDY_UNEXPECTED_FRAME);
|
| - return original_len - len;
|
| - } else if (control_frame_type_field == CONTINUATION &&
|
| - expect_continuation_ == 0) {
|
| - DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
|
| + const bool is_continuation_frame = (control_frame_type_field ==
|
| + SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
|
| + if ((expect_continuation_ != 0) != is_continuation_frame) {
|
| + if (expect_continuation_ != 0) {
|
| + DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
|
| + << "frame, but instead received frame type "
|
| + << control_frame_type_field;
|
| + } else {
|
| + DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
|
| + }
|
| set_error(SPDY_UNEXPECTED_FRAME);
|
| return original_len - len;
|
| }
|
| @@ -699,20 +725,28 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
|
|
|
| // if we're here, then we have the common header all received.
|
| if (!is_control_frame) {
|
| - if (protocol_version() >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| // Catch bogus tests sending oversized DATA frames.
|
| DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
|
| << "DATA frame too large for SPDY >= 4.";
|
| }
|
|
|
| - if (current_frame_flags_ & ~DATA_FLAG_FIN) {
|
| + uint8 valid_data_flags = 0;
|
| + if (protocol_version() > SPDY3) {
|
| + valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
|
| + DATA_FLAG_PAD_LOW | DATA_FLAG_PAD_HIGH;
|
| + } else {
|
| + valid_data_flags = DATA_FLAG_FIN;
|
| + }
|
| +
|
| + if (current_frame_flags_ & ~valid_data_flags) {
|
| set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
|
| } else {
|
| visitor_->OnDataFrameHeader(current_frame_stream_id_,
|
| remaining_data_length_,
|
| current_frame_flags_ & DATA_FLAG_FIN);
|
| if (remaining_data_length_ > 0) {
|
| - CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
|
| + CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
|
| } else {
|
| // Empty data frame.
|
| if (current_frame_flags_ & DATA_FLAG_FIN) {
|
| @@ -722,11 +756,11 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
|
| CHANGE_STATE(SPDY_AUTO_RESET);
|
| }
|
| }
|
| - } else if (version != spdy_version_) {
|
| + } else if (version != protocol_version()) {
|
| // We check version before we check validity: version can never be
|
| // 'invalid', it can only be unsupported.
|
| DVLOG(1) << "Unsupported SPDY version " << version
|
| - << " (expected " << spdy_version_ << ")";
|
| + << " (expected " << protocol_version() << ")";
|
| set_error(SPDY_UNSUPPORTED_VERSION);
|
| } else {
|
| ProcessControlFrameHeader(control_frame_type_field);
|
| @@ -739,31 +773,38 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| DCHECK_EQ(SPDY_NO_ERROR, error_code_);
|
| DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
|
|
|
| - if (control_frame_type_field < FIRST_CONTROL_TYPE ||
|
| - control_frame_type_field > LAST_CONTROL_TYPE) {
|
| - set_error(SPDY_INVALID_CONTROL_FRAME);
|
| - return;
|
| - }
|
| -
|
| - current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
|
| + // Early detection of deprecated frames that we ignore.
|
| + if (protocol_version() <= SPDY3) {
|
| + if (control_frame_type_field == NOOP) {
|
| + current_frame_type_ = NOOP;
|
| + DVLOG(1) << "NOOP control frame found. Ignoring.";
|
| + CHANGE_STATE(SPDY_AUTO_RESET);
|
| + return;
|
| + }
|
|
|
| - if (current_frame_type_ == NOOP) {
|
| - DVLOG(1) << "NOOP control frame found. Ignoring.";
|
| - CHANGE_STATE(SPDY_AUTO_RESET);
|
| - return;
|
| + if (control_frame_type_field == CREDENTIAL) {
|
| + current_frame_type_ = CREDENTIAL;
|
| + DCHECK_EQ(SPDY3, protocol_version());
|
| + DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
|
| + CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
|
| + return;
|
| + }
|
| }
|
|
|
| - if (current_frame_type_ == CREDENTIAL) {
|
| - DCHECK_EQ(3, protocol_version());
|
| - DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
|
| - CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
|
| + if (!SpdyConstants::IsValidFrameType(protocol_version(),
|
| + control_frame_type_field)) {
|
| + DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
|
| + << " (protocol version: " << protocol_version() << ")";
|
| + set_error(SPDY_INVALID_CONTROL_FRAME);
|
| return;
|
| }
|
|
|
| + current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
|
| + control_frame_type_field);
|
| +
|
| // Do some sanity checking on the control frame sizes and flags.
|
| switch (current_frame_type_) {
|
| case SYN_STREAM:
|
| - DCHECK_GT(4, spdy_version_);
|
| if (current_frame_length_ < GetSynStreamMinimumSize()) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| } else if (current_frame_flags_ &
|
| @@ -783,9 +824,9 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| // For SPDY version 4 and up, the RST_STREAM frame may include optional
|
| // opaque data, so we only have a lower limit on the frame size.
|
| if ((current_frame_length_ != GetRstStreamMinimumSize() &&
|
| - protocol_version() < 4) ||
|
| + protocol_version() <= SPDY3) ||
|
| (current_frame_length_ < GetRstStreamMinimumSize() &&
|
| - protocol_version() >= 4)) {
|
| + protocol_version() > SPDY3)) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| } else if (current_frame_flags_ != 0) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| @@ -795,23 +836,23 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| {
|
| // Make sure that we have an integral number of 8-byte key/value pairs,
|
| // plus a 4-byte length field in SPDY3 and below.
|
| - size_t values_prefix_size = (protocol_version() < 4 ? 4 : 0);
|
| + size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
|
| // Size of each key/value pair in bytes.
|
| - size_t setting_size = (protocol_version() < 4 ? 8 : 5);
|
| + size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5);
|
| if (current_frame_length_ < GetSettingsMinimumSize() ||
|
| (current_frame_length_ - GetControlFrameHeaderSize())
|
| % setting_size != values_prefix_size) {
|
| DLOG(WARNING) << "Invalid length for SETTINGS frame: "
|
| << current_frame_length_;
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| - } else if (protocol_version() < 4 &&
|
| + } else if (protocol_version() <= SPDY3 &&
|
| current_frame_flags_ &
|
| ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| - } else if (protocol_version() >= 4 &&
|
| + } else if (protocol_version() > SPDY3 &&
|
| current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| - } else if (protocol_version() >= 4 &&
|
| + } else if (protocol_version() > SPDY3 &&
|
| current_frame_flags_ & SETTINGS_FLAG_ACK &&
|
| current_frame_length_ > GetSettingsMinimumSize()) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| @@ -821,7 +862,7 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| case PING:
|
| if (current_frame_length_ != GetPingSize()) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| - } else if ((protocol_version() < 4 && current_frame_flags_ != 0) ||
|
| + } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
|
| (current_frame_flags_ & ~PING_FLAG_ACK)) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| }
|
| @@ -833,9 +874,9 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| // be appended to the GOAWAY frame, thus there is only a minimal length
|
| // restriction.
|
| if ((current_frame_length_ != GetGoAwayMinimumSize() &&
|
| - protocol_version() < 4) ||
|
| + protocol_version() <= SPDY3) ||
|
| (current_frame_length_ < GetGoAwayMinimumSize() &&
|
| - protocol_version() >= 4)) {
|
| + protocol_version() > SPDY3)) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| } else if (current_frame_flags_ != 0) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| @@ -845,16 +886,16 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| case HEADERS:
|
| {
|
| size_t min_size = GetHeadersMinimumSize();
|
| - if (spdy_version_ > 3 &&
|
| + if (protocol_version() > SPDY3 &&
|
| (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
|
| min_size += 4;
|
| }
|
| if (current_frame_length_ < min_size) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| - } else if (spdy_version_ < 4 &&
|
| + } else if (protocol_version() <= SPDY3 &&
|
| current_frame_flags_ & ~CONTROL_FLAG_FIN) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| - } else if (spdy_version_ >= 4 && current_frame_flags_ &
|
| + } else if (protocol_version() > SPDY3 && current_frame_flags_ &
|
| ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
|
| HEADERS_FLAG_END_HEADERS)) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| @@ -878,16 +919,15 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| case PUSH_PROMISE:
|
| if (current_frame_length_ < GetPushPromiseMinimumSize()) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| - } else if (spdy_version_ < 4 && current_frame_flags_ != 0) {
|
| + } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| - } else if (spdy_version_ >= 4 && current_frame_flags_ &
|
| + } else if (protocol_version() > SPDY3 && current_frame_flags_ &
|
| ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| }
|
| break;
|
| case CONTINUATION:
|
| - if (current_frame_length_ < GetContinuationMinimumSize() ||
|
| - protocol_version() < 4) {
|
| + if (current_frame_length_ < GetContinuationMinimumSize()) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
|
| @@ -943,7 +983,8 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
|
| break;
|
| case HEADERS:
|
| frame_size_without_variable_data = GetHeadersMinimumSize();
|
| - if (spdy_version_ > 3 && current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
|
| + if (protocol_version() > SPDY3 &&
|
| + current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
|
| frame_size_without_variable_data += 4; // priority
|
| }
|
| break;
|
| @@ -1228,12 +1269,10 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| switch (current_frame_type_) {
|
| case SYN_STREAM:
|
| {
|
| - DCHECK_GT(4, spdy_version_);
|
| + DCHECK_GE(SPDY3, protocol_version());
|
| bool successful_read = true;
|
| - if (spdy_version_ < 4) {
|
| - successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
|
| - DCHECK(successful_read);
|
| - }
|
| + successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
|
| + DCHECK(successful_read);
|
| if (current_frame_stream_id_ == 0) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| break;
|
| @@ -1246,7 +1285,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| SpdyPriority priority = 0;
|
| successful_read = reader.ReadUInt8(&priority);
|
| DCHECK(successful_read);
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() <= SPDY2) {
|
| priority = priority >> 6;
|
| } else {
|
| priority = priority >> 5;
|
| @@ -1272,7 +1311,8 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
|
| break;
|
| case SETTINGS:
|
| - if (spdy_version_ >= 4 && current_frame_flags_ & SETTINGS_FLAG_ACK) {
|
| + if (protocol_version() > SPDY3 &&
|
| + current_frame_flags_ & SETTINGS_FLAG_ACK) {
|
| visitor_->OnSettingsAck();
|
| CHANGE_STATE(SPDY_AUTO_RESET);
|
| } else {
|
| @@ -1285,11 +1325,11 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| case HEADERS:
|
| // SYN_REPLY and HEADERS are the same, save for the visitor call.
|
| {
|
| - if (spdy_version_ > 3) {
|
| + if (protocol_version() > SPDY3) {
|
| DCHECK_EQ(HEADERS, current_frame_type_);
|
| }
|
| bool successful_read = true;
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
|
| DCHECK(successful_read);
|
| }
|
| @@ -1297,11 +1337,11 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| break;
|
| }
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() <= SPDY2) {
|
| // SPDY 2 had two unused bytes here. Seek past them.
|
| reader.Seek(2);
|
| }
|
| - if (spdy_version_ > 3 &&
|
| + if (protocol_version() > SPDY3 &&
|
| !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
|
| current_frame_type_ == HEADERS) {
|
| expect_continuation_ = current_frame_stream_id_;
|
| @@ -1310,7 +1350,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| const bool has_priority =
|
| (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
|
| uint32 priority = 0;
|
| - if (protocol_version() > 3 && has_priority) {
|
| + if (protocol_version() > SPDY3 && has_priority) {
|
| successful_read = reader.ReadUInt31(&priority);
|
| DCHECK(successful_read);
|
| }
|
| @@ -1318,7 +1358,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| if (debug_visitor_) {
|
| // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
|
| SpdyFrameType reported_type = current_frame_type_;
|
| - if (protocol_version() > 3 && has_priority) {
|
| + if (protocol_version() > SPDY3 && has_priority) {
|
| reported_type = SYN_STREAM;
|
| }
|
| debug_visitor_->OnReceiveCompressedFrame(
|
| @@ -1330,7 +1370,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| visitor_->OnSynReply(
|
| current_frame_stream_id_,
|
| (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
|
| - } else if (spdy_version_ > 3 &&
|
| + } else if (protocol_version() > SPDY3 &&
|
| current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
|
| // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
|
| // can be made independent of wire changes.
|
| @@ -1351,7 +1391,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
|
| break;
|
| case PUSH_PROMISE:
|
| {
|
| - DCHECK_LE(4, protocol_version());
|
| + DCHECK_LT(SPDY3, protocol_version());
|
| if (current_frame_stream_id_ == 0) {
|
| set_error(SPDY_INVALID_CONTROL_FRAME);
|
| break;
|
| @@ -1440,7 +1480,7 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
|
| processed_successfully = false;
|
| }
|
| } else if (process_bytes > 0) {
|
| - if (enable_compression_ && spdy_version_ < 4) {
|
| + if (enable_compression_ && protocol_version() <= SPDY3) {
|
| processed_successfully = IncrementallyDecompressControlFrameHeaderData(
|
| current_frame_stream_id_, data, process_bytes);
|
| } else {
|
| @@ -1497,7 +1537,7 @@ size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
|
| size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
|
| size_t processed_bytes = 0;
|
|
|
| - size_t setting_size = spdy_version_ < 4 ? 8 : 5;
|
| + size_t setting_size = protocol_version() <= SPDY3 ? 8 : 5;
|
|
|
| // Loop over our incoming data.
|
| while (unprocessed_bytes > 0) {
|
| @@ -1547,8 +1587,8 @@ size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
|
| }
|
|
|
| void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
|
| - DCHECK_GE(spdy_version_, SPDY4);
|
| - DCHECK_EQ(remaining_data_length_, 0u);
|
| + DCHECK_LT(SPDY3, protocol_version());
|
| + DCHECK_EQ(0u, remaining_data_length_);
|
|
|
| const SpdyNameValueBlock& block = hpack_decoder_.decoded_block();
|
| if (block.empty()) {
|
| @@ -1567,43 +1607,35 @@ void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
|
| }
|
|
|
| bool SpdyFramer::ProcessSetting(const char* data) {
|
| + int id_field;
|
| SpdySettingsIds id;
|
| uint8 flags = 0;
|
| uint32 value;
|
|
|
| // Extract fields.
|
| // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
|
| SettingsFlagsAndId id_and_flags =
|
| - SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
|
| - id = static_cast<SpdySettingsIds>(id_and_flags.id());
|
| + SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
|
| + id_field = id_and_flags.id();
|
| flags = id_and_flags.flags();
|
| value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
|
| } else {
|
| - id = static_cast<SpdySettingsIds>(*(reinterpret_cast<const uint8*>(data)));
|
| + id_field = *(reinterpret_cast<const uint8*>(data));
|
| value = ntohl(*(reinterpret_cast<const uint32*>(data + 1)));
|
| }
|
|
|
| // Validate id.
|
| - switch (id) {
|
| - case SETTINGS_UPLOAD_BANDWIDTH:
|
| - case SETTINGS_DOWNLOAD_BANDWIDTH:
|
| - case SETTINGS_ROUND_TRIP_TIME:
|
| - case SETTINGS_MAX_CONCURRENT_STREAMS:
|
| - case SETTINGS_CURRENT_CWND:
|
| - case SETTINGS_DOWNLOAD_RETRANS_RATE:
|
| - case SETTINGS_INITIAL_WINDOW_SIZE:
|
| - // Valid values.
|
| - break;
|
| - default:
|
| - DLOG(WARNING) << "Unknown SETTINGS ID: " << id;
|
| - return false;
|
| + if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
|
| + DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
|
| + return false;
|
| }
|
| + id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
|
|
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| // Detect duplicates.
|
| - if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
|
| + if (id <= settings_scratch_.last_setting_id) {
|
| DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
|
| << " in " << display_protocol_ << " SETTINGS frame "
|
| << "(last setting id was "
|
| @@ -1640,10 +1672,10 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
|
| switch (current_frame_type_) {
|
| case PING: {
|
| SpdyPingId id = 0;
|
| - bool is_ack =
|
| - spdy_version_ >= 4 && (current_frame_flags_ & PING_FLAG_ACK);
|
| + bool is_ack = protocol_version() > SPDY3 &&
|
| + (current_frame_flags_ & PING_FLAG_ACK);
|
| bool successful_read = true;
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| uint32 id32 = 0;
|
| successful_read = reader.ReadUInt32(&id32);
|
| id = id32;
|
| @@ -1658,7 +1690,7 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
|
| case WINDOW_UPDATE: {
|
| uint32 delta_window_size = 0;
|
| bool successful_read = true;
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
|
| DCHECK(successful_read);
|
| }
|
| @@ -1670,7 +1702,7 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
|
| }
|
| break;
|
| case BLOCKED: {
|
| - DCHECK_LE(4, protocol_version());
|
| + DCHECK_LT(SPDY3, protocol_version());
|
| DCHECK(reader.IsDoneReading());
|
| visitor_->OnBlocked(current_frame_stream_id_);
|
| }
|
| @@ -1714,7 +1746,7 @@ size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
|
|
|
| // In SPDYv3 and up, frames also specify a status code - parse it out.
|
| SpdyGoAwayStatus status = GOAWAY_OK;
|
| - if (spdy_version_ >= 3) {
|
| + if (protocol_version() >= SPDY3) {
|
| uint32 status_raw = GOAWAY_OK;
|
| successful_read = reader.ReadUInt32(&status_raw);
|
| DCHECK(successful_read);
|
| @@ -1775,7 +1807,7 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
|
| SpdyFrameReader reader(current_frame_buffer_.get(),
|
| current_frame_buffer_length_);
|
| reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
|
| - if (protocol_version() < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
|
| DCHECK(successful_read);
|
| }
|
| @@ -1815,11 +1847,87 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
|
| return original_len;
|
| }
|
|
|
| -size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
|
| +size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
|
| + DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_);
|
| +
|
| size_t original_len = len;
|
| + if (remaining_padding_length_fields_ == 0) {
|
| + DCHECK_EQ(remaining_padding_payload_length_, 0u);
|
| + bool pad_low = false;
|
| + bool pad_high = false;
|
| + if (current_frame_flags_ & net::DATA_FLAG_PAD_LOW) {
|
| + pad_low = true;
|
| + ++remaining_padding_length_fields_;
|
| + }
|
| + if (current_frame_flags_ & net::DATA_FLAG_PAD_HIGH) {
|
| + pad_high = true;
|
| + ++remaining_padding_length_fields_;
|
| + }
|
| + if ((pad_high && !pad_low) ||
|
| + remaining_data_length_ < remaining_padding_length_fields_) {
|
| + set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
|
| + return 0;
|
| + }
|
| + }
|
|
|
| - if (remaining_data_length_ > 0) {
|
| - size_t amount_to_forward = std::min(remaining_data_length_, len);
|
| + // Parse the padding length.
|
| + while (len != 0 && remaining_padding_length_fields_ != 0) {
|
| + remaining_padding_payload_length_ =
|
| + (remaining_padding_payload_length_ << 8) +
|
| + *reinterpret_cast<const uint8*>(data);
|
| + ++data;
|
| + --len;
|
| + --remaining_padding_length_fields_;
|
| + --remaining_data_length_;
|
| + }
|
| +
|
| + if (remaining_padding_length_fields_ == 0) {
|
| + if (remaining_padding_payload_length_ > remaining_data_length_) {
|
| + set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
|
| + return 0;
|
| + }
|
| + CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
|
| + }
|
| + return original_len - len;
|
| +}
|
| +
|
| +size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
|
| + DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
|
| +
|
| + size_t original_len = len;
|
| + if (remaining_padding_payload_length_ > 0) {
|
| + DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
|
| + size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
|
| + // The visitor needs to know about padding so it can send window updates.
|
| + // Communicate the padding to the visitor through a NULL data pointer, with
|
| + // a nonzero size.
|
| + if (amount_to_discard) {
|
| + visitor_->OnStreamFrameData(
|
| + current_frame_stream_id_, NULL, amount_to_discard, false);
|
| + }
|
| + data += amount_to_discard;
|
| + len -= amount_to_discard;
|
| + remaining_padding_payload_length_ -= amount_to_discard;
|
| + remaining_data_length_ -= amount_to_discard;
|
| +
|
| + // If the FIN flag is set, and there is no more data in this data
|
| + // frame, inform the visitor of EOF via a 0-length data frame.
|
| + if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) {
|
| + visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
|
| + }
|
| + }
|
| +
|
| + if (remaining_data_length_ == 0) {
|
| + CHANGE_STATE(SPDY_AUTO_RESET);
|
| + }
|
| + return original_len - len;
|
| +}
|
| +
|
| +size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
|
| + size_t original_len = len;
|
| + if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
|
| + size_t amount_to_forward = std::min(
|
| + remaining_data_length_ - remaining_padding_payload_length_, len);
|
| if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
|
| // Only inform the visitor if there is data.
|
| if (amount_to_forward) {
|
| @@ -1838,8 +1946,8 @@ size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
|
| }
|
| }
|
|
|
| - if (remaining_data_length_ == 0) {
|
| - CHANGE_STATE(SPDY_AUTO_RESET);
|
| + if (remaining_data_length_ == remaining_padding_payload_length_) {
|
| + CHANGE_STATE(SPDY_CONSUME_PADDING);
|
| }
|
| return original_len - len;
|
| }
|
| @@ -1851,7 +1959,7 @@ size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
|
|
|
| // Read number of headers.
|
| uint32 num_headers;
|
| - if (spdy_version_ < 3) {
|
| + if (protocol_version() <= SPDY2) {
|
| uint16 temp;
|
| if (!reader.ReadUInt16(&temp)) {
|
| DVLOG(1) << "Unable to read number of headers.";
|
| @@ -1870,7 +1978,7 @@ size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
|
| base::StringPiece temp;
|
|
|
| // Read header name.
|
| - if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
|
| + if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
|
| : !reader.ReadStringPiece32(&temp)) {
|
| DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
|
| << num_headers << ").";
|
| @@ -1879,7 +1987,7 @@ size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
|
| std::string name = temp.as_string();
|
|
|
| // Read header value.
|
| - if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
|
| + if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
|
| : !reader.ReadStringPiece32(&temp)) {
|
| DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
|
| << num_headers << ").";
|
| @@ -1900,37 +2008,71 @@ size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
|
| return reader.GetBytesConsumed();
|
| }
|
|
|
| -SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const {
|
| - const size_t kSize = GetDataFrameMinimumSize() + data.data().length();
|
| -
|
| - SpdyDataFlags flags = DATA_FLAG_NONE;
|
| - if (data.fin()) {
|
| +SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& datair) const {
|
| + uint8 flags = DATA_FLAG_NONE;
|
| + if (datair.fin()) {
|
| flags = DATA_FLAG_FIN;
|
| }
|
|
|
| - SpdyFrameBuilder builder(kSize);
|
| - builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
|
| - builder.WriteBytes(data.data().data(), data.data().length());
|
| - DCHECK_EQ(kSize, builder.length());
|
| - return builder.take();
|
| + if (protocol_version() > SPDY3) {
|
| + int num_padding_fields = 0;
|
| + if (datair.pad_low()) {
|
| + flags |= DATA_FLAG_PAD_LOW;
|
| + ++num_padding_fields;
|
| + }
|
| + if (datair.pad_high()) {
|
| + flags |= DATA_FLAG_PAD_HIGH;
|
| + ++num_padding_fields;
|
| + }
|
| +
|
| + const size_t size_with_padding = num_padding_fields +
|
| + datair.data().length() + datair.padding_payload_len() +
|
| + GetDataFrameMinimumSize();
|
| + SpdyFrameBuilder builder(size_with_padding);
|
| + builder.WriteDataFrameHeader(*this, datair.stream_id(), flags);
|
| + if (datair.pad_high()) {
|
| + builder.WriteUInt8(datair.padding_payload_len() >> 8);
|
| + }
|
| + if (datair.pad_low()) {
|
| + builder.WriteUInt8(datair.padding_payload_len() & 0xff);
|
| + }
|
| + builder.WriteBytes(datair.data().data(), datair.data().length());
|
| + if (datair.padding_payload_len() > 0) {
|
| + string padding = string(datair.padding_payload_len(), '0');
|
| + builder.WriteBytes(padding.data(), padding.length());
|
| + }
|
| + DCHECK_EQ(size_with_padding, builder.length());
|
| + return builder.take();
|
| + } else {
|
| + const size_t size = GetDataFrameMinimumSize() + datair.data().length();
|
| + SpdyFrameBuilder builder(size);
|
| + builder.WriteDataFrameHeader(*this, datair.stream_id(), flags);
|
| + builder.WriteBytes(datair.data().data(), datair.data().length());
|
| + DCHECK_EQ(size, builder.length());
|
| + return builder.take();
|
| + }
|
| }
|
|
|
| SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader(
|
| const SpdyDataIR& data) const {
|
| const size_t kSize = GetDataFrameMinimumSize();
|
|
|
| - SpdyDataFlags flags = DATA_FLAG_NONE;
|
| + uint8 flags = DATA_FLAG_NONE;
|
| if (data.fin()) {
|
| flags = DATA_FLAG_FIN;
|
| }
|
| + if (protocol_version() > SPDY3) {
|
| + if (data.pad_low()) {
|
| + flags |= DATA_FLAG_PAD_LOW;
|
| + }
|
| + if (data.pad_high()) {
|
| + flags |= DATA_FLAG_PAD_HIGH;
|
| + }
|
| + }
|
|
|
| SpdyFrameBuilder builder(kSize);
|
| builder.WriteDataFrameHeader(*this, data.stream_id(), flags);
|
| - if (protocol_version() < 4) {
|
| - builder.OverwriteLength(*this, data.data().length());
|
| - } else {
|
| - builder.OverwriteLength(*this, data.data().length() + kSize);
|
| - }
|
| + builder.OverwriteLength(*this, data.data().length());
|
| DCHECK_EQ(kSize, builder.length());
|
| return builder.take();
|
| }
|
| @@ -1947,7 +2089,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
|
| }
|
| // In SPDY >= 4, SYN_STREAM frames are HEADERS frames, but for now
|
| // we never expect to have to overflow into a CONTINUATION frame.
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| flags |= HEADERS_FLAG_PRIORITY;
|
| flags |= HEADERS_FLAG_END_HEADERS;
|
| }
|
| @@ -1963,7 +2105,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
|
| size_t size = GetSynStreamMinimumSize();
|
|
|
| string hpack_encoding;
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| hpack_encoder_.EncodeHeaderSet(syn_stream.name_value_block(),
|
| &hpack_encoding);
|
| size += hpack_encoding.size();
|
| @@ -1972,11 +2114,11 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
|
| }
|
|
|
| SpdyFrameBuilder builder(size);
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
|
| builder.WriteUInt32(syn_stream.stream_id());
|
| builder.WriteUInt32(syn_stream.associated_to_stream_id());
|
| - builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5));
|
| + builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
|
| builder.WriteUInt8(0); // Unused byte where credential slot used to be.
|
| } else {
|
| builder.WriteFramePrefix(*this,
|
| @@ -1986,14 +2128,15 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
|
| builder.WriteUInt32(priority);
|
| }
|
| DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
|
| } else {
|
| SerializeNameValueBlock(&builder, syn_stream);
|
| }
|
|
|
| if (debug_visitor_) {
|
| - const size_t payload_len = spdy_version_ >= 4 ? hpack_encoding.size() :
|
| + const size_t payload_len = protocol_version() > SPDY3 ?
|
| + hpack_encoding.size() :
|
| GetSerializedLength(protocol_version(),
|
| &(syn_stream.name_value_block()));
|
| // SPDY 4 reports this compression as a SYN_STREAM compression.
|
| @@ -2014,7 +2157,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply(
|
| }
|
| // In SPDY >= 4, SYN_REPLY frames are HEADERS frames, but for now
|
| // we never expect to have to overflow into a CONTINUATION frame.
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| flags |= HEADERS_FLAG_END_HEADERS;
|
| }
|
|
|
| @@ -2022,7 +2165,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply(
|
| size_t size = GetSynReplyMinimumSize();
|
|
|
| string hpack_encoding;
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| hpack_encoder_.EncodeHeaderSet(syn_reply.name_value_block(),
|
| &hpack_encoding);
|
| size += hpack_encoding.size();
|
| @@ -2031,7 +2174,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply(
|
| }
|
|
|
| SpdyFrameBuilder builder(size);
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
|
| builder.WriteUInt32(syn_reply.stream_id());
|
| } else {
|
| @@ -2040,18 +2183,19 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply(
|
| flags,
|
| syn_reply.stream_id());
|
| }
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() < SPDY3) {
|
| builder.WriteUInt16(0); // Unused.
|
| }
|
| DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
|
| } else {
|
| SerializeNameValueBlock(&builder, syn_reply);
|
| }
|
|
|
| if (debug_visitor_) {
|
| - const size_t payload_len = spdy_version_ >= 4 ? hpack_encoding.size() :
|
| + const size_t payload_len = protocol_version() > SPDY3 ?
|
| + hpack_encoding.size() :
|
| GetSerializedLength(protocol_version(),
|
| &(syn_reply.name_value_block()));
|
| debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
|
| @@ -2071,13 +2215,13 @@ SpdySerializedFrame* SpdyFramer::SerializeRstStream(
|
| // commented but left in place to simplify future patching.
|
| // Compute the output buffer size, taking opaque data into account.
|
| uint16 expected_length = GetRstStreamMinimumSize();
|
| - if (protocol_version() >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| expected_length += rst_stream.description().size();
|
| }
|
| SpdyFrameBuilder builder(expected_length);
|
|
|
| // Serialize the RST_STREAM frame.
|
| - if (protocol_version() < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
|
| builder.WriteUInt32(rst_stream.stream_id());
|
| } else {
|
| @@ -2087,7 +2231,7 @@ SpdySerializedFrame* SpdyFramer::SerializeRstStream(
|
| builder.WriteUInt32(rst_stream.status());
|
|
|
| // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
|
| - if (protocol_version() >= 4 && rst_stream.description().size() > 0) {
|
| + if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
|
| builder.WriteBytes(rst_stream.description().data(),
|
| rst_stream.description().size());
|
| }
|
| @@ -2100,7 +2244,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
|
| const SpdySettingsIR& settings) const {
|
| uint8 flags = 0;
|
|
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| if (settings.clear_settings()) {
|
| flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
|
| }
|
| @@ -2111,30 +2255,30 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
|
| }
|
| const SpdySettingsIR::ValueMap* values = &(settings.values());
|
|
|
| - size_t setting_size = (protocol_version() < 4 ? 8 : 5);
|
| + size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5);
|
| // Size, in bytes, of this SETTINGS frame.
|
| const size_t size = GetSettingsMinimumSize() +
|
| (values->size() * setting_size);
|
| SpdyFrameBuilder builder(size);
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, SETTINGS, flags);
|
| } else {
|
| builder.WriteFramePrefix(*this, SETTINGS, flags, 0);
|
| }
|
|
|
| // If this is an ACK, payload should be empty.
|
| - if (spdy_version_ >= 4 && settings.is_ack()) {
|
| + if (protocol_version() > SPDY3 && settings.is_ack()) {
|
| return builder.take();
|
| }
|
|
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteUInt32(values->size());
|
| }
|
| DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
|
| for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
|
| it != values->end();
|
| ++it) {
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| uint8 setting_flags = 0;
|
| if (it->second.persist_value) {
|
| setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
|
| @@ -2142,11 +2286,14 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
|
| if (it->second.persisted) {
|
| setting_flags |= SETTINGS_FLAG_PERSISTED;
|
| }
|
| - SettingsFlagsAndId flags_and_id(setting_flags, it->first);
|
| + SettingsFlagsAndId flags_and_id(
|
| + setting_flags,
|
| + SpdyConstants::SerializeSettingId(protocol_version(), it->first));
|
| uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
|
| builder.WriteBytes(&id_and_flags_wire, 4);
|
| } else {
|
| - builder.WriteUInt8(static_cast<uint8>(it->first));
|
| + builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(),
|
| + it->first));
|
| }
|
| builder.WriteUInt32(it->second.value);
|
| }
|
| @@ -2155,7 +2302,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings(
|
| }
|
|
|
| SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
|
| - DCHECK_LE(4, protocol_version());
|
| + DCHECK_LT(SPDY3, protocol_version());
|
| SpdyFrameBuilder builder(GetBlockedSize());
|
| builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id());
|
| return builder.take();
|
| @@ -2163,7 +2310,7 @@ SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
|
|
|
| SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
|
| SpdyFrameBuilder builder(GetPingSize());
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, PING, kNoFlags);
|
| builder.WriteUInt32(static_cast<uint32>(ping.id()));
|
| } else {
|
| @@ -2183,13 +2330,13 @@ SpdySerializedFrame* SpdyFramer::SerializeGoAway(
|
|
|
| // Compute the output buffer size, take opaque data into account.
|
| uint16 expected_length = GetGoAwayMinimumSize();
|
| - if (protocol_version() >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| expected_length += goaway.description().size();
|
| }
|
| SpdyFrameBuilder builder(expected_length);
|
|
|
| // Serialize the GOAWAY frame.
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
|
| } else {
|
| builder.WriteFramePrefix(*this, GOAWAY, 0, 0);
|
| @@ -2199,12 +2346,12 @@ SpdySerializedFrame* SpdyFramer::SerializeGoAway(
|
| builder.WriteUInt32(goaway.last_good_stream_id());
|
|
|
| // In SPDY3 and up, GOAWAY frames also specify the error status code.
|
| - if (protocol_version() >= 3) {
|
| + if (protocol_version() >= SPDY3) {
|
| builder.WriteUInt32(goaway.status());
|
| }
|
|
|
| // In SPDY4 and up, GOAWAY frames may also specify opaque data.
|
| - if ((protocol_version() >= 4) && (goaway.description().size() > 0)) {
|
| + if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
|
| builder.WriteBytes(goaway.description().data(),
|
| goaway.description().size());
|
| }
|
| @@ -2219,7 +2366,7 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
|
| if (headers.fin()) {
|
| flags |= CONTROL_FLAG_FIN;
|
| }
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| if (headers.end_headers()) {
|
| flags |= HEADERS_FLAG_END_HEADERS;
|
| }
|
| @@ -2241,7 +2388,7 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
|
| }
|
|
|
| string hpack_encoding;
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| hpack_encoder_.EncodeHeaderSet(headers.name_value_block(), &hpack_encoding);
|
| size += hpack_encoding.size();
|
| } else {
|
| @@ -2249,7 +2396,7 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
|
| }
|
|
|
| SpdyFrameBuilder builder(size);
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, HEADERS, flags);
|
| builder.WriteUInt32(headers.stream_id());
|
| } else {
|
| @@ -2261,19 +2408,20 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
|
| builder.WriteUInt32(priority);
|
| }
|
| }
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() <= SPDY2) {
|
| builder.WriteUInt16(0); // Unused.
|
| }
|
| DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
|
|
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
|
| } else {
|
| SerializeNameValueBlock(&builder, headers);
|
| }
|
|
|
| if (debug_visitor_) {
|
| - const size_t payload_len = spdy_version_ >= 4 ? hpack_encoding.size() :
|
| + const size_t payload_len = protocol_version() > SPDY3 ?
|
| + hpack_encoding.size() :
|
| GetSerializedLength(protocol_version(),
|
| &(headers.name_value_block()));
|
| debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
|
| @@ -2288,7 +2436,7 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
|
| SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
|
| const SpdyWindowUpdateIR& window_update) const {
|
| SpdyFrameBuilder builder(GetWindowUpdateSize());
|
| - if (spdy_version_ < 4) {
|
| + if (protocol_version() <= SPDY3) {
|
| builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
|
| builder.WriteUInt32(window_update.stream_id());
|
| } else {
|
| @@ -2304,7 +2452,7 @@ SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
|
|
|
| SpdyFrame* SpdyFramer::SerializePushPromise(
|
| const SpdyPushPromiseIR& push_promise) {
|
| - DCHECK_LE(4, protocol_version());
|
| + DCHECK_LT(SPDY3, protocol_version());
|
| uint8 flags = 0;
|
| if (push_promise.end_push_promise()) {
|
| flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
|
| @@ -2313,7 +2461,7 @@ SpdyFrame* SpdyFramer::SerializePushPromise(
|
| size_t size = GetPushPromiseMinimumSize();
|
|
|
| string hpack_encoding;
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| hpack_encoder_.EncodeHeaderSet(push_promise.name_value_block(),
|
| &hpack_encoding);
|
| size += hpack_encoding.size();
|
| @@ -2327,14 +2475,15 @@ SpdyFrame* SpdyFramer::SerializePushPromise(
|
| builder.WriteUInt32(push_promise.promised_stream_id());
|
| DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
|
|
|
| - if (spdy_version_ >= 4) {
|
| + if (protocol_version() > SPDY3) {
|
| builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
|
| } else {
|
| SerializeNameValueBlock(&builder, push_promise);
|
| }
|
|
|
| if (debug_visitor_) {
|
| - const size_t payload_len = spdy_version_ >= 4 ? hpack_encoding.size() :
|
| + const size_t payload_len = protocol_version() > SPDY3 ?
|
| + hpack_encoding.size() :
|
| GetSerializedLength(protocol_version(),
|
| &(push_promise.name_value_block()));
|
| debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
|
| @@ -2349,7 +2498,7 @@ SpdyFrame* SpdyFramer::SerializePushPromise(
|
| // new one. Figure out whether it makes sense to keep SerializeContinuation().
|
| SpdyFrame* SpdyFramer::SerializeContinuation(
|
| const SpdyContinuationIR& continuation) {
|
| - CHECK_GE(spdy_version_, 4);
|
| + CHECK_LT(SPDY3, protocol_version());
|
| uint8 flags = 0;
|
| if (continuation.end_headers()) {
|
| flags |= HEADERS_FLAG_END_HEADERS;
|
| @@ -2441,7 +2590,7 @@ SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
|
| }
|
|
|
| size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
|
| - CHECK_LT(spdy_version_, 4);
|
| + CHECK_GE(SPDY3, protocol_version());
|
| const size_t uncompressed_length =
|
| GetSerializedLength(protocol_version(), &headers);
|
| if (!enable_compression_) {
|
| @@ -2481,10 +2630,10 @@ z_stream* SpdyFramer::GetHeaderCompressor() {
|
| kCompressorMemLevel,
|
| Z_DEFAULT_STRATEGY);
|
| if (success == Z_OK) {
|
| - const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
|
| - : kV3Dictionary;
|
| - const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
|
| - : kV3DictionarySize;
|
| + const char* dictionary = (protocol_version() <= SPDY2) ?
|
| + kV2Dictionary : kV3Dictionary;
|
| + const int dictionary_size = (protocol_version() <= SPDY2) ?
|
| + kV2DictionarySize : kV3DictionarySize;
|
| success = deflateSetDictionary(header_compressor_.get(),
|
| reinterpret_cast<const Bytef*>(dictionary),
|
| dictionary_size);
|
| @@ -2544,13 +2693,13 @@ bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
|
|
|
| int rv = inflate(decomp, Z_SYNC_FLUSH);
|
| if (rv == Z_NEED_DICT) {
|
| - const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
|
| - : kV3Dictionary;
|
| - const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
|
| - : kV3DictionarySize;
|
| + const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
|
| + : kV3Dictionary;
|
| + const int dictionary_size = (protocol_version() <= SPDY2) ?
|
| + kV2DictionarySize : kV3DictionarySize;
|
| const DictionaryIds& ids = g_dictionary_ids.Get();
|
| - const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id
|
| - : ids.v3_dictionary_id;
|
| + const uLong dictionary_id = (protocol_version() <= SPDY2) ?
|
| + ids.v2_dictionary_id : ids.v3_dictionary_id;
|
| // Need to try again with the right dictionary.
|
| if (decomp->adler == dictionary_id) {
|
| rv = inflateSetDictionary(decomp,
|
| @@ -2608,7 +2757,7 @@ void SpdyFramer::SerializeNameValueBlockWithoutCompression(
|
| SpdyFrameBuilder* builder,
|
| const SpdyNameValueBlock& name_value_block) const {
|
| // Serialize number of headers.
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() <= SPDY2) {
|
| builder->WriteUInt16(name_value_block.size());
|
| } else {
|
| builder->WriteUInt32(name_value_block.size());
|
| @@ -2618,7 +2767,7 @@ void SpdyFramer::SerializeNameValueBlockWithoutCompression(
|
| for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
|
| it != name_value_block.end();
|
| ++it) {
|
| - if (protocol_version() < 3) {
|
| + if (protocol_version() <= SPDY2) {
|
| builder->WriteString(it->first);
|
| builder->WriteString(it->second);
|
| } else {
|
| @@ -2631,7 +2780,7 @@ void SpdyFramer::SerializeNameValueBlockWithoutCompression(
|
| void SpdyFramer::SerializeNameValueBlock(
|
| SpdyFrameBuilder* builder,
|
| const SpdyFrameWithNameValueBlockIR& frame) {
|
| - CHECK_LT(spdy_version_, 4);
|
| + CHECK_GE(SPDY3, protocol_version());
|
| if (!enable_compression_) {
|
| return SerializeNameValueBlockWithoutCompression(builder,
|
| frame.name_value_block());
|
|
|