Index: net/spdy/spdy_frame_builder.cc |
diff --git a/net/spdy/spdy_frame_builder.cc b/net/spdy/spdy_frame_builder.cc |
index 7ea7716b41bfff075e51f796415e8130d2f209f0..fc37c0b4a290d534859b425a822ee3392d7418d3 100644 |
--- a/net/spdy/spdy_frame_builder.cc |
+++ b/net/spdy/spdy_frame_builder.cc |
@@ -32,10 +32,12 @@ FlagsAndLength CreateFlagsAndLength(uint8 flags, size_t length) { |
} // namespace |
-SpdyFrameBuilder::SpdyFrameBuilder(size_t size) |
+ SpdyFrameBuilder::SpdyFrameBuilder(size_t size, SpdyMajorVersion version) |
: buffer_(new char[size]), |
capacity_(size), |
- length_(0) { |
+ length_(0), |
+ offset_(0), |
+ version_(version) { |
} |
SpdyFrameBuilder::~SpdyFrameBuilder() { |
@@ -45,7 +47,7 @@ char* SpdyFrameBuilder::GetWritableBuffer(size_t length) { |
if (!CanWrite(length)) { |
return NULL; |
} |
- return buffer_.get() + length_; |
+ return buffer_.get() + offset_ + length_; |
} |
bool SpdyFrameBuilder::Seek(size_t length) { |
@@ -78,7 +80,7 @@ bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer& framer, |
SpdyStreamId stream_id, |
uint8 flags) { |
if (framer.protocol_version() >= 4) { |
- return WriteFramePrefix(framer, DATA, flags, stream_id); |
+ return BeginNewFrame(framer, DATA, flags, stream_id); |
} |
DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
bool success = true; |
@@ -94,28 +96,37 @@ bool SpdyFrameBuilder::WriteDataFrameHeader(const SpdyFramer& framer, |
return success; |
} |
-bool SpdyFrameBuilder::WriteFramePrefix(const SpdyFramer& framer, |
- SpdyFrameType type, |
- uint8 flags, |
- SpdyStreamId stream_id) { |
- DCHECK_NE(-1, |
- SpdyConstants::SerializeFrameType(framer.protocol_version(), type)); |
+bool SpdyFrameBuilder::BeginNewFrame(const SpdyFramer& framer, |
+ SpdyFrameType type, |
+ uint8 flags, |
+ SpdyStreamId stream_id) { |
+ DCHECK(SpdyConstants::IsValidFrameType(version_, |
+ SpdyConstants::SerializeFrameType(version_, type))); |
DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
- DCHECK_LE(4, framer.protocol_version()); |
+ DCHECK_LE(4, version_); |
+ |
bool success = true; |
- // Upstream DCHECK's that capacity_ is under the maximum frame size at this |
- // point. Chromium does not, because of the large additional zlib inflation |
- // factor we use. (Frame size is is still checked by OverwriteLength() below). |
- if (type != DATA) { |
- success &= WriteUInt16(capacity_ - framer.GetControlFrameHeaderSize()); |
- } else { |
- success &= WriteUInt16(capacity_ - framer.GetDataFrameMinimumSize()); |
+ if (length_ > 0) { |
+ // Update length field for previous frame. |
+ OverwriteLength(framer, length_ - framer.GetPrefixLength(type)); |
+ DLOG_IF(DFATAL, SpdyConstants::GetFrameMaximumSize(version_) < length_) |
+ << "Frame length " << length_ |
+ << " is longer than the maximum allowed length."; |
} |
+ |
+ offset_ += length_; |
+ length_ = 0; |
+ |
+ // Assume all remaining capacity will be used for this frame. If not, |
+ // the length will get overwritten when we begin the next frame. |
+ // Don't check for length limits here because this may be larger than the |
+ // actual frame length. |
+ success &= WriteUInt16(capacity_ - offset_ - framer.GetPrefixLength(type)); |
success &= WriteUInt8( |
- SpdyConstants::SerializeFrameType(framer.protocol_version(), type)); |
+ SpdyConstants::SerializeFrameType(version_, type)); |
success &= WriteUInt8(flags); |
success &= WriteUInt32(stream_id); |
- DCHECK_EQ(framer.GetDataFrameMinimumSize(), length()); |
+ DCHECK_EQ(framer.GetDataFrameMinimumSize(), length_); |
return success; |
} |
@@ -157,16 +168,17 @@ bool SpdyFrameBuilder::RewriteLength(const SpdyFramer& framer) { |
bool SpdyFrameBuilder::OverwriteLength(const SpdyFramer& framer, |
size_t length) { |
- if (framer.protocol_version() < 4) { |
- DCHECK_GE(framer.GetFrameMaximumSize() - framer.GetFrameMinimumSize(), |
+ if (version_ < 4) { |
+ DCHECK_GE(SpdyConstants::GetFrameMaximumSize(version_) - |
+ framer.GetFrameMinimumSize(), |
length); |
} else { |
- DCHECK_GE(framer.GetFrameMaximumSize(), length); |
+ DCHECK_GE(SpdyConstants::GetFrameMaximumSize(version_), length); |
} |
bool success = false; |
const size_t old_length = length_; |
- if (framer.protocol_version() < 4) { |
+ if (version_ < 4) { |
FlagsAndLength flags_length = CreateFlagsAndLength( |
0, // We're not writing over the flags value anyway. |
length); |
@@ -202,7 +214,7 @@ bool SpdyFrameBuilder::CanWrite(size_t length) const { |
return false; |
} |
- if (length_ + length > capacity_) { |
+ if (offset_ + length_ + length > capacity_) { |
DCHECK(false); |
return false; |
} |