diff options
author | jgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-19 12:51:50 +0000 |
---|---|---|
committer | jgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-19 12:51:50 +0000 |
commit | 1c173853f4a19b5328ad5154afb9a8fe600ae947 (patch) | |
tree | b29386815d965438feac08429475ceb00b54d632 /net/http | |
parent | f361a0d7b773112b60b80028aeaa2f42385d8487 (diff) | |
download | chromium_src-1c173853f4a19b5328ad5154afb9a8fe600ae947.zip chromium_src-1c173853f4a19b5328ad5154afb9a8fe600ae947.tar.gz chromium_src-1c173853f4a19b5328ad5154afb9a8fe600ae947.tar.bz2 |
Surface ERR_SPDY_SESSION_ALREADY_EXISTS to the proxy delegate.
Add a regression test, confirming that sessions which race host
resolutions don't fail network transactions.
BUG=334413
Review URL: https://codereview.chromium.org/346713003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278346 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 76 | ||||
-rw-r--r-- | net/http/http_proxy_client_socket_pool.cc | 7 |
2 files changed, 83 insertions, 0 deletions
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index d2ff7e9..01756a1 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -3028,6 +3028,82 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) { EXPECT_EQ(kUploadData, response_data); } +// Verifies that a session which races and wins against the owning transaction +// (completing prior to host resolution), doesn't fail the transaction. +// Regression test for crbug.com/334413. +TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) { + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.google.com/"); + request.load_flags = 0; + + // Configure SPDY proxy server "proxy:70". + session_deps_.proxy_service.reset( + ProxyService::CreateFixed("https://proxy:70")); + CapturingBoundNetLog log; + session_deps_.net_log = log.bound().net_log(); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + // Fetch http://www.google.com/ through the SPDY proxy. + scoped_ptr<SpdyFrame> req( + spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); + MockWrite spdy_writes[] = {CreateMockWrite(*req)}; + + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); + MockRead spdy_reads[] = { + CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0), + }; + + DelayedSocketData spdy_data( + 1, // wait for one write to finish before reading. + spdy_reads, + arraysize(spdy_reads), + spdy_writes, + arraysize(spdy_writes)); + session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); + + SSLSocketDataProvider ssl(ASYNC, OK); + ssl.SetNextProto(GetParam()); + session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); + + TestCompletionCallback callback1; + + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + + // Stall the hostname resolution begun by the transaction. + session_deps_.host_resolver->set_synchronous_mode(false); + session_deps_.host_resolver->set_ondemand_mode(true); + + int rv = trans->Start(&request, callback1.callback(), log.bound()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + // Race a session to the proxy, which completes first. + session_deps_.host_resolver->set_ondemand_mode(false); + SpdySessionKey key( + HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + base::WeakPtr<SpdySession> spdy_session = + CreateSecureSpdySession(session, key, log.bound()); + + // Unstall the resolution begun by the transaction. + session_deps_.host_resolver->set_ondemand_mode(true); + session_deps_.host_resolver->ResolveAllPending(); + + EXPECT_FALSE(callback1.have_result()); + rv = callback1.WaitForResult(); + EXPECT_EQ(OK, rv); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers.get() != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + EXPECT_EQ(kUploadData, response_data); +} + // Test a SPDY get through an HTTPS Proxy. TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) { HttpRequestInfo request; diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index 37ffa6d..829a5e7 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc @@ -237,6 +237,13 @@ int HttpProxyConnectJob::DoSSLConnectComplete(int result) { return ERR_PROXY_CERTIFICATE_INVALID; } } + // A SPDY session to the proxy completed prior to resolving the proxy + // hostname. Surface this error, and allow the delegate to retry. + // See crbug.com/334413. + if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { + DCHECK(!transport_socket_handle_->socket()); + return ERR_SPDY_SESSION_ALREADY_EXISTS; + } if (result < 0) { if (transport_socket_handle_->socket()) transport_socket_handle_->socket()->Disconnect(); |