OutboundMulticast.hpp 4.2 KB

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