transport_connect_job.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef NET_SOCKET_TRANSPORT_CONNECT_JOB_H_
  5. #define NET_SOCKET_TRANSPORT_CONNECT_JOB_H_
  6. #include <memory>
  7. #include <set>
  8. #include <string>
  9. #include <vector>
  10. #include "base/containers/flat_set.h"
  11. #include "base/containers/span.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/memory/weak_ptr.h"
  14. #include "base/time/time.h"
  15. #include "base/timer/timer.h"
  16. #include "net/base/host_port_pair.h"
  17. #include "net/base/net_export.h"
  18. #include "net/base/network_isolation_key.h"
  19. #include "net/dns/host_resolver.h"
  20. #include "net/dns/host_resolver_results.h"
  21. #include "net/dns/public/resolve_error_info.h"
  22. #include "net/dns/public/secure_dns_policy.h"
  23. #include "net/socket/connect_job.h"
  24. #include "net/socket/connection_attempts.h"
  25. #include "third_party/abseil-cpp/absl/types/optional.h"
  26. #include "third_party/abseil-cpp/absl/types/variant.h"
  27. #include "url/scheme_host_port.h"
  28. namespace net {
  29. class NetLogWithSource;
  30. class SocketTag;
  31. class TransportConnectSubJob;
  32. class NET_EXPORT_PRIVATE TransportSocketParams
  33. : public base::RefCounted<TransportSocketParams> {
  34. public:
  35. // Representation of the destination endpoint of the transport
  36. // socket/connection. Unlike ConnectJobFactory::Endpoint, this does not have a
  37. // `using_ssl` field for schemeless endpoints because that has no meaning for
  38. // transport parameters.
  39. using Endpoint = absl::variant<url::SchemeHostPort, HostPortPair>;
  40. // |host_resolution_callback| will be invoked after the the hostname is
  41. // resolved. |network_isolation_key| is passed to the HostResolver to prevent
  42. // cross-NIK leaks. If |host_resolution_callback| does not return OK, then the
  43. // connection will be aborted with that value. |supported_alpns| specifies
  44. // ALPN protocols for selecting HTTPS/SVCB records. If empty, addresses from
  45. // HTTPS/SVCB records will be ignored and only A/AAAA will be used.
  46. TransportSocketParams(Endpoint destination,
  47. NetworkIsolationKey network_isolation_key,
  48. SecureDnsPolicy secure_dns_policy,
  49. OnHostResolutionCallback host_resolution_callback,
  50. base::flat_set<std::string> supported_alpns);
  51. TransportSocketParams(const TransportSocketParams&) = delete;
  52. TransportSocketParams& operator=(const TransportSocketParams&) = delete;
  53. const Endpoint& destination() const { return destination_; }
  54. const NetworkIsolationKey& network_isolation_key() const {
  55. return network_isolation_key_;
  56. }
  57. SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; }
  58. const OnHostResolutionCallback& host_resolution_callback() const {
  59. return host_resolution_callback_;
  60. }
  61. const base::flat_set<std::string>& supported_alpns() const {
  62. return supported_alpns_;
  63. }
  64. private:
  65. friend class base::RefCounted<TransportSocketParams>;
  66. ~TransportSocketParams();
  67. const Endpoint destination_;
  68. const NetworkIsolationKey network_isolation_key_;
  69. const SecureDnsPolicy secure_dns_policy_;
  70. const OnHostResolutionCallback host_resolution_callback_;
  71. const base::flat_set<std::string> supported_alpns_;
  72. };
  73. // TransportConnectJob handles the host resolution necessary for socket creation
  74. // and the transport (likely TCP) connect. TransportConnectJob also has fallback
  75. // logic for IPv6 connect() timeouts (which may happen due to networks / routers
  76. // with broken IPv6 support). Those timeouts take 20s, so rather than make the
  77. // user wait 20s for the timeout to fire, we use a fallback timer
  78. // (kIPv6FallbackTime) and start a connect() to a IPv4 address if the timer
  79. // fires. Then we race the IPv4 connect() against the IPv6 connect() (which has
  80. // a headstart) and return the one that completes first to the socket pool.
  81. class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob {
  82. public:
  83. class NET_EXPORT_PRIVATE Factory {
  84. public:
  85. Factory() = default;
  86. virtual ~Factory() = default;
  87. virtual std::unique_ptr<TransportConnectJob> Create(
  88. RequestPriority priority,
  89. const SocketTag& socket_tag,
  90. const CommonConnectJobParams* common_connect_job_params,
  91. const scoped_refptr<TransportSocketParams>& params,
  92. Delegate* delegate,
  93. const NetLogWithSource* net_log);
  94. };
  95. // In cases where both IPv6 and IPv4 addresses were returned from DNS,
  96. // TransportConnectJobs will start a second connection attempt to just the
  97. // IPv4 addresses after this much time. (This is "Happy Eyeballs".)
  98. //
  99. // TODO(willchan): Base this off RTT instead of statically setting it. Note we
  100. // choose a timeout that is different from the backup connect job timer so
  101. // they don't synchronize.
  102. static constexpr base::TimeDelta kIPv6FallbackTime = base::Milliseconds(300);
  103. struct NET_EXPORT_PRIVATE EndpointResultOverride {
  104. EndpointResultOverride(HostResolverEndpointResult result,
  105. std::set<std::string> dns_aliases);
  106. EndpointResultOverride(EndpointResultOverride&&);
  107. EndpointResultOverride(const EndpointResultOverride&);
  108. ~EndpointResultOverride();
  109. EndpointResultOverride& operator=(EndpointResultOverride&&) = default;
  110. EndpointResultOverride& operator=(const EndpointResultOverride&) = default;
  111. HostResolverEndpointResult result;
  112. std::set<std::string> dns_aliases;
  113. };
  114. TransportConnectJob(RequestPriority priority,
  115. const SocketTag& socket_tag,
  116. const CommonConnectJobParams* common_connect_job_params,
  117. const scoped_refptr<TransportSocketParams>& params,
  118. Delegate* delegate,
  119. const NetLogWithSource* net_log,
  120. absl::optional<EndpointResultOverride>
  121. endpoint_result_override = absl::nullopt);
  122. TransportConnectJob(const TransportConnectJob&) = delete;
  123. TransportConnectJob& operator=(const TransportConnectJob&) = delete;
  124. ~TransportConnectJob() override;
  125. // ConnectJob methods.
  126. LoadState GetLoadState() const override;
  127. bool HasEstablishedConnection() const override;
  128. ConnectionAttempts GetConnectionAttempts() const override;
  129. ResolveErrorInfo GetResolveErrorInfo() const override;
  130. absl::optional<HostResolverEndpointResult> GetHostResolverEndpointResult()
  131. const override;
  132. static base::TimeDelta ConnectionTimeout();
  133. private:
  134. friend class TransportConnectSubJob;
  135. enum State {
  136. STATE_RESOLVE_HOST,
  137. STATE_RESOLVE_HOST_COMPLETE,
  138. STATE_RESOLVE_HOST_CALLBACK_COMPLETE,
  139. STATE_TRANSPORT_CONNECT,
  140. STATE_TRANSPORT_CONNECT_COMPLETE,
  141. STATE_NONE,
  142. };
  143. // Although it is not strictly necessary, it makes the code simpler if each
  144. // subjob knows what type it is.
  145. enum SubJobType { SUB_JOB_IPV4, SUB_JOB_IPV6 };
  146. void OnIOComplete(int result);
  147. int DoLoop(int result);
  148. int DoResolveHost();
  149. int DoResolveHostComplete(int result);
  150. int DoResolveHostCallbackComplete();
  151. int DoTransportConnect();
  152. int DoTransportConnectComplete(int result);
  153. // Helper method called called when a SubJob completes, synchronously
  154. // or asynchronously. Returns `ERR_IO_PENDING` if there is more work to
  155. // do and another error if completed. It's up to the caller to manage
  156. // advancing `DoLoop` if a value other than `ERR_IO_PENDING` is returned.
  157. int HandleSubJobComplete(int result, TransportConnectSubJob* job);
  158. // Called back from a SubJob when it completes. Invokes `OnIOComplete`,
  159. // re-entering `DoLoop`, if there is no more work to do. Must not
  160. // be called from within `DoLoop`.
  161. void OnSubJobComplete(int result, TransportConnectSubJob* job);
  162. // Called from |fallback_timer_|.
  163. void StartIPv4JobAsync();
  164. // Begins the host resolution and the TCP connect. Returns OK on success
  165. // and ERR_IO_PENDING if it cannot immediately service the request.
  166. // Otherwise, it returns a net error code.
  167. int ConnectInternal() override;
  168. void ChangePriorityInternal(RequestPriority priority) override;
  169. // Returns whether the client should be SVCB-optional when connecting to
  170. // `results`.
  171. bool IsSvcbOptional(
  172. base::span<const HostResolverEndpointResult> results) const;
  173. // Returns whether `result` is usable for this connection. If `svcb_optional`
  174. // is true, the non-HTTPS/SVCB fallback is allowed.
  175. bool IsEndpointResultUsable(const HostResolverEndpointResult& result,
  176. bool svcb_optional) const;
  177. // Returns the `HostResolverEndpointResult` for the current subjobs.
  178. const HostResolverEndpointResult& GetEndpointResultForCurrentSubJobs() const;
  179. scoped_refptr<TransportSocketParams> params_;
  180. std::unique_ptr<HostResolver::ResolveHostRequest> request_;
  181. std::vector<HostResolverEndpointResult> endpoint_results_;
  182. size_t current_endpoint_result_ = 0;
  183. std::set<std::string> dns_aliases_;
  184. bool has_dns_override_ = false;
  185. State next_state_ = STATE_NONE;
  186. // The addresses are divided into IPv4 and IPv6, which are performed partially
  187. // in parallel. If the list of IPv6 addresses is non-empty, then the IPv6 jobs
  188. // go first, followed after `kIPv6FallbackTime` by the IPv4 addresses. The
  189. // first sub-job to establish a connection wins. If one sub-job fails, the
  190. // other one is launched if needed, and we wait for it to complete.
  191. std::unique_ptr<TransportConnectSubJob> ipv4_job_;
  192. std::unique_ptr<TransportConnectSubJob> ipv6_job_;
  193. base::OneShotTimer fallback_timer_;
  194. ResolveErrorInfo resolve_error_info_;
  195. ConnectionAttempts connection_attempts_;
  196. base::WeakPtrFactory<TransportConnectJob> weak_ptr_factory_{this};
  197. };
  198. } // namespace net
  199. #endif // NET_SOCKET_TRANSPORT_CONNECT_JOB_H_