• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "base/check_op.h"
11 #include "base/metrics/field_trial_params.h"
12 #include "base/strings/string_piece.h"
13 #include "build/build_config.h"
14 #include "net/base/features.h"
15 #include "net/base/load_flags.h"
16 #include "net/base/proxy_chain.h"
17 #include "net/base/proxy_server.h"
18 #include "net/dns/public/secure_dns_policy.h"
19 #include "net/http/http_stream_factory.h"
20 #include "net/proxy_resolution/proxy_info.h"
21 #include "net/socket/client_socket_handle.h"
22 #include "net/socket/client_socket_pool.h"
23 #include "net/socket/connect_job.h"
24 #include "net/ssl/ssl_config.h"
25 #include "third_party/abseil-cpp/absl/types/optional.h"
26 #include "url/gurl.h"
27 #include "url/scheme_host_port.h"
28 #include "url/url_constants.h"
29 
30 namespace net {
31 
32 namespace {
33 
34 // Limit of sockets of each socket pool.
35 int g_max_sockets_per_pool[] = {
36   256,  // NORMAL_SOCKET_POOL
37   256   // WEBSOCKET_SOCKET_POOL
38 };
39 
40 static_assert(std::size(g_max_sockets_per_pool) ==
41                   HttpNetworkSession::NUM_SOCKET_POOL_TYPES,
42               "max sockets per pool length mismatch");
43 
44 // Default to allow up to 6 connections per host. Experiment and tuning may
45 // try other values (greater than 0).  Too large may cause many problems, such
46 // as home routers blocking the connections!?!?  See http://crbug.com/12066.
47 //
48 // WebSocket connections are long-lived, and should be treated differently
49 // than normal other connections. Use a limit of 255, so the limit for wss will
50 // be the same as the limit for ws. Also note that Firefox uses a limit of 200.
51 // See http://crbug.com/486800
52 int g_max_sockets_per_group[] = {
53     6,   // NORMAL_SOCKET_POOL
54     255  // WEBSOCKET_SOCKET_POOL
55 };
56 
57 static_assert(std::size(g_max_sockets_per_group) ==
58                   HttpNetworkSession::NUM_SOCKET_POOL_TYPES,
59               "max sockets per group length mismatch");
60 
61 // The max number of sockets to allow per proxy chain.  This applies both to
62 // http and SOCKS proxies.  See http://crbug.com/12066 and
63 // http://crbug.com/44501 for details about proxy chain connection limits.
64 int g_max_sockets_per_proxy_chain[] = {
65     kDefaultMaxSocketsPerProxyChain,  // NORMAL_SOCKET_POOL
66     kDefaultMaxSocketsPerProxyChain   // WEBSOCKET_SOCKET_POOL
67 };
68 
69 static_assert(std::size(g_max_sockets_per_proxy_chain) ==
70                   HttpNetworkSession::NUM_SOCKET_POOL_TYPES,
71               "max sockets per proxy chain length mismatch");
72 
73 // TODO(https://crbug.com/921369) In order to resolve longstanding issues
74 // related to pooling distinguishable sockets together, get rid of SocketParams
75 // entirely.
CreateSocketParams(const ClientSocketPool::GroupId & group_id,const ProxyChain & proxy_chain,const SSLConfig & ssl_config_for_origin,const SSLConfig & base_ssl_config_for_proxies)76 scoped_refptr<ClientSocketPool::SocketParams> CreateSocketParams(
77     const ClientSocketPool::GroupId& group_id,
78     const ProxyChain& proxy_chain,
79     const SSLConfig& ssl_config_for_origin,
80     const SSLConfig& base_ssl_config_for_proxies) {
81   bool using_ssl = GURL::SchemeIsCryptographic(group_id.destination().scheme());
82 
83   // If there is a proxy chain and any server in that chain is using SSL,
84   // then this socket will need to use SSL.
85   bool using_proxy_ssl =
86       !proxy_chain.is_direct() &&
87       std::any_of(proxy_chain.proxy_servers().begin(),
88                   proxy_chain.proxy_servers().end(),
89                   [](const ProxyServer& proxy_server) {
90                     return proxy_server.is_secure_http_like();
91                   });
92 
93   return base::MakeRefCounted<ClientSocketPool::SocketParams>(
94       using_ssl ? std::make_unique<SSLConfig>(ssl_config_for_origin) : nullptr,
95       using_proxy_ssl ? std::make_unique<SSLConfig>(base_ssl_config_for_proxies)
96                       : nullptr);
97 }
98 
InitSocketPoolHelper(url::SchemeHostPort endpoint,int request_load_flags,RequestPriority request_priority,HttpNetworkSession * session,const ProxyInfo & proxy_info,const SSLConfig & ssl_config_for_origin,const SSLConfig & base_ssl_config_for_proxies,PrivacyMode privacy_mode,NetworkAnonymizationKey network_anonymization_key,SecureDnsPolicy secure_dns_policy,const SocketTag & socket_tag,const NetLogWithSource & net_log,int num_preconnect_streams,ClientSocketHandle * socket_handle,HttpNetworkSession::SocketPoolType socket_pool_type,CompletionOnceCallback callback,const ClientSocketPool::ProxyAuthCallback & proxy_auth_callback)99 int InitSocketPoolHelper(
100     url::SchemeHostPort endpoint,
101     int request_load_flags,
102     RequestPriority request_priority,
103     HttpNetworkSession* session,
104     const ProxyInfo& proxy_info,
105     const SSLConfig& ssl_config_for_origin,
106     const SSLConfig& base_ssl_config_for_proxies,
107     PrivacyMode privacy_mode,
108     NetworkAnonymizationKey network_anonymization_key,
109     SecureDnsPolicy secure_dns_policy,
110     const SocketTag& socket_tag,
111     const NetLogWithSource& net_log,
112     int num_preconnect_streams,
113     ClientSocketHandle* socket_handle,
114     HttpNetworkSession::SocketPoolType socket_pool_type,
115     CompletionOnceCallback callback,
116     const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
117   DCHECK(endpoint.IsValid());
118 
119   bool using_ssl = GURL::SchemeIsCryptographic(endpoint.scheme());
120   if (!using_ssl && session->params().testing_fixed_http_port != 0) {
121     endpoint = url::SchemeHostPort(endpoint.scheme(), endpoint.host(),
122                                    session->params().testing_fixed_http_port);
123   } else if (using_ssl && session->params().testing_fixed_https_port != 0) {
124     endpoint = url::SchemeHostPort(endpoint.scheme(), endpoint.host(),
125                                    session->params().testing_fixed_https_port);
126   }
127 
128   ClientSocketPool::GroupId connection_group(
129       std::move(endpoint), privacy_mode, std::move(network_anonymization_key),
130       secure_dns_policy);
131   scoped_refptr<ClientSocketPool::SocketParams> socket_params =
132       CreateSocketParams(connection_group, proxy_info.proxy_chain(),
133                          ssl_config_for_origin, base_ssl_config_for_proxies);
134 
135   ClientSocketPool* pool =
136       session->GetSocketPool(socket_pool_type, proxy_info.proxy_chain());
137   ClientSocketPool::RespectLimits respect_limits =
138       ClientSocketPool::RespectLimits::ENABLED;
139   if ((request_load_flags & LOAD_IGNORE_LIMITS) != 0)
140     respect_limits = ClientSocketPool::RespectLimits::DISABLED;
141 
142   absl::optional<NetworkTrafficAnnotationTag> proxy_annotation =
143       proxy_info.is_direct() ? absl::nullopt
144                              : absl::optional<NetworkTrafficAnnotationTag>(
145                                    proxy_info.traffic_annotation());
146   if (num_preconnect_streams) {
147     return pool->RequestSockets(connection_group, std::move(socket_params),
148                                 proxy_annotation, num_preconnect_streams,
149                                 std::move(callback), net_log);
150   }
151 
152   return socket_handle->Init(connection_group, std::move(socket_params),
153                              proxy_annotation, request_priority, socket_tag,
154                              respect_limits, std::move(callback),
155                              proxy_auth_callback, pool, net_log);
156 }
157 
158 }  // namespace
159 
160 ClientSocketPoolManager::ClientSocketPoolManager() = default;
161 ClientSocketPoolManager::~ClientSocketPoolManager() = default;
162 
163 // static
max_sockets_per_pool(HttpNetworkSession::SocketPoolType pool_type)164 int ClientSocketPoolManager::max_sockets_per_pool(
165     HttpNetworkSession::SocketPoolType pool_type) {
166   DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
167   return g_max_sockets_per_pool[pool_type];
168 }
169 
170 // static
set_max_sockets_per_pool(HttpNetworkSession::SocketPoolType pool_type,int socket_count)171 void ClientSocketPoolManager::set_max_sockets_per_pool(
172     HttpNetworkSession::SocketPoolType pool_type,
173     int socket_count) {
174   DCHECK_LT(0, socket_count);
175   DCHECK_GT(1000, socket_count);  // Sanity check.
176   DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
177   g_max_sockets_per_pool[pool_type] = socket_count;
178   DCHECK_GE(g_max_sockets_per_pool[pool_type],
179             g_max_sockets_per_group[pool_type]);
180 }
181 
182 // static
max_sockets_per_group(HttpNetworkSession::SocketPoolType pool_type)183 int ClientSocketPoolManager::max_sockets_per_group(
184     HttpNetworkSession::SocketPoolType pool_type) {
185   DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
186   return g_max_sockets_per_group[pool_type];
187 }
188 
189 // static
set_max_sockets_per_group(HttpNetworkSession::SocketPoolType pool_type,int socket_count)190 void ClientSocketPoolManager::set_max_sockets_per_group(
191     HttpNetworkSession::SocketPoolType pool_type,
192     int socket_count) {
193   DCHECK_LT(0, socket_count);
194   // The following is a sanity check... but we should NEVER be near this value.
195   DCHECK_GT(100, socket_count);
196   DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
197   g_max_sockets_per_group[pool_type] = socket_count;
198 
199   DCHECK_GE(g_max_sockets_per_pool[pool_type],
200             g_max_sockets_per_group[pool_type]);
201   DCHECK_GE(g_max_sockets_per_proxy_chain[pool_type],
202             g_max_sockets_per_group[pool_type]);
203 }
204 
205 // static
max_sockets_per_proxy_chain(HttpNetworkSession::SocketPoolType pool_type)206 int ClientSocketPoolManager::max_sockets_per_proxy_chain(
207     HttpNetworkSession::SocketPoolType pool_type) {
208   DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
209   return g_max_sockets_per_proxy_chain[pool_type];
210 }
211 
212 // static
set_max_sockets_per_proxy_chain(HttpNetworkSession::SocketPoolType pool_type,int socket_count)213 void ClientSocketPoolManager::set_max_sockets_per_proxy_chain(
214     HttpNetworkSession::SocketPoolType pool_type,
215     int socket_count) {
216   DCHECK_LT(0, socket_count);
217   DCHECK_GT(100, socket_count);  // Sanity check.
218   DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
219   // Assert this case early on. The max number of sockets per group cannot
220   // exceed the max number of sockets per proxy chain.
221   DCHECK_LE(g_max_sockets_per_group[pool_type], socket_count);
222   g_max_sockets_per_proxy_chain[pool_type] = socket_count;
223 }
224 
225 // static
unused_idle_socket_timeout(HttpNetworkSession::SocketPoolType pool_type)226 base::TimeDelta ClientSocketPoolManager::unused_idle_socket_timeout(
227     HttpNetworkSession::SocketPoolType pool_type) {
228   return base::Seconds(base::GetFieldTrialParamByFeatureAsInt(
229       net::features::kNetUnusedIdleSocketTimeout,
230       "unused_idle_socket_timeout_seconds", 60));
231 }
232 
InitSocketHandleForHttpRequest(url::SchemeHostPort endpoint,int request_load_flags,RequestPriority request_priority,HttpNetworkSession * session,const ProxyInfo & proxy_info,const SSLConfig & ssl_config_for_origin,const SSLConfig & base_ssl_config_for_proxies,PrivacyMode privacy_mode,NetworkAnonymizationKey network_anonymization_key,SecureDnsPolicy secure_dns_policy,const SocketTag & socket_tag,const NetLogWithSource & net_log,ClientSocketHandle * socket_handle,CompletionOnceCallback callback,const ClientSocketPool::ProxyAuthCallback & proxy_auth_callback)233 int InitSocketHandleForHttpRequest(
234     url::SchemeHostPort endpoint,
235     int request_load_flags,
236     RequestPriority request_priority,
237     HttpNetworkSession* session,
238     const ProxyInfo& proxy_info,
239     const SSLConfig& ssl_config_for_origin,
240     const SSLConfig& base_ssl_config_for_proxies,
241     PrivacyMode privacy_mode,
242     NetworkAnonymizationKey network_anonymization_key,
243     SecureDnsPolicy secure_dns_policy,
244     const SocketTag& socket_tag,
245     const NetLogWithSource& net_log,
246     ClientSocketHandle* socket_handle,
247     CompletionOnceCallback callback,
248     const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
249   DCHECK(socket_handle);
250   return InitSocketPoolHelper(
251       std::move(endpoint), request_load_flags, request_priority, session,
252       proxy_info, ssl_config_for_origin, base_ssl_config_for_proxies,
253       privacy_mode, std::move(network_anonymization_key), secure_dns_policy,
254       socket_tag, net_log, 0, socket_handle,
255       HttpNetworkSession::NORMAL_SOCKET_POOL, std::move(callback),
256       proxy_auth_callback);
257 }
258 
InitSocketHandleForWebSocketRequest(url::SchemeHostPort endpoint,int request_load_flags,RequestPriority request_priority,HttpNetworkSession * session,const ProxyInfo & proxy_info,const SSLConfig & ssl_config_for_origin,const SSLConfig & base_ssl_config_for_proxies,PrivacyMode privacy_mode,NetworkAnonymizationKey network_anonymization_key,const NetLogWithSource & net_log,ClientSocketHandle * socket_handle,CompletionOnceCallback callback,const ClientSocketPool::ProxyAuthCallback & proxy_auth_callback)259 int InitSocketHandleForWebSocketRequest(
260     url::SchemeHostPort endpoint,
261     int request_load_flags,
262     RequestPriority request_priority,
263     HttpNetworkSession* session,
264     const ProxyInfo& proxy_info,
265     const SSLConfig& ssl_config_for_origin,
266     const SSLConfig& base_ssl_config_for_proxies,
267     PrivacyMode privacy_mode,
268     NetworkAnonymizationKey network_anonymization_key,
269     const NetLogWithSource& net_log,
270     ClientSocketHandle* socket_handle,
271     CompletionOnceCallback callback,
272     const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
273   DCHECK(socket_handle);
274 
275   // QUIC proxies are currently not supported through this method.
276   DCHECK(!proxy_info.is_quic());
277 
278   // Expect websocket schemes (ws and wss) to be converted to the http(s)
279   // equivalent.
280   DCHECK(endpoint.scheme() == url::kHttpScheme ||
281          endpoint.scheme() == url::kHttpsScheme);
282 
283   return InitSocketPoolHelper(
284       std::move(endpoint), request_load_flags, request_priority, session,
285       proxy_info, ssl_config_for_origin, base_ssl_config_for_proxies,
286       privacy_mode, std::move(network_anonymization_key),
287       SecureDnsPolicy::kAllow, SocketTag(), net_log, 0, socket_handle,
288       HttpNetworkSession::WEBSOCKET_SOCKET_POOL, std::move(callback),
289       proxy_auth_callback);
290 }
291 
PreconnectSocketsForHttpRequest(url::SchemeHostPort endpoint,int request_load_flags,RequestPriority request_priority,HttpNetworkSession * session,const ProxyInfo & proxy_info,const SSLConfig & ssl_config_for_origin,const SSLConfig & base_ssl_config_for_proxies,PrivacyMode privacy_mode,NetworkAnonymizationKey network_anonymization_key,SecureDnsPolicy secure_dns_policy,const NetLogWithSource & net_log,int num_preconnect_streams,CompletionOnceCallback callback)292 int PreconnectSocketsForHttpRequest(
293     url::SchemeHostPort endpoint,
294     int request_load_flags,
295     RequestPriority request_priority,
296     HttpNetworkSession* session,
297     const ProxyInfo& proxy_info,
298     const SSLConfig& ssl_config_for_origin,
299     const SSLConfig& base_ssl_config_for_proxies,
300     PrivacyMode privacy_mode,
301     NetworkAnonymizationKey network_anonymization_key,
302     SecureDnsPolicy secure_dns_policy,
303     const NetLogWithSource& net_log,
304     int num_preconnect_streams,
305     CompletionOnceCallback callback) {
306   // QUIC proxies are currently not supported through this method.
307   DCHECK(!proxy_info.is_quic());
308 
309   // Expect websocket schemes (ws and wss) to be converted to the http(s)
310   // equivalent.
311   DCHECK(endpoint.scheme() == url::kHttpScheme ||
312          endpoint.scheme() == url::kHttpsScheme);
313 
314   return InitSocketPoolHelper(
315       std::move(endpoint), request_load_flags, request_priority, session,
316       proxy_info, ssl_config_for_origin, base_ssl_config_for_proxies,
317       privacy_mode, std::move(network_anonymization_key), secure_dns_policy,
318       SocketTag(), net_log, num_preconnect_streams, nullptr,
319       HttpNetworkSession::NORMAL_SOCKET_POOL, std::move(callback),
320       ClientSocketPool::ProxyAuthCallback());
321 }
322 
323 }  // namespace net
324