/* * Copyright (c)2019 ZeroTier, Inc. * * Use of this software is governed by the Business Source License included * in the LICENSE.TXT file in the project's root directory. * * Change Date: 2023-01-01 * * On the date above, in accordance with the Business Source License, use * of this software will be governed by version 2.0 of the Apache License. */ /****/ #include "Topology.hpp" namespace ZeroTier { struct _RootSortComparisonOperator { ZT_ALWAYS_INLINE _RootSortComparisonOperator(const int64_t now) : _now(now) {} ZT_ALWAYS_INLINE bool operator()(const SharedPtr &a,const SharedPtr &b) { const int64_t now = _now; if (a->alive(now)) { if (b->alive(now)) return (a->latency() < b->latency()); return true; } return false; } const int64_t _now; }; Topology::Topology(const RuntimeEnvironment *renv,const Identity &myId) : RR(renv), _myIdentity(myId), _numConfiguredPhysicalPaths(0), _peers(128), _paths(256) { } Topology::~Topology() { } void Topology::getAllPeers(std::vector< SharedPtr > &allPeers) const { RWMutex::RLock l(_peers_l); allPeers.clear(); allPeers.reserve(_peers.size()); Hashtable< Address,SharedPtr >::Iterator i(*(const_cast > *>(&_peers))); Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; while (i.next(a,p)) allPeers.push_back(*p); } void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) { if (!pathNetwork) { _numConfiguredPhysicalPaths = 0; } else { std::map cpaths; for(unsigned int i=0,j=_numConfiguredPhysicalPaths;i ZT_MAX_PHYSMTU) pc.mtu = ZT_MAX_PHYSMTU; cpaths[*(reinterpret_cast(pathNetwork))] = pc; } else { cpaths.erase(*(reinterpret_cast(pathNetwork))); } unsigned int cnt = 0; for(std::map::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cntfirst; _physicalPathConfig[cnt].second = i->second; ++cnt; } _numConfiguredPhysicalPaths = cnt; } } void Topology::addRoot(const Identity &id) { if (id == _myIdentity) return; // sanity check RWMutex::Lock l1(_peers_l); std::pair< std::set::iterator,bool > ir(_roots.insert(id)); if (ir.second) { SharedPtr &p = _peers[id.address()]; if (!p) p.set(new Peer(RR,_myIdentity,id)); _rootPeers.push_back(p); } } bool Topology::removeRoot(const Identity &id) { RWMutex::Lock l1(_peers_l); std::set::iterator r(_roots.find(id)); if (r != _roots.end()) { for(std::vector< SharedPtr >::iterator p(_rootPeers.begin());p!=_rootPeers.end();++p) { if ((*p)->identity() == id) { _rootPeers.erase(p); break; } } _roots.erase(r); return true; } return false; } void Topology::rankRoots(const int64_t now) { RWMutex::Lock l1(_peers_l); std::sort(_rootPeers.begin(),_rootPeers.end(),_RootSortComparisonOperator(now)); } void Topology::doPeriodicTasks(const int64_t now) { { RWMutex::Lock l1(_peers_l); Hashtable< Address,SharedPtr >::Iterator i(_peers); Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; while (i.next(a,p)) { if ( (!(*p)->alive(now)) && (_roots.count((*p)->identity()) == 0) ) _peers.erase(*a); } } { RWMutex::Lock l1(_paths_l); Hashtable< Path::HashKey,SharedPtr >::Iterator i(_paths); Path::HashKey *k = (Path::HashKey *)0; SharedPtr *p = (SharedPtr *)0; while (i.next(k,p)) { if (p->references() <= 1) _paths.erase(*k); } } } } // namespace ZeroTier