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/logging.h" | 7 #include "base/logging.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/values.h" | 9 #include "base/values.h" |
10 #include "net/base/address_list.h" | 10 #include "net/base/address_list.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 ssl_config_service_->RemoveObserver(this); | 73 ssl_config_service_->RemoveObserver(this); |
74 NetworkChangeNotifier::RemoveIPAddressObserver(this); | 74 NetworkChangeNotifier::RemoveIPAddressObserver(this); |
75 CertDatabase::GetInstance()->RemoveObserver(this); | 75 CertDatabase::GetInstance()->RemoveObserver(this); |
76 } | 76 } |
77 | 77 |
78 net::Error SpdySessionPool::CreateAvailableSessionFromSocket( | 78 net::Error SpdySessionPool::CreateAvailableSessionFromSocket( |
79 const SpdySessionKey& key, | 79 const SpdySessionKey& key, |
80 scoped_ptr<ClientSocketHandle> connection, | 80 scoped_ptr<ClientSocketHandle> connection, |
81 const BoundNetLog& net_log, | 81 const BoundNetLog& net_log, |
82 int certificate_error_code, | 82 int certificate_error_code, |
83 scoped_refptr<SpdySession>* available_session, | 83 base::WeakPtr<SpdySession>* available_session, |
84 bool is_secure) { | 84 bool is_secure) { |
85 UMA_HISTOGRAM_ENUMERATION( | 85 UMA_HISTOGRAM_ENUMERATION( |
86 "Net.SpdySessionGet", IMPORTED_FROM_SOCKET, SPDY_SESSION_GET_MAX); | 86 "Net.SpdySessionGet", IMPORTED_FROM_SOCKET, SPDY_SESSION_GET_MAX); |
87 | 87 |
88 scoped_refptr<SpdySession> new_session( | 88 scoped_refptr<SpdySession> new_session( |
89 new SpdySession(key, | 89 new SpdySession(key, |
90 http_server_properties_, | 90 http_server_properties_, |
91 verify_domain_authentication_, | 91 verify_domain_authentication_, |
92 enable_sending_initial_settings_, | 92 enable_sending_initial_settings_, |
93 enable_credential_frames_, | 93 enable_credential_frames_, |
94 enable_compression_, | 94 enable_compression_, |
95 enable_ping_based_connection_checking_, | 95 enable_ping_based_connection_checking_, |
96 default_protocol_, | 96 default_protocol_, |
97 stream_initial_recv_window_size_, | 97 stream_initial_recv_window_size_, |
98 initial_max_concurrent_streams_, | 98 initial_max_concurrent_streams_, |
99 max_concurrent_streams_limit_, | 99 max_concurrent_streams_limit_, |
100 time_func_, | 100 time_func_, |
101 trusted_spdy_proxy_, | 101 trusted_spdy_proxy_, |
102 net_log.net_log())); | 102 net_log.net_log())); |
103 | 103 |
104 Error error = new_session->InitializeWithSocket( | 104 Error error = new_session->InitializeWithSocket( |
105 connection.Pass(), this, is_secure, certificate_error_code); | 105 connection.Pass(), this, is_secure, certificate_error_code); |
106 DCHECK_NE(error, ERR_IO_PENDING); | 106 DCHECK_NE(error, ERR_IO_PENDING); |
107 | 107 |
108 if (error != OK) { | 108 if (error != OK) { |
109 new_session = NULL; | 109 new_session = NULL; |
110 *available_session = NULL; | 110 available_session->reset(); |
111 return error; | 111 return error; |
112 } | 112 } |
113 | 113 |
114 sessions_.insert(new_session); | 114 sessions_.insert(new_session); |
115 available_session->swap(new_session); | 115 *available_session = new_session->GetWeakPtr(); |
116 MapKeyToAvailableSession(key, *available_session); | 116 MapKeyToAvailableSession(key, *available_session); |
117 | 117 |
118 net_log.AddEvent( | 118 net_log.AddEvent( |
119 NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET, | 119 NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET, |
120 (*available_session)->net_log().source().ToEventParametersCallback()); | 120 (*available_session)->net_log().source().ToEventParametersCallback()); |
121 | 121 |
122 // Look up the IP address for this session so that we can match | 122 // Look up the IP address for this session so that we can match |
123 // future sessions (potentially to different domains) which can | 123 // future sessions (potentially to different domains) which can |
124 // potentially be pooled with this one. Because GetPeerAddress() | 124 // potentially be pooled with this one. Because GetPeerAddress() |
125 // reports the proxy's address instead of the origin server, check | 125 // reports the proxy's address instead of the origin server, check |
126 // to see if this is a direct connection. | 126 // to see if this is a direct connection. |
127 if (enable_ip_pooling_ && key.proxy_server().is_direct()) { | 127 if (enable_ip_pooling_ && key.proxy_server().is_direct()) { |
128 IPEndPoint address; | 128 IPEndPoint address; |
129 if ((*available_session)->GetPeerAddress(&address) == OK) | 129 if ((*available_session)->GetPeerAddress(&address) == OK) |
130 aliases_[address] = key; | 130 aliases_[address] = key; |
131 } | 131 } |
132 | 132 |
133 return error; | 133 return error; |
134 } | 134 } |
135 | 135 |
136 scoped_refptr<SpdySession> SpdySessionPool::FindAvailableSession( | 136 base::WeakPtr<SpdySession> SpdySessionPool::FindAvailableSession( |
137 const SpdySessionKey& key, | 137 const SpdySessionKey& key, |
138 const BoundNetLog& net_log) { | 138 const BoundNetLog& net_log) { |
139 AvailableSessionMap::iterator it = LookupAvailableSessionByKey(key); | 139 AvailableSessionMap::iterator it = LookupAvailableSessionByKey(key); |
140 if (it != available_sessions_.end()) { | 140 if (it != available_sessions_.end()) { |
141 UMA_HISTOGRAM_ENUMERATION( | 141 UMA_HISTOGRAM_ENUMERATION( |
142 "Net.SpdySessionGet", FOUND_EXISTING, SPDY_SESSION_GET_MAX); | 142 "Net.SpdySessionGet", FOUND_EXISTING, SPDY_SESSION_GET_MAX); |
143 net_log.AddEvent( | 143 net_log.AddEvent( |
144 NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION, | 144 NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION, |
145 it->second->net_log().source().ToEventParametersCallback()); | 145 it->second->net_log().source().ToEventParametersCallback()); |
146 return it->second; | 146 return it->second; |
147 } | 147 } |
148 | 148 |
149 if (!enable_ip_pooling_) | 149 if (!enable_ip_pooling_) |
150 return scoped_refptr<SpdySession>(); | 150 return base::WeakPtr<SpdySession>(); |
151 | 151 |
152 // Look up the key's from the resolver's cache. | 152 // Look up the key's from the resolver's cache. |
153 net::HostResolver::RequestInfo resolve_info(key.host_port_pair()); | 153 net::HostResolver::RequestInfo resolve_info(key.host_port_pair()); |
154 AddressList addresses; | 154 AddressList addresses; |
155 int rv = resolver_->ResolveFromCache(resolve_info, &addresses, net_log); | 155 int rv = resolver_->ResolveFromCache(resolve_info, &addresses, net_log); |
156 DCHECK_NE(rv, ERR_IO_PENDING); | 156 DCHECK_NE(rv, ERR_IO_PENDING); |
157 if (rv != OK) | 157 if (rv != OK) |
158 return scoped_refptr<SpdySession>(); | 158 return base::WeakPtr<SpdySession>(); |
159 | 159 |
160 // Check if we have a session through a domain alias. | 160 // Check if we have a session through a domain alias. |
161 for (AddressList::const_iterator address_it = addresses.begin(); | 161 for (AddressList::const_iterator address_it = addresses.begin(); |
162 address_it != addresses.end(); | 162 address_it != addresses.end(); |
163 ++address_it) { | 163 ++address_it) { |
164 AliasMap::const_iterator alias_it = aliases_.find(*address_it); | 164 AliasMap::const_iterator alias_it = aliases_.find(*address_it); |
165 if (alias_it == aliases_.end()) | 165 if (alias_it == aliases_.end()) |
166 continue; | 166 continue; |
167 | 167 |
168 // We found an alias. | 168 // We found an alias. |
169 const SpdySessionKey& alias_key = alias_it->second; | 169 const SpdySessionKey& alias_key = alias_it->second; |
170 | 170 |
171 // We can reuse this session only if the proxy and privacy | 171 // We can reuse this session only if the proxy and privacy |
172 // settings match. | 172 // settings match. |
173 if (!(alias_key.proxy_server() == key.proxy_server()) || | 173 if (!(alias_key.proxy_server() == key.proxy_server()) || |
174 !(alias_key.privacy_mode() == key.privacy_mode())) | 174 !(alias_key.privacy_mode() == key.privacy_mode())) |
175 continue; | 175 continue; |
176 | 176 |
177 AvailableSessionMap::iterator available_session_it = | 177 AvailableSessionMap::iterator available_session_it = |
178 LookupAvailableSessionByKey(alias_key); | 178 LookupAvailableSessionByKey(alias_key); |
179 if (available_session_it == available_sessions_.end()) { | 179 if (available_session_it == available_sessions_.end()) { |
180 NOTREACHED(); // It shouldn't be in the aliases table if we can't get it! | 180 NOTREACHED(); // It shouldn't be in the aliases table if we can't get it! |
181 continue; | 181 continue; |
182 } | 182 } |
183 | 183 |
184 const scoped_refptr<SpdySession>& available_session = | 184 const base::WeakPtr<SpdySession>& available_session = |
185 available_session_it->second; | 185 available_session_it->second; |
186 DCHECK(ContainsKey(sessions_, available_session)); | 186 DCHECK(ContainsKey(sessions_, available_session.get())); |
187 // If the session is a secure one, we need to verify that the | 187 // If the session is a secure one, we need to verify that the |
188 // server is authenticated to serve traffic for |host_port_proxy_pair| too. | 188 // server is authenticated to serve traffic for |host_port_proxy_pair| too. |
189 if (!available_session->VerifyDomainAuthentication( | 189 if (!available_session->VerifyDomainAuthentication( |
190 key.host_port_pair().host())) { | 190 key.host_port_pair().host())) { |
191 UMA_HISTOGRAM_ENUMERATION("Net.SpdyIPPoolDomainMatch", 0, 2); | 191 UMA_HISTOGRAM_ENUMERATION("Net.SpdyIPPoolDomainMatch", 0, 2); |
192 continue; | 192 continue; |
193 } | 193 } |
194 | 194 |
195 UMA_HISTOGRAM_ENUMERATION("Net.SpdyIPPoolDomainMatch", 1, 2); | 195 UMA_HISTOGRAM_ENUMERATION("Net.SpdyIPPoolDomainMatch", 1, 2); |
196 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", | 196 UMA_HISTOGRAM_ENUMERATION("Net.SpdySessionGet", |
197 FOUND_EXISTING_FROM_IP_POOL, | 197 FOUND_EXISTING_FROM_IP_POOL, |
198 SPDY_SESSION_GET_MAX); | 198 SPDY_SESSION_GET_MAX); |
199 net_log.AddEvent( | 199 net_log.AddEvent( |
200 NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL, | 200 NetLog::TYPE_SPDY_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL, |
201 available_session->net_log().source().ToEventParametersCallback()); | 201 available_session->net_log().source().ToEventParametersCallback()); |
202 // Add this session to the map so that we can find it next time. | 202 // Add this session to the map so that we can find it next time. |
203 MapKeyToAvailableSession(key, available_session); | 203 MapKeyToAvailableSession(key, available_session); |
204 available_session->AddPooledAlias(key); | 204 available_session->AddPooledAlias(key); |
205 return available_session; | 205 return available_session; |
206 } | 206 } |
207 | 207 |
208 return scoped_refptr<SpdySession>(); | 208 return base::WeakPtr<SpdySession>(); |
209 } | 209 } |
210 | 210 |
211 void SpdySessionPool::MakeSessionUnavailable( | 211 void SpdySessionPool::MakeSessionUnavailable( |
212 const scoped_refptr<SpdySession>& available_session) { | 212 const base::WeakPtr<SpdySession>& available_session) { |
213 UnmapKey(available_session->spdy_session_key()); | 213 UnmapKey(available_session->spdy_session_key()); |
214 RemoveAliases(available_session->spdy_session_key()); | 214 RemoveAliases(available_session->spdy_session_key()); |
215 const std::set<SpdySessionKey>& aliases = available_session->pooled_aliases(); | 215 const std::set<SpdySessionKey>& aliases = available_session->pooled_aliases(); |
216 for (std::set<SpdySessionKey>::const_iterator it = aliases.begin(); | 216 for (std::set<SpdySessionKey>::const_iterator it = aliases.begin(); |
217 it != aliases.end(); ++it) { | 217 it != aliases.end(); ++it) { |
218 UnmapKey(*it); | 218 UnmapKey(*it); |
219 RemoveAliases(*it); | 219 RemoveAliases(*it); |
220 } | 220 } |
221 DCHECK(!IsSessionAvailable(available_session)); | 221 DCHECK(!IsSessionAvailable(available_session)); |
222 } | 222 } |
223 | 223 |
224 void SpdySessionPool::RemoveUnavailableSession( | 224 void SpdySessionPool::RemoveUnavailableSession( |
225 const scoped_refptr<SpdySession>& unavailable_session) { | 225 const base::WeakPtr<SpdySession>& unavailable_session) { |
226 DCHECK(!IsSessionAvailable(unavailable_session)); | 226 DCHECK(!IsSessionAvailable(unavailable_session)); |
227 | 227 |
228 unavailable_session->net_log().AddEvent( | 228 unavailable_session->net_log().AddEvent( |
229 NetLog::TYPE_SPDY_SESSION_POOL_REMOVE_SESSION, | 229 NetLog::TYPE_SPDY_SESSION_POOL_REMOVE_SESSION, |
230 unavailable_session->net_log().source().ToEventParametersCallback()); | 230 unavailable_session->net_log().source().ToEventParametersCallback()); |
231 | 231 |
232 SessionSet::iterator it = sessions_.find(unavailable_session); | 232 SessionSet::iterator it = sessions_.find(unavailable_session.get()); |
233 CHECK(it != sessions_.end()); | 233 CHECK(it != sessions_.end()); |
234 sessions_.erase(it); | 234 sessions_.erase(it); |
235 } | 235 } |
236 | 236 |
237 // Make a copy of |sessions_| in the Close* functions below to avoid | 237 // Make a copy of |sessions_| in the Close* functions below to avoid |
238 // reentrancy problems. Since arbitrary functions get called by close | 238 // reentrancy problems. Since arbitrary functions get called by close |
239 // handlers, it doesn't suffice to simply increment the iterator | 239 // handlers, it doesn't suffice to simply increment the iterator |
240 // before closing. | 240 // before closing. |
241 | 241 |
242 void SpdySessionPool::CloseCurrentSessions(net::Error error) { | 242 void SpdySessionPool::CloseCurrentSessions(net::Error error) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 | 286 |
287 void SpdySessionPool::OnCertTrustChanged(const X509Certificate* cert) { | 287 void SpdySessionPool::OnCertTrustChanged(const X509Certificate* cert) { |
288 // Per wtc, we actually only need to CloseCurrentSessions when trust is | 288 // Per wtc, we actually only need to CloseCurrentSessions when trust is |
289 // reduced. CloseCurrentSessions now because OnCertTrustChanged does not | 289 // reduced. CloseCurrentSessions now because OnCertTrustChanged does not |
290 // tell us this. | 290 // tell us this. |
291 // See comments in ClientSocketPoolManager::OnCertTrustChanged. | 291 // See comments in ClientSocketPoolManager::OnCertTrustChanged. |
292 CloseCurrentSessions(ERR_NETWORK_CHANGED); | 292 CloseCurrentSessions(ERR_NETWORK_CHANGED); |
293 } | 293 } |
294 | 294 |
295 bool SpdySessionPool::IsSessionAvailable( | 295 bool SpdySessionPool::IsSessionAvailable( |
296 const scoped_refptr<SpdySession>& session) const { | 296 const base::WeakPtr<SpdySession>& session) const { |
297 for (AvailableSessionMap::const_iterator it = available_sessions_.begin(); | 297 for (AvailableSessionMap::const_iterator it = available_sessions_.begin(); |
298 it != available_sessions_.end(); ++it) { | 298 it != available_sessions_.end(); ++it) { |
299 if (it->second == session) | 299 if (it->second.get() == session.get()) |
300 return true; | 300 return true; |
301 } | 301 } |
302 return false; | 302 return false; |
303 } | 303 } |
304 | 304 |
305 const SpdySessionKey& SpdySessionPool::NormalizeListKey( | 305 const SpdySessionKey& SpdySessionPool::NormalizeListKey( |
306 const SpdySessionKey& key) const { | 306 const SpdySessionKey& key) const { |
307 if (!force_single_domain_) | 307 if (!force_single_domain_) |
308 return key; | 308 return key; |
309 | 309 |
310 static SpdySessionKey* single_domain_key = NULL; | 310 static SpdySessionKey* single_domain_key = NULL; |
311 if (!single_domain_key) { | 311 if (!single_domain_key) { |
312 HostPortPair single_domain = HostPortPair("singledomain.com", 80); | 312 HostPortPair single_domain = HostPortPair("singledomain.com", 80); |
313 single_domain_key = new SpdySessionKey(single_domain, | 313 single_domain_key = new SpdySessionKey(single_domain, |
314 ProxyServer::Direct(), | 314 ProxyServer::Direct(), |
315 kPrivacyModeDisabled); | 315 kPrivacyModeDisabled); |
316 } | 316 } |
317 return *single_domain_key; | 317 return *single_domain_key; |
318 } | 318 } |
319 | 319 |
320 void SpdySessionPool::MapKeyToAvailableSession( | 320 void SpdySessionPool::MapKeyToAvailableSession( |
321 const SpdySessionKey& key, | 321 const SpdySessionKey& key, |
322 const scoped_refptr<SpdySession>& session) { | 322 const base::WeakPtr<SpdySession>& session) { |
323 DCHECK(ContainsKey(sessions_, session)); | 323 DCHECK(ContainsKey(sessions_, scoped_refptr<SpdySession>(session.get()))); |
324 const SpdySessionKey& normalized_key = NormalizeListKey(key); | 324 const SpdySessionKey& normalized_key = NormalizeListKey(key); |
325 std::pair<AvailableSessionMap::iterator, bool> result = | 325 std::pair<AvailableSessionMap::iterator, bool> result = |
326 available_sessions_.insert(std::make_pair(normalized_key, session)); | 326 available_sessions_.insert(std::make_pair(normalized_key, session)); |
327 CHECK(result.second); | 327 CHECK(result.second); |
328 } | 328 } |
329 | 329 |
330 SpdySessionPool::AvailableSessionMap::iterator | 330 SpdySessionPool::AvailableSessionMap::iterator |
331 SpdySessionPool::LookupAvailableSessionByKey( | 331 SpdySessionPool::LookupAvailableSessionByKey( |
332 const SpdySessionKey& key) { | 332 const SpdySessionKey& key) { |
333 const SpdySessionKey& normalized_key = NormalizeListKey(key); | 333 const SpdySessionKey& normalized_key = NormalizeListKey(key); |
(...skipping 27 matching lines...) Expand all Loading... |
361 SessionSet current_sessions = sessions_; | 361 SessionSet current_sessions = sessions_; |
362 for (SessionSet::const_iterator it = current_sessions.begin(); | 362 for (SessionSet::const_iterator it = current_sessions.begin(); |
363 it != current_sessions.end(); ++it) { | 363 it != current_sessions.end(); ++it) { |
364 if (!ContainsKey(sessions_, *it)) | 364 if (!ContainsKey(sessions_, *it)) |
365 continue; | 365 continue; |
366 | 366 |
367 if (idle_only && (*it)->is_active()) | 367 if (idle_only && (*it)->is_active()) |
368 continue; | 368 continue; |
369 | 369 |
370 (*it)->CloseSessionOnError(error, description); | 370 (*it)->CloseSessionOnError(error, description); |
371 DCHECK(!IsSessionAvailable(*it)); | 371 DCHECK(!IsSessionAvailable((*it)->GetWeakPtr())); |
372 DCHECK(!ContainsKey(sessions_, *it)); | 372 DCHECK(!ContainsKey(sessions_, *it)); |
373 } | 373 } |
374 } | 374 } |
375 | 375 |
376 } // namespace net | 376 } // namespace net |
OLD | NEW |