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

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

Issue 7289006: Basic HTTP pipelining support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use HttpStreamFactoryImpl::Job Created 9 years, 5 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) 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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698