Two for one! (std::map removal)

This commit is contained in:
Adam Ierymenko 2015-09-04 14:14:32 -07:00
parent d1341578d8
commit 307e44f7c8
2 changed files with 45 additions and 46 deletions

View file

@ -92,7 +92,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
com.deserialize2(p,e); com.deserialize2(p,e);
if (!com) if (!com)
break; break;
_membershipCertificates.insert(std::pair< Address,CertificateOfMembership >(com.issuedTo(),com)); _certInfo[com.issuedTo()].com = com;
} }
} }
} }
@ -125,21 +125,24 @@ Network::~Network()
clean(); clean();
std::string buf("ZTMCD0");
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.mcerts",_id); Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.mcerts",_id);
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
if ((!_config)||(_config->isPublic())||(_certInfo.empty())) {
if ((!_config)||(_config->isPublic())||(_membershipCertificates.size() == 0)) {
RR->node->dataStoreDelete(n); 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);
} }
for(std::map<Address,CertificateOfMembership>::iterator c(_membershipCertificates.begin());c!=_membershipCertificates.end();++c)
c->second.serialize2(buf);
RR->node->dataStorePut(n,buf,true); RR->node->dataStorePut(n,buf,true);
} }
} }
}
bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const bool Network::subscribedToMulticastGroup(const MulticastGroup &mg,bool includeBridgedGroups) const
{ {
@ -284,11 +287,12 @@ bool Network::validateAndAddMembershipCertificate(const CertificateOfMembership
return false; return false;
Mutex::Lock _l(_lock); 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) const _RemoteMemberCertificateInfo *ci = _certInfo.get(cert.issuedTo());
return true; // but if it's a duplicate of one we already accepted, return is 'true' if ((ci)&&(ci->com == cert))
return true; // we already have it
}
// Check signature, log and return if cert is invalid // Check signature, log and return if cert is invalid
if (cert.signedBy() != controller()) { if (cert.signedBy() != controller()) {
@ -322,9 +326,8 @@ bool Network::validateAndAddMembershipCertificate(const CertificateOfMembership
} }
} }
// If we made it past authentication, update cert // If we made it past authentication, add or update cert in our cert info store
if (cert.revision() != old.revision()) _certInfo[cert.issuedTo()].com = cert;
old = cert;
return true; return true;
} }
@ -333,9 +336,9 @@ bool Network::peerNeedsOurMembershipCertificate(const Address &to,uint64_t now)
{ {
Mutex::Lock _l(_lock); Mutex::Lock _l(_lock);
if ((_config)&&(!_config->isPublic())&&(_config->com())) { if ((_config)&&(!_config->isPublic())&&(_config->com())) {
uint64_t &lastPushed = _lastPushedMembershipCertificate[to]; _RemoteMemberCertificateInfo &ci = _certInfo[to];
if ((now - lastPushed) > (ZT_NETWORK_AUTOCONF_DELAY / 2)) { if ((now - ci.lastPushed) > (ZT_NETWORK_AUTOCONF_DELAY / 2)) {
lastPushed = now; ci.lastPushed = now;
return true; return true;
} }
} }
@ -352,23 +355,16 @@ void Network::clean()
if ((_config)&&(_config->isPublic())) { if ((_config)&&(_config->isPublic())) {
// Open (public) networks do not track certs or cert pushes at all. // Open (public) networks do not track certs or cert pushes at all.
_membershipCertificates.clear(); _certInfo.clear();
_lastPushedMembershipCertificate.clear();
} else if (_config) { } else if (_config) {
// Clean certificates that are no longer valid from the cache. // Clean obsolete entries from private network cert info table
for(std::map<Address,CertificateOfMembership>::iterator c=(_membershipCertificates.begin());c!=_membershipCertificates.end();) { Hashtable< Address,_RemoteMemberCertificateInfo >::Iterator i(_certInfo);
if (_config->com().agreesWith(c->second)) Address *a = (Address *)0;
++c; _RemoteMemberCertificateInfo *ci = (_RemoteMemberCertificateInfo *)0;
else _membershipCertificates.erase(c++); 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())))
// Clean entries from the last pushed tracking map if they're so old as _certInfo.erase(*a);
// 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;
} }
} }
@ -506,12 +502,10 @@ bool Network::_isAllowed(const Address &peer) const
return false; return false;
if (_config->isPublic()) if (_config->isPublic())
return true; return true;
const _RemoteMemberCertificateInfo *ci = _certInfo.get(peer);
std::map<Address,CertificateOfMembership>::const_iterator pc(_membershipCertificates.find(peer)); if (!ci)
if (pc == _membershipCertificates.end()) return false;
return false; // no certificate on file return _config->com().agreesWith(ci->com);
return _config->com().agreesWith(pc->second); // is other cert valid against ours?
} catch (std::exception &exc) { } catch (std::exception &exc) {
TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer.toString().c_str(),exc.what()); TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer.toString().c_str(),exc.what());
} catch ( ... ) { } catch ( ... ) {

View file

@ -347,6 +347,13 @@ public:
inline bool operator>=(const Network &n) const throw() { return (_id >= n._id); } inline bool operator>=(const Network &n) const throw() { return (_id >= n._id); }
private: 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; ZT1_VirtualNetworkStatus _status() const;
void _externalConfig(ZT1_VirtualNetworkConfig *ec) const; // assumes _lock is locked void _externalConfig(ZT1_VirtualNetworkConfig *ec) const; // assumes _lock is locked
bool _isAllowed(const Address &peer) const; bool _isAllowed(const Address &peer) const;
@ -361,11 +368,9 @@ private:
std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to (according to tap) 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< 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) Hashtable< Address,_RemoteMemberCertificateInfo > _certInfo;
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?
SharedPtr<NetworkConfig> _config; // Most recent network configuration, which is an immutable value-object SharedPtr<NetworkConfig> _config; // Most recent network configuration, which is an immutable value-object
volatile uint64_t _lastConfigUpdate; volatile uint64_t _lastConfigUpdate;