diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2014-02-03 11:09:09 -0800 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2014-02-03 11:09:09 -0800 |
commit | d04e5a1fe01f1d1c732a1c2d138d2a417f4dbbfb (patch) | |
tree | 7364cc57dd5e306cde66357acde8a3752d6594f3 | |
parent | bf5f09a0c7e388f622c0466f3bec19605c3990b2 (diff) | |
download | infinitytier-d04e5a1fe01f1d1c732a1c2d138d2a417f4dbbfb.tar.gz infinitytier-d04e5a1fe01f1d1c732a1c2d138d2a417f4dbbfb.zip |
Add a simple but very nice mechanism for avoiding potentially dead supernodes.
-rw-r--r-- | node/Constants.hpp | 5 | ||||
-rw-r--r-- | node/Topology.cpp | 27 |
2 files changed, 24 insertions, 8 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp index e64fec1c..241fb742 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -305,6 +305,11 @@ error_no_byte_order_defined; #define ZT_PEER_LINK_ACTIVITY_TIMEOUT ((ZT_PEER_DIRECT_PING_DELAY * 2) + 1000) /** + * Stop relaying via peers that have not responded to direct sends in this long + */ +#define ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD 10000 + +/** * Number of outgoing verb/packetId pairs to keep for sends expecting responses */ #define ZT_PEER_REQUEST_HISTORY_LENGTH 8 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(); |