summaryrefslogtreecommitdiffstats
path: root/netwerk/dns/nsHostResolver.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /netwerk/dns/nsHostResolver.h
parentInitial commit. (diff)
downloadfirefox-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.h654
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__