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