PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/llares.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 582 lines | 234 code | 88 blank | 260 comment | 1 complexity | 63abdc8393fba28e1c39a43e65fbf958 MD5 | raw file
Possible License(s): LGPL-2.1
  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=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #ifndef LL_LLARES_H
  29. #define LL_LLARES_H
  30. #ifdef LL_WINDOWS
  31. // ares.h is broken on windows in that it depends on types defined in ws2tcpip.h
  32. // we need to include them first to work around it, but the headers issue warnings
  33. # pragma warning(push)
  34. # pragma warning(disable:4996)
  35. # include <winsock2.h>
  36. # include <ws2tcpip.h>
  37. # pragma warning(pop)
  38. #endif
  39. #ifdef LL_STANDALONE
  40. # include <ares.h>
  41. #else
  42. # include <ares/ares.h>
  43. #endif
  44. #include "llpointer.h"
  45. #include "llrefcount.h"
  46. #include "lluri.h"
  47. #include <boost/shared_ptr.hpp>
  48. class LLQueryResponder;
  49. class LLAresListener;
  50. /**
  51. * @brief Supported DNS RR types.
  52. */
  53. enum LLResType
  54. {
  55. RES_INVALID = 0, /**< Cookie. */
  56. RES_A = 1, /**< "A" record. IPv4 address. */
  57. RES_NS = 2, /**< "NS" record. Authoritative server. */
  58. RES_CNAME = 5, /**< "CNAME" record. Canonical name. */
  59. RES_PTR = 12, /**< "PTR" record. Domain name pointer. */
  60. RES_AAAA = 28, /**< "AAAA" record. IPv6 Address. */
  61. RES_SRV = 33, /**< "SRV" record. Server Selection. */
  62. RES_MAX = 65536 /**< Sentinel; RR types are 16 bits wide. */
  63. };
  64. /**
  65. * @class LLDnsRecord
  66. * @brief Base class for all DNS RR types.
  67. */
  68. class LLDnsRecord : public LLRefCount
  69. {
  70. protected:
  71. friend class LLQueryResponder;
  72. LLResType mType;
  73. std::string mName;
  74. unsigned mTTL;
  75. virtual int parse(const char *buf, size_t len, const char *pos,
  76. size_t rrlen) = 0;
  77. LLDnsRecord(LLResType type, const std::string &name, unsigned ttl);
  78. public:
  79. /**
  80. * @brief Record name.
  81. */
  82. const std::string &name() const { return mName; }
  83. /**
  84. * @brief Time-to-live value, in seconds.
  85. */
  86. unsigned ttl() const { return mTTL; }
  87. /**
  88. * @brief RR type.
  89. */
  90. LLResType type() const { return mType; }
  91. };
  92. /**
  93. * @class LLAddrRecord
  94. * @brief Base class for address-related RRs.
  95. */
  96. class LLAddrRecord : public LLDnsRecord
  97. {
  98. protected:
  99. friend class LLQueryResponder;
  100. LLAddrRecord(LLResType type, const std::string &name, unsigned ttl);
  101. union
  102. {
  103. sockaddr sa;
  104. sockaddr_in sin;
  105. sockaddr_in6 sin6;
  106. } mSA;
  107. socklen_t mSize;
  108. public:
  109. /**
  110. * @brief Generic socket address.
  111. */
  112. const sockaddr &addr() const { return mSA.sa; }
  113. /**
  114. * @brief Size of the socket structure.
  115. */
  116. socklen_t size() const { return mSize; }
  117. };
  118. /**
  119. * @class LLARecord
  120. * @brief A RR, for IPv4 addresses.
  121. */
  122. class LLARecord : public LLAddrRecord
  123. {
  124. protected:
  125. friend class LLQueryResponder;
  126. LLARecord(const std::string &name, unsigned ttl);
  127. int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
  128. public:
  129. /**
  130. * @brief Socket address.
  131. */
  132. const sockaddr_in &addr_in() const { return mSA.sin; }
  133. };
  134. /**
  135. * @class LLAaaaRecord
  136. * @brief AAAA RR, for IPv6 addresses.
  137. */
  138. class LLAaaaRecord : public LLAddrRecord
  139. {
  140. protected:
  141. friend class LLQueryResponder;
  142. LLAaaaRecord(const std::string &name, unsigned ttl);
  143. int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
  144. public:
  145. /**
  146. * @brief Socket address.
  147. */
  148. const sockaddr_in6 &addr_in6() const { return mSA.sin6; }
  149. };
  150. /**
  151. * @class LLHostRecord
  152. * @brief Base class for host-related RRs.
  153. */
  154. class LLHostRecord : public LLDnsRecord
  155. {
  156. protected:
  157. LLHostRecord(LLResType type, const std::string &name, unsigned ttl);
  158. int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
  159. std::string mHost;
  160. public:
  161. /**
  162. * @brief Host name.
  163. */
  164. const std::string &host() const { return mHost; }
  165. };
  166. /**
  167. * @class LLCnameRecord
  168. * @brief CNAME RR.
  169. */
  170. class LLCnameRecord : public LLHostRecord
  171. {
  172. protected:
  173. friend class LLQueryResponder;
  174. LLCnameRecord(const std::string &name, unsigned ttl);
  175. };
  176. /**
  177. * @class LLPtrRecord
  178. * @brief PTR RR.
  179. */
  180. class LLPtrRecord : public LLHostRecord
  181. {
  182. protected:
  183. friend class LLQueryResponder;
  184. LLPtrRecord(const std::string &name, unsigned ttl);
  185. };
  186. /**
  187. * @class LLSrvRecord
  188. * @brief SRV RR.
  189. */
  190. class LLSrvRecord : public LLHostRecord
  191. {
  192. protected:
  193. U16 mPriority;
  194. U16 mWeight;
  195. U16 mPort;
  196. int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
  197. public:
  198. LLSrvRecord(const std::string &name, unsigned ttl);
  199. /**
  200. * @brief Service priority.
  201. */
  202. U16 priority() const { return mPriority; }
  203. /**
  204. * @brief Service weight.
  205. */
  206. U16 weight() const { return mWeight; }
  207. /**
  208. * @brief Port number of service.
  209. */
  210. U16 port() const { return mPort; }
  211. /**
  212. * @brief Functor for sorting SRV records by priority.
  213. */
  214. struct ComparePriorityLowest
  215. {
  216. bool operator()(const LLSrvRecord& lhs, const LLSrvRecord& rhs)
  217. {
  218. return lhs.mPriority < rhs.mPriority;
  219. }
  220. };
  221. };
  222. /**
  223. * @class LLNsRecord
  224. * @brief NS RR.
  225. */
  226. class LLNsRecord : public LLHostRecord
  227. {
  228. public:
  229. LLNsRecord(const std::string &name, unsigned ttl);
  230. };
  231. class LLQueryResponder;
  232. /**
  233. * @class LLAres
  234. * @brief Asynchronous address resolver.
  235. */
  236. class LLAres
  237. {
  238. public:
  239. /**
  240. * @class HostResponder
  241. * @brief Base class for responding to hostname lookups.
  242. * @see LLAres::getHostByName
  243. */
  244. class HostResponder : public LLRefCount
  245. {
  246. public:
  247. virtual ~HostResponder();
  248. virtual void hostResult(const hostent *ent);
  249. virtual void hostError(int code);
  250. };
  251. /**
  252. * @class NameInfoResponder
  253. * @brief Base class for responding to address lookups.
  254. * @see LLAres::getNameInfo
  255. */
  256. class NameInfoResponder : public LLRefCount
  257. {
  258. public:
  259. virtual ~NameInfoResponder();
  260. virtual void nameInfoResult(const char *node, const char *service);
  261. virtual void nameInfoError(int code);
  262. };
  263. /**
  264. * @class QueryResponder
  265. * @brief Base class for responding to custom searches.
  266. * @see LLAres::search
  267. */
  268. class QueryResponder : public LLRefCount
  269. {
  270. public:
  271. virtual ~QueryResponder();
  272. virtual void queryResult(const char *buf, size_t len);
  273. virtual void queryError(int code);
  274. };
  275. class SrvResponder;
  276. class UriRewriteResponder;
  277. LLAres();
  278. ~LLAres();
  279. /**
  280. * Cancel all outstanding requests. The error methods of the
  281. * corresponding responders will be called, with ARES_ETIMEOUT.
  282. */
  283. void cancel();
  284. /**
  285. * Look up the address of a host.
  286. *
  287. * @param name name of host to look up
  288. * @param resp responder to call with result
  289. * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
  290. */
  291. void getHostByName(const std::string &name, HostResponder *resp,
  292. int family = AF_INET) {
  293. getHostByName(name.c_str(), resp, family);
  294. }
  295. /**
  296. * Look up the address of a host.
  297. *
  298. * @param name name of host to look up
  299. * @param resp responder to call with result
  300. * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
  301. */
  302. void getHostByName(const char *name, HostResponder *resp,
  303. int family = PF_INET);
  304. /**
  305. * Look up the name associated with a socket address.
  306. *
  307. * @param sa socket address to look up
  308. * @param salen size of socket address
  309. * @param flags flags to use
  310. * @param resp responder to call with result
  311. */
  312. void getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags,
  313. NameInfoResponder *resp);
  314. /**
  315. * Look up SRV (service location) records for a service name.
  316. *
  317. * @param name service name (e.g. "_https._tcp.login.agni.lindenlab.com")
  318. * @param resp responder to call with result
  319. */
  320. void getSrvRecords(const std::string &name, SrvResponder *resp);
  321. /**
  322. * Rewrite a URI, using SRV (service location) records for its
  323. * protocol if available. If no SRV records are published, the
  324. * existing URI is handed to the responder.
  325. *
  326. * @param uri URI to rewrite
  327. * @param resp responder to call with result
  328. */
  329. void rewriteURI(const std::string &uri,
  330. UriRewriteResponder *resp);
  331. /**
  332. * Start a custom search.
  333. *
  334. * @param query query to make
  335. * @param type type of query to perform
  336. * @param resp responder to call with result
  337. */
  338. void search(const std::string &query, LLResType type,
  339. QueryResponder *resp);
  340. /**
  341. * Process any outstanding queries. This method takes an optional
  342. * timeout parameter (specified in microseconds). If provided, it
  343. * will block the calling thread for that length of time to await
  344. * possible responses. A timeout of zero will return immediately
  345. * if there are no responses or timeouts to process.
  346. *
  347. * @param timeoutUsecs number of microseconds to block before timing out
  348. * @return whether any responses were processed
  349. */
  350. bool process(U64 timeoutUsecs = 0);
  351. /**
  352. * Process all outstanding queries, blocking the calling thread
  353. * until all have either been responded to or timed out.
  354. *
  355. * @return whether any responses were processed
  356. */
  357. bool processAll();
  358. /**
  359. * Expand a DNS-encoded compressed string into a normal string.
  360. *
  361. * @param encoded the encoded name (null-terminated)
  362. * @param abuf the response buffer in which the string is embedded
  363. * @param alen the length of the response buffer
  364. * @param s the string into which to place the result
  365. * @return ARES_SUCCESS on success, otherwise an error indicator
  366. */
  367. static int expandName(const char *encoded, const char *abuf, size_t alen,
  368. std::string &s) {
  369. size_t ignore;
  370. return expandName(encoded, abuf, alen, s, ignore);
  371. }
  372. static int expandName(const char *encoded, const char *abuf, size_t alen,
  373. std::string &s, size_t &enclen);
  374. /**
  375. * Return a string describing an error code.
  376. */
  377. static const char *strerror(int code);
  378. bool isInitialized(void) { return mInitSuccess; }
  379. protected:
  380. ares_channel chan_;
  381. bool mInitSuccess;
  382. // boost::scoped_ptr would actually fit the requirement better, but it
  383. // can't handle incomplete types as boost::shared_ptr can.
  384. boost::shared_ptr<LLAresListener> mListener;
  385. };
  386. /**
  387. * An ordered collection of DNS resource records.
  388. */
  389. typedef std::vector<LLPointer<LLDnsRecord> > dns_rrs_t;
  390. /**
  391. * @class LLQueryResponder
  392. * @brief Base class for friendly handling of DNS query responses.
  393. *
  394. * This class parses a DNS response and represents it in a friendly
  395. * manner.
  396. *
  397. * @see LLDnsRecord
  398. * @see LLARecord
  399. * @see LLNsRecord
  400. * @see LLCnameRecord
  401. * @see LLPtrRecord
  402. * @see LLAaaaRecord
  403. * @see LLSrvRecord
  404. */
  405. class LLQueryResponder : public LLAres::QueryResponder
  406. {
  407. protected:
  408. int mResult;
  409. std::string mQuery;
  410. LLResType mType;
  411. dns_rrs_t mAnswers;
  412. dns_rrs_t mAuthorities;
  413. dns_rrs_t mAdditional;
  414. /**
  415. * Parse a single RR.
  416. */
  417. int parseRR(const char *buf, size_t len, const char *&pos,
  418. LLPointer<LLDnsRecord> &r);
  419. /**
  420. * Parse one section of a response.
  421. */
  422. int parseSection(const char *buf, size_t len,
  423. size_t count, const char *& pos, dns_rrs_t &rrs);
  424. void queryResult(const char *buf, size_t len);
  425. virtual void querySuccess();
  426. public:
  427. LLQueryResponder();
  428. /**
  429. * Indicate whether the response could be parsed successfully.
  430. */
  431. bool valid() const { return mResult == ARES_SUCCESS; }
  432. /**
  433. * The more detailed result of parsing the response.
  434. */
  435. int result() const { return mResult; }
  436. /**
  437. * Return the query embedded in the response.
  438. */
  439. const std::string &query() const { return mQuery; }
  440. /**
  441. * Return the contents of the "answers" section of the response.
  442. */
  443. const dns_rrs_t &answers() const { return mAnswers; }
  444. /**
  445. * Return the contents of the "authorities" section of the
  446. * response.
  447. */
  448. const dns_rrs_t &authorities() const { return mAuthorities; }
  449. /**
  450. * Return the contents of the "additional records" section of the
  451. * response.
  452. */
  453. const dns_rrs_t &additional() const { return mAdditional; }
  454. };
  455. /**
  456. * @class LLAres::SrvResponder
  457. * @brief Class for handling SRV query responses.
  458. */
  459. class LLAres::SrvResponder : public LLQueryResponder
  460. {
  461. public:
  462. friend void LLAres::getSrvRecords(const std::string &name,
  463. SrvResponder *resp);
  464. void querySuccess();
  465. void queryError(int code);
  466. virtual void srvResult(const dns_rrs_t &ents);
  467. virtual void srvError(int code);
  468. };
  469. /**
  470. * @class LLAres::UriRewriteResponder
  471. * @brief Class for handling URI rewrites based on SRV records.
  472. */
  473. class LLAres::UriRewriteResponder : public LLQueryResponder
  474. {
  475. protected:
  476. LLURI mUri;
  477. public:
  478. friend void LLAres::rewriteURI(const std::string &uri,
  479. UriRewriteResponder *resp);
  480. void querySuccess();
  481. void queryError(int code);
  482. virtual void rewriteResult(const std::vector<std::string> &uris);
  483. };
  484. /**
  485. * Singleton responder.
  486. */
  487. extern LLAres *gAres;
  488. /**
  489. * Set up the singleton responder. It's safe to call this more than
  490. * once from within a single thread, but this function is not
  491. * thread safe.
  492. */
  493. extern LLAres *ll_init_ares();
  494. #endif // LL_LLARES_H