Bug 1838739 - Initialize result of SetAsGPUOutOfMemoryError. r=webgpu-reviewers,nical
[gecko.git] / netwerk / dns / nsHostRecord.h
blob0064bb9e42064f8ee08f650d2df22959aac396aa
1 /* vim:set ts=4 sw=2 sts=2 et cin: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsHostRecord_h__
7 #define nsHostRecord_h__
9 #include "mozilla/AtomicBitfields.h"
10 #include "mozilla/DataMutex.h"
11 #include "mozilla/LinkedList.h"
12 #include "mozilla/net/HTTPSSVC.h"
13 #include "nsIDNSService.h"
14 #include "nsIDNSByTypeRecord.h"
15 #include "PLDHashTable.h"
16 #include "nsITRRSkipReason.h"
18 class nsHostRecord;
19 class nsHostResolver;
21 namespace mozilla {
22 namespace net {
23 class HostRecordQueue;
24 class TRR;
25 class TRRQuery;
26 } // namespace net
27 } // namespace mozilla
29 /**
30 * This class is used to notify listeners when a ResolveHost operation is
31 * complete. Classes that derive it must implement threadsafe nsISupports
32 * to be able to use RefPtr with this class.
34 class nsResolveHostCallback
35 : public mozilla::LinkedListElement<RefPtr<nsResolveHostCallback>>,
36 public nsISupports {
37 public:
38 /**
39 * OnResolveHostComplete
41 * this function is called to complete a host lookup initiated by
42 * nsHostResolver::ResolveHost. it may be invoked recursively from
43 * ResolveHost or on an unspecified background thread.
45 * NOTE: it is the responsibility of the implementor of this method
46 * to handle the callback in a thread safe manner.
48 * @param resolver
49 * nsHostResolver object associated with this result
50 * @param record
51 * the host record containing the results of the lookup
52 * @param status
53 * if successful, |record| contains non-null results
55 virtual void OnResolveHostComplete(nsHostResolver* resolver,
56 nsHostRecord* record, nsresult status) = 0;
57 /**
58 * EqualsAsyncListener
60 * Determines if the listener argument matches the listener member var.
61 * For subclasses not implementing a member listener, should return false.
62 * For subclasses having a member listener, the function should check if
63 * they are the same. Used for cases where a pointer to an object
64 * implementing nsResolveHostCallback is unknown, but a pointer to
65 * the original listener is known.
67 * @param aListener
68 * nsIDNSListener object associated with the original request
70 virtual bool EqualsAsyncListener(nsIDNSListener* aListener) = 0;
72 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0;
74 protected:
75 virtual ~nsResolveHostCallback() = default;
78 struct nsHostKey {
79 const nsCString host;
80 const nsCString mTrrServer;
81 uint16_t type = 0;
82 nsIDNSService::DNSFlags flags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
83 uint16_t af = 0;
84 bool pb = false;
85 const nsCString originSuffix;
86 explicit nsHostKey(const nsACString& host, const nsACString& aTrrServer,
87 uint16_t type, nsIDNSService::DNSFlags flags, uint16_t af,
88 bool pb, const nsACString& originSuffix);
89 bool operator==(const nsHostKey& other) const;
90 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
91 PLDHashNumber Hash() const;
94 /**
95 * nsHostRecord - ref counted object type stored in host resolver cache.
97 class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
98 public nsHostKey,
99 public nsISupports {
100 using TRRSkippedReason = mozilla::net::TRRSkippedReason;
102 public:
103 NS_DECL_THREADSAFE_ISUPPORTS
105 virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
106 return 0;
109 // Returns the TRR mode encoded by the flags
110 nsIRequest::TRRMode TRRMode();
112 // Records the first reason that caused TRR to be skipped or to fail.
113 void RecordReason(TRRSkippedReason reason) {
114 if (mTRRSkippedReason == TRRSkippedReason::TRR_UNSET) {
115 mTRRSkippedReason = reason;
119 enum DnsPriority {
120 DNS_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW,
121 DNS_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM,
122 DNS_PRIORITY_HIGH,
125 protected:
126 friend class nsHostResolver;
127 friend class mozilla::net::HostRecordQueue;
128 friend class mozilla::net::TRR;
129 friend class mozilla::net::TRRQuery;
131 explicit nsHostRecord(const nsHostKey& key);
132 virtual ~nsHostRecord() = default;
134 // Mark hostrecord as not usable
135 void Invalidate();
137 enum ExpirationStatus {
138 EXP_VALID,
139 EXP_GRACE,
140 EXP_EXPIRED,
143 ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const;
145 // Convenience function for setting the timestamps above (mValidStart,
146 // mValidEnd, and mGraceStart). valid and grace are durations in seconds.
147 void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid,
148 unsigned int grace);
149 void CopyExpirationTimesAndFlagsFrom(const nsHostRecord* aFromHostRecord);
151 // Checks if the record is usable (not expired and has a value)
152 bool HasUsableResult(const mozilla::TimeStamp& now,
153 nsIDNSService::DNSFlags queryFlags =
154 nsIDNSService::RESOLVE_DEFAULT_FLAGS) const;
156 static DnsPriority GetPriority(nsIDNSService::DNSFlags aFlags);
158 virtual void Cancel();
159 virtual bool HasUsableResultInternal(
160 const mozilla::TimeStamp& now,
161 nsIDNSService::DNSFlags queryFlags) const = 0;
162 virtual bool RefreshForNegativeResponse() const { return true; }
164 mozilla::LinkedList<RefPtr<nsResolveHostCallback>> mCallbacks;
166 bool IsAddrRecord() const {
167 return type == nsIDNSService::RESOLVE_TYPE_DEFAULT;
170 virtual void Reset() {
171 mTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
172 mFirstTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
173 mTrrAttempts = 0;
174 mTRRSuccess = false;
175 mNativeSuccess = false;
178 virtual void OnCompleteLookup() {}
180 // When the record began being valid. Used mainly for bookkeeping.
181 mozilla::TimeStamp mValidStart;
183 // When the record is no longer valid (it's time of expiration)
184 mozilla::TimeStamp mValidEnd;
186 // When the record enters its grace period. This must be before mValidEnd.
187 // If a record is in its grace period (and not expired), it will be used
188 // but a request to refresh it will be made.
189 mozilla::TimeStamp mGraceStart;
191 mozilla::Atomic<uint32_t, mozilla::Relaxed> mTtl{0};
193 // The computed TRR mode that is actually used by the request.
194 // It is set in nsHostResolver::NameLookup and is based on the mode of the
195 // default resolver and the TRRMode encoded in the flags.
196 // The mode into account if the TRR service is disabled,
197 // parental controls are on, domain matches exclusion list, etc.
198 mozilla::Atomic<nsIRequest::TRRMode> mEffectiveTRRMode{
199 nsIRequest::TRR_DEFAULT_MODE};
201 mozilla::Atomic<TRRSkippedReason> mTRRSkippedReason{
202 TRRSkippedReason::TRR_UNSET};
203 TRRSkippedReason mFirstTRRSkippedReason = TRRSkippedReason::TRR_UNSET;
205 mozilla::DataMutex<RefPtr<mozilla::net::TRRQuery>> mTRRQuery;
207 // counter of outstanding resolving calls
208 mozilla::Atomic<int32_t> mResolving{0};
210 // Number of times we've attempted TRR. Reset when we refresh.
211 // TRR is attempted at most twice - first attempt and retry.
212 mozilla::Atomic<int32_t> mTrrAttempts{0};
214 // True if this record is a cache of a failed lookup. Negative cache
215 // entries are valid just like any other (though never for more than 60
216 // seconds), but a use of that negative entry forces an asynchronous refresh.
217 bool negative = false;
219 // Explicitly expired
220 bool mDoomed = false;
222 // Whether this is resolved by TRR successfully or not.
223 bool mTRRSuccess = false;
225 // Whether this is resolved by native resolver successfully or not.
226 bool mNativeSuccess = false;
229 // b020e996-f6ab-45e5-9bf5-1da71dd0053a
230 #define ADDRHOSTRECORD_IID \
232 0xb020e996, 0xf6ab, 0x45e5, { \
233 0x9b, 0xf5, 0x1d, 0xa7, 0x1d, 0xd0, 0x05, 0x3a \
237 class AddrHostRecord final : public nsHostRecord {
238 using Mutex = mozilla::Mutex;
239 using DNSResolverType = mozilla::net::DNSResolverType;
241 public:
242 NS_DECLARE_STATIC_IID_ACCESSOR(ADDRHOSTRECORD_IID)
243 NS_DECL_ISUPPORTS_INHERITED
245 /* a fully resolved host record has either a non-null |addr_info| or |addr|
246 * field. if |addr_info| is null, it implies that the |host| is an IP
247 * address literal. in which case, |addr| contains the parsed address.
248 * otherwise, if |addr_info| is non-null, then it contains one or many
249 * IP addresses corresponding to the given host name. if both |addr_info|
250 * and |addr| are null, then the given host has not yet been fully resolved.
251 * |af| is the address family of the record we are querying for.
254 /* the lock protects |addr_info| and |addr_info_gencnt| because they
255 * are mutable and accessed by the resolver worker thread and the
256 * nsDNSService2 class. |addr| doesn't change after it has been
257 * assigned a value. only the resolver worker thread modifies
258 * nsHostRecord (and only in nsHostResolver::CompleteLookup);
259 * the other threads just read it. therefore the resolver worker
260 * thread doesn't need to lock when reading |addr_info|.
262 Mutex addr_info_lock MOZ_UNANNOTATED{"AddrHostRecord.addr_info_lock"};
263 // generation count of |addr_info|
264 int addr_info_gencnt = 0;
265 RefPtr<mozilla::net::AddrInfo> addr_info;
266 mozilla::UniquePtr<mozilla::net::NetAddr> addr;
268 // hold addr_info_lock when calling the blocklist functions
269 bool Blocklisted(const mozilla::net::NetAddr* query);
270 void ResetBlocklist();
271 void ReportUnusable(const mozilla::net::NetAddr* aAddress);
273 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
275 nsIRequest::TRRMode EffectiveTRRMode() const { return mEffectiveTRRMode; }
276 nsITRRSkipReason::value TrrSkipReason() const { return mTRRSkippedReason; }
278 nsresult GetTtl(uint32_t* aResult);
280 private:
281 friend class nsHostResolver;
282 friend class mozilla::net::HostRecordQueue;
283 friend class mozilla::net::TRR;
284 friend class mozilla::net::TRRQuery;
286 explicit AddrHostRecord(const nsHostKey& key);
287 ~AddrHostRecord();
289 // Checks if the record is usable (not expired and has a value)
290 bool HasUsableResultInternal(
291 const mozilla::TimeStamp& now,
292 nsIDNSService::DNSFlags queryFlags) const override;
294 bool RemoveOrRefresh(bool aTrrToo); // Mark records currently being resolved
295 // as needed to resolve again.
297 // Saves the skip reason of a first-attempt TRR lookup and clears
298 // it to prepare for a retry attempt.
299 void NotifyRetryingTrr();
300 void ResolveComplete();
302 static DnsPriority GetPriority(nsIDNSService::DNSFlags aFlags);
304 // true if pending and on the queue (not yet given to getaddrinfo())
305 bool onQueue() { return LoadNative() && isInList(); }
307 virtual void Reset() override {
308 nsHostRecord::Reset();
309 StoreNativeUsed(false);
310 mResolverType = DNSResolverType::Native;
313 virtual void OnCompleteLookup() override {
314 nsHostRecord::OnCompleteLookup();
315 // This should always be cleared when a request is completed.
316 StoreNative(false);
319 // When the lookups of this record started and their durations
320 mozilla::TimeStamp mNativeStart;
321 mozilla::TimeDuration mTrrDuration;
322 mozilla::TimeDuration mNativeDuration;
324 // TRR was used on this record
325 mozilla::Atomic<DNSResolverType> mResolverType{DNSResolverType::Native};
327 // clang-format off
328 MOZ_ATOMIC_BITFIELDS(mAtomicBitfields, 8, (
329 // true if this record is being resolved "natively", which means that
330 // it is either on the pending queue or owned by one of the worker threads.
331 (uint16_t, Native, 1),
332 (uint16_t, NativeUsed, 1),
333 // true if off queue and contributing to mActiveAnyThreadCount
334 (uint16_t, UsingAnyThread, 1),
335 (uint16_t, GetTtl, 1),
336 (uint16_t, ResolveAgain, 1)
338 // clang-format on
340 // The number of times ReportUnusable() has been called in the record's
341 // lifetime.
342 uint32_t mUnusableCount = 0;
344 // a list of addresses associated with this record that have been reported
345 // as unusable. the list is kept as a set of strings to make it independent
346 // of gencnt.
347 nsTArray<nsCString> mUnusableItems;
350 NS_DEFINE_STATIC_IID_ACCESSOR(AddrHostRecord, ADDRHOSTRECORD_IID)
352 // 77b786a7-04be-44f2-987c-ab8aa96676e0
353 #define TYPEHOSTRECORD_IID \
355 0x77b786a7, 0x04be, 0x44f2, { \
356 0x98, 0x7c, 0xab, 0x8a, 0xa9, 0x66, 0x76, 0xe0 \
360 class TypeHostRecord final : public nsHostRecord,
361 public nsIDNSTXTRecord,
362 public nsIDNSHTTPSSVCRecord,
363 public mozilla::net::DNSHTTPSSVCRecordBase {
364 public:
365 NS_DECLARE_STATIC_IID_ACCESSOR(TYPEHOSTRECORD_IID)
366 NS_DECL_ISUPPORTS_INHERITED
367 NS_DECL_NSIDNSTXTRECORD
368 NS_DECL_NSIDNSHTTPSSVCRECORD
370 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override;
371 uint32_t GetType();
372 mozilla::net::TypeRecordResultType GetResults();
374 private:
375 friend class nsHostResolver;
376 friend class mozilla::net::TRR;
377 friend class mozilla::net::TRRQuery;
379 explicit TypeHostRecord(const nsHostKey& key);
380 ~TypeHostRecord();
382 // Checks if the record is usable (not expired and has a value)
383 bool HasUsableResultInternal(
384 const mozilla::TimeStamp& now,
385 nsIDNSService::DNSFlags queryFlags) const override;
386 bool RefreshForNegativeResponse() const override;
388 mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing());
389 mozilla::Mutex mResultsLock MOZ_UNANNOTATED{"TypeHostRecord.mResultsLock"};
391 mozilla::Maybe<nsCString> mOriginHost;
393 // When the lookups of this record started (for telemetry).
394 mozilla::TimeStamp mStart;
395 bool mAllRecordsExcluded = false;
398 NS_DEFINE_STATIC_IID_ACCESSOR(TypeHostRecord, TYPEHOSTRECORD_IID)
400 static inline bool IsHighPriority(nsIDNSService::DNSFlags flags) {
401 return !(flags & (nsHostRecord::DNS_PRIORITY_LOW |
402 nsHostRecord::DNS_PRIORITY_MEDIUM));
405 static inline bool IsMediumPriority(nsIDNSService::DNSFlags flags) {
406 return flags & nsHostRecord::DNS_PRIORITY_MEDIUM;
409 static inline bool IsLowPriority(nsIDNSService::DNSFlags flags) {
410 return flags & nsHostRecord::DNS_PRIORITY_LOW;
413 #endif // nsHostRecord_h__