Multicaster.hpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (c)2019 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: 2023-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_MULTICASTER_HPP
  14. #define ZT_MULTICASTER_HPP
  15. #include <stdint.h>
  16. #include <string.h>
  17. #include <map>
  18. #include <vector>
  19. #include "Constants.hpp"
  20. #include "Hashtable.hpp"
  21. #include "Address.hpp"
  22. #include "MAC.hpp"
  23. #include "MulticastGroup.hpp"
  24. #include "Utils.hpp"
  25. #include "Mutex.hpp"
  26. #include "SharedPtr.hpp"
  27. #include "Packet.hpp"
  28. // Size in bits -- this is pretty close to the maximum allowed by the protocol
  29. #define ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS 16384
  30. namespace ZeroTier {
  31. class RuntimeEnvironment;
  32. class CertificateOfMembership;
  33. class Packet;
  34. class Network;
  35. /**
  36. * Multicast database and outbound multicast logic
  37. */
  38. class Multicaster
  39. {
  40. public:
  41. Multicaster(const RuntimeEnvironment *renv);
  42. ~Multicaster();
  43. /**
  44. * Add or update a member in a multicast group
  45. *
  46. * @param now Current time
  47. * @param nwid Network ID
  48. * @param mg Multicast group
  49. * @param member New member address
  50. */
  51. ZT_ALWAYS_INLINE void add(const int64_t now,const uint64_t nwid,const MulticastGroup &mg,const Address &member)
  52. {
  53. Mutex::Lock l(_groups_l);
  54. _groups[_K(nwid,mg)].set(member,now);
  55. }
  56. /**
  57. * Add multiple addresses from a binary array of 5-byte address fields
  58. *
  59. * It's up to the caller to check bounds on the array before calling this.
  60. *
  61. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  62. * @param now Current time
  63. * @param nwid Network ID
  64. * @param mg Multicast group
  65. * @param addresses Raw binary addresses in big-endian format, as a series of 5-byte fields
  66. * @param count Number of addresses
  67. * @param totalKnown Total number of known addresses as reported by peer
  68. */
  69. ZT_ALWAYS_INLINE void addMultiple(const int64_t now,const uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,const unsigned int totalKnown)
  70. {
  71. Mutex::Lock l(_groups_l);
  72. const uint8_t *a = (const uint8_t *)addresses;
  73. Hashtable< Address,int64_t > &members = _groups[_K(nwid,mg)];
  74. while (count--) {
  75. members.set(Address(a,ZT_ADDRESS_LENGTH),now);
  76. a += ZT_ADDRESS_LENGTH;
  77. }
  78. }
  79. /**
  80. * Remove a multicast group member (if present)
  81. *
  82. * @param nwid Network ID
  83. * @param mg Multicast group
  84. * @param member Member to unsubscribe
  85. */
  86. ZT_ALWAYS_INLINE void remove(const uint64_t nwid,const MulticastGroup &mg,const Address &member)
  87. {
  88. Mutex::Lock l(_groups_l);
  89. const _K gk(nwid,mg);
  90. Hashtable< Address,int64_t > *const members = _groups.get(gk);
  91. if (members) {
  92. members->erase(member);
  93. if (members->empty())
  94. _groups.erase(gk);
  95. }
  96. }
  97. /**
  98. * Iterate over members of a multicast group until function returns false
  99. *
  100. * Iteration order is in inverse order of most recent receipt of a LIKE
  101. * for a given membership.
  102. *
  103. * @param nwid Network ID
  104. * @param mg Multicast group
  105. * @param func f(Address)
  106. * @return Total number of known members (regardless of when function aborted)
  107. */
  108. template<typename F>
  109. ZT_ALWAYS_INLINE unsigned long eachMember(const uint64_t nwid,const MulticastGroup &mg,F func) const
  110. {
  111. std::vector< std::pair<int64_t,Address> > sortedByTime;
  112. Mutex::Lock l(_groups_l);
  113. _getMembersByTime(nwid,mg,sortedByTime);
  114. std::sort(sortedByTime.begin(),sortedByTime.end());
  115. for(std::vector< std::pair<int64_t,Address> >::const_reverse_iterator i(sortedByTime.begin());i!=sortedByTime.end();++i) {
  116. if (!func(i->second))
  117. break;
  118. }
  119. return sortedByTime.size();
  120. }
  121. /**
  122. * Send a multicast
  123. *
  124. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  125. * @param now Current time
  126. * @param network Network
  127. * @param mg Multicast group
  128. * @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
  129. * @param etherType Ethernet frame type
  130. * @param existingBloomMultiplier Existing bloom filter multiplier or 0 if none
  131. * @param existingBloom Existing bloom filter or NULL if none
  132. * @param data Packet data
  133. * @param len Length of packet data
  134. */
  135. void send(
  136. void *tPtr,
  137. int64_t now,
  138. const SharedPtr<Network> &network,
  139. const MulticastGroup &mg,
  140. const MAC &src,
  141. unsigned int etherType,
  142. const unsigned int existingBloomMultiplier,
  143. const uint8_t existingBloom[ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS / 8],
  144. const void *const data,
  145. unsigned int len);
  146. /**
  147. * Clean up database
  148. *
  149. * @param RR Runtime environment
  150. * @param now Current time
  151. */
  152. void clean(int64_t now);
  153. private:
  154. ZT_ALWAYS_INLINE void _getMembersByTime(const uint64_t nwid,const MulticastGroup &mg,std::vector< std::pair<int64_t,Address> > &byTime)
  155. {
  156. // assumes _groups_l is locked
  157. const _K gk(nwid,mg);
  158. const Hashtable< Address,int64_t > *const members = _groups.get(gk);
  159. if (members) {
  160. byTime.reserve(members->size());
  161. {
  162. Hashtable< Address,int64_t >::Iterator mi(*const_cast<Hashtable< Address,int64_t > *>(members));
  163. Address *mik = nullptr;
  164. int64_t *miv = nullptr;
  165. while (mi.next(mik,miv))
  166. byTime.push_back(std::pair<int64_t,Address>(*miv,*mik));
  167. }
  168. }
  169. }
  170. struct _K
  171. {
  172. uint64_t nwid;
  173. MulticastGroup mg;
  174. ZT_ALWAYS_INLINE _K() : nwid(0),mg() {}
  175. ZT_ALWAYS_INLINE _K(const uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {}
  176. ZT_ALWAYS_INLINE bool operator==(const _K &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); }
  177. ZT_ALWAYS_INLINE bool operator!=(const _K &k) const { return ((nwid != k.nwid)||(mg != k.mg)); }
  178. ZT_ALWAYS_INLINE unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); }
  179. };
  180. /*
  181. * Multicast frame:
  182. * <[8] 64-bit network ID>
  183. * <[1] flags>
  184. * [<[...] network certificate of membership (DEPRECATED)>]
  185. * [<[4] 32-bit implicit gather limit (DEPRECATED)>]
  186. * [<[5] ZeroTier address of originating sender (including w/0x08)>]
  187. * [<[2] 16-bit bloom filter multiplier>]
  188. * [<[2] 16-bit length of propagation bloom filter in bytes]
  189. * [<[...] propagation bloom filter>]
  190. * [<[6] source MAC>]
  191. * <[6] destination MAC (multicast address)>
  192. * <[4] 32-bit multicast ADI (multicast address extension)>
  193. * <[2] 16-bit ethertype>
  194. * <[...] ethernet payload>
  195. * [<[2] 16-bit length of signature>]
  196. * [<[...] signature (algorithm depends on sender identity)>]
  197. */
  198. struct _OM
  199. {
  200. uint64_t nwid;
  201. MAC src;
  202. MulticastGroup mg;
  203. unsigned int etherType;
  204. unsigned int dataSize;
  205. unsigned int bloomFilterMultiplier;
  206. uint8_t bloomFilter[ZT_MULTICAST_BLOOM_FILTER_SIZE_BITS / 8];
  207. uint8_t data[ZT_MAX_MTU];
  208. Mutex lock;
  209. };
  210. const RuntimeEnvironment *const RR;
  211. _OM _txQueue[ZT_TX_QUEUE_SIZE];
  212. unsigned int _txQueuePtr;
  213. Mutex _txQueue_l;
  214. Hashtable< _K,Hashtable< Address,int64_t > > _groups;
  215. Mutex _groups_l;
  216. };
  217. } // namespace ZeroTier
  218. #endif