diff options
| -rw-r--r-- | node/Network.cpp | 78 | ||||
| -rw-r--r-- | node/Network.hpp | 13 | 
2 files changed, 45 insertions, 46 deletions
diff --git a/node/Network.cpp b/node/Network.cpp index b0c2627b..331b37a2 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -92,7 +92,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :  						com.deserialize2(p,e);  						if (!com)  							break; -						_membershipCertificates.insert(std::pair< Address,CertificateOfMembership >(com.issuedTo(),com)); +						_certInfo[com.issuedTo()].com = com;  					}  				}  			} @@ -125,19 +125,22 @@ Network::~Network()  		clean(); -		std::string buf("ZTMCD0");  		Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.mcerts",_id); -		Mutex::Lock _l(_lock); -		if ((!_config)||(_config->isPublic())||(_membershipCertificates.size() == 0)) { +		Mutex::Lock _l(_lock); +		if ((!_config)||(_config->isPublic())||(_certInfo.empty())) {  			RR->node->dataStoreDelete(n); -			return; +		} else { +			std::string buf("ZTMCD0"); +			Hashtable< Address,_RemoteMemberCertificateInfo >::Iterator i(_certInfo); +			Address *a = (Address *)0; +			_RemoteMemberCertificateInfo *ci = (_RemoteMemberCertificateInfo *)0; +			while (i.next(a,ci)) { +				if (ci->com) +					ci->com.serialize2(buf); +			} +			RR->node->dataStorePut(n,buf,true);  		} - -		for(std::map<Address,CertificateOfMembership>::iterator c(_membershipCertificates.begin());c!=_membershipCertificates.end();++c) -			c->second.serialize2(buf); - -		RR->node->dataStorePut(n,buf,true);  	}  } @@ -284,11 +287,12 @@ bool Network::validateAndAddMembershipCertificate(const CertificateOfMembership  		return false;  	Mutex::Lock _l(_lock); -	CertificateOfMembership &old = _membershipCertificates[cert.issuedTo()]; -	// Nothing to do if the cert hasn't changed -- we get duplicates due to zealous cert pushing -	if (old == cert) -		return true; // but if it's a duplicate of one we already accepted, return is 'true' +	{ +		const _RemoteMemberCertificateInfo *ci = _certInfo.get(cert.issuedTo()); +		if ((ci)&&(ci->com == cert)) +			return true; // we already have it +	}  	// Check signature, log and return if cert is invalid  	if (cert.signedBy() != controller()) { @@ -322,9 +326,8 @@ bool Network::validateAndAddMembershipCertificate(const CertificateOfMembership  		}  	} -	// If we made it past authentication, update cert -	if (cert.revision() != old.revision()) -		old = cert; +	// If we made it past authentication, add or update cert in our cert info store +	_certInfo[cert.issuedTo()].com = cert;  	return true;  } @@ -333,9 +336,9 @@ bool Network::peerNeedsOurMembershipCertificate(const Address &to,uint64_t now)  {  	Mutex::Lock _l(_lock);  	if ((_config)&&(!_config->isPublic())&&(_config->com())) { -		uint64_t &lastPushed = _lastPushedMembershipCertificate[to]; -		if ((now - lastPushed) > (ZT_NETWORK_AUTOCONF_DELAY / 2)) { -			lastPushed = now; +		_RemoteMemberCertificateInfo &ci = _certInfo[to]; +		if ((now - ci.lastPushed) > (ZT_NETWORK_AUTOCONF_DELAY / 2)) { +			ci.lastPushed = now;  			return true;  		}  	} @@ -352,23 +355,16 @@ void Network::clean()  	if ((_config)&&(_config->isPublic())) {  		// Open (public) networks do not track certs or cert pushes at all. -		_membershipCertificates.clear(); -		_lastPushedMembershipCertificate.clear(); +		_certInfo.clear();  	} else if (_config) { -		// Clean certificates that are no longer valid from the cache. -		for(std::map<Address,CertificateOfMembership>::iterator c=(_membershipCertificates.begin());c!=_membershipCertificates.end();) { -			if (_config->com().agreesWith(c->second)) -				++c; -			else _membershipCertificates.erase(c++); -		} - -		// Clean entries from the last pushed tracking map if they're so old as -		// to be no longer relevant. -		uint64_t forgetIfBefore = now - (ZT_PEER_ACTIVITY_TIMEOUT * 16); // arbitrary reasonable cutoff -		for(std::map<Address,uint64_t>::iterator lp(_lastPushedMembershipCertificate.begin());lp!=_lastPushedMembershipCertificate.end();) { -			if (lp->second < forgetIfBefore) -				_lastPushedMembershipCertificate.erase(lp++); -			else ++lp; +		// Clean obsolete entries from private network cert info table +		Hashtable< Address,_RemoteMemberCertificateInfo >::Iterator i(_certInfo); +		Address *a = (Address *)0; +		_RemoteMemberCertificateInfo *ci = (_RemoteMemberCertificateInfo *)0; +		const uint64_t forgetIfBefore = now - (ZT_PEER_ACTIVITY_TIMEOUT * 16); // arbitrary reasonable cutoff +		while (i.next(a,ci)) { +			if ((ci->lastPushed < forgetIfBefore)&&(!ci->com.agreesWith(_config->com()))) +				_certInfo.erase(*a);  		}  	} @@ -506,12 +502,10 @@ bool Network::_isAllowed(const Address &peer) const  			return false;  		if (_config->isPublic())  			return true; - -		std::map<Address,CertificateOfMembership>::const_iterator pc(_membershipCertificates.find(peer)); -		if (pc == _membershipCertificates.end()) -			return false; // no certificate on file - -		return _config->com().agreesWith(pc->second); // is other cert valid against ours? +		const _RemoteMemberCertificateInfo *ci = _certInfo.get(peer); +		if (!ci) +			return false; +		return _config->com().agreesWith(ci->com);  	} catch (std::exception &exc) {  		TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer.toString().c_str(),exc.what());  	} catch ( ... ) { diff --git a/node/Network.hpp b/node/Network.hpp index d8ffd612..7f215555 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -347,6 +347,13 @@ public:  	inline bool operator>=(const Network &n) const throw() { return (_id >= n._id); }  private: +	struct _RemoteMemberCertificateInfo +	{ +		_RemoteMemberCertificateInfo() : com(),lastPushed(0) {} +		CertificateOfMembership com; // remote member's COM +		uint64_t lastPushed; // when did we last push ours to them? +	}; +  	ZT1_VirtualNetworkStatus _status() const;  	void _externalConfig(ZT1_VirtualNetworkConfig *ec) const; // assumes _lock is locked  	bool _isAllowed(const Address &peer) const; @@ -361,11 +368,9 @@ private:  	std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to (according to tap)  	Hashtable< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge) +	Hashtable< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges) -	Hashtable< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for remote bridges) - -	std::map<Address,CertificateOfMembership> _membershipCertificates; // Other members' certificates of membership -	std::map<Address,uint64_t> _lastPushedMembershipCertificate; // When did we last push our certificate to each remote member? +	Hashtable< Address,_RemoteMemberCertificateInfo > _certInfo;  	SharedPtr<NetworkConfig> _config; // Most recent network configuration, which is an immutable value-object  	volatile uint64_t _lastConfigUpdate;  | 
