Such ping logic. So edge case.

This commit is contained in:
Adam Ierymenko 2014-04-03 14:36:52 -07:00
parent b1088a6bd7
commit c96d3ebf8c
5 changed files with 82 additions and 27 deletions

View file

@ -180,6 +180,20 @@ public:
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
*/
@ -214,20 +228,16 @@ public:
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:
@ -236,6 +246,30 @@ public:
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
*