xref: /aosp_15_r20/external/cronet/net/quic/quic_chromium_client_session.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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_chromium_client_session.h"
6 
7 #include <memory>
8 #include <set>
9 #include <string_view>
10 #include <utility>
11 
12 #include "base/containers/contains.h"
13 #include "base/functional/bind.h"
14 #include "base/functional/callback_helpers.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h"
18 #include "base/metrics/histogram_functions.h"
19 #include "base/metrics/histogram_macros.h"
20 #include "base/metrics/sparse_histogram.h"
21 #include "base/no_destructor.h"
22 #include "base/observer_list.h"
23 #include "base/ranges/algorithm.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/task/sequenced_task_runner.h"
27 #include "base/task/single_thread_task_runner.h"
28 #include "base/time/tick_clock.h"
29 #include "base/trace_event/memory_usage_estimator.h"
30 #include "base/values.h"
31 #include "net/base/connection_endpoint_metadata.h"
32 #include "net/base/features.h"
33 #include "net/base/io_buffer.h"
34 #include "net/base/net_errors.h"
35 #include "net/base/network_activity_monitor.h"
36 #include "net/base/network_anonymization_key.h"
37 #include "net/base/privacy_mode.h"
38 #include "net/base/session_usage.h"
39 #include "net/base/url_util.h"
40 #include "net/cert/signed_certificate_timestamp_and_status.h"
41 #include "net/dns/public/secure_dns_policy.h"
42 #include "net/http/transport_security_state.h"
43 #include "net/log/net_log_event_type.h"
44 #include "net/log/net_log_source_type.h"
45 #include "net/log/net_log_values.h"
46 #include "net/quic/address_utils.h"
47 #include "net/quic/crypto/proof_verifier_chromium.h"
48 #include "net/quic/quic_chromium_connection_helper.h"
49 #include "net/quic/quic_chromium_packet_writer.h"
50 #include "net/quic/quic_crypto_client_stream_factory.h"
51 #include "net/quic/quic_server_info.h"
52 #include "net/quic/quic_session_pool.h"
53 #include "net/socket/datagram_client_socket.h"
54 #include "net/spdy/spdy_http_utils.h"
55 #include "net/spdy/spdy_log_util.h"
56 #include "net/spdy/spdy_session.h"
57 #include "net/ssl/ssl_connection_status_flags.h"
58 #include "net/ssl/ssl_info.h"
59 #include "net/third_party/quiche/src/quiche/quic/core/quic_stream_priority.h"
60 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
61 #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h"
62 #include "net/traffic_annotation/network_traffic_annotation.h"
63 #include "net/websockets/websocket_quic_spdy_stream.h"
64 #include "third_party/boringssl/src/include/openssl/ssl.h"
65 #include "url/origin.h"
66 #include "url/scheme_host_port.h"
67 
68 namespace net {
69 
70 namespace features {
71 
72 BASE_FEATURE(kQuicMigrationIgnoreDisconnectSignalDuringProbing,
73              "kQuicMigrationIgnoreDisconnectSignalDuringProbing",
74              base::FEATURE_DISABLED_BY_DEFAULT);
75 
76 }  // namespace features
77 
78 namespace {
79 
MidMigrationCallbackForTesting()80 base::OnceClosure& MidMigrationCallbackForTesting() {
81   static base::NoDestructor<base::OnceClosure> callback;
82   return *callback;
83 }
84 
85 // IPv6 packets have an additional 20 bytes of overhead than IPv4 packets.
86 const size_t kAdditionalOverheadForIPv6 = 20;
87 
88 // Maximum number of Readers that are created for any session due to
89 // connection migration. A new Reader is created every time this endpoint's
90 // IP address changes.
91 const size_t kMaxReadersPerQuicSession = 5;
92 
93 // Time to wait (in seconds) when no networks are available and
94 // migrating sessions need to wait for a new network to connect.
95 const size_t kWaitTimeForNewNetworkSecs = 10;
96 
97 const size_t kMinRetryTimeForDefaultNetworkSecs = 1;
98 
99 // These values are persisted to logs. Entries should not be renumbered,
100 // and numeric values should never be reused.
101 enum class AcceptChEntries {
102   kNoEntries = 0,
103   kOnlyValidEntries = 1,
104   kOnlyInvalidEntries = 2,
105   kBothValidAndInvalidEntries = 3,
106   kMaxValue = kBothValidAndInvalidEntries,
107 };
108 
LogAcceptChFrameReceivedHistogram(bool has_valid_entry,bool has_invalid_entry)109 void LogAcceptChFrameReceivedHistogram(bool has_valid_entry,
110                                        bool has_invalid_entry) {
111   AcceptChEntries value;
112   if (has_valid_entry) {
113     if (has_invalid_entry) {
114       value = AcceptChEntries::kBothValidAndInvalidEntries;
115     } else {
116       value = AcceptChEntries::kOnlyValidEntries;
117     }
118   } else {
119     if (has_invalid_entry) {
120       value = AcceptChEntries::kOnlyInvalidEntries;
121     } else {
122       value = AcceptChEntries::kNoEntries;
123     }
124   }
125   base::UmaHistogramEnumeration("Net.QuicSession.AcceptChFrameReceivedViaAlps",
126                                 value);
127 }
128 
LogAcceptChForOriginHistogram(bool value)129 void LogAcceptChForOriginHistogram(bool value) {
130   base::UmaHistogramBoolean("Net.QuicSession.AcceptChForOrigin", value);
131 }
132 
RecordConnectionCloseErrorCodeImpl(const std::string & histogram,uint64_t error,bool is_google_host,bool handshake_confirmed,bool has_ech_config_list)133 void RecordConnectionCloseErrorCodeImpl(const std::string& histogram,
134                                         uint64_t error,
135                                         bool is_google_host,
136                                         bool handshake_confirmed,
137                                         bool has_ech_config_list) {
138   base::UmaHistogramSparse(histogram, error);
139 
140   if (handshake_confirmed) {
141     base::UmaHistogramSparse(histogram + ".HandshakeConfirmed", error);
142   } else {
143     base::UmaHistogramSparse(histogram + ".HandshakeNotConfirmed", error);
144   }
145 
146   if (is_google_host) {
147     base::UmaHistogramSparse(histogram + "Google", error);
148 
149     if (handshake_confirmed) {
150       base::UmaHistogramSparse(histogram + "Google.HandshakeConfirmed", error);
151     } else {
152       base::UmaHistogramSparse(histogram + "Google.HandshakeNotConfirmed",
153                                error);
154     }
155   }
156 
157   // Record a set of metrics based on whether ECH was advertised in DNS. The ECH
158   // experiment does not change DNS behavior, so this measures the same servers
159   // in both experiment and control groups.
160   if (has_ech_config_list) {
161     base::UmaHistogramSparse(histogram + "ECH", error);
162 
163     if (handshake_confirmed) {
164       base::UmaHistogramSparse(histogram + "ECH.HandshakeConfirmed", error);
165     } else {
166       base::UmaHistogramSparse(histogram + "ECH.HandshakeNotConfirmed", error);
167     }
168   }
169 }
170 
LogMigrateToSocketStatus(bool success)171 void LogMigrateToSocketStatus(bool success) {
172   UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.MigrateToSocketSuccess", success);
173 }
174 
RecordConnectionCloseErrorCode(const quic::QuicConnectionCloseFrame & frame,quic::ConnectionCloseSource source,std::string_view hostname,bool handshake_confirmed,bool has_ech_config_list)175 void RecordConnectionCloseErrorCode(const quic::QuicConnectionCloseFrame& frame,
176                                     quic::ConnectionCloseSource source,
177                                     std::string_view hostname,
178                                     bool handshake_confirmed,
179                                     bool has_ech_config_list) {
180   bool is_google_host = IsGoogleHost(hostname);
181   std::string histogram = "Net.QuicSession.ConnectionCloseErrorCode";
182 
183   if (source == quic::ConnectionCloseSource::FROM_SELF) {
184     // When sending a CONNECTION_CLOSE frame, it is sufficient to record
185     // |quic_error_code|.
186     histogram += "Client";
187     RecordConnectionCloseErrorCodeImpl(histogram, frame.quic_error_code,
188                                        is_google_host, handshake_confirmed,
189                                        has_ech_config_list);
190     return;
191   }
192 
193   histogram += "Server";
194 
195   // Record |quic_error_code|.  Note that when using IETF QUIC, this is
196   // extracted from the CONNECTION_CLOSE frame reason phrase, and might be
197   // QUIC_IETF_GQUIC_ERROR_MISSING.
198   RecordConnectionCloseErrorCodeImpl(histogram, frame.quic_error_code,
199                                      is_google_host, handshake_confirmed,
200                                      has_ech_config_list);
201 
202   // For IETF QUIC frames, also record the error code received on the wire.
203   if (frame.close_type == quic::IETF_QUIC_TRANSPORT_CONNECTION_CLOSE) {
204     histogram += "IetfTransport";
205     RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
206                                        is_google_host, handshake_confirmed,
207                                        has_ech_config_list);
208     if (frame.quic_error_code == quic::QUIC_IETF_GQUIC_ERROR_MISSING) {
209       histogram += "GQuicErrorMissing";
210       RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
211                                          is_google_host, handshake_confirmed,
212                                          has_ech_config_list);
213     }
214   } else if (frame.close_type == quic::IETF_QUIC_APPLICATION_CONNECTION_CLOSE) {
215     histogram += "IetfApplication";
216     RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
217                                        is_google_host, handshake_confirmed,
218                                        has_ech_config_list);
219     if (frame.quic_error_code == quic::QUIC_IETF_GQUIC_ERROR_MISSING) {
220       histogram += "GQuicErrorMissing";
221       RecordConnectionCloseErrorCodeImpl(histogram, frame.wire_error_code,
222                                          is_google_host, handshake_confirmed,
223                                          has_ech_config_list);
224     }
225   }
226 }
227 
NetLogQuicMigrationFailureParams(quic::QuicConnectionId connection_id,std::string_view reason)228 base::Value::Dict NetLogQuicMigrationFailureParams(
229     quic::QuicConnectionId connection_id,
230     std::string_view reason) {
231   return base::Value::Dict()
232       .Set("connection_id", connection_id.ToString())
233       .Set("reason", reason);
234 }
235 
NetLogQuicMigrationSuccessParams(quic::QuicConnectionId connection_id)236 base::Value::Dict NetLogQuicMigrationSuccessParams(
237     quic::QuicConnectionId connection_id) {
238   return base::Value::Dict().Set("connection_id", connection_id.ToString());
239 }
240 
NetLogProbingResultParams(handles::NetworkHandle network,const quic::QuicSocketAddress * peer_address,bool is_success)241 base::Value::Dict NetLogProbingResultParams(
242     handles::NetworkHandle network,
243     const quic::QuicSocketAddress* peer_address,
244     bool is_success) {
245   return base::Value::Dict()
246       .Set("network", base::NumberToString(network))
247       .Set("peer address", peer_address->ToString())
248       .Set("is_success", is_success);
249 }
250 
NetLogAcceptChFrameReceivedParams(spdy::AcceptChOriginValuePair entry)251 base::Value::Dict NetLogAcceptChFrameReceivedParams(
252     spdy::AcceptChOriginValuePair entry) {
253   return base::Value::Dict()
254       .Set("origin", entry.origin)
255       .Set("accept_ch", entry.value);
256 }
257 
258 // Histogram for recording the different reasons that a QUIC session is unable
259 // to complete the handshake.
260 enum HandshakeFailureReason {
261   HANDSHAKE_FAILURE_UNKNOWN = 0,
262   HANDSHAKE_FAILURE_BLACK_HOLE = 1,
263   HANDSHAKE_FAILURE_PUBLIC_RESET = 2,
264   NUM_HANDSHAKE_FAILURE_REASONS = 3,
265 };
266 
RecordHandshakeFailureReason(HandshakeFailureReason reason)267 void RecordHandshakeFailureReason(HandshakeFailureReason reason) {
268   UMA_HISTOGRAM_ENUMERATION(
269       "Net.QuicSession.ConnectionClose.HandshakeNotConfirmed.Reason", reason,
270       NUM_HANDSHAKE_FAILURE_REASONS);
271 }
272 
273 // Note: these values must be kept in sync with the corresponding values in:
274 // tools/metrics/histograms/histograms.xml
275 enum HandshakeState {
276   STATE_STARTED = 0,
277   STATE_ENCRYPTION_ESTABLISHED = 1,
278   STATE_HANDSHAKE_CONFIRMED = 2,
279   STATE_FAILED = 3,
280   NUM_HANDSHAKE_STATES = 4
281 };
282 
283 enum class ZeroRttState {
284   kAttemptedAndSucceeded = 0,
285   kAttemptedAndRejected = 1,
286   kNotAttempted = 2,
287   kMaxValue = kNotAttempted,
288 };
289 
RecordHandshakeState(HandshakeState state)290 void RecordHandshakeState(HandshakeState state) {
291   UMA_HISTOGRAM_ENUMERATION("Net.QuicHandshakeState", state,
292                             NUM_HANDSHAKE_STATES);
293 }
294 
MigrationCauseToString(MigrationCause cause)295 std::string MigrationCauseToString(MigrationCause cause) {
296   switch (cause) {
297     case UNKNOWN_CAUSE:
298       return "Unknown";
299     case ON_NETWORK_CONNECTED:
300       return "OnNetworkConnected";
301     case ON_NETWORK_DISCONNECTED:
302       return "OnNetworkDisconnected";
303     case ON_WRITE_ERROR:
304       return "OnWriteError";
305     case ON_NETWORK_MADE_DEFAULT:
306       return "OnNetworkMadeDefault";
307     case ON_MIGRATE_BACK_TO_DEFAULT_NETWORK:
308       return "OnMigrateBackToDefaultNetwork";
309     case CHANGE_NETWORK_ON_PATH_DEGRADING:
310       return "OnPathDegrading";
311     case CHANGE_PORT_ON_PATH_DEGRADING:
312       return "ChangePortOnPathDegrading";
313     case NEW_NETWORK_CONNECTED_POST_PATH_DEGRADING:
314       return "NewNetworkConnectedPostPathDegrading";
315     case ON_SERVER_PREFERRED_ADDRESS_AVAILABLE:
316       return "OnServerPreferredAddressAvailable";
317     default:
318       QUICHE_NOTREACHED();
319       break;
320   }
321   return "InvalidCause";
322 }
323 
NetLogQuicClientSessionParams(const NetLogWithSource & net_log,const QuicSessionKey * session_key,const quic::QuicConnectionId & connection_id,const quic::QuicConnectionId & client_connection_id,const quic::ParsedQuicVersionVector & supported_versions,int cert_verify_flags,bool require_confirmation,base::span<const uint8_t> ech_config_list)324 base::Value::Dict NetLogQuicClientSessionParams(
325     const NetLogWithSource& net_log,
326     const QuicSessionKey* session_key,
327     const quic::QuicConnectionId& connection_id,
328     const quic::QuicConnectionId& client_connection_id,
329     const quic::ParsedQuicVersionVector& supported_versions,
330     int cert_verify_flags,
331     bool require_confirmation,
332     base::span<const uint8_t> ech_config_list) {
333   auto dict =
334       base::Value::Dict()
335           .Set("host", session_key->server_id().host())
336           .Set("port", session_key->server_id().port())
337           .Set("connection_id", connection_id.ToString())
338           .Set("versions", ParsedQuicVersionVectorToString(supported_versions))
339           .Set("require_confirmation", require_confirmation)
340           .Set("cert_verify_flags", cert_verify_flags)
341           .Set("server_id_privacy_mode",
342                session_key->server_id().privacy_mode_enabled())
343           .Set("privacy_mode",
344                PrivacyModeToDebugString(session_key->privacy_mode()))
345           .Set("proxy_chain", session_key->proxy_chain().ToDebugString())
346           .Set("session_usage",
347                session_key->session_usage() == SessionUsage::kDestination
348                    ? "destination"
349                    : "proxy")
350           .Set("network_anonymization_key",
351                session_key->network_anonymization_key().ToDebugString())
352           .Set("secure_dns_policy",
353                SecureDnsPolicyToDebugString(session_key->secure_dns_policy()))
354           .Set("require_dns_https_alpn", session_key->require_dns_https_alpn());
355   if (!client_connection_id.IsEmpty()) {
356     dict.Set("client_connection_id", client_connection_id.ToString());
357   }
358   if (!ech_config_list.empty()) {
359     dict.Set("ech_config_list", NetLogBinaryValue(ech_config_list));
360   }
361   net_log.source().AddToEventParameters(dict);
362   return dict;
363 }
364 
365 // TODO(fayang): Remove this when necessary data is collected.
LogProbeResultToHistogram(MigrationCause cause,bool success)366 void LogProbeResultToHistogram(MigrationCause cause, bool success) {
367   UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.PathValidationSuccess", success);
368   const std::string histogram_name =
369       "Net.QuicSession.PathValidationSuccess." + MigrationCauseToString(cause);
370   STATIC_HISTOGRAM_POINTER_GROUP(
371       histogram_name, cause, MIGRATION_CAUSE_MAX, AddBoolean(success),
372       base::BooleanHistogram::FactoryGet(
373           histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag));
374 }
375 
376 }  // namespace
377 
378 // static
SetMidMigrationCallbackForTesting(base::OnceClosure callback)379 void QuicChromiumClientSession::SetMidMigrationCallbackForTesting(
380     base::OnceClosure callback) {
381   MidMigrationCallbackForTesting() = std::move(callback);  // IN-TEST
382 }
383 
Handle(const base::WeakPtr<QuicChromiumClientSession> & session,url::SchemeHostPort destination)384 QuicChromiumClientSession::Handle::Handle(
385     const base::WeakPtr<QuicChromiumClientSession>& session,
386     url::SchemeHostPort destination)
387     : MultiplexedSessionHandle(session),
388       session_(session),
389       destination_(std::move(destination)),
390       net_log_(session_->net_log()),
391       was_handshake_confirmed_(session->OneRttKeysAvailable()),
392       server_id_(session_->server_id()),
393       quic_version_(session->connection()->version()) {
394   DCHECK(session_);
395   session_->AddHandle(this);
396 }
397 
~Handle()398 QuicChromiumClientSession::Handle::~Handle() {
399   if (session_) {
400     session_->RemoveHandle(this);
401   }
402 }
403 
OnCryptoHandshakeConfirmed()404 void QuicChromiumClientSession::Handle::OnCryptoHandshakeConfirmed() {
405   was_handshake_confirmed_ = true;
406 }
407 
OnSessionClosed(quic::ParsedQuicVersion quic_version,int net_error,quic::QuicErrorCode quic_error,bool port_migration_detected,bool quic_connection_migration_attempted,bool quic_connection_migration_successful,LoadTimingInfo::ConnectTiming connect_timing,bool was_ever_used)408 void QuicChromiumClientSession::Handle::OnSessionClosed(
409     quic::ParsedQuicVersion quic_version,
410     int net_error,
411     quic::QuicErrorCode quic_error,
412     bool port_migration_detected,
413     bool quic_connection_migration_attempted,
414     bool quic_connection_migration_successful,
415     LoadTimingInfo::ConnectTiming connect_timing,
416     bool was_ever_used) {
417   session_ = nullptr;
418   port_migration_detected_ = port_migration_detected;
419   quic_connection_migration_attempted_ = quic_connection_migration_attempted;
420   quic_connection_migration_successful_ = quic_connection_migration_successful;
421   net_error_ = net_error;
422   quic_error_ = quic_error;
423   quic_version_ = quic_version;
424   connect_timing_ = connect_timing;
425   was_ever_used_ = was_ever_used;
426 }
427 
IsConnected() const428 bool QuicChromiumClientSession::Handle::IsConnected() const {
429   return session_ != nullptr;
430 }
431 
OneRttKeysAvailable() const432 bool QuicChromiumClientSession::Handle::OneRttKeysAvailable() const {
433   return was_handshake_confirmed_;
434 }
435 
436 const LoadTimingInfo::ConnectTiming&
GetConnectTiming()437 QuicChromiumClientSession::Handle::GetConnectTiming() {
438   if (!session_) {
439     return connect_timing_;
440   }
441 
442   return session_->GetConnectTiming();
443 }
444 
PopulateNetErrorDetails(NetErrorDetails * details) const445 void QuicChromiumClientSession::Handle::PopulateNetErrorDetails(
446     NetErrorDetails* details) const {
447   if (session_) {
448     session_->PopulateNetErrorDetails(details);
449   } else {
450     details->quic_port_migration_detected = port_migration_detected_;
451     details->quic_connection_error = quic_error_;
452     details->quic_connection_migration_attempted =
453         quic_connection_migration_attempted_;
454     details->quic_connection_migration_successful =
455         quic_connection_migration_successful_;
456   }
457 }
458 
GetQuicVersion() const459 quic::ParsedQuicVersion QuicChromiumClientSession::Handle::GetQuicVersion()
460     const {
461   if (!session_) {
462     return quic_version_;
463   }
464 
465   return session_->GetQuicVersion();
466 }
467 
468 std::unique_ptr<quic::QuicConnection::ScopedPacketFlusher>
CreatePacketBundler()469 QuicChromiumClientSession::Handle::CreatePacketBundler() {
470   if (!session_) {
471     return nullptr;
472   }
473 
474   return std::make_unique<quic::QuicConnection::ScopedPacketFlusher>(
475       session_->connection());
476 }
477 
SharesSameSession(const Handle & other) const478 bool QuicChromiumClientSession::Handle::SharesSameSession(
479     const Handle& other) const {
480   return session_.get() == other.session_.get();
481 }
482 
RequestStream(bool requires_confirmation,CompletionOnceCallback callback,const NetworkTrafficAnnotationTag & traffic_annotation)483 int QuicChromiumClientSession::Handle::RequestStream(
484     bool requires_confirmation,
485     CompletionOnceCallback callback,
486     const NetworkTrafficAnnotationTag& traffic_annotation) {
487   DCHECK(!stream_request_);
488 
489   // TODO(crbug.com/41491379): Add a regression test.
490   if (!session_ || session_->going_away_) {
491     return ERR_CONNECTION_CLOSED;
492   }
493 
494   requires_confirmation |= session_->gquic_zero_rtt_disabled();
495 
496   // std::make_unique does not work because the StreamRequest constructor
497   // is private.
498   stream_request_ = base::WrapUnique(
499       new StreamRequest(this, requires_confirmation, traffic_annotation));
500   return stream_request_->StartRequest(std::move(callback));
501 }
502 
503 std::unique_ptr<QuicChromiumClientStream::Handle>
ReleaseStream()504 QuicChromiumClientSession::Handle::ReleaseStream() {
505   DCHECK(stream_request_);
506 
507   auto handle = stream_request_->ReleaseStream();
508   stream_request_.reset();
509   return handle;
510 }
511 
WaitForHandshakeConfirmation(CompletionOnceCallback callback)512 int QuicChromiumClientSession::Handle::WaitForHandshakeConfirmation(
513     CompletionOnceCallback callback) {
514   if (!session_) {
515     return ERR_CONNECTION_CLOSED;
516   }
517 
518   return session_->WaitForHandshakeConfirmation(std::move(callback));
519 }
520 
CancelRequest(StreamRequest * request)521 void QuicChromiumClientSession::Handle::CancelRequest(StreamRequest* request) {
522   if (session_) {
523     session_->CancelRequest(request);
524   }
525 }
526 
TryCreateStream(StreamRequest * request)527 int QuicChromiumClientSession::Handle::TryCreateStream(StreamRequest* request) {
528   if (!session_) {
529     return ERR_CONNECTION_CLOSED;
530   }
531 
532   return session_->TryCreateStream(request);
533 }
534 
GetPeerAddress(IPEndPoint * address) const535 int QuicChromiumClientSession::Handle::GetPeerAddress(
536     IPEndPoint* address) const {
537   if (!session_) {
538     return ERR_CONNECTION_CLOSED;
539   }
540 
541   *address = ToIPEndPoint(session_->peer_address());
542   return OK;
543 }
544 
GetSelfAddress(IPEndPoint * address) const545 int QuicChromiumClientSession::Handle::GetSelfAddress(
546     IPEndPoint* address) const {
547   if (!session_) {
548     return ERR_CONNECTION_CLOSED;
549   }
550 
551   *address = ToIPEndPoint(session_->self_address());
552   return OK;
553 }
554 
WasEverUsed() const555 bool QuicChromiumClientSession::Handle::WasEverUsed() const {
556   if (!session_) {
557     return was_ever_used_;
558   }
559 
560   return session_->WasConnectionEverUsed();
561 }
562 
563 const std::set<std::string>&
GetDnsAliasesForSessionKey(const QuicSessionKey & key) const564 QuicChromiumClientSession::Handle::GetDnsAliasesForSessionKey(
565     const QuicSessionKey& key) const {
566   static const base::NoDestructor<std::set<std::string>> emptyset_result;
567   return session_ ? session_->GetDnsAliasesForSessionKey(key)
568                   : *emptyset_result;
569 }
570 
571 #if BUILDFLAG(ENABLE_WEBSOCKETS)
572 std::unique_ptr<WebSocketQuicStreamAdapter>
CreateWebSocketQuicStreamAdapter(WebSocketQuicStreamAdapter::Delegate * delegate,base::OnceCallback<void (std::unique_ptr<WebSocketQuicStreamAdapter>)> callback,const NetworkTrafficAnnotationTag & traffic_annotation)573 QuicChromiumClientSession::Handle::CreateWebSocketQuicStreamAdapter(
574     WebSocketQuicStreamAdapter::Delegate* delegate,
575     base::OnceCallback<void(std::unique_ptr<WebSocketQuicStreamAdapter>)>
576         callback,
577     const NetworkTrafficAnnotationTag& traffic_annotation) {
578   DCHECK(!stream_request_);
579   // std::make_unique does not work because the StreamRequest constructor
580   // is private.
581   stream_request_ = base::WrapUnique(new StreamRequest(
582       this, /*requires_confirmation=*/false, traffic_annotation));
583   return session_->CreateWebSocketQuicStreamAdapter(
584       delegate, std::move(callback), stream_request_.get());
585 }
586 #endif  // BUILDFLAG(ENABLE_WEBSOCKETS)
587 
StreamRequest(QuicChromiumClientSession::Handle * session,bool requires_confirmation,const NetworkTrafficAnnotationTag & traffic_annotation)588 QuicChromiumClientSession::StreamRequest::StreamRequest(
589     QuicChromiumClientSession::Handle* session,
590     bool requires_confirmation,
591     const NetworkTrafficAnnotationTag& traffic_annotation)
592     : session_(session),
593       requires_confirmation_(requires_confirmation),
594       traffic_annotation_(traffic_annotation) {}
595 
~StreamRequest()596 QuicChromiumClientSession::StreamRequest::~StreamRequest() {
597   if (stream_) {
598     stream_->Reset(quic::QUIC_STREAM_CANCELLED);
599   }
600 
601   if (session_) {
602     session_->CancelRequest(this);
603   }
604 }
605 
StartRequest(CompletionOnceCallback callback)606 int QuicChromiumClientSession::StreamRequest::StartRequest(
607     CompletionOnceCallback callback) {
608   if (!session_->IsConnected()) {
609     return ERR_CONNECTION_CLOSED;
610   }
611 
612   next_state_ = STATE_WAIT_FOR_CONFIRMATION;
613   int rv = DoLoop(OK);
614   if (rv == ERR_IO_PENDING) {
615     callback_ = std::move(callback);
616   }
617 
618   return rv;
619 }
620 
621 std::unique_ptr<QuicChromiumClientStream::Handle>
ReleaseStream()622 QuicChromiumClientSession::StreamRequest::ReleaseStream() {
623   DCHECK(stream_);
624   return std::move(stream_);
625 }
626 
OnRequestCompleteSuccess(std::unique_ptr<QuicChromiumClientStream::Handle> stream)627 void QuicChromiumClientSession::StreamRequest::OnRequestCompleteSuccess(
628     std::unique_ptr<QuicChromiumClientStream::Handle> stream) {
629   DCHECK_EQ(STATE_REQUEST_STREAM_COMPLETE, next_state_);
630 
631   stream_ = std::move(stream);
632   // This method is called even when the request completes synchronously.
633   if (callback_) {
634     DoCallback(OK);
635   }
636 }
637 
OnRequestCompleteFailure(int rv)638 void QuicChromiumClientSession::StreamRequest::OnRequestCompleteFailure(
639     int rv) {
640   DCHECK_EQ(STATE_REQUEST_STREAM_COMPLETE, next_state_);
641   // This method is called even when the request completes synchronously.
642   if (callback_) {
643     // Avoid re-entrancy if the callback calls into the session.
644     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
645         FROM_HERE,
646         base::BindOnce(&QuicChromiumClientSession::StreamRequest::DoCallback,
647                        weak_factory_.GetWeakPtr(), rv));
648   }
649 }
650 
OnIOComplete(int rv)651 void QuicChromiumClientSession::StreamRequest::OnIOComplete(int rv) {
652   rv = DoLoop(rv);
653 
654   if (rv != ERR_IO_PENDING && !callback_.is_null()) {
655     DoCallback(rv);
656   }
657 }
658 
DoCallback(int rv)659 void QuicChromiumClientSession::StreamRequest::DoCallback(int rv) {
660   CHECK_NE(rv, ERR_IO_PENDING);
661   CHECK(!callback_.is_null());
662 
663   // The client callback can do anything, including destroying this class,
664   // so any pending callback must be issued after everything else is done.
665   std::move(callback_).Run(rv);
666 }
667 
DoLoop(int rv)668 int QuicChromiumClientSession::StreamRequest::DoLoop(int rv) {
669   do {
670     State state = next_state_;
671     next_state_ = STATE_NONE;
672     switch (state) {
673       case STATE_WAIT_FOR_CONFIRMATION:
674         CHECK_EQ(OK, rv);
675         rv = DoWaitForConfirmation();
676         break;
677       case STATE_WAIT_FOR_CONFIRMATION_COMPLETE:
678         rv = DoWaitForConfirmationComplete(rv);
679         break;
680       case STATE_REQUEST_STREAM:
681         CHECK_EQ(OK, rv);
682         rv = DoRequestStream();
683         break;
684       case STATE_REQUEST_STREAM_COMPLETE:
685         rv = DoRequestStreamComplete(rv);
686         break;
687       default:
688         NOTREACHED() << "next_state_: " << next_state_;
689         break;
690     }
691   } while (next_state_ != STATE_NONE && next_state_ && rv != ERR_IO_PENDING);
692 
693   return rv;
694 }
695 
DoWaitForConfirmation()696 int QuicChromiumClientSession::StreamRequest::DoWaitForConfirmation() {
697   next_state_ = STATE_WAIT_FOR_CONFIRMATION_COMPLETE;
698   if (requires_confirmation_) {
699     return session_->WaitForHandshakeConfirmation(
700         base::BindOnce(&QuicChromiumClientSession::StreamRequest::OnIOComplete,
701                        weak_factory_.GetWeakPtr()));
702   }
703 
704   return OK;
705 }
706 
DoWaitForConfirmationComplete(int rv)707 int QuicChromiumClientSession::StreamRequest::DoWaitForConfirmationComplete(
708     int rv) {
709   DCHECK_NE(ERR_IO_PENDING, rv);
710   if (rv < 0) {
711     return rv;
712   }
713 
714   next_state_ = STATE_REQUEST_STREAM;
715   return OK;
716 }
717 
DoRequestStream()718 int QuicChromiumClientSession::StreamRequest::DoRequestStream() {
719   next_state_ = STATE_REQUEST_STREAM_COMPLETE;
720 
721   return session_->TryCreateStream(this);
722 }
723 
DoRequestStreamComplete(int rv)724 int QuicChromiumClientSession::StreamRequest::DoRequestStreamComplete(int rv) {
725   DCHECK(rv == OK || !stream_);
726 
727   return rv;
728 }
729 
730 QuicChromiumClientSession::QuicChromiumPathValidationContext::
QuicChromiumPathValidationContext(const quic::QuicSocketAddress & self_address,const quic::QuicSocketAddress & peer_address,handles::NetworkHandle network,std::unique_ptr<QuicChromiumPacketWriter> writer,std::unique_ptr<QuicChromiumPacketReader> reader)731     QuicChromiumPathValidationContext(
732         const quic::QuicSocketAddress& self_address,
733         const quic::QuicSocketAddress& peer_address,
734         handles::NetworkHandle network,
735         std::unique_ptr<QuicChromiumPacketWriter> writer,
736         std::unique_ptr<QuicChromiumPacketReader> reader)
737     : QuicPathValidationContext(self_address, peer_address),
738       network_handle_(network),
739       writer_(std::move(writer)),
740       reader_(std::move(reader)) {}
741 
742 QuicChromiumClientSession::QuicChromiumPathValidationContext::
743     ~QuicChromiumPathValidationContext() = default;
744 
745 handles::NetworkHandle
network()746 QuicChromiumClientSession::QuicChromiumPathValidationContext::network() {
747   return network_handle_;
748 }
749 quic::QuicPacketWriter*
WriterToUse()750 QuicChromiumClientSession::QuicChromiumPathValidationContext::WriterToUse() {
751   return writer_.get();
752 }
753 std::unique_ptr<QuicChromiumPacketWriter>
ReleaseWriter()754 QuicChromiumClientSession::QuicChromiumPathValidationContext::ReleaseWriter() {
755   return std::move(writer_);
756 }
757 std::unique_ptr<QuicChromiumPacketReader>
ReleaseReader()758 QuicChromiumClientSession::QuicChromiumPathValidationContext::ReleaseReader() {
759   return std::move(reader_);
760 }
761 
762 QuicChromiumClientSession::ConnectionMigrationValidationResultDelegate::
ConnectionMigrationValidationResultDelegate(QuicChromiumClientSession * session)763     ConnectionMigrationValidationResultDelegate(
764         QuicChromiumClientSession* session)
765     : session_(session) {}
766 
767 void QuicChromiumClientSession::ConnectionMigrationValidationResultDelegate::
OnPathValidationSuccess(std::unique_ptr<quic::QuicPathValidationContext> context,quic::QuicTime start_time)768     OnPathValidationSuccess(
769         std::unique_ptr<quic::QuicPathValidationContext> context,
770         quic::QuicTime start_time) {
771   auto* chrome_context =
772       static_cast<QuicChromiumPathValidationContext*>(context.get());
773   session_->OnConnectionMigrationProbeSucceeded(
774       chrome_context->network(), chrome_context->peer_address(),
775       chrome_context->self_address(), chrome_context->ReleaseWriter(),
776       chrome_context->ReleaseReader());
777 }
778 
779 void QuicChromiumClientSession::ConnectionMigrationValidationResultDelegate::
OnPathValidationFailure(std::unique_ptr<quic::QuicPathValidationContext> context)780     OnPathValidationFailure(
781         std::unique_ptr<quic::QuicPathValidationContext> context) {
782   session_->connection()->OnPathValidationFailureAtClient(
783       /*is_multi_port=*/false, *context);
784   // Note that socket, packet writer, and packet reader in |context| will be
785   // discarded.
786   auto* chrome_context =
787       static_cast<QuicChromiumPathValidationContext*>(context.get());
788   session_->OnProbeFailed(chrome_context->network(),
789                           chrome_context->peer_address());
790 }
791 
792 QuicChromiumClientSession::PortMigrationValidationResultDelegate::
PortMigrationValidationResultDelegate(QuicChromiumClientSession * session)793     PortMigrationValidationResultDelegate(QuicChromiumClientSession* session)
794     : session_(session) {}
795 
796 void QuicChromiumClientSession::PortMigrationValidationResultDelegate::
OnPathValidationSuccess(std::unique_ptr<quic::QuicPathValidationContext> context,quic::QuicTime start_time)797     OnPathValidationSuccess(
798         std::unique_ptr<quic::QuicPathValidationContext> context,
799         quic::QuicTime start_time) {
800   auto* chrome_context =
801       static_cast<QuicChromiumPathValidationContext*>(context.get());
802   session_->OnPortMigrationProbeSucceeded(
803       chrome_context->network(), chrome_context->peer_address(),
804       chrome_context->self_address(), chrome_context->ReleaseWriter(),
805       chrome_context->ReleaseReader());
806 }
807 
808 void QuicChromiumClientSession::PortMigrationValidationResultDelegate::
OnPathValidationFailure(std::unique_ptr<quic::QuicPathValidationContext> context)809     OnPathValidationFailure(
810         std::unique_ptr<quic::QuicPathValidationContext> context) {
811   session_->connection()->OnPathValidationFailureAtClient(
812       /*is_multi_port=*/false, *context);
813   // Note that socket, packet writer, and packet reader in |context| will be
814   // discarded.
815   auto* chrome_context =
816       static_cast<QuicChromiumPathValidationContext*>(context.get());
817   session_->OnProbeFailed(chrome_context->network(),
818                           chrome_context->peer_address());
819 }
820 
821 QuicChromiumClientSession::ServerPreferredAddressValidationResultDelegate::
ServerPreferredAddressValidationResultDelegate(QuicChromiumClientSession * session)822     ServerPreferredAddressValidationResultDelegate(
823         QuicChromiumClientSession* session)
824     : session_(session) {}
825 
826 void QuicChromiumClientSession::ServerPreferredAddressValidationResultDelegate::
OnPathValidationSuccess(std::unique_ptr<quic::QuicPathValidationContext> context,quic::QuicTime start_time)827     OnPathValidationSuccess(
828         std::unique_ptr<quic::QuicPathValidationContext> context,
829         quic::QuicTime start_time) {
830   auto* chrome_context =
831       static_cast<QuicChromiumPathValidationContext*>(context.get());
832   session_->OnServerPreferredAddressProbeSucceeded(
833       chrome_context->network(), chrome_context->peer_address(),
834       chrome_context->self_address(), chrome_context->ReleaseWriter(),
835       chrome_context->ReleaseReader());
836 }
837 
838 void QuicChromiumClientSession::ServerPreferredAddressValidationResultDelegate::
OnPathValidationFailure(std::unique_ptr<quic::QuicPathValidationContext> context)839     OnPathValidationFailure(
840         std::unique_ptr<quic::QuicPathValidationContext> context) {
841   session_->connection()->OnPathValidationFailureAtClient(
842       /*is_multi_port=*/false, *context);
843   // Note that socket, packet writer, and packet reader in |context| will be
844   // discarded.
845   auto* chrome_context =
846       static_cast<QuicChromiumPathValidationContext*>(context.get());
847   session_->OnProbeFailed(chrome_context->network(),
848                           chrome_context->peer_address());
849 }
850 
851 QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
QuicChromiumPathValidationWriterDelegate(QuicChromiumClientSession * session,base::SequencedTaskRunner * task_runner)852     QuicChromiumPathValidationWriterDelegate(
853         QuicChromiumClientSession* session,
854         base::SequencedTaskRunner* task_runner)
855     : session_(session),
856       task_runner_(task_runner),
857       network_(handles::kInvalidNetworkHandle) {}
858 
859 QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
860     ~QuicChromiumPathValidationWriterDelegate() = default;
861 
862 int QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
HandleWriteError(int error_code,scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> last_packet)863     HandleWriteError(
864         int error_code,
865         scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> last_packet) {
866   // Write error on the probing network is not recoverable.
867   DVLOG(1) << "Probing packet encounters write error " << error_code;
868   // Post a task to notify |session_| that this probe failed and cancel
869   // undergoing probing, which will delete the packet writer.
870   task_runner_->PostTask(
871       FROM_HERE,
872       base::BindOnce(
873           &QuicChromiumPathValidationWriterDelegate::NotifySessionProbeFailed,
874           weak_factory_.GetWeakPtr(), network_));
875   return error_code;
876 }
877 
878 void QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
OnWriteError(int error_code)879     OnWriteError(int error_code) {
880   NotifySessionProbeFailed(network_);
881 }
882 void QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
OnWriteUnblocked()883     OnWriteUnblocked() {}
884 
885 void QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
NotifySessionProbeFailed(handles::NetworkHandle network)886     NotifySessionProbeFailed(handles::NetworkHandle network) {
887   session_->OnProbeFailed(network, peer_address_);
888 }
889 
890 void QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
set_peer_address(const quic::QuicSocketAddress & peer_address)891     set_peer_address(const quic::QuicSocketAddress& peer_address) {
892   peer_address_ = peer_address;
893 }
894 
895 void QuicChromiumClientSession::QuicChromiumPathValidationWriterDelegate::
set_network(handles::NetworkHandle network)896     set_network(handles::NetworkHandle network) {
897   network_ = network;
898 }
899 
QuicChromiumClientSession(quic::QuicConnection * connection,std::unique_ptr<DatagramClientSocket> socket,QuicSessionPool * session_pool,QuicCryptoClientStreamFactory * crypto_client_stream_factory,const quic::QuicClock * clock,TransportSecurityState * transport_security_state,SSLConfigService * ssl_config_service,std::unique_ptr<QuicServerInfo> server_info,const QuicSessionKey & session_key,bool require_confirmation,bool migrate_session_early_v2,bool migrate_sessions_on_network_change_v2,handles::NetworkHandle default_network,quic::QuicTime::Delta retransmittable_on_wire_timeout,bool migrate_idle_session,bool allow_port_migration,base::TimeDelta idle_migration_period,int multi_port_probing_interval,base::TimeDelta max_time_on_non_default_network,int max_migrations_to_non_default_network_on_write_error,int max_migrations_to_non_default_network_on_path_degrading,int yield_after_packets,quic::QuicTime::Delta yield_after_duration,int cert_verify_flags,const quic::QuicConfig & config,std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config,const char * const connection_description,base::TimeTicks dns_resolution_start_time,base::TimeTicks dns_resolution_end_time,const base::TickClock * tick_clock,base::SequencedTaskRunner * task_runner,std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,const ConnectionEndpointMetadata & metadata,const NetLogWithSource & net_log)900 QuicChromiumClientSession::QuicChromiumClientSession(
901     quic::QuicConnection* connection,
902     std::unique_ptr<DatagramClientSocket> socket,
903     QuicSessionPool* session_pool,
904     QuicCryptoClientStreamFactory* crypto_client_stream_factory,
905     const quic::QuicClock* clock,
906     TransportSecurityState* transport_security_state,
907     SSLConfigService* ssl_config_service,
908     std::unique_ptr<QuicServerInfo> server_info,
909     const QuicSessionKey& session_key,
910     bool require_confirmation,
911     bool migrate_session_early_v2,
912     bool migrate_sessions_on_network_change_v2,
913     handles::NetworkHandle default_network,
914     quic::QuicTime::Delta retransmittable_on_wire_timeout,
915     bool migrate_idle_session,
916     bool allow_port_migration,
917     base::TimeDelta idle_migration_period,
918     int multi_port_probing_interval,
919     base::TimeDelta max_time_on_non_default_network,
920     int max_migrations_to_non_default_network_on_write_error,
921     int max_migrations_to_non_default_network_on_path_degrading,
922     int yield_after_packets,
923     quic::QuicTime::Delta yield_after_duration,
924     int cert_verify_flags,
925     const quic::QuicConfig& config,
926     std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config,
927     const char* const connection_description,
928     base::TimeTicks dns_resolution_start_time,
929     base::TimeTicks dns_resolution_end_time,
930     const base::TickClock* tick_clock,
931     base::SequencedTaskRunner* task_runner,
932     std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
933     const ConnectionEndpointMetadata& metadata,
934     const NetLogWithSource& net_log)
935     : quic::QuicSpdyClientSessionBase(connection,
936                                       /*visitor=*/nullptr,
937                                       config,
938                                       connection->supported_versions()),
939       session_key_(session_key),
940       require_confirmation_(require_confirmation),
941       migrate_session_early_v2_(migrate_session_early_v2),
942       migrate_session_on_network_change_v2_(
943           migrate_sessions_on_network_change_v2),
944       migrate_idle_session_(migrate_idle_session),
945       allow_port_migration_(allow_port_migration),
946       idle_migration_period_(idle_migration_period),
947       max_time_on_non_default_network_(max_time_on_non_default_network),
948       max_migrations_to_non_default_network_on_write_error_(
949           max_migrations_to_non_default_network_on_write_error),
950       max_migrations_to_non_default_network_on_path_degrading_(
951           max_migrations_to_non_default_network_on_path_degrading),
952       clock_(clock),
953       yield_after_packets_(yield_after_packets),
954       yield_after_duration_(yield_after_duration),
955       most_recent_path_degrading_timestamp_(base::TimeTicks()),
956       most_recent_network_disconnected_timestamp_(base::TimeTicks()),
957       tick_clock_(tick_clock),
958       most_recent_stream_close_time_(tick_clock_->NowTicks()),
959       most_recent_write_error_timestamp_(base::TimeTicks()),
960       crypto_config_(std::move(crypto_config)),
961       session_pool_(session_pool),
962       transport_security_state_(transport_security_state),
963       ssl_config_service_(ssl_config_service),
964       server_info_(std::move(server_info)),
965       task_runner_(task_runner),
966       net_log_(NetLogWithSource::Make(net_log.net_log(),
967                                       NetLogSourceType::QUIC_SESSION)),
968       logger_(std::make_unique<QuicConnectionLogger>(
969           this,
970           connection_description,
971           std::move(socket_performance_watcher),
972           net_log_)),
973       http3_logger_(std::make_unique<QuicHttp3Logger>(net_log_)),
974       path_validation_writer_delegate_(this, task_runner_),
975       ech_config_list_(metadata.ech_config_list) {
976   default_network_ = default_network;
977   auto* socket_raw = socket.get();
978   packet_readers_.push_back(std::make_unique<QuicChromiumPacketReader>(
979       std::move(socket), clock, this, yield_after_packets, yield_after_duration,
980       net_log_));
981   crypto_stream_ = crypto_client_stream_factory->CreateQuicCryptoClientStream(
982       session_key.server_id(), this,
983       std::make_unique<ProofVerifyContextChromium>(cert_verify_flags, net_log_),
984       crypto_config_->GetConfig());
985   set_debug_visitor(http3_logger_.get());
986   connection->set_debug_visitor(logger_.get());
987   connection->set_creator_debug_delegate(logger_.get());
988   migrate_back_to_default_timer_.SetTaskRunner(task_runner_.get());
989   net_log_.BeginEvent(NetLogEventType::QUIC_SESSION, [&] {
990     return NetLogQuicClientSessionParams(
991         net_log, &session_key, connection_id(),
992         connection->client_connection_id(), supported_versions(),
993         cert_verify_flags, require_confirmation_, ech_config_list_);
994   });
995   // Associate the owned NetLog with the parent NetLog.
996   net_log.AddEventReferencingSource(NetLogEventType::QUIC_SESSION_CREATED,
997                                     net_log_.source());
998 
999   IPEndPoint address;
1000   if (socket_raw && socket_raw->GetLocalAddress(&address) == OK &&
1001       address.GetFamily() == ADDRESS_FAMILY_IPV6) {
1002     connection->SetMaxPacketLength(connection->max_packet_length() -
1003                                    kAdditionalOverheadForIPv6);
1004   }
1005   if (multi_port_probing_interval > 0) {
1006     connection->SetMultiPortProbingInterval(
1007         quic::QuicTime::Delta::FromSeconds(multi_port_probing_interval));
1008   }
1009   connect_timing_.domain_lookup_start = dns_resolution_start_time;
1010   connect_timing_.domain_lookup_end = dns_resolution_end_time;
1011   if (!retransmittable_on_wire_timeout.IsZero()) {
1012     connection->set_initial_retransmittable_on_wire_timeout(
1013         retransmittable_on_wire_timeout);
1014   }
1015 }
1016 
~QuicChromiumClientSession()1017 QuicChromiumClientSession::~QuicChromiumClientSession() {
1018   DCHECK(callback_.is_null());
1019 
1020   for (auto& observer : connectivity_observer_list_) {
1021     observer.OnSessionRemoved(this);
1022   }
1023 
1024   net_log_.EndEvent(NetLogEventType::QUIC_SESSION);
1025   DCHECK(waiting_for_confirmation_callbacks_.empty());
1026   DCHECK(!HasActiveRequestStreams());
1027   DCHECK(handles_.empty());
1028   if (!stream_requests_.empty()) {
1029     // The session must be closed before it is destroyed.
1030     CancelAllRequests(ERR_UNEXPECTED);
1031   }
1032   connection()->set_debug_visitor(nullptr);
1033 
1034   if (connection()->connected()) {
1035     // Ensure that the connection is closed by the time the session is
1036     // destroyed.
1037     connection()->CloseConnection(quic::QUIC_PEER_GOING_AWAY,
1038                                   "session torn down",
1039                                   quic::ConnectionCloseBehavior::SILENT_CLOSE);
1040   }
1041 
1042   if (IsEncryptionEstablished()) {
1043     RecordHandshakeState(STATE_ENCRYPTION_ESTABLISHED);
1044   }
1045   if (OneRttKeysAvailable()) {
1046     RecordHandshakeState(STATE_HANDSHAKE_CONFIRMED);
1047   } else {
1048     RecordHandshakeState(STATE_FAILED);
1049   }
1050 
1051   UMA_HISTOGRAM_ENUMERATION(
1052       "Net.QuicSession.EcnMarksObserved",
1053       static_cast<EcnPermutations>(observed_incoming_ecn_));
1054   UMA_HISTOGRAM_COUNTS_10M(
1055       "Net.QuicSession.PacketsBeforeEcnTransition",
1056       observed_ecn_transition_ ? incoming_packets_before_ecn_transition_ : 0);
1057   UMA_HISTOGRAM_COUNTS_1M("Net.QuicSession.NumTotalStreams",
1058                           num_total_streams_);
1059 
1060   if (!OneRttKeysAvailable()) {
1061     return;
1062   }
1063 
1064   // Sending one client_hello means we had zero handshake-round-trips.
1065   int round_trip_handshakes = crypto_stream_->num_sent_client_hellos() - 1;
1066 
1067   SSLInfo ssl_info;
1068   // QUIC supports only secure urls.
1069   if (GetSSLInfo(&ssl_info) && ssl_info.cert.get()) {
1070     UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.ConnectRandomPortForHTTPS",
1071                                 round_trip_handshakes, 1, 3, 4);
1072     if (require_confirmation_) {
1073       UMA_HISTOGRAM_CUSTOM_COUNTS(
1074           "Net.QuicSession.ConnectRandomPortRequiringConfirmationForHTTPS",
1075           round_trip_handshakes, 1, 3, 4);
1076     }
1077   }
1078 
1079   const quic::QuicConnectionStats stats = connection()->GetStats();
1080 
1081   // The MTU used by QUIC is limited to a fairly small set of predefined values
1082   // (initial values and MTU discovery values), but does not fare well when
1083   // bucketed.  Because of that, a sparse histogram is used here.
1084   base::UmaHistogramSparse("Net.QuicSession.ClientSideMtu", stats.egress_mtu);
1085   base::UmaHistogramSparse("Net.QuicSession.ServerSideMtu", stats.ingress_mtu);
1086 
1087   UMA_HISTOGRAM_COUNTS_1M("Net.QuicSession.MtuProbesSent",
1088                           connection()->mtu_probe_count());
1089 
1090   if (stats.packets_sent >= 100) {
1091     // Used to monitor for regressions that effect large uploads.
1092     UMA_HISTOGRAM_COUNTS_1000(
1093         "Net.QuicSession.PacketRetransmitsPerMille",
1094         1000 * stats.packets_retransmitted / stats.packets_sent);
1095   }
1096 
1097   if (stats.max_sequence_reordering == 0) {
1098     return;
1099   }
1100   const base::HistogramBase::Sample kMaxReordering = 100;
1101   base::HistogramBase::Sample reordering = kMaxReordering;
1102   if (stats.min_rtt_us > 0) {
1103     reordering = static_cast<base::HistogramBase::Sample>(
1104         100 * stats.max_time_reordering_us / stats.min_rtt_us);
1105   }
1106   UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.MaxReorderingTime", reordering,
1107                               1, kMaxReordering, 50);
1108   if (stats.min_rtt_us > 100 * 1000) {
1109     UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.MaxReorderingTimeLongRtt",
1110                                 reordering, 1, kMaxReordering, 50);
1111   }
1112   UMA_HISTOGRAM_COUNTS_1M(
1113       "Net.QuicSession.MaxReordering",
1114       static_cast<base::HistogramBase::Sample>(stats.max_sequence_reordering));
1115 }
1116 
Initialize()1117 void QuicChromiumClientSession::Initialize() {
1118   set_max_inbound_header_list_size(kQuicMaxHeaderListSize);
1119   quic::QuicSpdyClientSessionBase::Initialize();
1120 }
1121 
WriteHeadersOnHeadersStream(quic::QuicStreamId id,spdy::Http2HeaderBlock headers,bool fin,const spdy::SpdyStreamPrecedence & precedence,quiche::QuicheReferenceCountedPointer<quic::QuicAckListenerInterface> ack_listener)1122 size_t QuicChromiumClientSession::WriteHeadersOnHeadersStream(
1123     quic::QuicStreamId id,
1124     spdy::Http2HeaderBlock headers,
1125     bool fin,
1126     const spdy::SpdyStreamPrecedence& precedence,
1127     quiche::QuicheReferenceCountedPointer<quic::QuicAckListenerInterface>
1128         ack_listener) {
1129   const int weight =
1130       spdy::Spdy3PriorityToHttp2Weight(precedence.spdy3_priority());
1131   return WriteHeadersOnHeadersStreamImpl(id, std::move(headers), fin,
1132                                          /* parent_stream_id = */ 0, weight,
1133                                          /* exclusive = */ false,
1134                                          std::move(ack_listener));
1135 }
1136 
OnHttp3GoAway(uint64_t id)1137 void QuicChromiumClientSession::OnHttp3GoAway(uint64_t id) {
1138   quic::QuicSpdySession::OnHttp3GoAway(id);
1139   NotifyFactoryOfSessionGoingAway();
1140 
1141   PerformActionOnActiveStreams([id](quic::QuicStream* stream) {
1142     if (stream->id() >= id) {
1143       static_cast<QuicChromiumClientStream*>(stream)->OnError(
1144           ERR_QUIC_GOAWAY_REQUEST_CAN_BE_RETRIED);
1145     }
1146     return true;
1147   });
1148 }
1149 
OnAcceptChFrameReceivedViaAlps(const quic::AcceptChFrame & frame)1150 void QuicChromiumClientSession::OnAcceptChFrameReceivedViaAlps(
1151     const quic::AcceptChFrame& frame) {
1152   bool has_valid_entry = false;
1153   bool has_invalid_entry = false;
1154   for (const auto& entry : frame.entries) {
1155     const url::SchemeHostPort scheme_host_port(GURL(entry.origin));
1156     // |entry.origin| must be a valid SchemeHostPort.
1157     std::string serialized = scheme_host_port.Serialize();
1158     if (serialized.empty() || entry.origin != serialized) {
1159       has_invalid_entry = true;
1160       continue;
1161     }
1162     has_valid_entry = true;
1163     accept_ch_entries_received_via_alps_.emplace(std::move(scheme_host_port),
1164                                                  entry.value);
1165 
1166     net_log_.AddEvent(NetLogEventType::QUIC_ACCEPT_CH_FRAME_RECEIVED,
1167                       [&] { return NetLogAcceptChFrameReceivedParams(entry); });
1168   }
1169   LogAcceptChFrameReceivedHistogram(has_valid_entry, has_invalid_entry);
1170 }
1171 
AddHandle(Handle * handle)1172 void QuicChromiumClientSession::AddHandle(Handle* handle) {
1173   if (going_away_) {
1174     handle->OnSessionClosed(connection()->version(), ERR_UNEXPECTED, error(),
1175                             port_migration_detected_,
1176                             quic_connection_migration_attempted_,
1177                             quic_connection_migration_successful_,
1178                             GetConnectTiming(), WasConnectionEverUsed());
1179     return;
1180   }
1181 
1182   DCHECK(!base::Contains(handles_, handle));
1183   handles_.insert(handle);
1184 }
1185 
RemoveHandle(Handle * handle)1186 void QuicChromiumClientSession::RemoveHandle(Handle* handle) {
1187   DCHECK(base::Contains(handles_, handle));
1188   handles_.erase(handle);
1189 }
1190 
AddConnectivityObserver(ConnectivityObserver * observer)1191 void QuicChromiumClientSession::AddConnectivityObserver(
1192     ConnectivityObserver* observer) {
1193   connectivity_observer_list_.AddObserver(observer);
1194   observer->OnSessionRegistered(this, GetCurrentNetwork());
1195 }
1196 
RemoveConnectivityObserver(ConnectivityObserver * observer)1197 void QuicChromiumClientSession::RemoveConnectivityObserver(
1198     ConnectivityObserver* observer) {
1199   connectivity_observer_list_.RemoveObserver(observer);
1200 }
1201 
1202 // TODO(zhongyi): replace migration_session_* booleans with
1203 // ConnectionMigrationMode.
connection_migration_mode() const1204 ConnectionMigrationMode QuicChromiumClientSession::connection_migration_mode()
1205     const {
1206   if (migrate_session_early_v2_) {
1207     return ConnectionMigrationMode::FULL_MIGRATION_V2;
1208   }
1209 
1210   if (migrate_session_on_network_change_v2_) {
1211     return ConnectionMigrationMode::NO_MIGRATION_ON_PATH_DEGRADING_V2;
1212   }
1213 
1214   return ConnectionMigrationMode::NO_MIGRATION;
1215 }
1216 
WaitForHandshakeConfirmation(CompletionOnceCallback callback)1217 int QuicChromiumClientSession::WaitForHandshakeConfirmation(
1218     CompletionOnceCallback callback) {
1219   if (!connection()->connected()) {
1220     return ERR_CONNECTION_CLOSED;
1221   }
1222 
1223   if (OneRttKeysAvailable()) {
1224     return OK;
1225   }
1226 
1227   waiting_for_confirmation_callbacks_.push_back(std::move(callback));
1228   return ERR_IO_PENDING;
1229 }
1230 
TryCreateStream(StreamRequest * request)1231 int QuicChromiumClientSession::TryCreateStream(StreamRequest* request) {
1232   if (goaway_received()) {
1233     DVLOG(1) << "Going away.";
1234     return ERR_CONNECTION_CLOSED;
1235   }
1236 
1237   if (!connection()->connected()) {
1238     DVLOG(1) << "Already closed.";
1239     return ERR_CONNECTION_CLOSED;
1240   }
1241 
1242   if (going_away_) {
1243     return ERR_CONNECTION_CLOSED;
1244   }
1245 
1246   bool can_open_next = CanOpenNextOutgoingBidirectionalStream();
1247   if (can_open_next) {
1248     request->stream_ =
1249         CreateOutgoingReliableStreamImpl(request->traffic_annotation())
1250             ->CreateHandle();
1251     return OK;
1252   }
1253 
1254   // Calling CanOpenNextOutgoingBidirectionalStream() could close the
1255   // connection.
1256   if (!connection()->connected()) {
1257     return ERR_CONNECTION_CLOSED;
1258   }
1259 
1260   request->pending_start_time_ = tick_clock_->NowTicks();
1261   stream_requests_.push_back(request);
1262   UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumPendingStreamRequests",
1263                             stream_requests_.size());
1264   return ERR_IO_PENDING;
1265 }
1266 
CancelRequest(StreamRequest * request)1267 void QuicChromiumClientSession::CancelRequest(StreamRequest* request) {
1268   // Remove |request| from the queue while preserving the order of the
1269   // other elements.
1270   auto it = base::ranges::find(stream_requests_, request);
1271   if (it != stream_requests_.end()) {
1272     it = stream_requests_.erase(it);
1273   }
1274 }
1275 
ShouldCreateOutgoingBidirectionalStream()1276 bool QuicChromiumClientSession::ShouldCreateOutgoingBidirectionalStream() {
1277   if (!crypto_stream_->encryption_established()) {
1278     DVLOG(1) << "Encryption not active so no outgoing stream created.";
1279     return false;
1280   }
1281   if (!CanOpenNextOutgoingBidirectionalStream()) {
1282     DVLOG(1) << "Failed to create a new outgoing stream. " << "Already "
1283              << GetNumActiveStreams() << " open.";
1284     return false;
1285   }
1286   if (goaway_received()) {
1287     DVLOG(1) << "Failed to create a new outgoing stream. "
1288              << "Already received goaway.";
1289     return false;
1290   }
1291   if (going_away_) {
1292     return false;
1293   }
1294   return true;
1295 }
1296 
ShouldCreateOutgoingUnidirectionalStream()1297 bool QuicChromiumClientSession::ShouldCreateOutgoingUnidirectionalStream() {
1298   NOTREACHED() << "Try to create outgoing unidirectional streams";
1299   return false;
1300 }
1301 
WasConnectionEverUsed()1302 bool QuicChromiumClientSession::WasConnectionEverUsed() {
1303   const quic::QuicConnectionStats& stats = connection()->GetStats();
1304   return stats.bytes_sent > 0 || stats.bytes_received > 0;
1305 }
1306 
1307 QuicChromiumClientStream*
CreateOutgoingBidirectionalStream()1308 QuicChromiumClientSession::CreateOutgoingBidirectionalStream() {
1309   NOTREACHED() << "CreateOutgoingReliableStreamImpl should be called directly";
1310   return nullptr;
1311 }
1312 
1313 QuicChromiumClientStream*
CreateOutgoingUnidirectionalStream()1314 QuicChromiumClientSession::CreateOutgoingUnidirectionalStream() {
1315   NOTREACHED() << "Try to create outgoing unidirectional stream";
1316   return nullptr;
1317 }
1318 
1319 QuicChromiumClientStream*
CreateOutgoingReliableStreamImpl(const NetworkTrafficAnnotationTag & traffic_annotation)1320 QuicChromiumClientSession::CreateOutgoingReliableStreamImpl(
1321     const NetworkTrafficAnnotationTag& traffic_annotation) {
1322   DCHECK(connection()->connected());
1323   QuicChromiumClientStream* stream = new QuicChromiumClientStream(
1324       GetNextOutgoingBidirectionalStreamId(), this, quic::BIDIRECTIONAL,
1325       net_log_, traffic_annotation);
1326   ActivateStream(base::WrapUnique(stream));
1327   ++num_total_streams_;
1328   UMA_HISTOGRAM_COUNTS_1M("Net.QuicSession.NumOpenStreams",
1329                           GetNumActiveStreams());
1330   // The previous histogram puts 100 in a bucket betweeen 86-113 which does
1331   // not shed light on if chrome ever things it has more than 100 streams open.
1332   UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.TooManyOpenStreams",
1333                         GetNumActiveStreams() > 100);
1334   return stream;
1335 }
1336 
1337 quic::QuicCryptoClientStream*
GetMutableCryptoStream()1338 QuicChromiumClientSession::GetMutableCryptoStream() {
1339   return crypto_stream_.get();
1340 }
1341 
GetCryptoStream() const1342 const quic::QuicCryptoClientStream* QuicChromiumClientSession::GetCryptoStream()
1343     const {
1344   return crypto_stream_.get();
1345 }
1346 
GetRemoteEndpoint(IPEndPoint * endpoint)1347 int QuicChromiumClientSession::GetRemoteEndpoint(IPEndPoint* endpoint) {
1348   *endpoint = ToIPEndPoint(peer_address());
1349   return OK;
1350 }
1351 
1352 // TODO(rtenneti): Add unittests for GetSSLInfo which exercise the various ways
1353 // we learn about SSL info (sync vs async vs cached).
GetSSLInfo(SSLInfo * ssl_info) const1354 bool QuicChromiumClientSession::GetSSLInfo(SSLInfo* ssl_info) const {
1355   ssl_info->Reset();
1356   if (!cert_verify_result_) {
1357     return false;
1358   }
1359 
1360   ssl_info->cert_status = cert_verify_result_->cert_status;
1361   ssl_info->cert = cert_verify_result_->verified_cert;
1362 
1363   ssl_info->public_key_hashes = cert_verify_result_->public_key_hashes;
1364   ssl_info->is_issued_by_known_root =
1365       cert_verify_result_->is_issued_by_known_root;
1366   ssl_info->pkp_bypassed = pkp_bypassed_;
1367 
1368   ssl_info->client_cert_sent = false;
1369   ssl_info->handshake_type = SSLInfo::HANDSHAKE_FULL;
1370   ssl_info->is_fatal_cert_error = is_fatal_cert_error_;
1371 
1372   ssl_info->signed_certificate_timestamps = cert_verify_result_->scts;
1373   ssl_info->ct_policy_compliance = cert_verify_result_->policy_compliance;
1374 
1375   DCHECK(connection()->version().UsesTls());
1376   const auto& crypto_params = crypto_stream_->crypto_negotiated_params();
1377   uint16_t cipher_suite = crypto_params.cipher_suite;
1378   int ssl_connection_status = 0;
1379   SSLConnectionStatusSetCipherSuite(cipher_suite, &ssl_connection_status);
1380   SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_QUIC,
1381                                 &ssl_connection_status);
1382   ssl_info->connection_status = ssl_connection_status;
1383 
1384   ssl_info->key_exchange_group = crypto_params.key_exchange_group;
1385   ssl_info->peer_signature_algorithm = crypto_params.peer_signature_algorithm;
1386   ssl_info->encrypted_client_hello = crypto_params.encrypted_client_hello;
1387   return true;
1388 }
1389 
GetAcceptChViaAlps(const url::SchemeHostPort & scheme_host_port) const1390 std::string_view QuicChromiumClientSession::GetAcceptChViaAlps(
1391     const url::SchemeHostPort& scheme_host_port) const {
1392   auto it = accept_ch_entries_received_via_alps_.find(scheme_host_port);
1393   if (it == accept_ch_entries_received_via_alps_.end()) {
1394     LogAcceptChForOriginHistogram(false);
1395     return {};
1396   } else {
1397     LogAcceptChForOriginHistogram(true);
1398     return it->second;
1399   }
1400 }
1401 
CryptoConnect(CompletionOnceCallback callback)1402 int QuicChromiumClientSession::CryptoConnect(CompletionOnceCallback callback) {
1403   connect_timing_.connect_start = tick_clock_->NowTicks();
1404   RecordHandshakeState(STATE_STARTED);
1405   DCHECK(flow_controller());
1406 
1407   if (!crypto_stream_->CryptoConnect()) {
1408     return ERR_QUIC_HANDSHAKE_FAILED;
1409   }
1410 
1411   if (OneRttKeysAvailable()) {
1412     connect_timing_.connect_end = tick_clock_->NowTicks();
1413     return OK;
1414   }
1415 
1416   // Unless we require handshake confirmation, activate the session if
1417   // we have established initial encryption.
1418   if (!require_confirmation_ && IsEncryptionEstablished()) {
1419     return OK;
1420   }
1421 
1422   callback_ = std::move(callback);
1423   return ERR_IO_PENDING;
1424 }
1425 
GetNumSentClientHellos() const1426 int QuicChromiumClientSession::GetNumSentClientHellos() const {
1427   return crypto_stream_->num_sent_client_hellos();
1428 }
1429 
CanPool(std::string_view hostname,const QuicSessionKey & other_session_key) const1430 bool QuicChromiumClientSession::CanPool(
1431     std::string_view hostname,
1432     const QuicSessionKey& other_session_key) const {
1433   DCHECK(connection()->connected());
1434   if (!session_key_.CanUseForAliasing(other_session_key)) {
1435     return false;
1436   }
1437   SSLInfo ssl_info;
1438   if (!GetSSLInfo(&ssl_info) || !ssl_info.cert.get()) {
1439     NOTREACHED() << "QUIC should always have certificates.";
1440     return false;
1441   }
1442 
1443   return SpdySession::CanPool(transport_security_state_, ssl_info,
1444                               *ssl_config_service_, session_key_.host(),
1445                               hostname);
1446 }
1447 
ShouldCreateIncomingStream(quic::QuicStreamId id)1448 bool QuicChromiumClientSession::ShouldCreateIncomingStream(
1449     quic::QuicStreamId id) {
1450   if (!connection()->connected()) {
1451     LOG(DFATAL) << "ShouldCreateIncomingStream called when disconnected";
1452     return false;
1453   }
1454   if (goaway_received()) {
1455     DVLOG(1) << "Cannot create a new outgoing stream. "
1456              << "Already received goaway.";
1457     return false;
1458   }
1459   if (going_away_) {
1460     return false;
1461   }
1462   if (quic::QuicUtils::IsClientInitiatedStreamId(
1463           connection()->transport_version(), id) ||
1464       quic::QuicUtils::IsBidirectionalStreamId(id, connection()->version())) {
1465     LOG(WARNING) << "Received invalid push stream id " << id;
1466     connection()->CloseConnection(
1467         quic::QUIC_INVALID_STREAM_ID,
1468         "Server created non write unidirectional stream",
1469         quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
1470     return false;
1471   }
1472   return true;
1473 }
1474 
CreateIncomingStream(quic::QuicStreamId id)1475 QuicChromiumClientStream* QuicChromiumClientSession::CreateIncomingStream(
1476     quic::QuicStreamId id) {
1477   if (!ShouldCreateIncomingStream(id)) {
1478     return nullptr;
1479   }
1480   net::NetworkTrafficAnnotationTag traffic_annotation =
1481       net::DefineNetworkTrafficAnnotation("quic_chromium_incoming_session", R"(
1482       semantics {
1483         sender: "Quic Chromium Client Session"
1484         description:
1485           "When a web server needs to push a response to a client, an incoming "
1486           "stream is created to reply the client with pushed message instead "
1487           "of a message from the network."
1488         trigger:
1489           "A request by a server to push a response to the client."
1490         data: "None."
1491         destination: OTHER
1492         destination_other:
1493           "This stream is not used for sending data."
1494       }
1495       policy {
1496         cookies_allowed: NO
1497         setting: "This feature cannot be disabled in settings."
1498         policy_exception_justification:
1499           "Essential for network access."
1500       }
1501   )");
1502   return CreateIncomingReliableStreamImpl(id, traffic_annotation);
1503 }
1504 
CreateIncomingStream(quic::PendingStream * pending)1505 QuicChromiumClientStream* QuicChromiumClientSession::CreateIncomingStream(
1506     quic::PendingStream* pending) {
1507   net::NetworkTrafficAnnotationTag traffic_annotation =
1508       net::DefineNetworkTrafficAnnotation(
1509           "quic_chromium_incoming_pending_session", R"(
1510       semantics {
1511         sender: "Quic Chromium Client Session Pending Stream"
1512         description:
1513           "When a web server needs to push a response to a client, an incoming "
1514           "stream is created to reply to the client with pushed message instead "
1515           "of a message from the network."
1516         trigger:
1517           "A request by a server to push a response to the client."
1518         data: "This stream is only used to receive data from the server."
1519         destination: OTHER
1520         destination_other:
1521           "The web server pushing the response."
1522       }
1523       policy {
1524         cookies_allowed: NO
1525         setting: "This feature cannot be disabled in settings."
1526         policy_exception_justification:
1527           "Essential for network access."
1528       }
1529   )");
1530   return CreateIncomingReliableStreamImpl(pending, traffic_annotation);
1531 }
1532 
1533 QuicChromiumClientStream*
CreateIncomingReliableStreamImpl(quic::QuicStreamId id,const NetworkTrafficAnnotationTag & traffic_annotation)1534 QuicChromiumClientSession::CreateIncomingReliableStreamImpl(
1535     quic::QuicStreamId id,
1536     const NetworkTrafficAnnotationTag& traffic_annotation) {
1537   DCHECK(connection()->connected());
1538 
1539   QuicChromiumClientStream* stream = new QuicChromiumClientStream(
1540       id, this, quic::READ_UNIDIRECTIONAL, net_log_, traffic_annotation);
1541   ActivateStream(base::WrapUnique(stream));
1542   ++num_total_streams_;
1543   return stream;
1544 }
1545 
1546 QuicChromiumClientStream*
CreateIncomingReliableStreamImpl(quic::PendingStream * pending,const NetworkTrafficAnnotationTag & traffic_annotation)1547 QuicChromiumClientSession::CreateIncomingReliableStreamImpl(
1548     quic::PendingStream* pending,
1549     const NetworkTrafficAnnotationTag& traffic_annotation) {
1550   DCHECK(connection()->connected());
1551 
1552   QuicChromiumClientStream* stream =
1553       new QuicChromiumClientStream(pending, this, net_log_, traffic_annotation);
1554   ActivateStream(base::WrapUnique(stream));
1555   ++num_total_streams_;
1556   return stream;
1557 }
1558 
OnStreamClosed(quic::QuicStreamId stream_id)1559 void QuicChromiumClientSession::OnStreamClosed(quic::QuicStreamId stream_id) {
1560   most_recent_stream_close_time_ = tick_clock_->NowTicks();
1561   quic::QuicStream* stream = GetActiveStream(stream_id);
1562   if (stream != nullptr) {
1563     logger_->UpdateReceivedFrameCounts(stream_id, stream->num_frames_received(),
1564                                        stream->num_duplicate_frames_received());
1565   }
1566   quic::QuicSpdyClientSessionBase::OnStreamClosed(stream_id);
1567 }
1568 
OnCanCreateNewOutgoingStream(bool unidirectional)1569 void QuicChromiumClientSession::OnCanCreateNewOutgoingStream(
1570     bool unidirectional) {
1571   while (CanOpenNextOutgoingBidirectionalStream() &&
1572          !stream_requests_.empty() &&
1573          crypto_stream_->encryption_established() && !goaway_received() &&
1574          !going_away_ && connection()->connected()) {
1575     StreamRequest* request = stream_requests_.front();
1576     // TODO(ckrasic) - analyze data and then add logic to mark QUIC
1577     // broken if wait times are excessive.
1578     UMA_HISTOGRAM_TIMES("Net.QuicSession.PendingStreamsWaitTime",
1579                         tick_clock_->NowTicks() - request->pending_start_time_);
1580     stream_requests_.pop_front();
1581 
1582 #if BUILDFLAG(ENABLE_WEBSOCKETS)
1583     if (request->for_websockets_) {
1584       std::unique_ptr<WebSocketQuicStreamAdapter> adapter =
1585           CreateWebSocketQuicStreamAdapterImpl(
1586               request->websocket_adapter_delegate_);
1587       request->websocket_adapter_delegate_ = nullptr;
1588       std::move(request->start_websocket_callback_).Run(std::move(adapter));
1589       continue;
1590     }
1591 #endif  // BUILDFLAG(ENABLE_WEBSOCKETS)
1592 
1593     request->OnRequestCompleteSuccess(
1594         CreateOutgoingReliableStreamImpl(request->traffic_annotation())
1595             ->CreateHandle());
1596   }
1597 }
1598 
GetSSLConfig() const1599 quic::QuicSSLConfig QuicChromiumClientSession::GetSSLConfig() const {
1600   quic::QuicSSLConfig config = quic::QuicSpdyClientSessionBase::GetSSLConfig();
1601   if (ssl_config_service_->GetSSLContextConfig().ech_enabled) {
1602     config.ech_grease_enabled = true;
1603     config.ech_config_list.assign(ech_config_list_.begin(),
1604                                   ech_config_list_.end());
1605   }
1606   return config;
1607 }
1608 
OnConfigNegotiated()1609 void QuicChromiumClientSession::OnConfigNegotiated() {
1610   quic::QuicSpdyClientSessionBase::OnConfigNegotiated();
1611   if (!session_pool_ || !session_pool_->allow_server_migration()) {
1612     return;
1613   }
1614   if (!config()->HasReceivedPreferredAddressConnectionIdAndToken()) {
1615     return;
1616   }
1617 
1618   // Server has sent an alternate address to connect to.
1619   IPEndPoint old_address;
1620   GetDefaultSocket()->GetPeerAddress(&old_address);
1621 
1622   // Migrate only if address families match.
1623   IPEndPoint new_address;
1624   if (old_address.GetFamily() == ADDRESS_FAMILY_IPV6) {
1625     if (!config()->HasReceivedIPv6AlternateServerAddress()) {
1626       return;
1627     }
1628     new_address = ToIPEndPoint(config()->ReceivedIPv6AlternateServerAddress());
1629   } else if (old_address.GetFamily() == ADDRESS_FAMILY_IPV4) {
1630     if (!config()->HasReceivedIPv4AlternateServerAddress()) {
1631       return;
1632     }
1633     new_address = ToIPEndPoint(config()->ReceivedIPv4AlternateServerAddress());
1634   }
1635   DCHECK_EQ(new_address.GetFamily(), old_address.GetFamily());
1636 
1637   // Specifying handles::kInvalidNetworkHandle for the |network| parameter
1638   // causes the session to use the default network for the new socket.
1639   // DoNothingAs is passed in as `migration_callback` because OnConfigNegotiated
1640   // does not need to do anything directly with the migration result.
1641   Migrate(handles::kInvalidNetworkHandle, new_address,
1642           /*close_session_on_error=*/true,
1643           base::DoNothingAs<void(MigrationResult)>());
1644 }
1645 
SetDefaultEncryptionLevel(quic::EncryptionLevel level)1646 void QuicChromiumClientSession::SetDefaultEncryptionLevel(
1647     quic::EncryptionLevel level) {
1648   if (!callback_.is_null() &&
1649       (!require_confirmation_ || level == quic::ENCRYPTION_FORWARD_SECURE ||
1650        level == quic::ENCRYPTION_ZERO_RTT)) {
1651     // Currently for all CryptoHandshakeEvent events, callback_
1652     // could be called because there are no error events in CryptoHandshakeEvent
1653     // enum. If error events are added to CryptoHandshakeEvent, then the
1654     // following code needs to changed.
1655     std::move(callback_).Run(OK);
1656   }
1657   if (level == quic::ENCRYPTION_FORWARD_SECURE) {
1658     OnCryptoHandshakeComplete();
1659     LogZeroRttStats();
1660   }
1661   if (level == quic::ENCRYPTION_ZERO_RTT) {
1662     attempted_zero_rtt_ = true;
1663   }
1664   quic::QuicSpdySession::SetDefaultEncryptionLevel(level);
1665 }
1666 
OnTlsHandshakeComplete()1667 void QuicChromiumClientSession::OnTlsHandshakeComplete() {
1668   if (!callback_.is_null()) {
1669     // Currently for all CryptoHandshakeEvent events, callback_
1670     // could be called because there are no error events in CryptoHandshakeEvent
1671     // enum. If error events are added to CryptoHandshakeEvent, then the
1672     // following code needs to changed.
1673     std::move(callback_).Run(OK);
1674   }
1675 
1676   OnCryptoHandshakeComplete();
1677   LogZeroRttStats();
1678   quic::QuicSpdySession::OnTlsHandshakeComplete();
1679 }
1680 
OnNewEncryptionKeyAvailable(quic::EncryptionLevel level,std::unique_ptr<quic::QuicEncrypter> encrypter)1681 void QuicChromiumClientSession::OnNewEncryptionKeyAvailable(
1682     quic::EncryptionLevel level,
1683     std::unique_ptr<quic::QuicEncrypter> encrypter) {
1684   if (!attempted_zero_rtt_ && (level == quic::ENCRYPTION_ZERO_RTT ||
1685                                level == quic::ENCRYPTION_FORWARD_SECURE)) {
1686     base::TimeTicks now = tick_clock_->NowTicks();
1687     DCHECK_LE(connect_timing_.connect_start, now);
1688     UMA_HISTOGRAM_TIMES("Net.QuicSession.EncryptionEstablishedTime",
1689                         now - connect_timing_.connect_start);
1690   }
1691   if (level == quic::ENCRYPTION_ZERO_RTT) {
1692     attempted_zero_rtt_ = true;
1693   }
1694   QuicSpdySession::OnNewEncryptionKeyAvailable(level, std::move(encrypter));
1695 
1696   if (!callback_.is_null() &&
1697       (!require_confirmation_ && level == quic::ENCRYPTION_ZERO_RTT)) {
1698     // Currently for all CryptoHandshakeEvent events, callback_
1699     // could be called because there are no error events in CryptoHandshakeEvent
1700     // enum. If error events are added to CryptoHandshakeEvent, then the
1701     // following code needs to changed.
1702     std::move(callback_).Run(OK);
1703   }
1704 }
1705 
LogZeroRttStats()1706 void QuicChromiumClientSession::LogZeroRttStats() {
1707   DCHECK(OneRttKeysAvailable());
1708 
1709   ZeroRttState state;
1710 
1711   ssl_early_data_reason_t early_data_reason = crypto_stream_->EarlyDataReason();
1712   if (early_data_reason == ssl_early_data_accepted) {
1713     state = ZeroRttState::kAttemptedAndSucceeded;
1714   } else if (early_data_reason == ssl_early_data_peer_declined ||
1715              early_data_reason == ssl_early_data_session_not_resumed ||
1716              early_data_reason == ssl_early_data_hello_retry_request) {
1717     state = ZeroRttState::kAttemptedAndRejected;
1718   } else {
1719     state = ZeroRttState::kNotAttempted;
1720   }
1721   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttState", state);
1722   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttReason", early_data_reason,
1723                             ssl_early_data_reason_max_value + 1);
1724   if (IsGoogleHost(session_key_.host())) {
1725     UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttReasonGoogle",
1726                               early_data_reason,
1727                               ssl_early_data_reason_max_value + 1);
1728   } else {
1729     UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttReasonNonGoogle",
1730                               early_data_reason,
1731                               ssl_early_data_reason_max_value + 1);
1732   }
1733 }
1734 
OnCryptoHandshakeMessageSent(const quic::CryptoHandshakeMessage & message)1735 void QuicChromiumClientSession::OnCryptoHandshakeMessageSent(
1736     const quic::CryptoHandshakeMessage& message) {
1737   logger_->OnCryptoHandshakeMessageSent(message);
1738 }
1739 
OnCryptoHandshakeMessageReceived(const quic::CryptoHandshakeMessage & message)1740 void QuicChromiumClientSession::OnCryptoHandshakeMessageReceived(
1741     const quic::CryptoHandshakeMessage& message) {
1742   logger_->OnCryptoHandshakeMessageReceived(message);
1743   if (message.tag() == quic::kREJ) {
1744     UMA_HISTOGRAM_CUSTOM_COUNTS("Net.QuicSession.RejectLength",
1745                                 message.GetSerialized().length(), 1000, 10000,
1746                                 50);
1747     std::string_view proof;
1748     UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.RejectHasProof",
1749                           message.GetStringPiece(quic::kPROF, &proof));
1750   }
1751 }
1752 
OnGoAway(const quic::QuicGoAwayFrame & frame)1753 void QuicChromiumClientSession::OnGoAway(const quic::QuicGoAwayFrame& frame) {
1754   quic::QuicSession::OnGoAway(frame);
1755   NotifyFactoryOfSessionGoingAway();
1756   port_migration_detected_ =
1757       frame.error_code == quic::QUIC_ERROR_MIGRATING_PORT;
1758 }
1759 
OnConnectionClosed(const quic::QuicConnectionCloseFrame & frame,quic::ConnectionCloseSource source)1760 void QuicChromiumClientSession::OnConnectionClosed(
1761     const quic::QuicConnectionCloseFrame& frame,
1762     quic::ConnectionCloseSource source) {
1763   DCHECK(!connection()->connected());
1764   logger_->OnConnectionClosed(frame, source);
1765 
1766   UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumDefaultPathDegrading",
1767                             connection()->GetStats().num_path_degrading);
1768   if (connection()->GetStats().num_path_degrading > 0) {
1769     UMA_HISTOGRAM_COUNTS_1000(
1770         "Net.QuicSession.NumForwardProgressMadeAfterPathDegrading",
1771         connection()->GetStats().num_forward_progress_after_path_degrading);
1772   }
1773   if (const quic::QuicConnection::MultiPortStats* multi_port_stats =
1774           connection()->multi_port_stats()) {
1775     UMA_HISTOGRAM_COUNTS_1000("Net.QuicMultiPort.NumProbeAttempts",
1776                               multi_port_stats->num_client_probing_attempts);
1777     UMA_HISTOGRAM_COUNTS_1000("Net.QuicMultiPort.NumSuccessfulProbes",
1778                               multi_port_stats->num_successful_probes);
1779     UMA_HISTOGRAM_COUNTS_1000(
1780         "Net.QuicMultiPort.NumMultiPortFailureWhenPathNotDegrading",
1781         multi_port_stats
1782             ->num_multi_port_probe_failures_when_path_not_degrading);
1783     size_t total_multi_port_probe_failures =
1784         multi_port_stats
1785             ->num_multi_port_probe_failures_when_path_not_degrading +
1786         multi_port_stats->num_multi_port_probe_failures_when_path_degrading;
1787     uint64_t srtt_ms =
1788         multi_port_stats->rtt_stats.smoothed_rtt().ToMilliseconds();
1789     if (connection()->GetStats().num_path_degrading > 0 &&
1790         total_multi_port_probe_failures > 0 && srtt_ms > 0) {
1791       base::UmaHistogramSparse(
1792           "Net.QuicMultiPort.AltPortRttWhenPathDegradingVsGeneral",
1793           static_cast<int>(
1794               multi_port_stats->rtt_stats_when_default_path_degrading
1795                   .smoothed_rtt()
1796                   .ToMilliseconds() *
1797               100 / srtt_ms));
1798       UMA_HISTOGRAM_COUNTS_1000(
1799           "Net.QuicMultiPort.NumMultiPortFailureWhenPathDegrading",
1800           multi_port_stats->num_multi_port_probe_failures_when_path_degrading);
1801       base::UmaHistogramPercentage(
1802           "Net.QuicMultiPort.AltPortFailureWhenPathDegradingVsGeneral",
1803           static_cast<int>(
1804               multi_port_stats
1805                   ->num_multi_port_probe_failures_when_path_degrading *
1806               100 / total_multi_port_probe_failures));
1807     }
1808   }
1809 
1810   RecordConnectionCloseErrorCode(frame, source, session_key_.host(),
1811                                  OneRttKeysAvailable(),
1812                                  !ech_config_list_.empty());
1813   if (OneRttKeysAvailable()) {
1814     handles::NetworkHandle current_network = GetCurrentNetwork();
1815     for (auto& observer : connectivity_observer_list_) {
1816       observer.OnSessionClosedAfterHandshake(this, current_network, source,
1817                                              frame.quic_error_code);
1818     }
1819   }
1820 
1821   const quic::QuicErrorCode error = frame.quic_error_code;
1822   const std::string& error_details = frame.error_details;
1823 
1824   if (source == quic::ConnectionCloseSource::FROM_SELF &&
1825       error == quic::QUIC_NETWORK_IDLE_TIMEOUT && ShouldKeepConnectionAlive()) {
1826     quic::QuicStreamCount streams_waiting_to_write = 0;
1827     PerformActionOnActiveStreams(
1828         [&streams_waiting_to_write](quic::QuicStream* stream) {
1829           if (stream->HasBufferedData()) {
1830             ++streams_waiting_to_write;
1831           }
1832           return true;
1833         });
1834 
1835     UMA_HISTOGRAM_COUNTS_100(
1836         "Net.QuicSession.NumStreamsWaitingToWriteOnIdleTimeout",
1837         streams_waiting_to_write);
1838     UMA_HISTOGRAM_COUNTS_100("Net.QuicSession.NumActiveStreamsOnIdleTimeout",
1839                              GetNumActiveStreams());
1840   }
1841 
1842   if (source == quic::ConnectionCloseSource::FROM_PEER) {
1843     if (error == quic::QUIC_PUBLIC_RESET) {
1844       // is_from_google_server will be true if the received EPID is
1845       // kEPIDGoogleFrontEnd or kEPIDGoogleFrontEnd0.
1846       const bool is_from_google_server =
1847           error_details.find(base::StringPrintf(
1848               "From %s", quic::kEPIDGoogleFrontEnd)) != std::string::npos;
1849 
1850       if (OneRttKeysAvailable()) {
1851         UMA_HISTOGRAM_BOOLEAN(
1852             "Net.QuicSession.ClosedByPublicReset.HandshakeConfirmed",
1853             is_from_google_server);
1854       } else {
1855         UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedByPublicReset",
1856                               is_from_google_server);
1857       }
1858 
1859       if (is_from_google_server) {
1860         UMA_HISTOGRAM_COUNTS_100(
1861             "Net.QuicSession.NumMigrationsExercisedBeforePublicReset",
1862             packet_readers_.size() - 1);
1863       }
1864 
1865       base::UmaHistogramSparse(
1866           "Net.QuicSession.LastSentPacketContentBeforePublicReset",
1867           connection()
1868               ->sent_packet_manager()
1869               .unacked_packets()
1870               .GetLastPacketContent());
1871 
1872       const quic::QuicTime last_in_flight_packet_sent_time =
1873           connection()
1874               ->sent_packet_manager()
1875               .unacked_packets()
1876               .GetLastInFlightPacketSentTime();
1877       const quic::QuicTime handshake_completion_time =
1878           connection()->GetStats().handshake_completion_time;
1879       if (last_in_flight_packet_sent_time.IsInitialized() &&
1880           handshake_completion_time.IsInitialized() &&
1881           last_in_flight_packet_sent_time >= handshake_completion_time) {
1882         const quic::QuicTime::Delta delay =
1883             last_in_flight_packet_sent_time - handshake_completion_time;
1884         UMA_HISTOGRAM_LONG_TIMES_100(
1885             "Net.QuicSession."
1886             "LastInFlightPacketSentTimeFromHandshakeCompletionWithPublicReset",
1887             base::Milliseconds(delay.ToMilliseconds()));
1888       }
1889 
1890       UMA_HISTOGRAM_LONG_TIMES_100(
1891           "Net.QuicSession.ConnectionDurationWithPublicReset",
1892           tick_clock_->NowTicks() - connect_timing_.connect_end);
1893     }
1894     if (OneRttKeysAvailable()) {
1895       base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
1896           "Net.QuicSession.StreamCloseErrorCodeServer.HandshakeConfirmed",
1897           base::HistogramBase::kUmaTargetedHistogramFlag);
1898       size_t num_streams = GetNumActiveStreams();
1899       if (num_streams > 0) {
1900         histogram->AddCount(error, num_streams);
1901       }
1902     }
1903   } else {
1904     if (OneRttKeysAvailable()) {
1905       base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
1906           "Net.QuicSession.StreamCloseErrorCodeClient.HandshakeConfirmed",
1907           base::HistogramBase::kUmaTargetedHistogramFlag);
1908       size_t num_streams = GetNumActiveStreams();
1909       if (num_streams > 0) {
1910         histogram->AddCount(error, num_streams);
1911       }
1912     } else {
1913       if (error == quic::QUIC_HANDSHAKE_TIMEOUT) {
1914         UMA_HISTOGRAM_BOOLEAN(
1915             "Net.QuicSession.HandshakeTimeout.PathDegradingDetected",
1916             connection()->IsPathDegrading());
1917       }
1918     }
1919     if (error == quic::QUIC_TOO_MANY_RTOS) {
1920       UMA_HISTOGRAM_COUNTS_1000(
1921           "Net.QuicSession.ClosedByRtoAtClient.ReceivedPacketCount",
1922           connection()->GetStats().packets_received);
1923       UMA_HISTOGRAM_COUNTS_1000(
1924           "Net.QuicSession.ClosedByRtoAtClient.SentPacketCount",
1925           connection()->GetStats().packets_sent);
1926       UMA_HISTOGRAM_COUNTS_100(
1927           "Net.QuicSession."
1928           "MaxConsecutiveRtoWithForwardProgressAndBlackholeDetected",
1929           connection()->GetStats().max_consecutive_rto_with_forward_progress);
1930     }
1931   }
1932 
1933   if (error == quic::QUIC_NETWORK_IDLE_TIMEOUT) {
1934     UMA_HISTOGRAM_COUNTS_1M(
1935         "Net.QuicSession.ConnectionClose.NumOpenStreams.TimedOut",
1936         GetNumActiveStreams());
1937     if (OneRttKeysAvailable()) {
1938       if (GetNumActiveStreams() > 0) {
1939         UMA_HISTOGRAM_BOOLEAN(
1940             "Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets",
1941             connection()->sent_packet_manager().HasInFlightPackets());
1942         UMA_HISTOGRAM_COUNTS_1M(
1943             "Net.QuicSession.TimedOutWithOpenStreams.ConsecutivePTOCount",
1944             connection()->sent_packet_manager().GetConsecutivePtoCount());
1945         base::UmaHistogramSparse(
1946             "Net.QuicSession.TimedOutWithOpenStreams.LocalPort",
1947             connection()->self_address().port());
1948       }
1949     } else {
1950       UMA_HISTOGRAM_COUNTS_1M(
1951           "Net.QuicSession.ConnectionClose.NumOpenStreams.HandshakeTimedOut",
1952           GetNumActiveStreams());
1953       UMA_HISTOGRAM_COUNTS_1M(
1954           "Net.QuicSession.ConnectionClose.NumTotalStreams.HandshakeTimedOut",
1955           num_total_streams_);
1956     }
1957   }
1958 
1959   if (OneRttKeysAvailable()) {
1960     // QUIC connections should not timeout while there are open streams,
1961     // since PING frames are sent to prevent timeouts. If, however, the
1962     // connection timed out with open streams then QUIC traffic has become
1963     // blackholed. Alternatively, if too many retransmission timeouts occur
1964     // then QUIC traffic has become blackholed.
1965     if (session_pool_ && (error == quic::QUIC_TOO_MANY_RTOS ||
1966                           (error == quic::QUIC_NETWORK_IDLE_TIMEOUT &&
1967                            GetNumActiveStreams() > 0))) {
1968       session_pool_->OnBlackholeAfterHandshakeConfirmed(this);
1969     }
1970     UMA_HISTOGRAM_COUNTS_100(
1971         "Net.QuicSession.CryptoRetransmitCount.HandshakeConfirmed",
1972         connection()->GetStats().crypto_retransmit_count);
1973     UMA_HISTOGRAM_COUNTS_100(
1974         "Net.QuicSession.MaxConsecutiveRtoWithForwardProgress",
1975         connection()->GetStats().max_consecutive_rto_with_forward_progress);
1976     UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumPingsSent",
1977                               connection()->GetStats().ping_frames_sent);
1978     UMA_HISTOGRAM_LONG_TIMES_100(
1979         "Net.QuicSession.ConnectionDuration",
1980         tick_clock_->NowTicks() - connect_timing_.connect_end);
1981     UMA_HISTOGRAM_COUNTS_100("Net.QuicSession.NumMigrations", num_migrations_);
1982 
1983     // KeyUpdates are used in TLS, but we no longer support pre-TLS QUIC.
1984     DCHECK(connection()->version().UsesTls());
1985     base::UmaHistogramCounts100("Net.QuicSession.KeyUpdate.PerConnection2",
1986                                 connection()->GetStats().key_update_count);
1987     base::UmaHistogramCounts100(
1988         "Net.QuicSession.KeyUpdate.PotentialPeerKeyUpdateAttemptCount",
1989         connection()->PotentialPeerKeyUpdateAttemptCount());
1990     if (last_key_update_reason_ != quic::KeyUpdateReason::kInvalid) {
1991       std::string suffix =
1992           last_key_update_reason_ == quic::KeyUpdateReason::kRemote ? "Remote"
1993                                                                     : "Local";
1994       // These values are persisted to logs. Entries should not be renumbered
1995       // and numeric values should never be reused.
1996       enum class KeyUpdateSuccess {
1997         kInvalid = 0,
1998         kSuccess = 1,
1999         kFailedInitial = 2,
2000         kFailedNonInitial = 3,
2001         kMaxValue = kFailedNonInitial,
2002       };
2003       KeyUpdateSuccess value = KeyUpdateSuccess::kInvalid;
2004       if (connection()->HaveSentPacketsInCurrentKeyPhaseButNoneAcked()) {
2005         if (connection()->GetStats().key_update_count >= 2) {
2006           value = KeyUpdateSuccess::kFailedNonInitial;
2007         } else {
2008           value = KeyUpdateSuccess::kFailedInitial;
2009         }
2010       } else {
2011         value = KeyUpdateSuccess::kSuccess;
2012       }
2013       base::UmaHistogramEnumeration(
2014           "Net.QuicSession.KeyUpdate.Success." + suffix, value);
2015     }
2016   } else {
2017     if (error == quic::QUIC_PUBLIC_RESET) {
2018       RecordHandshakeFailureReason(HANDSHAKE_FAILURE_PUBLIC_RESET);
2019     } else if (connection()->GetStats().packets_received == 0) {
2020       RecordHandshakeFailureReason(HANDSHAKE_FAILURE_BLACK_HOLE);
2021       base::UmaHistogramSparse(
2022           "Net.QuicSession.ConnectionClose.HandshakeFailureBlackHole.QuicError",
2023           error);
2024     } else {
2025       RecordHandshakeFailureReason(HANDSHAKE_FAILURE_UNKNOWN);
2026       base::UmaHistogramSparse(
2027           "Net.QuicSession.ConnectionClose.HandshakeFailureUnknown.QuicError",
2028           error);
2029     }
2030     UMA_HISTOGRAM_COUNTS_100(
2031         "Net.QuicSession.CryptoRetransmitCount.HandshakeNotConfirmed",
2032         connection()->GetStats().crypto_retransmit_count);
2033   }
2034 
2035   base::UmaHistogramCounts1M(
2036       "Net.QuicSession.UndecryptablePacketsReceivedWithDecrypter",
2037       connection()->GetStats().num_failed_authentication_packets_received);
2038   base::UmaHistogramSparse("Net.QuicSession.QuicVersion",
2039                            connection()->transport_version());
2040   NotifyFactoryOfSessionGoingAway();
2041   quic::QuicSession::OnConnectionClosed(frame, source);
2042 
2043   if (!callback_.is_null()) {
2044     std::move(callback_).Run(ERR_QUIC_PROTOCOL_ERROR);
2045   }
2046 
2047   bool socket_found_in_writer = false;
2048   for (auto& packet_reader : packet_readers_) {
2049     packet_reader->CloseSocket();
2050     // If a writer exists that was not destroyed when the connection migrated,
2051     // then that writer may not be notified that its socket has been closed.
2052     // We know that the writer is a QuicChromiumPacketWriter since the packet
2053     // writer is set with the same type originally.
2054     socket_found_in_writer |=
2055         static_cast<QuicChromiumPacketWriter*>(connection()->writer())
2056             ->OnSocketClosed(packet_reader->socket());
2057   }
2058   CHECK(socket_found_in_writer);
2059   DCHECK(!HasActiveRequestStreams());
2060   CloseAllHandles(ERR_UNEXPECTED);
2061   CancelAllRequests(ERR_CONNECTION_CLOSED);
2062   NotifyRequestsOfConfirmation(ERR_CONNECTION_CLOSED);
2063   NotifyFactoryOfSessionClosedLater();
2064 }
2065 
OnSuccessfulVersionNegotiation(const quic::ParsedQuicVersion & version)2066 void QuicChromiumClientSession::OnSuccessfulVersionNegotiation(
2067     const quic::ParsedQuicVersion& version) {
2068   logger_->OnSuccessfulVersionNegotiation(version);
2069   quic::QuicSpdySession::OnSuccessfulVersionNegotiation(version);
2070 }
2071 
HandleWriteError(int error_code,scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> packet)2072 int QuicChromiumClientSession::HandleWriteError(
2073     int error_code,
2074     scoped_refptr<QuicChromiumPacketWriter::ReusableIOBuffer> packet) {
2075   current_migration_cause_ = ON_WRITE_ERROR;
2076   LogHandshakeStatusOnMigrationSignal();
2077 
2078   base::UmaHistogramSparse("Net.QuicSession.WriteError", -error_code);
2079   if (OneRttKeysAvailable()) {
2080     base::UmaHistogramSparse("Net.QuicSession.WriteError.HandshakeConfirmed",
2081                              -error_code);
2082   }
2083 
2084   // For now, skip reporting if there are multiple packet writers and
2085   // connection migration is enabled.
2086   if (packet_readers_.size() == 1u || !migrate_session_early_v2_) {
2087     handles::NetworkHandle current_network = GetCurrentNetwork();
2088     for (auto& observer : connectivity_observer_list_) {
2089       observer.OnSessionEncounteringWriteError(this, current_network,
2090                                                error_code);
2091     }
2092   }
2093 
2094   if (error_code == ERR_MSG_TOO_BIG || session_pool_ == nullptr ||
2095       !migrate_session_on_network_change_v2_ || !OneRttKeysAvailable()) {
2096     return error_code;
2097   }
2098 
2099   handles::NetworkHandle current_network = GetCurrentNetwork();
2100 
2101   net_log_.AddEventWithInt64Params(
2102       NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_WRITE_ERROR, "network",
2103       current_network);
2104 
2105   DCHECK(packet != nullptr);
2106   DCHECK_NE(ERR_IO_PENDING, error_code);
2107   DCHECK_GT(0, error_code);
2108   DCHECK(packet_ == nullptr);
2109 
2110   // Post a task to migrate the session onto a new network.
2111   task_runner_->PostTask(
2112       FROM_HERE,
2113       base::BindOnce(
2114           &QuicChromiumClientSession::MigrateSessionOnWriteError,
2115           weak_factory_.GetWeakPtr(), error_code,
2116           // UnsafeDanglingUntriaged triggered by test:
2117           // QuicSessionPoolTest.MigrateSessionOnSyncWriteErrorPauseBeforeConnected
2118           // TODO(https://crbug.com/1380714): Remove `UnsafeDanglingUntriaged`
2119           base::UnsafeDanglingUntriaged(connection()->writer())));
2120 
2121   ignore_read_error_ = true;
2122 
2123   // Cause the packet writer to return ERR_IO_PENDING and block so
2124   // that the actual migration happens from the message loop instead
2125   // of under the call stack of quic::QuicConnection::WritePacket.
2126   return ERR_IO_PENDING;
2127 }
2128 
MigrateSessionOnWriteError(int error_code,quic::QuicPacketWriter * writer)2129 void QuicChromiumClientSession::MigrateSessionOnWriteError(
2130     int error_code,
2131     quic::QuicPacketWriter* writer) {
2132   DCHECK(migrate_session_on_network_change_v2_);
2133   // If |writer| is no longer actively in use, or a session migration has
2134   // started from MigrateNetworkImmediately, abort this migration attempt.
2135   if (writer != connection()->writer() ||
2136       pending_migrate_network_immediately_) {
2137     return;
2138   }
2139 
2140   most_recent_write_error_timestamp_ = tick_clock_->NowTicks();
2141   most_recent_write_error_ = error_code;
2142 
2143   if (session_pool_ == nullptr) {
2144     // Close the connection if migration failed. Do not cause a
2145     // connection close packet to be sent since socket may be borked.
2146     connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
2147                                   "Write error with nulled stream factory",
2148                                   quic::ConnectionCloseBehavior::SILENT_CLOSE);
2149     return;
2150   }
2151 
2152   current_migration_cause_ = ON_WRITE_ERROR;
2153 
2154   if (migrate_idle_session_ && CheckIdleTimeExceedsIdleMigrationPeriod()) {
2155     return;
2156   }
2157 
2158   if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
2159     // connection close packet to be sent since socket may be borked.
2160     connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
2161                                   "Write error for non-migratable session",
2162                                   quic::ConnectionCloseBehavior::SILENT_CLOSE);
2163     return;
2164   }
2165 
2166   // Do not migrate if connection migration is disabled.
2167   if (config()->DisableConnectionMigration()) {
2168     HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
2169                                     connection_id(),
2170                                     "Migration disabled by config");
2171     // Close the connection since migration was disabled. Do not cause a
2172     // connection close packet to be sent since socket may be borked.
2173     connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
2174                                   "Write error for non-migratable session",
2175                                   quic::ConnectionCloseBehavior::SILENT_CLOSE);
2176     return;
2177   }
2178 
2179   handles::NetworkHandle new_network =
2180       session_pool_->FindAlternateNetwork(GetCurrentNetwork());
2181   if (new_network == handles::kInvalidNetworkHandle) {
2182     // No alternate network found.
2183     HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
2184                                     connection_id(),
2185                                     "No alternate network found");
2186     OnNoNewNetwork();
2187     return;
2188   }
2189 
2190   if (GetCurrentNetwork() == default_network_ &&
2191       current_migrations_to_non_default_network_on_write_error_ >=
2192           max_migrations_to_non_default_network_on_write_error_) {
2193     HistogramAndLogMigrationFailure(
2194         MIGRATION_STATUS_ON_WRITE_ERROR_DISABLED, connection_id(),
2195         "Exceeds maximum number of migrations on write error");
2196     connection()->CloseConnection(
2197         quic::QUIC_PACKET_WRITE_ERROR,
2198         "Too many migrations for write error for the same network",
2199         quic::ConnectionCloseBehavior::SILENT_CLOSE);
2200     return;
2201   }
2202   current_migrations_to_non_default_network_on_write_error_++;
2203 
2204   net_log_.BeginEventWithStringParams(
2205       NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
2206       "WriteError");
2207   pending_migrate_session_on_write_error_ = true;
2208   Migrate(new_network, ToIPEndPoint(connection()->peer_address()),
2209           /*close_session_on_error=*/false,
2210           base::BindOnce(
2211               &QuicChromiumClientSession::FinishMigrateSessionOnWriteError,
2212               weak_factory_.GetWeakPtr(), new_network));
2213   net_log_.EndEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
2214 }
2215 
FinishMigrateSessionOnWriteError(handles::NetworkHandle new_network,MigrationResult result)2216 void QuicChromiumClientSession::FinishMigrateSessionOnWriteError(
2217     handles::NetworkHandle new_network,
2218     MigrationResult result) {
2219   pending_migrate_session_on_write_error_ = false;
2220   if (result == MigrationResult::FAILURE) {
2221     // Close the connection if migration failed. Do not cause a
2222     // connection close packet to be sent since socket may be borked.
2223     connection()->CloseConnection(quic::QUIC_PACKET_WRITE_ERROR,
2224                                   "Write and subsequent migration failed",
2225                                   quic::ConnectionCloseBehavior::SILENT_CLOSE);
2226     return;
2227   }
2228   if (new_network != default_network_) {
2229     StartMigrateBackToDefaultNetworkTimer(
2230         base::Seconds(kMinRetryTimeForDefaultNetworkSecs));
2231   } else {
2232     CancelMigrateBackToDefaultNetworkTimer();
2233   }
2234 }
2235 
OnNoNewNetwork()2236 void QuicChromiumClientSession::OnNoNewNetwork() {
2237   DCHECK(OneRttKeysAvailable());
2238   wait_for_new_network_ = true;
2239   net_log_.AddEvent(
2240       NetLogEventType::QUIC_CONNECTION_MIGRATION_WAITING_FOR_NEW_NETWORK);
2241 
2242   DVLOG(1) << "Force blocking the packet writer";
2243   // Force blocking the packet writer to avoid any writes since there is no
2244   // alternate network available.
2245   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
2246       ->set_force_write_blocked(true);
2247 
2248   if (base::FeatureList::IsEnabled(features::kDisableBlackholeOnNoNewNetwork)) {
2249     // Turn off the black hole detector since the writer is blocked.
2250     // Blackhole will be re-enabled once a packet is sent again.
2251     connection()->blackhole_detector().StopDetection(false);
2252   }
2253 
2254   // Post a task to maybe close the session if the alarm fires.
2255   task_runner_->PostDelayedTask(
2256       FROM_HERE,
2257       base::BindOnce(&QuicChromiumClientSession::OnMigrationTimeout,
2258                      weak_factory_.GetWeakPtr(), packet_readers_.size()),
2259       base::Seconds(kWaitTimeForNewNetworkSecs));
2260 }
2261 
WriteToNewSocket()2262 void QuicChromiumClientSession::WriteToNewSocket() {
2263   // Set |send_packet_after_migration_| to true so that a packet will be
2264   // sent when the writer becomes unblocked.
2265   send_packet_after_migration_ = true;
2266 
2267   DVLOG(1) << "Cancel force blocking the packet writer";
2268   // Notify writer that it is no longer forced blocked, which may call
2269   // OnWriteUnblocked() if the writer has no write in progress.
2270   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
2271       ->set_force_write_blocked(false);
2272 }
2273 
OnMigrationTimeout(size_t num_sockets)2274 void QuicChromiumClientSession::OnMigrationTimeout(size_t num_sockets) {
2275   // If number of sockets has changed, this migration task is stale.
2276   if (num_sockets != packet_readers_.size()) {
2277     return;
2278   }
2279 
2280   net_log_.AddEvent(
2281       NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE_WAITING_FOR_NETWORK);
2282 
2283   int net_error = current_migration_cause_ == ON_NETWORK_DISCONNECTED
2284                       ? ERR_INTERNET_DISCONNECTED
2285                       : ERR_NETWORK_CHANGED;
2286 
2287   // |current_migration_cause_| will be reset after logging.
2288   LogMigrationResultToHistogram(MIGRATION_STATUS_TIMEOUT);
2289 
2290   CloseSessionOnError(net_error, quic::QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK,
2291                       quic::ConnectionCloseBehavior::SILENT_CLOSE);
2292 }
2293 
OnPortMigrationProbeSucceeded(handles::NetworkHandle network,const quic::QuicSocketAddress & peer_address,const quic::QuicSocketAddress & self_address,std::unique_ptr<QuicChromiumPacketWriter> writer,std::unique_ptr<QuicChromiumPacketReader> reader)2294 void QuicChromiumClientSession::OnPortMigrationProbeSucceeded(
2295     handles::NetworkHandle network,
2296     const quic::QuicSocketAddress& peer_address,
2297     const quic::QuicSocketAddress& self_address,
2298     std::unique_ptr<QuicChromiumPacketWriter> writer,
2299     std::unique_ptr<QuicChromiumPacketReader> reader) {
2300   DCHECK(writer);
2301   DCHECK(reader);
2302 
2303   net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CONNECTIVITY_PROBING_FINISHED,
2304                     [&] {
2305                       return NetLogProbingResultParams(network, &peer_address,
2306                                                        /*is_success=*/true);
2307                     });
2308 
2309   LogProbeResultToHistogram(current_migration_cause_, true);
2310 
2311   // Remove |this| as the old packet writer's delegate. Write error on old
2312   // writers will be ignored.
2313   // Set |this| to listen on socket write events on the packet writer
2314   // that was used for probing.
2315   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
2316       ->set_delegate(nullptr);
2317   writer->set_delegate(this);
2318 
2319   if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
2320     // If idle sessions won't be migrated, close the connection.
2321     CloseSessionOnErrorLater(
2322         ERR_NETWORK_CHANGED,
2323         quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
2324         quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2325     return;
2326   }
2327 
2328   if (migrate_idle_session_ && CheckIdleTimeExceedsIdleMigrationPeriod()) {
2329     return;
2330   }
2331 
2332   // Migrate to the probed socket immediately: socket, writer and reader will
2333   // be acquired by connection and used as default on success.
2334   if (!MigrateToSocket(self_address, peer_address, std::move(reader),
2335                        std::move(writer))) {
2336     LogMigrateToSocketStatus(false);
2337     net_log_.AddEvent(
2338         NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE_AFTER_PROBING);
2339     return;
2340   }
2341 
2342   LogMigrateToSocketStatus(true);
2343 
2344   num_migrations_++;
2345   HistogramAndLogMigrationSuccess(connection_id());
2346 }
2347 
OnConnectionMigrationProbeSucceeded(handles::NetworkHandle network,const quic::QuicSocketAddress & peer_address,const quic::QuicSocketAddress & self_address,std::unique_ptr<QuicChromiumPacketWriter> writer,std::unique_ptr<QuicChromiumPacketReader> reader)2348 void QuicChromiumClientSession::OnConnectionMigrationProbeSucceeded(
2349     handles::NetworkHandle network,
2350     const quic::QuicSocketAddress& peer_address,
2351     const quic::QuicSocketAddress& self_address,
2352     std::unique_ptr<QuicChromiumPacketWriter> writer,
2353     std::unique_ptr<QuicChromiumPacketReader> reader) {
2354   DCHECK(writer);
2355   DCHECK(reader);
2356 
2357   net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CONNECTIVITY_PROBING_FINISHED,
2358                     [&] {
2359                       return NetLogProbingResultParams(network, &peer_address,
2360                                                        /*is_success=*/true);
2361                     });
2362   if (network == handles::kInvalidNetworkHandle) {
2363     return;
2364   }
2365 
2366   LogProbeResultToHistogram(current_migration_cause_, true);
2367 
2368   // Remove |this| as the old packet writer's delegate. Write error on old
2369   // writers will be ignored.
2370   // Set |this| to listen on socket write events on the packet writer
2371   // that was used for probing.
2372   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
2373       ->set_delegate(nullptr);
2374   writer->set_delegate(this);
2375 
2376   // Close streams that are not migratable to the probed |network|.
2377   ResetNonMigratableStreams();
2378 
2379   if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
2380     // If idle sessions won't be migrated, close the connection.
2381     CloseSessionOnErrorLater(
2382         ERR_NETWORK_CHANGED,
2383         quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
2384         quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
2385     return;
2386   }
2387 
2388   if (migrate_idle_session_ && CheckIdleTimeExceedsIdleMigrationPeriod()) {
2389     return;
2390   }
2391 
2392   // Migrate to the probed socket immediately: socket, writer and reader will
2393   // be acquired by connection and used as default on success.
2394   if (!MigrateToSocket(self_address, peer_address, std::move(reader),
2395                        std::move(writer))) {
2396     LogMigrateToSocketStatus(false);
2397     net_log_.AddEvent(
2398         NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE_AFTER_PROBING);
2399     return;
2400   }
2401 
2402   LogMigrateToSocketStatus(true);
2403 
2404   net_log_.AddEventWithInt64Params(
2405       NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS_AFTER_PROBING,
2406       "migrate_to_network", network);
2407   num_migrations_++;
2408   HistogramAndLogMigrationSuccess(connection_id());
2409   if (network == default_network_) {
2410     DVLOG(1) << "Client successfully migrated to default network: "
2411              << default_network_;
2412     CancelMigrateBackToDefaultNetworkTimer();
2413     return;
2414   }
2415 
2416   DVLOG(1) << "Client successfully got off default network after "
2417            << "successful probing network: " << network << ".";
2418   current_migrations_to_non_default_network_on_path_degrading_++;
2419   if (!migrate_back_to_default_timer_.IsRunning()) {
2420     current_migration_cause_ = ON_MIGRATE_BACK_TO_DEFAULT_NETWORK;
2421     // Session gets off the |default_network|, stay on |network| for now but
2422     // try to migrate back to default network after 1 second.
2423     StartMigrateBackToDefaultNetworkTimer(
2424         base::Seconds(kMinRetryTimeForDefaultNetworkSecs));
2425   }
2426 }
2427 
OnServerPreferredAddressProbeSucceeded(handles::NetworkHandle network,const quic::QuicSocketAddress & peer_address,const quic::QuicSocketAddress & self_address,std::unique_ptr<QuicChromiumPacketWriter> writer,std::unique_ptr<QuicChromiumPacketReader> reader)2428 void QuicChromiumClientSession::OnServerPreferredAddressProbeSucceeded(
2429     handles::NetworkHandle network,
2430     const quic::QuicSocketAddress& peer_address,
2431     const quic::QuicSocketAddress& self_address,
2432     std::unique_ptr<QuicChromiumPacketWriter> writer,
2433     std::unique_ptr<QuicChromiumPacketReader> reader) {
2434   net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CONNECTIVITY_PROBING_FINISHED,
2435                     [&] {
2436                       return NetLogProbingResultParams(network, &peer_address,
2437                                                        /*is_success=*/true);
2438                     });
2439 
2440   LogProbeResultToHistogram(current_migration_cause_, true);
2441   connection()->mutable_stats().server_preferred_address_validated = true;
2442 
2443   // Remove |this| as the old packet writer's delegate. Write error on old
2444   // writers will be ignored.
2445   // Set |this| to listen on socket write events on the packet writer
2446   // that was used for probing.
2447   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
2448       ->set_delegate(nullptr);
2449   writer->set_delegate(this);
2450 
2451   // Migrate to the probed socket immediately: socket, writer and reader will
2452   // be acquired by connection and used as default on success.
2453   if (!MigrateToSocket(self_address, peer_address, std::move(reader),
2454                        std::move(writer))) {
2455     LogMigrateToSocketStatus(false);
2456     net_log_.AddEvent(
2457         NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE_AFTER_PROBING);
2458     return;
2459   }
2460 
2461   LogMigrateToSocketStatus(true);
2462 
2463   num_migrations_++;
2464   HistogramAndLogMigrationSuccess(connection_id());
2465 }
2466 
OnProbeFailed(handles::NetworkHandle network,const quic::QuicSocketAddress & peer_address)2467 void QuicChromiumClientSession::OnProbeFailed(
2468     handles::NetworkHandle network,
2469     const quic::QuicSocketAddress& peer_address) {
2470   net_log_.AddEvent(NetLogEventType::QUIC_SESSION_CONNECTIVITY_PROBING_FINISHED,
2471                     [&] {
2472                       return NetLogProbingResultParams(network, &peer_address,
2473                                                        /*is_success=*/false);
2474                     });
2475 
2476   LogProbeResultToHistogram(current_migration_cause_, false);
2477 
2478   auto* context = static_cast<QuicChromiumPathValidationContext*>(
2479       connection()->GetPathValidationContext());
2480 
2481   if (!context) {
2482     return;
2483   }
2484 
2485   if (context->network() == network &&
2486       context->peer_address() == peer_address) {
2487     connection()->CancelPathValidation();
2488   }
2489 
2490   if (network != handles::kInvalidNetworkHandle) {
2491     // Probing failure can be ignored.
2492     DVLOG(1) << "Connectivity probing failed on <network: " << network
2493              << ", peer_address: " << peer_address.ToString() << ">.";
2494     DVLOG_IF(1, network == default_network_ &&
2495                     GetCurrentNetwork() != default_network_)
2496         << "Client probing failed on the default network, still using "
2497            "non-default network.";
2498   }
2499 }
2500 
OnNetworkConnected(handles::NetworkHandle network)2501 void QuicChromiumClientSession::OnNetworkConnected(
2502     handles::NetworkHandle network) {
2503   if (connection()->IsPathDegrading()) {
2504     base::TimeDelta duration =
2505         tick_clock_->NowTicks() - most_recent_path_degrading_timestamp_;
2506     UMA_HISTOGRAM_CUSTOM_TIMES("Net.QuicNetworkDegradingDurationTillConnected",
2507                                duration, base::Milliseconds(1),
2508                                base::Minutes(10), 50);
2509   }
2510   net_log_.AddEventWithInt64Params(
2511       NetLogEventType::QUIC_SESSION_NETWORK_CONNECTED, "connected_network",
2512       network);
2513   if (!migrate_session_on_network_change_v2_) {
2514     return;
2515   }
2516 
2517   // If there was no migration waiting for new network and the path is not
2518   // degrading, ignore this signal.
2519   if (!wait_for_new_network_ && !connection()->IsPathDegrading()) {
2520     return;
2521   }
2522 
2523   net_log_.AddEventWithInt64Params(
2524       NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_NETWORK_CONNECTED,
2525       "connected_network", network);
2526 
2527   if (connection()->IsPathDegrading()) {
2528     current_migration_cause_ = NEW_NETWORK_CONNECTED_POST_PATH_DEGRADING;
2529   }
2530 
2531   if (wait_for_new_network_) {
2532     wait_for_new_network_ = false;
2533     net_log_.AddEventWithInt64Params(
2534         NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS_WAITING_FOR_NETWORK,
2535         "network", network);
2536     if (current_migration_cause_ == ON_WRITE_ERROR) {
2537       current_migrations_to_non_default_network_on_write_error_++;
2538     }
2539     // |wait_for_new_network_| is true, there was no working network previously.
2540     // |network| is now the only possible candidate, migrate immediately.
2541     MigrateNetworkImmediately(network);
2542   } else {
2543     // The connection is path degrading.
2544     DCHECK(connection()->IsPathDegrading());
2545     MaybeMigrateToAlternateNetworkOnPathDegrading();
2546   }
2547 }
2548 
OnNetworkDisconnectedV2(handles::NetworkHandle disconnected_network)2549 void QuicChromiumClientSession::OnNetworkDisconnectedV2(
2550     handles::NetworkHandle disconnected_network) {
2551   LogMetricsOnNetworkDisconnected();
2552   net_log_.AddEventWithInt64Params(
2553       NetLogEventType::QUIC_SESSION_NETWORK_DISCONNECTED,
2554       "disconnected_network", disconnected_network);
2555   if (!migrate_session_on_network_change_v2_) {
2556     return;
2557   }
2558   net_log_.AddEventWithInt64Params(
2559       NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_NETWORK_DISCONNECTED,
2560       "disconnected_network", disconnected_network);
2561 
2562   // Stop probing the disconnected network if there is one.
2563   auto* context = static_cast<QuicChromiumPathValidationContext*>(
2564       connection()->GetPathValidationContext());
2565   if (context && context->network() == disconnected_network &&
2566       context->peer_address() == peer_address()) {
2567     connection()->CancelPathValidation();
2568   }
2569 
2570   if (disconnected_network == default_network_) {
2571     DVLOG(1) << "Default network: " << default_network_ << " is disconnected.";
2572     default_network_ = handles::kInvalidNetworkHandle;
2573     current_migrations_to_non_default_network_on_write_error_ = 0;
2574   }
2575 
2576   // Ignore the signal if the current active network is not affected.
2577   if (GetCurrentNetwork() != disconnected_network) {
2578     DVLOG(1) << "Client's current default network is not affected by the "
2579              << "disconnected one.";
2580     return;
2581   }
2582 
2583   if (base::FeatureList::IsEnabled(
2584           features::kQuicMigrationIgnoreDisconnectSignalDuringProbing) &&
2585       current_migration_cause_ == ON_NETWORK_MADE_DEFAULT) {
2586     DVLOG(1) << "Ignoring a network disconnection signal because a "
2587                 "connection migration is happening on the default network.";
2588     return;
2589   }
2590 
2591   current_migration_cause_ = ON_NETWORK_DISCONNECTED;
2592   LogHandshakeStatusOnMigrationSignal();
2593   if (!OneRttKeysAvailable()) {
2594     // Close the connection if handshake is not confirmed. Migration before
2595     // handshake is not allowed.
2596     CloseSessionOnErrorLater(
2597         ERR_NETWORK_CHANGED,
2598         quic::QUIC_CONNECTION_MIGRATION_HANDSHAKE_UNCONFIRMED,
2599         quic::ConnectionCloseBehavior::SILENT_CLOSE);
2600     return;
2601   }
2602 
2603   // Attempt to find alternative network.
2604   handles::NetworkHandle new_network =
2605       session_pool_->FindAlternateNetwork(disconnected_network);
2606 
2607   if (new_network == handles::kInvalidNetworkHandle) {
2608     OnNoNewNetwork();
2609     return;
2610   }
2611 
2612   // Current network is being disconnected, migrate immediately to the
2613   // alternative network.
2614   MigrateNetworkImmediately(new_network);
2615 }
2616 
OnNetworkMadeDefault(handles::NetworkHandle new_network)2617 void QuicChromiumClientSession::OnNetworkMadeDefault(
2618     handles::NetworkHandle new_network) {
2619   LogMetricsOnNetworkMadeDefault();
2620   net_log_.AddEventWithInt64Params(
2621       NetLogEventType::QUIC_SESSION_NETWORK_MADE_DEFAULT, "new_default_network",
2622       new_network);
2623 
2624   if (!migrate_session_on_network_change_v2_) {
2625     return;
2626   }
2627 
2628   DCHECK_NE(handles::kInvalidNetworkHandle, new_network);
2629   net_log_.AddEventWithInt64Params(
2630       NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_NETWORK_MADE_DEFAULT,
2631       "new_default_network", new_network);
2632   default_network_ = new_network;
2633 
2634   DVLOG(1) << "Network: " << new_network
2635            << " becomes default, old default: " << default_network_;
2636   current_migration_cause_ = ON_NETWORK_MADE_DEFAULT;
2637   current_migrations_to_non_default_network_on_write_error_ = 0;
2638   current_migrations_to_non_default_network_on_path_degrading_ = 0;
2639 
2640   // Simply cancel the timer to migrate back to the default network if session
2641   // is already on the default network.
2642   if (GetCurrentNetwork() == new_network) {
2643     CancelMigrateBackToDefaultNetworkTimer();
2644     HistogramAndLogMigrationFailure(MIGRATION_STATUS_ALREADY_MIGRATED,
2645                                     connection_id(),
2646                                     "Already migrated on the new network");
2647     return;
2648   }
2649 
2650   LogHandshakeStatusOnMigrationSignal();
2651 
2652   // Stay on the current network. Try to migrate back to default network
2653   // without any delay, which will start probing the new default network and
2654   // migrate to the new network immediately on success.
2655   StartMigrateBackToDefaultNetworkTimer(base::TimeDelta());
2656 }
2657 
MigrateNetworkImmediately(handles::NetworkHandle network)2658 void QuicChromiumClientSession::MigrateNetworkImmediately(
2659     handles::NetworkHandle network) {
2660   // There is no choice but to migrate to |network|. If any error encountered,
2661   // close the session. When migration succeeds:
2662   // - if no longer on the default network, start timer to migrate back;
2663   // - otherwise, it's brought to default network, cancel the running timer to
2664   //   migrate back.
2665 
2666   DCHECK(migrate_session_on_network_change_v2_);
2667 
2668   if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
2669     HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
2670                                     connection_id(), "No active streams");
2671     CloseSessionOnErrorLater(
2672         ERR_NETWORK_CHANGED,
2673         quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
2674         quic::ConnectionCloseBehavior::SILENT_CLOSE);
2675     return;
2676   }
2677 
2678   if (migrate_idle_session_ && CheckIdleTimeExceedsIdleMigrationPeriod()) {
2679     return;
2680   }
2681 
2682   // Do not migrate if connection migration is disabled.
2683   if (config()->DisableConnectionMigration()) {
2684     HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
2685                                     connection_id(),
2686                                     "Migration disabled by config");
2687     CloseSessionOnErrorLater(ERR_NETWORK_CHANGED,
2688                              quic::QUIC_CONNECTION_MIGRATION_DISABLED_BY_CONFIG,
2689                              quic::ConnectionCloseBehavior::SILENT_CLOSE);
2690     return;
2691   }
2692 
2693   if (network == GetCurrentNetwork()) {
2694     HistogramAndLogMigrationFailure(MIGRATION_STATUS_ALREADY_MIGRATED,
2695                                     connection_id(),
2696                                     "Already bound to new network");
2697     return;
2698   }
2699 
2700   // Cancel probing on |network| if there is any.
2701   auto* context = static_cast<QuicChromiumPathValidationContext*>(
2702       connection()->GetPathValidationContext());
2703   if (context && context->network() == network &&
2704       context->peer_address() == peer_address()) {
2705     connection()->CancelPathValidation();
2706   }
2707   pending_migrate_network_immediately_ = true;
2708   Migrate(network, ToIPEndPoint(connection()->peer_address()),
2709           /*close_session_on_error=*/true,
2710           base::BindOnce(
2711               &QuicChromiumClientSession::FinishMigrateNetworkImmediately,
2712               weak_factory_.GetWeakPtr(), network));
2713 }
2714 
FinishMigrateNetworkImmediately(handles::NetworkHandle network,MigrationResult result)2715 void QuicChromiumClientSession::FinishMigrateNetworkImmediately(
2716     handles::NetworkHandle network,
2717     MigrationResult result) {
2718   pending_migrate_network_immediately_ = false;
2719   if (result == MigrationResult::FAILURE) {
2720     return;
2721   }
2722 
2723   if (network == default_network_) {
2724     CancelMigrateBackToDefaultNetworkTimer();
2725     return;
2726   }
2727 
2728   // TODO(zhongyi): reconsider this, maybe we just want to hear back
2729   // We are forced to migrate to |network|, probably |default_network_| is
2730   // not working, start to migrate back to default network after 1 secs.
2731   StartMigrateBackToDefaultNetworkTimer(
2732       base::Seconds(kMinRetryTimeForDefaultNetworkSecs));
2733 }
2734 
OnWriteError(int error_code)2735 void QuicChromiumClientSession::OnWriteError(int error_code) {
2736   DCHECK_NE(ERR_IO_PENDING, error_code);
2737   DCHECK_GT(0, error_code);
2738   connection()->OnWriteError(error_code);
2739 }
2740 
OnWriteUnblocked()2741 void QuicChromiumClientSession::OnWriteUnblocked() {
2742   DCHECK(!connection()->writer()->IsWriteBlocked());
2743 
2744   // A new packet will be written after migration completes, unignore read
2745   // errors.
2746   if (ignore_read_error_) {
2747     ignore_read_error_ = false;
2748   }
2749 
2750   if (packet_) {
2751     DCHECK(send_packet_after_migration_);
2752     send_packet_after_migration_ = false;
2753     static_cast<QuicChromiumPacketWriter*>(connection()->writer())
2754         ->WritePacketToSocket(std::move(packet_));
2755     return;
2756   }
2757 
2758   // Unblock the connection, which may send queued packets.
2759   connection()->OnCanWrite();
2760   if (send_packet_after_migration_) {
2761     send_packet_after_migration_ = false;
2762     if (!connection()->writer()->IsWriteBlocked()) {
2763       connection()->SendPing();
2764     }
2765   }
2766 }
2767 
OnPathDegrading()2768 void QuicChromiumClientSession::OnPathDegrading() {
2769   if (most_recent_path_degrading_timestamp_ == base::TimeTicks()) {
2770     most_recent_path_degrading_timestamp_ = tick_clock_->NowTicks();
2771   }
2772 
2773   handles::NetworkHandle current_network = GetCurrentNetwork();
2774   for (auto& observer : connectivity_observer_list_) {
2775     observer.OnSessionPathDegrading(this, current_network);
2776   }
2777 
2778   if (!session_pool_ || connection()->multi_port_stats()) {
2779     return;
2780   }
2781 
2782   if (allow_port_migration_ && !migrate_session_early_v2_) {
2783     MaybeMigrateToDifferentPortOnPathDegrading();
2784     return;
2785   }
2786 
2787   MaybeMigrateToAlternateNetworkOnPathDegrading();
2788 }
2789 
OnForwardProgressMadeAfterPathDegrading()2790 void QuicChromiumClientSession::OnForwardProgressMadeAfterPathDegrading() {
2791   handles::NetworkHandle current_network = GetCurrentNetwork();
2792   for (auto& observer : connectivity_observer_list_) {
2793     observer.OnSessionResumedPostPathDegrading(this, current_network);
2794   }
2795 }
2796 
OnKeyUpdate(quic::KeyUpdateReason reason)2797 void QuicChromiumClientSession::OnKeyUpdate(quic::KeyUpdateReason reason) {
2798   net_log_.AddEventWithStringParams(NetLogEventType::QUIC_SESSION_KEY_UPDATE,
2799                                     "reason",
2800                                     quic::KeyUpdateReasonString(reason));
2801 
2802   base::UmaHistogramEnumeration("Net.QuicSession.KeyUpdate.Reason", reason);
2803 
2804   last_key_update_reason_ = reason;
2805 }
2806 
OnProofValid(const quic::QuicCryptoClientConfig::CachedState & cached)2807 void QuicChromiumClientSession::OnProofValid(
2808     const quic::QuicCryptoClientConfig::CachedState& cached) {
2809   DCHECK(cached.proof_valid());
2810 
2811   if (!server_info_) {
2812     return;
2813   }
2814 
2815   QuicServerInfo::State* state = server_info_->mutable_state();
2816 
2817   state->server_config = cached.server_config();
2818   state->source_address_token = cached.source_address_token();
2819   state->cert_sct = cached.cert_sct();
2820   state->chlo_hash = cached.chlo_hash();
2821   state->server_config_sig = cached.signature();
2822   state->certs = cached.certs();
2823 
2824   server_info_->Persist();
2825 }
2826 
OnProofVerifyDetailsAvailable(const quic::ProofVerifyDetails & verify_details)2827 void QuicChromiumClientSession::OnProofVerifyDetailsAvailable(
2828     const quic::ProofVerifyDetails& verify_details) {
2829   const ProofVerifyDetailsChromium* verify_details_chromium =
2830       reinterpret_cast<const ProofVerifyDetailsChromium*>(&verify_details);
2831   cert_verify_result_ = std::make_unique<CertVerifyResult>(
2832       verify_details_chromium->cert_verify_result);
2833   logger_->OnCertificateVerified(*cert_verify_result_);
2834   pkp_bypassed_ = verify_details_chromium->pkp_bypassed;
2835   is_fatal_cert_error_ = verify_details_chromium->is_fatal_cert_error;
2836 }
2837 
StartReading()2838 void QuicChromiumClientSession::StartReading() {
2839   for (auto& packet_reader : packet_readers_) {
2840     packet_reader->StartReading();
2841   }
2842 }
2843 
CloseSessionOnError(int net_error,quic::QuicErrorCode quic_error,quic::ConnectionCloseBehavior behavior)2844 void QuicChromiumClientSession::CloseSessionOnError(
2845     int net_error,
2846     quic::QuicErrorCode quic_error,
2847     quic::ConnectionCloseBehavior behavior) {
2848   base::UmaHistogramSparse("Net.QuicSession.CloseSessionOnError", -net_error);
2849 
2850   if (!callback_.is_null()) {
2851     std::move(callback_).Run(net_error);
2852   }
2853 
2854   NotifyAllStreamsOfError(net_error);
2855 
2856   net_log_.AddEventWithIntParams(NetLogEventType::QUIC_SESSION_CLOSE_ON_ERROR,
2857                                  "net_error", net_error);
2858 
2859   if (connection()->connected()) {
2860     connection()->CloseConnection(quic_error, "net error", behavior);
2861   }
2862   DCHECK(!connection()->connected());
2863 
2864   CloseAllHandles(net_error);
2865   NotifyFactoryOfSessionClosed();
2866 }
2867 
CloseSessionOnErrorLater(int net_error,quic::QuicErrorCode quic_error,quic::ConnectionCloseBehavior behavior)2868 void QuicChromiumClientSession::CloseSessionOnErrorLater(
2869     int net_error,
2870     quic::QuicErrorCode quic_error,
2871     quic::ConnectionCloseBehavior behavior) {
2872   base::UmaHistogramSparse("Net.QuicSession.CloseSessionOnError", -net_error);
2873 
2874   if (!callback_.is_null()) {
2875     std::move(callback_).Run(net_error);
2876   }
2877   NotifyAllStreamsOfError(net_error);
2878   net_log_.AddEventWithIntParams(NetLogEventType::QUIC_SESSION_CLOSE_ON_ERROR,
2879                                  "net_error", net_error);
2880 
2881   if (connection()->connected()) {
2882     connection()->CloseConnection(quic_error, "net error", behavior);
2883   }
2884   DCHECK(!connection()->connected());
2885 
2886   CloseAllHandles(net_error);
2887   NotifyFactoryOfSessionClosedLater();
2888 }
2889 
NotifyAllStreamsOfError(int net_error)2890 void QuicChromiumClientSession::NotifyAllStreamsOfError(int net_error) {
2891   PerformActionOnActiveStreams([net_error](quic::QuicStream* stream) {
2892     static_cast<QuicChromiumClientStream*>(stream)->OnError(net_error);
2893     return true;
2894   });
2895 }
2896 
CloseAllHandles(int net_error)2897 void QuicChromiumClientSession::CloseAllHandles(int net_error) {
2898   while (!handles_.empty()) {
2899     Handle* handle = *handles_.begin();
2900     handles_.erase(handle);
2901     handle->OnSessionClosed(connection()->version(), net_error, error(),
2902                             port_migration_detected_,
2903                             quic_connection_migration_attempted_,
2904                             quic_connection_migration_successful_,
2905                             GetConnectTiming(), WasConnectionEverUsed());
2906   }
2907 }
2908 
CancelAllRequests(int net_error)2909 void QuicChromiumClientSession::CancelAllRequests(int net_error) {
2910   UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.AbortedPendingStreamRequests",
2911                             stream_requests_.size());
2912 
2913   while (!stream_requests_.empty()) {
2914     StreamRequest* request = stream_requests_.front();
2915     stream_requests_.pop_front();
2916     request->OnRequestCompleteFailure(net_error);
2917   }
2918 }
2919 
NotifyRequestsOfConfirmation(int net_error)2920 void QuicChromiumClientSession::NotifyRequestsOfConfirmation(int net_error) {
2921   // Post tasks to avoid reentrancy.
2922   for (auto& callback : waiting_for_confirmation_callbacks_) {
2923     task_runner_->PostTask(FROM_HERE,
2924                            base::BindOnce(std::move(callback), net_error));
2925   }
2926 
2927   waiting_for_confirmation_callbacks_.clear();
2928 }
2929 
MaybeMigrateToDifferentPortOnPathDegrading()2930 void QuicChromiumClientSession::MaybeMigrateToDifferentPortOnPathDegrading() {
2931   DCHECK(allow_port_migration_ && !migrate_session_early_v2_);
2932 
2933   current_migration_cause_ = CHANGE_PORT_ON_PATH_DEGRADING;
2934 
2935   // Migration before handshake confirmed is not allowed.
2936   if (!connection()->IsHandshakeConfirmed()) {
2937     HistogramAndLogMigrationFailure(
2938         MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
2939         connection_id(), "Path degrading before handshake confirmed");
2940     return;
2941   }
2942 
2943   if (config()->DisableConnectionMigration()) {
2944     HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
2945                                     connection_id(),
2946                                     "Migration disabled by config");
2947     return;
2948   }
2949 
2950   net_log_.BeginEvent(NetLogEventType::QUIC_PORT_MIGRATION_TRIGGERED);
2951 
2952   if (!session_pool_) {
2953     return;
2954   }
2955 
2956   // Probe a different port, session will migrate to the probed port on success.
2957   // DoNothingAs is passed in for `probing_callback` as the return value of
2958   // StartProbing is not needed.
2959   StartProbing(base::DoNothingAs<void(ProbingResult)>(), default_network_,
2960                peer_address());
2961   net_log_.EndEvent(NetLogEventType::QUIC_PORT_MIGRATION_TRIGGERED);
2962 }
2963 
2964 void QuicChromiumClientSession::
MaybeMigrateToAlternateNetworkOnPathDegrading()2965     MaybeMigrateToAlternateNetworkOnPathDegrading() {
2966   net_log_.AddEvent(
2967       NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_PATH_DEGRADING);
2968 
2969   current_migration_cause_ = CHANGE_NETWORK_ON_PATH_DEGRADING;
2970 
2971   if (!migrate_session_early_v2_) {
2972     HistogramAndLogMigrationFailure(MIGRATION_STATUS_PATH_DEGRADING_NOT_ENABLED,
2973                                     connection_id(),
2974                                     "Migration on path degrading not enabled");
2975     return;
2976   }
2977 
2978   if (GetCurrentNetwork() == default_network_ &&
2979       current_migrations_to_non_default_network_on_path_degrading_ >=
2980           max_migrations_to_non_default_network_on_path_degrading_) {
2981     HistogramAndLogMigrationFailure(
2982         MIGRATION_STATUS_ON_PATH_DEGRADING_DISABLED, connection_id(),
2983         "Exceeds maximum number of migrations on path degrading");
2984     return;
2985   }
2986 
2987   handles::NetworkHandle alternate_network =
2988       session_pool_->FindAlternateNetwork(GetCurrentNetwork());
2989   if (alternate_network == handles::kInvalidNetworkHandle) {
2990     HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_ALTERNATE_NETWORK,
2991                                     connection_id(),
2992                                     "No alternative network on path degrading");
2993     return;
2994   }
2995 
2996   LogHandshakeStatusOnMigrationSignal();
2997 
2998   if (!connection()->IsHandshakeConfirmed()) {
2999     HistogramAndLogMigrationFailure(
3000         MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
3001         connection_id(), "Path degrading before handshake confirmed");
3002     return;
3003   }
3004 
3005   net_log_.BeginEventWithStringParams(
3006       NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, "trigger",
3007       "PathDegrading");
3008   // Probe the alternative network, session will migrate to the probed
3009   // network and decide whether it wants to migrate back to the default
3010   // network on success. DoNothingAs is passed in for `probing_callback` as the
3011   // return value of MaybeStartProbing is not needed.
3012   MaybeStartProbing(base::DoNothingAs<void(ProbingResult)>(), alternate_network,
3013                     peer_address());
3014   net_log_.EndEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED);
3015 }
3016 
MaybeStartProbing(ProbingCallback probing_callback,handles::NetworkHandle network,const quic::QuicSocketAddress & peer_address)3017 void QuicChromiumClientSession::MaybeStartProbing(
3018     ProbingCallback probing_callback,
3019     handles::NetworkHandle network,
3020     const quic::QuicSocketAddress& peer_address) {
3021   if (!session_pool_) {
3022     task_runner_->PostTask(
3023         FROM_HERE, base::BindOnce(std::move(probing_callback),
3024                                   ProbingResult::DISABLED_WITH_IDLE_SESSION));
3025     return;
3026   }
3027 
3028   CHECK_NE(handles::kInvalidNetworkHandle, network);
3029 
3030   if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
3031     HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_MIGRATABLE_STREAMS,
3032                                     connection_id(), "No active streams");
3033     CloseSessionOnErrorLater(
3034         ERR_NETWORK_CHANGED,
3035         quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
3036         quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
3037     task_runner_->PostTask(
3038         FROM_HERE, base::BindOnce(std::move(probing_callback),
3039                                   ProbingResult::DISABLED_WITH_IDLE_SESSION));
3040     return;
3041   }
3042 
3043   if (migrate_idle_session_ && CheckIdleTimeExceedsIdleMigrationPeriod()) {
3044     task_runner_->PostTask(
3045         FROM_HERE, base::BindOnce(std::move(probing_callback),
3046                                   ProbingResult::DISABLED_WITH_IDLE_SESSION));
3047     return;
3048   }
3049 
3050   if (config()->DisableConnectionMigration()) {
3051     DVLOG(1) << "Client disables probing network with connection migration "
3052              << "disabled by config";
3053     HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
3054                                     connection_id(),
3055                                     "Migration disabled by config");
3056     task_runner_->PostTask(FROM_HERE,
3057                            base::BindOnce(std::move(probing_callback),
3058                                           ProbingResult::DISABLED_BY_CONFIG));
3059     return;
3060   }
3061 
3062   StartProbing(std::move(probing_callback), network, peer_address);
3063 }
3064 
CreateContextForMultiPortPath(std::unique_ptr<quic::MultiPortPathContextObserver> context_observer)3065 void QuicChromiumClientSession::CreateContextForMultiPortPath(
3066     std::unique_ptr<quic::MultiPortPathContextObserver> context_observer) {
3067   // Create and configure socket on default network
3068   std::unique_ptr<DatagramClientSocket> probing_socket =
3069       session_pool_->CreateSocket(net_log_.net_log(), net_log_.source());
3070   if (base::FeatureList::IsEnabled(net::features::kAsyncMultiPortPath)) {
3071     DatagramClientSocket* probing_socket_ptr = probing_socket.get();
3072     CompletionOnceCallback configure_callback = base::BindOnce(
3073         &QuicChromiumClientSession::FinishCreateContextForMultiPortPath,
3074         weak_factory_.GetWeakPtr(), std::move(context_observer),
3075         std::move(probing_socket));
3076     session_pool_->ConnectAndConfigureSocket(
3077         std::move(configure_callback), probing_socket_ptr,
3078         ToIPEndPoint(peer_address()), default_network_,
3079         session_key_.socket_tag());
3080     return;
3081   }
3082 
3083   if (session_pool_->ConfigureSocket(
3084           probing_socket.get(), ToIPEndPoint(peer_address()), default_network_,
3085           session_key_.socket_tag()) != OK) {
3086     return;
3087   }
3088 
3089   FinishCreateContextForMultiPortPath(std::move(context_observer),
3090                                       std::move(probing_socket), OK);
3091 }
3092 
FinishCreateContextForMultiPortPath(std::unique_ptr<quic::MultiPortPathContextObserver> context_observer,std::unique_ptr<DatagramClientSocket> probing_socket,int rv)3093 void QuicChromiumClientSession::FinishCreateContextForMultiPortPath(
3094     std::unique_ptr<quic::MultiPortPathContextObserver> context_observer,
3095     std::unique_ptr<DatagramClientSocket> probing_socket,
3096     int rv) {
3097   if (rv != OK) {
3098     context_observer->OnMultiPortPathContextAvailable(nullptr);
3099     return;
3100   }
3101   // Create new packet writer and reader on the probing socket.
3102   auto probing_writer = std::make_unique<QuicChromiumPacketWriter>(
3103       probing_socket.get(), task_runner_);
3104   auto probing_reader = std::make_unique<QuicChromiumPacketReader>(
3105       std::move(probing_socket), clock_, this, yield_after_packets_,
3106       yield_after_duration_, net_log_);
3107 
3108   probing_reader->StartReading();
3109   path_validation_writer_delegate_.set_network(default_network_);
3110   path_validation_writer_delegate_.set_peer_address(peer_address());
3111   probing_writer->set_delegate(&path_validation_writer_delegate_);
3112   IPEndPoint local_address;
3113   probing_reader->socket()->GetLocalAddress(&local_address);
3114   context_observer->OnMultiPortPathContextAvailable(
3115       std::make_unique<QuicChromiumPathValidationContext>(
3116           ToQuicSocketAddress(local_address), peer_address(), default_network_,
3117           std::move(probing_writer), std::move(probing_reader)));
3118 }
3119 
MigrateToMultiPortPath(std::unique_ptr<quic::QuicPathValidationContext> context)3120 void QuicChromiumClientSession::MigrateToMultiPortPath(
3121     std::unique_ptr<quic::QuicPathValidationContext> context) {
3122   DCHECK_NE(nullptr, context);
3123   auto* chrome_context =
3124       static_cast<QuicChromiumPathValidationContext*>(context.get());
3125   std::unique_ptr<QuicChromiumPacketWriter> owned_writer =
3126       chrome_context->ReleaseWriter();
3127   // Remove |this| as the old packet writer's delegate. Write error on old
3128   // writers will be ignored.
3129   // Set |this| to listen on socket write events on the packet writer
3130   // that was used for probing.
3131   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
3132       ->set_delegate(nullptr);
3133   owned_writer->set_delegate(this);
3134 
3135   if (!MigrateToSocket(
3136           chrome_context->self_address(), chrome_context->peer_address(),
3137           chrome_context->ReleaseReader(), std::move(owned_writer))) {
3138     LogMigrateToSocketStatus(false);
3139     return;
3140   }
3141   LogMigrateToSocketStatus(true);
3142   num_migrations_++;
3143 }
3144 
StartProbing(ProbingCallback probing_callback,handles::NetworkHandle network,const quic::QuicSocketAddress & peer_address)3145 void QuicChromiumClientSession::StartProbing(
3146     ProbingCallback probing_callback,
3147     handles::NetworkHandle network,
3148     const quic::QuicSocketAddress& peer_address) {
3149   // Check if probing manager is probing the same path.
3150   auto* existing_context = static_cast<QuicChromiumPathValidationContext*>(
3151       connection()->GetPathValidationContext());
3152   if (existing_context && existing_context->network() == network &&
3153       existing_context->peer_address() == peer_address) {
3154     task_runner_->PostTask(FROM_HERE,
3155                            base::BindOnce(std::move(probing_callback),
3156                                           ProbingResult::DISABLED_BY_CONFIG));
3157     return;
3158   }
3159 
3160   // Create and configure socket on |network|.
3161   std::unique_ptr<DatagramClientSocket> probing_socket =
3162       session_pool_->CreateSocket(net_log_.net_log(), net_log_.source());
3163   DatagramClientSocket* probing_socket_ptr = probing_socket.get();
3164   CompletionOnceCallback configure_callback =
3165       base::BindOnce(&QuicChromiumClientSession::FinishStartProbing,
3166                      weak_factory_.GetWeakPtr(), std::move(probing_callback),
3167                      std::move(probing_socket), network, peer_address);
3168 
3169   if (current_migration_cause_ != UNKNOWN_CAUSE &&
3170       !MidMigrationCallbackForTesting().is_null()) {
3171     std::move(MidMigrationCallbackForTesting()).Run();  // IN-TEST
3172   }
3173 
3174   session_pool_->ConnectAndConfigureSocket(
3175       std::move(configure_callback), probing_socket_ptr,
3176       ToIPEndPoint(peer_address), network, session_key_.socket_tag());
3177 
3178   return;
3179 }
3180 
FinishStartProbing(ProbingCallback probing_callback,std::unique_ptr<DatagramClientSocket> probing_socket,handles::NetworkHandle network,const quic::QuicSocketAddress & peer_address,int rv)3181 void QuicChromiumClientSession::FinishStartProbing(
3182     ProbingCallback probing_callback,
3183     std::unique_ptr<DatagramClientSocket> probing_socket,
3184     handles::NetworkHandle network,
3185     const quic::QuicSocketAddress& peer_address,
3186     int rv) {
3187   if (rv != OK) {
3188     HistogramAndLogMigrationFailure(MIGRATION_STATUS_INTERNAL_ERROR,
3189                                     connection_id(),
3190                                     "Socket configuration failed");
3191     task_runner_->PostTask(FROM_HERE,
3192                            base::BindOnce(std::move(probing_callback),
3193                                           ProbingResult::INTERNAL_ERROR));
3194 
3195     return;
3196   }
3197   // Create new packet writer and reader on the probing socket.
3198   auto probing_writer = std::make_unique<QuicChromiumPacketWriter>(
3199       probing_socket.get(), task_runner_);
3200   auto probing_reader = std::make_unique<QuicChromiumPacketReader>(
3201       std::move(probing_socket), clock_, this, yield_after_packets_,
3202       yield_after_duration_, net_log_);
3203 
3204   probing_reader->StartReading();
3205   path_validation_writer_delegate_.set_network(network);
3206   path_validation_writer_delegate_.set_peer_address(peer_address);
3207   probing_writer->set_delegate(&path_validation_writer_delegate_);
3208   IPEndPoint local_address;
3209   probing_reader->socket()->GetLocalAddress(&local_address);
3210   auto context = std::make_unique<QuicChromiumPathValidationContext>(
3211       ToQuicSocketAddress(local_address), peer_address, network,
3212       std::move(probing_writer), std::move(probing_reader));
3213   switch (current_migration_cause_) {
3214     case CHANGE_PORT_ON_PATH_DEGRADING:
3215       ValidatePath(
3216           std::move(context),
3217           std::make_unique<PortMigrationValidationResultDelegate>(this),
3218           quic::PathValidationReason::kPortMigration);
3219       break;
3220     case ON_SERVER_PREFERRED_ADDRESS_AVAILABLE:
3221       ValidatePath(
3222           std::move(context),
3223           std::make_unique<ServerPreferredAddressValidationResultDelegate>(
3224               this),
3225           quic::PathValidationReason::kServerPreferredAddressMigration);
3226       break;
3227     default:
3228       ValidatePath(
3229           std::move(context),
3230           std::make_unique<ConnectionMigrationValidationResultDelegate>(this),
3231           quic::PathValidationReason::kConnectionMigration);
3232       break;
3233   }
3234 
3235   task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(probing_callback),
3236                                                    ProbingResult::PENDING));
3237 }
3238 
StartMigrateBackToDefaultNetworkTimer(base::TimeDelta delay)3239 void QuicChromiumClientSession::StartMigrateBackToDefaultNetworkTimer(
3240     base::TimeDelta delay) {
3241   if (current_migration_cause_ != ON_NETWORK_MADE_DEFAULT) {
3242     current_migration_cause_ = ON_MIGRATE_BACK_TO_DEFAULT_NETWORK;
3243   }
3244 
3245   CancelMigrateBackToDefaultNetworkTimer();
3246   // Post a task to try migrate back to default network after |delay|.
3247   migrate_back_to_default_timer_.Start(
3248       FROM_HERE, delay,
3249       base::BindOnce(
3250           &QuicChromiumClientSession::MaybeRetryMigrateBackToDefaultNetwork,
3251           weak_factory_.GetWeakPtr()));
3252 }
3253 
CancelMigrateBackToDefaultNetworkTimer()3254 void QuicChromiumClientSession::CancelMigrateBackToDefaultNetworkTimer() {
3255   retry_migrate_back_count_ = 0;
3256   migrate_back_to_default_timer_.Stop();
3257 }
3258 
TryMigrateBackToDefaultNetwork(base::TimeDelta timeout)3259 void QuicChromiumClientSession::TryMigrateBackToDefaultNetwork(
3260     base::TimeDelta timeout) {
3261   if (default_network_ == handles::kInvalidNetworkHandle) {
3262     DVLOG(1) << "Default network is not connected";
3263     return;
3264   }
3265 
3266   net_log_.AddEventWithInt64Params(
3267       NetLogEventType::QUIC_CONNECTION_MIGRATION_ON_MIGRATE_BACK, "retry_count",
3268       retry_migrate_back_count_);
3269   // Start probe default network immediately, if manager is probing
3270   // the same network, this will be a no-op. Otherwise, previous probe
3271   // will be cancelled and manager starts to probe |default_network_|
3272   // immediately.
3273   MaybeStartProbing(
3274       base::BindOnce(
3275           &QuicChromiumClientSession::FinishTryMigrateBackToDefaultNetwork,
3276           weak_factory_.GetWeakPtr(), timeout),
3277       default_network_, peer_address());
3278 }
3279 
FinishTryMigrateBackToDefaultNetwork(base::TimeDelta timeout,ProbingResult result)3280 void QuicChromiumClientSession::FinishTryMigrateBackToDefaultNetwork(
3281     base::TimeDelta timeout,
3282     ProbingResult result) {
3283   if (result != ProbingResult::PENDING) {
3284     // Session is not allowed to migrate, mark session as going away, cancel
3285     // migrate back to default timer.
3286     NotifyFactoryOfSessionGoingAway();
3287     CancelMigrateBackToDefaultNetworkTimer();
3288     return;
3289   }
3290 
3291   retry_migrate_back_count_++;
3292   migrate_back_to_default_timer_.Start(
3293       FROM_HERE, timeout,
3294       base::BindOnce(
3295           &QuicChromiumClientSession::MaybeRetryMigrateBackToDefaultNetwork,
3296           weak_factory_.GetWeakPtr()));
3297 }
3298 
MaybeRetryMigrateBackToDefaultNetwork()3299 void QuicChromiumClientSession::MaybeRetryMigrateBackToDefaultNetwork() {
3300   base::TimeDelta retry_migrate_back_timeout =
3301       base::Seconds(UINT64_C(1) << retry_migrate_back_count_);
3302   if (pending_migrate_session_on_write_error_) {
3303     StartMigrateBackToDefaultNetworkTimer(base::TimeDelta());
3304     return;
3305   }
3306   if (default_network_ == GetCurrentNetwork()) {
3307     // If session has been back on the default already by other direct
3308     // migration attempt, cancel migrate back now.
3309     CancelMigrateBackToDefaultNetworkTimer();
3310     return;
3311   }
3312   if (retry_migrate_back_timeout > max_time_on_non_default_network_) {
3313     // Mark session as going away to accept no more streams.
3314     NotifyFactoryOfSessionGoingAway();
3315     return;
3316   }
3317   TryMigrateBackToDefaultNetwork(retry_migrate_back_timeout);
3318 }
3319 
CheckIdleTimeExceedsIdleMigrationPeriod()3320 bool QuicChromiumClientSession::CheckIdleTimeExceedsIdleMigrationPeriod() {
3321   if (!migrate_idle_session_) {
3322     return false;
3323   }
3324 
3325   if (HasActiveRequestStreams()) {
3326     return false;
3327   }
3328 
3329   // There are no active/drainning streams, check the last stream's finish time.
3330   if (tick_clock_->NowTicks() - most_recent_stream_close_time_ <
3331       idle_migration_period_) {
3332     // Still within the idle migration period.
3333     return false;
3334   }
3335 
3336   HistogramAndLogMigrationFailure(MIGRATION_STATUS_IDLE_MIGRATION_TIMEOUT,
3337                                   connection_id(),
3338                                   "Ilde migration period exceeded");
3339   CloseSessionOnErrorLater(ERR_NETWORK_CHANGED, quic::QUIC_NETWORK_IDLE_TIMEOUT,
3340                            quic::ConnectionCloseBehavior::SILENT_CLOSE);
3341   return true;
3342 }
3343 
ResetNonMigratableStreams()3344 void QuicChromiumClientSession::ResetNonMigratableStreams() {
3345   // TODO(zhongyi): may close non-migratable draining streams as well to avoid
3346   // sending additional data on alternate networks.
3347   PerformActionOnActiveStreams([](quic::QuicStream* stream) {
3348     QuicChromiumClientStream* chrome_stream =
3349         static_cast<QuicChromiumClientStream*>(stream);
3350     if (!chrome_stream->can_migrate_to_cellular_network()) {
3351       // Close the stream in both direction by resetting the stream.
3352       // TODO(zhongyi): use a different error code to reset streams for
3353       // connection migration.
3354       chrome_stream->Reset(quic::QUIC_STREAM_CANCELLED);
3355     }
3356     return true;
3357   });
3358 }
3359 
LogMetricsOnNetworkDisconnected()3360 void QuicChromiumClientSession::LogMetricsOnNetworkDisconnected() {
3361   if (most_recent_path_degrading_timestamp_ != base::TimeTicks()) {
3362     most_recent_network_disconnected_timestamp_ = tick_clock_->NowTicks();
3363     base::TimeDelta degrading_duration =
3364         most_recent_network_disconnected_timestamp_ -
3365         most_recent_path_degrading_timestamp_;
3366     UMA_HISTOGRAM_CUSTOM_TIMES(
3367         "Net.QuicNetworkDegradingDurationTillDisconnected", degrading_duration,
3368         base::Milliseconds(1), base::Minutes(10), 100);
3369   }
3370   if (most_recent_write_error_timestamp_ != base::TimeTicks()) {
3371     base::TimeDelta write_error_to_disconnection_gap =
3372         most_recent_network_disconnected_timestamp_ -
3373         most_recent_write_error_timestamp_;
3374     UMA_HISTOGRAM_CUSTOM_TIMES(
3375         "Net.QuicNetworkGapBetweenWriteErrorAndDisconnection",
3376         write_error_to_disconnection_gap, base::Milliseconds(1),
3377         base::Minutes(10), 100);
3378     base::UmaHistogramSparse("Net.QuicSession.WriteError.NetworkDisconnected",
3379                              -most_recent_write_error_);
3380     most_recent_write_error_ = 0;
3381     most_recent_write_error_timestamp_ = base::TimeTicks();
3382   }
3383 }
3384 
LogMetricsOnNetworkMadeDefault()3385 void QuicChromiumClientSession::LogMetricsOnNetworkMadeDefault() {
3386   if (most_recent_path_degrading_timestamp_ != base::TimeTicks()) {
3387     if (most_recent_network_disconnected_timestamp_ != base::TimeTicks()) {
3388       // NetworkDiscconected happens before NetworkMadeDefault, the platform
3389       // is dropping WiFi.
3390       base::TimeTicks now = tick_clock_->NowTicks();
3391       base::TimeDelta disconnection_duration =
3392           now - most_recent_network_disconnected_timestamp_;
3393       base::TimeDelta degrading_duration =
3394           now - most_recent_path_degrading_timestamp_;
3395       UMA_HISTOGRAM_CUSTOM_TIMES("Net.QuicNetworkDisconnectionDuration",
3396                                  disconnection_duration, base::Milliseconds(1),
3397                                  base::Minutes(10), 100);
3398       UMA_HISTOGRAM_CUSTOM_TIMES(
3399           "Net.QuicNetworkDegradingDurationTillNewNetworkMadeDefault",
3400           degrading_duration, base::Milliseconds(1), base::Minutes(10), 100);
3401       most_recent_network_disconnected_timestamp_ = base::TimeTicks();
3402     }
3403     most_recent_path_degrading_timestamp_ = base::TimeTicks();
3404   }
3405 }
3406 
LogMigrationResultToHistogram(QuicConnectionMigrationStatus status)3407 void QuicChromiumClientSession::LogMigrationResultToHistogram(
3408     QuicConnectionMigrationStatus status) {
3409   if (current_migration_cause_ == CHANGE_PORT_ON_PATH_DEGRADING) {
3410     UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.PortMigration", status,
3411                               MIGRATION_STATUS_MAX);
3412     current_migration_cause_ = UNKNOWN_CAUSE;
3413     return;
3414   }
3415 
3416   if (current_migration_cause_ == ON_SERVER_PREFERRED_ADDRESS_AVAILABLE) {
3417     UMA_HISTOGRAM_ENUMERATION(
3418         "Net.QuicSession.OnServerPreferredAddressAvailable", status,
3419         MIGRATION_STATUS_MAX);
3420     current_migration_cause_ = UNKNOWN_CAUSE;
3421     return;
3422   }
3423 
3424   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionMigration", status,
3425                             MIGRATION_STATUS_MAX);
3426 
3427   // Log the connection migraiton result to different histograms based on the
3428   // cause of the connection migration.
3429   std::string histogram_name = "Net.QuicSession.ConnectionMigration." +
3430                                MigrationCauseToString(current_migration_cause_);
3431   base::UmaHistogramEnumeration(histogram_name, status, MIGRATION_STATUS_MAX);
3432   current_migration_cause_ = UNKNOWN_CAUSE;
3433 }
3434 
LogHandshakeStatusOnMigrationSignal() const3435 void QuicChromiumClientSession::LogHandshakeStatusOnMigrationSignal() const {
3436   if (current_migration_cause_ == CHANGE_PORT_ON_PATH_DEGRADING) {
3437     UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.HandshakeStatusOnPortMigration",
3438                           OneRttKeysAvailable());
3439     return;
3440   }
3441 
3442   if (current_migration_cause_ == ON_SERVER_PREFERRED_ADDRESS_AVAILABLE) {
3443     UMA_HISTOGRAM_BOOLEAN(
3444         "Net.QuicSession.HandshakeStatusOnMigratingToServerPreferredAddress",
3445         OneRttKeysAvailable());
3446     return;
3447   }
3448 
3449   UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.HandshakeStatusOnConnectionMigration",
3450                         OneRttKeysAvailable());
3451 
3452   const std::string histogram_name =
3453       "Net.QuicSession.HandshakeStatusOnConnectionMigration." +
3454       MigrationCauseToString(current_migration_cause_);
3455   STATIC_HISTOGRAM_POINTER_GROUP(
3456       histogram_name, current_migration_cause_, MIGRATION_CAUSE_MAX,
3457       AddBoolean(OneRttKeysAvailable()),
3458       base::BooleanHistogram::FactoryGet(
3459           histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag));
3460 }
3461 
HistogramAndLogMigrationFailure(QuicConnectionMigrationStatus status,quic::QuicConnectionId connection_id,const char * reason)3462 void QuicChromiumClientSession::HistogramAndLogMigrationFailure(
3463     QuicConnectionMigrationStatus status,
3464     quic::QuicConnectionId connection_id,
3465     const char* reason) {
3466   NetLogEventType event_type =
3467       NetLogEventType::QUIC_CONNECTION_MIGRATION_FAILURE;
3468   if (current_migration_cause_ == CHANGE_PORT_ON_PATH_DEGRADING) {
3469     event_type = NetLogEventType::QUIC_PORT_MIGRATION_FAILURE;
3470   } else if (current_migration_cause_ ==
3471              ON_SERVER_PREFERRED_ADDRESS_AVAILABLE) {
3472     event_type =
3473         NetLogEventType::QUIC_FAILED_TO_VALIDATE_SERVER_PREFERRED_ADDRESS;
3474   }
3475 
3476   net_log_.AddEvent(event_type, [&] {
3477     return NetLogQuicMigrationFailureParams(connection_id, reason);
3478   });
3479 
3480   // |current_migration_cause_| will be reset afterwards.
3481   LogMigrationResultToHistogram(status);
3482 }
3483 
HistogramAndLogMigrationSuccess(quic::QuicConnectionId connection_id)3484 void QuicChromiumClientSession::HistogramAndLogMigrationSuccess(
3485     quic::QuicConnectionId connection_id) {
3486   NetLogEventType event_type =
3487       NetLogEventType::QUIC_CONNECTION_MIGRATION_SUCCESS;
3488   if (current_migration_cause_ == CHANGE_PORT_ON_PATH_DEGRADING) {
3489     event_type = NetLogEventType::QUIC_PORT_MIGRATION_SUCCESS;
3490   } else if (current_migration_cause_ ==
3491              ON_SERVER_PREFERRED_ADDRESS_AVAILABLE) {
3492     event_type =
3493         NetLogEventType::QUIC_SUCCESSFULLY_MIGRATED_TO_SERVER_PREFERRED_ADDRESS;
3494   }
3495 
3496   net_log_.AddEvent(event_type, [&] {
3497     return NetLogQuicMigrationSuccessParams(connection_id);
3498   });
3499 
3500   // |current_migration_cause_| will be reset afterwards.
3501   LogMigrationResultToHistogram(MIGRATION_STATUS_SUCCESS);
3502 }
3503 
GetInfoAsValue(const std::set<HostPortPair> & aliases)3504 base::Value::Dict QuicChromiumClientSession::GetInfoAsValue(
3505     const std::set<HostPortPair>& aliases) {
3506   base::Value::Dict dict;
3507   dict.Set("version", ParsedQuicVersionToString(connection()->version()));
3508   dict.Set("open_streams", static_cast<int>(GetNumActiveStreams()));
3509 
3510   base::Value::List stream_list;
3511   auto* stream_list_ptr = &stream_list;
3512 
3513   PerformActionOnActiveStreams([stream_list_ptr](quic::QuicStream* stream) {
3514     stream_list_ptr->Append(base::NumberToString(stream->id()));
3515     return true;
3516   });
3517 
3518   dict.Set("active_streams", std::move(stream_list));
3519 
3520   dict.Set("total_streams", static_cast<int>(num_total_streams_));
3521   dict.Set("peer_address", peer_address().ToString());
3522   dict.Set("network_anonymization_key",
3523            session_key_.network_anonymization_key().ToDebugString());
3524   dict.Set("connection_id", connection_id().ToString());
3525   if (!connection()->client_connection_id().IsEmpty()) {
3526     dict.Set("client_connection_id",
3527              connection()->client_connection_id().ToString());
3528   }
3529   dict.Set("connected", connection()->connected());
3530   const quic::QuicConnectionStats& stats = connection()->GetStats();
3531   dict.Set("packets_sent", static_cast<int>(stats.packets_sent));
3532   dict.Set("packets_received", static_cast<int>(stats.packets_received));
3533   dict.Set("packets_lost", static_cast<int>(stats.packets_lost));
3534   SSLInfo ssl_info;
3535 
3536   base::Value::List alias_list;
3537   for (const auto& alias : aliases) {
3538     alias_list.Append(alias.ToString());
3539   }
3540   dict.Set("aliases", std::move(alias_list));
3541 
3542   return dict;
3543 }
3544 
gquic_zero_rtt_disabled() const3545 bool QuicChromiumClientSession::gquic_zero_rtt_disabled() const {
3546   if (!session_pool_) {
3547     return false;
3548   }
3549   return session_pool_->gquic_zero_rtt_disabled();
3550 }
3551 
3552 std::unique_ptr<QuicChromiumClientSession::Handle>
CreateHandle(url::SchemeHostPort destination)3553 QuicChromiumClientSession::CreateHandle(url::SchemeHostPort destination) {
3554   return std::make_unique<QuicChromiumClientSession::Handle>(
3555       weak_factory_.GetWeakPtr(), std::move(destination));
3556 }
3557 
OnReadError(int result,const DatagramClientSocket * socket)3558 bool QuicChromiumClientSession::OnReadError(
3559     int result,
3560     const DatagramClientSocket* socket) {
3561   DCHECK(socket != nullptr);
3562   base::UmaHistogramSparse("Net.QuicSession.ReadError.AnyNetwork", -result);
3563   if (socket != GetDefaultSocket()) {
3564     DVLOG(1) << "Ignoring read error " << ErrorToString(result)
3565              << " on old socket";
3566     base::UmaHistogramSparse("Net.QuicSession.ReadError.OtherNetworks",
3567                              -result);
3568     // Ignore read errors from sockets that are not affecting the current
3569     // network, i.e., sockets that are no longer active and probing socket.
3570     // TODO(jri): Maybe clean up old sockets on error.
3571     return false;
3572   }
3573 
3574   if (ignore_read_error_) {
3575     DVLOG(1) << "Ignoring read error " << ErrorToString(result)
3576              << " during pending migration";
3577     // Ignore read errors during pending migration. Connection will be closed if
3578     // pending migration failed or timed out.
3579     base::UmaHistogramSparse("Net.QuicSession.ReadError.PendingMigration",
3580                              -result);
3581     return false;
3582   }
3583 
3584   base::UmaHistogramSparse("Net.QuicSession.ReadError.CurrentNetwork", -result);
3585   if (OneRttKeysAvailable()) {
3586     base::UmaHistogramSparse(
3587         "Net.QuicSession.ReadError.CurrentNetwork.HandshakeConfirmed", -result);
3588   }
3589 
3590   DVLOG(1) << "Closing session on read error " << ErrorToString(result);
3591   connection()->CloseConnection(quic::QUIC_PACKET_READ_ERROR,
3592                                 ErrorToString(result),
3593                                 quic::ConnectionCloseBehavior::SILENT_CLOSE);
3594   return false;
3595 }
3596 
OnPacket(const quic::QuicReceivedPacket & packet,const quic::QuicSocketAddress & local_address,const quic::QuicSocketAddress & peer_address)3597 bool QuicChromiumClientSession::OnPacket(
3598     const quic::QuicReceivedPacket& packet,
3599     const quic::QuicSocketAddress& local_address,
3600     const quic::QuicSocketAddress& peer_address) {
3601   ProcessUdpPacket(local_address, peer_address, packet);
3602   uint8_t new_incoming_ecn =
3603       (0x1 << static_cast<uint8_t>(packet.ecn_codepoint()));
3604   if (new_incoming_ecn != observed_incoming_ecn_ &&
3605       incoming_packets_before_ecn_transition_ > 0) {
3606     observed_ecn_transition_ = true;
3607   }
3608   if (!observed_ecn_transition_) {
3609     ++incoming_packets_before_ecn_transition_;
3610   }
3611   observed_incoming_ecn_ |= new_incoming_ecn;
3612   if (!connection()->connected()) {
3613     NotifyFactoryOfSessionClosedLater();
3614     return false;
3615   }
3616   return true;
3617 }
3618 
NotifyFactoryOfSessionGoingAway()3619 void QuicChromiumClientSession::NotifyFactoryOfSessionGoingAway() {
3620   going_away_ = true;
3621   if (session_pool_) {
3622     session_pool_->OnSessionGoingAway(this);
3623   }
3624 }
3625 
NotifyFactoryOfSessionClosedLater()3626 void QuicChromiumClientSession::NotifyFactoryOfSessionClosedLater() {
3627   going_away_ = true;
3628   DCHECK_EQ(0u, GetNumActiveStreams());
3629   DCHECK(!connection()->connected());
3630   task_runner_->PostTask(
3631       FROM_HERE,
3632       base::BindOnce(&QuicChromiumClientSession::NotifyFactoryOfSessionClosed,
3633                      weak_factory_.GetWeakPtr()));
3634 }
3635 
NotifyFactoryOfSessionClosed()3636 void QuicChromiumClientSession::NotifyFactoryOfSessionClosed() {
3637   going_away_ = true;
3638   DCHECK_EQ(0u, GetNumActiveStreams());
3639   // Will delete |this|.
3640   if (session_pool_) {
3641     session_pool_->OnSessionClosed(this);
3642   }
3643 }
3644 
OnCryptoHandshakeComplete()3645 void QuicChromiumClientSession::OnCryptoHandshakeComplete() {
3646   if (session_pool_) {
3647     session_pool_->set_is_quic_known_to_work_on_current_network(true);
3648   }
3649 
3650   // Update |connect_end| only when handshake is confirmed. This should also
3651   // take care of any failed 0-RTT request.
3652   connect_timing_.connect_end = tick_clock_->NowTicks();
3653   DCHECK_LE(connect_timing_.connect_start, connect_timing_.connect_end);
3654   base::TimeDelta handshake_confirmed_time =
3655       connect_timing_.connect_end - connect_timing_.connect_start;
3656   UMA_HISTOGRAM_TIMES("Net.QuicSession.HandshakeConfirmedTime",
3657                       handshake_confirmed_time);
3658 
3659   // Also record the handshake time when ECH was advertised in DNS. The ECH
3660   // experiment does not change DNS behavior, so this measures the same servers
3661   // in both experiment and control groups.
3662   if (!ech_config_list_.empty()) {
3663     UMA_HISTOGRAM_TIMES("Net.QuicSession.HandshakeConfirmedTime.ECH",
3664                         handshake_confirmed_time);
3665   }
3666 
3667   // Track how long it has taken to finish handshake after we have finished
3668   // DNS host resolution.
3669   if (!connect_timing_.domain_lookup_end.is_null()) {
3670     UMA_HISTOGRAM_TIMES(
3671         "Net.QuicSession.HostResolution.HandshakeConfirmedTime",
3672         tick_clock_->NowTicks() - connect_timing_.domain_lookup_end);
3673   }
3674 
3675   auto it = handles_.begin();
3676   while (it != handles_.end()) {
3677     Handle* handle = *it;
3678     ++it;
3679     handle->OnCryptoHandshakeConfirmed();
3680   }
3681 
3682   NotifyRequestsOfConfirmation(OK);
3683   // Attempt to migrate back to the default network after handshake has been
3684   // confirmed if the session is not created on the default network.
3685   if (migrate_session_on_network_change_v2_ &&
3686       default_network_ != handles::kInvalidNetworkHandle &&
3687       GetCurrentNetwork() != default_network_) {
3688     current_migration_cause_ = ON_MIGRATE_BACK_TO_DEFAULT_NETWORK;
3689     StartMigrateBackToDefaultNetworkTimer(
3690         base::Seconds(kMinRetryTimeForDefaultNetworkSecs));
3691   }
3692 }
3693 
Migrate(handles::NetworkHandle network,IPEndPoint peer_address,bool close_session_on_error,MigrationCallback migration_callback)3694 void QuicChromiumClientSession::Migrate(handles::NetworkHandle network,
3695                                         IPEndPoint peer_address,
3696                                         bool close_session_on_error,
3697                                         MigrationCallback migration_callback) {
3698   quic_connection_migration_attempted_ = true;
3699   quic_connection_migration_successful_ = false;
3700   if (!session_pool_) {
3701     task_runner_->PostTask(
3702         FROM_HERE,
3703         base::BindOnce(&QuicChromiumClientSession::DoMigrationCallback,
3704                        weak_factory_.GetWeakPtr(),
3705                        std::move(migration_callback),
3706                        MigrationResult::FAILURE));
3707     return;
3708   }
3709 
3710   if (network != handles::kInvalidNetworkHandle) {
3711     // This is a migration attempt from connection migration.
3712     ResetNonMigratableStreams();
3713     if (!migrate_idle_session_ && !HasActiveRequestStreams()) {
3714       task_runner_->PostTask(
3715           FROM_HERE,
3716           base::BindOnce(&QuicChromiumClientSession::DoMigrationCallback,
3717                          weak_factory_.GetWeakPtr(),
3718                          std::move(migration_callback),
3719                          MigrationResult::FAILURE));
3720       // If idle sessions can not be migrated, close the session if needed.
3721       if (close_session_on_error) {
3722         CloseSessionOnErrorLater(
3723             ERR_NETWORK_CHANGED,
3724             quic::QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS,
3725             quic::ConnectionCloseBehavior::SILENT_CLOSE);
3726       }
3727       return;
3728     }
3729   }
3730 
3731   // Create and configure socket on |network|.
3732   std::unique_ptr<DatagramClientSocket> socket(
3733       session_pool_->CreateSocket(net_log_.net_log(), net_log_.source()));
3734   DatagramClientSocket* socket_ptr = socket.get();
3735   DVLOG(1) << "Force blocking the packet writer";
3736   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
3737       ->set_force_write_blocked(true);
3738   if (base::FeatureList::IsEnabled(features::kDisableBlackholeOnNoNewNetwork)) {
3739     // Turn off the black hole detector since the writer is blocked.
3740     // Blackhole will be re-enabled once a packet is sent again.
3741     connection()->blackhole_detector().StopDetection(false);
3742   }
3743   CompletionOnceCallback connect_callback = base::BindOnce(
3744       &QuicChromiumClientSession::FinishMigrate, weak_factory_.GetWeakPtr(),
3745       std::move(socket), peer_address, close_session_on_error,
3746       std::move(migration_callback));
3747 
3748   if (!MidMigrationCallbackForTesting().is_null()) {
3749     std::move(MidMigrationCallbackForTesting()).Run();  // IN-TEST
3750   }
3751 
3752   session_pool_->ConnectAndConfigureSocket(std::move(connect_callback),
3753                                            socket_ptr, peer_address, network,
3754                                            session_key_.socket_tag());
3755 }
3756 
FinishMigrate(std::unique_ptr<DatagramClientSocket> socket,IPEndPoint peer_address,bool close_session_on_error,MigrationCallback callback,int rv)3757 void QuicChromiumClientSession::FinishMigrate(
3758     std::unique_ptr<DatagramClientSocket> socket,
3759     IPEndPoint peer_address,
3760     bool close_session_on_error,
3761     MigrationCallback callback,
3762     int rv) {
3763   if (rv != OK) {
3764     HistogramAndLogMigrationFailure(MIGRATION_STATUS_INTERNAL_ERROR,
3765                                     connection_id(),
3766                                     "Socket configuration failed");
3767     static_cast<QuicChromiumPacketWriter*>(connection()->writer())
3768         ->set_force_write_blocked(false);
3769     task_runner_->PostTask(
3770         FROM_HERE,
3771         base::BindOnce(&QuicChromiumClientSession::DoMigrationCallback,
3772                        weak_factory_.GetWeakPtr(), std::move(callback),
3773                        MigrationResult::FAILURE));
3774     if (close_session_on_error) {
3775       CloseSessionOnErrorLater(ERR_NETWORK_CHANGED,
3776                                quic::QUIC_CONNECTION_MIGRATION_INTERNAL_ERROR,
3777                                quic::ConnectionCloseBehavior::SILENT_CLOSE);
3778     }
3779     return;
3780   }
3781 
3782   // Create new packet reader and writer on the new socket.
3783   auto new_reader = std::make_unique<QuicChromiumPacketReader>(
3784       std::move(socket), clock_, this, yield_after_packets_,
3785       yield_after_duration_, net_log_);
3786   new_reader->StartReading();
3787   auto new_writer = std::make_unique<QuicChromiumPacketWriter>(
3788       new_reader->socket(), task_runner_);
3789 
3790   static_cast<QuicChromiumPacketWriter*>(connection()->writer())
3791       ->set_delegate(nullptr);
3792   new_writer->set_delegate(this);
3793 
3794   IPEndPoint self_address;
3795   new_reader->socket()->GetLocalAddress(&self_address);
3796   // Migrate to the new socket.
3797   if (!MigrateToSocket(ToQuicSocketAddress(self_address),
3798                        ToQuicSocketAddress(peer_address), std::move(new_reader),
3799                        std::move(new_writer))) {
3800     task_runner_->PostTask(
3801         FROM_HERE,
3802         base::BindOnce(&QuicChromiumClientSession::DoMigrationCallback,
3803                        weak_factory_.GetWeakPtr(), std::move(callback),
3804                        MigrationResult::FAILURE));
3805     if (close_session_on_error) {
3806       CloseSessionOnErrorLater(ERR_NETWORK_CHANGED,
3807                                quic::QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES,
3808                                quic::ConnectionCloseBehavior::SILENT_CLOSE);
3809     }
3810     return;
3811   }
3812   quic_connection_migration_successful_ = true;
3813   HistogramAndLogMigrationSuccess(connection_id());
3814   task_runner_->PostTask(
3815       FROM_HERE, base::BindOnce(&QuicChromiumClientSession::DoMigrationCallback,
3816                                 weak_factory_.GetWeakPtr(), std::move(callback),
3817                                 MigrationResult::SUCCESS));
3818 }
3819 
DoMigrationCallback(MigrationCallback callback,MigrationResult rv)3820 void QuicChromiumClientSession::DoMigrationCallback(MigrationCallback callback,
3821                                                     MigrationResult rv) {
3822   std::move(callback).Run(rv);
3823 }
3824 
MigrateToSocket(const quic::QuicSocketAddress & self_address,const quic::QuicSocketAddress & peer_address,std::unique_ptr<QuicChromiumPacketReader> reader,std::unique_ptr<QuicChromiumPacketWriter> writer)3825 bool QuicChromiumClientSession::MigrateToSocket(
3826     const quic::QuicSocketAddress& self_address,
3827     const quic::QuicSocketAddress& peer_address,
3828     std::unique_ptr<QuicChromiumPacketReader> reader,
3829     std::unique_ptr<QuicChromiumPacketWriter> writer) {
3830   // TODO(zhongyi): figure out whether we want to limit the number of
3831   // connection migrations for v2, which includes migration on platform signals,
3832   // write error events, and path degrading on original network.
3833   if (!migrate_session_on_network_change_v2_ &&
3834       packet_readers_.size() >= kMaxReadersPerQuicSession) {
3835     HistogramAndLogMigrationFailure(MIGRATION_STATUS_TOO_MANY_CHANGES,
3836                                     connection_id(), "Too many changes");
3837     return false;
3838   }
3839 
3840   packet_readers_.push_back(std::move(reader));
3841   // Force the writer to be blocked to prevent it being used until
3842   // WriteToNewSocket completes.
3843   DVLOG(1) << "Force blocking the packet writer";
3844   writer->set_force_write_blocked(true);
3845   if (!MigratePath(self_address, peer_address, writer.release(),
3846                    /*owns_writer=*/true)) {
3847     HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_UNUSED_CONNECTION_ID,
3848                                     connection_id(),
3849                                     "No unused server connection ID");
3850     DVLOG(1) << "MigratePath fails as there is no CID available";
3851     return false;
3852   }
3853   // Post task to write the pending packet or a PING packet to the new
3854   // socket. This avoids reentrancy issues if there is a write error
3855   // on the write to the new socket.
3856   task_runner_->PostTask(
3857       FROM_HERE, base::BindOnce(&QuicChromiumClientSession::WriteToNewSocket,
3858                                 weak_factory_.GetWeakPtr()));
3859   return true;
3860 }
3861 
PopulateNetErrorDetails(NetErrorDetails * details) const3862 void QuicChromiumClientSession::PopulateNetErrorDetails(
3863     NetErrorDetails* details) const {
3864   details->quic_port_migration_detected = port_migration_detected_;
3865   details->quic_connection_error = error();
3866   details->quic_connection_migration_attempted =
3867       quic_connection_migration_attempted_;
3868   details->quic_connection_migration_successful =
3869       quic_connection_migration_successful_;
3870 }
3871 
GetDefaultSocket() const3872 const DatagramClientSocket* QuicChromiumClientSession::GetDefaultSocket()
3873     const {
3874   DCHECK(packet_readers_.back()->socket() != nullptr);
3875   // The most recently added socket is the currently active one.
3876   return packet_readers_.back()->socket();
3877 }
3878 
GetCurrentNetwork() const3879 handles::NetworkHandle QuicChromiumClientSession::GetCurrentNetwork() const {
3880   // If connection migration is enabled, alternate network interface may be
3881   // used to send packet, it is identified as the bound network of the default
3882   // socket. Otherwise, always use |default_network_|.
3883   return migrate_session_on_network_change_v2_
3884              ? GetDefaultSocket()->GetBoundNetwork()
3885              : default_network_;
3886 }
3887 
OnServerPreferredAddressAvailable(const quic::QuicSocketAddress & server_preferred_address)3888 void QuicChromiumClientSession::OnServerPreferredAddressAvailable(
3889     const quic::QuicSocketAddress& server_preferred_address) {
3890   current_migration_cause_ = ON_SERVER_PREFERRED_ADDRESS_AVAILABLE;
3891 
3892   net_log_.BeginEvent(
3893       NetLogEventType::QUIC_ON_SERVER_PREFERRED_ADDRESS_AVAILABLE);
3894 
3895   if (!session_pool_) {
3896     return;
3897   }
3898 
3899   StartProbing(base::DoNothingAs<void(ProbingResult)>(), default_network_,
3900                server_preferred_address);
3901   net_log_.EndEvent(
3902       NetLogEventType::QUIC_START_VALIDATING_SERVER_PREFERRED_ADDRESS);
3903 }
3904 
3905 const LoadTimingInfo::ConnectTiming&
GetConnectTiming()3906 QuicChromiumClientSession::GetConnectTiming() {
3907   connect_timing_.ssl_start = connect_timing_.connect_start;
3908   connect_timing_.ssl_end = connect_timing_.connect_end;
3909   return connect_timing_;
3910 }
3911 
GetQuicVersion() const3912 quic::ParsedQuicVersion QuicChromiumClientSession::GetQuicVersion() const {
3913   return connection()->version();
3914 }
3915 
3916 const std::set<std::string>&
GetDnsAliasesForSessionKey(const QuicSessionKey & key) const3917 QuicChromiumClientSession::GetDnsAliasesForSessionKey(
3918     const QuicSessionKey& key) const {
3919   static const base::NoDestructor<std::set<std::string>> emptyset_result;
3920   return session_pool_ ? session_pool_->GetDnsAliasesForSessionKey(key)
3921                        : *emptyset_result;
3922 }
3923 
3924 quic::QuicPacketLength
GetGuaranteedLargestMessagePayload() const3925 QuicChromiumClientSession::Handle::GetGuaranteedLargestMessagePayload() const {
3926   if (!session_) {
3927     return 0;
3928   }
3929   return session_->GetGuaranteedLargestMessagePayload();
3930 }
3931 
3932 #if BUILDFLAG(ENABLE_WEBSOCKETS)
3933 std::unique_ptr<WebSocketQuicStreamAdapter>
CreateWebSocketQuicStreamAdapterImpl(WebSocketQuicStreamAdapter::Delegate * delegate)3934 QuicChromiumClientSession::CreateWebSocketQuicStreamAdapterImpl(
3935     WebSocketQuicStreamAdapter::Delegate* delegate) {
3936   DCHECK(connection()->connected());
3937   DCHECK(CanOpenNextOutgoingBidirectionalStream());
3938   auto websocket_quic_spdy_stream = std::make_unique<WebSocketQuicSpdyStream>(
3939       GetNextOutgoingBidirectionalStreamId(), this, quic::BIDIRECTIONAL);
3940 
3941   auto adapter = std::make_unique<WebSocketQuicStreamAdapter>(
3942       websocket_quic_spdy_stream.get(), delegate);
3943   ActivateStream(std::move(websocket_quic_spdy_stream));
3944 
3945   ++num_total_streams_;
3946   return adapter;
3947 }
3948 
3949 std::unique_ptr<WebSocketQuicStreamAdapter>
CreateWebSocketQuicStreamAdapter(WebSocketQuicStreamAdapter::Delegate * delegate,base::OnceCallback<void (std::unique_ptr<WebSocketQuicStreamAdapter>)> callback,StreamRequest * stream_request)3950 QuicChromiumClientSession::CreateWebSocketQuicStreamAdapter(
3951     WebSocketQuicStreamAdapter::Delegate* delegate,
3952     base::OnceCallback<void(std::unique_ptr<WebSocketQuicStreamAdapter>)>
3953         callback,
3954     StreamRequest* stream_request) {
3955   DCHECK(connection()->connected());
3956   if (!CanOpenNextOutgoingBidirectionalStream()) {
3957     stream_request->pending_start_time_ = tick_clock_->NowTicks();
3958     stream_request->for_websockets_ = true;
3959     stream_request->websocket_adapter_delegate_ = delegate;
3960     stream_request->start_websocket_callback_ = std::move(callback);
3961 
3962     stream_requests_.push_back(stream_request);
3963     UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumPendingStreamRequests",
3964                               stream_requests_.size());
3965     return nullptr;
3966   }
3967 
3968   return CreateWebSocketQuicStreamAdapterImpl(delegate);
3969 }
3970 #endif  // BUILDFLAG(ENABLE_WEBSOCKETS)
3971 
3972 }  // namespace net
3973