nsHostResolver.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /* vim:set ts=4 sw=4 sts=4 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. #ifndef nsHostResolver_h__
  6. #define nsHostResolver_h__
  7. #include "nscore.h"
  8. #include "prclist.h"
  9. #include "prnetdb.h"
  10. #include "PLDHashTable.h"
  11. #include "mozilla/CondVar.h"
  12. #include "mozilla/Mutex.h"
  13. #include "nsISupportsImpl.h"
  14. #include "nsIDNSListener.h"
  15. #include "nsIDNSService.h"
  16. #include "nsString.h"
  17. #include "nsTArray.h"
  18. #include "GetAddrInfo.h"
  19. #include "mozilla/net/DNS.h"
  20. #include "mozilla/net/DashboardTypes.h"
  21. #include "mozilla/TimeStamp.h"
  22. class nsHostResolver;
  23. class nsHostRecord;
  24. class nsResolveHostCallback;
  25. #define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY 3
  26. #define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
  27. #define MAX_NON_PRIORITY_REQUESTS 150
  28. #define MAX_RESOLVER_THREADS (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
  29. MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
  30. struct nsHostKey
  31. {
  32. const char *host;
  33. uint16_t flags;
  34. uint16_t af;
  35. const char *netInterface;
  36. };
  37. /**
  38. * nsHostRecord - ref counted object type stored in host resolver cache.
  39. */
  40. class nsHostRecord : public PRCList, public nsHostKey
  41. {
  42. typedef mozilla::Mutex Mutex;
  43. public:
  44. NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHostRecord)
  45. /* instantiates a new host record */
  46. static nsresult Create(const nsHostKey *key, nsHostRecord **record);
  47. /* a fully resolved host record has either a non-null |addr_info| or |addr|
  48. * field. if |addr_info| is null, it implies that the |host| is an IP
  49. * address literal. in which case, |addr| contains the parsed address.
  50. * otherwise, if |addr_info| is non-null, then it contains one or many
  51. * IP addresses corresponding to the given host name. if both |addr_info|
  52. * and |addr| are null, then the given host has not yet been fully resolved.
  53. * |af| is the address family of the record we are querying for.
  54. */
  55. /* the lock protects |addr_info| and |addr_info_gencnt| because they
  56. * are mutable and accessed by the resolver worker thread and the
  57. * nsDNSService2 class. |addr| doesn't change after it has been
  58. * assigned a value. only the resolver worker thread modifies
  59. * nsHostRecord (and only in nsHostResolver::OnLookupComplete);
  60. * the other threads just read it. therefore the resolver worker
  61. * thread doesn't need to lock when reading |addr_info|.
  62. */
  63. Mutex addr_info_lock;
  64. int addr_info_gencnt; /* generation count of |addr_info| */
  65. mozilla::net::AddrInfo *addr_info;
  66. mozilla::net::NetAddr *addr;
  67. bool negative; /* True if this record is a cache of a failed lookup.
  68. Negative cache entries are valid just like any other
  69. (though never for more than 60 seconds), but a use
  70. of that negative entry forces an asynchronous refresh. */
  71. enum ExpirationStatus {
  72. EXP_VALID,
  73. EXP_GRACE,
  74. EXP_EXPIRED,
  75. };
  76. ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const;
  77. // When the record began being valid. Used mainly for bookkeeping.
  78. mozilla::TimeStamp mValidStart;
  79. // When the record is no longer valid (it's time of expiration)
  80. mozilla::TimeStamp mValidEnd;
  81. // When the record enters its grace period. This must be before mValidEnd.
  82. // If a record is in its grace period (and not expired), it will be used
  83. // but a request to refresh it will be made.
  84. mozilla::TimeStamp mGraceStart;
  85. // Convenience function for setting the timestamps above (mValidStart,
  86. // mValidEnd, and mGraceStart). valid and grace are durations in seconds.
  87. void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid,
  88. unsigned int grace);
  89. void CopyExpirationTimesAndFlagsFrom(const nsHostRecord *aFromHostRecord);
  90. // Checks if the record is usable (not expired and has a value)
  91. bool HasUsableResult(const mozilla::TimeStamp& now, uint16_t queryFlags = 0) const;
  92. // hold addr_info_lock when calling the blacklist functions
  93. bool Blacklisted(mozilla::net::NetAddr *query);
  94. void ResetBlacklist();
  95. void ReportUnusable(mozilla::net::NetAddr *addr);
  96. size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
  97. enum DnsPriority {
  98. DNS_PRIORITY_LOW,
  99. DNS_PRIORITY_MEDIUM,
  100. DNS_PRIORITY_HIGH,
  101. };
  102. static DnsPriority GetPriority(uint16_t aFlags);
  103. bool RemoveOrRefresh(); // Mark records currently being resolved as needed
  104. // to resolve again.
  105. private:
  106. friend class nsHostResolver;
  107. PRCList callbacks; /* list of callbacks */
  108. bool resolving; /* true if this record is being resolved, which means
  109. * that it is either on the pending queue or owned by
  110. * one of the worker threads. */
  111. bool onQueue; /* true if pending and on the queue (not yet given to getaddrinfo())*/
  112. bool usingAnyThread; /* true if off queue and contributing to mActiveAnyThreadCount */
  113. bool mDoomed; /* explicitly expired */
  114. #if TTL_AVAILABLE
  115. bool mGetTtl;
  116. #endif
  117. // The number of times ReportUnusable() has been called in the record's
  118. // lifetime.
  119. uint32_t mBlacklistedCount;
  120. // when the results from this resolve is returned, it is not to be
  121. // trusted, but instead a new resolve must be made!
  122. bool mResolveAgain;
  123. // a list of addresses associated with this record that have been reported
  124. // as unusable. the list is kept as a set of strings to make it independent
  125. // of gencnt.
  126. nsTArray<nsCString> mBlacklistedItems;
  127. explicit nsHostRecord(const nsHostKey *key); /* use Create() instead */
  128. ~nsHostRecord();
  129. };
  130. /**
  131. * ResolveHost callback object. It's PRCList members are used by
  132. * the nsHostResolver and should not be used by anything else.
  133. */
  134. class NS_NO_VTABLE nsResolveHostCallback : public PRCList
  135. {
  136. public:
  137. /**
  138. * OnLookupComplete
  139. *
  140. * this function is called to complete a host lookup initiated by
  141. * nsHostResolver::ResolveHost. it may be invoked recursively from
  142. * ResolveHost or on an unspecified background thread.
  143. *
  144. * NOTE: it is the responsibility of the implementor of this method
  145. * to handle the callback in a thread safe manner.
  146. *
  147. * @param resolver
  148. * nsHostResolver object associated with this result
  149. * @param record
  150. * the host record containing the results of the lookup
  151. * @param status
  152. * if successful, |record| contains non-null results
  153. */
  154. virtual void OnLookupComplete(nsHostResolver *resolver,
  155. nsHostRecord *record,
  156. nsresult status) = 0;
  157. /**
  158. * EqualsAsyncListener
  159. *
  160. * Determines if the listener argument matches the listener member var.
  161. * For subclasses not implementing a member listener, should return false.
  162. * For subclasses having a member listener, the function should check if
  163. * they are the same. Used for cases where a pointer to an object
  164. * implementing nsResolveHostCallback is unknown, but a pointer to
  165. * the original listener is known.
  166. *
  167. * @param aListener
  168. * nsIDNSListener object associated with the original request
  169. */
  170. virtual bool EqualsAsyncListener(nsIDNSListener *aListener) = 0;
  171. virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0;
  172. };
  173. /**
  174. * nsHostResolver - an asynchronous host name resolver.
  175. */
  176. class nsHostResolver
  177. {
  178. typedef mozilla::CondVar CondVar;
  179. typedef mozilla::Mutex Mutex;
  180. public:
  181. /**
  182. * host resolver instances are reference counted.
  183. */
  184. NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHostResolver)
  185. /**
  186. * creates an addref'd instance of a nsHostResolver object.
  187. */
  188. static nsresult Create(uint32_t maxCacheEntries, // zero disables cache
  189. uint32_t defaultCacheEntryLifetime, // seconds
  190. uint32_t defaultGracePeriod, // seconds
  191. nsHostResolver **resolver);
  192. /**
  193. * puts the resolver in the shutdown state, which will cause any pending
  194. * callbacks to be detached. any future calls to ResolveHost will fail.
  195. */
  196. void Shutdown();
  197. /**
  198. * resolve the given hostname asynchronously. the caller can synthesize
  199. * a synchronous host lookup using a lock and a cvar. as noted above
  200. * the callback will occur re-entrantly from an unspecified thread. the
  201. * host lookup cannot be canceled (cancelation can be layered above this
  202. * by having the callback implementation return without doing anything).
  203. */
  204. nsresult ResolveHost(const char *hostname,
  205. uint16_t flags,
  206. uint16_t af,
  207. const char *netInterface,
  208. nsResolveHostCallback *callback);
  209. /**
  210. * removes the specified callback from the nsHostRecord for the given
  211. * hostname, flags, and address family. these parameters should correspond
  212. * to the parameters passed to ResolveHost. this function executes the
  213. * callback if the callback is still pending with the given status.
  214. */
  215. void DetachCallback(const char *hostname,
  216. uint16_t flags,
  217. uint16_t af,
  218. const char *netInterface,
  219. nsResolveHostCallback *callback,
  220. nsresult status);
  221. /**
  222. * Cancels an async request associated with the hostname, flags,
  223. * address family and listener. Cancels first callback found which matches
  224. * these criteria. These parameters should correspond to the parameters
  225. * passed to ResolveHost. If this is the last callback associated with the
  226. * host record, it is removed from any request queues it might be on.
  227. */
  228. void CancelAsyncRequest(const char *host,
  229. uint16_t flags,
  230. uint16_t af,
  231. const char *netInterface,
  232. nsIDNSListener *aListener,
  233. nsresult status);
  234. /**
  235. * values for the flags parameter passed to ResolveHost and DetachCallback
  236. * that may be bitwise OR'd together.
  237. *
  238. * NOTE: in this implementation, these flags correspond exactly in value
  239. * to the flags defined on nsIDNSService.
  240. */
  241. enum {
  242. RES_BYPASS_CACHE = nsIDNSService::RESOLVE_BYPASS_CACHE,
  243. RES_CANON_NAME = nsIDNSService::RESOLVE_CANONICAL_NAME,
  244. RES_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM,
  245. RES_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW,
  246. RES_SPECULATE = nsIDNSService::RESOLVE_SPECULATE,
  247. //RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used
  248. RES_OFFLINE = nsIDNSService::RESOLVE_OFFLINE,
  249. //RES_DISABLE_IPv4 = nsIDNSService::RESOLVE_DISABLE_IPV4, // Not Used
  250. RES_ALLOW_NAME_COLLISION = nsIDNSService::RESOLVE_ALLOW_NAME_COLLISION
  251. };
  252. size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
  253. /**
  254. * Flush the DNS cache.
  255. */
  256. void FlushCache();
  257. private:
  258. explicit nsHostResolver(uint32_t maxCacheEntries,
  259. uint32_t defaultCacheEntryLifetime,
  260. uint32_t defaultGracePeriod);
  261. ~nsHostResolver();
  262. nsresult Init();
  263. nsresult IssueLookup(nsHostRecord *);
  264. bool GetHostToLookup(nsHostRecord **m);
  265. enum LookupStatus {
  266. LOOKUP_OK,
  267. LOOKUP_RESOLVEAGAIN,
  268. };
  269. LookupStatus OnLookupComplete(nsHostRecord *, nsresult, mozilla::net::AddrInfo *);
  270. void DeQueue(PRCList &aQ, nsHostRecord **aResult);
  271. void ClearPendingQueue(PRCList *aPendingQueue);
  272. nsresult ConditionallyCreateThread(nsHostRecord *rec);
  273. /**
  274. * Starts a new lookup in the background for entries that are in the grace
  275. * period with a failed connect or all cached entries are negative.
  276. */
  277. nsresult ConditionallyRefreshRecord(nsHostRecord *rec, const char *host);
  278. static void MoveQueue(nsHostRecord *aRec, PRCList &aDestQ);
  279. static void ThreadFunc(void *);
  280. enum {
  281. METHOD_HIT = 1,
  282. METHOD_RENEWAL = 2,
  283. METHOD_NEGATIVE_HIT = 3,
  284. METHOD_LITERAL = 4,
  285. METHOD_OVERFLOW = 5,
  286. METHOD_NETWORK_FIRST = 6,
  287. METHOD_NETWORK_SHARED = 7
  288. };
  289. uint32_t mMaxCacheEntries;
  290. uint32_t mDefaultCacheLifetime; // granularity seconds
  291. uint32_t mDefaultGracePeriod; // granularity seconds
  292. mutable Mutex mLock; // mutable so SizeOfIncludingThis can be const
  293. CondVar mIdleThreadCV;
  294. PLDHashTable mDB;
  295. PRCList mHighQ;
  296. PRCList mMediumQ;
  297. PRCList mLowQ;
  298. PRCList mEvictionQ;
  299. uint32_t mEvictionQSize;
  300. PRTime mCreationTime;
  301. PRIntervalTime mLongIdleTimeout;
  302. PRIntervalTime mShortIdleTimeout;
  303. mozilla::Atomic<bool> mShutdown;
  304. mozilla::Atomic<uint32_t> mNumIdleThreads;
  305. mozilla::Atomic<uint32_t> mThreadCount;
  306. mozilla::Atomic<uint32_t> mActiveAnyThreadCount;
  307. mozilla::Atomic<uint32_t> mPendingCount;
  308. // Set the expiration time stamps appropriately.
  309. void PrepareRecordExpiration(nsHostRecord* rec) const;
  310. public:
  311. /*
  312. * Called by the networking dashboard via the DnsService2
  313. */
  314. void GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries> *);
  315. };
  316. #endif // nsHostResolver_h__