diff --git a/node/Node.cpp b/node/Node.cpp index 1661e9d1a..7d5bbe8b4 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -25,6 +25,12 @@ * LLC. Start here: http://www.zerotier.com/ */ +#include +#include +#include +#include +#include + #include "../version.h" #include "Constants.hpp" diff --git a/node/Peer.cpp b/node/Peer.cpp index 526e3a28f..7c0868eb7 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 e36b0c7b6..343cfcfaf 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 b6bfe9e4d..b1830ef03 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 &p) { p->resetWithinScope(RR,_scope,_now); } + + inline void operator()(Topology &t,const SharedPtr &p) + { + if (p->resetWithinScope(RR,_scope,_now)) + peersReset.push_back(p); + } + + std::vector< SharedPtr > 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 sn(RR->topology->getBestSupernode()); + if (sn) { + Path *snp = sn->getBestPath(now); + if (snp) { + for(std::vector< SharedPtr >::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); + } + } + } + } } } } diff --git a/service/OneService.cpp b/service/OneService.cpp index 3886c1573..421b47ddf 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -508,7 +508,7 @@ public: long sent = _phy.tcpSend(sock,tc->writeBuf.data(),tc->writeBuf.length(),true); if (sent > 0) { tc->lastActivity = OSUtils::now(); - if (sent == tc->writeBuf.length()) { + if ((unsigned long)sent == (unsigned long)tc->writeBuf.length()) { tc->writeBuf = ""; _phy.tcpSetNotifyWritable(sock,false); if (!tc->shouldKeepAlive)