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-inl.h" | 8 #include "base/stl_util-inl.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" |
22 #include "net/http/http_stream_factory_impl_request.h" | 26 #include "net/http/http_stream_factory_impl_request.h" |
23 #include "net/socket/client_socket_handle.h" | 27 #include "net/socket/client_socket_handle.h" |
24 #include "net/socket/client_socket_pool.h" | 28 #include "net/socket/client_socket_pool.h" |
25 #include "net/socket/socks_client_socket_pool.h" | 29 #include "net/socket/socks_client_socket_pool.h" |
26 #include "net/socket/ssl_client_socket.h" | 30 #include "net/socket/ssl_client_socket.h" |
27 #include "net/socket/ssl_client_socket_pool.h" | 31 #include "net/socket/ssl_client_socket_pool.h" |
28 #include "net/spdy/spdy_http_stream.h" | 32 #include "net/spdy/spdy_http_stream.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 dependent_job_(NULL), | 82 dependent_job_(NULL), |
79 using_ssl_(false), | 83 using_ssl_(false), |
80 using_spdy_(false), | 84 using_spdy_(false), |
81 force_spdy_always_(HttpStreamFactory::force_spdy_always()), | 85 force_spdy_always_(HttpStreamFactory::force_spdy_always()), |
82 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()), | 86 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()), |
83 spdy_certificate_error_(OK), | 87 spdy_certificate_error_(OK), |
84 establishing_tunnel_(false), | 88 establishing_tunnel_(false), |
85 was_npn_negotiated_(false), | 89 was_npn_negotiated_(false), |
86 num_streams_(0), | 90 num_streams_(0), |
87 spdy_session_direct_(false), | 91 spdy_session_direct_(false), |
92 existing_available_pipeline_(NULL), | |
88 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 93 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
89 DCHECK(stream_factory); | 94 DCHECK(stream_factory); |
90 DCHECK(session); | 95 DCHECK(session); |
91 } | 96 } |
92 | 97 |
93 HttpStreamFactoryImpl::Job::~Job() { | 98 HttpStreamFactoryImpl::Job::~Job() { |
94 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB, NULL); | 99 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB, NULL); |
95 | 100 |
96 // When we're in a partially constructed state, waiting for the user to | 101 // When we're in a partially constructed state, waiting for the user to |
97 // provide certificate handling information or authentication, we can't reuse | 102 // provide certificate handling information or authentication, we can't reuse |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
573 // actually need to preconnect any sockets, so we're done. | 578 // actually need to preconnect any sockets, so we're done. |
574 if (IsPreconnecting()) | 579 if (IsPreconnecting()) |
575 return OK; | 580 return OK; |
576 using_spdy_ = true; | 581 using_spdy_ = true; |
577 next_state_ = STATE_CREATE_STREAM; | 582 next_state_ = STATE_CREATE_STREAM; |
578 existing_spdy_session_ = spdy_session; | 583 existing_spdy_session_ = spdy_session; |
579 return OK; | 584 return OK; |
580 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { | 585 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { |
581 // Update the spdy session key for the request that launched this job. | 586 // Update the spdy session key for the request that launched this job. |
582 request_->SetSpdySessionKey(spdy_session_key); | 587 request_->SetSpdySessionKey(spdy_session_key); |
588 } else if (IsRequestEligibleForPipelining()) { | |
589 HttpPipelinedHost* host = session_->http_pipelined_host_pool()-> | |
590 GetPipelinedHostIfExists(origin_); | |
591 if (host) { | |
592 HttpPipelinedConnection* connection = host->FindAvailablePipeline(); | |
593 if (connection) { | |
594 next_state_ = STATE_CREATE_STREAM; | |
595 existing_available_pipeline_ = connection; | |
596 return OK; | |
597 } | |
598 } | |
599 request_->SetHttpPipeliningKey(origin_); | |
583 } | 600 } |
584 | 601 |
585 // OK, there's no available SPDY session. Let |dependent_job_| resume if it's | 602 // OK, there's no available SPDY session. Let |dependent_job_| resume if it's |
586 // paused. | 603 // paused. |
587 | 604 |
588 if (dependent_job_) { | 605 if (dependent_job_) { |
589 dependent_job_->Resume(this); | 606 dependent_job_->Resume(this); |
590 dependent_job_ = NULL; | 607 dependent_job_ = NULL; |
591 } | 608 } |
592 | 609 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
750 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { | 767 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) { |
751 // This state indicates that the stream request is in a partially | 768 // This state indicates that the stream request is in a partially |
752 // completed state, and we've called back to the delegate for more | 769 // completed state, and we've called back to the delegate for more |
753 // information. | 770 // information. |
754 | 771 |
755 // We're always waiting here for the delegate to call us back. | 772 // We're always waiting here for the delegate to call us back. |
756 return ERR_IO_PENDING; | 773 return ERR_IO_PENDING; |
757 } | 774 } |
758 | 775 |
759 int HttpStreamFactoryImpl::Job::DoCreateStream() { | 776 int HttpStreamFactoryImpl::Job::DoCreateStream() { |
760 if (!connection_->socket() && !existing_spdy_session_) | 777 if (!connection_->socket() && !existing_spdy_session_ && |
778 !existing_available_pipeline_) | |
willchan no longer on Chromium
2011/07/19 13:29:38
Heh, this is used to debug bug 80095. You probably
James Simonsen
2011/07/19 22:54:23
Done, but I still need to avoid falling into the H
| |
761 HACKCrashHereToDebug80095(); | 779 HACKCrashHereToDebug80095(); |
762 | 780 |
763 next_state_ = STATE_CREATE_STREAM_COMPLETE; | 781 next_state_ = STATE_CREATE_STREAM_COMPLETE; |
764 | 782 |
765 // We only set the socket motivation if we're the first to use | 783 // We only set the socket motivation if we're the first to use |
766 // this socket. Is there a race for two SPDY requests? We really | 784 // this socket. Is there a race for two SPDY requests? We really |
767 // need to plumb this through to the connect level. | 785 // need to plumb this through to the connect level. |
768 if (connection_->socket() && !connection_->is_reused()) | 786 if (connection_->socket() && !connection_->is_reused()) |
769 SetSocketMotivation(); | 787 SetSocketMotivation(); |
770 | 788 |
771 const ProxyServer& proxy_server = proxy_info_.proxy_server(); | 789 const ProxyServer& proxy_server = proxy_info_.proxy_server(); |
772 | 790 |
773 if (!using_spdy_) { | 791 if (!using_spdy_) { |
774 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && | 792 bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && |
775 request_info_.url.SchemeIs("http"); | 793 request_info_.url.SchemeIs("http"); |
776 stream_.reset(new HttpBasicStream(connection_.release(), NULL, | 794 // TODO(simonjam): Support proxies. |
777 using_proxy)); | 795 if (existing_available_pipeline_) { |
796 stream_.reset(new HttpPipelinedStream(existing_available_pipeline_)); | |
797 } else if (!using_proxy && IsRequestEligibleForPipelining()) { | |
798 HttpPipelinedConnection* pipeline = session_->http_pipelined_host_pool()-> | |
799 GetOrCreatePipelinedHost(origin_)->CreateNewPipeline( | |
willchan no longer on Chromium
2011/07/19 13:29:38
I need to look at this a bit more. This is pretty
James Simonsen
2011/07/19 22:54:23
Yeah, I'm still not sure exactly what we all need.
| |
800 connection_.release(), | |
801 ssl_config_, | |
802 proxy_info_, | |
803 net_log_, | |
804 was_npn_negotiated_); | |
805 stream_.reset(new HttpPipelinedStream(pipeline)); | |
806 } else { | |
807 stream_.reset(new HttpBasicStream(connection_.release(), NULL, | |
808 using_proxy)); | |
809 } | |
778 return OK; | 810 return OK; |
779 } | 811 } |
780 | 812 |
781 CHECK(!stream_.get()); | 813 CHECK(!stream_.get()); |
782 | 814 |
783 if (!connection_->socket() && !existing_spdy_session_) | 815 if (!connection_->socket() && !existing_spdy_session_) |
784 HACKCrashHereToDebug80095(); | 816 HACKCrashHereToDebug80095(); |
785 | 817 |
786 bool direct = true; | 818 bool direct = true; |
787 HostPortProxyPair pair(origin_, proxy_server); | 819 HostPortProxyPair pair(origin_, proxy_server); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1066 | 1098 |
1067 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { | 1099 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { |
1068 DCHECK_GE(num_streams_, 0); | 1100 DCHECK_GE(num_streams_, 0); |
1069 return num_streams_ > 0; | 1101 return num_streams_ > 0; |
1070 } | 1102 } |
1071 | 1103 |
1072 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { | 1104 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { |
1073 return !IsPreconnecting() && !request_; | 1105 return !IsPreconnecting() && !request_; |
1074 } | 1106 } |
1075 | 1107 |
1108 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() const { | |
willchan no longer on Chromium
2011/07/19 13:29:38
So, we probably want to expose pipelining via abou
James Simonsen
2011/07/19 22:54:23
Done. Yep, easy.
| |
1109 if (IsPreconnecting() || !request_) { | |
1110 return false; | |
1111 } | |
1112 return request_info_.method == "GET"; | |
willchan no longer on Chromium
2011/07/19 13:29:38
Allow other idempotent methods like HEAD?
James Simonsen
2011/07/19 22:54:23
Done. HEAD seems the only other safe and useful on
| |
1113 } | |
1114 | |
1076 #if defined(OS_WIN) | 1115 #if defined(OS_WIN) |
1077 #pragma warning (disable: 4748) | 1116 #pragma warning (disable: 4748) |
1078 #pragma optimize( "", off ) | 1117 #pragma optimize( "", off ) |
1079 #endif | 1118 #endif |
1080 | 1119 |
1081 void HttpStreamFactoryImpl::Job::HACKCrashHereToDebug80095() { | 1120 void HttpStreamFactoryImpl::Job::HACKCrashHereToDebug80095() { |
1082 // If we enter this code path, then we'll cause a crash later in | 1121 // If we enter this code path, then we'll cause a crash later in |
1083 // DoCreateStream(). Crash now and figure out what happened: | 1122 // DoCreateStream(). Crash now and figure out what happened: |
1084 // http://crbug.com/80095. | 1123 // http://crbug.com/80095. |
1085 GURL url = original_url_.get() ? *original_url_ : request_info_.url; | 1124 GURL url = original_url_.get() ? *original_url_ : request_info_.url; |
(...skipping 24 matching lines...) Expand all Loading... | |
1110 << (using_spdy ? "true\n" : "false\n"); | 1149 << (using_spdy ? "true\n" : "false\n"); |
1111 } | 1150 } |
1112 } | 1151 } |
1113 | 1152 |
1114 #if defined(OS_WIN) | 1153 #if defined(OS_WIN) |
1115 #pragma optimize( "", on ) | 1154 #pragma optimize( "", on ) |
1116 #pragma warning (default: 4748) | 1155 #pragma warning (default: 4748) |
1117 #endif | 1156 #endif |
1118 | 1157 |
1119 } // namespace net | 1158 } // namespace net |
OLD | NEW |