Multicaster.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 "OutboundMulticast.hpp"
  25. #include "Utils.hpp"
  26. #include "Mutex.hpp"
  27. #include "SharedPtr.hpp"
  28. namespace ZeroTier {
  29. class RuntimeEnvironment;
  30. class CertificateOfMembership;
  31. class Packet;
  32. class Network;
  33. /**
  34. * Multicast database and outbound multicast handler
  35. */
  36. class Multicaster
  37. {
  38. public:
  39. Multicaster(const RuntimeEnvironment *renv);
  40. ~Multicaster();
  41. /**
  42. * Add or update a member in a multicast group
  43. *
  44. * @param now Current time
  45. * @param nwid Network ID
  46. * @param mg Multicast group
  47. * @param member New member address
  48. */
  49. void add(const int64_t now,const uint64_t nwid,const MulticastGroup &mg,const Address &member);
  50. /**
  51. * Add multiple addresses from a binary array of 5-byte address fields
  52. *
  53. * It's up to the caller to check bounds on the array before calling this.
  54. *
  55. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  56. * @param now Current time
  57. * @param nwid Network ID
  58. * @param mg Multicast group
  59. * @param addresses Raw binary addresses in big-endian format, as a series of 5-byte fields
  60. * @param count Number of addresses
  61. * @param totalKnown Total number of known addresses as reported by peer
  62. */
  63. void addMultiple(const int64_t now,const uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,const unsigned int totalKnown);
  64. /**
  65. * Remove a multicast group member (if present)
  66. *
  67. * @param nwid Network ID
  68. * @param mg Multicast group
  69. * @param member Member to unsubscribe
  70. */
  71. void remove(const uint64_t nwid,const MulticastGroup &mg,const Address &member);
  72. /**
  73. * Iterate over members of a multicast group until function returns false
  74. *
  75. * Iteration order is in inverse order of most recent receipt of a LIKE
  76. * for a given membership.
  77. *
  78. * @param nwid Network ID
  79. * @param mg Multicast group
  80. * @param func f(Address)
  81. * @return Total number of known members (regardless of when function aborted)
  82. */
  83. template<typename F>
  84. inline unsigned long eachMember(const uint64_t nwid,const MulticastGroup &mg,F func) const
  85. {
  86. std::vector< std::pair<int64_t,Address> > sortedByTime;
  87. {
  88. Mutex::Lock l(_groups_l);
  89. const Multicaster::Key gk(nwid,mg);
  90. const Hashtable< Address,int64_t > *const members = _groups.get(gk);
  91. if (members) {
  92. totalKnown = members->size();
  93. sortedByTime.reserve(totalKnown);
  94. {
  95. Hashtable< Address,int64_t >::Iterator mi(*const_cast<Hashtable< Address,int64_t > *>(members));
  96. Address *mik = nullptr;
  97. int64_t *miv = nullptr;
  98. while (mi.next(mik,miv))
  99. sortedByTime.push_back(std::pair<int64_t,Address>(*miv,*mik));
  100. }
  101. std::sort(sortedByTime.begin(),sortedByTime.end());
  102. }
  103. }
  104. for(std::vector< std::pair<int64_t,Address> >::const_reverse_iterator i(sortedByTime.begin());i!=sortedByTime.end();++i) {
  105. if (!func(i->second))
  106. break;
  107. }
  108. return sortedByTime.size();
  109. }
  110. /**
  111. * Send a multicast
  112. *
  113. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  114. * @param now Current time
  115. * @param network Network
  116. * @param origin Origin of multicast (to not return to sender) or NULL if none
  117. * @param mg Multicast group
  118. * @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
  119. * @param etherType Ethernet frame type
  120. * @param data Packet data
  121. * @param len Length of packet data
  122. */
  123. void send(
  124. void *tPtr,
  125. int64_t now,
  126. const SharedPtr<Network> &network,
  127. const Address &origin,
  128. const MulticastGroup &mg,
  129. const MAC &src,
  130. unsigned int etherType,
  131. const void *data,
  132. unsigned int len);
  133. /**
  134. * Clean up and resort database
  135. *
  136. * @param RR Runtime environment
  137. * @param now Current time
  138. */
  139. void clean(int64_t now);
  140. private:
  141. struct Key
  142. {
  143. ZT_ALWAYS_INLINE Key() : nwid(0),mg() {}
  144. ZT_ALWAYS_INLINE Key(const uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {}
  145. uint64_t nwid;
  146. MulticastGroup mg;
  147. ZT_ALWAYS_INLINE bool operator==(const Key &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); }
  148. ZT_ALWAYS_INLINE bool operator!=(const Key &k) const { return ((nwid != k.nwid)||(mg != k.mg)); }
  149. ZT_ALWAYS_INLINE unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); }
  150. };
  151. const RuntimeEnvironment *const RR;
  152. OutboundMulticast _txQueue[ZT_TX_QUEUE_SIZE];
  153. unsigned int _txQueuePtr;
  154. Mutex _txQueue_l;
  155. Hashtable< Multicaster::Key,Hashtable< Address,int64_t > > _groups;
  156. Mutex _groups_l;
  157. };
  158. } // namespace ZeroTier
  159. #endif