Chromium Code Reviews| 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.h" | 5 #include "net/http/http_stream_factory_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 const SSLConfig& proxy_ssl_config, | 83 const SSLConfig& proxy_ssl_config, |
| 84 HttpStreamRequest::Delegate* delegate, | 84 HttpStreamRequest::Delegate* delegate, |
| 85 WebSocketHandshakeStreamBase::CreateHelper* | 85 WebSocketHandshakeStreamBase::CreateHelper* |
| 86 websocket_handshake_stream_create_helper, | 86 websocket_handshake_stream_create_helper, |
| 87 const BoundNetLog& net_log) { | 87 const BoundNetLog& net_log) { |
| 88 Request* request = new Request(request_info.url, | 88 Request* request = new Request(request_info.url, |
| 89 this, | 89 this, |
| 90 delegate, | 90 delegate, |
| 91 websocket_handshake_stream_create_helper, | 91 websocket_handshake_stream_create_helper, |
| 92 net_log); | 92 net_log); |
| 93 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 94 GURL origin_url = ApplyHostMappingRules(request_info.url, &server); | |
| 95 | |
| 93 Job* job = new Job(this, session_, request_info, priority, server_ssl_config, | 96 Job* job = new Job(this, session_, request_info, priority, server_ssl_config, |
| 94 proxy_ssl_config, net_log.net_log()); | 97 proxy_ssl_config, server, origin_url, net_log.net_log()); |
| 95 request->AttachJob(job); | 98 request->AttachJob(job); |
| 96 | 99 |
| 97 const AlternativeServiceVector alternative_service_vector = | 100 const AlternativeService alternative_service = |
| 98 GetAlternativeServicesFor(request_info.url, delegate); | 101 GetAlternativeServiceFor(request_info, delegate); |
| 99 | 102 |
| 100 if (!alternative_service_vector.empty()) { | 103 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| 101 // TODO(bnc): Pass on multiple alternative services to Job. | |
| 102 const AlternativeService& alternative_service = | |
| 103 alternative_service_vector[0]; | |
| 104 // Never share connection with other jobs for FTP requests. | 104 // Never share connection with other jobs for FTP requests. |
| 105 DCHECK(!request_info.url.SchemeIs("ftp")); | 105 DCHECK(!request_info.url.SchemeIs("ftp")); |
| 106 HostPortPair server = alternative_service.host_port_pair(); | |
| 107 GURL origin_url = ApplyHostMappingRules(request_info.url, &server); | |
| 106 | 108 |
| 107 Job* alternative_job = | 109 Job* alternative_job = |
| 108 new Job(this, session_, request_info, priority, server_ssl_config, | 110 new Job(this, session_, request_info, priority, server_ssl_config, |
| 109 proxy_ssl_config, alternative_service, net_log.net_log()); | 111 proxy_ssl_config, server, origin_url, alternative_service, |
| 112 net_log.net_log()); | |
| 110 request->AttachJob(alternative_job); | 113 request->AttachJob(alternative_job); |
| 111 | 114 |
| 112 job->WaitFor(alternative_job); | 115 job->WaitFor(alternative_job); |
| 113 // Make sure to wait until we call WaitFor(), before starting | 116 // Make sure to wait until we call WaitFor(), before starting |
| 114 // |alternative_job|, otherwise |alternative_job| will not notify |job| | 117 // |alternative_job|, otherwise |alternative_job| will not notify |job| |
| 115 // appropriately. | 118 // appropriately. |
| 116 alternative_job->Start(request); | 119 alternative_job->Start(request); |
| 117 } | 120 } |
| 118 | 121 |
| 119 // Even if |alternative_job| has already finished, it will not have notified | 122 // Even if |alternative_job| has already finished, it will not have notified |
| 120 // the request yet, since we defer that to the next iteration of the | 123 // the request yet, since we defer that to the next iteration of the |
| 121 // MessageLoop, so starting |job| is always safe. | 124 // MessageLoop, so starting |job| is always safe. |
| 122 job->Start(request); | 125 job->Start(request); |
| 123 return request; | 126 return request; |
| 124 } | 127 } |
| 125 | 128 |
| 126 void HttpStreamFactoryImpl::PreconnectStreams( | 129 void HttpStreamFactoryImpl::PreconnectStreams( |
| 127 int num_streams, | 130 int num_streams, |
| 128 const HttpRequestInfo& request_info, | 131 const HttpRequestInfo& request_info, |
| 129 const SSLConfig& server_ssl_config, | 132 const SSLConfig& server_ssl_config, |
| 130 const SSLConfig& proxy_ssl_config) { | 133 const SSLConfig& proxy_ssl_config) { |
| 131 DCHECK(!for_websockets_); | 134 DCHECK(!for_websockets_); |
| 132 AlternativeService alternative_service; | 135 AlternativeService alternative_service = |
| 133 AlternativeServiceVector alternative_service_vector = | 136 GetAlternativeServiceFor(request_info, nullptr); |
| 134 GetAlternativeServicesFor(request_info.url, nullptr); | 137 HostPortPair server; |
| 135 if (!alternative_service_vector.empty()) { | 138 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| 136 // TODO(bnc): Pass on multiple alternative services to Job. | 139 server = alternative_service.host_port_pair(); |
| 137 alternative_service = alternative_service_vector[0]; | |
| 138 if (session_->params().quic_disable_preconnect_if_0rtt && | 140 if (session_->params().quic_disable_preconnect_if_0rtt && |
| 139 alternative_service.protocol == QUIC && | 141 alternative_service.protocol == QUIC && |
| 140 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( | 142 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( |
| 141 alternative_service.host_port_pair(), request_info.privacy_mode))) { | 143 alternative_service.host_port_pair(), request_info.privacy_mode))) { |
| 142 return; | 144 return; |
| 143 } | 145 } |
| 146 } else { | |
| 147 server = HostPortPair::FromURL(request_info.url); | |
| 144 } | 148 } |
| 145 | 149 GURL origin_url = ApplyHostMappingRules(request_info.url, &server); |
| 146 // Due to how the socket pools handle priorities and idle sockets, only IDLE | 150 // Due to how the socket pools handle priorities and idle sockets, only IDLE |
| 147 // priority currently makes sense for preconnects. The priority for | 151 // priority currently makes sense for preconnects. The priority for |
| 148 // preconnects is currently ignored (see RequestSocketsForPool()), but could | 152 // preconnects is currently ignored (see RequestSocketsForPool()), but could |
| 149 // be used at some point for proxy resolution or something. | 153 // be used at some point for proxy resolution or something. |
| 150 Job* job = | 154 Job* job = new Job(this, session_, request_info, IDLE, server_ssl_config, |
| 151 new Job(this, session_, request_info, IDLE, server_ssl_config, | 155 proxy_ssl_config, server, origin_url, alternative_service, |
| 152 proxy_ssl_config, alternative_service, session_->net_log()); | 156 session_->net_log()); |
| 153 preconnect_job_set_.insert(job); | 157 preconnect_job_set_.insert(job); |
| 154 job->Preconnect(num_streams); | 158 job->Preconnect(num_streams); |
| 155 } | 159 } |
| 156 | 160 |
| 157 const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { | 161 const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { |
| 158 return session_->params().host_mapping_rules; | 162 return session_->params().host_mapping_rules; |
| 159 } | 163 } |
| 160 | 164 |
| 161 AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor( | 165 AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor( |
| 162 const GURL& original_url, | 166 const HttpRequestInfo& request_info, |
| 163 HttpStreamRequest::Delegate* delegate) { | 167 HttpStreamRequest::Delegate* delegate) { |
| 168 GURL original_url = request_info.url; | |
| 169 | |
| 164 if (original_url.SchemeIs("ftp")) | 170 if (original_url.SchemeIs("ftp")) |
| 165 return AlternativeServiceVector(); | 171 return AlternativeService(); |
| 166 | 172 |
| 167 HostPortPair origin = HostPortPair::FromURL(original_url); | 173 HostPortPair origin = HostPortPair::FromURL(original_url); |
| 168 HttpServerProperties& http_server_properties = | 174 HttpServerProperties& http_server_properties = |
| 169 *session_->http_server_properties(); | 175 *session_->http_server_properties(); |
| 170 const AlternativeServiceVector alternative_service_vector = | 176 const AlternativeServiceVector alternative_service_vector = |
| 171 http_server_properties.GetAlternativeServices(origin); | 177 http_server_properties.GetAlternativeServices(origin); |
| 172 if (alternative_service_vector.empty()) | 178 if (alternative_service_vector.empty()) |
| 173 return AlternativeServiceVector(); | 179 return AlternativeService(); |
| 174 | 180 |
| 175 bool quic_advertised = false; | 181 bool quic_advertised = false; |
| 176 bool quic_all_broken = true; | 182 bool quic_all_broken = true; |
| 177 | 183 |
| 178 const bool enable_different_host = | 184 const bool enable_different_host = |
| 179 session_->params().use_alternative_services; | 185 session_->params().use_alternative_services; |
| 180 | 186 |
| 181 AlternativeServiceVector enabled_alternative_service_vector; | 187 // First Alt-Svc that is not marked as broken. |
| 188 AlternativeService candidate_alternative_service; | |
|
Ryan Hamilton
2015/12/21 17:37:51
nit: I'd probably just drop "candidate_"
| |
| 189 | |
| 182 for (const AlternativeService& alternative_service : | 190 for (const AlternativeService& alternative_service : |
| 183 alternative_service_vector) { | 191 alternative_service_vector) { |
| 184 DCHECK(IsAlternateProtocolValid(alternative_service.protocol)); | 192 DCHECK(IsAlternateProtocolValid(alternative_service.protocol)); |
| 185 if (!quic_advertised && alternative_service.protocol == QUIC) | 193 if (!quic_advertised && alternative_service.protocol == QUIC) |
| 186 quic_advertised = true; | 194 quic_advertised = true; |
| 187 if (http_server_properties.IsAlternativeServiceBroken( | 195 if (http_server_properties.IsAlternativeServiceBroken( |
| 188 alternative_service)) { | 196 alternative_service)) { |
| 189 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_BROKEN); | 197 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_BROKEN); |
| 190 continue; | 198 continue; |
| 191 } | 199 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 207 | 215 |
| 208 origin.set_port(alternative_service.port); | 216 origin.set_port(alternative_service.port); |
| 209 if (alternative_service.protocol >= NPN_SPDY_MINIMUM_VERSION && | 217 if (alternative_service.protocol >= NPN_SPDY_MINIMUM_VERSION && |
| 210 alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { | 218 alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { |
| 211 if (!HttpStreamFactory::spdy_enabled()) | 219 if (!HttpStreamFactory::spdy_enabled()) |
| 212 continue; | 220 continue; |
| 213 | 221 |
| 214 if (session_->HasSpdyExclusion(origin)) | 222 if (session_->HasSpdyExclusion(origin)) |
| 215 continue; | 223 continue; |
| 216 | 224 |
| 217 enabled_alternative_service_vector.push_back(alternative_service); | 225 // Cache this entry if we don't have a non-broken Alt-Svc yet. |
| 226 if (candidate_alternative_service.protocol == | |
| 227 UNINITIALIZED_ALTERNATE_PROTOCOL) | |
| 228 candidate_alternative_service = alternative_service; | |
| 218 continue; | 229 continue; |
| 219 } | 230 } |
| 220 | 231 |
| 221 DCHECK_EQ(QUIC, alternative_service.protocol); | 232 DCHECK_EQ(QUIC, alternative_service.protocol); |
| 222 quic_all_broken = false; | 233 quic_all_broken = false; |
| 223 if (!session_->params().enable_quic) | 234 if (!session_->params().enable_quic) |
| 224 continue; | 235 continue; |
| 225 | 236 |
| 226 if (session_->quic_stream_factory()->IsQuicDisabled(origin.port())) | 237 if (session_->quic_stream_factory()->IsQuicDisabled(origin.port())) |
| 227 continue; | 238 continue; |
| 228 | 239 |
| 229 if (!original_url.SchemeIs("https")) | 240 if (!original_url.SchemeIs("https")) |
| 230 continue; | 241 continue; |
| 231 | 242 |
| 232 enabled_alternative_service_vector.push_back(alternative_service); | 243 // Check whether there's an existing session to use for this QUIC Alt-Svc. |
| 244 HostPortPair destination = alternative_service.host_port_pair(); | |
| 245 StringPiece origin_host = | |
| 246 ApplyHostMappingRules(request_info.url, &destination).host(); | |
|
Ryan Hamilton
2015/12/21 17:37:51
I'm not actually sure that this "works". StringPie
Zhongyi Shi
2015/12/28 22:43:22
Done.
| |
| 247 QuicServerId server_id(destination, request_info.privacy_mode); | |
| 248 if (session_->quic_stream_factory()->CanUseExistingSession( | |
| 249 server_id, request_info.privacy_mode, origin_host)) | |
| 250 return alternative_service; | |
| 251 | |
| 252 // Cache this entry if we don't have a non-broken Alt-Svc yet. | |
| 253 if (candidate_alternative_service.protocol == | |
| 254 UNINITIALIZED_ALTERNATE_PROTOCOL) | |
| 255 candidate_alternative_service = alternative_service; | |
| 233 } | 256 } |
| 257 | |
| 258 // Ask delegate to mark QUIC as broken for the origin. | |
| 234 if (quic_advertised && quic_all_broken && delegate != nullptr) | 259 if (quic_advertised && quic_all_broken && delegate != nullptr) |
| 235 delegate->OnQuicBroken(); | 260 delegate->OnQuicBroken(); |
| 236 return enabled_alternative_service_vector; | 261 |
| 262 return candidate_alternative_service; | |
| 237 } | 263 } |
| 238 | 264 |
| 239 void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { | 265 void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { |
| 240 DCHECK(ContainsKey(request_map_, job)); | 266 DCHECK(ContainsKey(request_map_, job)); |
| 241 DCHECK_EQ(request_map_[job], request); | 267 DCHECK_EQ(request_map_[job], request); |
| 242 DCHECK(!ContainsKey(orphaned_job_set_, job)); | 268 DCHECK(!ContainsKey(orphaned_job_set_, job)); |
| 243 | 269 |
| 244 request_map_.erase(job); | 270 request_map_.erase(job); |
| 245 | 271 |
| 246 orphaned_job_set_.insert(job); | 272 orphaned_job_set_.insert(job); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 delete job; | 318 delete job; |
| 293 } | 319 } |
| 294 | 320 |
| 295 void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { | 321 void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { |
| 296 preconnect_job_set_.erase(job); | 322 preconnect_job_set_.erase(job); |
| 297 delete job; | 323 delete job; |
| 298 OnPreconnectsCompleteInternal(); | 324 OnPreconnectsCompleteInternal(); |
| 299 } | 325 } |
| 300 | 326 |
| 301 } // namespace net | 327 } // namespace net |
| OLD | NEW |