summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/spdy/spdy_framer.cc16
-rw-r--r--net/spdy/spdy_framer.h30
-rw-r--r--net/spdy/spdy_framer_test.cc44
-rw-r--r--net/spdy/spdy_protocol.h2
4 files changed, 46 insertions, 46 deletions
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index fae97e8..70a6494 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -77,6 +77,8 @@ const size_t kPadLengthFieldSize = 1;
const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
+// We fragment sent control frames at smaller payload boundaries.
+const size_t SpdyFramer::kMaxControlFrameSize = 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.
@@ -163,6 +165,9 @@ SpdyFramer::SpdyFramer(SpdyMajorVersion version)
end_stream_when_done_(false) {
DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
+ DCHECK_LE(kMaxControlFrameSize,
+ SpdyConstants::GetFrameMaximumSize(spdy_version_) +
+ SpdyConstants::GetControlFrameHeaderSize(spdy_version_));
Reset();
}
@@ -1049,7 +1054,9 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
return;
}
- if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
+ if (current_frame_length_ >
+ SpdyConstants::GetFrameMaximumSize(protocol_version()) +
+ SpdyConstants::GetControlFrameHeaderSize(protocol_version())) {
DLOG(WARNING) << "Received control frame with way too big of a payload: "
<< current_frame_length_;
set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
@@ -2659,7 +2666,7 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
headers.name_value_block(), &hpack_encoding);
}
size += hpack_encoding.size();
- if (size > GetHeaderFragmentMaxSize()) {
+ if (size > kMaxControlFrameSize) {
size += GetNumberRequiredContinuationFrames(size) *
GetContinuationMinimumSize();
flags &= ~HEADERS_FLAG_END_HEADERS;
@@ -2767,7 +2774,7 @@ SpdyFrame* SpdyFramer::SerializePushPromise(
push_promise.name_value_block(), &hpack_encoding);
}
size += hpack_encoding.size();
- if (size > GetHeaderFragmentMaxSize()) {
+ if (size > kMaxControlFrameSize) {
size += GetNumberRequiredContinuationFrames(size) *
GetContinuationMinimumSize();
flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
@@ -2965,7 +2972,6 @@ size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
}
size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
- const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize();
DCHECK_GT(protocol_version(), SPDY3);
DCHECK_GT(size, kMaxControlFrameSize);
size_t overflow = size - kMaxControlFrameSize;
@@ -2977,8 +2983,6 @@ void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
SpdyStreamId stream_id,
SpdyFrameType type,
int padding_payload_len) {
- const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize();
-
uint8 end_flag = 0;
uint8 flags = 0;
if (type == HEADERS) {
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h
index 99db36a..29cab72 100644
--- a/net/spdy/spdy_framer.h
+++ b/net/spdy/spdy_framer.h
@@ -709,36 +709,18 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// Set the error code and moves the framer into the error state.
void set_error(SpdyError error);
- // The maximum size of the control frames that we support.
- // This limit is arbitrary. We can enforce it here or at the application
- // layer. We chose the framing layer, but this can be changed (or removed)
- // if necessary later down the line.
- size_t GetControlFrameBufferMaxSize() const {
- // The theoretical maximum for SPDY3 and earlier is (2^24 - 1) +
- // 8, since the length field does not count the size of the
- // header.
- if (spdy_version_ == SPDY2) {
- return 64 * 1024;
- }
- if (spdy_version_ == SPDY3) {
- return 16 * 1024 * 1024;
- }
- // Absolute maximum size of HTTP2 frame payload (section 4.2 "Frame size").
- return (1<<14) - 1;
- }
-
- // TODO(jgraettinger): For h2-13 interop testing coverage,
- // fragment at smaller payload boundaries.
- size_t GetHeaderFragmentMaxSize() const {
- return GetControlFrameBufferMaxSize() >> 4; // 1023 bytes.
- }
-
// The size of the control frame buffer.
// Since this is only used for control frame headers, the maximum control
// frame header size (SYN_STREAM) is sufficient; all remaining control
// frame data is streamed to the visitor.
static const size_t kControlFrameBufferSize;
+ // The maximum size of the control frames that we support.
+ // This limit is arbitrary. We can enforce it here or at the application
+ // layer. We chose the framing layer, but this can be changed (or removed)
+ // if necessary later down the line.
+ static const size_t kMaxControlFrameSize;
+
SpdyState state_;
SpdyState previous_state_;
SpdyError error_code_;
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc
index 84ea0d7..d55e072 100644
--- a/net/spdy/spdy_framer_test.cc
+++ b/net/spdy/spdy_framer_test.cc
@@ -502,6 +502,12 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
header_buffer_.reset(new char[header_buffer_size]);
}
+ // Largest control frame that the SPDY implementation sends, including the
+ // size of the header.
+ static size_t sent_control_frame_max_size() {
+ return SpdyFramer::kMaxControlFrameSize;
+ }
+
static size_t header_data_chunk_max_size() {
return SpdyFramer::kHeaderDataChunkMaxSize;
}
@@ -3147,12 +3153,12 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
"PUSH_PROMISE and CONTINUATION frames with one byte of padding";
const unsigned char kPartialPushPromiseFrameData[] = {
- 0x00, 0x03, 0xf6, 0x05, // PUSH_PROMISE
+ 0x00, 0x03, 0xf7, 0x05, // PUSH_PROMISE
0x08, 0x00, 0x00, 0x00, // PADDED
0x2a, 0x00, 0x00, 0x00, // Stream 42
0x00, 0x39, 0x00, 0x03, // Promised stream 57
0x78, 0x78, 0x78, 0x7f, // xxx.
- 0x80, 0x07, 0x78, 0x78, // ..xx
+ 0x81, 0x07, 0x78, 0x78, // ..xx
0x78, 0x78, 0x78, 0x78, // xxxx
0x78, 0x78, 0x78, 0x78, // xxxx
0x78, 0x78, 0x78, 0x78, // xxxx
@@ -3189,7 +3195,7 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
SpdyPushPromiseIR push_promise(42, 57);
push_promise.set_padding_len(1);
- string big_value(framer.GetHeaderFragmentMaxSize(), 'x');
+ string big_value(TestSpdyVisitor::sent_control_frame_max_size(), 'x');
push_promise.SetHeader("xxx", big_value);
scoped_ptr<SpdySerializedFrame> frame(
framer.SerializePushPromise(push_promise));
@@ -3211,8 +3217,9 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
// Length of everything listed above except big_value.
int len_non_data_payload = 31;
- EXPECT_EQ(framer.GetHeaderFragmentMaxSize() + len_non_data_payload,
- frame->size());
+ EXPECT_EQ(
+ TestSpdyVisitor::sent_control_frame_max_size() + len_non_data_payload,
+ frame->size());
// Partially compare the PUSH_PROMISE frame against the template.
const unsigned char* frame_data =
@@ -3224,7 +3231,7 @@ TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
arraysize(kPartialPushPromiseFrameData));
// Compare the CONTINUATION frame against the template.
- frame_data += framer.GetHeaderFragmentMaxSize();
+ frame_data += TestSpdyVisitor::sent_control_frame_max_size();
CompareCharArraysWithHexError(kDescription,
frame_data,
arraysize(kContinuationFrameData),
@@ -3395,14 +3402,15 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
syn_stream.SetHeader("aa", "");
scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
const size_t kBigValueSize =
- framer.GetControlFrameBufferMaxSize() - control_frame->size();
+ TestSpdyVisitor::sent_control_frame_max_size() - control_frame->size();
// Create a frame at exactly that size.
string big_value(kBigValueSize, 'x');
syn_stream.SetHeader("aa", big_value);
control_frame.reset(framer.SerializeSynStream(syn_stream));
EXPECT_TRUE(control_frame.get() != NULL);
- EXPECT_EQ(framer.GetControlFrameBufferMaxSize(), control_frame->size());
+ EXPECT_EQ(TestSpdyVisitor::sent_control_frame_max_size(),
+ control_frame->size());
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
@@ -3416,7 +3424,10 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
EXPECT_LT(kBigValueSize, visitor.header_buffer_length_);
}
-TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
+// This test is disabled because Chromium is willing to accept control frames up
+// to the maximum size allowed by the specification, and SpdyFrameBuilder is not
+// capable of building larger frames.
+TEST_P(SpdyFramerTest, DISABLED_ControlFrameTooLarge) {
if (spdy_version_ > SPDY3) {
// TODO(jgraettinger): This test setup doesn't work with HPACK.
return;
@@ -3430,7 +3441,8 @@ TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
syn_stream.set_priority(1);
scoped_ptr<SpdyFrame> control_frame(framer.SerializeSynStream(syn_stream));
const size_t kBigValueSize =
- framer.GetControlFrameBufferMaxSize() - control_frame->size() + 1;
+ SpdyConstants::GetFrameMaximumSize(spdy_version_) -
+ control_frame->size() + 1;
// Create a frame at exatly that size.
string big_value(kBigValueSize, 'x');
@@ -3441,7 +3453,7 @@ TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
control_frame.reset(framer.SerializeSynStream(syn_stream));
EXPECT_TRUE(control_frame.get() != NULL);
- EXPECT_EQ(framer.GetControlFrameBufferMaxSize() + 1,
+ EXPECT_EQ(SpdyConstants::GetFrameMaximumSize(spdy_version_) + 1,
control_frame->size());
TestSpdyVisitor visitor(spdy_version_);
@@ -3468,12 +3480,13 @@ TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
// Exact payload length will change with HPACK, but this should be long
// enough to cause an overflow.
- const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize();
+ const size_t kBigValueSize = kControlFrameSizeLimit;
string big_value(kBigValueSize, 'x');
headers.SetHeader("aa", big_value);
scoped_ptr<SpdyFrame> control_frame(framer.SerializeHeaders(headers));
EXPECT_TRUE(control_frame.get() != NULL);
- EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize());
+ EXPECT_GT(control_frame->size(),
+ TestSpdyVisitor::sent_control_frame_max_size());
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
@@ -3497,13 +3510,14 @@ TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
// Exact payload length will change with HPACK, but this should be long
// enough to cause an overflow.
- const size_t kBigValueSize = framer.GetControlFrameBufferMaxSize();
+ const size_t kBigValueSize = kControlFrameSizeLimit;
string big_value(kBigValueSize, 'x');
push_promise.SetHeader("aa", big_value);
scoped_ptr<SpdyFrame> control_frame(
framer.SerializePushPromise(push_promise));
EXPECT_TRUE(control_frame.get() != NULL);
- EXPECT_GT(control_frame->size(), framer.GetControlFrameBufferMaxSize());
+ EXPECT_GT(control_frame->size(),
+ TestSpdyVisitor::sent_control_frame_max_size());
TestSpdyVisitor visitor(spdy_version_);
visitor.SimulateInFramer(
diff --git a/net/spdy/spdy_protocol.h b/net/spdy/spdy_protocol.h
index 3a979b9..b3f71d44 100644
--- a/net/spdy/spdy_protocol.h
+++ b/net/spdy/spdy_protocol.h
@@ -52,7 +52,7 @@ const int32 kSpdyStreamInitialWindowSize = 64 * 1024; // 64 KBytes
// The maxmium possible control frame size allowed by the spec.
const int32 kSpdyMaxControlFrameSize = (1 << 24) - 1;
-// The maximum control frame size we actually send/accept.
+// The maximum control frame size we accept.
const int32 kControlFrameSizeLimit = 1 << 14;
// Initial window size for a Spdy session in bytes.