diff options
Diffstat (limited to 'net/spdy')
-rw-r--r-- | net/spdy/spdy_session.h | 5 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.cc | 16 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.h | 2 | ||||
-rw-r--r-- | net/spdy/spdy_session_unittest.cc | 106 |
4 files changed, 129 insertions, 0 deletions
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 4281a20..1a038f8 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -190,6 +190,11 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>, spdy_session_pool_ = NULL; } + // Returns true if session is not currently active + bool is_active() const { + return !active_streams_.empty(); + } + // Access to the number of active and pending streams. These are primarily // available for testing and diagnostics. size_t num_active_streams() const { return active_streams_.size(); } diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index d90a1d5..7bac3bc 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -413,4 +413,20 @@ void SpdySessionPool::CloseCurrentSessions() { DCHECK(aliases_.empty()); } +void SpdySessionPool::CloseIdleSessions() { + SpdySessionsMap::const_iterator map_it = sessions_.begin(); + while (map_it != sessions_.end()) { + SpdySessionList* list = map_it->second; + ++map_it; + CHECK(list); + + // Assumes there is only 1 element in the list + SpdySessionList::iterator session_it = list->begin(); + const scoped_refptr<SpdySession>& session = *session_it; + CHECK(session); + if (!session->is_active()) + session->CloseSessionOnError(net::ERR_ABORTED, true); + } +} + } // namespace net diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 327e179..3b1ec78 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -92,6 +92,8 @@ class NET_EXPORT SpdySessionPool // Close only the currently existing SpdySessions. Let any new ones created // continue to live. void CloseCurrentSessions(); + // Close only the idle SpdySessions. + void CloseIdleSessions(); // Removes a SpdySession from the SpdySessionPool. This should only be called // by SpdySession, because otherwise session->state_ is not set to CLOSED. diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index 351b8ed..9a0a2be 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -150,6 +150,112 @@ class StreamReleaserCallback : public CallbackRunner<Tuple1<int> > { TestCompletionCallback callback_; }; +// TODO(kristianm): Could also test with more sessions where some are idle, +// and more than one session to a HostPortPair. +TEST_F(SpdySessionTest, CloseIdleSessions) { + SpdySessionDependencies session_deps; + scoped_refptr<HttpNetworkSession> http_session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); + SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); + + // Set up session 1 + const std::string kTestHost1("http://www.a.com"); + HostPortPair test_host_port_pair1(kTestHost1, 80); + HostPortProxyPair pair1(test_host_port_pair1, ProxyServer::Direct()); + scoped_refptr<SpdySession> session1 = + spdy_session_pool->Get(pair1, BoundNetLog()); + scoped_refptr<SpdyStream> spdy_stream1; + TestCompletionCallback callback1; + GURL url1(kTestHost1); + EXPECT_EQ(OK, session1->CreateStream(url1, + MEDIUM, /* priority, not important */ + &spdy_stream1, + BoundNetLog(), + &callback1)); + + // Set up session 2 + const std::string kTestHost2("http://www.b.com"); + HostPortPair test_host_port_pair2(kTestHost2, 80); + HostPortProxyPair pair2(test_host_port_pair2, ProxyServer::Direct()); + scoped_refptr<SpdySession> session2 = + spdy_session_pool->Get(pair2, BoundNetLog()); + scoped_refptr<SpdyStream> spdy_stream2; + TestCompletionCallback callback2; + GURL url2(kTestHost2); + EXPECT_EQ(OK, session2->CreateStream(url2, + MEDIUM, /* priority, not important */ + &spdy_stream2, + BoundNetLog(), + &callback2)); + + // Set up session 3 + const std::string kTestHost3("http://www.c.com"); + HostPortPair test_host_port_pair3(kTestHost3, 80); + HostPortProxyPair pair3(test_host_port_pair3, ProxyServer::Direct()); + scoped_refptr<SpdySession> session3 = + spdy_session_pool->Get(pair3, BoundNetLog()); + scoped_refptr<SpdyStream> spdy_stream3; + TestCompletionCallback callback3; + GURL url3(kTestHost3); + EXPECT_EQ(OK, session3->CreateStream(url3, + MEDIUM, /* priority, not important */ + &spdy_stream3, + BoundNetLog(), + &callback3)); + + // All sessions are active and not closed + EXPECT_TRUE(session1->is_active()); + EXPECT_FALSE(session1->IsClosed()); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + EXPECT_TRUE(session3->is_active()); + EXPECT_FALSE(session3->IsClosed()); + + // Should not do anything, all are active + spdy_session_pool->CloseIdleSessions(); + EXPECT_TRUE(session1->is_active()); + EXPECT_FALSE(session1->IsClosed()); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + EXPECT_TRUE(session3->is_active()); + EXPECT_FALSE(session3->IsClosed()); + + // Make sessions 1 and 3 inactive, but keep them open. + // Session 2 still open and active + session1->CloseStream(spdy_stream1->stream_id(), OK); + session3->CloseStream(spdy_stream3->stream_id(), OK); + EXPECT_FALSE(session1->is_active()); + EXPECT_FALSE(session1->IsClosed()); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + EXPECT_FALSE(session3->is_active()); + EXPECT_FALSE(session3->IsClosed()); + + // Should close session 1 and 3, 2 should be left open + spdy_session_pool->CloseIdleSessions(); + EXPECT_FALSE(session1->is_active()); + EXPECT_TRUE(session1->IsClosed()); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + EXPECT_FALSE(session3->is_active()); + EXPECT_TRUE(session3->IsClosed()); + + // Should not do anything + spdy_session_pool->CloseIdleSessions(); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + + // Make 2 not active + session2->CloseStream(spdy_stream2->stream_id(), OK); + EXPECT_FALSE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + + // This should close session 2 + spdy_session_pool->CloseIdleSessions(); + EXPECT_FALSE(session2->is_active()); + EXPECT_TRUE(session2->IsClosed()); +} + // Start with max concurrent streams set to 1. Request two streams. Receive a // settings frame setting max concurrent streams to 2. Have the callback // release the stream, which releases its reference (the last) to the session. |