summaryrefslogtreecommitdiff
path: root/node/Topology.cpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-02-03 11:09:09 -0800
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-02-03 11:09:09 -0800
commitd04e5a1fe01f1d1c732a1c2d138d2a417f4dbbfb (patch)
tree7364cc57dd5e306cde66357acde8a3752d6594f3 /node/Topology.cpp
parentbf5f09a0c7e388f622c0466f3bec19605c3990b2 (diff)
downloadinfinitytier-d04e5a1fe01f1d1c732a1c2d138d2a417f4dbbfb.tar.gz
infinitytier-d04e5a1fe01f1d1c732a1c2d138d2a417f4dbbfb.zip
Add a simple but very nice mechanism for avoiding potentially dead supernodes.
Diffstat (limited to 'node/Topology.cpp')
-rw-r--r--node/Topology.cpp27
1 files changed, 19 insertions, 8 deletions
diff --git a/node/Topology.cpp b/node/Topology.cpp
index b499063c..b3748da6 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -134,19 +134,31 @@ void Topology::saveIdentity(const Identity &id)
SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const
{
SharedPtr<Peer> bestSupernode;
- unsigned int bestSupernodeLatency = 0xffff;
+ unsigned int bestSupernodeLatency = 65536;
uint64_t now = Utils::now();
Mutex::Lock _l(_supernodes_m);
- if (_supernodePeers.empty())
- return bestSupernode;
-
+ // First look for a best supernode by comparing latencies, but exclude
+ // supernodes that have not responded to direct messages in order to
+ // try to exclude any that are dead or unreachable.
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();) {
+ // Skip explicitly avoided relays
for(unsigned int i=0;i<avoidCount;++i) {
- if (avoid[i] == (*sn)->address())
- goto skip_and_try_next_supernode;
+ if (avoid[i] == (*sn)->address()) {
+ ++sn;
+ continue;
+ }
}
+
+ // Skip possibly comatose or unreachable relays
+ uint64_t lds = (*sn)->lastDirectSend();
+ uint64_t ldr = (*sn)->lastDirectReceive();
+ if ((lds)&&(ldr > lds)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD)) {
+ ++sn;
+ continue;
+ }
+
if ((*sn)->hasActiveDirectPath(now)) {
unsigned int l = (*sn)->latency();
if (bestSupernode) {
@@ -160,8 +172,6 @@ SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avo
bestSupernode = *sn;
}
}
-skip_and_try_next_supernode:
- ++sn;
}
if (bestSupernode) {
@@ -170,6 +180,7 @@ skip_and_try_next_supernode:
} else if (strictAvoid)
return SharedPtr<Peer>();
+ // If we have nothing from above, just pick one without avoidance criteria.
for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) {
if ((*sn)->hasActiveDirectPath(now)) {
unsigned int l = (*sn)->latency();