Index: net/spdy/spdy_framer.cc |
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc |
index d323e715a049216cbfed018f0e3a1533eea8399a..313ed8d2d373a2157bdebdf15644e1186d67c146 100644 |
--- a/net/spdy/spdy_framer.cc |
+++ b/net/spdy/spdy_framer.cc |
@@ -497,16 +497,16 @@ const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) { |
return "WINDOW_UPDATE"; |
case CREDENTIAL: |
return "CREDENTIAL"; |
- case BLOCKED: |
- return "BLOCKED"; |
case PUSH_PROMISE: |
return "PUSH_PROMISE"; |
case CONTINUATION: |
return "CONTINUATION"; |
- case ALTSVC: |
- return "ALTSVC"; |
case PRIORITY: |
return "PRIORITY"; |
+ case ALTSVC: |
+ return "ALTSVC"; |
+ case BLOCKED: |
+ return "BLOCKED"; |
} |
return "UNKNOWN_CONTROL_TYPE"; |
} |
@@ -837,7 +837,6 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { |
// or add them to parsing + serialization methods for SPDY3. |
// Early detection of deprecated frames that we ignore. |
if (protocol_version() <= SPDY3) { |
- |
if (control_frame_type_field == CREDENTIAL) { |
current_frame_type_ = CREDENTIAL; |
DCHECK_EQ(SPDY3, protocol_version()); |
@@ -849,10 +848,31 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { |
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; |
+ if (protocol_version() <= SPDY3) { |
+ DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field |
+ << " (protocol version: " << protocol_version() << ")"; |
+ set_error(SPDY_INVALID_CONTROL_FRAME); |
+ return; |
+ } else { |
+ // In HTTP2 we ignore unknown frame types for extensibility, as long as |
+ // the rest of the control frame header is valid. |
+ // We rely on the visitor to check validity of current_frame_stream_id_. |
+ bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_, |
+ control_frame_type_field); |
+ if (valid_stream) { |
+ DVLOG(1) << "Ignoring unknown frame type."; |
+ CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); |
+ } else { |
+ // Report an invalid frame error and close the stream if the |
+ // stream_id is not valid. |
+ DLOG(WARNING) << "Unknown control frame type " |
+ << control_frame_type_field |
+ << " received on invalid stream " |
+ << current_frame_stream_id_; |
+ set_error(SPDY_INVALID_CONTROL_FRAME); |
+ } |
+ return; |
+ } |
} |
current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(), |
@@ -970,7 +990,6 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { |
case BLOCKED: |
if (current_frame_length_ != GetBlockedSize() || |
protocol_version() <= SPDY3) { |
- // TODO(mlavan): BLOCKED frames are no longer part of SPDY4. |
set_error(SPDY_INVALID_CONTROL_FRAME); |
} else if (current_frame_flags_ != 0) { |
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); |
@@ -1732,7 +1751,12 @@ bool SpdyFramer::ProcessSetting(const char* data) { |
// Validate id. |
if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) { |
DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field; |
- return false; |
+ if (protocol_version() <= SPDY3) { |
+ return false; |
+ } else { |
+ // In HTTP2 we ignore unknown settings for extensibility. |
+ return true; |
+ } |
} |
id = SpdyConstants::ParseSettingId(protocol_version(), id_field); |