Endpoint.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2025-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #ifndef ZT_ENDPOINT_HPP
  14. #define ZT_ENDPOINT_HPP
  15. #include "Constants.hpp"
  16. #include "InetAddress.hpp"
  17. #include "Address.hpp"
  18. #include "Utils.hpp"
  19. #include "TriviallyCopyable.hpp"
  20. #include "Fingerprint.hpp"
  21. #include "MAC.hpp"
  22. #define ZT_ENDPOINT_STRING_SIZE_MAX 256
  23. #define ZT_ENDPOINT_MARSHAL_SIZE_MAX 192
  24. namespace ZeroTier {
  25. static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > ZT_INETADDRESS_MARSHAL_SIZE_MAX, "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
  26. static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(ZT_Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
  27. static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(InetAddress), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
  28. static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(MAC), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
  29. static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
  30. /**
  31. * Endpoint variant specifying some form of network endpoint.
  32. *
  33. * This is sort of a superset of InetAddress and for the standard UDP
  34. * protocol marshals and unmarshals to a compatible format. This makes
  35. * it backward compatible with older node versions' protocol fields
  36. * where InetAddress was used as long as only the UDP type is exchanged
  37. * with those nodes.
  38. */
  39. class Endpoint : public ZT_Endpoint, public TriviallyCopyable
  40. {
  41. public:
  42. /**
  43. * Create a NIL/empty endpoint
  44. */
  45. ZT_INLINE Endpoint() noexcept
  46. { memoryZero(this); }
  47. ZT_INLINE Endpoint(const ZT_Endpoint &ep) noexcept
  48. { Utils::copy< sizeof(ZT_Endpoint) >((ZT_Endpoint *)this, &ep); }
  49. /**
  50. * Create an endpoint for a type that uses an IP
  51. *
  52. * @param a IP/port
  53. * @param et Endpoint type (default: IP_UDP)
  54. */
  55. ZT_INLINE Endpoint(const InetAddress &inaddr, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_IP_UDP) noexcept
  56. {
  57. if (inaddr) {
  58. this->type = et;
  59. Utils::copy< sizeof(struct sockaddr_storage) >(&(this->value.ss), &(inaddr.as.ss));
  60. } else {
  61. memoryZero(this);
  62. }
  63. }
  64. /**
  65. * Create an endpoint for ZeroTier relaying (ZEROTIER type)
  66. *
  67. * @param zt_ ZeroTier identity fingerprint
  68. */
  69. ZT_INLINE Endpoint(const Fingerprint &zt_) noexcept
  70. {
  71. if (zt_) {
  72. this->type = ZT_ENDPOINT_TYPE_ZEROTIER;
  73. this->value.fp = zt_;
  74. } else {
  75. memoryZero(this);
  76. }
  77. }
  78. /**
  79. * Create an endpoint for a type that uses a MAC address
  80. *
  81. * @param eth_ Ethernet address
  82. * @param et Endpoint type (default: ETHERNET)
  83. */
  84. ZT_INLINE Endpoint(const MAC &eth_, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_ETHERNET) noexcept
  85. {
  86. if (eth_) {
  87. this->type = et;
  88. this->value.mac = eth_.toInt();
  89. } else {
  90. memoryZero(this);
  91. }
  92. }
  93. /**
  94. * @return True if endpoint type isn't NIL
  95. */
  96. ZT_INLINE operator bool() const noexcept
  97. { return this->type != ZT_ENDPOINT_TYPE_NIL; }
  98. /**
  99. * @return True if this endpoint type has an InetAddress address type and thus ip() is valid
  100. */
  101. ZT_INLINE bool isInetAddr() const noexcept
  102. {
  103. switch (this->type) {
  104. case ZT_ENDPOINT_TYPE_IP:
  105. case ZT_ENDPOINT_TYPE_IP_UDP:
  106. case ZT_ENDPOINT_TYPE_IP_TCP:
  107. case ZT_ENDPOINT_TYPE_IP_HTTP:
  108. return true;
  109. default:
  110. return false;
  111. }
  112. }
  113. /**
  114. * Check whether this endpoint's address is the same as another.
  115. *
  116. * Right now this checks whether IPs are equal if both are IP based endpoints.
  117. * Otherwise it checks for simple equality.
  118. *
  119. * @param ep Endpoint to check
  120. * @return True if endpoints seem to refer to the same address/host
  121. */
  122. ZT_INLINE bool isSameAddress(const Endpoint &ep) const noexcept
  123. {
  124. switch (this->type) {
  125. case ZT_ENDPOINT_TYPE_IP:
  126. case ZT_ENDPOINT_TYPE_IP_UDP:
  127. case ZT_ENDPOINT_TYPE_IP_TCP:
  128. case ZT_ENDPOINT_TYPE_IP_HTTP:
  129. switch (ep.type) {
  130. case ZT_ENDPOINT_TYPE_IP:
  131. case ZT_ENDPOINT_TYPE_IP_UDP:
  132. case ZT_ENDPOINT_TYPE_IP_TCP:
  133. case ZT_ENDPOINT_TYPE_IP_HTTP:
  134. return ip().ipsEqual(ep.ip());
  135. default:
  136. break;
  137. }
  138. break;
  139. default:
  140. break;
  141. }
  142. return (*this) == ep;
  143. }
  144. /**
  145. * Get InetAddress if this type uses IPv4 or IPv6 addresses (undefined otherwise)
  146. *
  147. * @return InetAddress instance
  148. */
  149. ZT_INLINE const InetAddress &ip() const noexcept
  150. { return asInetAddress(this->value.ss); }
  151. /**
  152. * Get MAC if this is an Ethernet, WiFi direct, or Bluetooth type (undefined otherwise)
  153. *
  154. * @return Ethernet MAC
  155. */
  156. ZT_INLINE MAC eth() const noexcept
  157. { return MAC(this->value.mac); }
  158. /**
  159. * Get fingerprint if this is a ZeroTier endpoint type (undefined otherwise)
  160. *
  161. * @return ZeroTier fingerprint
  162. */
  163. ZT_INLINE Fingerprint zt() const noexcept
  164. { return Fingerprint(this->value.fp); }
  165. ZT_INLINE unsigned long hashCode() const noexcept
  166. {
  167. switch (this->type) {
  168. default:
  169. return 1;
  170. case ZT_ENDPOINT_TYPE_ZEROTIER:
  171. return (unsigned long)this->value.fp.address;
  172. case ZT_ENDPOINT_TYPE_ETHERNET:
  173. case ZT_ENDPOINT_TYPE_WIFI_DIRECT:
  174. case ZT_ENDPOINT_TYPE_BLUETOOTH:
  175. return (unsigned long)Utils::hash64(this->value.mac);
  176. case ZT_ENDPOINT_TYPE_IP:
  177. case ZT_ENDPOINT_TYPE_IP_UDP:
  178. case ZT_ENDPOINT_TYPE_IP_TCP:
  179. case ZT_ENDPOINT_TYPE_IP_HTTP:
  180. return ip().hashCode();
  181. }
  182. }
  183. char *toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept;
  184. ZT_INLINE String toString() const
  185. {
  186. char tmp[ZT_ENDPOINT_STRING_SIZE_MAX];
  187. return String(toString(tmp));
  188. }
  189. bool fromString(const char *s) noexcept;
  190. static constexpr int marshalSizeMax() noexcept
  191. { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
  192. int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept;
  193. int unmarshal(const uint8_t *restrict data, int len) noexcept;
  194. bool operator==(const Endpoint &ep) const noexcept;
  195. ZT_INLINE bool operator!=(const Endpoint &ep) const noexcept
  196. { return !((*this) == ep); }
  197. bool operator<(const Endpoint &ep) const noexcept;
  198. ZT_INLINE bool operator>(const Endpoint &ep) const noexcept
  199. { return (ep < *this); }
  200. ZT_INLINE bool operator<=(const Endpoint &ep) const noexcept
  201. { return !(ep < *this); }
  202. ZT_INLINE bool operator>=(const Endpoint &ep) const noexcept
  203. { return !(*this < ep); }
  204. };
  205. static_assert(sizeof(Endpoint) == sizeof(ZT_Endpoint), "size mismatch");
  206. } // namespace ZeroTier
  207. #endif