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.
5 #include "net/quic/quic_stream_factory.h"
12 #include "base/containers/contains.h"
13 #include "base/feature_list.h"
14 #include "base/functional/bind.h"
15 #include "base/location.h"
16 #include "base/memory/memory_pressure_monitor.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/memory/raw_ptr_exclusion.h"
19 #include "base/metrics/field_trial.h"
20 #include "base/metrics/histogram_functions.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/no_destructor.h"
23 #include "base/numerics/safe_conversions.h"
24 #include "base/ranges/algorithm.h"
25 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_util.h"
27 #include "base/strings/stringprintf.h"
28 #include "base/task/sequenced_task_runner.h"
29 #include "base/task/single_thread_task_runner.h"
30 #include "base/time/default_clock.h"
31 #include "base/time/default_tick_clock.h"
32 #include "base/values.h"
33 #include "crypto/openssl_util.h"
34 #include "net/base/address_list.h"
35 #include "net/base/features.h"
36 #include "net/base/ip_address.h"
37 #include "net/base/net_errors.h"
38 #include "net/base/trace_constants.h"
39 #include "net/base/tracing.h"
40 #include "net/cert/cert_verifier.h"
41 #include "net/dns/host_resolver.h"
42 #include "net/dns/public/secure_dns_policy.h"
43 #include "net/log/net_log.h"
44 #include "net/log/net_log_capture_mode.h"
45 #include "net/log/net_log_event_type.h"
46 #include "net/log/net_log_source_type.h"
47 #include "net/quic/address_utils.h"
48 #include "net/quic/crypto/proof_verifier_chromium.h"
49 #include "net/quic/properties_based_quic_server_info.h"
50 #include "net/quic/quic_chromium_alarm_factory.h"
51 #include "net/quic/quic_chromium_connection_helper.h"
52 #include "net/quic/quic_chromium_packet_reader.h"
53 #include "net/quic/quic_chromium_packet_writer.h"
54 #include "net/quic/quic_context.h"
55 #include "net/quic/quic_crypto_client_stream_factory.h"
56 #include "net/quic/quic_http_stream.h"
57 #include "net/quic/quic_server_info.h"
58 #include "net/socket/client_socket_factory.h"
59 #include "net/socket/next_proto.h"
60 #include "net/socket/socket_performance_watcher.h"
61 #include "net/socket/socket_performance_watcher_factory.h"
62 #include "net/socket/udp_client_socket.h"
63 #include "net/third_party/quiche/src/quiche/quic/core/crypto/null_decrypter.h"
64 #include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_verifier.h"
65 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_client_session_cache.h"
66 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_random.h"
67 #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h"
68 #include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
69 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
70 #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
71 #include "third_party/boringssl/src/include/openssl/aead.h"
73 #include "url/scheme_host_port.h"
74 #include "url/url_constants.h"
80 enum InitialRttEstimateSource {
85 INITIAL_RTT_SOURCE_MAX,
88 enum class JobProtocolErrorLocation {
89 kSessionStartReadingFailedAsync = 0,
90 kSessionStartReadingFailedSync = 1,
91 kCreateSessionFailedAsync = 2,
92 kCreateSessionFailedSync = 3,
93 kCryptoConnectFailedSync = 4,
94 kCryptoConnectFailedAsync = 5,
95 kMaxValue = kCryptoConnectFailedAsync,
98 base::Value::Dict NetLogQuicStreamFactoryJobParams(
99 const QuicStreamFactory::QuicSessionAliasKey* key) {
100 return base::Value::Dict()
101 .Set("host", key->server_id().host())
102 .Set("port", key->server_id().port())
104 PrivacyModeToDebugString(key->session_key().privacy_mode()))
105 .Set("network_anonymization_key",
106 key->session_key().network_anonymization_key().ToDebugString());
109 std::string QuicPlatformNotificationToString(
110 QuicPlatformNotification notification) {
111 switch (notification) {
112 case NETWORK_CONNECTED:
113 return "OnNetworkConnected";
114 case NETWORK_MADE_DEFAULT:
115 return "OnNetworkMadeDefault";
116 case NETWORK_DISCONNECTED:
117 return "OnNetworkDisconnected";
118 case NETWORK_SOON_TO_DISCONNECT:
119 return "OnNetworkSoonToDisconnect";
120 case NETWORK_IP_ADDRESS_CHANGED:
121 return "OnIPAddressChanged";
126 return "InvalidNotification";
129 void HistogramCreateSessionFailure(enum CreateSessionFailure error) {
130 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error,
134 void HistogramProtocolErrorLocation(enum JobProtocolErrorLocation location) {
135 UMA_HISTOGRAM_ENUMERATION("Net.QuicStreamFactory.DoConnectFailureLocation",
139 void LogConnectionIpPooling(bool pooled) {
140 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectionIpPooled", pooled);
143 void LogStaleConnectionTime(base::TimeTicks start_time) {
144 UMA_HISTOGRAM_TIMES("Net.QuicSession.StaleConnectionTime",
145 base::TimeTicks::Now() - start_time);
148 void LogValidConnectionTime(base::TimeTicks start_time) {
149 UMA_HISTOGRAM_TIMES("Net.QuicSession.ValidConnectionTime",
150 base::TimeTicks::Now() - start_time);
153 void SetInitialRttEstimate(base::TimeDelta estimate,
154 enum InitialRttEstimateSource source,
155 quic::QuicConfig* config) {
156 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.InitialRttEsitmateSource", source,
157 INITIAL_RTT_SOURCE_MAX);
158 if (estimate != base::TimeDelta())
159 config->SetInitialRoundTripTimeUsToSend(
160 base::checked_cast<uint64_t>(estimate.InMicroseconds()));
163 // An implementation of quic::QuicCryptoClientConfig::ServerIdFilter that wraps
164 // an |origin_filter|.
165 class ServerIdOriginFilter
166 : public quic::QuicCryptoClientConfig::ServerIdFilter {
168 explicit ServerIdOriginFilter(
169 const base::RepeatingCallback<bool(const GURL&)> origin_filter)
170 : origin_filter_(origin_filter) {}
172 bool Matches(const quic::QuicServerId& server_id) const override {
173 if (origin_filter_.is_null())
176 GURL url(base::StringPrintf("%s%s%s:%d", url::kHttpsScheme,
177 url::kStandardSchemeSeparator,
178 server_id.host().c_str(), server_id.port()));
179 DCHECK(url.is_valid());
180 return origin_filter_.Run(url);
184 const base::RepeatingCallback<bool(const GURL&)> origin_filter_;
187 std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) {
188 std::set<std::string> hosts;
189 for (const auto& origin : origins) {
190 hosts.insert(origin.host());
197 // Refcounted class that owns quic::QuicCryptoClientConfig and tracks how many
198 // consumers are using it currently. When the last reference is freed, the
199 // QuicCryptoClientConfigHandle informs the owning QuicStreamFactory, moves it
200 // into an MRU cache.
201 class QuicStreamFactory::QuicCryptoClientConfigOwner {
203 QuicCryptoClientConfigOwner(
204 std::unique_ptr<quic::ProofVerifier> proof_verifier,
205 std::unique_ptr<quic::QuicClientSessionCache> session_cache,
206 QuicStreamFactory* quic_stream_factory)
207 : config_(std::move(proof_verifier), std::move(session_cache)),
208 clock_(base::DefaultClock::GetInstance()),
209 quic_stream_factory_(quic_stream_factory) {
210 DCHECK(quic_stream_factory_);
211 memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
213 base::BindRepeating(&QuicCryptoClientConfigOwner::OnMemoryPressure,
214 base::Unretained(this)));
215 if (quic_stream_factory_->ssl_config_service_->GetSSLContextConfig()
216 .PostQuantumKeyAgreementEnabled()) {
217 config_.set_preferred_groups({SSL_GROUP_X25519_KYBER768_DRAFT00,
218 SSL_GROUP_X25519, SSL_GROUP_SECP256R1,
219 SSL_GROUP_SECP384R1});
223 QuicCryptoClientConfigOwner(const QuicCryptoClientConfigOwner&) = delete;
224 QuicCryptoClientConfigOwner& operator=(const QuicCryptoClientConfigOwner&) =
227 ~QuicCryptoClientConfigOwner() { DCHECK_EQ(num_refs_, 0); }
229 quic::QuicCryptoClientConfig* config() { return &config_; }
231 int num_refs() const { return num_refs_; }
233 QuicStreamFactory* quic_stream_factory() { return quic_stream_factory_; }
235 void OnMemoryPressure(
236 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
237 quic::SessionCache* session_cache = config_.session_cache();
238 if (!session_cache) {
241 time_t now = clock_->Now().ToTimeT();
242 uint64_t now_u64 = 0;
244 now_u64 = static_cast<uint64_t>(now);
246 switch (memory_pressure_level) {
247 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
249 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
250 session_cache->RemoveExpiredEntries(
251 quic::QuicWallTime::FromUNIXSeconds(now_u64));
253 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
254 session_cache->Clear();
260 friend class CryptoClientConfigHandle;
262 // Simple ref counting. Not using scoped_refptr allows for both keeping around
263 // an MRU cache of 0-reference objects, and DCHECKing that there are no
264 // outstanding referenced QuicCryptoClientConfigOwner on destruction. Private
265 // so that only CryptoClientConfigHandle can add and remove refs.
267 void AddRef() { num_refs_++; }
270 DCHECK_GT(num_refs_, 0);
275 quic::QuicCryptoClientConfig config_;
276 raw_ptr<base::Clock> clock_;
277 std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
278 const raw_ptr<QuicStreamFactory> quic_stream_factory_;
281 // Class that owns a reference to a QuicCryptoClientConfigOwner. Handles
282 // incrementing the refcount on construction, and decrementing it on
284 class QuicStreamFactory::CryptoClientConfigHandle
285 : public QuicCryptoClientConfigHandle {
287 explicit CryptoClientConfigHandle(
288 const QuicCryptoClientConfigMap::iterator& map_iterator)
289 : map_iterator_(map_iterator) {
290 DCHECK_GE(map_iterator_->second->num_refs(), 0);
291 map_iterator->second->AddRef();
294 CryptoClientConfigHandle(const CryptoClientConfigHandle& other)
295 : CryptoClientConfigHandle(other.map_iterator_) {}
297 CryptoClientConfigHandle& operator=(const CryptoClientConfigHandle&) = delete;
299 ~CryptoClientConfigHandle() override {
300 DCHECK_GT(map_iterator_->second->num_refs(), 0);
301 map_iterator_->second->ReleaseRef();
302 if (map_iterator_->second->num_refs() == 0) {
303 map_iterator_->second->quic_stream_factory()
304 ->OnAllCryptoClientRefReleased(map_iterator_);
308 quic::QuicCryptoClientConfig* GetConfig() const override {
309 return map_iterator_->second->config();
313 QuicCryptoClientConfigMap::iterator map_iterator_;
316 // Responsible for creating a new QUIC session to the specified server, and
317 // for notifying any associated requests when complete. |client_config_handle|
318 // is not actually used, but serves to keep the corresponding CryptoClientConfig
319 // alive until the Job completes.
320 class QuicStreamFactory::Job {
322 Job(QuicStreamFactory* factory,
323 quic::ParsedQuicVersion quic_version,
324 HostResolver* host_resolver,
325 const QuicSessionAliasKey& key,
326 std::unique_ptr<CryptoClientConfigHandle> client_config_handle,
327 bool was_alternative_service_recently_broken,
328 bool retry_on_alternate_network_before_handshake,
329 RequestPriority priority,
330 bool use_dns_aliases,
331 bool require_dns_https_alpn,
332 int cert_verify_flags,
333 const NetLogWithSource& net_log);
335 Job(const Job&) = delete;
336 Job& operator=(const Job&) = delete;
340 int Run(CompletionOnceCallback callback);
344 int DoResolveHostComplete(int rv);
345 int DoCreateSession();
346 int DoCreateSessionComplete(int rv);
347 int DoConnect(int rv);
348 int DoConnectComplete(int rv);
349 int DoConfirmConnection(int rv);
351 void OnCreateSessionComplete(int rv);
352 void OnResolveHostComplete(int rv);
353 void OnCryptoConnectComplete(int rv);
355 const QuicSessionAliasKey& key() const { return key_; }
357 const NetLogWithSource& net_log() const { return net_log_; }
359 base::WeakPtr<Job> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
361 void PopulateNetErrorDetails(NetErrorDetails* details) const;
363 void AddRequest(QuicStreamRequest* request) {
364 stream_requests_.insert(request);
365 if (!host_resolution_finished_) {
366 request->ExpectOnHostResolution();
368 // Callers do not need to wait for OnQuicSessionCreationComplete if the
369 // kAsyncQuicSession flag is not set because session creation will be fully
370 // synchronous, so no need to call ExpectQuicSessionCreation.
371 if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession) &&
372 !session_creation_finished_) {
373 request->ExpectQuicSessionCreation();
377 void RemoveRequest(QuicStreamRequest* request) {
378 auto request_iter = stream_requests_.find(request);
379 DCHECK(request_iter != stream_requests_.end());
380 stream_requests_.erase(request_iter);
383 void SetPriority(RequestPriority priority) {
384 if (priority_ == priority)
387 priority_ = priority;
388 if (resolve_host_request_ && !host_resolution_finished_) {
389 resolve_host_request_->ChangeRequestPriority(priority);
393 const std::set<QuicStreamRequest*>& stream_requests() {
394 return stream_requests_;
397 RequestPriority priority() const { return priority_; }
403 STATE_RESOLVE_HOST_COMPLETE,
404 STATE_CREATE_SESSION,
405 STATE_CREATE_SESSION_COMPLETE,
407 STATE_CONFIRM_CONNECTION,
410 void CloseStaleHostConnection() {
411 DVLOG(1) << "Closing connection from stale host.";
413 QuicChromiumClientSession* session = session_;
415 // Use ERR_FAILED instead of ERR_ABORTED out of paranoia - ERR_ABORTED
416 // should only be used when the next layer up cancels a request, and has
417 // special semantic meaning for some consumers when they see it.
418 session->CloseSessionOnErrorLater(
419 ERR_FAILED, quic::QUIC_STALE_CONNECTION_CANCELLED,
420 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
424 // Returns whether the client should be SVCB-optional when connecting to
427 base::span<const HostResolverEndpointResult> results) const {
428 // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all
429 // routes support ECH, disable the A/AAAA fallback. See Section 10.1 of
430 // draft-ietf-dnsop-svcb-https-11.
431 if (!factory_->ssl_config_service_->GetSSLContextConfig()
432 .EncryptedClientHelloEnabled() ||
433 !base::FeatureList::IsEnabled(features::kEncryptedClientHelloQuic)) {
434 return true; // ECH is not supported for this request.
437 return !HostResolver::AllProtocolEndpointsHaveEch(results);
440 // Returns the QUIC version that would be used with `endpoint_result`, or
441 // `quic::ParsedQuicVersion::Unsupported()` if `endpoint_result` cannot be
443 quic::ParsedQuicVersion SelectQuicVersion(
444 const HostResolverEndpointResult& endpoint_result,
445 bool svcb_optional) const {
446 // TODO(davidben): `require_dns_https_alpn_` only exists to be `DCHECK`ed
447 // for consistency against `quic_version_`. Remove the parameter?
448 DCHECK_EQ(require_dns_https_alpn_, !quic_version_.IsKnown());
450 if (endpoint_result.metadata.supported_protocol_alpns.empty()) {
451 // `endpoint_result` came from A/AAAA records directly, without HTTPS/SVCB
452 // records. If we know the QUIC ALPN to use externally, i.e. via Alt-Svc,
453 // use it in SVCB-optional mode. Otherwise, `endpoint_result` is not
454 // eligible for QUIC.
455 return svcb_optional ? quic_version_
456 : quic::ParsedQuicVersion::Unsupported();
459 // Otherwise, `endpoint_result` came from an HTTPS/SVCB record. We can use
460 // QUIC if a suitable match is found in the record's ALPN list.
461 // Additionally, if this connection attempt came from Alt-Svc, the DNS
462 // result must be consistent with it. See
463 // https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-11.html#name-interaction-with-alt-svc
464 if (quic_version_.IsKnown()) {
465 std::string expected_alpn = quic::AlpnForVersion(quic_version_);
466 if (base::Contains(endpoint_result.metadata.supported_protocol_alpns,
467 quic::AlpnForVersion(quic_version_))) {
468 return quic_version_;
470 return quic::ParsedQuicVersion::Unsupported();
473 for (const auto& alpn : endpoint_result.metadata.supported_protocol_alpns) {
474 for (const auto& supported_version : factory_->supported_versions()) {
475 if (alpn == AlpnForVersion(supported_version)) {
476 return supported_version;
481 return quic::ParsedQuicVersion::Unsupported();
484 void LogStaleAndFreshHostMatched(bool matched) {
488 QUIC_STREAM_FACTORY_JOB_STALE_HOST_RESOLUTION_MATCHED);
492 QUIC_STREAM_FACTORY_JOB_STALE_HOST_RESOLUTION_NO_MATCH);
494 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StaleAndFreshHostMatched", matched);
497 IoState io_state_ = STATE_RESOLVE_HOST;
498 raw_ptr<QuicStreamFactory> factory_;
499 quic::ParsedQuicVersion quic_version_;
500 quic::ParsedQuicVersion quic_version_used_ =
501 quic::ParsedQuicVersion::Unsupported();
502 raw_ptr<HostResolver> host_resolver_;
503 const QuicSessionAliasKey key_;
504 const std::unique_ptr<CryptoClientConfigHandle> client_config_handle_;
505 RequestPriority priority_;
506 const bool use_dns_aliases_;
507 const bool require_dns_https_alpn_;
508 const int cert_verify_flags_;
509 const bool was_alternative_service_recently_broken_;
510 const bool retry_on_alternate_network_before_handshake_;
511 const NetLogWithSource net_log_;
512 bool host_resolution_finished_ = false;
513 bool session_creation_finished_ = false;
514 bool connection_retried_ = false;
515 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
517 RAW_PTR_EXCLUSION QuicChromiumClientSession* session_ = nullptr;
518 HostResolverEndpointResult endpoint_result_;
519 // If connection migraiton is supported, |network_| denotes the network on
520 // which |session_| is created.
521 handles::NetworkHandle network_;
522 CompletionOnceCallback host_resolution_callback_;
523 CompletionOnceCallback callback_;
524 std::unique_ptr<HostResolver::ResolveHostRequest> resolve_host_request_;
525 base::TimeTicks dns_resolution_start_time_;
526 base::TimeTicks dns_resolution_end_time_;
527 base::TimeTicks quic_connection_start_time_;
528 std::set<QuicStreamRequest*> stream_requests_;
529 base::WeakPtrFactory<Job> weak_factory_{this};
532 QuicStreamFactory::Job::Job(
533 QuicStreamFactory* factory,
534 quic::ParsedQuicVersion quic_version,
535 HostResolver* host_resolver,
536 const QuicSessionAliasKey& key,
537 std::unique_ptr<CryptoClientConfigHandle> client_config_handle,
538 bool was_alternative_service_recently_broken,
539 bool retry_on_alternate_network_before_handshake,
540 RequestPriority priority,
541 bool use_dns_aliases,
542 bool require_dns_https_alpn,
543 int cert_verify_flags,
544 const NetLogWithSource& net_log)
546 quic_version_(quic_version),
547 host_resolver_(host_resolver),
549 client_config_handle_(std::move(client_config_handle)),
551 use_dns_aliases_(use_dns_aliases),
552 require_dns_https_alpn_(require_dns_https_alpn),
553 cert_verify_flags_(cert_verify_flags),
554 was_alternative_service_recently_broken_(
555 was_alternative_service_recently_broken),
556 retry_on_alternate_network_before_handshake_(
557 retry_on_alternate_network_before_handshake),
559 NetLogWithSource::Make(net_log.net_log(),
560 NetLogSourceType::QUIC_STREAM_FACTORY_JOB)),
561 network_(handles::kInvalidNetworkHandle) {
562 DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn);
563 net_log_.BeginEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB,
564 [&] { return NetLogQuicStreamFactoryJobParams(&key_); });
565 // Associate |net_log_| with |net_log|.
566 net_log_.AddEventReferencingSource(
567 NetLogEventType::QUIC_STREAM_FACTORY_JOB_BOUND_TO_HTTP_STREAM_JOB,
569 net_log.AddEventReferencingSource(
570 NetLogEventType::HTTP_STREAM_JOB_BOUND_TO_QUIC_STREAM_FACTORY_JOB,
574 QuicStreamFactory::Job::~Job() {
575 net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB);
576 // If |this| is destroyed in QuicStreamFactory's destructor, |callback_| is
580 int QuicStreamFactory::Job::Run(CompletionOnceCallback callback) {
582 if (rv == ERR_IO_PENDING)
583 callback_ = std::move(callback);
585 return rv > 0 ? OK : rv;
588 int QuicStreamFactory::Job::DoLoop(int rv) {
589 TRACE_EVENT0(NetTracingCategory(), "QuicStreamFactory::Job::DoLoop");
592 IoState state = io_state_;
593 io_state_ = STATE_NONE;
595 case STATE_RESOLVE_HOST:
597 rv = DoResolveHost();
599 case STATE_RESOLVE_HOST_COMPLETE:
600 rv = DoResolveHostComplete(rv);
602 case STATE_CREATE_SESSION:
603 rv = DoCreateSession();
605 case STATE_CREATE_SESSION_COMPLETE:
606 rv = DoCreateSessionComplete(rv);
611 case STATE_CONFIRM_CONNECTION:
612 rv = DoConfirmConnection(rv);
615 NOTREACHED() << "io_state_: " << io_state_;
618 } while (io_state_ != STATE_NONE && rv != ERR_IO_PENDING);
622 void QuicStreamFactory::Job::OnResolveHostComplete(int rv) {
623 DCHECK(!host_resolution_finished_);
624 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
627 for (auto* request : stream_requests_) {
628 request->OnHostResolutionComplete(rv);
631 if (rv != ERR_IO_PENDING && !callback_.is_null())
632 std::move(callback_).Run(rv);
635 void QuicStreamFactory::Job::OnCryptoConnectComplete(int rv) {
636 // This early return will be triggered when CloseSessionOnError is called
637 // before crypto handshake has completed.
639 LogStaleConnectionTime(quic_connection_start_time_);
643 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
644 HistogramProtocolErrorLocation(
645 JobProtocolErrorLocation::kCryptoConnectFailedAsync);
648 io_state_ = STATE_CONFIRM_CONNECTION;
650 if (rv != ERR_IO_PENDING && !callback_.is_null())
651 std::move(callback_).Run(rv);
654 void QuicStreamFactory::Job::PopulateNetErrorDetails(
655 NetErrorDetails* details) const {
658 details->connection_info = QuicHttpStream::ConnectionInfoFromQuicVersion(
659 session_->connection()->version());
660 details->quic_connection_error = session_->error();
663 int QuicStreamFactory::Job::DoResolveHost() {
664 dns_resolution_start_time_ = base::TimeTicks::Now();
666 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
668 HostResolver::ResolveHostParameters parameters;
669 parameters.initial_priority = priority_;
670 parameters.secure_dns_policy = key_.session_key().secure_dns_policy();
671 resolve_host_request_ = host_resolver_->CreateRequest(
672 key_.destination(), key_.session_key().network_anonymization_key(),
673 net_log_, parameters);
674 // Unretained is safe because |this| owns the request, ensuring cancellation
676 return resolve_host_request_->Start(base::BindOnce(
677 &QuicStreamFactory::Job::OnResolveHostComplete, base::Unretained(this)));
680 int QuicStreamFactory::Job::DoResolveHostComplete(int rv) {
681 host_resolution_finished_ = true;
682 dns_resolution_end_time_ = base::TimeTicks::Now();
686 DCHECK(!factory_->HasActiveSession(key_.session_key()));
688 // Inform the factory of this resolution, which will set up
689 // a session alias, if possible.
690 const bool svcb_optional =
691 IsSvcbOptional(*resolve_host_request_->GetEndpointResults());
692 for (const auto& endpoint : *resolve_host_request_->GetEndpointResults()) {
693 // Only consider endpoints that would have been eligible for QUIC.
694 if (!SelectQuicVersion(endpoint, svcb_optional).IsKnown()) {
697 if (factory_->HasMatchingIpSession(
698 key_, endpoint.ip_endpoints,
699 *resolve_host_request_->GetDnsAliasResults(), use_dns_aliases_)) {
700 LogConnectionIpPooling(true);
704 io_state_ = STATE_CREATE_SESSION;
708 void QuicStreamFactory::Job::OnCreateSessionComplete(int rv) {
711 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
712 HistogramProtocolErrorLocation(
713 JobProtocolErrorLocation::kCreateSessionFailedAsync);
715 for (auto* request : stream_requests_) {
716 request->OnQuicSessionCreationComplete(rv);
718 if (!callback_.is_null()) {
719 std::move(callback_).Run(rv);
724 DVLOG(1) << "Created session on network: " << network_;
725 io_state_ = STATE_CREATE_SESSION_COMPLETE;
728 for (auto* request : stream_requests_) {
729 request->OnQuicSessionCreationComplete(rv);
732 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
733 std::move(callback_).Run(rv);
737 int QuicStreamFactory::Job::DoCreateSession() {
738 // TODO(https://crbug.com/1416409): This logic only knows how to try one
741 IsSvcbOptional(*resolve_host_request_->GetEndpointResults());
743 for (const auto& candidate : *resolve_host_request_->GetEndpointResults()) {
744 quic::ParsedQuicVersion version =
745 SelectQuicVersion(candidate, svcb_optional);
746 if (version.IsKnown()) {
748 quic_version_used_ = version;
749 endpoint_result_ = candidate;
754 return ERR_DNS_NO_MATCHING_SUPPORTED_ALPN;
757 quic_connection_start_time_ = base::TimeTicks::Now();
758 DCHECK(dns_resolution_end_time_ != base::TimeTicks());
759 io_state_ = STATE_CREATE_SESSION_COMPLETE;
760 bool require_confirmation = was_alternative_service_recently_broken_;
761 net_log_.AddEntryWithBoolParams(
762 NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT, NetLogEventPhase::BEGIN,
763 "require_confirmation", require_confirmation);
765 DCHECK_NE(quic_version_used_, quic::ParsedQuicVersion::Unsupported());
766 if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) {
767 return factory_->CreateSessionAsync(
768 base::BindOnce(&QuicStreamFactory::Job::OnCreateSessionComplete,
770 key_, quic_version_used_, cert_verify_flags_, require_confirmation,
771 endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_,
772 net_log_, &session_, &network_);
774 int rv = factory_->CreateSessionSync(
775 key_, quic_version_used_, cert_verify_flags_, require_confirmation,
776 endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_,
777 net_log_, &session_, &network_);
779 DVLOG(1) << "Created session on network: " << network_;
781 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
783 HistogramProtocolErrorLocation(
784 JobProtocolErrorLocation::kCreateSessionFailedSync);
789 int QuicStreamFactory::Job::DoCreateSessionComplete(int rv) {
790 session_creation_finished_ = true;
794 io_state_ = STATE_CONNECT;
795 if (!session_->connection()->connected()) {
796 return ERR_CONNECTION_CLOSED;
799 session_->StartReading();
800 if (!session_->connection()->connected()) {
801 if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) {
802 HistogramProtocolErrorLocation(
803 JobProtocolErrorLocation::kSessionStartReadingFailedAsync);
805 HistogramProtocolErrorLocation(
806 JobProtocolErrorLocation::kSessionStartReadingFailedSync);
808 return ERR_QUIC_PROTOCOL_ERROR;
813 int QuicStreamFactory::Job::DoConnect(int rv) {
818 io_state_ = STATE_CONFIRM_CONNECTION;
819 rv = session_->CryptoConnect(base::BindOnce(
820 &QuicStreamFactory::Job::OnCryptoConnectComplete, GetWeakPtr()));
822 if (rv != ERR_IO_PENDING) {
823 LogValidConnectionTime(quic_connection_start_time_);
826 if (!session_->connection()->connected() &&
827 session_->error() == quic::QUIC_PROOF_INVALID) {
828 return ERR_QUIC_HANDSHAKE_FAILED;
831 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
832 HistogramProtocolErrorLocation(
833 JobProtocolErrorLocation::kCryptoConnectFailedSync);
839 int QuicStreamFactory::Job::DoConfirmConnection(int rv) {
840 UMA_HISTOGRAM_TIMES("Net.QuicSession.TimeFromResolveHostToConfirmConnection",
841 base::TimeTicks::Now() - dns_resolution_start_time_);
842 net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT);
844 if (was_alternative_service_recently_broken_)
845 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectAfterBroken", rv == OK);
847 if (retry_on_alternate_network_before_handshake_ && session_ &&
848 !session_->OneRttKeysAvailable() &&
849 network_ == factory_->default_network()) {
850 if (session_->error() == quic::QUIC_NETWORK_IDLE_TIMEOUT ||
851 session_->error() == quic::QUIC_HANDSHAKE_TIMEOUT ||
852 session_->error() == quic::QUIC_PACKET_WRITE_ERROR) {
853 // Retry the connection on an alternate network if crypto handshake failed
854 // with network idle time out or handshake time out.
855 DCHECK(network_ != handles::kInvalidNetworkHandle);
856 network_ = factory_->FindAlternateNetwork(network_);
857 connection_retried_ = network_ != handles::kInvalidNetworkHandle;
858 UMA_HISTOGRAM_BOOLEAN(
859 "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake",
860 connection_retried_);
861 UMA_HISTOGRAM_ENUMERATION(
862 "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake."
863 "FailedConnectionType",
864 NetworkChangeNotifier::GetNetworkConnectionType(
865 factory_->default_network()),
866 NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1);
867 if (connection_retried_) {
868 UMA_HISTOGRAM_ENUMERATION(
869 "Net.QuicStreamFactory.MigrationBeforeHandshake.NewConnectionType",
870 NetworkChangeNotifier::GetNetworkConnectionType(network_),
871 NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1);
874 QUIC_STREAM_FACTORY_JOB_RETRY_ON_ALTERNATE_NETWORK);
875 // Notify requests that connection on the default network failed.
876 for (auto* request : stream_requests_) {
877 request->OnConnectionFailedOnDefaultNetwork();
879 DVLOG(1) << "Retry connection on alternate network: " << network_;
881 io_state_ = STATE_CREATE_SESSION;
887 if (connection_retried_) {
888 UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.MigrationBeforeHandshake2",
891 UMA_HISTOGRAM_BOOLEAN(
892 "Net.QuicStreamFactory.NetworkChangeDuringMigrationBeforeHandshake",
893 network_ == factory_->default_network());
895 base::UmaHistogramSparse(
896 "Net.QuicStreamFactory.MigrationBeforeHandshakeFailedReason", -rv);
898 } else if (network_ != handles::kInvalidNetworkHandle &&
899 network_ != factory_->default_network()) {
900 UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.ConnectionOnNonDefaultNetwork",
907 DCHECK(!factory_->HasActiveSession(key_.session_key()));
908 // There may well now be an active session for this IP. If so, use the
909 // existing session instead.
910 if (factory_->HasMatchingIpSession(
911 key_, {ToIPEndPoint(session_->connection()->peer_address())},
912 /*aliases=*/{}, use_dns_aliases_)) {
913 LogConnectionIpPooling(true);
914 session_->connection()->CloseConnection(
915 quic::QUIC_CONNECTION_IP_POOLED,
916 "An active session exists for the given IP.",
917 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
921 LogConnectionIpPooling(false);
923 std::set<std::string> dns_aliases =
924 use_dns_aliases_ && resolve_host_request_->GetDnsAliasResults()
925 ? *resolve_host_request_->GetDnsAliasResults()
926 : std::set<std::string>();
927 factory_->ActivateSession(key_, session_, std::move(dns_aliases));
932 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory)
933 : factory_(factory) {}
935 QuicStreamRequest::~QuicStreamRequest() {
936 if (factory_ && !callback_.is_null())
937 factory_->CancelRequest(this);
940 int QuicStreamRequest::Request(
941 url::SchemeHostPort destination,
942 quic::ParsedQuicVersion quic_version,
943 PrivacyMode privacy_mode,
944 RequestPriority priority,
945 const SocketTag& socket_tag,
946 const NetworkAnonymizationKey& network_anonymization_key,
947 SecureDnsPolicy secure_dns_policy,
948 bool use_dns_aliases,
949 bool require_dns_https_alpn,
950 int cert_verify_flags,
952 const NetLogWithSource& net_log,
953 NetErrorDetails* net_error_details,
954 CompletionOnceCallback failed_on_default_network_callback,
955 CompletionOnceCallback callback) {
956 DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn);
957 DCHECK(net_error_details);
958 DCHECK(callback_.is_null());
959 DCHECK(host_resolution_callback_.is_null());
962 net_error_details_ = net_error_details;
963 failed_on_default_network_callback_ =
964 std::move(failed_on_default_network_callback);
966 session_key_ = QuicSessionKey(HostPortPair::FromURL(url), privacy_mode,
967 socket_tag, network_anonymization_key,
968 secure_dns_policy, require_dns_https_alpn);
970 int rv = factory_->Create(session_key_, std::move(destination), quic_version,
971 priority, use_dns_aliases, cert_verify_flags, url,
973 if (rv == ERR_IO_PENDING) {
975 callback_ = std::move(callback);
977 DCHECK(!expect_on_host_resolution_);
986 bool QuicStreamRequest::WaitForHostResolution(CompletionOnceCallback callback) {
987 DCHECK(host_resolution_callback_.is_null());
988 if (expect_on_host_resolution_) {
989 host_resolution_callback_ = std::move(callback);
991 return expect_on_host_resolution_;
994 void QuicStreamRequest::ExpectOnHostResolution() {
995 expect_on_host_resolution_ = true;
998 void QuicStreamRequest::OnHostResolutionComplete(int rv) {
999 DCHECK(expect_on_host_resolution_);
1000 expect_on_host_resolution_ = false;
1001 if (!host_resolution_callback_.is_null()) {
1002 std::move(host_resolution_callback_).Run(rv);
1006 bool QuicStreamRequest::WaitForQuicSessionCreation(
1007 CompletionOnceCallback callback) {
1008 DCHECK(create_session_callback_.is_null());
1009 if (expect_on_quic_session_creation_) {
1010 create_session_callback_ = std::move(callback);
1012 return expect_on_quic_session_creation_;
1015 void QuicStreamRequest::ExpectQuicSessionCreation() {
1016 expect_on_quic_session_creation_ = true;
1019 void QuicStreamRequest::OnQuicSessionCreationComplete(int rv) {
1020 // DCHECK(expect_on_quic_session_creation_);
1021 expect_on_quic_session_creation_ = false;
1022 if (!create_session_callback_.is_null()) {
1023 std::move(create_session_callback_).Run(rv);
1027 void QuicStreamRequest::OnRequestComplete(int rv) {
1029 std::move(callback_).Run(rv);
1032 void QuicStreamRequest::OnConnectionFailedOnDefaultNetwork() {
1033 if (!failed_on_default_network_callback_.is_null())
1034 std::move(failed_on_default_network_callback_).Run(OK);
1037 base::TimeDelta QuicStreamRequest::GetTimeDelayForWaitingJob() const {
1039 return base::TimeDelta();
1040 return factory_->GetTimeDelayForWaitingJob(session_key_);
1043 void QuicStreamRequest::SetPriority(RequestPriority priority) {
1045 factory_->SetRequestPriority(this, priority);
1048 std::unique_ptr<QuicChromiumClientSession::Handle>
1049 QuicStreamRequest::ReleaseSessionHandle() {
1050 if (!session_ || !session_->IsConnected())
1053 return std::move(session_);
1056 void QuicStreamRequest::SetSession(
1057 std::unique_ptr<QuicChromiumClientSession::Handle> session) {
1058 session_ = std::move(session);
1061 bool QuicStreamRequest::CanUseExistingSession(
1063 PrivacyMode privacy_mode,
1064 const SocketTag& socket_tag,
1065 const NetworkAnonymizationKey& network_anonymization_key,
1066 SecureDnsPolicy secure_dns_policy,
1067 bool require_dns_https_alpn,
1068 const url::SchemeHostPort& destination) const {
1069 return factory_->CanUseExistingSession(
1070 QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, socket_tag,
1071 network_anonymization_key, secure_dns_policy,
1072 require_dns_https_alpn),
1076 QuicStreamFactory::QuicSessionAliasKey::QuicSessionAliasKey(
1077 url::SchemeHostPort destination,
1078 QuicSessionKey session_key)
1079 : destination_(std::move(destination)),
1080 session_key_(std::move(session_key)) {}
1082 bool QuicStreamFactory::QuicSessionAliasKey::operator<(
1083 const QuicSessionAliasKey& other) const {
1084 return std::tie(destination_, session_key_) <
1085 std::tie(other.destination_, other.session_key_);
1088 bool QuicStreamFactory::QuicSessionAliasKey::operator==(
1089 const QuicSessionAliasKey& other) const {
1090 return destination_ == other.destination_ &&
1091 session_key_ == other.session_key_;
1094 QuicStreamFactory::QuicStreamFactory(
1096 HostResolver* host_resolver,
1097 SSLConfigService* ssl_config_service,
1098 ClientSocketFactory* client_socket_factory,
1099 HttpServerProperties* http_server_properties,
1100 CertVerifier* cert_verifier,
1101 CTPolicyEnforcer* ct_policy_enforcer,
1102 TransportSecurityState* transport_security_state,
1103 SCTAuditingDelegate* sct_auditing_delegate,
1104 SocketPerformanceWatcherFactory* socket_performance_watcher_factory,
1105 QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
1106 QuicContext* quic_context)
1107 : net_log_(NetLogWithSource::Make(net_log,
1108 NetLogSourceType::QUIC_STREAM_FACTORY)),
1109 host_resolver_(host_resolver),
1110 client_socket_factory_(client_socket_factory),
1111 http_server_properties_(http_server_properties),
1112 cert_verifier_(cert_verifier),
1113 ct_policy_enforcer_(ct_policy_enforcer),
1114 transport_security_state_(transport_security_state),
1115 sct_auditing_delegate_(sct_auditing_delegate),
1116 quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
1117 random_generator_(quic_context->random_generator()),
1118 clock_(quic_context->clock()),
1119 // TODO(vasilvv): figure out how to avoid having multiple copies of
1121 params_(*quic_context->params()),
1122 clock_skew_detector_(base::TimeTicks::Now(), base::Time::Now()),
1123 socket_performance_watcher_factory_(socket_performance_watcher_factory),
1124 recent_crypto_config_map_(kMaxRecentCryptoConfigs),
1125 config_(InitializeQuicConfig(*quic_context->params())),
1126 ping_timeout_(quic::QuicTime::Delta::FromSeconds(quic::kPingTimeoutSecs)),
1127 reduced_ping_timeout_(quic::QuicTime::Delta::FromMicroseconds(
1128 quic_context->params()->reduced_ping_timeout.InMicroseconds())),
1129 retransmittable_on_wire_timeout_(quic::QuicTime::Delta::FromMicroseconds(
1130 quic_context->params()
1131 ->retransmittable_on_wire_timeout.InMicroseconds())),
1132 yield_after_packets_(kQuicYieldAfterPacketsRead),
1133 yield_after_duration_(quic::QuicTime::Delta::FromMilliseconds(
1134 kQuicYieldAfterDurationMilliseconds)),
1135 default_network_(handles::kInvalidNetworkHandle),
1136 connectivity_monitor_(default_network_),
1137 ssl_config_service_(ssl_config_service),
1138 use_network_anonymization_key_for_crypto_configs_(
1139 NetworkAnonymizationKey::IsPartitioningEnabled()) {
1140 DCHECK(transport_security_state_);
1141 DCHECK(http_server_properties_);
1142 if (params_.disable_tls_zero_rtt)
1143 SetQuicFlag(quic_disable_client_tls_zero_rtt, true);
1144 InitializeMigrationOptions();
1145 cert_verifier_->AddObserver(this);
1146 CertDatabase::GetInstance()->AddObserver(this);
1149 QuicStreamFactory::~QuicStreamFactory() {
1150 UMA_HISTOGRAM_COUNTS_1000("Net.NumQuicSessionsAtShutdown",
1151 all_sessions_.size());
1152 CloseAllSessions(ERR_ABORTED, quic::QUIC_CONNECTION_CANCELLED);
1153 while (!all_sessions_.empty()) {
1154 delete all_sessions_.begin()->first;
1155 all_sessions_.erase(all_sessions_.begin());
1157 active_jobs_.clear();
1159 DCHECK(dns_aliases_by_session_key_.empty());
1161 // This should have been moved to the recent map when all consumers of
1162 // QuicCryptoClientConfigs were deleted, in the above lines.
1163 DCHECK(active_crypto_config_map_.empty());
1165 CertDatabase::GetInstance()->RemoveObserver(this);
1166 cert_verifier_->RemoveObserver(this);
1167 if (params_.close_sessions_on_ip_change ||
1168 params_.goaway_sessions_on_ip_change) {
1169 NetworkChangeNotifier::RemoveIPAddressObserver(this);
1171 if (NetworkChangeNotifier::AreNetworkHandlesSupported()) {
1172 NetworkChangeNotifier::RemoveNetworkObserver(this);
1176 bool QuicStreamFactory::CanUseExistingSession(
1177 const QuicSessionKey& session_key,
1178 const url::SchemeHostPort& destination) const {
1179 if (base::Contains(active_sessions_, session_key))
1182 for (const auto& key_value : active_sessions_) {
1183 QuicChromiumClientSession* session = key_value.second;
1184 const auto& it = all_sessions_.find(session);
1185 if ((it != all_sessions_.end()) &&
1186 (destination == it->second.destination()) &&
1187 session->CanPool(session_key.host(), session_key)) {
1195 int QuicStreamFactory::Create(const QuicSessionKey& session_key,
1196 url::SchemeHostPort destination,
1197 quic::ParsedQuicVersion quic_version,
1198 RequestPriority priority,
1199 bool use_dns_aliases,
1200 int cert_verify_flags,
1202 const NetLogWithSource& net_log,
1203 QuicStreamRequest* request) {
1204 if (clock_skew_detector_.ClockSkewDetected(base::TimeTicks::Now(),
1205 base::Time::Now())) {
1206 MarkAllActiveSessionsGoingAway(kClockSkewDetected);
1208 DCHECK(HostPortPair(session_key.server_id().host(),
1209 session_key.server_id().port())
1210 .Equals(HostPortPair::FromURL(url)));
1212 // Use active session for |session_key| if such exists.
1213 auto active_session = active_sessions_.find(session_key);
1214 if (active_session != active_sessions_.end()) {
1215 QuicChromiumClientSession* session = active_session->second;
1216 request->SetSession(session->CreateHandle(std::move(destination)));
1220 // Associate with active job to |session_key| if such exists.
1221 auto active_job = active_jobs_.find(session_key);
1222 if (active_job != active_jobs_.end()) {
1223 const NetLogWithSource& job_net_log = active_job->second->net_log();
1224 job_net_log.AddEventReferencingSource(
1225 NetLogEventType::QUIC_STREAM_FACTORY_JOB_BOUND_TO_HTTP_STREAM_JOB,
1227 net_log.AddEventReferencingSource(
1228 NetLogEventType::HTTP_STREAM_JOB_BOUND_TO_QUIC_STREAM_FACTORY_JOB,
1229 job_net_log.source());
1230 active_job->second->AddRequest(request);
1231 return ERR_IO_PENDING;
1234 // Pool to active session to |destination| if possible.
1235 if (!active_sessions_.empty()) {
1236 for (const auto& key_value : active_sessions_) {
1237 QuicChromiumClientSession* session = key_value.second;
1238 if (destination == all_sessions_[session].destination() &&
1239 session->CanPool(session_key.server_id().host(), session_key)) {
1240 request->SetSession(session->CreateHandle(std::move(destination)));
1246 // TODO(rtenneti): |task_runner_| is used by the Job. Initialize task_runner_
1247 // in the constructor after WebRequestActionWithThreadsTest.* tests are fixed.
1249 task_runner_ = base::SequencedTaskRunner::GetCurrentDefault().get();
1252 tick_clock_ = base::DefaultTickClock::GetInstance();
1254 QuicSessionAliasKey key(destination, session_key);
1255 std::unique_ptr<Job> job = std::make_unique<Job>(
1256 this, quic_version, host_resolver_, key,
1257 CreateCryptoConfigHandle(session_key.network_anonymization_key()),
1258 WasQuicRecentlyBroken(session_key),
1259 params_.retry_on_alternate_network_before_handshake, priority,
1260 use_dns_aliases, session_key.require_dns_https_alpn(), cert_verify_flags,
1262 int rv = job->Run(base::BindOnce(&QuicStreamFactory::OnJobComplete,
1263 weak_factory_.GetWeakPtr(), job.get()));
1264 if (rv == ERR_IO_PENDING) {
1265 job->AddRequest(request);
1266 active_jobs_[session_key] = std::move(job);
1270 auto it = active_sessions_.find(session_key);
1271 DCHECK(it != active_sessions_.end());
1272 if (it == active_sessions_.end())
1273 return ERR_QUIC_PROTOCOL_ERROR;
1274 QuicChromiumClientSession* session = it->second;
1275 request->SetSession(session->CreateHandle(std::move(destination)));
1280 void QuicStreamFactory::OnSessionGoingAway(QuicChromiumClientSession* session) {
1281 const AliasSet& aliases = session_aliases_[session];
1282 for (const auto& alias : aliases) {
1283 const QuicSessionKey& session_key = alias.session_key();
1284 DCHECK(active_sessions_.count(session_key));
1285 DCHECK_EQ(session, active_sessions_[session_key]);
1286 // Track sessions which have recently gone away so that we can disable
1287 // port suggestions.
1288 if (session->goaway_received())
1289 gone_away_aliases_.insert(alias);
1291 active_sessions_.erase(session_key);
1292 ProcessGoingAwaySession(session, session_key.server_id(), true);
1294 ProcessGoingAwaySession(session, all_sessions_[session].server_id(), false);
1295 if (!aliases.empty()) {
1296 DCHECK(base::Contains(session_peer_ip_, session));
1297 const IPEndPoint peer_address = session_peer_ip_[session];
1298 ip_aliases_[peer_address].erase(session);
1299 if (ip_aliases_[peer_address].empty())
1300 ip_aliases_.erase(peer_address);
1301 session_peer_ip_.erase(session);
1303 UnmapSessionFromSessionAliases(session);
1306 void QuicStreamFactory::OnSessionClosed(QuicChromiumClientSession* session) {
1307 DCHECK_EQ(0u, session->GetNumActiveStreams());
1308 OnSessionGoingAway(session);
1310 all_sessions_.erase(session);
1313 void QuicStreamFactory::OnBlackholeAfterHandshakeConfirmed(
1314 QuicChromiumClientSession* session) {
1315 // Reduce PING timeout when connection blackholes after the handshake.
1316 if (ping_timeout_ > reduced_ping_timeout_)
1317 ping_timeout_ = reduced_ping_timeout_;
1320 void QuicStreamFactory::CancelRequest(QuicStreamRequest* request) {
1321 auto job_iter = active_jobs_.find(request->session_key());
1322 CHECK(job_iter != active_jobs_.end());
1323 job_iter->second->RemoveRequest(request);
1326 void QuicStreamFactory::SetRequestPriority(QuicStreamRequest* request,
1327 RequestPriority priority) {
1328 auto job_iter = active_jobs_.find(request->session_key());
1329 if (job_iter == active_jobs_.end())
1331 job_iter->second->SetPriority(priority);
1334 void QuicStreamFactory::CloseAllSessions(int error,
1335 quic::QuicErrorCode quic_error) {
1336 net_log_.AddEvent(NetLogEventType::QUIC_STREAM_FACTORY_CLOSE_ALL_SESSIONS);
1337 base::UmaHistogramSparse("Net.QuicSession.CloseAllSessionsError", -error);
1338 while (!active_sessions_.empty()) {
1339 size_t initial_size = active_sessions_.size();
1340 active_sessions_.begin()->second->CloseSessionOnError(
1342 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1343 DCHECK_NE(initial_size, active_sessions_.size());
1345 while (!all_sessions_.empty()) {
1346 size_t initial_size = all_sessions_.size();
1347 all_sessions_.begin()->first->CloseSessionOnError(
1349 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1350 DCHECK_NE(initial_size, all_sessions_.size());
1352 DCHECK(all_sessions_.empty());
1355 base::Value QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
1356 base::Value::List list;
1358 for (const auto& active_session : active_sessions_) {
1359 const quic::QuicServerId& server_id = active_session.first.server_id();
1360 QuicChromiumClientSession* session = active_session.second;
1361 const AliasSet& aliases = session_aliases_.find(session)->second;
1362 // Only add a session to the list once.
1363 if (server_id == aliases.begin()->server_id()) {
1364 std::set<HostPortPair> hosts;
1365 for (const auto& alias : aliases) {
1367 HostPortPair(alias.server_id().host(), alias.server_id().port()));
1369 list.Append(session->GetInfoAsValue(hosts));
1372 return base::Value(std::move(list));
1375 void QuicStreamFactory::ClearCachedStatesInCryptoConfig(
1376 const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {
1377 ServerIdOriginFilter filter(origin_filter);
1378 for (const auto& crypto_config : active_crypto_config_map_) {
1379 crypto_config.second->config()->ClearCachedStates(filter);
1382 for (const auto& crypto_config : recent_crypto_config_map_) {
1383 crypto_config.second->config()->ClearCachedStates(filter);
1387 int QuicStreamFactory::ConnectAndConfigureSocket(
1388 CompletionOnceCallback callback,
1389 DatagramClientSocket* socket,
1391 handles::NetworkHandle network,
1392 const SocketTag& socket_tag) {
1393 socket->UseNonBlockingIO();
1396 auto split_callback = base::SplitOnceCallback(std::move(callback));
1397 CompletionOnceCallback connect_callback =
1398 base::BindOnce(&QuicStreamFactory::FinishConnectAndConfigureSocket,
1399 weak_factory_.GetWeakPtr(),
1400 std::move(split_callback.first), socket, socket_tag);
1401 if (!params_.migrate_sessions_on_network_change_v2) {
1402 rv = socket->ConnectAsync(addr, std::move(connect_callback));
1403 } else if (network == handles::kInvalidNetworkHandle) {
1404 // If caller leaves network unspecified, use current default network.
1405 rv = socket->ConnectUsingDefaultNetworkAsync(addr,
1406 std::move(connect_callback));
1408 rv = socket->ConnectUsingNetworkAsync(network, addr,
1409 std::move(connect_callback));
1411 // Both callbacks within `split_callback` will always be run asynchronously,
1412 // even if a Connect call returns synchronously. Therefore we always return
1414 if (rv != ERR_IO_PENDING) {
1415 FinishConnectAndConfigureSocket(std::move(split_callback.second), socket,
1418 return ERR_IO_PENDING;
1421 void QuicStreamFactory::FinishConnectAndConfigureSocket(
1422 CompletionOnceCallback callback,
1423 DatagramClientSocket* socket,
1424 const SocketTag& socket_tag,
1427 OnFinishConnectAndConfigureSocketError(
1428 std::move(callback), CREATION_ERROR_CONNECTING_SOCKET, rv);
1432 socket->ApplySocketTag(socket_tag);
1434 rv = socket->SetReceiveBufferSize(kQuicSocketReceiveBufferSize);
1436 OnFinishConnectAndConfigureSocketError(
1437 std::move(callback), CREATION_ERROR_SETTING_RECEIVE_BUFFER, rv);
1441 rv = socket->SetDoNotFragment();
1442 // SetDoNotFragment is not implemented on all platforms, so ignore errors.
1443 if (rv != OK && rv != ERR_NOT_IMPLEMENTED) {
1444 OnFinishConnectAndConfigureSocketError(
1445 std::move(callback), CREATION_ERROR_SETTING_DO_NOT_FRAGMENT, rv);
1449 if (base::FeatureList::IsEnabled(net::features::kReceiveEcn)) {
1450 rv = socket->SetRecvEcn();
1452 OnFinishConnectAndConfigureSocketError(
1453 std::move(callback), CREATION_ERROR_SETTING_RECEIVE_ECN, rv);
1458 // Set a buffer large enough to contain the initial CWND's worth of packet
1459 // to work around the problem with CHLO packets being sent out with the
1460 // wrong encryption level, when the send buffer is full.
1461 rv = socket->SetSendBufferSize(quic::kMaxOutgoingPacketSize * 20);
1463 OnFinishConnectAndConfigureSocketError(
1464 std::move(callback), CREATION_ERROR_SETTING_SEND_BUFFER, rv);
1468 if (params_.ios_network_service_type > 0) {
1469 socket->SetIOSNetworkServiceType(params_.ios_network_service_type);
1472 socket->GetLocalAddress(&local_address_);
1473 if (need_to_check_persisted_supports_quic_) {
1474 need_to_check_persisted_supports_quic_ = false;
1475 if (http_server_properties_->WasLastLocalAddressWhenQuicWorked(
1476 local_address_.address())) {
1477 is_quic_known_to_work_on_current_network_ = true;
1478 // Clear the persisted IP address, in case the network no longer supports
1479 // QUIC so the next restart will require confirmation. It will be
1480 // re-persisted when the first job completes successfully.
1481 http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
1485 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
1487 base::BindOnce(&QuicStreamFactory::DoCallback, weak_factory_.GetWeakPtr(),
1488 std::move(callback), rv));
1491 void QuicStreamFactory::OnFinishConnectAndConfigureSocketError(
1492 CompletionOnceCallback callback,
1493 enum CreateSessionFailure error,
1496 HistogramCreateSessionFailure(error);
1497 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
1499 base::BindOnce(&QuicStreamFactory::DoCallback, weak_factory_.GetWeakPtr(),
1500 std::move(callback), rv));
1503 void QuicStreamFactory::DoCallback(CompletionOnceCallback callback, int rv) {
1504 std::move(callback).Run(rv);
1507 int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket,
1509 handles::NetworkHandle network,
1510 const SocketTag& socket_tag) {
1511 socket->UseNonBlockingIO();
1514 if (!params_.migrate_sessions_on_network_change_v2) {
1515 rv = socket->Connect(addr);
1516 } else if (network == handles::kInvalidNetworkHandle) {
1517 // If caller leaves network unspecified, use current default network.
1518 rv = socket->ConnectUsingDefaultNetwork(addr);
1520 rv = socket->ConnectUsingNetwork(network, addr);
1523 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET);
1527 socket->ApplySocketTag(socket_tag);
1529 rv = socket->SetReceiveBufferSize(kQuicSocketReceiveBufferSize);
1531 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER);
1535 rv = socket->SetDoNotFragment();
1536 // SetDoNotFragment is not implemented on all platforms, so ignore errors.
1537 if (rv != OK && rv != ERR_NOT_IMPLEMENTED) {
1538 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_DO_NOT_FRAGMENT);
1542 if (base::FeatureList::IsEnabled(net::features::kReceiveEcn)) {
1543 rv = socket->SetRecvEcn();
1545 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_ECN);
1550 // Set a buffer large enough to contain the initial CWND's worth of packet
1551 // to work around the problem with CHLO packets being sent out with the
1552 // wrong encryption level, when the send buffer is full.
1553 rv = socket->SetSendBufferSize(quic::kMaxOutgoingPacketSize * 20);
1555 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER);
1559 if (params_.ios_network_service_type > 0) {
1560 socket->SetIOSNetworkServiceType(params_.ios_network_service_type);
1563 socket->GetLocalAddress(&local_address_);
1564 if (need_to_check_persisted_supports_quic_) {
1565 need_to_check_persisted_supports_quic_ = false;
1566 if (http_server_properties_->WasLastLocalAddressWhenQuicWorked(
1567 local_address_.address())) {
1568 is_quic_known_to_work_on_current_network_ = true;
1569 // Clear the persisted IP address, in case the network no longer supports
1570 // QUIC so the next restart will require confirmation. It will be
1571 // re-persisted when the first job completes successfully.
1572 http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
1579 handles::NetworkHandle QuicStreamFactory::FindAlternateNetwork(
1580 handles::NetworkHandle old_network) {
1581 // Find a new network that sessions bound to |old_network| can be migrated to.
1582 NetworkChangeNotifier::NetworkList network_list;
1583 NetworkChangeNotifier::GetConnectedNetworks(&network_list);
1584 for (handles::NetworkHandle new_network : network_list) {
1585 if (new_network != old_network)
1588 return handles::kInvalidNetworkHandle;
1591 std::unique_ptr<DatagramClientSocket> QuicStreamFactory::CreateSocket(
1593 const NetLogSource& source) {
1594 auto socket = client_socket_factory_->CreateDatagramClientSocket(
1595 DatagramSocket::DEFAULT_BIND, net_log, source);
1596 if (params_.enable_socket_recv_optimization)
1597 socket->EnableRecvOptimization();
1601 void QuicStreamFactory::OnIPAddressChanged() {
1602 net_log_.AddEvent(NetLogEventType::QUIC_STREAM_FACTORY_ON_IP_ADDRESS_CHANGED);
1603 CollectDataOnPlatformNotification(NETWORK_IP_ADDRESS_CHANGED,
1604 handles::kInvalidNetworkHandle);
1605 // Do nothing if connection migration is turned on.
1606 if (params_.migrate_sessions_on_network_change_v2)
1609 connectivity_monitor_.OnIPAddressChanged();
1611 set_is_quic_known_to_work_on_current_network(false);
1612 if (params_.close_sessions_on_ip_change) {
1613 CloseAllSessions(ERR_NETWORK_CHANGED, quic::QUIC_IP_ADDRESS_CHANGED);
1615 DCHECK(params_.goaway_sessions_on_ip_change);
1616 MarkAllActiveSessionsGoingAway(kIPAddressChanged);
1620 void QuicStreamFactory::OnNetworkConnected(handles::NetworkHandle network) {
1621 CollectDataOnPlatformNotification(NETWORK_CONNECTED, network);
1622 if (params_.migrate_sessions_on_network_change_v2) {
1623 net_log_.AddEventWithStringParams(
1624 NetLogEventType::QUIC_STREAM_FACTORY_PLATFORM_NOTIFICATION, "signal",
1625 "OnNetworkConnected");
1627 // Broadcast network connected to all sessions.
1628 // If migration is not turned on, session will not migrate but collect data.
1629 auto it = all_sessions_.begin();
1630 // Sessions may be deleted while iterating through the map.
1631 while (it != all_sessions_.end()) {
1632 QuicChromiumClientSession* session = it->first;
1634 session->OnNetworkConnected(network);
1638 void QuicStreamFactory::OnNetworkDisconnected(handles::NetworkHandle network) {
1639 CollectDataOnPlatformNotification(NETWORK_DISCONNECTED, network);
1640 if (params_.migrate_sessions_on_network_change_v2) {
1641 net_log_.AddEventWithStringParams(
1642 NetLogEventType::QUIC_STREAM_FACTORY_PLATFORM_NOTIFICATION, "signal",
1643 "OnNetworkDisconnected");
1645 // Broadcast network disconnected to all sessions.
1646 // If migration is not turned on, session will not migrate but collect data.
1647 auto it = all_sessions_.begin();
1648 // Sessions may be deleted while iterating through the map.
1649 while (it != all_sessions_.end()) {
1650 QuicChromiumClientSession* session = it->first;
1652 session->OnNetworkDisconnectedV2(/*disconnected_network*/ network);
1656 // This method is expected to only be called when migrating from Cellular to
1657 // WiFi on Android, and should always be preceded by OnNetworkMadeDefault().
1658 void QuicStreamFactory::OnNetworkSoonToDisconnect(
1659 handles::NetworkHandle network) {
1660 CollectDataOnPlatformNotification(NETWORK_SOON_TO_DISCONNECT, network);
1663 void QuicStreamFactory::OnNetworkMadeDefault(handles::NetworkHandle network) {
1664 CollectDataOnPlatformNotification(NETWORK_MADE_DEFAULT, network);
1665 connectivity_monitor_.OnDefaultNetworkUpdated(network);
1667 // Clear alternative services that were marked as broken until default network
1669 if (params_.retry_on_alternate_network_before_handshake &&
1670 default_network_ != handles::kInvalidNetworkHandle &&
1671 network != default_network_) {
1672 http_server_properties_->OnDefaultNetworkChanged();
1675 DCHECK_NE(handles::kInvalidNetworkHandle, network);
1676 default_network_ = network;
1678 if (params_.migrate_sessions_on_network_change_v2) {
1679 net_log_.AddEventWithStringParams(
1680 NetLogEventType::QUIC_STREAM_FACTORY_PLATFORM_NOTIFICATION, "signal",
1681 "OnNetworkMadeDefault");
1684 auto it = all_sessions_.begin();
1685 // Sessions may be deleted while iterating through the map.
1686 while (it != all_sessions_.end()) {
1687 QuicChromiumClientSession* session = it->first;
1689 session->OnNetworkMadeDefault(network);
1691 if (params_.migrate_sessions_on_network_change_v2)
1692 set_is_quic_known_to_work_on_current_network(false);
1695 void QuicStreamFactory::OnTrustStoreChanged() {
1696 // We should flush the sessions if we removed trust from a
1697 // cert, because a previously trusted server may have become
1700 // We should not flush the sessions if we added trust to a cert.
1702 // Since the OnTrustStoreChanged method doesn't tell us what
1703 // kind of change it is, we have to flush the socket
1704 // pools to be safe.
1705 MarkAllActiveSessionsGoingAway(kCertDBChanged);
1708 void QuicStreamFactory::OnCertVerifierChanged() {
1709 // Flush sessions if the CertCerifier configuration has changed.
1710 MarkAllActiveSessionsGoingAway(kCertVerifierChanged);
1713 void QuicStreamFactory::set_is_quic_known_to_work_on_current_network(
1714 bool is_quic_known_to_work_on_current_network) {
1715 is_quic_known_to_work_on_current_network_ =
1716 is_quic_known_to_work_on_current_network;
1717 if (!(local_address_ == IPEndPoint())) {
1718 if (is_quic_known_to_work_on_current_network_) {
1719 http_server_properties_->SetLastLocalAddressWhenQuicWorked(
1720 local_address_.address());
1722 http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
1727 base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob(
1728 const QuicSessionKey& session_key) {
1729 // If |is_quic_known_to_work_on_current_network_| is false, then one of the
1730 // following is true:
1731 // 1) This is startup and QuicStreamFactory::CreateSession() and
1732 // ConfigureSocket() have yet to be called, and it is not yet known
1733 // if the current network is the last one where QUIC worked.
1734 // 2) Startup has been completed, and QUIC has not been used
1735 // successfully since startup, or on this network before.
1736 if (!is_quic_known_to_work_on_current_network_) {
1737 // If |need_to_check_persisted_supports_quic_| is false, this is case 1)
1738 // above. If HasLastLocalAddressWhenQuicWorked() is also true, then there's
1739 // a chance the current network is the last one on which QUIC worked. So
1740 // only delay the request if there's no chance that is the case.
1741 if (!need_to_check_persisted_supports_quic_ ||
1742 !http_server_properties_->HasLastLocalAddressWhenQuicWorked()) {
1743 return base::TimeDelta();
1747 // QUIC was recently broken. Do not delay the main job.
1748 if (WasQuicRecentlyBroken(session_key)) {
1749 return base::TimeDelta();
1752 int64_t srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(
1753 session_key.server_id(),
1754 session_key.network_anonymization_key());
1755 // Picked 300ms based on mean time from
1756 // Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram.
1757 const int kDefaultRTT = 300 * quic::kNumMicrosPerMilli;
1760 return base::Microseconds(srtt);
1763 const std::set<std::string>& QuicStreamFactory::GetDnsAliasesForSessionKey(
1764 const QuicSessionKey& key) const {
1765 auto it = dns_aliases_by_session_key_.find(key);
1767 if (it == dns_aliases_by_session_key_.end()) {
1768 static const base::NoDestructor<std::set<std::string>> emptyvector_result;
1769 return *emptyvector_result;
1775 bool QuicStreamFactory::HasMatchingIpSession(
1776 const QuicSessionAliasKey& key,
1777 const std::vector<IPEndPoint>& ip_endpoints,
1778 const std::set<std::string>& aliases,
1779 bool use_dns_aliases) {
1780 const quic::QuicServerId& server_id(key.server_id());
1781 DCHECK(!HasActiveSession(key.session_key()));
1782 for (const auto& address : ip_endpoints) {
1783 if (!base::Contains(ip_aliases_, address))
1786 const SessionSet& sessions = ip_aliases_[address];
1787 for (QuicChromiumClientSession* session : sessions) {
1788 if (!session->CanPool(server_id.host(), key.session_key()))
1790 active_sessions_[key.session_key()] = session;
1792 std::set<std::string> dns_aliases;
1793 if (use_dns_aliases) {
1794 dns_aliases = aliases;
1797 MapSessionToAliasKey(session, key, std::move(dns_aliases));
1805 void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
1806 auto iter = active_jobs_.find(job->key().session_key());
1807 DCHECK(iter != active_jobs_.end());
1809 if (!is_quic_known_to_work_on_current_network_) {
1810 set_is_quic_known_to_work_on_current_network(true);
1813 auto session_it = active_sessions_.find(job->key().session_key());
1814 CHECK(session_it != active_sessions_.end());
1815 QuicChromiumClientSession* session = session_it->second;
1816 for (auto* request : iter->second->stream_requests()) {
1817 // Do not notify |request| yet.
1818 request->SetSession(session->CreateHandle(job->key().destination()));
1822 for (auto* request : iter->second->stream_requests()) {
1823 // Even though we're invoking callbacks here, we don't need to worry
1824 // about |this| being deleted, because the factory is owned by the
1825 // profile which can not be deleted via callbacks.
1827 job->PopulateNetErrorDetails(request->net_error_details());
1829 request->OnRequestComplete(rv);
1831 active_jobs_.erase(iter);
1834 bool QuicStreamFactory::HasActiveSession(
1835 const QuicSessionKey& session_key) const {
1836 return base::Contains(active_sessions_, session_key);
1839 bool QuicStreamFactory::HasActiveJob(const QuicSessionKey& session_key) const {
1840 return base::Contains(active_jobs_, session_key);
1843 int QuicStreamFactory::CreateSessionSync(
1844 const QuicSessionAliasKey& key,
1845 quic::ParsedQuicVersion quic_version,
1846 int cert_verify_flags,
1847 bool require_confirmation,
1848 const HostResolverEndpointResult& endpoint_result,
1849 base::TimeTicks dns_resolution_start_time,
1850 base::TimeTicks dns_resolution_end_time,
1851 const NetLogWithSource& net_log,
1852 QuicChromiumClientSession** session,
1853 handles::NetworkHandle* network) {
1854 TRACE_EVENT0(NetTracingCategory(), "QuicStreamFactory::CreateSession");
1855 // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
1857 IPEndPoint addr = endpoint_result.ip_endpoints.front();
1858 std::unique_ptr<DatagramClientSocket> socket(
1859 CreateSocket(net_log.net_log(), net_log.source()));
1861 // If migrate_sessions_on_network_change_v2 is on, passing in
1862 // handles::kInvalidNetworkHandle will bind the socket to the default network.
1863 int rv = ConfigureSocket(socket.get(), addr, *network,
1864 key.session_key().socket_tag());
1868 bool closed_during_initialize = CreateSessionHelper(
1869 key, quic_version, cert_verify_flags, require_confirmation,
1870 endpoint_result, dns_resolution_start_time, dns_resolution_end_time,
1871 net_log, session, network, std::move(socket));
1872 if (closed_during_initialize) {
1873 DLOG(DFATAL) << "Session closed during initialize";
1876 return ERR_CONNECTION_CLOSED;
1882 int QuicStreamFactory::CreateSessionAsync(
1883 CompletionOnceCallback callback,
1884 const QuicSessionAliasKey& key,
1885 quic::ParsedQuicVersion quic_version,
1886 int cert_verify_flags,
1887 bool require_confirmation,
1888 const HostResolverEndpointResult& endpoint_result,
1889 base::TimeTicks dns_resolution_start_time,
1890 base::TimeTicks dns_resolution_end_time,
1891 const NetLogWithSource& net_log,
1892 QuicChromiumClientSession** session,
1893 handles::NetworkHandle* network) {
1894 TRACE_EVENT0(NetTracingCategory(), "QuicStreamFactory::CreateSession");
1895 // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
1897 IPEndPoint addr = endpoint_result.ip_endpoints.front();
1898 std::unique_ptr<DatagramClientSocket> socket(
1899 CreateSocket(net_log.net_log(), net_log.source()));
1900 DatagramClientSocket* socket_ptr = socket.get();
1901 CompletionOnceCallback connect_and_configure_callback = base::BindOnce(
1902 &QuicStreamFactory::FinishCreateSession, weak_factory_.GetWeakPtr(),
1903 std::move(callback), key, quic_version, cert_verify_flags,
1904 require_confirmation, endpoint_result, dns_resolution_start_time,
1905 dns_resolution_end_time, net_log, session, network, std::move(socket));
1907 // If migrate_sessions_on_network_change_v2 is on, passing in
1908 // handles::kInvalidNetworkHandle will bind the socket to the default network.
1909 return ConnectAndConfigureSocket(std::move(connect_and_configure_callback),
1910 socket_ptr, addr, *network,
1911 key.session_key().socket_tag());
1914 void QuicStreamFactory::FinishCreateSession(
1915 CompletionOnceCallback callback,
1916 const QuicSessionAliasKey& key,
1917 quic::ParsedQuicVersion quic_version,
1918 int cert_verify_flags,
1919 bool require_confirmation,
1920 const HostResolverEndpointResult& endpoint_result,
1921 base::TimeTicks dns_resolution_start_time,
1922 base::TimeTicks dns_resolution_end_time,
1923 const NetLogWithSource& net_log,
1924 QuicChromiumClientSession** session,
1925 handles::NetworkHandle* network,
1926 std::unique_ptr<DatagramClientSocket> socket,
1929 std::move(callback).Run(rv);
1932 bool closed_during_initialize = CreateSessionHelper(
1933 key, quic_version, cert_verify_flags, require_confirmation,
1934 endpoint_result, dns_resolution_start_time, dns_resolution_end_time,
1935 net_log, session, network, std::move(socket));
1936 if (closed_during_initialize) {
1937 DLOG(DFATAL) << "Session closed during initialize";
1940 std::move(callback).Run(ERR_CONNECTION_CLOSED);
1944 std::move(callback).Run(OK);
1947 bool QuicStreamFactory::CreateSessionHelper(
1948 const QuicSessionAliasKey& key,
1949 quic::ParsedQuicVersion quic_version,
1950 int cert_verify_flags,
1951 bool require_confirmation,
1952 const HostResolverEndpointResult& endpoint_result,
1953 base::TimeTicks dns_resolution_start_time,
1954 base::TimeTicks dns_resolution_end_time,
1955 const NetLogWithSource& net_log,
1956 QuicChromiumClientSession** session,
1957 handles::NetworkHandle* network,
1958 std::unique_ptr<DatagramClientSocket> socket) {
1959 // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
1961 IPEndPoint addr = endpoint_result.ip_endpoints.front();
1962 const quic::QuicServerId& server_id = key.server_id();
1964 if (params_.migrate_sessions_on_network_change_v2 &&
1965 *network == handles::kInvalidNetworkHandle) {
1966 *network = socket->GetBoundNetwork();
1967 if (default_network_ == handles::kInvalidNetworkHandle) {
1968 // QuicStreamFactory may miss the default network signal before its
1969 // creation, update |default_network_| when the first socket is bound
1970 // to the default network.
1971 default_network_ = *network;
1972 connectivity_monitor_.SetInitialDefaultNetwork(default_network_);
1974 UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.DefaultNetworkMatch",
1975 default_network_ == *network);
1979 if (!helper_.get()) {
1980 helper_ = std::make_unique<QuicChromiumConnectionHelper>(clock_,
1984 if (!alarm_factory_.get()) {
1985 alarm_factory_ = std::make_unique<QuicChromiumAlarmFactory>(
1986 base::SingleThreadTaskRunner::GetCurrentDefault().get(), clock_);
1989 quic::QuicConnectionId connection_id =
1990 quic::QuicUtils::CreateRandomConnectionId(random_generator_);
1991 std::unique_ptr<QuicServerInfo> server_info;
1992 if (params_.max_server_configs_stored_in_properties > 0) {
1993 server_info = std::make_unique<PropertiesBasedQuicServerInfo>(
1994 server_id, key.session_key().network_anonymization_key(),
1995 http_server_properties_);
1997 std::unique_ptr<CryptoClientConfigHandle> crypto_config_handle =
1998 CreateCryptoConfigHandle(key.session_key().network_anonymization_key());
1999 InitializeCachedStateInCryptoConfig(*crypto_config_handle, server_id,
2002 QuicChromiumPacketWriter* writer =
2003 new QuicChromiumPacketWriter(socket.get(), task_runner_);
2004 quic::QuicConnection* connection = new quic::QuicConnection(
2005 connection_id, quic::QuicSocketAddress(), ToQuicSocketAddress(addr),
2006 helper_.get(), alarm_factory_.get(), writer, true /* owns_writer */,
2007 quic::Perspective::IS_CLIENT, {quic_version}, connection_id_generator_);
2008 connection->set_keep_alive_ping_timeout(ping_timeout_);
2009 connection->SetMaxPacketLength(params_.max_packet_length);
2011 quic::QuicConfig config = config_;
2012 ConfigureInitialRttEstimate(
2013 server_id, key.session_key().network_anonymization_key(), &config);
2015 // Use the factory to create a new socket performance watcher, and pass the
2016 // ownership to QuicChromiumClientSession.
2017 std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher;
2018 if (socket_performance_watcher_factory_) {
2019 socket_performance_watcher =
2020 socket_performance_watcher_factory_->CreateSocketPerformanceWatcher(
2021 SocketPerformanceWatcherFactory::PROTOCOL_QUIC, addr.address());
2024 // Wait for handshake confirmation before allowing streams to be created if
2025 // either this session or the factory require confirmation.
2026 if (!is_quic_known_to_work_on_current_network_) {
2027 require_confirmation = true;
2030 *session = new QuicChromiumClientSession(
2031 connection, std::move(socket), this, quic_crypto_client_stream_factory_,
2032 clock_, transport_security_state_, ssl_config_service_,
2033 std::move(server_info), key.session_key(), require_confirmation,
2034 params_.migrate_sessions_early_v2,
2035 params_.migrate_sessions_on_network_change_v2, default_network_,
2036 retransmittable_on_wire_timeout_, params_.migrate_idle_sessions,
2037 params_.allow_port_migration, params_.idle_session_migration_period,
2038 params_.max_time_on_non_default_network,
2039 params_.max_migrations_to_non_default_network_on_write_error,
2040 params_.max_migrations_to_non_default_network_on_path_degrading,
2041 yield_after_packets_, yield_after_duration_, cert_verify_flags, config,
2042 std::move(crypto_config_handle), dns_resolution_start_time,
2043 dns_resolution_end_time, tick_clock_, task_runner_,
2044 std::move(socket_performance_watcher), endpoint_result,
2047 all_sessions_[*session] = key; // owning pointer
2048 writer->set_delegate(*session);
2049 (*session)->AddConnectivityObserver(&connectivity_monitor_);
2051 (*session)->Initialize();
2052 bool closed_during_initialize = !base::Contains(all_sessions_, *session) ||
2053 !(*session)->connection()->connected();
2054 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession",
2055 closed_during_initialize);
2056 return closed_during_initialize;
2059 void QuicStreamFactory::ActivateSession(const QuicSessionAliasKey& key,
2060 QuicChromiumClientSession* session,
2061 std::set<std::string> dns_aliases) {
2062 DCHECK(!HasActiveSession(key.session_key()));
2063 UMA_HISTOGRAM_COUNTS_1M("Net.QuicActiveSessions", active_sessions_.size());
2064 active_sessions_[key.session_key()] = session;
2065 MapSessionToAliasKey(session, key, std::move(dns_aliases));
2066 const IPEndPoint peer_address =
2067 ToIPEndPoint(session->connection()->peer_address());
2068 DCHECK(!base::Contains(ip_aliases_[peer_address], session));
2069 ip_aliases_[peer_address].insert(session);
2070 DCHECK(!base::Contains(session_peer_ip_, session));
2071 session_peer_ip_[session] = peer_address;
2074 void QuicStreamFactory::MarkAllActiveSessionsGoingAway(
2075 AllActiveSessionsGoingAwayReason reason) {
2077 NetLogEventType::QUIC_STREAM_FACTORY_MARK_ALL_ACTIVE_SESSIONS_GOING_AWAY);
2078 while (!active_sessions_.empty()) {
2079 QuicChromiumClientSession* session = active_sessions_.begin()->second;
2080 // If IP address change is detected, disable session's connectivity
2081 // monitoring by remove the Delegate.
2082 if (reason == kIPAddressChanged)
2083 connectivity_monitor_.OnSessionGoingAwayOnIPAddressChange(session);
2084 OnSessionGoingAway(session);
2088 void QuicStreamFactory::ConfigureInitialRttEstimate(
2089 const quic::QuicServerId& server_id,
2090 const NetworkAnonymizationKey& network_anonymization_key,
2091 quic::QuicConfig* config) {
2092 const base::TimeDelta* srtt =
2093 GetServerNetworkStatsSmoothedRtt(server_id, network_anonymization_key);
2094 // Sometimes *srtt is negative. See https://crbug.com/1225616.
2095 // TODO(ricea): When the root cause of the negative value is fixed, change the
2096 // non-negative assertion to a DCHECK.
2097 if (srtt && srtt->is_positive()) {
2098 SetInitialRttEstimate(*srtt, INITIAL_RTT_CACHED, config);
2102 NetworkChangeNotifier::ConnectionType type =
2103 network_connection_.connection_type();
2104 if (type == NetworkChangeNotifier::CONNECTION_2G) {
2105 SetInitialRttEstimate(base::Milliseconds(1200), INITIAL_RTT_CACHED, config);
2109 if (type == NetworkChangeNotifier::CONNECTION_3G) {
2110 SetInitialRttEstimate(base::Milliseconds(400), INITIAL_RTT_CACHED, config);
2114 if (params_.initial_rtt_for_handshake.is_positive()) {
2115 SetInitialRttEstimate(
2116 base::Microseconds(params_.initial_rtt_for_handshake.InMicroseconds()),
2117 INITIAL_RTT_DEFAULT, config);
2121 SetInitialRttEstimate(base::TimeDelta(), INITIAL_RTT_DEFAULT, config);
2124 int64_t QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds(
2125 const quic::QuicServerId& server_id,
2126 const NetworkAnonymizationKey& network_anonymization_key) const {
2127 const base::TimeDelta* srtt =
2128 GetServerNetworkStatsSmoothedRtt(server_id, network_anonymization_key);
2129 return srtt == nullptr ? 0 : srtt->InMicroseconds();
2132 const base::TimeDelta* QuicStreamFactory::GetServerNetworkStatsSmoothedRtt(
2133 const quic::QuicServerId& server_id,
2134 const NetworkAnonymizationKey& network_anonymization_key) const {
2135 url::SchemeHostPort server("https", server_id.host(), server_id.port());
2136 const ServerNetworkStats* stats =
2137 http_server_properties_->GetServerNetworkStats(server,
2138 network_anonymization_key);
2139 if (stats == nullptr)
2141 return &(stats->srtt);
2144 bool QuicStreamFactory::WasQuicRecentlyBroken(
2145 const QuicSessionKey& session_key) const {
2146 const AlternativeService alternative_service(
2147 kProtoQUIC, HostPortPair(session_key.server_id().host(),
2148 session_key.server_id().port()));
2149 return http_server_properties_->WasAlternativeServiceRecentlyBroken(
2150 alternative_service, session_key.network_anonymization_key());
2153 void QuicStreamFactory::InitializeMigrationOptions() {
2154 // The following list of options cannot be set immediately until
2155 // prerequisites are met. Cache the initial setting in local variables and
2156 // reset them in |params_|.
2157 bool migrate_sessions_on_network_change =
2158 params_.migrate_sessions_on_network_change_v2;
2159 bool migrate_sessions_early = params_.migrate_sessions_early_v2;
2160 bool retry_on_alternate_network_before_handshake =
2161 params_.retry_on_alternate_network_before_handshake;
2162 bool migrate_idle_sessions = params_.migrate_idle_sessions;
2163 bool allow_port_migration = params_.allow_port_migration;
2164 params_.migrate_sessions_on_network_change_v2 = false;
2165 params_.migrate_sessions_early_v2 = false;
2166 params_.allow_port_migration = false;
2167 params_.retry_on_alternate_network_before_handshake = false;
2168 params_.migrate_idle_sessions = false;
2170 // TODO(zhongyi): deprecate |goaway_sessions_on_ip_change| if the experiment
2171 // is no longer needed.
2172 // goaway_sessions_on_ip_change and close_sessions_on_ip_change should never
2173 // be simultaneously set to true.
2174 DCHECK(!(params_.close_sessions_on_ip_change &&
2175 params_.goaway_sessions_on_ip_change));
2177 bool handle_ip_change = params_.close_sessions_on_ip_change ||
2178 params_.goaway_sessions_on_ip_change;
2179 // If IP address changes are handled explicitly, connection migration should
2181 DCHECK(!(handle_ip_change && migrate_sessions_on_network_change));
2183 if (handle_ip_change)
2184 NetworkChangeNotifier::AddIPAddressObserver(this);
2186 if (allow_port_migration) {
2187 params_.allow_port_migration = true;
2188 if (migrate_idle_sessions) {
2189 params_.migrate_idle_sessions = true;
2193 if (!NetworkChangeNotifier::AreNetworkHandlesSupported())
2196 NetworkChangeNotifier::AddNetworkObserver(this);
2197 // Perform checks on the connection migration options.
2198 if (!migrate_sessions_on_network_change) {
2199 DCHECK(!migrate_sessions_early);
2203 // Enable migration on platform notifications.
2204 params_.migrate_sessions_on_network_change_v2 = true;
2206 if (!migrate_sessions_early) {
2207 DCHECK(!retry_on_alternate_network_before_handshake);
2211 // Enable migration on path degrading.
2212 params_.migrate_sessions_early_v2 = true;
2213 // Set retransmittable on wire timeout for migration on path degrading if no
2214 // value is specified.
2215 if (retransmittable_on_wire_timeout_.IsZero()) {
2216 retransmittable_on_wire_timeout_ = quic::QuicTime::Delta::FromMicroseconds(
2217 kDefaultRetransmittableOnWireTimeout.InMicroseconds());
2220 // Enable retry on alternate network before handshake.
2221 if (retry_on_alternate_network_before_handshake)
2222 params_.retry_on_alternate_network_before_handshake = true;
2224 // Enable migration for idle sessions.
2225 if (migrate_idle_sessions)
2226 params_.migrate_idle_sessions = true;
2229 void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
2230 const CryptoClientConfigHandle& crypto_config_handle,
2231 const quic::QuicServerId& server_id,
2232 const std::unique_ptr<QuicServerInfo>& server_info) {
2233 quic::QuicCryptoClientConfig::CachedState* cached =
2234 crypto_config_handle.GetConfig()->LookupOrCreate(server_id);
2236 if (!cached->IsEmpty()) {
2240 if (!server_info || !server_info->Load()) {
2244 cached->Initialize(server_info->state().server_config,
2245 server_info->state().source_address_token,
2246 server_info->state().certs, server_info->state().cert_sct,
2247 server_info->state().chlo_hash,
2248 server_info->state().server_config_sig, clock_->WallNow(),
2249 quic::QuicWallTime::Zero());
2252 void QuicStreamFactory::ProcessGoingAwaySession(
2253 QuicChromiumClientSession* session,
2254 const quic::QuicServerId& server_id,
2255 bool session_was_active) {
2256 if (!http_server_properties_)
2259 const quic::QuicConnectionStats& stats = session->connection()->GetStats();
2260 const AlternativeService alternative_service(
2261 kProtoQUIC, HostPortPair(server_id.host(), server_id.port()));
2263 url::SchemeHostPort server("https", server_id.host(), server_id.port());
2264 // Do nothing if QUIC is currently marked as broken.
2265 if (http_server_properties_->IsAlternativeServiceBroken(
2266 alternative_service,
2267 session->quic_session_key().network_anonymization_key())) {
2271 if (session->OneRttKeysAvailable()) {
2272 http_server_properties_->ConfirmAlternativeService(
2273 alternative_service,
2274 session->quic_session_key().network_anonymization_key());
2275 ServerNetworkStats network_stats;
2276 network_stats.srtt = base::Microseconds(stats.srtt_us);
2277 network_stats.bandwidth_estimate = stats.estimated_bandwidth;
2278 http_server_properties_->SetServerNetworkStats(
2279 server, session->quic_session_key().network_anonymization_key(),
2284 http_server_properties_->ClearServerNetworkStats(
2285 server, session->quic_session_key().network_anonymization_key());
2287 UMA_HISTOGRAM_COUNTS_1M("Net.QuicHandshakeNotConfirmedNumPacketsReceived",
2288 stats.packets_received);
2290 if (!session_was_active)
2293 // TODO(rch): In the special case where the session has received no packets
2294 // from the peer, we should consider blocking this differently so that we
2295 // still race TCP but we don't consider the session connected until the
2296 // handshake has been confirmed.
2297 HistogramBrokenAlternateProtocolLocation(
2298 BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY);
2300 // Since the session was active, there's no longer an HttpStreamFactory::Job
2301 // running which can mark it broken, unless the TCP job also fails. So to
2302 // avoid not using QUIC when we otherwise could, we mark it as recently
2303 // broken, which means that 0-RTT will be disabled but we'll still race.
2304 http_server_properties_->MarkAlternativeServiceRecentlyBroken(
2305 alternative_service,
2306 session->quic_session_key().network_anonymization_key());
2309 void QuicStreamFactory::MapSessionToAliasKey(
2310 QuicChromiumClientSession* session,
2311 const QuicSessionAliasKey& key,
2312 std::set<std::string> dns_aliases) {
2313 session_aliases_[session].insert(key);
2314 dns_aliases_by_session_key_[key.session_key()] = std::move(dns_aliases);
2317 void QuicStreamFactory::UnmapSessionFromSessionAliases(
2318 QuicChromiumClientSession* session) {
2319 for (const auto& key : session_aliases_[session])
2320 dns_aliases_by_session_key_.erase(key.session_key());
2321 session_aliases_.erase(session);
2324 std::unique_ptr<QuicStreamFactory::CryptoClientConfigHandle>
2325 QuicStreamFactory::CreateCryptoConfigHandle(
2326 const NetworkAnonymizationKey& network_anonymization_key) {
2327 NetworkAnonymizationKey actual_network_anonymization_key =
2328 use_network_anonymization_key_for_crypto_configs_
2329 ? network_anonymization_key
2330 : NetworkAnonymizationKey();
2332 // If there's a matching entry in |active_crypto_config_map_|, create a
2333 // CryptoClientConfigHandle for it.
2335 active_crypto_config_map_.find(actual_network_anonymization_key);
2336 if (map_iterator != active_crypto_config_map_.end()) {
2337 DCHECK_GT(map_iterator->second->num_refs(), 0);
2339 // If there's an active matching crypto config, there shouldn't also be an
2340 // inactive matching crypto config.
2341 DCHECK(recent_crypto_config_map_.Peek(actual_network_anonymization_key) ==
2342 recent_crypto_config_map_.end());
2344 return std::make_unique<CryptoClientConfigHandle>(map_iterator);
2347 // If there's a matching entry in |recent_crypto_config_map_|, move it to
2348 // |active_crypto_config_map_| and create a CryptoClientConfigHandle for it.
2350 recent_crypto_config_map_.Peek(actual_network_anonymization_key);
2351 if (mru_iterator != recent_crypto_config_map_.end()) {
2352 DCHECK_EQ(mru_iterator->second->num_refs(), 0);
2354 map_iterator = active_crypto_config_map_
2355 .emplace(std::make_pair(actual_network_anonymization_key,
2356 std::move(mru_iterator->second)))
2358 recent_crypto_config_map_.Erase(mru_iterator);
2359 return std::make_unique<CryptoClientConfigHandle>(map_iterator);
2362 // Otherwise, create a new QuicCryptoClientConfigOwner and add it to
2363 // |active_crypto_config_map_|.
2364 std::unique_ptr<QuicCryptoClientConfigOwner> crypto_config_owner =
2365 std::make_unique<QuicCryptoClientConfigOwner>(
2366 std::make_unique<ProofVerifierChromium>(
2367 cert_verifier_, ct_policy_enforcer_, transport_security_state_,
2368 sct_auditing_delegate_,
2369 HostsFromOrigins(params_.origins_to_force_quic_on),
2370 actual_network_anonymization_key),
2371 std::make_unique<quic::QuicClientSessionCache>(), this);
2373 quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config();
2374 crypto_config->AddCanonicalSuffix(".c.youtube.com");
2375 crypto_config->AddCanonicalSuffix(".ggpht.com");
2376 crypto_config->AddCanonicalSuffix(".googlevideo.com");
2377 crypto_config->AddCanonicalSuffix(".googleusercontent.com");
2378 crypto_config->AddCanonicalSuffix(".gvt1.com");
2380 ConfigureQuicCryptoClientConfig(*crypto_config);
2382 if (!prefer_aes_gcm_recorded_) {
2383 bool prefer_aes_gcm =
2384 !crypto_config->aead.empty() && (crypto_config->aead[0] == quic::kAESG);
2385 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.PreferAesGcm", prefer_aes_gcm);
2386 prefer_aes_gcm_recorded_ = true;
2389 map_iterator = active_crypto_config_map_
2390 .emplace(std::make_pair(actual_network_anonymization_key,
2391 std::move(crypto_config_owner)))
2393 return std::make_unique<CryptoClientConfigHandle>(map_iterator);
2396 void QuicStreamFactory::OnAllCryptoClientRefReleased(
2397 QuicCryptoClientConfigMap::iterator& map_iterator) {
2398 DCHECK_EQ(0, map_iterator->second->num_refs());
2399 recent_crypto_config_map_.Put(map_iterator->first,
2400 std::move(map_iterator->second));
2401 active_crypto_config_map_.erase(map_iterator);
2404 void QuicStreamFactory::CollectDataOnPlatformNotification(
2405 enum QuicPlatformNotification notification,
2406 handles::NetworkHandle affected_network) const {
2407 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.PlatformNotification",
2408 notification, NETWORK_NOTIFICATION_MAX);
2409 connectivity_monitor_.RecordConnectivityStatsToHistograms(
2410 QuicPlatformNotificationToString(notification), affected_network);
2413 std::unique_ptr<QuicCryptoClientConfigHandle>
2414 QuicStreamFactory::GetCryptoConfigForTesting(
2415 const NetworkAnonymizationKey& network_anonymization_key) {
2416 return CreateCryptoConfigHandle(network_anonymization_key);
2419 bool QuicStreamFactory::CryptoConfigCacheIsEmptyForTesting(
2420 const quic::QuicServerId& server_id,
2421 const NetworkAnonymizationKey& network_anonymization_key) {
2422 quic::QuicCryptoClientConfig::CachedState* cached = nullptr;
2423 NetworkAnonymizationKey actual_network_anonymization_key =
2424 use_network_anonymization_key_for_crypto_configs_
2425 ? network_anonymization_key
2426 : NetworkAnonymizationKey();
2428 active_crypto_config_map_.find(actual_network_anonymization_key);
2429 if (map_iterator != active_crypto_config_map_.end()) {
2430 cached = map_iterator->second->config()->LookupOrCreate(server_id);
2433 recent_crypto_config_map_.Peek(actual_network_anonymization_key);
2434 if (mru_iterator != recent_crypto_config_map_.end()) {
2435 cached = mru_iterator->second->config()->LookupOrCreate(server_id);
2438 return !cached || cached->IsEmpty();