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