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

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

Issue 275953002: Remove HTTP pipelining support. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge Created 6 years, 7 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 | Annotate | Revision Log
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 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/stl_util.h" 13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #include "base/values.h" 16 #include "base/values.h"
17 #include "build/build_config.h" 17 #include "build/build_config.h"
18 #include "net/base/connection_type_histograms.h" 18 #include "net/base/connection_type_histograms.h"
19 #include "net/base/net_log.h" 19 #include "net/base/net_log.h"
20 #include "net/base/net_util.h" 20 #include "net/base/net_util.h"
21 #include "net/http/http_basic_stream.h" 21 #include "net/http/http_basic_stream.h"
22 #include "net/http/http_network_session.h" 22 #include "net/http/http_network_session.h"
23 #include "net/http/http_pipelined_connection.h"
24 #include "net/http/http_pipelined_host.h"
25 #include "net/http/http_pipelined_host_pool.h"
26 #include "net/http/http_pipelined_stream.h"
27 #include "net/http/http_proxy_client_socket.h" 23 #include "net/http/http_proxy_client_socket.h"
28 #include "net/http/http_proxy_client_socket_pool.h" 24 #include "net/http/http_proxy_client_socket_pool.h"
29 #include "net/http/http_request_info.h" 25 #include "net/http/http_request_info.h"
30 #include "net/http/http_server_properties.h" 26 #include "net/http/http_server_properties.h"
31 #include "net/http/http_stream_factory.h" 27 #include "net/http/http_stream_factory.h"
32 #include "net/http/http_stream_factory_impl_request.h" 28 #include "net/http/http_stream_factory_impl_request.h"
33 #include "net/quic/quic_http_stream.h" 29 #include "net/quic/quic_http_stream.h"
34 #include "net/socket/client_socket_handle.h" 30 #include "net/socket/client_socket_handle.h"
35 #include "net/socket/client_socket_pool.h" 31 #include "net/socket/client_socket_pool.h"
36 #include "net/socket/client_socket_pool_manager.h" 32 #include "net/socket/client_socket_pool_manager.h"
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 quic_request_(session_->quic_stream_factory()), 96 quic_request_(session_->quic_stream_factory()),
101 using_existing_quic_session_(false), 97 using_existing_quic_session_(false),
102 force_spdy_always_(HttpStreamFactory::force_spdy_always()), 98 force_spdy_always_(HttpStreamFactory::force_spdy_always()),
103 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()), 99 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()),
104 spdy_certificate_error_(OK), 100 spdy_certificate_error_(OK),
105 establishing_tunnel_(false), 101 establishing_tunnel_(false),
106 was_npn_negotiated_(false), 102 was_npn_negotiated_(false),
107 protocol_negotiated_(kProtoUnknown), 103 protocol_negotiated_(kProtoUnknown),
108 num_streams_(0), 104 num_streams_(0),
109 spdy_session_direct_(false), 105 spdy_session_direct_(false),
110 existing_available_pipeline_(false),
111 ptr_factory_(this) { 106 ptr_factory_(this) {
112 DCHECK(stream_factory); 107 DCHECK(stream_factory);
113 DCHECK(session); 108 DCHECK(session);
114 } 109 }
115 110
116 HttpStreamFactoryImpl::Job::~Job() { 111 HttpStreamFactoryImpl::Job::~Job() {
117 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB); 112 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB);
118 113
119 // When we're in a partially constructed state, waiting for the user to 114 // When we're in a partially constructed state, waiting for the user to
120 // provide certificate handling information or authentication, we can't reuse 115 // provide certificate handling information or authentication, we can't reuse
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 int rv = RunLoop(OK); 604 int rv = RunLoop(OK);
610 DCHECK_EQ(ERR_IO_PENDING, rv); 605 DCHECK_EQ(ERR_IO_PENDING, rv);
611 return rv; 606 return rv;
612 } 607 }
613 608
614 int HttpStreamFactoryImpl::Job::DoStart() { 609 int HttpStreamFactoryImpl::Job::DoStart() {
615 int port = request_info_.url.EffectiveIntPort(); 610 int port = request_info_.url.EffectiveIntPort();
616 origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port); 611 origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port);
617 origin_url_ = stream_factory_->ApplyHostMappingRules( 612 origin_url_ = stream_factory_->ApplyHostMappingRules(
618 request_info_.url, &origin_); 613 request_info_.url, &origin_);
619 http_pipelining_key_.reset(new HttpPipelinedHost::Key(origin_));
620 614
621 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB, 615 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB,
622 base::Bind(&NetLogHttpStreamJobCallback, 616 base::Bind(&NetLogHttpStreamJobCallback,
623 &request_info_.url, &origin_url_, 617 &request_info_.url, &origin_url_,
624 priority_)); 618 priority_));
625 619
626 // Don't connect to restricted ports. 620 // Don't connect to restricted ports.
627 bool is_port_allowed = IsPortAllowedByDefault(port); 621 bool is_port_allowed = IsPortAllowedByDefault(port);
628 if (request_info_.url.SchemeIs("ftp")) { 622 if (request_info_.url.SchemeIs("ftp")) {
629 // Never share connection with other jobs for FTP requests. 623 // Never share connection with other jobs for FTP requests.
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 // actually need to preconnect any sockets, so we're done. 771 // actually need to preconnect any sockets, so we're done.
778 if (IsPreconnecting()) 772 if (IsPreconnecting())
779 return OK; 773 return OK;
780 using_spdy_ = true; 774 using_spdy_ = true;
781 next_state_ = STATE_CREATE_STREAM; 775 next_state_ = STATE_CREATE_STREAM;
782 existing_spdy_session_ = spdy_session; 776 existing_spdy_session_ = spdy_session;
783 return OK; 777 return OK;
784 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { 778 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) {
785 // Update the spdy session key for the request that launched this job. 779 // Update the spdy session key for the request that launched this job.
786 request_->SetSpdySessionKey(spdy_session_key); 780 request_->SetSpdySessionKey(spdy_session_key);
787 } else if (IsRequestEligibleForPipelining()) {
788 // TODO(simonjam): With pipelining, we might be better off using fewer
789 // connections and thus should make fewer preconnections. Explore
790 // preconnecting fewer than the requested num_connections.
791 //
792 // Separate note: A forced pipeline is always available if one exists for
793 // this key. This is different than normal pipelines, which may be
794 // unavailable or unusable. So, there is no need to worry about a race
795 // between when a pipeline becomes available and when this job blocks.
796 existing_available_pipeline_ = stream_factory_->http_pipelined_host_pool_.
797 IsExistingPipelineAvailableForKey(*http_pipelining_key_.get());
798 if (existing_available_pipeline_) {
799 return OK;
800 } else {
801 bool was_new_key = request_->SetHttpPipeliningKey(
802 *http_pipelining_key_.get());
803 if (!was_new_key && session_->force_http_pipelining()) {
804 return ERR_IO_PENDING;
805 }
806 }
807 } 781 }
808 782
809 // OK, there's no available SPDY session. Let |waiting_job_| resume if it's 783 // OK, there's no available SPDY session. Let |waiting_job_| resume if it's
810 // paused. 784 // paused.
811 785
812 if (waiting_job_) { 786 if (waiting_job_) {
813 waiting_job_->Resume(this); 787 waiting_job_->Resume(this);
814 waiting_job_ = NULL; 788 waiting_job_ = NULL;
815 } 789 }
816 790
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 return OK; 875 return OK;
902 } 876 }
903 877
904 // TODO(willchan): Make this a bit more exact. Maybe there are recoverable 878 // TODO(willchan): Make this a bit more exact. Maybe there are recoverable
905 // errors, such as ignoring certificate errors for Alternate-Protocol. 879 // errors, such as ignoring certificate errors for Alternate-Protocol.
906 if (result < 0 && waiting_job_) { 880 if (result < 0 && waiting_job_) {
907 waiting_job_->Resume(this); 881 waiting_job_->Resume(this);
908 waiting_job_ = NULL; 882 waiting_job_ = NULL;
909 } 883 }
910 884
911 if (result < 0 && session_->force_http_pipelining()) {
912 stream_factory_->AbortPipelinedRequestsWithKey(
913 this, *http_pipelining_key_.get(), result, server_ssl_config_);
914 }
915
916 // |result| may be the result of any of the stacked pools. The following 885 // |result| may be the result of any of the stacked pools. The following
917 // logic is used when determining how to interpret an error. 886 // logic is used when determining how to interpret an error.
918 // If |result| < 0: 887 // If |result| < 0:
919 // and connection_->socket() != NULL, then the SSL handshake ran and it 888 // and connection_->socket() != NULL, then the SSL handshake ran and it
920 // is a potentially recoverable error. 889 // is a potentially recoverable error.
921 // and connection_->socket == NULL and connection_->is_ssl_error() is true, 890 // and connection_->socket == NULL and connection_->is_ssl_error() is true,
922 // then the SSL handshake ran with an unrecoverable error. 891 // then the SSL handshake ran with an unrecoverable error.
923 // otherwise, the error came from one of the other pools. 892 // otherwise, the error came from one of the other pools.
924 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() || 893 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
925 connection_->is_ssl_error()); 894 connection_->is_ssl_error());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { 1008 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) {
1040 // This state indicates that the stream request is in a partially 1009 // This state indicates that the stream request is in a partially
1041 // completed state, and we've called back to the delegate for more 1010 // completed state, and we've called back to the delegate for more
1042 // information. 1011 // information.
1043 1012
1044 // We're always waiting here for the delegate to call us back. 1013 // We're always waiting here for the delegate to call us back.
1045 return ERR_IO_PENDING; 1014 return ERR_IO_PENDING;
1046 } 1015 }
1047 1016
1048 int HttpStreamFactoryImpl::Job::DoCreateStream() { 1017 int HttpStreamFactoryImpl::Job::DoCreateStream() {
1049 DCHECK(connection_->socket() || existing_spdy_session_.get() || 1018 DCHECK(connection_->socket() || existing_spdy_session_.get() || using_quic_);
1050 existing_available_pipeline_ || using_quic_);
1051 1019
1052 next_state_ = STATE_CREATE_STREAM_COMPLETE; 1020 next_state_ = STATE_CREATE_STREAM_COMPLETE;
1053 1021
1054 // We only set the socket motivation if we're the first to use 1022 // We only set the socket motivation if we're the first to use
1055 // this socket. Is there a race for two SPDY requests? We really 1023 // this socket. Is there a race for two SPDY requests? We really
1056 // need to plumb this through to the connect level. 1024 // need to plumb this through to the connect level.
1057 if (connection_->socket() && !connection_->is_reused()) 1025 if (connection_->socket() && !connection_->is_reused())
1058 SetSocketMotivation(); 1026 SetSocketMotivation();
1059 1027
1060 if (!using_spdy_) { 1028 if (!using_spdy_) {
1061 // We may get ftp scheme when fetching ftp resources through proxy. 1029 // We may get ftp scheme when fetching ftp resources through proxy.
1062 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && 1030 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
1063 (request_info_.url.SchemeIs("http") || 1031 (request_info_.url.SchemeIs("http") ||
1064 request_info_.url.SchemeIs("ftp")); 1032 request_info_.url.SchemeIs("ftp"));
1065 if (stream_factory_->http_pipelined_host_pool_. 1033 if (stream_factory_->for_websockets_) {
1066 IsExistingPipelineAvailableForKey(*http_pipelining_key_.get())) {
1067 DCHECK(!stream_factory_->for_websockets_);
1068 stream_.reset(stream_factory_->http_pipelined_host_pool_.
1069 CreateStreamOnExistingPipeline(
1070 *http_pipelining_key_.get()));
1071 CHECK(stream_.get());
1072 } else if (stream_factory_->for_websockets_) {
1073 DCHECK(request_); 1034 DCHECK(request_);
1074 DCHECK(request_->websocket_handshake_stream_create_helper()); 1035 DCHECK(request_->websocket_handshake_stream_create_helper());
1075 websocket_stream_.reset( 1036 websocket_stream_.reset(
1076 request_->websocket_handshake_stream_create_helper() 1037 request_->websocket_handshake_stream_create_helper()
1077 ->CreateBasicStream(connection_.Pass(), using_proxy)); 1038 ->CreateBasicStream(connection_.Pass(), using_proxy));
1078 } else if (!using_proxy && IsRequestEligibleForPipelining()) {
1079 // TODO(simonjam): Support proxies.
1080 stream_.reset(
1081 stream_factory_->http_pipelined_host_pool_.CreateStreamOnNewPipeline(
1082 *http_pipelining_key_.get(),
1083 connection_.release(),
1084 server_ssl_config_,
1085 proxy_info_,
1086 net_log_,
1087 was_npn_negotiated_,
1088 protocol_negotiated_));
1089 CHECK(stream_.get());
1090 } else { 1039 } else {
1091 stream_.reset(new HttpBasicStream(connection_.release(), using_proxy)); 1040 stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
1092 } 1041 }
1093 return OK; 1042 return OK;
1094 } 1043 }
1095 1044
1096 CHECK(!stream_.get()); 1045 CHECK(!stream_.get());
1097 1046
1098 bool direct = true; 1047 bool direct = true;
1099 const ProxyServer& proxy_server = proxy_info_.proxy_server(); 1048 const ProxyServer& proxy_server = proxy_info_.proxy_server();
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1196 1145
1197 return ReconsiderProxyAfterError(result); 1146 return ReconsiderProxyAfterError(result);
1198 } 1147 }
1199 1148
1200 void HttpStreamFactoryImpl::Job::ReturnToStateInitConnection( 1149 void HttpStreamFactoryImpl::Job::ReturnToStateInitConnection(
1201 bool close_connection) { 1150 bool close_connection) {
1202 if (close_connection && connection_->socket()) 1151 if (close_connection && connection_->socket())
1203 connection_->socket()->Disconnect(); 1152 connection_->socket()->Disconnect();
1204 connection_->Reset(); 1153 connection_->Reset();
1205 1154
1206 if (request_) { 1155 if (request_)
1207 request_->RemoveRequestFromSpdySessionRequestMap(); 1156 request_->RemoveRequestFromSpdySessionRequestMap();
1208 request_->RemoveRequestFromHttpPipeliningRequestMap();
1209 }
1210 1157
1211 next_state_ = STATE_INIT_CONNECTION; 1158 next_state_ = STATE_INIT_CONNECTION;
1212 } 1159 }
1213 1160
1214 void HttpStreamFactoryImpl::Job::SetSocketMotivation() { 1161 void HttpStreamFactoryImpl::Job::SetSocketMotivation() {
1215 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) 1162 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED)
1216 connection_->socket()->SetSubresourceSpeculation(); 1163 connection_->socket()->SetSubresourceSpeculation();
1217 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) 1164 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED)
1218 connection_->socket()->SetOmniboxSpeculation(); 1165 connection_->socket()->SetOmniboxSpeculation();
1219 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). 1166 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED).
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 } 1298 }
1352 1299
1353 int rv = session_->proxy_service()->ReconsiderProxyAfterError( 1300 int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1354 request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_); 1301 request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_);
1355 if (rv == OK || rv == ERR_IO_PENDING) { 1302 if (rv == OK || rv == ERR_IO_PENDING) {
1356 // If the error was during connection setup, there is no socket to 1303 // If the error was during connection setup, there is no socket to
1357 // disconnect. 1304 // disconnect.
1358 if (connection_->socket()) 1305 if (connection_->socket())
1359 connection_->socket()->Disconnect(); 1306 connection_->socket()->Disconnect();
1360 connection_->Reset(); 1307 connection_->Reset();
1361 if (request_) { 1308 if (request_)
1362 request_->RemoveRequestFromSpdySessionRequestMap(); 1309 request_->RemoveRequestFromSpdySessionRequestMap();
1363 request_->RemoveRequestFromHttpPipeliningRequestMap();
1364 }
1365 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; 1310 next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1366 } else { 1311 } else {
1367 // If ReconsiderProxyAfterError() failed synchronously, it means 1312 // If ReconsiderProxyAfterError() failed synchronously, it means
1368 // there was nothing left to fall-back to, so fail the transaction 1313 // there was nothing left to fall-back to, so fail the transaction
1369 // with the last connection error we got. 1314 // with the last connection error we got.
1370 // TODO(eroman): This is a confusing contract, make it more obvious. 1315 // TODO(eroman): This is a confusing contract, make it more obvious.
1371 rv = error; 1316 rv = error;
1372 } 1317 }
1373 1318
1374 return rv; 1319 return rv;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 } else if (original_url_) { 1408 } else if (original_url_) {
1464 // This job was the alternate protocol job, and hence won the race. 1409 // This job was the alternate protocol job, and hence won the race.
1465 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE); 1410 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_WON_RACE);
1466 } else { 1411 } else {
1467 // This job was the normal job, and hence the alternate protocol job lost 1412 // This job was the normal job, and hence the alternate protocol job lost
1468 // the race. 1413 // the race.
1469 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE); 1414 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_LOST_RACE);
1470 } 1415 }
1471 } 1416 }
1472 1417
1473 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() {
1474 if (IsPreconnecting() || !request_) {
1475 return false;
1476 }
1477 if (stream_factory_->for_websockets_) {
1478 return false;
1479 }
1480 if (session_->force_http_pipelining()) {
1481 return true;
1482 }
1483 if (!session_->params().http_pipelining_enabled) {
1484 return false;
1485 }
1486 if (using_ssl_) {
1487 return false;
1488 }
1489 if (request_info_.method != "GET" && request_info_.method != "HEAD") {
1490 return false;
1491 }
1492 if (request_info_.load_flags &
1493 (net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME | net::LOAD_PREFETCH |
1494 net::LOAD_IS_DOWNLOAD)) {
1495 // Avoid pipelining resources that may be streamed for a long time.
1496 return false;
1497 }
1498 return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining(
1499 *http_pipelining_key_.get());
1500 }
1501
1502 } // namespace net 1418 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698