Index: net/spdy/spdy_framer.cc |
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc |
index 125b6cc36006a74998bb10923198e4a9c2a06983..b3954484d4035dc332017d740243013c17088094 100644 |
--- a/net/spdy/spdy_framer.cc |
+++ b/net/spdy/spdy_framer.cc |
@@ -167,7 +167,7 @@ size_t SpdyFramer::GetControlFrameHeaderSize() const { |
case 3: |
return 8; |
case 4: |
- return 4; |
+ return 8; |
} |
LOG(DFATAL) << "Unhandled SPDY version."; |
return 0; |
@@ -175,16 +175,27 @@ 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. Calculated as: |
- // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) |
- return GetControlFrameHeaderSize() + 10; |
+ // name-value block. |
+ if (spdy_version_ < 4) { |
+ // Calculated as: |
+ // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) |
+ return GetControlFrameHeaderSize() + 10; |
+ } else { |
+ // Calculated as: |
+ // frame prefix + 4 (associated stream ID) + 1 (priority) + 1 (slot) |
+ return GetControlFrameHeaderSize() + 6; |
+ } |
} |
size_t SpdyFramer::GetSynReplyMinimumSize() const { |
// Size, in bytes, of a SYN_REPLY frame not including the variable-length |
- // name-value block. Calculated as: |
- // control frame header + 4 (stream ID) |
- size_t size = GetControlFrameHeaderSize() + 4; |
+ // name-value block. |
+ size_t size = GetControlFrameHeaderSize(); |
+ if (spdy_version_ < 4) { |
+ // Calculated as: |
+ // control frame header + 4 (stream IDs) |
+ size += 4; |
+ } |
// In SPDY 2, there were 2 unused bytes before payload. |
if (protocol_version() < 3) { |
@@ -195,9 +206,16 @@ size_t SpdyFramer::GetSynReplyMinimumSize() const { |
} |
size_t SpdyFramer::GetRstStreamSize() const { |
- // Size, in bytes, of a RST_STREAM frame. Calculated as: |
- // control frame header + 4 (stream id) + 4 (status code) |
- return GetControlFrameHeaderSize() + 8; |
+ // Size, in bytes, of a RST_STREAM frame. |
+ if (spdy_version_ < 4) { |
+ // Calculated as: |
+ // control frame header + 4 (stream id) + 4 (status code) |
+ return GetControlFrameHeaderSize() + 8; |
+ } else { |
+ // Calculated as: |
+ // frame prefix + 4 (status code) |
+ return GetControlFrameHeaderSize() + 4; |
+ } |
} |
size_t SpdyFramer::GetSettingsMinimumSize() const { |
@@ -227,10 +245,14 @@ size_t SpdyFramer::GetGoAwaySize() const { |
} |
size_t SpdyFramer::GetHeadersMinimumSize() const { |
- // Size, in bytes, of a HEADERS frame not including the variable-length |
- // name-value block. Calculated as: |
- // control frame header + 4 (stream ID) |
- size_t size = GetControlFrameHeaderSize() + 4; |
+ // Size, in bytes, of a SYN_REPLY frame not including the variable-length |
+ // name-value block. |
+ size_t size = GetControlFrameHeaderSize(); |
+ if (spdy_version_ < 4) { |
+ // Calculated as: |
+ // control frame header + 4 (stream IDs) |
+ size += 4; |
+ } |
// In SPDY 2, there were 2 unused bytes before payload. |
if (protocol_version() < 3) { |
@@ -241,9 +263,16 @@ size_t SpdyFramer::GetHeadersMinimumSize() const { |
} |
size_t SpdyFramer::GetWindowUpdateSize() const { |
- // Size, in bytes, of this WINDOW_UPDATE frame. Calculated as: |
- // control frame header + 4 (stream id) + 4 (delta) |
- return GetControlFrameHeaderSize() + 8; |
+ // Size, in bytes, of a WINDOW_UPDATE frame. |
+ if (spdy_version_ < 4) { |
+ // Calculated as: |
+ // control frame header + 4 (stream id) + 4 (delta) |
+ return GetControlFrameHeaderSize() + 8; |
+ } else { |
+ // Calculated as: |
+ // frame prefix + 4 (delta) |
+ return GetControlFrameHeaderSize() + 4; |
+ } |
} |
size_t SpdyFramer::GetCredentialMinimumSize() const { |
@@ -542,7 +571,6 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { |
remaining_data_length_ = length_field; |
current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); |
} else { |
- // TODO(hkhalil): Avoid re-reading fields as possible for DATA frames? |
version = protocol_version(); |
uint16 length_field = 0; |
bool successful_read = reader->ReadUInt16(&length_field); |
@@ -560,23 +588,9 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { |
successful_read = reader->ReadUInt8(¤t_frame_flags_); |
DCHECK(successful_read); |
- if (!is_control_frame) { |
- // We may not have the entirety of the DATA frame header. |
- if (current_frame_buffer_length_ < GetDataFrameMinimumSize()) { |
- size_t bytes_desired = |
- GetDataFrameMinimumSize() - current_frame_buffer_length_; |
- UpdateCurrentFrameBuffer(&data, &len, bytes_desired); |
- if (current_frame_buffer_length_ < GetDataFrameMinimumSize()) { |
- return original_len - len; |
- } |
- } |
- // Construct a new SpdyFrameReader aware of the new frame length. |
- reader.reset(new SpdyFrameReader(current_frame_buffer_.get(), |
- current_frame_buffer_length_)); |
- reader->Seek(GetControlFrameHeaderSize()); |
- successful_read = reader->ReadUInt31(¤t_frame_stream_id_); |
- DCHECK(successful_read); |
- } |
+ successful_read = reader->ReadUInt31(¤t_frame_stream_id_); |
+ DCHECK(successful_read); |
+ |
remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed(); |
} |
DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize() |
@@ -1042,8 +1056,11 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, |
switch (current_frame_type_) { |
case SYN_STREAM: |
{ |
- bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
- DCHECK(successful_read); |
+ bool successful_read = true; |
+ if (spdy_version_ < 4) { |
+ successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
+ DCHECK(successful_read); |
+ } |
SpdyStreamId associated_to_stream_id = kInvalidStream; |
successful_read = reader.ReadUInt31(&associated_to_stream_id); |
@@ -1082,8 +1099,11 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, |
case HEADERS: |
// SYN_REPLY and HEADERS are the same, save for the visitor call. |
{ |
- bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
- DCHECK(successful_read); |
+ bool successful_read = true; |
+ if (spdy_version_ < 4) { |
+ successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
+ DCHECK(successful_read); |
+ } |
if (protocol_version() < 3) { |
// SPDY 2 had two unused bytes here. Seek past them. |
reader.Seek(2); |
@@ -1288,9 +1308,12 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { |
break; |
case WINDOW_UPDATE: { |
uint32 delta_window_size = 0; |
- bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
- DCHECK(successful_read); |
- successful_read = reader.ReadUInt31(&delta_window_size); |
+ bool successful_read = true; |
+ if (spdy_version_ < 4) { |
+ successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
+ DCHECK(successful_read); |
+ } |
+ successful_read = reader.ReadUInt32(&delta_window_size); |
DCHECK(successful_read); |
DCHECK(reader.IsDoneReading()); |
visitor_->OnWindowUpdate(current_frame_stream_id_, |
@@ -1298,8 +1321,11 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { |
} |
break; |
case RST_STREAM: { |
- bool successful_read = reader.ReadUInt32(¤t_frame_stream_id_); |
- DCHECK(successful_read); |
+ bool successful_read = true; |
+ if (spdy_version_ < 4) { |
+ successful_read = reader.ReadUInt31(¤t_frame_stream_id_); |
+ DCHECK(successful_read); |
+ } |
SpdyRstStreamStatus status = RST_STREAM_INVALID; |
uint32 status_raw = status; |
successful_read = reader.ReadUInt32(&status_raw); |
@@ -1511,8 +1537,15 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream( |
+ GetSerializedLength(syn_stream.name_value_block()); |
SpdyFrameBuilder builder(size); |
- builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); |
- builder.WriteUInt32(syn_stream.stream_id()); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); |
+ builder.WriteUInt32(syn_stream.stream_id()); |
+ } else { |
+ builder.WriteFramePrefix(*this, |
+ SYN_STREAM, |
+ flags, |
+ syn_stream.stream_id()); |
+ } |
builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
uint8 priority = syn_stream.priority(); |
if (priority > GetLowestPriority()) { |
@@ -1559,8 +1592,15 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply( |
+ GetSerializedLength(syn_reply.name_value_block()); |
SpdyFrameBuilder builder(size); |
- builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); |
- builder.WriteUInt32(syn_reply.stream_id()); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); |
+ builder.WriteUInt32(syn_reply.stream_id()); |
+ } else { |
+ builder.WriteFramePrefix(*this, |
+ SYN_REPLY, |
+ flags, |
+ syn_reply.stream_id()); |
+ } |
if (protocol_version() < 3) { |
builder.WriteUInt16(0); // Unused. |
} |
@@ -1580,8 +1620,15 @@ SpdyFrame* SpdyFramer::CreateRstStream( |
SpdySerializedFrame* SpdyFramer::SerializeRstStream( |
const SpdyRstStreamIR& rst_stream) const { |
SpdyFrameBuilder builder(GetRstStreamSize()); |
- builder.WriteControlFrameHeader(*this, RST_STREAM, 0); |
- builder.WriteUInt32(rst_stream.stream_id()); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, RST_STREAM, 0); |
+ builder.WriteUInt32(rst_stream.stream_id()); |
+ } else { |
+ builder.WriteFramePrefix(*this, |
+ RST_STREAM, |
+ 0, |
+ rst_stream.stream_id()); |
+ } |
builder.WriteUInt32(rst_stream.status()); |
DCHECK_EQ(GetRstStreamSize(), builder.length()); |
return builder.take(); |
@@ -1613,7 +1660,11 @@ SpdySerializedFrame* SpdyFramer::SerializeSettings( |
const size_t size = GetSettingsMinimumSize() + (values->size() * 8); |
SpdyFrameBuilder builder(size); |
- builder.WriteControlFrameHeader(*this, SETTINGS, flags); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, SETTINGS, flags); |
+ } else { |
+ builder.WriteFramePrefix(*this, SETTINGS, flags, 0); |
+ } |
builder.WriteUInt32(values->size()); |
DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); |
for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); |
@@ -1642,7 +1693,11 @@ SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { |
SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
SpdyFrameBuilder builder(GetPingSize()); |
- builder.WriteControlFrameHeader(*this, PING, 0); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, PING, kNoFlags); |
+ } else { |
+ builder.WriteFramePrefix(*this, PING, 0, 0); |
+ } |
builder.WriteUInt32(ping.id()); |
DCHECK_EQ(GetPingSize(), builder.length()); |
return builder.take(); |
@@ -1658,7 +1713,11 @@ SpdyFrame* SpdyFramer::CreateGoAway( |
SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
const SpdyGoAwayIR& goaway) const { |
SpdyFrameBuilder builder(GetGoAwaySize()); |
- builder.WriteControlFrameHeader(*this, GOAWAY, 0); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); |
+ } else { |
+ builder.WriteFramePrefix(*this, GOAWAY, 0, 0); |
+ } |
builder.WriteUInt32(goaway.last_good_stream_id()); |
if (protocol_version() >= 3) { |
builder.WriteUInt32(goaway.status()); |
@@ -1697,8 +1756,15 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders( |
+ GetSerializedLength(headers.name_value_block()); |
SpdyFrameBuilder builder(size); |
- builder.WriteControlFrameHeader(*this, HEADERS, flags); |
- builder.WriteUInt32(headers.stream_id()); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, HEADERS, flags); |
+ builder.WriteUInt32(headers.stream_id()); |
+ } else { |
+ builder.WriteFramePrefix(*this, |
+ HEADERS, |
+ flags, |
+ headers.stream_id()); |
+ } |
if (protocol_version() < 3) { |
builder.WriteUInt16(0); // Unused. |
} |
@@ -1719,8 +1785,15 @@ SpdyFrame* SpdyFramer::CreateWindowUpdate( |
SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( |
const SpdyWindowUpdateIR& window_update) const { |
SpdyFrameBuilder builder(GetWindowUpdateSize()); |
- builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); |
- builder.WriteUInt32(window_update.stream_id()); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); |
+ builder.WriteUInt32(window_update.stream_id()); |
+ } else { |
+ builder.WriteFramePrefix(*this, |
+ WINDOW_UPDATE, |
+ kNoFlags, |
+ window_update.stream_id()); |
+ } |
builder.WriteUInt32(window_update.delta()); |
DCHECK_EQ(GetWindowUpdateSize(), builder.length()); |
return builder.take(); |
@@ -1751,7 +1824,11 @@ SpdySerializedFrame* SpdyFramer::SerializeCredential( |
} |
SpdyFrameBuilder builder(size); |
- builder.WriteControlFrameHeader(*this, CREDENTIAL, 0); |
+ if (spdy_version_ < 4) { |
+ builder.WriteControlFrameHeader(*this, CREDENTIAL, kNoFlags); |
+ } else { |
+ builder.WriteFramePrefix(*this, CREDENTIAL, kNoFlags, 0); |
+ } |
builder.WriteUInt16(credential.slot()); |
DCHECK_EQ(GetCredentialMinimumSize(), builder.length()); |
builder.WriteStringPiece32(credential.proof()); |