diff options
Diffstat (limited to 'node/Peer.hpp')
-rw-r--r-- | node/Peer.hpp | 136 |
1 files changed, 78 insertions, 58 deletions
diff --git a/node/Peer.hpp b/node/Peer.hpp index 0aca70b4..a70d9868 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -41,7 +41,7 @@ #include "RuntimeEnvironment.hpp" #include "CertificateOfMembership.hpp" -#include "RemotePath.hpp" +#include "Path.hpp" #include "Address.hpp" #include "Utils.hpp" #include "Identity.hpp" @@ -135,7 +135,7 @@ public: * @param now Current time * @return Best path or NULL if there are no active direct paths */ - inline RemotePath *getBestPath(uint64_t now) + inline Path *getBestPath(uint64_t now) { Mutex::Lock _l(_lock); return _getBestPath(now); @@ -150,14 +150,14 @@ public: * @param now Current time * @return Path used on success or NULL on failure */ - inline RemotePath *send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now) + inline Path *send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now) { - RemotePath *bestPath = getBestPath(now); + Path *bestPath = getBestPath(now); if (bestPath) { if (bestPath->send(RR,data,len,now)) return bestPath; } - return (RemotePath *)0; + return (Path *)0; } /** @@ -191,14 +191,14 @@ public: * @param now Current time * @param force If true, push regardless of rate limit */ - void pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_t now,bool force); + void pushDirectPaths(const RuntimeEnvironment *RR,Path *path,uint64_t now,bool force); /** * @return All known direct paths to this peer */ - inline std::vector<RemotePath> paths() const + inline std::vector<Path> paths() const { - std::vector<RemotePath> pp; + std::vector<Path> pp; Mutex::Lock _l(_lock); for(unsigned int p=0,np=_numPaths;p<np;++p) pp.push_back(_paths[p]); @@ -206,32 +206,6 @@ public: } /** - * @return Time of last direct packet receive for any path - */ - inline uint64_t lastDirectReceive() const - throw() - { - Mutex::Lock _l(_lock); - uint64_t x = 0; - for(unsigned int p=0,np=_numPaths;p<np;++p) - x = std::max(x,_paths[p].lastReceived()); - return x; - } - - /** - * @return Time of last direct packet send for any path - */ - inline uint64_t lastDirectSend() const - throw() - { - Mutex::Lock _l(_lock); - uint64_t x = 0; - for(unsigned int p=0,np=_numPaths;p<np;++p) - x = std::max(x,_paths[p].lastSend()); - return x; - } - - /** * @return Time of last receive of anything, whether direct or relayed */ inline uint64_t lastReceive() const throw() { return _lastReceive; } @@ -257,20 +231,38 @@ public: inline uint64_t lastAnnouncedTo() const throw() { return _lastAnnouncedTo; } /** - * @return True if peer has received an actual data frame within ZT_PEER_ACTIVITY_TIMEOUT milliseconds + * @return True if this peer is actively sending real network frames */ - inline uint64_t alive(uint64_t now) const throw() { return ((now - lastFrame()) < ZT_PEER_ACTIVITY_TIMEOUT); } + inline uint64_t activelyTransferringFrames(uint64_t now) const throw() { return ((now - lastFrame()) < ZT_PEER_ACTIVITY_TIMEOUT); } /** - * @return Current latency or 0 if unknown (max: 65535) + * @return Latency in milliseconds or 0 if unknown */ - inline unsigned int latency() const - throw() + inline unsigned int latency() const { return _latency; } + + /** + * This computes a quality score for relays and root servers + * + * If we haven't heard anything from these in ZT_PEER_ACTIVITY_TIMEOUT, they + * receive the worst possible quality (max unsigned int). Otherwise the + * quality is a product of latency and the number of potential missed + * pings. This causes roots and relays to switch over a bit faster if they + * fail. + * + * @return Relay quality score computed from latency and other factors, lower is better + */ + inline unsigned int relayQuality(const uint64_t now) const { + const uint64_t tsr = now - _lastReceive; + if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT) + return (~(unsigned int)0); unsigned int l = _latency; - return std::min(l,(unsigned int)65535); + if (!l) + l = 0xffff; + return (l * (((unsigned int)tsr / (ZT_PEER_DIRECT_PING_DELAY + 1000)) + 1)); } + /** * Update latency with a new direct measurment * @@ -286,11 +278,6 @@ public: } /** - * @return True if this peer has at least one direct IP address path - */ - inline bool hasDirectPath() const throw() { return (_numPaths != 0); } - - /** * @param now Current time * @return True if this peer has at least one active direct path */ @@ -408,19 +395,49 @@ public: bool needsOurNetworkMembershipCertificate(uint64_t nwid,uint64_t now,bool updateLastPushedTime); /** - * @return Time last direct path push was received + * Perform periodic cleaning operations */ - inline uint64_t lastDirectPathPushReceived() const throw() { return _lastDirectPathPushReceived; } + void clean(const RuntimeEnvironment *RR,uint64_t now); /** - * @param t New time of last direct path push received + * Remove all paths with this remote address + * + * @param addr Remote address to remove */ - inline void setLastDirectPathPushReceived(uint64_t t) throw() { _lastDirectPathPushReceived = t; } + inline void removePathByAddress(const InetAddress &addr) + { + Mutex::Lock _l(_lock); + unsigned int np = _numPaths; + unsigned int x = 0; + unsigned int y = 0; + while (x < np) { + if (_paths[x].address() != addr) + _paths[y++] = _paths[x]; + ++x; + } + _numPaths = y; + } /** - * Perform periodic cleaning operations + * Update direct path push stats and return true if we should respond + * + * This is a circuit breaker to make VERB_PUSH_DIRECT_PATHS not particularly + * useful as a DDOS amplification attack vector. Otherwise a malicious peer + * could send loads of these and cause others to bombard arbitrary IPs with + * traffic. + * + * @param now Current time + * @return True if we should respond */ - void clean(const RuntimeEnvironment *RR,uint64_t now); + inline bool shouldRespondToDirectPathPush(const uint64_t now) + { + Mutex::Lock _l(_lock); + if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME) + ++_directPathPushCutoffCount; + else _directPathPushCutoffCount = 0; + _lastDirectPathPushReceive = now; + return (_directPathPushCutoffCount < ZT_PUSH_DIRECT_PATHS_CUTOFF_LIMIT); + } /** * Find a common set of addresses by which two peers can link, if any @@ -461,13 +478,14 @@ public: b.append((uint64_t)_lastAnnouncedTo); b.append((uint64_t)_lastPathConfirmationSent); b.append((uint64_t)_lastDirectPathPushSent); - b.append((uint64_t)_lastDirectPathPushReceived); + b.append((uint64_t)_lastDirectPathPushReceive); b.append((uint64_t)_lastPathSort); b.append((uint16_t)_vProto); b.append((uint16_t)_vMajor); b.append((uint16_t)_vMinor); b.append((uint16_t)_vRevision); b.append((uint32_t)_latency); + b.append((uint16_t)_directPathPushCutoffCount); b.append((uint16_t)_numPaths); for(unsigned int i=0;i<_numPaths;++i) @@ -531,13 +549,14 @@ public: np->_lastAnnouncedTo = b.template at<uint64_t>(p); p += 8; np->_lastPathConfirmationSent = b.template at<uint64_t>(p); p += 8; np->_lastDirectPathPushSent = b.template at<uint64_t>(p); p += 8; - np->_lastDirectPathPushReceived = b.template at<uint64_t>(p); p += 8; + np->_lastDirectPathPushReceive = b.template at<uint64_t>(p); p += 8; np->_lastPathSort = b.template at<uint64_t>(p); p += 8; np->_vProto = b.template at<uint16_t>(p); p += 2; np->_vMajor = b.template at<uint16_t>(p); p += 2; np->_vMinor = b.template at<uint16_t>(p); p += 2; np->_vRevision = b.template at<uint16_t>(p); p += 2; np->_latency = b.template at<uint32_t>(p); p += 4; + np->_directPathPushCutoffCount = b.template at<uint16_t>(p); p += 2; const unsigned int numPaths = b.template at<uint16_t>(p); p += 2; for(unsigned int i=0;i<numPaths;++i) { @@ -545,7 +564,7 @@ public: p += np->_paths[np->_numPaths++].deserialize(b,p); } else { // Skip any paths beyond max, but still read stream - RemotePath foo; + Path foo; p += foo.deserialize(b,p); } } @@ -569,8 +588,8 @@ public: private: void _sortPaths(const uint64_t now); - RemotePath *_getBestPath(const uint64_t now); - RemotePath *_getBestPath(const uint64_t now,int inetAddressFamily); + Path *_getBestPath(const uint64_t now); + Path *_getBestPath(const uint64_t now,int inetAddressFamily); unsigned char _key[ZT_PEER_SECRET_KEY_LENGTH]; // computed with key agreement, not serialized @@ -581,16 +600,17 @@ private: uint64_t _lastAnnouncedTo; uint64_t _lastPathConfirmationSent; uint64_t _lastDirectPathPushSent; - uint64_t _lastDirectPathPushReceived; + uint64_t _lastDirectPathPushReceive; uint64_t _lastPathSort; uint16_t _vProto; uint16_t _vMajor; uint16_t _vMinor; uint16_t _vRevision; Identity _id; - RemotePath _paths[ZT_MAX_PEER_NETWORK_PATHS]; + Path _paths[ZT_MAX_PEER_NETWORK_PATHS]; unsigned int _numPaths; unsigned int _latency; + unsigned int _directPathPushCutoffCount; struct _NetworkCom { |