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