summaryrefslogtreecommitdiff
path: root/node/Peer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Peer.hpp')
-rw-r--r--node/Peer.hpp136
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
{