• 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/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_stream_factory.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   it = http2_settings.find(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
66   if (it == http2_settings.end())
67     http2_settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] =
68         kSpdyMaxConcurrentPushedStreams;
69 
70   it = http2_settings.find(spdy::SETTINGS_INITIAL_WINDOW_SIZE);
71   if (it == http2_settings.end())
72     http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
73         kSpdyStreamMaxRecvWindowSize;
74 
75   it = http2_settings.find(spdy::SETTINGS_MAX_HEADER_LIST_SIZE);
76   if (it == http2_settings.end())
77     http2_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
78         kSpdyMaxHeaderListSize;
79 
80   return http2_settings;
81 }
82 
83 }  // unnamed namespace
84 
HttpNetworkSessionParams()85 HttpNetworkSessionParams::HttpNetworkSessionParams()
86     : spdy_session_max_recv_window_size(kSpdySessionMaxRecvWindowSize),
87       spdy_session_max_queued_capped_frames(kSpdySessionMaxQueuedCappedFrames),
88       time_func(&base::TimeTicks::Now) {
89   enable_early_data =
90       base::FeatureList::IsEnabled(features::kEnableTLS13EarlyData);
91   use_dns_https_svcb_alpn =
92       base::FeatureList::IsEnabled(features::kUseDnsHttpsSvcbAlpn);
93 }
94 
95 HttpNetworkSessionParams::HttpNetworkSessionParams(
96     const HttpNetworkSessionParams& other) = default;
97 
98 HttpNetworkSessionParams::~HttpNetworkSessionParams() = default;
99 
HttpNetworkSessionContext()100 HttpNetworkSessionContext::HttpNetworkSessionContext()
101     : client_socket_factory(nullptr),
102       host_resolver(nullptr),
103       cert_verifier(nullptr),
104       transport_security_state(nullptr),
105       ct_policy_enforcer(nullptr),
106       sct_auditing_delegate(nullptr),
107       proxy_resolution_service(nullptr),
108       proxy_delegate(nullptr),
109       http_user_agent_settings(nullptr),
110       ssl_config_service(nullptr),
111       http_auth_handler_factory(nullptr),
112       net_log(nullptr),
113       socket_performance_watcher_factory(nullptr),
114       network_quality_estimator(nullptr),
115       quic_context(nullptr),
116 #if BUILDFLAG(ENABLE_REPORTING)
117       reporting_service(nullptr),
118       network_error_logging_service(nullptr),
119 #endif
120       quic_crypto_client_stream_factory(
121           QuicCryptoClientStreamFactory::GetDefaultFactory()) {
122 }
123 
124 HttpNetworkSessionContext::HttpNetworkSessionContext(
125     const HttpNetworkSessionContext& other) = default;
126 
127 HttpNetworkSessionContext::~HttpNetworkSessionContext() = default;
128 
129 // TODO(mbelshe): Move the socket factories into HttpStreamFactory.
HttpNetworkSession(const HttpNetworkSessionParams & params,const HttpNetworkSessionContext & context)130 HttpNetworkSession::HttpNetworkSession(const HttpNetworkSessionParams& params,
131                                        const HttpNetworkSessionContext& context)
132     : net_log_(context.net_log),
133       http_server_properties_(context.http_server_properties),
134       cert_verifier_(context.cert_verifier),
135       http_auth_handler_factory_(context.http_auth_handler_factory),
136       host_resolver_(context.host_resolver),
137 #if BUILDFLAG(ENABLE_REPORTING)
138       reporting_service_(context.reporting_service),
139       network_error_logging_service_(context.network_error_logging_service),
140 #endif
141       proxy_resolution_service_(context.proxy_resolution_service),
142       ssl_config_service_(context.ssl_config_service),
143       http_auth_cache_(
144           params.key_auth_cache_server_entries_by_network_anonymization_key),
145       ssl_client_session_cache_(SSLClientSessionCache::Config()),
146       ssl_client_context_(context.ssl_config_service,
147                           context.cert_verifier,
148                           context.transport_security_state,
149                           context.ct_policy_enforcer,
150                           &ssl_client_session_cache_,
151                           context.sct_auditing_delegate),
152       quic_stream_factory_(context.net_log,
153                            context.host_resolver,
154                            context.ssl_config_service,
155                            context.client_socket_factory,
156                            context.http_server_properties,
157                            context.cert_verifier,
158                            context.ct_policy_enforcer,
159                            context.transport_security_state,
160                            context.sct_auditing_delegate,
161                            context.socket_performance_watcher_factory,
162                            context.quic_crypto_client_stream_factory,
163                            context.quic_context),
164       spdy_session_pool_(context.host_resolver,
165                          &ssl_client_context_,
166                          context.http_server_properties,
167                          context.transport_security_state,
168                          context.quic_context->params()->supported_versions,
169                          params.enable_spdy_ping_based_connection_checking,
170                          params.enable_http2,
171                          params.enable_quic,
172                          params.spdy_session_max_recv_window_size,
173                          params.spdy_session_max_queued_capped_frames,
174                          AddDefaultHttp2Settings(params.http2_settings),
175                          params.enable_http2_settings_grease,
176                          params.greased_http2_frame,
177                          params.http2_end_stream_with_data_frame,
178                          params.enable_priority_update,
179                          params.spdy_go_away_on_ip_change,
180                          params.time_func,
181                          context.network_quality_estimator,
182                          // cleanup_sessions_on_ip_address_changed
183                          !params.ignore_ip_address_changes),
184       http_stream_factory_(std::make_unique<HttpStreamFactory>(this)),
185       params_(params),
186       context_(context) {
187   DCHECK(proxy_resolution_service_);
188   DCHECK(ssl_config_service_);
189   CHECK(http_server_properties_);
190   DCHECK(context_.client_socket_factory);
191 
192   normal_socket_pool_manager_ = std::make_unique<ClientSocketPoolManagerImpl>(
193       CreateCommonConnectJobParams(false /* for_websockets */),
194       CreateCommonConnectJobParams(true /* for_websockets */),
195       NORMAL_SOCKET_POOL,
196       // cleanup_on_ip_address_change
197       !params.ignore_ip_address_changes);
198   websocket_socket_pool_manager_ =
199       std::make_unique<ClientSocketPoolManagerImpl>(
200           CreateCommonConnectJobParams(false /* for_websockets */),
201           CreateCommonConnectJobParams(true /* for_websockets */),
202           WEBSOCKET_SOCKET_POOL,
203           // cleanup_on_ip_address_change
204           !params.ignore_ip_address_changes);
205 
206   if (params_.enable_http2) {
207     next_protos_.push_back(kProtoHTTP2);
208     if (base::FeatureList::IsEnabled(features::kAlpsForHttp2)) {
209       // Enable ALPS for HTTP/2 with empty data.
210       application_settings_[kProtoHTTP2] = {};
211     }
212   }
213 
214   next_protos_.push_back(kProtoHTTP11);
215 
216   http_server_properties_->SetMaxServerConfigsStoredInProperties(
217       context.quic_context->params()->max_server_configs_stored_in_properties);
218   http_server_properties_->SetBrokenAlternativeServicesDelayParams(
219       context.quic_context->params()
220           ->initial_delay_for_broken_alternative_service,
221       context.quic_context->params()->exponential_backoff_on_initial_delay);
222 
223   if (!params_.disable_idle_sockets_close_on_memory_pressure) {
224     memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
225         FROM_HERE, base::BindRepeating(&HttpNetworkSession::OnMemoryPressure,
226                                        base::Unretained(this)));
227   }
228 }
229 
~HttpNetworkSession()230 HttpNetworkSession::~HttpNetworkSession() {
231   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
232   response_drainers_.clear();
233   // TODO(bnc): CloseAllSessions() is also called in SpdySessionPool destructor,
234   // one of the two calls should be removed.
235   spdy_session_pool_.CloseAllSessions();
236 }
237 
StartResponseDrainer(std::unique_ptr<HttpResponseBodyDrainer> drainer)238 void HttpNetworkSession::StartResponseDrainer(
239     std::unique_ptr<HttpResponseBodyDrainer> drainer) {
240   DCHECK(!base::Contains(response_drainers_, drainer.get()));
241   HttpResponseBodyDrainer* drainer_ptr = drainer.get();
242   response_drainers_.insert(std::move(drainer));
243   drainer_ptr->Start(this);
244 }
245 
RemoveResponseDrainer(HttpResponseBodyDrainer * drainer)246 void HttpNetworkSession::RemoveResponseDrainer(
247     HttpResponseBodyDrainer* drainer) {
248   DCHECK(base::Contains(response_drainers_, drainer));
249 
250   response_drainers_.erase(response_drainers_.find(drainer));
251 }
252 
GetSocketPool(SocketPoolType pool_type,const ProxyServer & proxy_server)253 ClientSocketPool* HttpNetworkSession::GetSocketPool(
254     SocketPoolType pool_type,
255     const ProxyServer& proxy_server) {
256   return GetSocketPoolManager(pool_type)->GetSocketPool(proxy_server);
257 }
258 
SocketPoolInfoToValue() const259 base::Value HttpNetworkSession::SocketPoolInfoToValue() const {
260   // TODO(yutak): Should merge values from normal pools and WebSocket pools.
261   return normal_socket_pool_manager_->SocketPoolInfoToValue();
262 }
263 
SpdySessionPoolInfoToValue() const264 std::unique_ptr<base::Value> HttpNetworkSession::SpdySessionPoolInfoToValue()
265     const {
266   return spdy_session_pool_.SpdySessionPoolInfoToValue();
267 }
268 
QuicInfoToValue() const269 base::Value HttpNetworkSession::QuicInfoToValue() const {
270   base::Value::Dict dict;
271   dict.Set("sessions", quic_stream_factory_.QuicStreamFactoryInfoToValue());
272   dict.Set("quic_enabled", IsQuicEnabled());
273 
274   const QuicParams* quic_params = context_.quic_context->params();
275 
276   base::Value::List connection_options;
277   for (const auto& option : quic_params->connection_options)
278     connection_options.Append(quic::QuicTagToString(option));
279   dict.Set("connection_options", std::move(connection_options));
280 
281   base::Value::List supported_versions;
282   for (const auto& version : quic_params->supported_versions)
283     supported_versions.Append(ParsedQuicVersionToString(version));
284   dict.Set("supported_versions", std::move(supported_versions));
285 
286   base::Value::List origins_to_force_quic_on;
287   for (const auto& origin : quic_params->origins_to_force_quic_on)
288     origins_to_force_quic_on.Append(origin.ToString());
289   dict.Set("origins_to_force_quic_on", std::move(origins_to_force_quic_on));
290 
291   dict.Set("max_packet_length",
292            static_cast<int>(quic_params->max_packet_length));
293   dict.Set(
294       "max_server_configs_stored_in_properties",
295       static_cast<int>(quic_params->max_server_configs_stored_in_properties));
296   dict.Set("idle_connection_timeout_seconds",
297            static_cast<int>(quic_params->idle_connection_timeout.InSeconds()));
298   dict.Set("reduced_ping_timeout_seconds",
299            static_cast<int>(quic_params->reduced_ping_timeout.InSeconds()));
300   dict.Set("retry_without_alt_svc_on_quic_errors",
301            quic_params->retry_without_alt_svc_on_quic_errors);
302   dict.Set("close_sessions_on_ip_change",
303            quic_params->close_sessions_on_ip_change);
304   dict.Set("goaway_sessions_on_ip_change",
305            quic_params->goaway_sessions_on_ip_change);
306   dict.Set("migrate_sessions_on_network_change_v2",
307            quic_params->migrate_sessions_on_network_change_v2);
308   dict.Set("migrate_sessions_early_v2", quic_params->migrate_sessions_early_v2);
309   dict.Set("retransmittable_on_wire_timeout_milliseconds",
310            static_cast<int>(
311                quic_params->retransmittable_on_wire_timeout.InMilliseconds()));
312   dict.Set("retry_on_alternate_network_before_handshake",
313            quic_params->retry_on_alternate_network_before_handshake);
314   dict.Set("migrate_idle_sessions", quic_params->migrate_idle_sessions);
315   dict.Set(
316       "idle_session_migration_period_seconds",
317       static_cast<int>(quic_params->idle_session_migration_period.InSeconds()));
318   dict.Set("max_time_on_non_default_network_seconds",
319            static_cast<int>(
320                quic_params->max_time_on_non_default_network.InSeconds()));
321   dict.Set("max_num_migrations_to_non_default_network_on_write_error",
322            quic_params->max_migrations_to_non_default_network_on_write_error);
323   dict.Set(
324       "max_num_migrations_to_non_default_network_on_path_degrading",
325       quic_params->max_migrations_to_non_default_network_on_path_degrading);
326   dict.Set("allow_server_migration", quic_params->allow_server_migration);
327   dict.Set("race_stale_dns_on_connection",
328            quic_params->race_stale_dns_on_connection);
329   dict.Set("estimate_initial_rtt", quic_params->estimate_initial_rtt);
330   dict.Set("server_push_cancellation", params_.enable_server_push_cancellation);
331   dict.Set("initial_rtt_for_handshake_milliseconds",
332            static_cast<int>(
333                quic_params->initial_rtt_for_handshake.InMilliseconds()));
334 
335   return base::Value(std::move(dict));
336 }
337 
CloseAllConnections(int net_error,const char * net_log_reason_utf8)338 void HttpNetworkSession::CloseAllConnections(int net_error,
339                                              const char* net_log_reason_utf8) {
340   normal_socket_pool_manager_->FlushSocketPoolsWithError(net_error,
341                                                          net_log_reason_utf8);
342   websocket_socket_pool_manager_->FlushSocketPoolsWithError(
343       net_error, net_log_reason_utf8);
344   spdy_session_pool_.CloseCurrentSessions(static_cast<net::Error>(net_error));
345   quic_stream_factory_.CloseAllSessions(net_error, quic::QUIC_PEER_GOING_AWAY);
346 }
347 
CloseIdleConnections(const char * net_log_reason_utf8)348 void HttpNetworkSession::CloseIdleConnections(const char* net_log_reason_utf8) {
349   normal_socket_pool_manager_->CloseIdleSockets(net_log_reason_utf8);
350   websocket_socket_pool_manager_->CloseIdleSockets(net_log_reason_utf8);
351   spdy_session_pool_.CloseCurrentIdleSessions(net_log_reason_utf8);
352 }
353 
SetServerPushDelegate(std::unique_ptr<ServerPushDelegate> push_delegate)354 void HttpNetworkSession::SetServerPushDelegate(
355     std::unique_ptr<ServerPushDelegate> push_delegate) {
356   DCHECK(push_delegate);
357   if (!params_.enable_server_push_cancellation || push_delegate_)
358     return;
359 
360   push_delegate_ = std::move(push_delegate);
361   spdy_session_pool_.set_server_push_delegate(push_delegate_.get());
362   quic_stream_factory_.set_server_push_delegate(push_delegate_.get());
363 }
364 
IsQuicEnabled() const365 bool HttpNetworkSession::IsQuicEnabled() const {
366   return params_.enable_quic;
367 }
368 
DisableQuic()369 void HttpNetworkSession::DisableQuic() {
370   params_.enable_quic = false;
371 }
372 
ClearSSLSessionCache()373 void HttpNetworkSession::ClearSSLSessionCache() {
374   ssl_client_session_cache_.Flush();
375 }
376 
CreateCommonConnectJobParams(bool for_websockets)377 CommonConnectJobParams HttpNetworkSession::CreateCommonConnectJobParams(
378     bool for_websockets) {
379   // Use null websocket_endpoint_lock_manager, which is only set for WebSockets,
380   // and only when not using a proxy.
381   return CommonConnectJobParams(
382       context_.client_socket_factory, context_.host_resolver, &http_auth_cache_,
383       context_.http_auth_handler_factory, &spdy_session_pool_,
384       &context_.quic_context->params()->supported_versions,
385       &quic_stream_factory_, context_.proxy_delegate,
386       context_.http_user_agent_settings, &ssl_client_context_,
387       context_.socket_performance_watcher_factory,
388       context_.network_quality_estimator, context_.net_log,
389       for_websockets ? &websocket_endpoint_lock_manager_ : nullptr);
390 }
391 
GetSocketPoolManager(SocketPoolType pool_type)392 ClientSocketPoolManager* HttpNetworkSession::GetSocketPoolManager(
393     SocketPoolType pool_type) {
394   switch (pool_type) {
395     case NORMAL_SOCKET_POOL:
396       return normal_socket_pool_manager_.get();
397     case WEBSOCKET_SOCKET_POOL:
398       return websocket_socket_pool_manager_.get();
399     default:
400       NOTREACHED();
401       break;
402   }
403   return nullptr;
404 }
405 
OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level)406 void HttpNetworkSession::OnMemoryPressure(
407     base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
408   DCHECK(!params_.disable_idle_sockets_close_on_memory_pressure);
409 
410   switch (memory_pressure_level) {
411     case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
412       break;
413 
414     case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
415     case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
416       CloseIdleConnections("Low memory");
417       break;
418   }
419 }
420 
421 }  // namespace net
422