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

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, Addressed Ryan, Cherie comments Created 4 years, 4 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
208 if (IsSpdyAlternative()) { 221 if (IsSpdyAlternative()) {
209 DCHECK(origin_url_.SchemeIs("https")); 222 DCHECK(origin_url_.SchemeIs("https"));
210 } 223 }
211 if (IsQuicAlternative()) { 224 if (IsQuicAlternative()) {
212 DCHECK(session_->params().enable_quic); 225 DCHECK(session_->params().enable_quic);
213 using_quic_ = true; 226 using_quic_ = true;
214 } 227 }
215 } 228 }
216 229
217 HttpStreamFactoryImpl::Job::~Job() { 230 HttpStreamFactoryImpl::Job::~Job() {
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 DCHECK(!pac_request_); 707 DCHECK(!pac_request_);
695 DCHECK(session_); 708 DCHECK(session_);
696 709
697 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; 710 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
698 711
699 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { 712 if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
700 proxy_info_.UseDirect(); 713 proxy_info_.UseDirect();
701 return OK; 714 return OK;
702 } 715 }
703 716
717 // If an alternative proxy server was provided, use that.
718 if (alternative_proxy_server_.is_valid()) {
Zhongyi Shi 2016/08/20 06:15:40 nit: DCHECK_EQ(job_type_, ALTERNATIVE);
tbansal1 2016/08/22 15:42:33 good idea, I added a similar DCHECK in the constru
719 proxy_info_.UseProxyServer(alternative_proxy_server_);
720 return OK;
721 }
722
704 return session_->proxy_service()->ResolveProxy( 723 return session_->proxy_service()->ResolveProxy(
705 origin_url_, request_info_.method, &proxy_info_, io_callback_, 724 origin_url_, request_info_.method, &proxy_info_, io_callback_,
706 &pac_request_, session_->params().proxy_delegate, net_log_); 725 &pac_request_, session_->params().proxy_delegate, net_log_);
707 } 726 }
708 727
709 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { 728 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
710 pac_request_ = NULL; 729 pac_request_ = NULL;
711 730
712 if (result == OK) { 731 if (result == OK) {
713 // Remove unsupported proxies from the list. 732 // Remove unsupported proxies from the list.
(...skipping 17 matching lines...) Expand all
731 // user visible, because the non-alternative Job should be resumed. 750 // user visible, because the non-alternative Job should be resumed.
732 result = ERR_NO_SUPPORTED_PROXIES; 751 result = ERR_NO_SUPPORTED_PROXIES;
733 } 752 }
734 } 753 }
735 754
736 if (result != OK) { 755 if (result != OK) {
737 return result; 756 return result;
738 } 757 }
739 758
740 next_state_ = STATE_WAIT; 759 next_state_ = STATE_WAIT;
760
761 delegate_->OnResolveProxyComplete(this, request_info_, priority_,
762 server_ssl_config_, proxy_ssl_config_,
763 stream_type_);
764
741 return OK; 765 return OK;
742 } 766 }
743 767
744 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { 768 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
745 return session_->params().enable_quic && 769 return session_->params().enable_quic &&
746 (base::ContainsKey(session_->params().origins_to_force_quic_on, 770 (base::ContainsKey(session_->params().origins_to_force_quic_on,
747 HostPortPair()) || 771 HostPortPair()) ||
748 base::ContainsKey(session_->params().origins_to_force_quic_on, 772 base::ContainsKey(session_->params().origins_to_force_quic_on,
749 destination_)) && 773 destination_)) &&
750 proxy_info_.is_direct() && origin_url_.SchemeIs("https"); 774 proxy_info_.is_direct() && origin_url_.SchemeIs("https");
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 return error; 1411 return error;
1388 } 1412 }
1389 1413
1390 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. 1414 // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG.
1391 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) 1415 if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG)
1392 return error; 1416 return error;
1393 1417
1394 if (request_info_.load_flags & LOAD_BYPASS_PROXY) 1418 if (request_info_.load_flags & LOAD_BYPASS_PROXY)
1395 return error; 1419 return error;
1396 1420
1421 // Alternative proxy server job should not use fallback proxies, and instead
1422 // return. This would resume the main job (if possible) which may try the
1423 // fallback proxies.
1424 if (alternative_proxy_server_.is_valid()) {
1425 DCHECK_EQ(STATE_NONE, next_state_);
1426 return error;
1427 }
1428
1397 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { 1429 if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
1398 session_->ssl_client_auth_cache()->Remove( 1430 session_->ssl_client_auth_cache()->Remove(
1399 proxy_info_.proxy_server().host_port_pair()); 1431 proxy_info_.proxy_server().host_port_pair());
1400 } 1432 }
1401 1433
1402 int rv = session_->proxy_service()->ReconsiderProxyAfterError( 1434 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1403 request_info_.url, request_info_.method, error, &proxy_info_, 1435 request_info_.url, request_info_.method, error, &proxy_info_,
1404 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_); 1436 io_callback_, &pac_request_, session_->params().proxy_delegate, net_log_);
1405 if (rv == OK || rv == ERR_IO_PENDING) { 1437 if (rv == OK || rv == ERR_IO_PENDING) {
1406 // If the error was during connection setup, there is no socket to 1438 // 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. 1499 // This Job was the alternative Job, and hence won the race.
1468 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); 1500 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE);
1469 } else { 1501 } else {
1470 // This Job was the normal Job, and hence the alternative Job lost the race. 1502 // This Job was the normal Job, and hence the alternative Job lost the race.
1471 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); 1503 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE);
1472 } 1504 }
1473 } 1505 }
1474 1506
1475 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) { 1507 void HttpStreamFactoryImpl::Job::MarkOtherJobComplete(const Job& job) {
1476 DCHECK_EQ(STATUS_RUNNING, other_job_status_); 1508 DCHECK_EQ(STATUS_RUNNING, other_job_status_);
1509 DCHECK(!other_job_alternative_proxy_server_.is_valid());
1510
1477 other_job_status_ = job.job_status_; 1511 other_job_status_ = job.job_status_;
1478 other_job_alternative_service_ = job.alternative_service_; 1512 other_job_alternative_service_ = job.alternative_service_;
1513 other_job_alternative_proxy_server_ = job.alternative_proxy_server_;
1514
1515 // At most one job can have a valid |alternative_proxy_server_|.
1516 DCHECK(!alternative_proxy_server_.is_valid() ||
1517 !other_job_alternative_proxy_server_.is_valid());
1518
1479 MaybeMarkAlternativeServiceBroken(); 1519 MaybeMarkAlternativeServiceBroken();
1480 } 1520 }
1481 1521
1482 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() { 1522 void HttpStreamFactoryImpl::Job::MaybeMarkAlternativeServiceBroken() {
1483 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING) 1523 if (job_status_ == STATUS_RUNNING || other_job_status_ == STATUS_RUNNING)
1484 return; 1524 return;
1485 1525
1526 MaybeNotifyAlternativeProxyServerBroken();
1527
1486 if (IsSpdyAlternative() || IsQuicAlternative()) { 1528 if (IsSpdyAlternative() || IsQuicAlternative()) {
1487 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) { 1529 if (job_status_ == STATUS_BROKEN && other_job_status_ == STATUS_SUCCEEDED) {
1488 HistogramBrokenAlternateProtocolLocation( 1530 HistogramBrokenAlternateProtocolLocation(
1489 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); 1531 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT);
1490 session_->http_server_properties()->MarkAlternativeServiceBroken( 1532 session_->http_server_properties()->MarkAlternativeServiceBroken(
1491 alternative_service_); 1533 alternative_service_);
1492 } 1534 }
1493 return; 1535 return;
1494 } 1536 }
1495 1537
1496 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ == 1538 session_->quic_stream_factory()->OnTcpJobCompleted(job_status_ ==
1497 STATUS_SUCCEEDED); 1539 STATUS_SUCCEEDED);
1498 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) { 1540 if (job_status_ == STATUS_SUCCEEDED && other_job_status_ == STATUS_BROKEN) {
1499 HistogramBrokenAlternateProtocolLocation( 1541 HistogramBrokenAlternateProtocolLocation(
1500 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN); 1542 BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_MAIN);
1501 session_->http_server_properties()->MarkAlternativeServiceBroken( 1543 session_->http_server_properties()->MarkAlternativeServiceBroken(
1502 other_job_alternative_service_); 1544 other_job_alternative_service_);
1503 } 1545 }
1504 } 1546 }
1505 1547
1548 void HttpStreamFactoryImpl::Job::MaybeNotifyAlternativeProxyServerBroken()
1549 const {
1550 if (!alternative_proxy_server_.is_valid() &&
1551 !other_job_alternative_proxy_server_.is_valid()) {
Zhongyi Shi 2016/08/20 06:15:40 nit: DCHECK_EQ(alternative_service_.protocol != UN
tbansal1 2016/08/22 15:42:33 Isn't this the same as the DCHECKs in lInes 1558-1
Zhongyi Shi 2016/08/23 05:42:33 You won't be able to run the checks on line 1558-1
Zhongyi Shi 2016/08/23 05:42:33 I don't think those two checks has any correlation
tbansal1 2016/08/23 20:56:40 I think what you meant was: DCHECK(alternative_ser
1552 // Neither of the two jobs used an alternative proxy server.
1553 return;
1554 }
1555
1556 // Neither this job, nor the other job should have used the alternative
1557 // service.
1558 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL, alternative_service_.protocol);
1559 DCHECK_EQ(UNINITIALIZED_ALTERNATE_PROTOCOL,
1560 other_job_alternative_service_.protocol);
1561
1562 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
1563 if (!proxy_delegate)
1564 return;
1565
1566 if (alternative_proxy_server_.is_valid()) {
1567 // |this| connected to the alternative proxy server.
1568 if ((job_status_ == STATUS_BROKEN || job_status_ == STATUS_FAILED) &&
1569 other_job_status_ == STATUS_SUCCEEDED) {
1570 // Notify ProxyDelegate.
1571 proxy_delegate->OnAlternativeProxyBroken(alternative_proxy_server_);
1572 }
1573 return;
1574 }
1575
1576 if (other_job_alternative_proxy_server_.is_valid()) {
1577 // Other job connected to the alternative proxy server.
1578 if (job_status_ == STATUS_SUCCEEDED &&
1579 (other_job_status_ == STATUS_BROKEN ||
1580 other_job_status_ == STATUS_FAILED)) {
1581 // Notify ProxyDelegate.
1582 proxy_delegate->OnAlternativeProxyBroken(
1583 other_job_alternative_proxy_server_);
1584 }
1585 return;
1586 }
1587 }
1588
1506 ClientSocketPoolManager::SocketGroupType 1589 ClientSocketPoolManager::SocketGroupType
1507 HttpStreamFactoryImpl::Job::GetSocketGroup() const { 1590 HttpStreamFactoryImpl::Job::GetSocketGroup() const {
1508 std::string scheme = origin_url_.scheme(); 1591 std::string scheme = origin_url_.scheme();
1509 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative()) 1592 if (scheme == "https" || scheme == "wss" || IsSpdyAlternative())
1510 return ClientSocketPoolManager::SSL_GROUP; 1593 return ClientSocketPoolManager::SSL_GROUP;
1511 1594
1512 if (scheme == "ftp") 1595 if (scheme == "ftp")
1513 return ClientSocketPoolManager::FTP_GROUP; 1596 return ClientSocketPoolManager::FTP_GROUP;
1514 1597
1515 return ClientSocketPoolManager::NORMAL_GROUP; 1598 return ClientSocketPoolManager::NORMAL_GROUP;
(...skipping 11 matching lines...) Expand all
1527 1610
1528 ConnectionAttempts socket_attempts = connection_->connection_attempts(); 1611 ConnectionAttempts socket_attempts = connection_->connection_attempts();
1529 if (connection_->socket()) { 1612 if (connection_->socket()) {
1530 connection_->socket()->GetConnectionAttempts(&socket_attempts); 1613 connection_->socket()->GetConnectionAttempts(&socket_attempts);
1531 } 1614 }
1532 1615
1533 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts); 1616 delegate_->AddConnectionAttemptsToRequest(this, socket_attempts);
1534 } 1617 }
1535 1618
1536 } // namespace net 1619 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698