Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: net/http/http_stream_factory_impl_job.cc

Issue 2260623002: Race TCP connection to proxies with QUIC connections (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_stream_factory_impl_job.h" 5 #include "net/http/http_stream_factory_impl_job.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/metrics/sparse_histogram.h" 16 #include "base/metrics/sparse_histogram.h"
17 #include "base/profiler/scoped_tracker.h" 17 #include "base/profiler/scoped_tracker.h"
18 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
19 #include "base/stl_util.h" 19 #include "base/stl_util.h"
20 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h" 22 #include "base/strings/stringprintf.h"
23 #include "base/threading/thread_task_runner_handle.h" 23 #include "base/threading/thread_task_runner_handle.h"
24 #include "base/trace_event/trace_event.h" 24 #include "base/trace_event/trace_event.h"
25 #include "base/values.h" 25 #include "base/values.h"
26 #include "build/build_config.h" 26 #include "build/build_config.h"
27 #include "net/base/port_util.h" 27 #include "net/base/port_util.h"
28 #include "net/base/proxy_delegate.h"
28 #include "net/cert/cert_verifier.h" 29 #include "net/cert/cert_verifier.h"
29 #include "net/http/bidirectional_stream_impl.h" 30 #include "net/http/bidirectional_stream_impl.h"
30 #include "net/http/http_basic_stream.h" 31 #include "net/http/http_basic_stream.h"
31 #include "net/http/http_network_session.h" 32 #include "net/http/http_network_session.h"
32 #include "net/http/http_proxy_client_socket.h" 33 #include "net/http/http_proxy_client_socket.h"
33 #include "net/http/http_proxy_client_socket_pool.h" 34 #include "net/http/http_proxy_client_socket_pool.h"
34 #include "net/http/http_request_info.h" 35 #include "net/http/http_request_info.h"
35 #include "net/http/http_server_properties.h" 36 #include "net/http/http_server_properties.h"
36 #include "net/http/http_stream_factory.h" 37 #include "net/http/http_stream_factory.h"
37 #include "net/http/http_stream_factory_impl_request.h" 38 #include "net/http/http_stream_factory_impl_request.h"
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 : Job(delegate, 155 : Job(delegate,
155 job_type, 156 job_type,
156 session, 157 session,
157 request_info, 158 request_info,
158 priority, 159 priority,
159 server_ssl_config, 160 server_ssl_config,
160 proxy_ssl_config, 161 proxy_ssl_config,
161 destination, 162 destination,
162 origin_url, 163 origin_url,
163 AlternativeService(), 164 AlternativeService(),
165 ProxyServer(),
164 net_log) {} 166 net_log) {}
165 167
166 HttpStreamFactoryImpl::Job::Job(Delegate* delegate, 168 HttpStreamFactoryImpl::Job::Job(Delegate* delegate,
167 JobType job_type, 169 JobType job_type,
168 HttpNetworkSession* session, 170 HttpNetworkSession* session,
169 const HttpRequestInfo& request_info, 171 const HttpRequestInfo& request_info,
170 RequestPriority priority, 172 RequestPriority priority,
171 const SSLConfig& server_ssl_config, 173 const SSLConfig& server_ssl_config,
172 const SSLConfig& proxy_ssl_config, 174 const SSLConfig& proxy_ssl_config,
173 HostPortPair destination, 175 HostPortPair destination,
174 GURL origin_url, 176 GURL origin_url,
175 AlternativeService alternative_service, 177 AlternativeService alternative_service,
178 const ProxyServer& alternative_proxy_server,
176 NetLog* net_log) 179 NetLog* net_log)
177 : request_info_(request_info), 180 : request_info_(request_info),
178 priority_(priority), 181 priority_(priority),
179 server_ssl_config_(server_ssl_config), 182 server_ssl_config_(server_ssl_config),
180 proxy_ssl_config_(proxy_ssl_config), 183 proxy_ssl_config_(proxy_ssl_config),
181 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP_STREAM_JOB)), 184 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP_STREAM_JOB)),
182 io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))), 185 io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))),
183 connection_(new ClientSocketHandle), 186 connection_(new ClientSocketHandle),
184 session_(session), 187 session_(session),
185 next_state_(STATE_NONE), 188 next_state_(STATE_NONE),
186 pac_request_(NULL), 189 pac_request_(NULL),
187 destination_(destination), 190 destination_(destination),
188 origin_url_(origin_url), 191 origin_url_(origin_url),
189 alternative_service_(alternative_service), 192 alternative_service_(alternative_service),
190 delegate_(delegate), 193 delegate_(delegate),
194 alternative_proxy_server_(alternative_proxy_server),
191 job_type_(job_type), 195 job_type_(job_type),
192 using_ssl_(false), 196 using_ssl_(false),
193 using_spdy_(false), 197 using_spdy_(false),
194 using_quic_(false), 198 using_quic_(false),
195 quic_request_(session_->quic_stream_factory()), 199 quic_request_(session_->quic_stream_factory()),
196 using_existing_quic_session_(false), 200 using_existing_quic_session_(false),
197 spdy_certificate_error_(OK), 201 spdy_certificate_error_(OK),
198 establishing_tunnel_(false), 202 establishing_tunnel_(false),
199 was_npn_negotiated_(false), 203 was_npn_negotiated_(false),
200 negotiated_protocol_(kProtoUnknown), 204 negotiated_protocol_(kProtoUnknown),
201 num_streams_(0), 205 num_streams_(0),
202 spdy_session_direct_(false), 206 spdy_session_direct_(false),
203 job_status_(STATUS_RUNNING), 207 job_status_(STATUS_RUNNING),
204 other_job_status_(STATUS_RUNNING), 208 other_job_status_(STATUS_RUNNING),
205 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), 209 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM),
206 ptr_factory_(this) { 210 ptr_factory_(this) {
207 DCHECK(session); 211 DCHECK(session);
212 // The job can't have alternative service and alternative proxy server set at
213 // the same time since alternative services are used for requests that are
214 // fetched directly, while the alternative proxy server is used for requests
215 // that should be fetched using proxy.
216 DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL ||
217 !alternative_proxy_server_.is_valid());
218 DCHECK(!alternative_proxy_server_.is_valid() ||
219 !(IsSpdyAlternative() || IsQuicAlternative()));
220 DCHECK_EQ(alternative_service_.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL ||
221 alternative_proxy_server_.is_valid(),
222 job_type_ == ALTERNATIVE);
223
208 if (IsSpdyAlternative()) { 224 if (IsSpdyAlternative()) {
209 DCHECK(origin_url_.SchemeIs("https")); 225 DCHECK(origin_url_.SchemeIs("https"));
210 } 226 }
211 if (IsQuicAlternative()) { 227 if (IsQuicAlternative()) {
212 DCHECK(session_->params().enable_quic); 228 DCHECK(session_->params().enable_quic);
213 using_quic_ = true; 229 using_quic_ = true;
214 } 230 }
215 } 231 }
216 232
217 HttpStreamFactoryImpl::Job::~Job() { 233 HttpStreamFactoryImpl::Job::~Job() {
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 DCHECK(!pac_request_); 710 DCHECK(!pac_request_);
695 DCHECK(session_); 711 DCHECK(session_);
696 712
697 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; 713 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
698 714
699 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { 715 if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
700 proxy_info_.UseDirect(); 716 proxy_info_.UseDirect();
701 return OK; 717 return OK;
702 } 718 }
703 719
720 // If an alternative proxy server was provided, use that.
721 if (alternative_proxy_server_.is_valid()) {
722 proxy_info_.UseProxyServer(alternative_proxy_server_);
723 return OK;
724 }
725
704 return session_->proxy_service()->ResolveProxy( 726 return session_->proxy_service()->ResolveProxy(
705 origin_url_, request_info_.method, &proxy_info_, io_callback_, 727 origin_url_, request_info_.method, &proxy_info_, io_callback_,
706 &pac_request_, session_->params().proxy_delegate, net_log_); 728 &pac_request_, session_->params().proxy_delegate, net_log_);
707 } 729 }
708 730
709 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { 731 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
710 pac_request_ = NULL; 732 pac_request_ = NULL;
711 733
712 if (result == OK) { 734 if (result == OK) {
713 // Remove unsupported proxies from the list. 735 // Remove unsupported proxies from the list.
(...skipping 17 matching lines...) Expand all
731 // user visible, because the non-alternative Job should be resumed. 753 // user visible, because the non-alternative Job should be resumed.
732 result = ERR_NO_SUPPORTED_PROXIES; 754 result = ERR_NO_SUPPORTED_PROXIES;
733 } 755 }
734 } 756 }
735 757
736 if (result != OK) { 758 if (result != OK) {
737 return result; 759 return result;
738 } 760 }
739 761
740 next_state_ = STATE_WAIT; 762 next_state_ = STATE_WAIT;
763
764 delegate_->OnResolveProxyComplete(this, request_info_, priority_,
765 server_ssl_config_, proxy_ssl_config_,
766 stream_type_);
767
741 return OK; 768 return OK;
742 } 769 }
743 770
744 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { 771 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
745 return session_->params().enable_quic && 772 return session_->params().enable_quic &&
746 (base::ContainsKey(session_->params().origins_to_force_quic_on, 773 (base::ContainsKey(session_->params().origins_to_force_quic_on,
747 HostPortPair()) || 774 HostPortPair()) ||
748 base::ContainsKey(session_->params().origins_to_force_quic_on, 775 base::ContainsKey(session_->params().origins_to_force_quic_on,
749 destination_)) && 776 destination_)) &&
750 proxy_info_.is_direct() && origin_url_.SchemeIs("https"); 777 proxy_info_.is_direct() && origin_url_.SchemeIs("https");
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 return error; 1414 return error;
1388 } 1415 }
1389 1416
1390 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. 1417 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG.
1391 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) 1418 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG)
1392 return error; 1419 return error;
1393 1420
1394 if (request_info_.load_flags & LOAD_BYPASS_PROXY) 1421 if (request_info_.load_flags & LOAD_BYPASS_PROXY)
1395 return error; 1422 return error;
1396 1423
1424 // Alternative proxy server job should not use fallback proxies, and instead
1425 // return. This would resume the main job (if possible) which may try the
1426 // fallback proxies.
1427 if (alternative_proxy_server_.is_valid()) {
1428 DCHECK_EQ(STATE_NONE, next_state_);
1429 return error;
1430 }
1431
1397 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { 1432 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
1398 session_->ssl_client_auth_cache()->Remove( 1433 session_->ssl_client_auth_cache()->Remove(
1399 proxy_info_.proxy_server().host_port_pair()); 1434 proxy_info_.proxy_server().host_port_pair());
1400 } 1435 }
1401 1436
1402 int rv = session_->proxy_service()->ReconsiderProxyAfterError( 1437 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1403 request_info_.url, request_info_.method, error, &proxy_info_, 1438 request_info_.url, request_info_.method, error, &proxy_info_,
1404 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_); 1439 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_);
1405 if (rv == OK || rv == ERR_IO_PENDING) { 1440 if (rv == OK || rv == ERR_IO_PENDING) {
1406 // If the error was during connection setup, there is no socket to 1441 // If the error was during connection setup, there is no socket to
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 // This Job was the alternative Job, and hence won the race. 1502 // This Job was the alternative Job, and hence won the race.
1468 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); 1503 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE);
1469 } else { 1504 } else {
1470 // This Job was the normal Job, and hence the alternative Job lost the race. 1505 // This Job was the normal Job, and hence the alternative Job lost the race.
1471 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); 1506 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE);
1472 } 1507 }
1473 } 1508 }
1474 1509
1475 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) { 1510 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) {
1476 DCHECK_EQ(STATUS_RUNNING, other_job_status_); 1511 DCHECK_EQ(STATUS_RUNNING, other_job_status_);
1512 DCHECK(!other_job_alternative_proxy_server_.is_valid());
1513
1477 other_job_status_ = job.job_status_; 1514 other_job_status_ = job.job_status_;
1478 other_job_alternative_service_ = job.alternative_service_; 1515 other_job_alternative_service_ = job.alternative_service_;
1516 other_job_alternative_proxy_server_ = job.alternative_proxy_server_;
1517
1518 // At most one job can have a valid |alternative_proxy_server_|.
1519 DCHECK(!alternative_proxy_server_.is_valid() ||
1520 !other_job_alternative_proxy_server_.is_valid());
1521
1479 MaybeMarkAlternativeServiceBroken(); 1522 MaybeMarkAlternativeServiceBroken();
1480 } 1523 }
1481 1524
1482 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() { 1525 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() {
1526 // At least one job should not be an alternative job.
1527 DCHECK(alternative_service_.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL ||
1528 other_job_alternative_service_.protocol ==
1529 UNINITIALIZED_ALTERNATE_PROTOCOL);
1530
1483 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING) 1531 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING)
1484 return; 1532 return;
1485 1533
1534 MaybeNotifyAlternativeProxyServerBroken();
1535
1486 if (IsSpdyAlternative() || IsQuicAlternative()) { 1536 if (IsSpdyAlternative() || IsQuicAlternative()) {
1487 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) { 1537 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) {
1488 HistogramBrokenAlternateProtocolLocation( 1538 HistogramBrokenAlternateProtocolLocation(
1489 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); 1539 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
1490 session_->http_server_properties()->MarkAlternativeServiceBroken( 1540 session_->http_server_properties()->MarkAlternativeServiceBroken(
1491 alternative_service_); 1541 alternative_service_);
1492 } 1542 }
1493 return; 1543 return;
1494 } 1544 }
1495 1545
1496 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ == 1546 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ ==
1497 STATUS_SUCCEEDED); 1547 STATUS_SUCCEEDED);
1498 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) { 1548 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) {
1499 HistogramBrokenAlternateProtocolLocation( 1549 HistogramBrokenAlternateProtocolLocation(
1500 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN); 1550 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN);
1501 session_->http_server_properties()->MarkAlternativeServiceBroken( 1551 session_->http_server_properties()->MarkAlternativeServiceBroken(
1502 other_job_alternative_service_); 1552 other_job_alternative_service_);
1503 } 1553 }
1504 } 1554 }
1505 1555
1556 void HttpStreamFactoryImpl::Job::MaybeNotifyAlternativeProxyServerBroken()
1557 const {
1558 if (!alternative_proxy_server_.is_valid() &&
1559 !other_job_alternative_proxy_server_.is_valid()) {
1560 // Neither of the two jobs used an alternative proxy server.
1561 return;
1562 }
1563
1564 // Neither this job, nor the other job should have used the alternative
1565 // service.
1566 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service_.protocol);
1567 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL,
1568 other_job_alternative_service_.protocol);
1569
1570 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
1571 if (!proxy_delegate)
1572 return;
1573
1574 if (alternative_proxy_server_.is_valid()) {
1575 // |this| connected to the alternative proxy server.
1576 if ((job_status_ == STATUS_BROKEN || job_status_ == STATUS_FAILED) &&
1577 other_job_status_ == STATUS_SUCCEEDED) {
1578 // Notify ProxyDelegate.
1579 proxy_delegate->OnAlternativeProxyBroken(alternative_proxy_server_);
1580 }
1581 return;
1582 }
1583
1584 if (other_job_alternative_proxy_server_.is_valid()) {
1585 // Other job connected to the alternative proxy server.
1586 if (job_status_ == STATUS_SUCCEEDED &&
1587 (other_job_status_ == STATUS_BROKEN ||
1588 other_job_status_ == STATUS_FAILED)) {
1589 // Notify ProxyDelegate.
1590 proxy_delegate->OnAlternativeProxyBroken(
1591 other_job_alternative_proxy_server_);
1592 }
1593 return;
1594 }
1595 }
1596
1506 ClientSocketPoolManager::SocketGroupType 1597 ClientSocketPoolManager::SocketGroupType
1507 HttpStreamFactoryImpl::Job::GetSocketGroup() const { 1598 HttpStreamFactoryImpl::Job::GetSocketGroup() const {
1508 std::string scheme = origin_url_.scheme(); 1599 std::string scheme = origin_url_.scheme();
1509 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative()) 1600 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative())
1510 return ClientSocketPoolManager::SSL_GROUP; 1601 return ClientSocketPoolManager::SSL_GROUP;
1511 1602
1512 if (scheme == "ftp") 1603 if (scheme == "ftp")
1513 return ClientSocketPoolManager::FTP_GROUP; 1604 return ClientSocketPoolManager::FTP_GROUP;
1514 1605
1515 return ClientSocketPoolManager::NORMAL_GROUP; 1606 return ClientSocketPoolManager::NORMAL_GROUP;
(...skipping 11 matching lines...) Expand all
1527 1618
1528 ConnectionAttempts socket_attempts = connection_->connection_attempts(); 1619 ConnectionAttempts socket_attempts = connection_->connection_attempts();
1529 if (connection_->socket()) { 1620 if (connection_->socket()) {
1530 connection_->socket()->GetConnectionAttempts(&socket_attempts); 1621 connection_->socket()->GetConnectionAttempts(&socket_attempts);
1531 } 1622 }
1532 1623
1533 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); 1624 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts);
1534 } 1625 }
1535 1626
1536 } // namespace net 1627 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698