diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-04-30 21:09:41 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-04-30 21:09:41 -0700 |
commit | 9279bac385d842d7f031306bc9a68bbb737bd3ce (patch) | |
tree | b582112fe43b1ba87d5115af32f300d8b6122763 /node | |
parent | 105e1a016f5a4a5a6c2ed51bceb33e4f684a135f (diff) | |
download | infinitytier-9279bac385d842d7f031306bc9a68bbb737bd3ce.tar.gz infinitytier-9279bac385d842d7f031306bc9a68bbb737bd3ce.zip |
Fix deadlock in SelfAwareness by deferring reconnects.
Diffstat (limited to 'node')
-rw-r--r-- | node/Peer.cpp | 10 | ||||
-rw-r--r-- | node/Peer.hpp | 7 | ||||
-rw-r--r-- | node/SelfAwareness.cpp | 31 |
3 files changed, 34 insertions, 14 deletions
diff --git a/node/Peer.cpp b/node/Peer.cpp index 526e3a28..7c0868eb 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -261,7 +261,7 @@ void Peer::clearPaths(bool fixedToo) } } -void Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope scope,uint64_t now) +bool Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope scope,uint64_t now) { unsigned int np = _numPaths; unsigned int x = 0; @@ -278,13 +278,7 @@ void Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope sc ++x; } _numPaths = y; - - if ((y < np)&&(alive(now))) { - // Try to re-establish direct connectivity to this peer if it's alive - // and we have forgotten paths to it. - Packet outp(_id.address(),RR->identity.address(),Packet::VERB_NOP); - RR->sw->send(outp,true); - } + return (y < np); } void Peer::getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6,unsigned int maxDesperation) const diff --git a/node/Peer.hpp b/node/Peer.hpp index e36b0c7b..343cfcfa 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -311,15 +311,14 @@ public: * Reset paths within a given scope * * For fixed paths in this scope, a packet is sent. Non-fixed paths in this - * scope are forgotten. If there are no paths remaining, a message is sent - * indirectly to reestablish connectivity if we're actively exchanging - * data with this peer (alive). + * scope are forgotten. * * @param RR Runtime environment * @param scope IP scope of paths to reset * @param now Current time + * @return True if at least one path was forgotten */ - void resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope scope,uint64_t now); + bool resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope scope,uint64_t now); /** * @return 256-bit secret symmetric encryption key diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index b6bfe9e4..b1830ef0 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -46,7 +46,15 @@ public: RR(renv), _now(now), _scope(scope) {} - inline void operator()(Topology &t,const SharedPtr<Peer> &p) { p->resetWithinScope(RR,_scope,_now); } + + inline void operator()(Topology &t,const SharedPtr<Peer> &p) + { + if (p->resetWithinScope(RR,_scope,_now)) + peersReset.push_back(p); + } + + std::vector< SharedPtr<Peer> > peersReset; + private: const RuntimeEnvironment *RR; uint64_t _now; @@ -84,8 +92,27 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi } else if (lastPhy != myPhysicalAddress) { TRACE("learned physical address %s for scope %u from reporter %s(%s) (replaced %s, resetting within scope)",myPhysicalAddress.toString().c_str(),scope,reporter.toString().c_str(),reporterPhysicalAddress.toString().c_str(),lastPhy.toString().c_str()); lastPhy = myPhysicalAddress; - _ResetWithinScope rset(RR,RR->node->now(),(InetAddress::IpScope)scope); + uint64_t now = RR->node->now(); + + _ResetWithinScope rset(RR,now,(InetAddress::IpScope)scope); RR->topology->eachPeer<_ResetWithinScope &>(rset); + + // For all peers for whom we forgot an address, send a packet indirectly if + // they are still considered alive so that we will re-establish direct links. + SharedPtr<Peer> sn(RR->topology->getBestSupernode()); + if (sn) { + Path *snp = sn->getBestPath(now); + if (snp) { + for(std::vector< SharedPtr<Peer> >::const_iterator p(rset.peersReset.begin());p!=rset.peersReset.end();++p) { + if ((*p)->alive(now)) { + TRACE("sending indirect NOP to %s via %s(%s) to re-establish link",(*p)->address().toString().c_str(),sn->address().toString().c_str(),snp->address().toString().c_str()); + Packet outp((*p)->address(),RR->identity.address(),Packet::VERB_NOP); + outp.armor((*p)->key(),true); + snp->send(RR,outp.data(),outp.size(),now); + } + } + } + } } } } |