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__
11 #include "PLDHashTable.h"
12 #include "mozilla/CondVar.h"
13 #include "mozilla/DataMutex.h"
14 #include "nsISupportsImpl.h"
15 #include "nsIDNSListener.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"
30 #include "mozilla/StaticPrefs_network.h"
37 static inline uint32_t MaxResolverThreadsAnyPriority() {
38 return StaticPrefs::network_dns_max_any_priority_threads();
41 static inline uint32_t MaxResolverThreadsHighPriority() {
42 return StaticPrefs::network_dns_max_high_priority_threads();
45 static inline uint32_t MaxResolverThreads() {
46 return MaxResolverThreadsAnyPriority() + MaxResolverThreadsHighPriority();
50 } // namespace mozilla
52 #define TRR_DISABLED(x) \
53 (((x) == nsIDNSService::MODE_NATIVEONLY) || \
54 ((x) == nsIDNSService::MODE_TRROFF))
56 extern mozilla::Atomic
<bool, mozilla::Relaxed
> gNativeIsLocalhost
;
58 #define MAX_NON_PRIORITY_REQUESTS 150
62 AHostResolver() = default;
63 virtual ~AHostResolver() = default;
64 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
71 virtual LookupStatus
CompleteLookup(nsHostRecord
*, nsresult
,
72 mozilla::net::AddrInfo
*, bool pb
,
73 const nsACString
& aOriginsuffix
,
74 mozilla::net::TRRSkippedReason aReason
,
75 mozilla::net::TRR
*) = 0;
76 virtual LookupStatus
CompleteLookupByType(
77 nsHostRecord
*, nsresult
, mozilla::net::TypeRecordResultType
& aResult
,
78 uint32_t aTtl
, bool pb
) = 0;
79 virtual nsresult
GetHostRecord(const nsACString
& host
,
80 const nsACString
& aTrrServer
, uint16_t type
,
81 nsIDNSService::DNSFlags flags
, uint16_t af
,
82 bool pb
, const nsCString
& originSuffix
,
83 nsHostRecord
** result
) {
84 return NS_ERROR_FAILURE
;
86 virtual nsresult
TrrLookup_unlocked(nsHostRecord
*,
87 mozilla::net::TRR
* pushedTRR
= nullptr) {
88 return NS_ERROR_FAILURE
;
90 virtual void MaybeRenewHostRecord(nsHostRecord
* aRec
) {}
94 * nsHostResolver - an asynchronous host name resolver.
96 class nsHostResolver
: public nsISupports
, public AHostResolver
{
97 using CondVar
= mozilla::CondVar
;
98 using Mutex
= mozilla::Mutex
;
101 NS_DECL_THREADSAFE_ISUPPORTS
104 * creates an addref'd instance of a nsHostResolver object.
106 static nsresult
Create(uint32_t maxCacheEntries
, // zero disables cache
107 uint32_t defaultCacheEntryLifetime
, // seconds
108 uint32_t defaultGracePeriod
, // seconds
109 nsHostResolver
** result
);
112 * Set (new) cache limits.
114 void SetCacheLimits(uint32_t maxCacheEntries
, // zero disables cache
115 uint32_t defaultCacheEntryLifetime
, // seconds
116 uint32_t defaultGracePeriod
); // seconds
119 * puts the resolver in the shutdown state, which will cause any pending
120 * callbacks to be detached. any future calls to ResolveHost will fail.
125 * resolve the given hostname and originAttributes asynchronously. the caller
126 * can synthesize a synchronous host lookup using a lock and a cvar. as noted
127 * above the callback will occur re-entrantly from an unspecified thread. the
128 * host lookup cannot be canceled (cancelation can be layered above this by
129 * having the callback implementation return without doing anything).
131 nsresult
ResolveHost(const nsACString
& aHost
, const nsACString
& trrServer
,
132 int32_t aPort
, uint16_t type
,
133 const mozilla::OriginAttributes
& aOriginAttributes
,
134 nsIDNSService::DNSFlags flags
, uint16_t af
,
135 nsResolveHostCallback
* callback
);
137 nsHostRecord
* InitRecord(const nsHostKey
& key
);
138 mozilla::net::NetworkConnectivityService
* GetNCS() {
140 } // This is actually a singleton
143 * return a resolved hard coded loopback dns record for the specified key
145 already_AddRefed
<nsHostRecord
> InitLoopbackRecord(const nsHostKey
& key
,
149 * removes the specified callback from the nsHostRecord for the given
150 * hostname, originAttributes, flags, and address family. these parameters
151 * should correspond to the parameters passed to ResolveHost. this function
152 * executes the callback if the callback is still pending with the given
155 void DetachCallback(const nsACString
& hostname
, const nsACString
& trrServer
,
157 const mozilla::OriginAttributes
& aOriginAttributes
,
158 nsIDNSService::DNSFlags flags
, uint16_t af
,
159 nsResolveHostCallback
* callback
, nsresult status
);
162 * Cancels an async request associated with the hostname, originAttributes,
163 * flags, address family and listener. Cancels first callback found which
164 * matches these criteria. These parameters should correspond to the
165 * parameters passed to ResolveHost. If this is the last callback associated
166 * with the host record, it is removed from any request queues it might be on.
168 void CancelAsyncRequest(const nsACString
& host
, const nsACString
& trrServer
,
170 const mozilla::OriginAttributes
& aOriginAttributes
,
171 nsIDNSService::DNSFlags flags
, uint16_t af
,
172 nsIDNSListener
* aListener
, nsresult status
);
174 * values for the flags parameter passed to ResolveHost and DetachCallback
175 * that may be bitwise OR'd together.
177 * NOTE: in this implementation, these flags correspond exactly in value
178 * to the flags defined on nsIDNSService.
181 RES_BYPASS_CACHE
= nsIDNSService::RESOLVE_BYPASS_CACHE
,
182 RES_CANON_NAME
= nsIDNSService::RESOLVE_CANONICAL_NAME
,
183 RES_PRIORITY_MEDIUM
= nsHostRecord::DNS_PRIORITY_MEDIUM
,
184 RES_PRIORITY_LOW
= nsHostRecord::DNS_PRIORITY_LOW
,
185 RES_SPECULATE
= nsIDNSService::RESOLVE_SPECULATE
,
186 // RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used
187 RES_OFFLINE
= nsIDNSService::RESOLVE_OFFLINE
,
188 // RES_DISABLE_IPv4 = nsIDNSService::RESOLVE_DISABLE_IPV4, // Not Used
189 RES_ALLOW_NAME_COLLISION
= nsIDNSService::RESOLVE_ALLOW_NAME_COLLISION
,
190 RES_DISABLE_TRR
= nsIDNSService::RESOLVE_DISABLE_TRR
,
191 RES_REFRESH_CACHE
= nsIDNSService::RESOLVE_REFRESH_CACHE
,
192 RES_IP_HINT
= nsIDNSService::RESOLVE_IP_HINT
195 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
) const;
198 * Flush the DNS cache.
200 void FlushCache(bool aTrrToo
);
202 LookupStatus
CompleteLookup(nsHostRecord
*, nsresult
, mozilla::net::AddrInfo
*,
203 bool pb
, const nsACString
& aOriginsuffix
,
204 mozilla::net::TRRSkippedReason aReason
,
205 mozilla::net::TRR
* aTRRRequest
) override
;
206 LookupStatus
CompleteLookupByType(nsHostRecord
*, nsresult
,
207 mozilla::net::TypeRecordResultType
& aResult
,
208 uint32_t aTtl
, bool pb
) override
;
209 nsresult
GetHostRecord(const nsACString
& host
, const nsACString
& trrServer
,
210 uint16_t type
, nsIDNSService::DNSFlags flags
,
211 uint16_t af
, bool pb
, const nsCString
& originSuffix
,
212 nsHostRecord
** result
) override
;
213 nsresult
TrrLookup_unlocked(nsHostRecord
*,
214 mozilla::net::TRR
* pushedTRR
= nullptr) override
;
215 static nsIDNSService::ResolverMode
Mode();
217 virtual void MaybeRenewHostRecord(nsHostRecord
* aRec
) override
;
219 // Records true if the TRR service is enabled for the record's effective
220 // TRR mode. Also records the TRRSkipReason when the TRR service is not
221 // available/enabled.
222 bool TRRServiceEnabledForRecord(nsHostRecord
* aRec
) MOZ_REQUIRES(mLock
);
225 explicit nsHostResolver(uint32_t maxCacheEntries
,
226 uint32_t defaultCacheEntryLifetime
,
227 uint32_t defaultGracePeriod
);
228 virtual ~nsHostResolver();
230 bool DoRetryTRR(AddrHostRecord
* aAddrRec
,
231 const mozilla::MutexAutoLock
& aLock
);
232 bool MaybeRetryTRRLookup(
233 AddrHostRecord
* aAddrRec
, nsresult aFirstAttemptStatus
,
234 mozilla::net::TRRSkippedReason aFirstAttemptSkipReason
,
235 nsresult aChannelStatus
, const mozilla::MutexAutoLock
& aLock
);
237 LookupStatus
CompleteLookupLocked(nsHostRecord
*, nsresult
,
238 mozilla::net::AddrInfo
*, bool pb
,
239 const nsACString
& aOriginsuffix
,
240 mozilla::net::TRRSkippedReason aReason
,
241 mozilla::net::TRR
* aTRRRequest
,
242 const mozilla::MutexAutoLock
& aLock
)
244 LookupStatus
CompleteLookupByTypeLocked(
245 nsHostRecord
*, nsresult
, mozilla::net::TypeRecordResultType
& aResult
,
246 uint32_t aTtl
, bool pb
, const mozilla::MutexAutoLock
& aLock
)
249 static void ComputeEffectiveTRRMode(nsHostRecord
* aRec
);
250 nsresult
NativeLookup(nsHostRecord
* aRec
,
251 const mozilla::MutexAutoLock
& aLock
);
252 nsresult
TrrLookup(nsHostRecord
*, const mozilla::MutexAutoLock
& aLock
,
253 mozilla::net::TRR
* pushedTRR
= nullptr);
255 // Kick-off a name resolve operation, using native resolver and/or TRR
256 nsresult
NameLookup(nsHostRecord
* aRec
, const mozilla::MutexAutoLock
& aLock
);
257 bool GetHostToLookup(AddrHostRecord
** result
);
258 void MaybeRenewHostRecordLocked(nsHostRecord
* aRec
,
259 const mozilla::MutexAutoLock
& aLock
)
262 // Cancels host records in the pending queue and also
263 // calls CompleteLookup with the NS_ERROR_ABORT result code.
264 void ClearPendingQueue(mozilla::LinkedList
<RefPtr
<nsHostRecord
>>& aPendingQ
);
265 nsresult
ConditionallyCreateThread(nsHostRecord
* rec
) MOZ_REQUIRES(mLock
);
268 * Starts a new lookup in the background for entries that are in the grace
269 * period with a failed connect or all cached entries are negative.
271 nsresult
ConditionallyRefreshRecord(nsHostRecord
* rec
, const nsACString
& host
,
272 const mozilla::MutexAutoLock
& aLock
)
275 void AddToEvictionQ(nsHostRecord
* rec
, const mozilla::MutexAutoLock
& aLock
)
280 // Resolve the host from the DNS cache.
281 already_AddRefed
<nsHostRecord
> FromCache(nsHostRecord
* aRec
,
282 const nsACString
& aHost
,
283 uint16_t aType
, nsresult
& aStatus
,
284 const mozilla::MutexAutoLock
& aLock
)
286 // Called when the host name is an IP address and has been passed.
287 already_AddRefed
<nsHostRecord
> FromCachedIPLiteral(nsHostRecord
* aRec
);
288 // Like the above function, but the host name is not parsed to NetAddr yet.
289 already_AddRefed
<nsHostRecord
> FromIPLiteral(
290 AddrHostRecord
* aAddrRec
, const mozilla::net::NetAddr
& aAddr
);
291 // Called to check if we have an AF_UNSPEC entry in the cache.
292 already_AddRefed
<nsHostRecord
> FromUnspecEntry(
293 nsHostRecord
* aRec
, const nsACString
& aHost
, const nsACString
& aTrrServer
,
294 const nsACString
& aOriginSuffix
, uint16_t aType
,
295 nsIDNSService::DNSFlags aFlags
, uint16_t af
, bool aPb
, nsresult
& aStatus
)
301 METHOD_NEGATIVE_HIT
= 3,
304 METHOD_NETWORK_FIRST
= 6,
305 METHOD_NETWORK_SHARED
= 7
308 uint32_t mMaxCacheEntries
= 0;
309 uint32_t mDefaultCacheLifetime
= 0; // granularity seconds
310 uint32_t mDefaultGracePeriod
= 0; // granularity seconds
311 // mutable so SizeOfIncludingThis can be const
312 mutable Mutex mLock
{"nsHostResolver.mLock"};
314 nsRefPtrHashtable
<nsGenericHashKey
<nsHostKey
>, nsHostRecord
> mRecordDB
315 MOZ_GUARDED_BY(mLock
);
316 PRTime mCreationTime
;
317 mozilla::TimeDuration mLongIdleTimeout
;
318 mozilla::TimeDuration mShortIdleTimeout
;
320 RefPtr
<nsIThreadPool
> mResolverThreads
;
321 RefPtr
<mozilla::net::NetworkConnectivityService
>
322 mNCS
; // reference to a singleton
323 mozilla::net::HostRecordQueue mQueue
MOZ_GUARDED_BY(mLock
);
324 mozilla::Atomic
<bool> mShutdown
MOZ_GUARDED_BY(mLock
){true};
325 mozilla::Atomic
<uint32_t> mNumIdleTasks
MOZ_GUARDED_BY(mLock
){0};
326 mozilla::Atomic
<uint32_t> mActiveTaskCount
MOZ_GUARDED_BY(mLock
){0};
327 mozilla::Atomic
<uint32_t> mActiveAnyThreadCount
MOZ_GUARDED_BY(mLock
){0};
329 // Set the expiration time stamps appropriately.
330 void PrepareRecordExpirationAddrRecord(AddrHostRecord
* rec
) const;
334 * Called by the networking dashboard via the DnsService2
336 void GetDNSCacheEntries(nsTArray
<mozilla::net::DNSCacheEntries
>*);
339 #endif // nsHostResolver_h__