diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /netwerk/dns/nsHostResolver.h | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'netwerk/dns/nsHostResolver.h')
-rw-r--r-- | netwerk/dns/nsHostResolver.h | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/netwerk/dns/nsHostResolver.h b/netwerk/dns/nsHostResolver.h new file mode 100644 index 0000000000..798d0d0065 --- /dev/null +++ b/netwerk/dns/nsHostResolver.h @@ -0,0 +1,654 @@ +/* vim:set ts=4 sw=2 sts=2 et cin: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsHostResolver_h__ +#define nsHostResolver_h__ + +#include "nscore.h" +#include "prnetdb.h" +#include "PLDHashTable.h" +#include "mozilla/CondVar.h" +#include "mozilla/DataMutex.h" +#include "mozilla/Mutex.h" +#include "nsISupportsImpl.h" +#include "nsIDNSListener.h" +#include "nsIDNSService.h" +#include "nsTArray.h" +#include "GetAddrInfo.h" +#include "mozilla/net/DNS.h" +#include "mozilla/net/DashboardTypes.h" +#include "mozilla/AtomicBitfields.h" +#include "mozilla/Atomics.h" +#include "mozilla/LinkedList.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/UniquePtr.h" +#include "nsRefPtrHashtable.h" +#include "nsIThreadPool.h" +#include "mozilla/net/NetworkConnectivityService.h" +#include "nsIDNSByTypeRecord.h" +#include "mozilla/net/DNSByTypeRecord.h" +#include "mozilla/Maybe.h" + +class nsHostResolver; +class nsResolveHostCallback; +namespace mozilla { +namespace net { +class TRR; +class TRRQuery; +enum ResolverMode { + MODE_NATIVEONLY, // 0 - TRR OFF (by default) + MODE_RESERVED1, // 1 - Reserved value. Used to be parallel resolve. + MODE_TRRFIRST, // 2 - fallback to native on TRR failure + MODE_TRRONLY, // 3 - don't even fallback + MODE_RESERVED4, // 4 - Reserved value. Used to be race TRR with native. + MODE_TRROFF // 5 - identical to MODE_NATIVEONLY but explicitly selected +}; +} // namespace net +} // namespace mozilla + +#define TRR_DISABLED(x) (((x) == MODE_NATIVEONLY) || ((x) == MODE_TRROFF)) + +extern mozilla::Atomic<bool, mozilla::Relaxed> gNativeIsLocalhost; + +#define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY 3 +#define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5 +#define MAX_NON_PRIORITY_REQUESTS 150 + +#define MAX_RESOLVER_THREADS \ + (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \ + MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY) + +struct nsHostKey { + const nsCString host; + const nsCString mTrrServer; + uint16_t type; + uint16_t flags; + uint16_t af; + bool pb; + const nsCString originSuffix; + explicit nsHostKey(const nsACString& host, const nsACString& aTrrServer, + uint16_t type, uint16_t flags, uint16_t af, bool pb, + const nsACString& originSuffix); + bool operator==(const nsHostKey& other) const; + size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + PLDHashNumber Hash() const; +}; + +/** + * nsHostRecord - ref counted object type stored in host resolver cache. + */ +class nsHostRecord : public mozilla::LinkedListElement<RefPtr<nsHostRecord>>, + public nsHostKey, + public nsISupports { + public: + NS_DECL_THREADSAFE_ISUPPORTS + + virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { + return 0; + } + + // Returns the TRR mode encoded by the flags + nsIRequest::TRRMode TRRMode(); + + // IMPORTANT: when adding new values, always add them to the end, otherwise + // it will mess up telemetry. + enum TRRSkippedReason : uint32_t { + TRR_UNSET = 0, + TRR_OK = 1, // Only set when we actually got a positive TRR result + TRR_NO_GSERVICE = 2, // no gService + TRR_PARENTAL_CONTROL = 3, // parental control is on + TRR_OFF_EXPLICIT = 4, // user has set mode5 + TRR_REQ_MODE_DISABLED = 5, // request has disabled flags set + TRR_MODE_NOT_ENABLED = 6, // mode0 + TRR_FAILED = 7, // unknown failure + TRR_MODE_UNHANDLED_DEFAULT = 8, // Unhandled case in ComputeEffectiveMode + TRR_MODE_UNHANDLED_DISABLED = 9, // Unhandled case in ComputeEffectiveMode + TRR_DISABLED_FLAG = 10, // the DISABLE_TRR flag was set + TRR_TIMEOUT = 11, // the TRR channel timed out + TRR_CHANNEL_DNS_FAIL = 12, // DoH server name failed to resolve + TRR_IS_OFFLINE = 13, // The browser is offline/no interfaces up + TRR_NOT_CONFIRMED = 14, // TRR confirmation is not done yet + TRR_DID_NOT_MAKE_QUERY = 15, // TrrLookup exited without doing a TRR query + TRR_UNKNOWN_CHANNEL_FAILURE = 16, // unknown channel failure reason + TRR_HOST_BLOCKED_TEMPORARY = 17, // host blocklisted + TRR_SEND_FAILED = 18, // The call to TRR::SendHTTPRequest failed + TRR_NET_RESET = 19, // NS_ERROR_NET_RESET + TRR_NET_TIMEOUT = 20, // NS_ERROR_NET_TIMEOUT + TRR_NET_REFUSED = 21, // NS_ERROR_CONNECTION_REFUSED + TRR_NET_INTERRUPT = 22, // NS_ERROR_NET_INTERRUPT + TRR_NET_INADEQ_SEQURITY = 23, // NS_ERROR_NET_INADEQUATE_SECURITY + TRR_NO_ANSWERS = 24, // TRR returned no answers + TRR_DECODE_FAILED = 25, // DohDecode failed + TRR_EXCLUDED = 26, // ExcludedFromTRR + TRR_SERVER_RESPONSE_ERR = 27, // Server responded with non-200 code + TRR_RCODE_FAIL = 28, // DNS response contains a non-NOERROR rcode + TRR_NO_CONNECTIVITY = 29, // Not confirmed because of no connectivity + }; + + // Records the first reason that caused TRR to be skipped or to fail. + void RecordReason(TRRSkippedReason reason) { + if (mTRRTRRSkippedReason == TRR_UNSET) { + mTRRTRRSkippedReason = reason; + } + } + + protected: + friend class nsHostResolver; + friend class mozilla::net::TRR; + friend class mozilla::net::TRRQuery; + + explicit nsHostRecord(const nsHostKey& key); + virtual ~nsHostRecord() = default; + + // Mark hostrecord as not usable + void Invalidate(); + + enum ExpirationStatus { + EXP_VALID, + EXP_GRACE, + EXP_EXPIRED, + }; + + ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const; + + // Convenience function for setting the timestamps above (mValidStart, + // mValidEnd, and mGraceStart). valid and grace are durations in seconds. + void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid, + unsigned int grace); + void CopyExpirationTimesAndFlagsFrom(const nsHostRecord* aFromHostRecord); + + // Checks if the record is usable (not expired and has a value) + bool HasUsableResult(const mozilla::TimeStamp& now, + uint16_t queryFlags = 0) const; + + enum DnsPriority { + DNS_PRIORITY_LOW, + DNS_PRIORITY_MEDIUM, + DNS_PRIORITY_HIGH, + }; + static DnsPriority GetPriority(uint16_t aFlags); + + virtual void Cancel(); + virtual bool HasUsableResultInternal() const { return false; } + + mozilla::LinkedList<RefPtr<nsResolveHostCallback>> mCallbacks; + + bool IsAddrRecord() const { + return type == nsIDNSService::RESOLVE_TYPE_DEFAULT; + } + + // When the record began being valid. Used mainly for bookkeeping. + mozilla::TimeStamp mValidStart; + + // When the record is no longer valid (it's time of expiration) + mozilla::TimeStamp mValidEnd; + + // When the record enters its grace period. This must be before mValidEnd. + // If a record is in its grace period (and not expired), it will be used + // but a request to refresh it will be made. + mozilla::TimeStamp mGraceStart; + + // The computed TRR mode that is actually used by the request. + // It is set in nsHostResolver::NameLookup and is based on the mode of the + // default resolver and the TRRMode encoded in the flags. + // The mode into account if the TRR service is disabled, + // parental controls are on, domain matches exclusion list, etc. + nsIRequest::TRRMode mEffectiveTRRMode; + + TRRSkippedReason mTRRTRRSkippedReason = TRR_UNSET; + TRRSkippedReason mTRRAFailReason = TRR_UNSET; + TRRSkippedReason mTRRAAAAFailReason = TRR_UNSET; + + mozilla::DataMutex<RefPtr<mozilla::net::TRRQuery>> mTRRQuery; + + mozilla::Atomic<int32_t> + mResolving; // counter of outstanding resolving calls + + uint8_t negative : 1; /* True if this record is a cache of a failed + lookup. Negative cache entries are valid just + like any other (though never for more than 60 + seconds), but a use of that negative entry + forces an asynchronous refresh. */ + uint8_t mDoomed : 1; // explicitly expired +}; + +// b020e996-f6ab-45e5-9bf5-1da71dd0053a +#define ADDRHOSTRECORD_IID \ + { \ + 0xb020e996, 0xf6ab, 0x45e5, { \ + 0x9b, 0xf5, 0x1d, 0xa7, 0x1d, 0xd0, 0x05, 0x3a \ + } \ + } + +class AddrHostRecord final : public nsHostRecord { + typedef mozilla::Mutex Mutex; + + public: + NS_DECLARE_STATIC_IID_ACCESSOR(ADDRHOSTRECORD_IID) + NS_DECL_ISUPPORTS_INHERITED + + /* a fully resolved host record has either a non-null |addr_info| or |addr| + * field. if |addr_info| is null, it implies that the |host| is an IP + * address literal. in which case, |addr| contains the parsed address. + * otherwise, if |addr_info| is non-null, then it contains one or many + * IP addresses corresponding to the given host name. if both |addr_info| + * and |addr| are null, then the given host has not yet been fully resolved. + * |af| is the address family of the record we are querying for. + */ + + /* the lock protects |addr_info| and |addr_info_gencnt| because they + * are mutable and accessed by the resolver worker thread and the + * nsDNSService2 class. |addr| doesn't change after it has been + * assigned a value. only the resolver worker thread modifies + * nsHostRecord (and only in nsHostResolver::CompleteLookup); + * the other threads just read it. therefore the resolver worker + * thread doesn't need to lock when reading |addr_info|. + */ + Mutex addr_info_lock; + int addr_info_gencnt; /* generation count of |addr_info| */ + RefPtr<mozilla::net::AddrInfo> addr_info; + mozilla::UniquePtr<mozilla::net::NetAddr> addr; + + // hold addr_info_lock when calling the blocklist functions + bool Blocklisted(const mozilla::net::NetAddr* query); + void ResetBlocklist(); + void ReportUnusable(const mozilla::net::NetAddr* aAddress); + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override; + + nsIRequest::TRRMode EffectiveTRRMode() const { return mEffectiveTRRMode; } + + private: + friend class nsHostResolver; + friend class mozilla::net::TRR; + friend class mozilla::net::TRRQuery; + + explicit AddrHostRecord(const nsHostKey& key); + ~AddrHostRecord(); + + // Checks if the record is usable (not expired and has a value) + bool HasUsableResultInternal() const override; + + bool RemoveOrRefresh(bool aTrrToo); // Mark records currently being resolved + // as needed to resolve again. + + void ResolveComplete(); + + enum DnsPriority { + DNS_PRIORITY_LOW, + DNS_PRIORITY_MEDIUM, + DNS_PRIORITY_HIGH, + }; + static DnsPriority GetPriority(uint16_t aFlags); + + // true if pending and on the queue (not yet given to getaddrinfo()) + bool onQueue() { return LoadNative() && isInList(); } + + // When the lookups of this record started and their durations + mozilla::TimeStamp mTrrStart; + mozilla::TimeStamp mNativeStart; + mozilla::TimeDuration mTrrDuration; + mozilla::TimeDuration mNativeDuration; + + mozilla::Atomic<bool> mTRRUsed; // TRR was used on this record + uint8_t mTRRSuccess; // number of successful TRR responses + uint8_t mNativeSuccess; // number of native lookup responses + + // clang-format off + MOZ_ATOMIC_BITFIELDS(mAtomicBitfields, 8, ( + // true if this record is being resolved "natively", which means that + // it is either on the pending queue or owned by one of the worker threads. + (uint16_t, Native, 1), + (uint16_t, NativeUsed, 1), + // true if off queue and contributing to mActiveAnyThreadCount + (uint16_t, UsingAnyThread, 1), + (uint16_t, GetTtl, 1), + (uint16_t, ResolveAgain, 1) + )) + // clang-format on + + // The number of times ReportUnusable() has been called in the record's + // lifetime. + uint32_t mUnusableCount = 0; + + // a list of addresses associated with this record that have been reported + // as unusable. the list is kept as a set of strings to make it independent + // of gencnt. + nsTArray<nsCString> mUnusableItems; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(AddrHostRecord, ADDRHOSTRECORD_IID) + +// 77b786a7-04be-44f2-987c-ab8aa96676e0 +#define TYPEHOSTRECORD_IID \ + { \ + 0x77b786a7, 0x04be, 0x44f2, { \ + 0x98, 0x7c, 0xab, 0x8a, 0xa9, 0x66, 0x76, 0xe0 \ + } \ + } + +class TypeHostRecord final : public nsHostRecord, + public nsIDNSTXTRecord, + public nsIDNSHTTPSSVCRecord, + public mozilla::net::DNSHTTPSSVCRecordBase { + public: + NS_DECLARE_STATIC_IID_ACCESSOR(TYPEHOSTRECORD_IID) + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDNSTXTRECORD + NS_DECL_NSIDNSHTTPSSVCRECORD + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const override; + uint32_t GetType(); + mozilla::net::TypeRecordResultType GetResults(); + + private: + friend class nsHostResolver; + friend class mozilla::net::TRRQuery; + + explicit TypeHostRecord(const nsHostKey& key); + ~TypeHostRecord(); + + // Checks if the record is usable (not expired and has a value) + bool HasUsableResultInternal() const override; + + bool HasUsableResult(); + + mozilla::net::TypeRecordResultType mResults = AsVariant(mozilla::Nothing()); + mozilla::Mutex mResultsLock; + + // When the lookups of this record started (for telemetry). + mozilla::TimeStamp mStart; + bool mAllRecordsExcluded = false; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(TypeHostRecord, TYPEHOSTRECORD_IID) + +/** + * This class is used to notify listeners when a ResolveHost operation is + * complete. Classes that derive it must implement threadsafe nsISupports + * to be able to use RefPtr with this class. + */ +class nsResolveHostCallback + : public mozilla::LinkedListElement<RefPtr<nsResolveHostCallback>>, + public nsISupports { + public: + /** + * OnResolveHostComplete + * + * this function is called to complete a host lookup initiated by + * nsHostResolver::ResolveHost. it may be invoked recursively from + * ResolveHost or on an unspecified background thread. + * + * NOTE: it is the responsibility of the implementor of this method + * to handle the callback in a thread safe manner. + * + * @param resolver + * nsHostResolver object associated with this result + * @param record + * the host record containing the results of the lookup + * @param status + * if successful, |record| contains non-null results + */ + virtual void OnResolveHostComplete(nsHostResolver* resolver, + nsHostRecord* record, nsresult status) = 0; + /** + * EqualsAsyncListener + * + * Determines if the listener argument matches the listener member var. + * For subclasses not implementing a member listener, should return false. + * For subclasses having a member listener, the function should check if + * they are the same. Used for cases where a pointer to an object + * implementing nsResolveHostCallback is unknown, but a pointer to + * the original listener is known. + * + * @param aListener + * nsIDNSListener object associated with the original request + */ + virtual bool EqualsAsyncListener(nsIDNSListener* aListener) = 0; + + virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0; + + protected: + virtual ~nsResolveHostCallback() = default; +}; + +class AHostResolver { + public: + AHostResolver() = default; + virtual ~AHostResolver() = default; + NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING + + enum LookupStatus { + LOOKUP_OK, + LOOKUP_RESOLVEAGAIN, + }; + + virtual LookupStatus CompleteLookup( + nsHostRecord*, nsresult, mozilla::net::AddrInfo*, bool pb, + const nsACString& aOriginsuffix, + nsHostRecord::TRRSkippedReason aReason) = 0; + virtual LookupStatus CompleteLookupByType( + nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult, + uint32_t aTtl, bool pb) = 0; + virtual nsresult GetHostRecord(const nsACString& host, + const nsACString& aTrrServer, uint16_t type, + uint16_t flags, uint16_t af, bool pb, + const nsCString& originSuffix, + nsHostRecord** result) { + return NS_ERROR_FAILURE; + } + virtual nsresult TrrLookup_unlocked(nsHostRecord*, + mozilla::net::TRR* pushedTRR = nullptr) { + return NS_ERROR_FAILURE; + } + virtual void MaybeRenewHostRecord(nsHostRecord* aRec) {} +}; + +/** + * nsHostResolver - an asynchronous host name resolver. + */ +class nsHostResolver : public nsISupports, public AHostResolver { + using CondVar = mozilla::CondVar; + using Mutex = mozilla::Mutex; + + public: + NS_DECL_THREADSAFE_ISUPPORTS + + /** + * creates an addref'd instance of a nsHostResolver object. + */ + static nsresult Create(uint32_t maxCacheEntries, // zero disables cache + uint32_t defaultCacheEntryLifetime, // seconds + uint32_t defaultGracePeriod, // seconds + nsHostResolver** result); + + /** + * Set (new) cache limits. + */ + void SetCacheLimits(uint32_t maxCacheEntries, // zero disables cache + uint32_t defaultCacheEntryLifetime, // seconds + uint32_t defaultGracePeriod); // seconds + + /** + * puts the resolver in the shutdown state, which will cause any pending + * callbacks to be detached. any future calls to ResolveHost will fail. + */ + void Shutdown(); + + /** + * resolve the given hostname and originAttributes asynchronously. the caller + * can synthesize a synchronous host lookup using a lock and a cvar. as noted + * above the callback will occur re-entrantly from an unspecified thread. the + * host lookup cannot be canceled (cancelation can be layered above this by + * having the callback implementation return without doing anything). + */ + nsresult ResolveHost(const nsACString& aHost, const nsACString& trrServer, + uint16_t type, + const mozilla::OriginAttributes& aOriginAttributes, + uint16_t flags, uint16_t af, + nsResolveHostCallback* callback); + + nsHostRecord* InitRecord(const nsHostKey& key); + mozilla::net::NetworkConnectivityService* GetNCS() { return mNCS; } + + /** + * return a resolved hard coded loopback dns record for the specified key + */ + already_AddRefed<nsHostRecord> InitLoopbackRecord(const nsHostKey& key, + nsresult* aRv); + + /** + * removes the specified callback from the nsHostRecord for the given + * hostname, originAttributes, flags, and address family. these parameters + * should correspond to the parameters passed to ResolveHost. this function + * executes the callback if the callback is still pending with the given + * status. + */ + void DetachCallback(const nsACString& hostname, const nsACString& trrServer, + uint16_t type, + const mozilla::OriginAttributes& aOriginAttributes, + uint16_t flags, uint16_t af, + nsResolveHostCallback* callback, nsresult status); + + /** + * Cancels an async request associated with the hostname, originAttributes, + * flags, address family and listener. Cancels first callback found which + * matches these criteria. These parameters should correspond to the + * parameters passed to ResolveHost. If this is the last callback associated + * with the host record, it is removed from any request queues it might be on. + */ + void CancelAsyncRequest(const nsACString& host, const nsACString& trrServer, + uint16_t type, + const mozilla::OriginAttributes& aOriginAttributes, + uint16_t flags, uint16_t af, + nsIDNSListener* aListener, nsresult status); + /** + * values for the flags parameter passed to ResolveHost and DetachCallback + * that may be bitwise OR'd together. + * + * NOTE: in this implementation, these flags correspond exactly in value + * to the flags defined on nsIDNSService. + */ + enum { + RES_BYPASS_CACHE = nsIDNSService::RESOLVE_BYPASS_CACHE, + RES_CANON_NAME = nsIDNSService::RESOLVE_CANONICAL_NAME, + RES_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM, + RES_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW, + RES_SPECULATE = nsIDNSService::RESOLVE_SPECULATE, + // RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used + RES_OFFLINE = nsIDNSService::RESOLVE_OFFLINE, + // RES_DISABLE_IPv4 = nsIDNSService::RESOLVE_DISABLE_IPV4, // Not Used + RES_ALLOW_NAME_COLLISION = nsIDNSService::RESOLVE_ALLOW_NAME_COLLISION, + RES_DISABLE_TRR = nsIDNSService::RESOLVE_DISABLE_TRR, + RES_REFRESH_CACHE = nsIDNSService::RESOLVE_REFRESH_CACHE, + RES_IP_HINT = nsIDNSService::RESOLVE_IP_HINT + }; + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + + /** + * Flush the DNS cache. + */ + void FlushCache(bool aTrrToo); + + LookupStatus CompleteLookup(nsHostRecord*, nsresult, mozilla::net::AddrInfo*, + bool pb, const nsACString& aOriginsuffix, + nsHostRecord::TRRSkippedReason aReason) override; + LookupStatus CompleteLookupByType(nsHostRecord*, nsresult, + mozilla::net::TypeRecordResultType& aResult, + uint32_t aTtl, bool pb) override; + nsresult GetHostRecord(const nsACString& host, const nsACString& trrServer, + uint16_t type, uint16_t flags, uint16_t af, bool pb, + const nsCString& originSuffix, + nsHostRecord** result) override; + nsresult TrrLookup_unlocked(nsHostRecord*, + mozilla::net::TRR* pushedTRR = nullptr) override; + static mozilla::net::ResolverMode Mode(); + + virtual void MaybeRenewHostRecord(nsHostRecord* aRec) override; + + private: + explicit nsHostResolver(uint32_t maxCacheEntries, + uint32_t defaultCacheEntryLifetime, + uint32_t defaultGracePeriod); + virtual ~nsHostResolver(); + + nsresult Init(); + // In debug builds it asserts that the element is in the list. + void AssertOnQ(nsHostRecord*, mozilla::LinkedList<RefPtr<nsHostRecord>>&); + static void ComputeEffectiveTRRMode(nsHostRecord* aRec); + nsresult NativeLookup(nsHostRecord*); + nsresult TrrLookup(nsHostRecord*, mozilla::net::TRR* pushedTRR = nullptr); + + // Kick-off a name resolve operation, using native resolver and/or TRR + nsresult NameLookup(nsHostRecord*); + bool GetHostToLookup(AddrHostRecord** result); + void MaybeRenewHostRecordLocked(nsHostRecord* aRec); + + // Removes the first element from the list and returns it AddRef-ed in aResult + // Should not be called for an empty linked list. + void DeQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aQ, + AddrHostRecord** aResult); + // Cancels host records in the pending queue and also + // calls CompleteLookup with the NS_ERROR_ABORT result code. + void ClearPendingQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aPendingQ); + nsresult ConditionallyCreateThread(nsHostRecord* rec); + + /** + * Starts a new lookup in the background for entries that are in the grace + * period with a failed connect or all cached entries are negative. + */ + nsresult ConditionallyRefreshRecord(nsHostRecord* rec, + const nsACString& host); + + void AddToEvictionQ(nsHostRecord* rec); + + void ThreadFunc(); + + enum { + METHOD_HIT = 1, + METHOD_RENEWAL = 2, + METHOD_NEGATIVE_HIT = 3, + METHOD_LITERAL = 4, + METHOD_OVERFLOW = 5, + METHOD_NETWORK_FIRST = 6, + METHOD_NETWORK_SHARED = 7 + }; + + uint32_t mMaxCacheEntries; + uint32_t mDefaultCacheLifetime; // granularity seconds + uint32_t mDefaultGracePeriod; // granularity seconds + mutable Mutex mLock; // mutable so SizeOfIncludingThis can be const + CondVar mIdleTaskCV; + nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB; + mozilla::LinkedList<RefPtr<nsHostRecord>> mHighQ; + mozilla::LinkedList<RefPtr<nsHostRecord>> mMediumQ; + mozilla::LinkedList<RefPtr<nsHostRecord>> mLowQ; + mozilla::LinkedList<RefPtr<nsHostRecord>> mEvictionQ; + uint32_t mEvictionQSize; + PRTime mCreationTime; + mozilla::TimeDuration mLongIdleTimeout; + mozilla::TimeDuration mShortIdleTimeout; + + RefPtr<nsIThreadPool> mResolverThreads; + RefPtr<mozilla::net::NetworkConnectivityService> mNCS; + + mozilla::Atomic<bool> mShutdown; + mozilla::Atomic<uint32_t> mNumIdleTasks; + mozilla::Atomic<uint32_t> mActiveTaskCount; + mozilla::Atomic<uint32_t> mActiveAnyThreadCount; + mozilla::Atomic<uint32_t> mPendingCount; + + // Set the expiration time stamps appropriately. + void PrepareRecordExpirationAddrRecord(AddrHostRecord* rec) const; + + public: + /* + * Called by the networking dashboard via the DnsService2 + */ + void GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries>*); +}; + +#endif // nsHostResolver_h__ |