| 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/spdy/spdy_session_pool.h" | 5 #include "net/spdy/spdy_session_pool.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/values.h" | 10 #include "base/values.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 bool HostPortProxyPairsAreEqual(const HostPortProxyPair& a, | 29 bool HostPortProxyPairsAreEqual(const HostPortProxyPair& a, |
| 30 const HostPortProxyPair& b) { | 30 const HostPortProxyPair& b) { |
| 31 return a.first.Equals(b.first) && a.second == b.second; | 31 return a.first.Equals(b.first) && a.second == b.second; |
| 32 } | 32 } |
| 33 | 33 |
| 34 } | 34 } |
| 35 | 35 |
| 36 // The maximum number of sessions to open to a single domain. | 36 // The maximum number of sessions to open to a single domain. |
| 37 static const size_t kMaxSessionsPerDomain = 1; | 37 static const size_t kMaxSessionsPerDomain = 1; |
| 38 | 38 |
| 39 size_t SpdySessionPool::g_max_sessions_per_domain = kMaxSessionsPerDomain; | |
| 40 bool SpdySessionPool::g_force_single_domain = false; | |
| 41 bool SpdySessionPool::g_enable_ip_pooling = true; | |
| 42 | |
| 43 SpdySessionPool::SpdySessionPool( | 39 SpdySessionPool::SpdySessionPool( |
| 44 HostResolver* resolver, | 40 HostResolver* resolver, |
| 45 SSLConfigService* ssl_config_service, | 41 SSLConfigService* ssl_config_service, |
| 46 HttpServerProperties* http_server_properties, | 42 HttpServerProperties* http_server_properties, |
| 43 size_t max_sessions_per_domain, |
| 44 bool force_single_domain, |
| 45 bool enable_ip_pooling, |
| 46 bool enable_credential_frames, |
| 47 bool enable_compression, |
| 48 bool enable_ping_based_connection_checking, |
| 49 NextProto default_protocol, |
| 50 size_t initial_recv_window_size, |
| 51 size_t initial_max_concurrent_streams, |
| 52 size_t max_concurrent_streams_limit, |
| 53 SpdySessionPool::TimeFunc time_func, |
| 47 const std::string& trusted_spdy_proxy) | 54 const std::string& trusted_spdy_proxy) |
| 48 : http_server_properties_(http_server_properties), | 55 : http_server_properties_(http_server_properties), |
| 49 ssl_config_service_(ssl_config_service), | 56 ssl_config_service_(ssl_config_service), |
| 50 resolver_(resolver), | 57 resolver_(resolver), |
| 51 verify_domain_authentication_(true), | 58 verify_domain_authentication_(true), |
| 52 enable_sending_initial_settings_(true), | 59 enable_sending_initial_settings_(true), |
| 60 max_sessions_per_domain_(max_sessions_per_domain == 0 ? |
| 61 kMaxSessionsPerDomain : |
| 62 max_sessions_per_domain), |
| 63 force_single_domain_(force_single_domain), |
| 64 enable_ip_pooling_(enable_ip_pooling), |
| 65 enable_credential_frames_(enable_credential_frames), |
| 66 enable_compression_(enable_compression), |
| 67 enable_ping_based_connection_checking_( |
| 68 enable_ping_based_connection_checking), |
| 69 default_protocol_(default_protocol), |
| 70 initial_recv_window_size_(initial_recv_window_size), |
| 71 initial_max_concurrent_streams_(initial_max_concurrent_streams), |
| 72 max_concurrent_streams_limit_(max_concurrent_streams_limit), |
| 73 time_func_(time_func), |
| 53 trusted_spdy_proxy_( | 74 trusted_spdy_proxy_( |
| 54 HostPortPair::FromString(trusted_spdy_proxy)) { | 75 HostPortPair::FromString(trusted_spdy_proxy)) { |
| 55 NetworkChangeNotifier::AddIPAddressObserver(this); | 76 NetworkChangeNotifier::AddIPAddressObserver(this); |
| 56 if (ssl_config_service_) | 77 if (ssl_config_service_) |
| 57 ssl_config_service_->AddObserver(this); | 78 ssl_config_service_->AddObserver(this); |
| 58 CertDatabase::GetInstance()->AddObserver(this); | 79 CertDatabase::GetInstance()->AddObserver(this); |
| 59 } | 80 } |
| 60 | 81 |
| 61 SpdySessionPool::~SpdySessionPool() { | 82 SpdySessionPool::~SpdySessionPool() { |
| 62 CloseAllSessions(); | 83 CloseAllSessions(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 list->push_back(spdy_session); | 121 list->push_back(spdy_session); |
| 101 spdy_session->AddPooledAlias(host_port_proxy_pair); | 122 spdy_session->AddPooledAlias(host_port_proxy_pair); |
| 102 return spdy_session; | 123 return spdy_session; |
| 103 } else if (only_use_existing_sessions) { | 124 } else if (only_use_existing_sessions) { |
| 104 return NULL; | 125 return NULL; |
| 105 } | 126 } |
| 106 list = AddSessionList(host_port_proxy_pair); | 127 list = AddSessionList(host_port_proxy_pair); |
| 107 } | 128 } |
| 108 | 129 |
| 109 DCHECK(list); | 130 DCHECK(list); |
| 110 if (list->size() && list->size() == g_max_sessions_per_domain) { | 131 if (list->size() && list->size() == max_sessions_per_domain_) { |
| 111 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", | 132 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", |
| 112 FOUND_EXISTING, | 133 FOUND_EXISTING, |
| 113 SPDY_SESSION_GET_MAX); | 134 SPDY_SESSION_GET_MAX); |
| 114 spdy_session = GetExistingSession(list, net_log); | 135 spdy_session = GetExistingSession(list, net_log); |
| 115 net_log.AddEvent( | 136 net_log.AddEvent( |
| 116 NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION, | 137 NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION, |
| 117 spdy_session->net_log().source().ToEventParametersCallback()); | 138 spdy_session->net_log().source().ToEventParametersCallback()); |
| 118 return spdy_session; | 139 return spdy_session; |
| 119 } | 140 } |
| 120 | 141 |
| 121 DCHECK(!only_use_existing_sessions); | 142 DCHECK(!only_use_existing_sessions); |
| 122 | 143 |
| 123 spdy_session = new SpdySession(host_port_proxy_pair, this, | 144 spdy_session = new SpdySession(host_port_proxy_pair, this, |
| 124 http_server_properties_, | 145 http_server_properties_, |
| 125 verify_domain_authentication_, | 146 verify_domain_authentication_, |
| 126 enable_sending_initial_settings_, | 147 enable_sending_initial_settings_, |
| 148 enable_credential_frames_, |
| 149 enable_compression_, |
| 150 enable_ping_based_connection_checking_, |
| 151 default_protocol_, |
| 152 initial_recv_window_size_, |
| 153 initial_max_concurrent_streams_, |
| 154 max_concurrent_streams_limit_, |
| 155 time_func_, |
| 127 trusted_spdy_proxy_, | 156 trusted_spdy_proxy_, |
| 128 net_log.net_log()); | 157 net_log.net_log()); |
| 129 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", | 158 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", |
| 130 CREATED_NEW, | 159 CREATED_NEW, |
| 131 SPDY_SESSION_GET_MAX); | 160 SPDY_SESSION_GET_MAX); |
| 132 list->push_back(spdy_session); | 161 list->push_back(spdy_session); |
| 133 net_log.AddEvent( | 162 net_log.AddEvent( |
| 134 NetLog::TYPE_SPDY_SESSION_POOL_CREATED_NEW_SESSION, | 163 NetLog::TYPE_SPDY_SESSION_POOL_CREATED_NEW_SESSION, |
| 135 spdy_session->net_log().source().ToEventParametersCallback()); | 164 spdy_session->net_log().source().ToEventParametersCallback()); |
| 136 DCHECK_LE(list->size(), g_max_sessions_per_domain); | 165 DCHECK_LE(list->size(), max_sessions_per_domain_); |
| 137 return spdy_session; | 166 return spdy_session; |
| 138 } | 167 } |
| 139 | 168 |
| 140 net::Error SpdySessionPool::GetSpdySessionFromSocket( | 169 net::Error SpdySessionPool::GetSpdySessionFromSocket( |
| 141 const HostPortProxyPair& host_port_proxy_pair, | 170 const HostPortProxyPair& host_port_proxy_pair, |
| 142 ClientSocketHandle* connection, | 171 ClientSocketHandle* connection, |
| 143 const BoundNetLog& net_log, | 172 const BoundNetLog& net_log, |
| 144 int certificate_error_code, | 173 int certificate_error_code, |
| 145 scoped_refptr<SpdySession>* spdy_session, | 174 scoped_refptr<SpdySession>* spdy_session, |
| 146 bool is_secure) { | 175 bool is_secure) { |
| 147 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", | 176 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", |
| 148 IMPORTED_FROM_SOCKET, | 177 IMPORTED_FROM_SOCKET, |
| 149 SPDY_SESSION_GET_MAX); | 178 SPDY_SESSION_GET_MAX); |
| 150 // Create the SPDY session and add it to the pool. | 179 // Create the SPDY session and add it to the pool. |
| 151 *spdy_session = new SpdySession(host_port_proxy_pair, this, | 180 *spdy_session = new SpdySession(host_port_proxy_pair, this, |
| 152 http_server_properties_, | 181 http_server_properties_, |
| 153 verify_domain_authentication_, | 182 verify_domain_authentication_, |
| 154 enable_sending_initial_settings_, | 183 enable_sending_initial_settings_, |
| 184 enable_credential_frames_, |
| 185 enable_compression_, |
| 186 enable_ping_based_connection_checking_, |
| 187 default_protocol_, |
| 188 initial_recv_window_size_, |
| 189 initial_max_concurrent_streams_, |
| 190 max_concurrent_streams_limit_, |
| 191 time_func_, |
| 155 trusted_spdy_proxy_, | 192 trusted_spdy_proxy_, |
| 156 net_log.net_log()); | 193 net_log.net_log()); |
| 157 SpdySessionList* list = GetSessionList(host_port_proxy_pair); | 194 SpdySessionList* list = GetSessionList(host_port_proxy_pair); |
| 158 if (!list) | 195 if (!list) |
| 159 list = AddSessionList(host_port_proxy_pair); | 196 list = AddSessionList(host_port_proxy_pair); |
| 160 DCHECK(list->empty()); | 197 DCHECK(list->empty()); |
| 161 list->push_back(*spdy_session); | 198 list->push_back(*spdy_session); |
| 162 | 199 |
| 163 net_log.AddEvent( | 200 net_log.AddEvent( |
| 164 NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET, | 201 NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET, |
| 165 (*spdy_session)->net_log().source().ToEventParametersCallback()); | 202 (*spdy_session)->net_log().source().ToEventParametersCallback()); |
| 166 | 203 |
| 167 // We have a new session. Lookup the IP address for this session so that we | 204 // We have a new session. Lookup the IP address for this session so that we |
| 168 // can match future Sessions (potentially to different domains) which can | 205 // can match future Sessions (potentially to different domains) which can |
| 169 // potentially be pooled with this one. Because GetPeerAddress() reports the | 206 // potentially be pooled with this one. Because GetPeerAddress() reports the |
| 170 // proxy's address instead of the origin server, check to see if this is a | 207 // proxy's address instead of the origin server, check to see if this is a |
| 171 // direct connection. | 208 // direct connection. |
| 172 if (g_enable_ip_pooling && host_port_proxy_pair.second.is_direct()) { | 209 if (enable_ip_pooling_ && host_port_proxy_pair.second.is_direct()) { |
| 173 IPEndPoint address; | 210 IPEndPoint address; |
| 174 if (connection->socket()->GetPeerAddress(&address) == OK) | 211 if (connection->socket()->GetPeerAddress(&address) == OK) |
| 175 AddAlias(address, host_port_proxy_pair); | 212 AddAlias(address, host_port_proxy_pair); |
| 176 } | 213 } |
| 177 | 214 |
| 178 // Now we can initialize the session with the SSL socket. | 215 // Now we can initialize the session with the SSL socket. |
| 179 return (*spdy_session)->InitializeWithSocket(connection, is_secure, | 216 return (*spdy_session)->InitializeWithSocket(connection, is_secure, |
| 180 certificate_error_code); | 217 certificate_error_code); |
| 181 } | 218 } |
| 182 | 219 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 return spdy_session; | 297 return spdy_session; |
| 261 } | 298 } |
| 262 | 299 |
| 263 scoped_refptr<SpdySession> SpdySessionPool::GetFromAlias( | 300 scoped_refptr<SpdySession> SpdySessionPool::GetFromAlias( |
| 264 const HostPortProxyPair& host_port_proxy_pair, | 301 const HostPortProxyPair& host_port_proxy_pair, |
| 265 const BoundNetLog& net_log, | 302 const BoundNetLog& net_log, |
| 266 bool record_histograms) const { | 303 bool record_histograms) const { |
| 267 // We should only be checking aliases when there is no direct session. | 304 // We should only be checking aliases when there is no direct session. |
| 268 DCHECK(!GetSessionList(host_port_proxy_pair)); | 305 DCHECK(!GetSessionList(host_port_proxy_pair)); |
| 269 | 306 |
| 270 if (!g_enable_ip_pooling) | 307 if (!enable_ip_pooling_) |
| 271 return NULL; | 308 return NULL; |
| 272 | 309 |
| 273 AddressList addresses; | 310 AddressList addresses; |
| 274 if (!LookupAddresses(host_port_proxy_pair, net_log, &addresses)) | 311 if (!LookupAddresses(host_port_proxy_pair, net_log, &addresses)) |
| 275 return NULL; | 312 return NULL; |
| 276 for (AddressList::const_iterator iter = addresses.begin(); | 313 for (AddressList::const_iterator iter = addresses.begin(); |
| 277 iter != addresses.end(); | 314 iter != addresses.end(); |
| 278 ++iter) { | 315 ++iter) { |
| 279 SpdyAliasMap::const_iterator alias_iter = aliases_.find(*iter); | 316 SpdyAliasMap::const_iterator alias_iter = aliases_.find(*iter); |
| 280 if (alias_iter == aliases_.end()) | 317 if (alias_iter == aliases_.end()) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 void SpdySessionPool::OnCertTrustChanged(const X509Certificate* cert) { | 353 void SpdySessionPool::OnCertTrustChanged(const X509Certificate* cert) { |
| 317 // Per wtc, we actually only need to CloseCurrentSessions when trust is | 354 // Per wtc, we actually only need to CloseCurrentSessions when trust is |
| 318 // reduced. CloseCurrentSessions now because OnCertTrustChanged does not | 355 // reduced. CloseCurrentSessions now because OnCertTrustChanged does not |
| 319 // tell us this. | 356 // tell us this. |
| 320 // See comments in ClientSocketPoolManager::OnCertTrustChanged. | 357 // See comments in ClientSocketPoolManager::OnCertTrustChanged. |
| 321 CloseCurrentSessions(); | 358 CloseCurrentSessions(); |
| 322 } | 359 } |
| 323 | 360 |
| 324 const HostPortProxyPair& SpdySessionPool::NormalizeListPair( | 361 const HostPortProxyPair& SpdySessionPool::NormalizeListPair( |
| 325 const HostPortProxyPair& host_port_proxy_pair) const { | 362 const HostPortProxyPair& host_port_proxy_pair) const { |
| 326 if (!g_force_single_domain) | 363 if (!force_single_domain_) |
| 327 return host_port_proxy_pair; | 364 return host_port_proxy_pair; |
| 328 | 365 |
| 329 static HostPortProxyPair* single_domain_pair = NULL; | 366 static HostPortProxyPair* single_domain_pair = NULL; |
| 330 if (!single_domain_pair) { | 367 if (!single_domain_pair) { |
| 331 HostPortPair single_domain = HostPortPair("singledomain.com", 80); | 368 HostPortPair single_domain = HostPortPair("singledomain.com", 80); |
| 332 single_domain_pair = new HostPortProxyPair(single_domain, | 369 single_domain_pair = new HostPortProxyPair(single_domain, |
| 333 ProxyServer::Direct()); | 370 ProxyServer::Direct()); |
| 334 } | 371 } |
| 335 return *single_domain_pair; | 372 return *single_domain_pair; |
| 336 } | 373 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 const BoundNetLog& net_log, | 409 const BoundNetLog& net_log, |
| 373 AddressList* addresses) const { | 410 AddressList* addresses) const { |
| 374 net::HostResolver::RequestInfo resolve_info(pair.first); | 411 net::HostResolver::RequestInfo resolve_info(pair.first); |
| 375 int rv = resolver_->ResolveFromCache(resolve_info, addresses, net_log); | 412 int rv = resolver_->ResolveFromCache(resolve_info, addresses, net_log); |
| 376 DCHECK_NE(ERR_IO_PENDING, rv); | 413 DCHECK_NE(ERR_IO_PENDING, rv); |
| 377 return rv == OK; | 414 return rv == OK; |
| 378 } | 415 } |
| 379 | 416 |
| 380 void SpdySessionPool::AddAlias(const IPEndPoint& endpoint, | 417 void SpdySessionPool::AddAlias(const IPEndPoint& endpoint, |
| 381 const HostPortProxyPair& pair) { | 418 const HostPortProxyPair& pair) { |
| 382 DCHECK(g_enable_ip_pooling); | 419 DCHECK(enable_ip_pooling_); |
| 383 aliases_[endpoint] = pair; | 420 aliases_[endpoint] = pair; |
| 384 } | 421 } |
| 385 | 422 |
| 386 void SpdySessionPool::RemoveAliases(const HostPortProxyPair& pair) { | 423 void SpdySessionPool::RemoveAliases(const HostPortProxyPair& pair) { |
| 387 // Walk the aliases map, find references to this pair. | 424 // Walk the aliases map, find references to this pair. |
| 388 // TODO(mbelshe): Figure out if this is too expensive. | 425 // TODO(mbelshe): Figure out if this is too expensive. |
| 389 SpdyAliasMap::iterator alias_it = aliases_.begin(); | 426 SpdyAliasMap::iterator alias_it = aliases_.begin(); |
| 390 while (alias_it != aliases_.end()) { | 427 while (alias_it != aliases_.end()) { |
| 391 if (HostPortProxyPairsAreEqual(alias_it->second, pair)) { | 428 if (HostPortProxyPairsAreEqual(alias_it->second, pair)) { |
| 392 aliases_.erase(alias_it); | 429 aliases_.erase(alias_it); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 const scoped_refptr<SpdySession>& session = *session_it; | 489 const scoped_refptr<SpdySession>& session = *session_it; |
| 453 CHECK(session); | 490 CHECK(session); |
| 454 if (!session->is_active()) { | 491 if (!session->is_active()) { |
| 455 session->CloseSessionOnError( | 492 session->CloseSessionOnError( |
| 456 net::ERR_ABORTED, true, "Closing idle sessions."); | 493 net::ERR_ABORTED, true, "Closing idle sessions."); |
| 457 } | 494 } |
| 458 } | 495 } |
| 459 } | 496 } |
| 460 | 497 |
| 461 } // namespace net | 498 } // namespace net |
| OLD | NEW |