Harden PUSH_DIRECT_PATHS and simplify things by only doing it on receive when hops>0 and trust has been established.

This commit is contained in:
Adam Ierymenko 2016-08-24 16:16:39 -07:00
parent 63e8ad4cc3
commit c476285bd6
4 changed files with 135 additions and 137 deletions

View file

@ -66,7 +66,8 @@ void Peer::received(
uint64_t packetId,
Packet::Verb verb,
uint64_t inRePacketId,
Packet::Verb inReVerb)
Packet::Verb inReVerb,
const bool trustEstablished)
{
#ifdef ZT_ENABLE_CLUSTER
bool suboptimalPath = false;
@ -184,6 +185,8 @@ void Peer::received(
}
}
} else if (trustEstablished) {
_pushDirectPaths(localAddr,remoteAddr,now);
}
if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
@ -241,90 +244,6 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
return false;
}
bool Peer::pushDirectPaths(const InetAddress &localAddr,const InetAddress &toAddress,uint64_t now,bool force)
{
#ifdef ZT_ENABLE_CLUSTER
// Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection
if (RR->cluster)
return false;
#endif
if (!force) {
if ((now - _lastDirectPathPushSent) < ZT_DIRECT_PATH_PUSH_INTERVAL)
return false;
else _lastDirectPathPushSent = now;
}
std::vector<InetAddress> pathsToPush;
std::vector<InetAddress> dps(RR->node->directPaths());
for(std::vector<InetAddress>::const_iterator i(dps.begin());i!=dps.end();++i)
pathsToPush.push_back(*i);
std::vector<InetAddress> sym(RR->sa->getSymmetricNatPredictions());
for(unsigned long i=0,added=0;i<sym.size();++i) {
InetAddress tmp(sym[(unsigned long)RR->node->prng() % sym.size()]);
if (std::find(pathsToPush.begin(),pathsToPush.end(),tmp) == pathsToPush.end()) {
pathsToPush.push_back(tmp);
if (++added >= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY)
break;
}
}
if (pathsToPush.empty())
return false;
#ifdef ZT_TRACE
{
std::string ps;
for(std::vector<InetAddress>::const_iterator p(pathsToPush.begin());p!=pathsToPush.end();++p) {
if (ps.length() > 0)
ps.push_back(',');
ps.append(p->toString());
}
TRACE("pushing %u direct paths to %s: %s",(unsigned int)pathsToPush.size(),_id.address().toString().c_str(),ps.c_str());
}
#endif
std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
while (p != pathsToPush.end()) {
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
outp.addSize(2); // leave room for count
unsigned int count = 0;
while ((p != pathsToPush.end())&&((outp.size() + 24) < 1200)) {
uint8_t addressType = 4;
switch(p->ss_family) {
case AF_INET:
break;
case AF_INET6:
addressType = 6;
break;
default: // we currently only push IP addresses
++p;
continue;
}
outp.append((uint8_t)0); // no flags
outp.append((uint16_t)0); // no extensions
outp.append(addressType);
outp.append((uint8_t)((addressType == 4) ? 6 : 18));
outp.append(p->rawIpData(),((addressType == 4) ? 4 : 16));
outp.append((uint16_t)p->port());
++count;
++p;
}
if (count) {
outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
outp.armor(_key,true);
RR->node->putPacket(localAddr,toAddress,outp.data(),outp.size(),0);
}
}
return true;
}
bool Peer::resetWithinScope(InetAddress::IpScope scope,uint64_t now)
{
unsigned int np = _numPaths;
@ -453,4 +372,86 @@ Path *Peer::_getBestPath(const uint64_t now,int inetAddressFamily)
return bestPath;
}
bool Peer::_pushDirectPaths(const InetAddress &localAddr,const InetAddress &toAddress,uint64_t now)
{
#ifdef ZT_ENABLE_CLUSTER
// Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection
if (RR->cluster)
return false;
#endif
if ((now - _lastDirectPathPushSent) < ZT_DIRECT_PATH_PUSH_INTERVAL)
return false;
else _lastDirectPathPushSent = now;
std::vector<InetAddress> pathsToPush;
std::vector<InetAddress> dps(RR->node->directPaths());
for(std::vector<InetAddress>::const_iterator i(dps.begin());i!=dps.end();++i)
pathsToPush.push_back(*i);
std::vector<InetAddress> sym(RR->sa->getSymmetricNatPredictions());
for(unsigned long i=0,added=0;i<sym.size();++i) {
InetAddress tmp(sym[(unsigned long)RR->node->prng() % sym.size()]);
if (std::find(pathsToPush.begin(),pathsToPush.end(),tmp) == pathsToPush.end()) {
pathsToPush.push_back(tmp);
if (++added >= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY)
break;
}
}
if (pathsToPush.empty())
return false;
#ifdef ZT_TRACE
{
std::string ps;
for(std::vector<InetAddress>::const_iterator p(pathsToPush.begin());p!=pathsToPush.end();++p) {
if (ps.length() > 0)
ps.push_back(',');
ps.append(p->toString());
}
TRACE("pushing %u direct paths to %s: %s",(unsigned int)pathsToPush.size(),_id.address().toString().c_str(),ps.c_str());
}
#endif
std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
while (p != pathsToPush.end()) {
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS);
outp.addSize(2); // leave room for count
unsigned int count = 0;
while ((p != pathsToPush.end())&&((outp.size() + 24) < 1200)) {
uint8_t addressType = 4;
switch(p->ss_family) {
case AF_INET:
break;
case AF_INET6:
addressType = 6;
break;
default: // we currently only push IP addresses
++p;
continue;
}
outp.append((uint8_t)0); // no flags
outp.append((uint16_t)0); // no extensions
outp.append(addressType);
outp.append((uint8_t)((addressType == 4) ? 6 : 18));
outp.append(p->rawIpData(),((addressType == 4) ? 4 : 16));
outp.append((uint16_t)p->port());
++count;
++p;
}
if (count) {
outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count);
outp.armor(_key,true);
RR->node->putPacket(localAddr,toAddress,outp.data(),outp.size(),0);
}
}
return true;
}
} // namespace ZeroTier