// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_SOCKET_CONNECT_JOB_H_ #define NET_SOCKET_CONNECT_JOB_H_ #include #include #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "net/base/load_states.h" #include "net/base/load_timing_info.h" #include "net/base/net_export.h" #include "net/base/privacy_mode.h" #include "net/base/request_priority.h" #include "net/log/net_log_with_source.h" #include "net/socket/connection_attempts.h" #include "net/socket/socket_tag.h" #include "net/socket/ssl_client_socket.h" #include "net/third_party/quiche/src/quic/core/quic_versions.h" namespace net { class ClientSocketFactory; class HostResolver; class HttpAuthCache; class HttpAuthController; class HttpAuthHandlerFactory; class HttpResponseInfo; class HttpUserAgentSettings; class NetLog; class NetworkQualityEstimator; class ProxyDelegate; class SocketPerformanceWatcherFactory; class StreamSocket; class WebSocketEndpointLockManager; class QuicStreamFactory; class SpdySessionPool; class SSLCertRequestInfo; // Immutable socket parameters intended for shared use by all ConnectJob types. // Excludes priority because it can be modified over the lifetime of a // ConnectJob. Excludes connection timeout and NetLogWithSource because // ConnectJobs that wrap other ConnectJobs typically have different values for // those. struct NET_EXPORT_PRIVATE CommonConnectJobParams { CommonConnectJobParams( ClientSocketFactory* client_socket_factory, HostResolver* host_resolver, HttpAuthCache* http_auth_cache, HttpAuthHandlerFactory* http_auth_handler_factory, SpdySessionPool* spdy_session_pool, const quic::QuicTransportVersionVector* quic_supported_versions, QuicStreamFactory* quic_stream_factory, ProxyDelegate* proxy_delegate, const HttpUserAgentSettings* http_user_agent_settings, const SSLClientSocketContext& ssl_client_socket_context, const SSLClientSocketContext& ssl_client_socket_context_privacy_mode, SocketPerformanceWatcherFactory* socket_performance_watcher_factory, NetworkQualityEstimator* network_quality_estimator, NetLog* net_log, WebSocketEndpointLockManager* websocket_endpoint_lock_manager); CommonConnectJobParams(const CommonConnectJobParams& other); ~CommonConnectJobParams(); CommonConnectJobParams& operator=(const CommonConnectJobParams& other); ClientSocketFactory* client_socket_factory; HostResolver* host_resolver; HttpAuthCache* http_auth_cache; HttpAuthHandlerFactory* http_auth_handler_factory; SpdySessionPool* spdy_session_pool; const quic::QuicTransportVersionVector* quic_supported_versions; QuicStreamFactory* quic_stream_factory; ProxyDelegate* proxy_delegate; const HttpUserAgentSettings* http_user_agent_settings; SSLClientSocketContext ssl_client_socket_context; SSLClientSocketContext ssl_client_socket_context_privacy_mode; SocketPerformanceWatcherFactory* socket_performance_watcher_factory; NetworkQualityEstimator* network_quality_estimator; NetLog* net_log; // This must only be non-null for WebSockets. WebSocketEndpointLockManager* websocket_endpoint_lock_manager; }; // ConnectJob provides an abstract interface for "connecting" a socket. // The connection may involve host resolution, tcp connection, ssl connection, // etc. class NET_EXPORT_PRIVATE ConnectJob { public: // Alerts the delegate that the connection completed. |job| must be destroyed // by the delegate. A std::unique_ptr<> isn't used because the caller of this // function doesn't own |job|. class NET_EXPORT_PRIVATE Delegate { public: Delegate() {} virtual ~Delegate() {} // Alerts the delegate that the connection completed. |job| must be // destroyed by the delegate. A std::unique_ptr<> isn't used because the // caller of this function doesn't own |job|. virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; // Invoked when an HTTP proxy returns an HTTP auth challenge during tunnel // establishment. Always invoked asynchronously. The caller should use // |auth_controller| to set challenge response information and then invoke // |restart_with_auth_callback| to continue establishing a connection, or // delete the ConnectJob if it doesn't want to respond to the challenge. // // Will only be called once at a time. Neither OnConnectJobComplete() nor // OnNeedsProxyAuth() will be called synchronously when // |restart_with_auth_callback| is invoked. Will not be called after // OnConnectJobComplete() has been invoked. virtual void OnNeedsProxyAuth(const HttpResponseInfo& response, HttpAuthController* auth_controller, base::OnceClosure restart_with_auth_callback, ConnectJob* job) = 0; private: DISALLOW_COPY_AND_ASSIGN(Delegate); }; // A |timeout_duration| of 0 corresponds to no timeout. // // If |net_log| is non-NULL, the ConnectJob will use it for logging. // Otherwise, a new one will be created of type |net_log_source_type|. // // |net_log_connect_event_type| is the NetLog event type logged on Connect() // and connect completion. ConnectJob(RequestPriority priority, const SocketTag& socket_tag, base::TimeDelta timeout_duration, const CommonConnectJobParams* common_connect_job_params, Delegate* delegate, const NetLogWithSource* net_log, NetLogSourceType net_log_source_type, NetLogEventType net_log_connect_event_type); virtual ~ConnectJob(); // Accessors const NetLogWithSource& net_log() { return net_log_; } RequestPriority priority() const { return priority_; } // Releases ownership of the underlying socket to the caller. Returns the // released socket, or nullptr if there was a connection error. std::unique_ptr PassSocket(); // Returns the connected socket, or nullptr if PassSocket() has already been // called. Used to query the socket state. May only be called after the // ConnectJob completes. StreamSocket* socket() { return socket_.get(); } void ChangePriority(RequestPriority priority); // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it // cannot complete synchronously without blocking, or another net error code // on error. In asynchronous completion, the ConnectJob will notify // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous // completion, ReleaseSocket() can be called to acquire the connected socket // if it succeeded. // // On completion, the ConnectJob must be destroyed synchronously, since it // doesn't bother to stop its timer when complete. // TODO(mmenke): Can that be fixed? int Connect(); // Returns the current LoadState of the ConnectJob. Each ConnectJob class must // start (optionally) with a LOAD_STATE_RESOLVING_HOST followed by // LOAD_STATE_CONNECTING, and never return to LOAD_STATE_CONNECTING. This // behavior is needed for backup ConnectJobs to function correctly. // // TODO(mmenke): Can something better be done here? virtual LoadState GetLoadState() const = 0; // Returns true if the ConnectJob has ever successfully established a TCP // connection. Used solely for deciding if a backup job is needed. Once it // starts returning true, must always return true when called in the future. // Not safe to call after NotifyComplete() is invoked. virtual bool HasEstablishedConnection() const = 0; // If the ConnectJobFailed, this method returns a list of failed attempts to // connect to the destination server. Returns an empty list if connecting to a // proxy. virtual ConnectionAttempts GetConnectionAttempts() const; // On connect failure, returns the nested proxy socket, if there is one. // Returns nullptr otherwise. Only returns a non-null value for SSL sockets on // top of proxy sockets. virtual std::unique_ptr PassProxySocketOnFailure(); // If the ConnectJob failed, returns true if the failure occurred after SSL // negotiation started. If the ConnectJob succeeded, the returned value is // undefined. virtual bool IsSSLError() const; // If the ConnectJob failed with ERR_SSL_CLIENT_AUTH_CERT_NEEDED, returns the // SSLCertRequestInfo received. Otherwise, returns nullptr. virtual scoped_refptr GetCertRequestInfo(); const LoadTimingInfo::ConnectTiming& connect_timing() const { return connect_timing_; } const NetLogWithSource& net_log() const { return net_log_; } protected: const SocketTag& socket_tag() const { return socket_tag_; } ClientSocketFactory* client_socket_factory() { return common_connect_job_params_->client_socket_factory; } HostResolver* host_resolver() { return common_connect_job_params_->host_resolver; } const HttpUserAgentSettings* http_user_agent_settings() const { return common_connect_job_params_->http_user_agent_settings; } const SSLClientSocketContext& ssl_client_socket_context() { return common_connect_job_params_->ssl_client_socket_context; } const SSLClientSocketContext& ssl_client_socket_context_privacy_mode() { return common_connect_job_params_->ssl_client_socket_context_privacy_mode; } SocketPerformanceWatcherFactory* socket_performance_watcher_factory() { return common_connect_job_params_->socket_performance_watcher_factory; } NetworkQualityEstimator* network_quality_estimator() { return common_connect_job_params_->network_quality_estimator; } WebSocketEndpointLockManager* websocket_endpoint_lock_manager() { return common_connect_job_params_->websocket_endpoint_lock_manager; } const CommonConnectJobParams* common_connect_job_params() { return common_connect_job_params_; } void SetSocket(std::unique_ptr socket); void NotifyDelegateOfCompletion(int rv); void NotifyDelegateOfProxyAuth(const HttpResponseInfo& response, HttpAuthController* auth_controller, base::OnceClosure restart_with_auth_callback); // If |remaining_time| is base::TimeDelta(), stops the timeout timer, if it's // running. Otherwise, Starts / restarts the timeout timer to trigger in the // specified amount of time. void ResetTimer(base::TimeDelta remaining_time); // Returns whether or not the timeout timer is running. Only intended for use // by DCHECKs. bool TimerIsRunning() const; // Connection establishment timing information. // TODO(mmenke): This should be private. LoadTimingInfo::ConnectTiming connect_timing_; private: virtual int ConnectInternal() = 0; virtual void ChangePriorityInternal(RequestPriority priority) = 0; void LogConnectStart(); void LogConnectCompletion(int net_error); // Alerts the delegate that the ConnectJob has timed out. void OnTimeout(); // Invoked to notify subclasses that the has request timed out. virtual void OnTimedOutInternal(); const base::TimeDelta timeout_duration_; RequestPriority priority_; const SocketTag socket_tag_; const CommonConnectJobParams* common_connect_job_params_; // Timer to abort jobs that take too long. base::OneShotTimer timer_; Delegate* delegate_; std::unique_ptr socket_; // Indicates if this is the topmost ConnectJob. The topmost ConnectJob logs an // extra begin and end event, to allow callers to log extra data before the // ConnectJob has started / after it has completed. const bool top_level_job_; NetLogWithSource net_log_; const NetLogEventType net_log_connect_event_type_; DISALLOW_COPY_AND_ASSIGN(ConnectJob); }; } // namespace net #endif // NET_SOCKET_CONNECT_JOB_H_