summaryrefslogtreecommitdiff
path: root/node/Path.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Path.hpp')
-rw-r--r--node/Path.hpp176
1 files changed, 69 insertions, 107 deletions
diff --git a/node/Path.hpp b/node/Path.hpp
index aef628d4..e12328ff 100644
--- a/node/Path.hpp
+++ b/node/Path.hpp
@@ -1,6 +1,6 @@
/*
* ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
+ * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,6 +14,14 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial closed-source software that incorporates or links
+ * directly against ZeroTier software without disclosing the source code
+ * of your own application.
*/
#ifndef ZT_PATH_HPP
@@ -30,7 +38,6 @@
#include "InetAddress.hpp"
#include "SharedPtr.hpp"
#include "AtomicCounter.hpp"
-#include "NonCopyable.hpp"
#include "Utils.hpp"
/**
@@ -45,7 +52,7 @@ class RuntimeEnvironment;
/**
* A path across the physical network
*/
-class Path : NonCopyable
+class Path
{
friend class SharedPtr<Path>;
@@ -58,83 +65,50 @@ public:
public:
HashKey() {}
- HashKey(const InetAddress &l,const InetAddress &r)
+ HashKey(const int64_t l,const InetAddress &r)
{
- // This is an ad-hoc bit packing algorithm to yield unique keys for
- // remote addresses and their local-side counterparts if defined.
- // Portability across runtimes is not needed.
if (r.ss_family == AF_INET) {
_k[0] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_addr.s_addr;
_k[1] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_port;
- if (l.ss_family == AF_INET) {
- _k[2] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&l)->sin_addr.s_addr;
- _k[3] = (uint64_t)reinterpret_cast<const struct sockaddr_in *>(&r)->sin_port;
- } else {
- _k[2] = 0;
- _k[3] = 0;
- }
+ _k[2] = (uint64_t)l;
} else if (r.ss_family == AF_INET6) {
- const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr);
- uint8_t *b = reinterpret_cast<uint8_t *>(_k);
- for(unsigned int i=0;i<16;++i) b[i] = a[i];
- _k[2] = ~((uint64_t)reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port);
- if (l.ss_family == AF_INET6) {
- _k[2] ^= ((uint64_t)reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port) << 32;
- a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&l)->sin6_addr.s6_addr);
- b += 24;
- for(unsigned int i=0;i<8;++i) b[i] = a[i];
- a += 8;
- for(unsigned int i=0;i<8;++i) b[i] ^= a[i];
- }
+ ZT_FAST_MEMCPY(_k,reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,16);
+ _k[2] = ((uint64_t)reinterpret_cast<const struct sockaddr_in6 *>(&r)->sin6_port << 32) ^ (uint64_t)l;
} else {
- _k[0] = 0;
- _k[1] = 0;
- _k[2] = 0;
- _k[3] = 0;
+ ZT_FAST_MEMCPY(_k,&r,std::min(sizeof(_k),sizeof(InetAddress)));
+ _k[2] += (uint64_t)l;
}
}
- inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2] + _k[3]); }
+ inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); }
- inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) && (_k[3] == k._k[3]) ); }
+ inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); }
inline bool operator!=(const HashKey &k) const { return (!(*this == k)); }
private:
- uint64_t _k[4];
+ uint64_t _k[3];
};
Path() :
_lastOut(0),
_lastIn(0),
_lastTrustEstablishedPacketReceived(0),
- _incomingLinkQualityFastLog(0xffffffffffffffffULL),
- _incomingLinkQualitySlowLogPtr(0),
- _incomingLinkQualitySlowLogCounter(-64), // discard first fast log
- _incomingLinkQualityPreviousPacketCounter(0),
- _outgoingPacketCounter(0),
+ _localSocket(-1),
+ _latency(0xffff),
_addr(),
- _localAddress(),
_ipScope(InetAddress::IP_SCOPE_NONE)
{
- for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i)
- _incomingLinkQualitySlowLog[i] = ZT_PATH_LINK_QUALITY_MAX;
}
- Path(const InetAddress &localAddress,const InetAddress &addr) :
+ Path(const int64_t localSocket,const InetAddress &addr) :
_lastOut(0),
_lastIn(0),
_lastTrustEstablishedPacketReceived(0),
- _incomingLinkQualityFastLog(0xffffffffffffffffULL),
- _incomingLinkQualitySlowLogPtr(0),
- _incomingLinkQualitySlowLogCounter(-64), // discard first fast log
- _incomingLinkQualityPreviousPacketCounter(0),
- _outgoingPacketCounter(0),
+ _localSocket(localSocket),
+ _latency(0xffff),
_addr(addr),
- _localAddress(localAddress),
_ipScope(addr.ipScope())
{
- for(int i=0;i<(int)sizeof(_incomingLinkQualitySlowLog);++i)
- _incomingLinkQualitySlowLog[i] = ZT_PATH_LINK_QUALITY_MAX;
}
/**
@@ -145,39 +119,6 @@ public:
inline void received(const uint64_t t) { _lastIn = t; }
/**
- * Update link quality using a counter from an incoming packet (or packet head in fragmented case)
- *
- * @param counter Packet link quality counter (range 0 to 7, must not have other bits set)
- */
- inline void updateLinkQuality(const unsigned int counter)
- {
- const unsigned int prev = _incomingLinkQualityPreviousPacketCounter;
- _incomingLinkQualityPreviousPacketCounter = counter;
- const uint64_t fl = (_incomingLinkQualityFastLog = ((_incomingLinkQualityFastLog << 1) | (uint64_t)(prev == ((counter - 1) & 0x7))));
- if (++_incomingLinkQualitySlowLogCounter >= 64) {
- _incomingLinkQualitySlowLogCounter = 0;
- _incomingLinkQualitySlowLog[_incomingLinkQualitySlowLogPtr++ % sizeof(_incomingLinkQualitySlowLog)] = (uint8_t)Utils::countBits(fl);
- }
- }
-
- /**
- * @return Link quality from 0 (min) to 255 (max)
- */
- inline unsigned int linkQuality() const
- {
- unsigned long slsize = _incomingLinkQualitySlowLogPtr;
- if (slsize > (unsigned long)sizeof(_incomingLinkQualitySlowLog))
- slsize = (unsigned long)sizeof(_incomingLinkQualitySlowLog);
- else if (!slsize)
- return 255; // ZT_PATH_LINK_QUALITY_MAX
- unsigned long lq = 0;
- for(unsigned long i=0;i<slsize;++i)
- lq += (unsigned long)_incomingLinkQualitySlowLog[i] * 4;
- lq /= slsize;
- return (unsigned int)((lq >= 255) ? 255 : lq);
- }
-
- /**
* Set time last trusted packet was received (done in Peer::received())
*/
inline void trustedPacketReceived(const uint64_t t) { _lastTrustEstablishedPacketReceived = t; }
@@ -192,19 +133,32 @@ public:
* @param now Current time
* @return True if transport reported success
*/
- bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now);
+ bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now);
/**
* Manually update last sent time
*
* @param t Time of send
*/
- inline void sent(const uint64_t t) { _lastOut = t; }
+ inline void sent(const int64_t t) { _lastOut = t; }
/**
- * @return Address of local side of this path or NULL if unspecified
+ * Update path latency with a new measurement
+ *
+ * @param l Measured latency
*/
- inline const InetAddress &localAddress() const { return _localAddress; }
+ inline void updateLatency(const unsigned int l)
+ {
+ unsigned int pl = _latency;
+ if (pl < 0xffff)
+ _latency = (pl + l) / 2;
+ else _latency = l;
+ }
+
+ /**
+ * @return Local socket as specified by external code
+ */
+ inline int64_t localSocket() const { return _localSocket; }
/**
* @return Physical address
@@ -219,7 +173,7 @@ public:
/**
* @return True if path has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
*/
- inline bool trustEstablished(const uint64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
+ inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
/**
* @return Preference rank, higher == better
@@ -272,45 +226,53 @@ public:
}
/**
- * @return True if path appears alive
+ * @return Latency or 0xffff if unknown
+ */
+ inline unsigned int latency() const { return _latency; }
+
+ /**
+ * @return Path quality -- lower is better
+ */
+ inline long quality(const int64_t now) const
+ {
+ const int l = (long)_latency;
+ const int age = (long)std::min((now - _lastIn),(int64_t)(ZT_PATH_HEARTBEAT_PERIOD * 10)); // set an upper sanity limit to avoid overflow
+ return (((age < (ZT_PATH_HEARTBEAT_PERIOD + 5000)) ? l : (l + 0xffff + age)) * (long)((ZT_INETADDRESS_MAX_SCOPE - _ipScope) + 1));
+ }
+
+ /**
+ * @return True if this path is alive (receiving heartbeats)
*/
- inline bool alive(const uint64_t now) const { return ((now - _lastIn) <= ZT_PATH_ALIVE_TIMEOUT); }
+ inline bool alive(const int64_t now) const { return ((now - _lastIn) < (ZT_PATH_HEARTBEAT_PERIOD + 5000)); }
/**
* @return True if this path needs a heartbeat
*/
- inline bool needsHeartbeat(const uint64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); }
+ inline bool needsHeartbeat(const int64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); }
/**
* @return Last time we sent something
*/
- inline uint64_t lastOut() const { return _lastOut; }
+ inline int64_t lastOut() const { return _lastOut; }
/**
* @return Last time we received anything
*/
- inline uint64_t lastIn() const { return _lastIn; }
+ inline int64_t lastIn() const { return _lastIn; }
/**
- * Return and increment outgoing packet counter (used with Packet::armor())
- *
- * @return Next value that should be used for outgoing packet counter (only least significant 3 bits are used)
+ * @return Time last trust-established packet was received
*/
- inline unsigned int nextOutgoingCounter() { return _outgoingPacketCounter++; }
+ inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; }
private:
- volatile uint64_t _lastOut;
- volatile uint64_t _lastIn;
- volatile uint64_t _lastTrustEstablishedPacketReceived;
- volatile uint64_t _incomingLinkQualityFastLog;
- volatile unsigned long _incomingLinkQualitySlowLogPtr;
- volatile signed int _incomingLinkQualitySlowLogCounter;
- volatile unsigned int _incomingLinkQualityPreviousPacketCounter;
- volatile unsigned int _outgoingPacketCounter;
+ volatile int64_t _lastOut;
+ volatile int64_t _lastIn;
+ volatile int64_t _lastTrustEstablishedPacketReceived;
+ int64_t _localSocket;
+ volatile unsigned int _latency;
InetAddress _addr;
- InetAddress _localAddress;
InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often
- volatile uint8_t _incomingLinkQualitySlowLog[32];
AtomicCounter __refCount;
};