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 HttpNetworkSession::SocketPoolType pool_type
)
50 socket_factory_(socket_factory
),
51 host_resolver_(host_resolver
),
52 cert_verifier_(cert_verifier
),
53 channel_id_service_(channel_id_service
),
54 transport_security_state_(transport_security_state
),
55 cert_transparency_verifier_(cert_transparency_verifier
),
56 cert_policy_enforcer_(cert_policy_enforcer
),
57 ssl_session_cache_shard_(ssl_session_cache_shard
),
58 ssl_config_service_(ssl_config_service
),
59 pool_type_(pool_type
),
60 transport_pool_histograms_("TCP"),
61 transport_socket_pool_(
62 pool_type
== HttpNetworkSession::WEBSOCKET_SOCKET_POOL
63 ? new WebSocketTransportClientSocketPool(
64 max_sockets_per_pool(pool_type
),
65 max_sockets_per_group(pool_type
),
66 &transport_pool_histograms_
,
70 : new TransportClientSocketPool(max_sockets_per_pool(pool_type
),
71 max_sockets_per_group(pool_type
),
72 &transport_pool_histograms_
,
76 ssl_pool_histograms_("SSL2"),
77 ssl_socket_pool_(new SSLClientSocketPool(max_sockets_per_pool(pool_type
),
78 max_sockets_per_group(pool_type
),
79 &ssl_pool_histograms_
,
82 transport_security_state
,
83 cert_transparency_verifier
,
85 ssl_session_cache_shard
,
87 transport_socket_pool_
.get(),
88 NULL
/* no socks proxy */,
89 NULL
/* no http proxy */,
92 transport_for_socks_pool_histograms_("TCPforSOCKS"),
93 socks_pool_histograms_("SOCK"),
94 transport_for_http_proxy_pool_histograms_("TCPforHTTPProxy"),
95 transport_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"),
96 ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"),
97 http_proxy_pool_histograms_("HTTPProxy"),
98 ssl_socket_pool_for_proxies_histograms_("SSLForProxies") {
99 CertDatabase::GetInstance()->AddObserver(this);
102 ClientSocketPoolManagerImpl::~ClientSocketPoolManagerImpl() {
103 CertDatabase::GetInstance()->RemoveObserver(this);
106 void ClientSocketPoolManagerImpl::FlushSocketPoolsWithError(int error
) {
107 // Flush the highest level pools first, since higher level pools may release
108 // stuff to the lower level pools.
110 for (SSLSocketPoolMap::const_iterator it
=
111 ssl_socket_pools_for_proxies_
.begin();
112 it
!= ssl_socket_pools_for_proxies_
.end();
114 it
->second
->FlushWithError(error
);
116 for (HTTPProxySocketPoolMap::const_iterator it
=
117 http_proxy_socket_pools_
.begin();
118 it
!= http_proxy_socket_pools_
.end();
120 it
->second
->FlushWithError(error
);
122 for (SSLSocketPoolMap::const_iterator it
=
123 ssl_socket_pools_for_https_proxies_
.begin();
124 it
!= ssl_socket_pools_for_https_proxies_
.end();
126 it
->second
->FlushWithError(error
);
128 for (TransportSocketPoolMap::const_iterator it
=
129 transport_socket_pools_for_https_proxies_
.begin();
130 it
!= transport_socket_pools_for_https_proxies_
.end();
132 it
->second
->FlushWithError(error
);
134 for (TransportSocketPoolMap::const_iterator it
=
135 transport_socket_pools_for_http_proxies_
.begin();
136 it
!= transport_socket_pools_for_http_proxies_
.end();
138 it
->second
->FlushWithError(error
);
140 for (SOCKSSocketPoolMap::const_iterator it
=
141 socks_socket_pools_
.begin();
142 it
!= socks_socket_pools_
.end();
144 it
->second
->FlushWithError(error
);
146 for (TransportSocketPoolMap::const_iterator it
=
147 transport_socket_pools_for_socks_proxies_
.begin();
148 it
!= transport_socket_pools_for_socks_proxies_
.end();
150 it
->second
->FlushWithError(error
);
152 ssl_socket_pool_
->FlushWithError(error
);
153 transport_socket_pool_
->FlushWithError(error
);
156 void ClientSocketPoolManagerImpl::CloseIdleSockets() {
157 // Close sockets in the highest level pools first, since higher level pools'
158 // sockets may release stuff to the lower level pools.
159 for (SSLSocketPoolMap::const_iterator it
=
160 ssl_socket_pools_for_proxies_
.begin();
161 it
!= ssl_socket_pools_for_proxies_
.end();
163 it
->second
->CloseIdleSockets();
165 for (HTTPProxySocketPoolMap::const_iterator it
=
166 http_proxy_socket_pools_
.begin();
167 it
!= http_proxy_socket_pools_
.end();
169 it
->second
->CloseIdleSockets();
171 for (SSLSocketPoolMap::const_iterator it
=
172 ssl_socket_pools_for_https_proxies_
.begin();
173 it
!= ssl_socket_pools_for_https_proxies_
.end();
175 it
->second
->CloseIdleSockets();
177 for (TransportSocketPoolMap::const_iterator it
=
178 transport_socket_pools_for_https_proxies_
.begin();
179 it
!= transport_socket_pools_for_https_proxies_
.end();
181 it
->second
->CloseIdleSockets();
183 for (TransportSocketPoolMap::const_iterator it
=
184 transport_socket_pools_for_http_proxies_
.begin();
185 it
!= transport_socket_pools_for_http_proxies_
.end();
187 it
->second
->CloseIdleSockets();
189 for (SOCKSSocketPoolMap::const_iterator it
=
190 socks_socket_pools_
.begin();
191 it
!= socks_socket_pools_
.end();
193 it
->second
->CloseIdleSockets();
195 for (TransportSocketPoolMap::const_iterator it
=
196 transport_socket_pools_for_socks_proxies_
.begin();
197 it
!= transport_socket_pools_for_socks_proxies_
.end();
199 it
->second
->CloseIdleSockets();
201 ssl_socket_pool_
->CloseIdleSockets();
202 transport_socket_pool_
->CloseIdleSockets();
205 TransportClientSocketPool
*
206 ClientSocketPoolManagerImpl::GetTransportSocketPool() {
207 return transport_socket_pool_
.get();
210 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSSLSocketPool() {
211 return ssl_socket_pool_
.get();
214 SOCKSClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy(
215 const HostPortPair
& socks_proxy
) {
216 SOCKSSocketPoolMap::const_iterator it
= socks_socket_pools_
.find(socks_proxy
);
217 if (it
!= socks_socket_pools_
.end()) {
218 DCHECK(ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
222 DCHECK(!ContainsKey(transport_socket_pools_for_socks_proxies_
, socks_proxy
));
224 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_ret
=
225 transport_socket_pools_for_socks_proxies_
.insert(
228 new TransportClientSocketPool(
229 max_sockets_per_proxy_server(pool_type_
),
230 max_sockets_per_group(pool_type_
),
231 &transport_for_socks_pool_histograms_
,
235 DCHECK(tcp_ret
.second
);
237 std::pair
<SOCKSSocketPoolMap::iterator
, bool> ret
=
238 socks_socket_pools_
.insert(
239 std::make_pair(socks_proxy
, new SOCKSClientSocketPool(
240 max_sockets_per_proxy_server(pool_type_
),
241 max_sockets_per_group(pool_type_
),
242 &socks_pool_histograms_
,
244 tcp_ret
.first
->second
,
247 return ret
.first
->second
;
250 HttpProxyClientSocketPool
*
251 ClientSocketPoolManagerImpl::GetSocketPoolForHTTPProxy(
252 const HostPortPair
& http_proxy
) {
253 HTTPProxySocketPoolMap::const_iterator it
=
254 http_proxy_socket_pools_
.find(http_proxy
);
255 if (it
!= http_proxy_socket_pools_
.end()) {
256 DCHECK(ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
257 DCHECK(ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
258 DCHECK(ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
262 DCHECK(!ContainsKey(transport_socket_pools_for_http_proxies_
, http_proxy
));
263 DCHECK(!ContainsKey(transport_socket_pools_for_https_proxies_
, http_proxy
));
264 DCHECK(!ContainsKey(ssl_socket_pools_for_https_proxies_
, http_proxy
));
266 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_http_ret
=
267 transport_socket_pools_for_http_proxies_
.insert(
270 new TransportClientSocketPool(
271 max_sockets_per_proxy_server(pool_type_
),
272 max_sockets_per_group(pool_type_
),
273 &transport_for_http_proxy_pool_histograms_
,
277 DCHECK(tcp_http_ret
.second
);
279 std::pair
<TransportSocketPoolMap::iterator
, bool> tcp_https_ret
=
280 transport_socket_pools_for_https_proxies_
.insert(
283 new TransportClientSocketPool(
284 max_sockets_per_proxy_server(pool_type_
),
285 max_sockets_per_group(pool_type_
),
286 &transport_for_https_proxy_pool_histograms_
,
290 DCHECK(tcp_https_ret
.second
);
292 std::pair
<SSLSocketPoolMap::iterator
, bool> ssl_https_ret
=
293 ssl_socket_pools_for_https_proxies_
.insert(std::make_pair(
294 http_proxy
, new SSLClientSocketPool(
295 max_sockets_per_proxy_server(pool_type_
),
296 max_sockets_per_group(pool_type_
),
297 &ssl_for_https_proxy_pool_histograms_
, cert_verifier_
,
298 channel_id_service_
, transport_security_state_
,
299 cert_transparency_verifier_
, cert_policy_enforcer_
,
300 ssl_session_cache_shard_
, socket_factory_
,
301 tcp_https_ret
.first
->second
/* https proxy */,
302 NULL
/* no socks proxy */, NULL
/* no http proxy */,
303 ssl_config_service_
.get(), net_log_
)));
304 DCHECK(tcp_https_ret
.second
);
306 std::pair
<HTTPProxySocketPoolMap::iterator
, bool> ret
=
307 http_proxy_socket_pools_
.insert(
310 new HttpProxyClientSocketPool(
311 max_sockets_per_proxy_server(pool_type_
),
312 max_sockets_per_group(pool_type_
),
313 &http_proxy_pool_histograms_
,
314 tcp_http_ret
.first
->second
,
315 ssl_https_ret
.first
->second
,
318 return ret
.first
->second
;
321 SSLClientSocketPool
* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy(
322 const HostPortPair
& proxy_server
) {
323 SSLSocketPoolMap::const_iterator it
=
324 ssl_socket_pools_for_proxies_
.find(proxy_server
);
325 if (it
!= ssl_socket_pools_for_proxies_
.end())
328 SSLClientSocketPool
* new_pool
= new SSLClientSocketPool(
329 max_sockets_per_proxy_server(pool_type_
),
330 max_sockets_per_group(pool_type_
), &ssl_pool_histograms_
, cert_verifier_
,
331 channel_id_service_
, transport_security_state_
,
332 cert_transparency_verifier_
, cert_policy_enforcer_
,
333 ssl_session_cache_shard_
, socket_factory_
,
334 NULL
, /* no tcp pool, we always go through a proxy */
335 GetSocketPoolForSOCKSProxy(proxy_server
),
336 GetSocketPoolForHTTPProxy(proxy_server
), ssl_config_service_
.get(),
339 std::pair
<SSLSocketPoolMap::iterator
, bool> ret
=
340 ssl_socket_pools_for_proxies_
.insert(std::make_pair(proxy_server
,
343 return ret
.first
->second
;
346 base::Value
* ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const {
347 base::ListValue
* list
= new base::ListValue();
348 list
->Append(transport_socket_pool_
->GetInfoAsValue("transport_socket_pool",
349 "transport_socket_pool",
351 // Third parameter is false because |ssl_socket_pool_| uses
352 // |transport_socket_pool_| internally, and do not want to add it a second
354 list
->Append(ssl_socket_pool_
->GetInfoAsValue("ssl_socket_pool",
357 AddSocketPoolsToList(list
,
358 http_proxy_socket_pools_
,
359 "http_proxy_socket_pool",
361 AddSocketPoolsToList(list
,
366 // Third parameter is false because |ssl_socket_pools_for_proxies_| use
367 // socket pools in |http_proxy_socket_pools_| and |socks_socket_pools_|.
368 AddSocketPoolsToList(list
,
369 ssl_socket_pools_for_proxies_
,
370 "ssl_socket_pool_for_proxies",
375 void ClientSocketPoolManagerImpl::OnCertAdded(const X509Certificate
* cert
) {
376 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);
379 void ClientSocketPoolManagerImpl::OnCACertChanged(
380 const X509Certificate
* cert
) {
381 // We should flush the socket pools if we removed trust from a
382 // cert, because a previously trusted server may have become
385 // We should not flush the socket pools if we added trust to a
388 // Since the OnCACertChanged method doesn't tell us what
389 // kind of change it is, we have to flush the socket
391 FlushSocketPoolsWithError(ERR_NETWORK_CHANGED
);