blob: 70083a8ff7ec1c734c05edde562664ac41ed4537 [file] [log] [blame]
// 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.
#include <memory>
#include <string>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/address_list.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 HostPortPair;
class HostResolver;
class HttpAuthCache;
class HttpAuthController;
class HttpAuthHandlerFactory;
class HttpResponseInfo;
class HttpUserAgentSettings;
class NetLog;
class NetLogWithSource;
class NetworkQualityEstimator;
struct NetworkTrafficAnnotationTag;
class ProxyDelegate;
class ProxyServer;
class SocketPerformanceWatcherFactory;
struct SSLConfig;
class StreamSocket;
class WebSocketEndpointLockManager;
class QuicStreamFactory;
class SocketTag;
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 {
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& 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;
using OnHostResolutionCallback =
base::RepeatingCallback<int(const AddressList&,
const NetLogWithSource& net_log)>;
// 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 {
// 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 {
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;
// 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();
// Creates a ConnectJob with the specified parameters.
// |common_connect_job_params| and |delegate| must outlive the returned
// ConnectJob.
static std::unique_ptr<ConnectJob> CreateConnectJob(
bool using_ssl,
const HostPortPair& endpoint,
const ProxyServer& proxy_server,
const base::Optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
const SSLConfig* ssl_config_for_origin,
const SSLConfig* ssl_config_for_proxy,
bool force_tunnel,
PrivacyMode privacy_mode,
const OnHostResolutionCallback& resolution_callback,
RequestPriority request_priority,
SocketTag socket_tag,
const CommonConnectJobParams* common_connect_job_params,
ConnectJob::Delegate* delegate);
// 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<StreamSocket> 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
// 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;
// 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<SSLCertRequestInfo> GetCertRequestInfo();
const LoadTimingInfo::ConnectTiming& connect_timing() const {
return connect_timing_;
const NetLogWithSource& net_log() const { return net_log_; }
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<StreamSocket> 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_;
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<StreamSocket> 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_;
} // namespace net