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