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_stream_factory.h"
6
7 #include <memory>
8 #include <set>
9 #include <tuple>
10 #include <utility>
11
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/ssl/cert_compression.h"
64 #include "net/ssl/ssl_key_logger.h"
65 #include "net/third_party/quiche/src/quiche/quic/core/crypto/null_decrypter.h"
66 #include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_verifier.h"
67 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_client_session_cache.h"
68 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_random.h"
69 #include "net/third_party/quiche/src/quiche/quic/core/http/quic_client_promised_info.h"
70 #include "net/third_party/quiche/src/quiche/quic/core/http/quic_client_push_promise_index.h"
71 #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h"
72 #include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h"
73 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
74 #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
75 #include "third_party/boringssl/src/include/openssl/aead.h"
76 #include "url/gurl.h"
77 #include "url/scheme_host_port.h"
78 #include "url/url_constants.h"
79
80 namespace net {
81
82 namespace {
83
84 enum InitialRttEstimateSource {
85 INITIAL_RTT_DEFAULT,
86 INITIAL_RTT_CACHED,
87 INITIAL_RTT_2G,
88 INITIAL_RTT_3G,
89 INITIAL_RTT_SOURCE_MAX,
90 };
91
92 // These values are logged to UMA. Entries should not be renumbered and
93 // numeric values should never be reused. Please keep in sync with
94 // "ConnectionStateAfterDNS" in src/tools/metrics/histograms/enums.xml.
95 enum class ConnectionStateAfterDNS {
96 kDNSFailed = 0,
97 kIpPooled = 1,
98 kWaitingForCryptoDnsMatched = 2,
99 kWaitingForCryptoDnsNoMatch = 3,
100 kCryptoFinishedDnsMatch = 4,
101 kCryptoFinishedDnsNoMatch = 5,
102 kMaxValue = kCryptoFinishedDnsNoMatch,
103 };
104
105 enum class JobProtocolErrorLocation {
106 kSessionStartReadingFailedAsync = 0,
107 kSessionStartReadingFailedSync = 1,
108 kCreateSessionFailedAsync = 2,
109 kCreateSessionFailedSync = 3,
110 kCryptoConnectFailedSync = 4,
111 kCryptoConnectFailedAsync = 5,
112 kMaxValue = kCryptoConnectFailedAsync,
113 };
114
NetLogQuicStreamFactoryJobParams(const QuicStreamFactory::QuicSessionAliasKey * key)115 base::Value::Dict NetLogQuicStreamFactoryJobParams(
116 const QuicStreamFactory::QuicSessionAliasKey* key) {
117 base::Value::Dict dict;
118 dict.Set("host", key->server_id().host());
119 dict.Set("port", key->server_id().port());
120 dict.Set("privacy_mode",
121 PrivacyModeToDebugString(key->session_key().privacy_mode()));
122 dict.Set("network_anonymization_key",
123 key->session_key().network_anonymization_key().ToDebugString());
124 return dict;
125 }
126
QuicPlatformNotificationToString(QuicPlatformNotification notification)127 std::string QuicPlatformNotificationToString(
128 QuicPlatformNotification notification) {
129 switch (notification) {
130 case NETWORK_CONNECTED:
131 return "OnNetworkConnected";
132 case NETWORK_MADE_DEFAULT:
133 return "OnNetworkMadeDefault";
134 case NETWORK_DISCONNECTED:
135 return "OnNetworkDisconnected";
136 case NETWORK_SOON_TO_DISCONNECT:
137 return "OnNetworkSoonToDisconnect";
138 case NETWORK_IP_ADDRESS_CHANGED:
139 return "OnIPAddressChanged";
140 default:
141 QUICHE_NOTREACHED();
142 break;
143 }
144 return "InvalidNotification";
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
HistogramProtocolErrorLocation(enum JobProtocolErrorLocation location)152 void HistogramProtocolErrorLocation(enum JobProtocolErrorLocation location) {
153 UMA_HISTOGRAM_ENUMERATION("Net.QuicStreamFactory.DoConnectFailureLocation",
154 location);
155 }
156
LogConnectionIpPooling(bool pooled)157 void LogConnectionIpPooling(bool pooled) {
158 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectionIpPooled", pooled);
159 }
160
LogRacingStatus(ConnectionStateAfterDNS status)161 void LogRacingStatus(ConnectionStateAfterDNS status) {
162 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionStateAfterDNS", status);
163 }
164
LogStaleConnectionTime(base::TimeTicks start_time)165 void LogStaleConnectionTime(base::TimeTicks start_time) {
166 UMA_HISTOGRAM_TIMES("Net.QuicSession.StaleConnectionTime",
167 base::TimeTicks::Now() - start_time);
168 }
169
LogValidConnectionTime(base::TimeTicks start_time)170 void LogValidConnectionTime(base::TimeTicks start_time) {
171 UMA_HISTOGRAM_TIMES("Net.QuicSession.ValidConnectionTime",
172 base::TimeTicks::Now() - start_time);
173 }
174
LogFreshDnsResolveTime(base::TimeTicks start_time)175 void LogFreshDnsResolveTime(base::TimeTicks start_time) {
176 UMA_HISTOGRAM_TIMES("Net.QuicSession.FreshDnsResolutionTime",
177 base::TimeTicks::Now() - start_time);
178 }
179
SetInitialRttEstimate(base::TimeDelta estimate,enum InitialRttEstimateSource source,quic::QuicConfig * config)180 void SetInitialRttEstimate(base::TimeDelta estimate,
181 enum InitialRttEstimateSource source,
182 quic::QuicConfig* config) {
183 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.InitialRttEsitmateSource", source,
184 INITIAL_RTT_SOURCE_MAX);
185 if (estimate != base::TimeDelta())
186 config->SetInitialRoundTripTimeUsToSend(
187 base::checked_cast<uint64_t>(estimate.InMicroseconds()));
188 }
189
190 // An implementation of quic::QuicCryptoClientConfig::ServerIdFilter that wraps
191 // an |origin_filter|.
192 class ServerIdOriginFilter
193 : public quic::QuicCryptoClientConfig::ServerIdFilter {
194 public:
ServerIdOriginFilter(const base::RepeatingCallback<bool (const GURL &)> origin_filter)195 explicit ServerIdOriginFilter(
196 const base::RepeatingCallback<bool(const GURL&)> origin_filter)
197 : origin_filter_(origin_filter) {}
198
Matches(const quic::QuicServerId & server_id) const199 bool Matches(const quic::QuicServerId& server_id) const override {
200 if (origin_filter_.is_null())
201 return true;
202
203 GURL url(base::StringPrintf("%s%s%s:%d", url::kHttpsScheme,
204 url::kStandardSchemeSeparator,
205 server_id.host().c_str(), server_id.port()));
206 DCHECK(url.is_valid());
207 return origin_filter_.Run(url);
208 }
209
210 private:
211 const base::RepeatingCallback<bool(const GURL&)> origin_filter_;
212 };
213
HostsFromOrigins(std::set<HostPortPair> origins)214 std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) {
215 std::set<std::string> hosts;
216 for (const auto& origin : origins) {
217 hosts.insert(origin.host());
218 }
219 return hosts;
220 }
221
222 } // namespace
223
224 // Refcounted class that owns quic::QuicCryptoClientConfig and tracks how many
225 // consumers are using it currently. When the last reference is freed, the
226 // QuicCryptoClientConfigHandle informs the owning QuicStreamFactory, moves it
227 // into an MRU cache.
228 class QuicStreamFactory::QuicCryptoClientConfigOwner {
229 public:
QuicCryptoClientConfigOwner(std::unique_ptr<quic::ProofVerifier> proof_verifier,std::unique_ptr<quic::QuicClientSessionCache> session_cache,QuicStreamFactory * quic_stream_factory)230 QuicCryptoClientConfigOwner(
231 std::unique_ptr<quic::ProofVerifier> proof_verifier,
232 std::unique_ptr<quic::QuicClientSessionCache> session_cache,
233 QuicStreamFactory* quic_stream_factory)
234 : config_(std::move(proof_verifier), std::move(session_cache)),
235 clock_(base::DefaultClock::GetInstance()),
236 quic_stream_factory_(quic_stream_factory) {
237 DCHECK(quic_stream_factory_);
238 memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
239 FROM_HERE,
240 base::BindRepeating(&QuicCryptoClientConfigOwner::OnMemoryPressure,
241 base::Unretained(this)));
242 }
243
244 QuicCryptoClientConfigOwner(const QuicCryptoClientConfigOwner&) = delete;
245 QuicCryptoClientConfigOwner& operator=(const QuicCryptoClientConfigOwner&) =
246 delete;
247
~QuicCryptoClientConfigOwner()248 ~QuicCryptoClientConfigOwner() { DCHECK_EQ(num_refs_, 0); }
249
config()250 quic::QuicCryptoClientConfig* config() { return &config_; }
251
num_refs() const252 int num_refs() const { return num_refs_; }
253
quic_stream_factory()254 QuicStreamFactory* quic_stream_factory() { return quic_stream_factory_; }
255
OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level)256 void OnMemoryPressure(
257 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
258 quic::SessionCache* session_cache = config_.mutable_session_cache();
259 if (!session_cache) {
260 return;
261 }
262 time_t now = clock_->Now().ToTimeT();
263 uint64_t now_u64 = 0;
264 if (now > 0) {
265 now_u64 = static_cast<uint64_t>(now);
266 }
267 switch (memory_pressure_level) {
268 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
269 break;
270 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
271 session_cache->RemoveExpiredEntries(
272 quic::QuicWallTime::FromUNIXSeconds(now_u64));
273 break;
274 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
275 session_cache->Clear();
276 break;
277 }
278 }
279
280 private:
281 friend class CryptoClientConfigHandle;
282
283 // Simple ref counting. Not using scoped_refptr allows for both keeping around
284 // an MRU cache of 0-reference objects, and DCHECKing that there are no
285 // outstanding referenced QuicCryptoClientConfigOwner on destruction. Private
286 // so that only CryptoClientConfigHandle can add and remove refs.
287
AddRef()288 void AddRef() { num_refs_++; }
289
ReleaseRef()290 void ReleaseRef() {
291 DCHECK_GT(num_refs_, 0);
292 num_refs_--;
293 }
294
295 int num_refs_ = 0;
296 quic::QuicCryptoClientConfig config_;
297 raw_ptr<base::Clock> clock_;
298 std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
299 const raw_ptr<QuicStreamFactory> quic_stream_factory_;
300 };
301
302 // Class that owns a reference to a QuicCryptoClientConfigOwner. Handles
303 // incrementing the refcount on construction, and decrementing it on
304 // destruction.
305 class QuicStreamFactory::CryptoClientConfigHandle
306 : public QuicCryptoClientConfigHandle {
307 public:
CryptoClientConfigHandle(const QuicCryptoClientConfigMap::iterator & map_iterator)308 explicit CryptoClientConfigHandle(
309 const QuicCryptoClientConfigMap::iterator& map_iterator)
310 : map_iterator_(map_iterator) {
311 DCHECK_GE(map_iterator_->second->num_refs(), 0);
312 map_iterator->second->AddRef();
313 }
314
CryptoClientConfigHandle(const CryptoClientConfigHandle & other)315 CryptoClientConfigHandle(const CryptoClientConfigHandle& other)
316 : CryptoClientConfigHandle(other.map_iterator_) {}
317
318 CryptoClientConfigHandle& operator=(const CryptoClientConfigHandle&) = delete;
319
~CryptoClientConfigHandle()320 ~CryptoClientConfigHandle() override {
321 DCHECK_GT(map_iterator_->second->num_refs(), 0);
322 map_iterator_->second->ReleaseRef();
323 if (map_iterator_->second->num_refs() == 0) {
324 map_iterator_->second->quic_stream_factory()
325 ->OnAllCryptoClientRefReleased(map_iterator_);
326 }
327 }
328
GetConfig() const329 quic::QuicCryptoClientConfig* GetConfig() const override {
330 return map_iterator_->second->config();
331 }
332
333 private:
334 QuicCryptoClientConfigMap::iterator map_iterator_;
335 };
336
337 // Responsible for creating a new QUIC session to the specified server, and
338 // for notifying any associated requests when complete. |client_config_handle|
339 // is not actually used, but serves to keep the corresponding CryptoClientConfig
340 // alive until the Job completes.
341 class QuicStreamFactory::Job {
342 public:
343 Job(QuicStreamFactory* factory,
344 quic::ParsedQuicVersion quic_version,
345 HostResolver* host_resolver,
346 const QuicSessionAliasKey& key,
347 std::unique_ptr<CryptoClientConfigHandle> client_config_handle,
348 bool was_alternative_service_recently_broken,
349 bool retry_on_alternate_network_before_handshake,
350 bool race_stale_dns_on_connection,
351 RequestPriority priority,
352 bool use_dns_aliases,
353 bool require_dns_https_alpn,
354 int cert_verify_flags,
355 const NetLogWithSource& net_log);
356
357 Job(const Job&) = delete;
358 Job& operator=(const Job&) = delete;
359
360 ~Job();
361
362 int Run(CompletionOnceCallback callback);
363
364 int DoLoop(int rv);
365 int DoResolveHost();
366 int DoResolveHostComplete(int rv);
367 int DoCreateSession();
368 int DoCreateSessionComplete(int rv);
369 int DoConnect(int rv);
370 int DoConnectComplete(int rv);
371 int DoConfirmConnection(int rv);
372 int DoValidateHost();
373
374 void OnCreateSessionComplete(int rv);
375 void MaybeOnQuicSessionCreationComplete(int rv);
376 void OnResolveHostComplete(int rv);
377 void OnCryptoConnectComplete(int rv);
378 void OnSessionClosed(QuicChromiumClientSession* session);
379
key() const380 const QuicSessionAliasKey& key() const { return key_; }
381
net_log() const382 const NetLogWithSource& net_log() const { return net_log_; }
383
GetWeakPtr()384 base::WeakPtr<Job> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
385
386 void PopulateNetErrorDetails(NetErrorDetails* details) const;
387
AddRequest(QuicStreamRequest * request)388 void AddRequest(QuicStreamRequest* request) {
389 stream_requests_.insert(request);
390 if (!host_resolution_finished_) {
391 request->ExpectOnHostResolution();
392 }
393 // Callers do not need to wait for OnQuicSessionCreationComplete if the
394 // kAsyncQuicSession flag is not set because session creation will be fully
395 // synchronous, so no need to call ExpectQuicSessionCreation.
396 if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) {
397 request->ExpectQuicSessionCreation();
398 }
399 }
400
RemoveRequest(QuicStreamRequest * request)401 void RemoveRequest(QuicStreamRequest* request) {
402 auto request_iter = stream_requests_.find(request);
403 DCHECK(request_iter != stream_requests_.end());
404 stream_requests_.erase(request_iter);
405 }
406
SetPriority(RequestPriority priority)407 void SetPriority(RequestPriority priority) {
408 if (priority_ == priority)
409 return;
410
411 priority_ = priority;
412 if (resolve_host_request_ && !host_resolution_finished_) {
413 if (fresh_resolve_host_request_) {
414 fresh_resolve_host_request_->ChangeRequestPriority(priority);
415 } else {
416 resolve_host_request_->ChangeRequestPriority(priority);
417 }
418 }
419 }
420
stream_requests()421 const std::set<QuicStreamRequest*>& stream_requests() {
422 return stream_requests_;
423 }
424
priority() const425 RequestPriority priority() const { return priority_; }
426
427 private:
428 enum IoState {
429 STATE_NONE,
430 STATE_RESOLVE_HOST,
431 STATE_RESOLVE_HOST_COMPLETE,
432 STATE_CREATE_SESSION,
433 STATE_CREATE_SESSION_COMPLETE,
434 STATE_CONNECT,
435 STATE_CONNECT_COMPLETE,
436 STATE_HOST_VALIDATION,
437 STATE_CONFIRM_CONNECTION,
438 };
439
CloseStaleHostConnection()440 void CloseStaleHostConnection() {
441 DVLOG(1) << "Closing connection from stale host.";
442 if (session_) {
443 QuicChromiumClientSession* session = session_;
444 session_ = nullptr;
445 // Use ERR_FAILED instead of ERR_ABORTED out of paranoia - ERR_ABORTED
446 // should only be used when the next layer up cancels a request, and has
447 // special semantic meaning for some consumers when they see it.
448 session->CloseSessionOnErrorLater(
449 ERR_FAILED, quic::QUIC_STALE_CONNECTION_CANCELLED,
450 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
451 }
452 }
453
DoesConnectionMatchFreshHostResolution()454 bool DoesConnectionMatchFreshHostResolution() {
455 if (!session_)
456 return false;
457
458 DCHECK(quic_version_used_.IsKnown());
459 IPEndPoint stale_address = endpoint_result_.ip_endpoints.front();
460 bool svcb_optional =
461 IsSvcbOptional(*fresh_resolve_host_request_->GetEndpointResults());
462 for (const auto& candidate :
463 *fresh_resolve_host_request_->GetEndpointResults()) {
464 // TODO(https://crbug.com/1416963): Should other values also be checked
465 // for consistency?
466 if (SelectQuicVersion(candidate, svcb_optional) == quic_version_used_ &&
467 base::Contains(candidate.ip_endpoints, stale_address)) {
468 return true;
469 }
470 }
471
472 return false;
473 }
474
475 // Returns whether the client should be SVCB-optional when connecting to
476 // `results`.
IsSvcbOptional(base::span<const HostResolverEndpointResult> results) const477 bool IsSvcbOptional(
478 base::span<const HostResolverEndpointResult> results) const {
479 // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all
480 // routes support ECH, disable the A/AAAA fallback. See Section 10.1 of
481 // draft-ietf-dnsop-svcb-https-11.
482 if (!factory_->ssl_config_service_->GetSSLContextConfig()
483 .EncryptedClientHelloEnabled() ||
484 !base::FeatureList::IsEnabled(features::kEncryptedClientHelloQuic)) {
485 return true; // ECH is not supported for this request.
486 }
487
488 return !HostResolver::AllProtocolEndpointsHaveEch(results);
489 }
490
491 // Returns the QUIC version that would be used with `endpoint_result`, or
492 // `quic::ParsedQuicVersion::Unsupported()` if `endpoint_result` cannot be
493 // used with QUIC.
SelectQuicVersion(const HostResolverEndpointResult & endpoint_result,bool svcb_optional) const494 quic::ParsedQuicVersion SelectQuicVersion(
495 const HostResolverEndpointResult& endpoint_result,
496 bool svcb_optional) const {
497 // TODO(davidben): `require_dns_https_alpn_` only exists to be `DCHECK`ed
498 // for consistency against `quic_version_`. Remove the parameter?
499 DCHECK_EQ(require_dns_https_alpn_, !quic_version_.IsKnown());
500
501 if (endpoint_result.metadata.supported_protocol_alpns.empty()) {
502 // `endpoint_result` came from A/AAAA records directly, without HTTPS/SVCB
503 // records. If we know the QUIC ALPN to use externally, i.e. via Alt-Svc,
504 // use it in SVCB-optional mode. Otherwise, `endpoint_result` is not
505 // eligible for QUIC.
506 return svcb_optional ? quic_version_
507 : quic::ParsedQuicVersion::Unsupported();
508 }
509
510 // Otherwise, `endpoint_result` came from an HTTPS/SVCB record. We can use
511 // QUIC if a suitable match is found in the record's ALPN list.
512 // Additionally, if this connection attempt came from Alt-Svc, the DNS
513 // result must be consistent with it. See
514 // https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-11.html#name-interaction-with-alt-svc
515 if (quic_version_.IsKnown()) {
516 std::string expected_alpn = quic::AlpnForVersion(quic_version_);
517 if (base::Contains(endpoint_result.metadata.supported_protocol_alpns,
518 quic::AlpnForVersion(quic_version_))) {
519 return quic_version_;
520 }
521 return quic::ParsedQuicVersion::Unsupported();
522 }
523
524 for (const auto& alpn : endpoint_result.metadata.supported_protocol_alpns) {
525 for (const auto& supported_version : factory_->supported_versions()) {
526 if (alpn == AlpnForVersion(supported_version)) {
527 return supported_version;
528 }
529 }
530 }
531
532 return quic::ParsedQuicVersion::Unsupported();
533 }
534
LogStaleHostRacing(bool used)535 void LogStaleHostRacing(bool used) {
536 if (used) {
537 net_log_.AddEvent(
538 NetLogEventType::
539 QUIC_STREAM_FACTORY_JOB_STALE_HOST_TRIED_ON_CONNECTION);
540 } else {
541 net_log_.AddEvent(
542 NetLogEventType::
543 QUIC_STREAM_FACTORY_JOB_STALE_HOST_NOT_USED_ON_CONNECTION);
544 }
545 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StaleHostRacing", used);
546 }
547
LogStaleAndFreshHostMatched(bool matched)548 void LogStaleAndFreshHostMatched(bool matched) {
549 if (matched) {
550 net_log_.AddEvent(
551 NetLogEventType::
552 QUIC_STREAM_FACTORY_JOB_STALE_HOST_RESOLUTION_MATCHED);
553 } else {
554 net_log_.AddEvent(
555 NetLogEventType::
556 QUIC_STREAM_FACTORY_JOB_STALE_HOST_RESOLUTION_NO_MATCH);
557 }
558 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StaleAndFreshHostMatched", matched);
559 }
560
561 IoState io_state_ = STATE_RESOLVE_HOST;
562 raw_ptr<QuicStreamFactory> factory_;
563 quic::ParsedQuicVersion quic_version_;
564 quic::ParsedQuicVersion quic_version_used_ =
565 quic::ParsedQuicVersion::Unsupported();
566 raw_ptr<HostResolver> host_resolver_;
567 const QuicSessionAliasKey key_;
568 const std::unique_ptr<CryptoClientConfigHandle> client_config_handle_;
569 RequestPriority priority_;
570 const bool use_dns_aliases_;
571 const bool require_dns_https_alpn_;
572 const int cert_verify_flags_;
573 const bool was_alternative_service_recently_broken_;
574 const bool retry_on_alternate_network_before_handshake_;
575 const bool race_stale_dns_on_connection_;
576 const NetLogWithSource net_log_;
577 bool create_session_on_stale_dns_ = false;
578 bool host_resolution_finished_ = false;
579 bool quic_session_created_ = false;
580 bool connection_retried_ = false;
581 // This field is not a raw_ptr<> because it was filtered by the rewriter for:
582 // #addr-of
583 RAW_PTR_EXCLUSION QuicChromiumClientSession* session_ = nullptr;
584 HostResolverEndpointResult endpoint_result_;
585 // If connection migraiton is supported, |network_| denotes the network on
586 // which |session_| is created.
587 handles::NetworkHandle network_;
588 CompletionOnceCallback host_resolution_callback_;
589 CompletionOnceCallback callback_;
590 std::unique_ptr<HostResolver::ResolveHostRequest> resolve_host_request_;
591 // Only set during DNS race. After completion, cleared or replaces
592 // |resolve_host_request_|.
593 std::unique_ptr<HostResolver::ResolveHostRequest> fresh_resolve_host_request_;
594 base::TimeTicks dns_resolution_start_time_;
595 base::TimeTicks dns_resolution_end_time_;
596 base::TimeTicks quic_connection_start_time_;
597 std::set<QuicStreamRequest*> stream_requests_;
598 base::WeakPtrFactory<Job> weak_factory_{this};
599 };
600
Job(QuicStreamFactory * factory,quic::ParsedQuicVersion quic_version,HostResolver * host_resolver,const QuicSessionAliasKey & key,std::unique_ptr<CryptoClientConfigHandle> client_config_handle,bool was_alternative_service_recently_broken,bool retry_on_alternate_network_before_handshake,bool race_stale_dns_on_connection,RequestPriority priority,bool use_dns_aliases,bool require_dns_https_alpn,int cert_verify_flags,const NetLogWithSource & net_log)601 QuicStreamFactory::Job::Job(
602 QuicStreamFactory* factory,
603 quic::ParsedQuicVersion quic_version,
604 HostResolver* host_resolver,
605 const QuicSessionAliasKey& key,
606 std::unique_ptr<CryptoClientConfigHandle> client_config_handle,
607 bool was_alternative_service_recently_broken,
608 bool retry_on_alternate_network_before_handshake,
609 bool race_stale_dns_on_connection,
610 RequestPriority priority,
611 bool use_dns_aliases,
612 bool require_dns_https_alpn,
613 int cert_verify_flags,
614 const NetLogWithSource& net_log)
615 : factory_(factory),
616 quic_version_(quic_version),
617 host_resolver_(host_resolver),
618 key_(key),
619 client_config_handle_(std::move(client_config_handle)),
620 priority_(priority),
621 use_dns_aliases_(use_dns_aliases),
622 require_dns_https_alpn_(require_dns_https_alpn),
623 cert_verify_flags_(cert_verify_flags),
624 was_alternative_service_recently_broken_(
625 was_alternative_service_recently_broken),
626 retry_on_alternate_network_before_handshake_(
627 retry_on_alternate_network_before_handshake),
628 race_stale_dns_on_connection_(race_stale_dns_on_connection),
629 net_log_(
630 NetLogWithSource::Make(net_log.net_log(),
631 NetLogSourceType::QUIC_STREAM_FACTORY_JOB)),
632 network_(handles::kInvalidNetworkHandle) {
633 DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn);
634 net_log_.BeginEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB,
635 [&] { return NetLogQuicStreamFactoryJobParams(&key_); });
636 // Associate |net_log_| with |net_log|.
637 net_log_.AddEventReferencingSource(
638 NetLogEventType::QUIC_STREAM_FACTORY_JOB_BOUND_TO_HTTP_STREAM_JOB,
639 net_log.source());
640 net_log.AddEventReferencingSource(
641 NetLogEventType::HTTP_STREAM_JOB_BOUND_TO_QUIC_STREAM_FACTORY_JOB,
642 net_log_.source());
643 }
644
~Job()645 QuicStreamFactory::Job::~Job() {
646 net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB);
647 // If |this| is destroyed in QuicStreamFactory's destructor, |callback_| is
648 // non-null.
649 }
650
Run(CompletionOnceCallback callback)651 int QuicStreamFactory::Job::Run(CompletionOnceCallback callback) {
652 int rv = DoLoop(OK);
653 if (rv == ERR_IO_PENDING)
654 callback_ = std::move(callback);
655
656 return rv > 0 ? OK : rv;
657 }
658
DoLoop(int rv)659 int QuicStreamFactory::Job::DoLoop(int rv) {
660 TRACE_EVENT0(NetTracingCategory(), "QuicStreamFactory::Job::DoLoop");
661
662 do {
663 IoState state = io_state_;
664 io_state_ = STATE_NONE;
665 switch (state) {
666 case STATE_RESOLVE_HOST:
667 CHECK_EQ(OK, rv);
668 rv = DoResolveHost();
669 break;
670 case STATE_RESOLVE_HOST_COMPLETE:
671 rv = DoResolveHostComplete(rv);
672 break;
673 case STATE_CREATE_SESSION:
674 rv = DoCreateSession();
675 break;
676 case STATE_CREATE_SESSION_COMPLETE:
677 rv = DoCreateSessionComplete(rv);
678 break;
679 case STATE_CONNECT:
680 rv = DoConnect(rv);
681 break;
682 case STATE_CONNECT_COMPLETE:
683 rv = DoConnectComplete(rv);
684 break;
685 case STATE_HOST_VALIDATION:
686 rv = DoValidateHost();
687 break;
688 case STATE_CONFIRM_CONNECTION:
689 rv = DoConfirmConnection(rv);
690 break;
691 default:
692 NOTREACHED() << "io_state_: " << io_state_;
693 break;
694 }
695 } while (io_state_ != STATE_NONE && rv != ERR_IO_PENDING);
696 return rv;
697 }
698
OnSessionClosed(QuicChromiumClientSession * session)699 void QuicStreamFactory::Job::OnSessionClosed(
700 QuicChromiumClientSession* session) {
701 // When dns racing experiment is on, the job needs to know that the stale
702 // session is closed so that it will start the fresh session without matching
703 // dns results.
704 if (io_state_ == STATE_HOST_VALIDATION && session_ == session) {
705 DCHECK(race_stale_dns_on_connection_);
706 DCHECK(fresh_resolve_host_request_);
707 resolve_host_request_ = std::move(fresh_resolve_host_request_);
708 session_ = nullptr;
709 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
710 }
711 }
712
OnResolveHostComplete(int rv)713 void QuicStreamFactory::Job::OnResolveHostComplete(int rv) {
714 DCHECK(!host_resolution_finished_);
715
716 LogFreshDnsResolveTime(dns_resolution_start_time_);
717
718 if (fresh_resolve_host_request_) {
719 DCHECK(race_stale_dns_on_connection_);
720 dns_resolution_end_time_ = base::TimeTicks::Now();
721 if (rv != OK) {
722 LogRacingStatus(ConnectionStateAfterDNS::kDNSFailed);
723 CloseStaleHostConnection();
724 resolve_host_request_ = std::move(fresh_resolve_host_request_);
725 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
726 } else if (factory_->HasMatchingIpSession(
727 key_,
728 HostResolver::GetNonProtocolEndpoints(
729 *fresh_resolve_host_request_->GetEndpointResults()),
730 *fresh_resolve_host_request_->GetDnsAliasResults(),
731 use_dns_aliases_)) {
732 // TODO(crbug.com/1264933): Consider dealing with the other
733 // endpoints with protocol metadata.
734
735 // Session with resolved IP has already existed, so close racing
736 // connection, run callback, and return.
737 LogRacingStatus(ConnectionStateAfterDNS::kIpPooled);
738 LogConnectionIpPooling(true);
739 CloseStaleHostConnection();
740 if (!callback_.is_null())
741 std::move(callback_).Run(OK);
742 return;
743 } else if (io_state_ != STATE_HOST_VALIDATION) {
744 // Case where host resolution returns successfully, but stale connection
745 // hasn't finished yet.
746 if (DoesConnectionMatchFreshHostResolution()) {
747 LogRacingStatus(ConnectionStateAfterDNS::kWaitingForCryptoDnsMatched);
748 LogStaleAndFreshHostMatched(true);
749 fresh_resolve_host_request_ = nullptr;
750 return;
751 }
752 LogRacingStatus(ConnectionStateAfterDNS::kWaitingForCryptoDnsNoMatch);
753 LogStaleAndFreshHostMatched(false);
754 CloseStaleHostConnection();
755 resolve_host_request_ = std::move(fresh_resolve_host_request_);
756 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
757 } // Else stale connection has already finished successfully.
758 } else {
759 // If not in DNS race, we should have been waiting for this callback in
760 // STATE_RESOLVE_HOST_COMPLETE.
761 DCHECK_EQ(STATE_RESOLVE_HOST_COMPLETE, io_state_);
762 }
763
764 rv = DoLoop(rv);
765
766 // Expect to be marked by either DoResolveHostComplete() or DoValidateHost().
767 DCHECK(host_resolution_finished_);
768
769 // DNS race should be completed either above or by DoValidateHost().
770 DCHECK(!fresh_resolve_host_request_);
771
772 for (auto* request : stream_requests_) {
773 request->OnHostResolutionComplete(rv);
774 }
775
776 if (rv != ERR_IO_PENDING && !callback_.is_null())
777 std::move(callback_).Run(rv);
778 }
779
OnCryptoConnectComplete(int rv)780 void QuicStreamFactory::Job::OnCryptoConnectComplete(int rv) {
781 // This early return will be triggered when CloseSessionOnError is called
782 // before crypto handshake has completed.
783 if (!session_) {
784 LogStaleConnectionTime(quic_connection_start_time_);
785 return;
786 }
787
788 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
789 HistogramProtocolErrorLocation(
790 JobProtocolErrorLocation::kCryptoConnectFailedAsync);
791 }
792
793 io_state_ = STATE_CONNECT_COMPLETE;
794 rv = DoLoop(rv);
795 if (rv != ERR_IO_PENDING && !callback_.is_null())
796 std::move(callback_).Run(rv);
797 }
798
PopulateNetErrorDetails(NetErrorDetails * details) const799 void QuicStreamFactory::Job::PopulateNetErrorDetails(
800 NetErrorDetails* details) const {
801 if (!session_)
802 return;
803 details->connection_info = QuicHttpStream::ConnectionInfoFromQuicVersion(
804 session_->connection()->version());
805 details->quic_connection_error = session_->error();
806 }
807
DoResolveHost()808 int QuicStreamFactory::Job::DoResolveHost() {
809 dns_resolution_start_time_ = base::TimeTicks::Now();
810
811 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
812
813 HostResolver::ResolveHostParameters parameters;
814 parameters.initial_priority = priority_;
815 if (race_stale_dns_on_connection_) {
816 // Allow host resolver to return stale result immediately.
817 parameters.cache_usage =
818 HostResolver::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
819 }
820 parameters.secure_dns_policy = key_.session_key().secure_dns_policy();
821 resolve_host_request_ = host_resolver_->CreateRequest(
822 key_.destination(), key_.session_key().network_anonymization_key(),
823 net_log_, parameters);
824 // Unretained is safe because |this| owns the request, ensuring cancellation
825 // on destruction.
826 // When race_stale_dns_on_connection_ is on, this request will query for stale
827 // cache if no fresh host result is available.
828 int rv = resolve_host_request_->Start(base::BindOnce(
829 &QuicStreamFactory::Job::OnResolveHostComplete, base::Unretained(this)));
830
831 if (rv == ERR_IO_PENDING || !resolve_host_request_->GetStaleInfo() ||
832 !resolve_host_request_->GetStaleInfo().value().is_stale()) {
833 // Returns non-stale result synchronously.
834 if (rv != ERR_IO_PENDING) {
835 LogFreshDnsResolveTime(dns_resolution_start_time_);
836 }
837 // Not a stale result.
838 if (race_stale_dns_on_connection_)
839 LogStaleHostRacing(false);
840 return rv;
841 }
842
843 // If request resulted in a stale cache entry, start request for fresh results
844 DCHECK(race_stale_dns_on_connection_);
845
846 parameters.cache_usage =
847 HostResolver::ResolveHostParameters::CacheUsage::DISALLOWED;
848 fresh_resolve_host_request_ = host_resolver_->CreateRequest(
849 key_.destination(), key_.session_key().network_anonymization_key(),
850 net_log_, parameters);
851 // Unretained is safe because |this| owns the request, ensuring cancellation
852 // on destruction.
853 // This request will only query fresh host resolution.
854 int fresh_rv = fresh_resolve_host_request_->Start(base::BindOnce(
855 &QuicStreamFactory::Job::OnResolveHostComplete, base::Unretained(this)));
856 if (fresh_rv != ERR_IO_PENDING) {
857 // Fresh request returned immediate results.
858 LogFreshDnsResolveTime(dns_resolution_start_time_);
859 LogStaleHostRacing(false);
860 resolve_host_request_ = std::move(fresh_resolve_host_request_);
861 return fresh_rv;
862 }
863
864 // Check to make sure stale host request does produce valid results.
865 if (!resolve_host_request_->GetEndpointResults()) {
866 LogStaleHostRacing(false);
867 resolve_host_request_ = std::move(fresh_resolve_host_request_);
868 return fresh_rv;
869 }
870
871 // No fresh host resolution is available at this time, but there is available
872 // stale result. End time for stale host resolution is recorded and connection
873 // from stale host will be tried.
874 dns_resolution_end_time_ = base::TimeTicks().Now();
875 io_state_ = STATE_CREATE_SESSION;
876 create_session_on_stale_dns_ = true;
877 LogStaleHostRacing(true);
878 return OK;
879 }
880
DoResolveHostComplete(int rv)881 int QuicStreamFactory::Job::DoResolveHostComplete(int rv) {
882 host_resolution_finished_ = true;
883 dns_resolution_end_time_ = base::TimeTicks::Now();
884 if (rv != OK)
885 return rv;
886
887 DCHECK(!fresh_resolve_host_request_);
888 DCHECK(!factory_->HasActiveSession(key_.session_key()));
889
890 // Inform the factory of this resolution, which will set up
891 // a session alias, if possible.
892 // TODO(crbug.com/1264933): Consider dealing with the other endpoints
893 // with protocol metadata.
894 if (factory_->HasMatchingIpSession(
895 key_,
896 HostResolver::GetNonProtocolEndpoints(
897 *resolve_host_request_->GetEndpointResults()),
898 *resolve_host_request_->GetDnsAliasResults(), use_dns_aliases_)) {
899 LogConnectionIpPooling(true);
900 return OK;
901 }
902 io_state_ = STATE_CREATE_SESSION;
903 return OK;
904 }
905
OnCreateSessionComplete(int rv)906 void QuicStreamFactory::Job::OnCreateSessionComplete(int rv) {
907 DCHECK(!quic_session_created_);
908 if (!create_session_on_stale_dns_) {
909 quic_session_created_ = true;
910 }
911 if (rv != OK) {
912 DCHECK(!session_);
913 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
914 HistogramProtocolErrorLocation(
915 JobProtocolErrorLocation::kCreateSessionFailedAsync);
916 }
917 if (!create_session_on_stale_dns_) {
918 MaybeOnQuicSessionCreationComplete(rv);
919 } else {
920 create_session_on_stale_dns_ = false;
921 }
922 return;
923 }
924 DCHECK(session_);
925 create_session_on_stale_dns_ = false;
926 DVLOG(1) << "Created session on network: " << network_;
927 io_state_ = STATE_CREATE_SESSION_COMPLETE;
928 rv = DoLoop(rv);
929
930 if (host_resolution_finished_) {
931 for (auto* request : stream_requests_) {
932 request->OnQuicSessionCreationComplete(rv);
933 }
934 }
935
936 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
937 std::move(callback_).Run(rv);
938 }
939 }
940
MaybeOnQuicSessionCreationComplete(int rv)941 void QuicStreamFactory::Job::MaybeOnQuicSessionCreationComplete(int rv) {
942 if (!create_session_on_stale_dns_ && host_resolution_finished_) {
943 for (auto* request : stream_requests_) {
944 request->OnQuicSessionCreationComplete(rv);
945 }
946 if (!callback_.is_null()) {
947 std::move(callback_).Run(rv);
948 }
949 }
950 }
951
DoCreateSession()952 int QuicStreamFactory::Job::DoCreateSession() {
953 // TODO(https://crbug.com/1416409): This logic only knows how to try one
954 // endpoint result.
955 bool svcb_optional =
956 IsSvcbOptional(*resolve_host_request_->GetEndpointResults());
957 bool found = false;
958 for (const auto& candidate : *resolve_host_request_->GetEndpointResults()) {
959 quic::ParsedQuicVersion version =
960 SelectQuicVersion(candidate, svcb_optional);
961 if (version.IsKnown()) {
962 found = true;
963 quic_version_used_ = version;
964 endpoint_result_ = candidate;
965 break;
966 }
967 }
968 if (!found) {
969 return ERR_DNS_NO_MATCHING_SUPPORTED_ALPN;
970 }
971
972 quic_connection_start_time_ = base::TimeTicks::Now();
973 DCHECK(dns_resolution_end_time_ != base::TimeTicks());
974 io_state_ = STATE_CREATE_SESSION_COMPLETE;
975 bool require_confirmation = was_alternative_service_recently_broken_;
976 net_log_.AddEntryWithBoolParams(
977 NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT, NetLogEventPhase::BEGIN,
978 "require_confirmation", require_confirmation);
979
980 DCHECK_NE(quic_version_used_, quic::ParsedQuicVersion::Unsupported());
981 if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) {
982 return factory_->CreateSessionAsync(
983 base::BindOnce(&QuicStreamFactory::Job::OnCreateSessionComplete,
984 GetWeakPtr()),
985 key_, quic_version_used_, cert_verify_flags_, require_confirmation,
986 endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_,
987 net_log_, &session_, &network_);
988 }
989 int rv = factory_->CreateSessionSync(
990 key_, quic_version_used_, cert_verify_flags_, require_confirmation,
991 endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_,
992 net_log_, &session_, &network_);
993
994 DVLOG(1) << "Created session on network: " << network_;
995
996 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
997 DCHECK(!session_);
998 HistogramProtocolErrorLocation(
999 JobProtocolErrorLocation::kCreateSessionFailedSync);
1000 }
1001
1002 return rv;
1003 }
DoCreateSessionComplete(int rv)1004 int QuicStreamFactory::Job::DoCreateSessionComplete(int rv) {
1005 if (rv != OK) {
1006 return rv;
1007 }
1008 io_state_ = STATE_CONNECT;
1009 if (!session_->connection()->connected()) {
1010 return ERR_CONNECTION_CLOSED;
1011 }
1012
1013 session_->StartReading();
1014 if (!session_->connection()->connected()) {
1015 if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) {
1016 HistogramProtocolErrorLocation(
1017 JobProtocolErrorLocation::kSessionStartReadingFailedAsync);
1018 } else {
1019 HistogramProtocolErrorLocation(
1020 JobProtocolErrorLocation::kSessionStartReadingFailedSync);
1021 }
1022 return ERR_QUIC_PROTOCOL_ERROR;
1023 }
1024 return OK;
1025 }
1026
DoConnect(int rv)1027 int QuicStreamFactory::Job::DoConnect(int rv) {
1028 if (rv != OK) {
1029 return rv;
1030 }
1031 DCHECK(session_);
1032 io_state_ = STATE_CONNECT_COMPLETE;
1033 rv = session_->CryptoConnect(base::BindOnce(
1034 &QuicStreamFactory::Job::OnCryptoConnectComplete, GetWeakPtr()));
1035
1036 if (!session_->connection()->connected() &&
1037 session_->error() == quic::QUIC_PROOF_INVALID) {
1038 return ERR_QUIC_HANDSHAKE_FAILED;
1039 }
1040
1041 if (rv == ERR_QUIC_PROTOCOL_ERROR) {
1042 HistogramProtocolErrorLocation(
1043 JobProtocolErrorLocation::kCryptoConnectFailedSync);
1044 }
1045
1046 return rv;
1047 }
1048
DoConnectComplete(int rv)1049 int QuicStreamFactory::Job::DoConnectComplete(int rv) {
1050 if (!fresh_resolve_host_request_) {
1051 LogValidConnectionTime(quic_connection_start_time_);
1052 io_state_ = STATE_CONFIRM_CONNECTION;
1053 return rv;
1054 }
1055
1056 if (rv == OK) {
1057 io_state_ = STATE_HOST_VALIDATION;
1058 return ERR_IO_PENDING;
1059 }
1060
1061 // Connection from stale host resolution failed, has been closed and will
1062 // be deleted soon. Update Job status accordingly to wait for fresh host
1063 // resolution.
1064 LogStaleConnectionTime(quic_connection_start_time_);
1065 resolve_host_request_ = std::move(fresh_resolve_host_request_);
1066 session_ = nullptr;
1067 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
1068 return ERR_IO_PENDING;
1069 }
1070
1071 // This state is reached iff both host resolution and connection from stale dns
1072 // have finished successfully.
DoValidateHost()1073 int QuicStreamFactory::Job::DoValidateHost() {
1074 if (DoesConnectionMatchFreshHostResolution()) {
1075 LogValidConnectionTime(quic_connection_start_time_);
1076 LogRacingStatus(ConnectionStateAfterDNS::kCryptoFinishedDnsMatch);
1077 LogStaleAndFreshHostMatched(true);
1078 fresh_resolve_host_request_ = nullptr;
1079 host_resolution_finished_ = true;
1080 io_state_ = STATE_CONFIRM_CONNECTION;
1081 return OK;
1082 }
1083
1084 LogStaleConnectionTime(quic_connection_start_time_);
1085 LogRacingStatus(ConnectionStateAfterDNS::kCryptoFinishedDnsNoMatch);
1086 LogStaleAndFreshHostMatched(false);
1087 resolve_host_request_ = std::move(fresh_resolve_host_request_);
1088 CloseStaleHostConnection();
1089 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
1090 return OK;
1091 }
1092
DoConfirmConnection(int rv)1093 int QuicStreamFactory::Job::DoConfirmConnection(int rv) {
1094 UMA_HISTOGRAM_TIMES("Net.QuicSession.TimeFromResolveHostToConfirmConnection",
1095 base::TimeTicks::Now() - dns_resolution_start_time_);
1096 net_log_.EndEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT);
1097
1098 if (was_alternative_service_recently_broken_)
1099 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectAfterBroken", rv == OK);
1100
1101 if (retry_on_alternate_network_before_handshake_ && session_ &&
1102 !session_->OneRttKeysAvailable() &&
1103 network_ == factory_->default_network()) {
1104 if (session_->error() == quic::QUIC_NETWORK_IDLE_TIMEOUT ||
1105 session_->error() == quic::QUIC_HANDSHAKE_TIMEOUT ||
1106 session_->error() == quic::QUIC_PACKET_WRITE_ERROR) {
1107 // Retry the connection on an alternate network if crypto handshake failed
1108 // with network idle time out or handshake time out.
1109 DCHECK(network_ != handles::kInvalidNetworkHandle);
1110 network_ = factory_->FindAlternateNetwork(network_);
1111 connection_retried_ = network_ != handles::kInvalidNetworkHandle;
1112 UMA_HISTOGRAM_BOOLEAN(
1113 "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake",
1114 connection_retried_);
1115 UMA_HISTOGRAM_ENUMERATION(
1116 "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake."
1117 "FailedConnectionType",
1118 NetworkChangeNotifier::GetNetworkConnectionType(
1119 factory_->default_network()),
1120 NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1);
1121 if (connection_retried_) {
1122 UMA_HISTOGRAM_ENUMERATION(
1123 "Net.QuicStreamFactory.MigrationBeforeHandshake.NewConnectionType",
1124 NetworkChangeNotifier::GetNetworkConnectionType(network_),
1125 NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1);
1126 net_log_.AddEvent(
1127 NetLogEventType::
1128 QUIC_STREAM_FACTORY_JOB_RETRY_ON_ALTERNATE_NETWORK);
1129 // Notify requests that connection on the default network failed.
1130 for (auto* request : stream_requests_) {
1131 request->OnConnectionFailedOnDefaultNetwork();
1132 }
1133 DVLOG(1) << "Retry connection on alternate network: " << network_;
1134 session_ = nullptr;
1135 io_state_ = STATE_CREATE_SESSION;
1136 return OK;
1137 }
1138 }
1139 }
1140
1141 if (connection_retried_) {
1142 UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.MigrationBeforeHandshake2",
1143 rv == OK);
1144 if (rv == OK) {
1145 UMA_HISTOGRAM_BOOLEAN(
1146 "Net.QuicStreamFactory.NetworkChangeDuringMigrationBeforeHandshake",
1147 network_ == factory_->default_network());
1148 } else {
1149 base::UmaHistogramSparse(
1150 "Net.QuicStreamFactory.MigrationBeforeHandshakeFailedReason", -rv);
1151 }
1152 } else if (network_ != handles::kInvalidNetworkHandle &&
1153 network_ != factory_->default_network()) {
1154 UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.ConnectionOnNonDefaultNetwork",
1155 rv == OK);
1156 }
1157
1158 if (rv != OK)
1159 return rv;
1160
1161 DCHECK(!factory_->HasActiveSession(key_.session_key()));
1162 // There may well now be an active session for this IP. If so, use the
1163 // existing session instead.
1164 if (factory_->HasMatchingIpSession(
1165 key_, {ToIPEndPoint(session_->connection()->peer_address())},
1166 /*aliases=*/{}, use_dns_aliases_)) {
1167 LogConnectionIpPooling(true);
1168 session_->connection()->CloseConnection(
1169 quic::QUIC_CONNECTION_IP_POOLED,
1170 "An active session exists for the given IP.",
1171 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1172 session_ = nullptr;
1173 return OK;
1174 }
1175 LogConnectionIpPooling(false);
1176
1177 std::set<std::string> dns_aliases =
1178 use_dns_aliases_ && resolve_host_request_->GetDnsAliasResults()
1179 ? *resolve_host_request_->GetDnsAliasResults()
1180 : std::set<std::string>();
1181 factory_->ActivateSession(key_, session_, std::move(dns_aliases));
1182
1183 return OK;
1184 }
1185
QuicStreamRequest(QuicStreamFactory * factory)1186 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory)
1187 : factory_(factory) {}
1188
~QuicStreamRequest()1189 QuicStreamRequest::~QuicStreamRequest() {
1190 if (factory_ && !callback_.is_null())
1191 factory_->CancelRequest(this);
1192 }
1193
Request(url::SchemeHostPort destination,quic::ParsedQuicVersion quic_version,PrivacyMode privacy_mode,RequestPriority priority,const SocketTag & socket_tag,const NetworkAnonymizationKey & network_anonymization_key,SecureDnsPolicy secure_dns_policy,bool use_dns_aliases,bool require_dns_https_alpn,int cert_verify_flags,const GURL & url,const NetLogWithSource & net_log,NetErrorDetails * net_error_details,CompletionOnceCallback failed_on_default_network_callback,CompletionOnceCallback callback)1194 int QuicStreamRequest::Request(
1195 url::SchemeHostPort destination,
1196 quic::ParsedQuicVersion quic_version,
1197 PrivacyMode privacy_mode,
1198 RequestPriority priority,
1199 const SocketTag& socket_tag,
1200 const NetworkAnonymizationKey& network_anonymization_key,
1201 SecureDnsPolicy secure_dns_policy,
1202 bool use_dns_aliases,
1203 bool require_dns_https_alpn,
1204 int cert_verify_flags,
1205 const GURL& url,
1206 const NetLogWithSource& net_log,
1207 NetErrorDetails* net_error_details,
1208 CompletionOnceCallback failed_on_default_network_callback,
1209 CompletionOnceCallback callback) {
1210 DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn);
1211 DCHECK(net_error_details);
1212 DCHECK(callback_.is_null());
1213 DCHECK(host_resolution_callback_.is_null());
1214 DCHECK(factory_);
1215
1216 net_error_details_ = net_error_details;
1217 failed_on_default_network_callback_ =
1218 std::move(failed_on_default_network_callback);
1219
1220 session_key_ = QuicSessionKey(HostPortPair::FromURL(url), privacy_mode,
1221 socket_tag, network_anonymization_key,
1222 secure_dns_policy, require_dns_https_alpn);
1223
1224 int rv = factory_->Create(session_key_, std::move(destination), quic_version,
1225 priority, use_dns_aliases, cert_verify_flags, url,
1226 net_log, this);
1227 if (rv == ERR_IO_PENDING) {
1228 net_log_ = net_log;
1229 callback_ = std::move(callback);
1230 } else {
1231 DCHECK(!expect_on_host_resolution_);
1232 factory_ = nullptr;
1233 }
1234
1235 if (rv == OK)
1236 DCHECK(session_);
1237 return rv;
1238 }
1239
WaitForHostResolution(CompletionOnceCallback callback)1240 bool QuicStreamRequest::WaitForHostResolution(CompletionOnceCallback callback) {
1241 DCHECK(host_resolution_callback_.is_null());
1242 if (expect_on_host_resolution_) {
1243 host_resolution_callback_ = std::move(callback);
1244 }
1245 return expect_on_host_resolution_;
1246 }
1247
ExpectOnHostResolution()1248 void QuicStreamRequest::ExpectOnHostResolution() {
1249 expect_on_host_resolution_ = true;
1250 }
1251
OnHostResolutionComplete(int rv)1252 void QuicStreamRequest::OnHostResolutionComplete(int rv) {
1253 DCHECK(expect_on_host_resolution_);
1254 expect_on_host_resolution_ = false;
1255 if (!host_resolution_callback_.is_null()) {
1256 std::move(host_resolution_callback_).Run(rv);
1257 }
1258 }
1259
WaitForQuicSessionCreation(CompletionOnceCallback callback)1260 bool QuicStreamRequest::WaitForQuicSessionCreation(
1261 CompletionOnceCallback callback) {
1262 DCHECK(create_session_callback_.is_null());
1263 if (expect_on_quic_session_creation_) {
1264 create_session_callback_ = std::move(callback);
1265 }
1266 return expect_on_quic_session_creation_;
1267 }
1268
ExpectQuicSessionCreation()1269 void QuicStreamRequest::ExpectQuicSessionCreation() {
1270 expect_on_quic_session_creation_ = true;
1271 }
1272
OnQuicSessionCreationComplete(int rv)1273 void QuicStreamRequest::OnQuicSessionCreationComplete(int rv) {
1274 // DCHECK(expect_on_quic_session_creation_);
1275 expect_on_quic_session_creation_ = false;
1276 if (!create_session_callback_.is_null()) {
1277 std::move(create_session_callback_).Run(rv);
1278 }
1279 }
1280
OnRequestComplete(int rv)1281 void QuicStreamRequest::OnRequestComplete(int rv) {
1282 factory_ = nullptr;
1283 std::move(callback_).Run(rv);
1284 }
1285
OnConnectionFailedOnDefaultNetwork()1286 void QuicStreamRequest::OnConnectionFailedOnDefaultNetwork() {
1287 if (!failed_on_default_network_callback_.is_null())
1288 std::move(failed_on_default_network_callback_).Run(OK);
1289 }
1290
GetTimeDelayForWaitingJob() const1291 base::TimeDelta QuicStreamRequest::GetTimeDelayForWaitingJob() const {
1292 if (!factory_)
1293 return base::TimeDelta();
1294 return factory_->GetTimeDelayForWaitingJob(session_key_);
1295 }
1296
SetPriority(RequestPriority priority)1297 void QuicStreamRequest::SetPriority(RequestPriority priority) {
1298 if (factory_)
1299 factory_->SetRequestPriority(this, priority);
1300 }
1301
1302 std::unique_ptr<QuicChromiumClientSession::Handle>
ReleaseSessionHandle()1303 QuicStreamRequest::ReleaseSessionHandle() {
1304 if (!session_ || !session_->IsConnected())
1305 return nullptr;
1306
1307 return std::move(session_);
1308 }
1309
SetSession(std::unique_ptr<QuicChromiumClientSession::Handle> session)1310 void QuicStreamRequest::SetSession(
1311 std::unique_ptr<QuicChromiumClientSession::Handle> session) {
1312 session_ = std::move(session);
1313 }
1314
CanUseExistingSession(const GURL & url,PrivacyMode privacy_mode,const SocketTag & socket_tag,const NetworkAnonymizationKey & network_anonymization_key,SecureDnsPolicy secure_dns_policy,bool require_dns_https_alpn,const url::SchemeHostPort & destination) const1315 bool QuicStreamRequest::CanUseExistingSession(
1316 const GURL& url,
1317 PrivacyMode privacy_mode,
1318 const SocketTag& socket_tag,
1319 const NetworkAnonymizationKey& network_anonymization_key,
1320 SecureDnsPolicy secure_dns_policy,
1321 bool require_dns_https_alpn,
1322 const url::SchemeHostPort& destination) const {
1323 return factory_->CanUseExistingSession(
1324 QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, socket_tag,
1325 network_anonymization_key, secure_dns_policy,
1326 require_dns_https_alpn),
1327 destination);
1328 }
1329
QuicSessionAliasKey(url::SchemeHostPort destination,QuicSessionKey session_key)1330 QuicStreamFactory::QuicSessionAliasKey::QuicSessionAliasKey(
1331 url::SchemeHostPort destination,
1332 QuicSessionKey session_key)
1333 : destination_(std::move(destination)),
1334 session_key_(std::move(session_key)) {}
1335
operator <(const QuicSessionAliasKey & other) const1336 bool QuicStreamFactory::QuicSessionAliasKey::operator<(
1337 const QuicSessionAliasKey& other) const {
1338 return std::tie(destination_, session_key_) <
1339 std::tie(other.destination_, other.session_key_);
1340 }
1341
operator ==(const QuicSessionAliasKey & other) const1342 bool QuicStreamFactory::QuicSessionAliasKey::operator==(
1343 const QuicSessionAliasKey& other) const {
1344 return destination_ == other.destination_ &&
1345 session_key_ == other.session_key_;
1346 }
1347
QuicStreamFactory(NetLog * net_log,HostResolver * host_resolver,SSLConfigService * ssl_config_service,ClientSocketFactory * client_socket_factory,HttpServerProperties * http_server_properties,CertVerifier * cert_verifier,CTPolicyEnforcer * ct_policy_enforcer,TransportSecurityState * transport_security_state,SCTAuditingDelegate * sct_auditing_delegate,SocketPerformanceWatcherFactory * socket_performance_watcher_factory,QuicCryptoClientStreamFactory * quic_crypto_client_stream_factory,QuicContext * quic_context)1348 QuicStreamFactory::QuicStreamFactory(
1349 NetLog* net_log,
1350 HostResolver* host_resolver,
1351 SSLConfigService* ssl_config_service,
1352 ClientSocketFactory* client_socket_factory,
1353 HttpServerProperties* http_server_properties,
1354 CertVerifier* cert_verifier,
1355 CTPolicyEnforcer* ct_policy_enforcer,
1356 TransportSecurityState* transport_security_state,
1357 SCTAuditingDelegate* sct_auditing_delegate,
1358 SocketPerformanceWatcherFactory* socket_performance_watcher_factory,
1359 QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
1360 QuicContext* quic_context)
1361 : net_log_(net_log),
1362 host_resolver_(host_resolver),
1363 client_socket_factory_(client_socket_factory),
1364 http_server_properties_(http_server_properties),
1365 cert_verifier_(cert_verifier),
1366 ct_policy_enforcer_(ct_policy_enforcer),
1367 transport_security_state_(transport_security_state),
1368 sct_auditing_delegate_(sct_auditing_delegate),
1369 quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
1370 random_generator_(quic_context->random_generator()),
1371 clock_(quic_context->clock()),
1372 // TODO(vasilvv): figure out how to avoid having multiple copies of
1373 // QuicParams.
1374 params_(*quic_context->params()),
1375 clock_skew_detector_(base::TimeTicks::Now(), base::Time::Now()),
1376 socket_performance_watcher_factory_(socket_performance_watcher_factory),
1377 recent_crypto_config_map_(kMaxRecentCryptoConfigs),
1378 config_(InitializeQuicConfig(*quic_context->params())),
1379 ping_timeout_(quic::QuicTime::Delta::FromSeconds(quic::kPingTimeoutSecs)),
1380 reduced_ping_timeout_(quic::QuicTime::Delta::FromMicroseconds(
1381 quic_context->params()->reduced_ping_timeout.InMicroseconds())),
1382 retransmittable_on_wire_timeout_(quic::QuicTime::Delta::FromMicroseconds(
1383 quic_context->params()
1384 ->retransmittable_on_wire_timeout.InMicroseconds())),
1385 yield_after_packets_(kQuicYieldAfterPacketsRead),
1386 yield_after_duration_(quic::QuicTime::Delta::FromMilliseconds(
1387 kQuicYieldAfterDurationMilliseconds)),
1388 default_network_(handles::kInvalidNetworkHandle),
1389 connectivity_monitor_(default_network_),
1390 ssl_config_service_(ssl_config_service),
1391 use_network_anonymization_key_for_crypto_configs_(
1392 NetworkAnonymizationKey::IsPartitioningEnabled()) {
1393 DCHECK(transport_security_state_);
1394 DCHECK(http_server_properties_);
1395 if (params_.disable_tls_zero_rtt)
1396 SetQuicFlag(quic_disable_client_tls_zero_rtt, true);
1397 InitializeMigrationOptions();
1398 cert_verifier_->AddObserver(this);
1399 CertDatabase::GetInstance()->AddObserver(this);
1400 }
1401
~QuicStreamFactory()1402 QuicStreamFactory::~QuicStreamFactory() {
1403 UMA_HISTOGRAM_COUNTS_1000("Net.NumQuicSessionsAtShutdown",
1404 all_sessions_.size());
1405 CloseAllSessions(ERR_ABORTED, quic::QUIC_CONNECTION_CANCELLED);
1406 while (!all_sessions_.empty()) {
1407 delete all_sessions_.begin()->first;
1408 all_sessions_.erase(all_sessions_.begin());
1409 }
1410 active_jobs_.clear();
1411
1412 DCHECK(dns_aliases_by_session_key_.empty());
1413
1414 // This should have been moved to the recent map when all consumers of
1415 // QuicCryptoClientConfigs were deleted, in the above lines.
1416 DCHECK(active_crypto_config_map_.empty());
1417
1418 CertDatabase::GetInstance()->RemoveObserver(this);
1419 cert_verifier_->RemoveObserver(this);
1420 if (params_.close_sessions_on_ip_change ||
1421 params_.goaway_sessions_on_ip_change) {
1422 NetworkChangeNotifier::RemoveIPAddressObserver(this);
1423 }
1424 if (NetworkChangeNotifier::AreNetworkHandlesSupported()) {
1425 NetworkChangeNotifier::RemoveNetworkObserver(this);
1426 }
1427 }
1428
CanUseExistingSession(const QuicSessionKey & session_key,const url::SchemeHostPort & destination) const1429 bool QuicStreamFactory::CanUseExistingSession(
1430 const QuicSessionKey& session_key,
1431 const url::SchemeHostPort& destination) const {
1432 if (base::Contains(active_sessions_, session_key))
1433 return true;
1434
1435 for (const auto& key_value : active_sessions_) {
1436 QuicChromiumClientSession* session = key_value.second;
1437 const auto& it = all_sessions_.find(session);
1438 if ((it != all_sessions_.end()) &&
1439 (destination == it->second.destination()) &&
1440 session->CanPool(session_key.host(), session_key)) {
1441 return true;
1442 }
1443 }
1444
1445 return false;
1446 }
1447
Create(const QuicSessionKey & session_key,url::SchemeHostPort destination,quic::ParsedQuicVersion quic_version,RequestPriority priority,bool use_dns_aliases,int cert_verify_flags,const GURL & url,const NetLogWithSource & net_log,QuicStreamRequest * request)1448 int QuicStreamFactory::Create(const QuicSessionKey& session_key,
1449 url::SchemeHostPort destination,
1450 quic::ParsedQuicVersion quic_version,
1451 RequestPriority priority,
1452 bool use_dns_aliases,
1453 int cert_verify_flags,
1454 const GURL& url,
1455 const NetLogWithSource& net_log,
1456 QuicStreamRequest* request) {
1457 if (clock_skew_detector_.ClockSkewDetected(base::TimeTicks::Now(),
1458 base::Time::Now())) {
1459 MarkAllActiveSessionsGoingAway(kClockSkewDetected);
1460 }
1461 DCHECK(HostPortPair(session_key.server_id().host(),
1462 session_key.server_id().port())
1463 .Equals(HostPortPair::FromURL(url)));
1464
1465 // Search sessions for a matching promised stream.
1466 for (auto session : active_sessions_) {
1467 quic::QuicClientPromisedInfo* promised =
1468 session.second->GetPromised(url, session_key);
1469 if (!promised)
1470 continue;
1471 DCHECK_EQ(promised->session(), session.second);
1472 request->SetSession(session.second->CreateHandle(std::move(destination)));
1473 ++num_push_streams_created_;
1474 return OK;
1475 }
1476
1477 // Use active session for |session_key| if such exists.
1478 auto active_session = active_sessions_.find(session_key);
1479 if (active_session != active_sessions_.end()) {
1480 QuicChromiumClientSession* session = active_session->second;
1481 request->SetSession(session->CreateHandle(std::move(destination)));
1482 return OK;
1483 }
1484
1485 // Associate with active job to |session_key| if such exists.
1486 auto active_job = active_jobs_.find(session_key);
1487 if (active_job != active_jobs_.end()) {
1488 const NetLogWithSource& job_net_log = active_job->second->net_log();
1489 job_net_log.AddEventReferencingSource(
1490 NetLogEventType::QUIC_STREAM_FACTORY_JOB_BOUND_TO_HTTP_STREAM_JOB,
1491 net_log.source());
1492 net_log.AddEventReferencingSource(
1493 NetLogEventType::HTTP_STREAM_JOB_BOUND_TO_QUIC_STREAM_FACTORY_JOB,
1494 job_net_log.source());
1495 active_job->second->AddRequest(request);
1496 return ERR_IO_PENDING;
1497 }
1498
1499 // Pool to active session to |destination| if possible.
1500 if (!active_sessions_.empty()) {
1501 for (const auto& key_value : active_sessions_) {
1502 QuicChromiumClientSession* session = key_value.second;
1503 if (destination == all_sessions_[session].destination() &&
1504 session->CanPool(session_key.server_id().host(), session_key)) {
1505 request->SetSession(session->CreateHandle(std::move(destination)));
1506 return OK;
1507 }
1508 }
1509 }
1510
1511 // TODO(rtenneti): |task_runner_| is used by the Job. Initialize task_runner_
1512 // in the constructor after WebRequestActionWithThreadsTest.* tests are fixed.
1513 if (!task_runner_)
1514 task_runner_ = base::SequencedTaskRunner::GetCurrentDefault().get();
1515
1516 if (!tick_clock_)
1517 tick_clock_ = base::DefaultTickClock::GetInstance();
1518
1519 QuicSessionAliasKey key(destination, session_key);
1520 std::unique_ptr<Job> job = std::make_unique<Job>(
1521 this, quic_version, host_resolver_, key,
1522 CreateCryptoConfigHandle(session_key.network_anonymization_key()),
1523 WasQuicRecentlyBroken(session_key),
1524 params_.retry_on_alternate_network_before_handshake,
1525 params_.race_stale_dns_on_connection, priority, use_dns_aliases,
1526 session_key.require_dns_https_alpn(), cert_verify_flags, net_log);
1527 int rv = job->Run(base::BindOnce(&QuicStreamFactory::OnJobComplete,
1528 weak_factory_.GetWeakPtr(), job.get()));
1529 if (rv == ERR_IO_PENDING) {
1530 job->AddRequest(request);
1531 active_jobs_[session_key] = std::move(job);
1532 return rv;
1533 }
1534 if (rv == OK) {
1535 auto it = active_sessions_.find(session_key);
1536 DCHECK(it != active_sessions_.end());
1537 if (it == active_sessions_.end())
1538 return ERR_QUIC_PROTOCOL_ERROR;
1539 QuicChromiumClientSession* session = it->second;
1540 request->SetSession(session->CreateHandle(std::move(destination)));
1541 }
1542 return rv;
1543 }
1544
OnSessionGoingAway(QuicChromiumClientSession * session)1545 void QuicStreamFactory::OnSessionGoingAway(QuicChromiumClientSession* session) {
1546 const AliasSet& aliases = session_aliases_[session];
1547 for (const auto& alias : aliases) {
1548 const QuicSessionKey& session_key = alias.session_key();
1549 DCHECK(active_sessions_.count(session_key));
1550 DCHECK_EQ(session, active_sessions_[session_key]);
1551 // Track sessions which have recently gone away so that we can disable
1552 // port suggestions.
1553 if (session->goaway_received())
1554 gone_away_aliases_.insert(alias);
1555
1556 active_sessions_.erase(session_key);
1557 ProcessGoingAwaySession(session, session_key.server_id(), true);
1558 }
1559 ProcessGoingAwaySession(session, all_sessions_[session].server_id(), false);
1560 if (!aliases.empty()) {
1561 DCHECK(base::Contains(session_peer_ip_, session));
1562 const IPEndPoint peer_address = session_peer_ip_[session];
1563 ip_aliases_[peer_address].erase(session);
1564 if (ip_aliases_[peer_address].empty())
1565 ip_aliases_.erase(peer_address);
1566 session_peer_ip_.erase(session);
1567 }
1568 UnmapSessionFromSessionAliases(session);
1569 }
1570
OnSessionClosed(QuicChromiumClientSession * session)1571 void QuicStreamFactory::OnSessionClosed(QuicChromiumClientSession* session) {
1572 DCHECK_EQ(0u, session->GetNumActiveStreams());
1573 OnSessionGoingAway(session);
1574 for (const auto& iter : active_jobs_) {
1575 if (iter.first == session->quic_session_key()) {
1576 iter.second->OnSessionClosed(session);
1577 }
1578 }
1579 delete session;
1580 all_sessions_.erase(session);
1581 }
1582
OnBlackholeAfterHandshakeConfirmed(QuicChromiumClientSession * session)1583 void QuicStreamFactory::OnBlackholeAfterHandshakeConfirmed(
1584 QuicChromiumClientSession* session) {
1585 // Reduce PING timeout when connection blackholes after the handshake.
1586 if (ping_timeout_ > reduced_ping_timeout_)
1587 ping_timeout_ = reduced_ping_timeout_;
1588 }
1589
CancelRequest(QuicStreamRequest * request)1590 void QuicStreamFactory::CancelRequest(QuicStreamRequest* request) {
1591 auto job_iter = active_jobs_.find(request->session_key());
1592 CHECK(job_iter != active_jobs_.end());
1593 job_iter->second->RemoveRequest(request);
1594 }
1595
SetRequestPriority(QuicStreamRequest * request,RequestPriority priority)1596 void QuicStreamFactory::SetRequestPriority(QuicStreamRequest* request,
1597 RequestPriority priority) {
1598 auto job_iter = active_jobs_.find(request->session_key());
1599 if (job_iter == active_jobs_.end())
1600 return;
1601 job_iter->second->SetPriority(priority);
1602 }
1603
CloseAllSessions(int error,quic::QuicErrorCode quic_error)1604 void QuicStreamFactory::CloseAllSessions(int error,
1605 quic::QuicErrorCode quic_error) {
1606 base::UmaHistogramSparse("Net.QuicSession.CloseAllSessionsError", -error);
1607 while (!active_sessions_.empty()) {
1608 size_t initial_size = active_sessions_.size();
1609 active_sessions_.begin()->second->CloseSessionOnError(
1610 error, quic_error,
1611 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1612 DCHECK_NE(initial_size, active_sessions_.size());
1613 }
1614 while (!all_sessions_.empty()) {
1615 size_t initial_size = all_sessions_.size();
1616 all_sessions_.begin()->first->CloseSessionOnError(
1617 error, quic_error,
1618 quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1619 DCHECK_NE(initial_size, all_sessions_.size());
1620 }
1621 DCHECK(all_sessions_.empty());
1622 }
1623
QuicStreamFactoryInfoToValue() const1624 base::Value QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
1625 base::Value::List list;
1626
1627 for (const auto& active_session : active_sessions_) {
1628 const quic::QuicServerId& server_id = active_session.first.server_id();
1629 QuicChromiumClientSession* session = active_session.second;
1630 const AliasSet& aliases = session_aliases_.find(session)->second;
1631 // Only add a session to the list once.
1632 if (server_id == aliases.begin()->server_id()) {
1633 std::set<HostPortPair> hosts;
1634 for (const auto& alias : aliases) {
1635 hosts.insert(
1636 HostPortPair(alias.server_id().host(), alias.server_id().port()));
1637 }
1638 list.Append(session->GetInfoAsValue(hosts));
1639 }
1640 }
1641 return base::Value(std::move(list));
1642 }
1643
ClearCachedStatesInCryptoConfig(const base::RepeatingCallback<bool (const GURL &)> & origin_filter)1644 void QuicStreamFactory::ClearCachedStatesInCryptoConfig(
1645 const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {
1646 ServerIdOriginFilter filter(origin_filter);
1647 for (const auto& crypto_config : active_crypto_config_map_) {
1648 crypto_config.second->config()->ClearCachedStates(filter);
1649 }
1650
1651 for (const auto& crypto_config : recent_crypto_config_map_) {
1652 crypto_config.second->config()->ClearCachedStates(filter);
1653 }
1654 }
1655
ConnectAndConfigureSocket(CompletionOnceCallback callback,DatagramClientSocket * socket,IPEndPoint addr,handles::NetworkHandle network,const SocketTag & socket_tag)1656 int QuicStreamFactory::ConnectAndConfigureSocket(
1657 CompletionOnceCallback callback,
1658 DatagramClientSocket* socket,
1659 IPEndPoint addr,
1660 handles::NetworkHandle network,
1661 const SocketTag& socket_tag) {
1662 socket->UseNonBlockingIO();
1663
1664 int rv;
1665 auto split_callback = base::SplitOnceCallback(std::move(callback));
1666 CompletionOnceCallback connect_callback =
1667 base::BindOnce(&QuicStreamFactory::FinishConnectAndConfigureSocket,
1668 weak_factory_.GetWeakPtr(),
1669 std::move(split_callback.first), socket, socket_tag);
1670 if (!params_.migrate_sessions_on_network_change_v2) {
1671 rv = socket->ConnectAsync(addr, std::move(connect_callback));
1672 } else if (network == handles::kInvalidNetworkHandle) {
1673 // If caller leaves network unspecified, use current default network.
1674 rv = socket->ConnectUsingDefaultNetworkAsync(addr,
1675 std::move(connect_callback));
1676 } else {
1677 rv = socket->ConnectUsingNetworkAsync(network, addr,
1678 std::move(connect_callback));
1679 }
1680 // Both callbacks within `split_callback` will always be run asynchronously,
1681 // even if a Connect call returns synchronously. Therefore we always return
1682 // ERR_IO_PENDING.
1683 if (rv != ERR_IO_PENDING) {
1684 FinishConnectAndConfigureSocket(std::move(split_callback.second), socket,
1685 socket_tag, rv);
1686 }
1687 return ERR_IO_PENDING;
1688 }
1689
FinishConnectAndConfigureSocket(CompletionOnceCallback callback,DatagramClientSocket * socket,const SocketTag & socket_tag,int rv)1690 void QuicStreamFactory::FinishConnectAndConfigureSocket(
1691 CompletionOnceCallback callback,
1692 DatagramClientSocket* socket,
1693 const SocketTag& socket_tag,
1694 int rv) {
1695 if (rv != OK) {
1696 OnFinishConnectAndConfigureSocketError(
1697 std::move(callback), CREATION_ERROR_CONNECTING_SOCKET, rv);
1698 return;
1699 }
1700
1701 socket->ApplySocketTag(socket_tag);
1702
1703 rv = socket->SetReceiveBufferSize(kQuicSocketReceiveBufferSize);
1704 if (rv != OK) {
1705 OnFinishConnectAndConfigureSocketError(
1706 std::move(callback), CREATION_ERROR_SETTING_RECEIVE_BUFFER, rv);
1707 return;
1708 }
1709
1710 rv = socket->SetDoNotFragment();
1711 // SetDoNotFragment is not implemented on all platforms, so ignore errors.
1712 if (rv != OK && rv != ERR_NOT_IMPLEMENTED) {
1713 OnFinishConnectAndConfigureSocketError(
1714 std::move(callback), CREATION_ERROR_SETTING_DO_NOT_FRAGMENT, rv);
1715 return;
1716 }
1717
1718 // Set a buffer large enough to contain the initial CWND's worth of packet
1719 // to work around the problem with CHLO packets being sent out with the
1720 // wrong encryption level, when the send buffer is full.
1721 rv = socket->SetSendBufferSize(quic::kMaxOutgoingPacketSize * 20);
1722 if (rv != OK) {
1723 OnFinishConnectAndConfigureSocketError(
1724 std::move(callback), CREATION_ERROR_SETTING_SEND_BUFFER, rv);
1725 return;
1726 }
1727
1728 if (params_.ios_network_service_type > 0) {
1729 socket->SetIOSNetworkServiceType(params_.ios_network_service_type);
1730 }
1731
1732 socket->GetLocalAddress(&local_address_);
1733 if (need_to_check_persisted_supports_quic_) {
1734 need_to_check_persisted_supports_quic_ = false;
1735 if (http_server_properties_->WasLastLocalAddressWhenQuicWorked(
1736 local_address_.address())) {
1737 is_quic_known_to_work_on_current_network_ = true;
1738 // Clear the persisted IP address, in case the network no longer supports
1739 // QUIC so the next restart will require confirmation. It will be
1740 // re-persisted when the first job completes successfully.
1741 http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
1742 }
1743 }
1744
1745 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
1746 FROM_HERE,
1747 base::BindOnce(&QuicStreamFactory::DoCallback, weak_factory_.GetWeakPtr(),
1748 std::move(callback), rv));
1749 }
1750
OnFinishConnectAndConfigureSocketError(CompletionOnceCallback callback,enum CreateSessionFailure error,int rv)1751 void QuicStreamFactory::OnFinishConnectAndConfigureSocketError(
1752 CompletionOnceCallback callback,
1753 enum CreateSessionFailure error,
1754 int rv) {
1755 DCHECK(callback);
1756 HistogramCreateSessionFailure(error);
1757 base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
1758 FROM_HERE,
1759 base::BindOnce(&QuicStreamFactory::DoCallback, weak_factory_.GetWeakPtr(),
1760 std::move(callback), rv));
1761 }
1762
DoCallback(CompletionOnceCallback callback,int rv)1763 void QuicStreamFactory::DoCallback(CompletionOnceCallback callback, int rv) {
1764 std::move(callback).Run(rv);
1765 }
1766
ConfigureSocket(DatagramClientSocket * socket,IPEndPoint addr,handles::NetworkHandle network,const SocketTag & socket_tag)1767 int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket,
1768 IPEndPoint addr,
1769 handles::NetworkHandle network,
1770 const SocketTag& socket_tag) {
1771 socket->UseNonBlockingIO();
1772
1773 int rv;
1774 if (!params_.migrate_sessions_on_network_change_v2) {
1775 rv = socket->Connect(addr);
1776 } else if (network == handles::kInvalidNetworkHandle) {
1777 // If caller leaves network unspecified, use current default network.
1778 rv = socket->ConnectUsingDefaultNetwork(addr);
1779 } else {
1780 rv = socket->ConnectUsingNetwork(network, addr);
1781 }
1782 if (rv != OK) {
1783 HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET);
1784 return rv;
1785 }
1786
1787 socket->ApplySocketTag(socket_tag);
1788
1789 rv = socket->SetReceiveBufferSize(kQuicSocketReceiveBufferSize);
1790 if (rv != OK) {
1791 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER);
1792 return rv;
1793 }
1794
1795 rv = socket->SetDoNotFragment();
1796 // SetDoNotFragment is not implemented on all platforms, so ignore errors.
1797 if (rv != OK && rv != ERR_NOT_IMPLEMENTED) {
1798 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_DO_NOT_FRAGMENT);
1799 return rv;
1800 }
1801
1802 // Set a buffer large enough to contain the initial CWND's worth of packet
1803 // to work around the problem with CHLO packets being sent out with the
1804 // wrong encryption level, when the send buffer is full.
1805 rv = socket->SetSendBufferSize(quic::kMaxOutgoingPacketSize * 20);
1806 if (rv != OK) {
1807 HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER);
1808 return rv;
1809 }
1810
1811 if (params_.ios_network_service_type > 0) {
1812 socket->SetIOSNetworkServiceType(params_.ios_network_service_type);
1813 }
1814
1815 socket->GetLocalAddress(&local_address_);
1816 if (need_to_check_persisted_supports_quic_) {
1817 need_to_check_persisted_supports_quic_ = false;
1818 if (http_server_properties_->WasLastLocalAddressWhenQuicWorked(
1819 local_address_.address())) {
1820 is_quic_known_to_work_on_current_network_ = true;
1821 // Clear the persisted IP address, in case the network no longer supports
1822 // QUIC so the next restart will require confirmation. It will be
1823 // re-persisted when the first job completes successfully.
1824 http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
1825 }
1826 }
1827
1828 return OK;
1829 }
1830
FindAlternateNetwork(handles::NetworkHandle old_network)1831 handles::NetworkHandle QuicStreamFactory::FindAlternateNetwork(
1832 handles::NetworkHandle old_network) {
1833 // Find a new network that sessions bound to |old_network| can be migrated to.
1834 NetworkChangeNotifier::NetworkList network_list;
1835 NetworkChangeNotifier::GetConnectedNetworks(&network_list);
1836 for (handles::NetworkHandle new_network : network_list) {
1837 if (new_network != old_network)
1838 return new_network;
1839 }
1840 return handles::kInvalidNetworkHandle;
1841 }
1842
CreateSocket(NetLog * net_log,const NetLogSource & source)1843 std::unique_ptr<DatagramClientSocket> QuicStreamFactory::CreateSocket(
1844 NetLog* net_log,
1845 const NetLogSource& source) {
1846 auto socket = client_socket_factory_->CreateDatagramClientSocket(
1847 DatagramSocket::DEFAULT_BIND, net_log, source);
1848 if (params_.enable_socket_recv_optimization)
1849 socket->EnableRecvOptimization();
1850 return socket;
1851 }
1852
OnIPAddressChanged()1853 void QuicStreamFactory::OnIPAddressChanged() {
1854 CollectDataOnPlatformNotification(NETWORK_IP_ADDRESS_CHANGED,
1855 handles::kInvalidNetworkHandle);
1856 // Do nothing if connection migration is turned on.
1857 if (params_.migrate_sessions_on_network_change_v2)
1858 return;
1859
1860 connectivity_monitor_.OnIPAddressChanged();
1861
1862 set_is_quic_known_to_work_on_current_network(false);
1863 if (params_.close_sessions_on_ip_change) {
1864 CloseAllSessions(ERR_NETWORK_CHANGED, quic::QUIC_IP_ADDRESS_CHANGED);
1865 } else {
1866 DCHECK(params_.goaway_sessions_on_ip_change);
1867 MarkAllActiveSessionsGoingAway(kIPAddressChanged);
1868 }
1869 }
1870
OnNetworkConnected(handles::NetworkHandle network)1871 void QuicStreamFactory::OnNetworkConnected(handles::NetworkHandle network) {
1872 CollectDataOnPlatformNotification(NETWORK_CONNECTED, network);
1873 if (params_.migrate_sessions_on_network_change_v2) {
1874 NetLogWithSource net_log = NetLogWithSource::Make(
1875 net_log_, NetLogSourceType::QUIC_CONNECTION_MIGRATION);
1876 net_log.AddEventWithStringParams(
1877 NetLogEventType::QUIC_CONNECTION_MIGRATION_PLATFORM_NOTIFICATION,
1878 "signal", "OnNetworkConnected");
1879 }
1880 // Broadcast network connected to all sessions.
1881 // If migration is not turned on, session will not migrate but collect data.
1882 auto it = all_sessions_.begin();
1883 // Sessions may be deleted while iterating through the map.
1884 while (it != all_sessions_.end()) {
1885 QuicChromiumClientSession* session = it->first;
1886 ++it;
1887 session->OnNetworkConnected(network);
1888 }
1889 }
1890
OnNetworkDisconnected(handles::NetworkHandle network)1891 void QuicStreamFactory::OnNetworkDisconnected(handles::NetworkHandle network) {
1892 CollectDataOnPlatformNotification(NETWORK_DISCONNECTED, network);
1893 if (params_.migrate_sessions_on_network_change_v2) {
1894 NetLogWithSource net_log = NetLogWithSource::Make(
1895 net_log_, NetLogSourceType::QUIC_CONNECTION_MIGRATION);
1896 net_log.AddEventWithStringParams(
1897 NetLogEventType::QUIC_CONNECTION_MIGRATION_PLATFORM_NOTIFICATION,
1898 "signal", "OnNetworkDisconnected");
1899 }
1900 // Broadcast network disconnected to all sessions.
1901 // If migration is not turned on, session will not migrate but collect data.
1902 auto it = all_sessions_.begin();
1903 // Sessions may be deleted while iterating through the map.
1904 while (it != all_sessions_.end()) {
1905 QuicChromiumClientSession* session = it->first;
1906 ++it;
1907 session->OnNetworkDisconnectedV2(/*disconnected_network*/ network);
1908 }
1909 }
1910
1911 // This method is expected to only be called when migrating from Cellular to
1912 // WiFi on Android, and should always be preceded by OnNetworkMadeDefault().
OnNetworkSoonToDisconnect(handles::NetworkHandle network)1913 void QuicStreamFactory::OnNetworkSoonToDisconnect(
1914 handles::NetworkHandle network) {
1915 CollectDataOnPlatformNotification(NETWORK_SOON_TO_DISCONNECT, network);
1916 }
1917
OnNetworkMadeDefault(handles::NetworkHandle network)1918 void QuicStreamFactory::OnNetworkMadeDefault(handles::NetworkHandle network) {
1919 CollectDataOnPlatformNotification(NETWORK_MADE_DEFAULT, network);
1920 connectivity_monitor_.OnDefaultNetworkUpdated(network);
1921
1922 // Clear alternative services that were marked as broken until default network
1923 // changes.
1924 if (params_.retry_on_alternate_network_before_handshake &&
1925 default_network_ != handles::kInvalidNetworkHandle &&
1926 network != default_network_) {
1927 http_server_properties_->OnDefaultNetworkChanged();
1928 }
1929
1930 DCHECK_NE(handles::kInvalidNetworkHandle, network);
1931 default_network_ = network;
1932
1933 if (params_.migrate_sessions_on_network_change_v2) {
1934 NetLogWithSource net_log = NetLogWithSource::Make(
1935 net_log_, NetLogSourceType::QUIC_CONNECTION_MIGRATION);
1936 net_log.AddEventWithStringParams(
1937 NetLogEventType::QUIC_CONNECTION_MIGRATION_PLATFORM_NOTIFICATION,
1938 "signal", "OnNetworkMadeDefault");
1939 }
1940
1941 auto it = all_sessions_.begin();
1942 // Sessions may be deleted while iterating through the map.
1943 while (it != all_sessions_.end()) {
1944 QuicChromiumClientSession* session = it->first;
1945 ++it;
1946 session->OnNetworkMadeDefault(network);
1947 }
1948 if (params_.migrate_sessions_on_network_change_v2)
1949 set_is_quic_known_to_work_on_current_network(false);
1950 }
1951
OnCertDBChanged()1952 void QuicStreamFactory::OnCertDBChanged() {
1953 // We should flush the sessions if we removed trust from a
1954 // cert, because a previously trusted server may have become
1955 // untrusted.
1956 //
1957 // We should not flush the sessions if we added trust to a cert.
1958 //
1959 // Since the OnCertDBChanged method doesn't tell us what
1960 // kind of change it is, we have to flush the socket
1961 // pools to be safe.
1962 MarkAllActiveSessionsGoingAway(kCertDBChanged);
1963 }
1964
OnCertVerifierChanged()1965 void QuicStreamFactory::OnCertVerifierChanged() {
1966 // Flush sessions if the CertCerifier configuration has changed.
1967 MarkAllActiveSessionsGoingAway(kCertVerifierChanged);
1968 }
1969
set_is_quic_known_to_work_on_current_network(bool is_quic_known_to_work_on_current_network)1970 void QuicStreamFactory::set_is_quic_known_to_work_on_current_network(
1971 bool is_quic_known_to_work_on_current_network) {
1972 is_quic_known_to_work_on_current_network_ =
1973 is_quic_known_to_work_on_current_network;
1974 if (!(local_address_ == IPEndPoint())) {
1975 if (is_quic_known_to_work_on_current_network_) {
1976 http_server_properties_->SetLastLocalAddressWhenQuicWorked(
1977 local_address_.address());
1978 } else {
1979 http_server_properties_->ClearLastLocalAddressWhenQuicWorked();
1980 }
1981 }
1982 }
1983
GetTimeDelayForWaitingJob(const QuicSessionKey & session_key)1984 base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob(
1985 const QuicSessionKey& session_key) {
1986 // If |is_quic_known_to_work_on_current_network_| is false, then one of the
1987 // following is true:
1988 // 1) This is startup and QuicStreamFactory::CreateSession() and
1989 // ConfigureSocket() have yet to be called, and it is not yet known
1990 // if the current network is the last one where QUIC worked.
1991 // 2) Startup has been completed, and QUIC has not been used
1992 // successfully since startup, or on this network before.
1993 if (!is_quic_known_to_work_on_current_network_) {
1994 // If |need_to_check_persisted_supports_quic_| is false, this is case 1)
1995 // above. If HasLastLocalAddressWhenQuicWorked() is also true, then there's
1996 // a chance the current network is the last one on which QUIC worked. So
1997 // only delay the request if there's no chance that is the case.
1998 if (!need_to_check_persisted_supports_quic_ ||
1999 !http_server_properties_->HasLastLocalAddressWhenQuicWorked()) {
2000 return base::TimeDelta();
2001 }
2002 }
2003
2004 // QUIC was recently broken. Do not delay the main job.
2005 if (WasQuicRecentlyBroken(session_key)) {
2006 return base::TimeDelta();
2007 }
2008
2009 int64_t srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds(
2010 session_key.server_id(),
2011 session_key.network_anonymization_key());
2012 // Picked 300ms based on mean time from
2013 // Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram.
2014 const int kDefaultRTT = 300 * quic::kNumMicrosPerMilli;
2015 if (!srtt)
2016 srtt = kDefaultRTT;
2017 return base::Microseconds(srtt);
2018 }
2019
GetDnsAliasesForSessionKey(const QuicSessionKey & key) const2020 const std::set<std::string>& QuicStreamFactory::GetDnsAliasesForSessionKey(
2021 const QuicSessionKey& key) const {
2022 auto it = dns_aliases_by_session_key_.find(key);
2023
2024 if (it == dns_aliases_by_session_key_.end()) {
2025 static const base::NoDestructor<std::set<std::string>> emptyvector_result;
2026 return *emptyvector_result;
2027 }
2028
2029 return it->second;
2030 }
2031
HasMatchingIpSession(const QuicSessionAliasKey & key,const std::vector<IPEndPoint> & ip_endpoints,const std::set<std::string> & aliases,bool use_dns_aliases)2032 bool QuicStreamFactory::HasMatchingIpSession(
2033 const QuicSessionAliasKey& key,
2034 const std::vector<IPEndPoint>& ip_endpoints,
2035 const std::set<std::string>& aliases,
2036 bool use_dns_aliases) {
2037 const quic::QuicServerId& server_id(key.server_id());
2038 DCHECK(!HasActiveSession(key.session_key()));
2039 for (const auto& address : ip_endpoints) {
2040 if (!base::Contains(ip_aliases_, address))
2041 continue;
2042
2043 const SessionSet& sessions = ip_aliases_[address];
2044 for (QuicChromiumClientSession* session : sessions) {
2045 if (!session->CanPool(server_id.host(), key.session_key()))
2046 continue;
2047 active_sessions_[key.session_key()] = session;
2048
2049 std::set<std::string> dns_aliases;
2050 if (use_dns_aliases) {
2051 dns_aliases = aliases;
2052 }
2053
2054 MapSessionToAliasKey(session, key, std::move(dns_aliases));
2055
2056 return true;
2057 }
2058 }
2059 return false;
2060 }
2061
OnJobComplete(Job * job,int rv)2062 void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
2063 auto iter = active_jobs_.find(job->key().session_key());
2064 DCHECK(iter != active_jobs_.end());
2065 if (rv == OK) {
2066 if (!is_quic_known_to_work_on_current_network_) {
2067 set_is_quic_known_to_work_on_current_network(true);
2068 }
2069
2070 auto session_it = active_sessions_.find(job->key().session_key());
2071 CHECK(session_it != active_sessions_.end());
2072 QuicChromiumClientSession* session = session_it->second;
2073 for (auto* request : iter->second->stream_requests()) {
2074 // Do not notify |request| yet.
2075 request->SetSession(session->CreateHandle(job->key().destination()));
2076 }
2077 }
2078
2079 for (auto* request : iter->second->stream_requests()) {
2080 // Even though we're invoking callbacks here, we don't need to worry
2081 // about |this| being deleted, because the factory is owned by the
2082 // profile which can not be deleted via callbacks.
2083 if (rv < 0) {
2084 job->PopulateNetErrorDetails(request->net_error_details());
2085 }
2086 request->OnRequestComplete(rv);
2087 }
2088 active_jobs_.erase(iter);
2089 }
2090
HasActiveSession(const QuicSessionKey & session_key) const2091 bool QuicStreamFactory::HasActiveSession(
2092 const QuicSessionKey& session_key) const {
2093 return base::Contains(active_sessions_, session_key);
2094 }
2095
HasActiveJob(const QuicSessionKey & session_key) const2096 bool QuicStreamFactory::HasActiveJob(const QuicSessionKey& session_key) const {
2097 return base::Contains(active_jobs_, session_key);
2098 }
2099
CreateSessionSync(const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,const HostResolverEndpointResult & endpoint_result,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,const NetLogWithSource & net_log,QuicChromiumClientSession ** session,handles::NetworkHandle * network)2100 int QuicStreamFactory::CreateSessionSync(
2101 const QuicSessionAliasKey& key,
2102 quic::ParsedQuicVersion quic_version,
2103 int cert_verify_flags,
2104 bool require_confirmation,
2105 const HostResolverEndpointResult& endpoint_result,
2106 base::TimeTicks dns_resolution_start_time,
2107 base::TimeTicks dns_resolution_end_time,
2108 const NetLogWithSource& net_log,
2109 QuicChromiumClientSession** session,
2110 handles::NetworkHandle* network) {
2111 TRACE_EVENT0(NetTracingCategory(), "QuicStreamFactory::CreateSession");
2112 // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
2113 // endpoint.
2114 IPEndPoint addr = endpoint_result.ip_endpoints.front();
2115 std::unique_ptr<DatagramClientSocket> socket(
2116 CreateSocket(net_log.net_log(), net_log.source()));
2117
2118 // If migrate_sessions_on_network_change_v2 is on, passing in
2119 // handles::kInvalidNetworkHandle will bind the socket to the default network.
2120 int rv = ConfigureSocket(socket.get(), addr, *network,
2121 key.session_key().socket_tag());
2122 if (rv != OK) {
2123 return rv;
2124 }
2125 bool closed_during_initialize = CreateSessionHelper(
2126 key, quic_version, cert_verify_flags, require_confirmation,
2127 endpoint_result, dns_resolution_start_time, dns_resolution_end_time,
2128 net_log, session, network, std::move(socket));
2129 if (closed_during_initialize) {
2130 DLOG(DFATAL) << "Session closed during initialize";
2131 *session = nullptr;
2132
2133 return ERR_CONNECTION_CLOSED;
2134 }
2135
2136 return OK;
2137 }
2138
CreateSessionAsync(CompletionOnceCallback callback,const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,const HostResolverEndpointResult & endpoint_result,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,const NetLogWithSource & net_log,QuicChromiumClientSession ** session,handles::NetworkHandle * network)2139 int QuicStreamFactory::CreateSessionAsync(
2140 CompletionOnceCallback callback,
2141 const QuicSessionAliasKey& key,
2142 quic::ParsedQuicVersion quic_version,
2143 int cert_verify_flags,
2144 bool require_confirmation,
2145 const HostResolverEndpointResult& endpoint_result,
2146 base::TimeTicks dns_resolution_start_time,
2147 base::TimeTicks dns_resolution_end_time,
2148 const NetLogWithSource& net_log,
2149 QuicChromiumClientSession** session,
2150 handles::NetworkHandle* network) {
2151 TRACE_EVENT0(NetTracingCategory(), "QuicStreamFactory::CreateSession");
2152 // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
2153 // endpoint.
2154 IPEndPoint addr = endpoint_result.ip_endpoints.front();
2155 std::unique_ptr<DatagramClientSocket> socket(
2156 CreateSocket(net_log.net_log(), net_log.source()));
2157 DatagramClientSocket* socket_ptr = socket.get();
2158 CompletionOnceCallback connect_and_configure_callback = base::BindOnce(
2159 &QuicStreamFactory::FinishCreateSession, weak_factory_.GetWeakPtr(),
2160 std::move(callback), key, quic_version, cert_verify_flags,
2161 require_confirmation, endpoint_result, dns_resolution_start_time,
2162 dns_resolution_end_time, net_log, session, network, std::move(socket));
2163
2164 // If migrate_sessions_on_network_change_v2 is on, passing in
2165 // handles::kInvalidNetworkHandle will bind the socket to the default network.
2166 return ConnectAndConfigureSocket(std::move(connect_and_configure_callback),
2167 socket_ptr, addr, *network,
2168 key.session_key().socket_tag());
2169 }
2170
FinishCreateSession(CompletionOnceCallback callback,const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,const HostResolverEndpointResult & endpoint_result,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,const NetLogWithSource & net_log,QuicChromiumClientSession ** session,handles::NetworkHandle * network,std::unique_ptr<DatagramClientSocket> socket,int rv)2171 void QuicStreamFactory::FinishCreateSession(
2172 CompletionOnceCallback callback,
2173 const QuicSessionAliasKey& key,
2174 quic::ParsedQuicVersion quic_version,
2175 int cert_verify_flags,
2176 bool require_confirmation,
2177 const HostResolverEndpointResult& endpoint_result,
2178 base::TimeTicks dns_resolution_start_time,
2179 base::TimeTicks dns_resolution_end_time,
2180 const NetLogWithSource& net_log,
2181 QuicChromiumClientSession** session,
2182 handles::NetworkHandle* network,
2183 std::unique_ptr<DatagramClientSocket> socket,
2184 int rv) {
2185 if (rv != OK) {
2186 std::move(callback).Run(rv);
2187 return;
2188 }
2189 bool closed_during_initialize = CreateSessionHelper(
2190 key, quic_version, cert_verify_flags, require_confirmation,
2191 endpoint_result, dns_resolution_start_time, dns_resolution_end_time,
2192 net_log, session, network, std::move(socket));
2193 if (closed_during_initialize) {
2194 DLOG(DFATAL) << "Session closed during initialize";
2195 *session = nullptr;
2196
2197 std::move(callback).Run(ERR_CONNECTION_CLOSED);
2198 return;
2199 }
2200
2201 std::move(callback).Run(OK);
2202 }
2203
CreateSessionHelper(const QuicSessionAliasKey & key,quic::ParsedQuicVersion quic_version,int cert_verify_flags,bool require_confirmation,const HostResolverEndpointResult & endpoint_result,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,const NetLogWithSource & net_log,QuicChromiumClientSession ** session,handles::NetworkHandle * network,std::unique_ptr<DatagramClientSocket> socket)2204 bool QuicStreamFactory::CreateSessionHelper(
2205 const QuicSessionAliasKey& key,
2206 quic::ParsedQuicVersion quic_version,
2207 int cert_verify_flags,
2208 bool require_confirmation,
2209 const HostResolverEndpointResult& endpoint_result,
2210 base::TimeTicks dns_resolution_start_time,
2211 base::TimeTicks dns_resolution_end_time,
2212 const NetLogWithSource& net_log,
2213 QuicChromiumClientSession** session,
2214 handles::NetworkHandle* network,
2215 std::unique_ptr<DatagramClientSocket> socket) {
2216 // TODO(https://crbug.com/1416409): This logic only knows how to try one IP
2217 // endpoint.
2218 IPEndPoint addr = endpoint_result.ip_endpoints.front();
2219 const quic::QuicServerId& server_id = key.server_id();
2220
2221 if (params_.migrate_sessions_on_network_change_v2 &&
2222 *network == handles::kInvalidNetworkHandle) {
2223 *network = socket->GetBoundNetwork();
2224 if (default_network_ == handles::kInvalidNetworkHandle) {
2225 // QuicStreamFactory may miss the default network signal before its
2226 // creation, update |default_network_| when the first socket is bound
2227 // to the default network.
2228 default_network_ = *network;
2229 connectivity_monitor_.SetInitialDefaultNetwork(default_network_);
2230 } else {
2231 UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.DefaultNetworkMatch",
2232 default_network_ == *network);
2233 }
2234 }
2235
2236 if (!helper_.get()) {
2237 helper_ = std::make_unique<QuicChromiumConnectionHelper>(clock_,
2238 random_generator_);
2239 }
2240
2241 if (!alarm_factory_.get()) {
2242 alarm_factory_ = std::make_unique<QuicChromiumAlarmFactory>(
2243 base::SingleThreadTaskRunner::GetCurrentDefault().get(), clock_);
2244 }
2245
2246 quic::QuicConnectionId connection_id =
2247 quic::QuicUtils::CreateRandomConnectionId(random_generator_);
2248 std::unique_ptr<QuicServerInfo> server_info;
2249 if (params_.max_server_configs_stored_in_properties > 0) {
2250 server_info = std::make_unique<PropertiesBasedQuicServerInfo>(
2251 server_id, key.session_key().network_anonymization_key(),
2252 http_server_properties_);
2253 }
2254 std::unique_ptr<CryptoClientConfigHandle> crypto_config_handle =
2255 CreateCryptoConfigHandle(key.session_key().network_anonymization_key());
2256 InitializeCachedStateInCryptoConfig(*crypto_config_handle, server_id,
2257 server_info);
2258
2259 QuicChromiumPacketWriter* writer =
2260 new QuicChromiumPacketWriter(socket.get(), task_runner_);
2261 quic::QuicConnection* connection = new quic::QuicConnection(
2262 connection_id, quic::QuicSocketAddress(), ToQuicSocketAddress(addr),
2263 helper_.get(), alarm_factory_.get(), writer, true /* owns_writer */,
2264 quic::Perspective::IS_CLIENT, {quic_version}, connection_id_generator_);
2265 connection->set_keep_alive_ping_timeout(ping_timeout_);
2266 connection->SetMaxPacketLength(params_.max_packet_length);
2267
2268 quic::QuicConfig config = config_;
2269 ConfigureInitialRttEstimate(
2270 server_id, key.session_key().network_anonymization_key(), &config);
2271
2272 // Use the factory to create a new socket performance watcher, and pass the
2273 // ownership to QuicChromiumClientSession.
2274 std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher;
2275 if (socket_performance_watcher_factory_) {
2276 socket_performance_watcher =
2277 socket_performance_watcher_factory_->CreateSocketPerformanceWatcher(
2278 SocketPerformanceWatcherFactory::PROTOCOL_QUIC, addr.address());
2279 }
2280
2281 // Wait for handshake confirmation before allowing streams to be created if
2282 // either this session or the factory require confirmation.
2283 if (!is_quic_known_to_work_on_current_network_) {
2284 require_confirmation = true;
2285 }
2286
2287 *session = new QuicChromiumClientSession(
2288 connection, std::move(socket), this, quic_crypto_client_stream_factory_,
2289 clock_, transport_security_state_, ssl_config_service_,
2290 std::move(server_info), key.session_key(), require_confirmation,
2291 params_.migrate_sessions_early_v2,
2292 params_.migrate_sessions_on_network_change_v2, default_network_,
2293 retransmittable_on_wire_timeout_, params_.migrate_idle_sessions,
2294 params_.allow_port_migration, params_.idle_session_migration_period,
2295 params_.max_time_on_non_default_network,
2296 params_.max_migrations_to_non_default_network_on_write_error,
2297 params_.max_migrations_to_non_default_network_on_path_degrading,
2298 yield_after_packets_, yield_after_duration_, cert_verify_flags, config,
2299 std::move(crypto_config_handle),
2300 network_connection_.connection_description(), dns_resolution_start_time,
2301 dns_resolution_end_time,
2302 std::make_unique<quic::QuicClientPushPromiseIndex>(), push_delegate_,
2303 tick_clock_, task_runner_, std::move(socket_performance_watcher),
2304 endpoint_result, net_log.net_log());
2305
2306 all_sessions_[*session] = key; // owning pointer
2307 writer->set_delegate(*session);
2308 (*session)->AddConnectivityObserver(&connectivity_monitor_);
2309
2310 (*session)->Initialize();
2311 bool closed_during_initialize = !base::Contains(all_sessions_, *session) ||
2312 !(*session)->connection()->connected();
2313 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession",
2314 closed_during_initialize);
2315 return closed_during_initialize;
2316 }
2317
ActivateSession(const QuicSessionAliasKey & key,QuicChromiumClientSession * session,std::set<std::string> dns_aliases)2318 void QuicStreamFactory::ActivateSession(const QuicSessionAliasKey& key,
2319 QuicChromiumClientSession* session,
2320 std::set<std::string> dns_aliases) {
2321 DCHECK(!HasActiveSession(key.session_key()));
2322 UMA_HISTOGRAM_COUNTS_1M("Net.QuicActiveSessions", active_sessions_.size());
2323 active_sessions_[key.session_key()] = session;
2324 MapSessionToAliasKey(session, key, std::move(dns_aliases));
2325 const IPEndPoint peer_address =
2326 ToIPEndPoint(session->connection()->peer_address());
2327 DCHECK(!base::Contains(ip_aliases_[peer_address], session));
2328 ip_aliases_[peer_address].insert(session);
2329 DCHECK(!base::Contains(session_peer_ip_, session));
2330 session_peer_ip_[session] = peer_address;
2331 }
2332
MarkAllActiveSessionsGoingAway(AllActiveSessionsGoingAwayReason reason)2333 void QuicStreamFactory::MarkAllActiveSessionsGoingAway(
2334 AllActiveSessionsGoingAwayReason reason) {
2335 while (!active_sessions_.empty()) {
2336 QuicChromiumClientSession* session = active_sessions_.begin()->second;
2337 // If IP address change is detected, disable session's connectivity
2338 // monitoring by remove the Delegate.
2339 if (reason == kIPAddressChanged)
2340 connectivity_monitor_.OnSessionGoingAwayOnIPAddressChange(session);
2341 OnSessionGoingAway(session);
2342 }
2343 }
2344
ConfigureInitialRttEstimate(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key,quic::QuicConfig * config)2345 void QuicStreamFactory::ConfigureInitialRttEstimate(
2346 const quic::QuicServerId& server_id,
2347 const NetworkAnonymizationKey& network_anonymization_key,
2348 quic::QuicConfig* config) {
2349 const base::TimeDelta* srtt =
2350 GetServerNetworkStatsSmoothedRtt(server_id, network_anonymization_key);
2351 // Sometimes *srtt is negative. See https://crbug.com/1225616.
2352 // TODO(ricea): When the root cause of the negative value is fixed, change the
2353 // non-negative assertion to a DCHECK.
2354 if (srtt && srtt->is_positive()) {
2355 SetInitialRttEstimate(*srtt, INITIAL_RTT_CACHED, config);
2356 return;
2357 }
2358
2359 NetworkChangeNotifier::ConnectionType type =
2360 network_connection_.connection_type();
2361 if (type == NetworkChangeNotifier::CONNECTION_2G) {
2362 SetInitialRttEstimate(base::Milliseconds(1200), INITIAL_RTT_CACHED, config);
2363 return;
2364 }
2365
2366 if (type == NetworkChangeNotifier::CONNECTION_3G) {
2367 SetInitialRttEstimate(base::Milliseconds(400), INITIAL_RTT_CACHED, config);
2368 return;
2369 }
2370
2371 if (params_.initial_rtt_for_handshake.is_positive()) {
2372 SetInitialRttEstimate(
2373 base::Microseconds(params_.initial_rtt_for_handshake.InMicroseconds()),
2374 INITIAL_RTT_DEFAULT, config);
2375 return;
2376 }
2377
2378 SetInitialRttEstimate(base::TimeDelta(), INITIAL_RTT_DEFAULT, config);
2379 }
2380
GetServerNetworkStatsSmoothedRttInMicroseconds(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key) const2381 int64_t QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds(
2382 const quic::QuicServerId& server_id,
2383 const NetworkAnonymizationKey& network_anonymization_key) const {
2384 const base::TimeDelta* srtt =
2385 GetServerNetworkStatsSmoothedRtt(server_id, network_anonymization_key);
2386 return srtt == nullptr ? 0 : srtt->InMicroseconds();
2387 }
2388
GetServerNetworkStatsSmoothedRtt(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key) const2389 const base::TimeDelta* QuicStreamFactory::GetServerNetworkStatsSmoothedRtt(
2390 const quic::QuicServerId& server_id,
2391 const NetworkAnonymizationKey& network_anonymization_key) const {
2392 url::SchemeHostPort server("https", server_id.host(), server_id.port());
2393 const ServerNetworkStats* stats =
2394 http_server_properties_->GetServerNetworkStats(server,
2395 network_anonymization_key);
2396 if (stats == nullptr)
2397 return nullptr;
2398 return &(stats->srtt);
2399 }
2400
WasQuicRecentlyBroken(const QuicSessionKey & session_key) const2401 bool QuicStreamFactory::WasQuicRecentlyBroken(
2402 const QuicSessionKey& session_key) const {
2403 const AlternativeService alternative_service(
2404 kProtoQUIC, HostPortPair(session_key.server_id().host(),
2405 session_key.server_id().port()));
2406 return http_server_properties_->WasAlternativeServiceRecentlyBroken(
2407 alternative_service, session_key.network_anonymization_key());
2408 }
2409
InitializeMigrationOptions()2410 void QuicStreamFactory::InitializeMigrationOptions() {
2411 // The following list of options cannot be set immediately until
2412 // prerequisites are met. Cache the initial setting in local variables and
2413 // reset them in |params_|.
2414 bool migrate_sessions_on_network_change =
2415 params_.migrate_sessions_on_network_change_v2;
2416 bool migrate_sessions_early = params_.migrate_sessions_early_v2;
2417 bool retry_on_alternate_network_before_handshake =
2418 params_.retry_on_alternate_network_before_handshake;
2419 bool migrate_idle_sessions = params_.migrate_idle_sessions;
2420 bool allow_port_migration = params_.allow_port_migration;
2421 params_.migrate_sessions_on_network_change_v2 = false;
2422 params_.migrate_sessions_early_v2 = false;
2423 params_.allow_port_migration = false;
2424 params_.retry_on_alternate_network_before_handshake = false;
2425 params_.migrate_idle_sessions = false;
2426
2427 // TODO(zhongyi): deprecate |goaway_sessions_on_ip_change| if the experiment
2428 // is no longer needed.
2429 // goaway_sessions_on_ip_change and close_sessions_on_ip_change should never
2430 // be simultaneously set to true.
2431 DCHECK(!(params_.close_sessions_on_ip_change &&
2432 params_.goaway_sessions_on_ip_change));
2433
2434 bool handle_ip_change = params_.close_sessions_on_ip_change ||
2435 params_.goaway_sessions_on_ip_change;
2436 // If IP address changes are handled explicitly, connection migration should
2437 // not be set.
2438 DCHECK(!(handle_ip_change && migrate_sessions_on_network_change));
2439
2440 if (handle_ip_change)
2441 NetworkChangeNotifier::AddIPAddressObserver(this);
2442
2443 if (allow_port_migration) {
2444 params_.allow_port_migration = true;
2445 if (migrate_idle_sessions) {
2446 params_.migrate_idle_sessions = true;
2447 }
2448 }
2449
2450 if (!NetworkChangeNotifier::AreNetworkHandlesSupported())
2451 return;
2452
2453 NetworkChangeNotifier::AddNetworkObserver(this);
2454 // Perform checks on the connection migration options.
2455 if (!migrate_sessions_on_network_change) {
2456 DCHECK(!migrate_sessions_early);
2457 return;
2458 }
2459
2460 // Enable migration on platform notifications.
2461 params_.migrate_sessions_on_network_change_v2 = true;
2462
2463 if (!migrate_sessions_early) {
2464 DCHECK(!retry_on_alternate_network_before_handshake);
2465 return;
2466 }
2467
2468 // Enable migration on path degrading.
2469 params_.migrate_sessions_early_v2 = true;
2470 // Set retransmittable on wire timeout for migration on path degrading if no
2471 // value is specified.
2472 if (retransmittable_on_wire_timeout_.IsZero()) {
2473 retransmittable_on_wire_timeout_ = quic::QuicTime::Delta::FromMicroseconds(
2474 kDefaultRetransmittableOnWireTimeout.InMicroseconds());
2475 }
2476
2477 // Enable retry on alternate network before handshake.
2478 if (retry_on_alternate_network_before_handshake)
2479 params_.retry_on_alternate_network_before_handshake = true;
2480
2481 // Enable migration for idle sessions.
2482 if (migrate_idle_sessions)
2483 params_.migrate_idle_sessions = true;
2484 }
2485
InitializeCachedStateInCryptoConfig(const CryptoClientConfigHandle & crypto_config_handle,const quic::QuicServerId & server_id,const std::unique_ptr<QuicServerInfo> & server_info)2486 void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
2487 const CryptoClientConfigHandle& crypto_config_handle,
2488 const quic::QuicServerId& server_id,
2489 const std::unique_ptr<QuicServerInfo>& server_info) {
2490 quic::QuicCryptoClientConfig::CachedState* cached =
2491 crypto_config_handle.GetConfig()->LookupOrCreate(server_id);
2492
2493 if (!cached->IsEmpty()) {
2494 return;
2495 }
2496
2497 if (!server_info || !server_info->Load()) {
2498 return;
2499 }
2500
2501 cached->Initialize(server_info->state().server_config,
2502 server_info->state().source_address_token,
2503 server_info->state().certs, server_info->state().cert_sct,
2504 server_info->state().chlo_hash,
2505 server_info->state().server_config_sig, clock_->WallNow(),
2506 quic::QuicWallTime::Zero());
2507 }
2508
ProcessGoingAwaySession(QuicChromiumClientSession * session,const quic::QuicServerId & server_id,bool session_was_active)2509 void QuicStreamFactory::ProcessGoingAwaySession(
2510 QuicChromiumClientSession* session,
2511 const quic::QuicServerId& server_id,
2512 bool session_was_active) {
2513 if (!http_server_properties_)
2514 return;
2515
2516 const quic::QuicConnectionStats& stats = session->connection()->GetStats();
2517 const AlternativeService alternative_service(
2518 kProtoQUIC, HostPortPair(server_id.host(), server_id.port()));
2519
2520 url::SchemeHostPort server("https", server_id.host(), server_id.port());
2521 // Do nothing if QUIC is currently marked as broken.
2522 if (http_server_properties_->IsAlternativeServiceBroken(
2523 alternative_service,
2524 session->quic_session_key().network_anonymization_key())) {
2525 return;
2526 }
2527
2528 if (session->OneRttKeysAvailable()) {
2529 http_server_properties_->ConfirmAlternativeService(
2530 alternative_service,
2531 session->quic_session_key().network_anonymization_key());
2532 ServerNetworkStats network_stats;
2533 network_stats.srtt = base::Microseconds(stats.srtt_us);
2534 network_stats.bandwidth_estimate = stats.estimated_bandwidth;
2535 http_server_properties_->SetServerNetworkStats(
2536 server, session->quic_session_key().network_anonymization_key(),
2537 network_stats);
2538 return;
2539 }
2540
2541 http_server_properties_->ClearServerNetworkStats(
2542 server, session->quic_session_key().network_anonymization_key());
2543
2544 UMA_HISTOGRAM_COUNTS_1M("Net.QuicHandshakeNotConfirmedNumPacketsReceived",
2545 stats.packets_received);
2546
2547 if (!session_was_active)
2548 return;
2549
2550 // TODO(rch): In the special case where the session has received no packets
2551 // from the peer, we should consider blocking this differently so that we
2552 // still race TCP but we don't consider the session connected until the
2553 // handshake has been confirmed.
2554 HistogramBrokenAlternateProtocolLocation(
2555 BROKEN_ALTERNATE_PROTOCOL_LOCATION_QUIC_STREAM_FACTORY);
2556
2557 // Since the session was active, there's no longer an HttpStreamFactory::Job
2558 // running which can mark it broken, unless the TCP job also fails. So to
2559 // avoid not using QUIC when we otherwise could, we mark it as recently
2560 // broken, which means that 0-RTT will be disabled but we'll still race.
2561 http_server_properties_->MarkAlternativeServiceRecentlyBroken(
2562 alternative_service,
2563 session->quic_session_key().network_anonymization_key());
2564 }
2565
MapSessionToAliasKey(QuicChromiumClientSession * session,const QuicSessionAliasKey & key,std::set<std::string> dns_aliases)2566 void QuicStreamFactory::MapSessionToAliasKey(
2567 QuicChromiumClientSession* session,
2568 const QuicSessionAliasKey& key,
2569 std::set<std::string> dns_aliases) {
2570 session_aliases_[session].insert(key);
2571 dns_aliases_by_session_key_[key.session_key()] = std::move(dns_aliases);
2572 }
2573
UnmapSessionFromSessionAliases(QuicChromiumClientSession * session)2574 void QuicStreamFactory::UnmapSessionFromSessionAliases(
2575 QuicChromiumClientSession* session) {
2576 for (const auto& key : session_aliases_[session])
2577 dns_aliases_by_session_key_.erase(key.session_key());
2578 session_aliases_.erase(session);
2579 }
2580
2581 std::unique_ptr<QuicStreamFactory::CryptoClientConfigHandle>
CreateCryptoConfigHandle(const NetworkAnonymizationKey & network_anonymization_key)2582 QuicStreamFactory::CreateCryptoConfigHandle(
2583 const NetworkAnonymizationKey& network_anonymization_key) {
2584 NetworkAnonymizationKey actual_network_anonymization_key =
2585 use_network_anonymization_key_for_crypto_configs_
2586 ? network_anonymization_key
2587 : NetworkAnonymizationKey();
2588
2589 // If there's a matching entry in |active_crypto_config_map_|, create a
2590 // CryptoClientConfigHandle for it.
2591 auto map_iterator =
2592 active_crypto_config_map_.find(actual_network_anonymization_key);
2593 if (map_iterator != active_crypto_config_map_.end()) {
2594 DCHECK_GT(map_iterator->second->num_refs(), 0);
2595
2596 // If there's an active matching crypto config, there shouldn't also be an
2597 // inactive matching crypto config.
2598 DCHECK(recent_crypto_config_map_.Peek(actual_network_anonymization_key) ==
2599 recent_crypto_config_map_.end());
2600
2601 return std::make_unique<CryptoClientConfigHandle>(map_iterator);
2602 }
2603
2604 // If there's a matching entry in |recent_crypto_config_map_|, move it to
2605 // |active_crypto_config_map_| and create a CryptoClientConfigHandle for it.
2606 auto mru_iterator =
2607 recent_crypto_config_map_.Peek(actual_network_anonymization_key);
2608 if (mru_iterator != recent_crypto_config_map_.end()) {
2609 DCHECK_EQ(mru_iterator->second->num_refs(), 0);
2610
2611 map_iterator = active_crypto_config_map_
2612 .emplace(std::make_pair(actual_network_anonymization_key,
2613 std::move(mru_iterator->second)))
2614 .first;
2615 recent_crypto_config_map_.Erase(mru_iterator);
2616 return std::make_unique<CryptoClientConfigHandle>(map_iterator);
2617 }
2618
2619 // Otherwise, create a new QuicCryptoClientConfigOwner and add it to
2620 // |active_crypto_config_map_|.
2621 std::unique_ptr<QuicCryptoClientConfigOwner> crypto_config_owner =
2622 std::make_unique<QuicCryptoClientConfigOwner>(
2623 std::make_unique<ProofVerifierChromium>(
2624 cert_verifier_, ct_policy_enforcer_, transport_security_state_,
2625 sct_auditing_delegate_,
2626 HostsFromOrigins(params_.origins_to_force_quic_on),
2627 actual_network_anonymization_key),
2628 std::make_unique<quic::QuicClientSessionCache>(), this);
2629
2630 quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config();
2631 crypto_config->set_user_agent_id(params_.user_agent_id);
2632 crypto_config->AddCanonicalSuffix(".c.youtube.com");
2633 crypto_config->AddCanonicalSuffix(".ggpht.com");
2634 crypto_config->AddCanonicalSuffix(".googlevideo.com");
2635 crypto_config->AddCanonicalSuffix(".googleusercontent.com");
2636 crypto_config->AddCanonicalSuffix(".gvt1.com");
2637 if (SSLKeyLoggerManager::IsActive()) {
2638 SSL_CTX_set_keylog_callback(crypto_config->ssl_ctx(),
2639 SSLKeyLoggerManager::KeyLogCallback);
2640 }
2641
2642 ConfigureCertificateCompression(crypto_config->ssl_ctx());
2643
2644 if (!prefer_aes_gcm_recorded_) {
2645 bool prefer_aes_gcm =
2646 !crypto_config->aead.empty() && (crypto_config->aead[0] == quic::kAESG);
2647 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.PreferAesGcm", prefer_aes_gcm);
2648 prefer_aes_gcm_recorded_ = true;
2649 }
2650
2651 map_iterator = active_crypto_config_map_
2652 .emplace(std::make_pair(actual_network_anonymization_key,
2653 std::move(crypto_config_owner)))
2654 .first;
2655 return std::make_unique<CryptoClientConfigHandle>(map_iterator);
2656 }
2657
OnAllCryptoClientRefReleased(QuicCryptoClientConfigMap::iterator & map_iterator)2658 void QuicStreamFactory::OnAllCryptoClientRefReleased(
2659 QuicCryptoClientConfigMap::iterator& map_iterator) {
2660 DCHECK_EQ(0, map_iterator->second->num_refs());
2661 recent_crypto_config_map_.Put(map_iterator->first,
2662 std::move(map_iterator->second));
2663 active_crypto_config_map_.erase(map_iterator);
2664 }
2665
CollectDataOnPlatformNotification(enum QuicPlatformNotification notification,handles::NetworkHandle affected_network) const2666 void QuicStreamFactory::CollectDataOnPlatformNotification(
2667 enum QuicPlatformNotification notification,
2668 handles::NetworkHandle affected_network) const {
2669 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.PlatformNotification",
2670 notification, NETWORK_NOTIFICATION_MAX);
2671 connectivity_monitor_.RecordConnectivityStatsToHistograms(
2672 QuicPlatformNotificationToString(notification), affected_network);
2673 }
2674
2675 std::unique_ptr<QuicCryptoClientConfigHandle>
GetCryptoConfigForTesting(const NetworkAnonymizationKey & network_anonymization_key)2676 QuicStreamFactory::GetCryptoConfigForTesting(
2677 const NetworkAnonymizationKey& network_anonymization_key) {
2678 return CreateCryptoConfigHandle(network_anonymization_key);
2679 }
2680
CryptoConfigCacheIsEmptyForTesting(const quic::QuicServerId & server_id,const NetworkAnonymizationKey & network_anonymization_key)2681 bool QuicStreamFactory::CryptoConfigCacheIsEmptyForTesting(
2682 const quic::QuicServerId& server_id,
2683 const NetworkAnonymizationKey& network_anonymization_key) {
2684 quic::QuicCryptoClientConfig::CachedState* cached = nullptr;
2685 NetworkAnonymizationKey actual_network_anonymization_key =
2686 use_network_anonymization_key_for_crypto_configs_
2687 ? network_anonymization_key
2688 : NetworkAnonymizationKey();
2689 auto map_iterator =
2690 active_crypto_config_map_.find(actual_network_anonymization_key);
2691 if (map_iterator != active_crypto_config_map_.end()) {
2692 cached = map_iterator->second->config()->LookupOrCreate(server_id);
2693 } else {
2694 auto mru_iterator =
2695 recent_crypto_config_map_.Peek(actual_network_anonymization_key);
2696 if (mru_iterator != recent_crypto_config_map_.end()) {
2697 cached = mru_iterator->second->config()->LookupOrCreate(server_id);
2698 }
2699 }
2700 return !cached || cached->IsEmpty();
2701 }
2702
2703 } // namespace net
2704