Endpoint.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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 <cstdio>
  16. #include <cstdlib>
  17. #include <cstdint>
  18. #include <cstring>
  19. #include "Constants.hpp"
  20. #include "InetAddress.hpp"
  21. #include "Address.hpp"
  22. #include "Utils.hpp"
  23. // max name size + type byte + port (for DNS name/port) + 3x 16-bit coordinate for location
  24. #define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+1+2+2+2+2)
  25. namespace ZeroTier {
  26. /**
  27. * Endpoint variant specifying some form of network endpoint
  28. *
  29. * This data structure supports a number of types that are not yet actually used:
  30. * DNSNAME, URL, and ETHERNET. These are present to reserve them for future use.
  31. */
  32. class Endpoint
  33. {
  34. public:
  35. enum Type
  36. {
  37. NIL = 0, // NIL value
  38. INETADDR = 1, // InetAddress (v4 or v6)
  39. DNSNAME = 2, // DNS name and port that resolves to InetAddress
  40. ZEROTIER = 3, // ZeroTier Address (for relaying and meshy behavior)
  41. URL = 4, // URL for http/https/ws/etc. (not implemented yet)
  42. ETHERNET = 5, // 48-bit LAN-local Ethernet address
  43. UNRECOGNIZED = 255 // Unrecognized endpoint type encountered in stream
  44. };
  45. ZT_ALWAYS_INLINE Endpoint()
  46. {
  47. memset(reinterpret_cast<void *>(this),0,sizeof(Endpoint));
  48. }
  49. ZT_ALWAYS_INLINE Endpoint(const Endpoint &ep)
  50. {
  51. memcpy(reinterpret_cast<void *>(this),&ep,sizeof(Endpoint));
  52. }
  53. explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) :
  54. _t(INETADDR)
  55. {
  56. _v.sa = sa;
  57. }
  58. ZT_ALWAYS_INLINE Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) :
  59. _t(ZEROTIER)
  60. {
  61. _v.zt.a = zt.toInt();
  62. memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE);
  63. }
  64. ZT_ALWAYS_INLINE Endpoint(const char *name,const int port) :
  65. _t(DNSNAME)
  66. {
  67. _v.dns.port = port;
  68. Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name);
  69. }
  70. explicit ZT_ALWAYS_INLINE Endpoint(const char *url) :
  71. _t(URL)
  72. {
  73. Utils::scopy(_v.url,sizeof(_v.url),url);
  74. }
  75. ZT_ALWAYS_INLINE Endpoint &operator=(const Endpoint &ep)
  76. {
  77. memcpy(reinterpret_cast<void *>(this),&ep,sizeof(Endpoint));
  78. return *this;
  79. }
  80. ZT_ALWAYS_INLINE Endpoint &operator=(const InetAddress &sa)
  81. {
  82. _t = INETADDR;
  83. _v.sa = sa;
  84. return *this;
  85. }
  86. /**
  87. * @return InetAddress or NIL if not of this type
  88. */
  89. ZT_ALWAYS_INLINE const InetAddress &inetAddr() const { return (_t == INETADDR) ? *reinterpret_cast<const InetAddress *>(&_v.sa) : InetAddress::NIL; }
  90. /**
  91. * @return DNS name or empty string if not of this type
  92. */
  93. ZT_ALWAYS_INLINE const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : ""; }
  94. /**
  95. * @return Port associated with DNS name or -1 if not of this type
  96. */
  97. ZT_ALWAYS_INLINE int dnsPort() const { return (_t == DNSNAME) ? _v.dns.port : -1; }
  98. /**
  99. * @return ZeroTier address or NIL if not of this type
  100. */
  101. ZT_ALWAYS_INLINE Address ztAddress() const { return Address((_t == ZEROTIER) ? _v.zt.a : (uint64_t)0); }
  102. /**
  103. * @return 384-bit hash of identity keys or NULL if not of this type
  104. */
  105. ZT_ALWAYS_INLINE const uint8_t *ztIdentityHash() const { return (_t == ZEROTIER) ? _v.zt.idh : nullptr; }
  106. /**
  107. * @return URL or empty string if not of this type
  108. */
  109. ZT_ALWAYS_INLINE const char *url() const { return (_t == URL) ? _v.url : ""; }
  110. /**
  111. * @return Ethernet address or NIL if not of this type
  112. */
  113. ZT_ALWAYS_INLINE MAC ethernet() const { return (_t == ETHERNET) ? MAC(_v.eth) : MAC(); }
  114. /**
  115. * @return Endpoint type or NIL if unset/empty
  116. */
  117. ZT_ALWAYS_INLINE Type type() const { return _t; }
  118. explicit ZT_ALWAYS_INLINE operator bool() const { return _t != NIL; }
  119. bool operator==(const Endpoint &ep) const;
  120. ZT_ALWAYS_INLINE bool operator!=(const Endpoint &ep) const { return (!(*this == ep)); }
  121. bool operator<(const Endpoint &ep) const;
  122. ZT_ALWAYS_INLINE bool operator>(const Endpoint &ep) const { return (ep < *this); }
  123. ZT_ALWAYS_INLINE bool operator<=(const Endpoint &ep) const { return !(ep < *this); }
  124. ZT_ALWAYS_INLINE bool operator>=(const Endpoint &ep) const { return !(*this < ep); }
  125. static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
  126. int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const;
  127. int unmarshal(const uint8_t *restrict data,const int len);
  128. private:
  129. Type _t;
  130. int _l[3]; // X,Y,Z location in kilometers from the nearest gravitational center of mass
  131. union {
  132. struct sockaddr_storage sa;
  133. ZT_PACKED_STRUCT(struct {
  134. uint16_t port;
  135. char name[ZT_ENDPOINT_MAX_NAME_SIZE];
  136. }) dns;
  137. ZT_PACKED_STRUCT(struct {
  138. uint64_t a;
  139. uint8_t idh[ZT_IDENTITY_HASH_SIZE];
  140. }) zt;
  141. char url[ZT_ENDPOINT_MAX_NAME_SIZE];
  142. uint64_t eth;
  143. } _v;
  144. };
  145. } // namespace ZeroTier
  146. #endif