• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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