xref: /aosp_15_r20/external/cronet/net/dns/host_cache.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_DNS_HOST_CACHE_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_DNS_HOST_CACHE_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <functional>
11*6777b538SAndroid Build Coastguard Worker #include <map>
12*6777b538SAndroid Build Coastguard Worker #include <memory>
13*6777b538SAndroid Build Coastguard Worker #include <optional>
14*6777b538SAndroid Build Coastguard Worker #include <ostream>
15*6777b538SAndroid Build Coastguard Worker #include <set>
16*6777b538SAndroid Build Coastguard Worker #include <string>
17*6777b538SAndroid Build Coastguard Worker #include <string_view>
18*6777b538SAndroid Build Coastguard Worker #include <tuple>
19*6777b538SAndroid Build Coastguard Worker #include <utility>
20*6777b538SAndroid Build Coastguard Worker #include <vector>
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/numerics/clamped_math.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/types/optional_util.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/values.h"
30*6777b538SAndroid Build Coastguard Worker #include "net/base/address_family.h"
31*6777b538SAndroid Build Coastguard Worker #include "net/base/connection_endpoint_metadata.h"
32*6777b538SAndroid Build Coastguard Worker #include "net/base/expiring_cache.h"
33*6777b538SAndroid Build Coastguard Worker #include "net/base/host_port_pair.h"
34*6777b538SAndroid Build Coastguard Worker #include "net/base/ip_endpoint.h"
35*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
36*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
37*6777b538SAndroid Build Coastguard Worker #include "net/base/network_anonymization_key.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_query_type.h"
39*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/host_resolver_results.h"
40*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/host_resolver_source.h"
41*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_capture_mode.h"
42*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/types/variant.h"
43*6777b538SAndroid Build Coastguard Worker #include "url/scheme_host_port.h"
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker namespace base {
46*6777b538SAndroid Build Coastguard Worker class TickClock;
47*6777b538SAndroid Build Coastguard Worker }  // namespace base
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker namespace net {
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker class HostResolverInternalResult;
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker // Cache used by HostResolver to map hostnames to their resolved result.
54*6777b538SAndroid Build Coastguard Worker class NET_EXPORT HostCache {
55*6777b538SAndroid Build Coastguard Worker  public:
56*6777b538SAndroid Build Coastguard Worker   struct NET_EXPORT Key {
57*6777b538SAndroid Build Coastguard Worker     // Hostnames in `host` must not be IP literals. IP literals should be
58*6777b538SAndroid Build Coastguard Worker     // resolved directly to the IP address and not be stored/queried in
59*6777b538SAndroid Build Coastguard Worker     // HostCache.
60*6777b538SAndroid Build Coastguard Worker     Key(absl::variant<url::SchemeHostPort, std::string> host,
61*6777b538SAndroid Build Coastguard Worker         DnsQueryType dns_query_type,
62*6777b538SAndroid Build Coastguard Worker         HostResolverFlags host_resolver_flags,
63*6777b538SAndroid Build Coastguard Worker         HostResolverSource host_resolver_source,
64*6777b538SAndroid Build Coastguard Worker         const NetworkAnonymizationKey& network_anonymization_key);
65*6777b538SAndroid Build Coastguard Worker     Key();
66*6777b538SAndroid Build Coastguard Worker     Key(const Key& key);
67*6777b538SAndroid Build Coastguard Worker     Key(Key&& key);
68*6777b538SAndroid Build Coastguard Worker     ~Key();
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker     // This is a helper used in comparing keys. The order of comparisons of
71*6777b538SAndroid Build Coastguard Worker     // `Key` fields is arbitrary, but the tuple is constructed with
72*6777b538SAndroid Build Coastguard Worker     // `dns_query_type` and `host_resolver_flags` before `host` under the
73*6777b538SAndroid Build Coastguard Worker     // assumption that integer comparisons are faster than string comparisons.
GetTupleKey74*6777b538SAndroid Build Coastguard Worker     static auto GetTuple(const Key* key) {
75*6777b538SAndroid Build Coastguard Worker       return std::tie(key->dns_query_type, key->host_resolver_flags, key->host,
76*6777b538SAndroid Build Coastguard Worker                       key->host_resolver_source, key->network_anonymization_key,
77*6777b538SAndroid Build Coastguard Worker                       key->secure);
78*6777b538SAndroid Build Coastguard Worker     }
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker     bool operator==(const Key& other) const {
81*6777b538SAndroid Build Coastguard Worker       return GetTuple(this) == GetTuple(&other);
82*6777b538SAndroid Build Coastguard Worker     }
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker     bool operator!=(const Key& other) const {
85*6777b538SAndroid Build Coastguard Worker       return GetTuple(this) != GetTuple(&other);
86*6777b538SAndroid Build Coastguard Worker     }
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker     bool operator<(const Key& other) const {
89*6777b538SAndroid Build Coastguard Worker       return GetTuple(this) < GetTuple(&other);
90*6777b538SAndroid Build Coastguard Worker     }
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker     absl::variant<url::SchemeHostPort, std::string> host;
93*6777b538SAndroid Build Coastguard Worker     DnsQueryType dns_query_type = DnsQueryType::UNSPECIFIED;
94*6777b538SAndroid Build Coastguard Worker     HostResolverFlags host_resolver_flags = 0;
95*6777b538SAndroid Build Coastguard Worker     HostResolverSource host_resolver_source = HostResolverSource::ANY;
96*6777b538SAndroid Build Coastguard Worker     NetworkAnonymizationKey network_anonymization_key;
97*6777b538SAndroid Build Coastguard Worker     bool secure = false;
98*6777b538SAndroid Build Coastguard Worker   };
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker   struct NET_EXPORT EntryStaleness {
101*6777b538SAndroid Build Coastguard Worker     // Time since the entry's TTL has expired. Negative if not expired.
102*6777b538SAndroid Build Coastguard Worker     base::TimeDelta expired_by;
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker     // Number of network changes since this result was cached.
105*6777b538SAndroid Build Coastguard Worker     int network_changes;
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker     // Number of hits to the cache entry while stale (expired or past-network).
108*6777b538SAndroid Build Coastguard Worker     int stale_hits;
109*6777b538SAndroid Build Coastguard Worker 
is_staleEntryStaleness110*6777b538SAndroid Build Coastguard Worker     bool is_stale() const {
111*6777b538SAndroid Build Coastguard Worker       return network_changes > 0 || expired_by >= base::TimeDelta();
112*6777b538SAndroid Build Coastguard Worker     }
113*6777b538SAndroid Build Coastguard Worker   };
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker   // Stores the latest address list that was looked up for a hostname.
116*6777b538SAndroid Build Coastguard Worker   class NET_EXPORT Entry {
117*6777b538SAndroid Build Coastguard Worker    public:
118*6777b538SAndroid Build Coastguard Worker     enum Source : int {
119*6777b538SAndroid Build Coastguard Worker       // Address list was obtained from an unknown source.
120*6777b538SAndroid Build Coastguard Worker       SOURCE_UNKNOWN,
121*6777b538SAndroid Build Coastguard Worker       // Address list was obtained via a DNS lookup.
122*6777b538SAndroid Build Coastguard Worker       SOURCE_DNS,
123*6777b538SAndroid Build Coastguard Worker       // Address list was obtained by searching a HOSTS file.
124*6777b538SAndroid Build Coastguard Worker       SOURCE_HOSTS,
125*6777b538SAndroid Build Coastguard Worker       // Address list was a preset from the DnsConfig.
126*6777b538SAndroid Build Coastguard Worker       SOURCE_CONFIG,
127*6777b538SAndroid Build Coastguard Worker     };
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker     // |ttl=std::nullopt| for unknown TTL.
130*6777b538SAndroid Build Coastguard Worker     template <typename T>
Entry(int error,T && results,Source source,std::optional<base::TimeDelta> ttl)131*6777b538SAndroid Build Coastguard Worker     Entry(int error,
132*6777b538SAndroid Build Coastguard Worker           T&& results,
133*6777b538SAndroid Build Coastguard Worker           Source source,
134*6777b538SAndroid Build Coastguard Worker           std::optional<base::TimeDelta> ttl)
135*6777b538SAndroid Build Coastguard Worker         : error_(error),
136*6777b538SAndroid Build Coastguard Worker           source_(source),
137*6777b538SAndroid Build Coastguard Worker           ttl_(ttl ? ttl.value() : kUnknownTtl) {
138*6777b538SAndroid Build Coastguard Worker       DCHECK(!ttl || ttl.value() >= base::TimeDelta());
139*6777b538SAndroid Build Coastguard Worker       SetResult(std::forward<T>(results));
140*6777b538SAndroid Build Coastguard Worker     }
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker     // Use when |ttl| is unknown.
143*6777b538SAndroid Build Coastguard Worker     template <typename T>
Entry(int error,T && results,Source source)144*6777b538SAndroid Build Coastguard Worker     Entry(int error, T&& results, Source source)
145*6777b538SAndroid Build Coastguard Worker         : Entry(error, std::forward<T>(results), source, std::nullopt) {}
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker     // Use for address entries.
148*6777b538SAndroid Build Coastguard Worker     Entry(int error,
149*6777b538SAndroid Build Coastguard Worker           std::vector<IPEndPoint> ip_endpoints,
150*6777b538SAndroid Build Coastguard Worker           std::set<std::string> aliases,
151*6777b538SAndroid Build Coastguard Worker           Source source,
152*6777b538SAndroid Build Coastguard Worker           std::optional<base::TimeDelta> ttl = std::nullopt);
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker     // For errors with no |results|.
155*6777b538SAndroid Build Coastguard Worker     Entry(int error,
156*6777b538SAndroid Build Coastguard Worker           Source source,
157*6777b538SAndroid Build Coastguard Worker           std::optional<base::TimeDelta> ttl = std::nullopt);
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker     // Adaptor to construct from HostResolverInternalResults. Only supports
160*6777b538SAndroid Build Coastguard Worker     // results extracted from a single DnsTransaction. `empty_source` is Source
161*6777b538SAndroid Build Coastguard Worker     // to assume if `results` is empty of any results from which Source can be
162*6777b538SAndroid Build Coastguard Worker     // read.
163*6777b538SAndroid Build Coastguard Worker     Entry(const std::set<std::unique_ptr<HostResolverInternalResult>>& results,
164*6777b538SAndroid Build Coastguard Worker           base::Time now,
165*6777b538SAndroid Build Coastguard Worker           base::TimeTicks now_ticks,
166*6777b538SAndroid Build Coastguard Worker           Source empty_source = SOURCE_UNKNOWN);
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker     Entry(const Entry& entry);
169*6777b538SAndroid Build Coastguard Worker     Entry(Entry&& entry);
170*6777b538SAndroid Build Coastguard Worker     ~Entry();
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker     Entry& operator=(const Entry& entry);
173*6777b538SAndroid Build Coastguard Worker     Entry& operator=(Entry&& entry);
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker     bool operator==(const Entry& other) const {
176*6777b538SAndroid Build Coastguard Worker       return ContentsEqual(other) &&
177*6777b538SAndroid Build Coastguard Worker              std::tie(source_, pinning_, ttl_, expires_, network_changes_,
178*6777b538SAndroid Build Coastguard Worker                       total_hits_, stale_hits_) ==
179*6777b538SAndroid Build Coastguard Worker                  std::tie(other.source_, other.pinning_, other.ttl_,
180*6777b538SAndroid Build Coastguard Worker                           other.expires_, other.network_changes_,
181*6777b538SAndroid Build Coastguard Worker                           other.total_hits_, other.stale_hits_);
182*6777b538SAndroid Build Coastguard Worker     }
183*6777b538SAndroid Build Coastguard Worker 
ContentsEqual(const Entry & other)184*6777b538SAndroid Build Coastguard Worker     bool ContentsEqual(const Entry& other) const {
185*6777b538SAndroid Build Coastguard Worker       return std::tie(error_, ip_endpoints_, endpoint_metadatas_, aliases_,
186*6777b538SAndroid Build Coastguard Worker                       text_records_, hostnames_, https_record_compatibility_,
187*6777b538SAndroid Build Coastguard Worker                       canonical_names_) ==
188*6777b538SAndroid Build Coastguard Worker              std::tie(
189*6777b538SAndroid Build Coastguard Worker                  other.error_, other.ip_endpoints_, other.endpoint_metadatas_,
190*6777b538SAndroid Build Coastguard Worker                  other.aliases_, other.text_records_, other.hostnames_,
191*6777b538SAndroid Build Coastguard Worker                  other.https_record_compatibility_, other.canonical_names_);
192*6777b538SAndroid Build Coastguard Worker     }
193*6777b538SAndroid Build Coastguard Worker 
error()194*6777b538SAndroid Build Coastguard Worker     int error() const { return error_; }
did_complete()195*6777b538SAndroid Build Coastguard Worker     bool did_complete() const {
196*6777b538SAndroid Build Coastguard Worker       return error_ != ERR_NETWORK_CHANGED &&
197*6777b538SAndroid Build Coastguard Worker              error_ != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE;
198*6777b538SAndroid Build Coastguard Worker     }
set_error(int error)199*6777b538SAndroid Build Coastguard Worker     void set_error(int error) { error_ = error; }
200*6777b538SAndroid Build Coastguard Worker     std::vector<HostResolverEndpointResult> GetEndpoints() const;
ip_endpoints()201*6777b538SAndroid Build Coastguard Worker     const std::vector<IPEndPoint>& ip_endpoints() const {
202*6777b538SAndroid Build Coastguard Worker       return ip_endpoints_;
203*6777b538SAndroid Build Coastguard Worker     }
set_ip_endpoints(std::vector<IPEndPoint> ip_endpoints)204*6777b538SAndroid Build Coastguard Worker     void set_ip_endpoints(std::vector<IPEndPoint> ip_endpoints) {
205*6777b538SAndroid Build Coastguard Worker       ip_endpoints_ = std::move(ip_endpoints);
206*6777b538SAndroid Build Coastguard Worker     }
207*6777b538SAndroid Build Coastguard Worker     std::vector<ConnectionEndpointMetadata> GetMetadatas() const;
ClearMetadatas()208*6777b538SAndroid Build Coastguard Worker     void ClearMetadatas() { endpoint_metadatas_.clear(); }
aliases()209*6777b538SAndroid Build Coastguard Worker     const std::set<std::string>& aliases() const { return aliases_; }
set_aliases(std::set<std::string> aliases)210*6777b538SAndroid Build Coastguard Worker     void set_aliases(std::set<std::string> aliases) {
211*6777b538SAndroid Build Coastguard Worker       aliases_ = std::move(aliases);
212*6777b538SAndroid Build Coastguard Worker     }
text_records()213*6777b538SAndroid Build Coastguard Worker     const std::vector<std::string>& text_records() const {
214*6777b538SAndroid Build Coastguard Worker       return text_records_;
215*6777b538SAndroid Build Coastguard Worker     }
set_text_records(std::vector<std::string> text_records)216*6777b538SAndroid Build Coastguard Worker     void set_text_records(std::vector<std::string> text_records) {
217*6777b538SAndroid Build Coastguard Worker       text_records_ = std::move(text_records);
218*6777b538SAndroid Build Coastguard Worker     }
hostnames()219*6777b538SAndroid Build Coastguard Worker     const std::vector<HostPortPair>& hostnames() const { return hostnames_; }
set_hostnames(std::vector<HostPortPair> hostnames)220*6777b538SAndroid Build Coastguard Worker     void set_hostnames(std::vector<HostPortPair> hostnames) {
221*6777b538SAndroid Build Coastguard Worker       hostnames_ = std::move(hostnames);
222*6777b538SAndroid Build Coastguard Worker     }
https_record_compatibility()223*6777b538SAndroid Build Coastguard Worker     const std::vector<bool>& https_record_compatibility() const {
224*6777b538SAndroid Build Coastguard Worker       return https_record_compatibility_;
225*6777b538SAndroid Build Coastguard Worker     }
set_https_record_compatibility(std::vector<bool> https_record_compatibility)226*6777b538SAndroid Build Coastguard Worker     void set_https_record_compatibility(
227*6777b538SAndroid Build Coastguard Worker         std::vector<bool> https_record_compatibility) {
228*6777b538SAndroid Build Coastguard Worker       https_record_compatibility_ = std::move(https_record_compatibility);
229*6777b538SAndroid Build Coastguard Worker     }
pinning()230*6777b538SAndroid Build Coastguard Worker     std::optional<bool> pinning() const { return pinning_; }
set_pinning(std::optional<bool> pinning)231*6777b538SAndroid Build Coastguard Worker     void set_pinning(std::optional<bool> pinning) { pinning_ = pinning; }
232*6777b538SAndroid Build Coastguard Worker 
canonical_names()233*6777b538SAndroid Build Coastguard Worker     const std::set<std::string>& canonical_names() const {
234*6777b538SAndroid Build Coastguard Worker       return canonical_names_;
235*6777b538SAndroid Build Coastguard Worker     }
set_canonical_names(std::set<std::string> canonical_names)236*6777b538SAndroid Build Coastguard Worker     void set_canonical_names(std::set<std::string> canonical_names) {
237*6777b538SAndroid Build Coastguard Worker       canonical_names_ = std::move(canonical_names);
238*6777b538SAndroid Build Coastguard Worker     }
239*6777b538SAndroid Build Coastguard Worker 
source()240*6777b538SAndroid Build Coastguard Worker     Source source() const { return source_; }
has_ttl()241*6777b538SAndroid Build Coastguard Worker     bool has_ttl() const { return ttl_ >= base::TimeDelta(); }
ttl()242*6777b538SAndroid Build Coastguard Worker     base::TimeDelta ttl() const { return ttl_; }
243*6777b538SAndroid Build Coastguard Worker     std::optional<base::TimeDelta> GetOptionalTtl() const;
set_ttl(base::TimeDelta ttl)244*6777b538SAndroid Build Coastguard Worker     void set_ttl(base::TimeDelta ttl) { ttl_ = ttl; }
245*6777b538SAndroid Build Coastguard Worker 
expires()246*6777b538SAndroid Build Coastguard Worker     base::TimeTicks expires() const { return expires_; }
247*6777b538SAndroid Build Coastguard Worker 
248*6777b538SAndroid Build Coastguard Worker     // Public for the net-internals UI.
network_changes()249*6777b538SAndroid Build Coastguard Worker     int network_changes() const { return network_changes_; }
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker     // Merge |front| and |back|, representing results from multiple transactions
252*6777b538SAndroid Build Coastguard Worker     // for the same overall host resolution query.
253*6777b538SAndroid Build Coastguard Worker     //
254*6777b538SAndroid Build Coastguard Worker     // Merges lists, placing elements from |front| before elements from |back|.
255*6777b538SAndroid Build Coastguard Worker     // Further, dedupes legacy address lists and moves IPv6 addresses before
256*6777b538SAndroid Build Coastguard Worker     // IPv4 addresses (maintaining stable order otherwise).
257*6777b538SAndroid Build Coastguard Worker     //
258*6777b538SAndroid Build Coastguard Worker     // Fields that cannot be merged take precedence from |front|.
259*6777b538SAndroid Build Coastguard Worker     static Entry MergeEntries(Entry front, Entry back);
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker     // Creates a value representation of the entry for use with NetLog.
262*6777b538SAndroid Build Coastguard Worker     base::Value NetLogParams() const;
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker     // Creates a copy of |this| with the port of all address and hostname values
265*6777b538SAndroid Build Coastguard Worker     // set to |port| if the current port is 0. Preserves any non-zero ports.
266*6777b538SAndroid Build Coastguard Worker     HostCache::Entry CopyWithDefaultPort(uint16_t port) const;
267*6777b538SAndroid Build Coastguard Worker 
268*6777b538SAndroid Build Coastguard Worker     static std::optional<base::TimeDelta> TtlFromInternalResults(
269*6777b538SAndroid Build Coastguard Worker         const std::set<std::unique_ptr<HostResolverInternalResult>>& results,
270*6777b538SAndroid Build Coastguard Worker         base::Time now,
271*6777b538SAndroid Build Coastguard Worker         base::TimeTicks now_ticks);
272*6777b538SAndroid Build Coastguard Worker 
273*6777b538SAndroid Build Coastguard Worker    private:
274*6777b538SAndroid Build Coastguard Worker     using HttpsRecordPriority = uint16_t;
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker     friend class HostCache;
277*6777b538SAndroid Build Coastguard Worker 
278*6777b538SAndroid Build Coastguard Worker     static constexpr base::TimeDelta kUnknownTtl = base::Seconds(-1);
279*6777b538SAndroid Build Coastguard Worker 
280*6777b538SAndroid Build Coastguard Worker     Entry(const Entry& entry,
281*6777b538SAndroid Build Coastguard Worker           base::TimeTicks now,
282*6777b538SAndroid Build Coastguard Worker           base::TimeDelta ttl,
283*6777b538SAndroid Build Coastguard Worker           int network_changes);
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker     Entry(int error,
286*6777b538SAndroid Build Coastguard Worker           std::vector<IPEndPoint> ip_endpoints,
287*6777b538SAndroid Build Coastguard Worker           std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
288*6777b538SAndroid Build Coastguard Worker               endpoint_metadatas,
289*6777b538SAndroid Build Coastguard Worker           std::set<std::string> aliases,
290*6777b538SAndroid Build Coastguard Worker           std::vector<std::string>&& text_results,
291*6777b538SAndroid Build Coastguard Worker           std::vector<HostPortPair>&& hostnames,
292*6777b538SAndroid Build Coastguard Worker           std::vector<bool>&& https_record_compatibility,
293*6777b538SAndroid Build Coastguard Worker           Source source,
294*6777b538SAndroid Build Coastguard Worker           base::TimeTicks expires,
295*6777b538SAndroid Build Coastguard Worker           int network_changes);
296*6777b538SAndroid Build Coastguard Worker 
297*6777b538SAndroid Build Coastguard Worker     void PrepareForCacheInsertion();
298*6777b538SAndroid Build Coastguard Worker 
SetResult(std::multimap<HttpsRecordPriority,ConnectionEndpointMetadata> endpoint_metadatas)299*6777b538SAndroid Build Coastguard Worker     void SetResult(
300*6777b538SAndroid Build Coastguard Worker         std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
301*6777b538SAndroid Build Coastguard Worker             endpoint_metadatas) {
302*6777b538SAndroid Build Coastguard Worker       endpoint_metadatas_ = std::move(endpoint_metadatas);
303*6777b538SAndroid Build Coastguard Worker     }
SetResult(std::vector<std::string> text_records)304*6777b538SAndroid Build Coastguard Worker     void SetResult(std::vector<std::string> text_records) {
305*6777b538SAndroid Build Coastguard Worker       text_records_ = std::move(text_records);
306*6777b538SAndroid Build Coastguard Worker     }
SetResult(std::vector<HostPortPair> hostnames)307*6777b538SAndroid Build Coastguard Worker     void SetResult(std::vector<HostPortPair> hostnames) {
308*6777b538SAndroid Build Coastguard Worker       hostnames_ = std::move(hostnames);
309*6777b538SAndroid Build Coastguard Worker     }
SetResult(std::vector<bool> https_record_compatibility)310*6777b538SAndroid Build Coastguard Worker     void SetResult(std::vector<bool> https_record_compatibility) {
311*6777b538SAndroid Build Coastguard Worker       https_record_compatibility_ = std::move(https_record_compatibility);
312*6777b538SAndroid Build Coastguard Worker     }
313*6777b538SAndroid Build Coastguard Worker 
total_hits()314*6777b538SAndroid Build Coastguard Worker     int total_hits() const { return total_hits_; }
stale_hits()315*6777b538SAndroid Build Coastguard Worker     int stale_hits() const { return stale_hits_; }
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker     bool IsStale(base::TimeTicks now, int network_changes) const;
318*6777b538SAndroid Build Coastguard Worker     void CountHit(bool hit_is_stale);
319*6777b538SAndroid Build Coastguard Worker     void GetStaleness(base::TimeTicks now,
320*6777b538SAndroid Build Coastguard Worker                       int network_changes,
321*6777b538SAndroid Build Coastguard Worker                       EntryStaleness* out) const;
322*6777b538SAndroid Build Coastguard Worker 
323*6777b538SAndroid Build Coastguard Worker     base::Value::Dict GetAsValue(bool include_staleness) const;
324*6777b538SAndroid Build Coastguard Worker 
325*6777b538SAndroid Build Coastguard Worker     // The resolve results for this entry.
326*6777b538SAndroid Build Coastguard Worker     int error_ = ERR_FAILED;
327*6777b538SAndroid Build Coastguard Worker     std::vector<IPEndPoint> ip_endpoints_;
328*6777b538SAndroid Build Coastguard Worker     std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>
329*6777b538SAndroid Build Coastguard Worker         endpoint_metadatas_;
330*6777b538SAndroid Build Coastguard Worker     std::set<std::string> aliases_;
331*6777b538SAndroid Build Coastguard Worker     std::vector<std::string> text_records_;
332*6777b538SAndroid Build Coastguard Worker     std::vector<HostPortPair> hostnames_;
333*6777b538SAndroid Build Coastguard Worker 
334*6777b538SAndroid Build Coastguard Worker     // Bool of whether each HTTPS record received is compatible
335*6777b538SAndroid Build Coastguard Worker     // (draft-ietf-dnsop-svcb-https-08#section-8), considering alias records to
336*6777b538SAndroid Build Coastguard Worker     // always be compatible.
337*6777b538SAndroid Build Coastguard Worker     //
338*6777b538SAndroid Build Coastguard Worker     // This field may be reused for experimental query types to record
339*6777b538SAndroid Build Coastguard Worker     // successfully received records of that experimental type.
340*6777b538SAndroid Build Coastguard Worker     //
341*6777b538SAndroid Build Coastguard Worker     // For either usage, cleared before inserting in cache.
342*6777b538SAndroid Build Coastguard Worker     std::vector<bool> https_record_compatibility_;
343*6777b538SAndroid Build Coastguard Worker 
344*6777b538SAndroid Build Coastguard Worker     // Where results were obtained (e.g. DNS lookup, hosts file, etc).
345*6777b538SAndroid Build Coastguard Worker     Source source_ = SOURCE_UNKNOWN;
346*6777b538SAndroid Build Coastguard Worker     // If true, this entry cannot be evicted from the cache until after the next
347*6777b538SAndroid Build Coastguard Worker     // network change.  When an Entry is replaced by one whose pinning flag
348*6777b538SAndroid Build Coastguard Worker     // is not set, HostCache will copy this flag to the replacement.
349*6777b538SAndroid Build Coastguard Worker     // If this flag is null, HostCache will set it to false for simplicity.
350*6777b538SAndroid Build Coastguard Worker     // Note: This flag is not yet used, and should be removed if the proposals
351*6777b538SAndroid Build Coastguard Worker     // for followup queries after insecure/expired bootstrap are abandoned (see
352*6777b538SAndroid Build Coastguard Worker     // TODO(crbug.com/1200908) in HostResolverManager).
353*6777b538SAndroid Build Coastguard Worker     std::optional<bool> pinning_;
354*6777b538SAndroid Build Coastguard Worker 
355*6777b538SAndroid Build Coastguard Worker     // The final name at the end of the alias chain that was the record name for
356*6777b538SAndroid Build Coastguard Worker     // the A/AAAA records.
357*6777b538SAndroid Build Coastguard Worker     std::set<std::string> canonical_names_;
358*6777b538SAndroid Build Coastguard Worker 
359*6777b538SAndroid Build Coastguard Worker     // TTL obtained from the nameserver. Negative if unknown.
360*6777b538SAndroid Build Coastguard Worker     base::TimeDelta ttl_ = kUnknownTtl;
361*6777b538SAndroid Build Coastguard Worker 
362*6777b538SAndroid Build Coastguard Worker     base::TimeTicks expires_;
363*6777b538SAndroid Build Coastguard Worker     // Copied from the cache's network_changes_ when the entry is set; can
364*6777b538SAndroid Build Coastguard Worker     // later be compared to it to see if the entry was received on the current
365*6777b538SAndroid Build Coastguard Worker     // network.
366*6777b538SAndroid Build Coastguard Worker     int network_changes_ = -1;
367*6777b538SAndroid Build Coastguard Worker     // Use clamped math to cap hit counts at INT_MAX.
368*6777b538SAndroid Build Coastguard Worker     base::ClampedNumeric<int> total_hits_ = 0;
369*6777b538SAndroid Build Coastguard Worker     base::ClampedNumeric<int> stale_hits_ = 0;
370*6777b538SAndroid Build Coastguard Worker   };
371*6777b538SAndroid Build Coastguard Worker 
372*6777b538SAndroid Build Coastguard Worker   // Interface for interacting with persistent storage, to be provided by the
373*6777b538SAndroid Build Coastguard Worker   // embedder. Does not include support for writes that must happen immediately.
374*6777b538SAndroid Build Coastguard Worker   class PersistenceDelegate {
375*6777b538SAndroid Build Coastguard Worker    public:
376*6777b538SAndroid Build Coastguard Worker     // Calling ScheduleWrite() signals that data has changed and should be
377*6777b538SAndroid Build Coastguard Worker     // written to persistent storage. The write might be delayed.
378*6777b538SAndroid Build Coastguard Worker     virtual void ScheduleWrite() = 0;
379*6777b538SAndroid Build Coastguard Worker   };
380*6777b538SAndroid Build Coastguard Worker 
381*6777b538SAndroid Build Coastguard Worker   using EntryMap = std::map<Key, Entry>;
382*6777b538SAndroid Build Coastguard Worker 
383*6777b538SAndroid Build Coastguard Worker   // The two ways to serialize the cache to a value.
384*6777b538SAndroid Build Coastguard Worker   enum class SerializationType {
385*6777b538SAndroid Build Coastguard Worker     // Entries with transient NetworkAnonymizationKeys are not serialized, and
386*6777b538SAndroid Build Coastguard Worker     // RestoreFromListValue() can load the returned value.
387*6777b538SAndroid Build Coastguard Worker     kRestorable,
388*6777b538SAndroid Build Coastguard Worker     // Entries with transient NetworkAnonymizationKeys are serialized, and
389*6777b538SAndroid Build Coastguard Worker     // RestoreFromListValue() cannot load the returned value, since the debug
390*6777b538SAndroid Build Coastguard Worker     // serialization of NetworkAnonymizationKeys is used instead of the
391*6777b538SAndroid Build Coastguard Worker     // deserializable representation.
392*6777b538SAndroid Build Coastguard Worker     kDebug,
393*6777b538SAndroid Build Coastguard Worker   };
394*6777b538SAndroid Build Coastguard Worker 
395*6777b538SAndroid Build Coastguard Worker   // A HostCache::EntryStaleness representing a non-stale (fresh) cache entry.
396*6777b538SAndroid Build Coastguard Worker   static const HostCache::EntryStaleness kNotStale;
397*6777b538SAndroid Build Coastguard Worker 
398*6777b538SAndroid Build Coastguard Worker   // Constructs a HostCache that stores up to |max_entries|.
399*6777b538SAndroid Build Coastguard Worker   explicit HostCache(size_t max_entries);
400*6777b538SAndroid Build Coastguard Worker 
401*6777b538SAndroid Build Coastguard Worker   HostCache(const HostCache&) = delete;
402*6777b538SAndroid Build Coastguard Worker   HostCache& operator=(const HostCache&) = delete;
403*6777b538SAndroid Build Coastguard Worker 
404*6777b538SAndroid Build Coastguard Worker   ~HostCache();
405*6777b538SAndroid Build Coastguard Worker 
406*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the matching (key, entry) pair, which is valid at time
407*6777b538SAndroid Build Coastguard Worker   // |now|. If |ignore_secure| is true, ignores the secure field in |key| when
408*6777b538SAndroid Build Coastguard Worker   // looking for a match. If there is no matching entry, returns NULL.
409*6777b538SAndroid Build Coastguard Worker   const std::pair<const Key, Entry>* Lookup(const Key& key,
410*6777b538SAndroid Build Coastguard Worker                                             base::TimeTicks now,
411*6777b538SAndroid Build Coastguard Worker                                             bool ignore_secure = false);
412*6777b538SAndroid Build Coastguard Worker 
413*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the matching (key, entry) pair, whether it is valid or
414*6777b538SAndroid Build Coastguard Worker   // stale at time |now|. Fills in |stale_out| with information about how stale
415*6777b538SAndroid Build Coastguard Worker   // it is. If |ignore_secure| is true, ignores the secure field in |key| when
416*6777b538SAndroid Build Coastguard Worker   // looking for a match. If there is no matching entry, returns NULL.
417*6777b538SAndroid Build Coastguard Worker   const std::pair<const Key, Entry>* LookupStale(const Key& key,
418*6777b538SAndroid Build Coastguard Worker                                                  base::TimeTicks now,
419*6777b538SAndroid Build Coastguard Worker                                                  EntryStaleness* stale_out,
420*6777b538SAndroid Build Coastguard Worker                                                  bool ignore_secure = false);
421*6777b538SAndroid Build Coastguard Worker 
422*6777b538SAndroid Build Coastguard Worker   // Overwrites or creates an entry for |key|.
423*6777b538SAndroid Build Coastguard Worker   // |entry| is the value to set, |now| is the current time
424*6777b538SAndroid Build Coastguard Worker   // |ttl| is the "time to live".
425*6777b538SAndroid Build Coastguard Worker   void Set(const Key& key,
426*6777b538SAndroid Build Coastguard Worker            const Entry& entry,
427*6777b538SAndroid Build Coastguard Worker            base::TimeTicks now,
428*6777b538SAndroid Build Coastguard Worker            base::TimeDelta ttl);
429*6777b538SAndroid Build Coastguard Worker 
430*6777b538SAndroid Build Coastguard Worker   // Checks whether an entry exists for `hostname`.
431*6777b538SAndroid Build Coastguard Worker   // If so, returns the matching key and writes the source (e.g. DNS, HOSTS
432*6777b538SAndroid Build Coastguard Worker   // file, etc.) to `source_out` and the staleness to `stale_out` (if they are
433*6777b538SAndroid Build Coastguard Worker   // not null). If no entry exists, returns nullptr.
434*6777b538SAndroid Build Coastguard Worker   //
435*6777b538SAndroid Build Coastguard Worker   // For testing use only and not very performant. Production code should only
436*6777b538SAndroid Build Coastguard Worker   // do lookups by precise Key.
437*6777b538SAndroid Build Coastguard Worker   const HostCache::Key* GetMatchingKeyForTesting(
438*6777b538SAndroid Build Coastguard Worker       std::string_view hostname,
439*6777b538SAndroid Build Coastguard Worker       HostCache::Entry::Source* source_out = nullptr,
440*6777b538SAndroid Build Coastguard Worker       HostCache::EntryStaleness* stale_out = nullptr) const;
441*6777b538SAndroid Build Coastguard Worker 
442*6777b538SAndroid Build Coastguard Worker   // Marks all entries as stale on account of a network change.
443*6777b538SAndroid Build Coastguard Worker   void Invalidate();
444*6777b538SAndroid Build Coastguard Worker 
445*6777b538SAndroid Build Coastguard Worker   void set_persistence_delegate(PersistenceDelegate* delegate);
446*6777b538SAndroid Build Coastguard Worker 
set_tick_clock_for_testing(const base::TickClock * tick_clock)447*6777b538SAndroid Build Coastguard Worker   void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
448*6777b538SAndroid Build Coastguard Worker     tick_clock_ = tick_clock;
449*6777b538SAndroid Build Coastguard Worker   }
450*6777b538SAndroid Build Coastguard Worker 
451*6777b538SAndroid Build Coastguard Worker   // Empties the cache.
452*6777b538SAndroid Build Coastguard Worker   void clear();
453*6777b538SAndroid Build Coastguard Worker 
454*6777b538SAndroid Build Coastguard Worker   // Clears hosts matching |host_filter| from the cache.
455*6777b538SAndroid Build Coastguard Worker   void ClearForHosts(
456*6777b538SAndroid Build Coastguard Worker       const base::RepeatingCallback<bool(const std::string&)>& host_filter);
457*6777b538SAndroid Build Coastguard Worker 
458*6777b538SAndroid Build Coastguard Worker   // Fills the provided base::Value with the contents of the cache for
459*6777b538SAndroid Build Coastguard Worker   // serialization. `entry_list` must be non-null list, and will be cleared
460*6777b538SAndroid Build Coastguard Worker   // before adding the cache contents.
461*6777b538SAndroid Build Coastguard Worker   void GetList(base::Value::List& entry_list,
462*6777b538SAndroid Build Coastguard Worker                bool include_staleness,
463*6777b538SAndroid Build Coastguard Worker                SerializationType serialization_type) const;
464*6777b538SAndroid Build Coastguard Worker   // Takes a base::Value list representing cache entries and stores them in the
465*6777b538SAndroid Build Coastguard Worker   // cache, skipping any that already have entries. Returns true on success,
466*6777b538SAndroid Build Coastguard Worker   // false on failure.
467*6777b538SAndroid Build Coastguard Worker   bool RestoreFromListValue(const base::Value::List& old_cache);
468*6777b538SAndroid Build Coastguard Worker   // Returns the number of entries that were restored in the last call to
469*6777b538SAndroid Build Coastguard Worker   // RestoreFromListValue().
last_restore_size()470*6777b538SAndroid Build Coastguard Worker   size_t last_restore_size() const { return restore_size_; }
471*6777b538SAndroid Build Coastguard Worker 
472*6777b538SAndroid Build Coastguard Worker   // Returns the number of entries in the cache.
473*6777b538SAndroid Build Coastguard Worker   size_t size() const;
474*6777b538SAndroid Build Coastguard Worker 
475*6777b538SAndroid Build Coastguard Worker   // Following are used by net_internals UI.
476*6777b538SAndroid Build Coastguard Worker   size_t max_entries() const;
network_changes()477*6777b538SAndroid Build Coastguard Worker   int network_changes() const { return network_changes_; }
entries()478*6777b538SAndroid Build Coastguard Worker   const EntryMap& entries() const { return entries_; }
479*6777b538SAndroid Build Coastguard Worker 
480*6777b538SAndroid Build Coastguard Worker  private:
481*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(HostCacheTest, NoCache);
482*6777b538SAndroid Build Coastguard Worker 
483*6777b538SAndroid Build Coastguard Worker   enum SetOutcome : int;
484*6777b538SAndroid Build Coastguard Worker   enum LookupOutcome : int;
485*6777b538SAndroid Build Coastguard Worker   enum EraseReason : int;
486*6777b538SAndroid Build Coastguard Worker 
487*6777b538SAndroid Build Coastguard Worker   // Returns the result that is least stale, based on the number of network
488*6777b538SAndroid Build Coastguard Worker   // changes since the result was cached. If the results are equally stale,
489*6777b538SAndroid Build Coastguard Worker   // prefers a securely retrieved result. Returns nullptr if both results are
490*6777b538SAndroid Build Coastguard Worker   // nullptr.
491*6777b538SAndroid Build Coastguard Worker   static std::pair<const HostCache::Key, HostCache::Entry>*
492*6777b538SAndroid Build Coastguard Worker   GetLessStaleMoreSecureResult(
493*6777b538SAndroid Build Coastguard Worker       base::TimeTicks now,
494*6777b538SAndroid Build Coastguard Worker       std::pair<const HostCache::Key, HostCache::Entry>* result1,
495*6777b538SAndroid Build Coastguard Worker       std::pair<const HostCache::Key, HostCache::Entry>* result2);
496*6777b538SAndroid Build Coastguard Worker 
497*6777b538SAndroid Build Coastguard Worker   // Returns matching key and entry from cache and nullptr if no match. Ignores
498*6777b538SAndroid Build Coastguard Worker   // the secure field in |initial_key| if |ignore_secure| is true.
499*6777b538SAndroid Build Coastguard Worker   std::pair<const Key, Entry>* LookupInternalIgnoringFields(
500*6777b538SAndroid Build Coastguard Worker       const Key& initial_key,
501*6777b538SAndroid Build Coastguard Worker       base::TimeTicks now,
502*6777b538SAndroid Build Coastguard Worker       bool ignore_secure);
503*6777b538SAndroid Build Coastguard Worker 
504*6777b538SAndroid Build Coastguard Worker   // Returns matching key and entry from cache and nullptr if no match. An exact
505*6777b538SAndroid Build Coastguard Worker   // match for |key| is required.
506*6777b538SAndroid Build Coastguard Worker   std::pair<const Key, Entry>* LookupInternal(const Key& key);
507*6777b538SAndroid Build Coastguard Worker 
508*6777b538SAndroid Build Coastguard Worker   // Returns true if this HostCache can contain no entries.
caching_is_disabled()509*6777b538SAndroid Build Coastguard Worker   bool caching_is_disabled() const { return max_entries_ == 0; }
510*6777b538SAndroid Build Coastguard Worker 
511*6777b538SAndroid Build Coastguard Worker   // Returns true if an entry was removed.
512*6777b538SAndroid Build Coastguard Worker   bool EvictOneEntry(base::TimeTicks now);
513*6777b538SAndroid Build Coastguard Worker   // Helper to check if an Entry is currently pinned in the cache.
514*6777b538SAndroid Build Coastguard Worker   bool HasActivePin(const Entry& entry);
515*6777b538SAndroid Build Coastguard Worker   // Helper to insert an Entry into the cache.
516*6777b538SAndroid Build Coastguard Worker   void AddEntry(const Key& key, Entry&& entry);
517*6777b538SAndroid Build Coastguard Worker 
518*6777b538SAndroid Build Coastguard Worker   // Map from hostname (presumably in lowercase canonicalized format) to
519*6777b538SAndroid Build Coastguard Worker   // a resolved result entry.
520*6777b538SAndroid Build Coastguard Worker   EntryMap entries_;
521*6777b538SAndroid Build Coastguard Worker   size_t max_entries_;
522*6777b538SAndroid Build Coastguard Worker   int network_changes_ = 0;
523*6777b538SAndroid Build Coastguard Worker   // Number of cache entries that were restored in the last call to
524*6777b538SAndroid Build Coastguard Worker   // RestoreFromListValue(). Used in histograms.
525*6777b538SAndroid Build Coastguard Worker   size_t restore_size_ = 0;
526*6777b538SAndroid Build Coastguard Worker 
527*6777b538SAndroid Build Coastguard Worker   raw_ptr<PersistenceDelegate> delegate_ = nullptr;
528*6777b538SAndroid Build Coastguard Worker   // Shared tick clock, overridden for testing.
529*6777b538SAndroid Build Coastguard Worker   raw_ptr<const base::TickClock> tick_clock_;
530*6777b538SAndroid Build Coastguard Worker 
531*6777b538SAndroid Build Coastguard Worker   THREAD_CHECKER(thread_checker_);
532*6777b538SAndroid Build Coastguard Worker };
533*6777b538SAndroid Build Coastguard Worker 
534*6777b538SAndroid Build Coastguard Worker }  // namespace net
535*6777b538SAndroid Build Coastguard Worker 
536*6777b538SAndroid Build Coastguard Worker // Debug logging support
537*6777b538SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out,
538*6777b538SAndroid Build Coastguard Worker                          const net::HostCache::EntryStaleness& s);
539*6777b538SAndroid Build Coastguard Worker 
540*6777b538SAndroid Build Coastguard Worker #endif  // NET_DNS_HOST_CACHE_H_
541