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