| 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_job.h" | 5 #include "net/http/http_stream_factory_impl_job.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 origin_url_.SchemeIs(url::kWssScheme)), | 213 origin_url_.SchemeIs(url::kWssScheme)), |
| 214 using_spdy_(false), | 214 using_spdy_(false), |
| 215 using_quic_(false), | 215 using_quic_(false), |
| 216 should_reconsider_proxy_(false), | 216 should_reconsider_proxy_(false), |
| 217 quic_request_(session_->quic_stream_factory()), | 217 quic_request_(session_->quic_stream_factory()), |
| 218 using_existing_quic_session_(false), | 218 using_existing_quic_session_(false), |
| 219 establishing_tunnel_(false), | 219 establishing_tunnel_(false), |
| 220 was_alpn_negotiated_(false), | 220 was_alpn_negotiated_(false), |
| 221 negotiated_protocol_(kProtoUnknown), | 221 negotiated_protocol_(kProtoUnknown), |
| 222 num_streams_(0), | 222 num_streams_(0), |
| 223 spdy_session_direct_(false), | 223 spdy_session_direct_( |
| 224 !(proxy_info.is_https() && origin_url_.SchemeIs(url::kHttpScheme))), |
| 225 spdy_session_key_(GetSpdySessionKey()), |
| 224 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), | 226 stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), |
| 225 ptr_factory_(this) { | 227 ptr_factory_(this) { |
| 226 DCHECK(session); | 228 DCHECK(session); |
| 227 // The job can't have alternative service and alternative proxy server set at | 229 // The job can't have alternative service and alternative proxy server set at |
| 228 // the same time since alternative services are used for requests that are | 230 // the same time since alternative services are used for requests that are |
| 229 // fetched directly, while the alternative proxy server is used for requests | 231 // fetched directly, while the alternative proxy server is used for requests |
| 230 // that should be fetched using proxy. | 232 // that should be fetched using proxy. |
| 231 DCHECK(alternative_service_.protocol == kProtoUnknown || | 233 DCHECK(alternative_service_.protocol == kProtoUnknown || |
| 232 !alternative_proxy_server_.is_valid()); | 234 !alternative_proxy_server_.is_valid()); |
| 233 DCHECK(!alternative_proxy_server_.is_valid() || | 235 DCHECK(!alternative_proxy_server_.is_valid() || |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 DCHECK(connection_.get() && connection_->socket()); | 393 DCHECK(connection_.get() && connection_->socket()); |
| 392 SSLClientSocket* ssl_socket = | 394 SSLClientSocket* ssl_socket = |
| 393 static_cast<SSLClientSocket*>(connection_->socket()); | 395 static_cast<SSLClientSocket*>(connection_->socket()); |
| 394 ssl_socket->GetSSLInfo(&ssl_info_); | 396 ssl_socket->GetSSLInfo(&ssl_info_); |
| 395 } | 397 } |
| 396 | 398 |
| 397 SpdySessionKey HttpStreamFactoryImpl::Job::GetSpdySessionKey() const { | 399 SpdySessionKey HttpStreamFactoryImpl::Job::GetSpdySessionKey() const { |
| 398 // In the case that we're using an HTTPS proxy for an HTTP url, | 400 // In the case that we're using an HTTPS proxy for an HTTP url, |
| 399 // we look for a SPDY session *to* the proxy, instead of to the | 401 // we look for a SPDY session *to* the proxy, instead of to the |
| 400 // origin server. | 402 // origin server. |
| 401 if (IsHttpsProxyAndHttpUrl()) { | 403 if (!spdy_session_direct_) { |
| 402 return SpdySessionKey(proxy_info_.proxy_server().host_port_pair(), | 404 return SpdySessionKey(proxy_info_.proxy_server().host_port_pair(), |
| 403 ProxyServer::Direct(), PRIVACY_MODE_DISABLED); | 405 ProxyServer::Direct(), PRIVACY_MODE_DISABLED); |
| 404 } | 406 } |
| 405 return SpdySessionKey(HostPortPair::FromURL(origin_url_), | 407 return SpdySessionKey(HostPortPair::FromURL(origin_url_), |
| 406 proxy_info_.proxy_server(), request_info_.privacy_mode); | 408 proxy_info_.proxy_server(), request_info_.privacy_mode); |
| 407 } | 409 } |
| 408 | 410 |
| 409 bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const { | 411 bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const { |
| 410 // We need to make sure that if a spdy session was created for | 412 // We need to make sure that if a spdy session was created for |
| 411 // https://somehost/ that we don't use that session for http://somehost:443/. | 413 // https://somehost/ that we don't use that session for http://somehost:443/. |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 // There's no available QUIC session. Inform the delegate how long to | 870 // There's no available QUIC session. Inform the delegate how long to |
| 869 // delay the main job. | 871 // delay the main job. |
| 870 if (rv == ERR_IO_PENDING) { | 872 if (rv == ERR_IO_PENDING) { |
| 871 delegate_->MaybeSetWaitTimeForMainJob( | 873 delegate_->MaybeSetWaitTimeForMainJob( |
| 872 quic_request_.GetTimeDelayForWaitingJob()); | 874 quic_request_.GetTimeDelayForWaitingJob()); |
| 873 } | 875 } |
| 874 } | 876 } |
| 875 return rv; | 877 return rv; |
| 876 } | 878 } |
| 877 | 879 |
| 878 SpdySessionKey spdy_session_key = GetSpdySessionKey(); | |
| 879 | |
| 880 // Check first if we have a spdy session for this group. If so, then go | 880 // Check first if we have a spdy session for this group. If so, then go |
| 881 // straight to using that. | 881 // straight to using that. |
| 882 if (CanUseExistingSpdySession()) { | 882 if (CanUseExistingSpdySession()) { |
| 883 base::WeakPtr<SpdySession> spdy_session = | 883 base::WeakPtr<SpdySession> spdy_session = |
| 884 session_->spdy_session_pool()->FindAvailableSession( | 884 session_->spdy_session_pool()->FindAvailableSession( |
| 885 spdy_session_key, origin_url_, enable_ip_based_pooling_, net_log_); | 885 spdy_session_key_, origin_url_, enable_ip_based_pooling_, net_log_); |
| 886 if (spdy_session) { | 886 if (spdy_session) { |
| 887 // If we're preconnecting, but we already have a SpdySession, we don't | 887 // If we're preconnecting, but we already have a SpdySession, we don't |
| 888 // actually need to preconnect any sockets, so we're done. | 888 // actually need to preconnect any sockets, so we're done. |
| 889 if (job_type_ == PRECONNECT) | 889 if (job_type_ == PRECONNECT) |
| 890 return OK; | 890 return OK; |
| 891 using_spdy_ = true; | 891 using_spdy_ = true; |
| 892 next_state_ = STATE_CREATE_STREAM; | 892 next_state_ = STATE_CREATE_STREAM; |
| 893 existing_spdy_session_ = spdy_session; | 893 existing_spdy_session_ = spdy_session; |
| 894 return OK; | 894 return OK; |
| 895 } | 895 } |
| 896 } | 896 } |
| 897 if (using_ssl_) { | 897 if (using_ssl_) { |
| 898 // Ask |delegate_delegate_| to update the spdy session key for the request | 898 // Ask |delegate_delegate_| to update the spdy session key for the request |
| 899 // that launched this job. | 899 // that launched this job. |
| 900 delegate_->SetSpdySessionKey(this, spdy_session_key); | 900 delegate_->SetSpdySessionKey(this, spdy_session_key_); |
| 901 } | 901 } |
| 902 | 902 |
| 903 if (proxy_info_.is_http() || proxy_info_.is_https()) | 903 if (proxy_info_.is_http() || proxy_info_.is_https()) |
| 904 establishing_tunnel_ = using_ssl_; | 904 establishing_tunnel_ = using_ssl_; |
| 905 | 905 |
| 906 const bool expect_spdy = IsSpdyAlternative(); | 906 const bool expect_spdy = IsSpdyAlternative(); |
| 907 | 907 |
| 908 HttpServerProperties* http_server_properties = | 908 HttpServerProperties* http_server_properties = |
| 909 session_->http_server_properties(); | 909 session_->http_server_properties(); |
| 910 if (http_server_properties) { | 910 if (http_server_properties) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 922 request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy, | 922 request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy, |
| 923 server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode, | 923 server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode, |
| 924 net_log_, num_streams_); | 924 net_log_, num_streams_); |
| 925 } | 925 } |
| 926 | 926 |
| 927 // If we can't use a SPDY session, don't bother checking for one after | 927 // If we can't use a SPDY session, don't bother checking for one after |
| 928 // the hostname is resolved. | 928 // the hostname is resolved. |
| 929 OnHostResolutionCallback resolution_callback = | 929 OnHostResolutionCallback resolution_callback = |
| 930 CanUseExistingSpdySession() | 930 CanUseExistingSpdySession() |
| 931 ? base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(), | 931 ? base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(), |
| 932 spdy_session_key, origin_url_, enable_ip_based_pooling_) | 932 spdy_session_key_, origin_url_, enable_ip_based_pooling_) |
| 933 : OnHostResolutionCallback(); | 933 : OnHostResolutionCallback(); |
| 934 if (delegate_->for_websockets()) { | 934 if (delegate_->for_websockets()) { |
| 935 SSLConfig websocket_server_ssl_config = server_ssl_config_; | 935 SSLConfig websocket_server_ssl_config = server_ssl_config_; |
| 936 websocket_server_ssl_config.alpn_protos.clear(); | 936 websocket_server_ssl_config.alpn_protos.clear(); |
| 937 return InitSocketHandleForWebSocketRequest( | 937 return InitSocketHandleForWebSocketRequest( |
| 938 GetSocketGroup(), destination_, request_info_.extra_headers, | 938 GetSocketGroup(), destination_, request_info_.extra_headers, |
| 939 request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy, | 939 request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy, |
| 940 websocket_server_ssl_config, proxy_ssl_config_, | 940 websocket_server_ssl_config, proxy_ssl_config_, |
| 941 request_info_.privacy_mode, net_log_, connection_.get(), | 941 request_info_.privacy_mode, net_log_, connection_.get(), |
| 942 resolution_callback, io_callback_); | 942 resolution_callback, io_callback_); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 954 if (job_type_ == PRECONNECT) { | 954 if (job_type_ == PRECONNECT) { |
| 955 if (using_quic_) | 955 if (using_quic_) |
| 956 return result; | 956 return result; |
| 957 DCHECK_EQ(OK, result); | 957 DCHECK_EQ(OK, result); |
| 958 return OK; | 958 return OK; |
| 959 } | 959 } |
| 960 | 960 |
| 961 if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { | 961 if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) { |
| 962 // We found a SPDY connection after resolving the host. This is | 962 // We found a SPDY connection after resolving the host. This is |
| 963 // probably an IP pooled connection. | 963 // probably an IP pooled connection. |
| 964 SpdySessionKey spdy_session_key = GetSpdySessionKey(); | |
| 965 existing_spdy_session_ = | 964 existing_spdy_session_ = |
| 966 session_->spdy_session_pool()->FindAvailableSession( | 965 session_->spdy_session_pool()->FindAvailableSession( |
| 967 spdy_session_key, origin_url_, enable_ip_based_pooling_, net_log_); | 966 spdy_session_key_, origin_url_, enable_ip_based_pooling_, net_log_); |
| 968 if (existing_spdy_session_) { | 967 if (existing_spdy_session_) { |
| 969 using_spdy_ = true; | 968 using_spdy_ = true; |
| 970 next_state_ = STATE_CREATE_STREAM; | 969 next_state_ = STATE_CREATE_STREAM; |
| 971 } else { | 970 } else { |
| 972 // It is possible that the spdy session no longer exists. | 971 // It is possible that the spdy session no longer exists. |
| 973 ReturnToStateInitConnection(true /* close connection */); | 972 ReturnToStateInitConnection(true /* close connection */); |
| 974 } | 973 } |
| 975 return OK; | 974 return OK; |
| 976 } | 975 } |
| 977 | 976 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 } else { | 1157 } else { |
| 1159 stream_ = base::MakeUnique<HttpBasicStream>( | 1158 stream_ = base::MakeUnique<HttpBasicStream>( |
| 1160 std::move(connection_), using_proxy, | 1159 std::move(connection_), using_proxy, |
| 1161 session_->params().http_09_on_non_default_ports_enabled); | 1160 session_->params().http_09_on_non_default_ports_enabled); |
| 1162 } | 1161 } |
| 1163 return OK; | 1162 return OK; |
| 1164 } | 1163 } |
| 1165 | 1164 |
| 1166 CHECK(!stream_.get()); | 1165 CHECK(!stream_.get()); |
| 1167 | 1166 |
| 1168 SpdySessionKey spdy_session_key = GetSpdySessionKey(); | |
| 1169 if (!existing_spdy_session_) { | 1167 if (!existing_spdy_session_) { |
| 1170 existing_spdy_session_ = | 1168 existing_spdy_session_ = |
| 1171 session_->spdy_session_pool()->FindAvailableSession( | 1169 session_->spdy_session_pool()->FindAvailableSession( |
| 1172 spdy_session_key, origin_url_, enable_ip_based_pooling_, net_log_); | 1170 spdy_session_key_, origin_url_, enable_ip_based_pooling_, net_log_); |
| 1173 } | 1171 } |
| 1174 bool direct = !IsHttpsProxyAndHttpUrl(); | |
| 1175 if (existing_spdy_session_.get()) { | 1172 if (existing_spdy_session_.get()) { |
| 1176 // We picked up an existing session, so we don't need our socket. | 1173 // We picked up an existing session, so we don't need our socket. |
| 1177 if (connection_->socket()) | 1174 if (connection_->socket()) |
| 1178 connection_->socket()->Disconnect(); | 1175 connection_->socket()->Disconnect(); |
| 1179 connection_->Reset(); | 1176 connection_->Reset(); |
| 1180 | 1177 |
| 1181 int set_result = SetSpdyHttpStreamOrBidirectionalStreamImpl( | 1178 int set_result = SetSpdyHttpStreamOrBidirectionalStreamImpl( |
| 1182 existing_spdy_session_, direct); | 1179 existing_spdy_session_, spdy_session_direct_); |
| 1183 existing_spdy_session_.reset(); | 1180 existing_spdy_session_.reset(); |
| 1184 return set_result; | 1181 return set_result; |
| 1185 } | 1182 } |
| 1186 | 1183 |
| 1187 // Close idle sockets in this group, since subsequent requests will go over | 1184 // Close idle sockets in this group, since subsequent requests will go over |
| 1188 // |spdy_session|. | 1185 // |spdy_session|. |
| 1189 if (connection_->socket()->IsConnected()) | 1186 if (connection_->socket()->IsConnected()) |
| 1190 connection_->CloseIdleSocketsInGroup(); | 1187 connection_->CloseIdleSocketsInGroup(); |
| 1191 | 1188 |
| 1192 base::WeakPtr<SpdySession> spdy_session = | 1189 base::WeakPtr<SpdySession> spdy_session = |
| 1193 session_->spdy_session_pool()->CreateAvailableSessionFromSocket( | 1190 session_->spdy_session_pool()->CreateAvailableSessionFromSocket( |
| 1194 spdy_session_key, std::move(connection_), net_log_, using_ssl_); | 1191 spdy_session_key_, std::move(connection_), net_log_, using_ssl_); |
| 1195 | 1192 |
| 1196 if (!spdy_session->HasAcceptableTransportSecurity()) { | 1193 if (!spdy_session->HasAcceptableTransportSecurity()) { |
| 1197 spdy_session->CloseSessionOnError( | 1194 spdy_session->CloseSessionOnError( |
| 1198 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, ""); | 1195 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, ""); |
| 1199 return ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY; | 1196 return ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY; |
| 1200 } | 1197 } |
| 1201 | 1198 |
| 1202 new_spdy_session_ = spdy_session; | 1199 new_spdy_session_ = spdy_session; |
| 1203 spdy_session_direct_ = direct; | |
| 1204 const HostPortPair host_port_pair = spdy_session_key.host_port_pair(); | |
| 1205 url::SchemeHostPort scheme_host_port( | 1200 url::SchemeHostPort scheme_host_port( |
| 1206 using_ssl_ ? url::kHttpsScheme : url::kHttpScheme, host_port_pair.host(), | 1201 using_ssl_ ? url::kHttpsScheme : url::kHttpScheme, |
| 1207 host_port_pair.port()); | 1202 spdy_session_key_.host_port_pair().host(), |
| 1203 spdy_session_key_.host_port_pair().port()); |
| 1208 | 1204 |
| 1209 HttpServerProperties* http_server_properties = | 1205 HttpServerProperties* http_server_properties = |
| 1210 session_->http_server_properties(); | 1206 session_->http_server_properties(); |
| 1211 if (http_server_properties) | 1207 if (http_server_properties) |
| 1212 http_server_properties->SetSupportsSpdy(scheme_host_port, true); | 1208 http_server_properties->SetSupportsSpdy(scheme_host_port, true); |
| 1213 | 1209 |
| 1214 // Create a SpdyHttpStream or a BidirectionalStreamImpl attached to the | 1210 // Create a SpdyHttpStream or a BidirectionalStreamImpl attached to the |
| 1215 // session; OnNewSpdySessionReadyCallback is not called until an event loop | 1211 // session; OnNewSpdySessionReadyCallback is not called until an event loop |
| 1216 // iteration later, so if the SpdySession is closed between then, allow | 1212 // iteration later, so if the SpdySession is closed between then, allow |
| 1217 // reuse state from the underlying socket, sampled by SpdyHttpStream, | 1213 // reuse state from the underlying socket, sampled by SpdyHttpStream, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 } | 1264 } |
| 1269 | 1265 |
| 1270 void HttpStreamFactoryImpl::Job::SetSocketMotivation() { | 1266 void HttpStreamFactoryImpl::Job::SetSocketMotivation() { |
| 1271 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) | 1267 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) |
| 1272 connection_->socket()->SetSubresourceSpeculation(); | 1268 connection_->socket()->SetSubresourceSpeculation(); |
| 1273 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) | 1269 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) |
| 1274 connection_->socket()->SetOmniboxSpeculation(); | 1270 connection_->socket()->SetOmniboxSpeculation(); |
| 1275 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). | 1271 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). |
| 1276 } | 1272 } |
| 1277 | 1273 |
| 1278 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() const { | |
| 1279 if (!proxy_info_.is_https()) | |
| 1280 return false; | |
| 1281 DCHECK(!IsSpdyAlternative()); | |
| 1282 if (IsQuicAlternative()) { | |
| 1283 // We currently only support Alternate-Protocol where the original scheme | |
| 1284 // is http. | |
| 1285 // TODO(bnc): This comment is probably incorrect. | |
| 1286 DCHECK(origin_url_.SchemeIs(url::kHttpScheme)); | |
| 1287 return origin_url_.SchemeIs(url::kHttpScheme); | |
| 1288 } | |
| 1289 return request_info_.url.SchemeIs(url::kHttpScheme); | |
| 1290 } | |
| 1291 | |
| 1292 bool HttpStreamFactoryImpl::Job::IsSpdyAlternative() const { | 1274 bool HttpStreamFactoryImpl::Job::IsSpdyAlternative() const { |
| 1293 return alternative_service_.protocol == kProtoHTTP2; | 1275 return alternative_service_.protocol == kProtoHTTP2; |
| 1294 } | 1276 } |
| 1295 | 1277 |
| 1296 bool HttpStreamFactoryImpl::Job::IsQuicAlternative() const { | 1278 bool HttpStreamFactoryImpl::Job::IsQuicAlternative() const { |
| 1297 return alternative_service_.protocol == kProtoQUIC; | 1279 return alternative_service_.protocol == kProtoQUIC; |
| 1298 } | 1280 } |
| 1299 | 1281 |
| 1300 void HttpStreamFactoryImpl::Job::InitSSLConfig(SSLConfig* ssl_config, | 1282 void HttpStreamFactoryImpl::Job::InitSSLConfig(SSLConfig* ssl_config, |
| 1301 bool is_proxy) const { | 1283 bool is_proxy) const { |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 bool enable_ip_based_pooling, | 1486 bool enable_ip_based_pooling, |
| 1505 NetLog* net_log) { | 1487 NetLog* net_log) { |
| 1506 return base::MakeUnique<HttpStreamFactoryImpl::Job>( | 1488 return base::MakeUnique<HttpStreamFactoryImpl::Job>( |
| 1507 delegate, job_type, session, request_info, priority, proxy_info, | 1489 delegate, job_type, session, request_info, priority, proxy_info, |
| 1508 server_ssl_config, proxy_ssl_config, destination, origin_url, | 1490 server_ssl_config, proxy_ssl_config, destination, origin_url, |
| 1509 AlternativeService(), alternative_proxy_server, enable_ip_based_pooling, | 1491 AlternativeService(), alternative_proxy_server, enable_ip_based_pooling, |
| 1510 net_log); | 1492 net_log); |
| 1511 } | 1493 } |
| 1512 | 1494 |
| 1513 } // namespace net | 1495 } // namespace net |
| OLD | NEW |