ipv6_address.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #pragma once
  2. #include <util/generic/hash_set.h>
  3. #include <util/generic/strbuf.h>
  4. #include <util/network/ip.h>
  5. #include <util/stream/input.h>
  6. #include <library/cpp/int128/int128.h>
  7. #if defined(_freebsd_)
  8. // #include required to avoid problem with undefined 'socklen_t' on FreeBSD
  9. #include <sys/socket.h>
  10. #endif
  11. #if defined(_win_)
  12. // #include required to avoid problem with undefined 'socklen_t' on Windows
  13. #include <util/network/socket.h>
  14. #endif
  15. namespace NAddr {
  16. class IRemoteAddr;
  17. }
  18. struct in6_addr;
  19. struct in_addr;
  20. struct sockaddr;
  21. struct sockaddr_in;
  22. struct sockaddr_in6;
  23. // TODO (dimanne): rename to something like TIntInetAddress or THostAddress
  24. class TIpv6Address {
  25. public:
  26. enum TIpType { Ipv6,
  27. Ipv4,
  28. LAST };
  29. constexpr TIpv6Address() noexcept = default;
  30. constexpr TIpv6Address(const TIpv6Address&) noexcept = default;
  31. constexpr TIpv6Address& operator=(const TIpv6Address&) noexcept = default;
  32. constexpr TIpv6Address(const ui128& ip, TIpType Type) noexcept
  33. : Ip(ip), Type_(Type)
  34. {}
  35. constexpr TIpv6Address(ui8 a, ui8 b, ui8 c, ui8 d) noexcept
  36. : Ip((ui32(a) << 24) | (ui32(b) << 16) | (ui32(c) << 8) | ui32(d))
  37. , Type_(TIpv6Address::Ipv4)
  38. {}
  39. constexpr TIpv6Address(ui16 a, ui16 b, ui16 c, ui16 d, ui16 e, ui16 f, ui16 g, ui16 h, ui32 scope = 0) noexcept
  40. : Type_(TIpv6Address::Ipv6)
  41. , ScopeId_(scope)
  42. {
  43. auto hi = (ui64(a) << 48) | (ui64(b) << 32) | (ui64(c) << 16) | ui64(d);
  44. auto lo = (ui64(e) << 48) | (ui64(f) << 32) | (ui64(g) << 16) | ui64(h);
  45. Ip = {hi, lo};
  46. }
  47. explicit TIpv6Address(const NAddr::IRemoteAddr& addr);
  48. explicit TIpv6Address(const sockaddr_in6& Addr);
  49. explicit TIpv6Address(const sockaddr_in& Addr);
  50. explicit TIpv6Address(const in6_addr& addr, ui32 Scope);
  51. explicit TIpv6Address(const in_addr& addr);
  52. static TIpv6Address FromString(TStringBuf srcStr, bool& ok) noexcept;
  53. static TIpv6Address FromString(TStringBuf str) noexcept;
  54. constexpr bool IsNull() const noexcept {
  55. return Ip == 0;
  56. }
  57. constexpr bool IsValid() const noexcept {
  58. return Ip != 0 && (Type_ == Ipv6 || Type_ == Ipv4);
  59. }
  60. constexpr bool IsIpv6() const noexcept {
  61. return Type_ == Ipv6;
  62. }
  63. explicit constexpr operator bool() const noexcept {
  64. return IsValid();
  65. }
  66. constexpr bool operator ! () const noexcept {
  67. return !IsValid();
  68. }
  69. bool Isv4MappedTov6() const noexcept;
  70. TIpv6Address TryToExtractIpv4From6() const noexcept;
  71. TIpv6Address Normalized() const noexcept;
  72. TString ToString(bool* ok = nullptr) const noexcept;
  73. TString ToString(bool PrintScopeId, bool* ok = nullptr) const noexcept;
  74. void ToSockaddrAndSocklen(sockaddr_in& sockAddrIPv4,
  75. sockaddr_in6& sockAddrIPv6, // in
  76. const sockaddr*& sockAddrPtr,
  77. socklen_t& sockAddrSize,
  78. ui16 Port) const; // out
  79. void ToInAddr(in_addr& Addr4) const;
  80. void ToIn6Addr(in6_addr& Addr6) const;
  81. // int SocketFamily() const;
  82. constexpr bool operator<(const TIpv6Address& other) const noexcept {
  83. if (Type_ != other.Type_)
  84. return Type_ > other.Type_;
  85. else
  86. return Ip < other.Ip;
  87. }
  88. constexpr bool operator>(const TIpv6Address& other) const noexcept {
  89. if (Type_ != other.Type_)
  90. return Type_ < other.Type_;
  91. else
  92. return Ip > other.Ip;
  93. }
  94. constexpr bool operator==(const TIpv6Address& other) const noexcept {
  95. return Type_ == other.Type_ && Ip == other.Ip;
  96. }
  97. constexpr bool operator!=(const TIpv6Address& other) const noexcept {
  98. return Type_ != other.Type_ || Ip != other.Ip;
  99. }
  100. constexpr bool operator<=(const TIpv6Address& other) const noexcept {
  101. return !(*this > other);
  102. }
  103. constexpr bool operator>=(const TIpv6Address& other) const noexcept {
  104. return !(*this < other);
  105. }
  106. constexpr operator ui128() const noexcept {
  107. return Ip;
  108. }
  109. constexpr TIpType Type() const noexcept {
  110. return Type_;
  111. }
  112. void SetScopeId(ui32 New) noexcept {
  113. ScopeId_ = New;
  114. }
  115. constexpr ui32 ScopeId() const noexcept {
  116. return ScopeId_;
  117. }
  118. void Save(IOutputStream* out) const;
  119. void Load(IInputStream* in);
  120. private:
  121. void InitFrom(const in6_addr& addr);
  122. void InitFrom(const in_addr& addr);
  123. void InitFrom(const sockaddr_in6& Addr);
  124. void InitFrom(const sockaddr_in& Addr);
  125. ui128 Ip{};
  126. TIpType Type_ = LAST;
  127. ui32 ScopeId_ = 0;
  128. };
  129. IOutputStream& operator<<(IOutputStream& Out, const TIpv6Address::TIpType Type) noexcept;
  130. IOutputStream& operator<<(IOutputStream& Out, const TIpv6Address& ipv6Address) noexcept;
  131. constexpr TIpv6Address Get127001() noexcept {
  132. return {127, 0, 0, 1};
  133. }
  134. constexpr TIpv6Address Get1() noexcept {
  135. return {1, TIpv6Address::Ipv6};
  136. }
  137. struct THostAddressAndPortPrintOptions {
  138. bool PrintScopeId = false;
  139. };
  140. struct THostAddressAndPort {
  141. constexpr THostAddressAndPort() noexcept = default;
  142. constexpr THostAddressAndPort(const TIpv6Address& i, TIpPort p) noexcept {
  143. Ip = i;
  144. Port = p;
  145. }
  146. constexpr bool operator==(const THostAddressAndPort& Other) const noexcept {
  147. return Ip == Other.Ip && Port == Other.Port;
  148. }
  149. constexpr bool operator!=(const THostAddressAndPort& Other) const noexcept {
  150. return !(*this == Other);
  151. }
  152. constexpr bool IsValid() const noexcept {
  153. return Ip.IsValid() && Port != 0;
  154. }
  155. TString ToString() const noexcept;
  156. TString ToString(THostAddressAndPortPrintOptions options) const noexcept;
  157. TIpv6Address Ip {};
  158. TIpPort Port {0};
  159. };
  160. ///
  161. /// Returns
  162. /// 1. either valid THostAddressAndPort
  163. /// 2. or TString with hostname (which you should resolve) and TIpPort with port
  164. /// 3. or error, if Ok == false
  165. ///
  166. /// Supported RawStrs are
  167. /// 1.2.3.4 // port wil be equal to DefaultPort
  168. /// 1.2.3.4:80
  169. /// [2001::7348] // port wil be equal to DefaultPort
  170. /// 2001::7348 // port wil be equal to DefaultPort
  171. /// [2001::7348]:80
  172. ///
  173. std::tuple<THostAddressAndPort, TString, TIpPort> ParseHostAndMayBePortFromString(const TStringBuf RawStr,
  174. TIpPort DefaultPort,
  175. bool& Ok) noexcept;
  176. using TIpv6AddressesSet = THashSet<TIpv6Address>;
  177. template <>
  178. struct THash<TIpv6Address> {
  179. inline size_t operator()(const TIpv6Address& ip) const {
  180. const ui128& Tmp = static_cast<ui128>(ip);
  181. return CombineHashes(THash<ui128>()(Tmp), THash<ui8>()(static_cast<ui8>(ip.Type())));
  182. }
  183. };
  184. template <>
  185. struct THash<THostAddressAndPort> {
  186. inline size_t operator()(const THostAddressAndPort& IpAndPort) const {
  187. return CombineHashes(THash<TIpv6Address>()(IpAndPort.Ip), THash<TIpPort>()(IpAndPort.Port));
  188. }
  189. };
  190. namespace std {
  191. template <>
  192. struct hash<TIpv6Address> {
  193. std::size_t operator()(const TIpv6Address& Ip) const noexcept {
  194. return THash<TIpv6Address>()(Ip);
  195. }
  196. };
  197. }
  198. NAddr::IRemoteAddr* ToIRemoteAddr(const TIpv6Address& Address, TIpPort Port);
  199. // template <>
  200. // class TSerializer<TIpv6Address> {
  201. // public:
  202. // static void Save(IOutputStream *out, const TIpv6Address &ip);
  203. // static void Load(IInputStream *in, TIpv6Address &ip);
  204. //};