OutboundMulticast.hpp 4.1 KB

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