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
3 // found in the LICENSE file.
5 #include "net/socket/client_socket_pool_manager_impl.h"
7 #include "base/logging.h"
8 #include "base/values.h"
9 #include "net/http/http_network_session.h"
10 #include "net/http/http_proxy_client_socket_pool.h"
11 #include "net/socket/socks_client_socket_pool.h"
12 #include "net/socket/ssl_client_socket_pool.h"
13 #include "net/socket/transport_client_socket_pool.h"
14 #include "net/ssl/ssl_config_service.h"
20 // Appends information about all |socket_pools| to the end of |list|.
21 template <class MapType
>
22 void AddSocketPoolsToList(base::ListValue
* list
,
23 const MapType
& socket_pools
,
24 const std::string
& type
,
25 bool include_nested_pools
) {
26 for (typename
MapType::const_iterator it
= socket_pools
.begin();
27 it
!= socket_pools
.end(); it
++) {
28 list
->Append(it
->second
->GetInfoAsValue(it
->first
.ToString(),
30 include_nested_pools
));
36 ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl(
38 ClientSocketFactory
* socket_factory
,
39 HostResolver
* host_resolver
,
40 CertVerifier
* cert_verifier
,
41 ServerBoundCertService
* server_bound_cert_service
,
42 TransportSecurityState
* transport_security_state
,
43 const std::string
& ssl_session_cache_shard
,
44 ProxyService
* proxy_service
,
45 SSLConfigService
* ssl_config_service
,
46 HttpNetworkSession::SocketPoolType pool_type
)
48 socket_factory_(socket_factory
),
49 host_resolver_(host_resolver
),
50 cert_verifier_(cert_verifier
),
51 server_bound_cert_service_(server_bound_cert_service
),
52 transport_security_state_(transport_security_state
),
53 ssl_session_cache_shard_(ssl_session_cache_shard
),
54 proxy_service_(proxy_service
),
55 ssl_config_service_(ssl_config_service
),
56 pool_type_(pool_type
),
57 transport_pool_histograms_("TCP"),
58 transport_socket_pool_(new TransportClientSocketPool(
59 max_sockets_per_pool(pool_type
), max_sockets_per_group(pool_type
),
60 &transport_pool_histograms_
,
64 ssl_pool_histograms_("SSL2"),
65 ssl_socket_pool_(new SSLClientSocketPool(
66 max_sockets_per_pool(pool_type
), max_sockets_per_group(pool_type
),
67 &ssl_pool_histograms_
,
70 server_bound_cert_service
,
71 transport_security_state
,
72 ssl_session_cache_shard
,
74 transport_socket_pool_
.get(),
75 NULL
/* no socks proxy */,
76 NULL
/* no http proxy */,
79 transport_for_socks_pool_histograms_("TCPforSOCKS"),
80 socks_pool_histograms_("SOCK"),
81 transport_for_http_proxy_pool_histograms_("TCPforHTTPProxy"),
82 transport_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"),
83 ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"),
84 http_proxy_pool_histograms_("HTTPProxy"),
85 ssl_socket_pool_for_proxies_histograms_("SSLForProxies") {
86 CertDatabase::GetInstance()->AddObserver(this);
89 ClientSocketPoolManagerImpl::~ClientSocketPoolManagerImpl() {
90 CertDatabase::GetInstance()->RemoveObserver(this);
93 void ClientSocketPoolManagerImpl::FlushSocketPoolsWithError(int error
) {
94 // Flush the highest level pools first, since higher level pools may release
95 // stuff to the lower level pools.
97 for (SSLSocketPoolMap::const_iterator it
=
98 ssl_socket_pools_for_proxies_
.begin();
99 it
!= ssl_socket_pools_for_proxies_
.end();
101 it
->second
->FlushWithError(error
);
103 for (HTTPProxySocketPoolMap::const_iterator it
=
104 http_proxy_socket_pools_
.begin();
105 it
!= http_proxy_socket_pools_
.end();
107 it
->second
->FlushWithError(error
);
109 for (SSLSocketPoolMap::const_iterator it
=
110 ssl_socket_pools_for_https_proxies_
.begin();
111 it
!= ssl_socket_pools_for_https_proxies_
.end();
113 it
->second
->FlushWithError(error
);
115 for (TransportSocketPoolMap::const_iterator it
=
116 transport_socket_pools_for_https_proxies_
.begin();
117 it
!= transport_socket_pools_for_https_proxies_
.end();
119 it
->second
->FlushWithError(error
);
121 for (TransportSocketPoolMap::const_iterator it
=
122 transport_socket_pools_for_http_proxies_
.begin();
123 it
!= transport_socket_pools_for_http_proxies_
.end();
125 it
->second
->FlushWithError(error
);
127 for (SOCKSSocketPoolMap::const_iterator it
=
128 socks_socket_pools_
.begin();
129 it
!= socks_socket_pools_
.end();
131 it
->second
->FlushWithError(error
);
133 for (TransportSocketPoolMap::const_iterator it
=
134 transport_socket_pools_for_socks_proxies_
.begin();
135 it
!= transport_socket_pools_for_socks_proxies_
.end();
137 it
->second
->FlushWithError(error
);
139 ssl_socket_pool_
->FlushWithError(error
);
140 transport_socket_pool_
->FlushWithError(error
);
143 void ClientSocketPoolManagerImpl::CloseIdleSockets() {
144 // Close sockets in the highest level pools first, since higher level pools'
145 // sockets may release stuff to the lower level pools.
146 for (SSLSocketPoolMap::const_iterator it
=
147 ssl_socket_pools_for_proxies_
.begin();
148 it
!= ssl_socket_pools_for_proxies_
.end();
150 it
->second
->CloseIdleSockets();
152 for (HTTPProxySocketPoolMap::const_iterator it
=
153 http_proxy_socket_pools_
.begin();
154 it
!= http_proxy_socket_pools_
.end();
156 it
->second
->CloseIdleSockets();
158 for (SSLSocketPoolMap::const_iterator it
=
159 ssl_socket_pools_for_https_proxies_
.begin();
160 it
!= ssl_socket_pools_for_https_proxies_
.end();
162 it
->second
->CloseIdleSockets();
164 for (TransportSocketPoolMap::const_iterator it
=
165 transport_socket_pools_for_https_proxies_
.begin();
166 it
!= transport_socket_pools_for_https_proxies_
.end();
168 it
->second
->CloseIdleSockets();
170 for (TransportSocketPoolMap::const_iterator it
=
171 transport_socket_pools_for_http_proxies_
.begin();
172 it
!= transport_socket_pools_for_http_proxies_
.end();
174 it
->second
->CloseIdleSockets();
176 for (SOCKSSocketPoolMap::const_iterator it
=
177 socks_socket_pools_
.begin();
178 it
!= socks_socket_pools_
.end();
180 it
->second
->CloseIdleSockets();
182 for (TransportSocketPoolMap::const_iterator it
=
183 transport_socket_pools_for_socks_proxies_
.begin();
184 it
!= transport_socket_pools_for_socks_proxies_
.end();
186 it
->second
->CloseIdleSockets();
188 ssl_socket_pool_
->CloseIdleSockets();
189 transport_socket_pool_
->CloseIdleSockets();
192 TransportClientSocketPool
*
193 ClientSocketPoolManagerImpl::GetTransportSocketPool() {
194 return transport_socket_pool_
.get();
197 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSSLSocketPool() {
198 return ssl_socket_pool_
.get();
201 SOCKSClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy(
202 const HostPortPair
& socks_proxy
) {
203 SOCKSSocketPoolMap::const_iterator it
= socks_socket_pools_
.find(socks_proxy
);
204 if (it
!= socks_socket_pools_
.end()) {
205 DCHECK(ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
209 DCHECK(!ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
211 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_ret
=
212 transport_socket_pools_for_socks_proxies_
.insert(
215 new TransportClientSocketPool(
216 max_sockets_per_proxy_server(pool_type_
),
217 max_sockets_per_group(pool_type_
),
218 &transport_for_socks_pool_histograms_
,
222 DCHECK(tcp_ret
.second
);
224 std::pair
<SOCKSSocketPoolMap::iterator
, bool> ret
=
225 socks_socket_pools_
.insert(
226 std::make_pair(socks_proxy
, new SOCKSClientSocketPool(
227 max_sockets_per_proxy_server(pool_type_
),
228 max_sockets_per_group(pool_type_
),
229 &socks_pool_histograms_
,
231 tcp_ret
.first
->second
,
234 return ret
.first
->second
;
237 HttpProxyClientSocketPool
*
238 ClientSocketPoolManagerImpl::GetSocketPoolForHTTPProxy(
239 const HostPortPair
& http_proxy
) {
240 HTTPProxySocketPoolMap::const_iterator it
=
241 http_proxy_socket_pools_
.find(http_proxy
);
242 if (it
!= http_proxy_socket_pools_
.end()) {
243 DCHECK(ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
244 DCHECK(ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
245 DCHECK(ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
249 DCHECK(!ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
250 DCHECK(!ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
251 DCHECK(!ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
253 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_http_ret
=
254 transport_socket_pools_for_http_proxies_
.insert(
257 new TransportClientSocketPool(
258 max_sockets_per_proxy_server(pool_type_
),
259 max_sockets_per_group(pool_type_
),
260 &transport_for_http_proxy_pool_histograms_
,
264 DCHECK(tcp_http_ret
.second
);
266 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_https_ret
=
267 transport_socket_pools_for_https_proxies_
.insert(
270 new TransportClientSocketPool(
271 max_sockets_per_proxy_server(pool_type_
),
272 max_sockets_per_group(pool_type_
),
273 &transport_for_https_proxy_pool_histograms_
,
277 DCHECK(tcp_https_ret
.second
);
279 std::pair
<SSLSocketPoolMap::iterator
, bool> ssl_https_ret
=
280 ssl_socket_pools_for_https_proxies_
.insert(std::make_pair(
282 new SSLClientSocketPool(max_sockets_per_proxy_server(pool_type_
),
283 max_sockets_per_group(pool_type_
),
284 &ssl_for_https_proxy_pool_histograms_
,
287 server_bound_cert_service_
,
288 transport_security_state_
,
289 ssl_session_cache_shard_
,
291 tcp_https_ret
.first
->second
/* https proxy */,
292 NULL
/* no socks proxy */,
293 NULL
/* no http proxy */,
294 ssl_config_service_
.get(),
296 DCHECK(tcp_https_ret
.second
);
298 std::pair
<HTTPProxySocketPoolMap::iterator
, bool> ret
=
299 http_proxy_socket_pools_
.insert(
302 new HttpProxyClientSocketPool(
303 max_sockets_per_proxy_server(pool_type_
),
304 max_sockets_per_group(pool_type_
),
305 &http_proxy_pool_histograms_
,
307 tcp_http_ret
.first
->second
,
308 ssl_https_ret
.first
->second
,
311 return ret
.first
->second
;
314 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy(
315 const HostPortPair
& proxy_server
) {
316 SSLSocketPoolMap::const_iterator it
=
317 ssl_socket_pools_for_proxies_
.find(proxy_server
);
318 if (it
!= ssl_socket_pools_for_proxies_
.end())
321 SSLClientSocketPool
* new_pool
= new SSLClientSocketPool(
322 max_sockets_per_proxy_server(pool_type_
),
323 max_sockets_per_group(pool_type_
),
324 &ssl_pool_histograms_
,
327 server_bound_cert_service_
,
328 transport_security_state_
,
329 ssl_session_cache_shard_
,
331 NULL
, /* no tcp pool, we always go through a proxy */
332 GetSocketPoolForSOCKSProxy(proxy_server
),
333 GetSocketPoolForHTTPProxy(proxy_server
),
334 ssl_config_service_
.get(),
337 std::pair
<SSLSocketPoolMap::iterator
, bool> ret
=
338 ssl_socket_pools_for_proxies_
.insert(std::make_pair(proxy_server
,
341 return ret
.first
->second
;
344 base::Value
* ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const {
345 base::ListValue
* list
= new base::ListValue();
346 list
->Append(transport_socket_pool_
->GetInfoAsValue("transport_socket_pool",
347 "transport_socket_pool",
349 // Third parameter is false because |ssl_socket_pool_| uses
350 // |transport_socket_pool_| internally, and do not want to add it a second
352 list
->Append(ssl_socket_pool_
->GetInfoAsValue("ssl_socket_pool",
355 AddSocketPoolsToList(list
,
356 http_proxy_socket_pools_
,
357 "http_proxy_socket_pool",
359 AddSocketPoolsToList(list
,
364 // Third parameter is false because |ssl_socket_pools_for_proxies_| use
365 // socket pools in |http_proxy_socket_pools_| and |socks_socket_pools_|.
366 AddSocketPoolsToList(list
,
367 ssl_socket_pools_for_proxies_
,
368 "ssl_socket_pool_for_proxies",
373 void ClientSocketPoolManagerImpl::OnCertAdded(const X509Certificate
* cert
) {
374 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);
377 void ClientSocketPoolManagerImpl::OnCACertChanged(
378 const X509Certificate
* cert
) {
379 // We should flush the socket pools if we removed trust from a
380 // cert, because a previously trusted server may have become
383 // We should not flush the socket pools if we added trust to a
386 // Since the OnCACertChanged method doesn't tell us what
387 // kind of change it is, we have to flush the socket
389 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);