xref: /aosp_15_r20/external/cronet/net/dns/host_resolver_dns_task.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2024 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_DNS_TASK_H_
6 #define NET_DNS_HOST_RESOLVER_DNS_TASK_H_
7 
8 #include <initializer_list>
9 #include <memory>
10 #include <optional>
11 #include <set>
12 #include <vector>
13 
14 #include "base/containers/circular_deque.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/memory/safe_ref.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/numerics/safe_conversions.h"
19 #include "base/time/time.h"
20 #include "base/timer/timer.h"
21 #include "base/values.h"
22 #include "net/base/ip_endpoint.h"
23 #include "net/base/net_export.h"
24 #include "net/base/request_priority.h"
25 #include "net/dns/host_cache.h"
26 #include "net/dns/host_resolver.h"
27 #include "net/dns/httpssvc_metrics.h"
28 #include "net/dns/public/secure_dns_mode.h"
29 #include "net/dns/resolve_context.h"
30 #include "net/log/net_log_with_source.h"
31 #include "third_party/abseil-cpp/absl/types/variant.h"
32 
33 namespace net {
34 
35 class DnsClient;
36 class DnsTransaction;
37 class DnsResponse;
38 
39 // Resolves the hostname using DnsTransaction, which is a full implementation of
40 // a DNS stub resolver. One DnsTransaction is created for each resolution
41 // needed, which for AF_UNSPEC resolutions includes both A and AAAA. The
42 // transactions are scheduled separately and started separately.
43 class NET_EXPORT_PRIVATE HostResolverDnsTask
44     : public base::SupportsWeakPtr<HostResolverDnsTask> {
45  public:
46   using Results = std::set<std::unique_ptr<HostResolverInternalResult>>;
47 
48   // Represents a single transaction results.
49   struct SingleTransactionResults {
50     SingleTransactionResults(DnsQueryType query_type, Results results);
51     ~SingleTransactionResults();
52 
53     SingleTransactionResults(SingleTransactionResults&&);
54     SingleTransactionResults& operator=(SingleTransactionResults&&);
55 
56     SingleTransactionResults(const SingleTransactionResults&) = delete;
57     SingleTransactionResults& operator=(const SingleTransactionResults&) =
58         delete;
59 
60     DnsQueryType query_type;
61     Results results;
62   };
63 
64   class Delegate {
65    public:
66     virtual void OnDnsTaskComplete(base::TimeTicks start_time,
67                                    bool allow_fallback,
68                                    HostCache::Entry results,
69                                    bool secure) = 0;
70 
71     // Called when one transaction completes successfully, or one more
72     // transactions get cancelled, but only if more transactions are
73     // needed. If no more transactions are needed, expect `OnDnsTaskComplete()`
74     // to be called instead. `single_transaction_results` is passed only when
75     // one transaction completes successfully.
76     virtual void OnIntermediateTransactionsComplete(
77         std::optional<SingleTransactionResults> single_transaction_results) = 0;
78 
79     virtual RequestPriority priority() const = 0;
80 
81     virtual void AddTransactionTimeQueued(base::TimeDelta time_queued) = 0;
82 
83    protected:
84     Delegate() = default;
85     virtual ~Delegate() = default;
86   };
87 
88   HostResolverDnsTask(DnsClient* client,
89                       HostResolver::Host host,
90                       NetworkAnonymizationKey anonymization_key,
91                       DnsQueryTypeSet query_types,
92                       ResolveContext* resolve_context,
93                       bool secure,
94                       SecureDnsMode secure_dns_mode,
95                       Delegate* delegate,
96                       const NetLogWithSource& job_net_log,
97                       const base::TickClock* tick_clock,
98                       bool fallback_available,
99                       const HostResolver::HttpsSvcbOptions& https_svcb_options);
100   ~HostResolverDnsTask();
101 
102   HostResolverDnsTask(const HostResolverDnsTask&) = delete;
103   HostResolverDnsTask& operator=(const HostResolverDnsTask&) = delete;
104 
num_additional_transactions_needed()105   int num_additional_transactions_needed() const {
106     return base::checked_cast<int>(transactions_needed_.size());
107   }
108 
num_transactions_in_progress()109   int num_transactions_in_progress() const {
110     return base::checked_cast<int>(transactions_in_progress_.size());
111   }
112 
secure()113   bool secure() const { return secure_; }
114 
115   void StartNextTransaction();
116 
117  private:
118   enum class TransactionErrorBehavior {
119     // Errors lead to task fallback (immediately unless another pending/started
120     // transaction has the `kFatalOrEmpty` behavior).
121     kFallback,
122 
123     // Transaction errors are treated as if a NOERROR response were received,
124     // allowing task success if other transactions complete successfully.
125     kSynthesizeEmpty,
126 
127     // Transaction errors are potentially fatal (determined by
128     // `OnTransactionComplete` and often its helper
129     // `IsFatalTransactionFailure()`) for the entire Job and may disallow
130     // fallback. Otherwise, same as `kSynthesizeEmpty`.
131     // TODO(crbug.com/1264933): Implement the fatality behavior.
132     kFatalOrEmpty,
133   };
134 
135   struct TransactionInfo {
136     explicit TransactionInfo(DnsQueryType type,
137                              TransactionErrorBehavior error_behavior =
138                                  TransactionErrorBehavior::kFallback);
139     ~TransactionInfo();
140 
141     TransactionInfo(TransactionInfo&&);
142     TransactionInfo& operator=(TransactionInfo&&);
143 
144     bool operator<(const TransactionInfo& other) const;
145 
146     DnsQueryType type;
147     TransactionErrorBehavior error_behavior;
148     std::unique_ptr<DnsTransaction> transaction;
149   };
150 
151   base::Value::Dict NetLogDnsTaskCreationParams();
152 
153   base::Value::Dict NetLogDnsTaskTimeoutParams();
154 
155   DnsQueryTypeSet MaybeDisableAdditionalQueries(DnsQueryTypeSet types);
156 
157   void PushTransactionsNeeded(DnsQueryTypeSet query_types);
158 
159   void CreateAndStartTransaction(TransactionInfo transaction_info);
160 
161   void OnTimeout();
162 
163   // Called on completion of a `DnsTransaction`, but not necessarily completion
164   // of all work for the individual transaction in this task (see
165   // `OnTransactionsFinished()`).
166   void OnDnsTransactionComplete(
167       std::set<TransactionInfo>::iterator transaction_info_it,
168       uint16_t request_port,
169       int net_error,
170       const DnsResponse* response);
171 
172   bool IsFatalTransactionFailure(int transaction_error,
173                                  const TransactionInfo& transaction_info,
174                                  const DnsResponse* response);
175 
176   void SortTransactionAndHandleResults(TransactionInfo transaction_info,
177                                        Results transaction_results);
178   void OnTransactionSorted(
179       std::set<TransactionInfo>::iterator transaction_info_it,
180       Results transaction_results,
181       bool success,
182       std::vector<IPEndPoint> sorted);
183   void HandleTransactionResults(TransactionInfo transaction_info,
184                                 Results transaction_results);
185 
186   void OnTransactionsFinished(
187       std::optional<SingleTransactionResults> single_transaction_results);
188 
189   void OnSortComplete(base::TimeTicks sort_start_time,
190                       HostCache::Entry results,
191                       bool secure,
192                       bool success,
193                       std::vector<IPEndPoint> sorted);
194 
195   bool AnyPotentiallyFatalTransactionsRemain();
196 
197   void CancelNonFatalTransactions();
198 
199   void OnFailure(
200       int net_error,
201       bool allow_fallback,
202       std::optional<base::TimeDelta> ttl = std::nullopt,
203       std::optional<DnsQueryType> failed_transaction_type = std::nullopt);
204 
205   void OnSuccess(HostCache::Entry results);
206 
207   // Returns whether any transactions left to finish are of a transaction type
208   // in `types`. Used for logging and starting the timeout timer (see
209   // MaybeStartTimeoutTimer()).
210   bool AnyOfTypeTransactionsRemain(
211       std::initializer_list<DnsQueryType> types) const;
212 
213   void MaybeStartTimeoutTimer();
214 
215   bool ShouldTriggerHttpToHttpsUpgrade(const Results& results);
216 
217   const raw_ptr<DnsClient> client_;
218 
219   HostResolver::Host host_;
220   NetworkAnonymizationKey anonymization_key_;
221 
222   base::SafeRef<ResolveContext> resolve_context_;
223 
224   // Whether lookups in this DnsTask should occur using DoH or plaintext.
225   const bool secure_;
226   const SecureDnsMode secure_dns_mode_;
227 
228   // The listener to the results of this DnsTask.
229   const raw_ptr<Delegate> delegate_;
230   const NetLogWithSource net_log_;
231 
232   bool any_transaction_started_ = false;
233   base::circular_deque<TransactionInfo> transactions_needed_;
234   // Active transactions have iterators pointing to their entry in this set, so
235   // individual entries should not be modified or removed until completion or
236   // cancellation of the transaction.
237   std::set<TransactionInfo> transactions_in_progress_;
238 
239   // For histograms.
240   base::TimeTicks a_record_end_time_;
241   base::TimeTicks aaaa_record_end_time_;
242 
243   std::optional<HostCache::Entry> saved_results_;
244   bool saved_results_is_failure_ = false;
245 
246   const raw_ptr<const base::TickClock> tick_clock_;
247   base::TimeTicks task_start_time_;
248 
249   std::optional<HttpssvcMetrics> httpssvc_metrics_;
250 
251   // Timer for task timeout. Generally started after completion of address
252   // transactions to allow aborting experimental or supplemental transactions.
253   base::OneShotTimer timeout_timer_;
254 
255   // If true, there are still significant fallback options available if this
256   // task completes unsuccessfully. Used as a signal that underlying
257   // transactions should timeout more quickly.
258   bool fallback_available_;
259 
260   const HostResolver::HttpsSvcbOptions https_svcb_options_;
261 };
262 
263 }  // namespace net
264 
265 #endif  // NET_DNS_HOST_RESOLVER_DNS_TASK_H_
266