Imported existing code
This commit is contained in:
575
indra/llmessage/llares.h
Normal file
575
indra/llmessage/llares.h
Normal file
@@ -0,0 +1,575 @@
|
||||
/**
|
||||
* @file llares.h
|
||||
* @author Bryan O'Sullivan
|
||||
* @date 2007-08-15
|
||||
* @brief Wrapper for asynchronous DNS lookups.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2007-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLARES_H
|
||||
#define LL_LLARES_H
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifdef LL_STANDALONE
|
||||
# include <ares.h>
|
||||
#else
|
||||
# include <ares/ares.h>
|
||||
#endif
|
||||
|
||||
#include "llmemory.h"
|
||||
#include "lluri.h"
|
||||
|
||||
class LLQueryResponder;
|
||||
|
||||
/**
|
||||
* @brief Supported DNS RR types.
|
||||
*/
|
||||
enum LLResType
|
||||
{
|
||||
RES_INVALID = 0, /**< Cookie. */
|
||||
RES_A = 1, /**< "A" record. IPv4 address. */
|
||||
RES_NS = 2, /**< "NS" record. Authoritative server. */
|
||||
RES_CNAME = 5, /**< "CNAME" record. Canonical name. */
|
||||
RES_PTR = 12, /**< "PTR" record. Domain name pointer. */
|
||||
RES_AAAA = 28, /**< "AAAA" record. IPv6 Address. */
|
||||
RES_SRV = 33, /**< "SRV" record. Server Selection. */
|
||||
RES_MAX = 65536 /**< Sentinel; RR types are 16 bits wide. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLDnsRecord
|
||||
* @brief Base class for all DNS RR types.
|
||||
*/
|
||||
class LLDnsRecord : public LLRefCount
|
||||
{
|
||||
protected:
|
||||
friend class LLQueryResponder;
|
||||
|
||||
LLResType mType;
|
||||
std::string mName;
|
||||
unsigned mTTL;
|
||||
|
||||
virtual int parse(const char *buf, size_t len, const char *pos,
|
||||
size_t rrlen) = 0;
|
||||
|
||||
LLDnsRecord(LLResType type, const std::string &name, unsigned ttl);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Record name.
|
||||
*/
|
||||
const std::string &name() const { return mName; }
|
||||
|
||||
/**
|
||||
* @brief Time-to-live value, in seconds.
|
||||
*/
|
||||
unsigned ttl() const { return mTTL; }
|
||||
|
||||
/**
|
||||
* @brief RR type.
|
||||
*/
|
||||
LLResType type() const { return mType; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLAddrRecord
|
||||
* @brief Base class for address-related RRs.
|
||||
*/
|
||||
class LLAddrRecord : public LLDnsRecord
|
||||
{
|
||||
protected:
|
||||
friend class LLQueryResponder;
|
||||
|
||||
LLAddrRecord(LLResType type, const std::string &name, unsigned ttl);
|
||||
|
||||
union
|
||||
{
|
||||
sockaddr sa;
|
||||
sockaddr_in sin;
|
||||
sockaddr_in6 sin6;
|
||||
} mSA;
|
||||
|
||||
socklen_t mSize;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Generic socket address.
|
||||
*/
|
||||
const sockaddr &addr() const { return mSA.sa; }
|
||||
|
||||
/**
|
||||
* @brief Size of the socket structure.
|
||||
*/
|
||||
socklen_t size() const { return mSize; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLARecord
|
||||
* @brief A RR, for IPv4 addresses.
|
||||
*/
|
||||
class LLARecord : public LLAddrRecord
|
||||
{
|
||||
protected:
|
||||
friend class LLQueryResponder;
|
||||
|
||||
LLARecord(const std::string &name, unsigned ttl);
|
||||
|
||||
int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Socket address.
|
||||
*/
|
||||
const sockaddr_in &addr_in() const { return mSA.sin; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLAaaaRecord
|
||||
* @brief AAAA RR, for IPv6 addresses.
|
||||
*/
|
||||
class LLAaaaRecord : public LLAddrRecord
|
||||
{
|
||||
protected:
|
||||
friend class LLQueryResponder;
|
||||
|
||||
LLAaaaRecord(const std::string &name, unsigned ttl);
|
||||
|
||||
int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Socket address.
|
||||
*/
|
||||
const sockaddr_in6 &addr_in6() const { return mSA.sin6; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLHostRecord
|
||||
* @brief Base class for host-related RRs.
|
||||
*/
|
||||
class LLHostRecord : public LLDnsRecord
|
||||
{
|
||||
protected:
|
||||
LLHostRecord(LLResType type, const std::string &name, unsigned ttl);
|
||||
|
||||
int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
|
||||
|
||||
std::string mHost;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Host name.
|
||||
*/
|
||||
const std::string &host() const { return mHost; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLCnameRecord
|
||||
* @brief CNAME RR.
|
||||
*/
|
||||
class LLCnameRecord : public LLHostRecord
|
||||
{
|
||||
protected:
|
||||
friend class LLQueryResponder;
|
||||
|
||||
LLCnameRecord(const std::string &name, unsigned ttl);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLPtrRecord
|
||||
* @brief PTR RR.
|
||||
*/
|
||||
class LLPtrRecord : public LLHostRecord
|
||||
{
|
||||
protected:
|
||||
friend class LLQueryResponder;
|
||||
|
||||
LLPtrRecord(const std::string &name, unsigned ttl);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLSrvRecord
|
||||
* @brief SRV RR.
|
||||
*/
|
||||
class LLSrvRecord : public LLHostRecord
|
||||
{
|
||||
protected:
|
||||
U16 mPriority;
|
||||
U16 mWeight;
|
||||
U16 mPort;
|
||||
|
||||
int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
|
||||
|
||||
public:
|
||||
LLSrvRecord(const std::string &name, unsigned ttl);
|
||||
|
||||
/**
|
||||
* @brief Service priority.
|
||||
*/
|
||||
U16 priority() const { return mPriority; }
|
||||
|
||||
/**
|
||||
* @brief Service weight.
|
||||
*/
|
||||
U16 weight() const { return mWeight; }
|
||||
|
||||
/**
|
||||
* @brief Port number of service.
|
||||
*/
|
||||
U16 port() const { return mPort; }
|
||||
|
||||
/**
|
||||
* @brief Functor for sorting SRV records by priority.
|
||||
*/
|
||||
struct ComparePriorityLowest
|
||||
{
|
||||
bool operator()(const LLSrvRecord& lhs, const LLSrvRecord& rhs)
|
||||
{
|
||||
return lhs.mPriority < rhs.mPriority;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLNsRecord
|
||||
* @brief NS RR.
|
||||
*/
|
||||
class LLNsRecord : public LLHostRecord
|
||||
{
|
||||
public:
|
||||
LLNsRecord(const std::string &name, unsigned ttl);
|
||||
};
|
||||
|
||||
class LLQueryResponder;
|
||||
|
||||
/**
|
||||
* @class LLAres
|
||||
* @brief Asynchronous address resolver.
|
||||
*/
|
||||
class LLAres
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @class HostResponder
|
||||
* @brief Base class for responding to hostname lookups.
|
||||
* @see LLAres::getHostByName
|
||||
*/
|
||||
class HostResponder : public LLRefCount
|
||||
{
|
||||
public:
|
||||
virtual ~HostResponder();
|
||||
|
||||
virtual void hostResult(const hostent *ent);
|
||||
virtual void hostError(int code);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class NameInfoResponder
|
||||
* @brief Base class for responding to address lookups.
|
||||
* @see LLAres::getNameInfo
|
||||
*/
|
||||
class NameInfoResponder : public LLRefCount
|
||||
{
|
||||
public:
|
||||
virtual ~NameInfoResponder();
|
||||
|
||||
virtual void nameInfoResult(const char *node, const char *service);
|
||||
virtual void nameInfoError(int code);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class QueryResponder
|
||||
* @brief Base class for responding to custom searches.
|
||||
* @see LLAres::search
|
||||
*/
|
||||
class QueryResponder : public LLRefCount
|
||||
{
|
||||
public:
|
||||
virtual ~QueryResponder();
|
||||
|
||||
virtual void queryResult(const char *buf, size_t len);
|
||||
virtual void queryError(int code);
|
||||
};
|
||||
|
||||
class SrvResponder;
|
||||
class UriRewriteResponder;
|
||||
|
||||
LLAres();
|
||||
|
||||
~LLAres();
|
||||
|
||||
/**
|
||||
* Cancel all outstanding requests. The error methods of the
|
||||
* corresponding responders will be called, with ARES_ETIMEOUT.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Look up the address of a host.
|
||||
*
|
||||
* @param name name of host to look up
|
||||
* @param resp responder to call with result
|
||||
* @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
|
||||
*/
|
||||
void getHostByName(const std::string &name, HostResponder *resp,
|
||||
int family = AF_INET) {
|
||||
getHostByName(name.c_str(), resp, family);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the address of a host.
|
||||
*
|
||||
* @param name name of host to look up
|
||||
* @param resp responder to call with result
|
||||
* @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
|
||||
*/
|
||||
void getHostByName(const char *name, HostResponder *resp,
|
||||
int family = PF_INET);
|
||||
|
||||
/**
|
||||
* Look up the name associated with a socket address.
|
||||
*
|
||||
* @param sa socket address to look up
|
||||
* @param salen size of socket address
|
||||
* @param flags flags to use
|
||||
* @param resp responder to call with result
|
||||
*/
|
||||
void getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags,
|
||||
NameInfoResponder *resp);
|
||||
|
||||
/**
|
||||
* Look up SRV (service location) records for a service name.
|
||||
*
|
||||
* @param name service name (e.g. "_https._tcp.login.agni.lindenlab.com")
|
||||
* @param resp responder to call with result
|
||||
*/
|
||||
void getSrvRecords(const std::string &name, SrvResponder *resp);
|
||||
|
||||
/**
|
||||
* Rewrite a URI, using SRV (service location) records for its
|
||||
* protocol if available. If no SRV records are published, the
|
||||
* existing URI is handed to the responder.
|
||||
*
|
||||
* @param uri URI to rewrite
|
||||
* @param resp responder to call with result
|
||||
*/
|
||||
void rewriteURI(const std::string &uri,
|
||||
UriRewriteResponder *resp);
|
||||
|
||||
/**
|
||||
* Start a custom search.
|
||||
*
|
||||
* @param query query to make
|
||||
* @param type type of query to perform
|
||||
* @param resp responder to call with result
|
||||
*/
|
||||
void search(const std::string &query, LLResType type,
|
||||
QueryResponder *resp);
|
||||
|
||||
/**
|
||||
* Process any outstanding queries. This method takes an optional
|
||||
* timeout parameter (specified in microseconds). If provided, it
|
||||
* will block the calling thread for that length of time to await
|
||||
* possible responses. A timeout of zero will return immediately
|
||||
* if there are no responses or timeouts to process.
|
||||
*
|
||||
* @param timeoutUsecs number of microseconds to block before timing out
|
||||
* @return whether any responses were processed
|
||||
*/
|
||||
bool process(U64 timeoutUsecs = 0);
|
||||
|
||||
/**
|
||||
* Process all outstanding queries, blocking the calling thread
|
||||
* until all have either been responded to or timed out.
|
||||
*
|
||||
* @return whether any responses were processed
|
||||
*/
|
||||
bool processAll();
|
||||
|
||||
/**
|
||||
* Expand a DNS-encoded compressed string into a normal string.
|
||||
*
|
||||
* @param encoded the encoded name (null-terminated)
|
||||
* @param abuf the response buffer in which the string is embedded
|
||||
* @param alen the length of the response buffer
|
||||
* @param s the string into which to place the result
|
||||
* @return ARES_SUCCESS on success, otherwise an error indicator
|
||||
*/
|
||||
static int expandName(const char *encoded, const char *abuf, size_t alen,
|
||||
std::string &s) {
|
||||
size_t ignore;
|
||||
return expandName(encoded, abuf, alen, s, ignore);
|
||||
}
|
||||
|
||||
static int expandName(const char *encoded, const char *abuf, size_t alen,
|
||||
std::string &s, size_t &enclen);
|
||||
|
||||
/**
|
||||
* Return a string describing an error code.
|
||||
*/
|
||||
static const char *strerror(int code);
|
||||
|
||||
bool isInitialized(void) { return mInitSuccess; }
|
||||
|
||||
protected:
|
||||
ares_channel chan_;
|
||||
bool mInitSuccess;
|
||||
};
|
||||
|
||||
/**
|
||||
* An ordered collection of DNS resource records.
|
||||
*/
|
||||
typedef std::vector<LLPointer<LLDnsRecord> > dns_rrs_t;
|
||||
|
||||
/**
|
||||
* @class LLQueryResponder
|
||||
* @brief Base class for friendly handling of DNS query responses.
|
||||
*
|
||||
* This class parses a DNS response and represents it in a friendly
|
||||
* manner.
|
||||
*
|
||||
* @see LLDnsRecord
|
||||
* @see LLARecord
|
||||
* @see LLNsRecord
|
||||
* @see LLCnameRecord
|
||||
* @see LLPtrRecord
|
||||
* @see LLAaaaRecord
|
||||
* @see LLSrvRecord
|
||||
*/
|
||||
class LLQueryResponder : public LLAres::QueryResponder
|
||||
{
|
||||
protected:
|
||||
int mResult;
|
||||
std::string mQuery;
|
||||
LLResType mType;
|
||||
|
||||
dns_rrs_t mAnswers;
|
||||
dns_rrs_t mAuthorities;
|
||||
dns_rrs_t mAdditional;
|
||||
|
||||
/**
|
||||
* Parse a single RR.
|
||||
*/
|
||||
int parseRR(const char *buf, size_t len, const char *&pos,
|
||||
LLPointer<LLDnsRecord> &r);
|
||||
/**
|
||||
* Parse one section of a response.
|
||||
*/
|
||||
int parseSection(const char *buf, size_t len,
|
||||
size_t count, const char *& pos, dns_rrs_t &rrs);
|
||||
|
||||
void queryResult(const char *buf, size_t len);
|
||||
virtual void querySuccess();
|
||||
|
||||
public:
|
||||
LLQueryResponder();
|
||||
|
||||
/**
|
||||
* Indicate whether the response could be parsed successfully.
|
||||
*/
|
||||
bool valid() const { return mResult == ARES_SUCCESS; }
|
||||
|
||||
/**
|
||||
* The more detailed result of parsing the response.
|
||||
*/
|
||||
int result() const { return mResult; }
|
||||
|
||||
/**
|
||||
* Return the query embedded in the response.
|
||||
*/
|
||||
const std::string &query() const { return mQuery; }
|
||||
|
||||
/**
|
||||
* Return the contents of the "answers" section of the response.
|
||||
*/
|
||||
const dns_rrs_t &answers() const { return mAnswers; }
|
||||
|
||||
/**
|
||||
* Return the contents of the "authorities" section of the
|
||||
* response.
|
||||
*/
|
||||
const dns_rrs_t &authorities() const { return mAuthorities; }
|
||||
|
||||
/**
|
||||
* Return the contents of the "additional records" section of the
|
||||
* response.
|
||||
*/
|
||||
const dns_rrs_t &additional() const { return mAdditional; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLAres::SrvResponder
|
||||
* @brief Class for handling SRV query responses.
|
||||
*/
|
||||
class LLAres::SrvResponder : public LLQueryResponder
|
||||
{
|
||||
public:
|
||||
friend void LLAres::getSrvRecords(const std::string &name,
|
||||
SrvResponder *resp);
|
||||
void querySuccess();
|
||||
void queryError(int code);
|
||||
|
||||
virtual void srvResult(const dns_rrs_t &ents);
|
||||
virtual void srvError(int code);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLAres::UriRewriteResponder
|
||||
* @brief Class for handling URI rewrites based on SRV records.
|
||||
*/
|
||||
class LLAres::UriRewriteResponder : public LLQueryResponder
|
||||
{
|
||||
protected:
|
||||
LLURI mUri;
|
||||
|
||||
public:
|
||||
friend void LLAres::rewriteURI(const std::string &uri,
|
||||
UriRewriteResponder *resp);
|
||||
void querySuccess();
|
||||
void queryError(int code);
|
||||
|
||||
virtual void rewriteResult(const std::vector<std::string> &uris);
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton responder.
|
||||
*/
|
||||
extern LLAres *gAres;
|
||||
|
||||
/**
|
||||
* Set up the singleton responder. It's safe to call this more than
|
||||
* once from within a single thread, but this function is not
|
||||
* thread safe.
|
||||
*/
|
||||
extern LLAres *ll_init_ares();
|
||||
|
||||
#endif // LL_LLARES_H
|
||||
Reference in New Issue
Block a user