Chromium Code Reviews| Index: net/socket/client_socket_pool_manager_impl.cc |
| diff --git a/net/socket/client_socket_pool_manager_impl.cc b/net/socket/client_socket_pool_manager_impl.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e2f40e3dac6fb5fc300b0a1afb2b9398fadaabc8 |
| --- /dev/null |
| +++ b/net/socket/client_socket_pool_manager_impl.cc |
| @@ -0,0 +1,394 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "net/socket/client_socket_pool_manager_impl.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/values.h" |
| +#include "net/base/ssl_config_service.h" |
| +#include "net/http/http_proxy_client_socket_pool.h" |
| +#include "net/socket/socks_client_socket_pool.h" |
| +#include "net/socket/ssl_client_socket_pool.h" |
| +#include "net/socket/transport_client_socket_pool.h" |
| + |
| +namespace net { |
| + |
| +namespace { |
| + |
| +// Appends information about all |socket_pools| to the end of |list|. |
| +template <class MapType> |
| +void AddSocketPoolsToList(ListValue* list, |
| + const MapType& socket_pools, |
| + const std::string& type, |
| + bool include_nested_pools) { |
| + for (typename MapType::const_iterator it = socket_pools.begin(); |
| + it != socket_pools.end(); it++) { |
| + list->Append(it->second->GetInfoAsValue(it->first.ToString(), |
| + type, |
| + include_nested_pools)); |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl( |
| + NetLog* net_log, |
| + ClientSocketFactory* socket_factory, |
| + HostResolver* host_resolver, |
| + CertVerifier* cert_verifier, |
| + OriginBoundCertService* origin_bound_cert_service, |
| + DnsRRResolver* dnsrr_resolver, |
| + DnsCertProvenanceChecker* dns_cert_checker, |
| + SSLHostInfoFactory* ssl_host_info_factory, |
| + ProxyService* proxy_service, |
| + SSLConfigService* ssl_config_service) |
| + : net_log_(net_log), |
| + socket_factory_(socket_factory), |
| + host_resolver_(host_resolver), |
| + cert_verifier_(cert_verifier), |
| + origin_bound_cert_service_(origin_bound_cert_service), |
| + dnsrr_resolver_(dnsrr_resolver), |
| + dns_cert_checker_(dns_cert_checker), |
| + ssl_host_info_factory_(ssl_host_info_factory), |
| + proxy_service_(proxy_service), |
| + ssl_config_service_(ssl_config_service), |
| + transport_pool_histograms_("TCP"), |
| + transport_socket_pool_(new TransportClientSocketPool( |
| + max_sockets_per_pool(), max_sockets_per_group(), |
| + &transport_pool_histograms_, |
| + host_resolver, |
| + socket_factory_, |
| + net_log)), |
| + ssl_pool_histograms_("SSL2"), |
| + ssl_socket_pool_(new SSLClientSocketPool( |
| + max_sockets_per_pool(), max_sockets_per_group(), |
| + &ssl_pool_histograms_, |
| + host_resolver, |
| + cert_verifier, |
| + origin_bound_cert_service, |
| + dnsrr_resolver, |
| + dns_cert_checker, |
| + ssl_host_info_factory, |
| + socket_factory, |
| + transport_socket_pool_.get(), |
| + NULL /* no socks proxy */, |
| + NULL /* no http proxy */, |
| + ssl_config_service, |
| + net_log)), |
| + transport_for_socks_pool_histograms_("TCPforSOCKS"), |
| + socks_pool_histograms_("SOCK"), |
| + transport_for_http_proxy_pool_histograms_("TCPforHTTPProxy"), |
| + transport_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"), |
| + ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"), |
| + http_proxy_pool_histograms_("HTTPProxy"), |
| + ssl_socket_pool_for_proxies_histograms_("SSLForProxies") { |
| + CertDatabase::AddObserver(this); |
| +} |
| + |
| +ClientSocketPoolManagerImpl::~ClientSocketPoolManagerImpl() { |
| + CertDatabase::RemoveObserver(this); |
| +} |
| + |
| +void ClientSocketPoolManagerImpl::FlushSocketPools() { |
| + // Flush the highest level pools first, since higher level pools may release |
| + // stuff to the lower level pools. |
| + |
| + for (SSLSocketPoolMap::const_iterator it = |
| + ssl_socket_pools_for_proxies_.begin(); |
| + it != ssl_socket_pools_for_proxies_.end(); |
| + ++it) |
| + it->second->Flush(); |
| + |
| + for (HTTPProxySocketPoolMap::const_iterator it = |
| + http_proxy_socket_pools_.begin(); |
| + it != http_proxy_socket_pools_.end(); |
| + ++it) |
| + it->second->Flush(); |
| + |
| + for (SSLSocketPoolMap::const_iterator it = |
| + ssl_socket_pools_for_https_proxies_.begin(); |
| + it != ssl_socket_pools_for_https_proxies_.end(); |
| + ++it) |
| + it->second->Flush(); |
| + |
| + for (TransportSocketPoolMap::const_iterator it = |
| + transport_socket_pools_for_https_proxies_.begin(); |
| + it != transport_socket_pools_for_https_proxies_.end(); |
| + ++it) |
| + it->second->Flush(); |
| + |
| + for (TransportSocketPoolMap::const_iterator it = |
| + transport_socket_pools_for_http_proxies_.begin(); |
| + it != transport_socket_pools_for_http_proxies_.end(); |
| + ++it) |
| + it->second->Flush(); |
| + |
| + for (SOCKSSocketPoolMap::const_iterator it = |
| + socks_socket_pools_.begin(); |
| + it != socks_socket_pools_.end(); |
| + ++it) |
| + it->second->Flush(); |
| + |
| + for (TransportSocketPoolMap::const_iterator it = |
| + transport_socket_pools_for_socks_proxies_.begin(); |
| + it != transport_socket_pools_for_socks_proxies_.end(); |
| + ++it) |
| + it->second->Flush(); |
| + |
| + ssl_socket_pool_->Flush(); |
| + transport_socket_pool_->Flush(); |
| +} |
| + |
| +TransportClientSocketPool* |
| +ClientSocketPoolManagerImpl::GetTransportSocketPool() { |
|
mmenke
2011/11/16 16:12:03
nit: This method and the next should be below the
willchan no longer on Chromium
2011/11/16 17:26:06
Done.
|
| + return transport_socket_pool_.get(); |
| +} |
| + |
| +SSLClientSocketPool* ClientSocketPoolManagerImpl::GetSSLSocketPool() { |
| + return ssl_socket_pool_.get(); |
| +} |
| + |
| +void ClientSocketPoolManagerImpl::CloseIdleSockets() { |
| + // Close sockets in the highest level pools first, since higher level pools' |
| + // sockets may release stuff to the lower level pools. |
| + for (SSLSocketPoolMap::const_iterator it = |
| + ssl_socket_pools_for_proxies_.begin(); |
| + it != ssl_socket_pools_for_proxies_.end(); |
| + ++it) |
| + it->second->CloseIdleSockets(); |
| + |
| + for (HTTPProxySocketPoolMap::const_iterator it = |
| + http_proxy_socket_pools_.begin(); |
| + it != http_proxy_socket_pools_.end(); |
| + ++it) |
| + it->second->CloseIdleSockets(); |
| + |
| + for (SSLSocketPoolMap::const_iterator it = |
| + ssl_socket_pools_for_https_proxies_.begin(); |
| + it != ssl_socket_pools_for_https_proxies_.end(); |
| + ++it) |
| + it->second->CloseIdleSockets(); |
| + |
| + for (TransportSocketPoolMap::const_iterator it = |
| + transport_socket_pools_for_https_proxies_.begin(); |
| + it != transport_socket_pools_for_https_proxies_.end(); |
| + ++it) |
| + it->second->CloseIdleSockets(); |
| + |
| + for (TransportSocketPoolMap::const_iterator it = |
| + transport_socket_pools_for_http_proxies_.begin(); |
| + it != transport_socket_pools_for_http_proxies_.end(); |
| + ++it) |
| + it->second->CloseIdleSockets(); |
| + |
| + for (SOCKSSocketPoolMap::const_iterator it = |
| + socks_socket_pools_.begin(); |
| + it != socks_socket_pools_.end(); |
| + ++it) |
| + it->second->CloseIdleSockets(); |
| + |
| + for (TransportSocketPoolMap::const_iterator it = |
| + transport_socket_pools_for_socks_proxies_.begin(); |
| + it != transport_socket_pools_for_socks_proxies_.end(); |
| + ++it) |
| + it->second->CloseIdleSockets(); |
| + |
| + ssl_socket_pool_->CloseIdleSockets(); |
| + transport_socket_pool_->CloseIdleSockets(); |
| +} |
| + |
| +SOCKSClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy( |
| + const HostPortPair& socks_proxy) { |
| + SOCKSSocketPoolMap::const_iterator it = socks_socket_pools_.find(socks_proxy); |
| + if (it != socks_socket_pools_.end()) { |
| + DCHECK(ContainsKey(transport_socket_pools_for_socks_proxies_, socks_proxy)); |
| + return it->second; |
| + } |
| + |
| + DCHECK(!ContainsKey(transport_socket_pools_for_socks_proxies_, socks_proxy)); |
| + |
| + std::pair<TransportSocketPoolMap::iterator, bool> tcp_ret = |
| + transport_socket_pools_for_socks_proxies_.insert( |
| + std::make_pair( |
| + socks_proxy, |
| + new TransportClientSocketPool( |
| + max_sockets_per_proxy_server(), |
| + max_sockets_per_group(), |
| + &transport_for_socks_pool_histograms_, |
| + host_resolver_, |
| + socket_factory_, |
| + net_log_))); |
| + DCHECK(tcp_ret.second); |
| + |
| + std::pair<SOCKSSocketPoolMap::iterator, bool> ret = |
| + socks_socket_pools_.insert( |
| + std::make_pair(socks_proxy, new SOCKSClientSocketPool( |
| + max_sockets_per_proxy_server(), |
| + max_sockets_per_group(), |
| + &socks_pool_histograms_, |
| + host_resolver_, |
| + tcp_ret.first->second, |
| + net_log_))); |
| + |
| + return ret.first->second; |
| +} |
| + |
| +HttpProxyClientSocketPool* |
| +ClientSocketPoolManagerImpl::GetSocketPoolForHTTPProxy( |
| + const HostPortPair& http_proxy) { |
| + HTTPProxySocketPoolMap::const_iterator it = |
| + http_proxy_socket_pools_.find(http_proxy); |
| + if (it != http_proxy_socket_pools_.end()) { |
| + DCHECK(ContainsKey(transport_socket_pools_for_http_proxies_, http_proxy)); |
| + DCHECK(ContainsKey(transport_socket_pools_for_https_proxies_, http_proxy)); |
| + DCHECK(ContainsKey(ssl_socket_pools_for_https_proxies_, http_proxy)); |
| + return it->second; |
| + } |
| + |
| + DCHECK(!ContainsKey(transport_socket_pools_for_http_proxies_, http_proxy)); |
| + DCHECK(!ContainsKey(transport_socket_pools_for_https_proxies_, http_proxy)); |
| + DCHECK(!ContainsKey(ssl_socket_pools_for_https_proxies_, http_proxy)); |
| + |
| + std::pair<TransportSocketPoolMap::iterator, bool> tcp_http_ret = |
| + transport_socket_pools_for_http_proxies_.insert( |
| + std::make_pair( |
| + http_proxy, |
| + new TransportClientSocketPool( |
| + max_sockets_per_proxy_server(), |
| + max_sockets_per_group(), |
| + &transport_for_http_proxy_pool_histograms_, |
| + host_resolver_, |
| + socket_factory_, |
| + net_log_))); |
| + DCHECK(tcp_http_ret.second); |
| + |
| + std::pair<TransportSocketPoolMap::iterator, bool> tcp_https_ret = |
| + transport_socket_pools_for_https_proxies_.insert( |
| + std::make_pair( |
| + http_proxy, |
| + new TransportClientSocketPool( |
| + max_sockets_per_proxy_server(), |
| + max_sockets_per_group(), |
| + &transport_for_https_proxy_pool_histograms_, |
| + host_resolver_, |
| + socket_factory_, |
| + net_log_))); |
| + DCHECK(tcp_https_ret.second); |
| + |
| + std::pair<SSLSocketPoolMap::iterator, bool> ssl_https_ret = |
| + ssl_socket_pools_for_https_proxies_.insert( |
| + std::make_pair( |
| + http_proxy, |
| + new SSLClientSocketPool( |
| + max_sockets_per_proxy_server(), |
| + max_sockets_per_group(), |
| + &ssl_for_https_proxy_pool_histograms_, |
| + host_resolver_, |
| + cert_verifier_, |
| + origin_bound_cert_service_, |
| + dnsrr_resolver_, |
| + dns_cert_checker_, |
| + ssl_host_info_factory_, |
| + socket_factory_, |
| + tcp_https_ret.first->second /* https proxy */, |
| + NULL /* no socks proxy */, |
| + NULL /* no http proxy */, |
| + ssl_config_service_, net_log_))); |
| + DCHECK(tcp_https_ret.second); |
| + |
| + std::pair<HTTPProxySocketPoolMap::iterator, bool> ret = |
| + http_proxy_socket_pools_.insert( |
| + std::make_pair( |
| + http_proxy, |
| + new HttpProxyClientSocketPool( |
| + max_sockets_per_proxy_server(), |
| + max_sockets_per_group(), |
| + &http_proxy_pool_histograms_, |
| + host_resolver_, |
| + tcp_http_ret.first->second, |
| + ssl_https_ret.first->second, |
| + net_log_))); |
| + |
| + return ret.first->second; |
| +} |
| + |
| +SSLClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy( |
| + const HostPortPair& proxy_server) { |
| + SSLSocketPoolMap::const_iterator it = |
| + ssl_socket_pools_for_proxies_.find(proxy_server); |
| + if (it != ssl_socket_pools_for_proxies_.end()) |
| + return it->second; |
| + |
| + SSLClientSocketPool* new_pool = new SSLClientSocketPool( |
| + max_sockets_per_proxy_server(), max_sockets_per_group(), |
| + &ssl_pool_histograms_, |
| + host_resolver_, |
| + cert_verifier_, |
| + origin_bound_cert_service_, |
| + dnsrr_resolver_, |
| + dns_cert_checker_, |
| + ssl_host_info_factory_, |
| + socket_factory_, |
| + NULL, /* no tcp pool, we always go through a proxy */ |
| + GetSocketPoolForSOCKSProxy(proxy_server), |
| + GetSocketPoolForHTTPProxy(proxy_server), |
| + ssl_config_service_, |
| + net_log_); |
| + |
| + std::pair<SSLSocketPoolMap::iterator, bool> ret = |
| + ssl_socket_pools_for_proxies_.insert(std::make_pair(proxy_server, |
| + new_pool)); |
| + |
| + return ret.first->second; |
| +} |
| + |
| +Value* ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const { |
| + ListValue* list = new ListValue(); |
| + list->Append(transport_socket_pool_->GetInfoAsValue("transport_socket_pool", |
| + "transport_socket_pool", |
| + false)); |
| + // Third parameter is false because |ssl_socket_pool_| uses |
| + // |transport_socket_pool_| internally, and do not want to add it a second |
| + // time. |
| + list->Append(ssl_socket_pool_->GetInfoAsValue("ssl_socket_pool", |
| + "ssl_socket_pool", |
| + false)); |
| + AddSocketPoolsToList(list, |
| + http_proxy_socket_pools_, |
| + "http_proxy_socket_pool", |
| + true); |
| + AddSocketPoolsToList(list, |
| + socks_socket_pools_, |
| + "socks_socket_pool", |
| + true); |
| + |
| + // Third parameter is false because |ssl_socket_pools_for_proxies_| use |
| + // socket pools in |http_proxy_socket_pools_| and |socks_socket_pools_|. |
| + AddSocketPoolsToList(list, |
| + ssl_socket_pools_for_proxies_, |
| + "ssl_socket_pool_for_proxies", |
| + false); |
| + return list; |
| +} |
| + |
| +void ClientSocketPoolManagerImpl::OnUserCertAdded(const X509Certificate* cert) { |
| + FlushSocketPools(); |
| +} |
| + |
| +void ClientSocketPoolManagerImpl::OnCertTrustChanged( |
| + const X509Certificate* cert) { |
| + // We should flush the socket pools if we removed trust from a |
| + // cert, because a previously trusted server may have become |
| + // untrusted. |
| + // |
| + // We should not flush the socket pools if we added trust to a |
| + // cert. |
| + // |
| + // Since the OnCertTrustChanged method doesn't tell us what |
| + // kind of trust change it is, we have to flush the socket |
| + // pools to be safe. |
| + FlushSocketPools(); |
| +} |
| + |
| +} // namespace net |