• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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