Index: net/spdy/spdy_framer_test.cc |
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc |
index 2fa77ed650c4d2c98c42df673784517c660f62af..ff6f3ea4026849a07bc6ceac6158346744190f63 100644 |
--- a/net/spdy/spdy_framer_test.cc |
+++ b/net/spdy/spdy_framer_test.cc |
@@ -198,6 +198,12 @@ class SpdyFramerTestUtil { |
// Do nothing. |
} |
+ virtual bool OnUnknownFrame(SpdyStreamId stream_id, |
+ int frame_type) override { |
+ LOG(FATAL); |
+ return false; |
+ } |
+ |
char* ReleaseBuffer() { |
CHECK(finished_); |
return buffer_.release(); |
@@ -249,6 +255,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
altsvc_count_(0), |
priority_count_(0), |
test_altsvc_ir_(0), |
+ on_unknown_frame_result_(false), |
last_window_update_stream_(0), |
last_window_update_delta_(0), |
last_push_promise_stream_(0), |
@@ -438,6 +445,18 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
++altsvc_count_; |
} |
+ virtual void OnPriority(SpdyStreamId stream_id, |
+ SpdyStreamId parent_stream_id, |
+ uint8 weight, |
+ bool exclusive) OVERRIDE { |
+ ++priority_count_; |
+ } |
+ |
+ virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override { |
+ DLOG(INFO) << "Unknown frame type " << frame_type; |
+ return on_unknown_frame_result_; |
+ } |
+ |
virtual void OnSendCompressedFrame(SpdyStreamId stream_id, |
SpdyFrameType type, |
size_t payload_len, |
@@ -446,13 +465,6 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
last_frame_len_ = frame_len; |
} |
- virtual void OnPriority(SpdyStreamId stream_id, |
- SpdyStreamId parent_stream_id, |
- uint8 weight, |
- bool exclusive) OVERRIDE { |
- ++priority_count_; |
- } |
- |
virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id, |
SpdyFrameType type, |
size_t frame_len) OVERRIDE { |
@@ -523,6 +535,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, |
int altsvc_count_; |
int priority_count_; |
SpdyAltSvcIR test_altsvc_ir_; |
+ bool on_unknown_frame_result_; |
SpdyStreamId last_window_update_stream_; |
uint32 last_window_update_delta_; |
SpdyStreamId last_push_promise_stream_; |
@@ -3526,6 +3539,51 @@ TEST_P(SpdyFramerTest, ReadDuplicateSettings) { |
} |
} |
+// Tests handling of SETTINGS frame with a setting we don't recognize. |
+TEST_P(SpdyFramerTest, ReadUnknownSettingsId) { |
+ SpdyFramer framer(spdy_version_); |
+ |
+ const unsigned char kV2FrameData[] = { |
+ 0x80, spdy_version_ch_, 0x00, 0x04, |
+ 0x00, 0x00, 0x00, 0x1C, |
+ 0x00, 0x00, 0x00, 0x01, |
+ 0x10, 0x00, 0x00, 0x00, // 1st Setting |
+ 0x00, 0x00, 0x00, 0x02, |
+ }; |
+ const unsigned char kV3FrameData[] = { |
+ 0x80, spdy_version_ch_, 0x00, 0x04, |
+ 0x00, 0x00, 0x00, 0x1C, |
+ 0x00, 0x00, 0x00, 0x01, |
+ 0x00, 0x00, 0x00, 0x10, // 1st Setting |
+ 0x00, 0x00, 0x00, 0x02, |
+ }; |
+ const unsigned char kV4FrameData[] = { |
+ 0x00, 0x06, 0x04, 0x00, |
+ 0x00, 0x00, 0x00, 0x00, |
+ 0x00, 0x10, // 1st Setting |
+ 0x00, 0x00, 0x00, 0x02, |
+ }; |
+ |
+ TestSpdyVisitor visitor(spdy_version_); |
+ visitor.use_compression_ = false; |
+ if (IsSpdy2()) { |
+ visitor.SimulateInFramer(kV2FrameData, sizeof(kV2FrameData)); |
+ } else if (IsSpdy3()) { |
+ visitor.SimulateInFramer(kV3FrameData, sizeof(kV3FrameData)); |
+ } else { |
+ visitor.SimulateInFramer(kV4FrameData, sizeof(kV4FrameData)); |
+ } |
+ |
+ if (!IsSpdy4()) { |
+ EXPECT_EQ(0, visitor.setting_count_); |
+ EXPECT_EQ(1, visitor.error_count_); |
+ } else { |
+ // In SPDY 4+, we ignore unknown settings because of extensions. |
+ EXPECT_EQ(0, visitor.setting_count_); |
+ EXPECT_EQ(0, visitor.error_count_); |
+ } |
+} |
+ |
// Tests handling of SETTINGS frame with entries out of order. |
TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) { |
SpdyFramer framer(spdy_version_); |
@@ -3580,7 +3638,6 @@ TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) { |
// In SPDY 4+, settings are allowed in any order. |
EXPECT_EQ(3, visitor.setting_count_); |
EXPECT_EQ(0, visitor.error_count_); |
- // EXPECT_EQ(1, visitor.settings_ack_count_); |
} |
} |
@@ -4125,13 +4182,50 @@ TEST_P(SpdyFramerTest, ReadGarbage) { |
EXPECT_EQ(1, visitor.error_count_); |
} |
+TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) { |
+ if (spdy_version_ <= SPDY3) { |
+ return; |
+ } |
+ SpdyFramer framer(spdy_version_); |
+ |
+ // The unrecognized frame type should still have a valid length. |
+ const unsigned char unknown_frame[] = { |
+ 0x00, 0x08, 0xff, 0xff, |
+ 0xff, 0xff, 0xff, 0xff, |
+ 0xff, 0xff, 0xff, 0xff, |
+ 0xff, 0xff, 0xff, 0xff, |
+ }; |
+ TestSpdyVisitor visitor(spdy_version_); |
+ |
+ // Simulate the case where the stream id validation checks out. |
+ visitor.on_unknown_frame_result_ = true; |
+ visitor.use_compression_ = false; |
+ visitor.SimulateInFramer(unknown_frame, arraysize(unknown_frame)); |
+ EXPECT_EQ(0, visitor.error_count_); |
+ |
+ // Follow it up with a valid control frame to make sure we handle |
+ // subsequent frames correctly. |
+ SpdySettingsIR settings_ir; |
+ settings_ir.AddSetting(SpdyConstants::ParseSettingId(spdy_version_, 1), |
+ false, // persist |
+ false, // persisted |
+ 10); |
+ scoped_ptr<SpdyFrame> control_frame(framer.SerializeSettings(settings_ir)); |
+ visitor.SimulateInFramer( |
+ reinterpret_cast<unsigned char*>(control_frame->data()), |
+ control_frame->size()); |
+ EXPECT_EQ(0, visitor.error_count_); |
+ EXPECT_EQ(1u, static_cast<unsigned>(visitor.setting_count_)); |
+ EXPECT_EQ(1u, static_cast<unsigned>(visitor.settings_ack_sent_)); |
+} |
+ |
TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) { |
if (!IsSpdy4()) { |
return; |
} |
SpdyFramer framer(spdy_version_); |
const unsigned char kFrameData[] = { |
- 0x00, 0x10, 0xff, 0xff, |
+ 0x00, 0x08, 0xff, 0xff, |
0xff, 0xff, 0xff, 0xff, |
0xff, 0xff, 0xff, 0xff, |
0xff, 0xff, 0xff, 0xff, |