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