summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-19 01:50:02 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-19 01:50:02 +0000
commiteb6234efc7ac3995b27b207e7d6ec66bf93c2b5a (patch)
tree68828f2253b05a33dda0f4bfffc032246547060e /net
parent75715c3104c131d1a0ea811afd4165f9d1412f80 (diff)
downloadchromium_src-eb6234efc7ac3995b27b207e7d6ec66bf93c2b5a.zip
chromium_src-eb6234efc7ac3995b27b207e7d6ec66bf93c2b5a.tar.gz
chromium_src-eb6234efc7ac3995b27b207e7d6ec66bf93c2b5a.tar.bz2
Fix a bug where an alternate protocol request to an unsafe port
would hang indefinitely, and a logging bug from the same original CL, add unit test. Buggy commit: http://codereview.chromium.org/8898008/ R=wtc@chromium.org BUG=93326 Review URL: http://codereview.chromium.org/9240012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118210 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_network_transaction_unittest.cc56
-rw-r--r--net/http/http_stream_factory_impl_job.cc56
-rw-r--r--net/http/http_stream_factory_impl_job.h8
3 files changed, 94 insertions, 26 deletions
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index cca2f8e..f0dad75 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6817,6 +6817,60 @@ TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
HttpStreamFactory::set_use_alternate_protocols(false);
}
+TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
+ // Ensure that we're not allowed to redirect traffic via an alternate
+ // protocol to an unsafe port, and that we resume the second
+ // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
+ HttpStreamFactory::set_use_alternate_protocols(true);
+ SessionDependencies session_deps;
+
+ HttpRequestInfo request;
+ request.method = "GET";
+ request.url = GURL("http://www.google.com/");
+ request.load_flags = 0;
+
+ // The alternate protocol request will error out before we attempt to connect,
+ // so only the standard HTTP request will try to connect.
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+ MockRead("hello world"),
+ MockRead(true, OK),
+ };
+ StaticSocketDataProvider data(
+ data_reads, arraysize(data_reads), NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data);
+
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
+
+ HttpServerProperties* http_server_properties =
+ session->http_server_properties();
+ const int kUnsafePort = 7;
+ http_server_properties->SetAlternateProtocol(
+ HostPortPair::FromURL(request.url),
+ kUnsafePort,
+ NPN_SPDY_2);
+
+ scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
+ TestCompletionCallback callback;
+
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ // The HTTP request should succeed.
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // Disable alternate protocol before the asserts.
+ HttpStreamFactory::set_use_alternate_protocols(false);
+
+ const HttpResponseInfo* response = trans->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(trans.get(), &response_data));
+ EXPECT_EQ("hello world", response_data);
+}
+
TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
HttpStreamFactory::set_use_alternate_protocols(true);
HttpStreamFactory::set_next_protos(SpdyNextProtos());
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index f401db6..9c5820c 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -123,7 +123,7 @@ HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
next_state_(STATE_NONE),
pac_request_(NULL),
blocking_job_(NULL),
- dependent_job_(NULL),
+ waiting_job_(NULL),
using_ssl_(false),
using_spdy_(false),
force_spdy_always_(HttpStreamFactory::force_spdy_always()),
@@ -211,9 +211,9 @@ void HttpStreamFactoryImpl::Job::WaitFor(Job* job) {
DCHECK_EQ(STATE_NONE, next_state_);
DCHECK_EQ(STATE_NONE, job->next_state_);
DCHECK(!blocking_job_);
- DCHECK(!job->dependent_job_);
+ DCHECK(!job->waiting_job_);
blocking_job_ = job;
- job->dependent_job_ = this;
+ job->waiting_job_ = this;
}
void HttpStreamFactoryImpl::Job::Resume(Job* job) {
@@ -236,8 +236,8 @@ void HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
// We've been orphaned, but there's a job we're blocked on. Don't bother
// racing, just cancel ourself.
if (blocking_job_) {
- DCHECK(blocking_job_->dependent_job_);
- blocking_job_->dependent_job_ = NULL;
+ DCHECK(blocking_job_->waiting_job_);
+ blocking_job_->waiting_job_ = NULL;
blocking_job_ = NULL;
stream_factory_->OnOrphanedJobComplete(this);
}
@@ -386,6 +386,10 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
if (result == ERR_IO_PENDING)
return result;
+ // If there was an error, we should have already resumed the |waiting_job_|,
+ // if there was one.
+ DCHECK(result == OK || waiting_job_ == NULL);
+
if (IsPreconnecting()) {
MessageLoop::current()->PostTask(
FROM_HERE,
@@ -549,24 +553,30 @@ int HttpStreamFactoryImpl::Job::DoLoop(int result) {
int HttpStreamFactoryImpl::Job::StartInternal() {
CHECK_EQ(STATE_NONE, next_state_);
next_state_ = STATE_START;
- net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB,
- HttpStreamJobParameters::Create(request_info_.url,
- origin_url_));
int rv = RunLoop(OK);
DCHECK_EQ(ERR_IO_PENDING, rv);
return rv;
}
int HttpStreamFactoryImpl::Job::DoStart() {
- // Don't connect to restricted ports.
int port = request_info_.url.EffectiveIntPort();
- if (!IsPortAllowedByDefault(port) && !IsPortAllowedByOverride(port))
- return ERR_UNSAFE_PORT;
-
origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port);
origin_url_ = HttpStreamFactory::ApplyHostMappingRules(
request_info_.url, &origin_);
+ net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB,
+ HttpStreamJobParameters::Create(request_info_.url,
+ origin_url_));
+
+ // Don't connect to restricted ports.
+ if (!IsPortAllowedByDefault(port) && !IsPortAllowedByOverride(port)) {
+ if (waiting_job_) {
+ waiting_job_->Resume(this);
+ waiting_job_ = NULL;
+ }
+ return ERR_UNSAFE_PORT;
+ }
+
next_state_ = STATE_RESOLVE_PROXY;
return OK;
}
@@ -603,8 +613,10 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
}
if (result != OK) {
- if (dependent_job_)
- dependent_job_->Resume(this);
+ if (waiting_job_) {
+ waiting_job_->Resume(this);
+ waiting_job_ = NULL;
+ }
return result;
}
@@ -684,12 +696,12 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
}
}
- // OK, there's no available SPDY session. Let |dependent_job_| resume if it's
+ // OK, there's no available SPDY session. Let |waiting_job_| resume if it's
// paused.
- if (dependent_job_) {
- dependent_job_->Resume(this);
- dependent_job_ = NULL;
+ if (waiting_job_) {
+ waiting_job_->Resume(this);
+ waiting_job_ = NULL;
}
if (proxy_info_.is_http() || proxy_info_.is_https())
@@ -739,9 +751,9 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
// TODO(willchan): Make this a bit more exact. Maybe there are recoverable
// errors, such as ignoring certificate errors for Alternate-Protocol.
- if (result < 0 && dependent_job_) {
- dependent_job_->Resume(this);
- dependent_job_ = NULL;
+ if (result < 0 && waiting_job_) {
+ waiting_job_->Resume(this);
+ waiting_job_ = NULL;
}
// |result| may be the result of any of the stacked pools. The following
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h
index e93b111..492a317 100644
--- a/net/http/http_stream_factory_impl_job.h
+++ b/net/http/http_stream_factory_impl_job.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -232,8 +232,10 @@ class HttpStreamFactoryImpl::Job {
// proceed.
Job* blocking_job_;
- // |dependent_job_| is dependent on |this|. Notify it when it's ok to proceed.
- Job* dependent_job_;
+ // |waiting_job_| is a Job waiting to see if |this| can reuse a connection.
+ // If |this| is unable to do so, we'll notify |waiting_job_| that it's ok to
+ // proceed and then race the two Jobs.
+ Job* waiting_job_;
// True if handling a HTTPS request, or using SPDY with SSL
bool using_ssl_;