diff options
-rw-r--r-- | net/spdy/spdy_framer.cc | 16 | ||||
-rw-r--r-- | net/spdy/spdy_framer.h | 30 | ||||
-rw-r--r-- | net/spdy/spdy_framer_test.cc | 44 | ||||
-rw-r--r-- | net/spdy/spdy_protocol.h | 2 |
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. |