1 // Copyright 2022 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_HOST_RESOLVER_INTERNAL_RESULT_H_ 6 #define NET_DNS_HOST_RESOLVER_INTERNAL_RESULT_H_ 7 8 #include <map> 9 #include <memory> 10 #include <string> 11 #include <tuple> 12 #include <vector> 13 14 #include "base/time/time.h" 15 #include "base/values.h" 16 #include "net/base/connection_endpoint_metadata.h" 17 #include "net/base/host_port_pair.h" 18 #include "net/base/ip_endpoint.h" 19 #include "net/base/net_export.h" 20 #include "net/dns/https_record_rdata.h" 21 #include "net/dns/public/dns_query_type.h" 22 #include "third_party/abseil-cpp/absl/types/optional.h" 23 24 namespace net { 25 26 class HostResolverInternalDataResult; 27 class HostResolverInternalMetadataResult; 28 class HostResolverInternalErrorResult; 29 class HostResolverInternalAliasResult; 30 31 // Parsed and extracted result type for use internally to HostResolver code. 32 class NET_EXPORT_PRIVATE HostResolverInternalResult { 33 public: 34 enum class Type { kData, kMetadata, kError, kAlias }; 35 enum class Source { kDns, kHosts, kUnknown }; 36 37 // Nullptr if `value` is malformed to be deserialized. 38 static std::unique_ptr<HostResolverInternalResult> FromValue( 39 const base::Value& value); 40 41 virtual ~HostResolverInternalResult() = default; 42 domain_name()43 const std::string& domain_name() const { return domain_name_; } query_type()44 DnsQueryType query_type() const { return query_type_; } type()45 Type type() const { return type_; } source()46 Source source() const { return source_; } expiration()47 absl::optional<base::TimeTicks> expiration() const { return expiration_; } timed_expiration()48 absl::optional<base::Time> timed_expiration() const { 49 return timed_expiration_; 50 } 51 52 const HostResolverInternalDataResult& AsData() const; 53 const HostResolverInternalMetadataResult& AsMetadata() const; 54 const HostResolverInternalErrorResult& AsError() const; 55 const HostResolverInternalAliasResult& AsAlias() const; 56 57 virtual base::Value ToValue() const = 0; 58 59 protected: 60 HostResolverInternalResult(std::string domain_name, 61 DnsQueryType query_type, 62 absl::optional<base::TimeTicks> expiration, 63 absl::optional<base::Time> timed_expiration, 64 Type type, 65 Source source); 66 // Expect to only be called with a `dict` well-formed for deserialization. Can 67 // be checked via ValidateValueBaseDict(). 68 explicit HostResolverInternalResult(const base::Value::Dict& dict); 69 70 bool operator==(const HostResolverInternalResult& other) const { 71 return std::tie(domain_name_, query_type_, type_, source_, expiration_, 72 timed_expiration_) == 73 std::tie(other.domain_name_, other.query_type_, other.type_, 74 other.source_, other.expiration_, other.timed_expiration_); 75 } 76 77 static bool ValidateValueBaseDict(const base::Value::Dict& dict, 78 bool require_timed_expiration); 79 base::Value::Dict ToValueBaseDict() const; 80 81 private: 82 const std::string domain_name_; 83 const DnsQueryType query_type_; 84 const Type type_; 85 const Source source_; 86 87 // Expiration logic should prefer to be based on `expiration_` for correctness 88 // through system time changes. But if result has been serialized to disk, it 89 // may be that only `timed_expiration_` is available. 90 const absl::optional<base::TimeTicks> expiration_; 91 const absl::optional<base::Time> timed_expiration_; 92 }; 93 94 // Parsed and extracted result containing result data. 95 class NET_EXPORT_PRIVATE HostResolverInternalDataResult final 96 : public HostResolverInternalResult { 97 public: 98 static std::unique_ptr<HostResolverInternalDataResult> FromValue( 99 const base::Value& value); 100 101 // `domain_name` is dotted form. 102 HostResolverInternalDataResult(std::string domain_name, 103 DnsQueryType query_type, 104 absl::optional<base::TimeTicks> expiration, 105 base::Time timed_expiration, 106 Source source, 107 std::vector<IPEndPoint> endpoints, 108 std::vector<std::string> strings, 109 std::vector<HostPortPair> hosts); 110 ~HostResolverInternalDataResult() override; 111 112 HostResolverInternalDataResult(const HostResolverInternalDataResult&) = 113 delete; 114 HostResolverInternalDataResult& operator=( 115 const HostResolverInternalDataResult&) = delete; 116 117 bool operator==(const HostResolverInternalDataResult& other) const { 118 return HostResolverInternalResult::operator==(other) && 119 std::tie(endpoints_, strings_, hosts_) == 120 std::tie(other.endpoints_, other.strings_, other.hosts_); 121 } 122 endpoints()123 const std::vector<IPEndPoint>& endpoints() const { return endpoints_; } strings()124 const std::vector<std::string>& strings() const { return strings_; } hosts()125 const std::vector<HostPortPair>& hosts() const { return hosts_; } 126 127 base::Value ToValue() const override; 128 129 private: 130 HostResolverInternalDataResult(const base::Value::Dict& dict, 131 std::vector<IPEndPoint> endpoints, 132 std::vector<std::string> strings, 133 std::vector<HostPortPair> hosts); 134 135 // Corresponds to the `HostResolverEndpointResult::ip_endpoints` portion of 136 // `HostResolver::ResolveHostRequest::GetEndpointResults()`. 137 const std::vector<IPEndPoint> endpoints_; 138 139 // Corresponds to `HostResolver::ResolveHostRequest::GetTextResults()`. 140 const std::vector<std::string> strings_; 141 142 // Corresponds to `HostResolver::ResolveHostRequest::GetHostnameResults()`. 143 const std::vector<HostPortPair> hosts_; 144 }; 145 146 // Parsed and extracted connection metadata, but not usable on its own without 147 // being paired with separate HostResolverInternalDataResult data (for the 148 // domain name specified by `ConnectionEndpointMetadata::target_name`). An empty 149 // metadata result signifies that compatible HTTPS records were received but 150 // with no contained metadata of use to Chrome. 151 class NET_EXPORT_PRIVATE HostResolverInternalMetadataResult final 152 : public HostResolverInternalResult { 153 public: 154 static std::unique_ptr<HostResolverInternalMetadataResult> FromValue( 155 const base::Value& value); 156 157 // `domain_name` and `data_domain` are dotted form domain names. 158 HostResolverInternalMetadataResult( 159 std::string domain_name, 160 DnsQueryType query_type, 161 absl::optional<base::TimeTicks> expiration, 162 base::Time timed_expiration, 163 Source source, 164 std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas); 165 ~HostResolverInternalMetadataResult() override; 166 167 HostResolverInternalMetadataResult( 168 const HostResolverInternalMetadataResult&) = delete; 169 HostResolverInternalMetadataResult& operator=( 170 const HostResolverInternalMetadataResult&) = delete; 171 172 bool operator==(const HostResolverInternalMetadataResult& other) const { 173 return HostResolverInternalResult::operator==(other) && 174 metadatas_ == other.metadatas_; 175 } 176 177 const std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata>& metadatas()178 metadatas() const { 179 return metadatas_; 180 } 181 182 base::Value ToValue() const override; 183 184 private: 185 HostResolverInternalMetadataResult( 186 const base::Value::Dict& dict, 187 std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas); 188 189 std::multimap<HttpsRecordPriority, ConnectionEndpointMetadata> metadatas_; 190 }; 191 192 // Parsed and extracted error. 193 class NET_EXPORT_PRIVATE HostResolverInternalErrorResult final 194 : public HostResolverInternalResult { 195 public: 196 static std::unique_ptr<HostResolverInternalErrorResult> FromValue( 197 const base::Value& value); 198 199 // `domain_name` is dotted form. `timed_expiration` may be `nullopt` for 200 // non-cacheable errors. 201 HostResolverInternalErrorResult(std::string domain_name, 202 DnsQueryType query_type, 203 absl::optional<base::TimeTicks> expiration, 204 absl::optional<base::Time> timed_expiration, 205 Source source, 206 int error); 207 ~HostResolverInternalErrorResult() override = default; 208 209 HostResolverInternalErrorResult(const HostResolverInternalErrorResult&) = 210 delete; 211 HostResolverInternalErrorResult& operator=( 212 const HostResolverInternalErrorResult&) = delete; 213 214 bool operator==(const HostResolverInternalErrorResult& other) const { 215 return HostResolverInternalResult::operator==(other) && 216 error_ == other.error_; 217 } 218 error()219 int error() const { return error_; } 220 221 base::Value ToValue() const override; 222 223 private: 224 HostResolverInternalErrorResult(const base::Value::Dict& dict, int error); 225 226 const int error_; 227 }; 228 229 // Parsed and extracted alias (CNAME or alias-type HTTPS). 230 class NET_EXPORT_PRIVATE HostResolverInternalAliasResult final 231 : public HostResolverInternalResult { 232 public: 233 static std::unique_ptr<HostResolverInternalAliasResult> FromValue( 234 const base::Value& value); 235 236 // `domain_name` and `alias_target` are dotted form domain names. 237 HostResolverInternalAliasResult(std::string domain_name, 238 DnsQueryType query_type, 239 absl::optional<base::TimeTicks> expiration, 240 base::Time timed_expiration, 241 Source source, 242 std::string alias_target); 243 ~HostResolverInternalAliasResult() override = default; 244 245 HostResolverInternalAliasResult(const HostResolverInternalAliasResult&) = 246 delete; 247 HostResolverInternalAliasResult& operator=( 248 const HostResolverInternalAliasResult&) = delete; 249 250 bool operator==(const HostResolverInternalAliasResult& other) const { 251 return HostResolverInternalResult::operator==(other) && 252 alias_target_ == other.alias_target_; 253 } 254 alias_target()255 const std::string& alias_target() const { return alias_target_; } 256 257 base::Value ToValue() const override; 258 259 private: 260 HostResolverInternalAliasResult(const base::Value::Dict& dict, 261 std::string alias_target); 262 263 const std::string alias_target_; 264 }; 265 266 } // namespace net 267 268 #endif // NET_DNS_HOST_RESOLVER_INTERNAL_RESULT_H_ 269