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()); |