Index: net/spdy/spdy_framer.cc |
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc |
index 53070f23061b2aebf6bf627aab92c4c6f95bed2e..3e3d32bae1898e5f7c9d775ce35ab5bdf70c8287 100644 |
--- a/net/spdy/spdy_framer.cc |
+++ b/net/spdy/spdy_framer.cc |
@@ -671,11 +671,7 @@ void SpdyFramer::ProcessControlFrameHeader() { |
break; |
case SYN_REPLY: |
syn_frame_processed_ = true; |
- frame_size_without_variable_data = SpdySynReplyControlFrame::size(); |
- // SPDY 2 had two bytes of unused space preceeding payload. |
- if (spdy_version_ < 3) { |
- frame_size_without_variable_data += 2; |
- } |
+ frame_size_without_variable_data = GetSynReplyMinimumSize(); |
break; |
case HEADERS: |
frame_size_without_variable_data = SpdyHeadersControlFrame::size(); |
@@ -970,11 +966,22 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, |
break; |
case SYN_REPLY: |
{ |
- SpdySynReplyControlFrame* syn_reply_frame = |
- reinterpret_cast<SpdySynReplyControlFrame*>(&control_frame); |
- visitor_->OnSynReply( |
- syn_reply_frame->stream_id(), |
- (syn_reply_frame->flags() & CONTROL_FLAG_FIN) != 0); |
+ SpdyFrameReader reader(current_frame_buffer_.get(), |
+ current_frame_len_); |
+ reader.Seek(4); // Seek past control bit, type and version. |
+ uint8 flags; |
+ bool successful_read = reader.ReadUInt8(&flags); |
+ DCHECK(successful_read); |
+ reader.Seek(3); // Seek past length. |
+ SpdyStreamId stream_id = kInvalidStream; |
+ successful_read = reader.ReadUInt31(&stream_id); |
+ DCHECK(successful_read); |
+ if (protocol_version() < 3) { |
+ // SPDY 2 had two unused bytes here. Seek past them. |
+ reader.Seek(2); |
+ } |
+ DCHECK(reader.IsDoneReading()); |
+ visitor_->OnSynReply(stream_id, (flags & CONTROL_FLAG_FIN) != 0); |
} |
CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); |
break; |
@@ -1194,15 +1201,28 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { |
} |
break; |
case GOAWAY: { |
- SpdyGoAwayControlFrame* go_away_frame = |
- reinterpret_cast<SpdyGoAwayControlFrame*>(&control_frame); |
- if (spdy_version_ < 3) { |
- visitor_->OnGoAway(go_away_frame->last_accepted_stream_id(), |
- GOAWAY_OK); |
- } else { |
- visitor_->OnGoAway(go_away_frame->last_accepted_stream_id(), |
- go_away_frame->status()); |
+ SpdyFrameReader reader(current_frame_buffer_.get(), |
+ current_frame_len_); |
+ reader.Seek(GetControlFrameMinimumSize()); // Skip frame header. |
+ SpdyStreamId last_accepted_stream_id = kInvalidStream; |
+ bool successful_read = reader.ReadUInt32(&last_accepted_stream_id); |
+ DCHECK(successful_read); |
+ SpdyGoAwayStatus status = GOAWAY_OK; |
+ if (spdy_version_ >= 3) { |
+ uint32 status_raw = GOAWAY_OK; |
+ successful_read = reader.ReadUInt32(&status_raw); |
+ DCHECK(successful_read); |
+ if (status_raw > static_cast<uint32>(GOAWAY_INVALID) && |
+ status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) { |
+ status = static_cast<SpdyGoAwayStatus>(status_raw); |
+ } else { |
+ // TODO(hkhalil): Probably best to OnError here, depending on |
+ // our interpretation of the spec. Keeping with existing liberal |
+ // behavior for now. |
+ } |
} |
+ DCHECK(reader.IsDoneReading()); |
+ visitor_->OnGoAway(last_accepted_stream_id, status); |
} |
break; |
default: |
@@ -1434,7 +1454,7 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream( |
return builder.take(); |
} |
-SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( |
+SpdyFrame* SpdyFramer::CreateSynReply( |
SpdyStreamId stream_id, |
SpdyControlFlags flags, |
bool compressed, |
@@ -1446,12 +1466,10 @@ SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( |
// TODO(hkhalil): Avoid copy here. |
*(syn_reply.GetMutableNameValueBlock()) = *headers; |
- scoped_ptr<SpdySynReplyControlFrame> reply_frame( |
- reinterpret_cast<SpdySynReplyControlFrame*>(SerializeSynReply( |
- syn_reply))); |
+ scoped_ptr<SpdyControlFrame> reply_frame( |
+ reinterpret_cast<SpdyControlFrame*>(SerializeSynReply(syn_reply))); |
if (compressed) { |
- return reinterpret_cast<SpdySynReplyControlFrame*>( |
- CompressControlFrame(*reply_frame.get(), headers)); |
+ return CompressControlFrame(*reply_frame.get(), headers); |
} |
return reply_frame.release(); |
} |
@@ -1559,11 +1577,11 @@ SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
return builder.take(); |
} |
-SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( |
+SpdyFrame* SpdyFramer::CreateGoAway( |
SpdyStreamId last_accepted_stream_id, |
SpdyGoAwayStatus status) const { |
SpdyGoAwayIR goaway(last_accepted_stream_id, status); |
- return reinterpret_cast<SpdyGoAwayControlFrame*>(SerializeGoAway(goaway)); |
+ return SerializeGoAway(goaway); |
} |
SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
@@ -1791,17 +1809,10 @@ bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame, |
break; |
case SYN_REPLY: |
{ |
- const SpdySynReplyControlFrame& syn_frame = |
- reinterpret_cast<const SpdySynReplyControlFrame&>(frame); |
- frame_size = SpdySynReplyControlFrame::size(); |
- *payload_length = syn_frame.header_block_len(); |
- *header_length = frame_size; |
+ *header_length = GetSynReplyMinimumSize(); |
+ *payload_length = frame.length() - |
+ (*header_length - GetControlFrameMinimumSize()); |
*payload = frame.data() + *header_length; |
- // SPDY 2 had two bytes of unused space preceeding payload. |
- if (spdy_version_ < 3) { |
- *header_length += 2; |
- *payload += 2; |
- } |
} |
break; |
case HEADERS: |