xref: /aosp_15_r20/external/cronet/net/quic/quic_session_pool.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/quic/quic_session_pool.h"
6 
7 #include <memory>
8 #include <set>
9 #include <tuple>
10 #include <utility>
11 #include <string_view>
12 
13 #include "base/containers/contains.h"
14 #include "base/feature_list.h"
15 #include "base/functional/bind.h"
16 #include "base/location.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/metrics/field_trial.h"
19 #include "base/metrics/histogram_functions.h"
20 #include "base/metrics/histogram_macros.h"
21 #include "base/no_destructor.h"
22 #include "base/numerics/safe_conversions.h"
23 #include "base/ranges/algorithm.h"
24 #include "base/strings/escape.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_util.h"
27 #include "base/strings/stringprintf.h"
28 #include "base/task/sequenced_task_runner.h"
29 #include "base/task/single_thread_task_runner.h"
30 #include "base/values.h"
31 #include "crypto/openssl_util.h"
32 #include "net/base/address_list.h"
33 #include "net/base/connection_endpoint_metadata.h"
34 #include "net/base/features.h"
35 #include "net/base/http_user_agent_settings.h"
36 #include "net/base/ip_address.h"
37 #include "net/base/net_errors.h"
38 #include "net/base/network_anonymization_key.h"
39 #include "net/base/network_handle.h"
40 #include "net/base/proxy_delegate.h"
41 #include "net/base/session_usage.h"
42 #include "net/base/trace_constants.h"
43 #include "net/base/tracing.h"
44 #include "net/cert/cert_verifier.h"
45 #include "net/dns/host_resolver.h"
46 #include "net/dns/public/secure_dns_policy.h"
47 #include "net/log/net_log.h"
48 #include "net/log/net_log_capture_mode.h"
49 #include "net/log/net_log_event_type.h"
50 #include "net/log/net_log_source_type.h"
51 #include "net/quic/address_utils.h"
52 #include "net/quic/crypto/proof_verifier_chromium.h"
53 #include "net/quic/properties_based_quic_server_info.h"
54 #include "net/quic/quic_chromium_alarm_factory.h"
55 #include "net/quic/quic_chromium_connection_helper.h"
56 #include "net/quic/quic_chromium_packet_reader.h"
57 #include "net/quic/quic_chromium_packet_writer.h"
58 #include "net/quic/quic_context.h"
59 #include "net/quic/quic_crypto_client_stream_factory.h"
60 #include "net/quic/quic_server_info.h"
61 #include "net/quic/quic_session_key.h"
62 #include "net/quic/quic_session_pool_direct_job.h"
63 #include "net/quic/quic_session_pool_job.h"
64 #include "net/quic/quic_session_pool_proxy_job.h"
65 #include "net/socket/client_socket_factory.h"
66 #include "net/socket/next_proto.h"
67 #include "net/socket/socket_performance_watcher.h"
68 #include "net/socket/socket_performance_watcher_factory.h"
69 #include "net/socket/udp_client_socket.h"
70 #include "net/third_party/quiche/src/quiche/quic/core/crypto/null_decrypter.h"
71 #include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_verifier.h"
72 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_random.h"
73 #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h"
74 #include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
75 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
76 #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
77 #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
78 #include "net/traffic_annotation/network_traffic_annotation.h"
79 #include "third_party/boringssl/src/include/openssl/aead.h"
80 #include "url/gurl.h"
81 #include "url/scheme_host_port.h"
82 #include "url/url_constants.h"
83 
84 namespace net {
85 
86 namespace {
87 
88 enum InitialRttEstimateSource {
89   INITIAL_RTT_DEFAULT,
90   INITIAL_RTT_CACHED,
91   INITIAL_RTT_2G,
92   INITIAL_RTT_3G,
93   INITIAL_RTT_SOURCE_MAX,
94 };
95 
QuicPlatformNotificationToString(QuicPlatformNotification notification)96 std::string QuicPlatformNotificationToString(
97     QuicPlatformNotification notification) {
98   switch (notification) {
99     case NETWORK_CONNECTED:
100       return "OnNetworkConnected";
101     case NETWORK_MADE_DEFAULT:
102       return "OnNetworkMadeDefault";
103     case NETWORK_DISCONNECTED:
104       return "OnNetworkDisconnected";
105     case NETWORK_SOON_TO_DISCONNECT:
106       return "OnNetworkSoonToDisconnect";
107     case NETWORK_IP_ADDRESS_CHANGED:
108       return "OnIPAddressChanged";
109     default:
110       QUICHE_NOTREACHED();
111       break;
112   }
113   return "InvalidNotification";
114 }
115 
AllActiveSessionsGoingAwayReasonToString(AllActiveSessionsGoingAwayReason reason)116 const char* AllActiveSessionsGoingAwayReasonToString(
117     AllActiveSessionsGoingAwayReason reason) {
118   switch (reason) {
119     case kClockSkewDetected:
120       return "ClockSkewDetected";
121     case kIPAddressChanged:
122       return "IPAddressChanged";
123     case kCertDBChanged:
124       return "CertDBChanged";
125     case kCertVerifierChanged:
126       return "CertVerifierChanged";
127   }
128 }
129 
HistogramCreateSessionFailure(enum CreateSessionFailure error)130 void HistogramCreateSessionFailure(enum CreateSessionFailure error) {
131   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error,
132                             CREATION_ERROR_MAX);
133 }
134 
SetInitialRttEstimate(base::TimeDelta estimate,enum InitialRttEstimateSource source,quic::QuicConfig * config)135 void SetInitialRttEstimate(base::TimeDelta estimate,
136                            enum InitialRttEstimateSource source,
137                            quic::QuicConfig* config) {
138   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.InitialRttEsitmateSource", source,
139                             INITIAL_RTT_SOURCE_MAX);
140   if (estimate != base::TimeDelta()) {
141     config->SetInitialRoundTripTimeUsToSend(
142         base::checked_cast<uint64_t>(estimate.InMicroseconds()));
143   }
144 }
145 
146 // An implementation of quic::QuicCryptoClientConfig::ServerIdFilter that wraps
147 // an |origin_filter|.
148 class ServerIdOriginFilter
149     : public quic::QuicCryptoClientConfig::ServerIdFilter {
150  public:
ServerIdOriginFilter(const base::RepeatingCallback<bool (const GURL &)> origin_filter)151   explicit ServerIdOriginFilter(
152       const base::RepeatingCallback<bool(const GURL&)> origin_filter)
153       : origin_filter_(origin_filter) {}
154 
Matches(const quic::QuicServerId & server_id) const155   bool Matches(const quic::QuicServerId& server_id) const override {
156     if (origin_filter_.is_null()) {
157       return true;
158     }
159 
160     GURL url(base::StringPrintf("%s%s%s:%d", url::kHttpsScheme,
161                                 url::kStandardSchemeSeparator,
162                                 server_id.host().c_str(), server_id.port()));
163     DCHECK(url.is_valid());
164     return origin_filter_.Run(url);
165   }
166 
167  private:
168   const base::RepeatingCallback<bool(const GURL&)> origin_filter_;
169 };
170 
HostsFromOrigins(std::set<HostPortPair> origins)171 std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) {
172   std::set<std::string> hosts;
173   for (const auto& origin : origins) {
174     hosts.insert(origin.host());
175   }
176   return hosts;
177 }
178 
LogUsingExistingSession(const NetLogWithSource & request_net_log,QuicChromiumClientSession * session,const url::SchemeHostPort & destination,std::string_view reason)179 void LogUsingExistingSession(const NetLogWithSource& request_net_log,
180                              QuicChromiumClientSession* session,
181                              const url::SchemeHostPort& destination,
182                              std::string_view reason) {
183   request_net_log.AddEvent(
184       NetLogEventType::QUIC_SESSION_POOL_USE_EXISTING_SESSION, [&] {
185         base::Value::Dict dict;
186         dict.Set("destination", destination.Serialize());
187         dict.Set("reason", reason);
188         session->net_log().source().AddToEventParameters(dict);
189         return dict;
190       });
191   session->net_log().AddEventReferencingSource(
192       NetLogEventType::
193           QUIC_SESSION_POOL_ATTACH_HTTP_STREAM_JOB_TO_EXISTING_SESSION,
194       request_net_log.source());
195 }
196 
197 }  // namespace
198 
QuicSessionRequest(QuicSessionPool * pool)199 QuicSessionRequest::QuicSessionRequest(QuicSessionPool* pool) : pool_(pool) {}
200 
~QuicSessionRequest()201 QuicSessionRequest::~QuicSessionRequest() {
202   if (pool_ && !callback_.is_null()) {
203     pool_->CancelRequest(this);
204   }
205 }
206 
Request(url::SchemeHostPort destination,quic::ParsedQuicVersion quic_version,const ProxyChain & proxy_chain,const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag,const HttpUserAgentSettings * http_user_agent_settings,SessionUsage session_usage,PrivacyMode privacy_mode,RequestPriority priority,const SocketTag & socket_tag,const NetworkAnonymizationKey & network_anonymization_key,SecureDnsPolicy secure_dns_policy,bool require_dns_https_alpn,int cert_verify_flags,const GURL & url,const NetLogWithSource & net_log,NetErrorDetails * net_error_details,CompletionOnceCallback failed_on_default_network_callback,CompletionOnceCallback callback)207 int QuicSessionRequest::Request(
208     url::SchemeHostPort destination,
209     quic::ParsedQuicVersion quic_version,
210     const ProxyChain& proxy_chain,
211     const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag,
212     const HttpUserAgentSettings* http_user_agent_settings,
213     SessionUsage session_usage,
214     PrivacyMode privacy_mode,
215     RequestPriority priority,
216     const SocketTag& socket_tag,
217     const NetworkAnonymizationKey& network_anonymization_key,
218     SecureDnsPolicy secure_dns_policy,
219     bool require_dns_https_alpn,
220     int cert_verify_flags,
221     const GURL& url,
222     const NetLogWithSource& net_log,
223     NetErrorDetails* net_error_details,
224     CompletionOnceCallback failed_on_default_network_callback,
225     CompletionOnceCallback callback) {
226   DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn);
227   DCHECK(net_error_details);
228   DCHECK(callback_.is_null());
229   DCHECK(host_resolution_callback_.is_null());
230   DCHECK(pool_);
231 
232   net_error_details_ = net_error_details;
233   failed_on_default_network_callback_ =
234       std::move(failed_on_default_network_callback);
235 
236   session_key_ =
237       QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, proxy_chain,
238                      session_usage, socket_tag, network_anonymization_key,
239                      secure_dns_policy, require_dns_https_alpn);
240   bool use_dns_aliases = session_usage == SessionUsage::kProxy ? false : true;
241 
242   int rv = pool_->RequestSession(
243       session_key_, std::move(destination), quic_version,
244       std::move(proxy_annotation_tag), http_user_agent_settings, priority,
245       use_dns_aliases, cert_verify_flags, url, net_log, this);
246   if (rv == ERR_IO_PENDING) {
247     net_log_ = net_log;
248     callback_ = std::move(callback);
249   } else {
250     DCHECK(!expect_on_host_resolution_);
251     pool_ = nullptr;
252   }
253 
254   if (rv == OK) {
255     DCHECK(session_);
256   }
257   return rv;
258 }
259 
WaitForHostResolution(CompletionOnceCallback callback)260 bool QuicSessionRequest::WaitForHostResolution(
261     CompletionOnceCallback callback) {
262   DCHECK(host_resolution_callback_.is_null());
263   if (expect_on_host_resolution_) {
264     host_resolution_callback_ = std::move(callback);
265   }
266   return expect_on_host_resolution_;
267 }
268 
ExpectOnHostResolution()269 void QuicSessionRequest::ExpectOnHostResolution() {
270   expect_on_host_resolution_ = true;
271 }
272 
OnHostResolutionComplete(int rv)273 void QuicSessionRequest::OnHostResolutionComplete(int rv) {
274   DCHECK(expect_on_host_resolution_);
275   expect_on_host_resolution_ = false;
276   if (!host_resolution_callback_.is_null()) {
277     std::move(host_resolution_callback_).Run(rv);
278   }
279 }
280 
WaitForQuicSessionCreation(CompletionOnceCallback callback)281 bool QuicSessionRequest::WaitForQuicSessionCreation(
282     CompletionOnceCallback callback) {
283   DCHECK(create_session_callback_.is_null());
284   if (expect_on_quic_session_creation_) {
285     create_session_callback_ = std::move(callback);
286   }
287   return expect_on_quic_session_creation_;
288 }
289 
ExpectQuicSessionCreation()290 void QuicSessionRequest::ExpectQuicSessionCreation() {
291   expect_on_quic_session_creation_ = true;
292 }
293 
OnQuicSessionCreationComplete(int rv)294 void QuicSessionRequest::OnQuicSessionCreationComplete(int rv) {
295   // DCHECK(expect_on_quic_session_creation_);
296   expect_on_quic_session_creation_ = false;
297   if (!create_session_callback_.is_null()) {
298     std::move(create_session_callback_).Run(rv);
299   }
300 }
301 
OnRequestComplete(int rv)302 void QuicSessionRequest::OnRequestComplete(int rv) {
303   pool_ = nullptr;
304   std::move(callback_).Run(rv);
305 }
306 
OnConnectionFailedOnDefaultNetwork()307 void QuicSessionRequest::OnConnectionFailedOnDefaultNetwork() {
308   if (!failed_on_default_network_callback_.is_null()) {
309     std::move(failed_on_default_network_callback_).Run(OK);
310   }
311 }
312 
GetTimeDelayForWaitingJob() const313 base::TimeDelta QuicSessionRequest::GetTimeDelayForWaitingJob() const {
314   if (!pool_) {
315     return base::TimeDelta();
316   }
317   return pool_->GetTimeDelayForWaitingJob(session_key_);
318 }
319 
SetPriority(RequestPriority priority)320 void QuicSessionRequest::SetPriority(RequestPriority priority) {
321   if (pool_) {
322     pool_->SetRequestPriority(this, priority);
323   }
324 }
325 
326 std::unique_ptr<QuicChromiumClientSession::Handle>
ReleaseSessionHandle()327 QuicSessionRequest::ReleaseSessionHandle() {
328   if (!session_ || !session_->IsConnected()) {
329     return nullptr;
330   }
331 
332   return std::move(session_);
333 }
334 
SetSession(std::unique_ptr<QuicChromiumClientSession::Handle> session)335 void QuicSessionRequest::SetSession(
336     std::unique_ptr<QuicChromiumClientSession::Handle> session) {
337   session_ = std::move(session);
338 }
339 
CanUseExistingSession(const GURL & url,const ProxyChain & proxy_chain,PrivacyMode privacy_mode,SessionUsage session_usage,const SocketTag & socket_tag,const NetworkAnonymizationKey & network_anonymization_key,SecureDnsPolicy secure_dns_policy,bool require_dns_https_alpn,const url::SchemeHostPort & destination) const340 bool QuicSessionRequest::CanUseExistingSession(
341     const GURL& url,
342     const ProxyChain& proxy_chain,
343     PrivacyMode privacy_mode,
344     SessionUsage session_usage,
345     const SocketTag& socket_tag,
346     const NetworkAnonymizationKey& network_anonymization_key,
347     SecureDnsPolicy secure_dns_policy,
348     bool require_dns_https_alpn,
349     const url::SchemeHostPort& destination) const {
350   return pool_->CanUseExistingSession(
351       QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, proxy_chain,
352                      session_usage, socket_tag, network_anonymization_key,
353                      secure_dns_policy, require_dns_https_alpn),
354       destination);
355 }
356 
QuicSessionAliasKey(url::SchemeHostPort destination,QuicSessionKey session_key)357 QuicSessionPool::QuicSessionAliasKey::QuicSessionAliasKey(
358     url::SchemeHostPort destination,
359     QuicSessionKey session_key)
360     : destination_(std::move(destination)),
361       session_key_(std::move(session_key)) {}
362 
operator <(const QuicSessionAliasKey & other) const363 bool QuicSessionPool::QuicSessionAliasKey::operator<(
364     const QuicSessionAliasKey& other) const {
365   return std::tie(destination_, session_key_) <
366          std::tie(other.destination_, other.session_key_);
367 }
368 
operator ==(const QuicSessionAliasKey & other) const369 bool QuicSessionPool::QuicSessionAliasKey::operator==(
370     const QuicSessionAliasKey& other) const {
371   return destination_ == other.destination_ &&
372          session_key_ == other.session_key_;
373 }
374 
QuicCryptoClientConfigOwner(std::unique_ptr<quic::ProofVerifier> proof_verifier,std::unique_ptr<quic::QuicClientSessionCache> session_cache,QuicSessionPool * quic_session_pool)375 QuicSessionPool::QuicCryptoClientConfigOwner::QuicCryptoClientConfigOwner(
376     std::unique_ptr<quic::ProofVerifier> proof_verifier,
377     std::unique_ptr<quic::QuicClientSessionCache> session_cache,
378     QuicSessionPool* quic_session_pool)
379     : config_(std::move(proof_verifier), std::move(session_cache)),
380       clock_(base::DefaultClock::GetInstance()),
381       quic_session_pool_(quic_session_pool) {
382   DCHECK(quic_session_pool_);
383   memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
384       FROM_HERE,
385       base::BindRepeating(&QuicCryptoClientConfigOwner::OnMemoryPressure,
386                           base::Unretained(this)));
387   if (quic_session_pool_->ssl_config_service_->GetSSLContextConfig()
388           .PostQuantumKeyAgreementEnabled()) {
389     config_.set_preferred_groups({SSL_GROUP_X25519_KYBER768_DRAFT00,
390                                   SSL_GROUP_X25519, SSL_GROUP_SECP256R1,
391                                   SSL_GROUP_SECP384R1});
392   }
393 }
~QuicCryptoClientConfigOwner()394 QuicSessionPool::QuicCryptoClientConfigOwner::~QuicCryptoClientConfigOwner() {
395   DCHECK_EQ(num_refs_, 0);
396 }
397 
OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level)398 void QuicSessionPool::QuicCryptoClientConfigOwner::OnMemoryPressure(
399     base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
400   quic::SessionCache* session_cache = config_.session_cache();
401   if (!session_cache) {
402     return;
403   }
404   time_t now = clock_->Now().ToTimeT();
405   uint64_t now_u64 = 0;
406   if (now > 0) {
407     now_u64 = static_cast<uint64_t>(now);
408   }
409   switch (memory_pressure_level) {
410     case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
411       break;
412     case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
413       session_cache->RemoveExpiredEntries(
414           quic::QuicWallTime::FromUNIXSeconds(now_u64));
415       break;
416     case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
417       session_cache->Clear();
418       break;
419   }
420 }
421 
CryptoClientConfigHandle(const QuicCryptoClientConfigMap::iterator & map_iterator)422 QuicSessionPool::CryptoClientConfigHandle::CryptoClientConfigHandle(
423     const QuicCryptoClientConfigMap::iterator& map_iterator)
424     : map_iterator_(map_iterator) {
425   DCHECK_GE(map_iterator_->second->num_refs(), 0);
426   map_iterator->second->AddRef();
427 }
428 
~CryptoClientConfigHandle()429 QuicSessionPool::CryptoClientConfigHandle::~CryptoClientConfigHandle() {
430   DCHECK_GT(map_iterator_->second->num_refs(), 0);
431   map_iterator_->second->ReleaseRef();
432   if (map_iterator_->second->num_refs() == 0) {
433     map_iterator_->second->quic_session_pool()->OnAllCryptoClientRefReleased(
434         map_iterator_);
435   }
436 }
437 
438 quic::QuicCryptoClientConfig*
GetConfig() const439 QuicSessionPool::CryptoClientConfigHandle::GetConfig() const {
440   return map_iterator_->second->config();
441 }
442 
QuicSessionPool(NetLog * net_log,HostResolver * host_resolver,SSLConfigService * ssl_config_service,ClientSocketFactory * client_socket_factory,HttpServerProperties * http_server_properties,CertVerifier * cert_verifier,TransportSecurityState * transport_security_state,ProxyDelegate * proxy_delegate,SCTAuditingDelegate * sct_auditing_delegate,SocketPerformanceWatcherFactory * socket_performance_watcher_factory,QuicCryptoClientStreamFactory * quic_crypto_client_stream_factory,QuicContext * quic_context)443 QuicSessionPool::QuicSessionPool(
444     NetLog* net_log,
445     HostResolver* host_resolver,
446     SSLConfigService* ssl_config_service,
447     ClientSocketFactory* client_socket_factory,
448     HttpServerProperties* http_server_properties,
449     CertVerifier* cert_verifier,
450     TransportSecurityState* transport_security_state,
451     ProxyDelegate* proxy_delegate,
452     SCTAuditingDelegate* sct_auditing_delegate,
453     SocketPerformanceWatcherFactory* socket_performance_watcher_factory,
454     QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
455     QuicContext* quic_context)
456     : net_log_(
457           NetLogWithSource::Make(net_log, NetLogSourceType::QUIC_SESSION_POOL)),
458       host_resolver_(host_resolver),
459       client_socket_factory_(client_socket_factory),
460       http_server_properties_(http_server_properties),
461       cert_verifier_(cert_verifier),
462       transport_security_state_(transport_security_state),
463       proxy_delegate_(proxy_delegate),
464       sct_auditing_delegate_(sct_auditing_delegate),
465       quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
466       random_generator_(quic_context->random_generator()),
467       clock_(quic_context->clock()),
468       // TODO(vasilvv): figure out how to avoid having multiple copies of
469       // QuicParams.
470       params_(*quic_context->params()),
471       clock_skew_detector_(base::TimeTicks::Now(), base::Time::Now()),
472       socket_performance_watcher_factory_(socket_performance_watcher_factory),
473       recent_crypto_config_map_(kMaxRecentCryptoConfigs),
474       config_(InitializeQuicConfig(*quic_context->params())),
475       ping_timeout_(quic::QuicTime::Delta::FromSeconds(quic::kPingTimeoutSecs)),
476       reduced_ping_timeout_(quic::QuicTime::Delta::FromMicroseconds(
477           quic_context->params()->reduced_ping_timeout.InMicroseconds())),
478       retransmittable_on_wire_timeout_(quic::QuicTime::Delta::FromMicroseconds(
479           quic_context->params()
480               ->retransmittable_on_wire_timeout.InMicroseconds())),
481       yield_after_packets_(kQuicYieldAfterPacketsRead),
482       yield_after_duration_(quic::QuicTime::Delta::FromMilliseconds(
483           kQuicYieldAfterDurationMilliseconds)),
484       default_network_(handles::kInvalidNetworkHandle),
485       connectivity_monitor_(default_network_),
486       ssl_config_service_(ssl_config_service),
487       use_network_anonymization_key_for_crypto_configs_(
488           NetworkAnonymizationKey::IsPartitioningEnabled()) {
489   DCHECK(transport_security_state_);
490   DCHECK(http_server_properties_);
491   if (params_.disable_tls_zero_rtt) {
492     SetQuicFlag(quic_disable_client_tls_zero_rtt, true);
493   }
494   InitializeMigrationOptions();
495   cert_verifier_->AddObserver(this);
496   CertDatabase::GetInstance()->AddObserver(this);
497 }
498 
~QuicSessionPool()499 QuicSessionPool::~QuicSessionPool() {
500   UMA_HISTOGRAM_COUNTS_1000("Net.NumQuicSessionsAtShutdown",
501                             all_sessions_.size());
502   CloseAllSessions(ERR_ABORTED, quic::QUIC_CONNECTION_CANCELLED);
503   while (!all_sessions_.empty()) {
504     delete all_sessions_.begin()->first;
505     all_sessions_.erase(all_sessions_.begin());
506   }
507   active_jobs_.clear();
508 
509   DCHECK(dns_aliases_by_session_key_.empty());
510 
511   // This should have been moved to the recent map when all consumers of
512   // QuicCryptoClientConfigs were deleted, in the above lines.
513   DCHECK(active_crypto_config_map_.empty());
514 
515   CertDatabase::GetInstance()->RemoveObserver(this);
516   cert_verifier_->RemoveObserver(this);
517   if (params_.close_sessions_on_ip_change ||
518       params_.goaway_sessions_on_ip_change) {
519     NetworkChangeNotifier::RemoveIPAddressObserver(this);
520   }
521   if (NetworkChangeNotifier::AreNetworkHandlesSupported()) {
522     NetworkChangeNotifier::RemoveNetworkObserver(this);
523   }
524 }
525 
CanUseExistingSession(const QuicSessionKey & session_key,const url::SchemeHostPort & destination) const526 bool QuicSessionPool::CanUseExistingSession(
527     const QuicSessionKey& session_key,
528     const url::SchemeHostPort& destination) const {
529   if (base::Contains(active_sessions_, session_key)) {
530     return true;
531   }
532 
533   for (const auto& key_value : active_sessions_) {
534     QuicChromiumClientSession* session = key_value.second;
535     const auto& it = all_sessions_.find(session);
536     if ((it != all_sessions_.end()) &&
537         (destination == it->second.destination()) &&
538         session->CanPool(session_key.host(), session_key)) {
539       return true;
540     }
541   }
542 
543   return false;
544 }
545 
RequestSession(const QuicSessionKey & session_key,url::SchemeHostPort destination,quic::ParsedQuicVersion quic_version,const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag,const HttpUserAgentSettings * http_user_agent_settings,RequestPriority priority,bool use_dns_aliases,int cert_verify_flags,const GURL & url,const NetLogWithSource & net_log,QuicSessionRequest * request)546 int QuicSessionPool::RequestSession(
547     const QuicSessionKey& session_key,
548     url::SchemeHostPort destination,
549     quic::ParsedQuicVersion quic_version,
550     const std::optional<NetworkTrafficAnnotationTag> proxy_annotation_tag,
551     const HttpUserAgentSettings* http_user_agent_settings,
552     RequestPriority priority,
553     bool use_dns_aliases,
554     int cert_verify_flags,
555     const GURL& url,
556     const NetLogWithSource& net_log,
557     QuicSessionRequest* request) {
558   if (clock_skew_detector_.ClockSkewDetected(base::TimeTicks::Now(),
559                                              base::Time::Now())) {
560     MarkAllActiveSessionsGoingAway(kClockSkewDetected);
561   }
562   DCHECK(HostPortPair(session_key.server_id().host(),
563                       session_key.server_id().port())
564              .Equals(HostPortPair::FromURL(url)));
565 
566   // Use active session for |session_key| if such exists.
567   auto active_session = active_sessions_.find(session_key);
568   if (active_session != active_sessions_.end()) {
569     LogUsingExistingSession(net_log, active_session->second, destination,
570                             "session key match");
571     QuicChromiumClientSession* session = active_session->second;
572     request->SetSession(session->CreateHandle(std::move(destination)));
573     return OK;
574   }
575 
576   // Associate with active job to |session_key| if such exists.
577   auto active_job = active_jobs_.find(session_key);
578   if (active_job != active_jobs_.end()) {
579     active_job->second->AssociateWithNetLogSource(net_log);
580     active_job->second->AddRequest(request);
581     return ERR_IO_PENDING;
582   }
583 
584   // Pool to active session to |destination| if possible.
585   if (!active_sessions_.empty()) {
586     for (const auto& key_value : active_sessions_) {
587       QuicChromiumClientSession* session = key_value.second;
588       if (destination == all_sessions_[session].destination() &&
589           session->CanPool(session_key.server_id().host(), session_key)) {
590         LogUsingExistingSession(
591             net_log, session, destination,
592             "session key doesn't match but an existing session can pool");
593         request->SetSession(session->CreateHandle(std::move(destination)));
594         return OK;
595       }
596     }
597   }
598 
599   // TODO(rtenneti): |task_runner_| is used by the Job. Initialize task_runner_
600   // in the constructor after WebRequestActionWithThreadsTest.* tests are fixed.
601   if (!task_runner_) {
602     task_runner_ = base::SequencedTaskRunner::GetCurrentDefault();
603   }
604 
605   if (!tick_clock_) {
606     tick_clock_ = base::DefaultTickClock::GetInstance();
607   }
608 
609   // If a proxy is in use, then a traffic annotation is required.
610   if (!session_key.proxy_chain().is_direct()) {
611     DCHECK(proxy_annotation_tag);
612   }
613 
614   QuicSessionAliasKey key(destination, session_key);
615   std::unique_ptr<Job> job;
616   if (session_key.proxy_chain().is_direct()) {
617     job = std::make_unique<DirectJob>(
618         this, quic_version, host_resolver_, std::move(key),
619         CreateCryptoConfigHandle(session_key.network_anonymization_key()),
620         params_.retry_on_alternate_network_before_handshake, priority,
621         use_dns_aliases, session_key.require_dns_https_alpn(),
622         cert_verify_flags, net_log);
623   } else {
624     job = std::make_unique<ProxyJob>(
625         this, quic_version, std::move(key), *proxy_annotation_tag,
626         http_user_agent_settings,
627         CreateCryptoConfigHandle(session_key.network_anonymization_key()),
628         priority, cert_verify_flags, net_log);
629   }
630   job->AssociateWithNetLogSource(net_log);
631   int rv = job->Run(base::BindOnce(&QuicSessionPool::OnJobComplete,
632                                    weak_factory_.GetWeakPtr(), job.get()));
633   if (rv == ERR_IO_PENDING) {
634     job->AddRequest(request);
635     active_jobs_[session_key] = std::move(job);
636     return rv;
637   }
638   if (rv == OK) {
639     auto it = active_sessions_.find(session_key);
640     DCHECK(it != active_sessions_.end());
641     if (it == active_sessions_.end()) {
642       return ERR_QUIC_PROTOCOL_ERROR;
643     }
644     QuicChromiumClientSession* session = it->second;
645     request->SetSession(session->CreateHandle(std::move(destination)));
646   }
647   return rv;
648 }
649 
OnSessionGoingAway(QuicChromiumClientSession * session)650 void QuicSessionPool::OnSessionGoingAway(QuicChromiumClientSession* session) {
651   const AliasSet& aliases = session_aliases_[session];
652   for (const auto& alias : aliases) {
653     const QuicSessionKey& session_key = alias.session_key();
654     DCHECK(active_sessions_.count(session_key));
655     DCHECK_EQ(session, active_sessions_[session_key]);
656     // Track sessions which have recently gone away so that we can disable
657     // port suggestions.
658     if (session->goaway_received()) {
659       gone_away_aliases_.insert(alias);
660     }
661 
662     active_sessions_.erase(session_key);
663     ProcessGoingAwaySession(session, session_key.server_id(), true);
664   }
665   ProcessGoingAwaySession(session, all_sessions_[session].server_id(), false);
666   if (!aliases.empty()) {
667     DCHECK(base::Contains(session_peer_ip_, session));
668     const IPEndPoint peer_address = session_peer_ip_[session];
669     ip_aliases_[peer_address].erase(session);
670     if (ip_aliases_[peer_address].empty()) {
671       ip_aliases_.erase(peer_address);
672     }
673     session_peer_ip_.erase(session);
674   }
675   UnmapSessionFromSessionAliases(session);
676 }
677 
OnSessionClosed(QuicChromiumClientSession * session)678 void QuicSessionPool::OnSessionClosed(QuicChromiumClientSession* session) {
679   DCHECK_EQ(0u, session->GetNumActiveStreams());
680   OnSessionGoingAway(session);
681   delete session;
682   all_sessions_.erase(session);
683 }
684 
OnBlackholeAfterHandshakeConfirmed(QuicChromiumClientSession * session)685 void QuicSessionPool::OnBlackholeAfterHandshakeConfirmed(
686     QuicChromiumClientSession* session) {
687   // Reduce PING timeout when connection blackholes after the handshake.
688   if (ping_timeout_ > reduced_ping_timeout_) {
689     ping_timeout_ = reduced_ping_timeout_;
690   }
691 }
692 
CancelRequest(QuicSessionRequest * request)693 void QuicSessionPool::CancelRequest(QuicSessionRequest* request) {
694   auto job_iter = active_jobs_.find(request->session_key());
695   CHECK(job_iter != active_jobs_.end());
696   job_iter->second->RemoveRequest(request);
697 }
698 
SetRequestPriority(QuicSessionRequest * request,RequestPriority priority)699 void QuicSessionPool::SetRequestPriority(QuicSessionRequest* request,
700                                          RequestPriority priority) {
701   auto job_iter = active_jobs_.find(request->session_key());
702   if (job_iter == active_jobs_.end()) {
703     return;
704   }
705   job_iter->second->SetPriority(priority);
706 }
707 
CloseAllSessions(int error,quic::QuicErrorCode quic_error)708 void QuicSessionPool::CloseAllSessions(int error,
709                                        quic::QuicErrorCode quic_error) {
710   net_log_.AddEvent(NetLogEventType::QUIC_SESSION_POOL_CLOSE_ALL_SESSIONS);
711   base::UmaHistogramSparse("Net.QuicSession.CloseAllSessionsError", -error);
712   while (!active_sessions_.empty()) {
713     size_t initial_size = active_sessions_.size();
714     active_sessions_.begin()->second->CloseSessionOnError(
715         error, quic_error,
716         quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
717     DCHECK_NE(initial_size, active_sessions_.size());
718   }
719   while (!all_sessions_.empty()) {
720     size_t initial_size = all_sessions_.size();
721     all_sessions_.begin()->first->CloseSessionOnError(
722         error, quic_error,
723         quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
724     DCHECK_NE(initial_size, all_sessions_.size());
725   }
726   DCHECK(all_sessions_.empty());
727 }
728 
QuicSessionPoolInfoToValue() const729 base::Value QuicSessionPool::QuicSessionPoolInfoToValue() const {
730   base::Value::List list;
731 
732   for (const auto& active_session : active_sessions_) {
733     const quic::QuicServerId& server_id = active_session.first.server_id();
734     QuicChromiumClientSession* session = active_session.second;
735     const AliasSet& aliases = session_aliases_.find(session)->second;
736     // Only add a session to the list once.
737     if (server_id == aliases.begin()->server_id()) {
738       std::set<HostPortPair> hosts;
739       for (const auto& alias : aliases) {
740         hosts.insert(
741             HostPortPair(alias.server_id().host(), alias.server_id().port()));
742       }
743       list.Append(session->GetInfoAsValue(hosts));
744     }
745   }
746   return base::Value(std::move(list));
747 }
748 
ClearCachedStatesInCryptoConfig(const base::RepeatingCallback<bool (const GURL &)> & origin_filter)749 void QuicSessionPool::ClearCachedStatesInCryptoConfig(
750     const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {
751   ServerIdOriginFilter filter(origin_filter);
752   for (const auto& crypto_config : active_crypto_config_map_) {
753     crypto_config.second->config()->ClearCachedStates(filter);
754   }
755 
756   for (const auto& crypto_config : recent_crypto_config_map_) {
757     crypto_config.second->config()->ClearCachedStates(filter);
758   }
759 }
760 
ConnectAndConfigureSocket(CompletionOnceCallback callback,DatagramClientSocket * socket,IPEndPoint addr,handles::NetworkHandle network,const SocketTag & socket_tag)761 int QuicSessionPool::ConnectAndConfigureSocket(CompletionOnceCallback callback,
762                                                DatagramClientSocket* socket,
763                                                IPEndPoint addr,
764                                                handles::NetworkHandle network,
765                                                const SocketTag& socket_tag) {
766   socket->UseNonBlockingIO();
767 
768   int rv;
769   auto split_callback = base::SplitOnceCallback(std::move(callback));
770   CompletionOnceCallback connect_callback =
771       base::BindOnce(&QuicSessionPool::FinishConnectAndConfigureSocket,
772                      weak_factory_.GetWeakPtr(),
773                      std::move(split_callback.first), socket, socket_tag);
774   if (!params_.migrate_sessions_on_network_change_v2) {
775     rv = socket->ConnectAsync(addr, std::move(connect_callback));
776   } else if (network == handles::kInvalidNetworkHandle) {
777     // If caller leaves network unspecified, use current default network.
778     rv = socket->ConnectUsingDefaultNetworkAsync(addr,
779                                                  std::move(connect_callback));
780   } else {
781     rv = socket->ConnectUsingNetworkAsync(network, addr,
782                                           std::move(connect_callback));
783   }
784   // Both callbacks within `split_callback` will always be run asynchronously,
785   // even if a Connect call returns synchronously. Therefore we always return
786   // ERR_IO_PENDING.
787   if (rv != ERR_IO_PENDING) {
788     FinishConnectAndConfigureSocket(std::move(split_callback.second), socket,
789                                     socket_tag, rv);
790   }
791   return ERR_IO_PENDING;
792 }
793 
FinishConnectAndConfigureSocket(CompletionOnceCallback callback,DatagramClientSocket * socket,const SocketTag & socket_tag,int rv)794 void QuicSessionPool::FinishConnectAndConfigureSocket(
795     CompletionOnceCallback callback,
796     DatagramClientSocket* socket,
797     const SocketTag& socket_tag,
798     int rv) {
799   if (rv != OK) {
800     OnFinishConnectAndConfigureSocketError(
801         std::move(callback), CREATION_ERROR_CONNECTING_SOCKET, rv);
802     return;
803   }
804 
805   socket->ApplySocketTag(socket_tag);
806 
807   rv = socket->SetReceiveBufferSize(kQuicSocketReceiveBufferSize);
808   if (rv != OK) {
809     OnFinishConnectAndConfigureSocketError(
810         std::move(callback), CREATION_ERROR_SETTING_RECEIVE_BUFFER, rv);
811     return;
812   }
813 
814   rv = socket->SetDoNotFragment();
815   // SetDoNotFragment is not implemented on all platforms, so ignore errors.
816   if (rv != OK && rv != ERR_NOT_IMPLEMENTED) {
817     OnFinishConnectAndConfigureSocketError(
818         std::move(callback), CREATION_ERROR_SETTING_DO_NOT_FRAGMENT, rv);
819     return;
820   }
821 
822   if (base::FeatureList::IsEnabled(net::features::kReceiveEcn)) {
823     rv = socket->SetRecvTos();
824     if (rv != OK) {
825       OnFinishConnectAndConfigureSocketError(
826           std::move(callback), CREATION_ERROR_SETTING_RECEIVE_ECN, rv);
827       return;
828     }
829   }
830 
831   // Set a buffer large enough to contain the initial CWND's worth of packet
832   // to work around the problem with CHLO packets being sent out with the
833   // wrong encryption level, when the send buffer is full.
834   rv = socket->SetSendBufferSize(quic::kMaxOutgoingPacketSize * 20);
835   if (rv != OK) {
836     OnFinishConnectAndConfigureSocketError(
837         std::move(callback), CREATION_ERROR_SETTING_SEND_BUFFER, rv);
838     return;
839   }
840 
841   if (params_.ios_network_service_type > 0) {
842     socket->SetIOSNetworkServiceType(params_.ios_network_service_type);
843   }
844 
845   socket->GetLocalAddress(&local_address_);
846   if (need_to_check_persisted_supports_quic_) {
847     need_to_check_persisted_supports_quic_ = false;
848     if (http_server_properties_->WasLastLocalAddressWhenQuicWorked(
849             local_address_.address())) {
850       is_quic_known_to_work_on_current_network_ = true;
851       // Clear the persisted IP address, in case the network no longer supports
852       // QUIC so the next restart will require confirmation. It will be
853       // re-persisted when the first job completes successfully.
854       http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
855     }
856   }
857 
858   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
859       FROM_HERE,
860       base::BindOnce(&QuicSessionPool::DoCallback, weak_factory_.GetWeakPtr(),
861                      std::move(callback), rv));
862 }
863 
OnFinishConnectAndConfigureSocketError(CompletionOnceCallback callback,enum CreateSessionFailure error,int rv)864 void QuicSessionPool::OnFinishConnectAndConfigureSocketError(
865     CompletionOnceCallback callback,
866     enum CreateSessionFailure error,
867     int rv) {
868   DCHECK(callback);
869   HistogramCreateSessionFailure(error);
870   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
871       FROM_HERE,
872       base::BindOnce(&QuicSessionPool::DoCallback, weak_factory_.GetWeakPtr(),
873                      std::move(callback), rv));
874 }
875 
DoCallback(CompletionOnceCallback callback,int rv)876 void QuicSessionPool::DoCallback(CompletionOnceCallback callback, int rv) {
877   std::move(callback).Run(rv);
878 }
879 
ConfigureSocket(DatagramClientSocket * socket,IPEndPoint addr,handles::NetworkHandle network,const SocketTag & socket_tag)880 int QuicSessionPool::ConfigureSocket(DatagramClientSocket* socket,
881                                      IPEndPoint addr,
882                                      handles::NetworkHandle network,
883                                      const SocketTag& socket_tag) {
884   socket->UseNonBlockingIO();
885 
886   int rv;
887   if (!params_.migrate_sessions_on_network_change_v2) {
888     rv = socket->Connect(addr);
889   } else if (network == handles::kInvalidNetworkHandle) {
890     // If caller leaves network unspecified, use current default network.
891     rv = socket->ConnectUsingDefaultNetwork(addr);
892   } else {
893     rv = socket->ConnectUsingNetwork(network, addr);
894   }
895   if (rv != OK) {
896     HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET);
897     return rv;
898   }
899 
900   socket->ApplySocketTag(socket_tag);
901 
902   rv = socket->SetReceiveBufferSize(kQuicSocketReceiveBufferSize);
903   if (rv != OK) {
904     HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER);
905     return rv;
906   }
907 
908   rv = socket->SetDoNotFragment();
909   // SetDoNotFragment is not implemented on all platforms, so ignore errors.
910   if (rv != OK && rv != ERR_NOT_IMPLEMENTED) {
911     HistogramCreateSessionFailure(CREATION_ERROR_SETTING_DO_NOT_FRAGMENT);
912     return rv;
913   }
914 
915   if (base::FeatureList::IsEnabled(net::features::kReceiveEcn)) {
916     rv = socket->SetRecvTos();
917     if (rv != OK) {
918       HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_ECN);
919       return rv;
920     }
921   }
922 
923   // Set a buffer large enough to contain the initial CWND's worth of packet
924   // to work around the problem with CHLO packets being sent out with the
925   // wrong encryption level, when the send buffer is full.
926   rv = socket->SetSendBufferSize(quic::kMaxOutgoingPacketSize * 20);
927   if (rv != OK) {
928     HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER);
929     return rv;
930   }
931 
932   if (params_.ios_network_service_type > 0) {
933     socket->SetIOSNetworkServiceType(params_.ios_network_service_type);
934   }
935 
936   socket->GetLocalAddress(&local_address_);
937   if (need_to_check_persisted_supports_quic_) {
938     need_to_check_persisted_supports_quic_ = false;
939     if (http_server_properties_->WasLastLocalAddressWhenQuicWorked(
940             local_address_.address())) {
941       is_quic_known_to_work_on_current_network_ = true;
942       // Clear the persisted IP address, in case the network no longer supports
943       // QUIC so the next restart will require confirmation. It will be
944       // re-persisted when the first job completes successfully.
945       http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
946     }
947   }
948 
949   return OK;
950 }
951 
FindAlternateNetwork(handles::NetworkHandle old_network)952 handles::NetworkHandle QuicSessionPool::FindAlternateNetwork(
953     handles::NetworkHandle old_network) {
954   // Find a new network that sessions bound to |old_network| can be migrated to.
955   NetworkChangeNotifier::NetworkList network_list;
956   NetworkChangeNotifier::GetConnectedNetworks(&network_list);
957   for (handles::NetworkHandle new_network : network_list) {
958     if (new_network != old_network) {
959       return new_network;
960     }
961   }
962   return handles::kInvalidNetworkHandle;
963 }
964 
CreateSocket(NetLog * net_log,const NetLogSource & source)965 std::unique_ptr<DatagramClientSocket> QuicSessionPool::CreateSocket(
966     NetLog* net_log,
967     const NetLogSource& source) {
968   auto socket = client_socket_factory_->CreateDatagramClientSocket(
969       DatagramSocket::DEFAULT_BIND, net_log, source);
970   if (params_.enable_socket_recv_optimization) {
971     socket->EnableRecvOptimization();
972   }
973   return socket;
974 }
975 
OnIPAddressChanged()976 void QuicSessionPool::OnIPAddressChanged() {
977   net_log_.AddEvent(NetLogEventType::QUIC_SESSION_POOL_ON_IP_ADDRESS_CHANGED);
978   CollectDataOnPlatformNotification(NETWORK_IP_ADDRESS_CHANGED,
979                                     handles::kInvalidNetworkHandle);
980   // Do nothing if connection migration is turned on.
981   if (params_.migrate_sessions_on_network_change_v2) {
982     return;
983   }
984 
985   connectivity_monitor_.OnIPAddressChanged();
986 
987   set_is_quic_known_to_work_on_current_network(false);
988   if (params_.close_sessions_on_ip_change) {
989     CloseAllSessions(ERR_NETWORK_CHANGED, quic::QUIC_IP_ADDRESS_CHANGED);
990   } else {
991     DCHECK(params_.goaway_sessions_on_ip_change);
992     MarkAllActiveSessionsGoingAway(kIPAddressChanged);
993   }
994 }
995 
OnNetworkConnected(handles::NetworkHandle network)996 void QuicSessionPool::OnNetworkConnected(handles::NetworkHandle network) {
997   CollectDataOnPlatformNotification(NETWORK_CONNECTED, network);
998   if (params_.migrate_sessions_on_network_change_v2) {
999     net_log_.AddEvent(NetLogEventType::QUIC_SESSION_POOL_PLATFORM_NOTIFICATION,
1000                       [&] {
1001                         base::Value::Dict dict;
1002                         dict.Set("signal", "OnNetworkConnected");
1003                         dict.Set("network", base::NumberToString(network));
1004                         return dict;
1005                       });
1006   }
1007   // Broadcast network connected to all sessions.
1008   // If migration is not turned on, session will not migrate but collect data.
1009   auto it = all_sessions_.begin();
1010   // Sessions may be deleted while iterating through the map.
1011   while (it != all_sessions_.end()) {
1012     QuicChromiumClientSession* session = it->first;
1013     ++it;
1014     session->OnNetworkConnected(network);
1015   }
1016 }
1017 
OnNetworkDisconnected(handles::NetworkHandle network)1018 void QuicSessionPool::OnNetworkDisconnected(handles::NetworkHandle network) {
1019   CollectDataOnPlatformNotification(NETWORK_DISCONNECTED, network);
1020   if (params_.migrate_sessions_on_network_change_v2) {
1021     net_log_.AddEvent(NetLogEventType::QUIC_SESSION_POOL_PLATFORM_NOTIFICATION,
1022                       [&] {
1023                         base::Value::Dict dict;
1024                         dict.Set("signal", "OnNetworkDisconnected");
1025                         dict.Set("network", base::NumberToString(network));
1026                         return dict;
1027                       });
1028   }
1029   // Broadcast network disconnected to all sessions.
1030   // If migration is not turned on, session will not migrate but collect data.
1031   auto it = all_sessions_.begin();
1032   // Sessions may be deleted while iterating through the map.
1033   while (it != all_sessions_.end()) {
1034     QuicChromiumClientSession* session = it->first;
1035     ++it;
1036     session->OnNetworkDisconnectedV2(/*disconnected_network*/ network);
1037   }
1038 }
1039 
1040 // This method is expected to only be called when migrating from Cellular to
1041 // WiFi on Android, and should always be preceded by OnNetworkMadeDefault().
OnNetworkSoonToDisconnect(handles::NetworkHandle network)1042 void QuicSessionPool::OnNetworkSoonToDisconnect(
1043     handles::NetworkHandle network) {
1044   CollectDataOnPlatformNotification(NETWORK_SOON_TO_DISCONNECT, network);
1045 }
1046 
OnNetworkMadeDefault(handles::NetworkHandle network)1047 void QuicSessionPool::OnNetworkMadeDefault(handles::NetworkHandle network) {
1048   CollectDataOnPlatformNotification(NETWORK_MADE_DEFAULT, network);
1049   connectivity_monitor_.OnDefaultNetworkUpdated(network);
1050 
1051   // Clear alternative services that were marked as broken until default network
1052   // changes.
1053   if (params_.retry_on_alternate_network_before_handshake &&
1054       default_network_ != handles::kInvalidNetworkHandle &&
1055       network != default_network_) {
1056     http_server_properties_->OnDefaultNetworkChanged();
1057   }
1058 
1059   DCHECK_NE(handles::kInvalidNetworkHandle, network);
1060   default_network_ = network;
1061 
1062   if (params_.migrate_sessions_on_network_change_v2) {
1063     net_log_.AddEvent(NetLogEventType::QUIC_SESSION_POOL_PLATFORM_NOTIFICATION,
1064                       [&] {
1065                         base::Value::Dict dict;
1066                         dict.Set("signal", "OnNetworkMadeDefault");
1067                         dict.Set("network", base::NumberToString(network));
1068                         return dict;
1069                       });
1070   }
1071 
1072   auto it = all_sessions_.begin();
1073   // Sessions may be deleted while iterating through the map.
1074   while (it != all_sessions_.end()) {
1075     QuicChromiumClientSession* session = it->first;
1076     ++it;
1077     session->OnNetworkMadeDefault(network);
1078   }
1079   if (params_.migrate_sessions_on_network_change_v2) {
1080     set_is_quic_known_to_work_on_current_network(false);
1081   }
1082 }
1083 
OnTrustStoreChanged()1084 void QuicSessionPool::OnTrustStoreChanged() {
1085   // We should flush the sessions if we removed trust from a
1086   // cert, because a previously trusted server may have become
1087   // untrusted.
1088   //
1089   // We should not flush the sessions if we added trust to a cert.
1090   //
1091   // Since the OnTrustStoreChanged method doesn't tell us what
1092   // kind of change it is, we have to flush the socket
1093   // pools to be safe.
1094   MarkAllActiveSessionsGoingAway(kCertDBChanged);
1095 }
1096 
OnCertVerifierChanged()1097 void QuicSessionPool::OnCertVerifierChanged() {
1098   // Flush sessions if the CertCerifier configuration has changed.
1099   MarkAllActiveSessionsGoingAway(kCertVerifierChanged);
1100 }
1101 
set_is_quic_known_to_work_on_current_network(bool is_quic_known_to_work_on_current_network)1102 void QuicSessionPool::set_is_quic_known_to_work_on_current_network(
1103     bool is_quic_known_to_work_on_current_network) {
1104   is_quic_known_to_work_on_current_network_ =
1105       is_quic_known_to_work_on_current_network;
1106   if (!(local_address_ == IPEndPoint())) {
1107     if (is_quic_known_to_work_on_current_network_) {
1108       http_server_properties_->SetLastLocalAddressWhenQuicWorked(
1109           local_address_.address());
1110     } else {
1111       http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
1112     }
1113   }
1114 }
1115 
GetTimeDelayForWaitingJob(const QuicSessionKey & session_key)1116 base::TimeDelta QuicSessionPool::GetTimeDelayForWaitingJob(
1117     const QuicSessionKey& session_key) {
1118   // If |is_quic_known_to_work_on_current_network_| is false, then one of the
1119   // following is true:
1120   // 1) This is startup and QuicSessionPool::CreateSession() and
1121   // ConfigureSocket() have yet to be called, and it is not yet known
1122   // if the current network is the last one where QUIC worked.
1123   // 2) Startup has been completed, and QUIC has not been used
1124   // successfully since startup, or on this network before.
1125   if (!is_quic_known_to_work_on_current_network_) {
1126     // If |need_to_check_persisted_supports_quic_| is false, this is case 1)
1127     // above. If HasLastLocalAddressWhenQuicWorked() is also true, then there's
1128     // a chance the current network is the last one on which QUIC worked. So
1129     // only delay the request if there's no chance that is the case.
1130     if (!need_to_check_persisted_supports_quic_ ||
1131         !http_server_properties_->HasLastLocalAddressWhenQuicWorked()) {
1132       return base::TimeDelta();
1133     }
1134   }
1135 
1136   // QUIC was recently broken. Do not delay the main job.
1137   if (WasQuicRecentlyBroken(session_key)) {
1138     return base::TimeDelta();
1139   }
1140 
1141   int64_t srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(
1142                            session_key.server_id(),
1143                            session_key.network_anonymization_key());
1144   // Picked 300ms based on mean time from
1145   // Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram.
1146   const int kDefaultRTT = 300 * quic::kNumMicrosPerMilli;
1147   if (!srtt) {
1148     srtt = kDefaultRTT;
1149   }
1150   return base::Microseconds(srtt);
1151 }
1152 
GetDnsAliasesForSessionKey(const QuicSessionKey & key) const1153 const std::set<std::string>& QuicSessionPool::GetDnsAliasesForSessionKey(
1154     const QuicSessionKey& key) const {
1155   auto it = dns_aliases_by_session_key_.find(key);
1156 
1157   if (it == dns_aliases_by_session_key_.end()) {
1158     static const base::NoDestructor<std::set<std::string>> emptyvector_result;
1159     return *emptyvector_result;
1160   }
1161 
1162   return it->second;
1163 }
1164 
SelectQuicVersion(const quic::ParsedQuicVersion & known_quic_version,const ConnectionEndpointMetadata & metadata,bool svcb_optional) const1165 quic::ParsedQuicVersion QuicSessionPool::SelectQuicVersion(
1166     const quic::ParsedQuicVersion& known_quic_version,
1167     const ConnectionEndpointMetadata& metadata,
1168     bool svcb_optional) const {
1169   if (metadata.supported_protocol_alpns.empty()) {
1170     // `metadata` doesn't contain QUIC ALPN. If we know the QUIC ALPN to use
1171     // externally, i.e. via Alt-Svc, use it in SVCB-optional mode. Otherwise,
1172     // the endpoint associated with `metadata` is not eligible for QUIC.
1173     return svcb_optional ? known_quic_version
1174                          : quic::ParsedQuicVersion::Unsupported();
1175   }
1176 
1177   // Otherwise, `metadata` came from an HTTPS/SVCB record. We can use
1178   // QUIC if a suitable match is found in the record's ALPN list.
1179   // Additionally, if this connection attempt came from Alt-Svc, the DNS
1180   // result must be consistent with it. See
1181   // https://datatracker.ietf.org/doc/html/rfc9460#name-interaction-with-alt-svc
1182   if (known_quic_version.IsKnown()) {
1183     std::string expected_alpn = quic::AlpnForVersion(known_quic_version);
1184     if (base::Contains(metadata.supported_protocol_alpns,
1185                        quic::AlpnForVersion(known_quic_version))) {
1186       return known_quic_version;
1187     }
1188     return quic::ParsedQuicVersion::Unsupported();
1189   }
1190 
1191   for (const auto& alpn : metadata.supported_protocol_alpns) {
1192     for (const auto& supported_version : supported_versions()) {
1193       if (alpn == AlpnForVersion(supported_version)) {
1194         return supported_version;
1195       }
1196     }
1197   }
1198 
1199   return quic::ParsedQuicVersion::Unsupported();
1200 }
1201 
1202 // static
LogConnectionIpPooling(bool pooled)1203 void QuicSessionPool::LogConnectionIpPooling(bool pooled) {
1204   base::UmaHistogramBoolean("Net.QuicSession.ConnectionIpPooled", pooled);
1205 }
1206 
HasMatchingIpSession(const QuicSessionAliasKey & key,const std::vector<IPEndPoint> & ip_endpoints,const std::set<std::string> & aliases,bool use_dns_aliases)1207 bool QuicSessionPool::HasMatchingIpSession(
1208     const QuicSessionAliasKey& key,
1209     const std::vector<IPEndPoint>& ip_endpoints,
1210     const std::set<std::string>& aliases,
1211     bool use_dns_aliases) {
1212   const quic::QuicServerId& server_id(key.server_id());
1213   DCHECK(!HasActiveSession(key.session_key()));
1214   for (const auto& address : ip_endpoints) {
1215     if (!base::Contains(ip_aliases_, address)) {
1216       continue;
1217     }
1218 
1219     const SessionSet& sessions = ip_aliases_[address];
1220     for (QuicChromiumClientSession* session : sessions) {
1221       if (!session->CanPool(server_id.host(), key.session_key())) {
1222         continue;
1223       }
1224       active_sessions_[key.session_key()] = session;
1225 
1226       std::set<std::string> dns_aliases;
1227       if (use_dns_aliases) {
1228         dns_aliases = aliases;
1229       }
1230 
1231       MapSessionToAliasKey(session, key, std::move(dns_aliases));
1232 
1233       return true;
1234     }
1235   }
1236   return false;
1237 }
1238 
OnJobComplete(Job * job,int rv)1239 void QuicSessionPool::OnJobComplete(Job* job, int rv) {
1240   auto iter = active_jobs_.find(job->key().session_key());
1241   DCHECK(iter != active_jobs_.end());
1242   if (rv == OK) {
1243     if (!is_quic_known_to_work_on_current_network_) {
1244       set_is_quic_known_to_work_on_current_network(true);
1245     }
1246 
1247     auto session_it = active_sessions_.find(job->key().session_key());
1248     CHECK(session_it != active_sessions_.end());
1249     QuicChromiumClientSession* session = session_it->second;
1250     for (QuicSessionRequest* request : iter->second->requests()) {
1251       // Do not notify |request| yet.
1252       request->SetSession(session->CreateHandle(job->key().destination()));
1253     }
1254   }
1255 
1256   for (QuicSessionRequest* request : iter->second->requests()) {
1257     // Even though we're invoking callbacks here, we don't need to worry
1258     // about |this| being deleted, because the pool is owned by the
1259     // profile which can not be deleted via callbacks.
1260     if (rv < 0) {
1261       job->PopulateNetErrorDetails(request->net_error_details());
1262     }
1263     request->OnRequestComplete(rv);
1264   }
1265   active_jobs_.erase(iter);
1266 }
1267 
HasActiveSession(const QuicSessionKey & session_key) const1268 bool QuicSessionPool::HasActiveSession(
1269     const QuicSessionKey& session_key) const {
1270   return base::Contains(active_sessions_, session_key);
1271 }
1272 
HasActiveJob(const QuicSessionKey & session_key) const1273 bool QuicSessionPool::HasActiveJob(const QuicSessionKey& session_key) const {
1274   return base::Contains(active_jobs_, session_key);
1275 }
1276 
CreateSessionSync(const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,IPEndPoint peer_address,ConnectionEndpointMetadata metadata,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,const NetLogWithSource & net_log,raw_ptr<QuicChromiumClientSession> * session,handles::NetworkHandle * network)1277 int QuicSessionPool::CreateSessionSync(
1278     const QuicSessionAliasKey& key,
1279     quic::ParsedQuicVersion quic_version,
1280     int cert_verify_flags,
1281     bool require_confirmation,
1282     IPEndPoint peer_address,
1283     ConnectionEndpointMetadata metadata,
1284     base::TimeTicks dns_resolution_start_time,
1285     base::TimeTicks dns_resolution_end_time,
1286     const NetLogWithSource& net_log,
1287     raw_ptr<QuicChromiumClientSession>* session,
1288     handles::NetworkHandle* network) {
1289   // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
1290   // endpoint.
1291   std::unique_ptr<DatagramClientSocket> socket(
1292       CreateSocket(net_log.net_log(), net_log.source()));
1293 
1294   // If migrate_sessions_on_network_change_v2 is on, passing in
1295   // handles::kInvalidNetworkHandle will bind the socket to the default network.
1296   int rv = ConfigureSocket(socket.get(), peer_address, *network,
1297                            key.session_key().socket_tag());
1298   if (rv != OK) {
1299     return rv;
1300   }
1301   bool closed_during_initialize = CreateSessionHelper(
1302       key, quic_version, cert_verify_flags, require_confirmation,
1303       std::move(peer_address), std::move(metadata), dns_resolution_start_time,
1304       dns_resolution_end_time, /*max_packet_length=*/0, net_log, session,
1305       network, std::move(socket));
1306   if (closed_during_initialize) {
1307     DLOG(DFATAL) << "Session closed during initialize";
1308     *session = nullptr;
1309 
1310     return ERR_CONNECTION_CLOSED;
1311   }
1312 
1313   return OK;
1314 }
1315 
CreateSessionAsync(CompletionOnceCallback callback,const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,IPEndPoint peer_address,ConnectionEndpointMetadata metadata,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,const NetLogWithSource & net_log,raw_ptr<QuicChromiumClientSession> * session,handles::NetworkHandle * network)1316 int QuicSessionPool::CreateSessionAsync(
1317     CompletionOnceCallback callback,
1318     const QuicSessionAliasKey& key,
1319     quic::ParsedQuicVersion quic_version,
1320     int cert_verify_flags,
1321     bool require_confirmation,
1322     IPEndPoint peer_address,
1323     ConnectionEndpointMetadata metadata,
1324     base::TimeTicks dns_resolution_start_time,
1325     base::TimeTicks dns_resolution_end_time,
1326     const NetLogWithSource& net_log,
1327     raw_ptr<QuicChromiumClientSession>* session,
1328     handles::NetworkHandle* network) {
1329   // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
1330   // endpoint.
1331   std::unique_ptr<DatagramClientSocket> socket(
1332       CreateSocket(net_log.net_log(), net_log.source()));
1333   DatagramClientSocket* socket_ptr = socket.get();
1334   CompletionOnceCallback connect_and_configure_callback = base::BindOnce(
1335       &QuicSessionPool::FinishCreateSession, weak_factory_.GetWeakPtr(),
1336       std::move(callback), key, quic_version, cert_verify_flags,
1337       require_confirmation, peer_address, std::move(metadata),
1338       dns_resolution_start_time, dns_resolution_end_time,
1339       /*max_packet_length=*/0, net_log, session, network, std::move(socket));
1340 
1341   // If migrate_sessions_on_network_change_v2 is on, passing in
1342   // handles::kInvalidNetworkHandle will bind the socket to the default network.
1343   return ConnectAndConfigureSocket(std::move(connect_and_configure_callback),
1344                                    socket_ptr, std::move(peer_address),
1345                                    *network, key.session_key().socket_tag());
1346 }
1347 
CreateSessionOnProxyStream(CompletionOnceCallback callback,const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,IPEndPoint local_address,IPEndPoint proxy_peer_address,std::unique_ptr<QuicChromiumClientStream::Handle> proxy_stream,std::string user_agent,const NetLogWithSource & net_log,raw_ptr<QuicChromiumClientSession> * session)1348 int QuicSessionPool::CreateSessionOnProxyStream(
1349     CompletionOnceCallback callback,
1350     const QuicSessionAliasKey& key,
1351     quic::ParsedQuicVersion quic_version,
1352     int cert_verify_flags,
1353     bool require_confirmation,
1354     IPEndPoint local_address,
1355     IPEndPoint proxy_peer_address,
1356     std::unique_ptr<QuicChromiumClientStream::Handle> proxy_stream,
1357     std::string user_agent,
1358     const NetLogWithSource& net_log,
1359     raw_ptr<QuicChromiumClientSession>* session) {
1360   // Use the host and port from the proxy server along with the example URI
1361   // template in https://datatracker.ietf.org/doc/html/rfc9298#section-2.
1362   const ProxyChain& proxy_chain = key.session_key().proxy_chain();
1363   const ProxyServer& last_proxy = proxy_chain.Last();
1364   const quic::QuicServerId& server_id = key.server_id();
1365   const std::string encocded_host =
1366       base::EscapeQueryParamValue(last_proxy.GetHost().c_str(), false);
1367   GURL url(base::StringPrintf("https://%s:%d/.well-known/masque/udp/%s/%d/",
1368                               last_proxy.GetHost().c_str(),
1369                               last_proxy.GetPort(), server_id.host().c_str(),
1370                               server_id.port()));
1371 
1372   auto socket = std::make_unique<QuicProxyDatagramClientSocket>(
1373       url, key.session_key().proxy_chain(), user_agent, net_log,
1374       proxy_delegate_);
1375   QuicProxyDatagramClientSocket* socket_ptr = socket.get();
1376 
1377   socket->ApplySocketTag(key.session_key().socket_tag());
1378 
1379   // No host resolution took place, so pass an empty metadata,
1380   // pretend resolution started and ended right now, and pass an
1381   // invalid network handle.
1382   ConnectionEndpointMetadata metadata;
1383   auto dns_resolution_time = base::TimeTicks::Now();
1384   auto network = handles::kInvalidNetworkHandle;
1385 
1386   // Maximum packet length for the session inside this stream is limited
1387   // by the largest message payload allowed, accounting for the quarter-stream
1388   // ID (up to 8 bytes) and the context ID (1 byte). If we cannot determine the
1389   // max payload size for the stream, or there is no room for the overhead, use
1390   // 0 as a sentinel value to use the default packet size.
1391   quic::QuicPacketLength quarter_stream_id_length =
1392       quiche::QuicheDataWriter::GetVarInt62Len(proxy_stream->id() / 4);
1393   constexpr quic::QuicPacketLength context_id_length = 1;
1394   quic::QuicPacketLength guaranteed_largest_message_payload =
1395       proxy_stream->GetGuaranteedLargestMessagePayload();
1396   quic::QuicPacketLength overhead =
1397       quarter_stream_id_length + context_id_length;
1398   quic::QuicPacketLength max_packet_length =
1399       guaranteed_largest_message_payload > overhead
1400           ? guaranteed_largest_message_payload - overhead
1401           : 0;
1402 
1403   CompletionOnceCallback on_connected_via_stream = base::BindOnce(
1404       &QuicSessionPool::FinishCreateSession, weak_factory_.GetWeakPtr(),
1405       std::move(callback), key, quic_version, cert_verify_flags,
1406       require_confirmation, proxy_peer_address, std::move(metadata),
1407       dns_resolution_time, dns_resolution_time, max_packet_length, net_log,
1408       session, &network, std::move(socket));
1409 
1410   return socket_ptr->ConnectViaStream(
1411       std::move(local_address), std::move(proxy_peer_address),
1412       std::move(proxy_stream), std::move(on_connected_via_stream));
1413 }
1414 
FinishCreateSession(CompletionOnceCallback callback,const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,IPEndPoint peer_address,ConnectionEndpointMetadata metadata,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,quic::QuicPacketLength max_packet_length,const NetLogWithSource & net_log,raw_ptr<QuicChromiumClientSession> * session,handles::NetworkHandle * network,std::unique_ptr<DatagramClientSocket> socket,int rv)1415 void QuicSessionPool::FinishCreateSession(
1416     CompletionOnceCallback callback,
1417     const QuicSessionAliasKey& key,
1418     quic::ParsedQuicVersion quic_version,
1419     int cert_verify_flags,
1420     bool require_confirmation,
1421     IPEndPoint peer_address,
1422     ConnectionEndpointMetadata metadata,
1423     base::TimeTicks dns_resolution_start_time,
1424     base::TimeTicks dns_resolution_end_time,
1425     quic::QuicPacketLength max_packet_length,
1426     const NetLogWithSource& net_log,
1427     raw_ptr<QuicChromiumClientSession>* session,
1428     handles::NetworkHandle* network,
1429     std::unique_ptr<DatagramClientSocket> socket,
1430     int rv) {
1431   if (rv != OK) {
1432     std::move(callback).Run(rv);
1433     return;
1434   }
1435   bool closed_during_initialize = CreateSessionHelper(
1436       key, quic_version, cert_verify_flags, require_confirmation,
1437       std::move(peer_address), std::move(metadata), dns_resolution_start_time,
1438       dns_resolution_end_time, max_packet_length, net_log, session, network,
1439       std::move(socket));
1440   if (closed_during_initialize) {
1441     DLOG(DFATAL) << "Session closed during initialize";
1442     *session = nullptr;
1443 
1444     std::move(callback).Run(ERR_CONNECTION_CLOSED);
1445     return;
1446   }
1447 
1448   std::move(callback).Run(OK);
1449 }
1450 
CreateSessionHelper(const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,IPEndPoint peer_address,ConnectionEndpointMetadata metadata,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,quic::QuicPacketLength max_packet_length,const NetLogWithSource & net_log,raw_ptr<QuicChromiumClientSession> * session,handles::NetworkHandle * network,std::unique_ptr<DatagramClientSocket> socket)1451 bool QuicSessionPool::CreateSessionHelper(
1452     const QuicSessionAliasKey& key,
1453     quic::ParsedQuicVersion quic_version,
1454     int cert_verify_flags,
1455     bool require_confirmation,
1456     IPEndPoint peer_address,
1457     ConnectionEndpointMetadata metadata,
1458     base::TimeTicks dns_resolution_start_time,
1459     base::TimeTicks dns_resolution_end_time,
1460     quic::QuicPacketLength max_packet_length,
1461     const NetLogWithSource& net_log,
1462     raw_ptr<QuicChromiumClientSession>* session,
1463     handles::NetworkHandle* network,
1464     std::unique_ptr<DatagramClientSocket> socket) {
1465   const quic::QuicServerId& server_id = key.server_id();
1466 
1467   if (params_.migrate_sessions_on_network_change_v2 &&
1468       *network == handles::kInvalidNetworkHandle) {
1469     *network = socket->GetBoundNetwork();
1470     if (default_network_ == handles::kInvalidNetworkHandle) {
1471       // QuicSessionPool may miss the default network signal before its
1472       // creation, update |default_network_| when the first socket is bound
1473       // to the default network.
1474       default_network_ = *network;
1475       connectivity_monitor_.SetInitialDefaultNetwork(default_network_);
1476     } else {
1477       UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.DefaultNetworkMatch",
1478                             default_network_ == *network);
1479     }
1480   }
1481 
1482   if (!helper_.get()) {
1483     helper_ = std::make_unique<QuicChromiumConnectionHelper>(clock_,
1484                                                              random_generator_);
1485   }
1486 
1487   if (!alarm_factory_.get()) {
1488     alarm_factory_ = std::make_unique<QuicChromiumAlarmFactory>(
1489         base::SingleThreadTaskRunner::GetCurrentDefault().get(), clock_);
1490   }
1491 
1492   quic::QuicConnectionId connection_id =
1493       quic::QuicUtils::CreateRandomConnectionId(random_generator_);
1494   std::unique_ptr<QuicServerInfo> server_info;
1495   if (params_.max_server_configs_stored_in_properties > 0) {
1496     server_info = std::make_unique<PropertiesBasedQuicServerInfo>(
1497         server_id, key.session_key().network_anonymization_key(),
1498         http_server_properties_);
1499   }
1500   std::unique_ptr<CryptoClientConfigHandle> crypto_config_handle =
1501       CreateCryptoConfigHandle(key.session_key().network_anonymization_key());
1502   InitializeCachedStateInCryptoConfig(*crypto_config_handle, server_id,
1503                                       server_info);
1504 
1505   QuicChromiumPacketWriter* writer =
1506       new QuicChromiumPacketWriter(socket.get(), task_runner_.get());
1507   quic::QuicConnection* connection = new quic::QuicConnection(
1508       connection_id, quic::QuicSocketAddress(),
1509       ToQuicSocketAddress(peer_address), helper_.get(), alarm_factory_.get(),
1510       writer, true /* owns_writer */, quic::Perspective::IS_CLIENT,
1511       {quic_version}, connection_id_generator_);
1512   connection->set_keep_alive_ping_timeout(ping_timeout_);
1513   if (max_packet_length > 0) {
1514     connection->SetMaxPacketLength(std::min(
1515         static_cast<size_t>(max_packet_length), params_.max_packet_length));
1516   } else {
1517     connection->SetMaxPacketLength(params_.max_packet_length);
1518   }
1519 
1520   quic::QuicConfig config = config_;
1521   ConfigureInitialRttEstimate(
1522       server_id, key.session_key().network_anonymization_key(), &config);
1523 
1524   // Use the factory to create a new socket performance watcher, and pass the
1525   // ownership to QuicChromiumClientSession.
1526   std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher;
1527   if (socket_performance_watcher_factory_) {
1528     socket_performance_watcher =
1529         socket_performance_watcher_factory_->CreateSocketPerformanceWatcher(
1530             SocketPerformanceWatcherFactory::PROTOCOL_QUIC,
1531             peer_address.address());
1532   }
1533 
1534   // Wait for handshake confirmation before allowing streams to be created if
1535   // either this session or the pool require confirmation.
1536   if (!is_quic_known_to_work_on_current_network_) {
1537     require_confirmation = true;
1538   }
1539 
1540   *session = new QuicChromiumClientSession(
1541       connection, std::move(socket), this, quic_crypto_client_stream_factory_,
1542       clock_, transport_security_state_, ssl_config_service_,
1543       std::move(server_info), key.session_key(), require_confirmation,
1544       params_.migrate_sessions_early_v2,
1545       params_.migrate_sessions_on_network_change_v2, default_network_,
1546       retransmittable_on_wire_timeout_, params_.migrate_idle_sessions,
1547       params_.allow_port_migration, params_.idle_session_migration_period,
1548       params_.multi_port_probing_interval,
1549       params_.max_time_on_non_default_network,
1550       params_.max_migrations_to_non_default_network_on_write_error,
1551       params_.max_migrations_to_non_default_network_on_path_degrading,
1552       yield_after_packets_, yield_after_duration_, cert_verify_flags, config,
1553       std::move(crypto_config_handle),
1554       network_connection_.connection_description(), dns_resolution_start_time,
1555       dns_resolution_end_time, tick_clock_, task_runner_.get(),
1556       std::move(socket_performance_watcher), metadata, net_log);
1557 
1558   all_sessions_[*session] = key;  // owning pointer
1559   writer->set_delegate(*session);
1560   (*session)->AddConnectivityObserver(&connectivity_monitor_);
1561 
1562   net_log.AddEventReferencingSource(
1563       NetLogEventType::QUIC_SESSION_POOL_JOB_RESULT,
1564       (*session)->net_log().source());
1565 
1566   (*session)->Initialize();
1567   bool closed_during_initialize = !base::Contains(all_sessions_, *session) ||
1568                                   !(*session)->connection()->connected();
1569   UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession",
1570                         closed_during_initialize);
1571   return closed_during_initialize;
1572 }
1573 
ActivateSession(const QuicSessionAliasKey & key,QuicChromiumClientSession * session,std::set<std::string> dns_aliases)1574 void QuicSessionPool::ActivateSession(const QuicSessionAliasKey& key,
1575                                       QuicChromiumClientSession* session,
1576                                       std::set<std::string> dns_aliases) {
1577   DCHECK(!HasActiveSession(key.session_key()));
1578   UMA_HISTOGRAM_COUNTS_1M("Net.QuicActiveSessions", active_sessions_.size());
1579   active_sessions_[key.session_key()] = session;
1580   MapSessionToAliasKey(session, key, std::move(dns_aliases));
1581   const IPEndPoint peer_address =
1582       ToIPEndPoint(session->connection()->peer_address());
1583   DCHECK(!base::Contains(ip_aliases_[peer_address], session));
1584   ip_aliases_[peer_address].insert(session);
1585   DCHECK(!base::Contains(session_peer_ip_, session));
1586   session_peer_ip_[session] = peer_address;
1587 }
1588 
MarkAllActiveSessionsGoingAway(AllActiveSessionsGoingAwayReason reason)1589 void QuicSessionPool::MarkAllActiveSessionsGoingAway(
1590     AllActiveSessionsGoingAwayReason reason) {
1591   net_log_.AddEvent(
1592       NetLogEventType::QUIC_SESSION_POOL_MARK_ALL_ACTIVE_SESSIONS_GOING_AWAY);
1593   base::UmaHistogramCounts10000(
1594       std::string("Net.QuicActiveSessionCount.") +
1595           AllActiveSessionsGoingAwayReasonToString(reason),
1596       active_sessions_.size());
1597   while (!active_sessions_.empty()) {
1598     QuicChromiumClientSession* session = active_sessions_.begin()->second;
1599     // If IP address change is detected, disable session's connectivity
1600     // monitoring by remove the Delegate.
1601     if (reason == kIPAddressChanged) {
1602       connectivity_monitor_.OnSessionGoingAwayOnIPAddressChange(session);
1603     }
1604     OnSessionGoingAway(session);
1605   }
1606 }
1607 
ConfigureInitialRttEstimate(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key,quic::QuicConfig * config)1608 void QuicSessionPool::ConfigureInitialRttEstimate(
1609     const quic::QuicServerId& server_id,
1610     const NetworkAnonymizationKey& network_anonymization_key,
1611     quic::QuicConfig* config) {
1612   const base::TimeDelta* srtt =
1613       GetServerNetworkStatsSmoothedRtt(server_id, network_anonymization_key);
1614   // Sometimes *srtt is negative. See https://crbug.com/1225616.
1615   // TODO(ricea): When the root cause of the negative value is fixed, change the
1616   // non-negative assertion to a DCHECK.
1617   if (srtt && srtt->is_positive()) {
1618     SetInitialRttEstimate(*srtt, INITIAL_RTT_CACHED, config);
1619     return;
1620   }
1621 
1622   NetworkChangeNotifier::ConnectionType type =
1623       network_connection_.connection_type();
1624   if (type == NetworkChangeNotifier::CONNECTION_2G) {
1625     SetInitialRttEstimate(base::Milliseconds(1200), INITIAL_RTT_CACHED, config);
1626     return;
1627   }
1628 
1629   if (type == NetworkChangeNotifier::CONNECTION_3G) {
1630     SetInitialRttEstimate(base::Milliseconds(400), INITIAL_RTT_CACHED, config);
1631     return;
1632   }
1633 
1634   if (params_.initial_rtt_for_handshake.is_positive()) {
1635     SetInitialRttEstimate(
1636         base::Microseconds(params_.initial_rtt_for_handshake.InMicroseconds()),
1637         INITIAL_RTT_DEFAULT, config);
1638     return;
1639   }
1640 
1641   SetInitialRttEstimate(base::TimeDelta(), INITIAL_RTT_DEFAULT, config);
1642 }
1643 
GetServerNetworkStatsSmoothedRttInMicroseconds(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key) const1644 int64_t QuicSessionPool::GetServerNetworkStatsSmoothedRttInMicroseconds(
1645     const quic::QuicServerId& server_id,
1646     const NetworkAnonymizationKey& network_anonymization_key) const {
1647   const base::TimeDelta* srtt =
1648       GetServerNetworkStatsSmoothedRtt(server_id, network_anonymization_key);
1649   return srtt == nullptr ? 0 : srtt->InMicroseconds();
1650 }
1651 
GetServerNetworkStatsSmoothedRtt(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key) const1652 const base::TimeDelta* QuicSessionPool::GetServerNetworkStatsSmoothedRtt(
1653     const quic::QuicServerId& server_id,
1654     const NetworkAnonymizationKey& network_anonymization_key) const {
1655   url::SchemeHostPort server("https", server_id.host(), server_id.port());
1656   const ServerNetworkStats* stats =
1657       http_server_properties_->GetServerNetworkStats(server,
1658                                                      network_anonymization_key);
1659   if (stats == nullptr) {
1660     return nullptr;
1661   }
1662   return &(stats->srtt);
1663 }
1664 
WasQuicRecentlyBroken(const QuicSessionKey & session_key) const1665 bool QuicSessionPool::WasQuicRecentlyBroken(
1666     const QuicSessionKey& session_key) const {
1667   const AlternativeService alternative_service(
1668       kProtoQUIC, HostPortPair(session_key.server_id().host(),
1669                                session_key.server_id().port()));
1670   return http_server_properties_->WasAlternativeServiceRecentlyBroken(
1671       alternative_service, session_key.network_anonymization_key());
1672 }
1673 
InitializeMigrationOptions()1674 void QuicSessionPool::InitializeMigrationOptions() {
1675   // The following list of options cannot be set immediately until
1676   // prerequisites are met. Cache the initial setting in local variables and
1677   // reset them in |params_|.
1678   bool migrate_sessions_on_network_change =
1679       params_.migrate_sessions_on_network_change_v2;
1680   bool migrate_sessions_early = params_.migrate_sessions_early_v2;
1681   bool retry_on_alternate_network_before_handshake =
1682       params_.retry_on_alternate_network_before_handshake;
1683   bool migrate_idle_sessions = params_.migrate_idle_sessions;
1684   bool allow_port_migration = params_.allow_port_migration;
1685   params_.migrate_sessions_on_network_change_v2 = false;
1686   params_.migrate_sessions_early_v2 = false;
1687   params_.allow_port_migration = false;
1688   params_.retry_on_alternate_network_before_handshake = false;
1689   params_.migrate_idle_sessions = false;
1690 
1691   // TODO(zhongyi): deprecate |goaway_sessions_on_ip_change| if the experiment
1692   // is no longer needed.
1693   // goaway_sessions_on_ip_change and close_sessions_on_ip_change should never
1694   // be simultaneously set to true.
1695   DCHECK(!(params_.close_sessions_on_ip_change &&
1696            params_.goaway_sessions_on_ip_change));
1697 
1698   bool handle_ip_change = params_.close_sessions_on_ip_change ||
1699                           params_.goaway_sessions_on_ip_change;
1700   // If IP address changes are handled explicitly, connection migration should
1701   // not be set.
1702   DCHECK(!(handle_ip_change && migrate_sessions_on_network_change));
1703 
1704   if (handle_ip_change) {
1705     NetworkChangeNotifier::AddIPAddressObserver(this);
1706   }
1707 
1708   if (allow_port_migration) {
1709     params_.allow_port_migration = true;
1710     if (migrate_idle_sessions) {
1711       params_.migrate_idle_sessions = true;
1712     }
1713   }
1714 
1715   if (!NetworkChangeNotifier::AreNetworkHandlesSupported()) {
1716     return;
1717   }
1718 
1719   NetworkChangeNotifier::AddNetworkObserver(this);
1720   // Perform checks on the connection migration options.
1721   if (!migrate_sessions_on_network_change) {
1722     DCHECK(!migrate_sessions_early);
1723     return;
1724   }
1725 
1726   // Enable migration on platform notifications.
1727   params_.migrate_sessions_on_network_change_v2 = true;
1728 
1729   if (!migrate_sessions_early) {
1730     DCHECK(!retry_on_alternate_network_before_handshake);
1731     return;
1732   }
1733 
1734   // Enable migration on path degrading.
1735   params_.migrate_sessions_early_v2 = true;
1736   // Set retransmittable on wire timeout for migration on path degrading if no
1737   // value is specified.
1738   if (retransmittable_on_wire_timeout_.IsZero()) {
1739     retransmittable_on_wire_timeout_ = quic::QuicTime::Delta::FromMicroseconds(
1740         kDefaultRetransmittableOnWireTimeout.InMicroseconds());
1741   }
1742 
1743   // Enable retry on alternate network before handshake.
1744   if (retry_on_alternate_network_before_handshake) {
1745     params_.retry_on_alternate_network_before_handshake = true;
1746   }
1747 
1748   // Enable migration for idle sessions.
1749   if (migrate_idle_sessions) {
1750     params_.migrate_idle_sessions = true;
1751   }
1752 }
1753 
InitializeCachedStateInCryptoConfig(const CryptoClientConfigHandle & crypto_config_handle,const quic::QuicServerId & server_id,const std::unique_ptr<QuicServerInfo> & server_info)1754 void QuicSessionPool::InitializeCachedStateInCryptoConfig(
1755     const CryptoClientConfigHandle& crypto_config_handle,
1756     const quic::QuicServerId& server_id,
1757     const std::unique_ptr<QuicServerInfo>& server_info) {
1758   quic::QuicCryptoClientConfig::CachedState* cached =
1759       crypto_config_handle.GetConfig()->LookupOrCreate(server_id);
1760 
1761   if (!cached->IsEmpty()) {
1762     return;
1763   }
1764 
1765   if (!server_info || !server_info->Load()) {
1766     return;
1767   }
1768 
1769   cached->Initialize(server_info->state().server_config,
1770                      server_info->state().source_address_token,
1771                      server_info->state().certs, server_info->state().cert_sct,
1772                      server_info->state().chlo_hash,
1773                      server_info->state().server_config_sig, clock_->WallNow(),
1774                      quic::QuicWallTime::Zero());
1775 }
1776 
ProcessGoingAwaySession(QuicChromiumClientSession * session,const quic::QuicServerId & server_id,bool session_was_active)1777 void QuicSessionPool::ProcessGoingAwaySession(
1778     QuicChromiumClientSession* session,
1779     const quic::QuicServerId& server_id,
1780     bool session_was_active) {
1781   if (!http_server_properties_) {
1782     return;
1783   }
1784 
1785   const quic::QuicConnectionStats& stats = session->connection()->GetStats();
1786   const AlternativeService alternative_service(
1787       kProtoQUIC, HostPortPair(server_id.host(), server_id.port()));
1788 
1789   url::SchemeHostPort server("https", server_id.host(), server_id.port());
1790   // Do nothing if QUIC is currently marked as broken.
1791   if (http_server_properties_->IsAlternativeServiceBroken(
1792           alternative_service,
1793           session->quic_session_key().network_anonymization_key())) {
1794     return;
1795   }
1796 
1797   if (session->OneRttKeysAvailable()) {
1798     http_server_properties_->ConfirmAlternativeService(
1799         alternative_service,
1800         session->quic_session_key().network_anonymization_key());
1801     ServerNetworkStats network_stats;
1802     network_stats.srtt = base::Microseconds(stats.srtt_us);
1803     network_stats.bandwidth_estimate = stats.estimated_bandwidth;
1804     http_server_properties_->SetServerNetworkStats(
1805         server, session->quic_session_key().network_anonymization_key(),
1806         network_stats);
1807     return;
1808   }
1809 
1810   http_server_properties_->ClearServerNetworkStats(
1811       server, session->quic_session_key().network_anonymization_key());
1812 
1813   UMA_HISTOGRAM_COUNTS_1M("Net.QuicHandshakeNotConfirmedNumPacketsReceived",
1814                           stats.packets_received);
1815 
1816   if (!session_was_active) {
1817     return;
1818   }
1819 
1820   // TODO(rch):  In the special case where the session has received no packets
1821   // from the peer, we should consider blocking this differently so that we
1822   // still race TCP but we don't consider the session connected until the
1823   // handshake has been confirmed.
1824   HistogramBrokenAlternateProtocolLocation(
1825       BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_SESSION_POOL);
1826 
1827   // Since the session was active, there's no longer an HttpStreamFactory::Job
1828   // running which can mark it broken, unless the TCP job also fails. So to
1829   // avoid not using QUIC when we otherwise could, we mark it as recently
1830   // broken, which means that 0-RTT will be disabled but we'll still race.
1831   http_server_properties_->MarkAlternativeServiceRecentlyBroken(
1832       alternative_service,
1833       session->quic_session_key().network_anonymization_key());
1834 }
1835 
MapSessionToAliasKey(QuicChromiumClientSession * session,const QuicSessionAliasKey & key,std::set<std::string> dns_aliases)1836 void QuicSessionPool::MapSessionToAliasKey(QuicChromiumClientSession* session,
1837                                            const QuicSessionAliasKey& key,
1838                                            std::set<std::string> dns_aliases) {
1839   session_aliases_[session].insert(key);
1840   dns_aliases_by_session_key_[key.session_key()] = std::move(dns_aliases);
1841 }
1842 
UnmapSessionFromSessionAliases(QuicChromiumClientSession * session)1843 void QuicSessionPool::UnmapSessionFromSessionAliases(
1844     QuicChromiumClientSession* session) {
1845   for (const auto& key : session_aliases_[session]) {
1846     dns_aliases_by_session_key_.erase(key.session_key());
1847   }
1848   session_aliases_.erase(session);
1849 }
1850 
1851 std::unique_ptr<QuicSessionPool::CryptoClientConfigHandle>
CreateCryptoConfigHandle(const NetworkAnonymizationKey & network_anonymization_key)1852 QuicSessionPool::CreateCryptoConfigHandle(
1853     const NetworkAnonymizationKey& network_anonymization_key) {
1854   NetworkAnonymizationKey actual_network_anonymization_key =
1855       use_network_anonymization_key_for_crypto_configs_
1856           ? network_anonymization_key
1857           : NetworkAnonymizationKey();
1858 
1859   // If there's a matching entry in |active_crypto_config_map_|, create a
1860   // CryptoClientConfigHandle for it.
1861   auto map_iterator =
1862       active_crypto_config_map_.find(actual_network_anonymization_key);
1863   if (map_iterator != active_crypto_config_map_.end()) {
1864     DCHECK_GT(map_iterator->second->num_refs(), 0);
1865 
1866     // If there's an active matching crypto config, there shouldn't also be an
1867     // inactive matching crypto config.
1868     DCHECK(recent_crypto_config_map_.Peek(actual_network_anonymization_key) ==
1869            recent_crypto_config_map_.end());
1870 
1871     return std::make_unique<CryptoClientConfigHandle>(map_iterator);
1872   }
1873 
1874   // If there's a matching entry in |recent_crypto_config_map_|, move it to
1875   // |active_crypto_config_map_| and create a CryptoClientConfigHandle for it.
1876   auto mru_iterator =
1877       recent_crypto_config_map_.Peek(actual_network_anonymization_key);
1878   if (mru_iterator != recent_crypto_config_map_.end()) {
1879     DCHECK_EQ(mru_iterator->second->num_refs(), 0);
1880 
1881     map_iterator = active_crypto_config_map_
1882                        .emplace(actual_network_anonymization_key,
1883                                 std::move(mru_iterator->second))
1884                        .first;
1885     recent_crypto_config_map_.Erase(mru_iterator);
1886     return std::make_unique<CryptoClientConfigHandle>(map_iterator);
1887   }
1888 
1889   // Otherwise, create a new QuicCryptoClientConfigOwner and add it to
1890   // |active_crypto_config_map_|.
1891   std::unique_ptr<QuicCryptoClientConfigOwner> crypto_config_owner =
1892       std::make_unique<QuicCryptoClientConfigOwner>(
1893           std::make_unique<ProofVerifierChromium>(
1894               cert_verifier_, transport_security_state_, sct_auditing_delegate_,
1895               HostsFromOrigins(params_.origins_to_force_quic_on),
1896               actual_network_anonymization_key),
1897           std::make_unique<quic::QuicClientSessionCache>(), this);
1898 
1899   quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config();
1900   crypto_config->AddCanonicalSuffix(".c.youtube.com");
1901   crypto_config->AddCanonicalSuffix(".ggpht.com");
1902   crypto_config->AddCanonicalSuffix(".googlevideo.com");
1903   crypto_config->AddCanonicalSuffix(".googleusercontent.com");
1904   crypto_config->AddCanonicalSuffix(".gvt1.com");
1905   crypto_config->set_alps_use_new_codepoint(params_.use_new_alps_codepoint);
1906 
1907   ConfigureQuicCryptoClientConfig(*crypto_config);
1908 
1909   if (!prefer_aes_gcm_recorded_) {
1910     bool prefer_aes_gcm =
1911         !crypto_config->aead.empty() && (crypto_config->aead[0] == quic::kAESG);
1912     UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.PreferAesGcm", prefer_aes_gcm);
1913     prefer_aes_gcm_recorded_ = true;
1914   }
1915 
1916   map_iterator = active_crypto_config_map_
1917                      .emplace(actual_network_anonymization_key,
1918                               std::move(crypto_config_owner))
1919                      .first;
1920   return std::make_unique<CryptoClientConfigHandle>(map_iterator);
1921 }
1922 
OnAllCryptoClientRefReleased(QuicCryptoClientConfigMap::iterator & map_iterator)1923 void QuicSessionPool::OnAllCryptoClientRefReleased(
1924     QuicCryptoClientConfigMap::iterator& map_iterator) {
1925   DCHECK_EQ(0, map_iterator->second->num_refs());
1926   recent_crypto_config_map_.Put(map_iterator->first,
1927                                 std::move(map_iterator->second));
1928   active_crypto_config_map_.erase(map_iterator);
1929 }
1930 
CollectDataOnPlatformNotification(enum QuicPlatformNotification notification,handles::NetworkHandle affected_network) const1931 void QuicSessionPool::CollectDataOnPlatformNotification(
1932     enum QuicPlatformNotification notification,
1933     handles::NetworkHandle affected_network) const {
1934   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.PlatformNotification",
1935                             notification, NETWORK_NOTIFICATION_MAX);
1936   connectivity_monitor_.RecordConnectivityStatsToHistograms(
1937       QuicPlatformNotificationToString(notification), affected_network);
1938 }
1939 
1940 std::unique_ptr<QuicCryptoClientConfigHandle>
GetCryptoConfigForTesting(const NetworkAnonymizationKey & network_anonymization_key)1941 QuicSessionPool::GetCryptoConfigForTesting(
1942     const NetworkAnonymizationKey& network_anonymization_key) {
1943   return CreateCryptoConfigHandle(network_anonymization_key);
1944 }
1945 
CryptoConfigCacheIsEmptyForTesting(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key)1946 bool QuicSessionPool::CryptoConfigCacheIsEmptyForTesting(
1947     const quic::QuicServerId& server_id,
1948     const NetworkAnonymizationKey& network_anonymization_key) {
1949   quic::QuicCryptoClientConfig::CachedState* cached = nullptr;
1950   NetworkAnonymizationKey actual_network_anonymization_key =
1951       use_network_anonymization_key_for_crypto_configs_
1952           ? network_anonymization_key
1953           : NetworkAnonymizationKey();
1954   auto map_iterator =
1955       active_crypto_config_map_.find(actual_network_anonymization_key);
1956   if (map_iterator != active_crypto_config_map_.end()) {
1957     cached = map_iterator->second->config()->LookupOrCreate(server_id);
1958   } else {
1959     auto mru_iterator =
1960         recent_crypto_config_map_.Peek(actual_network_anonymization_key);
1961     if (mru_iterator != recent_crypto_config_map_.end()) {
1962       cached = mru_iterator->second->config()->LookupOrCreate(server_id);
1963     }
1964   }
1965   return !cached || cached->IsEmpty();
1966 }
1967 
1968 }  // namespace net
1969