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