Multicaster.hpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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: 2026-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 <list>
  20. #include "Constants.hpp"
  21. #include "Hashtable.hpp"
  22. #include "Address.hpp"
  23. #include "MAC.hpp"
  24. #include "MulticastGroup.hpp"
  25. #include "OutboundMulticast.hpp"
  26. #include "Utils.hpp"
  27. #include "Mutex.hpp"
  28. #include "SharedPtr.hpp"
  29. namespace ZeroTier {
  30. class RuntimeEnvironment;
  31. class CertificateOfMembership;
  32. class Packet;
  33. class Network;
  34. /**
  35. * Database of known multicast peers within a network
  36. */
  37. class Multicaster
  38. {
  39. public:
  40. Multicaster(const RuntimeEnvironment *renv);
  41. ~Multicaster();
  42. /**
  43. * Add or update a member in a multicast group
  44. *
  45. * @param now Current time
  46. * @param nwid Network ID
  47. * @param mg Multicast group
  48. * @param member New member address
  49. */
  50. inline void add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member)
  51. {
  52. Mutex::Lock _l(_groups_m);
  53. _add(tPtr,now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member);
  54. }
  55. /**
  56. * Add multiple addresses from a binary array of 5-byte address fields
  57. *
  58. * It's up to the caller to check bounds on the array before calling this.
  59. *
  60. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  61. * @param now Current time
  62. * @param nwid Network ID
  63. * @param mg Multicast group
  64. * @param addresses Raw binary addresses in big-endian format, as a series of 5-byte fields
  65. * @param count Number of addresses
  66. * @param totalKnown Total number of known addresses as reported by peer
  67. */
  68. void addMultiple(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown);
  69. /**
  70. * Remove a multicast group member (if present)
  71. *
  72. * @param nwid Network ID
  73. * @param mg Multicast group
  74. * @param member Member to unsubscribe
  75. */
  76. void remove(uint64_t nwid,const MulticastGroup &mg,const Address &member);
  77. /**
  78. * Append gather results to a packet by choosing registered multicast recipients at random
  79. *
  80. * This appends the following fields to the packet:
  81. * <[4] 32-bit total number of known members in this multicast group>
  82. * <[2] 16-bit number of members enumerated in this packet>
  83. * <[...] series of 5-byte ZeroTier addresses of enumerated members>
  84. *
  85. * If zero is returned, the first two fields will still have been appended.
  86. *
  87. * @param queryingPeer Peer asking for gather (to skip in results)
  88. * @param nwid Network ID
  89. * @param mg Multicast group
  90. * @param appendTo Packet to append to
  91. * @param limit Maximum number of 5-byte addresses to append
  92. * @return Number of addresses appended
  93. * @throws std::out_of_range Buffer overflow writing to packet
  94. */
  95. unsigned int gather(const Address &queryingPeer,uint64_t nwid,const MulticastGroup &mg,Buffer<ZT_PROTO_MAX_PACKET_LENGTH> &appendTo,unsigned int limit) const;
  96. /**
  97. * Get subscribers to a multicast group
  98. *
  99. * @param nwid Network ID
  100. * @param mg Multicast group
  101. */
  102. std::vector<Address> getMembers(uint64_t nwid,const MulticastGroup &mg,unsigned int limit) const;
  103. /**
  104. * Send a multicast
  105. *
  106. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  107. * @param now Current time
  108. * @param network Network
  109. * @param origin Origin of multicast (to not return to sender) or NULL if none
  110. * @param mg Multicast group
  111. * @param src Source Ethernet MAC address or NULL to skip in packet and compute from ZT address (non-bridged mode)
  112. * @param etherType Ethernet frame type
  113. * @param data Packet data
  114. * @param len Length of packet data
  115. */
  116. void send(
  117. void *tPtr,
  118. int64_t now,
  119. const SharedPtr<Network> &network,
  120. const Address &origin,
  121. const MulticastGroup &mg,
  122. const MAC &src,
  123. unsigned int etherType,
  124. const void *data,
  125. unsigned int len);
  126. /**
  127. * Clean database
  128. *
  129. * @param RR Runtime environment
  130. * @param now Current time
  131. */
  132. void clean(int64_t now);
  133. private:
  134. struct Key
  135. {
  136. Key() : nwid(0),mg() {}
  137. Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {}
  138. uint64_t nwid;
  139. MulticastGroup mg;
  140. inline bool operator==(const Key &k) const { return ((nwid == k.nwid)&&(mg == k.mg)); }
  141. inline bool operator!=(const Key &k) const { return ((nwid != k.nwid)||(mg != k.mg)); }
  142. inline unsigned long hashCode() const { return (mg.hashCode() ^ (unsigned long)(nwid ^ (nwid >> 32))); }
  143. };
  144. struct MulticastGroupMember
  145. {
  146. MulticastGroupMember() {}
  147. MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {}
  148. inline bool operator<(const MulticastGroupMember &a) const { return (address < a.address); }
  149. inline bool operator==(const MulticastGroupMember &a) const { return (address == a.address); }
  150. inline bool operator!=(const MulticastGroupMember &a) const { return (address != a.address); }
  151. inline bool operator<(const Address &a) const { return (address < a); }
  152. inline bool operator==(const Address &a) const { return (address == a); }
  153. inline bool operator!=(const Address &a) const { return (address != a); }
  154. Address address;
  155. int64_t timestamp; // time of last notification
  156. };
  157. struct MulticastGroupStatus
  158. {
  159. MulticastGroupStatus() : lastExplicitGather(0) {}
  160. int64_t lastExplicitGather;
  161. std::list<OutboundMulticast> txQueue; // pending outbound multicasts
  162. std::vector<MulticastGroupMember> members; // members of this group
  163. };
  164. void _add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member);
  165. const RuntimeEnvironment *const RR;
  166. Hashtable<Multicaster::Key,MulticastGroupStatus> _groups;
  167. Mutex _groups_m;
  168. };
  169. } // namespace ZeroTier
  170. #endif