summaryrefslogtreecommitdiffstats
path: root/net/spdy/spdy_framer.cc
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-25 08:37:30 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-25 08:37:30 +0000
commit3f2aac72c5766e101a619d66aee526b8251653b6 (patch)
treef465923c36c678d30c66800e4db90be55fc28d4f /net/spdy/spdy_framer.cc
parent01d65174be5027747da08803ff1acc865b76ec03 (diff)
downloadchromium_src-3f2aac72c5766e101a619d66aee526b8251653b6.zip
chromium_src-3f2aac72c5766e101a619d66aee526b8251653b6.tar.gz
chromium_src-3f2aac72c5766e101a619d66aee526b8251653b6.tar.bz2
Changes to read SPDY headers incrementally.
Added buffered_spdy_framer class to support buffering of spdy control header frames. It calls SpdySession's OnSyn, OnSynReply and OnHeaders methods after receiving all the control frame header data. spdy_framer*.* - integrated changes from the server. Changed OnControlFrameHeaderData to send control frame instead of stream_id. Merged changes from the following issue into this issue. http://codereview.chromium.org/8953012/ R=willchan TEST=network unit tests Review URL: http://codereview.chromium.org/8980015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115769 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/spdy/spdy_framer.cc')
-rw-r--r--net/spdy/spdy_framer.cc157
1 files changed, 97 insertions, 60 deletions
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index 7734eb8..8b41a48 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -357,37 +357,42 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
size_t original_len = len;
SpdyFrame current_frame(current_frame_buffer_, false);
- do {
- if (current_frame_len_ < SpdyFrame::kHeaderSize) {
- size_t bytes_desired = SpdyFrame::kHeaderSize - current_frame_len_;
- UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
- // Check for an empty data frame.
- if (current_frame_len_ == SpdyFrame::kHeaderSize &&
- !current_frame.is_control_frame() &&
- current_frame.length() == 0) {
- if (current_frame.flags() & CONTROL_FLAG_FIN) {
- SpdyDataFrame data_frame(current_frame_buffer_, false);
- visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
- }
- CHANGE_STATE(SPDY_AUTO_RESET);
- }
- break;
+ // Update current frame buffer as needed.
+ if (current_frame_len_ < SpdyFrame::kHeaderSize) {
+ size_t bytes_desired = SpdyFrame::kHeaderSize - current_frame_len_;
+ UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
+ }
+
+ if (current_frame_len_ < SpdyFrame::kHeaderSize) {
+ // Do nothing.
+ } else if (current_frame_len_ == SpdyFrame::kHeaderSize &&
+ !current_frame.is_control_frame() &&
+ current_frame.length() == 0) {
+ // Empty data frame.
+ SpdyDataFrame data_frame(current_frame_buffer_, false);
+ visitor_->OnDataFrameHeader(&data_frame);
+ if (current_frame.flags() & DATA_FLAG_FIN) {
+ visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
}
+ CHANGE_STATE(SPDY_AUTO_RESET);
+ } else {
remaining_data_ = current_frame.length();
// This is just a sanity check for help debugging early frame errors.
if (remaining_data_ > 1000000u) {
- LOG(WARNING) <<
- "Unexpectedly large frame. Spdy session is likely corrupt.";
+ LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
+ << " session is likely corrupt.";
}
// if we're here, then we have the common header all received.
- if (!current_frame.is_control_frame())
+ if (!current_frame.is_control_frame()) {
+ SpdyDataFrame data_frame(current_frame_buffer_, false);
+ visitor_->OnDataFrameHeader(&data_frame);
CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
- else
- CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER);
- } while (false);
-
+ } else {
+ ProcessControlFrameHeader();
+ }
+ }
return original_len - len;
}
@@ -479,12 +484,47 @@ void SpdyFramer::ProcessControlFrameHeader() {
}
remaining_control_payload_ = current_control_frame.length();
- if (remaining_control_payload_ > kControlFrameBufferMaxSize) {
+ if (remaining_control_payload_ >
+ kControlFrameBufferMaxSize - SpdyFrame::kHeaderSize) {
set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
return;
}
- ExpandControlFrameBuffer(remaining_control_payload_);
+ int32 frame_size_without_header_block;
+ switch (current_control_frame.type()) {
+ case SYN_STREAM:
+ frame_size_without_header_block = SpdySynStreamControlFrame::size();
+ break;
+ case SYN_REPLY:
+ frame_size_without_header_block = SpdySynReplyControlFrame::size();
+ break;
+ case HEADERS:
+ frame_size_without_header_block = SpdyHeadersControlFrame::size();
+ break;
+ default:
+ frame_size_without_header_block = -1;
+ LOG_IF(DFATAL, remaining_control_payload_ + SpdyFrame::kHeaderSize >
+ current_frame_capacity_)
+ << display_protocol_
+ << " control frame buffer too small for fixed-length frame.";
+ ExpandControlFrameBuffer(remaining_control_payload_);
+ break;
+ }
+
+ if (frame_size_without_header_block > 0) {
+ // We have a control frame with a header block. We need to parse the
+ // remainder of the control frame's header before we can parse the header
+ // block. The start of the header block varies with the control type.
+ DCHECK_GE(static_cast<uint32>(frame_size_without_header_block),
+ current_frame_len_);
+ remaining_control_header_ = frame_size_without_header_block -
+ current_frame_len_;
+ remaining_control_payload_ += SpdyFrame::kHeaderSize -
+ frame_size_without_header_block;
+ CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
+ return;
+ }
+
CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
}
@@ -526,8 +566,8 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
// visitor or decompresses and then passes directly to the visitor, via
// IncrementallyDeliverControlFrameHeaderData() or
// IncrementallyDecompressControlFrameHeaderData() respectively.
-size_t SpdyFramer::NewProcessControlFrameHeaderBlock(const char* data,
- size_t data_len) {
+size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
+ size_t data_len) {
DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
SpdyControlFrame control_frame(current_frame_buffer_, false);
bool processed_successfully = true;
@@ -538,7 +578,7 @@ size_t SpdyFramer::NewProcessControlFrameHeaderBlock(const char* data,
DCHECK_GT(process_bytes, 0u);
if (enable_compression_) {
- processed_successfully = NewIncrementallyDecompressControlFrameHeaderData(
+ processed_successfully = IncrementallyDecompressControlFrameHeaderData(
&control_frame, data, process_bytes);
} else {
processed_successfully = IncrementallyDeliverControlFrameHeaderData(
@@ -550,8 +590,7 @@ size_t SpdyFramer::NewProcessControlFrameHeaderBlock(const char* data,
if (remaining_control_payload_ == 0 && processed_successfully) {
// The complete header block has been delivered. We send a zero-length
// OnControlFrameHeaderData() to indicate this.
- visitor_->OnControlFrameHeaderData(
- GetControlFrameStreamId(&control_frame), NULL, 0);
+ visitor_->OnControlFrameHeaderData(&control_frame, NULL, 0);
// If this is a FIN, tell the caller.
if (control_frame.flags() & CONTROL_FLAG_FIN) {
@@ -571,8 +610,8 @@ size_t SpdyFramer::NewProcessControlFrameHeaderBlock(const char* data,
return process_bytes;
}
-size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
- size_t data_len) {
+size_t SpdyFramer::OldProcessControlFrameHeaderBlock(const char* data,
+ size_t data_len) {
DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
size_t original_data_len = data_len;
SpdyControlFrame control_frame(current_frame_buffer_, false);
@@ -591,7 +630,7 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
remaining_control_payload_);
remaining_control_payload_ -= bytes_read;
if (remaining_control_payload_ == 0) {
- read_successfully = IncrementallyDecompressControlFrameHeaderData(
+ read_successfully = OldIncrementallyDecompressControlFrameHeaderData(
&control_frame);
}
}
@@ -605,8 +644,7 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
}
if (remaining_control_payload_ == 0 && read_successfully) {
// The complete header block has been delivered.
- visitor_->OnControlFrameHeaderData(GetControlFrameStreamId(&control_frame),
- NULL, 0);
+ visitor_->OnControlFrameHeaderData(&control_frame, NULL, 0);
// If this is a FIN, tell the caller.
if (control_frame.flags() & CONTROL_FLAG_FIN) {
@@ -624,28 +662,27 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
size_t original_len = len;
- do {
- if (remaining_control_payload_) {
- size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
- remaining_control_payload_);
- remaining_control_payload_ -= bytes_read;
- remaining_data_ -= bytes_read;
- if (remaining_control_payload_)
- break;
- }
- SpdyControlFrame control_frame(current_frame_buffer_, false);
- visitor_->OnControl(&control_frame);
+ if (remaining_control_payload_) {
+ size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
+ remaining_control_payload_);
+ remaining_control_payload_ -= bytes_read;
+ remaining_data_ -= bytes_read;
+ if (remaining_control_payload_ == 0) {
+ SpdyControlFrame control_frame(current_frame_buffer_, false);
+ DCHECK(!control_frame.has_header_block());
+ visitor_->OnControl(&control_frame);
- // If this is a FIN, tell the caller.
- if (control_frame.type() == SYN_REPLY &&
- control_frame.flags() & CONTROL_FLAG_FIN) {
- visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>(
- &control_frame)->stream_id(),
- NULL, 0);
- }
+ // If this is a FIN, tell the caller.
+ if (control_frame.type() == SYN_REPLY &&
+ control_frame.flags() & CONTROL_FLAG_FIN) {
+ visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>(
+ &control_frame)->stream_id(),
+ NULL, 0);
+ }
- CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
- } while (false);
+ CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
+ }
+ }
return original_len - len;
}
@@ -1427,7 +1464,7 @@ SpdyFrame* SpdyFramer::DecompressFrameWithZStream(const SpdyFrame& frame,
// result to the visitor in chunks. Continue this until the visitor
// indicates that it cannot process any more data, or (more commonly) we
// run out of data to deliver.
-bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
+bool SpdyFramer::OldIncrementallyDecompressControlFrameHeaderData(
const SpdyControlFrame* control_frame) {
z_stream* decomp = GetHeaderDecompressor();
int payload_length;
@@ -1459,8 +1496,8 @@ bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
} else {
DCHECK_GT(arraysize(buffer), decomp->avail_out);
size_t len = arraysize(buffer) - decomp->avail_out;
- read_successfully = visitor_->OnControlFrameHeaderData(stream_id, buffer,
- len);
+ read_successfully = visitor_->OnControlFrameHeaderData(
+ control_frame, buffer, len);
if (!read_successfully) {
// Assume that the problem was the header block was too large for the
// visitor.
@@ -1476,7 +1513,7 @@ bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
// result to the visitor in chunks. Continue this until the visitor
// indicates that it cannot process any more data, or (more commonly) we
// run out of data to deliver.
-bool SpdyFramer::NewIncrementallyDecompressControlFrameHeaderData(
+bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
const SpdyControlFrame* control_frame,
const char* data,
size_t len) {
@@ -1507,7 +1544,7 @@ bool SpdyFramer::NewIncrementallyDecompressControlFrameHeaderData(
size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
if (decompressed_len > 0) {
processed_successfully = visitor_->OnControlFrameHeaderData(
- stream_id, buffer, decompressed_len);
+ control_frame, buffer, decompressed_len);
}
if (!processed_successfully) {
// Assume that the problem was the header block was too large for the
@@ -1526,7 +1563,7 @@ bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
DCHECK_LT(0u, stream_id);
while (read_successfully && len > 0) {
size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
- read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
+ read_successfully = visitor_->OnControlFrameHeaderData(control_frame, data,
bytes_to_deliver);
data += bytes_to_deliver;
len -= bytes_to_deliver;