Bug 1796551 [wpt PR 36570] - WebKit export of https://bugs.webkit.org/show_bug.cgi...
[gecko.git] / netwerk / dns / nsHostResolver.h
blob3467b3884a7574b7b17e3431899f9c38ff696bed
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 nsHostResolver_h__
7 #define nsHostResolver_h__
9 #include "nscore.h"
10 #include "prnetdb.h"
11 #include "PLDHashTable.h"
12 #include "mozilla/CondVar.h"
13 #include "mozilla/DataMutex.h"
14 #include "nsISupportsImpl.h"
15 #include "nsIDNSListener.h"
16 #include "nsTArray.h"
17 #include "GetAddrInfo.h"
18 #include "HostRecordQueue.h"
19 #include "mozilla/net/DNS.h"
20 #include "mozilla/net/DashboardTypes.h"
21 #include "mozilla/Atomics.h"
22 #include "mozilla/TimeStamp.h"
23 #include "mozilla/UniquePtr.h"
24 #include "nsHostRecord.h"
25 #include "nsRefPtrHashtable.h"
26 #include "nsIThreadPool.h"
27 #include "mozilla/net/NetworkConnectivityService.h"
28 #include "mozilla/net/DNSByTypeRecord.h"
29 #include "mozilla/Maybe.h"
31 namespace mozilla {
32 namespace net {
33 class TRR;
34 class TRRQuery;
35 } // namespace net
36 } // namespace mozilla
38 #define TRR_DISABLED(x) \
39 (((x) == nsIDNSService::MODE_NATIVEONLY) || \
40 ((x) == nsIDNSService::MODE_TRROFF))
42 extern mozilla::Atomic<bool, mozilla::Relaxed> gNativeIsLocalhost;
44 #define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY 3
45 #define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
46 #define MAX_NON_PRIORITY_REQUESTS 150
48 #define MAX_RESOLVER_THREADS \
49 (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
50 MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
52 class AHostResolver {
53 public:
54 AHostResolver() = default;
55 virtual ~AHostResolver() = default;
56 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
58 enum LookupStatus {
59 LOOKUP_OK,
60 LOOKUP_RESOLVEAGAIN,
63 virtual LookupStatus CompleteLookup(nsHostRecord*, nsresult,
64 mozilla::net::AddrInfo*, bool pb,
65 const nsACString& aOriginsuffix,
66 mozilla::net::TRRSkippedReason aReason,
67 mozilla::net::TRR*) = 0;
68 virtual LookupStatus CompleteLookupByType(
69 nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
70 uint32_t aTtl, bool pb) = 0;
71 virtual nsresult GetHostRecord(const nsACString& host,
72 const nsACString& aTrrServer, uint16_t type,
73 uint16_t flags, uint16_t af, bool pb,
74 const nsCString& originSuffix,
75 nsHostRecord** result) {
76 return NS_ERROR_FAILURE;
78 virtual nsresult TrrLookup_unlocked(nsHostRecord*,
79 mozilla::net::TRR* pushedTRR = nullptr) {
80 return NS_ERROR_FAILURE;
82 virtual void MaybeRenewHostRecord(nsHostRecord* aRec) {}
85 /**
86 * nsHostResolver - an asynchronous host name resolver.
88 class nsHostResolver : public nsISupports, public AHostResolver {
89 using CondVar = mozilla::CondVar;
90 using Mutex = mozilla::Mutex;
92 public:
93 NS_DECL_THREADSAFE_ISUPPORTS
95 /**
96 * creates an addref'd instance of a nsHostResolver object.
98 static nsresult Create(uint32_t maxCacheEntries, // zero disables cache
99 uint32_t defaultCacheEntryLifetime, // seconds
100 uint32_t defaultGracePeriod, // seconds
101 nsHostResolver** result);
104 * Set (new) cache limits.
106 void SetCacheLimits(uint32_t maxCacheEntries, // zero disables cache
107 uint32_t defaultCacheEntryLifetime, // seconds
108 uint32_t defaultGracePeriod); // seconds
111 * puts the resolver in the shutdown state, which will cause any pending
112 * callbacks to be detached. any future calls to ResolveHost will fail.
114 void Shutdown();
117 * resolve the given hostname and originAttributes asynchronously. the caller
118 * can synthesize a synchronous host lookup using a lock and a cvar. as noted
119 * above the callback will occur re-entrantly from an unspecified thread. the
120 * host lookup cannot be canceled (cancelation can be layered above this by
121 * having the callback implementation return without doing anything).
123 nsresult ResolveHost(const nsACString& aHost, const nsACString& trrServer,
124 int32_t aPort, uint16_t type,
125 const mozilla::OriginAttributes& aOriginAttributes,
126 uint16_t flags, uint16_t af,
127 nsResolveHostCallback* callback);
129 nsHostRecord* InitRecord(const nsHostKey& key);
130 mozilla::net::NetworkConnectivityService* GetNCS() {
131 return mNCS;
132 } // This is actually a singleton
135 * return a resolved hard coded loopback dns record for the specified key
137 already_AddRefed<nsHostRecord> InitLoopbackRecord(const nsHostKey& key,
138 nsresult* aRv);
141 * removes the specified callback from the nsHostRecord for the given
142 * hostname, originAttributes, flags, and address family. these parameters
143 * should correspond to the parameters passed to ResolveHost. this function
144 * executes the callback if the callback is still pending with the given
145 * status.
147 void DetachCallback(const nsACString& hostname, const nsACString& trrServer,
148 uint16_t type,
149 const mozilla::OriginAttributes& aOriginAttributes,
150 uint16_t flags, uint16_t af,
151 nsResolveHostCallback* callback, nsresult status);
154 * Cancels an async request associated with the hostname, originAttributes,
155 * flags, address family and listener. Cancels first callback found which
156 * matches these criteria. These parameters should correspond to the
157 * parameters passed to ResolveHost. If this is the last callback associated
158 * with the host record, it is removed from any request queues it might be on.
160 void CancelAsyncRequest(const nsACString& host, const nsACString& trrServer,
161 uint16_t type,
162 const mozilla::OriginAttributes& aOriginAttributes,
163 uint16_t flags, uint16_t af,
164 nsIDNSListener* aListener, nsresult status);
166 * values for the flags parameter passed to ResolveHost and DetachCallback
167 * that may be bitwise OR'd together.
169 * NOTE: in this implementation, these flags correspond exactly in value
170 * to the flags defined on nsIDNSService.
172 enum {
173 RES_BYPASS_CACHE = nsIDNSService::RESOLVE_BYPASS_CACHE,
174 RES_CANON_NAME = nsIDNSService::RESOLVE_CANONICAL_NAME,
175 RES_PRIORITY_MEDIUM = nsHostRecord::DNS_PRIORITY_MEDIUM,
176 RES_PRIORITY_LOW = nsHostRecord::DNS_PRIORITY_LOW,
177 RES_SPECULATE = nsIDNSService::RESOLVE_SPECULATE,
178 // RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used
179 RES_OFFLINE = nsIDNSService::RESOLVE_OFFLINE,
180 // RES_DISABLE_IPv4 = nsIDNSService::RESOLVE_DISABLE_IPV4, // Not Used
181 RES_ALLOW_NAME_COLLISION = nsIDNSService::RESOLVE_ALLOW_NAME_COLLISION,
182 RES_DISABLE_TRR = nsIDNSService::RESOLVE_DISABLE_TRR,
183 RES_REFRESH_CACHE = nsIDNSService::RESOLVE_REFRESH_CACHE,
184 RES_IP_HINT = nsIDNSService::RESOLVE_IP_HINT
187 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
190 * Flush the DNS cache.
192 void FlushCache(bool aTrrToo);
194 LookupStatus CompleteLookup(nsHostRecord*, nsresult, mozilla::net::AddrInfo*,
195 bool pb, const nsACString& aOriginsuffix,
196 mozilla::net::TRRSkippedReason aReason,
197 mozilla::net::TRR* aTRRRequest) override;
198 LookupStatus CompleteLookupByType(nsHostRecord*, nsresult,
199 mozilla::net::TypeRecordResultType& aResult,
200 uint32_t aTtl, bool pb) override;
201 nsresult GetHostRecord(const nsACString& host, const nsACString& trrServer,
202 uint16_t type, uint16_t flags, uint16_t af, bool pb,
203 const nsCString& originSuffix,
204 nsHostRecord** result) override;
205 nsresult TrrLookup_unlocked(nsHostRecord*,
206 mozilla::net::TRR* pushedTRR = nullptr) override;
207 static nsIDNSService::ResolverMode Mode();
209 virtual void MaybeRenewHostRecord(nsHostRecord* aRec) override;
211 // Records true if the TRR service is enabled for the record's effective
212 // TRR mode. Also records the TRRSkipReason when the TRR service is not
213 // available/enabled.
214 bool TRRServiceEnabledForRecord(nsHostRecord* aRec) MOZ_REQUIRES(mLock);
216 private:
217 explicit nsHostResolver(uint32_t maxCacheEntries,
218 uint32_t defaultCacheEntryLifetime,
219 uint32_t defaultGracePeriod);
220 virtual ~nsHostResolver();
222 bool MaybeRetryTRRLookup(
223 AddrHostRecord* aAddrRec, nsresult aFirstAttemptStatus,
224 mozilla::net::TRRSkippedReason aFirstAttemptSkipReason,
225 const mozilla::MutexAutoLock& aLock);
227 LookupStatus CompleteLookupLocked(nsHostRecord*, nsresult,
228 mozilla::net::AddrInfo*, bool pb,
229 const nsACString& aOriginsuffix,
230 mozilla::net::TRRSkippedReason aReason,
231 mozilla::net::TRR* aTRRRequest,
232 const mozilla::MutexAutoLock& aLock)
233 MOZ_REQUIRES(mLock);
234 LookupStatus CompleteLookupByTypeLocked(
235 nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult,
236 uint32_t aTtl, bool pb, const mozilla::MutexAutoLock& aLock)
237 MOZ_REQUIRES(mLock);
238 nsresult Init();
239 static void ComputeEffectiveTRRMode(nsHostRecord* aRec);
240 nsresult NativeLookup(nsHostRecord* aRec,
241 const mozilla::MutexAutoLock& aLock);
242 nsresult TrrLookup(nsHostRecord*, const mozilla::MutexAutoLock& aLock,
243 mozilla::net::TRR* pushedTRR = nullptr);
245 // Kick-off a name resolve operation, using native resolver and/or TRR
246 nsresult NameLookup(nsHostRecord* aRec, const mozilla::MutexAutoLock& aLock);
247 bool GetHostToLookup(AddrHostRecord** result);
248 void MaybeRenewHostRecordLocked(nsHostRecord* aRec,
249 const mozilla::MutexAutoLock& aLock)
250 MOZ_REQUIRES(mLock);
252 // Cancels host records in the pending queue and also
253 // calls CompleteLookup with the NS_ERROR_ABORT result code.
254 void ClearPendingQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aPendingQ);
255 nsresult ConditionallyCreateThread(nsHostRecord* rec) MOZ_REQUIRES(mLock);
258 * Starts a new lookup in the background for entries that are in the grace
259 * period with a failed connect or all cached entries are negative.
261 nsresult ConditionallyRefreshRecord(nsHostRecord* rec, const nsACString& host,
262 const mozilla::MutexAutoLock& aLock)
263 MOZ_REQUIRES(mLock);
265 void AddToEvictionQ(nsHostRecord* rec, const mozilla::MutexAutoLock& aLock)
266 MOZ_REQUIRES(mLock);
268 void ThreadFunc();
270 // Resolve the host from the DNS cache.
271 already_AddRefed<nsHostRecord> FromCache(nsHostRecord* aRec,
272 const nsACString& aHost,
273 uint16_t aType, nsresult& aStatus,
274 const mozilla::MutexAutoLock& aLock)
275 MOZ_REQUIRES(mLock);
276 // Called when the host name is an IP address and has been passed.
277 already_AddRefed<nsHostRecord> FromCachedIPLiteral(nsHostRecord* aRec);
278 // Like the above function, but the host name is not parsed to NetAddr yet.
279 already_AddRefed<nsHostRecord> FromIPLiteral(
280 AddrHostRecord* aAddrRec, const mozilla::net::NetAddr& aAddr);
281 // Called to check if we have an AF_UNSPEC entry in the cache.
282 already_AddRefed<nsHostRecord> FromUnspecEntry(
283 nsHostRecord* aRec, const nsACString& aHost, const nsACString& aTrrServer,
284 const nsACString& aOriginSuffix, uint16_t aType, uint16_t aFlags,
285 uint16_t af, bool aPb, nsresult& aStatus) MOZ_REQUIRES(mLock);
287 enum {
288 METHOD_HIT = 1,
289 METHOD_RENEWAL = 2,
290 METHOD_NEGATIVE_HIT = 3,
291 METHOD_LITERAL = 4,
292 METHOD_OVERFLOW = 5,
293 METHOD_NETWORK_FIRST = 6,
294 METHOD_NETWORK_SHARED = 7
297 uint32_t mMaxCacheEntries = 0;
298 uint32_t mDefaultCacheLifetime = 0; // granularity seconds
299 uint32_t mDefaultGracePeriod = 0; // granularity seconds
300 // mutable so SizeOfIncludingThis can be const
301 mutable Mutex mLock{"nsHostResolver.mLock"};
302 CondVar mIdleTaskCV;
303 nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB
304 MOZ_GUARDED_BY(mLock);
305 PRTime mCreationTime;
306 mozilla::TimeDuration mLongIdleTimeout;
307 mozilla::TimeDuration mShortIdleTimeout;
309 RefPtr<nsIThreadPool> mResolverThreads;
310 RefPtr<mozilla::net::NetworkConnectivityService>
311 mNCS; // reference to a singleton
312 mozilla::net::HostRecordQueue mQueue MOZ_GUARDED_BY(mLock);
313 mozilla::Atomic<bool> mShutdown MOZ_GUARDED_BY(mLock){true};
314 mozilla::Atomic<uint32_t> mNumIdleTasks MOZ_GUARDED_BY(mLock){0};
315 mozilla::Atomic<uint32_t> mActiveTaskCount MOZ_GUARDED_BY(mLock){0};
316 mozilla::Atomic<uint32_t> mActiveAnyThreadCount MOZ_GUARDED_BY(mLock){0};
318 // Set the expiration time stamps appropriately.
319 void PrepareRecordExpirationAddrRecord(AddrHostRecord* rec) const;
321 public:
323 * Called by the networking dashboard via the DnsService2
325 void GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries>*);
328 #endif // nsHostResolver_h__