dnscache.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #pragma once
  2. #include <library/cpp/deprecated/atomic/atomic.h>
  3. #include <util/generic/map.h>
  4. #include <util/generic/vector.h>
  5. #include <util/network/address.h>
  6. #include <util/system/mutex.h>
  7. #include <util/datetime/base.h>
  8. /** Asynchronous DNS resolver.
  9. *
  10. * This is NOT general purpose resolver! It is designed with very specific assumptions:
  11. * 1) there is relatively small and rarely changed set of resolved names (like, server pool in cluster)
  12. * 2) this names supposed to have addresses, absense of A record is equal to DNS error
  13. * 3) most of the time IP addresses do not change
  14. * 4) it's OK to return old IP address when DNS server not responding in time
  15. */
  16. class TDnsCache {
  17. public:
  18. TDnsCache(bool allowIpv4 = true, bool allowIpv6 = true, time_t entry_lifetime = 1800, time_t neg_lifetime = 1, ui32 request_timeout = 500000);
  19. ~TDnsCache();
  20. TString GetHostByAddr(const NAddr::IRemoteAddr&);
  21. // ip in network byte order
  22. TIpHost Get(const TString& host);
  23. /* use with AF_INET, AF_INET6 or AF_UNSPEC */
  24. NAddr::IRemoteAddrPtr GetAddr(const TString& host,
  25. int family,
  26. TIpPort port = 0,
  27. bool cacheOnly = false);
  28. void GetAllAddresses(const TString& host, TVector<NAddr::IRemoteAddrPtr>&);
  29. void GetStats(ui64& a_cache_hits, ui64& a_cache_misses,
  30. ui64& ptr_cache_hits, ui64& ptr_cache_misses);
  31. protected:
  32. bool ValidateHName(const TString& host) const noexcept;
  33. private:
  34. struct TGHBNContext {
  35. TDnsCache* Owner;
  36. TString Hostname;
  37. int Family;
  38. };
  39. struct TGHBAContext {
  40. TDnsCache* Owner;
  41. in6_addr Addr;
  42. };
  43. struct THost {
  44. THost() noexcept {
  45. }
  46. TVector<TIpHost> AddrsV4;
  47. time_t ResolvedV4 = 0;
  48. time_t NotFoundV4 = 0;
  49. TAtomic InProgressV4 = 0;
  50. TVector<in6_addr> AddrsV6;
  51. time_t ResolvedV6 = 0;
  52. time_t NotFoundV6 = 0;
  53. TAtomic InProgressV6 = 0;
  54. TString AddrsV4ToString() const;
  55. TString AddrsV6ToString() const;
  56. bool IsStale(int family, const TDnsCache* ctx) const noexcept;
  57. };
  58. typedef TMap<TString, THost> THostCache;
  59. struct TAddr {
  60. TString Hostname;
  61. time_t Resolved = 0;
  62. time_t NotFound = 0;
  63. TAtomic InProgress = 0;
  64. };
  65. /* IRemoteAddr is annoingly hard to use, so I'll use in6_addr as key
  66. * and put v4 addrs in it.
  67. */
  68. struct TAddrCmp {
  69. bool operator()(const in6_addr& left, const in6_addr& right) const {
  70. for (size_t i = 0; i < sizeof(left); i++) {
  71. if (left.s6_addr[i] < right.s6_addr[i]) {
  72. return true;
  73. } else if (left.s6_addr[i] > right.s6_addr[i]) {
  74. return false;
  75. }
  76. }
  77. // equal
  78. return false;
  79. }
  80. };
  81. typedef TMap<in6_addr, TAddr, TAddrCmp> TAddrCache;
  82. const THost& Resolve(const TString&, int family, bool cacheOnly = false);
  83. const TAddr& ResolveAddr(const in6_addr&, int family);
  84. void WaitTask(TAtomic&);
  85. static void GHBNCallback(void* arg, int status, int timeouts,
  86. struct hostent* info);
  87. static void GHBACallback(void* arg, int status, int timeouts,
  88. struct hostent* info);
  89. const time_t EntryLifetime;
  90. const time_t NegativeLifetime;
  91. const TDuration Timeout;
  92. const bool AllowIpV4;
  93. const bool AllowIpV6;
  94. TMutex CacheMtx;
  95. THostCache HostCache;
  96. TAddrCache AddrCache;
  97. ui64 ACacheHits;
  98. ui64 ACacheMisses;
  99. ui64 PtrCacheHits;
  100. ui64 PtrCacheMisses;
  101. const static THost NullHost;
  102. TMutex AresMtx;
  103. void* Channel;
  104. struct TAresLibInit {
  105. TAresLibInit();
  106. ~TAresLibInit();
  107. };
  108. static TAresLibInit InitAresLib;
  109. };