diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-08 14:13:20 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-08 14:13:20 +0000 |
commit | ca1812bf81813c39931ccc3bd5accc0275b3d3e0 (patch) | |
tree | db0a59aa4c5f10929728b468992f56f370e25790 /net | |
parent | 5a64e82151109e69bbf8cb83ee945a9f5e966910 (diff) | |
download | chromium_src-ca1812bf81813c39931ccc3bd5accc0275b3d3e0.zip chromium_src-ca1812bf81813c39931ccc3bd5accc0275b3d3e0.tar.gz chromium_src-ca1812bf81813c39931ccc3bd5accc0275b3d3e0.tar.bz2 |
[SPDY] Fix session flow control bug with incoming data for inactive streams
The session receive flow control window should not decrease on incoming
data for an inactive stream.
BUG=176592
Review URL: https://chromiumcodereview.appspot.com/12648002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186960 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/spdy/spdy_session.cc | 7 | ||||
-rw-r--r-- | net/spdy/spdy_session.h | 2 | ||||
-rw-r--r-- | net/spdy/spdy_session_spdy3_unittest.cc | 35 |
3 files changed, 41 insertions, 3 deletions
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 61fd280..8336640 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -1388,13 +1388,14 @@ void SpdySession::OnStreamFrameData(SpdyStreamId stream_id, base::Bind(&NetLogSpdyDataCallback, stream_id, len, fin)); } - if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION && len > 0) - DecreaseRecvWindowSize(static_cast<int32>(len)); - // By the time data comes in, the stream may already be inactive. if (!IsStreamActive(stream_id)) return; + // Only decrease the window size for data for active streams. + if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION && len > 0) + DecreaseRecvWindowSize(static_cast<int32>(len)); + scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; stream->OnDataReceived(data, len); } diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 4facb51..4c8f251 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -449,6 +449,8 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>, FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, IncreaseRecvWindowSize); FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, AdjustRecvWindowSize31); FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, AdjustSendWindowSize31); + FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, + SessionFlowControlInactiveStream31); FRIEND_TEST_ALL_PREFIXES(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31); typedef std::deque<SpdyStreamRequest*> PendingStreamRequestQueue; diff --git a/net/spdy/spdy_session_spdy3_unittest.cc b/net/spdy/spdy_session_spdy3_unittest.cc index a0d8583..e814f45 100644 --- a/net/spdy/spdy_session_spdy3_unittest.cc +++ b/net/spdy/spdy_session_spdy3_unittest.cc @@ -2275,6 +2275,41 @@ TEST_F(SpdySessionSpdy3Test, AdjustSendWindowSize31) { EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_send_window_size_); } +// Incoming data for an inactive stream should not cause the session +// receive window size to decrease. +TEST_F(SpdySessionSpdy3Test, SessionFlowControlInactiveStream31) { + session_deps_.enable_spdy_31 = true; + session_deps_.host_resolver->set_synchronous_mode(true); + + MockConnect connect_data(SYNCHRONOUS, OK); + scoped_ptr<SpdyFrame> resp(ConstructSpdyBodyFrame(1, false)); + MockRead reads[] = { + CreateMockRead(*resp, 0), + MockRead(ASYNC, 0, 1) // EOF + }; + DeterministicSocketData data(reads, arraysize(reads), NULL, 0); + data.set_connect_data(connect_data); + session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); + + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); + + CreateDeterministicNetworkSession(); + scoped_refptr<SpdySession> session = GetSession(pair_); + InitializeSession( + http_session_.get(), session.get(), test_host_port_pair_); + EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, + session->flow_control_state()); + + EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); + EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); + + data.RunFor(2); + + EXPECT_EQ(kSpdySessionInitialWindowSize, session->session_recv_window_size_); + EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); +} + namespace { void ExpectOK(int status) { |