Endpoint.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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: 2024-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. { *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_HTTP2:
  108. return true;
  109. default:
  110. return false;
  111. }
  112. }
  113. /**
  114. * Get InetAddress if this type uses IPv4 or IPv6 addresses (undefined otherwise)
  115. *
  116. * @return InetAddress instance
  117. */
  118. ZT_INLINE const InetAddress &ip() const noexcept
  119. { return asInetAddress(this->value.ss); }
  120. /**
  121. * Get MAC if this is an Ethernet, WiFi direct, or Bluetooth type (undefined otherwise)
  122. *
  123. * @return Ethernet MAC
  124. */
  125. ZT_INLINE MAC eth() const noexcept
  126. { return MAC(this->value.mac); }
  127. /**
  128. * Get fingerprint if this is a ZeroTier endpoint type (undefined otherwise)
  129. *
  130. * @return ZeroTier fingerprint
  131. */
  132. ZT_INLINE Fingerprint zt() const noexcept
  133. { return Fingerprint(this->value.fp); }
  134. char *toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept;
  135. ZT_INLINE String toString() const { char tmp[ZT_ENDPOINT_STRING_SIZE_MAX]; return String(toString(tmp)); }
  136. bool fromString(const char *s) noexcept;
  137. static constexpr int marshalSizeMax() noexcept
  138. { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
  139. int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept;
  140. int unmarshal(const uint8_t *restrict data, int len) noexcept;
  141. bool operator==(const Endpoint &ep) const noexcept;
  142. ZT_INLINE bool operator!=(const Endpoint &ep) const noexcept
  143. { return !((*this) == ep); }
  144. bool operator<(const Endpoint &ep) const noexcept;
  145. ZT_INLINE bool operator>(const Endpoint &ep) const noexcept
  146. { return (ep < *this); }
  147. ZT_INLINE bool operator<=(const Endpoint &ep) const noexcept
  148. { return !(ep < *this); }
  149. ZT_INLINE bool operator>=(const Endpoint &ep) const noexcept
  150. { return !(*this < ep); }
  151. };
  152. } // namespace ZeroTier
  153. #endif