Endpoint.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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_MARSHAL_SIZE_MAX 128
  23. static_assert(ZT_ENDPOINT_MARSHAL_SIZE_MAX > (ZT_INETADDRESS_MARSHAL_SIZE_MAX + 1),"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
  24. static_assert(ZT_ENDPOINT_MARSHAL_SIZE_MAX > (sizeof(ZT_Fingerprint) + 1),"ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
  25. namespace ZeroTier {
  26. /**
  27. * Endpoint variant specifying some form of network endpoint.
  28. *
  29. * This is sort of a superset of InetAddress and for the standard UDP
  30. * protocol marshals and unmarshals to a compatible format. This makes
  31. * it backward compatible with older node versions' protocol fields
  32. * where InetAddress was used as long as only the UDP type is exchanged
  33. * with those nodes.
  34. */
  35. class Endpoint : public TriviallyCopyable
  36. {
  37. public:
  38. /**
  39. * Endpoint type (defined in the API)
  40. */
  41. typedef ZT_EndpointType Type;
  42. /**
  43. * Create a NIL/empty endpoint
  44. */
  45. ZT_INLINE Endpoint() noexcept { memoryZero(this); }
  46. /**
  47. * Create an endpoint for a type that uses an IP
  48. *
  49. * @param a IP/port
  50. * @param et Endpoint type (default: IP_UDP)
  51. */
  52. ZT_INLINE Endpoint(const InetAddress &a,const Type et = ZT_ENDPOINT_TYPE_IP_UDP) noexcept
  53. {
  54. if (a) {
  55. Utils::copy<sizeof(InetAddress)>(m_value,&a);
  56. m_value[ZT_ENDPOINT_MARSHAL_SIZE_MAX-1] = (uint8_t)et;
  57. } else {
  58. memoryZero(this);
  59. }
  60. }
  61. /**
  62. * Create an endpoint for ZeroTier relaying (ZEROTIER type)
  63. *
  64. * @param zt_ ZeroTier identity fingerprint
  65. */
  66. ZT_INLINE Endpoint(const Fingerprint &zt_) noexcept
  67. {
  68. if (zt_) {
  69. Utils::copy<sizeof(Fingerprint)>(m_value,&zt_);
  70. m_value[ZT_ENDPOINT_MARSHAL_SIZE_MAX-1] = (uint8_t)ZT_ENDPOINT_TYPE_ZEROTIER;
  71. } else {
  72. memoryZero(this);
  73. }
  74. }
  75. /**
  76. * Create an endpoint for a type that uses a MAC address
  77. *
  78. * @param eth_ Ethernet address
  79. * @param et Endpoint type (default: ETHERNET)
  80. */
  81. ZT_INLINE Endpoint(const MAC &eth_,const Type et = ZT_ENDPOINT_TYPE_ETHERNET) noexcept
  82. {
  83. if (eth_) {
  84. Utils::copy<sizeof(MAC)>(m_value,&eth_);
  85. m_value[ZT_ENDPOINT_MARSHAL_SIZE_MAX-1] = (uint8_t)et;
  86. } else {
  87. memoryZero(this);
  88. }
  89. }
  90. /**
  91. * @return Endpoint type
  92. */
  93. ZT_INLINE Type type() const noexcept { return (Type)m_value[ZT_ENDPOINT_MARSHAL_SIZE_MAX-1]; }
  94. /**
  95. * @return True if endpoint type isn't NIL
  96. */
  97. ZT_INLINE operator bool() const noexcept { return (m_value[ZT_ENDPOINT_MARSHAL_SIZE_MAX-1] != (uint8_t)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 { return *reinterpret_cast<const InetAddress *>(m_value); }
  119. /**
  120. * Get MAC if this is an Ethernet, WiFi direct, or Bluetooth type (undefined otherwise)
  121. *
  122. * @return Ethernet MAC
  123. */
  124. ZT_INLINE const MAC &eth() const noexcept { return *reinterpret_cast<const MAC *>(m_value); }
  125. /**
  126. * Get fingerprint if this is a ZeroTier endpoint type (undefined otherwise)
  127. *
  128. * @return ZeroTier fingerprint
  129. */
  130. ZT_INLINE const Fingerprint &zt() const noexcept { return *reinterpret_cast<const Fingerprint *>(m_value); }
  131. static constexpr int marshalSizeMax() noexcept { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
  132. int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept;
  133. int unmarshal(const uint8_t *restrict data,int len) noexcept;
  134. private:
  135. uint8_t m_value[ZT_ENDPOINT_MARSHAL_SIZE_MAX]; // the last byte in this buffer is the type
  136. };
  137. } // namespace ZeroTier
  138. #endif