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