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

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

Issue 2595413002: Race preconnects to HTTP2 proxies that support alternate proxies
Patch Set: ps Created 3 years, 11 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 <memory> 7 #include <memory>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 91
92 void HttpStreamFactoryImpl::JobController::Preconnect( 92 void HttpStreamFactoryImpl::JobController::Preconnect(
93 int num_streams, 93 int num_streams,
94 const HttpRequestInfo& request_info, 94 const HttpRequestInfo& request_info,
95 const SSLConfig& server_ssl_config, 95 const SSLConfig& server_ssl_config,
96 const SSLConfig& proxy_ssl_config) { 96 const SSLConfig& proxy_ssl_config) {
97 DCHECK(!main_job_); 97 DCHECK(!main_job_);
98 DCHECK(!alternative_job_); 98 DCHECK(!alternative_job_);
99 99
100 is_preconnect_ = true; 100 is_preconnect_ = true;
101
102 can_start_alternative_proxy_job_ =
103 session_->params().race_preconnects_to_proxies;
104
101 HostPortPair destination(HostPortPair::FromURL(request_info.url)); 105 HostPortPair destination(HostPortPair::FromURL(request_info.url));
102 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); 106 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
103 107
104 const AlternativeService alternative_service = GetAlternativeServiceFor( 108 const AlternativeService alternative_service = GetAlternativeServiceFor(
105 request_info, nullptr, HttpStreamRequest::HTTP_STREAM); 109 request_info, nullptr, HttpStreamRequest::HTTP_STREAM);
106 110
107 if (alternative_service.protocol != kProtoUnknown) { 111 if (alternative_service.protocol != kProtoUnknown) {
108 if (session_->params().quic_disable_preconnect_if_0rtt && 112 if (session_->params().quic_disable_preconnect_if_0rtt &&
109 alternative_service.protocol == kProtoQUIC && 113 alternative_service.protocol == kProtoQUIC &&
110 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( 114 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId(
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 HttpStreamRequest::StreamType stream_type) { 387 HttpStreamRequest::StreamType stream_type) {
384 DCHECK(job); 388 DCHECK(job);
385 389
386 ProxyServer alternative_proxy_server; 390 ProxyServer alternative_proxy_server;
387 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(), 391 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(),
388 request_info.url, 392 request_info.url,
389 &alternative_proxy_server)) { 393 &alternative_proxy_server)) {
390 return; 394 return;
391 } 395 }
392 396
393 DCHECK(main_job_); 397 DCHECK(is_preconnect_ || job->job_type() == MAIN);
394 DCHECK_EQ(MAIN, job->job_type()); 398 DCHECK_EQ(main_job_.get(), job);
395 DCHECK(!alternative_job_); 399 DCHECK(!alternative_job_);
396 DCHECK(!main_job_is_blocked_); 400 DCHECK(!main_job_is_blocked_);
401 DCHECK(alternative_proxy_server.is_quic());
Ryan Hamilton 2017/01/23 18:05:53 Why is this guaranteed to be true?
tbansal1 2017/01/23 21:48:22 Removed. (Currently it is true because QUIC is the
Ryan Hamilton 2017/01/24 19:36:59 We also support HTTP/2 based Alt-Svc.
402
403 if (is_preconnect_) {
404 // Restrict the number of streams to 1 since the proxy server supports spdy.
405 job->RestrictNumStreamsToOne();
Ryan Hamilton 2017/01/23 18:05:53 It seems like this is a bit orthogonal to racing a
tbansal1 2017/01/23 21:48:22 The preconnections for non-proxy http2 jobs restri
Ryan Hamilton 2017/01/24 19:36:59 Ah, I see. You're saying that "restrict to 1 strea
406 }
397 407
398 HostPortPair destination(HostPortPair::FromURL(request_info.url)); 408 HostPortPair destination(HostPortPair::FromURL(request_info.url));
399 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination); 409 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
400 410
401 alternative_job_.reset(job_factory_->CreateJob( 411 alternative_job_.reset(job_factory_->CreateJob(
402 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, 412 this, is_preconnect_ ? PRECONNECT : ALTERNATIVE, session_, request_info,
403 proxy_ssl_config, destination, origin_url, alternative_proxy_server, 413 priority, server_ssl_config, proxy_ssl_config, destination, origin_url,
404 job->net_log().net_log())); 414 alternative_proxy_server, job->net_log().net_log()));
405 AttachJob(alternative_job_.get()); 415
416 if (!is_preconnect_) {
417 // Preconnect jobs do not have an associated request. So, the preconnect
418 // job can't be attached.
419 AttachJob(alternative_job_.get());
420 }
406 421
407 can_start_alternative_proxy_job_ = false; 422 can_start_alternative_proxy_job_ = false;
408 main_job_is_blocked_ = true; 423 main_job_is_blocked_ = true;
409 424
410 base::ThreadTaskRunnerHandle::Get()->PostTask( 425 base::ThreadTaskRunnerHandle::Get()->PostTask(
411 FROM_HERE, 426 FROM_HERE,
412 base::Bind( 427 base::Bind(
413 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob, 428 &HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob,
414 ptr_factory_.GetWeakPtr())); 429 ptr_factory_.GetWeakPtr()));
415 } 430 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 factory->OnNewSpdySessionReady(spdy_session, direct, used_ssl_config, 490 factory->OnNewSpdySessionReady(spdy_session, direct, used_ssl_config,
476 used_proxy_info, was_alpn_negotiated, 491 used_proxy_info, was_alpn_negotiated,
477 negotiated_protocol, using_spdy, net_log); 492 negotiated_protocol, using_spdy, net_log);
478 } 493 }
479 if (is_job_orphaned) { 494 if (is_job_orphaned) {
480 OnOrphanedJobComplete(job); 495 OnOrphanedJobComplete(job);
481 } 496 }
482 } 497 }
483 498
484 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) { 499 void HttpStreamFactoryImpl::JobController::OnPreconnectsComplete(Job* job) {
485 DCHECK_EQ(main_job_.get(), job); 500 DCHECK(job);
486 main_job_.reset(); 501 DCHECK(main_job_.get() == job || alternative_job_.get() == job);
487 factory_->OnPreconnectsCompleteInternal(); 502 DCHECK_EQ(PRECONNECT, job->job_type());
488 MaybeNotifyFactoryOfCompletion(); 503 if (is_preconnect_ && main_job_ && alternative_job_) {
504 UMA_HISTOGRAM_EXACT_LINEAR("Net.QuicAlternativeProxy.PreconnectJobsRaced",
505 1, 2);
Ryan Hamilton 2017/01/23 18:05:53 I don't understand what this histogram is recordin
tbansal1 2017/01/23 21:48:23 It is just recording how many times preconnect job
506 }
507
508 // Note that completion of a preconnect job does not indicate that
509 // preconnection was actually successful since the socket layer currently does
510 // not provide the success or failure status of the (possibly) multiple
511 // preconnect sockets.
512 if (job == main_job_.get())
513 main_job_.reset();
514
515 if (job == alternative_job_.get())
516 alternative_job_.reset();
517
518 if (!main_job_ && !alternative_job_) {
519 factory_->OnPreconnectsCompleteInternal();
520 MaybeNotifyFactoryOfCompletion();
521 }
489 } 522 }
490 523
491 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete( 524 void HttpStreamFactoryImpl::JobController::OnOrphanedJobComplete(
492 const Job* job) { 525 const Job* job) {
493 if (job->job_type() == MAIN) { 526 if (job->job_type() == MAIN) {
494 DCHECK_EQ(main_job_.get(), job); 527 DCHECK_EQ(main_job_.get(), job);
495 main_job_.reset(); 528 main_job_.reset();
496 } else { 529 } else {
497 DCHECK_EQ(alternative_job_.get(), job); 530 DCHECK_EQ(alternative_job_.get(), job);
498 alternative_job_.reset(); 531 alternative_job_.reset();
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 can_start_alternative_proxy_job_ = true; 708 can_start_alternative_proxy_job_ = true;
676 } 709 }
677 // Even if |alternative_job| has already finished, it will not have notified 710 // Even if |alternative_job| has already finished, it will not have notified
678 // the request yet, since we defer that to the next iteration of the 711 // the request yet, since we defer that to the next iteration of the
679 // MessageLoop, so starting |main_job_| is always safe. 712 // MessageLoop, so starting |main_job_| is always safe.
680 main_job_->Start(request_->stream_type()); 713 main_job_->Start(request_->stream_type());
681 } 714 }
682 715
683 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { 716 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) {
684 DCHECK(job); 717 DCHECK(job);
718 DCHECK(!is_preconnect_);
685 factory_->request_map_[job] = request_; 719 factory_->request_map_[job] = request_;
686 } 720 }
687 721
688 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) { 722 void HttpStreamFactoryImpl::JobController::BindJob(Job* job) {
689 DCHECK(request_); 723 DCHECK(request_);
690 DCHECK(job); 724 DCHECK(job);
691 DCHECK(job == alternative_job_.get() || job == main_job_.get()); 725 DCHECK(job == alternative_job_.get() || job == main_job_.get());
692 DCHECK(!job_bound_); 726 DCHECK(!job_bound_);
693 DCHECK(!bound_job_); 727 DCHECK(!bound_job_);
694 728
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 // already been started. 1033 // already been started.
1000 return false; 1034 return false;
1001 } 1035 }
1002 1036
1003 if (job->job_type() == ALTERNATIVE) { 1037 if (job->job_type() == ALTERNATIVE) {
1004 // If |job| is using alternative service, then alternative proxy server 1038 // If |job| is using alternative service, then alternative proxy server
1005 // should not be used. 1039 // should not be used.
1006 return false; 1040 return false;
1007 } 1041 }
1008 1042
1009 if (is_preconnect_ || job->job_type() == PRECONNECT) {
1010 // Preconnects should be fetched using only the main job to keep the
1011 // resource utilization down.
1012 return false;
1013 }
1014
1015 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) { 1043 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) {
1016 // Alternative proxy server job can be created only if |job| fetches the 1044 // Alternative proxy server job can be created only if |job| fetches the
1017 // |request_| through a non-QUIC proxy. 1045 // |request_| through a non-QUIC proxy.
1018 return false; 1046 return false;
1019 } 1047 }
1020 1048
1021 if (!url.SchemeIs(url::kHttpScheme)) { 1049 if (!url.SchemeIs(url::kHttpScheme)) {
1022 // Only HTTP URLs can be fetched through alternative proxy server, since the 1050 // Only HTTP URLs can be fetched through alternative proxy server, since the
1023 // alternative proxy server may not support fetching of URLs with other 1051 // alternative proxy server may not support fetching of URLs with other
1024 // schemes. 1052 // schemes.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE, 1100 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_NO_RACE,
1073 proxy_server_used); 1101 proxy_server_used);
1074 return; 1102 return;
1075 } 1103 }
1076 1104
1077 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE, 1105 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE,
1078 proxy_server_used); 1106 proxy_server_used);
1079 } 1107 }
1080 1108
1081 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() { 1109 void HttpStreamFactoryImpl::JobController::StartAlternativeProxyServerJob() {
1082 if (!alternative_job_ || !request_) 1110 if (!alternative_job_)
1083 return; 1111 return;
1084 DCHECK(alternative_job_->alternative_proxy_server().is_valid()); 1112 DCHECK(alternative_job_->alternative_proxy_server().is_valid());
1085 alternative_job_->Start(request_->stream_type()); 1113
1114 if (!is_preconnect_) {
1115 if (!request_)
1116 return;
1117 DCHECK(alternative_job_->alternative_proxy_server().is_quic());
1118 alternative_job_->Start(request_->stream_type());
1119 } else {
1120 // Restrict the number of streams to 1 since the alternative proxy server
1121 // supports request priorities.
1122 DCHECK(alternative_job_->alternative_proxy_server().is_quic());
1123 alternative_job_->Preconnect(1 /* num_streams */);
1124 }
1086 } 1125 }
1087 1126
1088 } // namespace net 1127 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698