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