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