Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1347)

Unified Diff: net/spdy/spdy_framer.cc

Issue 485833002: HTTP2 draft 14 support (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add ignore_result(). Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_framer.cc
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index 04ace4017fb6a56d2ec34b918f693fda03bfc0d1..edcc82e5fa021a3e68a7cd7ee206b8f2c92a2d97 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -74,9 +74,10 @@ const size_t kPriorityWeightPayloadSize = 1;
const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
+// The size of the control frame buffer. Must be >= the minimum size of the
// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
// calculation details.
-const size_t SpdyFramer::kControlFrameBufferSize = 18;
+const size_t SpdyFramer::kControlFrameBufferSize = 19;
#ifdef DEBUG_SPDY_STATE_CHANGES
#define CHANGE_STATE(newstate) \
@@ -188,7 +189,7 @@ void SpdyFramer::Reset() {
}
size_t SpdyFramer::GetDataFrameMinimumSize() const {
- return SpdyConstants::GetDataFrameMinimumSize();
+ return SpdyConstants::GetDataFrameMinimumSize(protocol_version());
}
// Size, in bytes, of the control frame header.
@@ -497,16 +498,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";
}
@@ -722,8 +723,8 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
} else {
version = protocol_version();
- uint16 length_field = 0;
- bool successful_read = reader->ReadUInt16(&length_field);
+ uint32 length_field = 0;
+ bool successful_read = reader->ReadUInt24(&length_field);
DCHECK(successful_read);
uint8 control_frame_type_field_uint8 =
@@ -734,9 +735,9 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
// ProcessControlFrameHeader().
control_frame_type_field = control_frame_type_field_uint8;
is_control_frame = (protocol_version() > SPDY3) ?
- control_frame_type_field !=
- SpdyConstants::SerializeFrameType(protocol_version(), DATA) :
- control_frame_type_field != 0;
+ control_frame_type_field !=
+ SpdyConstants::SerializeFrameType(protocol_version(), DATA) :
+ control_frame_type_field != 0;
if (is_control_frame) {
current_frame_length_ = length_field + GetControlFrameHeaderSize();
@@ -837,7 +838,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 +849,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(),
@@ -947,6 +968,8 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
min_size += 4;
}
if (current_frame_length_ < min_size) {
+ // TODO(mlavan): check here for HEADERS with no payload?
+ // (not allowed in SPDY4)
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (protocol_version() <= SPDY3 &&
current_frame_flags_ & ~CONTROL_FLAG_FIN) {
@@ -970,7 +993,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 +1754,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);
@@ -1877,13 +1904,10 @@ size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
status_raw);
} else {
- DCHECK(false);
- // Throw an error for SPDY4+, keep liberal behavior
- // for earlier versions.
if (protocol_version() > SPDY3) {
- DLOG(WARNING) << "Invalid GO_AWAY status " << status_raw;
- set_error(SPDY_INVALID_CONTROL_FRAME);
- return 0;
+ // Treat unrecognized status codes as INTERNAL_ERROR as
+ // recommended by the HTTP/2 spec.
+ status = GOAWAY_INTERNAL_ERROR;
}
}
}
@@ -1946,12 +1970,10 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
status_raw)) {
status = static_cast<SpdyRstStreamStatus>(status_raw);
} else {
- // Throw an error for SPDY4+, keep liberal behavior
- // for earlier versions.
if (protocol_version() > SPDY3) {
- DLOG(WARNING) << "Invalid RST_STREAM status " << status_raw;
- set_error(SPDY_INVALID_CONTROL_FRAME);
- return 0;
+ // Treat unrecognized status codes as INTERNAL_ERROR as
+ // recommended by the HTTP/2 spec.
+ status = RST_STREAM_INTERNAL_ERROR;
}
}
// Finished parsing the RST_STREAM header, call frame handler.
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698