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