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 |