| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_HTTP_HTTP_STREAM_POOL_ATTEMPT_MANAGER_H_ |
| #define NET_HTTP_HTTP_STREAM_POOL_ATTEMPT_MANAGER_H_ |
| |
| #include <memory> |
| #include <optional> |
| #include <set> |
| #include <vector> |
| |
| #include "base/containers/flat_set.h" |
| #include "base/containers/unique_ptr_adapters.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "base/trace_event/trace_event.h" |
| #include "base/types/expected.h" |
| #include "net/base/completion_once_callback.h" |
| #include "net/base/ip_endpoint.h" |
| #include "net/base/load_states.h" |
| #include "net/base/load_timing_info.h" |
| #include "net/base/load_timing_internal_info.h" |
| #include "net/base/net_error_details.h" |
| #include "net/base/net_export.h" |
| #include "net/base/priority_queue.h" |
| #include "net/base/request_priority.h" |
| #include "net/dns/host_resolver.h" |
| #include "net/dns/public/resolve_error_info.h" |
| #include "net/http/http_stream_pool.h" |
| #include "net/http/http_stream_pool_ip_endpoint_state_tracker.h" |
| #include "net/http/http_stream_pool_job.h" |
| #include "net/http/http_stream_request.h" |
| #include "net/log/net_log_with_source.h" |
| #include "net/quic/quic_session_pool.h" |
| #include "net/socket/connection_attempts.h" |
| #include "net/socket/next_proto.h" |
| #include "net/socket/stream_attempt.h" |
| #include "net/socket/stream_socket_close_reason.h" |
| #include "net/socket/stream_socket_handle.h" |
| #include "net/socket/tls_stream_attempt.h" |
| #include "net/spdy/multiplexed_session_creation_initiator.h" |
| #include "net/ssl/ssl_cert_request_info.h" |
| #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" |
| |
| namespace net { |
| |
| class HttpNetworkSession; |
| class NetLog; |
| class HttpStreamKey; |
| |
| // Drives connection attempts for a single destination. |
| // |
| // Maintains multiple in-flight Jobs for a single destination keyed by |
| // HttpStreamKey. Peforms DNS resolution and manages connection attempts. |
| // Delegates QUIC connection attempts to QuicAttempt. Upon successful HttpStream |
| // creations or fatal error occurrence, notify jobs of success or failure. |
| // |
| // Created by an HttpStreamPool::Group when new connection attempts are needed |
| // and destroyed when all jobs, in-flight attempts, and the QuicAttempt are |
| // completed. |
| class HttpStreamPool::AttemptManager |
| : public HostResolver::ServiceEndpointRequest::Delegate, |
| public IPEndPointStateTracker::Delegate { |
| public: |
| // Represents the initial attempt state of this manager. |
| // These values are persisted to logs. Entries should not be renumbered and |
| // numeric values should never be reused. |
| // |
| // LINT.IfChange(InitialAttemptState) |
| enum class InitialAttemptState { |
| kOther = 0, |
| // CanUseQuic() && quic_version_.IsKnown() && !SupportsSpdy() |
| kCanUseQuicWithKnownVersion = 1, |
| // CanUseQuic() && quic_version_.IsKnown() && SupportsSpdy() |
| kCanUseQuicWithKnownVersionAndSupportsSpdy = 2, |
| // CanUseQuic() && !quic_version_.IsKnown() && !SupportsSpdy() |
| kCanUseQuicWithUnknownVersion = 3, |
| // CanUseQuic() && !quic_version_.IsKnown() && SupportsSpdy() |
| kCanUseQuicWithUnknownVersionAndSupportsSpdy = 4, |
| // !CanUseQuic() && quic_version_.IsKnown() && !SupportsSpdy() |
| kCannotUseQuicWithKnownVersion = 5, |
| // !CanUseQuic() && quic_version_.IsKnown() && SupportsSpdy() |
| kCannotUseQuicWithKnownVersionAndSupportsSpdy = 6, |
| // !CanUseQuic() && !quic_version_.IsKnown() && !SupportsSpdy() |
| kCannotUseQuicWithUnknownVersion = 7, |
| // !CanUseQuic() && !quic_version_.IsKnown() && SupportsSpdy() |
| kCannotUseQuicWithUnknownVersionAndSupportsSpdy = 8, |
| kMaxValue = kCannotUseQuicWithUnknownVersionAndSupportsSpdy, |
| }; |
| // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:HttpStreamPoolInitialAttemptState) |
| |
| // Time to delay connection attempts more than one when the destination is |
| // known to support HTTP/2, to avoid unnecessary socket connection |
| // establishments. See https://crbug.com/718576 |
| static constexpr base::TimeDelta kSpdyThrottleDelay = base::Milliseconds(300); |
| |
| // `group` must outlive `this`. |
| AttemptManager(Group* group, NetLog* net_log); |
| |
| AttemptManager(const AttemptManager&) = delete; |
| AttemptManager& operator=(const AttemptManager&) = delete; |
| |
| ~AttemptManager() override; |
| |
| const HttpStreamKey& stream_key() const; |
| |
| const SpdySessionKey& spdy_session_key() const; |
| |
| const QuicSessionAliasKey& quic_session_alias_key() const; |
| |
| HttpNetworkSession* http_network_session() const; |
| SpdySessionPool* spdy_session_pool() const; |
| QuicSessionPool* quic_session_pool() const; |
| |
| HttpStreamPool* pool(); |
| const HttpStreamPool* pool() const; |
| |
| Group* group() { return group_; } |
| |
| HostResolver::ServiceEndpointRequest* service_endpoint_request() { |
| return service_endpoint_request_.get(); |
| } |
| |
| const perfetto::Track& track() const { return track_; } |
| |
| std::optional<InitialAttemptState> initial_attempt_state() const { |
| return initial_attempt_state_; |
| } |
| |
| bool is_shutting_down() const { |
| return availability_state_ != AvailabilityState::kAvailable; |
| } |
| |
| int final_error_to_notify_jobs() const; |
| |
| base::TimeTicks dns_resolution_start_time() const { |
| return dns_resolution_start_time_; |
| } |
| |
| base::TimeTicks dns_resolution_end_time() const { |
| return dns_resolution_end_time_; |
| } |
| |
| NextProtoSet allowed_alpns() const { return allowed_alpns_; } |
| |
| const NetLogWithSource& net_log(); |
| |
| // Starts `job` for a stream request. Will call one of Job::Delegate methods |
| // to notify results. |
| void RequestStream(Job* job); |
| |
| // Creates idle streams or sessions for `num_streams` be opened. |
| // Note that `job` will be notified once `this` has enough streams/sessions |
| // for `num_streams` be opened. This means that when there are two preconnect |
| // requests with `num_streams = 1`, all jobs are notified when one |
| // stream/session is established (not two). |
| void Preconnect(Job* job); |
| |
| // HostResolver::ServiceEndpointRequest::Delegate implementation: |
| void OnServiceEndpointsUpdated() override; |
| void OnServiceEndpointRequestFinished(int rv) override; |
| |
| // IPEndPointStateTracker::Delegate implementation: |
| HostResolver::ServiceEndpointRequest* GetServiceEndpointRequest() override; |
| bool IsSvcbOptional() override; |
| bool HasEnoughTcpBasedAttemptsForSlowIPEndPoint( |
| const IPEndPoint& ip_endpoint) override; |
| bool IsEndpointUsableForTcpBasedAttempt(const ServiceEndpoint& endpoint, |
| bool svcb_optional) override; |
| |
| // Tries to process a single pending request/preconnect. |
| void ProcessPendingJob(); |
| |
| // Returns the number of request jobs that haven't yet been notified success |
| // or failure. |
| size_t RequestJobCount() const { return request_jobs_.size(); } |
| |
| // Returns the number of request jobs that have already been notified success |
| // or failure. |
| size_t NotifiedRequestJobCount() const { return notified_jobs_.size(); } |
| |
| // Returns the number of in-flight TCP based attempts. |
| size_t TcpBasedAttemptCount() const { return tcp_based_attempts_.size(); } |
| |
| // Cancels all in-flight TCP based attempts. |
| void CancelTcpBasedAttempts(StreamSocketCloseReason reason); |
| |
| // Called when `job` is going to be destroyed. |
| void OnJobComplete(Job* job); |
| |
| // Cancels all jobs. |
| void CancelJobs(int error); |
| |
| // Cancels the QuicAttempt if it exists. |
| void CancelQuicAttempt(int error); |
| |
| // Returns the current load state. |
| LoadState GetLoadState() const; |
| |
| // Called when the priority of `job` is set. |
| void SetJobPriority(Job* job, RequestPriority priority); |
| |
| // Returns the highest priority in `jobs_` when there is at least one job. |
| // Otherwise, returns IDLE assuming this manager is doing preconnects. |
| RequestPriority GetPriority() const; |
| |
| // Returns true when `this` is blocked by the pool's stream limit. |
| bool IsStalledByPoolLimit(); |
| |
| // Returns the SSLConfig to use for TLS connections, not incorporating any |
| // configuration based on the service endpoint. |
| SSLConfig GetBaseSSLConfig(); |
| |
| base::expected<ServiceEndpoint, TlsStreamAttempt::GetServiceEndpointError> |
| GetServiceEndpoint(const IPEndPoint& endpoint); |
| |
| void OnTcpBasedAttemptComplete(TcpBasedAttempt* raw_attempt, int rv); |
| void OnTcpBasedAttemptSlow(TcpBasedAttempt* raw_attempt); |
| |
| bool CanUseExistingQuicSession(); |
| |
| // Runs the TCP based attempt delay timer if TCP based attempts are blocked |
| // and the timer is not running. TcpBasedAttemptDelayBehavior specifies when |
| // this method is called. |
| void MaybeRunTcpBasedAttemptDelayTimer(); |
| |
| // Called when the QuicAttempt owned by `this` is completed. |
| void OnQuicAttemptComplete(QuicAttemptOutcome result); |
| |
| // Called when the QuicAttempt owned by `this` is slow. |
| void OnQuicAttemptSlow(); |
| |
| // Retrieves information on the current state of `this` as a base::Value. |
| base::Value::Dict GetInfoAsValue() const; |
| |
| base::Value::Dict GetStatesAsNetLogParams() const; |
| |
| MultiplexedSessionCreationInitiator |
| CalculateMultiplexedSessionCreationInitiator(); |
| |
| std::optional<int> GetQuicAttemptResultForTesting() { |
| return quic_attempt_result_; |
| } |
| |
| base::WeakPtr<AttemptManager> GetWeakPtrForTesting() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| QuicAttempt* quic_attempt_for_testing() const { return quic_attempt_.get(); } |
| |
| void SetOnCompleteCallbackForTesting(base::OnceClosure callback); |
| |
| private: |
| // Represents the availability of this instance. If not kAvailable, `this` |
| // can't handle new Jobs and this should not have in-flight attempts. |
| enum class AvailabilityState { |
| // Can handle new Jobs and make connection attempts. |
| kAvailable = 0, |
| // Is in preparation of a successful completion. |
| kDraining = 1, |
| // Is handling a fatal error. |
| kFailing = 2, |
| }; |
| |
| // Represents failure of connection attempts. Used to notify job of completion |
| // for failure cases. |
| enum class FailureKind { |
| kStreamFailed, |
| kCertifcateError, |
| kNeedsClientAuth, |
| }; |
| |
| // Represents reasons if future connection attempts could be blocked or not. |
| enum class CanAttemptResult { |
| kAttempt, |
| kNoPendingJob, |
| kBlockedTcpBasedAttempt, |
| kThrottledForSpdy, |
| kReachedGroupLimit, |
| kReachedPoolLimit, |
| }; |
| |
| // The state of TCP/TLS connection attempts. |
| enum class TcpBasedAttemptState { |
| kNotStarted, |
| kAttempting, |
| kSucceededAtLeastOnce, |
| kAllEndpointsFailed, |
| }; |
| |
| std::string_view InitialAttemptStateToString(InitialAttemptState state); |
| |
| using JobQueue = PriorityQueue<raw_ptr<Job>>; |
| |
| static std::string_view CanAttemptResultToString(CanAttemptResult result); |
| |
| static std::string_view TcpBasedAttemptStateToString( |
| TcpBasedAttemptState state); |
| |
| bool is_service_endpoint_request_finished() const { |
| return service_endpoint_request_finished_; |
| } |
| |
| void SetInitialAttemptState(); |
| InitialAttemptState CalculateInitialAttemptState(); |
| |
| bool UsingTls() const; |
| |
| void StartInternal(Job* job); |
| |
| void ResolveServiceEndpoint(RequestPriority initial_priority); |
| |
| // Helper methods to reset ServiceEndpointRequest later. |
| // TODO(crbug.com/421299722, crbug.com/397597592): Remove these helper |
| // methods and reset ServiceEndpointRequest without PostTask(). We need to |
| // update the HostResolver's object management first. See comment #8 of |
| // crbug.com/397597592. |
| void ResetServiceEndpointRequestLater(); |
| void ResetServiceEndpointRequest(); |
| |
| void RestrictAllowedProtocols(NextProtoSet allowed_alpns); |
| |
| void MaybeChangeServiceEndpointRequestPriority(); |
| |
| // Called when service endpoint results have changed or finished. |
| void ProcessServiceEndpointChanges(); |
| |
| // Returns an active QUIC session when there is an active QUIC session that |
| // can be used for on-going jobs after service endpoint results have changed. |
| QuicChromiumClientSession* CanUseExistingQuicSessionAfterEndpointChanges(); |
| |
| // Returns an active SPDY session when there is an active SPDY session that |
| // can be used for on-going jobs after service endpoint results have changed. |
| base::WeakPtr<SpdySession> CanUseExistingSpdySessionAfterEndpointChanges(); |
| |
| // If `this` is ready to start cryptographic handshakes, notifies TCP based |
| // attempts that SSLConfigs are ready. |
| void MaybeNotifySSLConfigReady(); |
| |
| // Attempts QUIC sessions if QUIC can be used and `this` is ready to start |
| // cryptographic connection handshakes. |
| void MaybeAttemptQuic(); |
| |
| // Attempts connections if there are pending jobs and IPEndPoints that |
| // haven't failed. If `exclude_ip_endpoint` is given, exclude the IPEndPoint |
| // from attempts. If `max_attempts` is given, attempts connections up to |
| // `max_attempts`. |
| void MaybeAttemptTcpBased( |
| std::optional<IPEndPoint> exclude_ip_endpoint = std::nullopt, |
| std::optional<size_t> max_attempts = std::nullopt); |
| |
| // Returns true if there are pending jobs and the pool and the group |
| // haven't reached stream limits. If the pool reached the stream limit, may |
| // close idle sockets in other groups. Also may cancel preconnects or trigger |
| // `spdy_throttle_timer_`. |
| bool IsTcpBasedAttemptReady(); |
| |
| // Actual implementation of IsConnectionAttemptReady(), without having side |
| // effects. |
| CanAttemptResult CanAttemptConnection() const; |
| |
| // Returns true only when there are no jobs that ignore the pool and group |
| // limits. |
| bool ShouldRespectLimits() const; |
| |
| // Returns true only when there are no jobs that disable IP based pooling for |
| // HTTP/2. Note that this does nothing with QUIC. |
| bool IsIpBasedPoolingEnabledForH2() const; |
| |
| // Returns true only when there are no jobs that disable alternative services. |
| bool IsAlternativeServiceEnabled() const; |
| |
| // Returns true when the destination is known to support HTTP/2. Note that |
| // this could return false while initializing HttpServerProperties. |
| bool SupportsSpdy() const; |
| |
| // Returns true when connection attempts should be throttled because there is |
| // an in-flight TCP based attempt and the destination is known to support |
| // HTTP/2. |
| bool ShouldThrottleAttemptForSpdy() const; |
| |
| // Calculates the maximum streams counts requested by preconnects. |
| size_t CalculateMaxPreconnectCount() const; |
| |
| // Calculates the number of TCP based attempts required to satisfy |
| // preconnects. |
| size_t CalculateRequiredTcpBasedAttemptForPreconnect() const; |
| |
| // Returns the number of TCP based attempts that are not considered as slow. |
| size_t NonSlowTcpBasedAttemptCount() const; |
| |
| // Returns a QUIC endpoint to make a connection attempt. See the comments in |
| // QuicSessionPool::SelectQuicVersion() for the criteria to select a QUIC |
| // endpoint. |
| std::optional<QuicEndpoint> GetQuicEndpointToAttempt(); |
| |
| // Called when this gets a fatal error. Notifies all jobs of the failure and |
| // cancels in-flight TCP based attempts and QuicAttempt's, if they exist. |
| void HandleFinalError(int error); |
| |
| // Calculate the failure kind to notify jobs of failure. Used to call one of |
| // the job's methods. |
| FailureKind DetermineFailureKind(); |
| |
| // Notifies a failure to a single request job. Used by NotifyFailure(). |
| void NotifyJobOfFailure(); |
| |
| // Notifies all preconnects of completion. |
| void NotifyPreconnectsComplete(int rv); |
| |
| // Called after completion of a connection attempt to decrement stream |
| // counts in preconnect entries. Invokes the callback of an entry when the |
| // entry's stream counts is less than or equal to `active_stream_count` |
| // (i.e., `this` has enough streams). |
| void ProcessPreconnectsAfterAttemptComplete(int rv, |
| size_t active_stream_count); |
| |
| // Notifies a job of preconnect completion. |
| void NotifyJobOfPreconnectComplete(raw_ptr<Job> job, int rv); |
| |
| // Creates a text based stream and Notifies the highest priority job. |
| void CreateTextBasedStreamAndNotify( |
| std::unique_ptr<StreamSocket> stream_socket, |
| StreamSocketHandle::SocketReuseType reuse_type, |
| LoadTimingInfo::ConnectTiming connect_timing); |
| |
| bool HasAvailableSpdySession() const; |
| |
| void MaybeStartDraining(); |
| |
| void MaybeCreateSpdyStreamAndNotify(base::WeakPtr<SpdySession> spdy_session, |
| SessionSource session_source); |
| |
| void MaybeCreateQuicStreamAndNotify(QuicChromiumClientSession* quic_session, |
| SessionSource session_source); |
| |
| void NotifyStreamReady(std::unique_ptr<HttpStream> stream, |
| NextProto negotiated_protocol, |
| std::optional<SessionSource> session_source); |
| |
| // Called when a SPDY session is ready to use. Cancels in-flight attempts. |
| // Closes idle streams. Completes request/preconnect jobs. |
| void HandleSpdySessionReady(base::WeakPtr<SpdySession> spdy_session, |
| StreamSocketCloseReason refresh_group_reason); |
| |
| // Called when a QUIC session is ready to use. Cancels in-flight attempts. |
| // Closes idle streams. Completes request/preconnect jobs. |
| void HandleQuicSessionReady(QuicChromiumClientSession* quic_session, |
| StreamSocketCloseReason refresh_group_reason); |
| |
| // Extracts an entry from `request_jobs_` of which priority is highest. The |
| // ownership of the entry is moved to `notified_jobs_`. |
| Job* ExtractFirstJobToNotify(); |
| |
| // Remove the pointeee of `job_pointer` from `request_jobs_`. May cancel |
| // in-flight TCP based attempts when there are no limit ignoring jobs after |
| // removing the job and in-flight TCP based attempts count is larger than the |
| // limit. |
| raw_ptr<Job> RemoveJobFromQueue(JobQueue::Pointer job_pointer); |
| |
| // Transfers the ownership of `raw_attempt` to the caller. |
| std::unique_ptr<TcpBasedAttempt> ExtractTcpBasedAttempt( |
| TcpBasedAttempt* raw_attempt); |
| |
| void HandleTcpBasedAttemptFailure( |
| std::unique_ptr<TcpBasedAttempt> tcp_based_attempt, |
| int rv); |
| |
| void OnSpdyThrottleDelayPassed(); |
| |
| // Returns the delay for TCP based attempts in favor of QUIC. |
| base::TimeDelta GetTcpBasedAttemptDelay(); |
| |
| // Updates whether TCP based attempts should be blocked or not. May cancel |
| // `tcp_based_attempt_delay_timer_`. |
| void UpdateTcpBasedAttemptState(); |
| |
| // Cancels `tcp_based_attempt_delay_timer_`. |
| void CancelTcpBasedAttemptDelayTimer(); |
| |
| // Called when `tcp_based_attempt_delay_timer_` is fired. |
| void OnTcpBasedAttemptDelayPassed(); |
| |
| bool CanUseTcpBasedProtocols(); |
| |
| bool CanUseQuic(); |
| |
| bool IsEchEnabled() const; |
| |
| // Mark QUIC brokenness if QUIC attempts failed but TCP/TLS attempts succeeded |
| // or not attempted. |
| void MaybeMarkQuicBroken(); |
| |
| // Returns true when this can complete. |
| bool CanComplete() const; |
| |
| // Notifies `group_` that `this` has completed and can be destroyed. |
| void MaybeComplete(); |
| |
| // If `this` is ready to complete, posts a task to call MaybeComplete(). |
| void MaybeCompleteLater(); |
| |
| const raw_ptr<Group> group_; |
| |
| const NetLogWithSource net_log_; |
| |
| // For trace events. |
| const perfetto::Track track_; |
| |
| const base::TimeTicks created_time_; |
| |
| // Keeps the initial attempt state. Set when `this` attempts a TCP based |
| // attempt for the first time. |
| std::optional<InitialAttemptState> initial_attempt_state_; |
| |
| NextProtoSet allowed_alpns_ = NextProtoSet::All(); |
| |
| // Holds request jobs that are waiting for notifications. |
| JobQueue request_jobs_; |
| // Holds preconnect jobs that are waiting for notifications. |
| std::set<raw_ptr<Job>> preconnect_jobs_; |
| // Holds jobs that are already notified results. We need to keep them to avoid |
| // dangling pointers. |
| std::set<raw_ptr<Job>> notified_jobs_; |
| |
| base::flat_set<raw_ptr<Job>> limit_ignoring_jobs_; |
| |
| base::flat_set<raw_ptr<Job>> ip_based_pooling_disabling_jobs_; |
| |
| base::flat_set<raw_ptr<Job>> alternative_service_disabling_jobs_; |
| |
| std::unique_ptr<HostResolver::ServiceEndpointRequest> |
| service_endpoint_request_; |
| bool service_endpoint_request_finished_ = false; |
| base::TimeTicks dns_resolution_start_time_; |
| base::TimeTicks dns_resolution_end_time_; |
| |
| AvailabilityState availability_state_ = AvailabilityState::kAvailable; |
| |
| NetErrorDetails net_error_details_; |
| ResolveErrorInfo resolve_error_info_; |
| ConnectionAttempts connection_attempts_; |
| |
| // TODO(crbug.com/406936736): Remove this once we identify the cause of the |
| // bug. |
| bool ip_matching_spdy_session_found_ = false; |
| |
| // An error code to notify jobs when `this` cannot make any further progress. |
| // Set to an error from service endpoint resolution failure, the last stream |
| // attempt failure, network change events, or QUIC task failure. |
| std::optional<int> final_error_to_notify_jobs_; |
| |
| // Set to the most recent TCP based attempt failure, if any. |
| std::optional<int> most_recent_tcp_error_; |
| |
| // Set to a SSLInfo when an attempt has failed with a certificate error. Used |
| // to notify jobs. |
| std::optional<SSLInfo> cert_error_ssl_info_; |
| |
| // Set to a SSLCertRequestInfo when an attempt has requested a client cert. |
| // Used to notify jobs. |
| scoped_refptr<SSLCertRequestInfo> client_auth_cert_info_; |
| |
| // Base SSLConfig for TCP based attempts, Allowed bad certificates are set |
| // from the newest job. |
| std::optional<SSLConfig> base_ssl_config_; |
| |
| std::set<std::unique_ptr<TcpBasedAttempt>, base::UniquePtrComparator> |
| tcp_based_attempts_; |
| // The number of in-flight TCP based attempts that are treated as slow. |
| size_t slow_tcp_based_attempt_count_ = 0; |
| |
| base::OneShotTimer spdy_throttle_timer_; |
| bool spdy_throttle_delay_passed_ = false; |
| |
| // Tracks the states of IPEndPoints. |
| IPEndPointStateTracker ip_endpoint_state_tracker_{this}; |
| |
| // The current state of TCP/TLS connection attempts. |
| TcpBasedAttemptState tcp_based_attempt_state_ = |
| TcpBasedAttemptState::kNotStarted; |
| |
| // QUIC version that is known to be used for the destination, usually coming |
| // from Alt-Svc. |
| quic::ParsedQuicVersion quic_version_ = |
| quic::ParsedQuicVersion::Unsupported(); |
| // Created when attempting a QUIC session. |
| std::unique_ptr<QuicAttempt> quic_attempt_; |
| // Set when `quic_attempt_` is completed. |
| std::optional<int> quic_attempt_result_; |
| |
| // The delay for TCP based stream attempts in favor of QUIC. |
| base::TimeDelta tcp_based_attempt_delay_; |
| // Set to true when TCP based attempts should be blocked. |
| bool should_block_tcp_based_attempt_ = false; |
| base::OneShotTimer tcp_based_attempt_delay_timer_; |
| |
| base::OnceClosure on_complete_callback_for_testing_; |
| |
| base::WeakPtrFactory<AttemptManager> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_HTTP_HTTP_STREAM_POOL_ATTEMPT_MANAGER_H_ |