Locator.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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_LOCATOR_HPP
  14. #define ZT_LOCATOR_HPP
  15. #include "Constants.hpp"
  16. #include "Endpoint.hpp"
  17. #include "Identity.hpp"
  18. #include "TriviallyCopyable.hpp"
  19. #include "SharedPtr.hpp"
  20. #include "FCV.hpp"
  21. #include "Containers.hpp"
  22. #include "Dictionary.hpp"
  23. /**
  24. * Maximum size of endpoint attributes dictionary plus one byte for size.
  25. *
  26. * This cannot be (easily) changed.
  27. */
  28. #define ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE 256
  29. /**
  30. * Maximum number of endpoints, which can be increased.
  31. */
  32. #define ZT_LOCATOR_MAX_ENDPOINTS 16
  33. #define ZT_LOCATOR_MARSHAL_SIZE_MAX (8 + ZT_FINGERPRINT_MARSHAL_SIZE + 2 + (ZT_LOCATOR_MAX_ENDPOINTS * (ZT_ENDPOINT_MARSHAL_SIZE_MAX + ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE)) + 2 + 2 + ZT_SIGNATURE_BUFFER_SIZE)
  34. /**
  35. * Maximum size of a string format Locator (this is way larger than needed)
  36. */
  37. #define ZT_LOCATOR_STRING_SIZE_MAX 16384
  38. namespace ZeroTier {
  39. /**
  40. * Signed information about a node's location on the network
  41. *
  42. * A locator contains long-lived endpoints for a node such as IP/port pairs,
  43. * URLs, or other nodes, and is signed by the node it describes.
  44. */
  45. class Locator
  46. {
  47. friend class SharedPtr< Locator >;
  48. friend class SharedPtr< const Locator >;
  49. public:
  50. /**
  51. * Attributes of an endpoint in this locator
  52. *
  53. * This is specified for future use, but there are currently no attributes
  54. * defined. A Dictionary is used for serialization for extensibility.
  55. */
  56. struct EndpointAttributes
  57. {
  58. friend class SharedPtr< Locator::EndpointAttributes >;
  59. friend class SharedPtr< const Locator::EndpointAttributes >;
  60. /**
  61. * Default endpoint attributes
  62. */
  63. static const SharedPtr< const Locator::EndpointAttributes > DEFAULT;
  64. /**
  65. * Raw attributes data in the form of a dictionary prefixed by its size.
  66. *
  67. * The maximum size of attributes is 255, which is more than enough for
  68. * tiny things like bandwidth and priority.
  69. */
  70. uint8_t data[ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE];
  71. ZT_INLINE EndpointAttributes() noexcept
  72. { Utils::zero< ZT_LOCATOR_MAX_ENDPOINT_ATTRIBUTES_SIZE >(data); }
  73. ZT_INLINE bool operator==(const EndpointAttributes &a) const noexcept
  74. { return ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) == 0)); }
  75. ZT_INLINE bool operator<(const EndpointAttributes &a) const noexcept
  76. { return ((data[0] < a.data[0]) || ((data[0] == a.data[0]) && (memcmp(data, a.data, data[0]) < 0))); }
  77. ZT_INLINE bool operator!=(const EndpointAttributes &a) const noexcept
  78. { return !(*this == a); }
  79. ZT_INLINE bool operator>(const EndpointAttributes &a) const noexcept
  80. { return (a < *this); }
  81. ZT_INLINE bool operator<=(const EndpointAttributes &a) const noexcept
  82. { return !(a < *this); }
  83. ZT_INLINE bool operator>=(const EndpointAttributes &a) const noexcept
  84. { return !(*this < a); }
  85. private:
  86. std::atomic< int > __refCount;
  87. };
  88. ZT_INLINE Locator() noexcept:
  89. m_ts(0)
  90. {}
  91. explicit Locator(const char *const str) noexcept;
  92. ZT_INLINE Locator(const Locator &loc) noexcept:
  93. m_ts(loc.m_ts),
  94. m_signer(loc.m_signer),
  95. m_endpoints(loc.m_endpoints),
  96. m_signature(loc.m_signature),
  97. __refCount(0)
  98. {}
  99. /**
  100. * @return Timestamp (a.k.a. revision number) set by Location signer
  101. */
  102. ZT_INLINE int64_t timestamp() const noexcept
  103. { return m_ts; }
  104. /**
  105. * @return Fingerprint of identity that signed this locator
  106. */
  107. ZT_INLINE const Fingerprint &signer() const noexcept
  108. { return m_signer; }
  109. /**
  110. * @return Endpoints specified in locator
  111. */
  112. ZT_INLINE const Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > > &endpoints() const noexcept
  113. { return m_endpoints; }
  114. /**
  115. * @return Signature data
  116. */
  117. ZT_INLINE const FCV< uint8_t, ZT_SIGNATURE_BUFFER_SIZE > &signature() const noexcept
  118. { return m_signature; }
  119. /**
  120. * Add an endpoint to this locator
  121. *
  122. * This doesn't check for the presence of the endpoint, so take
  123. * care not to add duplicates.
  124. *
  125. * @param ep Endpoint to add
  126. * @param a Endpoint attributes or NULL to use default
  127. * @return True if endpoint was added (or already present), false if locator is full
  128. */
  129. bool add(const Endpoint &ep, const SharedPtr< const EndpointAttributes > &a);
  130. /**
  131. * Sign this locator
  132. *
  133. * This sets timestamp, sorts endpoints so that the same set of endpoints
  134. * will always produce the same locator, and signs.
  135. *
  136. * @param id Identity that includes private key
  137. * @return True if signature successful
  138. */
  139. bool sign(int64_t ts, const Identity &id) noexcept;
  140. /**
  141. * Verify this Locator's validity and signature
  142. *
  143. * @param id Identity corresponding to hash
  144. * @return True if valid and signature checks out
  145. */
  146. bool verify(const Identity &id) const noexcept;
  147. /**
  148. * Convert this locator to a string
  149. *
  150. * @param s String buffer
  151. * @return Pointer to buffer
  152. */
  153. char *toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept;
  154. ZT_INLINE String toString() const
  155. {
  156. char tmp[ZT_LOCATOR_STRING_SIZE_MAX];
  157. return String(toString(tmp));
  158. }
  159. /**
  160. * Decode a string format locator
  161. *
  162. * @param s Locator from toString()
  163. * @return True if format was valid
  164. */
  165. bool fromString(const char *s) noexcept;
  166. explicit ZT_INLINE operator bool() const noexcept
  167. { return m_ts > 0; }
  168. static constexpr int marshalSizeMax() noexcept
  169. { return ZT_LOCATOR_MARSHAL_SIZE_MAX; }
  170. int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], bool excludeSignature = false) const noexcept;
  171. int unmarshal(const uint8_t *data, int len) noexcept;
  172. ZT_INLINE bool operator==(const Locator &l) const noexcept
  173. {
  174. const unsigned long es = (unsigned long)m_endpoints.size();
  175. if ((m_ts == l.m_ts) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size()) && (m_signature == l.m_signature)) {
  176. for(unsigned long i=0;i<es;++i) {
  177. if (m_endpoints[i].first != l.m_endpoints[i].first)
  178. return false;
  179. if (!m_endpoints[i].second) {
  180. if (l.m_endpoints[i].second)
  181. return false;
  182. } else {
  183. if ((!l.m_endpoints[i].second) || (*(m_endpoints[i].second) != *(l.m_endpoints[i].second)))
  184. return false;
  185. }
  186. }
  187. return true;
  188. }
  189. return false;
  190. }
  191. ZT_INLINE bool operator!=(const Locator &l) const noexcept
  192. { return !(*this == l); }
  193. private:
  194. void m_sortEndpoints() noexcept;
  195. int64_t m_ts;
  196. Fingerprint m_signer;
  197. Vector< std::pair< Endpoint, SharedPtr< const EndpointAttributes > > > m_endpoints;
  198. FCV< uint8_t, ZT_SIGNATURE_BUFFER_SIZE > m_signature;
  199. std::atomic< int > __refCount;
  200. };
  201. } // namespace ZeroTier
  202. #endif