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())*/
140 * ResolveHost callback object. It's PRCList members are used by
141 * the nsHostResolver and should not be used by anything else.
143 class NS_NO_VTABLE nsResolveHostCallback
: public PRCList
149 * this function is called to complete a host lookup initiated by
150 * nsHostResolver::ResolveHost. it may be invoked recursively from
151 * ResolveHost or on an unspecified background thread.
153 * NOTE: it is the responsibility of the implementor of this method
154 * to handle the callback in a thread safe manner.
157 * nsHostResolver object associated with this result
159 * the host record containing the results of the lookup
161 * if successful, |record| contains non-null results
163 virtual void OnLookupComplete(nsHostResolver
*resolver
,
164 nsHostRecord
*record
,
165 nsresult status
) = 0;
169 * nsHostResolverThreadInfo structures are passed to the resolver
172 struct nsHostResolverThreadInfo
174 nsHostResolver
*self
;
175 PRBool onlyHighPriority
;
179 * nsHostResolver - an asynchronous host name resolver.
185 * host resolver instances are reference counted.
187 NS_DECL_REFCOUNTED_THREADSAFE(nsHostResolver
)
190 * creates an addref'd instance of a nsHostResolver object.
192 static nsresult
Create(PRUint32 maxCacheEntries
, // zero disables cache
193 PRUint32 maxCacheLifetime
, // minutes
194 nsHostResolver
**resolver
);
197 * puts the resolver in the shutdown state, which will cause any pending
198 * callbacks to be detached. any future calls to ResolveHost will fail.
203 * resolve the given hostname asynchronously. the caller can synthesize
204 * a synchronous host lookup using a lock and a cvar. as noted above
205 * the callback will occur re-entrantly from an unspecified thread. the
206 * host lookup cannot be canceled (cancelation can be layered above this
207 * by having the callback implementation return without doing anything).
209 nsresult
ResolveHost(const char *hostname
,
212 nsResolveHostCallback
*callback
);
215 * removes the specified callback from the nsHostRecord for the given
216 * hostname, flags, and address family. these parameters should correspond
217 * to the parameters passed to ResolveHost. this function executes the
218 * callback if the callback is still pending with the given status.
220 void DetachCallback(const char *hostname
,
223 nsResolveHostCallback
*callback
,
227 * values for the flags parameter passed to ResolveHost and DetachCallback
228 * that may be bitwise OR'd together.
230 * NOTE: in this implementation, these flags correspond exactly in value
231 * to the flags defined on nsIDNSService.
234 RES_BYPASS_CACHE
= 1 << 0,
235 RES_CANON_NAME
= 1 << 1,
236 RES_PRIORITY_MEDIUM
= 1 << 2,
237 RES_PRIORITY_LOW
= 1 << 3
241 nsHostResolver(PRUint32 maxCacheEntries
=50, PRUint32 maxCacheLifetime
=1);
244 // nsHostResolverThreadInfo * is passed to the ThreadFunc
245 struct nsHostResolverThreadInfo mHighPriorityInfo
, mAnyPriorityInfo
;
248 nsresult
IssueLookup(nsHostRecord
*);
249 PRBool
GetHostToLookup(nsHostRecord
**m
, struct nsHostResolverThreadInfo
*aID
);
250 void OnLookupComplete(nsHostRecord
*, nsresult
, PRAddrInfo
*);
251 void DeQueue(PRCList
&aQ
, nsHostRecord
**aResult
);
252 void ClearPendingQueue(PRCList
*aPendingQueue
);
253 nsresult
ConditionallyCreateThread(nsHostRecord
*rec
);
255 static void MoveQueue(nsHostRecord
*aRec
, PRCList
&aDestQ
);
257 static void ThreadFunc(void *);
259 PRUint32 mMaxCacheEntries
;
260 PRUint32 mMaxCacheLifetime
;
262 PRCondVar
*mIdleThreadCV
; // non-null if idle thread
263 PRUint32 mNumIdleThreads
;
264 PRUint32 mThreadCount
;
265 PRUint32 mAnyPriorityThreadCount
;
271 PRUint32 mEvictionQSize
;
272 PRUint32 mPendingCount
;
273 PRTime mCreationTime
;
275 PRIntervalTime mLongIdleTimeout
;
276 PRIntervalTime mShortIdleTimeout
;
279 #endif // nsHostResolver_h__