1 // Copyright 2012 The Chromium Authors
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 <algorithm>
8 #include <utility>
9
10 #include "base/check_op.h"
11 #include "base/values.h"
12 #include "net/base/proxy_chain.h"
13 #include "net/base/proxy_server.h"
14 #include "net/base/proxy_string_util.h"
15 #include "net/http/http_network_session.h"
16 #include "net/socket/socks_connect_job.h"
17 #include "net/socket/ssl_connect_job.h"
18 #include "net/socket/transport_client_socket_pool.h"
19 #include "net/socket/transport_connect_job.h"
20 #include "net/socket/websocket_transport_client_socket_pool.h"
21
22 namespace net {
23
24 class SocketPerformanceWatcherFactory;
25
ClientSocketPoolManagerImpl(const CommonConnectJobParams & common_connect_job_params,const CommonConnectJobParams & websocket_common_connect_job_params,HttpNetworkSession::SocketPoolType pool_type,bool cleanup_on_ip_address_change)26 ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl(
27 const CommonConnectJobParams& common_connect_job_params,
28 const CommonConnectJobParams& websocket_common_connect_job_params,
29 HttpNetworkSession::SocketPoolType pool_type,
30 bool cleanup_on_ip_address_change)
31 : common_connect_job_params_(common_connect_job_params),
32 websocket_common_connect_job_params_(websocket_common_connect_job_params),
33 pool_type_(pool_type),
34 cleanup_on_ip_address_change_(cleanup_on_ip_address_change) {
35 // |websocket_endpoint_lock_manager| must only be set for websocket
36 // connections.
37 DCHECK(!common_connect_job_params_.websocket_endpoint_lock_manager);
38 DCHECK(websocket_common_connect_job_params.websocket_endpoint_lock_manager);
39 }
40
~ClientSocketPoolManagerImpl()41 ClientSocketPoolManagerImpl::~ClientSocketPoolManagerImpl() {
42 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
43 }
44
FlushSocketPoolsWithError(int net_error,const char * net_log_reason_utf8)45 void ClientSocketPoolManagerImpl::FlushSocketPoolsWithError(
46 int net_error,
47 const char* net_log_reason_utf8) {
48 for (const auto& it : socket_pools_) {
49 it.second->FlushWithError(net_error, net_log_reason_utf8);
50 }
51 }
52
CloseIdleSockets(const char * net_log_reason_utf8)53 void ClientSocketPoolManagerImpl::CloseIdleSockets(
54 const char* net_log_reason_utf8) {
55 for (const auto& it : socket_pools_) {
56 it.second->CloseIdleSockets(net_log_reason_utf8);
57 }
58 }
59
GetSocketPool(const ProxyChain & proxy_chain)60 ClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPool(
61 const ProxyChain& proxy_chain) {
62 SocketPoolMap::const_iterator it = socket_pools_.find(proxy_chain);
63 if (it != socket_pools_.end())
64 return it->second.get();
65
66 int sockets_per_proxy_chain;
67 int sockets_per_group;
68 if (proxy_chain.is_direct()) {
69 sockets_per_proxy_chain = max_sockets_per_pool(pool_type_);
70 sockets_per_group = max_sockets_per_group(pool_type_);
71 } else {
72 sockets_per_proxy_chain = max_sockets_per_proxy_chain(pool_type_);
73 sockets_per_group =
74 std::min(sockets_per_proxy_chain, max_sockets_per_group(pool_type_));
75 }
76
77 std::unique_ptr<ClientSocketPool> new_pool;
78
79 // Use specialized WebSockets pool for WebSockets when no proxies are in use.
80 if (pool_type_ == HttpNetworkSession::WEBSOCKET_SOCKET_POOL &&
81 proxy_chain.is_direct()) {
82 new_pool = std::make_unique<WebSocketTransportClientSocketPool>(
83 sockets_per_proxy_chain, sockets_per_group, proxy_chain,
84 &websocket_common_connect_job_params_);
85 } else {
86 new_pool = std::make_unique<TransportClientSocketPool>(
87 sockets_per_proxy_chain, sockets_per_group,
88 unused_idle_socket_timeout(pool_type_), proxy_chain,
89 pool_type_ == HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
90 &common_connect_job_params_, cleanup_on_ip_address_change_);
91 }
92
93 std::pair<SocketPoolMap::iterator, bool> ret =
94 socket_pools_.emplace(proxy_chain, std::move(new_pool));
95 return ret.first->second.get();
96 }
97
SocketPoolInfoToValue() const98 base::Value ClientSocketPoolManagerImpl::SocketPoolInfoToValue() const {
99 base::Value::List list;
100 for (const auto& socket_pool : socket_pools_) {
101 // TODO(menke): Is this really needed?
102 const char* type;
103 // Note that it's actually the last proxy that determines the type of socket
104 // pool, although for SOCKS proxy chains, multi-proxy chains aren't
105 // supported.
106 const ProxyChain& proxy_chain = socket_pool.first;
107 if (proxy_chain.is_direct()) {
108 type = "transport_socket_pool";
109 } else if (proxy_chain.Last().is_socks()) {
110 type = "socks_socket_pool";
111 } else {
112 type = "http_proxy_socket_pool";
113 }
114 list.Append(
115 socket_pool.second->GetInfoAsValue(proxy_chain.ToDebugString(), type));
116 }
117
118 return base::Value(std::move(list));
119 }
120
121 } // namespace net
122