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

Unified Diff: net/spdy/spdy_framer.cc

Issue 290203003: HTTP/2 framer support for reading headers with padding, and for segments. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | « no previous file | 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 f7b52831d7912d9bf166f3bbfb55f35d2559c948..7153ad491dab20cb42ac2e8882d93eac4956e980 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -929,9 +929,11 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
} else if (protocol_version() <= SPDY3 &&
current_frame_flags_ & ~CONTROL_FLAG_FIN) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 && current_frame_flags_ &
- ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
- HEADERS_FLAG_END_HEADERS)) {
+ } else if (protocol_version() > SPDY3 &&
+ current_frame_flags_ &
+ ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
+ HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
+ HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
}
@@ -957,8 +959,10 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 && current_frame_flags_ &
- ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE) {
+ } else if (protocol_version() > SPDY3 &&
+ current_frame_flags_ &
+ ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
+ HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
break;
@@ -966,7 +970,9 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
if (current_frame_length_ < GetContinuationMinimumSize() ||
protocol_version() <= SPDY3) {
set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
+ } else if (current_frame_flags_ &
+ ~(HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PAD_LOW |
+ HEADERS_FLAG_PAD_HIGH)) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
break;
@@ -1444,7 +1450,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
expect_continuation_ == 0);
}
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
break;
case PUSH_PROMISE:
{
@@ -1475,7 +1481,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
(current_frame_flags_ &
PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
break;
case CONTINUATION:
{
@@ -1501,7 +1507,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
(current_frame_flags_ &
HEADERS_FLAG_END_HEADERS) != 0);
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
break;
default:
DCHECK(false);
@@ -1527,7 +1533,8 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
current_frame_type_ != CONTINUATION) {
LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
}
- size_t process_bytes = std::min(data_len, remaining_data_length_);
+ size_t process_bytes = std::min(
+ data_len, remaining_data_length_ - remaining_padding_payload_length_);
if (is_hpack_header_block) {
if (!GetHpackDecoder()->HandleControlFrameHeadersData(
current_frame_stream_id_, data, process_bytes)) {
@@ -1547,7 +1554,8 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
remaining_data_length_ -= process_bytes;
// Handle the case that there is no futher data in this frame.
- if (remaining_data_length_ == 0 && processed_successfully) {
+ if (remaining_data_length_ == remaining_padding_payload_length_ &&
+ processed_successfully) {
if (expect_continuation_ == 0) {
if (is_hpack_header_block) {
if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
@@ -1567,14 +1575,10 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
// OnControlFrameHeaderData() to indicate this.
visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
}
- // If this is a FIN, tell the caller.
- if ((current_frame_flags_ & CONTROL_FLAG_FIN) || end_stream_when_done_) {
- end_stream_when_done_ = false;
- visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
- }
}
- if (processed_successfully)
- CHANGE_STATE(SPDY_AUTO_RESET);
+ if (processed_successfully) {
+ CHANGE_STATE(SPDY_CONSUME_PADDING);
+ }
}
// Handle error.
@@ -1644,7 +1648,7 @@ size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
DCHECK_LT(SPDY3, protocol_version());
- DCHECK_EQ(0u, remaining_data_length_);
+ DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
if (block.empty()) {
@@ -1659,8 +1663,16 @@ void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
SerializeNameValueBlockWithoutCompression(&builder, block);
scoped_ptr<SpdyFrame> frame(builder.take());
+ // Preserve padding length, and reset it after the re-entrant call.
+ size_t remaining_padding = remaining_padding_payload_length_;
+
+ remaining_padding_payload_length_ = 0;
remaining_data_length_ = frame->size();
+
ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
+
+ remaining_padding_payload_length_ = remaining_padding;
+ remaining_data_length_ = remaining_padding;
}
bool SpdyFramer::ProcessSetting(const char* data) {
@@ -2083,7 +2095,17 @@ size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
return 0;
}
- CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
+ if (current_frame_type_ == DATA) {
+ CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
+ } else {
+ DCHECK(current_frame_type_ == HEADERS ||
+ current_frame_type_ == PUSH_PROMISE ||
+ current_frame_type_ == CONTINUATION ||
+ current_frame_type_ == SYN_STREAM ||
+ current_frame_type_ == SYN_REPLY)
+ << current_frame_type_;
+ CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ }
}
return original_len - len;
}
@@ -2095,10 +2117,10 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t 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) {
+ if (current_frame_type_ == DATA && amount_to_discard > 0) {
+ // 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.
visitor_->OnStreamFrameData(
current_frame_stream_id_, NULL, amount_to_discard, false);
}
@@ -2109,12 +2131,14 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
}
if (remaining_data_length_ == 0) {
- // If the FIN flag is set, and there is no more data in this data frame,
+ // If the FIN flag is set, or this ends a header block which set FIN,
// inform the visitor of EOF via a 0-length data frame.
- if (current_frame_flags_ & DATA_FLAG_FIN) {
+ if (expect_continuation_ == 0 &&
+ ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
+ end_stream_when_done_)) {
+ end_stream_when_done_ = false;
visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
}
-
CHANGE_STATE(SPDY_AUTO_RESET);
}
return original_len - len;
« no previous file with comments | « no previous file | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698