|
|
|
@ -25,6 +25,7 @@ |
|
|
|
* LLC. Start here: http://www.zerotier.com/
|
|
|
|
* LLC. Start here: http://www.zerotier.com/
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <algorithm> |
|
|
|
#include "Topology.hpp" |
|
|
|
#include "Topology.hpp" |
|
|
|
#include "NodeConfig.hpp" |
|
|
|
#include "NodeConfig.hpp" |
|
|
|
|
|
|
|
|
|
|
|
@ -145,23 +146,32 @@ SharedPtr<Peer> Topology::getPeer(const Address &zta) |
|
|
|
return SharedPtr<Peer>(); |
|
|
|
return SharedPtr<Peer>(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount) const |
|
|
|
SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
SharedPtr<Peer> bestSupernode; |
|
|
|
SharedPtr<Peer> bestSupernode; |
|
|
|
unsigned long bestSupernodeLatency = 0xffff; |
|
|
|
unsigned int bestSupernodeLatency = 0xffff; |
|
|
|
uint64_t now = Utils::now(); |
|
|
|
uint64_t now = Utils::now(); |
|
|
|
|
|
|
|
|
|
|
|
Mutex::Lock _l(_supernodes_m); |
|
|
|
Mutex::Lock _l(_supernodes_m); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (_supernodePeers.empty()) |
|
|
|
|
|
|
|
return bestSupernode; |
|
|
|
|
|
|
|
|
|
|
|
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();) { |
|
|
|
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();) { |
|
|
|
for(unsigned int i=0;i<avoidCount;++i) { |
|
|
|
for(unsigned int i=0;i<avoidCount;++i) { |
|
|
|
if (avoid[i] == (*sn)->address()) |
|
|
|
if (avoid[i] == (*sn)->address()) |
|
|
|
goto skip_and_try_next_supernode; |
|
|
|
goto skip_and_try_next_supernode; |
|
|
|
} |
|
|
|
} |
|
|
|
if ((*sn)->hasActiveDirectPath(now)) { // only consider those that responded to pings
|
|
|
|
if ((*sn)->hasActiveDirectPath(now)) { |
|
|
|
unsigned int l = (*sn)->latency(); |
|
|
|
unsigned int l = (*sn)->latency(); |
|
|
|
if ((l)&&(l <= bestSupernodeLatency)) { |
|
|
|
if (bestSupernode) { |
|
|
|
bestSupernodeLatency = l; |
|
|
|
if ((l)&&(l < bestSupernodeLatency)) { |
|
|
|
|
|
|
|
bestSupernodeLatency = l; |
|
|
|
|
|
|
|
bestSupernode = *sn; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (l) |
|
|
|
|
|
|
|
bestSupernodeLatency = l; |
|
|
|
bestSupernode = *sn; |
|
|
|
bestSupernode = *sn; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -169,14 +179,20 @@ skip_and_try_next_supernode: |
|
|
|
++sn; |
|
|
|
++sn; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (bestSupernode) |
|
|
|
if ((bestSupernode)||(strictAvoid)) |
|
|
|
return bestSupernode; |
|
|
|
return bestSupernode; |
|
|
|
|
|
|
|
|
|
|
|
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) { |
|
|
|
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) { |
|
|
|
if ((*sn)->hasActiveDirectPath(now)) { // only consider those that responded to pings
|
|
|
|
if ((*sn)->hasActiveDirectPath(now)) { |
|
|
|
unsigned int l = (*sn)->latency(); |
|
|
|
unsigned int l = (*sn)->latency(); |
|
|
|
if ((l)&&(l <= bestSupernodeLatency)) { |
|
|
|
if (bestSupernode) { |
|
|
|
bestSupernodeLatency = l; |
|
|
|
if ((l)&&(l < bestSupernodeLatency)) { |
|
|
|
|
|
|
|
bestSupernodeLatency = l; |
|
|
|
|
|
|
|
bestSupernode = *sn; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (l) |
|
|
|
|
|
|
|
bestSupernodeLatency = l; |
|
|
|
bestSupernode = *sn; |
|
|
|
bestSupernode = *sn; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -185,16 +201,7 @@ skip_and_try_next_supernode: |
|
|
|
if (bestSupernode) |
|
|
|
if (bestSupernode) |
|
|
|
return bestSupernode; |
|
|
|
return bestSupernode; |
|
|
|
|
|
|
|
|
|
|
|
uint64_t bestSupernodeLastDirectReceive = 0; |
|
|
|
return _supernodePeers[Utils::randomInt<unsigned int>() % _supernodePeers.size()]; |
|
|
|
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) { |
|
|
|
|
|
|
|
uint64_t l = (*sn)->lastDirectReceive(); |
|
|
|
|
|
|
|
if (l > bestSupernodeLastDirectReceive) { |
|
|
|
|
|
|
|
bestSupernodeLastDirectReceive = l; |
|
|
|
|
|
|
|
bestSupernode = *sn; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return bestSupernode; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Topology::clean() |
|
|
|
void Topology::clean() |
|
|
|
|