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 CertPolicyEnforcer
* cert_policy_enforcer
,
46 const std::string
& ssl_session_cache_shard
,
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 cert_policy_enforcer_(cert_policy_enforcer
),
58 ssl_session_cache_shard_(ssl_session_cache_shard
),
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_
,
84 transport_security_state
,
85 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(
297 http_proxy
, new SSLClientSocketPool(
298 max_sockets_per_proxy_server(pool_type_
),
299 max_sockets_per_group(pool_type_
),
300 &ssl_for_https_proxy_pool_histograms_
, cert_verifier_
,
301 channel_id_service_
, transport_security_state_
,
302 cert_transparency_verifier_
, cert_policy_enforcer_
,
303 ssl_session_cache_shard_
, socket_factory_
,
304 tcp_https_ret
.first
->second
/* https proxy */,
305 NULL
/* no socks proxy */, NULL
/* no http proxy */,
306 ssl_config_service_
.get(),
307 enable_ssl_connect_job_waiting_
, net_log_
)));
308 DCHECK(tcp_https_ret
.second
);
310 std::pair
<HTTPProxySocketPoolMap::iterator
, bool> ret
=
311 http_proxy_socket_pools_
.insert(
314 new HttpProxyClientSocketPool(
315 max_sockets_per_proxy_server(pool_type_
),
316 max_sockets_per_group(pool_type_
),
317 &http_proxy_pool_histograms_
,
318 tcp_http_ret
.first
->second
,
319 ssl_https_ret
.first
->second
,
322 return ret
.first
->second
;
325 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy(
326 const HostPortPair
& proxy_server
) {
327 SSLSocketPoolMap::const_iterator it
=
328 ssl_socket_pools_for_proxies_
.find(proxy_server
);
329 if (it
!= ssl_socket_pools_for_proxies_
.end())
332 SSLClientSocketPool
* new_pool
= new SSLClientSocketPool(
333 max_sockets_per_proxy_server(pool_type_
),
334 max_sockets_per_group(pool_type_
), &ssl_pool_histograms_
, cert_verifier_
,
335 channel_id_service_
, transport_security_state_
,
336 cert_transparency_verifier_
, cert_policy_enforcer_
,
337 ssl_session_cache_shard_
, socket_factory_
,
338 NULL
, /* no tcp pool, we always go through a proxy */
339 GetSocketPoolForSOCKSProxy(proxy_server
),
340 GetSocketPoolForHTTPProxy(proxy_server
), ssl_config_service_
.get(),
341 enable_ssl_connect_job_waiting_
, net_log_
);
343 std::pair
<SSLSocketPoolMap::iterator
, bool> ret
=
344 ssl_socket_pools_for_proxies_
.insert(std::make_pair(proxy_server
,
347 return ret
.first
->second
;
350 base::Value
* ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const {
351 base::ListValue
* list
= new base::ListValue();
352 list
->Append(transport_socket_pool_
->GetInfoAsValue("transport_socket_pool",
353 "transport_socket_pool",
355 // Third parameter is false because |ssl_socket_pool_| uses
356 // |transport_socket_pool_| internally, and do not want to add it a second
358 list
->Append(ssl_socket_pool_
->GetInfoAsValue("ssl_socket_pool",
361 AddSocketPoolsToList(list
,
362 http_proxy_socket_pools_
,
363 "http_proxy_socket_pool",
365 AddSocketPoolsToList(list
,
370 // Third parameter is false because |ssl_socket_pools_for_proxies_| use
371 // socket pools in |http_proxy_socket_pools_| and |socks_socket_pools_|.
372 AddSocketPoolsToList(list
,
373 ssl_socket_pools_for_proxies_
,
374 "ssl_socket_pool_for_proxies",
379 void ClientSocketPoolManagerImpl::OnCertAdded(const X509Certificate
* cert
) {
380 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);
383 void ClientSocketPoolManagerImpl::OnCACertChanged(
384 const X509Certificate
* cert
) {
385 // We should flush the socket pools if we removed trust from a
386 // cert, because a previously trusted server may have become
389 // We should not flush the socket pools if we added trust to a
392 // Since the OnCACertChanged method doesn't tell us what
393 // kind of change it is, we have to flush the socket
395 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);