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.
4
5#include "net/socket/client_socket_pool_manager_impl.h"
6
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"
16
17namespace net {
18
19namespace {
20
21// Appends information about all |socket_pools| to the end of |list|.
22template <class MapType>
23void 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(),
30                                            type,
31                                            include_nested_pools));
32  }
33}
34
35}  // namespace
36
37ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl(
38    NetLog* net_log,
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    ProxyDelegate* proxy_delegate,
50    HttpNetworkSession::SocketPoolType pool_type)
51    : net_log_(net_log),
52      socket_factory_(socket_factory),
53      host_resolver_(host_resolver),
54      cert_verifier_(cert_verifier),
55      channel_id_service_(channel_id_service),
56      transport_security_state_(transport_security_state),
57      cert_transparency_verifier_(cert_transparency_verifier),
58      ssl_session_cache_shard_(ssl_session_cache_shard),
59      proxy_service_(proxy_service),
60      ssl_config_service_(ssl_config_service),
61      enable_ssl_connect_job_waiting_(enable_ssl_connect_job_waiting),
62      pool_type_(pool_type),
63      transport_pool_histograms_("TCP"),
64      transport_socket_pool_(
65          pool_type == HttpNetworkSession::WEBSOCKET_SOCKET_POOL
66              ? new WebSocketTransportClientSocketPool(
67                    max_sockets_per_pool(pool_type),
68                    max_sockets_per_group(pool_type),
69                    &transport_pool_histograms_,
70                    host_resolver,
71                    socket_factory_,
72                    net_log)
73              : new TransportClientSocketPool(max_sockets_per_pool(pool_type),
74                                              max_sockets_per_group(pool_type),
75                                              &transport_pool_histograms_,
76                                              host_resolver,
77                                              socket_factory_,
78                                              net_log)),
79      ssl_pool_histograms_("SSL2"),
80      ssl_socket_pool_(new SSLClientSocketPool(max_sockets_per_pool(pool_type),
81                                               max_sockets_per_group(pool_type),
82                                               &ssl_pool_histograms_,
83                                               host_resolver,
84                                               cert_verifier,
85                                               channel_id_service,
86                                               transport_security_state,
87                                               cert_transparency_verifier,
88                                               ssl_session_cache_shard,
89                                               socket_factory,
90                                               transport_socket_pool_.get(),
91                                               NULL /* no socks proxy */,
92                                               NULL /* no http proxy */,
93                                               ssl_config_service,
94                                               enable_ssl_connect_job_waiting,
95                                               net_log)),
96      transport_for_socks_pool_histograms_("TCPforSOCKS"),
97      socks_pool_histograms_("SOCK"),
98      transport_for_http_proxy_pool_histograms_("TCPforHTTPProxy"),
99      transport_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"),
100      ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"),
101      http_proxy_pool_histograms_("HTTPProxy"),
102      ssl_socket_pool_for_proxies_histograms_("SSLForProxies"),
103      proxy_delegate_(proxy_delegate) {
104  CertDatabase::GetInstance()->AddObserver(this);
105}
106
107ClientSocketPoolManagerImpl::~ClientSocketPoolManagerImpl() {
108  CertDatabase::GetInstance()->RemoveObserver(this);
109}
110
111void ClientSocketPoolManagerImpl::FlushSocketPoolsWithError(int error) {
112  // Flush the highest level pools first, since higher level pools may release
113  // stuff to the lower level pools.
114
115  for (SSLSocketPoolMap::const_iterator it =
116       ssl_socket_pools_for_proxies_.begin();
117       it != ssl_socket_pools_for_proxies_.end();
118       ++it)
119    it->second->FlushWithError(error);
120
121  for (HTTPProxySocketPoolMap::const_iterator it =
122       http_proxy_socket_pools_.begin();
123       it != http_proxy_socket_pools_.end();
124       ++it)
125    it->second->FlushWithError(error);
126
127  for (SSLSocketPoolMap::const_iterator it =
128       ssl_socket_pools_for_https_proxies_.begin();
129       it != ssl_socket_pools_for_https_proxies_.end();
130       ++it)
131    it->second->FlushWithError(error);
132
133  for (TransportSocketPoolMap::const_iterator it =
134       transport_socket_pools_for_https_proxies_.begin();
135       it != transport_socket_pools_for_https_proxies_.end();
136       ++it)
137    it->second->FlushWithError(error);
138
139  for (TransportSocketPoolMap::const_iterator it =
140       transport_socket_pools_for_http_proxies_.begin();
141       it != transport_socket_pools_for_http_proxies_.end();
142       ++it)
143    it->second->FlushWithError(error);
144
145  for (SOCKSSocketPoolMap::const_iterator it =
146       socks_socket_pools_.begin();
147       it != socks_socket_pools_.end();
148       ++it)
149    it->second->FlushWithError(error);
150
151  for (TransportSocketPoolMap::const_iterator it =
152       transport_socket_pools_for_socks_proxies_.begin();
153       it != transport_socket_pools_for_socks_proxies_.end();
154       ++it)
155    it->second->FlushWithError(error);
156
157  ssl_socket_pool_->FlushWithError(error);
158  transport_socket_pool_->FlushWithError(error);
159}
160
161void ClientSocketPoolManagerImpl::CloseIdleSockets() {
162  // Close sockets in the highest level pools first, since higher level pools'
163  // sockets may release stuff to the lower level pools.
164  for (SSLSocketPoolMap::const_iterator it =
165       ssl_socket_pools_for_proxies_.begin();
166       it != ssl_socket_pools_for_proxies_.end();
167       ++it)
168    it->second->CloseIdleSockets();
169
170  for (HTTPProxySocketPoolMap::const_iterator it =
171       http_proxy_socket_pools_.begin();
172       it != http_proxy_socket_pools_.end();
173       ++it)
174    it->second->CloseIdleSockets();
175
176  for (SSLSocketPoolMap::const_iterator it =
177       ssl_socket_pools_for_https_proxies_.begin();
178       it != ssl_socket_pools_for_https_proxies_.end();
179       ++it)
180    it->second->CloseIdleSockets();
181
182  for (TransportSocketPoolMap::const_iterator it =
183       transport_socket_pools_for_https_proxies_.begin();
184       it != transport_socket_pools_for_https_proxies_.end();
185       ++it)
186    it->second->CloseIdleSockets();
187
188  for (TransportSocketPoolMap::const_iterator it =
189       transport_socket_pools_for_http_proxies_.begin();
190       it != transport_socket_pools_for_http_proxies_.end();
191       ++it)
192    it->second->CloseIdleSockets();
193
194  for (SOCKSSocketPoolMap::const_iterator it =
195       socks_socket_pools_.begin();
196       it != socks_socket_pools_.end();
197       ++it)
198    it->second->CloseIdleSockets();
199
200  for (TransportSocketPoolMap::const_iterator it =
201       transport_socket_pools_for_socks_proxies_.begin();
202       it != transport_socket_pools_for_socks_proxies_.end();
203       ++it)
204    it->second->CloseIdleSockets();
205
206  ssl_socket_pool_->CloseIdleSockets();
207  transport_socket_pool_->CloseIdleSockets();
208}
209
210TransportClientSocketPool*
211ClientSocketPoolManagerImpl::GetTransportSocketPool() {
212  return transport_socket_pool_.get();
213}
214
215SSLClientSocketPool* ClientSocketPoolManagerImpl::GetSSLSocketPool() {
216  return ssl_socket_pool_.get();
217}
218
219SOCKSClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy(
220    const HostPortPair& socks_proxy) {
221  SOCKSSocketPoolMap::const_iterator it = socks_socket_pools_.find(socks_proxy);
222  if (it != socks_socket_pools_.end()) {
223    DCHECK(ContainsKey(transport_socket_pools_for_socks_proxies_, socks_proxy));
224    return it->second;
225  }
226
227  DCHECK(!ContainsKey(transport_socket_pools_for_socks_proxies_, socks_proxy));
228
229  std::pair<TransportSocketPoolMap::iterator, bool> tcp_ret =
230      transport_socket_pools_for_socks_proxies_.insert(
231          std::make_pair(
232              socks_proxy,
233              new TransportClientSocketPool(
234                  max_sockets_per_proxy_server(pool_type_),
235                  max_sockets_per_group(pool_type_),
236                  &transport_for_socks_pool_histograms_,
237                  host_resolver_,
238                  socket_factory_,
239                  net_log_)));
240  DCHECK(tcp_ret.second);
241
242  std::pair<SOCKSSocketPoolMap::iterator, bool> ret =
243      socks_socket_pools_.insert(
244          std::make_pair(socks_proxy, new SOCKSClientSocketPool(
245              max_sockets_per_proxy_server(pool_type_),
246              max_sockets_per_group(pool_type_),
247              &socks_pool_histograms_,
248              host_resolver_,
249              tcp_ret.first->second,
250              net_log_)));
251
252  return ret.first->second;
253}
254
255HttpProxyClientSocketPool*
256ClientSocketPoolManagerImpl::GetSocketPoolForHTTPProxy(
257    const HostPortPair& http_proxy) {
258  HTTPProxySocketPoolMap::const_iterator it =
259      http_proxy_socket_pools_.find(http_proxy);
260  if (it != http_proxy_socket_pools_.end()) {
261    DCHECK(ContainsKey(transport_socket_pools_for_http_proxies_, http_proxy));
262    DCHECK(ContainsKey(transport_socket_pools_for_https_proxies_, http_proxy));
263    DCHECK(ContainsKey(ssl_socket_pools_for_https_proxies_, http_proxy));
264    return it->second;
265  }
266
267  DCHECK(!ContainsKey(transport_socket_pools_for_http_proxies_, http_proxy));
268  DCHECK(!ContainsKey(transport_socket_pools_for_https_proxies_, http_proxy));
269  DCHECK(!ContainsKey(ssl_socket_pools_for_https_proxies_, http_proxy));
270
271  std::pair<TransportSocketPoolMap::iterator, bool> tcp_http_ret =
272      transport_socket_pools_for_http_proxies_.insert(
273          std::make_pair(
274              http_proxy,
275              new TransportClientSocketPool(
276                  max_sockets_per_proxy_server(pool_type_),
277                  max_sockets_per_group(pool_type_),
278                  &transport_for_http_proxy_pool_histograms_,
279                  host_resolver_,
280                  socket_factory_,
281                  net_log_)));
282  DCHECK(tcp_http_ret.second);
283
284  std::pair<TransportSocketPoolMap::iterator, bool> tcp_https_ret =
285      transport_socket_pools_for_https_proxies_.insert(
286          std::make_pair(
287              http_proxy,
288              new TransportClientSocketPool(
289                  max_sockets_per_proxy_server(pool_type_),
290                  max_sockets_per_group(pool_type_),
291                  &transport_for_https_proxy_pool_histograms_,
292                  host_resolver_,
293                  socket_factory_,
294                  net_log_)));
295  DCHECK(tcp_https_ret.second);
296
297  std::pair<SSLSocketPoolMap::iterator, bool> ssl_https_ret =
298      ssl_socket_pools_for_https_proxies_.insert(std::make_pair(
299          http_proxy,
300          new SSLClientSocketPool(max_sockets_per_proxy_server(pool_type_),
301                                  max_sockets_per_group(pool_type_),
302                                  &ssl_for_https_proxy_pool_histograms_,
303                                  host_resolver_,
304                                  cert_verifier_,
305                                  channel_id_service_,
306                                  transport_security_state_,
307                                  cert_transparency_verifier_,
308                                  ssl_session_cache_shard_,
309                                  socket_factory_,
310                                  tcp_https_ret.first->second /* https proxy */,
311                                  NULL /* no socks proxy */,
312                                  NULL /* no http proxy */,
313                                  ssl_config_service_.get(),
314                                  enable_ssl_connect_job_waiting_,
315                                  net_log_)));
316  DCHECK(tcp_https_ret.second);
317
318  std::pair<HTTPProxySocketPoolMap::iterator, bool> ret =
319      http_proxy_socket_pools_.insert(
320          std::make_pair(
321              http_proxy,
322              new HttpProxyClientSocketPool(
323                  max_sockets_per_proxy_server(pool_type_),
324                  max_sockets_per_group(pool_type_),
325                  &http_proxy_pool_histograms_,
326                  host_resolver_,
327                  tcp_http_ret.first->second,
328                  ssl_https_ret.first->second,
329                  proxy_delegate_,
330                  net_log_)));
331
332  return ret.first->second;
333}
334
335SSLClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy(
336    const HostPortPair& proxy_server) {
337  SSLSocketPoolMap::const_iterator it =
338      ssl_socket_pools_for_proxies_.find(proxy_server);
339  if (it != ssl_socket_pools_for_proxies_.end())
340    return it->second;
341
342  SSLClientSocketPool* new_pool = new SSLClientSocketPool(
343      max_sockets_per_proxy_server(pool_type_),
344      max_sockets_per_group(pool_type_),
345      &ssl_pool_histograms_,
346      host_resolver_,
347      cert_verifier_,
348      channel_id_service_,
349      transport_security_state_,
350      cert_transparency_verifier_,
351      ssl_session_cache_shard_,
352      socket_factory_,
353      NULL, /* no tcp pool, we always go through a proxy */
354      GetSocketPoolForSOCKSProxy(proxy_server),
355      GetSocketPoolForHTTPProxy(proxy_server),
356      ssl_config_service_.get(),
357      enable_ssl_connect_job_waiting_,
358      net_log_);
359
360  std::pair<SSLSocketPoolMap::iterator, bool> ret =
361      ssl_socket_pools_for_proxies_.insert(std::make_pair(proxy_server,
362                                                          new_pool));
363
364  return ret.first->second;
365}
366
367base::Value* ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const {
368  base::ListValue* list = new base::ListValue();
369  list->Append(transport_socket_pool_->GetInfoAsValue("transport_socket_pool",
370                                                "transport_socket_pool",
371                                                false));
372  // Third parameter is false because |ssl_socket_pool_| uses
373  // |transport_socket_pool_| internally, and do not want to add it a second
374  // time.
375  list->Append(ssl_socket_pool_->GetInfoAsValue("ssl_socket_pool",
376                                                "ssl_socket_pool",
377                                                false));
378  AddSocketPoolsToList(list,
379                       http_proxy_socket_pools_,
380                       "http_proxy_socket_pool",
381                       true);
382  AddSocketPoolsToList(list,
383                       socks_socket_pools_,
384                       "socks_socket_pool",
385                       true);
386
387  // Third parameter is false because |ssl_socket_pools_for_proxies_| use
388  // socket pools in |http_proxy_socket_pools_| and |socks_socket_pools_|.
389  AddSocketPoolsToList(list,
390                       ssl_socket_pools_for_proxies_,
391                       "ssl_socket_pool_for_proxies",
392                       false);
393  return list;
394}
395
396void ClientSocketPoolManagerImpl::OnCertAdded(const X509Certificate* cert) {
397  FlushSocketPoolsWithError(ERR_NETWORK_CHANGED);
398}
399
400void ClientSocketPoolManagerImpl::OnCACertChanged(
401    const X509Certificate* cert) {
402  // We should flush the socket pools if we removed trust from a
403  // cert, because a previously trusted server may have become
404  // untrusted.
405  //
406  // We should not flush the socket pools if we added trust to a
407  // cert.
408  //
409  // Since the OnCACertChanged method doesn't tell us what
410  // kind of change it is, we have to flush the socket
411  // pools to be safe.
412  FlushSocketPoolsWithError(ERR_NETWORK_CHANGED);
413}
414
415}  // namespace net
416