summaryrefslogtreecommitdiff
path: root/node/Peer.cpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-27 18:23:02 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-27 18:23:02 -0700
commitb73c36acbf03431fd7fa3584e8621875fdcbebf4 (patch)
treea08a976e4d4a63efecc2892bc969cc60141b4c5f /node/Peer.cpp
parent181369964f501c3c702971b30c82b9e84eed58db (diff)
parentd2c5d7150253a5ae5613cac1d65e84b3aa5d33bc (diff)
downloadinfinitytier-b73c36acbf03431fd7fa3584e8621875fdcbebf4.tar.gz
infinitytier-b73c36acbf03431fd7fa3584e8621875fdcbebf4.zip
Merge branch 'adamierymenko-dev' of ssh://shub-niggurath.zerotier.com:222/git/ZeroTierOne into adamierymenko-dev
Diffstat (limited to 'node/Peer.cpp')
-rw-r--r--node/Peer.cpp44
1 files changed, 30 insertions, 14 deletions
diff --git a/node/Peer.cpp b/node/Peer.cpp
index b9b9b0c7..fa8ab3e8 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -69,6 +69,8 @@ void Peer::receive(
Packet::Verb inReVerb,
uint64_t now)
{
+ *((const_cast<uint64_t *>(&(_r->timeOfLastPacketReceived)))) = now;
+
if (!hops) { // direct packet
{
Mutex::Lock _l(_lock);
@@ -91,6 +93,7 @@ void Peer::receive(
}
// Announce multicast LIKEs to peers to whom we have a direct link
+ // Lock can't be locked here or it'll recurse and deadlock.
if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
_lastAnnouncedTo = now;
_r->sw->announceMulticastGroups(SharedPtr<Peer>(this));
@@ -107,19 +110,23 @@ bool Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int len,u
{
Mutex::Lock _l(_lock);
- if (_paths.empty())
+ std::vector<Path>::iterator p(_paths.begin());
+ if (p == _paths.end()) {
+ TRACE("send to %s failed: no paths available",_id.address().toString().c_str());
return false;
-
- uint64_t bestPathLastReceived = 0;
- std::vector<Path>::iterator bestPath;
- for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
+ }
+ uint64_t bestPathLastReceived = p->lastReceived();
+ std::vector<Path>::iterator bestPath = p;
+ while (++p != _paths.end()) {
uint64_t lr = p->lastReceived();
- if (lr >= bestPathLastReceived) {
+ if (lr > bestPathLastReceived) {
bestPathLastReceived = lr;
bestPath = p;
}
}
+ TRACE("send to %s: using path: %s",_id.address().toString().c_str(),bestPath->toString().c_str());
+
if (_r->sm->send(bestPath->address(),bestPath->tcp(),data,len)) {
bestPath->sent(now);
return true;
@@ -145,21 +152,30 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now,bool firstSinceRes
{
bool sent = false;
SharedPtr<Peer> self(this);
+
Mutex::Lock _l(_lock);
- bool allPingsUnanswered;
+ // NOTE: this will never ping a peer that has *only* TCP paths. Right
+ // now there's never such a thing as TCP is only for failover.
+
+ bool pingTcp;
if (!firstSinceReset) {
- allPingsUnanswered = true;
+ // Do not use TCP if one of our UDP endpoints has answered recently.
+ uint64_t lastPing = 0;
+ uint64_t lastDirectReceive = 0;
+
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
- if (!p->pingUnanswered(now)) {
- allPingsUnanswered = false;
- break;
- }
+ lastPing = std::max(lastPing,p->lastPing());
+ lastDirectReceive = std::max(lastDirectReceive,p->lastReceived());
}
- } else allPingsUnanswered = false;
+
+ pingTcp = ( (lastDirectReceive < lastPing) && ((lastPing - lastDirectReceive) >= ZT_PING_UNANSWERED_AFTER) );
+ } else pingTcp = false;
+
+ TRACE("PING %s (pingTcp==%d)",_id.address().toString().c_str(),(int)pingTcp);
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
- if ((allPingsUnanswered)||(!p->tcp())) {
+ if ((pingTcp)||(!p->tcp())) {
if (_r->sw->sendHELLO(self,p->address(),p->tcp())) {
p->sent(now);
p->pinged(now);