diff options
Diffstat (limited to 'node/Topology.cpp')
| -rw-r--r-- | node/Topology.cpp | 87 |
1 files changed, 61 insertions, 26 deletions
diff --git a/node/Topology.cpp b/node/Topology.cpp index 12a7cc0b..48ced7c5 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -111,9 +111,8 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta) { Mutex::Lock _l(_lock); const SharedPtr<Peer> *const ap = _peers.get(zta); - if (ap) { + if (ap) return *ap; - } } try { @@ -158,7 +157,7 @@ void Topology::saveIdentity(const Identity &id) } } -SharedPtr<Peer> Topology::getBestRoot(const Address *avoid,unsigned int avoidCount,bool strictAvoid) +SharedPtr<Peer> Topology::getUpstreamPeer(const Address *avoid,unsigned int avoidCount,bool strictAvoid) { const uint64_t now = RR->node->now(); Mutex::Lock _l(_lock); @@ -189,22 +188,25 @@ SharedPtr<Peer> Topology::getBestRoot(const Address *avoid,unsigned int avoidCou const SharedPtr<Peer> *bestOverall = (const SharedPtr<Peer> *)0; const SharedPtr<Peer> *bestNotAvoid = (const SharedPtr<Peer> *)0; - for(std::vector< SharedPtr<Peer> >::const_iterator r(_rootPeers.begin());r!=_rootPeers.end();++r) { - bool avoiding = false; - for(unsigned int i=0;i<avoidCount;++i) { - if (avoid[i] == (*r)->address()) { - avoiding = true; - break; + for(std::vector<Address>::const_iterator a(_upstreamAddresses.begin());a!=_upstreamAddresses.end();++a) { + const SharedPtr<Peer> *const p = _peers.get(*a); + if (p) { + bool avoiding = false; + for(unsigned int i=0;i<avoidCount;++i) { + if (avoid[i] == (*p)->address()) { + avoiding = true; + break; + } + } + const unsigned int q = (*p)->relayQuality(now); + if (q <= bestQualityOverall) { + bestQualityOverall = q; + bestOverall = &(*p); + } + if ((!avoiding)&&(q <= bestQualityNotAvoid)) { + bestQualityNotAvoid = q; + bestNotAvoid = &(*p); } - } - const unsigned int q = (*r)->relayQuality(now); - if (q <= bestQualityOverall) { - bestQualityOverall = q; - bestOverall = &(*r); - } - if ((!avoiding)&&(q <= bestQualityNotAvoid)) { - bestQualityNotAvoid = q; - bestNotAvoid = &(*r); } } @@ -219,9 +221,34 @@ SharedPtr<Peer> Topology::getBestRoot(const Address *avoid,unsigned int avoidCou return SharedPtr<Peer>(); } +bool Topology::isRoot(const Identity &id) const +{ + Mutex::Lock _l(_lock); + return (std::find(_rootAddresses.begin(),_rootAddresses.end(),id.address()) != _rootAddresses.end()); +} + bool Topology::isUpstream(const Identity &id) const { - return isRoot(id); + Mutex::Lock _l(_lock); + return (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),id.address()) != _upstreamAddresses.end()); +} + +void Topology::setUpstream(const Address &a,bool upstream) +{ + Mutex::Lock _l(_lock); + if (std::find(_rootAddresses.begin(),_rootAddresses.end(),a) == _rootAddresses.end()) { + if (upstream) { + if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),a) == _upstreamAddresses.end()) + _upstreamAddresses.push_back(a); + } else { + std::vector<Address> ua; + for(std::vector<Address>::iterator i(_upstreamAddresses.begin());i!=_upstreamAddresses.end();++i) { + if (a != *i) + ua.push_back(*i); + } + _upstreamAddresses.swap(ua); + } + } } bool Topology::worldUpdateIfValid(const World &newWorld) @@ -249,7 +276,7 @@ void Topology::clean(uint64_t now) Address *a = (Address *)0; SharedPtr<Peer> *p = (SharedPtr<Peer> *)0; while (i.next(a,p)) { - if ( (!(*p)->isAlive(now)) && (std::find(_rootAddresses.begin(),_rootAddresses.end(),*a) == _rootAddresses.end()) ) + if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) _peers.erase(*a); } } @@ -280,25 +307,33 @@ Identity Topology::_getIdentity(const Address &zta) void Topology::_setWorld(const World &newWorld) { // assumed _lock is locked (or in constructor) + + std::vector<Address> ua; + for(std::vector<Address>::iterator a(_upstreamAddresses.begin());a!=_upstreamAddresses.end();++a) { + if (std::find(_rootAddresses.begin(),_rootAddresses.end(),*a) == _rootAddresses.end()) + ua.push_back(*a); + } + _world = newWorld; - _amRoot = false; _rootAddresses.clear(); - _rootPeers.clear(); + _amRoot = false; + for(std::vector<World::Root>::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) { _rootAddresses.push_back(r->identity.address()); + if (std::find(ua.begin(),ua.end(),r->identity.address()) == ua.end()) + ua.push_back(r->identity.address()); if (r->identity.address() == RR->identity.address()) { _amRoot = true; } else { SharedPtr<Peer> *rp = _peers.get(r->identity.address()); - if (rp) { - _rootPeers.push_back(*rp); - } else { + if (!rp) { SharedPtr<Peer> newrp(new Peer(RR,RR->identity,r->identity)); _peers.set(r->identity.address(),newrp); - _rootPeers.push_back(newrp); } } } + + _upstreamAddresses.swap(ua); } } // namespace ZeroTier |
