summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorjgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-19 12:51:50 +0000
committerjgraettinger@chromium.org <jgraettinger@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-19 12:51:50 +0000
commit1c173853f4a19b5328ad5154afb9a8fe600ae947 (patch)
treeb29386815d965438feac08429475ceb00b54d632 /net/http
parentf361a0d7b773112b60b80028aeaa2f42385d8487 (diff)
downloadchromium_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.cc76
-rw-r--r--net/http/http_proxy_client_socket_pool.cc7
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();