• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/quic/quic_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