OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/logging.h" | 7 #include "base/logging.h" |
8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "build/build_config.h" | 12 #include "build/build_config.h" |
13 #include "net/base/connection_type_histograms.h" | 13 #include "net/base/connection_type_histograms.h" |
14 #include "net/base/net_log.h" | 14 #include "net/base/net_log.h" |
15 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
16 #include "net/base/ssl_cert_request_info.h" | 16 #include "net/base/ssl_cert_request_info.h" |
17 #include "net/http/http_basic_stream.h" | 17 #include "net/http/http_basic_stream.h" |
18 #include "net/http/http_network_session.h" | 18 #include "net/http/http_network_session.h" |
19 #include "net/http/http_pipelined_connection.h" | |
20 #include "net/http/http_pipelined_host.h" | |
21 #include "net/http/http_pipelined_host_pool.h" | |
22 #include "net/http/http_pipelined_stream.h" | |
19 #include "net/http/http_proxy_client_socket.h" | 23 #include "net/http/http_proxy_client_socket.h" |
20 #include "net/http/http_proxy_client_socket_pool.h" | 24 #include "net/http/http_proxy_client_socket_pool.h" |
21 #include "net/http/http_request_info.h" | 25 #include "net/http/http_request_info.h" |
26 #include "net/http/http_stream_factory.h" | |
22 #include "net/http/http_stream_factory_impl_request.h" | 27 #include "net/http/http_stream_factory_impl_request.h" |
23 #include "net/socket/client_socket_handle.h" | 28 #include "net/socket/client_socket_handle.h" |
24 #include "net/socket/client_socket_pool.h" | 29 #include "net/socket/client_socket_pool.h" |
25 #include "net/socket/socks_client_socket_pool.h" | 30 #include "net/socket/socks_client_socket_pool.h" |
26 #include "net/socket/ssl_client_socket.h" | 31 #include "net/socket/ssl_client_socket.h" |
27 #include "net/socket/ssl_client_socket_pool.h" | 32 #include "net/socket/ssl_client_socket_pool.h" |
28 #include "net/spdy/spdy_http_stream.h" | 33 #include "net/spdy/spdy_http_stream.h" |
29 #include "net/spdy/spdy_session.h" | 34 #include "net/spdy/spdy_session.h" |
30 #include "net/spdy/spdy_session_pool.h" | 35 #include "net/spdy/spdy_session_pool.h" |
31 | 36 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
80 dependent_job_(NULL), | 85 dependent_job_(NULL), |
81 using_ssl_(false), | 86 using_ssl_(false), |
82 using_spdy_(false), | 87 using_spdy_(false), |
83 force_spdy_always_(HttpStreamFactory::force_spdy_always()), | 88 force_spdy_always_(HttpStreamFactory::force_spdy_always()), |
84 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()), | 89 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()), |
85 spdy_certificate_error_(OK), | 90 spdy_certificate_error_(OK), |
86 establishing_tunnel_(false), | 91 establishing_tunnel_(false), |
87 was_npn_negotiated_(false), | 92 was_npn_negotiated_(false), |
88 num_streams_(0), | 93 num_streams_(0), |
89 spdy_session_direct_(false), | 94 spdy_session_direct_(false), |
95 existing_available_pipeline_(NULL), | |
90 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 96 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
91 DCHECK(stream_factory); | 97 DCHECK(stream_factory); |
92 DCHECK(session); | 98 DCHECK(session); |
93 } | 99 } |
94 | 100 |
95 HttpStreamFactoryImpl::Job::~Job() { | 101 HttpStreamFactoryImpl::Job::~Job() { |
96 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB, NULL); | 102 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB, NULL); |
97 | 103 |
98 // When we're in a partially constructed state, waiting for the user to | 104 // When we're in a partially constructed state, waiting for the user to |
99 // provide certificate handling information or authentication, we can't reuse | 105 // provide certificate handling information or authentication, we can't reuse |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
580 // actually need to preconnect any sockets, so we're done. | 586 // actually need to preconnect any sockets, so we're done. |
581 if (IsPreconnecting()) | 587 if (IsPreconnecting()) |
582 return OK; | 588 return OK; |
583 using_spdy_ = true; | 589 using_spdy_ = true; |
584 next_state_ = STATE_CREATE_STREAM; | 590 next_state_ = STATE_CREATE_STREAM; |
585 existing_spdy_session_ = spdy_session; | 591 existing_spdy_session_ = spdy_session; |
586 return OK; | 592 return OK; |
587 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { | 593 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { |
588 // Update the spdy session key for the request that launched this job. | 594 // Update the spdy session key for the request that launched this job. |
589 request_->SetSpdySessionKey(spdy_session_key); | 595 request_->SetSpdySessionKey(spdy_session_key); |
596 } else if (IsRequestEligibleForPipelining()) { | |
597 // TODO(simonjam): With pipelining, we might be better off using fewer | |
598 // connections and thus should make fewer preconnections. Explore | |
599 // preconnecting fewer than the requested num_connections. | |
600 HttpPipelinedHost* host = session_->http_pipelined_host_pool()-> | |
601 GetPipelinedHostIfExists(origin_); | |
602 if (host) { | |
603 HttpPipelinedConnection* connection = host->FindAvailablePipeline(); | |
604 if (connection) { | |
605 next_state_ = STATE_CREATE_STREAM; | |
606 existing_available_pipeline_ = connection; | |
607 return OK; | |
608 } | |
609 } | |
610 request_->SetHttpPipeliningKey(origin_); | |
590 } | 611 } |
591 | 612 |
592 // OK, there's no available SPDY session. Let |dependent_job_| resume if it's | 613 // OK, there's no available SPDY session. Let |dependent_job_| resume if it's |
593 // paused. | 614 // paused. |
594 | 615 |
595 if (dependent_job_) { | 616 if (dependent_job_) { |
596 dependent_job_->Resume(this); | 617 dependent_job_->Resume(this); |
597 dependent_job_ = NULL; | 618 dependent_job_ = NULL; |
598 } | 619 } |
599 | 620 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
756 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { | 777 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { |
757 // This state indicates that the stream request is in a partially | 778 // This state indicates that the stream request is in a partially |
758 // completed state, and we've called back to the delegate for more | 779 // completed state, and we've called back to the delegate for more |
759 // information. | 780 // information. |
760 | 781 |
761 // We're always waiting here for the delegate to call us back. | 782 // We're always waiting here for the delegate to call us back. |
762 return ERR_IO_PENDING; | 783 return ERR_IO_PENDING; |
763 } | 784 } |
764 | 785 |
765 int HttpStreamFactoryImpl::Job::DoCreateStream() { | 786 int HttpStreamFactoryImpl::Job::DoCreateStream() { |
766 if (!connection_->socket() && !existing_spdy_session_) | 787 if (!connection_->socket() && !existing_spdy_session_ && |
788 !existing_available_pipeline_) | |
767 HACKCrashHereToDebug80095(); | 789 HACKCrashHereToDebug80095(); |
willchan no longer on Chromium
2011/09/26 23:49:20
Can you just kill this code? It's been debugged, I
James Simonsen
2011/09/29 02:39:31
Done.
| |
768 | 790 |
791 DCHECK(connection_->socket() || existing_spdy_session_ || | |
792 existing_available_pipeline_); | |
793 | |
769 next_state_ = STATE_CREATE_STREAM_COMPLETE; | 794 next_state_ = STATE_CREATE_STREAM_COMPLETE; |
770 | 795 |
771 // We only set the socket motivation if we're the first to use | 796 // We only set the socket motivation if we're the first to use |
772 // this socket. Is there a race for two SPDY requests? We really | 797 // this socket. Is there a race for two SPDY requests? We really |
773 // need to plumb this through to the connect level. | 798 // need to plumb this through to the connect level. |
774 if (connection_->socket() && !connection_->is_reused()) | 799 if (connection_->socket() && !connection_->is_reused()) |
775 SetSocketMotivation(); | 800 SetSocketMotivation(); |
776 | 801 |
777 const ProxyServer& proxy_server = proxy_info_.proxy_server(); | 802 const ProxyServer& proxy_server = proxy_info_.proxy_server(); |
778 | 803 |
779 if (!using_spdy_) { | 804 if (!using_spdy_) { |
780 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && | 805 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && |
781 request_info_.url.SchemeIs("http"); | 806 request_info_.url.SchemeIs("http"); |
782 stream_.reset(new HttpBasicStream(connection_.release(), NULL, | 807 // TODO(simonjam): Support proxies. |
783 using_proxy)); | 808 if (existing_available_pipeline_) { |
809 stream_.reset(existing_available_pipeline_->CreateNewStream()); | |
810 } else if (!using_proxy && IsRequestEligibleForPipelining()) { | |
811 HttpPipelinedConnection* pipeline = session_->http_pipelined_host_pool()-> | |
willchan no longer on Chromium
2011/09/26 23:49:20
It's not clear why the HttpPipelinedConnection* is
James Simonsen
2011/09/29 02:39:31
Done.
willchan no longer on Chromium
2011/10/13 02:29:16
I see. I feel like this is revealing a problem wit
| |
812 GetOrCreatePipelinedHost(origin_)->CreateNewPipeline( | |
813 connection_.release(), | |
814 server_ssl_config_, | |
815 proxy_info_, | |
816 net_log_, | |
817 was_npn_negotiated_); | |
818 stream_.reset(pipeline->CreateNewStream()); | |
819 } else { | |
820 stream_.reset(new HttpBasicStream(connection_.release(), NULL, | |
821 using_proxy)); | |
822 } | |
784 return OK; | 823 return OK; |
785 } | 824 } |
786 | 825 |
787 CHECK(!stream_.get()); | 826 CHECK(!stream_.get()); |
788 | 827 |
789 if (!connection_->socket() && !existing_spdy_session_) | 828 if (!connection_->socket() && !existing_spdy_session_) |
790 HACKCrashHereToDebug80095(); | 829 HACKCrashHereToDebug80095(); |
791 | 830 |
792 bool direct = true; | 831 bool direct = true; |
793 HostPortProxyPair pair(origin_, proxy_server); | 832 HostPortProxyPair pair(origin_, proxy_server); |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1079 | 1118 |
1080 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { | 1119 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { |
1081 DCHECK_GE(num_streams_, 0); | 1120 DCHECK_GE(num_streams_, 0); |
1082 return num_streams_ > 0; | 1121 return num_streams_ > 0; |
1083 } | 1122 } |
1084 | 1123 |
1085 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { | 1124 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { |
1086 return !IsPreconnecting() && !request_; | 1125 return !IsPreconnecting() && !request_; |
1087 } | 1126 } |
1088 | 1127 |
1128 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() const { | |
1129 if (!HttpStreamFactory::http_pipelining_enabled()) { | |
1130 return false; | |
1131 } | |
1132 if (IsPreconnecting() || !request_) { | |
1133 return false; | |
1134 } | |
1135 if (using_ssl_) { | |
1136 return false; | |
1137 } | |
1138 return request_info_.method == "GET" || request_info_.method == "HEAD"; | |
1139 } | |
1140 | |
1089 #if defined(OS_WIN) | 1141 #if defined(OS_WIN) |
1090 #pragma warning (disable: 4748) | 1142 #pragma warning (disable: 4748) |
1091 #pragma optimize( "", off ) | 1143 #pragma optimize( "", off ) |
1092 #endif | 1144 #endif |
1093 | 1145 |
1094 void HttpStreamFactoryImpl::Job::HACKCrashHereToDebug80095() { | 1146 void HttpStreamFactoryImpl::Job::HACKCrashHereToDebug80095() { |
1095 // If we enter this code path, then we'll cause a crash later in | 1147 // If we enter this code path, then we'll cause a crash later in |
1096 // DoCreateStream(). Crash now and figure out what happened: | 1148 // DoCreateStream(). Crash now and figure out what happened: |
1097 // http://crbug.com/80095. | 1149 // http://crbug.com/80095. |
1098 GURL url = original_url_.get() ? *original_url_ : request_info_.url; | 1150 GURL url = original_url_.get() ? *original_url_ : request_info_.url; |
(...skipping 24 matching lines...) Expand all Loading... | |
1123 << (using_spdy ? "true\n" : "false\n"); | 1175 << (using_spdy ? "true\n" : "false\n"); |
1124 } | 1176 } |
1125 } | 1177 } |
1126 | 1178 |
1127 #if defined(OS_WIN) | 1179 #if defined(OS_WIN) |
1128 #pragma optimize( "", on ) | 1180 #pragma optimize( "", on ) |
1129 #pragma warning (default: 4748) | 1181 #pragma warning (default: 4748) |
1130 #endif | 1182 #endif |
1131 | 1183 |
1132 } // namespace net | 1184 } // namespace net |
OLD | NEW |