diff --git a/node/Constants.hpp b/node/Constants.hpp index ac9dbc99c..1f0d8426c 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -319,6 +319,11 @@ */ #define ZT_MIN_PATH_CONFIRMATION_INTERVAL 5000 +/** + * Interval between direct path pushes in milliseconds + */ +#define ZT_DIRECT_PATH_PUSH_INTERVAL 300000 + /** * Sanity limit on maximum bridge routes * diff --git a/node/Packet.hpp b/node/Packet.hpp index 14fac1bf4..9b86709a2 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -892,7 +892,6 @@ public: VERB_SET_EPHEMERAL_KEY = 15, /* Push of potential endpoints for direct communication: - * <[1] flags (unused, must be zero)> * <[2] 16-bit number of paths> * <[...] paths> * diff --git a/node/Peer.cpp b/node/Peer.cpp index cb046b9b0..ec04357ae 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -208,9 +208,66 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) } } -//void Peer::pushDirectPaths(const std::vector &dps,uint64_t now,bool force) -//{ -//} +void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector &dps,uint64_t now,bool force) +{ + if (((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force)) { + _lastDirectPathPush = now; + + std::vector::const_iterator p(dps.begin()); + while (p != dps.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 != dps.end())&&((outp.size() + 24) < ZT_PROTO_MAX_PACKET_LENGTH)) { + uint8_t addressType = 4; + switch(p->address().ss_family) { + case AF_INET: + break; + case AF_INET6: + addressType = 6; + break; + default: + ++p; + continue; + } + + uint8_t flags = 0; + if (p->metric() < 0) + flags |= (0x01 | 0x02); // forget and blacklist + else { + if (p->reliable()) + flags |= 0x04; // no NAT keepalives and such + switch(p->trust()) { + default: + break; + case Path::TRUST_PRIVACY: + flags |= 0x08; // no encryption + break; + case Path::TRUST_ULTIMATE: + flags |= (0x08 | 0x10); // no encryption, no authentication (redundant but go ahead and set both) + break; + } + } + + outp.append(flags); + outp.append((uint8_t)((p->metric() >= 0) ? ((p->metric() <= 255) ? p->metric() : 255) : 0)); + outp.append((uint16_t)0); + outp.append(addressType); + outp.append(p->address().rawIpData(),((addressType == 4) ? 4 : 16)); + outp.append((uint16_t)p->address().port()); + + ++count; + ++p; + } + + if (count) { + outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); + RR->sw->send(outp,true,0); + } + } + } +} void Peer::addPath(const RemotePath &newp) { diff --git a/node/Peer.hpp b/node/Peer.hpp index 6ca29393c..2af3b9e69 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -181,11 +181,12 @@ public: /** * Push direct paths (if within rate limit) * + * @param RR Runtime environment * @param dps Direct paths to me to push to this peer * @param now Current time * @param force If true, force regardless of when we pushed direct paths last */ - void pushDirectPaths(const std::vector &dps,uint64_t now,bool force); + void pushDirectPaths(const RuntimeEnvironment *RR,const std::vector &dps,uint64_t now,bool force); /** * @return All known direct paths to this peer