1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
/*
* ZeroTier One - Global Peer to Peer Ethernet
* Copyright (C) 2011-2014 ZeroTier Networks LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*
* ZeroTier may be used and distributed under the terms of the GPLv3, which
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form, please contact ZeroTier Networks
* LLC. Start here: http://www.zerotier.com/
*/
#ifndef ZT_OUTBOUNDMULTICAST_HPP
#define ZT_OUTBOUNDMULTICAST_HPP
#include <stdint.h>
#include <vector>
#include <algorithm>
#include "Constants.hpp"
#include "MAC.hpp"
#include "MulticastGroup.hpp"
#include "Address.hpp"
#include "Packet.hpp"
namespace ZeroTier {
class Switch;
class CertificateOfMembership;
/**
* An outbound multicast packet
*
* This object isn't guarded by a mutex; caller must synchronize access.
*/
class OutboundMulticast
{
public:
/**
* Create an uninitialized outbound multicast
*
* It must be initialized with init().
*/
OutboundMulticast() {}
/**
* Initialize outbound multicast
*
* @param timestamp Creation time
* @param self My ZeroTier address
* @param nwid Network ID
* @param com Certificate of membership to attach or NULL to omit
* @param limit Multicast limit for desired number of packets to send
* @param gatherLimit Number to lazily/implicitly gather with this frame or 0 for none
* @param src Source MAC address of frame
* @param dest Destination multicast group (MAC + ADI)
* @param etherType 16-bit Ethernet type ID
* @param payload Data
* @param len Length of data
* @throws std::out_of_range Data too large to fit in a MULTICAST_FRAME
*/
void init(
uint64_t timestamp,
const Address &self,
uint64_t nwid,
const CertificateOfMembership *com,
unsigned int limit,
unsigned int gatherLimit,
const MAC &src,
const MulticastGroup &dest,
unsigned int etherType,
const void *payload,
unsigned int len);
/**
* @return Multicast creation time
*/
inline uint64_t timestamp() const throw() { return _timestamp; }
/**
* @param now Current time
* @return True if this multicast is expired (has exceeded transmit timeout)
*/
inline bool expired(uint64_t now) const throw() { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); }
/**
* @return True if this outbound multicast has been sent to enough peers
*/
inline bool atLimit() const throw() { return (_alreadySentTo.size() > _limit); }
/**
* Just send without checking log
*
* @param sw Switch instance to send packets
* @param toAddr Destination address
*/
void sendOnly(Switch &sw,const Address &toAddr);
/**
* Just send and log but do not check sent log
*
* @param sw Switch instance to send packets
* @param toAddr Destination address
*/
inline void sendAndLog(Switch &sw,const Address &toAddr)
{
_alreadySentTo.push_back(toAddr);
sendOnly(sw,toAddr);
}
/**
* Try to send this to a given peer if it hasn't been sent to them already
*
* @param sw Switch instance to send packets
* @param toAddr Destination address
* @return True if address is new and packet was sent to switch, false if duplicate
*/
inline bool sendIfNew(Switch &sw,const Address &toAddr)
{
for(std::vector<Address>::iterator a(_alreadySentTo.begin());a!=_alreadySentTo.end();++a) {
if (*a == toAddr)
return false;
}
sendAndLog(sw,toAddr);
return true;
}
private:
uint64_t _timestamp;
uint64_t _nwid;
MAC _source;
MulticastGroup _destination;
unsigned int _limit;
unsigned int _etherType;
Packet _packet; // packet contains basic structure of MULTICAST_FRAME and payload, is re-used with new IV and addressing each time
std::vector<Address> _alreadySentTo;
};
} // namespace ZeroTier
#endif
|