• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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_DNS_STALE_HOST_RESOLVER_H_
6 #define NET_DNS_STALE_HOST_RESOLVER_H_
7 
8 #include <memory>
9 #include <optional>
10 #include <unordered_map>
11 
12 #include "base/memory/raw_ptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/time/default_tick_clock.h"
15 #include "base/values.h"
16 #include "net/base/completion_once_callback.h"
17 #include "net/base/net_export.h"
18 #include "net/base/network_anonymization_key.h"
19 #include "net/dns/host_resolver.h"
20 #include "net/log/net_log_with_source.h"
21 #include "url/scheme_host_port.h"
22 
23 namespace base {
24 class TickClock;
25 }  // namespace base
26 
27 namespace net {
28 class ContextHostResolver;
29 
30 namespace {
31 class StaleHostResolverTest;
32 }  // namespace
33 
34 // A HostResolver that wraps a ContextHostResolver and uses it to make requests,
35 // but "impatiently" returns stale data (if available and usable) after a delay,
36 // to reduce DNS latency at the expense of accuracy.
37 class StaleHostResolver : public HostResolver {
38  public:
39   struct NET_EXPORT StaleOptions {
40     StaleOptions();
41 
42     // How long to wait before returning stale data, if available.
43     base::TimeDelta delay;
44 
45     // If positive, how long stale data can be past the expiration time before
46     // it's considered unusable. If zero or negative, stale data can be used
47     // indefinitely.
48     base::TimeDelta max_expired_time;
49 
50     // If set, stale data from previous networks is usable; if clear, it's not.
51     //
52     // If the other network had a working, correct DNS setup, this can increase
53     // the availability of useful stale results.
54     //
55     // If the other network had a broken (e.g. hijacked for captive portal) DNS
56     // setup, this will instead end up returning useless results.
57     bool allow_other_network;
58 
59     // If positive, the maximum number of times a stale entry can be used. If
60     // zero, there is no limit.
61     int max_stale_uses;
62 
63     // If network resolution returns ERR_NAME_NOT_RESOLVED, use stale result if
64     // available.
65     bool use_stale_on_name_not_resolved;
66   };
67 
68   // Creates a StaleHostResolver that uses `inner_resolver` for actual
69   // resolution, but potentially returns stale data according to
70   // `stale_options`.
71   NET_EXPORT StaleHostResolver(
72       std::unique_ptr<ContextHostResolver> inner_resolver,
73       const StaleOptions& stale_options);
74 
75   StaleHostResolver(const StaleHostResolver&) = delete;
76   StaleHostResolver& operator=(const StaleHostResolver&) = delete;
77 
78   ~StaleHostResolver() override;
79 
80   // HostResolver implementation:
81 
82   void OnShutdown() override;
83 
84   // Resolves as a regular HostResolver, but if stale data is available and
85   // usable (according to the options passed to the constructor), and fresh data
86   // is not returned before the specified delay, returns the stale data instead.
87   //
88   // If stale data is returned, the StaleHostResolver allows the underlying
89   // request to continue in order to repopulate the cache.
90   std::unique_ptr<ResolveHostRequest> CreateRequest(
91       url::SchemeHostPort host,
92       NetworkAnonymizationKey network_anonymization_key,
93       NetLogWithSource net_log,
94       std::optional<ResolveHostParameters> optional_parameters) override;
95   std::unique_ptr<ResolveHostRequest> CreateRequest(
96       const HostPortPair& host,
97       const NetworkAnonymizationKey& network_anonymization_key,
98       const NetLogWithSource& net_log,
99       const std::optional<ResolveHostParameters>& optional_parameters) override;
100   std::unique_ptr<ServiceEndpointRequest> CreateServiceEndpointRequest(
101       Host host,
102       NetworkAnonymizationKey network_anonymization_key,
103       NetLogWithSource net_log,
104       ResolveHostParameters parameters) override;
105 
106   // The remaining public methods pass through to the inner resolver:
107 
108   HostCache* GetHostCache() override;
109   base::Value::Dict GetDnsConfigAsValue() const override;
110   void SetRequestContext(URLRequestContext* request_context) override;
111 
112   // Set `tick_clock_` for testing. Must be set before issuing any requests.
113   NET_EXPORT void SetTickClockForTesting(const base::TickClock* tick_clock);
114 
set_inner_resolver_for_testing(std::unique_ptr<ContextHostResolver> inner_resolver)115   void set_inner_resolver_for_testing(
116       std::unique_ptr<ContextHostResolver> inner_resolver) {
117     inner_resolver_ = std::move(inner_resolver);
118   }
119 
120  private:
121   class RequestImpl;
122   friend class StaleHostResolverTest;
123 
124   // Called on completion of `network_request` when completed asynchronously (a
125   // "network" request). Determines if the request is owned by a RequestImpl or
126   // if it is a detached request and handles appropriately.
127   void OnNetworkRequestComplete(ResolveHostRequest* network_request,
128                                 base::WeakPtr<RequestImpl> stale_request,
129                                 int error);
130 
131   // Detach an inner request from a RequestImpl, letting it finish (and populate
132   // the host cache) as long as `this` is not destroyed.
133   void DetachRequest(std::unique_ptr<ResolveHostRequest> request);
134 
135   // The underlying ContextHostResolver that will be used to make cache and
136   // network requests.
137   std::unique_ptr<ContextHostResolver> inner_resolver_;
138 
139   // Shared instance of tick clock, overridden for testing.
140   raw_ptr<const base::TickClock> tick_clock_ =
141       base::DefaultTickClock::GetInstance();
142 
143   // Options that govern when a stale response can or can't be returned.
144   const StaleOptions options_;
145 
146   // Requests not used for returned results but allowed to continue (unless
147   // `this` is destroyed) to backfill the cache.
148   std::unordered_map<ResolveHostRequest*, std::unique_ptr<ResolveHostRequest>>
149       detached_requests_;
150 
151   base::WeakPtrFactory<StaleHostResolver> weak_ptr_factory_{this};
152 };
153 
154 }  // namespace net
155 
156 #endif  // NET_DNS_STALE_HOST_RESOLVER_H_
157