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

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

Issue 2260623002: Race TCP connection to proxies with QUIC connections (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Cherie's 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) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 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_controller.h" 5 #include "net/http/http_stream_factory_impl_job_controller.h"
6 6
7 #include "base/metrics/histogram_macros.h" 7 #include "base/metrics/histogram_macros.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/values.h" 10 #include "base/values.h"
11 #include "net/base/host_mapping_rules.h" 11 #include "net/base/host_mapping_rules.h"
12 #include "net/base/proxy_delegate.h"
12 #include "net/http/bidirectional_stream_impl.h" 13 #include "net/http/bidirectional_stream_impl.h"
13 #include "net/http/transport_security_state.h" 14 #include "net/http/transport_security_state.h"
15 #include "net/proxy/proxy_server.h"
14 #include "net/spdy/spdy_session.h" 16 #include "net/spdy/spdy_session.h"
15 17
16 namespace net { 18 namespace net {
17 19
18 // Returns parameters associated with the delay of the HTTP stream job. 20 // Returns parameters associated with the delay of the HTTP stream job.
19 std::unique_ptr<base::Value> NetLogHttpStreamJobDelayCallback( 21 std::unique_ptr<base::Value> NetLogHttpStreamJobDelayCallback(
20 base::TimeDelta delay, 22 base::TimeDelta delay,
21 NetLogCaptureMode /* capture_mode */) { 23 NetLogCaptureMode /* capture_mode */) {
22 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 24 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
23 dict->SetInteger("resume_after_ms", static_cast<int>(delay.InMilliseconds())); 25 dict->SetInteger("resume_after_ms", static_cast<int>(delay.InMilliseconds()));
24 return std::move(dict); 26 return std::move(dict);
25 } 27 }
26 28
27 HttpStreamFactoryImpl::JobController::JobController( 29 HttpStreamFactoryImpl::JobController::JobController(
28 HttpStreamFactoryImpl* factory, 30 HttpStreamFactoryImpl* factory,
29 HttpStreamRequest::Delegate* delegate, 31 HttpStreamRequest::Delegate* delegate,
30 HttpNetworkSession* session, 32 HttpNetworkSession* session,
31 JobFactory* job_factory) 33 JobFactory* job_factory)
32 : factory_(factory), 34 : factory_(factory),
33 session_(session), 35 session_(session),
34 job_factory_(job_factory), 36 job_factory_(job_factory),
35 request_(nullptr), 37 request_(nullptr),
36 delegate_(delegate), 38 delegate_(delegate),
37 is_preconnect_(false), 39 is_preconnect_(false),
38 job_bound_(false), 40 job_bound_(false),
39 main_job_is_blocked_(false), 41 main_job_is_blocked_(false),
40 bound_job_(nullptr), 42 bound_job_(nullptr),
43 can_start_alternative_proxy_job_(false),
41 ptr_factory_(this) { 44 ptr_factory_(this) {
42 DCHECK(factory); 45 DCHECK(factory);
43 } 46 }
44 47
45 HttpStreamFactoryImpl::JobController::~JobController() { 48 HttpStreamFactoryImpl::JobController::~JobController() {
46 main_job_.reset(); 49 main_job_.reset();
47 alternative_job_.reset(); 50 alternative_job_.reset();
48 bound_job_ = nullptr; 51 bound_job_ = nullptr;
49 } 52 }
50 53
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 ignore_result(ApplyHostMappingRules(request_info.url, &destination)); 105 ignore_result(ApplyHostMappingRules(request_info.url, &destination));
103 } 106 }
104 107
105 // Due to how the socket pools handle priorities and idle sockets, only IDLE 108 // Due to how the socket pools handle priorities and idle sockets, only IDLE
106 // priority currently makes sense for preconnects. The priority for 109 // priority currently makes sense for preconnects. The priority for
107 // preconnects is currently ignored (see RequestSocketsForPool()), but could 110 // preconnects is currently ignored (see RequestSocketsForPool()), but could
108 // be used at some point for proxy resolution or something. 111 // be used at some point for proxy resolution or something.
109 main_job_.reset(job_factory_->CreateJob( 112 main_job_.reset(job_factory_->CreateJob(
110 this, PRECONNECT, session_, request_info, IDLE, server_ssl_config, 113 this, PRECONNECT, session_, request_info, IDLE, server_ssl_config,
111 proxy_ssl_config, destination, origin_url, alternative_service, 114 proxy_ssl_config, destination, origin_url, alternative_service,
112 session_->net_log())); 115 ProxyServer(), session_->net_log()));
113 main_job_->Preconnect(num_streams); 116 main_job_->Preconnect(num_streams);
114 } 117 }
115 118
116 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const { 119 LoadState HttpStreamFactoryImpl::JobController::GetLoadState() const {
117 DCHECK(request_); 120 DCHECK(request_);
118 DCHECK(main_job_ || alternative_job_); 121 DCHECK(main_job_ || alternative_job_);
119 if (bound_job_) 122 if (bound_job_)
120 return bound_job_->GetLoadState(); 123 return bound_job_->GetLoadState();
121 124
122 // Just pick the first one. 125 // Just pick the first one.
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 } 351 }
349 352
350 if (!request_) 353 if (!request_)
351 return; 354 return;
352 if (!bound_job_) 355 if (!bound_job_)
353 BindJob(job); 356 BindJob(job);
354 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, 357 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info,
355 auth_controller); 358 auth_controller);
356 } 359 }
357 360
361 void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete(
362 Job* job,
363 const HttpRequestInfo& request_info,
364 RequestPriority priority,
365 const SSLConfig& server_ssl_config,
366 const SSLConfig& proxy_ssl_config,
367 HttpStreamRequest::StreamType stream_type) {
368 DCHECK(job);
369
370 ProxyServer alternative_proxy_server;
371 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(),
372 request_info.url,
373 &alternative_proxy_server)) {
374 return;
375 }
376
377 DCHECK(main_job_);
378 DCHECK(!alternative_job_);
379 DCHECK(!main_job_is_blocked_);
380
381 HostPortPair destination(HostPortPair::FromURL(request_info.url));
382 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
383
384 alternative_job_.reset(job_factory_->CreateJob(
385 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config,
386 proxy_ssl_config, destination, origin_url, AlternativeService(),
387 alternative_proxy_server, job->net_log().net_log()));
388 AttachJob(alternative_job_.get());
389
390 can_start_alternative_proxy_job_ = false;
391 main_job_is_blocked_ = true;
392
393 base::ThreadTaskRunnerHandle::Get()->PostTask(
394 FROM_HERE, base::Bind(&HttpStreamFactoryImpl::Job::Start,
395 base::Unretained(alternative_job_.get()),
396 request_->stream_type()));
397 }
398
358 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( 399 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
359 Job* job, 400 Job* job,
360 const base::WeakPtr<SpdySession>& spdy_session, 401 const base::WeakPtr<SpdySession>& spdy_session,
361 bool direct) { 402 bool direct) {
362 DCHECK(job); 403 DCHECK(job);
363 DCHECK(job->using_spdy()); 404 DCHECK(job->using_spdy());
364 405
365 bool is_job_orphaned = job_bound_ && bound_job_ != job; 406 bool is_job_orphaned = job_bound_ && bound_job_ != job;
366 407
367 // Cache these values in case the job gets deleted. 408 // Cache these values in case the job gets deleted.
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 << " port: " << alternative_service.host_port_pair().port() << ")"; 636 << " port: " << alternative_service.host_port_pair().port() << ")";
596 637
597 DCHECK(!request_info.url.SchemeIs("ftp")); 638 DCHECK(!request_info.url.SchemeIs("ftp"));
598 HostPortPair alternative_destination(alternative_service.host_port_pair()); 639 HostPortPair alternative_destination(alternative_service.host_port_pair());
599 ignore_result( 640 ignore_result(
600 ApplyHostMappingRules(request_info.url, &alternative_destination)); 641 ApplyHostMappingRules(request_info.url, &alternative_destination));
601 642
602 alternative_job_.reset(job_factory_->CreateJob( 643 alternative_job_.reset(job_factory_->CreateJob(
603 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, 644 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config,
604 proxy_ssl_config, alternative_destination, origin_url, 645 proxy_ssl_config, alternative_destination, origin_url,
605 alternative_service, net_log.net_log())); 646 alternative_service, ProxyServer(), net_log.net_log()));
606 AttachJob(alternative_job_.get()); 647 AttachJob(alternative_job_.get());
607 648
608 main_job_is_blocked_ = true; 649 main_job_is_blocked_ = true;
609 alternative_job_->Start(request_->stream_type()); 650 alternative_job_->Start(request_->stream_type());
651 } else {
652 can_start_alternative_proxy_job_ = true;
610 } 653 }
611 // Even if |alternative_job| has already finished, it will not have notified 654 // Even if |alternative_job| has already finished, it will not have notified
612 // the request yet, since we defer that to the next iteration of the 655 // the request yet, since we defer that to the next iteration of the
613 // MessageLoop, so starting |main_job_| is always safe. 656 // MessageLoop, so starting |main_job_| is always safe.
614 main_job_->Start(request_->stream_type()); 657 main_job_->Start(request_->stream_type());
615 } 658 }
616 659
617 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { 660 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) {
618 DCHECK(job); 661 DCHECK(job);
619 factory_->request_map_[job] = request_; 662 factory_->request_map_[job] = request_;
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) 931 if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
889 first_alternative_service = alternative_service; 932 first_alternative_service = alternative_service;
890 } 933 }
891 934
892 // Ask delegate to mark QUIC as broken for the origin. 935 // Ask delegate to mark QUIC as broken for the origin.
893 if (quic_advertised && quic_all_broken && delegate != nullptr) 936 if (quic_advertised && quic_all_broken && delegate != nullptr)
894 delegate->OnQuicBroken(); 937 delegate->OnQuicBroken();
895 938
896 return first_alternative_service; 939 return first_alternative_service;
897 } 940 }
941
942 bool HttpStreamFactoryImpl::JobController::
943 ShouldCreateAlternativeProxyServerJob(
944 Job* job,
945 const ProxyInfo& proxy_info,
946 const GURL& url,
947 ProxyServer* alternative_proxy_server) const {
948 DCHECK(!alternative_proxy_server->is_valid());
949 if (!can_start_alternative_proxy_job_) {
950 // Either an alternative service job or an alternative proxy server job has
951 // already been started.
952 return false;
953 }
954
955 if (job->job_type() == ALTERNATIVE) {
956 // If |job| is using alternative service, then alternative proxy server
957 // should not be used.
958 return false;
959 }
960
961 if (job->job_type() == PRECONNECT) {
962 // Preconnects should be fetched using only the main job to keep the
963 // resource utilization down.
964 return false;
965 }
966
967 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) {
968 // Alternative proxy server job can be created only if |job| fetches the
969 // |request_| through a non-QUIC proxy.
970 return false;
971 }
972
973 if (!url.SchemeIs(url::kHttpScheme)) {
974 // Only HTTP URLs can be fetched through alternative proxy server, since the
975 // alternative proxy server may not support fetching of URLs with other
976 // schemes.
977 return false;
978 }
979
980 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
981 if (!proxy_delegate)
982 return false;
983
984 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(),
985 alternative_proxy_server);
986
987 if (!alternative_proxy_server->is_valid())
988 return false;
989
990 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server()));
991
992 if (!alternative_proxy_server->is_https() &&
993 !alternative_proxy_server->is_quic()) {
994 // Alternative proxy server should be a secure server.
995 return false;
996 }
997
998 if (alternative_proxy_server->is_quic()) {
999 // Check that QUIC is enabled globally, and it is not disabled on
1000 // the specified port.
1001 if (!session_->params().enable_quic ||
1002 session_->quic_stream_factory()->IsQuicDisabled(
1003 alternative_proxy_server->host_port_pair().port())) {
1004 return false;
1005 }
1006 }
1007
1008 return true;
898 } 1009 }
1010 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698