inline unsigned int pickSocialPropagationPeers(
CMWC4096 &prng,
T &topology,
uint64_t nwid,
const MulticastGroup &mg,
const Address &originalSubmitter,
const Address &upstream,
MulticastBloomFilter &bf,
unsigned int max,
P *peers,
uint64_t now)
{
typename std::set< P,_PeerPropagationPrioritySortOrder > toConsider;
/* Pick up to ZT_MULTICAST_PICK_MAX_SAMPLE_SIZE peers that meet
* our minimal criteria for this multicast group and place them
* into a set that is sorted in descending order of time of most
* recent unicast frame transfer (implicit social ordering). */
{
Mutex::Lock _l(_multicastMemberships_m);
std::map< MulticastChannel,std::vector >::iterator mm(_multicastMemberships.find(MulticastChannel(nwid,mg)));
if ((mm != _multicastMemberships.end())&&(!mm->second.empty())) {
for(unsigned int stries=0;striessecond[prng.next32() % mm->second.size()];
if (
((now - m.second) < ZT_MULTICAST_LIKE_EXPIRE)&& /* LIKE is not expired */
(!bf.contains(m.first.sum()))&& /* Not in propagation bloom */
(m.first != originalSubmitter)&& /* Not the original submitter */
(m.first != upstream) ) { /* Not where the frame came from */
P peer(topology.getPeer(m.first));
if (peer)
toConsider.insert(peer); /* Consider propagating to this peer */
}
}
}
}
/* The first peers in toConsider will be the "best" */
unsigned int chosen = 0;
for(typename std::set< P,_PeerPropagationPrioritySortOrder >::iterator i(toConsider.begin());((i!=toConsider.end())&&(chosen < max));++i)
bf.set((peers[chosen++] = *i)->address().sum());
/* Tack on a supernode if we have no next hops */
if (!chosen) {
Address exclude[1];
exclude[0] = originalSubmitter; // if it came from a supernode, don't boomerang
P peer = topology.getBestSupernode(exclude,1,true);
if (peer)
peers[chosen++] = peer;
}
return chosen;
}
private:
// Sort order for chosen propagation peers
template
struct _PeerPropagationPrioritySortOrder
{
inline bool operator()(const P &p1,const P &p2) const
{
return (p1->lastUnicastFrame() > p2->lastUnicastFrame());
}
};
// ring buffer: [0] - CRC, [1] - timestamp
uint64_t _multicastHistory[ZT_MULTICAST_DEDUP_HISTORY_LENGTH][2];
volatile unsigned int _multicastHistoryPtr;
// A multicast channel, essentially a pub/sub channel. It consists of a
// network ID and a multicast group within that network.
typedef std::pair MulticastChannel;
// A membership in a multicast channel, an address and time of last LIKE
typedef std::pair MulticastMembership;
// Network : MulticastGroup -> vector
std::map< MulticastChannel,std::vector > _multicastMemberships;
Mutex _multicastMemberships_m;
};
} // namespace ZeroTier
#endif