diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_network_transaction.cc | 12 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 4 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream_unittest.cc | 11 | ||||
-rw-r--r-- | net/spdy/spdy_network_transaction.cc | 3 | ||||
-rw-r--r-- | net/spdy/spdy_network_transaction_unittest.cc | 280 | ||||
-rw-r--r-- | net/spdy/spdy_session.cc | 13 | ||||
-rw-r--r-- | net/spdy/spdy_session.h | 15 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.cc | 52 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.h | 23 | ||||
-rw-r--r-- | net/spdy/spdy_session_unittest.cc | 21 | ||||
-rw-r--r-- | net/spdy/spdy_stream_unittest.cc | 4 | ||||
-rw-r--r-- | net/spdy/spdy_test_util.cc | 8 | ||||
-rw-r--r-- | net/spdy/spdy_test_util.h | 3 |
13 files changed, 377 insertions, 72 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index a3624f3..966eccb 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -744,7 +744,8 @@ int HttpNetworkTransaction::DoInitConnection() { // Check first if we have a spdy session for this group. If so, then go // straight to using that. - if (session_->spdy_session_pool()->HasSession(endpoint_)) { + HostPortProxyPair pair(endpoint_, proxy_info_.ToPacString()); + if (session_->spdy_session_pool()->HasSession(pair)) { using_spdy_ = true; reused_socket_ = true; next_state_ = STATE_SPDY_GET_STREAM; @@ -1323,8 +1324,9 @@ int HttpNetworkTransaction::DoSpdyGetStream() { session_->spdy_session_pool(); scoped_refptr<SpdySession> spdy_session; - if (spdy_pool->HasSession(endpoint_)) { - spdy_session = spdy_pool->Get(endpoint_, session_, net_log_); + HostPortProxyPair pair(endpoint_, proxy_info_.ToPacString()); + if (spdy_pool->HasSession(pair)) { + spdy_session = spdy_pool->Get(pair, session_, net_log_); } else { if(using_ssl_) { // SPDY can be negotiated using the TLS next protocol negotiation (NPN) @@ -1332,7 +1334,7 @@ int HttpNetworkTransaction::DoSpdyGetStream() { // contain an SSLClientSocket. CHECK(connection_->socket()); int error = spdy_pool->GetSpdySessionFromSocket( - endpoint_, session_, connection_.release(), net_log_, + pair, session_, connection_.release(), net_log_, spdy_certificate_error_, &spdy_session, true); if (error != OK) return error; @@ -1340,7 +1342,7 @@ int HttpNetworkTransaction::DoSpdyGetStream() { else { // We may want SPDY without SSL int error = spdy_pool->GetSpdySessionFromSocket( - endpoint_, session_, connection_.release(), net_log_, + pair, session_, connection_.release(), net_log_, spdy_certificate_error_, &spdy_session, false); if (error != OK) return error; diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index ea087d0..ec54865 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -5606,9 +5606,9 @@ TEST_F(HttpNetworkTransactionTest, EXPECT_EQ("hello world", response_data); // Set up an initial SpdySession in the pool to reuse. + HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT"); scoped_refptr<SpdySession> spdy_session = - session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443), - session, BoundNetLog()); + session->spdy_session_pool()->Get(pair, session, BoundNetLog()); scoped_refptr<TCPSocketParams> tcp_params = new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false); spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM); diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index ee2ef94..7f78142 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -25,11 +25,12 @@ class SpdyHttpStreamTest : public testing::Test { int InitSession(MockRead* reads, size_t reads_count, MockWrite* writes, size_t writes_count, HostPortPair& host_port_pair) { + HostPortProxyPair pair(host_port_pair, ""); data_ = 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(host_port_pair, http_session_.get(), BoundNetLog()); + Get(pair, http_session_.get(), BoundNetLog()); tcp_params_ = new TCPSocketParams(host_port_pair.host(), host_port_pair.port(), MEDIUM, GURL(), false); @@ -58,6 +59,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) { }; HostPortPair host_port_pair("www.google.com", 80); + HostPortProxyPair pair(host_port_pair, ""); EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), host_port_pair)); @@ -74,7 +76,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) { EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest("", NULL, &response, &callback)); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(host_port_pair)); + EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair)); // This triggers the MockWrite and read 2 callback.WaitForResult(); @@ -84,7 +86,7 @@ TEST_F(SpdyHttpStreamTest, SendRequest) { // Because we abandoned the stream, we don't expect to find a session in the // pool anymore. - EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(host_port_pair)); + EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(pair)); EXPECT_TRUE(data()->at_read_eof()); EXPECT_TRUE(data()->at_write_eof()); } @@ -105,6 +107,7 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) { }; HostPortPair host_port_pair("www.google.com", 80); + HostPortProxyPair pair(host_port_pair, ""); EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), host_port_pair)); @@ -131,7 +134,7 @@ TEST_F(SpdyHttpStreamTest, SpdyURLTest) { FAIL() << "No url is set in spdy_header!"; MessageLoop::current()->RunAllPending(); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(host_port_pair)); + EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair)); http_session_->spdy_session_pool()->CloseAllSessions(); EXPECT_TRUE(!data()->at_read_eof()); } diff --git a/net/spdy/spdy_network_transaction.cc b/net/spdy/spdy_network_transaction.cc index 6b3e26b..cdfd216 100644 --- a/net/spdy/spdy_network_transaction.cc +++ b/net/spdy/spdy_network_transaction.cc @@ -230,8 +230,9 @@ int SpdyNetworkTransaction::DoInitConnection() { new TCPSocketParams(host_port_pair, request_->priority, request_->referrer, false); + HostPortProxyPair pair(host_port_pair, ""); spdy_ = session_->spdy_session_pool()->Get( - host_port_pair, session_, net_log_); + pair, session_, net_log_); DCHECK(spdy_); return spdy_->Connect( diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 5460aae..ef1f03e 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -59,7 +59,9 @@ class SpdyNetworkTransactionTest const BoundNetLog& log, SpdyNetworkTransactionTestTypes test_type) : request_(request), - session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)), + session_deps_(new SpdySessionDependencies()), + session_(SpdySessionDependencies::SpdyCreateSession( + session_deps_.get())), log_(log), test_type_(test_type) { switch (test_type_) { @@ -76,6 +78,12 @@ class SpdyNetworkTransactionTest } void RunPreTestSetup() { + if (!session_deps_.get()) + session_deps_.reset(new SpdySessionDependencies()); + if (!session_.get()) + session_ = SpdySessionDependencies::SpdyCreateSession( + session_deps_.get()); + HttpNetworkTransaction::SetUseAlternateProtocols(false); HttpNetworkTransaction::SetUseSSLOverSpdyWithoutNPN(false); HttpNetworkTransaction::SetUseSpdyWithoutNPN(false); @@ -189,15 +197,15 @@ class SpdyNetworkTransactionTest ssl_->was_npn_negotiated = true; } ssl_vector_.push_back(ssl_); - if (test_type_ == SPDYNPN || test_type_ == SPDYSSL) - session_deps_.socket_factory.AddSSLSocketDataProvider(ssl_.get()); - session_deps_.socket_factory.AddSocketDataProvider(data); + if(test_type_ == SPDYNPN || test_type_ == SPDYSSL) + session_deps_->socket_factory.AddSSLSocketDataProvider(ssl_.get()); + session_deps_->socket_factory.AddSocketDataProvider(data); } // This can only be called after RunPreTestSetup. It adds a Data Provider, // but not a corresponding SSL data provider void AddDataNoSSL(StaticSocketDataProvider* data) { - session_deps_.socket_factory.AddSocketDataProvider(data); + session_deps_->socket_factory.AddSocketDataProvider(data); } void SetSession(const scoped_refptr<HttpNetworkSession>& session) { @@ -208,13 +216,16 @@ class SpdyNetworkTransactionTest TransactionHelperResult& output() { return output_; } HttpRequestInfo& request() { return request_; } scoped_refptr<HttpNetworkSession>& session() { return session_; } + scoped_ptr<SpdySessionDependencies>& session_deps() { + return session_deps_; + } int port() { return port_; } private: typedef std::vector<StaticSocketDataProvider*> DataVector; typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector; HttpRequestInfo request_; - SpdySessionDependencies session_deps_; + scoped_ptr<SpdySessionDependencies> session_deps_; scoped_refptr<HttpNetworkSession> session_; TransactionHelperResult output_; scoped_ptr<StaticSocketDataProvider> first_transaction_; @@ -2783,6 +2794,262 @@ TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) { helper.VerifyDataConsumed(); } +// Test to make sure we can correctly connect through a proxy. +TEST_P(SpdyNetworkTransactionTest, ProxyConnect) { + NormalSpdyTransactionHelper helper(CreateGetRequest(), + BoundNetLog(), GetParam()); + helper.session_deps().reset(new SpdySessionDependencies( + net::SpdyCreateFixedProxyService("myproxy:70"))); + helper.session() = SpdySessionDependencies::SpdyCreateSession( + helper.session_deps().get()); + helper.RunPreTestSetup(); + HttpNetworkTransaction* trans = helper.trans(); + + const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"}; + const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"}; + const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; + scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); + scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); + + MockWrite writes_SPDYNPN[] = { + MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0), + CreateMockWrite(*req, 2), + }; + MockRead reads_SPDYNPN[] = { + MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1), + CreateMockRead(*resp, 3), + CreateMockRead(*body.get(), 4), + MockRead(true, 0, 0, 5), + }; + + MockWrite writes_SPDYSSL[] = { + MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0), + CreateMockWrite(*req, 2), + }; + MockRead reads_SPDYSSL[] = { + MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1), + CreateMockRead(*resp, 3), + CreateMockRead(*body.get(), 4), + MockRead(true, 0, 0, 5), + }; + + MockWrite writes_SPDYNOSSL[] = { + CreateMockWrite(*req, 0), + }; + + MockRead reads_SPDYNOSSL[] = { + CreateMockRead(*resp, 1), + CreateMockRead(*body.get(), 2), + MockRead(true, 0, 0, 3), + }; + + scoped_refptr<OrderedSocketData> data; + switch(GetParam()) { + case SPDYNOSSL: + data = new OrderedSocketData(reads_SPDYNOSSL, + arraysize(reads_SPDYNOSSL), + writes_SPDYNOSSL, + arraysize(writes_SPDYNOSSL)); + break; + case SPDYSSL: + data = new OrderedSocketData(reads_SPDYSSL, arraysize(reads_SPDYSSL), + writes_SPDYSSL, arraysize(writes_SPDYSSL)); + break; + case SPDYNPN: + data = new OrderedSocketData(reads_SPDYNPN, arraysize(reads_SPDYNPN), + writes_SPDYNPN, arraysize(writes_SPDYNPN)); + break; + default: + NOTREACHED(); + } + + helper.AddData(data.get()); + TestCompletionCallback callback; + + int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + rv = callback.WaitForResult(); + EXPECT_EQ(0, rv); + + // Verify the SYN_REPLY. + HttpResponseInfo response = *trans->GetResponseInfo(); + EXPECT_TRUE(response.headers != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); + EXPECT_EQ("hello!", response_data); + helper.VerifyDataConsumed(); +} + +// Test to make sure we can correctly connect through a proxy to www.google.com, +// if there already exists a direct spdy connection to www.google.com. See +// http://crbug.com/49874 +TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) { + // When setting up the first transaction, we store the SpdySessionPool so that + // we can use the same pool in the second transaction. + NormalSpdyTransactionHelper helper(CreateGetRequest(), + BoundNetLog(), GetParam()); + scoped_refptr<SpdySessionPool> spdy_session_pool = + helper.session_deps()->spdy_session_pool; + helper.RunPreTestSetup(); + + // Construct and send a simple GET request. + scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); + MockWrite writes[] = { + CreateMockWrite(*req, 1), + }; + + scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); + MockRead reads[] = { + CreateMockRead(*resp, 2), + CreateMockRead(*body, 3), + MockRead(true, ERR_IO_PENDING, 4), // Force a pause + MockRead(true, 0, 5) // EOF + }; + scoped_refptr<OrderedSocketData> data( + new OrderedSocketData(reads, arraysize(reads), + writes, arraysize(writes))); + helper.AddData(data.get()); + HttpNetworkTransaction* trans = helper.trans(); + + TestCompletionCallback callback; + TransactionHelperResult out; + out.rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); + + EXPECT_EQ(out.rv, ERR_IO_PENDING); + out.rv = callback.WaitForResult(); + EXPECT_EQ(out.rv, OK); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + EXPECT_TRUE(response->headers != NULL); + EXPECT_TRUE(response->was_fetched_via_spdy); + out.rv = ReadTransaction(trans, &out.response_data); + EXPECT_EQ(OK, out.rv); + out.status_line = response->headers->GetStatusLine(); + EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); + EXPECT_EQ("hello!", out.response_data); + + // Check that the SpdySession is still in the SpdySessionPool. + HostPortPair host_port_pair("www.google.com", helper.port()); + HostPortProxyPair pair(host_port_pair, "DIRECT"); + EXPECT_TRUE(spdy_session_pool->HasSession(pair)); + HostPortProxyPair nonexistent_pair(host_port_pair, "PROXY www.foo.com"); + EXPECT_FALSE(spdy_session_pool->HasSession(nonexistent_pair)); + + // Set up data for the proxy connection. + const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"}; + const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Proxy-Connection: keep-alive\r\n\r\n"}; + const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; + scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet( + "http://www.google.com/foo.dat", false, 1, LOWEST)); + scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true)); + + MockWrite writes_SPDYNPN[] = { + MockWrite(false, kConnect443, arraysize(kConnect443) - 1, 0), + CreateMockWrite(*req2, 2), + }; + MockRead reads_SPDYNPN[] = { + MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1), + CreateMockRead(*resp2, 3), + CreateMockRead(*body2, 4), + MockRead(true, 0, 5) // EOF + }; + + MockWrite writes_SPDYNOSSL[] = { + CreateMockWrite(*req2, 0), + }; + MockRead reads_SPDYNOSSL[] = { + CreateMockRead(*resp2, 1), + CreateMockRead(*body2, 2), + MockRead(true, 0, 3) // EOF + }; + + MockWrite writes_SPDYSSL[] = { + MockWrite(false, kConnect80, arraysize(kConnect80) - 1, 0), + CreateMockWrite(*req2, 2), + }; + MockRead reads_SPDYSSL[] = { + MockRead(false, kHTTP200, arraysize(kHTTP200) - 1, 1), + CreateMockRead(*resp2, 3), + CreateMockRead(*body2, 4), + MockRead(true, 0, 0, 5), + }; + + scoped_refptr<OrderedSocketData> data_proxy; + switch(GetParam()) { + case SPDYNPN: + data_proxy = new OrderedSocketData(reads_SPDYNPN, + arraysize(reads_SPDYNPN), + writes_SPDYNPN, + arraysize(writes_SPDYNPN)); + break; + case SPDYNOSSL: + data_proxy = new OrderedSocketData(reads_SPDYNOSSL, + arraysize(reads_SPDYNOSSL), + writes_SPDYNOSSL, + arraysize(writes_SPDYNOSSL)); + break; + case SPDYSSL: + data_proxy = new OrderedSocketData(reads_SPDYSSL, + arraysize(reads_SPDYSSL), + writes_SPDYSSL, + arraysize(writes_SPDYSSL)); + break; + default: + NOTREACHED(); + } + + // Create another request to www.google.com, but this time through a proxy. + HttpRequestInfo request_proxy; + request_proxy.method = "GET"; + request_proxy.url = GURL("http://www.google.com/foo.dat"); + request_proxy.load_flags = 0; + scoped_ptr<SpdySessionDependencies> ssd_proxy( + new SpdySessionDependencies(net::SpdyCreateFixedProxyService( + "myproxy:70"))); + // Ensure that this transaction uses the same SpdySessionPool. + ssd_proxy->spdy_session_pool = spdy_session_pool; + scoped_refptr<HttpNetworkSession> session_proxy = + SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()); + NormalSpdyTransactionHelper helper_proxy(request_proxy, + BoundNetLog(), GetParam()); + helper_proxy.session_deps().swap(ssd_proxy); + helper_proxy.session() = session_proxy; + helper_proxy.RunPreTestSetup(); + helper_proxy.AddData(data_proxy.get()); + + HttpNetworkTransaction* trans_proxy = helper_proxy.trans(); + TestCompletionCallback callback_proxy; + int rv = trans_proxy->Start(&request_proxy, &callback_proxy, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + rv = callback_proxy.WaitForResult(); + EXPECT_EQ(0, rv); + + HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo(); + EXPECT_TRUE(response_proxy.headers != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine()); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data)); + EXPECT_EQ("hello!", response_data); + + data->CompleteRead(); + helper_proxy.VerifyDataConsumed(); +} + // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction // on a new connection, if the connection was previously known to be good. // This can happen when a server reboots without saying goodbye, or when @@ -2865,5 +3132,4 @@ TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) { helper.VerifyDataConsumed(); } } - } // namespace net diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 2aa2289..9776bce 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -138,7 +138,7 @@ bool SpdySession::use_ssl_ = true; // static bool SpdySession::use_flow_control_ = false; -SpdySession::SpdySession(const HostPortPair& host_port_pair, +SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, HttpNetworkSession* session, NetLog* net_log) : ALLOW_THIS_IN_INITIALIZER_LIST( @@ -149,7 +149,7 @@ SpdySession::SpdySession(const HostPortPair& host_port_pair, read_callback_(this, &SpdySession::OnReadComplete)), ALLOW_THIS_IN_INITIALIZER_LIST( write_callback_(this, &SpdySession::OnWriteComplete)), - host_port_pair_(host_port_pair), + host_port_proxy_pair_(host_port_proxy_pair), session_(session), connection_(new ClientSocketHandle), read_buffer_(new IOBuffer(kReadBufferSize)), @@ -174,7 +174,8 @@ SpdySession::SpdySession(const HostPortPair& host_port_pair, net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)) { net_log_.BeginEvent( NetLog::TYPE_SPDY_SESSION, - new NetLogStringParameter("host_port", host_port_pair_.ToString())); + new NetLogStringParameter("host_port", + host_port_proxy_pair_.first.ToString())); // TODO(mbelshe): consider randomization of the stream_hi_water_mark. @@ -1225,7 +1226,7 @@ void SpdySession::OnSettings(const spdy::SpdySettingsControlFrame& frame) { if (spdy_framer_.ParseSettings(&frame, &settings)) { HandleSettings(settings); SpdySettingsStorage* settings_storage = session_->mutable_spdy_settings(); - settings_storage->Set(host_port_pair_, settings); + settings_storage->Set(host_port_pair(), settings); } received_settings_ = true; @@ -1263,7 +1264,7 @@ void SpdySession::OnWindowUpdate( void SpdySession::SendSettings() { const SpdySettingsStorage& settings_storage = session_->spdy_settings(); - const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair_); + const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair()); if (settings.empty()) return; HandleSettings(settings); @@ -1314,7 +1315,7 @@ void SpdySession::RecordHistograms() { if (received_settings_) { // Enumerate the saved settings, and set histograms for it. const SpdySettingsStorage& settings_storage = session_->spdy_settings(); - const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair_); + const spdy::SpdySettings& settings = settings_storage.Get(host_port_pair()); spdy::SpdySettings::const_iterator it; for (it = settings.begin(); it != settings.end(); ++it) { diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 22facba..39fe56b 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -48,13 +48,20 @@ class SpdySession : public base::RefCounted<SpdySession>, public spdy::SpdyFramerVisitorInterface { public: // Create a new SpdySession. - // |host_port_pair| is the host/port that this session connects to. + // |host_port_proxy_pair| is the host/port that this session connects to, and + // the proxy configuration settings that it's using. // |session| is the HttpNetworkSession. |net_log| is the NetLog that we log // network events to. - SpdySession(const HostPortPair& host_port_pair, HttpNetworkSession* session, + SpdySession(const HostPortProxyPair& host_port_proxy_pair, + HttpNetworkSession* session, NetLog* net_log); - const HostPortPair& host_port_pair() const { return host_port_pair_; } + const HostPortPair& host_port_pair() const { + return host_port_proxy_pair_.first; + } + const HostPortProxyPair& host_port_proxy_pair() const { + return host_port_proxy_pair_; + } // Connect the Spdy Socket. // Returns net::Error::OK on success. @@ -271,7 +278,7 @@ class SpdySession : public base::RefCounted<SpdySession>, CompletionCallbackImpl<SpdySession> write_callback_; // The domain this session is connected to. - const HostPortPair host_port_pair_; + const HostPortProxyPair host_port_proxy_pair_; SSLConfig ssl_config_; diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index da8b358..7bccd5c43 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -25,22 +25,24 @@ SpdySessionPool::~SpdySessionPool() { } scoped_refptr<SpdySession> SpdySessionPool::Get( - const HostPortPair& host_port_pair, HttpNetworkSession* session, + const HostPortProxyPair& host_port_proxy_pair, HttpNetworkSession* session, const BoundNetLog& net_log) { scoped_refptr<SpdySession> spdy_session; - SpdySessionList* list = GetSessionList(host_port_pair); + SpdySessionList* list = GetSessionList(host_port_proxy_pair); if (list) { if (list->size() >= static_cast<unsigned int>(g_max_sessions_per_domain)) { spdy_session = list->front(); list->pop_front(); } } else { - list = AddSessionList(host_port_pair); + list = AddSessionList(host_port_proxy_pair); } DCHECK(list); if (!spdy_session) - spdy_session = new SpdySession(host_port_pair, session, net_log.net_log()); + spdy_session = new SpdySession(host_port_proxy_pair, + session, + net_log.net_log()); DCHECK(spdy_session); list->push_back(spdy_session); @@ -49,7 +51,7 @@ scoped_refptr<SpdySession> SpdySessionPool::Get( } net::Error SpdySessionPool::GetSpdySessionFromSocket( - const HostPortPair& host_port_pair, + const HostPortProxyPair& host_port_proxy_pair, HttpNetworkSession* session, ClientSocketHandle* connection, const BoundNetLog& net_log, @@ -57,10 +59,11 @@ net::Error SpdySessionPool::GetSpdySessionFromSocket( scoped_refptr<SpdySession>* spdy_session, bool is_secure) { // Create the SPDY session and add it to the pool. - *spdy_session = new SpdySession(host_port_pair, session, net_log.net_log()); - SpdySessionList* list = GetSessionList(host_port_pair); + *spdy_session = new SpdySession(host_port_proxy_pair, + session, net_log.net_log()); + SpdySessionList* list = GetSessionList(host_port_proxy_pair); if (!list) - list = AddSessionList(host_port_pair); + list = AddSessionList(host_port_proxy_pair); DCHECK(list->empty()); list->push_back(*spdy_session); @@ -69,20 +72,21 @@ net::Error SpdySessionPool::GetSpdySessionFromSocket( certificate_error_code); } -bool SpdySessionPool::HasSession(const HostPortPair& host_port_pair) const { - if (GetSessionList(host_port_pair)) +bool SpdySessionPool::HasSession( + const HostPortProxyPair& host_port_proxy_pair) const { + if (GetSessionList(host_port_proxy_pair)) return true; return false; } void SpdySessionPool::Remove(const scoped_refptr<SpdySession>& session) { - SpdySessionList* list = GetSessionList(session->host_port_pair()); + SpdySessionList* list = GetSessionList(session->host_port_proxy_pair()); DCHECK(list); // We really shouldn't remove if we've already been removed. if (!list) return; list->remove(session); if (list->empty()) - RemoveSessionList(session->host_port_pair()); + RemoveSessionList(session->host_port_proxy_pair()); } void SpdySessionPool::OnIPAddressChanged() { @@ -90,34 +94,38 @@ void SpdySessionPool::OnIPAddressChanged() { } SpdySessionPool::SpdySessionList* - SpdySessionPool::AddSessionList(const HostPortPair& host_port_pair) { - DCHECK(sessions_.find(host_port_pair) == sessions_.end()); + SpdySessionPool::AddSessionList( + const HostPortProxyPair& host_port_proxy_pair) { + DCHECK(sessions_.find(host_port_proxy_pair) == sessions_.end()); SpdySessionPool::SpdySessionList* list = new SpdySessionList(); - sessions_[host_port_pair] = list; + sessions_[host_port_proxy_pair] = list; return list; } SpdySessionPool::SpdySessionList* - SpdySessionPool::GetSessionList(const HostPortPair& host_port_pair) { - SpdySessionsMap::iterator it = sessions_.find(host_port_pair); + SpdySessionPool::GetSessionList( + const HostPortProxyPair& host_port_proxy_pair) { + SpdySessionsMap::iterator it = sessions_.find(host_port_proxy_pair); if (it == sessions_.end()) return NULL; return it->second; } const SpdySessionPool::SpdySessionList* - SpdySessionPool::GetSessionList(const HostPortPair& host_port_pair) const { - SpdySessionsMap::const_iterator it = sessions_.find(host_port_pair); + SpdySessionPool::GetSessionList( + const HostPortProxyPair& host_port_proxy_pair) const { + SpdySessionsMap::const_iterator it = sessions_.find(host_port_proxy_pair); if (it == sessions_.end()) return NULL; return it->second; } -void SpdySessionPool::RemoveSessionList(const HostPortPair& host_port_pair) { - SpdySessionList* list = GetSessionList(host_port_pair); +void SpdySessionPool::RemoveSessionList( + const HostPortProxyPair& host_port_proxy_pair) { + SpdySessionList* list = GetSessionList(host_port_proxy_pair); if (list) { delete list; - sessions_.erase(host_port_pair); + sessions_.erase(host_port_proxy_pair); } else { DCHECK(false) << "removing orphaned session list"; } diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index e0320d3..3bdd2b3 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -17,8 +17,12 @@ #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" #include "net/base/network_change_notifier.h" +#include "net/proxy/proxy_config.h" namespace net { +// Sessions are uniquely identified by their HostPortPair and the PAC-style list +// of valid proxy servers. +typedef std::pair<HostPortPair, std::string> HostPortProxyPair; class BoundNetLog; class ClientSocketHandle; @@ -36,7 +40,8 @@ class SpdySessionPool // Either returns an existing SpdySession or creates a new SpdySession for // use. scoped_refptr<SpdySession> Get( - const HostPortPair& host_port_pair, HttpNetworkSession* session, + const HostPortProxyPair& host_port_proxy_pair, + HttpNetworkSession* session, const BoundNetLog& net_log); // Set the maximum concurrent sessions per domain. @@ -56,7 +61,7 @@ class SpdySessionPool // 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 HostPortPair& host_port_pair, + const HostPortProxyPair& host_port_proxy_pair, HttpNetworkSession* session, ClientSocketHandle* connection, const BoundNetLog& net_log, @@ -66,7 +71,7 @@ class SpdySessionPool // TODO(willchan): Consider renaming to HasReusableSession, since perhaps we // should be creating a new session. - bool HasSession(const HostPortPair& host_port_pair)const; + bool HasSession(const HostPortProxyPair& host_port_proxy_pair) const; // Close all Spdy Sessions; used for debugging. void CloseAllSessions(); @@ -89,16 +94,18 @@ class SpdySessionPool FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateOverflow); typedef std::list<scoped_refptr<SpdySession> > SpdySessionList; - typedef std::map<HostPortPair, SpdySessionList*> SpdySessionsMap; + typedef std::map<HostPortProxyPair, SpdySessionList*> SpdySessionsMap; virtual ~SpdySessionPool(); // Helper functions for manipulating the lists. - SpdySessionList* AddSessionList(const HostPortPair& host_port_pair); - SpdySessionList* GetSessionList(const HostPortPair& host_port_pair); + SpdySessionList* AddSessionList( + const HostPortProxyPair& host_port_proxy_pair); + SpdySessionList* GetSessionList( + const HostPortProxyPair& host_port_proxy_pair); const SpdySessionList* GetSessionList( - const HostPortPair& host_port_pair) const; - void RemoveSessionList(const HostPortPair& host_port_pair); + const HostPortProxyPair& host_port_proxy_pair) const; + void RemoveSessionList(const HostPortProxyPair& host_port_proxy_pair); // Releases the SpdySessionPool reference to all sessions. Will result in all // idle sessions being deleted, and the active sessions from being reused, so // they will be deleted once all active streams belonging to that session go diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index 70c7863..e78f0d9 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -80,14 +80,14 @@ TEST_F(SpdySessionTest, GoAway) { const std::string kTestHost("www.foo.com"); const int kTestPort = 80; HostPortPair test_host_port_pair(kTestHost, kTestPort); + HostPortProxyPair pair(test_host_port_pair, ""); scoped_refptr<SpdySessionPool> spdy_session_pool( http_session->spdy_session_pool()); - EXPECT_FALSE(spdy_session_pool->HasSession(test_host_port_pair)); + EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session = - spdy_session_pool->Get( - test_host_port_pair, http_session.get(), BoundNetLog()); - EXPECT_TRUE(spdy_session_pool->HasSession(test_host_port_pair)); + spdy_session_pool->Get(pair, http_session.get(), BoundNetLog()); + EXPECT_TRUE(spdy_session_pool->HasSession(pair)); scoped_refptr<TCPSocketParams> tcp_params = new TCPSocketParams(kTestHost, kTestPort, MEDIUM, GURL(), false); @@ -97,11 +97,10 @@ TEST_F(SpdySessionTest, GoAway) { // Flush the SpdySession::OnReadComplete() task. MessageLoop::current()->RunAllPending(); - EXPECT_FALSE(spdy_session_pool->HasSession(test_host_port_pair)); + EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session2 = - spdy_session_pool->Get( - test_host_port_pair, http_session.get(), BoundNetLog()); + spdy_session_pool->Get(pair, http_session.get(), BoundNetLog()); // Delete the first session. session = NULL; @@ -144,14 +143,14 @@ TEST_F(SpdySessionTest, GetActivePushStream) { const std::string kTestHost("www.foo.com"); const int kTestPort = 80; HostPortPair test_host_port_pair(kTestHost, kTestPort); + HostPortProxyPair pair(test_host_port_pair, ""); scoped_refptr<SpdySessionPool> spdy_session_pool( http_session->spdy_session_pool()); - EXPECT_FALSE(spdy_session_pool->HasSession(test_host_port_pair)); + EXPECT_FALSE(spdy_session_pool->HasSession(pair)); scoped_refptr<SpdySession> session = - spdy_session_pool->Get( - test_host_port_pair, http_session.get(), BoundNetLog()); - EXPECT_TRUE(spdy_session_pool->HasSession(test_host_port_pair)); + spdy_session_pool->Get(pair, http_session.get(), BoundNetLog()); + EXPECT_TRUE(spdy_session_pool->HasSession(pair)); // No push streams should exist in the beginning. std::string test_push_path = "/foo.js"; diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 471a1786..94b08ec 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc @@ -118,9 +118,9 @@ class SpdyStreamTest : public testing::Test { scoped_refptr<SpdySession> CreateSpdySession() { spdy::SpdyFramer::set_enable_compression_default(false); HostPortPair host_port_pair("www.google.com", 80); + HostPortProxyPair pair(host_port_pair, ""); scoped_refptr<SpdySession> session( - session_->spdy_session_pool()->Get( - host_port_pair, session_, BoundNetLog())); + session_->spdy_session_pool()->Get(pair, session_, BoundNetLog())); return session; } diff --git a/net/spdy/spdy_test_util.cc b/net/spdy/spdy_test_util.cc index 94b9889..aa566d1 100644 --- a/net/spdy/spdy_test_util.cc +++ b/net/spdy/spdy_test_util.cc @@ -599,4 +599,12 @@ int CombineFrames(const spdy::SpdyFrame** frames, int num_frames, return total_len; } +// This creates a proxy for testing purposes. +// |proxy| should be in the form "myproxy:70". +ProxyService* SpdyCreateFixedProxyService(const std::string& proxy) { + net::ProxyConfig proxy_config; + proxy_config.proxy_rules().ParseFromString(proxy); + return ProxyService::CreateFixed(proxy_config); +} + } // namespace net diff --git a/net/spdy/spdy_test_util.h b/net/spdy/spdy_test_util.h index 0282763..26b9a87 100644 --- a/net/spdy/spdy_test_util.h +++ b/net/spdy/spdy_test_util.h @@ -261,6 +261,9 @@ class SpdySessionDependencies { } }; +// This creates a proxy for testing purposes. +// |proxy| should be in the form "myproxy:70". +ProxyService* SpdyCreateFixedProxyService(const std::string& proxy); } // namespace net |