diff options
author | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 23:55:02 +0000 |
---|---|---|
committer | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 23:55:02 +0000 |
commit | d2b5f09e54322cdd0c1046b6661324672a948394 (patch) | |
tree | 5d2012e2c6aa74847504caabff6a6dfb00d1aaaa /net/http | |
parent | cc7823bc07a6f6a05e30a4670041c5b28f40c4aa (diff) | |
download | chromium_src-d2b5f09e54322cdd0c1046b6661324672a948394.zip chromium_src-d2b5f09e54322cdd0c1046b6661324672a948394.tar.gz chromium_src-d2b5f09e54322cdd0c1046b6661324672a948394.tar.bz2 |
Add a new OnHostResolutionCallback to TransportSocketParams
Correctly implement OnHostResolution in HttpStreamFactoryImpl::Job
BUG=106235
TEST=HttpNetworkTransactionSpdy\*Test.UseIPConnectionPoolingAfterResolution
Review URL: https://chromiumcodereview.appspot.com/10238010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141328 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_network_transaction_spdy2_unittest.cc | 163 | ||||
-rw-r--r-- | net/http/http_network_transaction_spdy3_unittest.cc | 161 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool_spdy2_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool_spdy3_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl_job.cc | 56 | ||||
-rw-r--r-- | net/http/http_stream_factory_impl_job.h | 14 |
6 files changed, 288 insertions, 112 deletions
diff --git a/net/http/http_network_transaction_spdy2_unittest.cc b/net/http/http_network_transaction_spdy2_unittest.cc index f11aebd..b7c3023 100644 --- a/net/http/http_network_transaction_spdy2_unittest.cc +++ b/net/http/http_network_transaction_spdy2_unittest.cc @@ -7745,7 +7745,8 @@ TEST_F(HttpNetworkTransactionSpdy2Test, scoped_refptr<SpdySession> spdy_session = session->spdy_session_pool()->Get(pair, BoundNetLog()); scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(host_port_pair, MEDIUM, false, false)); + new TransportSocketParams(host_port_pair, MEDIUM, false, false, + OnHostResolutionCallback())); scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); EXPECT_EQ(ERR_IO_PENDING, @@ -9005,7 +9006,8 @@ TEST_F(HttpNetworkTransactionSpdy2Test, PreconnectWithExistingSpdySession) { scoped_refptr<SpdySession> spdy_session = session->spdy_session_pool()->Get(pair, BoundNetLog()); scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(host_port_pair, MEDIUM, false, false)); + new TransportSocketParams(host_port_pair, MEDIUM, false, false, + OnHostResolutionCallback())); TestCompletionCallback callback; scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); @@ -9397,42 +9399,6 @@ TEST_F(HttpNetworkTransactionSpdy2Test, ClientAuthCertCache_Proxy_Fail) { } } -namespace { - -void IPPoolingAddAlias(MockCachingHostResolver* host_resolver, - SpdySessionPoolPeer* pool_peer, - std::string host, - int port, - std::string iplist) { - // Create a host resolver dependency that returns address |iplist| for - // resolutions of |host|. - host_resolver->rules()->AddIPLiteralRule(host, iplist, ""); - - // Setup a HostPortProxyPair. - HostPortPair host_port_pair(host, port); - HostPortProxyPair pair = HostPortProxyPair(host_port_pair, - ProxyServer::Direct()); - - // Resolve the host and port. - AddressList addresses; - HostResolver::RequestInfo info(host_port_pair); - TestCompletionCallback callback; - int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL, - BoundNetLog()); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); - DCHECK_EQ(OK, rv); - - // Add the first address as an alias. It would have been better to call - // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas - // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use - // the first address (127.0.0.1) returned by MockHostResolver as an alias for - // the |pair|. - pool_peer->AddAlias(addresses.front(), pair); -} - -} // namespace - // Times out on Win7 dbg(2) bot. http://crbug.com/124776 #if defined(OS_WIN) #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling @@ -9484,8 +9450,13 @@ TEST_F(HttpNetworkTransactionSpdy2Test, MAYBE_UseIPConnectionPooling) { MockRead(ASYNC, 0, 7), }; + IPAddressNumber ip; + ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); + IPEndPoint peer_addr = IPEndPoint(ip, 443); + MockConnect connect(ASYNC, OK, peer_addr); scoped_ptr<OrderedSocketData> spdy_data( new OrderedSocketData( + connect, spdy_reads, arraysize(spdy_reads), spdy_writes, arraysize(spdy_writes))); session_deps.socket_factory.AddSocketDataProvider(spdy_data.get()); @@ -9520,12 +9491,6 @@ TEST_F(HttpNetworkTransactionSpdy2Test, MAYBE_UseIPConnectionPooling) { rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/ - // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair: - // (www.google.com, 443). - IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443, - "127.0.0.1"); - HttpRequestInfo request2; request2.method = "GET"; request2.url = GURL("https://www.gmail.com/"); @@ -9550,6 +9515,105 @@ TEST_F(HttpNetworkTransactionSpdy2Test, MAYBE_UseIPConnectionPooling) { } #undef MAYBE_UseIPConnectionPooling +TEST_F(HttpNetworkTransactionSpdy2Test, UseIPConnectionPoolingAfterResolution) { + HttpStreamFactory::set_use_alternate_protocols(true); + HttpStreamFactory::SetNextProtos(SpdyNextProtos()); + + // Set up a special HttpNetworkSession with a MockCachingHostResolver. + SessionDependencies session_deps; + MockCachingHostResolver host_resolver; + net::HttpNetworkSession::Params params; + params.client_socket_factory = &session_deps.socket_factory; + params.host_resolver = &host_resolver; + params.cert_verifier = session_deps.cert_verifier.get(); + params.proxy_service = session_deps.proxy_service.get(); + params.ssl_config_service = session_deps.ssl_config_service; + params.http_auth_handler_factory = + session_deps.http_auth_handler_factory.get(); + params.http_server_properties = &session_deps.http_server_properties; + params.net_log = session_deps.net_log; + scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params)); + SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); + pool_peer.DisableDomainAuthenticationVerification(); + + SSLSocketDataProvider ssl(ASYNC, OK); + ssl.SetNextProto(kProtoSPDY2); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + + scoped_ptr<SpdyFrame> host1_req(ConstructSpdyGet( + "https://www.google.com", false, 1, LOWEST)); + scoped_ptr<SpdyFrame> host2_req(ConstructSpdyGet( + "https://www.gmail.com", false, 3, LOWEST)); + MockWrite spdy_writes[] = { + CreateMockWrite(*host1_req, 1), + CreateMockWrite(*host2_req, 4), + }; + scoped_ptr<SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true)); + scoped_ptr<SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true)); + MockRead spdy_reads[] = { + CreateMockRead(*host1_resp, 2), + CreateMockRead(*host1_resp_body, 3), + CreateMockRead(*host2_resp, 5), + CreateMockRead(*host2_resp_body, 6), + MockRead(ASYNC, 0, 7), + }; + + IPAddressNumber ip; + ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); + IPEndPoint peer_addr = IPEndPoint(ip, 443); + MockConnect connect(ASYNC, OK, peer_addr); + scoped_ptr<OrderedSocketData> spdy_data( + new OrderedSocketData( + connect, + spdy_reads, arraysize(spdy_reads), + spdy_writes, arraysize(spdy_writes))); + session_deps.socket_factory.AddSocketDataProvider(spdy_data.get()); + + TestCompletionCallback callback; + HttpRequestInfo request1; + request1.method = "GET"; + request1.url = GURL("https://www.google.com/"); + request1.load_flags = 0; + HttpNetworkTransaction trans1(session); + + int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_EQ(OK, callback.WaitForResult()); + + const HttpResponseInfo* response = trans1.GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); + EXPECT_EQ("hello!", response_data); + + HttpRequestInfo request2; + request2.method = "GET"; + request2.url = GURL("https://www.gmail.com/"); + request2.load_flags = 0; + HttpNetworkTransaction trans2(session); + + rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_EQ(OK, callback.WaitForResult()); + + response = trans2.GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + EXPECT_TRUE(response->was_fetched_via_spdy); + EXPECT_TRUE(response->was_npn_negotiated); + ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); + EXPECT_EQ("hello!", response_data); + + HttpStreamFactory::SetNextProtos(std::vector<std::string>()); + HttpStreamFactory::set_use_alternate_protocols(false); +} + class OneTimeCachingHostResolver : public net::HostResolver { public: explicit OneTimeCachingHostResolver(const HostPortPair& host_port) @@ -9642,8 +9706,13 @@ TEST_F(HttpNetworkTransactionSpdy2Test, MockRead(ASYNC, 0, 7), }; + IPAddressNumber ip; + ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); + IPEndPoint peer_addr = IPEndPoint(ip, 443); + MockConnect connect(ASYNC, OK, peer_addr); scoped_ptr<OrderedSocketData> spdy_data( new OrderedSocketData( + connect, spdy_reads, arraysize(spdy_reads), spdy_writes, arraysize(spdy_writes))); session_deps.socket_factory.AddSocketDataProvider(spdy_data.get()); @@ -9683,12 +9752,6 @@ TEST_F(HttpNetworkTransactionSpdy2Test, request2.load_flags = 0; HttpNetworkTransaction trans2(session); - // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/ - // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair: - // (www.google.com, 443). - IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer, - "www.google.com", 443, "127.0.0.1"); - rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(OK, callback.WaitForResult()); diff --git a/net/http/http_network_transaction_spdy3_unittest.cc b/net/http/http_network_transaction_spdy3_unittest.cc index 4b67b28..c9da692 100644 --- a/net/http/http_network_transaction_spdy3_unittest.cc +++ b/net/http/http_network_transaction_spdy3_unittest.cc @@ -7744,7 +7744,8 @@ TEST_F(HttpNetworkTransactionSpdy3Test, scoped_refptr<SpdySession> spdy_session = session->spdy_session_pool()->Get(pair, BoundNetLog()); scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(host_port_pair, MEDIUM, false, false)); + new TransportSocketParams(host_port_pair, MEDIUM, false, false, + OnHostResolutionCallback())); scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); EXPECT_EQ(ERR_IO_PENDING, @@ -9004,7 +9005,8 @@ TEST_F(HttpNetworkTransactionSpdy3Test, PreconnectWithExistingSpdySession) { scoped_refptr<SpdySession> spdy_session = session->spdy_session_pool()->Get(pair, BoundNetLog()); scoped_refptr<TransportSocketParams> transport_params( - new TransportSocketParams(host_port_pair, MEDIUM, false, false)); + new TransportSocketParams(host_port_pair, MEDIUM, false, false, + OnHostResolutionCallback())); TestCompletionCallback callback; scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); @@ -9395,42 +9397,6 @@ TEST_F(HttpNetworkTransactionSpdy3Test, ClientAuthCertCache_Proxy_Fail) { } } -namespace { - -void IPPoolingAddAlias(MockCachingHostResolver* host_resolver, - SpdySessionPoolPeer* pool_peer, - std::string host, - int port, - std::string iplist) { - // Create a host resolver dependency that returns address |iplist| for - // resolutions of |host|. - host_resolver->rules()->AddIPLiteralRule(host, iplist, ""); - - // Setup a HostPortProxyPair. - HostPortPair host_port_pair(host, port); - HostPortProxyPair pair = HostPortProxyPair(host_port_pair, - ProxyServer::Direct()); - - // Resolve the host and port. - AddressList addresses; - HostResolver::RequestInfo info(host_port_pair); - TestCompletionCallback callback; - int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL, - BoundNetLog()); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); - DCHECK_EQ(OK, rv); - - // Add the first address as an alias. It would have been better to call - // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas - // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use - // the first address (127.0.0.1) returned by MockHostResolver as an alias for - // the |pair|. - pool_peer->AddAlias(addresses.front(), pair); -} - -} // namespace - TEST_F(HttpNetworkTransactionSpdy3Test, UseIPConnectionPooling) { HttpStreamFactory::set_use_alternate_protocols(true); HttpStreamFactory::SetNextProtos(SpdyNextProtos()); @@ -9476,8 +9442,13 @@ TEST_F(HttpNetworkTransactionSpdy3Test, UseIPConnectionPooling) { MockRead(ASYNC, 0, 7), }; + IPAddressNumber ip; + ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); + IPEndPoint peer_addr = IPEndPoint(ip, 443); + MockConnect connect(ASYNC, OK, peer_addr); scoped_ptr<OrderedSocketData> spdy_data( new OrderedSocketData( + connect, spdy_reads, arraysize(spdy_reads), spdy_writes, arraysize(spdy_writes))); session_deps.socket_factory.AddSocketDataProvider(spdy_data.get()); @@ -9512,11 +9483,104 @@ TEST_F(HttpNetworkTransactionSpdy3Test, UseIPConnectionPooling) { rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/ - // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair: - // (www.google.com, 443). - IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443, - "127.0.0.1"); + HttpRequestInfo request2; + request2.method = "GET"; + request2.url = GURL("https://www.gmail.com/"); + request2.load_flags = 0; + HttpNetworkTransaction trans2(session); + + rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_EQ(OK, callback.WaitForResult()); + + response = trans2.GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + EXPECT_TRUE(response->was_fetched_via_spdy); + EXPECT_TRUE(response->was_npn_negotiated); + ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); + EXPECT_EQ("hello!", response_data); + + HttpStreamFactory::SetNextProtos(std::vector<std::string>()); + HttpStreamFactory::set_use_alternate_protocols(false); +} + +TEST_F(HttpNetworkTransactionSpdy3Test, UseIPConnectionPoolingAfterResolution) { + HttpStreamFactory::set_use_alternate_protocols(true); + HttpStreamFactory::SetNextProtos(SpdyNextProtos()); + + // Set up a special HttpNetworkSession with a MockCachingHostResolver. + SessionDependencies session_deps; + MockCachingHostResolver host_resolver; + net::HttpNetworkSession::Params params; + params.client_socket_factory = &session_deps.socket_factory; + params.host_resolver = &host_resolver; + params.cert_verifier = session_deps.cert_verifier.get(); + params.proxy_service = session_deps.proxy_service.get(); + params.ssl_config_service = session_deps.ssl_config_service; + params.http_auth_handler_factory = + session_deps.http_auth_handler_factory.get(); + params.http_server_properties = &session_deps.http_server_properties; + params.net_log = session_deps.net_log; + scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params)); + SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); + pool_peer.DisableDomainAuthenticationVerification(); + + SSLSocketDataProvider ssl(ASYNC, OK); + ssl.SetNextProto(kProtoSPDY3); + session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + + scoped_ptr<SpdyFrame> host1_req(ConstructSpdyGet( + "https://www.google.com", false, 1, LOWEST)); + scoped_ptr<SpdyFrame> host2_req(ConstructSpdyGet( + "https://www.gmail.com", false, 3, LOWEST)); + MockWrite spdy_writes[] = { + CreateMockWrite(*host1_req, 1), + CreateMockWrite(*host2_req, 4), + }; + scoped_ptr<SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true)); + scoped_ptr<SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true)); + MockRead spdy_reads[] = { + CreateMockRead(*host1_resp, 2), + CreateMockRead(*host1_resp_body, 3), + CreateMockRead(*host2_resp, 5), + CreateMockRead(*host2_resp_body, 6), + MockRead(ASYNC, 0, 7), + }; + + IPAddressNumber ip; + ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); + IPEndPoint peer_addr = IPEndPoint(ip, 443); + MockConnect connect(ASYNC, OK, peer_addr); + scoped_ptr<OrderedSocketData> spdy_data( + new OrderedSocketData( + connect, + spdy_reads, arraysize(spdy_reads), + spdy_writes, arraysize(spdy_writes))); + session_deps.socket_factory.AddSocketDataProvider(spdy_data.get()); + + TestCompletionCallback callback; + HttpRequestInfo request1; + request1.method = "GET"; + request1.url = GURL("https://www.google.com/"); + request1.load_flags = 0; + HttpNetworkTransaction trans1(session); + + int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_EQ(OK, callback.WaitForResult()); + + const HttpResponseInfo* response = trans1.GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); + EXPECT_EQ("hello!", response_data); HttpRequestInfo request2; request2.method = "GET"; @@ -9627,8 +9691,13 @@ TEST_F(HttpNetworkTransactionSpdy3Test, MockRead(ASYNC, 0, 7), }; + IPAddressNumber ip; + ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); + IPEndPoint peer_addr = IPEndPoint(ip, 443); + MockConnect connect(ASYNC, OK, peer_addr); scoped_ptr<OrderedSocketData> spdy_data( new OrderedSocketData( + connect, spdy_reads, arraysize(spdy_reads), spdy_writes, arraysize(spdy_writes))); session_deps.socket_factory.AddSocketDataProvider(spdy_data.get()); @@ -9668,12 +9737,6 @@ TEST_F(HttpNetworkTransactionSpdy3Test, request2.load_flags = 0; HttpNetworkTransaction trans2(session); - // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/ - // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair: - // (www.google.com, 443). - IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer, - "www.google.com", 443, "127.0.0.1"); - rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(OK, callback.WaitForResult()); diff --git a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc index 8e46efe..5f7a8e0 100644 --- a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc @@ -53,7 +53,8 @@ class HttpProxyClientSocketPoolSpdy2Test : public TestWithHttpParam { HttpProxyClientSocketPoolSpdy2Test() : ssl_config_(), ignored_transport_socket_params_(new TransportSocketParams( - HostPortPair("proxy", 80), LOWEST, false, false)), + HostPortPair("proxy", 80), LOWEST, false, false, + OnHostResolutionCallback())), ignored_ssl_socket_params_(new SSLSocketParams( ignored_transport_socket_params_, NULL, NULL, ProxyServer::SCHEME_DIRECT, HostPortPair("www.google.com", 443), diff --git a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc index f1bf16a..bc0c62a 100644 --- a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc @@ -53,7 +53,8 @@ class HttpProxyClientSocketPoolSpdy3Test : public TestWithHttpParam { HttpProxyClientSocketPoolSpdy3Test() : ssl_config_(), ignored_transport_socket_params_(new TransportSocketParams( - HostPortPair("proxy", 80), LOWEST, false, false)), + HostPortPair("proxy", 80), LOWEST, false, false, + OnHostResolutionCallback())), ignored_ssl_socket_params_(new SSLSocketParams( ignored_transport_socket_params_, NULL, NULL, ProxyServer::SCHEME_DIRECT, HostPortPair("www.google.com", 443), diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 15cba9d..4b04a24 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc @@ -285,6 +285,15 @@ void HttpStreamFactoryImpl::Job::GetSSLInfo() { ssl_socket->GetSSLInfo(&ssl_info_); } +HostPortProxyPair HttpStreamFactoryImpl::Job::GetSpdySessionKey() const { + if (IsHttpsProxyAndHttpUrl()) { + return HostPortProxyPair(proxy_info_.proxy_server().host_port_pair(), + ProxyServer::Direct()); + } else { + return HostPortProxyPair(origin_, proxy_info_.proxy_server()); + } +} + void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { DCHECK(stream_.get()); DCHECK(!IsPreconnecting()); @@ -384,6 +393,20 @@ void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() { // |this| may be deleted after this call. } +// static +int HttpStreamFactoryImpl::Job::OnHostResolution( + SpdySessionPool* spdy_session_pool, + const HostPortProxyPair spdy_session_key, + const AddressList& addresses, + const BoundNetLog& net_log) { + // It is OK to dereference spdy_session_pool, because the + // ClientSocketPoolManager will be destroyed in the same callback that + // destroys the SpdySessionPool. + bool has_session = + spdy_session_pool->GetIfExists(spdy_session_key, net_log) != NULL; + return has_session ? ERR_SPDY_SESSION_ALREADY_EXISTS : OK; +} + void HttpStreamFactoryImpl::Job::OnIOComplete(int result) { RunLoop(result); } @@ -670,14 +693,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() { // Check first if we have a spdy session for this group. If so, then go // straight to using that. - HostPortProxyPair spdy_session_key; - if (IsHttpsProxyAndHttpUrl()) { - spdy_session_key = - HostPortProxyPair(proxy_info_.proxy_server().host_port_pair(), - ProxyServer::Direct()); - } else { - spdy_session_key = HostPortProxyPair(origin_, proxy_info_.proxy_server()); - } + HostPortProxyPair spdy_session_key = GetSpdySessionKey(); scoped_refptr<SpdySession> spdy_session = session_->spdy_session_pool()->GetIfExists(spdy_session_key, net_log_); if (spdy_session) { @@ -757,7 +773,11 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() { origin_url_, request_info_.extra_headers, request_info_.load_flags, request_info_.priority, session_, proxy_info_, ShouldForceSpdySSL(), want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_, net_log_, - connection_.get(), io_callback_); + connection_.get(), + //OnHostResolutionCallback(), + base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(), + GetSpdySessionKey()), + io_callback_); } } @@ -767,6 +787,22 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) { return OK; } + if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { + // We found a SPDY connection after resolving the host. This is + // probably an IP pooled connection. + HostPortProxyPair spdy_session_key = GetSpdySessionKey(); + existing_spdy_session_ = + session_->spdy_session_pool()->GetIfExists(spdy_session_key, net_log_); + if (existing_spdy_session_) { + using_spdy_ = true; + next_state_ = STATE_CREATE_STREAM; + } else { + // It is possible that the spdy session no longer exists. + ReturnToStateInitConnection(true /* close connection */); + } + return OK; + } + // TODO(willchan): Make this a bit more exact. Maybe there are recoverable // errors, such as ignoring certificate errors for Alternate-Protocol. if (result < 0 && waiting_job_) { @@ -1042,7 +1078,7 @@ void HttpStreamFactoryImpl::Job::SetSocketMotivation() { // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). } -bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() { +bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() const { if (!proxy_info_.is_https()) return false; if (original_url_.get()) { diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h index f03aab8..7b6bd07 100644 --- a/net/http/http_stream_factory_impl_job.h +++ b/net/http/http_stream_factory_impl_job.h @@ -26,6 +26,7 @@ class ClientSocketHandle; class HttpAuthController; class HttpNetworkSession; class HttpStream; +class SpdySessionPool; // An HttpStreamRequestImpl exists for each stream which is in progress of being // created for the StreamFactory. @@ -157,7 +158,7 @@ class HttpStreamFactoryImpl::Job { // Set the motivation for this request onto the underlying socket. void SetSocketMotivation(); - bool IsHttpsProxyAndHttpUrl(); + bool IsHttpsProxyAndHttpUrl() const; // Sets several fields of ssl_config for the given origin_server based on the // proxy info and other factors. @@ -172,6 +173,8 @@ class HttpStreamFactoryImpl::Job { // After calling, the caller can use ssl_info_. void GetSSLInfo(); + HostPortProxyPair GetSpdySessionKey() const; + // Called when we encounter a network error that could be resolved by trying // a new proxy configuration. If there is another proxy configuration to try // then this method sets next_state_ appropriately and returns either OK or @@ -202,6 +205,15 @@ class HttpStreamFactoryImpl::Job { // Record histograms of latency until Connect() completes. static void LogHttpConnectedMetrics(const ClientSocketHandle& handle); + // Invoked by the transport socket pool after host resolution is complete + // to allow the connection to be aborted, if a matching SPDY session can + // be found. Will return ERR_SPDY_SESSION_ALREADY_EXISTS if such a + // session is found, and OK otherwise. + static int OnHostResolution(SpdySessionPool* spdy_session_pool, + const HostPortProxyPair spdy_session_key, + const AddressList& addresses, + const BoundNetLog& net_log); + Request* request_; const HttpRequestInfo request_info_; |