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/http/http_network_session.h"
6
7 #include <inttypes.h>
8
9 #include <utility>
10
11 #include "base/atomic_sequence_num.h"
12 #include "base/check_op.h"
13 #include "base/compiler_specific.h"
14 #include "base/containers/contains.h"
15 #include "base/notreached.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "base/values.h"
19 #include "build/build_config.h"
20 #include "net/base/features.h"
21 #include "net/dns/host_resolver.h"
22 #include "net/http/http_auth_handler_factory.h"
23 #include "net/http/http_response_body_drainer.h"
24 #include "net/http/http_stream_factory.h"
25 #include "net/http/url_security_manager.h"
26 #include "net/proxy_resolution/proxy_resolution_service.h"
27 #include "net/quic/platform/impl/quic_chromium_clock.h"
28 #include "net/quic/quic_crypto_client_stream_factory.h"
29 #include "net/quic/quic_session_pool.h"
30 #include "net/socket/client_socket_factory.h"
31 #include "net/socket/client_socket_pool_manager_impl.h"
32 #include "net/socket/next_proto.h"
33 #include "net/socket/ssl_client_socket.h"
34 #include "net/spdy/spdy_session.h"
35 #include "net/spdy/spdy_session_pool.h"
36 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_random.h"
37 #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
38 #include "net/third_party/quiche/src/quiche/quic/core/quic_tag.h"
39 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
40
41 namespace net {
42
43 // The maximum receive window sizes for HTTP/2 sessions and streams.
44 const int32_t kSpdySessionMaxRecvWindowSize = 15 * 1024 * 1024; // 15 MB
45 const int32_t kSpdyStreamMaxRecvWindowSize = 6 * 1024 * 1024; // 6 MB
46
47 // Value of SETTINGS_ENABLE_PUSH reflecting that server push is not supported.
48 const uint32_t kSpdyDisablePush = 0;
49
50 namespace {
51
52 // Keep all HTTP2 parameters in |http2_settings|, even the ones that are not
53 // implemented, to be sent to the server.
54 // Set default values for settings that |http2_settings| does not specify.
AddDefaultHttp2Settings(spdy::SettingsMap http2_settings)55 spdy::SettingsMap AddDefaultHttp2Settings(spdy::SettingsMap http2_settings) {
56 // Server push is not supported.
57 http2_settings[spdy::SETTINGS_ENABLE_PUSH] = kSpdyDisablePush;
58
59 // For other setting parameters, set default values only if |http2_settings|
60 // does not have a value set for given setting.
61 auto it = http2_settings.find(spdy::SETTINGS_HEADER_TABLE_SIZE);
62 if (it == http2_settings.end()) {
63 http2_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
64 }
65
66 it = http2_settings.find(spdy::SETTINGS_INITIAL_WINDOW_SIZE);
67 if (it == http2_settings.end()) {
68 http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
69 kSpdyStreamMaxRecvWindowSize;
70 }
71
72 it = http2_settings.find(spdy::SETTINGS_MAX_HEADER_LIST_SIZE);
73 if (it == http2_settings.end()) {
74 http2_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
75 kSpdyMaxHeaderListSize;
76 }
77
78 return http2_settings;
79 }
80
81 } // unnamed namespace
82
HttpNetworkSessionParams()83 HttpNetworkSessionParams::HttpNetworkSessionParams()
84 : spdy_session_max_recv_window_size(kSpdySessionMaxRecvWindowSize),
85 spdy_session_max_queued_capped_frames(kSpdySessionMaxQueuedCappedFrames),
86 time_func(&base::TimeTicks::Now) {
87 enable_early_data =
88 base::FeatureList::IsEnabled(features::kEnableTLS13EarlyData);
89 use_dns_https_svcb_alpn =
90 base::FeatureList::IsEnabled(features::kUseDnsHttpsSvcbAlpn);
91 }
92
93 HttpNetworkSessionParams::HttpNetworkSessionParams(
94 const HttpNetworkSessionParams& other) = default;
95
96 HttpNetworkSessionParams::~HttpNetworkSessionParams() = default;
97
HttpNetworkSessionContext()98 HttpNetworkSessionContext::HttpNetworkSessionContext()
99 : client_socket_factory(nullptr),
100 host_resolver(nullptr),
101 cert_verifier(nullptr),
102 transport_security_state(nullptr),
103 sct_auditing_delegate(nullptr),
104 proxy_resolution_service(nullptr),
105 proxy_delegate(nullptr),
106 http_user_agent_settings(nullptr),
107 ssl_config_service(nullptr),
108 http_auth_handler_factory(nullptr),
109 net_log(nullptr),
110 socket_performance_watcher_factory(nullptr),
111 network_quality_estimator(nullptr),
112 quic_context(nullptr),
113 #if BUILDFLAG(ENABLE_REPORTING)
114 reporting_service(nullptr),
115 network_error_logging_service(nullptr),
116 #endif
117 quic_crypto_client_stream_factory(
118 QuicCryptoClientStreamFactory::GetDefaultFactory()) {
119 }
120
121 HttpNetworkSessionContext::HttpNetworkSessionContext(
122 const HttpNetworkSessionContext& other) = default;
123
124 HttpNetworkSessionContext::~HttpNetworkSessionContext() = default;
125
126 // TODO(mbelshe): Move the socket factories into HttpStreamFactory.
HttpNetworkSession(const HttpNetworkSessionParams & params,const HttpNetworkSessionContext & context)127 HttpNetworkSession::HttpNetworkSession(const HttpNetworkSessionParams& params,
128 const HttpNetworkSessionContext& context)
129 : net_log_(context.net_log),
130 http_server_properties_(context.http_server_properties),
131 cert_verifier_(context.cert_verifier),
132 http_auth_handler_factory_(context.http_auth_handler_factory),
133 host_resolver_(context.host_resolver),
134 #if BUILDFLAG(ENABLE_REPORTING)
135 reporting_service_(context.reporting_service),
136 network_error_logging_service_(context.network_error_logging_service),
137 #endif
138 proxy_resolution_service_(context.proxy_resolution_service),
139 ssl_config_service_(context.ssl_config_service),
140 http_auth_cache_(
141 params.key_auth_cache_server_entries_by_network_anonymization_key),
142 ssl_client_session_cache_(SSLClientSessionCache::Config()),
143 ssl_client_context_(context.ssl_config_service,
144 context.cert_verifier,
145 context.transport_security_state,
146 &ssl_client_session_cache_,
147 context.sct_auditing_delegate),
148 quic_session_pool_(context.net_log,
149 context.host_resolver,
150 context.ssl_config_service,
151 context.client_socket_factory,
152 context.http_server_properties,
153 context.cert_verifier,
154 context.transport_security_state,
155 context.proxy_delegate,
156 context.sct_auditing_delegate,
157 context.socket_performance_watcher_factory,
158 context.quic_crypto_client_stream_factory,
159 context.quic_context),
160 spdy_session_pool_(context.host_resolver,
161 &ssl_client_context_,
162 context.http_server_properties,
163 context.transport_security_state,
164 context.quic_context->params()->supported_versions,
165 params.enable_spdy_ping_based_connection_checking,
166 params.enable_http2,
167 params.enable_quic,
168 params.spdy_session_max_recv_window_size,
169 params.spdy_session_max_queued_capped_frames,
170 AddDefaultHttp2Settings(params.http2_settings),
171 params.enable_http2_settings_grease,
172 params.greased_http2_frame,
173 params.http2_end_stream_with_data_frame,
174 params.enable_priority_update,
175 params.spdy_go_away_on_ip_change,
176 params.time_func,
177 context.network_quality_estimator,
178 // cleanup_sessions_on_ip_address_changed
179 !params.ignore_ip_address_changes),
180 http_stream_factory_(std::make_unique<HttpStreamFactory>(this)),
181 params_(params),
182 context_(context) {
183 DCHECK(proxy_resolution_service_);
184 DCHECK(ssl_config_service_);
185 CHECK(http_server_properties_);
186 DCHECK(context_.client_socket_factory);
187
188 normal_socket_pool_manager_ = std::make_unique<ClientSocketPoolManagerImpl>(
189 CreateCommonConnectJobParams(false /* for_websockets */),
190 CreateCommonConnectJobParams(true /* for_websockets */),
191 NORMAL_SOCKET_POOL,
192 // cleanup_on_ip_address_change
193 !params.ignore_ip_address_changes);
194 websocket_socket_pool_manager_ =
195 std::make_unique<ClientSocketPoolManagerImpl>(
196 CreateCommonConnectJobParams(false /* for_websockets */),
197 CreateCommonConnectJobParams(true /* for_websockets */),
198 WEBSOCKET_SOCKET_POOL,
199 // cleanup_on_ip_address_change
200 !params.ignore_ip_address_changes);
201
202 if (params_.enable_http2) {
203 next_protos_.push_back(kProtoHTTP2);
204 if (base::FeatureList::IsEnabled(features::kAlpsForHttp2)) {
205 // Enable ALPS for HTTP/2 with empty data.
206 application_settings_[kProtoHTTP2] = {};
207 }
208 }
209
210 next_protos_.push_back(kProtoHTTP11);
211
212 http_server_properties_->SetMaxServerConfigsStoredInProperties(
213 context.quic_context->params()->max_server_configs_stored_in_properties);
214 http_server_properties_->SetBrokenAlternativeServicesDelayParams(
215 context.quic_context->params()
216 ->initial_delay_for_broken_alternative_service,
217 context.quic_context->params()->exponential_backoff_on_initial_delay);
218
219 if (!params_.disable_idle_sockets_close_on_memory_pressure) {
220 memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
221 FROM_HERE, base::BindRepeating(&HttpNetworkSession::OnMemoryPressure,
222 base::Unretained(this)));
223 }
224 }
225
~HttpNetworkSession()226 HttpNetworkSession::~HttpNetworkSession() {
227 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
228 response_drainers_.clear();
229 // TODO(bnc): CloseAllSessions() is also called in SpdySessionPool destructor,
230 // one of the two calls should be removed.
231 spdy_session_pool_.CloseAllSessions();
232 }
233
StartResponseDrainer(std::unique_ptr<HttpResponseBodyDrainer> drainer)234 void HttpNetworkSession::StartResponseDrainer(
235 std::unique_ptr<HttpResponseBodyDrainer> drainer) {
236 DCHECK(!base::Contains(response_drainers_, drainer.get()));
237 HttpResponseBodyDrainer* drainer_ptr = drainer.get();
238 response_drainers_.insert(std::move(drainer));
239 drainer_ptr->Start(this);
240 }
241
RemoveResponseDrainer(HttpResponseBodyDrainer * drainer)242 void HttpNetworkSession::RemoveResponseDrainer(
243 HttpResponseBodyDrainer* drainer) {
244 DCHECK(base::Contains(response_drainers_, drainer));
245
246 response_drainers_.erase(response_drainers_.find(drainer));
247 }
248
GetSocketPool(SocketPoolType pool_type,const ProxyChain & proxy_chain)249 ClientSocketPool* HttpNetworkSession::GetSocketPool(
250 SocketPoolType pool_type,
251 const ProxyChain& proxy_chain) {
252 return GetSocketPoolManager(pool_type)->GetSocketPool(proxy_chain);
253 }
254
SocketPoolInfoToValue() const255 base::Value HttpNetworkSession::SocketPoolInfoToValue() const {
256 // TODO(yutak): Should merge values from normal pools and WebSocket pools.
257 return normal_socket_pool_manager_->SocketPoolInfoToValue();
258 }
259
SpdySessionPoolInfoToValue() const260 std::unique_ptr<base::Value> HttpNetworkSession::SpdySessionPoolInfoToValue()
261 const {
262 return spdy_session_pool_.SpdySessionPoolInfoToValue();
263 }
264
QuicInfoToValue() const265 base::Value HttpNetworkSession::QuicInfoToValue() const {
266 base::Value::Dict dict;
267 dict.Set("sessions", quic_session_pool_.QuicSessionPoolInfoToValue());
268 dict.Set("quic_enabled", IsQuicEnabled());
269
270 const QuicParams* quic_params = context_.quic_context->params();
271
272 base::Value::List connection_options;
273 for (const auto& option : quic_params->connection_options) {
274 connection_options.Append(quic::QuicTagToString(option));
275 }
276 dict.Set("connection_options", std::move(connection_options));
277
278 base::Value::List supported_versions;
279 for (const auto& version : quic_params->supported_versions) {
280 supported_versions.Append(ParsedQuicVersionToString(version));
281 }
282 dict.Set("supported_versions", std::move(supported_versions));
283
284 base::Value::List origins_to_force_quic_on;
285 for (const auto& origin : quic_params->origins_to_force_quic_on) {
286 origins_to_force_quic_on.Append(origin.ToString());
287 }
288 dict.Set("origins_to_force_quic_on", std::move(origins_to_force_quic_on));
289
290 dict.Set("max_packet_length",
291 static_cast<int>(quic_params->max_packet_length));
292 dict.Set(
293 "max_server_configs_stored_in_properties",
294 static_cast<int>(quic_params->max_server_configs_stored_in_properties));
295 dict.Set("idle_connection_timeout_seconds",
296 static_cast<int>(quic_params->idle_connection_timeout.InSeconds()));
297 dict.Set("reduced_ping_timeout_seconds",
298 static_cast<int>(quic_params->reduced_ping_timeout.InSeconds()));
299 dict.Set("retry_without_alt_svc_on_quic_errors",
300 quic_params->retry_without_alt_svc_on_quic_errors);
301 dict.Set("close_sessions_on_ip_change",
302 quic_params->close_sessions_on_ip_change);
303 dict.Set("goaway_sessions_on_ip_change",
304 quic_params->goaway_sessions_on_ip_change);
305 dict.Set("migrate_sessions_on_network_change_v2",
306 quic_params->migrate_sessions_on_network_change_v2);
307 dict.Set("migrate_sessions_early_v2", quic_params->migrate_sessions_early_v2);
308 dict.Set("retransmittable_on_wire_timeout_milliseconds",
309 static_cast<int>(
310 quic_params->retransmittable_on_wire_timeout.InMilliseconds()));
311 dict.Set("retry_on_alternate_network_before_handshake",
312 quic_params->retry_on_alternate_network_before_handshake);
313 dict.Set("migrate_idle_sessions", quic_params->migrate_idle_sessions);
314 dict.Set(
315 "idle_session_migration_period_seconds",
316 static_cast<int>(quic_params->idle_session_migration_period.InSeconds()));
317 dict.Set("max_time_on_non_default_network_seconds",
318 static_cast<int>(
319 quic_params->max_time_on_non_default_network.InSeconds()));
320 dict.Set("max_num_migrations_to_non_default_network_on_write_error",
321 quic_params->max_migrations_to_non_default_network_on_write_error);
322 dict.Set(
323 "max_num_migrations_to_non_default_network_on_path_degrading",
324 quic_params->max_migrations_to_non_default_network_on_path_degrading);
325 dict.Set("allow_server_migration", quic_params->allow_server_migration);
326 dict.Set("estimate_initial_rtt", quic_params->estimate_initial_rtt);
327 dict.Set("initial_rtt_for_handshake_milliseconds",
328 static_cast<int>(
329 quic_params->initial_rtt_for_handshake.InMilliseconds()));
330
331 return base::Value(std::move(dict));
332 }
333
CloseAllConnections(int net_error,const char * net_log_reason_utf8)334 void HttpNetworkSession::CloseAllConnections(int net_error,
335 const char* net_log_reason_utf8) {
336 normal_socket_pool_manager_->FlushSocketPoolsWithError(net_error,
337 net_log_reason_utf8);
338 websocket_socket_pool_manager_->FlushSocketPoolsWithError(
339 net_error, net_log_reason_utf8);
340 spdy_session_pool_.CloseCurrentSessions(static_cast<net::Error>(net_error));
341 quic_session_pool_.CloseAllSessions(net_error, quic::QUIC_PEER_GOING_AWAY);
342 }
343
CloseIdleConnections(const char * net_log_reason_utf8)344 void HttpNetworkSession::CloseIdleConnections(const char* net_log_reason_utf8) {
345 normal_socket_pool_manager_->CloseIdleSockets(net_log_reason_utf8);
346 websocket_socket_pool_manager_->CloseIdleSockets(net_log_reason_utf8);
347 spdy_session_pool_.CloseCurrentIdleSessions(net_log_reason_utf8);
348 }
349
IsQuicEnabled() const350 bool HttpNetworkSession::IsQuicEnabled() const {
351 return params_.enable_quic;
352 }
353
DisableQuic()354 void HttpNetworkSession::DisableQuic() {
355 params_.enable_quic = false;
356 }
357
IgnoreCertificateErrorsForTesting()358 void HttpNetworkSession::IgnoreCertificateErrorsForTesting() {
359 params_.ignore_certificate_errors = true;
360 }
361
ClearSSLSessionCache()362 void HttpNetworkSession::ClearSSLSessionCache() {
363 ssl_client_session_cache_.Flush();
364 }
365
CreateCommonConnectJobParams(bool for_websockets)366 CommonConnectJobParams HttpNetworkSession::CreateCommonConnectJobParams(
367 bool for_websockets) {
368 // Use null websocket_endpoint_lock_manager, which is only set for WebSockets,
369 // and only when not using a proxy.
370 return CommonConnectJobParams(
371 context_.client_socket_factory, context_.host_resolver, &http_auth_cache_,
372 context_.http_auth_handler_factory, &spdy_session_pool_,
373 &context_.quic_context->params()->supported_versions, &quic_session_pool_,
374 context_.proxy_delegate, context_.http_user_agent_settings,
375 &ssl_client_context_, context_.socket_performance_watcher_factory,
376 context_.network_quality_estimator, context_.net_log,
377 for_websockets ? &websocket_endpoint_lock_manager_ : nullptr,
378 context_.http_server_properties, &next_protos_, &application_settings_,
379 ¶ms_.ignore_certificate_errors, ¶ms_.enable_early_data);
380 }
381
GetSocketPoolManager(SocketPoolType pool_type)382 ClientSocketPoolManager* HttpNetworkSession::GetSocketPoolManager(
383 SocketPoolType pool_type) {
384 switch (pool_type) {
385 case NORMAL_SOCKET_POOL:
386 return normal_socket_pool_manager_.get();
387 case WEBSOCKET_SOCKET_POOL:
388 return websocket_socket_pool_manager_.get();
389 default:
390 NOTREACHED();
391 break;
392 }
393 return nullptr;
394 }
395
OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level)396 void HttpNetworkSession::OnMemoryPressure(
397 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
398 DCHECK(!params_.disable_idle_sockets_close_on_memory_pressure);
399
400 switch (memory_pressure_level) {
401 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
402 break;
403
404 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
405 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
406 CloseIdleConnections("Low memory");
407 break;
408 }
409 }
410
411 } // namespace net
412