netwerk/dns/nsHostResolver.h

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

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

mercurial