diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-03 22:44:26 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-03 22:44:26 +0000 |
commit | 41d64e8ded3eec5ad56df98085bd205ad1164ee3 (patch) | |
tree | 970141ab3223adc0f729da84714d92a8d4499933 /net | |
parent | 8ed2d35815bcf433555db5bea6d1e9eeec4b4ca7 (diff) | |
download | chromium_src-41d64e8ded3eec5ad56df98085bd205ad1164ee3.zip chromium_src-41d64e8ded3eec5ad56df98085bd205ad1164ee3.tar.gz chromium_src-41d64e8ded3eec5ad56df98085bd205ad1164ee3.tar.bz2 |
[SPDY] Refactor and clean up SpdySessionPool
Replace the map of keys to lists of sessions to a map
of keys to sessions, since we were already limiting
the lists to be of size 1 anyway.
Remove the functions from SpdySessionPool that were
used mostly by tests. Replace them with functions
in spdy_test_util_common.{h,cc}. Make a bunch of
tests use these functions.
Make the Close*Sessions() behave consistently.
Make SpdySession::CloseSessionOnError() always remove
the session from its pool.
Move the SpdySessionPool tests for spdy_session_unittest.cc
to a new file spdy_session_pool_unittest.cc. Add
a few more for the Close*Sessions() tests.
Remove --max-spdy-sessions-per-domain switch.
Parametrize HttpStreamFactoryTest on NextProto.
Misc. cleanup here and there.
BUG=255701
TBR=rch@chromium.org
Review URL: https://codereview.chromium.org/18226004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210054 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
24 files changed, 1232 insertions, 1464 deletions
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 20f71f4..7c64d1d 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc @@ -70,7 +70,6 @@ HttpNetworkSession::Params::Params() http_pipelining_enabled(false), testing_fixed_http_port(0), testing_fixed_https_port(0), - max_spdy_sessions_per_domain(0), force_spdy_single_domain(false), enable_spdy_ip_pooling(true), enable_spdy_credential_frames(false), @@ -114,7 +113,6 @@ HttpNetworkSession::HttpNetworkSession(const Params& params) spdy_session_pool_(params.host_resolver, params.ssl_config_service, params.http_server_properties, - params.max_spdy_sessions_per_domain, params.force_spdy_single_domain, params.enable_spdy_ip_pooling, params.enable_spdy_credential_frames, @@ -208,7 +206,7 @@ void HttpNetworkSession::CloseAllConnections() { void HttpNetworkSession::CloseIdleConnections() { normal_socket_pool_manager_->CloseIdleSockets(); websocket_socket_pool_manager_->CloseIdleSockets(); - spdy_session_pool_.CloseIdleSessions(); + spdy_session_pool_.CloseCurrentIdleSessions(); } ClientSocketPoolManager* HttpNetworkSession::GetSocketPoolManager( diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 1e1af31..3ca928e 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -73,7 +73,6 @@ class NET_EXPORT HttpNetworkSession bool http_pipelining_enabled; uint16 testing_fixed_http_port; uint16 testing_fixed_https_port; - size_t max_spdy_sessions_per_domain; bool force_spdy_single_domain; bool enable_spdy_ip_pooling; bool enable_spdy_credential_frames; diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 0c256aa..11141ba 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -8856,41 +8856,7 @@ TEST_P(HttpNetworkTransactionTest, SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); scoped_refptr<SpdySession> spdy_session = - session->spdy_session_pool()->Get(key, BoundNetLog()); - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(host_port_pair, MEDIUM, false, false, - OnHostResolutionCallback())); - - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - transport_params, - LOWEST, - callback.callback(), - session->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, callback.WaitForResult()); - - SSLConfig ssl_config; - session->ssl_config_service()->GetSSLConfig(&ssl_config); - scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle); - SSLClientSocketContext context; - context.cert_verifier = session_deps_.cert_verifier.get(); - context.transport_security_state = - session_deps_.transport_security_state.get(); - ssl_connection->set_socket( - session_deps_.socket_factory->CreateSSLClientSocket( - connection.release(), - HostPortPair(std::string(), 443), - ssl_config, - context)); - EXPECT_EQ(ERR_IO_PENDING, - ssl_connection->socket()->Connect(callback.callback())); - EXPECT_EQ(OK, callback.WaitForResult()); - - EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(), - true, OK)); + CreateSecureSpdySession(session, key, BoundNetLog()); trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -10022,23 +9988,7 @@ TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) { SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); scoped_refptr<SpdySession> spdy_session = - session->spdy_session_pool()->Get(key, BoundNetLog()); - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(host_port_pair, MEDIUM, false, false, - OnHostResolutionCallback())); - TestCompletionCallback callback; - - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - transport_params, - LOWEST, - callback.callback(), - session->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, callback.WaitForResult()); - spdy_session->InitializeWithSocket(connection.release(), false, OK); + CreateInsecureSpdySession(session, key, BoundNetLog()); HttpRequestInfo request; request.method = "GET"; @@ -10051,6 +10001,7 @@ TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) { scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + TestCompletionCallback callback; int rv = trans->Start(&request, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(OK, callback.WaitForResult()); @@ -11386,7 +11337,7 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) { SpdySessionKey spdy_session_key_a( host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled); EXPECT_FALSE( - session->spdy_session_pool()->HasSession(spdy_session_key_a)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); TestCompletionCallback callback; HttpRequestInfo request1; @@ -11412,13 +11363,13 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) { EXPECT_EQ("hello!", response_data); trans.reset(); EXPECT_TRUE( - session->spdy_session_pool()->HasSession(spdy_session_key_a)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); HostPortPair host_port_pair_b("www.b.com", 443); SpdySessionKey spdy_session_key_b( host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled); EXPECT_FALSE( - session->spdy_session_pool()->HasSession(spdy_session_key_b)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); HttpRequestInfo request2; request2.method = "GET"; request2.url = GURL("https://www.b.com/"); @@ -11438,15 +11389,15 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) { ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); EXPECT_EQ("hello!", response_data); EXPECT_FALSE( - session->spdy_session_pool()->HasSession(spdy_session_key_a)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); EXPECT_TRUE( - session->spdy_session_pool()->HasSession(spdy_session_key_b)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); HostPortPair host_port_pair_a1("www.a.com", 80); SpdySessionKey spdy_session_key_a1( host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled); EXPECT_FALSE( - session->spdy_session_pool()->HasSession(spdy_session_key_a1)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1)); HttpRequestInfo request3; request3.method = "GET"; request3.url = GURL("http://www.a.com/"); @@ -11466,9 +11417,9 @@ TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) { ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); EXPECT_EQ("hello!", response_data); EXPECT_FALSE( - session->spdy_session_pool()->HasSession(spdy_session_key_a)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); EXPECT_FALSE( - session->spdy_session_pool()->HasSession(spdy_session_key_b)); + HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); HttpStreamFactory::SetNextProtos(std::vector<std::string>()); } diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index 9f4cbb9..7b493ac 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc @@ -204,7 +204,7 @@ int HttpProxyConnectJob::DoSSLConnect() { SpdySessionKey key(params_->destination().host_port_pair(), ProxyServer::Direct(), kPrivacyModeDisabled); - if (params_->spdy_session_pool()->HasSession(key)) { + if (params_->spdy_session_pool()->GetIfExists(key, net_log())) { using_spdy_ = true; next_state_ = STATE_SPDY_PROXY_CREATE_STREAM; return OK; @@ -302,19 +302,19 @@ int HttpProxyConnectJob::DoSpdyProxyCreateStream() { ProxyServer::Direct(), kPrivacyModeDisabled); SpdySessionPool* spdy_pool = params_->spdy_session_pool(); - scoped_refptr<SpdySession> spdy_session; + scoped_refptr<SpdySession> spdy_session = + spdy_pool->GetIfExists(key, net_log()); // It's possible that a session to the proxy has recently been created - if (spdy_pool->HasSession(key)) { + if (spdy_session) { if (transport_socket_handle_.get()) { if (transport_socket_handle_->socket()) transport_socket_handle_->socket()->Disconnect(); transport_socket_handle_->Reset(); } - spdy_session = spdy_pool->Get(key, net_log()); } else { // Create a session direct to the proxy itself int rv = spdy_pool->GetSpdySessionFromSocket( - key, transport_socket_handle_.release(), + key, transport_socket_handle_.Pass(), net_log(), OK, &spdy_session, /*using_ssl_*/ true); if (rv < 0) return rv; diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 63160d0..f03ca2d 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc @@ -1099,7 +1099,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() { spdy_session = spdy_pool->GetIfExists(spdy_session_key, net_log_); if (!spdy_session.get()) { int error = spdy_pool->GetSpdySessionFromSocket(spdy_session_key, - connection_.release(), + connection_.Pass(), net_log_, spdy_certificate_error_, &new_spdy_session_, diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc index 1e9a714..a2d0990 100644 --- a/net/http/http_stream_factory_impl_unittest.cc +++ b/net/http/http_stream_factory_impl_unittest.cc @@ -8,6 +8,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/compiler_specific.h" #include "net/base/net_log.h" #include "net/base/test_completion_callback.h" #include "net/cert/mock_cert_verifier.h" @@ -242,46 +243,6 @@ class WebSocketStreamFactory : public WebSocketStreamBase::Factory { } }; -struct SessionDependencies { - // Custom proxy service dependency. - explicit SessionDependencies(ProxyService* proxy_service) - : host_resolver(new MockHostResolver), - cert_verifier(new MockCertVerifier), - transport_security_state(new TransportSecurityState), - proxy_service(proxy_service), - ssl_config_service(new SSLConfigServiceDefaults), - http_auth_handler_factory( - HttpAuthHandlerFactory::CreateDefault(host_resolver.get())), - net_log(NULL) {} - - scoped_ptr<MockHostResolverBase> host_resolver; - scoped_ptr<CertVerifier> cert_verifier; - scoped_ptr<TransportSecurityState> transport_security_state; - scoped_ptr<ProxyService> proxy_service; - scoped_refptr<SSLConfigService> ssl_config_service; - MockClientSocketFactory socket_factory; - scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory; - HttpServerPropertiesImpl http_server_properties; - NetLog* net_log; -}; - -HttpNetworkSession* CreateSession(SessionDependencies* session_deps) { - HttpNetworkSession::Params params; - params.host_resolver = session_deps->host_resolver.get(); - params.cert_verifier = session_deps->cert_verifier.get(); - params.transport_security_state = - session_deps->transport_security_state.get(); - params.proxy_service = session_deps->proxy_service.get(); - params.ssl_config_service = session_deps->ssl_config_service.get(); - params.client_socket_factory = &session_deps->socket_factory; - params.http_auth_handler_factory = - session_deps->http_auth_handler_factory.get(); - params.net_log = session_deps->net_log; - params.http_server_properties = &session_deps->http_server_properties; - - return new HttpNetworkSession(params); -} - struct TestCase { int num_streams; bool ssl; @@ -424,10 +385,21 @@ CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool( NULL), last_num_streams_(-1) {} -TEST(HttpStreamFactoryTest, PreconnectDirect) { +class HttpStreamFactoryTest : public ::testing::Test, + public ::testing::WithParamInterface<NextProto> { +}; + +INSTANTIATE_TEST_CASE_P( + NextProto, + HttpStreamFactoryTest, + testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2)); + +TEST_P(HttpStreamFactoryTest, PreconnectDirect) { for (size_t i = 0; i < arraysize(kTests); ++i) { - SessionDependencies session_deps(ProxyService::CreateDirect()); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); HttpNetworkSessionPeer peer(session); CapturePreconnectsTransportSocketPool* transport_conn_pool = new CapturePreconnectsTransportSocketPool( @@ -450,10 +422,12 @@ TEST(HttpStreamFactoryTest, PreconnectDirect) { } } -TEST(HttpStreamFactoryTest, PreconnectHttpProxy) { +TEST_P(HttpStreamFactoryTest, PreconnectHttpProxy) { for (size_t i = 0; i < arraysize(kTests); ++i) { - SessionDependencies session_deps(ProxyService::CreateFixed("http_proxy")); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateFixed("http_proxy")); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); HttpNetworkSessionPeer peer(session); HostPortPair proxy_host("http_proxy", 80); CapturePreconnectsHttpProxySocketPool* http_proxy_pool = @@ -477,11 +451,12 @@ TEST(HttpStreamFactoryTest, PreconnectHttpProxy) { } } -TEST(HttpStreamFactoryTest, PreconnectSocksProxy) { +TEST_P(HttpStreamFactoryTest, PreconnectSocksProxy) { for (size_t i = 0; i < arraysize(kTests); ++i) { - SessionDependencies session_deps( - ProxyService::CreateFixed("socks4://socks_proxy:1080")); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateFixed("socks4://socks_proxy:1080")); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); HttpNetworkSessionPeer peer(session); HostPortPair proxy_host("socks_proxy", 1080); CapturePreconnectsSOCKSSocketPool* socks_proxy_pool = @@ -505,18 +480,19 @@ TEST(HttpStreamFactoryTest, PreconnectSocksProxy) { } } -TEST(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) { +TEST_P(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) { for (size_t i = 0; i < arraysize(kTests); ++i) { - SessionDependencies session_deps(ProxyService::CreateDirect()); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); HttpNetworkSessionPeer peer(session); - // Set an existing SpdySession in the pool. + // Put a SpdySession in the pool. HostPortPair host_port_pair("www.google.com", 443); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> spdy_session = - session->spdy_session_pool()->Get(key, BoundNetLog()); + ignore_result(CreateFakeSpdySession(session->spdy_session_pool(), key)); CapturePreconnectsTransportSocketPool* transport_conn_pool = new CapturePreconnectsTransportSocketPool( @@ -537,18 +513,21 @@ TEST(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) { if (kTests[i].ssl) EXPECT_EQ(-1, ssl_conn_pool->last_num_streams()); else - EXPECT_EQ(kTests[i].num_streams, transport_conn_pool->last_num_streams()); + EXPECT_EQ(kTests[i].num_streams, + transport_conn_pool->last_num_streams()); } } // Verify that preconnects to unsafe ports are cancelled before they reach // the SocketPool. -TEST(HttpStreamFactoryTest, PreconnectUnsafePort) { +TEST_P(HttpStreamFactoryTest, PreconnectUnsafePort) { ASSERT_FALSE(IsPortAllowedByDefault(7)); ASSERT_FALSE(IsPortAllowedByOverride(7)); - SessionDependencies session_deps(ProxyService::CreateDirect()); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); HttpNetworkSessionPeer peer(session); CapturePreconnectsTransportSocketPool* transport_conn_pool = new CapturePreconnectsTransportSocketPool( @@ -564,22 +543,23 @@ TEST(HttpStreamFactoryTest, PreconnectUnsafePort) { EXPECT_EQ(-1, transport_conn_pool->last_num_streams()); } -TEST(HttpStreamFactoryTest, JobNotifiesProxy) { +TEST_P(HttpStreamFactoryTest, JobNotifiesProxy) { const char* kProxyString = "PROXY bad:99; PROXY maybe:80; DIRECT"; - SessionDependencies session_deps( - ProxyService::CreateFixedFromPacResult(kProxyString)); + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateFixedFromPacResult(kProxyString)); // First connection attempt fails StaticSocketDataProvider socket_data1; socket_data1.set_connect_data(MockConnect(ASYNC, ERR_ADDRESS_UNREACHABLE)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data1); + session_deps.socket_factory->AddSocketDataProvider(&socket_data1); // Second connection attempt succeeds StaticSocketDataProvider socket_data2; socket_data2.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data2); + session_deps.socket_factory->AddSocketDataProvider(&socket_data2); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Now request a stream. It should succeed using the second proxy in the // list. @@ -603,17 +583,19 @@ TEST(HttpStreamFactoryTest, JobNotifiesProxy) { EXPECT_TRUE(iter != retry_info.end()); } -TEST(HttpStreamFactoryTest, PrivacyModeDisablesChannelId) { - SessionDependencies session_deps(ProxyService::CreateDirect()); +TEST_P(HttpStreamFactoryTest, PrivacyModeDisablesChannelId) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); StaticSocketDataProvider socket_data; socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); SSLSocketDataProvider ssl(ASYNC, OK); - session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Set an existing SpdySession in the pool. HostPortPair host_port_pair("www.google.com", 443); @@ -655,17 +637,19 @@ int GetSocketPoolGroupCount(ClientSocketPool* pool) { } } // namespace -TEST(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) { - SessionDependencies session_deps(ProxyService::CreateDirect()); +TEST_P(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); StaticSocketDataProvider socket_data; socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); SSLSocketDataProvider ssl(ASYNC, OK); - session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); SSLClientSocketPool* ssl_pool = session->GetSSLSocketPool( HttpNetworkSession::NORMAL_SOCKET_POOL); @@ -706,14 +690,16 @@ TEST(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) { EXPECT_EQ(GetSocketPoolGroupCount(ssl_pool), 2); } -TEST(HttpStreamFactoryTest, GetLoadState) { - SessionDependencies session_deps(ProxyService::CreateDirect()); +TEST_P(HttpStreamFactoryTest, GetLoadState) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); StaticSocketDataProvider socket_data; socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); HttpRequestInfo request_info; request_info.method = "GET"; @@ -731,14 +717,16 @@ TEST(HttpStreamFactoryTest, GetLoadState) { waiter.WaitForStream(); } -TEST(HttpStreamFactoryTest, RequestHttpStream) { - SessionDependencies session_deps(ProxyService::CreateDirect()); +TEST_P(HttpStreamFactoryTest, RequestHttpStream) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); StaticSocketDataProvider socket_data; socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Now request a stream. It should succeed using the second proxy in the // list. @@ -775,18 +763,20 @@ TEST(HttpStreamFactoryTest, RequestHttpStream) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, RequestHttpStreamOverSSL) { - SessionDependencies session_deps(ProxyService::CreateDirect()); +TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverSSL) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); MockRead mock_read(ASYNC, OK); StaticSocketDataProvider socket_data(&mock_read, 1, NULL, 0); socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); SSLSocketDataProvider ssl_socket_data(ASYNC, OK); - session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_socket_data); + session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Now request a stream. HttpRequestInfo request_info; @@ -821,14 +811,16 @@ TEST(HttpStreamFactoryTest, RequestHttpStreamOverSSL) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, RequestHttpStreamOverProxy) { - SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:8888")); +TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverProxy) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateFixed("myproxy:8888")); StaticSocketDataProvider socket_data; socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Now request a stream. It should succeed using the second proxy in the // list. @@ -871,14 +863,16 @@ TEST(HttpStreamFactoryTest, RequestHttpStreamOverProxy) { EXPECT_FALSE(waiter.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, RequestWebSocketBasicStream) { - SessionDependencies session_deps(ProxyService::CreateDirect()); +TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStream) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); StaticSocketDataProvider socket_data; socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Now request a stream. HttpRequestInfo request_info; @@ -916,18 +910,20 @@ TEST(HttpStreamFactoryTest, RequestWebSocketBasicStream) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) { - SessionDependencies session_deps(ProxyService::CreateDirect()); +TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateDirect()); MockRead mock_read(ASYNC, OK); StaticSocketDataProvider socket_data(&mock_read, 1, NULL, 0); socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); SSLSocketDataProvider ssl_socket_data(ASYNC, OK); - session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_socket_data); + session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Now request a stream. HttpRequestInfo request_info; @@ -965,15 +961,17 @@ TEST(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverProxy) { - SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:8888")); +TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverProxy) { + SpdySessionDependencies session_deps( + GetParam(), ProxyService::CreateFixed("myproxy:8888")); MockRead read(SYNCHRONOUS, "HTTP/1.0 200 Connection established\r\n\r\n"); StaticSocketDataProvider socket_data(&read, 1, 0, 0); socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory.AddSocketDataProvider(&socket_data); + session_deps.socket_factory->AddSocketDataProvider(&socket_data); - scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); + scoped_refptr<HttpNetworkSession> session( + SpdySessionDependencies::SpdyCreateSession(&session_deps)); // Now request a stream. HttpRequestInfo request_info; @@ -1019,8 +1017,8 @@ TEST(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverProxy) { EXPECT_FALSE(waiter.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, RequestSpdyHttpStream) { - SpdySessionDependencies session_deps(kProtoSPDY3, +TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) { + SpdySessionDependencies session_deps(GetParam(), ProxyService::CreateDirect()); MockRead mock_read(ASYNC, OK); @@ -1029,7 +1027,7 @@ TEST(HttpStreamFactoryTest, RequestSpdyHttpStream) { session_deps.socket_factory->AddSocketDataProvider(&socket_data); SSLSocketDataProvider ssl_socket_data(ASYNC, OK); - ssl_socket_data.SetNextProto(kProtoSPDY3); + ssl_socket_data.SetNextProto(GetParam()); session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); HostPortPair host_port_pair("www.google.com", 443); @@ -1069,8 +1067,8 @@ TEST(HttpStreamFactoryTest, RequestSpdyHttpStream) { EXPECT_TRUE(waiter.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, RequestWebSocketSpdyStream) { - SpdySessionDependencies session_deps(kProtoSPDY3, +TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyStream) { + SpdySessionDependencies session_deps(GetParam(), ProxyService::CreateDirect()); MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING); @@ -1079,7 +1077,7 @@ TEST(HttpStreamFactoryTest, RequestWebSocketSpdyStream) { session_deps.socket_factory->AddSocketDataProvider(&socket_data); SSLSocketDataProvider ssl_socket_data(ASYNC, OK); - ssl_socket_data.SetNextProto(kProtoSPDY3); + ssl_socket_data.SetNextProto(GetParam()); session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); HostPortPair host_port_pair("www.google.com", 80); @@ -1145,9 +1143,9 @@ TEST(HttpStreamFactoryTest, RequestWebSocketSpdyStream) { EXPECT_TRUE(waiter1.used_proxy_info().is_direct()); } -TEST(HttpStreamFactoryTest, OrphanedWebSocketStream) { +TEST_P(HttpStreamFactoryTest, OrphanedWebSocketStream) { UseAlternateProtocolsScopedSetter use_alternate_protocols(true); - SpdySessionDependencies session_deps(kProtoSPDY3, + SpdySessionDependencies session_deps(GetParam(), ProxyService::CreateDirect()); MockRead mock_read(ASYNC, OK); @@ -1161,7 +1159,7 @@ TEST(HttpStreamFactoryTest, OrphanedWebSocketStream) { session_deps.socket_factory->AddSocketDataProvider(&socket_data2); SSLSocketDataProvider ssl_socket_data(ASYNC, OK); - ssl_socket_data.SetNextProto(kProtoSPDY3); + ssl_socket_data.SetNextProto(GetParam()); session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_socket_data); scoped_refptr<HttpNetworkSession> diff --git a/net/net.gyp b/net/net.gyp index 5d5c131..ebb9cd9 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -1774,6 +1774,7 @@ 'spdy/spdy_protocol_test.cc', 'spdy/spdy_proxy_client_socket_unittest.cc', 'spdy/spdy_read_queue_unittest.cc', + 'spdy/spdy_session_pool_unittest.cc', 'spdy/spdy_session_test_util.cc', 'spdy/spdy_session_test_util.h', 'spdy/spdy_session_unittest.cc', @@ -2038,12 +2039,10 @@ 'cookies/cookie_store_unittest.h', 'http/http_auth_controller_unittest.cc', 'http/http_network_layer_unittest.cc', - 'http/http_network_transaction_spdy2_unittest.cc', - 'http/http_network_transaction_spdy3_unittest.cc', - 'spdy/spdy_http_stream_spdy2_unittest.cc', - 'spdy/spdy_http_stream_spdy3_unittest.cc', - 'spdy/spdy_proxy_client_socket_spdy3_unittest.cc', - 'spdy/spdy_session_spdy3_unittest.cc', + 'http/http_network_transaction_unittest.cc', + 'spdy/spdy_http_stream_unittest.cc', + 'spdy/spdy_proxy_client_socket_unittest.cc', + 'spdy/spdy_session_unittest.cc', # These tests crash when run with coverage turned on: # http://crbug.com/177203 diff --git a/net/socket/next_proto.h b/net/socket/next_proto.h index 04ecc0f..f9c1659 100644 --- a/net/socket/next_proto.h +++ b/net/socket/next_proto.h @@ -16,9 +16,11 @@ enum NextProto { kProtoHTTP11 = 1, kProtoMinimumVersion = kProtoHTTP11, + // TODO(akalin): Stop advertising SPDY/1 and remove this. kProtoSPDY1 = 2, kProtoSPDYMinimumVersion = kProtoSPDY1, kProtoSPDY2 = 3, + // TODO(akalin): Stop adverising SPDY/2.1, too. kProtoSPDY21 = 4, kProtoSPDY3 = 5, kProtoSPDY31 = 6, diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index 814010b..bd5e377 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc @@ -757,43 +757,15 @@ TEST_F(SSLClientSocketPoolTest, IPPooling) { socket_factory_.AddSSLSocketDataProvider(&ssl); CreatePool(true /* tcp pool */, false, false); - scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - true); - - scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle()); - TestCompletionCallback callback; - int rv = handle->Init( - "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_FALSE(handle->is_initialized()); - EXPECT_FALSE(handle->socket()); - - EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_TRUE(handle->is_initialized()); - EXPECT_TRUE(handle->socket()); - - SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle->socket()); - EXPECT_TRUE(ssl_socket->WasNpnNegotiated()); - std::string proto; - std::string server_protos; - ssl_socket->GetNextProto(&proto, &server_protos); - EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), - kProtoSPDY2); - - // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port - // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. - SpdySessionPoolPeer pool_peer(session_->spdy_session_pool()); - pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].key); - - scoped_refptr<SpdySession> spdy_session; - rv = session_->spdy_session_pool()->GetSpdySessionFromSocket( - test_hosts[0].key, handle.release(), BoundNetLog(), 0, - &spdy_session, true); - EXPECT_EQ(0, rv); + scoped_refptr<SpdySession> spdy_session = + CreateSecureSpdySession(session_, test_hosts[0].key, BoundNetLog()); - EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[0].key)); - EXPECT_FALSE(session_->spdy_session_pool()->HasSession(test_hosts[1].key)); - EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[2].key)); + EXPECT_TRUE( + HasSpdySession(session_->spdy_session_pool(), test_hosts[0].key)); + EXPECT_FALSE( + HasSpdySession(session_->spdy_session_pool(), test_hosts[1].key)); + EXPECT_TRUE( + HasSpdySession(session_->spdy_session_pool(), test_hosts[2].key)); session_->spdy_session_pool()->CloseAllSessions(); } @@ -838,41 +810,13 @@ void SSLClientSocketPoolTest::TestIPPoolingDisabled( socket_factory_.AddSSLSocketDataProvider(ssl); CreatePool(true /* tcp pool */, false, false); - scoped_refptr<SSLSocketParams> params = SSLParams(ProxyServer::SCHEME_DIRECT, - true); - - scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle()); - rv = handle->Init( - "a", params, MEDIUM, callback.callback(), pool_.get(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - EXPECT_FALSE(handle->is_initialized()); - EXPECT_FALSE(handle->socket()); - - EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_TRUE(handle->is_initialized()); - EXPECT_TRUE(handle->socket()); - - SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(handle->socket()); - EXPECT_TRUE(ssl_socket->WasNpnNegotiated()); - std::string proto; - std::string server_protos; - ssl_socket->GetNextProto(&proto, &server_protos); - EXPECT_EQ(SSLClientSocket::NextProtoFromString(proto), - kProtoSPDY2); - - // TODO(rtenneti): MockClientSocket::GetPeerAddress returns 0 as the port - // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. - SpdySessionPoolPeer pool_peer(session_->spdy_session_pool()); - pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].key); - - scoped_refptr<SpdySession> spdy_session; - rv = session_->spdy_session_pool()->GetSpdySessionFromSocket( - test_hosts[0].key, handle.release(), BoundNetLog(), 0, - &spdy_session, true); - EXPECT_EQ(0, rv); + scoped_refptr<SpdySession> spdy_session = + CreateSecureSpdySession(session_, test_hosts[0].key, BoundNetLog()); - EXPECT_TRUE(session_->spdy_session_pool()->HasSession(test_hosts[0].key)); - EXPECT_FALSE(session_->spdy_session_pool()->HasSession(test_hosts[1].key)); + EXPECT_TRUE( + HasSpdySession(session_->spdy_session_pool(), test_hosts[0].key)); + EXPECT_FALSE( + HasSpdySession(session_->spdy_session_pool(), test_hosts[1].key)); session_->spdy_session_pool()->CloseAllSessions(); } diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index b9df685..f91594e 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -87,61 +87,27 @@ class SpdyHttpStreamTest : public testing::Test, // Initializes the session using DeterministicSocketData. It's advisable // to use this function rather than the OrderedSocketData, since the // DeterministicSocketData behaves in a reasonable manner. - int InitSessionDeterministic(MockRead* reads, size_t reads_count, - MockWrite* writes, size_t writes_count, - HostPortPair& host_port_pair) { - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); + void InitSessionDeterministic(MockRead* reads, size_t reads_count, + MockWrite* writes, size_t writes_count, + const SpdySessionKey& key) { deterministic_data_.reset( new DeterministicSocketData(reads, reads_count, writes, writes_count)); session_deps_.deterministic_socket_factory->AddSocketDataProvider( deterministic_data_.get()); http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); - session_ = http_session_->spdy_session_pool()->Get(key, BoundNetLog()); - transport_params_ = new TransportSocketParams(host_port_pair, - MEDIUM, false, false, - OnHostResolutionCallback()); - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - transport_params_, - MEDIUM, - callback.callback(), - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, callback.WaitForResult()); - return session_->InitializeWithSocket(connection.release(), false, OK); + session_ = CreateInsecureSpdySession(http_session_, key, BoundNetLog()); } // Initializes the session using the finicky OrderedSocketData class. - int InitSession(MockRead* reads, size_t reads_count, - MockWrite* writes, size_t writes_count, - HostPortPair& host_port_pair) { - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); + void InitSession(MockRead* reads, size_t reads_count, + MockWrite* writes, size_t writes_count, + const SpdySessionKey& key) { data_.reset(new OrderedSocketData(reads, reads_count, writes, writes_count)); session_deps_.socket_factory->AddSocketDataProvider(data_.get()); http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); - session_ = http_session_->spdy_session_pool()->Get(key, BoundNetLog()); - transport_params_ = new TransportSocketParams(host_port_pair, - MEDIUM, false, false, - OnHostResolutionCallback()); - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - transport_params_, - MEDIUM, - callback.callback(), - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, callback.WaitForResult()); - return session_->InitializeWithSocket(connection.release(), false, OK); + session_ = CreateInsecureSpdySession(http_session_, key, BoundNetLog()); } void TestSendCredentials( @@ -156,7 +122,6 @@ class SpdyHttpStreamTest : public testing::Test, scoped_ptr<DeterministicSocketData> deterministic_data_; scoped_refptr<HttpNetworkSession> http_session_; scoped_refptr<SpdySession> session_; - scoped_refptr<TransportSocketParams> transport_params_; private: MockECSignatureCreatorFactory ec_signature_creator_factory_; @@ -177,7 +142,7 @@ TEST_P(SpdyHttpStreamTest, GetUploadProgressBeforeInitialization) { HostPortPair host_port_pair("www.google.com", 80); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), NULL, 0, host_port_pair)); + InitSession(reads, arraysize(reads), NULL, 0, key); SpdyHttpStream stream(session_.get(), false); UploadProgress progress = stream.GetUploadProgress(); @@ -200,8 +165,7 @@ TEST_P(SpdyHttpStreamTest, SendRequest) { HostPortPair host_port_pair("www.google.com", 80); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), - host_port_pair)); + InitSession(reads, arraysize(reads), writes, arraysize(writes), key); HttpRequestInfo request; request.method = "GET"; @@ -224,7 +188,7 @@ TEST_P(SpdyHttpStreamTest, SendRequest) { EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info)); // This triggers the MockWrite and read 2 @@ -238,7 +202,7 @@ TEST_P(SpdyHttpStreamTest, SendRequest) { // Because we abandoned the stream, we don't expect to find a session in the // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); @@ -277,9 +241,9 @@ TEST_P(SpdyHttpStreamTest, LoadTimingTwoRequests) { HostPortPair host_port_pair("www.google.com", 80); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - ASSERT_EQ(OK, InitSessionDeterministic(reads, arraysize(reads), - writes, arraysize(writes), - host_port_pair)); + InitSessionDeterministic(reads, arraysize(reads), + writes, arraysize(writes), + key); HttpRequestInfo request1; request1.method = "GET"; @@ -296,7 +260,7 @@ TEST_P(SpdyHttpStreamTest, LoadTimingTwoRequests) { CompletionCallback())); EXPECT_EQ(ERR_IO_PENDING, http_stream1->SendRequest(headers1, &response1, callback1.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); HttpRequestInfo request2; request2.method = "GET"; @@ -313,7 +277,7 @@ TEST_P(SpdyHttpStreamTest, LoadTimingTwoRequests) { CompletionCallback())); EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers2, &response2, callback2.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); // First write. deterministic_data()->RunFor(1); @@ -368,9 +332,9 @@ TEST_P(SpdyHttpStreamTest, SendChunkedPost) { HostPortPair host_port_pair("www.google.com", 80); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - EXPECT_EQ(OK, InitSession(vector_as_array(&reads), reads.size(), - vector_as_array(&writes), writes.size(), - host_port_pair)); + InitSession(vector_as_array(&reads), reads.size(), + vector_as_array(&writes), writes.size(), + key); EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion()); UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); @@ -398,7 +362,7 @@ TEST_P(SpdyHttpStreamTest, SendChunkedPost) { EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest( headers, &response, callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); // This results in writing the post body and reading the response headers. callback.WaitForResult(); @@ -410,7 +374,7 @@ TEST_P(SpdyHttpStreamTest, SendChunkedPost) { // Because we abandoned the stream, we don't expect to find a session in the // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } @@ -444,10 +408,9 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPost) { HostPortPair host_port_pair("www.google.com", 80); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - - ASSERT_EQ(OK, InitSessionDeterministic(reads, arraysize(reads), - writes, arraysize(writes), - host_port_pair)); + InitSessionDeterministic(reads, arraysize(reads), + writes, arraysize(writes), + key); UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); @@ -472,7 +435,7 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPost) { // complete asynchronously. EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); // Complete the initial request write and the first chunk. deterministic_data()->RunFor(2); @@ -540,8 +503,7 @@ TEST_P(SpdyHttpStreamTest, SpdyURLTest) { HostPortPair host_port_pair("www.google.com", 80); SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), - host_port_pair)); + InitSession(reads, arraysize(reads), writes, arraysize(writes), key); HttpRequestInfo request; request.method = "GET"; @@ -569,7 +531,7 @@ TEST_P(SpdyHttpStreamTest, SpdyURLTest) { // Because we abandoned the stream, we don't expect to find a session in the // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } @@ -686,36 +648,7 @@ void SpdyHttpStreamTest::TestSendCredentials( socket_factory->AddSSLSocketDataProvider(&ssl); http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( &session_deps_); - session_ = http_session_->spdy_session_pool()->Get(key, BoundNetLog()); - transport_params_ = new TransportSocketParams(host_port_pair, - MEDIUM, false, false, - OnHostResolutionCallback()); - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - SSLConfig ssl_config; - scoped_refptr<SOCKSSocketParams> socks_params; - scoped_refptr<HttpProxySocketParams> http_proxy_params; - scoped_refptr<SSLSocketParams> ssl_params( - new SSLSocketParams(transport_params_, - socks_params, - http_proxy_params, - ProxyServer::SCHEME_DIRECT, - host_port_pair, - ssl_config, - 0, - false, - false)); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - ssl_params, - MEDIUM, - callback.callback(), - http_session_->GetSSLSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - callback.WaitForResult(); - EXPECT_EQ(OK, - session_->InitializeWithSocket(connection.release(), true, OK)); + session_ = CreateSecureSpdySession(http_session_, key, BoundNetLog()); HttpRequestInfo request; request.method = "GET"; @@ -734,9 +667,10 @@ void SpdyHttpStreamTest::TestSendCredentials( // GURL new_origin(kUrl2); // EXPECT_TRUE(session_->NeedsCredentials(new_origin)); + TestCompletionCallback callback; EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); data.RunFor(2); callback.WaitForResult(); @@ -790,35 +724,9 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) { SpdySessionKey key(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - - DeterministicMockClientSocketFactory* socket_factory = - session_deps_.deterministic_socket_factory.get(); - socket_factory->AddSocketDataProvider(&data); - - http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( - &session_deps_); - session_ = http_session_->spdy_session_pool()->Get(key, BoundNetLog()); - transport_params_ = new TransportSocketParams(host_port_pair, - MEDIUM, false, false, - OnHostResolutionCallback()); - - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - transport_params_, - MEDIUM, - callback.callback(), - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - - callback.WaitForResult(); - EXPECT_EQ(OK, - session_->InitializeWithSocket(connection.release(), false, OK)); + InitSessionDeterministic(reads, arraysize(reads), + writes, arraysize(writes), + key); UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); @@ -840,12 +748,13 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) { HttpResponseInfo response; // This will attempt to Write() the initial request and headers, which will // complete asynchronously. + TestCompletionCallback callback; EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); // Complete the initial request write and first chunk. - data.RunFor(2); + deterministic_data_->RunFor(2); ASSERT_TRUE(callback.have_result()); EXPECT_EQ(OK, callback.WaitForResult()); @@ -855,7 +764,7 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) { http_stream->stream()->send_window_size()); // Read window update. - data.RunFor(1); + deterministic_data_->RunFor(1); // Verify the window update. ASSERT_TRUE(http_stream->stream() != NULL); @@ -863,11 +772,11 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) { http_stream->stream()->send_window_size()); // Read response headers. - data.RunFor(1); + deterministic_data_->RunFor(1); ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback())); // Read and check |chunk1| response. - data.RunFor(1); + deterministic_data_->RunFor(1); scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize)); ASSERT_EQ(kUploadDataSize, http_stream->ReadResponseBody( @@ -875,11 +784,11 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) { EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize)); // Finish reading the |EOF|. - data.RunFor(1); + deterministic_data_->RunFor(1); ASSERT_TRUE(response.headers.get()); ASSERT_EQ(200, response.headers->response_code()); - EXPECT_TRUE(data.at_read_eof()); - EXPECT_TRUE(data.at_write_eof()); + EXPECT_TRUE(deterministic_data_->at_read_eof()); + EXPECT_TRUE(deterministic_data_->at_write_eof()); } TEST_P(SpdyHttpStreamTest, SendCredentialsEC) { @@ -947,49 +856,9 @@ TEST_P(SpdyHttpStreamTest, DontSendCredentialsForHttpUrlsEC) { ProxyServer::FromURI("proxy.google.com", ProxyServer::SCHEME_HTTPS), kPrivacyModeDisabled); - - DeterministicMockClientSocketFactory* socket_factory = - session_deps_.deterministic_socket_factory.get(); - DeterministicSocketData data(reads, arraysize(reads), - writes, arraysize(writes)); - socket_factory->AddSocketDataProvider(&data); - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - ssl.channel_id_sent = true; - ssl.server_bound_cert_service = server_bound_cert_service.get(); - ssl.protocol_negotiated = GetParam(); - socket_factory->AddSSLSocketDataProvider(&ssl); - http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( - &session_deps_); - session_ = http_session_->spdy_session_pool()->Get(key, BoundNetLog()); - transport_params_ = new TransportSocketParams(host_port_pair, - MEDIUM, false, false, - OnHostResolutionCallback()); - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - SSLConfig ssl_config; - scoped_refptr<SOCKSSocketParams> socks_params; - scoped_refptr<HttpProxySocketParams> http_proxy_params; - scoped_refptr<SSLSocketParams> ssl_params( - new SSLSocketParams(transport_params_, - socks_params, - http_proxy_params, - ProxyServer::SCHEME_DIRECT, - host_port_pair, - ssl_config, - 0, - false, - false)); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - ssl_params, - MEDIUM, - callback.callback(), - http_session_->GetSSLSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - callback.WaitForResult(); - EXPECT_EQ(OK, - session_->InitializeWithSocket(connection.release(), true, OK)); + InitSessionDeterministic(reads, arraysize(reads), + writes, arraysize(writes), + key); HttpRequestInfo request; request.method = "GET"; @@ -1004,11 +873,12 @@ TEST_P(SpdyHttpStreamTest, DontSendCredentialsForHttpUrlsEC) { http_stream->InitializeStream(&request, DEFAULT_PRIORITY, net_log, CompletionCallback())); + TestCompletionCallback callback; EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); + EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); - data.RunFor(2); + deterministic_data_->RunFor(2); EXPECT_EQ(OK, callback.WaitForResult()); // Start up second request for resource on a new origin. @@ -1021,16 +891,16 @@ TEST_P(SpdyHttpStreamTest, DontSendCredentialsForHttpUrlsEC) { net_log, CompletionCallback())); EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers, &response, callback.callback())); - data.RunFor(1); + deterministic_data_->RunFor(1); EXPECT_EQ(OK, callback.WaitForResult()); EXPECT_EQ(ERR_IO_PENDING, http_stream2->ReadResponseHeaders( callback.callback())); - data.RunFor(1); + deterministic_data_->RunFor(1); EXPECT_EQ(OK, callback.WaitForResult()); ASSERT_TRUE(response.headers.get() != NULL); ASSERT_EQ(200, response.headers->response_code()); - data.RunFor(1); + deterministic_data_->RunFor(1); sequenced_worker_pool->Shutdown(); } diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index f0e4c8c..b533f29 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -562,10 +562,9 @@ class SpdyNetworkTransactionTest kPrivacyModeDisabled); BoundNetLog log; const scoped_refptr<HttpNetworkSession>& session = helper.session(); - SpdySessionPool* pool(session->spdy_session_pool()); - EXPECT_TRUE(pool->HasSession(key)); - scoped_refptr<SpdySession> spdy_session(pool->Get(key, log)); - ASSERT_TRUE(spdy_session.get() != NULL); + scoped_refptr<SpdySession> spdy_session = + session->spdy_session_pool()->GetIfExists(key, log); + ASSERT_TRUE(spdy_session != NULL); EXPECT_EQ(0u, spdy_session->num_active_streams()); EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams()); } @@ -4603,12 +4602,12 @@ TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) { HostPortPair host_port_pair("www.google.com", helper.port()); SpdySessionKey session_pool_key_direct( host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct)); SpdySessionKey session_pool_key_proxy( host_port_pair, ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP), kPrivacyModeDisabled); - EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy)); // Set up data for the proxy connection. const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n" diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index 5580f29..5af767b 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc @@ -129,7 +129,6 @@ class SpdyProxyClientSocketTest HostPortPair endpoint_host_port_pair_; ProxyServer proxy_; SpdySessionKey endpoint_spdy_session_key_; - scoped_refptr<TransportSocketParams> transport_params_; DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest); }; @@ -154,12 +153,7 @@ SpdyProxyClientSocketTest::SpdyProxyClientSocketTest() proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_), endpoint_spdy_session_key_(endpoint_host_port_pair_, proxy_, - kPrivacyModeDisabled), - transport_params_(new TransportSocketParams(proxy_host_port_, - LOWEST, - false, - false, - OnHostResolutionCallback())) { + kPrivacyModeDisabled) { session_deps_.net_log = net_log_.bound().net_log(); } @@ -189,22 +183,10 @@ void SpdyProxyClientSocketTest::Initialize(MockRead* reads, session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( &session_deps_); - // Creates a new spdy session. + // Creates the SPDY session and stream. spdy_session_ = - session_->spdy_session_pool()->Get(endpoint_spdy_session_key_, - net_log_.bound()); - - // Perform the TCP connect. - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, - connection->Init(endpoint_host_port_pair_.ToString(), - transport_params_, LOWEST, CompletionCallback(), - session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - net_log_.bound())); - spdy_session_->InitializeWithSocket(connection.release(), false, OK); - - // Create the SPDY Stream. + CreateInsecureSpdySession( + session_, endpoint_spdy_session_key_, BoundNetLog()); base::WeakPtr<SpdyStream> spdy_stream( CreateStreamSynchronously( SPDY_BIDIRECTIONAL_STREAM, spdy_session_, url_, LOWEST, diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 4ad5184..2ff50a028 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -57,6 +57,7 @@ const int kMinPushedStreamLifetimeSeconds = 300; SpdyMajorVersion NPNToSpdyVersion(NextProto next_proto) { switch (next_proto) { case kProtoSPDY2: + case kProtoSPDY21: return SPDY2; case kProtoSPDY3: case kProtoSPDY31: @@ -440,20 +441,21 @@ SpdySession::~SpdySession() { } Error SpdySession::InitializeWithSocket( - ClientSocketHandle* connection, + scoped_ptr<ClientSocketHandle> connection, bool is_secure, int certificate_error_code) { base::StatsCounter spdy_sessions("spdy.sessions"); spdy_sessions.Increment(); state_ = STATE_DO_READ; - connection_.reset(connection); + connection_ = connection.Pass(); connection_->AddLayeredPool(this); is_secure_ = is_secure; certificate_error_code_ = certificate_error_code; NextProto protocol = default_protocol_; - NextProto protocol_negotiated = connection->socket()->GetNegotiatedProtocol(); + NextProto protocol_negotiated = + connection_->socket()->GetNegotiatedProtocol(); if (protocol_negotiated != kProtoUnknown) { protocol = protocol_negotiated; } @@ -466,8 +468,10 @@ Error SpdySession::InitializeWithSocket( host_port_pair().ToString())); } + // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we + // stop supporting SPDY/1. DCHECK_GE(protocol, kProtoSPDY2); - DCHECK_LE(protocol, kProtoSPDY4a2); + DCHECK_LE(protocol, kProtoSPDYMaximumVersion); if (protocol >= kProtoSPDY31) { flow_control_state_ = FLOW_CONTROL_STREAM_AND_SESSION; session_send_window_size_ = kSpdySessionInitialWindowSize; @@ -532,7 +536,6 @@ int SpdySession::GetPushStream( PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION); CloseSessionOnError( static_cast<Error>(certificate_error_code_), - true, "Tried to get SPDY stream for secure content over an unauthenticated " "session."); return ERR_SPDY_PROTOCOL_ERROR; @@ -573,7 +576,6 @@ int SpdySession::CreateStream(const SpdyStreamRequest& request, PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION); CloseSessionOnError( static_cast<Error>(certificate_error_code_), - true, "Tried to create SPDY stream for secure content over an " "unauthenticated session."); return ERR_SPDY_PROTOCOL_ERROR; @@ -587,7 +589,6 @@ int SpdySession::CreateStream(const SpdyStreamRequest& request, if (!connection_->socket()->IsConnected()) { CloseSessionOnError( ERR_CONNECTION_CLOSED, - true, "Tried to create SPDY stream for a closed socket connection."); return ERR_CONNECTION_CLOSED; } @@ -1095,7 +1096,7 @@ int SpdySession::DoReadComplete(int result) { total_bytes_received_, 1, 100000000, 50); error = ERR_CONNECTION_CLOSED; } - CloseSessionOnError(error, true, "result is <= 0."); + CloseSessionOnError(error, "result is <= 0."); return ERR_CONNECTION_CLOSED; } @@ -1139,7 +1140,7 @@ void SpdySession::OnWriteComplete(int result) { in_flight_write_frame_type_ = DATA; in_flight_write_frame_size_ = 0; in_flight_write_stream_.reset(); - CloseSessionOnError(static_cast<Error>(result), true, "Write error"); + CloseSessionOnError(static_cast<Error>(result), "Write error"); return; } @@ -1338,7 +1339,6 @@ int SpdySession::GetNewStreamId() { } void SpdySession::CloseSessionOnError(Error err, - bool remove_from_pool, const std::string& description) { // Closing all streams can have a side-effect of dropping the last reference // to |this|. Hold a reference through this function. @@ -1358,8 +1358,9 @@ void SpdySession::CloseSessionOnError(Error err, total_bytes_received_, 1, 100000000, 50); state_ = STATE_CLOSED; error_ = err; - if (remove_from_pool) - RemoveFromPool(); + // TODO(akalin): Move this after CloseAllStreams() once we're + // owned by the pool. + RemoveFromPool(); CloseAllStreams(err); } } @@ -1574,7 +1575,7 @@ void SpdySession::OnError(SpdyFramer::SpdyError error_code) { static_cast<SpdyProtocolErrorDetails>(error_code)); std::string description = base::StringPrintf( "SPDY_ERROR error_code: %d.", error_code); - CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, true, description); + CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, description); } void SpdySession::OnStreamError(SpdyStreamId stream_id, @@ -1965,6 +1966,7 @@ void SpdySession::OnGoAway(SpdyStreamId last_accepted_stream_id, active_streams_.size(), unclaimed_pushed_streams_.size(), status)); + // TODO(akalin): Move into a "going away" state in the pool instead. RemoveFromPool(); CloseAllStreamsAfter(last_accepted_stream_id, ERR_ABORTED); } @@ -1983,8 +1985,7 @@ void SpdySession::OnPing(uint32 unique_id) { --pings_in_flight_; if (pings_in_flight_ < 0) { RecordProtocolErrorHistogram(PROTOCOL_ERROR_UNEXPECTED_PING); - CloseSessionOnError( - ERR_SPDY_PROTOCOL_ERROR, true, "pings_in_flight_ is < 0."); + CloseSessionOnError(ERR_SPDY_PROTOCOL_ERROR, "pings_in_flight_ is < 0."); pings_in_flight_ = 0; return; } @@ -2018,7 +2019,6 @@ void SpdySession::OnWindowUpdate(SpdyStreamId stream_id, RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); CloseSessionOnError( ERR_SPDY_PROTOCOL_ERROR, - true, "Received WINDOW_UPDATE with an invalid delta_window_size " + base::UintToString(delta_window_size)); return; @@ -2269,7 +2269,7 @@ void SpdySession::CheckPingStatus(base::TimeTicks last_check_time) { base::TimeDelta delay = hung_interval_ - (now - last_activity_time_); if (delay.InMilliseconds() < 0 || last_activity_time_ < last_check_time) { - CloseSessionOnError(ERR_SPDY_PING_FAILED, true, "Failed ping."); + CloseSessionOnError(ERR_SPDY_PING_FAILED, "Failed ping."); // Track all failed PING messages in a separate bucket. const base::TimeDelta kFailedPing = base::TimeDelta::FromInternalValue(INT_MAX); @@ -2427,7 +2427,6 @@ void SpdySession::IncreaseSendWindowSize(int32 delta_window_size) { RecordProtocolErrorHistogram(PROTOCOL_ERROR_INVALID_WINDOW_UPDATE_SIZE); CloseSessionOnError( ERR_SPDY_PROTOCOL_ERROR, - true, "Received WINDOW_UPDATE [delta: " + base::IntToString(delta_window_size) + "] for session overflows session_send_window_size_ [current: " + @@ -2509,7 +2508,6 @@ void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) { RecordProtocolErrorHistogram(PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION); CloseSessionOnError( ERR_SPDY_PROTOCOL_ERROR, - true, "delta_window_size is " + base::IntToString(delta_window_size) + " in DecreaseRecvWindowSize, which is larger than the receive " + "window size of " + base::IntToString(session_recv_window_size_)); diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 586534f..28e53da 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -207,7 +207,7 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>, bool enable_credential_frames, bool enable_compression, bool enable_ping_based_connection_checking, - NextProto default_protocol_, + NextProto default_protocol, size_t stream_initial_recv_window_size, size_t initial_max_concurrent_streams, size_t max_concurrent_streams_limit, @@ -240,7 +240,7 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>, // testing, setting is_secure to false allows initialization with a // pre-existing TCP socket. // Returns OK on success, or an error on failure. - Error InitializeWithSocket(ClientSocketHandle* connection, + Error InitializeWithSocket(scoped_ptr<ClientSocketHandle> connection, bool is_secure, int certificate_error_code); @@ -340,9 +340,7 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>, // |remove_from_pool| indicates whether to also remove the session from the // session pool. // |description| indicates the reason for the error. - void CloseSessionOnError(Error err, - bool remove_from_pool, - const std::string& description); + void CloseSessionOnError(Error err, const std::string& description); // Retrieves information on the current state of the SPDY session as a // Value. Caller takes possession of the returned value. @@ -369,10 +367,6 @@ class NET_EXPORT SpdySession : public base::RefCounted<SpdySession>, bool GetLoadTimingInfo(SpdyStreamId stream_id, LoadTimingInfo* load_timing_info) const; - void set_spdy_session_pool(SpdySessionPool* pool) { - spdy_session_pool_ = NULL; - } - // Returns true if session is not currently active bool is_active() const { return !active_streams_.empty() || !created_streams_.empty(); diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index 499670e..0d4fb19 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -4,7 +4,6 @@ #include "net/spdy/spdy_session_pool.h" -#include "base/callback.h" #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/values.h" @@ -26,16 +25,12 @@ enum SpdySessionGetTypes { SPDY_SESSION_GET_MAX = 4 }; -} - -// The maximum number of sessions to open to a single domain. -static const size_t kMaxSessionsPerDomain = 1; +} // namespace SpdySessionPool::SpdySessionPool( HostResolver* resolver, SSLConfigService* ssl_config_service, HttpServerProperties* http_server_properties, - size_t max_sessions_per_domain, bool force_single_domain, bool enable_ip_pooling, bool enable_credential_frames, @@ -52,9 +47,6 @@ SpdySessionPool::SpdySessionPool( resolver_(resolver), verify_domain_authentication_(true), enable_sending_initial_settings_(true), - max_sessions_per_domain_(max_sessions_per_domain == 0 ? - kMaxSessionsPerDomain : - max_sessions_per_domain), force_single_domain_(force_single_domain), enable_ip_pooling_(enable_ip_pooling), enable_credential_frames_(enable_credential_frames), @@ -83,87 +75,42 @@ SpdySessionPool::~SpdySessionPool() { CertDatabase::GetInstance()->RemoveObserver(this); } -scoped_refptr<SpdySession> SpdySessionPool::Get( - const SpdySessionKey& spdy_session_key, - const BoundNetLog& net_log) { - return GetInternal(spdy_session_key, net_log, false); -} - scoped_refptr<SpdySession> SpdySessionPool::GetIfExists( const SpdySessionKey& spdy_session_key, const BoundNetLog& net_log) { - return GetInternal(spdy_session_key, net_log, true); -} - -scoped_refptr<SpdySession> SpdySessionPool::GetInternal( - const SpdySessionKey& spdy_session_key, - const BoundNetLog& net_log, - bool only_use_existing_sessions) { - scoped_refptr<SpdySession> spdy_session; - SpdySessionList* list = GetSessionList(spdy_session_key); - if (!list) { - // Check if we have a Session through a domain alias. - spdy_session = GetFromAlias(spdy_session_key, net_log, true); - if (spdy_session.get()) { - UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", - FOUND_EXISTING_FROM_IP_POOL, - SPDY_SESSION_GET_MAX); - net_log.AddEvent( - NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL, - spdy_session->net_log().source().ToEventParametersCallback()); - // Add this session to the map so that we can find it next time. - list = AddSessionList(spdy_session_key); - list->push_back(spdy_session); - spdy_session->AddPooledAlias(spdy_session_key); - return spdy_session; - } else if (only_use_existing_sessions) { - return NULL; - } - list = AddSessionList(spdy_session_key); + SpdySessionsMap::iterator it = FindSessionByKey(spdy_session_key); + if (it != sessions_.end()) { + UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", + FOUND_EXISTING, + SPDY_SESSION_GET_MAX); + net_log.AddEvent( + NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION, + it->second->net_log().source().ToEventParametersCallback()); + return it->second; } - DCHECK(list); - if (list->size() && list->size() == max_sessions_per_domain_) { + // Check if we have a Session through a domain alias. + scoped_refptr<SpdySession> spdy_session = + GetFromAlias(spdy_session_key, net_log, true); + if (spdy_session) { UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", - FOUND_EXISTING, + FOUND_EXISTING_FROM_IP_POOL, SPDY_SESSION_GET_MAX); - spdy_session = GetExistingSession(list, net_log); net_log.AddEvent( - NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION, - spdy_session->net_log().source().ToEventParametersCallback()); + NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL, + spdy_session->net_log().source().ToEventParametersCallback()); + // Add this session to the map so that we can find it next time. + AddSession(spdy_session_key, spdy_session); + spdy_session->AddPooledAlias(spdy_session_key); return spdy_session; } - DCHECK(!only_use_existing_sessions); - - spdy_session = new SpdySession(spdy_session_key, this, - http_server_properties_, - verify_domain_authentication_, - enable_sending_initial_settings_, - enable_credential_frames_, - enable_compression_, - enable_ping_based_connection_checking_, - default_protocol_, - stream_initial_recv_window_size_, - initial_max_concurrent_streams_, - max_concurrent_streams_limit_, - time_func_, - trusted_spdy_proxy_, - net_log.net_log()); - UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", - CREATED_NEW, - SPDY_SESSION_GET_MAX); - list->push_back(spdy_session); - net_log.AddEvent( - NetLog::TYPE_SPDY_SESSION_POOL_CREATED_NEW_SESSION, - spdy_session->net_log().source().ToEventParametersCallback()); - DCHECK_LE(list->size(), max_sessions_per_domain_); - return spdy_session; + return scoped_refptr<SpdySession>(); } net::Error SpdySessionPool::GetSpdySessionFromSocket( const SpdySessionKey& spdy_session_key, - ClientSocketHandle* connection, + scoped_ptr<ClientSocketHandle> connection, const BoundNetLog& net_log, int certificate_error_code, scoped_refptr<SpdySession>* spdy_session, @@ -186,11 +133,7 @@ net::Error SpdySessionPool::GetSpdySessionFromSocket( time_func_, trusted_spdy_proxy_, net_log.net_log()); - SpdySessionList* list = GetSessionList(spdy_session_key); - if (!list) - list = AddSessionList(spdy_session_key); - DCHECK(list->empty()); - list->push_back(*spdy_session); + AddSession(spdy_session_key, *spdy_session); net_log.AddEvent( NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET, @@ -205,28 +148,64 @@ net::Error SpdySessionPool::GetSpdySessionFromSocket( spdy_session_key.proxy_server().is_direct()) { IPEndPoint address; if (connection->socket()->GetPeerAddress(&address) == OK) - AddAlias(address, spdy_session_key); + aliases_[address] = spdy_session_key; } // Now we can initialize the session with the SSL socket. - return (*spdy_session)->InitializeWithSocket(connection, is_secure, + return (*spdy_session)->InitializeWithSocket(connection.Pass(), is_secure, certificate_error_code); } -bool SpdySessionPool::HasSession( - const SpdySessionKey& spdy_session_key) const { - if (GetSessionList(spdy_session_key)) - return true; +// Make a copy of |sessions_| in the Close* functions below to avoid +// reentrancy problems. Due to aliases, it doesn't suffice to simply +// increment the iterator before closing. - // Check if we have a session via an alias. - scoped_refptr<SpdySession> spdy_session = - GetFromAlias(spdy_session_key, BoundNetLog(), false); - return spdy_session.get() != NULL; +void SpdySessionPool::CloseCurrentSessions(net::Error error) { + SpdySessionsMap sessions_copy = sessions_; + for (SpdySessionsMap::const_iterator it = sessions_copy.begin(); + it != sessions_copy.end(); ++it) { + TryCloseSession(it->first, error, "Closing current sessions."); + } +} + +void SpdySessionPool::CloseCurrentIdleSessions() { + SpdySessionsMap sessions_copy = sessions_; + for (SpdySessionsMap::const_iterator it = sessions_copy.begin(); + it != sessions_copy.end(); ++it) { + if (!it->second->is_active()) + TryCloseSession(it->first, ERR_ABORTED, "Closing idle sessions."); + } +} + +void SpdySessionPool::CloseAllSessions() { + while (!sessions_.empty()) { + SpdySessionsMap sessions_copy = sessions_; + for (SpdySessionsMap::const_iterator it = sessions_copy.begin(); + it != sessions_copy.end(); ++it) { + TryCloseSession(it->first, ERR_ABORTED, "Closing all sessions."); + } + } +} + +void SpdySessionPool::TryCloseSession(const SpdySessionKey& key, + net::Error error, + const std::string& description) { + SpdySessionsMap::const_iterator it = sessions_.find(key); + if (it == sessions_.end()) + return; + scoped_refptr<SpdySession> session = it->second; + session->CloseSessionOnError(error, description); + if (DCHECK_IS_ON()) { + it = sessions_.find(key); + // A new session with the same key may have been added, but it + // must not be the one we just closed. + if (it != sessions_.end()) + DCHECK_NE(it->second, session); + } } void SpdySessionPool::Remove(const scoped_refptr<SpdySession>& session) { - bool ok = RemoveFromSessionList(session, session->spdy_session_key()); - DCHECK(ok); + RemoveSession(session->spdy_session_key()); session->net_log().AddEvent( NetLog::TYPE_SPDY_SESSION_POOL_REMOVE_SESSION, session->net_log().source().ToEventParametersCallback()); @@ -234,38 +213,21 @@ void SpdySessionPool::Remove(const scoped_refptr<SpdySession>& session) { const std::set<SpdySessionKey>& aliases = session->pooled_aliases(); for (std::set<SpdySessionKey>::const_iterator it = aliases.begin(); it != aliases.end(); ++it) { - ok = RemoveFromSessionList(session, *it); - DCHECK(ok); + RemoveSession(*it); } } -bool SpdySessionPool::RemoveFromSessionList( - const scoped_refptr<SpdySession>& session, - const SpdySessionKey& spdy_session_key) { - SpdySessionList* list = GetSessionList(spdy_session_key); - if (!list) - return false; - list->remove(session); - if (list->empty()) - RemoveSessionList(spdy_session_key); - return true; -} - base::Value* SpdySessionPool::SpdySessionPoolInfoToValue() const { base::ListValue* list = new base::ListValue(); for (SpdySessionsMap::const_iterator it = sessions_.begin(); it != sessions_.end(); ++it) { - SpdySessionList* sessions = it->second; - for (SpdySessionList::const_iterator session = sessions->begin(); - session != sessions->end(); ++session) { - // Only add the session if the key in the map matches the main - // host_port_proxy_pair (not an alias). - const SpdySessionKey& key = it->first; - const SpdySessionKey& session_key = session->get()->spdy_session_key(); - if (key.Equals(session_key)) - list->Append(session->get()->GetInfoAsValue()); - } + // Only add the session if the key in the map matches the main + // host_port_proxy_pair (not an alias). + const SpdySessionKey& key = it->first; + const SpdySessionKey& session_key = it->second->spdy_session_key(); + if (key.Equals(session_key)) + list->Append(it->second->GetInfoAsValue()); } return list; } @@ -279,26 +241,12 @@ void SpdySessionPool::OnSSLConfigChanged() { CloseCurrentSessions(ERR_NETWORK_CHANGED); } -scoped_refptr<SpdySession> SpdySessionPool::GetExistingSession( - SpdySessionList* list, - const BoundNetLog& net_log) const { - DCHECK(list); - DCHECK_LT(0u, list->size()); - scoped_refptr<SpdySession> spdy_session = list->front(); - if (list->size() > 1) { - list->pop_front(); // Rotate the list. - list->push_back(spdy_session); - } - - return spdy_session; -} - scoped_refptr<SpdySession> SpdySessionPool::GetFromAlias( const SpdySessionKey& spdy_session_key, const BoundNetLog& net_log, - bool record_histograms) const { + bool record_histograms) { // We should only be checking aliases when there is no direct session. - DCHECK(!GetSessionList(spdy_session_key)); + DCHECK(FindSessionByKey(spdy_session_key) == sessions_.end()); if (!enable_ip_pooling_) return NULL; @@ -322,13 +270,13 @@ scoped_refptr<SpdySession> SpdySessionPool::GetFromAlias( spdy_session_key.privacy_mode())) continue; - SpdySessionList* list = GetSessionList(alias_key); - if (!list) { + SpdySessionsMap::iterator it = FindSessionByKey(alias_key); + if (it == sessions_.end()) { NOTREACHED(); // It shouldn't be in the aliases table if we can't get it! continue; } - scoped_refptr<SpdySession> spdy_session = GetExistingSession(list, net_log); + scoped_refptr<SpdySession> spdy_session = it->second; // If the SPDY session is a secure one, we need to verify that the server // is authenticated to serve traffic for |host_port_proxy_pair| too. if (!spdy_session->VerifyDomainAuthentication( @@ -371,36 +319,25 @@ const SpdySessionKey& SpdySessionPool::NormalizeListKey( return *single_domain_key; } -SpdySessionPool::SpdySessionList* - SpdySessionPool::AddSessionList( - const SpdySessionKey& spdy_session_key) { +void SpdySessionPool::AddSession( + const SpdySessionKey& spdy_session_key, + const scoped_refptr<SpdySession>& spdy_session) { const SpdySessionKey& key = NormalizeListKey(spdy_session_key); - DCHECK(sessions_.find(key) == sessions_.end()); - SpdySessionPool::SpdySessionList* list = new SpdySessionList(); - sessions_[spdy_session_key] = list; - return list; + std::pair<SpdySessionsMap::iterator, bool> result = + sessions_.insert(std::make_pair(key, spdy_session)); + CHECK(result.second); } -SpdySessionPool::SpdySessionList* - SpdySessionPool::GetSessionList( - const SpdySessionKey& spdy_session_key) const { +SpdySessionPool::SpdySessionsMap::iterator +SpdySessionPool::FindSessionByKey(const SpdySessionKey& spdy_session_key) { const SpdySessionKey& key = NormalizeListKey(spdy_session_key); - SpdySessionsMap::const_iterator it = sessions_.find(key); - if (it != sessions_.end()) - return it->second; - return NULL; + return sessions_.find(key); } -void SpdySessionPool::RemoveSessionList( - const SpdySessionKey& spdy_session_key) { - const SpdySessionKey& key = NormalizeListKey(spdy_session_key); - SpdySessionList* list = GetSessionList(key); - if (list) { - delete list; - sessions_.erase(key); - } else { - DCHECK(false) << "removing orphaned session list"; - } +void SpdySessionPool::RemoveSession(const SpdySessionKey& spdy_session_key) { + SpdySessionsMap::iterator it = FindSessionByKey(spdy_session_key); + CHECK(it != sessions_.end()); + sessions_.erase(it); RemoveAliases(spdy_session_key); } @@ -414,12 +351,6 @@ bool SpdySessionPool::LookupAddresses(const SpdySessionKey& spdy_session_key, return rv == OK; } -void SpdySessionPool::AddAlias(const IPEndPoint& endpoint, - const SpdySessionKey& spdy_session_key) { - DCHECK(enable_ip_pooling_); - aliases_[endpoint] = spdy_session_key; -} - void SpdySessionPool::RemoveAliases(const SpdySessionKey& spdy_session_key) { // Walk the aliases map, find references to this pair. // TODO(mbelshe): Figure out if this is too expensive. @@ -434,69 +365,4 @@ void SpdySessionPool::RemoveAliases(const SpdySessionKey& spdy_session_key) { } } -void SpdySessionPool::CloseAllSessions() { - while (!sessions_.empty()) { - SpdySessionList* list = sessions_.begin()->second; - CHECK(list); - const scoped_refptr<SpdySession>& session = list->front(); - CHECK(session.get()); - // This call takes care of removing the session from the pool, as well as - // removing the session list if the list is empty. - session->CloseSessionOnError( - net::ERR_ABORTED, true, "Closing all sessions."); - } -} - -void SpdySessionPool::CloseCurrentSessions(net::Error error) { - SpdySessionsMap old_map; - old_map.swap(sessions_); - for (SpdySessionsMap::const_iterator it = old_map.begin(); - it != old_map.end(); ++it) { - SpdySessionList* list = it->second; - CHECK(list); - const scoped_refptr<SpdySession>& session = list->front(); - CHECK(session.get()); - session->set_spdy_session_pool(NULL); - } - - while (!old_map.empty()) { - SpdySessionList* list = old_map.begin()->second; - CHECK(list); - const scoped_refptr<SpdySession>& session = list->front(); - CHECK(session.get()); - session->CloseSessionOnError(error, false, "Closing current sessions."); - list->pop_front(); - if (list->empty()) { - delete list; - RemoveAliases(old_map.begin()->first); - old_map.erase(old_map.begin()->first); - } - } - DCHECK(sessions_.empty()); - DCHECK(aliases_.empty()); -} - -void SpdySessionPool::CloseIdleSessions() { - SpdySessionsMap::const_iterator map_it = sessions_.begin(); - while (map_it != sessions_.end()) { - SpdySessionList* list = map_it->second; - 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.get()); - if (session->is_active()) { - ++map_it; - continue; - } - - SpdySessionKey key(map_it->first); - session->CloseSessionOnError( - net::ERR_ABORTED, true, "Closing idle sessions."); - // CloseSessionOnError can invalidate the iterator. - map_it = sessions_.lower_bound(key); - } -} - } // namespace net diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 2c49aee..2e6b993 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -5,7 +5,6 @@ #ifndef NET_SPDY_SPDY_SESSION_POOL_H_ #define NET_SPDY_SPDY_SESSION_POOL_H_ -#include <list> #include <map> #include <string> @@ -44,7 +43,6 @@ class NET_EXPORT SpdySessionPool SpdySessionPool(HostResolver* host_resolver, SSLConfigService* ssl_config_service, HttpServerProperties* http_server_properties, - size_t max_sessions_per_domain, bool force_single_domain, bool enable_ip_pooling, bool enable_credential_frames, @@ -58,50 +56,50 @@ class NET_EXPORT SpdySessionPool const std::string& trusted_spdy_proxy); virtual ~SpdySessionPool(); - // Either returns an existing SpdySession or creates a new SpdySession for - // use. - scoped_refptr<SpdySession> Get( - const SpdySessionKey& spdy_session_key, - const BoundNetLog& net_log); - - // Only returns a SpdySession if it already exists. + // Returns the SPDY session for the given key, or NULL if there is + // none. scoped_refptr<SpdySession> GetIfExists( const SpdySessionKey& spdy_session_key, const BoundNetLog& net_log); - // Builds a SpdySession from an existing SSL socket. Users should try - // calling Get() first to use an existing SpdySession so we don't get - // multiple SpdySessions per domain. Note that ownership of |connection| is - // transferred from the caller to the SpdySession. - // |certificate_error_code| is used to indicate the certificate error - // encountered when connecting the SSL socket. OK means there was no error. - // For testing, setting is_secure to false allows Spdy to connect with a - // pre-existing TCP socket. + // Builds a SpdySession from an existing SSL socket. There must not + // already be a session for the given key. Note that ownership of + // |connection| is transferred from the caller to the SpdySession. + // + // |certificate_error_code| is used to indicate the certificate + // error encountered when connecting the SSL socket. OK means there + // was no error. For testing and when SPDY is configured to work + // with non-secure sockets, setting is_secure to false allows Spdy + // to connect with a pre-existing TCP socket. + // // Returns OK on success, and the |spdy_session| will be provided. // Returns an error on failure, and |spdy_session| will be NULL. net::Error GetSpdySessionFromSocket( const SpdySessionKey& spdy_session_key, - ClientSocketHandle* connection, + scoped_ptr<ClientSocketHandle> connection, const BoundNetLog& net_log, int certificate_error_code, scoped_refptr<SpdySession>* spdy_session, bool is_secure); - // TODO(willchan): Consider renaming to HasReusableSession, since perhaps we - // should be creating a new session. WARNING: Because of IP connection pooling - // using the HostCache, if HasSession() returns true at one point, it does not - // imply the SpdySessionPool will still have a matching session in the near - // future, since the HostCache's entry may have expired. - bool HasSession(const SpdySessionKey& spdy_session_key) const; + // Close only the currently existing SpdySessions with |error|. + // Let any new ones created while this method is running continue to + // live. + void CloseCurrentSessions(net::Error error); + + // Close only the currently existing SpdySessions that are idle. + // Let any new ones created while this method is running continue to + // live. + void CloseCurrentIdleSessions(); // Close all SpdySessions, including any new ones created in the process of // closing the current ones. void CloseAllSessions(); - // Close only the currently existing SpdySessions with |error|. - // Let any new ones created continue to live. - void CloseCurrentSessions(net::Error error); - // Close only the idle SpdySessions. - void CloseIdleSessions(); + + // Look up the session for the given key and close it if found. + void TryCloseSession(const SpdySessionKey& key, + net::Error error, + const std::string& description); // Removes a SpdySession from the SpdySessionPool. This should only be called // by SpdySession, because otherwise session->state_ is not set to CLOSED. @@ -134,31 +132,36 @@ class NET_EXPORT SpdySessionPool private: friend class SpdySessionPoolPeer; // For testing. - typedef std::list<scoped_refptr<SpdySession> > SpdySessionList; - typedef std::map<SpdySessionKey, SpdySessionList*> SpdySessionsMap; + typedef std::map<SpdySessionKey, scoped_refptr<SpdySession> > SpdySessionsMap; typedef std::map<IPEndPoint, SpdySessionKey> SpdyAliasMap; - - scoped_refptr<SpdySession> GetInternal( - const SpdySessionKey& spdy_session_key, - const BoundNetLog& net_log, - bool only_use_existing_sessions); - scoped_refptr<SpdySession> GetExistingSession( - SpdySessionList* list, - const BoundNetLog& net_log) const; + // Looks up any aliases for the given key, which must not already + // have a session, and returns the session for first matching one, + // or NULL if there is none. If a matching session is found, it is + // then inserted into |sessions_|. scoped_refptr<SpdySession> GetFromAlias( const SpdySessionKey& spdy_session_key, const BoundNetLog& net_log, - bool record_histograms) const; + bool record_histograms); - // Helper functions for manipulating the lists. + // Returns a normalized version of the given key suitable for lookup + // into |sessions_|. const SpdySessionKey& NormalizeListKey( const SpdySessionKey& spdy_session_key) const; - SpdySessionList* AddSessionList( + + // Add the given key/session mapping. There must not already be a + // session for the given key. + void AddSession(const SpdySessionKey& spdy_session_key, + const scoped_refptr<SpdySession>& spdy_session); + + // Returns an iterator into |sessions_| for the given key, which may + // be equal to |sessions_.end()|. + SpdySessionsMap::iterator FindSessionByKey( const SpdySessionKey& spdy_session_key); - SpdySessionList* GetSessionList( - const SpdySessionKey& spdy_session_key) const; - void RemoveSessionList(const SpdySessionKey& spdy_session_key); + + // Remove the session associated with |spdy_session_key|, which must + // exist. + void RemoveSession(const SpdySessionKey& spdy_session_key); // Does a DNS cache lookup for |spdy_session_key|, and returns // the |addresses| found. @@ -167,22 +170,18 @@ class NET_EXPORT SpdySessionPool const BoundNetLog& net_log, AddressList* addresses) const; - // Add |address| as an IP-equivalent address for |spdy_session_key|. - void AddAlias(const IPEndPoint& address, - const SpdySessionKey& spdy_session_key); - // Remove all aliases for |spdy_session_key| from the aliases table. void RemoveAliases(const SpdySessionKey& spdy_session_key); - // Removes |session| from the session list associated with |spdy_session_key|. - // Returns true if the session was removed, false otherwise. - bool RemoveFromSessionList(const scoped_refptr<SpdySession>& session, - const SpdySessionKey& spdy_session_key); - HttpServerProperties* const http_server_properties_; - // This is our weak session pool - one session per domain. + // This is a map of session keys to sessions. A session may appear + // more than once in this map if it has aliases. + // + // TODO(akalin): Have a map which owns the sessions and another one + // for the aliased session cache. SpdySessionsMap sessions_; + // A map of IPEndPoint aliases for sessions. SpdyAliasMap aliases_; @@ -194,7 +193,6 @@ class NET_EXPORT SpdySessionPool // Defaults to true. May be controlled via SpdySessionPoolPeer for tests. bool verify_domain_authentication_; bool enable_sending_initial_settings_; - size_t max_sessions_per_domain_; bool force_single_domain_; bool enable_ip_pooling_; bool enable_credential_frames_; diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc new file mode 100644 index 0000000..7d99ea3 --- /dev/null +++ b/net/spdy/spdy_session_pool_unittest.cc @@ -0,0 +1,497 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/spdy/spdy_session_pool.h" + +#include <cstddef> +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/dns/host_cache.h" +#include "net/http/http_network_session.h" +#include "net/socket/client_socket_handle.h" +#include "net/socket/transport_client_socket_pool.h" +#include "net/spdy/spdy_session.h" +#include "net/spdy/spdy_test_util_common.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +class SpdySessionPoolTest : public ::testing::Test, + public ::testing::WithParamInterface<NextProto> { + protected: + // Used by RunIPPoolingTest(). + enum SpdyPoolCloseSessionsType { + SPDY_POOL_CLOSE_SESSIONS_MANUALLY, + SPDY_POOL_CLOSE_CURRENT_SESSIONS, + SPDY_POOL_CLOSE_IDLE_SESSIONS, + }; + + SpdySessionPoolTest() + : session_deps_(GetParam()), + spdy_session_pool_(NULL) {} + + void CreateNetworkSession() { + http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); + spdy_session_pool_ = http_session_->spdy_session_pool(); + } + + void RunIPPoolingTest(SpdyPoolCloseSessionsType close_sessions_type); + + SpdySessionDependencies session_deps_; + scoped_refptr<HttpNetworkSession> http_session_; + SpdySessionPool* spdy_session_pool_; +}; + +INSTANTIATE_TEST_CASE_P( + NextProto, + SpdySessionPoolTest, + testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2)); + +// A delegate that opens a new session when it is closed. +class SessionOpeningDelegate : public SpdyStream::Delegate { + public: + SessionOpeningDelegate(SpdySessionPool* spdy_session_pool, + const SpdySessionKey& key) + : spdy_session_pool_(spdy_session_pool), + key_(key) {} + + virtual ~SessionOpeningDelegate() {} + + virtual void OnRequestHeadersSent() OVERRIDE {} + + virtual SpdyResponseHeadersStatus OnResponseHeadersUpdated( + const SpdyHeaderBlock& response_headers) OVERRIDE { + return RESPONSE_HEADERS_ARE_COMPLETE; + } + + virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) OVERRIDE {} + + virtual void OnDataSent() OVERRIDE {} + + virtual void OnClose(int status) OVERRIDE { + ignore_result(CreateFakeSpdySession(spdy_session_pool_, key_)); + } + + private: + SpdySessionPool* const spdy_session_pool_; + const SpdySessionKey key_; +}; + +// Set up a SpdyStream to create a new session when it is closed. +// CloseCurrentSessions should not close the newly-created session. +TEST_P(SpdySessionPoolTest, CloseCurrentSessions) { + const char kTestHost[] = "www.foo.com"; + const int kTestPort = 80; + + session_deps_.host_resolver->set_synchronous_mode(true); + + HostPortPair test_host_port_pair(kTestHost, kTestPort); + SpdySessionKey test_key = + SpdySessionKey( + test_host_port_pair, ProxyServer::Direct(), + kPrivacyModeDisabled); + + MockConnect connect_data(SYNCHRONOUS, OK); + MockRead reads[] = { + MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. + }; + + StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); + data.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + CreateNetworkSession(); + + // Setup the first session to the first host. + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, test_key, BoundNetLog()); + + // Flush the SpdySession::OnReadComplete() task. + base::MessageLoop::current()->RunUntilIdle(); + + // Verify that we have sessions for everything. + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key)); + + // Set the stream to create a new session when it is closed. + base::WeakPtr<SpdyStream> spdy_stream = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session, GURL("http://www.foo.com"), + MEDIUM, BoundNetLog()); + SessionOpeningDelegate delegate(spdy_session_pool_, test_key); + spdy_stream->SetDelegate(&delegate); + + // Close the current session. + spdy_session_pool_->CloseCurrentSessions(net::ERR_ABORTED); + + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key)); +} + +TEST_P(SpdySessionPoolTest, CloseCurrentIdleSessions) { + MockConnect connect_data(SYNCHRONOUS, OK); + MockRead reads[] = { + MockRead(ASYNC, 0, 0) // EOF + }; + + session_deps_.host_resolver->set_synchronous_mode(true); + + StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); + data.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + CreateNetworkSession(); + + // Set up session 1 + const std::string kTestHost1("http://www.a.com"); + HostPortPair test_host_port_pair1(kTestHost1, 80); + SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(), + kPrivacyModeDisabled); + scoped_refptr<SpdySession> session1 = + CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); + GURL url1(kTestHost1); + base::WeakPtr<SpdyStream> spdy_stream1 = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session1, url1, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream1.get() != NULL); + + // Set up session 2 + session_deps_.socket_factory->AddSocketDataProvider(&data); + const std::string kTestHost2("http://www.b.com"); + HostPortPair test_host_port_pair2(kTestHost2, 80); + SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(), + kPrivacyModeDisabled); + scoped_refptr<SpdySession> session2 = + CreateInsecureSpdySession(http_session_, key2, BoundNetLog()); + GURL url2(kTestHost2); + base::WeakPtr<SpdyStream> spdy_stream2 = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session2, url2, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream2.get() != NULL); + + // Set up session 3 + session_deps_.socket_factory->AddSocketDataProvider(&data); + const std::string kTestHost3("http://www.c.com"); + HostPortPair test_host_port_pair3(kTestHost3, 80); + SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(), + kPrivacyModeDisabled); + scoped_refptr<SpdySession> session3 = + CreateInsecureSpdySession(http_session_, key3, BoundNetLog()); + GURL url3(kTestHost3); + base::WeakPtr<SpdyStream> spdy_stream3 = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session3, url3, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream3.get() != NULL); + + // 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_->CloseCurrentIdleSessions(); + 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->CloseCreatedStream(spdy_stream1, OK); + EXPECT_EQ(NULL, spdy_stream1.get()); + session3->CloseCreatedStream(spdy_stream3, OK); + EXPECT_EQ(NULL, spdy_stream3.get()); + 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_->CloseCurrentIdleSessions(); + 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_->CloseCurrentIdleSessions(); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + + // Make 2 not active + session2->CloseCreatedStream(spdy_stream2, OK); + EXPECT_EQ(NULL, spdy_stream2.get()); + EXPECT_FALSE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + + // This should close session 2 + spdy_session_pool_->CloseCurrentIdleSessions(); + EXPECT_FALSE(session2->is_active()); + EXPECT_TRUE(session2->IsClosed()); +} + +// Set up a SpdyStream to create a new session when it is closed. +// CloseAllSessions should close the newly-created session. +TEST_P(SpdySessionPoolTest, CloseAllSessions) { + const char kTestHost[] = "www.foo.com"; + const int kTestPort = 80; + + session_deps_.host_resolver->set_synchronous_mode(true); + + HostPortPair test_host_port_pair(kTestHost, kTestPort); + SpdySessionKey test_key = + SpdySessionKey( + test_host_port_pair, ProxyServer::Direct(), + kPrivacyModeDisabled); + + MockConnect connect_data(SYNCHRONOUS, OK); + MockRead reads[] = { + MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. + }; + + StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); + data.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + CreateNetworkSession(); + + // Setup the first session to the first host. + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, test_key, BoundNetLog()); + + // Flush the SpdySession::OnReadComplete() task. + base::MessageLoop::current()->RunUntilIdle(); + + // Verify that we have sessions for everything. + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key)); + + // Set the stream to create a new session when it is closed. + base::WeakPtr<SpdyStream> spdy_stream = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session, GURL("http://www.foo.com"), + MEDIUM, BoundNetLog()); + SessionOpeningDelegate delegate(spdy_session_pool_, test_key); + spdy_stream->SetDelegate(&delegate); + + // Close the current session. + spdy_session_pool_->CloseAllSessions(); + + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_key)); +} + +// This test has three variants, one for each style of closing the connection. +// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY, +// the sessions are closed manually, calling SpdySessionPool::Remove() directly. +// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS, +// sessions are closed with SpdySessionPool::CloseCurrentSessions(). +// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS, +// sessions are closed with SpdySessionPool::CloseIdleSessions(). +void SpdySessionPoolTest::RunIPPoolingTest( + SpdyPoolCloseSessionsType close_sessions_type) { + const int kTestPort = 80; + struct TestHosts { + std::string url; + std::string name; + std::string iplist; + SpdySessionKey key; + AddressList addresses; + } test_hosts[] = { + { "http:://www.foo.com", + "www.foo.com", + "192.0.2.33,192.168.0.1,192.168.0.5" + }, + { "http://js.foo.com", + "js.foo.com", + "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33" + }, + { "http://images.foo.com", + "images.foo.com", + "192.168.0.4,192.168.0.3" + }, + }; + + session_deps_.host_resolver->set_synchronous_mode(true); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { + session_deps_.host_resolver->rules()->AddIPLiteralRule( + test_hosts[i].name, test_hosts[i].iplist, std::string()); + + // This test requires that the HostResolver cache be populated. Normal + // code would have done this already, but we do it manually. + HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); + session_deps_.host_resolver->Resolve( + info, &test_hosts[i].addresses, CompletionCallback(), NULL, + BoundNetLog()); + + // Setup a SpdySessionKey + test_hosts[i].key = SpdySessionKey( + HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), + kPrivacyModeDisabled); + } + + MockConnect connect_data(SYNCHRONOUS, OK); + MockRead reads[] = { + MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. + }; + + StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); + data.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + SSLSocketDataProvider ssl(SYNCHRONOUS, OK); + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + CreateNetworkSession(); + + // Setup the first session to the first host. + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession( + http_session_, test_hosts[0].key, BoundNetLog()); + + // Flush the SpdySession::OnReadComplete() task. + base::MessageLoop::current()->RunUntilIdle(); + + // The third host has no overlap with the first, so it can't pool IPs. + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key)); + + // The second host overlaps with the first, and should IP pool. + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key)); + + // Verify that the second host, through a proxy, won't share the IP. + SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(), + ProxyServer::FromPacString("HTTP http://proxy.foo.com/"), + kPrivacyModeDisabled); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, proxy_key)); + + // Overlap between 2 and 3 does is not transitive to 1. + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key)); + + // Create a new session to host 2. + session_deps_.socket_factory->AddSocketDataProvider(&data); + scoped_refptr<SpdySession> session2 = + CreateInsecureSpdySession( + http_session_, test_hosts[2].key, BoundNetLog()); + + // Verify that we have sessions for everything. + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[0].key)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[2].key)); + + // Grab the session to host 1 and verify that it is the same session + // we got with host 0, and that is a different from host 2's session. + scoped_refptr<SpdySession> session1 = + spdy_session_pool_->GetIfExists(test_hosts[1].key, BoundNetLog()); + EXPECT_EQ(session.get(), session1.get()); + EXPECT_NE(session2.get(), session1.get()); + + // Remove the aliases and observe that we still have a session for host1. + SpdySessionPoolPeer pool_peer(spdy_session_pool_); + pool_peer.RemoveAliases(test_hosts[0].key); + pool_peer.RemoveAliases(test_hosts[1].key); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key)); + + // Expire the host cache + session_deps_.host_resolver->GetHostCache()->clear(); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_hosts[1].key)); + + // Cleanup the sessions. + switch (close_sessions_type) { + case SPDY_POOL_CLOSE_SESSIONS_MANUALLY: + spdy_session_pool_->Remove(session); + session = NULL; + spdy_session_pool_->Remove(session2); + session2 = NULL; + break; + case SPDY_POOL_CLOSE_CURRENT_SESSIONS: + spdy_session_pool_->CloseCurrentSessions(net::ERR_ABORTED); + break; + case SPDY_POOL_CLOSE_IDLE_SESSIONS: + GURL url(test_hosts[0].url); + base::WeakPtr<SpdyStream> spdy_stream = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session, url, MEDIUM, BoundNetLog()); + GURL url1(test_hosts[1].url); + base::WeakPtr<SpdyStream> spdy_stream1 = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session1, url1, MEDIUM, BoundNetLog()); + GURL url2(test_hosts[2].url); + base::WeakPtr<SpdyStream> spdy_stream2 = + CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, + session2, url2, MEDIUM, BoundNetLog()); + + // Close streams to make spdy_session and spdy_session1 inactive. + session->CloseCreatedStream(spdy_stream, OK); + EXPECT_EQ(NULL, spdy_stream.get()); + session1->CloseCreatedStream(spdy_stream1, OK); + EXPECT_EQ(NULL, spdy_stream1.get()); + + // Check spdy_session and spdy_session1 are not closed. + EXPECT_FALSE(session->is_active()); + EXPECT_FALSE(session->IsClosed()); + EXPECT_FALSE(session1->is_active()); + EXPECT_FALSE(session1->IsClosed()); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + + // Test that calling CloseIdleSessions, does not cause a crash. + // http://crbug.com/181400 + spdy_session_pool_->CloseCurrentIdleSessions(); + + // Verify spdy_session and spdy_session1 are closed. + EXPECT_FALSE(session->is_active()); + EXPECT_TRUE(session->IsClosed()); + EXPECT_FALSE(session1->is_active()); + EXPECT_TRUE(session1->IsClosed()); + EXPECT_TRUE(session2->is_active()); + EXPECT_FALSE(session2->IsClosed()); + + spdy_stream2->Cancel(); + EXPECT_EQ(NULL, spdy_stream.get()); + EXPECT_EQ(NULL, spdy_stream1.get()); + EXPECT_EQ(NULL, spdy_stream2.get()); + spdy_session_pool_->Remove(session2); + session2 = NULL; + break; + } + + // Verify that the map is all cleaned up. + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[0].key)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[1].key)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key)); +} + +TEST_P(SpdySessionPoolTest, IPPooling) { + RunIPPoolingTest(SPDY_POOL_CLOSE_SESSIONS_MANUALLY); +} + +TEST_P(SpdySessionPoolTest, IPPoolingCloseCurrentSessions) { + RunIPPoolingTest(SPDY_POOL_CLOSE_CURRENT_SESSIONS); +} + +TEST_P(SpdySessionPoolTest, IPPoolingCloseIdleSessions) { + RunIPPoolingTest(SPDY_POOL_CLOSE_IDLE_SESSIONS); +} + +} // namespace + +} // namespace net diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index cce77ef..dae5837 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -14,7 +14,6 @@ #include "net/base/request_priority.h" #include "net/base/test_data_directory.h" #include "net/base/test_data_stream.h" -#include "net/dns/host_cache.h" #include "net/socket/client_socket_pool_manager.h" #include "net/socket/next_proto.h" #include "net/socket/socket_test_util.h" @@ -136,40 +135,6 @@ class SpdySessionTest : public PlatformTest, spdy_session_pool_ = http_session_->spdy_session_pool(); } - scoped_refptr<SpdySession> GetSession(const SpdySessionKey& key) { - EXPECT_FALSE(spdy_session_pool_->HasSession(key)); - scoped_refptr<SpdySession> session = - spdy_session_pool_->Get(key, BoundNetLog()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key)); - return session; - } - - // Creates an initialized session to |key_|. - scoped_refptr<SpdySession> CreateInitializedSession() { - scoped_refptr<SpdySession> session = GetSession(key_); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_)); - return session; - } - - net::Error InitializeSession(HttpNetworkSession* http_session, - SpdySession* session, - const HostPortPair& host_port_pair) { - transport_params_ = new TransportSocketParams( - host_port_pair, MEDIUM, false, false, OnHostResolutionCallback()); - - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(host_port_pair.ToString(), - transport_params_, MEDIUM, - CompletionCallback(), - http_session->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - return session->InitializeWithSocket(connection.release(), false, OK); - } - void StallSessionSend(SpdySession* session) { // Reduce the send window size to 0 to stall. while (session->session_send_window_size_ > 0) { @@ -195,7 +160,7 @@ class SpdySessionTest : public PlatformTest, } void RunResumeAfterUnstallTest( - const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, + const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function, const base::Callback<void(SpdySession*, SpdyStream*, int32)>& unstall_function); @@ -205,7 +170,6 @@ class SpdySessionTest : public PlatformTest, int old_max_pool_sockets_; SpdyTestUtil spdy_util_; - scoped_refptr<TransportSocketParams> transport_params_; SpdySessionDependencies session_deps_; scoped_refptr<HttpNetworkSession> http_session_; SpdySessionPool* spdy_session_pool_; @@ -246,7 +210,8 @@ TEST_P(SpdySessionTest, GoAway) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); EXPECT_EQ(spdy_util_.spdy_version(), session->GetProtocolVersion()); @@ -277,17 +242,18 @@ TEST_P(SpdySessionTest, GoAway) { EXPECT_EQ(1u, spdy_stream1->stream_id()); EXPECT_EQ(3u, spdy_stream2->stream_id()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); // Read and process the GOAWAY frame. data.RunFor(1); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); EXPECT_TRUE(session->IsStreamActive(1)); EXPECT_FALSE(session->IsStreamActive(3)); - scoped_refptr<SpdySession> session2 = GetSession(key_); + scoped_refptr<SpdySession> session2 = + CreateFakeSpdySession(spdy_session_pool_, key_); spdy_stream1->Close(); EXPECT_EQ(NULL, spdy_stream1.get()); @@ -325,7 +291,8 @@ TEST_P(SpdySessionTest, ClientPing) { CreateNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, @@ -351,7 +318,7 @@ TEST_P(SpdySessionTest, ClientPing) { EXPECT_FALSE(session->check_ping_status_pending()); EXPECT_GE(session->last_activity_time(), before_ping_time); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); // Delete the first session. session = NULL; @@ -380,7 +347,8 @@ TEST_P(SpdySessionTest, ServerPing) { CreateNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, @@ -392,7 +360,7 @@ TEST_P(SpdySessionTest, ServerPing) { // Flush the SpdySession::OnReadComplete() task. base::MessageLoop::current()->RunUntilIdle(); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); // Delete the session. session = NULL; @@ -408,7 +376,8 @@ TEST_P(SpdySessionTest, DeleteExpiredPushStreams) { CreateNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); + scoped_refptr<SpdySession> session = + CreateFakeSpdySession(spdy_session_pool_, key_); session->buffered_spdy_framer_.reset( new BufferedSpdyFramer(spdy_util_.spdy_version(), false)); @@ -478,7 +447,8 @@ TEST_P(SpdySessionTest, FailedPing) { CreateNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, @@ -499,7 +469,7 @@ TEST_P(SpdySessionTest, FailedPing) { // Assert session is not closed. EXPECT_FALSE(session->IsClosed()); EXPECT_LT(0u, session->num_active_streams() + session->num_created_streams()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); // We set last time we have received any data in 1 sec less than now. // CheckPingStatus will trigger timeout because hung interval is zero. @@ -510,131 +480,13 @@ TEST_P(SpdySessionTest, FailedPing) { EXPECT_TRUE(session->IsClosed()); EXPECT_EQ(0u, session->num_active_streams()); EXPECT_EQ(0u, session->num_unclaimed_pushed_streams()); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); // Delete the first session. session = NULL; EXPECT_EQ(NULL, spdy_stream1.get()); } -TEST_P(SpdySessionTest, CloseIdleSessions) { - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(ASYNC, 0, 0) // EOF - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - CreateNetworkSession(); - - // Set up session 1 - const std::string kTestHost1("http://www.a.com"); - HostPortPair test_host_port_pair1(kTestHost1, 80); - SpdySessionKey key1(test_host_port_pair1, ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session1.get(), test_host_port_pair1)); - GURL url1(kTestHost1); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session1, url1, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream1.get() != NULL); - - // Set up session 2 - session_deps_.socket_factory->AddSocketDataProvider(&data); - const std::string kTestHost2("http://www.b.com"); - HostPortPair test_host_port_pair2(kTestHost2, 80); - SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session2 = GetSession(key2); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session2.get(), test_host_port_pair2)); - GURL url2(kTestHost2); - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session2, url2, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream2.get() != NULL); - - // Set up session 3 - session_deps_.socket_factory->AddSocketDataProvider(&data); - const std::string kTestHost3("http://www.c.com"); - HostPortPair test_host_port_pair3(kTestHost3, 80); - SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(), - kPrivacyModeDisabled); - scoped_refptr<SpdySession> session3 = GetSession(key3); - EXPECT_EQ( - OK, - InitializeSession( - http_session_.get(), session3.get(), test_host_port_pair3)); - GURL url3(kTestHost3); - base::WeakPtr<SpdyStream> spdy_stream3 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session3, url3, MEDIUM, BoundNetLog()); - ASSERT_TRUE(spdy_stream3.get() != NULL); - - // 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->CloseCreatedStream(spdy_stream1, OK); - EXPECT_EQ(NULL, spdy_stream1.get()); - session3->CloseCreatedStream(spdy_stream3, OK); - EXPECT_EQ(NULL, spdy_stream3.get()); - 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->CloseCreatedStream(spdy_stream2, OK); - EXPECT_EQ(NULL, spdy_stream2.get()); - 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. @@ -675,7 +527,8 @@ TEST_P(SpdySessionTest, OnSettings) { SETTINGS_FLAG_PLEASE_PERSIST, 1); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); // Create 2 streams. First will succeed. Second will be pending. base::WeakPtr<SpdyStream> spdy_stream1 = @@ -738,7 +591,8 @@ TEST_P(SpdySessionTest, ClearSettings) { EXPECT_EQ(1u, spdy_session_pool_->http_server_properties()->GetSpdySettings( test_host_port_pair_).size()); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); // Create 2 streams. First will succeed. Second will be pending. base::WeakPtr<SpdyStream> spdy_stream1 = @@ -796,7 +650,8 @@ TEST_P(SpdySessionTest, CancelPendingCreateStream) { SETTINGS_FLAG_PLEASE_PERSIST, 1); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); // Create 2 streams. First will succeed. Second will be pending. base::WeakPtr<SpdyStream> spdy_stream1 = @@ -873,7 +728,8 @@ TEST_P(SpdySessionTest, SendInitialSettingsOnNewSession) { SpdySessionPoolPeer pool_peer(spdy_session_pool_); pool_peer.EnableSendingInitialSettings(true); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); base::MessageLoop::current()->RunUntilIdle(); EXPECT_TRUE(data.at_write_eof()); @@ -918,262 +774,11 @@ TEST_P(SpdySessionTest, SendSettingsOnNewSession) { SETTINGS_FLAG_PLEASE_PERSIST, kBogusSettingValue); - scoped_refptr<SpdySession> session = CreateInitializedSession(); - - base::MessageLoop::current()->RunUntilIdle(); - EXPECT_TRUE(data.at_write_eof()); -} - -namespace { - -// Specifies the style for closing the connection. -enum SpdyPoolCloseSessionsType { - SPDY_POOL_CLOSE_SESSIONS_MANUALLY, - SPDY_POOL_CLOSE_CURRENT_SESSIONS, - SPDY_POOL_CLOSE_IDLE_SESSIONS, -}; - -// Initialize the SpdySession with socket. -void IPPoolingInitializedSession( - const std::string& group_name, - const scoped_refptr<TransportSocketParams>& transport_params, - HttpNetworkSession* http_session, - SpdySession* session) { - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(group_name, - transport_params, MEDIUM, CompletionCallback(), - http_session->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); -} - -// This test has three variants, one for each style of closing the connection. -// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_SESSIONS_MANUALLY, -// the sessions are closed manually, calling SpdySessionPool::Remove() directly. -// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_CURRENT_SESSIONS, -// sessions are closed with SpdySessionPool::CloseCurrentSessions(). -// If |clean_via_close_current_sessions| is SPDY_POOL_CLOSE_IDLE_SESSIONS, -// sessions are closed with SpdySessionPool::CloseIdleSessions(). -void IPPoolingTest(NextProto next_proto, - SpdyPoolCloseSessionsType close_sessions_type) { - const int kTestPort = 80; - struct TestHosts { - std::string url; - std::string name; - std::string iplist; - SpdySessionKey key; - AddressList addresses; - } test_hosts[] = { - { "http:://www.foo.com", - "www.foo.com", - "192.0.2.33,192.168.0.1,192.168.0.5" - }, - { "http://js.foo.com", - "js.foo.com", - "192.168.0.2,192.168.0.3,192.168.0.5,192.0.2.33" - }, - { "http://images.foo.com", - "images.foo.com", - "192.168.0.4,192.168.0.3" - }, - }; - - SpdySessionDependencies session_deps(next_proto); - session_deps.host_resolver->set_synchronous_mode(true); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_hosts); i++) { - session_deps.host_resolver->rules()->AddIPLiteralRule( - test_hosts[i].name, test_hosts[i].iplist, std::string()); - - // This test requires that the HostResolver cache be populated. Normal - // code would have done this already, but we do it manually. - HostResolver::RequestInfo info(HostPortPair(test_hosts[i].name, kTestPort)); - session_deps.host_resolver->Resolve( - info, &test_hosts[i].addresses, CompletionCallback(), NULL, - BoundNetLog()); - - // Setup a SpdySessionKey - test_hosts[i].key = SpdySessionKey( - HostPortPair(test_hosts[i].name, kTestPort), ProxyServer::Direct(), - kPrivacyModeDisabled); - } - - MockConnect connect_data(SYNCHRONOUS, OK); - MockRead reads[] = { - MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. - }; - - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(SYNCHRONOUS, OK); - session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); - - scoped_refptr<HttpNetworkSession> http_session( - SpdySessionDependencies::SpdyCreateSession(&session_deps)); - - // Setup the first session to the first host. - SpdySessionPool* spdy_session_pool(http_session->spdy_session_pool()); - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[0].key)); scoped_refptr<SpdySession> session = - spdy_session_pool->Get(test_hosts[0].key, BoundNetLog()); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[0].key)); - - HostPortPair test_host_port_pair(test_hosts[0].name, kTestPort); - - // Initialize session for the first host. - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(test_host_port_pair, - MEDIUM, - false, - false, - OnHostResolutionCallback())); - IPPoolingInitializedSession(test_host_port_pair.ToString(), - transport_params, - http_session.get(), - session.get()); - - // TODO(rtenneti): MockClientSocket::GetPeerAddress return's 0 as the port - // number. Fix it to return port 80 and then use GetPeerAddress to AddAlias. - SpdySessionPoolPeer pool_peer(spdy_session_pool); - pool_peer.AddAlias(test_hosts[0].addresses.front(), test_hosts[0].key); + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); - // Flush the SpdySession::OnReadComplete() task. base::MessageLoop::current()->RunUntilIdle(); - - // The third host has no overlap with the first, so it can't pool IPs. - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); - - // The second host overlaps with the first, and should IP pool. - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - - // Verify that the second host, through a proxy, won't share the IP. - SpdySessionKey proxy_key(test_hosts[1].key.host_port_pair(), - ProxyServer::FromPacString("HTTP http://proxy.foo.com/"), - kPrivacyModeDisabled); - EXPECT_FALSE(spdy_session_pool->HasSession(proxy_key)); - - // Overlap between 2 and 3 does is not transitive to 1. - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); - - // Create a new session to host 2. - scoped_refptr<SpdySession> session2 = - spdy_session_pool->Get(test_hosts[2].key, BoundNetLog()); - - // Verify that we have sessions for everything. - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[0].key)); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[2].key)); - - // Initialize session for host 2. - session_deps.socket_factory->AddSocketDataProvider(&data); - IPPoolingInitializedSession(test_hosts[2].key.host_port_pair().ToString(), - transport_params, - http_session.get(), - session2.get()); - - // Grab the session to host 1 and verify that it is the same session - // we got with host 0, and that is a different than host 2's session. - scoped_refptr<SpdySession> session1 = - spdy_session_pool->Get(test_hosts[1].key, BoundNetLog()); - EXPECT_EQ(session.get(), session1.get()); - EXPECT_NE(session2.get(), session1.get()); - - // Initialize session for host 1. - session_deps.socket_factory->AddSocketDataProvider(&data); - IPPoolingInitializedSession(test_hosts[2].key.host_port_pair().ToString(), - transport_params, - http_session.get(), - session2.get()); - - // Remove the aliases and observe that we still have a session for host1. - pool_peer.RemoveAliases(test_hosts[0].key); - pool_peer.RemoveAliases(test_hosts[1].key); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - - // Expire the host cache - session_deps.host_resolver->GetHostCache()->clear(); - EXPECT_TRUE(spdy_session_pool->HasSession(test_hosts[1].key)); - - // Cleanup the sessions. - switch (close_sessions_type) { - case SPDY_POOL_CLOSE_SESSIONS_MANUALLY: - spdy_session_pool->Remove(session); - session = NULL; - spdy_session_pool->Remove(session2); - session2 = NULL; - break; - case SPDY_POOL_CLOSE_CURRENT_SESSIONS: - spdy_session_pool->CloseCurrentSessions(net::ERR_ABORTED); - break; - case SPDY_POOL_CLOSE_IDLE_SESSIONS: - GURL url(test_hosts[0].url); - base::WeakPtr<SpdyStream> spdy_stream = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session, url, MEDIUM, BoundNetLog()); - GURL url1(test_hosts[1].url); - base::WeakPtr<SpdyStream> spdy_stream1 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session1, url1, MEDIUM, BoundNetLog()); - GURL url2(test_hosts[2].url); - base::WeakPtr<SpdyStream> spdy_stream2 = - CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, - session2, url2, MEDIUM, BoundNetLog()); - - // Close streams to make spdy_session and spdy_session1 inactive. - session->CloseCreatedStream(spdy_stream, OK); - EXPECT_EQ(NULL, spdy_stream.get()); - session1->CloseCreatedStream(spdy_stream1, OK); - EXPECT_EQ(NULL, spdy_stream1.get()); - - // Check spdy_session and spdy_session1 are not closed. - EXPECT_FALSE(session->is_active()); - EXPECT_FALSE(session->IsClosed()); - EXPECT_FALSE(session1->is_active()); - EXPECT_FALSE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - - // Test that calling CloseIdleSessions, does not cause a crash. - // http://crbug.com/181400 - spdy_session_pool->CloseIdleSessions(); - - // Verify spdy_session and spdy_session1 are closed. - EXPECT_FALSE(session->is_active()); - EXPECT_TRUE(session->IsClosed()); - EXPECT_FALSE(session1->is_active()); - EXPECT_TRUE(session1->IsClosed()); - EXPECT_TRUE(session2->is_active()); - EXPECT_FALSE(session2->IsClosed()); - - spdy_stream2->Cancel(); - EXPECT_EQ(NULL, spdy_stream.get()); - EXPECT_EQ(NULL, spdy_stream1.get()); - EXPECT_EQ(NULL, spdy_stream2.get()); - spdy_session_pool->Remove(session2); - session2 = NULL; - break; - } - - // Verify that the map is all cleaned up. - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[0].key)); - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[1].key)); - EXPECT_FALSE(spdy_session_pool->HasSession(test_hosts[2].key)); -} - -} // namespace - -TEST_P(SpdySessionTest, IPPooling) { - IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_SESSIONS_MANUALLY); -} - -TEST_P(SpdySessionTest, IPPoolingCloseCurrentSessions) { - IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_CURRENT_SESSIONS); -} - -TEST_P(SpdySessionTest, IPPoolingCloseIdleSessions) { - IPPoolingTest(GetParam(), SPDY_POOL_CLOSE_IDLE_SESSIONS); + EXPECT_TRUE(data.at_write_eof()); } TEST_P(SpdySessionTest, ClearSettingsStorageOnIPAddressChanged) { @@ -1214,12 +819,8 @@ TEST_P(SpdySessionTest, Initialize) { CreateNetworkSession(); scoped_refptr<SpdySession> session = - spdy_session_pool_->Get(key_, log.bound()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); - - EXPECT_EQ(OK, - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_)); + CreateInsecureSpdySession(http_session_, key_, log.bound()); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); // Flush the SpdySession::OnReadComplete() task. base::MessageLoop::current()->RunUntilIdle(); @@ -1241,6 +842,8 @@ TEST_P(SpdySessionTest, Initialize) { &socket_source)); EXPECT_TRUE(socket_source.IsValid()); EXPECT_NE(log.bound().source().id, socket_source.id); + + session->CloseSessionOnError(ERR_ABORTED, std::string()); } TEST_P(SpdySessionTest, CloseSessionOnError) { @@ -1264,17 +867,13 @@ TEST_P(SpdySessionTest, CloseSessionOnError) { CapturingBoundNetLog log; scoped_refptr<SpdySession> session = - spdy_session_pool_->Get(key_, log.bound()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); - - EXPECT_EQ(OK, - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_)); + CreateInsecureSpdySession(http_session_, key_, log.bound()); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); // Flush the SpdySession::OnReadComplete() task. base::MessageLoop::current()->RunUntilIdle(); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); // Check that the NetLog was filled reasonably. net::CapturingNetLog::CapturedEntryList entries; @@ -1336,7 +935,8 @@ TEST_P(SpdySessionTest, OutOfOrderSynStreams) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url("http://www.google.com"); @@ -1408,7 +1008,8 @@ TEST_P(SpdySessionTest, CancelStream) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -1480,7 +1081,8 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -1517,7 +1119,7 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedSelfClosingStreams) { EXPECT_EQ(0u, spdy_stream2->stream_id()); // Ensure we don't crash while closing the session. - session->CloseSessionOnError(ERR_ABORTED, true, std::string()); + session->CloseSessionOnError(ERR_ABORTED, std::string()); EXPECT_EQ(NULL, spdy_stream1.get()); EXPECT_EQ(NULL, spdy_stream2.get()); @@ -1553,7 +1155,8 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -1592,7 +1195,7 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoCreatedMutuallyClosingStreams) { EXPECT_EQ(0u, spdy_stream2->stream_id()); // Ensure we don't crash while closing the session. - session->CloseSessionOnError(ERR_ABORTED, true, std::string()); + session->CloseSessionOnError(ERR_ABORTED, std::string()); EXPECT_EQ(NULL, spdy_stream1.get()); EXPECT_EQ(NULL, spdy_stream2.get()); @@ -1633,7 +1236,8 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -1675,7 +1279,7 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) { EXPECT_EQ(3u, spdy_stream2->stream_id()); // Ensure we don't crash while closing the session. - session->CloseSessionOnError(ERR_ABORTED, true, std::string()); + session->CloseSessionOnError(ERR_ABORTED, std::string()); EXPECT_EQ(NULL, spdy_stream1.get()); EXPECT_EQ(NULL, spdy_stream2.get()); @@ -1716,7 +1320,8 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -1760,7 +1365,7 @@ TEST_P(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) { EXPECT_EQ(3u, spdy_stream2->stream_id()); // Ensure we don't crash while closing the session. - session->CloseSessionOnError(ERR_ABORTED, true, std::string()); + session->CloseSessionOnError(ERR_ABORTED, std::string()); EXPECT_EQ(NULL, spdy_stream1.get()); EXPECT_EQ(NULL, spdy_stream2.get()); @@ -1804,7 +1409,8 @@ TEST_P(SpdySessionTest, VerifyDomainAuthentication) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); + scoped_refptr<SpdySession> session = + CreateFakeSpdySession(spdy_session_pool_, key_); SSLConfig ssl_config; scoped_refptr<TransportSocketParams> transport_params( @@ -1832,7 +1438,7 @@ TEST_P(SpdySessionTest, VerifyDomainAuthentication) { HttpNetworkSession::NORMAL_SOCKET_POOL), BoundNetLog())); - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); + EXPECT_EQ(OK, session->InitializeWithSocket(connection.Pass(), false, OK)); EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.com")); @@ -1873,7 +1479,8 @@ TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); + scoped_refptr<SpdySession> session = + CreateFakeSpdySession(spdy_session_pool_, key_); SSLConfig ssl_config; scoped_refptr<TransportSocketParams> transport_params( @@ -1901,7 +1508,7 @@ TEST_P(SpdySessionTest, ConnectionPooledWithTlsChannelId) { HttpNetworkSession::NORMAL_SOCKET_POOL), BoundNetLog())); - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), false, OK)); + EXPECT_EQ(OK, session->InitializeWithSocket(connection.Pass(), false, OK)); EXPECT_TRUE(session->VerifyDomainAuthentication("www.example.org")); EXPECT_TRUE(session->VerifyDomainAuthentication("mail.example.org")); EXPECT_FALSE(session->VerifyDomainAuthentication("mail.example.com")); @@ -1966,7 +1573,8 @@ TEST_P(SpdySessionTest, CloseTwoStalledCreateStream) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); // Read the settings frame. data.RunFor(1); @@ -2071,7 +1679,8 @@ TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) { SETTINGS_FLAG_PLEASE_PERSIST, 1); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -2144,7 +1753,8 @@ TEST_P(SpdySessionTest, NeedsCredentials) { SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session = GetSession(key); + scoped_refptr<SpdySession> session = + CreateFakeSpdySession(spdy_session_pool_, key); SSLConfig ssl_config; scoped_refptr<TransportSocketParams> transport_params( @@ -2172,7 +1782,7 @@ TEST_P(SpdySessionTest, NeedsCredentials) { HttpNetworkSession::NORMAL_SOCKET_POOL), BoundNetLog())); - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); + EXPECT_EQ(OK, session->InitializeWithSocket(connection.Pass(), true, OK)); EXPECT_EQ(spdy_util_.spdy_version() >= SPDY3, session->NeedsCredentials()); @@ -2234,7 +1844,8 @@ TEST_P(SpdySessionTest, ReadDataWithoutYielding) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -2323,7 +1934,8 @@ TEST_P(SpdySessionTest, TestYieldingDuringReadData) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -2435,7 +2047,8 @@ TEST_P(SpdySessionTest, TestYieldingDuringAsyncReadData) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -2509,7 +2122,8 @@ TEST_P(SpdySessionTest, GoAwayWhileInDoLoop) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url1("http://www.google.com"); base::WeakPtr<SpdyStream> spdy_stream1 = @@ -2558,16 +2172,8 @@ TEST_P(SpdySessionTest, ProtocolNegotiation) { session_deps_.socket_factory->AddSocketDataProvider(&data); CreateNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - - EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state()); - EXPECT_TRUE(session->buffered_spdy_framer_ == NULL); - EXPECT_EQ(0, session->session_send_window_size_); - EXPECT_EQ(0, session->session_recv_window_size_); - EXPECT_EQ(0, session->session_unacked_recv_window_bytes_); - - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateFakeSpdySession(spdy_session_pool_, key_); EXPECT_EQ(spdy_util_.spdy_version(), session->buffered_spdy_framer_->protocol_version()); @@ -2616,11 +2222,8 @@ TEST_P(SpdySessionTest, CloseOneIdleConnection) { // Create an idle SPDY session. SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); + scoped_refptr<SpdySession> session1 = + CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); EXPECT_FALSE(pool->IsStalled()); // Release the pointer to the session so it can be closed. session1 = NULL; @@ -2680,29 +2283,22 @@ TEST_P(SpdySessionTest, CloseOneIdleConnectionWithAlias) { // Create an idle SPDY session. SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); + scoped_refptr<SpdySession> session1 = + CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); EXPECT_FALSE(pool->IsStalled()); // Set up an alias for the idle SPDY session, increasing its ref count to 2. SpdySessionKey key2(HostPortPair("2.com", 80), ProxyServer::Direct(), kPrivacyModeDisabled); - SpdySessionPoolPeer pool_peer(spdy_session_pool_); HostResolver::RequestInfo info(key2.host_port_pair()); AddressList addresses; // Pre-populate the DNS cache, since a synchronous resolution is required in // order to create the alias. session_deps_.host_resolver->Resolve( info, &addresses, CompletionCallback(), NULL, BoundNetLog()); - // Add the alias for the first session's key. Has to be done manually since - // the usual process is bypassed. - pool_peer.AddAlias(addresses.front(), key1); // Get a session for |key2|, which should return the session created earlier. scoped_refptr<SpdySession> session2 = - spdy_session_pool_->Get(key2, BoundNetLog()); + spdy_session_pool_->GetIfExists(key2, BoundNetLog()); ASSERT_EQ(session1.get(), session2.get()); EXPECT_FALSE(pool->IsStalled()); @@ -2755,11 +2351,8 @@ TEST_P(SpdySessionTest, CloseOneIdleConnectionSessionStillHeld) { // Create an idle SPDY session. SpdySessionKey key1(HostPortPair("1.com", 80), ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); + scoped_refptr<SpdySession> session1 = + CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); EXPECT_FALSE(pool->IsStalled()); // Trying to create a new connection should cause the pool to be stalled, and @@ -2823,11 +2416,8 @@ TEST_P(SpdySessionTest, CloseOneIdleConnectionFailsWhenSessionInUse) { GURL url1("http://www.google.com"); SpdySessionKey key1(HostPortPair(url1.host(), 80), ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session1 = GetSession(key1); - EXPECT_EQ( - OK, - InitializeSession(http_session_.get(), session1.get(), - key1.host_port_pair())); + scoped_refptr<SpdySession> session1 = + CreateInsecureSpdySession(http_session_, key1, BoundNetLog()); EXPECT_FALSE(pool->IsStalled()); // Create a stream using the session, and send a request. @@ -2894,30 +2484,30 @@ TEST_P(SpdySessionTest, SpdySessionKeyPrivacyMode) { SpdySessionKey key_privacy_disabled(host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled)); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); // Add SpdySession with PrivacyMode Enabled to the pool. scoped_refptr<SpdySession> session_privacy_enabled = - spdy_session_pool_->Get(key_privacy_enabled, BoundNetLog()); + CreateFakeSpdySession(spdy_session_pool_, key_privacy_enabled); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled)); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); // Add SpdySession with PrivacyMode Disabled to the pool. scoped_refptr<SpdySession> session_privacy_disabled = - spdy_session_pool_->Get(key_privacy_disabled, BoundNetLog()); + CreateFakeSpdySession(spdy_session_pool_, key_privacy_disabled); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_enabled)); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); spdy_session_pool_->Remove(session_privacy_enabled); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled)); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_privacy_disabled)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); spdy_session_pool_->Remove(session_privacy_disabled); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_enabled)); - EXPECT_FALSE(spdy_session_pool_->HasSession(key_privacy_disabled)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_enabled)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_privacy_disabled)); } // The tests below are only for SPDY/3 and above. @@ -2953,7 +2543,8 @@ TEST_P(SpdySessionTest, SendCredentials) { SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session = GetSession(key); + scoped_refptr<SpdySession> session = + CreateFakeSpdySession(spdy_session_pool_, key); SSLConfig ssl_config; scoped_refptr<TransportSocketParams> transport_params( @@ -2981,14 +2572,14 @@ TEST_P(SpdySessionTest, SendCredentials) { HttpNetworkSession::NORMAL_SOCKET_POOL), BoundNetLog())); - EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); + EXPECT_EQ(OK, session->InitializeWithSocket(connection.Pass(), true, OK)); EXPECT_TRUE(session->NeedsCredentials()); // Flush the SpdySession::OnReadComplete() task. base::MessageLoop::current()->RunUntilIdle(); spdy_session_pool_->Remove(session); - EXPECT_FALSE(spdy_session_pool_->HasSession(key)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key)); } TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) { @@ -3024,7 +2615,8 @@ TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously(SPDY_BIDIRECTIONAL_STREAM, session, test_url_, MEDIUM, BoundNetLog()); @@ -3084,9 +2676,8 @@ TEST_P(SpdySessionTest, AdjustRecvWindowSize) { session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, session->flow_control_state()); @@ -3132,9 +2723,8 @@ TEST_P(SpdySessionTest, AdjustSendWindowSize) { session_deps_.socket_factory->AddSocketDataProvider(&data); CreateNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateFakeSpdySession(spdy_session_pool_, key_); EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, session->flow_control_state()); @@ -3172,9 +2762,8 @@ TEST_P(SpdySessionTest, SessionFlowControlInactiveStream) { session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, session->flow_control_state()); @@ -3250,7 +2839,8 @@ TEST_P(SpdySessionTest, SessionFlowControlNoReceiveLeaks) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url(kStreamUrl); base::WeakPtr<SpdyStream> stream = @@ -3327,7 +2917,8 @@ TEST_P(SpdySessionTest, SessionFlowControlNoSendLeaks) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url(kStreamUrl); base::WeakPtr<SpdyStream> stream = @@ -3418,7 +3009,8 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) { CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = CreateInitializedSession(); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); GURL url(kStreamUrl); base::WeakPtr<SpdyStream> stream = @@ -3499,7 +3091,7 @@ TEST_P(SpdySessionTest, SessionFlowControlEndToEnd) { // Given a stall function and an unstall function, runs a test to make // sure that a stream resumes after unstall. void SpdySessionTest::RunResumeAfterUnstallTest( - const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, + const base::Callback<void(SpdySession*, SpdyStream*)>& stall_function, const base::Callback<void(SpdySession*, SpdyStream*, int32)>& unstall_function) { const char kStreamUrl[] = "http://www.google.com/"; @@ -3534,9 +3126,8 @@ void SpdySessionTest::RunResumeAfterUnstallTest( session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, session->flow_control_state()); @@ -3558,7 +3149,7 @@ void SpdySessionTest::RunResumeAfterUnstallTest( EXPECT_TRUE(stream->HasUrl()); EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); - stall_fn.Run(session.get(), stream.get()); + stall_function.Run(session.get(), stream.get()); data.RunFor(1); @@ -3695,9 +3286,8 @@ TEST_P(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, session->flow_control_state()); @@ -3851,9 +3441,8 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, session->flow_control_state()); @@ -4008,9 +3597,8 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); CreateDeterministicNetworkSession(); - scoped_refptr<SpdySession> session = GetSession(key_); - InitializeSession( - http_session_.get(), session.get(), test_host_port_pair_); + scoped_refptr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); EXPECT_EQ(SpdySession::FLOW_CONTROL_STREAM_AND_SESSION, session->flow_control_state()); @@ -4061,17 +3649,17 @@ TEST_P(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) { EXPECT_EQ(3u, stream2->stream_id()); EXPECT_TRUE(stream2->send_stalled_by_flow_control()); - EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); + EXPECT_TRUE(HasSpdySession(spdy_session_pool_, key_)); // Unstall stream1. UnstallSessionSend(session.get(), kBodyDataSize); // Close the session (since we can't do it from within the delegate // method, since it's in the stream's loop). - session->CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "Closing session"); + session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session"); session = NULL; - EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); + EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_)); EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 6ee92db..726fcff 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc @@ -47,31 +47,14 @@ class SpdyStreamTest : public ::testing::Test, SpdyStreamTest() : spdy_util_(GetParam()), - host_port_pair_("www.google.com", 80), session_deps_(GetParam()), offset_(0) {} - scoped_refptr<SpdySession> CreateSpdySession() { - SpdySessionKey key(host_port_pair_, ProxyServer::Direct(), + scoped_refptr<SpdySession> CreateDefaultSpdySession() { + SpdySessionKey key(HostPortPair("www.google.com", 80), + ProxyServer::Direct(), kPrivacyModeDisabled); - scoped_refptr<SpdySession> session( - session_->spdy_session_pool()->Get(key, BoundNetLog())); - return session; - } - - void InitializeSpdySession(const scoped_refptr<SpdySession>& session, - const HostPortPair& host_port_pair) { - scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(host_port_pair, LOWEST, false, false, - OnHostResolutionCallback())); - - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(OK, connection->Init(host_port_pair_.ToString(), transport_params, - LOWEST, CompletionCallback(), - session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - session->InitializeWithSocket(connection.release(), false, OK); + return CreateInsecureSpdySession(session_, key, BoundNetLog()); } virtual void TearDown() { @@ -116,7 +99,6 @@ class SpdyStreamTest : public ::testing::Test, } SpdyTestUtil spdy_util_; - HostPortPair host_port_pair_; SpdySessionDependencies session_deps_; scoped_refptr<HttpNetworkSession> session_; @@ -163,9 +145,7 @@ TEST_P(SpdyStreamTest, SendDataAfterOpen) { session_deps_.socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -197,7 +177,6 @@ TEST_P(SpdyStreamTest, SendDataAfterOpen) { TEST_P(SpdyStreamTest, PushedStream) { session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); - scoped_refptr<SpdySession> spdy_session(CreateSpdySession()); AddReadEOF(); @@ -208,8 +187,7 @@ TEST_P(SpdyStreamTest, PushedStream) { session_deps_.socket_factory->AddSocketDataProvider(&data); - InitializeSpdySession(spdy_session, host_port_pair_); - BoundNetLog net_log; + scoped_refptr<SpdySession> spdy_session(CreateDefaultSpdySession()); // Conjure up a stream. SpdyStream stream(SPDY_PUSH_STREAM, @@ -218,7 +196,7 @@ TEST_P(SpdyStreamTest, PushedStream) { DEFAULT_PRIORITY, kSpdyStreamInitialWindowSize, kSpdyStreamInitialWindowSize, - net_log); + BoundNetLog()); stream.set_stream_id(2); EXPECT_FALSE(stream.HasUrl()); @@ -244,8 +222,7 @@ TEST_P(SpdyStreamTest, PushedStream) { EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); - spdy_session->CloseSessionOnError( - ERR_CONNECTION_CLOSED, true, "Closing session"); + spdy_session->CloseSessionOnError(ERR_CONNECTION_CLOSED, "Closing session"); } TEST_P(SpdyStreamTest, StreamError) { @@ -281,9 +258,7 @@ TEST_P(SpdyStreamTest, StreamError) { session_deps_.socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -367,9 +342,7 @@ TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) { session_deps_.socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -432,9 +405,7 @@ TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) { session_deps_.socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -494,9 +465,7 @@ TEST_P(SpdyStreamTest, UpperCaseHeaders) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -554,9 +523,7 @@ TEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -631,9 +598,7 @@ TEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -713,9 +678,7 @@ TEST_P(SpdyStreamTest, DuplicateHeaders) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -784,11 +747,9 @@ TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) { session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); GURL url(kStreamUrl); - InitializeSpdySession(session, host_port_pair_); - base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound()); @@ -877,9 +838,7 @@ void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest( session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( @@ -971,9 +930,7 @@ void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest( session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); - scoped_refptr<SpdySession> session(CreateSpdySession()); - - InitializeSpdySession(session, host_port_pair_); + scoped_refptr<SpdySession> session(CreateDefaultSpdySession()); base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously( diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 919dd45..34da314 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc @@ -17,10 +17,12 @@ #include "net/http/http_server_properties_impl.h" #include "net/socket/socket_test_util.h" #include "net/socket/ssl_client_socket.h" +#include "net/socket/transport_client_socket_pool.h" #include "net/spdy/buffered_spdy_framer.h" #include "net/spdy/spdy_framer.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_session.h" +#include "net/spdy/spdy_session_pool.h" #include "net/spdy/spdy_stream.h" namespace net { @@ -28,8 +30,9 @@ namespace net { namespace { bool next_proto_is_spdy(NextProto next_proto) { - return next_proto >= kProtoSPDYMinimumVersion && - next_proto <= kProtoSPDYMaximumVersion; + // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we + // stop supporting SPDY/1. + return next_proto >= kProtoSPDY2 && next_proto <= kProtoSPDYMaximumVersion; } // Parses a URL into the scheme, host, and path components required for a @@ -478,22 +481,165 @@ SpdyURLRequestContext::SpdyURLRequestContext(NextProto protocol) SpdyURLRequestContext::~SpdyURLRequestContext() { } -SpdySessionPoolPeer::SpdySessionPoolPeer(SpdySessionPool* pool) : pool_(pool) { +bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key) { + return pool->GetIfExists(key, BoundNetLog()) != NULL; } -void SpdySessionPoolPeer::AddAlias( - const IPEndPoint& address, - const SpdySessionKey& key) { - pool_->AddAlias(address, key); +namespace { + +scoped_refptr<SpdySession> CreateSpdySessionHelper( + const scoped_refptr<HttpNetworkSession>& http_session, + const SpdySessionKey& key, + const BoundNetLog& net_log, + bool is_secure) { + EXPECT_FALSE(HasSpdySession(http_session->spdy_session_pool(), key)); + + scoped_refptr<TransportSocketParams> transport_params( + new TransportSocketParams( + key.host_port_pair(), MEDIUM, false, false, + OnHostResolutionCallback())); + + scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); + TestCompletionCallback callback; + + int rv = ERR_UNEXPECTED; + if (is_secure) { + SSLConfig ssl_config; + scoped_refptr<SOCKSSocketParams> socks_params; + scoped_refptr<HttpProxySocketParams> http_proxy_params; + scoped_refptr<SSLSocketParams> ssl_params( + new SSLSocketParams(transport_params, + socks_params, + http_proxy_params, + ProxyServer::SCHEME_DIRECT, + key.host_port_pair(), + ssl_config, + 0, + false, + false)); + rv = connection->Init(key.host_port_pair().ToString(), + ssl_params, + MEDIUM, + callback.callback(), + http_session->GetSSLSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL), + net_log); + } else { + rv = connection->Init(key.host_port_pair().ToString(), + transport_params, + MEDIUM, + callback.callback(), + http_session->GetTransportSocketPool( + HttpNetworkSession::NORMAL_SOCKET_POOL), + net_log); + } + + if (rv == ERR_IO_PENDING) + rv = callback.WaitForResult(); + + EXPECT_EQ(OK, rv); + + scoped_refptr<SpdySession> spdy_session; + EXPECT_EQ( + OK, + http_session->spdy_session_pool()->GetSpdySessionFromSocket( + key, connection.Pass(), net_log, OK, &spdy_session, + is_secure)); + EXPECT_TRUE(HasSpdySession(http_session->spdy_session_pool(), key)); + return spdy_session; } -void SpdySessionPoolPeer::RemoveAliases(const SpdySessionKey& key) { - pool_->RemoveAliases(key); +} // namespace + +scoped_refptr<SpdySession> CreateInsecureSpdySession( + const scoped_refptr<HttpNetworkSession>& http_session, + const SpdySessionKey& key, + const BoundNetLog& net_log) { + return CreateSpdySessionHelper(http_session, key, net_log, + false /* is_secure */); +} + +scoped_refptr<SpdySession> CreateSecureSpdySession( + const scoped_refptr<HttpNetworkSession>& http_session, + const SpdySessionKey& key, + const BoundNetLog& net_log) { + return CreateSpdySessionHelper(http_session, key, net_log, + true /* is_secure */); +} + +namespace { + +// A ClientSocket used for CreateFakeSpdySession() below. +class FakeSpdySessionClientSocket : public MockClientSocket { + public: + FakeSpdySessionClientSocket() : MockClientSocket(BoundNetLog()) {} + virtual ~FakeSpdySessionClientSocket() {} + + virtual int Read(IOBuffer* buf, int buf_len, + const CompletionCallback& callback) OVERRIDE { + return ERR_IO_PENDING; + } + + virtual int Write(IOBuffer* buf, int buf_len, + const CompletionCallback& callback) OVERRIDE { + return ERR_IO_PENDING; + } + + // Return kProtoUnknown to use the pool's default protocol. + virtual NextProto GetNegotiatedProtocol() const OVERRIDE { + return kProtoUnknown; + } + + // The functions below are not expected to be called. + + virtual int Connect(const CompletionCallback& callback) OVERRIDE { + ADD_FAILURE(); + return ERR_UNEXPECTED; + } + + virtual bool WasEverUsed() const OVERRIDE { + ADD_FAILURE(); + return false; + } + + virtual bool UsingTCPFastOpen() const OVERRIDE { + ADD_FAILURE(); + return false; + } + + virtual bool WasNpnNegotiated() const OVERRIDE { + ADD_FAILURE(); + return false; + } + + virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { + ADD_FAILURE(); + return false; + } +}; + +} // namespace + +scoped_refptr<SpdySession> CreateFakeSpdySession(SpdySessionPool* pool, + const SpdySessionKey& key) { + EXPECT_FALSE(HasSpdySession(pool, key)); + scoped_refptr<SpdySession> spdy_session; + scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle()); + handle->set_socket(new FakeSpdySessionClientSocket()); + EXPECT_EQ( + OK, + pool->GetSpdySessionFromSocket( + key, handle.Pass(), BoundNetLog(), OK, &spdy_session, + true /* is_secure */)); + EXPECT_TRUE(HasSpdySession(pool, key)); + return spdy_session; +} + +SpdySessionPoolPeer::SpdySessionPoolPeer(SpdySessionPool* pool) : pool_(pool) { } -void SpdySessionPoolPeer::RemoveSpdySession( - const scoped_refptr<SpdySession>& session) { - pool_->Remove(session); +void SpdySessionPoolPeer::RemoveAliases(const SpdySessionKey& key) { + pool_->RemoveAliases(key); } void SpdySessionPoolPeer::DisableDomainAuthenticationVerification() { diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index 50baff7..d7dfbf2 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h @@ -37,6 +37,8 @@ namespace net { class BoundNetLog; class SpdySession; +class SpdySessionKey; +class SpdySessionPool; class SpdyStream; class SpdyStreamRequest; @@ -232,13 +234,34 @@ class SpdyURLRequestContext : public URLRequestContext { net::URLRequestContextStorage storage_; }; +// Equivalent to pool->GetIfExists(spdy_session_key, BoundNetLog()) != NULL. +bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key); + +// Creates a SPDY session for the given key and puts it in the SPDY +// session pool in |http_session|. A SPDY session for |key| must not +// already exist. +scoped_refptr<SpdySession> CreateInsecureSpdySession( + const scoped_refptr<HttpNetworkSession>& http_session, + const SpdySessionKey& key, + const BoundNetLog& net_log); + +// Like CreateInsecureSpdySession(), but uses TLS. +scoped_refptr<SpdySession> CreateSecureSpdySession( + const scoped_refptr<HttpNetworkSession>& http_session, + const SpdySessionKey& key, + const BoundNetLog& net_log); + +// Creates an insecure SPDY session for the given key and puts it in +// |pool|. The returned session will neither receiver nor send any +// data. A SPDY session for |key| must not already exist. +scoped_refptr<SpdySession> CreateFakeSpdySession(SpdySessionPool* pool, + const SpdySessionKey& key); + class SpdySessionPoolPeer { public: explicit SpdySessionPoolPeer(SpdySessionPool* pool); - void AddAlias(const IPEndPoint& address, const SpdySessionKey& key); void RemoveAliases(const SpdySessionKey& key); - void RemoveSpdySession(const scoped_refptr<SpdySession>& session); void DisableDomainAuthenticationVerification(); void EnableSendingInitialSettings(bool enabled); diff --git a/net/spdy/spdy_websocket_stream_unittest.cc b/net/spdy/spdy_websocket_stream_unittest.cc index 5a64afe..54a7100 100644 --- a/net/spdy/spdy_websocket_stream_unittest.cc +++ b/net/spdy/spdy_websocket_stream_unittest.cc @@ -237,9 +237,9 @@ class SpdyWebSocketStreamTest false)); } - int InitSession(MockRead* reads, size_t reads_count, - MockWrite* writes, size_t writes_count, - bool throttling) { + void InitSession(MockRead* reads, size_t reads_count, + MockWrite* writes, size_t writes_count, + bool throttling) { data_.reset(new OrderedSocketData(reads, reads_count, writes, writes_count)); session_deps_.socket_factory->AddSocketDataProvider(data_.get()); @@ -255,22 +255,8 @@ class SpdyWebSocketStreamTest spdy_settings_value_to_set_); } - EXPECT_FALSE(spdy_session_pool->HasSession(spdy_session_key_)); - session_ = spdy_session_pool->Get(spdy_session_key_, BoundNetLog()); - EXPECT_TRUE(spdy_session_pool->HasSession(spdy_session_key_)); - transport_params_ = new TransportSocketParams(host_port_pair_, MEDIUM, - false, false, - OnHostResolutionCallback()); - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair_.ToString(), transport_params_, - MEDIUM, callback.callback(), - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, callback.WaitForResult()); - return session_->InitializeWithSocket(connection.release(), false, OK); + session_ = CreateInsecureSpdySession( + http_session_, spdy_session_key_, BoundNetLog()); } void SendRequest() { @@ -292,7 +278,6 @@ class SpdyWebSocketStreamTest scoped_ptr<OrderedSocketData> data_; scoped_refptr<HttpNetworkSession> http_session_; scoped_refptr<SpdySession> session_; - scoped_refptr<TransportSocketParams> transport_params_; scoped_ptr<SpdyWebSocketStream> websocket_stream_; SpdyStreamId stream_id_; SpdyStreamId created_stream_id_; @@ -341,8 +326,7 @@ TEST_P(SpdyWebSocketStreamTest, Basic) { MockRead(SYNCHRONOUS, 0, 8) // EOF cause OnCloseSpdyStream event. }; - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), - writes, arraysize(writes), false)); + InitSession(reads, arraysize(reads), writes, arraysize(writes), false); SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); delegate.SetOnReceivedHeader( @@ -395,8 +379,8 @@ TEST_P(SpdyWebSocketStreamTest, Basic) { EXPECT_EQ(OK, events[6].result); // EOF close SPDY session. - EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession( - spdy_session_key_)); + EXPECT_FALSE( + HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } @@ -414,8 +398,7 @@ TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) { MockRead(ASYNC, ERR_IO_PENDING, 5) }; - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), - writes, arraysize(writes), false)); + InitSession(reads, arraysize(reads), writes, arraysize(writes), false); SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); delegate.SetOnReceivedHeader( @@ -457,8 +440,8 @@ TEST_P(SpdyWebSocketStreamTest, DestructionBeforeClose) { events[3].event_type); EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession( - spdy_session_key_)); + EXPECT_TRUE( + HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } @@ -477,8 +460,7 @@ TEST_P(SpdyWebSocketStreamTest, DestructionAfterExplicitClose) { MockRead(ASYNC, ERR_IO_PENDING, 6) }; - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), - writes, arraysize(writes), false)); + InitSession(reads, arraysize(reads), writes, arraysize(writes), false); SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback()); delegate.SetOnReceivedHeader( @@ -520,8 +502,8 @@ TEST_P(SpdyWebSocketStreamTest, DestructionAfterExplicitClose) { EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result); EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, events[4].event_type); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession( - spdy_session_key_)); + EXPECT_TRUE( + HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); } TEST_P(SpdyWebSocketStreamTest, IOPending) { @@ -546,8 +528,7 @@ TEST_P(SpdyWebSocketStreamTest, IOPending) { MockRead(SYNCHRONOUS, 0, 11) // EOF cause OnCloseSpdyStream event. }; - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), - writes, arraysize(writes), true)); + InitSession(reads, arraysize(reads), writes, arraysize(writes), true); // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another // WebSocketStream under test. @@ -621,8 +602,8 @@ TEST_P(SpdyWebSocketStreamTest, IOPending) { EXPECT_EQ(OK, events[7].result); // EOF close SPDY session. - EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession( - spdy_session_key_)); + EXPECT_FALSE( + HasSpdySession(http_session_->spdy_session_pool(), spdy_session_key_)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } diff --git a/net/websockets/websocket_job.cc b/net/websockets/websocket_job.cc index 1fe2f49..301f0ae 100644 --- a/net/websockets/websocket_job.cc +++ b/net/websockets/websocket_job.cc @@ -593,14 +593,14 @@ int WebSocketJob::TrySpdyStream() { SpdySessionPool* spdy_pool = session->spdy_session_pool(); PrivacyMode privacy_mode = socket_->privacy_mode(); const SpdySessionKey key(HostPortPair::FromURL(socket_->url()), - socket_->proxy_server(), privacy_mode); - if (!spdy_pool->HasSession(key)) - return OK; - + socket_->proxy_server(), privacy_mode); // Forbid wss downgrade to SPDY without SSL. // TODO(toyoshim): Does it realize the same policy with HTTP? scoped_refptr<SpdySession> spdy_session = - spdy_pool->Get(key, *socket_->net_log()); + spdy_pool->GetIfExists(key, *socket_->net_log()); + if (!spdy_session) + return OK; + SSLInfo ssl_info; bool was_npn_negotiated; NextProto protocol_negotiated = kProtoUnknown; diff --git a/net/websockets/websocket_job_unittest.cc b/net/websockets/websocket_job_unittest.cc index 9068482..69f8560 100644 --- a/net/websockets/websocket_job_unittest.cc +++ b/net/websockets/websocket_job_unittest.cc @@ -272,29 +272,8 @@ class MockHttpTransactionFactory : public HttpTransactionFactory { spdy_session_key_ = SpdySessionKey(host_port_pair_, ProxyServer::Direct(), kPrivacyModeDisabled); - SpdySessionPool* spdy_session_pool = - http_session_->spdy_session_pool(); - DCHECK(spdy_session_pool); - EXPECT_FALSE(spdy_session_pool->HasSession(spdy_session_key_)); - session_ = - spdy_session_pool->Get(spdy_session_key_, BoundNetLog()); - EXPECT_TRUE(spdy_session_pool->HasSession(spdy_session_key_)); - - transport_params_ = - new TransportSocketParams(host_port_pair_, - MEDIUM, - false, - false, - OnHostResolutionCallback()); - ClientSocketHandle* connection = new ClientSocketHandle; - EXPECT_EQ(OK, - connection->Init(host_port_pair_.ToString(), transport_params_, - MEDIUM, CompletionCallback(), - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, - session_->InitializeWithSocket(connection, false, OK)); + session_ = CreateInsecureSpdySession( + http_session_, spdy_session_key_, BoundNetLog()); } virtual int CreateTransaction( @@ -318,7 +297,6 @@ class MockHttpTransactionFactory : public HttpTransactionFactory { OrderedSocketData* data_; scoped_ptr<SpdySessionDependencies> session_deps_; scoped_refptr<HttpNetworkSession> http_session_; - scoped_refptr<TransportSocketParams> transport_params_; scoped_refptr<SpdySession> session_; HostPortPair host_port_pair_; SpdySessionKey spdy_session_key_; |