summaryrefslogtreecommitdiff
path: root/node/Peer.cpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-31 22:23:55 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-03-31 22:23:55 -0700
commitf13493edb2aae228ddbe70cc2f0609c541faf2d7 (patch)
treecb1a6845ec82e2ea361ce15e88440a249992091c /node/Peer.cpp
parent595b386afcd4e4eca0cf379cd14689c1db8ee647 (diff)
downloadinfinitytier-f13493edb2aae228ddbe70cc2f0609c541faf2d7.tar.gz
infinitytier-f13493edb2aae228ddbe70cc2f0609c541faf2d7.zip
Oops... turns out we need to differentiate incoming from outgoing TCP and indeed learn incoming TCP paths. Otherwise the recipient of a TCP connection does not know to reply via TCP! Heh.
Diffstat (limited to 'node/Peer.cpp')
-rw-r--r--node/Peer.cpp80
1 files changed, 48 insertions, 32 deletions
diff --git a/node/Peer.cpp b/node/Peer.cpp
index f7d24fee..6e8ecc01 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -69,25 +69,36 @@ void Peer::receive(
Packet::Verb inReVerb,
uint64_t now)
{
+ // Update system-wide last packet receive time
*((const_cast<uint64_t *>(&(_r->timeOfLastPacketReceived)))) = now;
- if (!hops) { // direct packet
+ // Learn paths from direct packets (hops == 0)
+ if (!hops) {
{
Mutex::Lock _l(_lock);
- // Update receive time on known paths
bool havePath = false;
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
- if ((p->address() == remoteAddr)&&(p->tcp() == (fromSock->type() == Socket::ZT_SOCKET_TYPE_TCP))) {
+ if ((p->address() == remoteAddr)&&(p->tcp() == fromSock->tcp())) {
p->received(now);
havePath = true;
break;
}
}
- // Learn new UDP paths (learning TCP would require an explicit mechanism)
- if ((!havePath)&&(fromSock->type() != Socket::ZT_SOCKET_TYPE_TCP)) {
- _paths.push_back(Path(remoteAddr,false,false));
+ if (!havePath) {
+ Path::Type pt = Path::PATH_TYPE_UDP;
+ switch(fromSock->type()) {
+ case Socket::ZT_SOCKET_TYPE_TCP_IN:
+ pt = Path::PATH_TYPE_TCP_IN;
+ break;
+ case Socket::ZT_SOCKET_TYPE_TCP_OUT:
+ pt = Path::PATH_TYPE_TCP_OUT;
+ break;
+ default:
+ break;
+ }
+ _paths.push_back(Path(remoteAddr,pt,false));
_paths.back().received(now);
}
}
@@ -110,26 +121,30 @@ bool Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int len,u
{
Mutex::Lock _l(_lock);
- 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 = p->lastReceived();
- std::vector<Path>::iterator bestPath = p;
- while (++p != _paths.end()) {
- uint64_t lr = p->lastReceived();
- if (lr > bestPathLastReceived) {
- bestPathLastReceived = lr;
- bestPath = p;
+ for(;;) {
+ std::vector<Path>::iterator p(_paths.begin());
+ if (p == _paths.end())
+ return false;
+
+ uint64_t bestPathLastReceived = p->lastReceived();
+ std::vector<Path>::iterator bestPath = p;
+ while (++p != _paths.end()) {
+ uint64_t lr = p->lastReceived();
+ 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;
+ if (_r->sm->send(bestPath->address(),bestPath->tcp(),bestPath->type() == Path::PATH_TYPE_TCP_OUT,data,len)) {
+ bestPath->sent(now);
+ return true;
+ } else {
+ if (bestPath->fixed())
+ return false;
+ _paths.erase(bestPath);
+ // ... try again and pick a different path
+ }
}
return false;
@@ -160,23 +175,24 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now,bool firstSinceRes
bool pingTcp;
if (!firstSinceReset) {
- // Do not use TCP if one of our UDP endpoints has answered recently.
+ uint64_t lastUdp = 0;
+ uint64_t lastTcp = 0;
uint64_t lastPing = 0;
- uint64_t lastDirectReceive = 0;
-
for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
- lastPing = std::max(lastPing,p->lastPing());
- lastDirectReceive = std::max(lastDirectReceive,p->lastReceived());
+ if (p->tcp())
+ lastTcp = std::max(p->lastReceived(),lastTcp);
+ else lastUdp = std::max(p->lastReceived(),lastUdp);
+ lastPing = std::max(p->lastPing(),lastPing);
}
-
- pingTcp = ( (lastDirectReceive < lastPing) && ((lastPing - lastDirectReceive) >= ZT_PING_UNANSWERED_AFTER) );
+ uint64_t lastAny = std::max(lastUdp,lastTcp);
+ pingTcp = ( ( (lastAny < lastPing) && ((lastPing - lastAny) >= ZT_PING_UNANSWERED_AFTER) ) || (lastTcp > lastUdp) );
} 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 ((pingTcp)||(!p->tcp())) {
- if (_r->sw->sendHELLO(self,p->address(),p->tcp())) {
+ if (_r->sw->sendHELLO(self,*p)) {
p->sent(now);
p->pinged(now);
sent = true;