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