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 CTVerifier
* cert_transparency_verifier
,
44 const std::string
& ssl_session_cache_shard
,
45 ProxyService
* proxy_service
,
46 SSLConfigService
* ssl_config_service
,
47 HttpNetworkSession::SocketPoolType pool_type
)
49 socket_factory_(socket_factory
),
50 host_resolver_(host_resolver
),
51 cert_verifier_(cert_verifier
),
52 server_bound_cert_service_(server_bound_cert_service
),
53 transport_security_state_(transport_security_state
),
54 cert_transparency_verifier_(cert_transparency_verifier
),
55 ssl_session_cache_shard_(ssl_session_cache_shard
),
56 proxy_service_(proxy_service
),
57 ssl_config_service_(ssl_config_service
),
58 pool_type_(pool_type
),
59 transport_pool_histograms_("TCP"),
60 transport_socket_pool_(new TransportClientSocketPool(
61 max_sockets_per_pool(pool_type
), max_sockets_per_group(pool_type
),
62 &transport_pool_histograms_
,
66 ssl_pool_histograms_("SSL2"),
67 ssl_socket_pool_(new SSLClientSocketPool(
68 max_sockets_per_pool(pool_type
), max_sockets_per_group(pool_type
),
69 &ssl_pool_histograms_
,
72 server_bound_cert_service
,
73 transport_security_state
,
74 cert_transparency_verifier
,
75 ssl_session_cache_shard
,
77 transport_socket_pool_
.get(),
78 NULL
/* no socks proxy */,
79 NULL
/* no http proxy */,
82 transport_for_socks_pool_histograms_("TCPforSOCKS"),
83 socks_pool_histograms_("SOCK"),
84 transport_for_http_proxy_pool_histograms_("TCPforHTTPProxy"),
85 transport_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"),
86 ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"),
87 http_proxy_pool_histograms_("HTTPProxy"),
88 ssl_socket_pool_for_proxies_histograms_("SSLForProxies") {
89 CertDatabase::GetInstance()->AddObserver(this);
92 ClientSocketPoolManagerImpl::~ClientSocketPoolManagerImpl() {
93 CertDatabase::GetInstance()->RemoveObserver(this);
96 void ClientSocketPoolManagerImpl::FlushSocketPoolsWithError(int error
) {
97 // Flush the highest level pools first, since higher level pools may release
98 // stuff to the lower level pools.
100 for (SSLSocketPoolMap::const_iterator it
=
101 ssl_socket_pools_for_proxies_
.begin();
102 it
!= ssl_socket_pools_for_proxies_
.end();
104 it
->second
->FlushWithError(error
);
106 for (HTTPProxySocketPoolMap::const_iterator it
=
107 http_proxy_socket_pools_
.begin();
108 it
!= http_proxy_socket_pools_
.end();
110 it
->second
->FlushWithError(error
);
112 for (SSLSocketPoolMap::const_iterator it
=
113 ssl_socket_pools_for_https_proxies_
.begin();
114 it
!= ssl_socket_pools_for_https_proxies_
.end();
116 it
->second
->FlushWithError(error
);
118 for (TransportSocketPoolMap::const_iterator it
=
119 transport_socket_pools_for_https_proxies_
.begin();
120 it
!= transport_socket_pools_for_https_proxies_
.end();
122 it
->second
->FlushWithError(error
);
124 for (TransportSocketPoolMap::const_iterator it
=
125 transport_socket_pools_for_http_proxies_
.begin();
126 it
!= transport_socket_pools_for_http_proxies_
.end();
128 it
->second
->FlushWithError(error
);
130 for (SOCKSSocketPoolMap::const_iterator it
=
131 socks_socket_pools_
.begin();
132 it
!= socks_socket_pools_
.end();
134 it
->second
->FlushWithError(error
);
136 for (TransportSocketPoolMap::const_iterator it
=
137 transport_socket_pools_for_socks_proxies_
.begin();
138 it
!= transport_socket_pools_for_socks_proxies_
.end();
140 it
->second
->FlushWithError(error
);
142 ssl_socket_pool_
->FlushWithError(error
);
143 transport_socket_pool_
->FlushWithError(error
);
146 void ClientSocketPoolManagerImpl::CloseIdleSockets() {
147 // Close sockets in the highest level pools first, since higher level pools'
148 // sockets may release stuff to the lower level pools.
149 for (SSLSocketPoolMap::const_iterator it
=
150 ssl_socket_pools_for_proxies_
.begin();
151 it
!= ssl_socket_pools_for_proxies_
.end();
153 it
->second
->CloseIdleSockets();
155 for (HTTPProxySocketPoolMap::const_iterator it
=
156 http_proxy_socket_pools_
.begin();
157 it
!= http_proxy_socket_pools_
.end();
159 it
->second
->CloseIdleSockets();
161 for (SSLSocketPoolMap::const_iterator it
=
162 ssl_socket_pools_for_https_proxies_
.begin();
163 it
!= ssl_socket_pools_for_https_proxies_
.end();
165 it
->second
->CloseIdleSockets();
167 for (TransportSocketPoolMap::const_iterator it
=
168 transport_socket_pools_for_https_proxies_
.begin();
169 it
!= transport_socket_pools_for_https_proxies_
.end();
171 it
->second
->CloseIdleSockets();
173 for (TransportSocketPoolMap::const_iterator it
=
174 transport_socket_pools_for_http_proxies_
.begin();
175 it
!= transport_socket_pools_for_http_proxies_
.end();
177 it
->second
->CloseIdleSockets();
179 for (SOCKSSocketPoolMap::const_iterator it
=
180 socks_socket_pools_
.begin();
181 it
!= socks_socket_pools_
.end();
183 it
->second
->CloseIdleSockets();
185 for (TransportSocketPoolMap::const_iterator it
=
186 transport_socket_pools_for_socks_proxies_
.begin();
187 it
!= transport_socket_pools_for_socks_proxies_
.end();
189 it
->second
->CloseIdleSockets();
191 ssl_socket_pool_
->CloseIdleSockets();
192 transport_socket_pool_
->CloseIdleSockets();
195 TransportClientSocketPool
*
196 ClientSocketPoolManagerImpl::GetTransportSocketPool() {
197 return transport_socket_pool_
.get();
200 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSSLSocketPool() {
201 return ssl_socket_pool_
.get();
204 SOCKSClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy(
205 const HostPortPair
& socks_proxy
) {
206 SOCKSSocketPoolMap::const_iterator it
= socks_socket_pools_
.find(socks_proxy
);
207 if (it
!= socks_socket_pools_
.end()) {
208 DCHECK(ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
212 DCHECK(!ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
214 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_ret
=
215 transport_socket_pools_for_socks_proxies_
.insert(
218 new TransportClientSocketPool(
219 max_sockets_per_proxy_server(pool_type_
),
220 max_sockets_per_group(pool_type_
),
221 &transport_for_socks_pool_histograms_
,
225 DCHECK(tcp_ret
.second
);
227 std::pair
<SOCKSSocketPoolMap::iterator
, bool> ret
=
228 socks_socket_pools_
.insert(
229 std::make_pair(socks_proxy
, new SOCKSClientSocketPool(
230 max_sockets_per_proxy_server(pool_type_
),
231 max_sockets_per_group(pool_type_
),
232 &socks_pool_histograms_
,
234 tcp_ret
.first
->second
,
237 return ret
.first
->second
;
240 HttpProxyClientSocketPool
*
241 ClientSocketPoolManagerImpl::GetSocketPoolForHTTPProxy(
242 const HostPortPair
& http_proxy
) {
243 HTTPProxySocketPoolMap::const_iterator it
=
244 http_proxy_socket_pools_
.find(http_proxy
);
245 if (it
!= http_proxy_socket_pools_
.end()) {
246 DCHECK(ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
247 DCHECK(ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
248 DCHECK(ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
252 DCHECK(!ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
253 DCHECK(!ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
254 DCHECK(!ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
256 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_http_ret
=
257 transport_socket_pools_for_http_proxies_
.insert(
260 new TransportClientSocketPool(
261 max_sockets_per_proxy_server(pool_type_
),
262 max_sockets_per_group(pool_type_
),
263 &transport_for_http_proxy_pool_histograms_
,
267 DCHECK(tcp_http_ret
.second
);
269 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_https_ret
=
270 transport_socket_pools_for_https_proxies_
.insert(
273 new TransportClientSocketPool(
274 max_sockets_per_proxy_server(pool_type_
),
275 max_sockets_per_group(pool_type_
),
276 &transport_for_https_proxy_pool_histograms_
,
280 DCHECK(tcp_https_ret
.second
);
282 std::pair
<SSLSocketPoolMap::iterator
, bool> ssl_https_ret
=
283 ssl_socket_pools_for_https_proxies_
.insert(std::make_pair(
285 new SSLClientSocketPool(max_sockets_per_proxy_server(pool_type_
),
286 max_sockets_per_group(pool_type_
),
287 &ssl_for_https_proxy_pool_histograms_
,
290 server_bound_cert_service_
,
291 transport_security_state_
,
292 cert_transparency_verifier_
,
293 ssl_session_cache_shard_
,
295 tcp_https_ret
.first
->second
/* https proxy */,
296 NULL
/* no socks proxy */,
297 NULL
/* no http proxy */,
298 ssl_config_service_
.get(),
300 DCHECK(tcp_https_ret
.second
);
302 std::pair
<HTTPProxySocketPoolMap::iterator
, bool> ret
=
303 http_proxy_socket_pools_
.insert(
306 new HttpProxyClientSocketPool(
307 max_sockets_per_proxy_server(pool_type_
),
308 max_sockets_per_group(pool_type_
),
309 &http_proxy_pool_histograms_
,
311 tcp_http_ret
.first
->second
,
312 ssl_https_ret
.first
->second
,
315 return ret
.first
->second
;
318 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy(
319 const HostPortPair
& proxy_server
) {
320 SSLSocketPoolMap::const_iterator it
=
321 ssl_socket_pools_for_proxies_
.find(proxy_server
);
322 if (it
!= ssl_socket_pools_for_proxies_
.end())
325 SSLClientSocketPool
* new_pool
= new SSLClientSocketPool(
326 max_sockets_per_proxy_server(pool_type_
),
327 max_sockets_per_group(pool_type_
),
328 &ssl_pool_histograms_
,
331 server_bound_cert_service_
,
332 transport_security_state_
,
333 cert_transparency_verifier_
,
334 ssl_session_cache_shard_
,
336 NULL
, /* no tcp pool, we always go through a proxy */
337 GetSocketPoolForSOCKSProxy(proxy_server
),
338 GetSocketPoolForHTTPProxy(proxy_server
),
339 ssl_config_service_
.get(),
342 std::pair
<SSLSocketPoolMap::iterator
, bool> ret
=
343 ssl_socket_pools_for_proxies_
.insert(std::make_pair(proxy_server
,
346 return ret
.first
->second
;
349 base::Value
* ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const {
350 base::ListValue
* list
= new base::ListValue();
351 list
->Append(transport_socket_pool_
->GetInfoAsValue("transport_socket_pool",
352 "transport_socket_pool",
354 // Third parameter is false because |ssl_socket_pool_| uses
355 // |transport_socket_pool_| internally, and do not want to add it a second
357 list
->Append(ssl_socket_pool_
->GetInfoAsValue("ssl_socket_pool",
360 AddSocketPoolsToList(list
,
361 http_proxy_socket_pools_
,
362 "http_proxy_socket_pool",
364 AddSocketPoolsToList(list
,
369 // Third parameter is false because |ssl_socket_pools_for_proxies_| use
370 // socket pools in |http_proxy_socket_pools_| and |socks_socket_pools_|.
371 AddSocketPoolsToList(list
,
372 ssl_socket_pools_for_proxies_
,
373 "ssl_socket_pool_for_proxies",
378 void ClientSocketPoolManagerImpl::OnCertAdded(const X509Certificate
* cert
) {
379 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);
382 void ClientSocketPoolManagerImpl::OnCACertChanged(
383 const X509Certificate
* cert
) {
384 // We should flush the socket pools if we removed trust from a
385 // cert, because a previously trusted server may have become
388 // We should not flush the socket pools if we added trust to a
391 // Since the OnCACertChanged method doesn't tell us what
392 // kind of change it is, we have to flush the socket
394 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);