blob: d38737abfc2d40dafa37bce37ebc35ed42a1fe2c [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2018 The Chromium Authors
Matt Menke3abc57c2019-01-10 21:48:422// 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_TRANSPORT_CONNECT_JOB_H_
6#define NET_SOCKET_TRANSPORT_CONNECT_JOB_H_
7
8#include <memory>
Arthur Sonzogni4787fce2024-02-08 13:42:489#include <optional>
David Benjamin13072a42022-02-10 22:23:2110#include <set>
11#include <string>
Victor Hugo Vianna Silvac6de5ce2025-03-18 16:33:1112#include <variant>
David Benjamin13072a42022-02-10 22:23:2113#include <vector>
Matt Menke3abc57c2019-01-10 21:48:4214
David Benjamin13072a42022-02-10 22:23:2115#include "base/containers/flat_set.h"
David Benjamin6e089be2022-02-11 18:22:2116#include "base/containers/span.h"
Matt Menke3abc57c2019-01-10 21:48:4217#include "base/memory/ref_counted.h"
Matt Menke5062be22019-05-01 17:50:2418#include "base/memory/weak_ptr.h"
Matt Menke3abc57c2019-01-10 21:48:4219#include "base/time/time.h"
20#include "base/timer/timer.h"
Eric Orth7287eb602019-02-13 19:49:5521#include "net/base/host_port_pair.h"
Matt Menke3abc57c2019-01-10 21:48:4222#include "net/base/net_export.h"
Brianna Goldsteinc8ae1392022-10-10 20:09:4723#include "net/base/network_anonymization_key.h"
Matt Menke3abc57c2019-01-10 21:48:4224#include "net/dns/host_resolver.h"
Yoichiro Hibara6a4e282b2022-09-05 04:20:0225#include "net/dns/public/host_resolver_results.h"
dalykedd30d982019-12-16 15:31:1026#include "net/dns/public/resolve_error_info.h"
Ben Schwartz3ff4dc1e62021-04-27 21:15:2327#include "net/dns/public/secure_dns_policy.h"
Matt Menke3abc57c2019-01-10 21:48:4228#include "net/socket/connect_job.h"
29#include "net/socket/connection_attempts.h"
Eric Orthc98a3e62021-07-02 17:46:3730#include "url/scheme_host_port.h"
Matt Menke3abc57c2019-01-10 21:48:4231
32namespace net {
33
Matt Menke3abc57c2019-01-10 21:48:4234class NetLogWithSource;
Matt Menkea6f99ad2019-03-08 02:26:4335class SocketTag;
David Benjamin9f47d662022-05-13 21:09:0236class TransportConnectSubJob;
Matt Menke3abc57c2019-01-10 21:48:4237
Matt Menke3abc57c2019-01-10 21:48:4238class NET_EXPORT_PRIVATE TransportSocketParams
39 : public base::RefCounted<TransportSocketParams> {
40 public:
Eric Orthc98a3e62021-07-02 17:46:3741 // Representation of the destination endpoint of the transport
42 // socket/connection. Unlike ConnectJobFactory::Endpoint, this does not have a
43 // `using_ssl` field for schemeless endpoints because that has no meaning for
44 // transport parameters.
Victor Hugo Vianna Silvac6de5ce2025-03-18 16:33:1145 using Endpoint = std::variant<url::SchemeHostPort, HostPortPair>;
Eric Orthc98a3e62021-07-02 17:46:3746
Andrew Williams08a81e5d82023-12-19 17:10:3447 // `host_resolution_callback` will be invoked after the the hostname is
48 // resolved. `network_anonymization_key` is passed to the HostResolver to
49 // prevent cross-NAK leaks. If `host_resolution_callback` does not return OK,
50 // then the connection will be aborted with that value. `supported_alpns`
Brianna Goldsteinc8ae1392022-10-10 20:09:4751 // specifies ALPN protocols for selecting HTTPS/SVCB records. If empty,
52 // addresses from HTTPS/SVCB records will be ignored and only A/AAAA will be
53 // used.
Eric Orthc98a3e62021-07-02 17:46:3754 TransportSocketParams(Endpoint destination,
Brianna Goldsteinc8ae1392022-10-10 20:09:4755 NetworkAnonymizationKey network_anonymization_key,
Eric Orthc98a3e62021-07-02 17:46:3756 SecureDnsPolicy secure_dns_policy,
David Benjamin13072a42022-02-10 22:23:2157 OnHostResolutionCallback host_resolution_callback,
58 base::flat_set<std::string> supported_alpns);
Matt Menke3abc57c2019-01-10 21:48:4259
Peter Boström407869b2021-10-07 04:42:4860 TransportSocketParams(const TransportSocketParams&) = delete;
61 TransportSocketParams& operator=(const TransportSocketParams&) = delete;
62
Eric Orthc98a3e62021-07-02 17:46:3763 const Endpoint& destination() const { return destination_; }
Brianna Goldsteinc8ae1392022-10-10 20:09:4764 const NetworkAnonymizationKey& network_anonymization_key() const {
65 return network_anonymization_key_;
Matt Menkecd439232019-11-05 15:15:3366 }
Ben Schwartz3ff4dc1e62021-04-27 21:15:2367 SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; }
Matt Menke3abc57c2019-01-10 21:48:4268 const OnHostResolutionCallback& host_resolution_callback() const {
69 return host_resolution_callback_;
70 }
David Benjamin13072a42022-02-10 22:23:2171 const base::flat_set<std::string>& supported_alpns() const {
72 return supported_alpns_;
73 }
Matt Menke3abc57c2019-01-10 21:48:4274
75 private:
76 friend class base::RefCounted<TransportSocketParams>;
77 ~TransportSocketParams();
78
Eric Orthc98a3e62021-07-02 17:46:3779 const Endpoint destination_;
Brianna Goldsteinc8ae1392022-10-10 20:09:4780 const NetworkAnonymizationKey network_anonymization_key_;
Ben Schwartz3ff4dc1e62021-04-27 21:15:2381 const SecureDnsPolicy secure_dns_policy_;
Matt Menke3abc57c2019-01-10 21:48:4282 const OnHostResolutionCallback host_resolution_callback_;
David Benjamin13072a42022-02-10 22:23:2183 const base::flat_set<std::string> supported_alpns_;
Matt Menke3abc57c2019-01-10 21:48:4284};
85
86// TransportConnectJob handles the host resolution necessary for socket creation
87// and the transport (likely TCP) connect. TransportConnectJob also has fallback
88// logic for IPv6 connect() timeouts (which may happen due to networks / routers
89// with broken IPv6 support). Those timeouts take 20s, so rather than make the
90// user wait 20s for the timeout to fire, we use a fallback timer
David Benjaminfac74eb2022-05-03 17:37:3791// (kIPv6FallbackTime) and start a connect() to a IPv4 address if the timer
Matt Menke3abc57c2019-01-10 21:48:4292// fires. Then we race the IPv4 connect() against the IPv6 connect() (which has
93// a headstart) and return the one that completes first to the socket pool.
94class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob {
95 public:
Eric Ortha9b8be02021-06-29 23:09:0896 class NET_EXPORT_PRIVATE Factory {
97 public:
98 Factory() = default;
99 virtual ~Factory() = default;
100
101 virtual std::unique_ptr<TransportConnectJob> Create(
102 RequestPriority priority,
103 const SocketTag& socket_tag,
104 const CommonConnectJobParams* common_connect_job_params,
105 const scoped_refptr<TransportSocketParams>& params,
106 Delegate* delegate,
107 const NetLogWithSource* net_log);
108 };
109
Matt Menke3abc57c2019-01-10 21:48:42110 // In cases where both IPv6 and IPv4 addresses were returned from DNS,
111 // TransportConnectJobs will start a second connection attempt to just the
David Benjaminfac74eb2022-05-03 17:37:37112 // IPv4 addresses after this much time. (This is "Happy Eyeballs".)
113 //
114 // TODO(willchan): Base this off RTT instead of statically setting it. Note we
115 // choose a timeout that is different from the backup connect job timer so
116 // they don't synchronize.
117 static constexpr base::TimeDelta kIPv6FallbackTime = base::Milliseconds(300);
Matt Menke3abc57c2019-01-10 21:48:42118
David Benjamindc5fd6a2022-03-24 23:00:41119 struct NET_EXPORT_PRIVATE EndpointResultOverride {
120 EndpointResultOverride(HostResolverEndpointResult result,
121 std::set<std::string> dns_aliases);
122 EndpointResultOverride(EndpointResultOverride&&);
123 EndpointResultOverride(const EndpointResultOverride&);
124 ~EndpointResultOverride();
David Benjamin9f47d662022-05-13 21:09:02125 EndpointResultOverride& operator=(EndpointResultOverride&&) = default;
126 EndpointResultOverride& operator=(const EndpointResultOverride&) = default;
David Benjamindc5fd6a2022-03-24 23:00:41127
128 HostResolverEndpointResult result;
129 std::set<std::string> dns_aliases;
130 };
131
Matt Menkeab90584b02019-01-18 08:22:34132 TransportConnectJob(RequestPriority priority,
Matt Menkea6f99ad2019-03-08 02:26:43133 const SocketTag& socket_tag,
134 const CommonConnectJobParams* common_connect_job_params,
Matt Menkeab90584b02019-01-18 08:22:34135 const scoped_refptr<TransportSocketParams>& params,
Matt Menke1a6c92d2019-02-23 00:25:38136 Delegate* delegate,
David Benjamindc5fd6a2022-03-24 23:00:41137 const NetLogWithSource* net_log,
Arthur Sonzogni4787fce2024-02-08 13:42:48138 std::optional<EndpointResultOverride>
139 endpoint_result_override = std::nullopt);
Peter Boström293b1342021-09-22 17:31:43140
141 TransportConnectJob(const TransportConnectJob&) = delete;
142 TransportConnectJob& operator=(const TransportConnectJob&) = delete;
143
Matt Menke3abc57c2019-01-10 21:48:42144 ~TransportConnectJob() override;
145
146 // ConnectJob methods.
147 LoadState GetLoadState() const override;
Matt Menke141b87f22019-01-30 02:43:03148 bool HasEstablishedConnection() const override;
Matt Menke6030ed9f2019-04-11 20:25:55149 ConnectionAttempts GetConnectionAttempts() const override;
dalykedd30d982019-12-16 15:31:10150 ResolveErrorInfo GetResolveErrorInfo() const override;
Arthur Sonzogni4787fce2024-02-08 13:42:48151 std::optional<HostResolverEndpointResult> GetHostResolverEndpointResult()
David Benjamindc5fd6a2022-03-24 23:00:41152 const override;
153
Matt Menke3abc57c2019-01-10 21:48:42154 static base::TimeDelta ConnectionTimeout();
155
156 private:
David Benjamin9f47d662022-05-13 21:09:02157 friend class TransportConnectSubJob;
158
Matt Menke3abc57c2019-01-10 21:48:42159 enum State {
160 STATE_RESOLVE_HOST,
161 STATE_RESOLVE_HOST_COMPLETE,
David Benjamin13072a42022-02-10 22:23:21162 STATE_RESOLVE_HOST_CALLBACK_COMPLETE,
Matt Menke3abc57c2019-01-10 21:48:42163 STATE_TRANSPORT_CONNECT,
164 STATE_TRANSPORT_CONNECT_COMPLETE,
165 STATE_NONE,
166 };
167
David Benjamin9f47d662022-05-13 21:09:02168 // Although it is not strictly necessary, it makes the code simpler if each
169 // subjob knows what type it is.
170 enum SubJobType { SUB_JOB_IPV4, SUB_JOB_IPV6 };
171
Matt Menke3abc57c2019-01-10 21:48:42172 void OnIOComplete(int result);
173 int DoLoop(int result);
174
175 int DoResolveHost();
176 int DoResolveHostComplete(int result);
David Benjamin13072a42022-02-10 22:23:21177 int DoResolveHostCallbackComplete();
Matt Menke3abc57c2019-01-10 21:48:42178 int DoTransportConnect();
David Benjamin9f47d662022-05-13 21:09:02179 int DoTransportConnectComplete(int result);
Matt Menke3abc57c2019-01-10 21:48:42180
David Benjamin9f47d662022-05-13 21:09:02181 // Helper method called called when a SubJob completes, synchronously
182 // or asynchronously. Returns `ERR_IO_PENDING` if there is more work to
183 // do and another error if completed. It's up to the caller to manage
184 // advancing `DoLoop` if a value other than `ERR_IO_PENDING` is returned.
185 int HandleSubJobComplete(int result, TransportConnectSubJob* job);
186 // Called back from a SubJob when it completes. Invokes `OnIOComplete`,
187 // re-entering `DoLoop`, if there is no more work to do. Must not
188 // be called from within `DoLoop`.
189 void OnSubJobComplete(int result, TransportConnectSubJob* job);
190
191 // Called from |fallback_timer_|.
192 void StartIPv4JobAsync();
Matt Menke3abc57c2019-01-10 21:48:42193
194 // Begins the host resolution and the TCP connect. Returns OK on success
195 // and ERR_IO_PENDING if it cannot immediately service the request.
196 // Otherwise, it returns a net error code.
197 int ConnectInternal() override;
198
Matt Menke3abc57c2019-01-10 21:48:42199 void ChangePriorityInternal(RequestPriority priority) override;
200
David Benjamin6e089be2022-02-11 18:22:21201 // Returns whether the client should be SVCB-optional when connecting to
202 // `results`.
203 bool IsSvcbOptional(
204 base::span<const HostResolverEndpointResult> results) const;
205
206 // Returns whether `result` is usable for this connection. If `svcb_optional`
207 // is true, the non-HTTPS/SVCB fallback is allowed.
208 bool IsEndpointResultUsable(const HostResolverEndpointResult& result,
209 bool svcb_optional) const;
David Benjamin13072a42022-02-10 22:23:21210
David Benjamin9f47d662022-05-13 21:09:02211 // Returns the `HostResolverEndpointResult` for the current subjobs.
212 const HostResolverEndpointResult& GetEndpointResultForCurrentSubJobs() const;
David Benjamin13072a42022-02-10 22:23:21213
Matt Menke3abc57c2019-01-10 21:48:42214 scoped_refptr<TransportSocketParams> params_;
Eric Orth7287eb602019-02-13 19:49:55215 std::unique_ptr<HostResolver::ResolveHostRequest> request_;
David Benjamin13072a42022-02-10 22:23:21216 std::vector<HostResolverEndpointResult> endpoint_results_;
217 size_t current_endpoint_result_ = 0;
218 std::set<std::string> dns_aliases_;
David Benjamindc5fd6a2022-03-24 23:00:41219 bool has_dns_override_ = false;
Matt Menke3abc57c2019-01-10 21:48:42220
Tsuyoshi Horo2ec06e002022-06-09 01:38:59221 State next_state_ = STATE_NONE;
Matt Menke3abc57c2019-01-10 21:48:42222
David Benjamin9f47d662022-05-13 21:09:02223 // The addresses are divided into IPv4 and IPv6, which are performed partially
224 // in parallel. If the list of IPv6 addresses is non-empty, then the IPv6 jobs
225 // go first, followed after `kIPv6FallbackTime` by the IPv4 addresses. The
226 // first sub-job to establish a connection wins. If one sub-job fails, the
227 // other one is launched if needed, and we wait for it to complete.
228 std::unique_ptr<TransportConnectSubJob> ipv4_job_;
229 std::unique_ptr<TransportConnectSubJob> ipv6_job_;
Matt Menke3abc57c2019-01-10 21:48:42230
Matt Menke3abc57c2019-01-10 21:48:42231 base::OneShotTimer fallback_timer_;
Matt Menke3abc57c2019-01-10 21:48:42232
dalykedd30d982019-12-16 15:31:10233 ResolveErrorInfo resolve_error_info_;
Matt Menke3abc57c2019-01-10 21:48:42234 ConnectionAttempts connection_attempts_;
Matt Menke3abc57c2019-01-10 21:48:42235
Jeremy Romand54000b22019-07-08 18:40:16236 base::WeakPtrFactory<TransportConnectJob> weak_ptr_factory_{this};
Matt Menke3abc57c2019-01-10 21:48:42237};
238
239} // namespace net
240
241#endif // NET_SOCKET_TRANSPORT_CONNECT_JOB_H_