summaryrefslogtreecommitdiff
path: root/node/Peer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Peer.cpp')
-rw-r--r--node/Peer.cpp108
1 files changed, 76 insertions, 32 deletions
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 87882dad..fa3ce6c8 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -37,13 +37,11 @@
namespace ZeroTier {
-// Used to send varying values for NAT keepalive
-static uint32_t _natKeepaliveBuf = 0;
-
Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
+ RR(renv),
_lastReceive(0),
- _lastUnicastFrame(0),
- _lastMulticastFrame(0),
+ _lastNontrivialReceive(0),
+ _lastTriedMemorizedPath(0),
_lastDirectPathPushSent(0),
_lastDirectPathPushReceive(0),
_lastCredentialRequestSent(0),
@@ -53,7 +51,6 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
_lastComRequestSent(0),
_lastCredentialsReceived(0),
_lastTrustEstablishedPacketReceived(0),
- RR(renv),
_remoteClusterOptimal4(0),
_vProto(0),
_vMajor(0),
@@ -104,7 +101,7 @@ void Peer::received(
outp.append(redirectTo.rawIpData(),16);
}
outp.append((uint16_t)redirectTo.port());
- outp.armor(_key,true);
+ outp.armor(_key,true,path->nextOutgoingCounter());
path->send(RR,outp.data(),outp.size(),now);
} else {
// For older peers we use RENDEZVOUS to coax them into contacting us elsewhere.
@@ -119,7 +116,7 @@ void Peer::received(
outp.append((uint8_t)16);
outp.append(redirectTo.rawIpData(),16);
}
- outp.armor(_key,true);
+ outp.armor(_key,true,path->nextOutgoingCounter());
path->send(RR,outp.data(),outp.size(),now);
}
suboptimalPath = true;
@@ -128,16 +125,25 @@ void Peer::received(
#endif
_lastReceive = now;
- if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME))
- _lastUnicastFrame = now;
- else if (verb == Packet::VERB_MULTICAST_FRAME)
- _lastMulticastFrame = now;
+ switch (verb) {
+ case Packet::VERB_FRAME:
+ case Packet::VERB_EXT_FRAME:
+ case Packet::VERB_NETWORK_CONFIG_REQUEST:
+ case Packet::VERB_NETWORK_CONFIG:
+ case Packet::VERB_MULTICAST_FRAME:
+ _lastNontrivialReceive = now;
+ break;
+ default: break;
+ }
if (trustEstablished) {
_lastTrustEstablishedPacketReceived = now;
path->trustedPacketReceived(now);
}
+ if (_vProto >= 9)
+ path->updateLinkQuality((unsigned int)(packetId & 7));
+
if (hops == 0) {
bool pathIsConfirmed = false;
{
@@ -155,7 +161,7 @@ void Peer::received(
}
}
- if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(path->localAddress(),path->address())) ) {
+ if ( (!pathIsConfirmed) && (RR->node->shouldUsePathForZeroTierTraffic(_id.address(),path->localAddress(),path->address())) ) {
if (verb == Packet::VERB_OK) {
Mutex::Lock _l(_paths_m);
@@ -200,11 +206,11 @@ void Peer::received(
#endif
} else {
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str());
- attemptToContactAt(path->localAddress(),path->address(),now);
+ attemptToContactAt(path->localAddress(),path->address(),now,true,path->nextOutgoingCounter());
path->sent(now);
}
}
- } else if (trustEstablished) {
+ } else if (this->trustEstablished(now)) {
// Send PUSH_DIRECT_PATHS if hops>0 (relayed) and we have a trust relationship (common network membership)
#ifdef ZT_ENABLE_CLUSTER
// Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection
@@ -274,7 +280,7 @@ void Peer::received(
if (count) {
outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
- outp.armor(_key,true);
+ outp.armor(_key,true,path->nextOutgoingCounter());
path->send(RR,outp.data(),outp.size(),now);
}
}
@@ -339,9 +345,10 @@ SharedPtr<Path> Peer::getBestPath(uint64_t now,bool includeExpired)
}
}
-void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now)
+void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int counter)
{
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
+
outp.append((unsigned char)ZT_PROTO_VERSION);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
@@ -349,22 +356,62 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u
outp.append(now);
RR->identity.serialize(outp,false);
atAddress.serialize(outp);
- outp.append((uint64_t)RR->topology->worldId());
- outp.append((uint64_t)RR->topology->worldTimestamp());
+
+ outp.append((uint64_t)RR->topology->planetWorldId());
+ outp.append((uint64_t)RR->topology->planetWorldTimestamp());
+
+ const unsigned int startCryptedPortionAt = outp.size();
+
+ std::vector<World> moons(RR->topology->moons());
+ std::vector<uint64_t> moonsWanted(RR->topology->moonsWanted());
+ outp.append((uint16_t)(moons.size() + moonsWanted.size()));
+ for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) {
+ outp.append((uint8_t)m->type());
+ outp.append((uint64_t)m->id());
+ outp.append((uint64_t)m->timestamp());
+ }
+ for(std::vector<uint64_t>::const_iterator m(moonsWanted.begin());m!=moonsWanted.end();++m) {
+ outp.append((uint8_t)World::TYPE_MOON);
+ outp.append(*m);
+ outp.append((uint64_t)0);
+ }
+
+ const unsigned int corSizeAt = outp.size();
+ outp.addSize(2);
+ RR->topology->appendCertificateOfRepresentation(outp);
+ outp.setAt(corSizeAt,(uint16_t)(outp.size() - (corSizeAt + 2)));
+
+ outp.cryptField(_key,startCryptedPortionAt,outp.size() - startCryptedPortionAt);
+
RR->node->expectReplyTo(outp.packetId());
- outp.armor(_key,false); // HELLO is sent in the clear
- RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size());
+
+ if (atAddress) {
+ outp.armor(_key,false,counter); // false == don't encrypt full payload, but add MAC
+ RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size());
+ } else {
+ RR->sw->send(outp,false); // false == don't encrypt full payload, but add MAC
+ }
}
-void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now)
+void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter)
{
- if ( (_vProto >= 5) && ( !((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0)) ) ) {
+ if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) {
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
RR->node->expectReplyTo(outp.packetId());
- outp.armor(_key,true);
+ outp.armor(_key,true,counter);
RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size());
} else {
- sendHELLO(localAddr,atAddress,now);
+ sendHELLO(localAddr,atAddress,now,counter);
+ }
+}
+
+void Peer::tryMemorizedPath(uint64_t now)
+{
+ if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
+ _lastTriedMemorizedPath = now;
+ InetAddress mp;
+ if (RR->node->externalPathLookup(_id.address(),-1,mp))
+ attemptToContactAt(InetAddress(),mp,now,true,0);
}
}
@@ -385,12 +432,9 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
}
if (bestp >= 0) {
- if ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) {
- attemptToContactAt(_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now);
+ if ( ((now - _paths[bestp].lastReceive) >= ZT_PEER_PING_PERIOD) || (_paths[bestp].path->needsHeartbeat(now)) ) {
+ attemptToContactAt(_paths[bestp].path->localAddress(),_paths[bestp].path->address(),now,false,_paths[bestp].path->nextOutgoingCounter());
_paths[bestp].path->sent(now);
- } else if (_paths[bestp].path->needsHeartbeat(now)) {
- _natKeepaliveBuf += (uint32_t)((now * 0x9e3779b1) >> 1); // tumble this around to send constantly varying (meaningless) payloads
- _paths[bestp].path->send(RR,&_natKeepaliveBuf,sizeof(_natKeepaliveBuf),now);
}
return true;
} else {
@@ -413,14 +457,14 @@ void Peer::resetWithinScope(InetAddress::IpScope scope,int inetAddressFamily,uin
Mutex::Lock _l(_paths_m);
for(unsigned int p=0;p<_numPaths;++p) {
if ( (_paths[p].path->address().ss_family == inetAddressFamily) && (_paths[p].path->address().ipScope() == scope) ) {
- attemptToContactAt(_paths[p].path->localAddress(),_paths[p].path->address(),now);
+ attemptToContactAt(_paths[p].path->localAddress(),_paths[p].path->address(),now,false,_paths[p].path->nextOutgoingCounter());
_paths[p].path->sent(now);
_paths[p].lastReceive = 0; // path will not be used unless it speaks again
}
}
}
-void Peer::getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) const
+void Peer::getRendezvousAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) const
{
Mutex::Lock _l(_paths_m);