MulticastSubscriptions.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * ZeroTier One - Network Virtualization Everywhere
  3. * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * --
  19. *
  20. * You can be released from the requirements of the license by purchasing
  21. * a commercial license. Buying such a license is mandatory as soon as you
  22. * develop commercial closed-source software that incorporates or links
  23. * directly against ZeroTier software without disclosing the source code
  24. * of your own application.
  25. */
  26. #ifndef ZT_MULTICASTSUBSCRIPTIONS_HPP
  27. #define ZT_MULTICASTSUBSCRIPTIONS_HPP
  28. #include "Constants.hpp"
  29. #include "MulticastGroup.hpp"
  30. #include "Identity.hpp"
  31. #include "Buffer.hpp"
  32. namespace ZeroTier {
  33. /**
  34. * A compact collection of multicast subscriptions identified by 32-bit hash values
  35. */
  36. class MulticastSubscriptions
  37. {
  38. public:
  39. inline MulticastSubscriptions() : _signatureLength(0) {}
  40. inline void add(const MulticastGroup &mg)
  41. {
  42. if (_subscriptions.size() < ZT_MAX_MULTICAST_SUBSCRIPTIONS)
  43. _subscriptions.push_back(mg.id32());
  44. }
  45. inline bool sign(const Identity &signer,const int64_t ts)
  46. {
  47. _ts = ts;
  48. std::sort(_subscriptions.begin(),_subscriptions.end());
  49. _subscriptions.erase(std::unique(_subscriptions.begin(),_subscriptions.end()),_subscriptions.end());
  50. _SRec tmp;
  51. tmp.ts = Utils::hton((uint64_t)ts);
  52. for(unsigned long i=0,j=(unsigned long)_subscriptions.size();i<j;++i)
  53. tmp.g[i] = Utils::hton(_subscriptions[i]);
  54. _signatureLength = signer.sign(&tmp,(unsigned int)((_subscriptions.size() * sizeof(uint32_t)) + sizeof(uint64_t)),_signature,sizeof(_signature));
  55. return (_signatureLength > 0);
  56. }
  57. inline bool verify(const Identity &signer)
  58. {
  59. if ((_signatureLength == 0)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE))
  60. return false;
  61. _SRec tmp;
  62. tmp.ts = Utils::hton((uint64_t)_ts);
  63. for(unsigned long i=0,j=(unsigned long)_subscriptions.size();i<j;++i)
  64. tmp.g[i] = Utils::hton(_subscriptions[i]);
  65. return signer.verify(&tmp,(unsigned int)((_subscriptions.size() * sizeof(uint32_t)) + sizeof(uint64_t)),_signature,_signatureLength);
  66. }
  67. inline int64_t timestamp() const { return _ts; }
  68. inline unsigned int count() const { return (unsigned int)_subscriptions.size(); }
  69. inline bool contains(const MulticastGroup &mg) const { return std::binary_search(_subscriptions.begin(),_subscriptions.end(),mg.id32()); }
  70. template<unsigned int C>
  71. inline void serialize(Buffer<C> &b) const
  72. {
  73. b.append((uint64_t)_ts);
  74. b.append((uint16_t)_subscriptions.size());
  75. for(std::vector<uint32_t>::const_iterator i(_subscriptions.begin());i!=_subscriptions.end();++i)
  76. b.append(*i);
  77. b.append((uint16_t)_signatureLength);
  78. b.append(_signature,_signatureLength);
  79. }
  80. template<unsigned int C>
  81. inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
  82. {
  83. unsigned int p = startAt;
  84. _ts = (int64_t)(b.template at<uint64_t>(p)); p += 8;
  85. _subscriptions.resize(b.template at<uint16_t>(p)); p += 2;
  86. for(std::vector<uint32_t>::iterator i(_subscriptions.begin());i!=_subscriptions.end();++i) {
  87. *i = b.template at<uint32_t>(p);
  88. p += 4;
  89. }
  90. _signatureLength = b.template at<uint16_t>(p); p += 2;
  91. if (_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)
  92. throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
  93. memcpy(_signature,b.field(p,_signatureLength),_signatureLength); p += _signatureLength;
  94. return (p - startAt);
  95. }
  96. private:
  97. ZT_PACKED_STRUCT(struct _SRec {
  98. uint64_t ts;
  99. uint32_t g[ZT_MAX_MULTICAST_SUBSCRIPTIONS];
  100. });
  101. int64_t _ts;
  102. std::vector<uint32_t> _subscriptions;
  103. unsigned int _signatureLength;
  104. uint8_t _signature[ZT_SIGNATURE_BUFFER_SIZE];
  105. };
  106. } // namespace ZeroTier
  107. #endif