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