aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llares.h
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llcommon/llares.h')
-rw-r--r--linden/indra/llcommon/llares.h572
1 files changed, 572 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llares.h b/linden/indra/llcommon/llares.h
new file mode 100644
index 0000000..63bb3e3
--- /dev/null
+++ b/linden/indra/llcommon/llares.h
@@ -0,0 +1,572 @@
1/**
2 * @file llares.h
3 * @author Bryan O'Sullivan
4 * @date 2007-08-15
5 * @brief Wrapper for asynchronous DNS lookups.
6 *
7 * $LicenseInfo:firstyear=2007&license=viewergpl$
8 *
9 * Copyright (c) 2007, Linden Research, Inc.
10 *
11 * Second Life Viewer Source Code
12 * The source code in this file ("Source Code") is provided by Linden Lab
13 * to you under the terms of the GNU General Public License, version 2.0
14 * ("GPL"), unless you have obtained a separate licensing agreement
15 * ("Other License"), formally executed by you and Linden Lab. Terms of
16 * the GPL can be found in doc/GPL-license.txt in this distribution, or
17 * online at http://secondlife.com/developers/opensource/gplv2
18 *
19 * There are special exceptions to the terms and conditions of the GPL as
20 * it is applied to this Source Code. View the full text of the exception
21 * in the file doc/FLOSS-exception.txt in this software distribution, or
22 * online at http://secondlife.com/developers/opensource/flossexception
23 *
24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above,
26 * and agree to abide by those obligations.
27 *
28 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$
32 */
33
34#ifndef LL_LLARES_H
35#define LL_LLARES_H
36
37#ifdef LL_WINDOWS
38# include <ws2tcpip.h>
39#endif
40
41#ifdef LL_STANDALONE
42# include <ares.h>
43#else
44# include <ares/ares.h>
45#endif
46
47#include "llmemory.h"
48#include "lluri.h"
49
50class LLQueryResponder;
51
52/**
53 * @brief Supported DNS RR types.
54 */
55enum LLResType
56{
57 RES_INVALID = 0, /**< Cookie. */
58 RES_A = 1, /**< "A" record. IPv4 address. */
59 RES_NS = 2, /**< "NS" record. Authoritative server. */
60 RES_CNAME = 5, /**< "CNAME" record. Canonical name. */
61 RES_PTR = 12, /**< "PTR" record. Domain name pointer. */
62 RES_AAAA = 28, /**< "AAAA" record. IPv6 Address. */
63 RES_SRV = 33, /**< "SRV" record. Server Selection. */
64 RES_MAX = 65536 /**< Sentinel; RR types are 16 bits wide. */
65};
66
67/**
68 * @class LLDnsRecord
69 * @brief Base class for all DNS RR types.
70 */
71class LLDnsRecord : public LLRefCount
72{
73protected:
74 friend class LLQueryResponder;
75
76 LLResType mType;
77 std::string mName;
78 unsigned mTTL;
79
80 virtual int parse(const char *buf, size_t len, const char *pos,
81 size_t rrlen) = 0;
82
83 LLDnsRecord(LLResType type, const std::string &name, unsigned ttl);
84
85public:
86 /**
87 * @brief Record name.
88 */
89 const std::string &name() const { return mName; }
90
91 /**
92 * @brief Time-to-live value, in seconds.
93 */
94 unsigned ttl() const { return mTTL; }
95
96 /**
97 * @brief RR type.
98 */
99 LLResType type() const { return mType; }
100};
101
102/**
103 * @class LLAddrRecord
104 * @brief Base class for address-related RRs.
105 */
106class LLAddrRecord : public LLDnsRecord
107{
108protected:
109 friend class LLQueryResponder;
110
111 LLAddrRecord(LLResType type, const std::string &name, unsigned ttl);
112
113 union
114 {
115 sockaddr sa;
116 sockaddr_in sin;
117 sockaddr_in6 sin6;
118 } mSA;
119
120 socklen_t mSize;
121
122public:
123 /**
124 * @brief Generic socket address.
125 */
126 const sockaddr &addr() const { return mSA.sa; }
127
128 /**
129 * @brief Size of the socket structure.
130 */
131 socklen_t size() const { return mSize; }
132};
133
134/**
135 * @class LLARecord
136 * @brief A RR, for IPv4 addresses.
137 */
138class LLARecord : public LLAddrRecord
139{
140protected:
141 friend class LLQueryResponder;
142
143 LLARecord(const std::string &name, unsigned ttl);
144
145 int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
146
147public:
148 /**
149 * @brief Socket address.
150 */
151 const sockaddr_in &addr_in() const { return mSA.sin; }
152};
153
154/**
155 * @class LLAaaaRecord
156 * @brief AAAA RR, for IPv6 addresses.
157 */
158class LLAaaaRecord : public LLAddrRecord
159{
160protected:
161 friend class LLQueryResponder;
162
163 LLAaaaRecord(const std::string &name, unsigned ttl);
164
165 int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
166
167public:
168 /**
169 * @brief Socket address.
170 */
171 const sockaddr_in6 &addr_in6() const { return mSA.sin6; }
172};
173
174/**
175 * @class LLHostRecord
176 * @brief Base class for host-related RRs.
177 */
178class LLHostRecord : public LLDnsRecord
179{
180protected:
181 LLHostRecord(LLResType type, const std::string &name, unsigned ttl);
182
183 int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
184
185 std::string mHost;
186
187public:
188 /**
189 * @brief Host name.
190 */
191 const std::string &host() const { return mHost; }
192};
193
194/**
195 * @class LLCnameRecord
196 * @brief CNAME RR.
197 */
198class LLCnameRecord : public LLHostRecord
199{
200protected:
201 friend class LLQueryResponder;
202
203 LLCnameRecord(const std::string &name, unsigned ttl);
204};
205
206/**
207 * @class LLPtrRecord
208 * @brief PTR RR.
209 */
210class LLPtrRecord : public LLHostRecord
211{
212protected:
213 friend class LLQueryResponder;
214
215 LLPtrRecord(const std::string &name, unsigned ttl);
216};
217
218/**
219 * @class LLSrvRecord
220 * @brief SRV RR.
221 */
222class LLSrvRecord : public LLHostRecord
223{
224protected:
225 U16 mPriority;
226 U16 mWeight;
227 U16 mPort;
228
229 int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
230
231public:
232 LLSrvRecord(const std::string &name, unsigned ttl);
233
234 /**
235 * @brief Service priority.
236 */
237 U16 priority() const { return mPriority; }
238
239 /**
240 * @brief Service weight.
241 */
242 U16 weight() const { return mWeight; }
243
244 /**
245 * @brief Port number of service.
246 */
247 U16 port() const { return mPort; }
248
249 /**
250 * @brief Functor for sorting SRV records by priority.
251 */
252 struct ComparePriorityLowest
253 {
254 bool operator()(const LLSrvRecord& lhs, const LLSrvRecord& rhs)
255 {
256 return lhs.mPriority < rhs.mPriority;
257 }
258 };
259};
260
261/**
262 * @class LLNsRecord
263 * @brief NS RR.
264 */
265class LLNsRecord : public LLHostRecord
266{
267public:
268 LLNsRecord(const std::string &name, unsigned ttl);
269};
270
271class LLQueryResponder;
272
273/**
274 * @class LLAres
275 * @brief Asynchronous address resolver.
276 */
277class LLAres
278{
279public:
280 /**
281 * @class HostResponder
282 * @brief Base class for responding to hostname lookups.
283 * @see LLAres::getHostByName
284 */
285 class HostResponder : public LLRefCount
286 {
287 public:
288 virtual ~HostResponder();
289
290 virtual void hostResult(const hostent *ent);
291 virtual void hostError(int code);
292 };
293
294 /**
295 * @class NameInfoResponder
296 * @brief Base class for responding to address lookups.
297 * @see LLAres::getNameInfo
298 */
299 class NameInfoResponder : public LLRefCount
300 {
301 public:
302 virtual ~NameInfoResponder();
303
304 virtual void nameInfoResult(const char *node, const char *service);
305 virtual void nameInfoError(int code);
306 };
307
308 /**
309 * @class QueryResponder
310 * @brief Base class for responding to custom searches.
311 * @see LLAres::search
312 */
313 class QueryResponder : public LLRefCount
314 {
315 public:
316 virtual ~QueryResponder();
317
318 virtual void queryResult(const char *buf, size_t len);
319 virtual void queryError(int code);
320 };
321
322 class SrvResponder;
323 class UriRewriteResponder;
324
325 LLAres();
326
327 ~LLAres();
328
329 /**
330 * Cancel all outstanding requests. The error methods of the
331 * corresponding responders will be called, with ARES_ETIMEOUT.
332 */
333 void cancel();
334
335 /**
336 * Look up the address of a host.
337 *
338 * @param name name of host to look up
339 * @param resp responder to call with result
340 * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
341 */
342 void getHostByName(const std::string &name, HostResponder *resp,
343 int family = AF_INET) {
344 getHostByName(name.c_str(), resp, family);
345 }
346
347 /**
348 * Look up the address of a host.
349 *
350 * @param name name of host to look up
351 * @param resp responder to call with result
352 * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
353 */
354 void getHostByName(const char *name, HostResponder *resp,
355 int family = PF_INET);
356
357 /**
358 * Look up the name associated with a socket address.
359 *
360 * @param sa socket address to look up
361 * @param salen size of socket address
362 * @param flags flags to use
363 * @param resp responder to call with result
364 */
365 void getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags,
366 NameInfoResponder *resp);
367
368 /**
369 * Look up SRV (service location) records for a service name.
370 *
371 * @param name service name (e.g. "_https._tcp.login.agni.lindenlab.com")
372 * @param resp responder to call with result
373 */
374 void getSrvRecords(const std::string &name, SrvResponder *resp);
375
376 /**
377 * Rewrite a URI, using SRV (service location) records for its
378 * protocol if available. If no SRV records are published, the
379 * existing URI is handed to the responder.
380 *
381 * @param uri URI to rewrite
382 * @param resp responder to call with result
383 */
384 void rewriteURI(const std::string &uri,
385 UriRewriteResponder *resp);
386
387 /**
388 * Start a custom search.
389 *
390 * @param query query to make
391 * @param type type of query to perform
392 * @param resp responder to call with result
393 */
394 void search(const std::string &query, LLResType type,
395 QueryResponder *resp);
396
397 /**
398 * Process any outstanding queries. This method takes an optional
399 * timeout parameter (specified in microseconds). If provided, it
400 * will block the calling thread for that length of time to await
401 * possible responses. A timeout of zero will return immediately
402 * if there are no responses or timeouts to process.
403 *
404 * @param timeoutUsecs number of microseconds to block before timing out
405 * @return whether any responses were processed
406 */
407 bool process(U64 timeoutUsecs = 0);
408
409 /**
410 * Process all outstanding queries, blocking the calling thread
411 * until all have either been responded to or timed out.
412 *
413 * @return whether any responses were processed
414 */
415 bool processAll();
416
417 /**
418 * Expand a DNS-encoded compressed string into a normal string.
419 *
420 * @param encoded the encoded name (null-terminated)
421 * @param abuf the response buffer in which the string is embedded
422 * @param alen the length of the response buffer
423 * @param s the string into which to place the result
424 * @return ARES_SUCCESS on success, otherwise an error indicator
425 */
426 static int expandName(const char *encoded, const char *abuf, size_t alen,
427 std::string &s) {
428 size_t ignore;
429 return expandName(encoded, abuf, alen, s, ignore);
430 }
431
432 static int expandName(const char *encoded, const char *abuf, size_t alen,
433 std::string &s, size_t &enclen);
434
435 /**
436 * Return a string describing an error code.
437 */
438 static const char *strerror(int code);
439
440protected:
441 ares_channel chan_;
442
443};
444
445/**
446 * An ordered collection of DNS resource records.
447 */
448typedef std::vector<LLPointer<LLDnsRecord> > dns_rrs_t;
449
450/**
451 * @class LLQueryResponder
452 * @brief Base class for friendly handling of DNS query responses.
453 *
454 * This class parses a DNS response and represents it in a friendly
455 * manner.
456 *
457 * @see LLDnsRecord
458 * @see LLARecord
459 * @see LLNsRecord
460 * @see LLCnameRecord
461 * @see LLPtrRecord
462 * @see LLAaaaRecord
463 * @see LLSrvRecord
464 */
465class LLQueryResponder : public LLAres::QueryResponder
466{
467protected:
468 int mResult;
469 std::string mQuery;
470 LLResType mType;
471
472 dns_rrs_t mAnswers;
473 dns_rrs_t mAuthorities;
474 dns_rrs_t mAdditional;
475
476 /**
477 * Parse a single RR.
478 */
479 int parseRR(const char *buf, size_t len, const char *&pos,
480 LLPointer<LLDnsRecord> &r);
481 /**
482 * Parse one section of a response.
483 */
484 int parseSection(const char *buf, size_t len,
485 size_t count, const char *& pos, dns_rrs_t &rrs);
486
487 void queryResult(const char *buf, size_t len);
488 virtual void queryResult();
489
490public:
491 LLQueryResponder();
492
493 /**
494 * Indicate whether the response could be parsed successfully.
495 */
496 bool valid() const { return mResult == ARES_SUCCESS; }
497
498 /**
499 * The more detailed result of parsing the response.
500 */
501 int result() const { return mResult; }
502
503 /**
504 * Return the query embedded in the response.
505 */
506 const std::string &query() const { return mQuery; }
507
508 /**
509 * Return the contents of the "answers" section of the response.
510 */
511 const dns_rrs_t &answers() const { return mAnswers; }
512
513 /**
514 * Return the contents of the "authorities" section of the
515 * response.
516 */
517 const dns_rrs_t &authorities() const { return mAuthorities; }
518
519 /**
520 * Return the contents of the "additional records" section of the
521 * response.
522 */
523 const dns_rrs_t &additional() const { return mAdditional; }
524};
525
526/**
527 * @class LLAres::SrvResponder
528 * @brief Class for handling SRV query responses.
529 */
530class LLAres::SrvResponder : public LLQueryResponder
531{
532public:
533 friend void LLAres::getSrvRecords(const std::string &name,
534 SrvResponder *resp);
535 void queryResult();
536 void queryError(int code);
537
538 virtual void srvResult(const dns_rrs_t &ents);
539 virtual void srvError(int code);
540};
541
542/**
543 * @class LLAres::UriRewriteResponder
544 * @brief Class for handling URI rewrites based on SRV records.
545 */
546class LLAres::UriRewriteResponder : public LLQueryResponder
547{
548protected:
549 LLURI mUri;
550
551public:
552 friend void LLAres::rewriteURI(const std::string &uri,
553 UriRewriteResponder *resp);
554 void queryResult();
555 void queryError(int code);
556
557 virtual void rewriteResult(const std::vector<std::string> &uris);
558};
559
560/**
561 * Singleton responder.
562 */
563extern LLAres *gAres;
564
565/**
566 * Set up the singleton responder. It's safe to call this more than
567 * once from within a single thread, but this function is not
568 * thread safe.
569 */
570extern LLAres *ll_init_ares();
571
572#endif // LL_LLARES_H