nsHostResolver.h (12787B)
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/. */ 5 6 #ifndef nsHostResolver_h__ 7 #define nsHostResolver_h__ 8 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 "nsHostRecord.h" 24 #include "nsRefPtrHashtable.h" 25 #include "nsIThreadPool.h" 26 #include "mozilla/net/NetworkConnectivityService.h" 27 #include "mozilla/net/DNSByTypeRecord.h" 28 #include "mozilla/StaticPrefs_network.h" 29 30 namespace mozilla { 31 namespace net { 32 class TRR; 33 class TRRQuery; 34 35 static inline uint32_t MaxResolverThreadsAnyPriority() { 36 return StaticPrefs::network_dns_max_any_priority_threads(); 37 } 38 39 static inline uint32_t MaxResolverThreadsHighPriority() { 40 return StaticPrefs::network_dns_max_high_priority_threads(); 41 } 42 43 static inline uint32_t MaxResolverThreads() { 44 return MaxResolverThreadsAnyPriority() + MaxResolverThreadsHighPriority(); 45 } 46 47 } // namespace net 48 } // namespace mozilla 49 50 #define TRR_DISABLED(x) \ 51 (((x) == nsIDNSService::MODE_NATIVEONLY) || \ 52 ((x) == nsIDNSService::MODE_TRROFF)) 53 54 #define MAX_NON_PRIORITY_REQUESTS 150 55 56 class AHostResolver { 57 public: 58 AHostResolver() = default; 59 virtual ~AHostResolver() = default; 60 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 61 62 enum LookupStatus { 63 LOOKUP_OK, 64 LOOKUP_RESOLVEAGAIN, 65 }; 66 67 virtual LookupStatus CompleteLookup(nsHostRecord*, nsresult, 68 mozilla::net::AddrInfo*, bool pb, 69 const nsACString& aOriginsuffix, 70 mozilla::net::TRRSkippedReason aReason, 71 mozilla::net::TRR*) = 0; 72 virtual LookupStatus CompleteLookupByType( 73 nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult, 74 mozilla::net::TRRSkippedReason aReason, uint32_t aTtl, bool pb) = 0; 75 virtual nsresult GetHostRecord(const nsACString& host, 76 const nsACString& aTrrServer, uint16_t type, 77 nsIDNSService::DNSFlags flags, uint16_t af, 78 bool pb, const nsCString& originSuffix, 79 nsHostRecord** result) { 80 return NS_ERROR_FAILURE; 81 } 82 virtual nsresult TrrLookup_unlocked(nsHostRecord*, 83 mozilla::net::TRR* pushedTRR = nullptr) { 84 return NS_ERROR_FAILURE; 85 } 86 virtual void MaybeRenewHostRecord(nsHostRecord* aRec) {} 87 }; 88 89 /** 90 * nsHostResolver - an asynchronous host name resolver. 91 */ 92 class nsHostResolver : public nsISupports, public AHostResolver { 93 using CondVar = mozilla::CondVar; 94 using Mutex = mozilla::Mutex; 95 96 public: 97 NS_DECL_THREADSAFE_ISUPPORTS 98 99 /** 100 * creates an addref'd instance of a nsHostResolver object. 101 */ 102 static nsresult Create(nsHostResolver** result); 103 /** 104 * puts the resolver in the shutdown state, which will cause any pending 105 * callbacks to be detached. any future calls to ResolveHost will fail. 106 */ 107 void Shutdown(); 108 109 /** 110 * resolve the given hostname and originAttributes asynchronously. the caller 111 * can synthesize a synchronous host lookup using a lock and a cvar. as noted 112 * above the callback will occur re-entrantly from an unspecified thread. the 113 * host lookup cannot be canceled (cancelation can be layered above this by 114 * having the callback implementation return without doing anything). 115 */ 116 nsresult ResolveHost(const nsACString& aHost, const nsACString& trrServer, 117 int32_t aPort, uint16_t type, 118 const mozilla::OriginAttributes& aOriginAttributes, 119 nsIDNSService::DNSFlags flags, uint16_t af, 120 nsResolveHostCallback* callback); 121 122 nsHostRecord* InitRecord(const nsHostKey& key); 123 mozilla::net::NetworkConnectivityService* GetNCS() { 124 return mNCS; 125 } // This is actually a singleton 126 127 /** 128 * return a resolved hard coded loopback dns record for the specified key 129 */ 130 already_AddRefed<nsHostRecord> InitLoopbackRecord(const nsHostKey& key, 131 nsresult* aRv); 132 133 /** 134 * return a mock HTTPS record 135 */ 136 already_AddRefed<nsHostRecord> InitMockHTTPSRecord(const nsHostKey& key); 137 138 /** 139 * removes the specified callback from the nsHostRecord for the given 140 * hostname, originAttributes, flags, and address family. these parameters 141 * should correspond to the parameters passed to ResolveHost. this function 142 * executes the callback if the callback is still pending with the given 143 * status. 144 */ 145 void DetachCallback(const nsACString& hostname, const nsACString& trrServer, 146 uint16_t type, 147 const mozilla::OriginAttributes& aOriginAttributes, 148 nsIDNSService::DNSFlags flags, uint16_t af, 149 nsResolveHostCallback* callback, nsresult status); 150 151 /** 152 * Cancels an async request associated with the hostname, originAttributes, 153 * flags, address family and listener. Cancels first callback found which 154 * matches these criteria. These parameters should correspond to the 155 * parameters passed to ResolveHost. If this is the last callback associated 156 * with the host record, it is removed from any request queues it might be on. 157 */ 158 void CancelAsyncRequest(const nsACString& host, const nsACString& trrServer, 159 uint16_t type, 160 const mozilla::OriginAttributes& aOriginAttributes, 161 nsIDNSService::DNSFlags flags, uint16_t af, 162 nsIDNSListener* aListener, nsresult status); 163 164 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 165 166 /** 167 * Flush the DNS cache. 168 */ 169 void FlushCache(bool aTrrToo, bool aFlushEvictionQueue = false); 170 171 LookupStatus CompleteLookup(nsHostRecord*, nsresult, mozilla::net::AddrInfo*, 172 bool pb, const nsACString& aOriginsuffix, 173 mozilla::net::TRRSkippedReason aReason, 174 mozilla::net::TRR* aTRRRequest) override; 175 LookupStatus CompleteLookupByType(nsHostRecord*, nsresult, 176 mozilla::net::TypeRecordResultType& aResult, 177 mozilla::net::TRRSkippedReason aReason, 178 uint32_t aTtl, bool pb) override; 179 nsresult GetHostRecord(const nsACString& host, const nsACString& trrServer, 180 uint16_t type, nsIDNSService::DNSFlags flags, 181 uint16_t af, bool pb, const nsCString& originSuffix, 182 nsHostRecord** result) override; 183 nsresult TrrLookup_unlocked(nsHostRecord*, 184 mozilla::net::TRR* pushedTRR = nullptr) override; 185 static nsIDNSService::ResolverMode Mode(); 186 187 virtual void MaybeRenewHostRecord(nsHostRecord* aRec) override; 188 189 // Records true if the TRR service is enabled for the record's effective 190 // TRR mode. Also records the TRRSkipReason when the TRR service is not 191 // available/enabled. 192 bool TRRServiceEnabledForRecord(nsHostRecord* aRec) MOZ_REQUIRES(mLock); 193 194 private: 195 explicit nsHostResolver(); 196 virtual ~nsHostResolver(); 197 198 bool DoRetryTRR(AddrHostRecord* aAddrRec, 199 const mozilla::MutexAutoLock& aLock); 200 bool MaybeRetryTRRLookup( 201 AddrHostRecord* aAddrRec, nsresult aFirstAttemptStatus, 202 mozilla::net::TRRSkippedReason aFirstAttemptSkipReason, 203 nsresult aChannelStatus, const mozilla::MutexAutoLock& aLock); 204 205 LookupStatus CompleteLookupLocked(nsHostRecord*, nsresult, 206 mozilla::net::AddrInfo*, bool pb, 207 const nsACString& aOriginsuffix, 208 mozilla::net::TRRSkippedReason aReason, 209 mozilla::net::TRR* aTRRRequest, 210 const mozilla::MutexAutoLock& aLock) 211 MOZ_REQUIRES(mLock); 212 LookupStatus CompleteLookupByTypeLocked( 213 nsHostRecord*, nsresult, mozilla::net::TypeRecordResultType& aResult, 214 mozilla::net::TRRSkippedReason aReason, uint32_t aTtl, bool pb, 215 const mozilla::MutexAutoLock& aLock) MOZ_REQUIRES(mLock); 216 nsresult Init(); 217 static void ComputeEffectiveTRRMode(nsHostRecord* aRec); 218 nsresult NativeLookup(nsHostRecord* aRec, 219 const mozilla::MutexAutoLock& aLock); 220 nsresult TrrLookup(nsHostRecord*, const mozilla::MutexAutoLock& aLock, 221 mozilla::net::TRR* pushedTRR = nullptr); 222 223 // Kick-off a name resolve operation, using native resolver and/or TRR 224 nsresult NameLookup(nsHostRecord* aRec, const mozilla::MutexAutoLock& aLock); 225 bool GetHostToLookup(nsHostRecord** result); 226 void MaybeRenewHostRecordLocked(nsHostRecord* aRec, 227 const mozilla::MutexAutoLock& aLock) 228 MOZ_REQUIRES(mLock); 229 230 // Cancels host records in the pending queue and also 231 // calls CompleteLookup with the NS_ERROR_ABORT result code. 232 void ClearPendingQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aPendingQ); 233 nsresult ConditionallyCreateThread(nsHostRecord* rec) MOZ_REQUIRES(mLock); 234 235 /** 236 * Starts a new lookup in the background for cached entries that are in the 237 * grace period or that are are negative. 238 * 239 * Also records telemetry for type of cache hit (HIT/NEGATIVE_HIT/RENEWAL). 240 */ 241 nsresult ConditionallyRefreshRecord(nsHostRecord* rec, const nsACString& host, 242 const mozilla::MutexAutoLock& aLock) 243 MOZ_REQUIRES(mLock); 244 245 void OnResolveComplete(nsHostRecord* aRec, 246 const mozilla::MutexAutoLock& aLock) 247 MOZ_REQUIRES(mLock); 248 249 void AddToEvictionQ(nsHostRecord* rec, const mozilla::MutexAutoLock& aLock) 250 MOZ_REQUIRES(mLock); 251 252 void ThreadFunc(); 253 254 // Resolve the host from the DNS cache. 255 already_AddRefed<nsHostRecord> FromCache(nsHostRecord* aRec, 256 const nsACString& aHost, 257 uint16_t aType, nsresult& aStatus, 258 const mozilla::MutexAutoLock& aLock) 259 MOZ_REQUIRES(mLock); 260 // Called when the host name is an IP address and has been passed. 261 already_AddRefed<nsHostRecord> FromCachedIPLiteral(nsHostRecord* aRec); 262 // Like the above function, but the host name is not parsed to NetAddr yet. 263 already_AddRefed<nsHostRecord> FromIPLiteral( 264 AddrHostRecord* aAddrRec, const mozilla::net::NetAddr& aAddr); 265 // Called to check if we have an AF_UNSPEC entry in the cache. 266 already_AddRefed<nsHostRecord> FromUnspecEntry( 267 nsHostRecord* aRec, const nsACString& aHost, const nsACString& aTrrServer, 268 const nsACString& aOriginSuffix, uint16_t aType, 269 nsIDNSService::DNSFlags aFlags, uint16_t af, bool aPb, nsresult& aStatus, 270 const mozilla::MutexAutoLock& aLock) MOZ_REQUIRES(mLock); 271 272 enum { 273 METHOD_HIT = 1, 274 METHOD_RENEWAL = 2, 275 METHOD_NEGATIVE_HIT = 3, 276 METHOD_LITERAL = 4, 277 METHOD_OVERFLOW = 5, 278 METHOD_NETWORK_FIRST = 6, 279 METHOD_NETWORK_SHARED = 7 280 }; 281 282 // mutable so SizeOfIncludingThis can be const 283 mutable Mutex mLock{"nsHostResolver.mLock"}; 284 CondVar mIdleTaskCV; 285 nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB 286 MOZ_GUARDED_BY(mLock); 287 PRTime mCreationTime; 288 mozilla::TimeDuration mLongIdleTimeout; 289 mozilla::TimeDuration mShortIdleTimeout; 290 291 RefPtr<nsIThreadPool> mResolverThreads; 292 RefPtr<mozilla::net::NetworkConnectivityService> 293 mNCS; // reference to a singleton 294 mozilla::net::HostRecordQueue mQueue MOZ_GUARDED_BY(mLock); 295 mozilla::Atomic<bool> mShutdown MOZ_GUARDED_BY(mLock){true}; 296 mozilla::Atomic<uint32_t> mNumIdleTasks MOZ_GUARDED_BY(mLock){0}; 297 mozilla::Atomic<uint32_t> mActiveTaskCount MOZ_GUARDED_BY(mLock){0}; 298 mozilla::Atomic<uint32_t> mActiveAnyThreadCount MOZ_GUARDED_BY(mLock){0}; 299 300 // Set the expiration time stamps appropriately. 301 void PrepareRecordExpirationAddrRecord(AddrHostRecord* rec) const; 302 303 public: 304 /* 305 * Called by the networking dashboard via the DnsService2 306 */ 307 void GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries>*); 308 309 static bool IsNativeHTTPSEnabled(); 310 }; 311 312 #endif // nsHostResolver_h__