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