1 // Copyright 2018 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 #ifndef NET_SOCKET_CONNECT_JOB_H_ 6 #define NET_SOCKET_CONNECT_JOB_H_ 7 8 #include <memory> 9 #include <set> 10 #include <string> 11 12 #include "base/functional/callback_forward.h" 13 #include "base/functional/callback_helpers.h" 14 #include "base/memory/raw_ptr.h" 15 #include "base/memory/scoped_refptr.h" 16 #include "base/time/time.h" 17 #include "base/timer/timer.h" 18 #include "net/base/load_states.h" 19 #include "net/base/load_timing_info.h" 20 #include "net/base/net_export.h" 21 #include "net/base/request_priority.h" 22 #include "net/dns/public/host_resolver_results.h" 23 #include "net/dns/public/resolve_error_info.h" 24 #include "net/log/net_log_with_source.h" 25 #include "net/socket/connection_attempts.h" 26 #include "net/socket/socket_tag.h" 27 #include "net/socket/ssl_client_socket.h" 28 #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" 29 #include "third_party/abseil-cpp/absl/types/optional.h" 30 31 namespace net { 32 33 class ClientSocketFactory; 34 class HostPortPair; 35 class HostResolver; 36 struct HostResolverEndpointResult; 37 class HttpAuthCache; 38 class HttpAuthController; 39 class HttpAuthHandlerFactory; 40 class HttpResponseInfo; 41 class HttpUserAgentSettings; 42 class NetLog; 43 class NetLogWithSource; 44 class NetworkQualityEstimator; 45 class ProxyDelegate; 46 class QuicStreamFactory; 47 class SocketPerformanceWatcherFactory; 48 class SocketTag; 49 class SpdySessionPool; 50 class SSLCertRequestInfo; 51 class StreamSocket; 52 class WebSocketEndpointLockManager; 53 54 // Immutable socket parameters intended for shared use by all ConnectJob types. 55 // Excludes priority because it can be modified over the lifetime of a 56 // ConnectJob. Excludes connection timeout and NetLogWithSource because 57 // ConnectJobs that wrap other ConnectJobs typically have different values for 58 // those. 59 struct NET_EXPORT_PRIVATE CommonConnectJobParams { 60 CommonConnectJobParams( 61 ClientSocketFactory* client_socket_factory, 62 HostResolver* host_resolver, 63 HttpAuthCache* http_auth_cache, 64 HttpAuthHandlerFactory* http_auth_handler_factory, 65 SpdySessionPool* spdy_session_pool, 66 const quic::ParsedQuicVersionVector* quic_supported_versions, 67 QuicStreamFactory* quic_stream_factory, 68 ProxyDelegate* proxy_delegate, 69 const HttpUserAgentSettings* http_user_agent_settings, 70 SSLClientContext* ssl_client_context, 71 SocketPerformanceWatcherFactory* socket_performance_watcher_factory, 72 NetworkQualityEstimator* network_quality_estimator, 73 NetLog* net_log, 74 WebSocketEndpointLockManager* websocket_endpoint_lock_manager); 75 CommonConnectJobParams(const CommonConnectJobParams& other); 76 ~CommonConnectJobParams(); 77 78 CommonConnectJobParams& operator=(const CommonConnectJobParams& other); 79 80 raw_ptr<ClientSocketFactory> client_socket_factory; 81 raw_ptr<HostResolver> host_resolver; 82 raw_ptr<HttpAuthCache> http_auth_cache; 83 raw_ptr<HttpAuthHandlerFactory> http_auth_handler_factory; 84 raw_ptr<SpdySessionPool> spdy_session_pool; 85 raw_ptr<const quic::ParsedQuicVersionVector> quic_supported_versions; 86 raw_ptr<QuicStreamFactory> quic_stream_factory; 87 raw_ptr<ProxyDelegate> proxy_delegate; 88 raw_ptr<const HttpUserAgentSettings> http_user_agent_settings; 89 raw_ptr<SSLClientContext> ssl_client_context; 90 raw_ptr<SocketPerformanceWatcherFactory> socket_performance_watcher_factory; 91 raw_ptr<NetworkQualityEstimator> network_quality_estimator; 92 raw_ptr<NetLog> net_log; 93 94 // This must only be non-null for WebSockets. 95 raw_ptr<WebSocketEndpointLockManager> websocket_endpoint_lock_manager; 96 }; 97 98 // When a host resolution completes, OnHostResolutionCallback() is invoked. If 99 // it returns |kContinue|, the ConnectJob can continue immediately. If it 100 // returns |kMayBeDeletedAsync|, the ConnectJob may be slated for asychronous 101 // destruction, so should post a task before continuing, in case it will be 102 // deleted. The purpose of kMayBeDeletedAsync is to avoid needlessly creating 103 // and connecting a socket when it might not be needed. 104 enum class OnHostResolutionCallbackResult { 105 kContinue, 106 kMayBeDeletedAsync, 107 }; 108 109 // If non-null, invoked when host resolution completes. May not destroy the 110 // ConnectJob synchronously, but may signal the ConnectJob may be destroyed 111 // asynchronously. See OnHostResolutionCallbackResult above. 112 // 113 // |address_list| is the list of addresses the host being connected to was 114 // resolved to, with the port fields populated to the port being connected to. 115 using OnHostResolutionCallback = 116 base::RepeatingCallback<OnHostResolutionCallbackResult( 117 const HostPortPair& host_port_pair, 118 const std::vector<HostResolverEndpointResult>& endpoint_results, 119 const std::set<std::string>& aliases)>; 120 121 // ConnectJob provides an abstract interface for "connecting" a socket. 122 // The connection may involve host resolution, tcp connection, ssl connection, 123 // etc. 124 class NET_EXPORT_PRIVATE ConnectJob { 125 public: 126 // Alerts the delegate that the connection completed. |job| must be destroyed 127 // by the delegate. A std::unique_ptr<> isn't used because the caller of this 128 // function doesn't own |job|. 129 class NET_EXPORT_PRIVATE Delegate { 130 public: 131 Delegate() = default; 132 133 Delegate(const Delegate&) = delete; 134 Delegate& operator=(const Delegate&) = delete; 135 136 virtual ~Delegate() = default; 137 138 // Alerts the delegate that the connection completed. |job| must be 139 // destroyed by the delegate. A std::unique_ptr<> isn't used because the 140 // caller of this function doesn't own |job|. 141 virtual void OnConnectJobComplete(int result, ConnectJob* job) = 0; 142 143 // Invoked when an HTTP proxy returns an HTTP auth challenge during tunnel 144 // establishment. Always invoked asynchronously. The caller should use 145 // |auth_controller| to set challenge response information and then invoke 146 // |restart_with_auth_callback| to continue establishing a connection, or 147 // delete the ConnectJob if it doesn't want to respond to the challenge. 148 // 149 // Will only be called once at a time. Neither OnConnectJobComplete() nor 150 // OnNeedsProxyAuth() will be called synchronously when 151 // |restart_with_auth_callback| is invoked. Will not be called after 152 // OnConnectJobComplete() has been invoked. 153 virtual void OnNeedsProxyAuth(const HttpResponseInfo& response, 154 HttpAuthController* auth_controller, 155 base::OnceClosure restart_with_auth_callback, 156 ConnectJob* job) = 0; 157 }; 158 159 // A |timeout_duration| of 0 corresponds to no timeout. 160 // 161 // If |net_log| is non-NULL, the ConnectJob will use it for logging. 162 // Otherwise, a new one will be created of type |net_log_source_type|. 163 // 164 // |net_log_connect_event_type| is the NetLog event type logged on Connect() 165 // and connect completion. 166 ConnectJob(RequestPriority priority, 167 const SocketTag& socket_tag, 168 base::TimeDelta timeout_duration, 169 const CommonConnectJobParams* common_connect_job_params, 170 Delegate* delegate, 171 const NetLogWithSource* net_log, 172 NetLogSourceType net_log_source_type, 173 NetLogEventType net_log_connect_event_type); 174 175 ConnectJob(const ConnectJob&) = delete; 176 ConnectJob& operator=(const ConnectJob&) = delete; 177 178 virtual ~ConnectJob(); 179 180 // Accessors net_log()181 const NetLogWithSource& net_log() { return net_log_; } priority()182 RequestPriority priority() const { return priority_; } 183 184 // Releases ownership of the underlying socket to the caller. Returns the 185 // released socket, or nullptr if there was a connection error. 186 std::unique_ptr<StreamSocket> PassSocket(); 187 188 // Returns the connected socket, or nullptr if PassSocket() has already been 189 // called. Used to query the socket state. May only be called after the 190 // ConnectJob completes. socket()191 StreamSocket* socket() { return socket_.get(); } 192 193 void ChangePriority(RequestPriority priority); 194 195 // Begins connecting the socket. Returns OK on success, ERR_IO_PENDING if it 196 // cannot complete synchronously without blocking, or another net error code 197 // on error. In asynchronous completion, the ConnectJob will notify 198 // |delegate_| via OnConnectJobComplete. In both asynchronous and synchronous 199 // completion, ReleaseSocket() can be called to acquire the connected socket 200 // if it succeeded. 201 // 202 // On completion, the ConnectJob must be destroyed synchronously, since it 203 // doesn't bother to stop its timer when complete. 204 // TODO(mmenke): Can that be fixed? 205 int Connect(); 206 207 // Returns the current LoadState of the ConnectJob. Each ConnectJob class must 208 // start (optionally) with a LOAD_STATE_RESOLVING_HOST followed by 209 // LOAD_STATE_CONNECTING, and never return to LOAD_STATE_CONNECTING. This 210 // behavior is needed for backup ConnectJobs to function correctly. 211 // 212 // TODO(mmenke): Can something better be done here? 213 virtual LoadState GetLoadState() const = 0; 214 215 // Returns true if the ConnectJob has ever successfully established a TCP 216 // connection. Used solely for deciding if a backup job is needed. Once it 217 // starts returning true, must always return true when called in the future. 218 // Not safe to call after NotifyComplete() is invoked. 219 virtual bool HasEstablishedConnection() const = 0; 220 221 // Returns a list of failed attempts to connect to the destination server. 222 // Returns an empty list if connecting to a proxy. 223 virtual ConnectionAttempts GetConnectionAttempts() const; 224 225 // Returns error information about any host resolution attempt. 226 virtual ResolveErrorInfo GetResolveErrorInfo() const = 0; 227 228 // If the ConnectJob failed, returns true if the failure occurred after SSL 229 // negotiation started. If the ConnectJob succeeded, the returned value is 230 // undefined. 231 virtual bool IsSSLError() const; 232 233 // If the ConnectJob failed with ERR_SSL_CLIENT_AUTH_CERT_NEEDED, returns the 234 // SSLCertRequestInfo received. Otherwise, returns nullptr. 235 virtual scoped_refptr<SSLCertRequestInfo> GetCertRequestInfo(); 236 237 // Returns the `HostResolverEndpointResult` structure corresponding to the 238 // chosen route. Should only be called on a successful connect. If the 239 // `ConnectJob` does not make DNS queries, or does not use the SVCB/HTTPS 240 // record, it may return `absl::nullopt`, to avoid callers getting confused by 241 // an empty `IPEndPoint` list. 242 virtual absl::optional<HostResolverEndpointResult> 243 GetHostResolverEndpointResult() const; 244 connect_timing()245 const LoadTimingInfo::ConnectTiming& connect_timing() const { 246 return connect_timing_; 247 } 248 249 // Sets |done_closure_| which will be called when |this| is deleted. 250 void set_done_closure(base::OnceClosure done_closure); 251 net_log()252 const NetLogWithSource& net_log() const { return net_log_; } 253 254 protected: socket_tag()255 const SocketTag& socket_tag() const { return socket_tag_; } client_socket_factory()256 ClientSocketFactory* client_socket_factory() { 257 return common_connect_job_params_->client_socket_factory; 258 } host_resolver()259 HostResolver* host_resolver() { 260 return common_connect_job_params_->host_resolver; 261 } http_user_agent_settings()262 const HttpUserAgentSettings* http_user_agent_settings() const { 263 return common_connect_job_params_->http_user_agent_settings; 264 } ssl_client_context()265 SSLClientContext* ssl_client_context() { 266 return common_connect_job_params_->ssl_client_context; 267 } socket_performance_watcher_factory()268 SocketPerformanceWatcherFactory* socket_performance_watcher_factory() { 269 return common_connect_job_params_->socket_performance_watcher_factory; 270 } network_quality_estimator()271 NetworkQualityEstimator* network_quality_estimator() { 272 return common_connect_job_params_->network_quality_estimator; 273 } websocket_endpoint_lock_manager()274 WebSocketEndpointLockManager* websocket_endpoint_lock_manager() { 275 return common_connect_job_params_->websocket_endpoint_lock_manager; 276 } common_connect_job_params()277 const CommonConnectJobParams* common_connect_job_params() const { 278 return common_connect_job_params_; 279 } 280 281 void SetSocket(std::unique_ptr<StreamSocket> socket, 282 absl::optional<std::set<std::string>> dns_aliases); 283 void NotifyDelegateOfCompletion(int rv); 284 void NotifyDelegateOfProxyAuth(const HttpResponseInfo& response, 285 HttpAuthController* auth_controller, 286 base::OnceClosure restart_with_auth_callback); 287 288 // If |remaining_time| is base::TimeDelta(), stops the timeout timer, if it's 289 // running. Otherwise, Starts / restarts the timeout timer to trigger in the 290 // specified amount of time. 291 void ResetTimer(base::TimeDelta remaining_time); 292 293 // Returns whether or not the timeout timer is running. Only intended for use 294 // by DCHECKs. 295 bool TimerIsRunning() const; 296 297 // Connection establishment timing information. 298 // TODO(mmenke): This should be private. 299 LoadTimingInfo::ConnectTiming connect_timing_; 300 301 private: 302 virtual int ConnectInternal() = 0; 303 304 virtual void ChangePriorityInternal(RequestPriority priority) = 0; 305 306 void LogConnectStart(); 307 void LogConnectCompletion(int net_error); 308 309 // Alerts the delegate that the ConnectJob has timed out. 310 void OnTimeout(); 311 312 // Invoked to notify subclasses that the has request timed out. 313 virtual void OnTimedOutInternal(); 314 315 const base::TimeDelta timeout_duration_; 316 RequestPriority priority_; 317 const SocketTag socket_tag_; 318 raw_ptr<const CommonConnectJobParams> common_connect_job_params_; 319 // Timer to abort jobs that take too long. 320 base::OneShotTimer timer_; 321 raw_ptr<Delegate> delegate_; 322 std::unique_ptr<StreamSocket> socket_; 323 // Indicates if this is the topmost ConnectJob. The topmost ConnectJob logs an 324 // extra begin and end event, to allow callers to log extra data before the 325 // ConnectJob has started / after it has completed. 326 const bool top_level_job_; 327 NetLogWithSource net_log_; 328 // This is called when |this| is deleted. 329 base::ScopedClosureRunner done_closure_; 330 const NetLogEventType net_log_connect_event_type_; 331 }; 332 333 } // namespace net 334 335 #endif // NET_SOCKET_CONNECT_JOB_H_ 336