OLD | NEW |
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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 int rv = RunLoop(OK); | 555 int rv = RunLoop(OK); |
556 DCHECK_EQ(ERR_IO_PENDING, rv); | 556 DCHECK_EQ(ERR_IO_PENDING, rv); |
557 return rv; | 557 return rv; |
558 } | 558 } |
559 | 559 |
560 int HttpStreamFactoryImpl::Job::DoStart() { | 560 int HttpStreamFactoryImpl::Job::DoStart() { |
561 int port = request_info_.url.EffectiveIntPort(); | 561 int port = request_info_.url.EffectiveIntPort(); |
562 origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port); | 562 origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port); |
563 origin_url_ = HttpStreamFactory::ApplyHostMappingRules( | 563 origin_url_ = HttpStreamFactory::ApplyHostMappingRules( |
564 request_info_.url, &origin_); | 564 request_info_.url, &origin_); |
| 565 http_pipelining_key_.reset(new HttpPipelinedHost::Key(origin_)); |
565 | 566 |
566 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB, | 567 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB, |
567 HttpStreamJobParameters::Create(request_info_.url, | 568 HttpStreamJobParameters::Create(request_info_.url, |
568 origin_url_)); | 569 origin_url_)); |
569 | 570 |
570 // Don't connect to restricted ports. | 571 // Don't connect to restricted ports. |
571 if (!IsPortAllowedByDefault(port) && !IsPortAllowedByOverride(port)) { | 572 if (!IsPortAllowedByDefault(port) && !IsPortAllowedByOverride(port)) { |
572 if (waiting_job_) { | 573 if (waiting_job_) { |
573 waiting_job_->Resume(this); | 574 waiting_job_->Resume(this); |
574 waiting_job_ = NULL; | 575 waiting_job_ = NULL; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 next_state_ = STATE_CREATE_STREAM; | 680 next_state_ = STATE_CREATE_STREAM; |
680 existing_spdy_session_ = spdy_session; | 681 existing_spdy_session_ = spdy_session; |
681 return OK; | 682 return OK; |
682 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { | 683 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { |
683 // Update the spdy session key for the request that launched this job. | 684 // Update the spdy session key for the request that launched this job. |
684 request_->SetSpdySessionKey(spdy_session_key); | 685 request_->SetSpdySessionKey(spdy_session_key); |
685 } else if (IsRequestEligibleForPipelining()) { | 686 } else if (IsRequestEligibleForPipelining()) { |
686 // TODO(simonjam): With pipelining, we might be better off using fewer | 687 // TODO(simonjam): With pipelining, we might be better off using fewer |
687 // connections and thus should make fewer preconnections. Explore | 688 // connections and thus should make fewer preconnections. Explore |
688 // preconnecting fewer than the requested num_connections. | 689 // preconnecting fewer than the requested num_connections. |
| 690 // |
| 691 // Separate note: A forced pipeline is always available if one exists for |
| 692 // this key. This is different than normal pipelines, which may be |
| 693 // unavailable or unusable. So, there is no need to worry about a race |
| 694 // between when a pipeline becomes available and when this job blocks. |
689 existing_available_pipeline_ = stream_factory_->http_pipelined_host_pool_. | 695 existing_available_pipeline_ = stream_factory_->http_pipelined_host_pool_. |
690 IsExistingPipelineAvailableForOrigin(origin_); | 696 IsExistingPipelineAvailableForKey(*http_pipelining_key_.get()); |
691 if (existing_available_pipeline_) { | 697 if (existing_available_pipeline_) { |
692 return OK; | 698 return OK; |
693 } else { | 699 } else { |
694 request_->SetHttpPipeliningKey(origin_); | 700 bool was_new_key = request_->SetHttpPipeliningKey( |
| 701 *http_pipelining_key_.get()); |
| 702 if (!was_new_key && session_->force_http_pipelining()) { |
| 703 return ERR_IO_PENDING; |
| 704 } |
695 } | 705 } |
696 } | 706 } |
697 | 707 |
698 // OK, there's no available SPDY session. Let |waiting_job_| resume if it's | 708 // OK, there's no available SPDY session. Let |waiting_job_| resume if it's |
699 // paused. | 709 // paused. |
700 | 710 |
701 if (waiting_job_) { | 711 if (waiting_job_) { |
702 waiting_job_->Resume(this); | 712 waiting_job_->Resume(this); |
703 waiting_job_ = NULL; | 713 waiting_job_ = NULL; |
704 } | 714 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 return OK; | 758 return OK; |
749 } | 759 } |
750 | 760 |
751 // TODO(willchan): Make this a bit more exact. Maybe there are recoverable | 761 // TODO(willchan): Make this a bit more exact. Maybe there are recoverable |
752 // errors, such as ignoring certificate errors for Alternate-Protocol. | 762 // errors, such as ignoring certificate errors for Alternate-Protocol. |
753 if (result < 0 && waiting_job_) { | 763 if (result < 0 && waiting_job_) { |
754 waiting_job_->Resume(this); | 764 waiting_job_->Resume(this); |
755 waiting_job_ = NULL; | 765 waiting_job_ = NULL; |
756 } | 766 } |
757 | 767 |
| 768 if (result < 0 && session_->force_http_pipelining()) { |
| 769 stream_factory_->AbortPipelinedRequestsWithKey( |
| 770 this, *http_pipelining_key_.get(), result, server_ssl_config_); |
| 771 } |
| 772 |
758 // |result| may be the result of any of the stacked pools. The following | 773 // |result| may be the result of any of the stacked pools. The following |
759 // logic is used when determining how to interpret an error. | 774 // logic is used when determining how to interpret an error. |
760 // If |result| < 0: | 775 // If |result| < 0: |
761 // and connection_->socket() != NULL, then the SSL handshake ran and it | 776 // and connection_->socket() != NULL, then the SSL handshake ran and it |
762 // is a potentially recoverable error. | 777 // is a potentially recoverable error. |
763 // and connection_->socket == NULL and connection_->is_ssl_error() is true, | 778 // and connection_->socket == NULL and connection_->is_ssl_error() is true, |
764 // then the SSL handshake ran with an unrecoverable error. | 779 // then the SSL handshake ran with an unrecoverable error. |
765 // otherwise, the error came from one of the other pools. | 780 // otherwise, the error came from one of the other pools. |
766 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() || | 781 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() || |
767 connection_->is_ssl_error()); | 782 connection_->is_ssl_error()); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 // need to plumb this through to the connect level. | 895 // need to plumb this through to the connect level. |
881 if (connection_->socket() && !connection_->is_reused()) | 896 if (connection_->socket() && !connection_->is_reused()) |
882 SetSocketMotivation(); | 897 SetSocketMotivation(); |
883 | 898 |
884 const ProxyServer& proxy_server = proxy_info_.proxy_server(); | 899 const ProxyServer& proxy_server = proxy_info_.proxy_server(); |
885 | 900 |
886 if (!using_spdy_) { | 901 if (!using_spdy_) { |
887 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && | 902 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && |
888 request_info_.url.SchemeIs("http"); | 903 request_info_.url.SchemeIs("http"); |
889 // TODO(simonjam): Support proxies. | 904 // TODO(simonjam): Support proxies. |
890 if (existing_available_pipeline_) { | 905 if (stream_factory_->http_pipelined_host_pool_. |
| 906 IsExistingPipelineAvailableForKey(*http_pipelining_key_.get())) { |
891 stream_.reset(stream_factory_->http_pipelined_host_pool_. | 907 stream_.reset(stream_factory_->http_pipelined_host_pool_. |
892 CreateStreamOnExistingPipeline(origin_)); | 908 CreateStreamOnExistingPipeline( |
| 909 *http_pipelining_key_.get())); |
893 CHECK(stream_.get()); | 910 CHECK(stream_.get()); |
894 } else if (!using_proxy && IsRequestEligibleForPipelining()) { | 911 } else if (!using_proxy && IsRequestEligibleForPipelining()) { |
895 stream_.reset( | 912 stream_.reset( |
896 stream_factory_->http_pipelined_host_pool_.CreateStreamOnNewPipeline( | 913 stream_factory_->http_pipelined_host_pool_.CreateStreamOnNewPipeline( |
897 origin_, | 914 *http_pipelining_key_.get(), |
898 connection_.release(), | 915 connection_.release(), |
899 server_ssl_config_, | 916 server_ssl_config_, |
900 proxy_info_, | 917 proxy_info_, |
901 net_log_, | 918 net_log_, |
902 was_npn_negotiated_, | 919 was_npn_negotiated_, |
903 protocol_negotiated_)); | 920 protocol_negotiated_)); |
904 CHECK(stream_.get()); | 921 CHECK(stream_.get()); |
905 } else { | 922 } else { |
906 stream_.reset(new HttpBasicStream(connection_.release(), NULL, | 923 stream_.reset(new HttpBasicStream(connection_.release(), NULL, |
907 using_proxy)); | 924 using_proxy)); |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { | 1219 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { |
1203 DCHECK_GE(num_streams_, 0); | 1220 DCHECK_GE(num_streams_, 0); |
1204 return num_streams_ > 0; | 1221 return num_streams_ > 0; |
1205 } | 1222 } |
1206 | 1223 |
1207 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { | 1224 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { |
1208 return !IsPreconnecting() && !request_; | 1225 return !IsPreconnecting() && !request_; |
1209 } | 1226 } |
1210 | 1227 |
1211 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() { | 1228 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() { |
| 1229 if (IsPreconnecting() || !request_) { |
| 1230 return false; |
| 1231 } |
| 1232 if (session_->force_http_pipelining()) { |
| 1233 return true; |
| 1234 } |
1212 if (!HttpStreamFactory::http_pipelining_enabled()) { | 1235 if (!HttpStreamFactory::http_pipelining_enabled()) { |
1213 return false; | 1236 return false; |
1214 } | 1237 } |
1215 if (IsPreconnecting() || !request_) { | |
1216 return false; | |
1217 } | |
1218 if (using_ssl_) { | 1238 if (using_ssl_) { |
1219 return false; | 1239 return false; |
1220 } | 1240 } |
1221 if (request_info_.method != "GET" && request_info_.method != "HEAD") { | 1241 if (request_info_.method != "GET" && request_info_.method != "HEAD") { |
1222 return false; | 1242 return false; |
1223 } | 1243 } |
1224 return stream_factory_->http_pipelined_host_pool_.IsHostEligibleForPipelining( | 1244 return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining( |
1225 origin_); | 1245 *http_pipelining_key_.get()); |
1226 } | 1246 } |
1227 | 1247 |
1228 } // namespace net | 1248 } // namespace net |
OLD | NEW |