summaryrefslogtreecommitdiffstats
path: root/net/spdy
diff options
context:
space:
mode:
Diffstat (limited to 'net/spdy')
-rw-r--r--net/spdy/spdy_session.h5
-rw-r--r--net/spdy/spdy_session_pool.cc16
-rw-r--r--net/spdy/spdy_session_pool.h2
-rw-r--r--net/spdy/spdy_session_unittest.cc106
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.