1 /* vim:set ts=4 sw=4 sts=4 et cin: */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla.
17 * The Initial Developer of the Original Code is IBM Corporation.
18 * Portions created by IBM Corporation are Copyright (C) 2003
19 * IBM Corporation. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef nsHostResolver_h__
39 #define nsHostResolver_h__
47 #include "nsISupportsImpl.h"
51 class nsResolveHostCallback
;
53 /* XXX move this someplace more generic */
54 #define NS_DECL_REFCOUNTED_THREADSAFE(classname) \
59 PRInt32 n = PR_AtomicIncrement((PRInt32*)&_refc); \
60 NS_LOG_ADDREF(this, n, #classname, sizeof(classname)); \
64 PRInt32 n = PR_AtomicDecrement((PRInt32*)&_refc); \
65 NS_LOG_RELEASE(this, n, #classname); \
71 #define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY 3
72 #define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
73 #define MAX_RESOLVER_THREADS (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
74 MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
84 * nsHostRecord - ref counted object type stored in host resolver cache.
86 class nsHostRecord
: public PRCList
, public nsHostKey
89 NS_DECL_REFCOUNTED_THREADSAFE(nsHostRecord
)
91 /* instantiates a new host record */
92 static nsresult
Create(const nsHostKey
*key
, nsHostRecord
**record
);
94 /* a fully resolved host record has either a non-null |addr_info| or |addr|
95 * field. if |addr_info| is null, it implies that the |host| is an IP
96 * address literal. in which case, |addr| contains the parsed address.
97 * otherwise, if |addr_info| is non-null, then it contains one or many
98 * IP addresses corresponding to the given host name. if both |addr_info|
99 * and |addr| are null, then the given host has not yet been fully resolved.
100 * |af| is the address family of the record we are querying for.
103 /* the lock protects |addr_info| and |addr_info_gencnt| because they
104 * are mutable and accessed by the resolver worker thread and the
105 * nsDNSService2 class. |addr| doesn't change after it has been
106 * assigned a value. only the resolver worker thread modifies
107 * nsHostRecord (and only in nsHostResolver::OnLookupComplete);
108 * the other threads just read it. therefore the resolver worker
109 * thread doesn't need to lock when reading |addr_info|.
111 PRLock
*addr_info_lock
;
112 int addr_info_gencnt
; /* generation count of |addr_info| */
113 PRAddrInfo
*addr_info
;
115 PRBool negative
; /* True if this record is a cache of a failed lookup.
116 Negative cache entries are valid just like any other
117 (though never for more than 60 seconds), but a use
118 of that negative entry forces an asynchronous refresh. */
120 PRUint32 expiration
; /* measured in minutes since epoch */
122 PRBool
HasResult() const { return addr_info
|| addr
|| negative
; }
125 friend class nsHostResolver
;
127 PRCList callbacks
; /* list of callbacks */
129 PRBool resolving
; /* true if this record is being resolved, which means
130 * that it is either on the pending queue or owned by
131 * one of the worker threads. */
133 PRBool onQueue
; /* true if pending and on the queue (not yet given to getaddrinfo())*/
134 PRBool usingAnyThread
; /* true if off queue and contributing to mActiveAnyThreadCount */
141 * ResolveHost callback object. It's PRCList members are used by
142 * the nsHostResolver and should not be used by anything else.
144 class NS_NO_VTABLE nsResolveHostCallback
: public PRCList
150 * this function is called to complete a host lookup initiated by
151 * nsHostResolver::ResolveHost. it may be invoked recursively from
152 * ResolveHost or on an unspecified background thread.
154 * NOTE: it is the responsibility of the implementor of this method
155 * to handle the callback in a thread safe manner.
158 * nsHostResolver object associated with this result
160 * the host record containing the results of the lookup
162 * if successful, |record| contains non-null results
164 virtual void OnLookupComplete(nsHostResolver
*resolver
,
165 nsHostRecord
*record
,
166 nsresult status
) = 0;
170 * nsHostResolver - an asynchronous host name resolver.
176 * host resolver instances are reference counted.
178 NS_DECL_REFCOUNTED_THREADSAFE(nsHostResolver
)
181 * creates an addref'd instance of a nsHostResolver object.
183 static nsresult
Create(PRUint32 maxCacheEntries
, // zero disables cache
184 PRUint32 maxCacheLifetime
, // minutes
185 nsHostResolver
**resolver
);
188 * puts the resolver in the shutdown state, which will cause any pending
189 * callbacks to be detached. any future calls to ResolveHost will fail.
194 * resolve the given hostname asynchronously. the caller can synthesize
195 * a synchronous host lookup using a lock and a cvar. as noted above
196 * the callback will occur re-entrantly from an unspecified thread. the
197 * host lookup cannot be canceled (cancelation can be layered above this
198 * by having the callback implementation return without doing anything).
200 nsresult
ResolveHost(const char *hostname
,
203 nsResolveHostCallback
*callback
);
206 * removes the specified callback from the nsHostRecord for the given
207 * hostname, flags, and address family. these parameters should correspond
208 * to the parameters passed to ResolveHost. this function executes the
209 * callback if the callback is still pending with the given status.
211 void DetachCallback(const char *hostname
,
214 nsResolveHostCallback
*callback
,
218 * values for the flags parameter passed to ResolveHost and DetachCallback
219 * that may be bitwise OR'd together.
221 * NOTE: in this implementation, these flags correspond exactly in value
222 * to the flags defined on nsIDNSService.
225 RES_BYPASS_CACHE
= 1 << 0,
226 RES_CANON_NAME
= 1 << 1,
227 RES_PRIORITY_MEDIUM
= 1 << 2,
228 RES_PRIORITY_LOW
= 1 << 3,
229 RES_SPECULATE
= 1 << 4
233 nsHostResolver(PRUint32 maxCacheEntries
=50, PRUint32 maxCacheLifetime
=1);
237 nsresult
IssueLookup(nsHostRecord
*);
238 PRBool
GetHostToLookup(nsHostRecord
**m
);
239 void OnLookupComplete(nsHostRecord
*, nsresult
, PRAddrInfo
*);
240 void DeQueue(PRCList
&aQ
, nsHostRecord
**aResult
);
241 void ClearPendingQueue(PRCList
*aPendingQueue
);
242 nsresult
ConditionallyCreateThread(nsHostRecord
*rec
);
244 static void MoveQueue(nsHostRecord
*aRec
, PRCList
&aDestQ
);
246 static void ThreadFunc(void *);
248 PRUint32 mMaxCacheEntries
;
249 PRUint32 mMaxCacheLifetime
;
251 PRCondVar
*mIdleThreadCV
; // non-null if idle thread
252 PRUint32 mNumIdleThreads
;
253 PRUint32 mThreadCount
;
254 PRUint32 mActiveAnyThreadCount
;
260 PRUint32 mEvictionQSize
;
261 PRUint32 mPendingCount
;
262 PRTime mCreationTime
;
264 PRIntervalTime mLongIdleTimeout
;
265 PRIntervalTime mShortIdleTimeout
;
268 #endif // nsHostResolver_h__