OutboundMulticast.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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_OUTBOUNDMULTICAST_HPP
  14. #define ZT_OUTBOUNDMULTICAST_HPP
  15. #include "Address.hpp"
  16. #include "Constants.hpp"
  17. #include "MAC.hpp"
  18. #include "MulticastGroup.hpp"
  19. #include "Packet.hpp"
  20. #include <algorithm>
  21. #include <stdint.h>
  22. #include <vector>
  23. namespace ZeroTier {
  24. class CertificateOfMembership;
  25. class RuntimeEnvironment;
  26. /**
  27. * An outbound multicast packet
  28. *
  29. * This object isn't guarded by a mutex; caller must synchronize access.
  30. */
  31. class OutboundMulticast {
  32. public:
  33. /**
  34. * Create an uninitialized outbound multicast
  35. *
  36. * It must be initialized with init().
  37. */
  38. OutboundMulticast()
  39. {
  40. }
  41. /**
  42. * Initialize outbound multicast
  43. *
  44. * @param RR Runtime environment
  45. * @param timestamp Creation time
  46. * @param nwid Network ID
  47. * @param disableCompression Disable compression of frame payload
  48. * @param limit Multicast limit for desired number of packets to send
  49. * @param gatherLimit Number to lazily/implicitly gather with this frame or 0 for none
  50. * @param src Source MAC address of frame or NULL to imply compute from sender ZT address
  51. * @param dest Destination multicast group (MAC + ADI)
  52. * @param etherType 16-bit Ethernet type ID
  53. * @param payload Data
  54. * @param len Length of data
  55. * @throws std::out_of_range Data too large to fit in a MULTICAST_FRAME
  56. */
  57. void init(
  58. const RuntimeEnvironment* RR,
  59. uint64_t timestamp,
  60. uint64_t nwid,
  61. bool disableCompression,
  62. unsigned int limit,
  63. unsigned int gatherLimit,
  64. const MAC& src,
  65. const MulticastGroup& dest,
  66. unsigned int etherType,
  67. const void* payload,
  68. unsigned int len);
  69. /**
  70. * @return Multicast creation time
  71. */
  72. inline uint64_t timestamp() const
  73. {
  74. return _timestamp;
  75. }
  76. /**
  77. * @param now Current time
  78. * @return True if this multicast is expired (has exceeded transmit timeout)
  79. */
  80. inline bool expired(int64_t now) const
  81. {
  82. return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT);
  83. }
  84. /**
  85. * @return True if this outbound multicast has been sent to enough peers
  86. */
  87. inline bool atLimit() const
  88. {
  89. return (_alreadySentTo.size() >= _limit);
  90. }
  91. /**
  92. * Just send without checking log
  93. *
  94. * @param RR Runtime environment
  95. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  96. * @param toAddr Destination address
  97. */
  98. void sendOnly(const RuntimeEnvironment* RR, void* tPtr, const Address& toAddr);
  99. /**
  100. * Just send and log but do not check sent log
  101. *
  102. * @param RR Runtime environment
  103. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  104. * @param toAddr Destination address
  105. */
  106. inline void sendAndLog(const RuntimeEnvironment* RR, void* tPtr, const Address& toAddr)
  107. {
  108. _alreadySentTo.push_back(toAddr);
  109. sendOnly(RR, tPtr, toAddr);
  110. }
  111. /**
  112. * Log an address as having been used so we will not send there in the future
  113. *
  114. * @param toAddr Address to log as sent
  115. */
  116. inline void logAsSent(const Address& toAddr)
  117. {
  118. _alreadySentTo.push_back(toAddr);
  119. }
  120. /**
  121. * Try to send this to a given peer if it hasn't been sent to them already
  122. *
  123. * @param RR Runtime environment
  124. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
  125. * @param toAddr Destination address
  126. * @return True if address is new and packet was sent to switch, false if duplicate
  127. */
  128. inline bool sendIfNew(const RuntimeEnvironment* RR, void* tPtr, const Address& toAddr)
  129. {
  130. if (std::find(_alreadySentTo.begin(), _alreadySentTo.end(), toAddr) == _alreadySentTo.end()) {
  131. sendAndLog(RR, tPtr, toAddr);
  132. return true;
  133. }
  134. else {
  135. return false;
  136. }
  137. }
  138. private:
  139. uint64_t _timestamp;
  140. uint64_t _nwid;
  141. MAC _macSrc;
  142. MAC _macDest;
  143. unsigned int _limit;
  144. unsigned int _frameLen;
  145. unsigned int _etherType;
  146. Packet _packet, _tmp;
  147. std::vector<Address> _alreadySentTo;
  148. uint8_t _frameData[ZT_MAX_MTU];
  149. };
  150. } // namespace ZeroTier
  151. #endif