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/socket/websocket_transport_client_socket_pool.h"
15 #include "net/ssl/ssl_config_service.h"
21 // Appends information about all |socket_pools| to the end of |list|.
22 template <class MapType
>
23 void AddSocketPoolsToList(base::ListValue
* list
,
24 const MapType
& socket_pools
,
25 const std::string
& type
,
26 bool include_nested_pools
) {
27 for (typename
MapType::const_iterator it
= socket_pools
.begin();
28 it
!= socket_pools
.end(); it
++) {
29 list
->Append(it
->second
->GetInfoAsValue(it
->first
.ToString(),
31 include_nested_pools
));
37 ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl(
39 ClientSocketFactory
* socket_factory
,
40 HostResolver
* host_resolver
,
41 CertVerifier
* cert_verifier
,
42 ChannelIDService
* channel_id_service
,
43 TransportSecurityState
* transport_security_state
,
44 CTVerifier
* cert_transparency_verifier
,
45 const std::string
& ssl_session_cache_shard
,
46 ProxyService
* proxy_service
,
47 SSLConfigService
* ssl_config_service
,
48 bool enable_ssl_connect_job_waiting
,
49 HttpNetworkSession::SocketPoolType pool_type
)
51 socket_factory_(socket_factory
),
52 host_resolver_(host_resolver
),
53 cert_verifier_(cert_verifier
),
54 channel_id_service_(channel_id_service
),
55 transport_security_state_(transport_security_state
),
56 cert_transparency_verifier_(cert_transparency_verifier
),
57 ssl_session_cache_shard_(ssl_session_cache_shard
),
58 proxy_service_(proxy_service
),
59 ssl_config_service_(ssl_config_service
),
60 enable_ssl_connect_job_waiting_(enable_ssl_connect_job_waiting
),
61 pool_type_(pool_type
),
62 transport_pool_histograms_("TCP"),
63 transport_socket_pool_(
64 pool_type
== HttpNetworkSession::WEBSOCKET_SOCKET_POOL
65 ? new WebSocketTransportClientSocketPool(
66 max_sockets_per_pool(pool_type
),
67 max_sockets_per_group(pool_type
),
68 &transport_pool_histograms_
,
72 : new TransportClientSocketPool(max_sockets_per_pool(pool_type
),
73 max_sockets_per_group(pool_type
),
74 &transport_pool_histograms_
,
78 ssl_pool_histograms_("SSL2"),
79 ssl_socket_pool_(new SSLClientSocketPool(max_sockets_per_pool(pool_type
),
80 max_sockets_per_group(pool_type
),
81 &ssl_pool_histograms_
,
85 transport_security_state
,
86 cert_transparency_verifier
,
87 ssl_session_cache_shard
,
89 transport_socket_pool_
.get(),
90 NULL
/* no socks proxy */,
91 NULL
/* no http proxy */,
93 enable_ssl_connect_job_waiting
,
95 transport_for_socks_pool_histograms_("TCPforSOCKS"),
96 socks_pool_histograms_("SOCK"),
97 transport_for_http_proxy_pool_histograms_("TCPforHTTPProxy"),
98 transport_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"),
99 ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"),
100 http_proxy_pool_histograms_("HTTPProxy"),
101 ssl_socket_pool_for_proxies_histograms_("SSLForProxies") {
102 CertDatabase::GetInstance()->AddObserver(this);
105 ClientSocketPoolManagerImpl::~ClientSocketPoolManagerImpl() {
106 CertDatabase::GetInstance()->RemoveObserver(this);
109 void ClientSocketPoolManagerImpl::FlushSocketPoolsWithError(int error
) {
110 // Flush the highest level pools first, since higher level pools may release
111 // stuff to the lower level pools.
113 for (SSLSocketPoolMap::const_iterator it
=
114 ssl_socket_pools_for_proxies_
.begin();
115 it
!= ssl_socket_pools_for_proxies_
.end();
117 it
->second
->FlushWithError(error
);
119 for (HTTPProxySocketPoolMap::const_iterator it
=
120 http_proxy_socket_pools_
.begin();
121 it
!= http_proxy_socket_pools_
.end();
123 it
->second
->FlushWithError(error
);
125 for (SSLSocketPoolMap::const_iterator it
=
126 ssl_socket_pools_for_https_proxies_
.begin();
127 it
!= ssl_socket_pools_for_https_proxies_
.end();
129 it
->second
->FlushWithError(error
);
131 for (TransportSocketPoolMap::const_iterator it
=
132 transport_socket_pools_for_https_proxies_
.begin();
133 it
!= transport_socket_pools_for_https_proxies_
.end();
135 it
->second
->FlushWithError(error
);
137 for (TransportSocketPoolMap::const_iterator it
=
138 transport_socket_pools_for_http_proxies_
.begin();
139 it
!= transport_socket_pools_for_http_proxies_
.end();
141 it
->second
->FlushWithError(error
);
143 for (SOCKSSocketPoolMap::const_iterator it
=
144 socks_socket_pools_
.begin();
145 it
!= socks_socket_pools_
.end();
147 it
->second
->FlushWithError(error
);
149 for (TransportSocketPoolMap::const_iterator it
=
150 transport_socket_pools_for_socks_proxies_
.begin();
151 it
!= transport_socket_pools_for_socks_proxies_
.end();
153 it
->second
->FlushWithError(error
);
155 ssl_socket_pool_
->FlushWithError(error
);
156 transport_socket_pool_
->FlushWithError(error
);
159 void ClientSocketPoolManagerImpl::CloseIdleSockets() {
160 // Close sockets in the highest level pools first, since higher level pools'
161 // sockets may release stuff to the lower level pools.
162 for (SSLSocketPoolMap::const_iterator it
=
163 ssl_socket_pools_for_proxies_
.begin();
164 it
!= ssl_socket_pools_for_proxies_
.end();
166 it
->second
->CloseIdleSockets();
168 for (HTTPProxySocketPoolMap::const_iterator it
=
169 http_proxy_socket_pools_
.begin();
170 it
!= http_proxy_socket_pools_
.end();
172 it
->second
->CloseIdleSockets();
174 for (SSLSocketPoolMap::const_iterator it
=
175 ssl_socket_pools_for_https_proxies_
.begin();
176 it
!= ssl_socket_pools_for_https_proxies_
.end();
178 it
->second
->CloseIdleSockets();
180 for (TransportSocketPoolMap::const_iterator it
=
181 transport_socket_pools_for_https_proxies_
.begin();
182 it
!= transport_socket_pools_for_https_proxies_
.end();
184 it
->second
->CloseIdleSockets();
186 for (TransportSocketPoolMap::const_iterator it
=
187 transport_socket_pools_for_http_proxies_
.begin();
188 it
!= transport_socket_pools_for_http_proxies_
.end();
190 it
->second
->CloseIdleSockets();
192 for (SOCKSSocketPoolMap::const_iterator it
=
193 socks_socket_pools_
.begin();
194 it
!= socks_socket_pools_
.end();
196 it
->second
->CloseIdleSockets();
198 for (TransportSocketPoolMap::const_iterator it
=
199 transport_socket_pools_for_socks_proxies_
.begin();
200 it
!= transport_socket_pools_for_socks_proxies_
.end();
202 it
->second
->CloseIdleSockets();
204 ssl_socket_pool_
->CloseIdleSockets();
205 transport_socket_pool_
->CloseIdleSockets();
208 TransportClientSocketPool
*
209 ClientSocketPoolManagerImpl::GetTransportSocketPool() {
210 return transport_socket_pool_
.get();
213 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSSLSocketPool() {
214 return ssl_socket_pool_
.get();
217 SOCKSClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy(
218 const HostPortPair
& socks_proxy
) {
219 SOCKSSocketPoolMap::const_iterator it
= socks_socket_pools_
.find(socks_proxy
);
220 if (it
!= socks_socket_pools_
.end()) {
221 DCHECK(ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
225 DCHECK(!ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
227 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_ret
=
228 transport_socket_pools_for_socks_proxies_
.insert(
231 new TransportClientSocketPool(
232 max_sockets_per_proxy_server(pool_type_
),
233 max_sockets_per_group(pool_type_
),
234 &transport_for_socks_pool_histograms_
,
238 DCHECK(tcp_ret
.second
);
240 std::pair
<SOCKSSocketPoolMap::iterator
, bool> ret
=
241 socks_socket_pools_
.insert(
242 std::make_pair(socks_proxy
, new SOCKSClientSocketPool(
243 max_sockets_per_proxy_server(pool_type_
),
244 max_sockets_per_group(pool_type_
),
245 &socks_pool_histograms_
,
247 tcp_ret
.first
->second
,
250 return ret
.first
->second
;
253 HttpProxyClientSocketPool
*
254 ClientSocketPoolManagerImpl::GetSocketPoolForHTTPProxy(
255 const HostPortPair
& http_proxy
) {
256 HTTPProxySocketPoolMap::const_iterator it
=
257 http_proxy_socket_pools_
.find(http_proxy
);
258 if (it
!= http_proxy_socket_pools_
.end()) {
259 DCHECK(ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
260 DCHECK(ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
261 DCHECK(ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
265 DCHECK(!ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
266 DCHECK(!ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
267 DCHECK(!ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
269 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_http_ret
=
270 transport_socket_pools_for_http_proxies_
.insert(
273 new TransportClientSocketPool(
274 max_sockets_per_proxy_server(pool_type_
),
275 max_sockets_per_group(pool_type_
),
276 &transport_for_http_proxy_pool_histograms_
,
280 DCHECK(tcp_http_ret
.second
);
282 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_https_ret
=
283 transport_socket_pools_for_https_proxies_
.insert(
286 new TransportClientSocketPool(
287 max_sockets_per_proxy_server(pool_type_
),
288 max_sockets_per_group(pool_type_
),
289 &transport_for_https_proxy_pool_histograms_
,
293 DCHECK(tcp_https_ret
.second
);
295 std::pair
<SSLSocketPoolMap::iterator
, bool> ssl_https_ret
=
296 ssl_socket_pools_for_https_proxies_
.insert(std::make_pair(
298 new SSLClientSocketPool(max_sockets_per_proxy_server(pool_type_
),
299 max_sockets_per_group(pool_type_
),
300 &ssl_for_https_proxy_pool_histograms_
,
304 transport_security_state_
,
305 cert_transparency_verifier_
,
306 ssl_session_cache_shard_
,
308 tcp_https_ret
.first
->second
/* https proxy */,
309 NULL
/* no socks proxy */,
310 NULL
/* no http proxy */,
311 ssl_config_service_
.get(),
312 enable_ssl_connect_job_waiting_
,
314 DCHECK(tcp_https_ret
.second
);
316 std::pair
<HTTPProxySocketPoolMap::iterator
, bool> ret
=
317 http_proxy_socket_pools_
.insert(
320 new HttpProxyClientSocketPool(
321 max_sockets_per_proxy_server(pool_type_
),
322 max_sockets_per_group(pool_type_
),
323 &http_proxy_pool_histograms_
,
325 tcp_http_ret
.first
->second
,
326 ssl_https_ret
.first
->second
,
329 return ret
.first
->second
;
332 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy(
333 const HostPortPair
& proxy_server
) {
334 SSLSocketPoolMap::const_iterator it
=
335 ssl_socket_pools_for_proxies_
.find(proxy_server
);
336 if (it
!= ssl_socket_pools_for_proxies_
.end())
339 SSLClientSocketPool
* new_pool
= new SSLClientSocketPool(
340 max_sockets_per_proxy_server(pool_type_
),
341 max_sockets_per_group(pool_type_
),
342 &ssl_pool_histograms_
,
346 transport_security_state_
,
347 cert_transparency_verifier_
,
348 ssl_session_cache_shard_
,
350 NULL
, /* no tcp pool, we always go through a proxy */
351 GetSocketPoolForSOCKSProxy(proxy_server
),
352 GetSocketPoolForHTTPProxy(proxy_server
),
353 ssl_config_service_
.get(),
354 enable_ssl_connect_job_waiting_
,
357 std::pair
<SSLSocketPoolMap::iterator
, bool> ret
=
358 ssl_socket_pools_for_proxies_
.insert(std::make_pair(proxy_server
,
361 return ret
.first
->second
;
364 base::Value
* ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const {
365 base::ListValue
* list
= new base::ListValue();
366 list
->Append(transport_socket_pool_
->GetInfoAsValue("transport_socket_pool",
367 "transport_socket_pool",
369 // Third parameter is false because |ssl_socket_pool_| uses
370 // |transport_socket_pool_| internally, and do not want to add it a second
372 list
->Append(ssl_socket_pool_
->GetInfoAsValue("ssl_socket_pool",
375 AddSocketPoolsToList(list
,
376 http_proxy_socket_pools_
,
377 "http_proxy_socket_pool",
379 AddSocketPoolsToList(list
,
384 // Third parameter is false because |ssl_socket_pools_for_proxies_| use
385 // socket pools in |http_proxy_socket_pools_| and |socks_socket_pools_|.
386 AddSocketPoolsToList(list
,
387 ssl_socket_pools_for_proxies_
,
388 "ssl_socket_pool_for_proxies",
393 void ClientSocketPoolManagerImpl::OnCertAdded(const X509Certificate
* cert
) {
394 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);
397 void ClientSocketPoolManagerImpl::OnCACertChanged(
398 const X509Certificate
* cert
) {
399 // We should flush the socket pools if we removed trust from a
400 // cert, because a previously trusted server may have become
403 // We should not flush the socket pools if we added trust to a
406 // Since the OnCACertChanged method doesn't tell us what
407 // kind of change it is, we have to flush the socket
409 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);