summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 23:55:02 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 23:55:02 +0000
commitd2b5f09e54322cdd0c1046b6661324672a948394 (patch)
tree5d2012e2c6aa74847504caabff6a6dfb00d1aaaa /net/http
parentcc7823bc07a6f6a05e30a4670041c5b28f40c4aa (diff)
downloadchromium_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.cc163
-rw-r--r--net/http/http_network_transaction_spdy3_unittest.cc161
-rw-r--r--net/http/http_proxy_client_socket_pool_spdy2_unittest.cc3
-rw-r--r--net/http/http_proxy_client_socket_pool_spdy3_unittest.cc3
-rw-r--r--net/http/http_stream_factory_impl_job.cc56
-rw-r--r--net/http/http_stream_factory_impl_job.h14
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_;