336 lines
14 KiB
C++
336 lines
14 KiB
C++
// Copyright 2018 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_SOCKET_CONNECT_JOB_H_
|
|
#define NET_SOCKET_CONNECT_JOB_H_
|
|
|
|
#include <memory>
|
|
#include <set>
|
|
#include <string>
|
|
|
|
#include "base/functional/callback_forward.h"
|
|
#include "base/functional/callback_helpers.h"
|
|
#include "base/memory/raw_ptr.h"
|
|
#include "base/memory/scoped_refptr.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/request_priority.h"
|
|
#include "net/dns/public/host_resolver_results.h"
|
|
#include "net/dns/public/resolve_error_info.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/quiche/quic/core/quic_versions.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
|
|
namespace net {
|
|
|
|
class ClientSocketFactory;
|
|
class HostPortPair;
|
|
class HostResolver;
|
|
struct HostResolverEndpointResult;
|
|
class HttpAuthCache;
|
|
class HttpAuthController;
|
|
class HttpAuthHandlerFactory;
|
|
class HttpResponseInfo;
|
|
class HttpUserAgentSettings;
|
|
class NetLog;
|
|
class NetLogWithSource;
|
|
class NetworkQualityEstimator;
|
|
class ProxyDelegate;
|
|
class QuicStreamFactory;
|
|
class SocketPerformanceWatcherFactory;
|
|
class SocketTag;
|
|
class SpdySessionPool;
|
|
class SSLCertRequestInfo;
|
|
class StreamSocket;
|
|
class WebSocketEndpointLockManager;
|
|
|
|
// 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::ParsedQuicVersionVector* quic_supported_versions,
|
|
QuicStreamFactory* quic_stream_factory,
|
|
ProxyDelegate* proxy_delegate,
|
|
const HttpUserAgentSettings* http_user_agent_settings,
|
|
SSLClientContext* ssl_client_context,
|
|
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);
|
|
|
|
raw_ptr<ClientSocketFactory> client_socket_factory;
|
|
raw_ptr<HostResolver> host_resolver;
|
|
raw_ptr<HttpAuthCache> http_auth_cache;
|
|
raw_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
|
|
raw_ptr<SpdySessionPool> spdy_session_pool;
|
|
raw_ptr<const quic::ParsedQuicVersionVector> quic_supported_versions;
|
|
raw_ptr<QuicStreamFactory> quic_stream_factory;
|
|
raw_ptr<ProxyDelegate> proxy_delegate;
|
|
raw_ptr<const HttpUserAgentSettings> http_user_agent_settings;
|
|
raw_ptr<SSLClientContext> ssl_client_context;
|
|
raw_ptr<SocketPerformanceWatcherFactory> socket_performance_watcher_factory;
|
|
raw_ptr<NetworkQualityEstimator> network_quality_estimator;
|
|
raw_ptr<NetLog> net_log;
|
|
|
|
// This must only be non-null for WebSockets.
|
|
raw_ptr<WebSocketEndpointLockManager> websocket_endpoint_lock_manager;
|
|
};
|
|
|
|
// When a host resolution completes, OnHostResolutionCallback() is invoked. If
|
|
// it returns |kContinue|, the ConnectJob can continue immediately. If it
|
|
// returns |kMayBeDeletedAsync|, the ConnectJob may be slated for asychronous
|
|
// destruction, so should post a task before continuing, in case it will be
|
|
// deleted. The purpose of kMayBeDeletedAsync is to avoid needlessly creating
|
|
// and connecting a socket when it might not be needed.
|
|
enum class OnHostResolutionCallbackResult {
|
|
kContinue,
|
|
kMayBeDeletedAsync,
|
|
};
|
|
|
|
// If non-null, invoked when host resolution completes. May not destroy the
|
|
// ConnectJob synchronously, but may signal the ConnectJob may be destroyed
|
|
// asynchronously. See OnHostResolutionCallbackResult above.
|
|
//
|
|
// |address_list| is the list of addresses the host being connected to was
|
|
// resolved to, with the port fields populated to the port being connected to.
|
|
using OnHostResolutionCallback =
|
|
base::RepeatingCallback<OnHostResolutionCallbackResult(
|
|
const HostPortPair& host_port_pair,
|
|
const std::vector<HostResolverEndpointResult>& endpoint_results,
|
|
const std::set<std::string>& aliases)>;
|
|
|
|
// 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() = default;
|
|
|
|
Delegate(const Delegate&) = delete;
|
|
Delegate& operator=(const Delegate&) = delete;
|
|
|
|
virtual ~Delegate() = default;
|
|
|
|
// 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);
|
|
|
|
ConnectJob(const ConnectJob&) = delete;
|
|
ConnectJob& operator=(const ConnectJob&) = delete;
|
|
|
|
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<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
|
|
// 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;
|
|
|
|
// 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;
|
|
|
|
// Returns error information about any host resolution attempt.
|
|
virtual ResolveErrorInfo GetResolveErrorInfo() const = 0;
|
|
|
|
// 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();
|
|
|
|
// Returns the `HostResolverEndpointResult` structure corresponding to the
|
|
// chosen route. Should only be called on a successful connect. If the
|
|
// `ConnectJob` does not make DNS queries, or does not use the SVCB/HTTPS
|
|
// record, it may return `absl::nullopt`, to avoid callers getting confused by
|
|
// an empty `IPEndPoint` list.
|
|
virtual absl::optional<HostResolverEndpointResult>
|
|
GetHostResolverEndpointResult() const;
|
|
|
|
const LoadTimingInfo::ConnectTiming& connect_timing() const {
|
|
return connect_timing_;
|
|
}
|
|
|
|
// Sets |done_closure_| which will be called when |this| is deleted.
|
|
void set_done_closure(base::OnceClosure done_closure);
|
|
|
|
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;
|
|
}
|
|
SSLClientContext* ssl_client_context() {
|
|
return common_connect_job_params_->ssl_client_context;
|
|
}
|
|
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() const {
|
|
return common_connect_job_params_;
|
|
}
|
|
|
|
void SetSocket(std::unique_ptr<StreamSocket> socket,
|
|
absl::optional<std::set<std::string>> dns_aliases);
|
|
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_;
|
|
raw_ptr<const CommonConnectJobParams> common_connect_job_params_;
|
|
// Timer to abort jobs that take too long.
|
|
base::OneShotTimer timer_;
|
|
raw_ptr<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_;
|
|
// This is called when |this| is deleted.
|
|
base::ScopedClosureRunner done_closure_;
|
|
const NetLogEventType net_log_connect_event_type_;
|
|
};
|
|
|
|
} // namespace net
|
|
|
|
#endif // NET_SOCKET_CONNECT_JOB_H_
|