| 
					
				 | 
			
			
				@@ -877,7 +877,7 @@ void Network::multicastSubscribe(const MulticastGroup &mg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		_myMulticastGroups.push_back(mg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		std::sort(_myMulticastGroups.begin(),_myMulticastGroups.end()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_announceMulticastGroups(&mg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		_pushStateToMembers(&mg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1062,6 +1062,36 @@ void Network::requestConfiguration() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	_inboundConfigChunks.clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool Network::gate(const SharedPtr<Peer> &peer,const Packet::Verb verb,const uint64_t packetId) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Mutex::Lock _l(_lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (_config) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Membership &m = _membership(peer->address()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			const bool allow = m.isAllowedOnNetwork(_config); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (allow) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const uint64_t now = RR->node->now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				m.sendCredentialsIfNeeded(RR,now,peer->address(),_config,(const Capability *)0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (m.shouldLikeMulticasts(now)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					_announceMulticastGroupsTo(peer->address(),_allMulticastGroups()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					m.likingMulticasts(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else if (m.recentlyAllowedOnNetwork(_config)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				outp.append((uint8_t)verb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				outp.append(packetId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				outp.append(_id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				RR->sw->send(outp,true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return allow; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} catch ( ... ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		TRACE("gate() check failed for peer %s: unexpected exception",peer->address().toString().c_str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void Network::clean() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	const uint64_t now = RR->node->now(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1135,7 +1165,7 @@ void Network::learnBridgedMulticastGroup(const MulticastGroup &mg,uint64_t now) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	_multicastGroupsBehindMe.set(mg,now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if (tmp != _multicastGroupsBehindMe.size()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_announceMulticastGroups(&mg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		_pushStateToMembers(&mg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void Network::destroy() 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1200,33 +1230,18 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-bool Network::_isAllowed(const SharedPtr<Peer> &peer) const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// Assumes _lock is locked 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (_config) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			const Membership *const m = _memberships.get(peer->address()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if (m) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				return m->isAllowedOnNetwork(_config); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} catch ( ... ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		TRACE("isAllowed() check failed for peer %s: unexpected exception",peer->address().toString().c_str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void Network::_announceMulticastGroups(const MulticastGroup *const onlyThis) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void Network::_pushStateToMembers(const MulticastGroup *const newMulticastGroup) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// Assumes _lock is locked 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	const uint64_t now = RR->node->now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	std::vector<MulticastGroup> groups; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (onlyThis) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		groups.push_back(*onlyThis); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (newMulticastGroup) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		groups.push_back(*newMulticastGroup); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	else groups = _allMulticastGroups(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if ((onlyThis)||((now - _lastAnnouncedMulticastGroupsUpstream) >= ZT_MULTICAST_ANNOUNCE_PERIOD)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (!onlyThis) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ((newMulticastGroup)||((now - _lastAnnouncedMulticastGroupsUpstream) >= ZT_MULTICAST_ANNOUNCE_PERIOD)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (!newMulticastGroup) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			_lastAnnouncedMulticastGroupsUpstream = now; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		// Announce multicast groups to upstream peers (roots, etc.) and also send 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1255,7 +1270,7 @@ void Network::_announceMulticastGroups(const MulticastGroup *const onlyThis) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// piecemeal on-demand fashion. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	const std::vector<Address> anchors(_config.anchors()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	for(std::vector<Address>::const_iterator a(anchors.begin());a!=anchors.end();++a) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_memberships[*a]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		_membership(*a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// Send MULTICAST_LIKE(s) to all members of this network 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1263,11 +1278,13 @@ void Network::_announceMulticastGroups(const MulticastGroup *const onlyThis) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Membership *m = (Membership *)0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Hashtable<Address,Membership>::Iterator i(_memberships); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		while (i.next(a,m)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if ((onlyThis)||(m->shouldLikeMulticasts(now))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if (!onlyThis) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					m->likingMulticasts(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ( (m->recentlyAllowedOnNetwork(_config)) || (std::find(anchors.begin(),anchors.end(),*a) != anchors.end()) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				m->sendCredentialsIfNeeded(RR,RR->node->now(),*a,_config,(const Capability *)0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				_announceMulticastGroupsTo(*a,groups); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if ( ((newMulticastGroup)||(m->shouldLikeMulticasts(now))) && (m->isAllowedOnNetwork(_config)) ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					if (!newMulticastGroup) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						m->likingMulticasts(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					_announceMulticastGroupsTo(*a,groups); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1314,15 +1331,7 @@ std::vector<MulticastGroup> Network::_allMulticastGroups() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 Membership &Network::_membership(const Address &a) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// assumes _lock is locked 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	const unsigned long ms = _memberships.size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Membership &m = _memberships[a]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	if (ms != _memberships.size()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const uint64_t now = RR->node->now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		m.sendCredentialsIfNeeded(RR,now,a,_config,(const Capability *)0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		_announceMulticastGroupsTo(a,_allMulticastGroups()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		m.likingMulticasts(now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	return m; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return _memberships[a]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } // namespace ZeroTier 
			 |