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