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 <optional>
9 #include <utility>
10
11 #include "base/check_op.h"
12 #include "base/metrics/field_trial_params.h"
13 #include "base/strings/string_piece.h"
14 #include "build/build_config.h"
15 #include "net/base/features.h"
16 #include "net/base/load_flags.h"
17 #include "net/base/proxy_chain.h"
18 #include "net/base/proxy_server.h"
19 #include "net/dns/public/secure_dns_policy.h"
20 #include "net/http/http_stream_factory.h"
21 #include "net/proxy_resolution/proxy_info.h"
22 #include "net/socket/client_socket_handle.h"
23 #include "net/socket/client_socket_pool.h"
24 #include "net/socket/connect_job.h"
25 #include "net/ssl/ssl_config.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 std::vector<SSLConfig::CertAndStatus> & allowed_bad_certs)76 scoped_refptr<ClientSocketPool::SocketParams> CreateSocketParams(
77 const ClientSocketPool::GroupId& group_id,
78 const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs) {
79 bool using_ssl = GURL::SchemeIsCryptographic(group_id.destination().scheme());
80 return base::MakeRefCounted<ClientSocketPool::SocketParams>(
81 using_ssl ? allowed_bad_certs : std::vector<SSLConfig::CertAndStatus>());
82 }
83
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)84 int InitSocketPoolHelper(
85 url::SchemeHostPort endpoint,
86 int request_load_flags,
87 RequestPriority request_priority,
88 HttpNetworkSession* session,
89 const ProxyInfo& proxy_info,
90 const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
91 PrivacyMode privacy_mode,
92 NetworkAnonymizationKey network_anonymization_key,
93 SecureDnsPolicy secure_dns_policy,
94 const SocketTag& socket_tag,
95 const NetLogWithSource& net_log,
96 int num_preconnect_streams,
97 ClientSocketHandle* socket_handle,
98 HttpNetworkSession::SocketPoolType socket_pool_type,
99 CompletionOnceCallback callback,
100 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
101 DCHECK(endpoint.IsValid());
102
103 bool using_ssl = GURL::SchemeIsCryptographic(endpoint.scheme());
104 if (!using_ssl && session->params().testing_fixed_http_port != 0) {
105 endpoint = url::SchemeHostPort(endpoint.scheme(), endpoint.host(),
106 session->params().testing_fixed_http_port);
107 } else if (using_ssl && session->params().testing_fixed_https_port != 0) {
108 endpoint = url::SchemeHostPort(endpoint.scheme(), endpoint.host(),
109 session->params().testing_fixed_https_port);
110 }
111
112 bool disable_cert_network_fetches =
113 !!(request_load_flags & LOAD_DISABLE_CERT_NETWORK_FETCHES);
114 ClientSocketPool::GroupId connection_group(
115 std::move(endpoint), privacy_mode, std::move(network_anonymization_key),
116 secure_dns_policy, disable_cert_network_fetches);
117 scoped_refptr<ClientSocketPool::SocketParams> socket_params =
118 CreateSocketParams(connection_group, allowed_bad_certs);
119
120 ClientSocketPool* pool =
121 session->GetSocketPool(socket_pool_type, proxy_info.proxy_chain());
122 ClientSocketPool::RespectLimits respect_limits =
123 ClientSocketPool::RespectLimits::ENABLED;
124 if ((request_load_flags & LOAD_IGNORE_LIMITS) != 0)
125 respect_limits = ClientSocketPool::RespectLimits::DISABLED;
126
127 std::optional<NetworkTrafficAnnotationTag> proxy_annotation =
128 proxy_info.is_direct() ? std::nullopt
129 : std::optional<NetworkTrafficAnnotationTag>(
130 proxy_info.traffic_annotation());
131 if (num_preconnect_streams) {
132 return pool->RequestSockets(connection_group, std::move(socket_params),
133 proxy_annotation, num_preconnect_streams,
134 std::move(callback), net_log);
135 }
136
137 return socket_handle->Init(connection_group, std::move(socket_params),
138 proxy_annotation, request_priority, socket_tag,
139 respect_limits, std::move(callback),
140 proxy_auth_callback, pool, net_log);
141 }
142
143 } // namespace
144
145 ClientSocketPoolManager::ClientSocketPoolManager() = default;
146 ClientSocketPoolManager::~ClientSocketPoolManager() = default;
147
148 // static
max_sockets_per_pool(HttpNetworkSession::SocketPoolType pool_type)149 int ClientSocketPoolManager::max_sockets_per_pool(
150 HttpNetworkSession::SocketPoolType pool_type) {
151 DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
152 return g_max_sockets_per_pool[pool_type];
153 }
154
155 // static
set_max_sockets_per_pool(HttpNetworkSession::SocketPoolType pool_type,int socket_count)156 void ClientSocketPoolManager::set_max_sockets_per_pool(
157 HttpNetworkSession::SocketPoolType pool_type,
158 int socket_count) {
159 DCHECK_LT(0, socket_count);
160 DCHECK_GT(1000, socket_count); // Sanity check.
161 DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
162 g_max_sockets_per_pool[pool_type] = socket_count;
163 DCHECK_GE(g_max_sockets_per_pool[pool_type],
164 g_max_sockets_per_group[pool_type]);
165 }
166
167 // static
max_sockets_per_group(HttpNetworkSession::SocketPoolType pool_type)168 int ClientSocketPoolManager::max_sockets_per_group(
169 HttpNetworkSession::SocketPoolType pool_type) {
170 DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
171 return g_max_sockets_per_group[pool_type];
172 }
173
174 // static
set_max_sockets_per_group(HttpNetworkSession::SocketPoolType pool_type,int socket_count)175 void ClientSocketPoolManager::set_max_sockets_per_group(
176 HttpNetworkSession::SocketPoolType pool_type,
177 int socket_count) {
178 DCHECK_LT(0, socket_count);
179 // The following is a sanity check... but we should NEVER be near this value.
180 DCHECK_GT(100, socket_count);
181 DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
182 g_max_sockets_per_group[pool_type] = socket_count;
183
184 DCHECK_GE(g_max_sockets_per_pool[pool_type],
185 g_max_sockets_per_group[pool_type]);
186 DCHECK_GE(g_max_sockets_per_proxy_chain[pool_type],
187 g_max_sockets_per_group[pool_type]);
188 }
189
190 // static
max_sockets_per_proxy_chain(HttpNetworkSession::SocketPoolType pool_type)191 int ClientSocketPoolManager::max_sockets_per_proxy_chain(
192 HttpNetworkSession::SocketPoolType pool_type) {
193 DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
194 return g_max_sockets_per_proxy_chain[pool_type];
195 }
196
197 // static
set_max_sockets_per_proxy_chain(HttpNetworkSession::SocketPoolType pool_type,int socket_count)198 void ClientSocketPoolManager::set_max_sockets_per_proxy_chain(
199 HttpNetworkSession::SocketPoolType pool_type,
200 int socket_count) {
201 DCHECK_LT(0, socket_count);
202 DCHECK_GT(100, socket_count); // Sanity check.
203 DCHECK_LT(pool_type, HttpNetworkSession::NUM_SOCKET_POOL_TYPES);
204 // Assert this case early on. The max number of sockets per group cannot
205 // exceed the max number of sockets per proxy chain.
206 DCHECK_LE(g_max_sockets_per_group[pool_type], socket_count);
207 g_max_sockets_per_proxy_chain[pool_type] = socket_count;
208 }
209
210 // static
unused_idle_socket_timeout(HttpNetworkSession::SocketPoolType pool_type)211 base::TimeDelta ClientSocketPoolManager::unused_idle_socket_timeout(
212 HttpNetworkSession::SocketPoolType pool_type) {
213 return base::Seconds(base::GetFieldTrialParamByFeatureAsInt(
214 net::features::kNetUnusedIdleSocketTimeout,
215 "unused_idle_socket_timeout_seconds", 60));
216 }
217
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)218 int InitSocketHandleForHttpRequest(
219 url::SchemeHostPort endpoint,
220 int request_load_flags,
221 RequestPriority request_priority,
222 HttpNetworkSession* session,
223 const ProxyInfo& proxy_info,
224 const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
225 PrivacyMode privacy_mode,
226 NetworkAnonymizationKey network_anonymization_key,
227 SecureDnsPolicy secure_dns_policy,
228 const SocketTag& socket_tag,
229 const NetLogWithSource& net_log,
230 ClientSocketHandle* socket_handle,
231 CompletionOnceCallback callback,
232 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
233 DCHECK(socket_handle);
234 return InitSocketPoolHelper(
235 std::move(endpoint), request_load_flags, request_priority, session,
236 proxy_info, allowed_bad_certs, privacy_mode,
237 std::move(network_anonymization_key), secure_dns_policy, socket_tag,
238 net_log, 0, socket_handle, HttpNetworkSession::NORMAL_SOCKET_POOL,
239 std::move(callback), proxy_auth_callback);
240 }
241
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)242 int InitSocketHandleForWebSocketRequest(
243 url::SchemeHostPort endpoint,
244 int request_load_flags,
245 RequestPriority request_priority,
246 HttpNetworkSession* session,
247 const ProxyInfo& proxy_info,
248 const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
249 PrivacyMode privacy_mode,
250 NetworkAnonymizationKey network_anonymization_key,
251 const NetLogWithSource& net_log,
252 ClientSocketHandle* socket_handle,
253 CompletionOnceCallback callback,
254 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
255 DCHECK(socket_handle);
256
257 // QUIC proxies are currently not supported through this method.
258 DCHECK(proxy_info.is_direct() || !proxy_info.proxy_chain().Last().is_quic());
259
260 // Expect websocket schemes (ws and wss) to be converted to the http(s)
261 // equivalent.
262 DCHECK(endpoint.scheme() == url::kHttpScheme ||
263 endpoint.scheme() == url::kHttpsScheme);
264
265 return InitSocketPoolHelper(
266 std::move(endpoint), request_load_flags, request_priority, session,
267 proxy_info, allowed_bad_certs, privacy_mode,
268 std::move(network_anonymization_key), SecureDnsPolicy::kAllow,
269 SocketTag(), net_log, 0, socket_handle,
270 HttpNetworkSession::WEBSOCKET_SOCKET_POOL, std::move(callback),
271 proxy_auth_callback);
272 }
273
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)274 int PreconnectSocketsForHttpRequest(
275 url::SchemeHostPort endpoint,
276 int request_load_flags,
277 RequestPriority request_priority,
278 HttpNetworkSession* session,
279 const ProxyInfo& proxy_info,
280 const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs,
281 PrivacyMode privacy_mode,
282 NetworkAnonymizationKey network_anonymization_key,
283 SecureDnsPolicy secure_dns_policy,
284 const NetLogWithSource& net_log,
285 int num_preconnect_streams,
286 CompletionOnceCallback callback) {
287 // Expect websocket schemes (ws and wss) to be converted to the http(s)
288 // equivalent.
289 DCHECK(endpoint.scheme() == url::kHttpScheme ||
290 endpoint.scheme() == url::kHttpsScheme);
291
292 return InitSocketPoolHelper(
293 std::move(endpoint), request_load_flags, request_priority, session,
294 proxy_info, allowed_bad_certs, privacy_mode,
295 std::move(network_anonymization_key), secure_dns_policy, SocketTag(),
296 net_log, num_preconnect_streams, nullptr,
297 HttpNetworkSession::NORMAL_SOCKET_POOL, std::move(callback),
298 ClientSocketPool::ProxyAuthCallback());
299 }
300
301 } // namespace net
302