|
@@ -180,6 +180,20 @@ public:
|
|
f(*this,p->second);
|
|
f(*this,p->second);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Apply a function or function object to all supernode peers
|
|
|
|
+ *
|
|
|
|
+ * @param f Function to apply
|
|
|
|
+ * @tparam F Function or function object type
|
|
|
|
+ */
|
|
|
|
+ template<typename F>
|
|
|
|
+ inline void eachSupernodePeer(F f)
|
|
|
|
+ {
|
|
|
|
+ Mutex::Lock _l(_supernodes_m);
|
|
|
|
+ for(std::vector< SharedPtr<Peer> >::const_iterator p(_supernodePeers.begin());p!=_supernodePeers.end();++p)
|
|
|
|
+ f(*this,*p);
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Function object to collect peers that need a firewall opener sent
|
|
* Function object to collect peers that need a firewall opener sent
|
|
*/
|
|
*/
|
|
@@ -214,20 +228,16 @@ public:
|
|
|
|
|
|
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
|
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
|
{
|
|
{
|
|
- if (
|
|
|
|
- /* 1: we have not heard anything directly in ZT_PEER_DIRECT_PING_DELAY ms */
|
|
|
|
- ((_now - p->lastDirectReceive()) >= ZT_PEER_DIRECT_PING_DELAY) &&
|
|
|
|
- /* 2: */
|
|
|
|
- (
|
|
|
|
- /* 2a: peer has direct path, and has sent us something recently */
|
|
|
|
- (
|
|
|
|
- (p->hasDirectPath())&&
|
|
|
|
- ((_now - p->lastFrame()) < ZT_PEER_PATH_ACTIVITY_TIMEOUT)
|
|
|
|
- ) &&
|
|
|
|
- /* 2b: peer is not a supernode */
|
|
|
|
- (!_supernodeAddresses.count(p->address()))
|
|
|
|
- )
|
|
|
|
- ) { p->sendPing(_r,_now); }
|
|
|
|
|
|
+ /* For ordinary nodes we ping if they've sent us a frame recently,
|
|
|
|
+ * otherwise they are stale and we let the link die.
|
|
|
|
+ *
|
|
|
|
+ * Note that we measure ping time from time of last receive rather
|
|
|
|
+ * than time of last send in order to only count full round trips. */
|
|
|
|
+ if ( (!_supernodeAddresses.count(p->address())) &&
|
|
|
|
+ ((_now - p->lastFrame()) < ZT_PEER_PATH_ACTIVITY_TIMEOUT) &&
|
|
|
|
+ ((_now - p->lastDirectReceive()) > ZT_PEER_DIRECT_PING_DELAY) ) {
|
|
|
|
+ p->sendPing(_r,_now);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
private:
|
|
private:
|
|
@@ -236,6 +246,30 @@ public:
|
|
const RuntimeEnvironment *_r;
|
|
const RuntimeEnvironment *_r;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Ping peers that need ping according to supernode rules (slightly more aggressive)
|
|
|
|
+ */
|
|
|
|
+ class PingSupernodesThatNeedPing
|
|
|
|
+ {
|
|
|
|
+ public:
|
|
|
|
+ PingSupernodesThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) throw() :
|
|
|
|
+ _now(now),
|
|
|
|
+ _r(renv) {}
|
|
|
|
+
|
|
|
|
+ inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
|
|
|
+ {
|
|
|
|
+ /* For supernodes we always ping even if no frames have been seen, and
|
|
|
|
+ * we ping aggressively if pings are unanswered. The limit to this
|
|
|
|
+ * frequency is set in the main loop to no more than ZT_STARTUP_AGGRO. */
|
|
|
|
+ if ( (p->pingUnanswered(_r,_now)) || ((_now - p->lastDirectReceive()) > ZT_PEER_DIRECT_PING_DELAY) )
|
|
|
|
+ p->sendPing(_r,_now);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private:
|
|
|
|
+ uint64_t _now;
|
|
|
|
+ const RuntimeEnvironment *_r;
|
|
|
|
+ };
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Function object to forget direct links to active peers and then ping them indirectly
|
|
* Function object to forget direct links to active peers and then ping them indirectly
|
|
*
|
|
*
|