summaryrefslogtreecommitdiff
path: root/node/Path.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Path.hpp')
-rw-r--r--node/Path.hpp187
1 files changed, 142 insertions, 45 deletions
diff --git a/node/Path.hpp b/node/Path.hpp
index 0e53772d..00f8ed36 100644
--- a/node/Path.hpp
+++ b/node/Path.hpp
@@ -28,12 +28,29 @@
#ifndef ZT_PATH_HPP
#define ZT_PATH_HPP
+#include <stdint.h>
+#include <string.h>
+
+#include <stdexcept>
+#include <algorithm>
+
#include "Constants.hpp"
#include "InetAddress.hpp"
-#include "Utils.hpp"
+
+/**
+ * Flag indicating that this path is suboptimal
+ *
+ * This is used in cluster mode to indicate that the peer has been directed
+ * to a better path. This path can continue to be used but shouldn't be kept
+ * or advertised to other cluster members. Not used if clustering is not
+ * built and enabled.
+ */
+#define ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL 0x0001
namespace ZeroTier {
+class RuntimeEnvironment;
+
/**
* Base class for paths
*
@@ -42,43 +59,84 @@ namespace ZeroTier {
class Path
{
public:
+ Path() :
+ _lastSend(0),
+ _lastReceived(0),
+ _addr(),
+ _localAddress(),
+ _flags(0),
+ _ipScope(InetAddress::IP_SCOPE_NONE)
+ {
+ }
+
+ Path(const InetAddress &localAddress,const InetAddress &addr) :
+ _lastSend(0),
+ _lastReceived(0),
+ _addr(addr),
+ _localAddress(localAddress),
+ _flags(0),
+ _ipScope(addr.ipScope())
+ {
+ }
+
+ inline Path &operator=(const Path &p)
+ {
+ if (this != &p)
+ memcpy(this,&p,sizeof(Path));
+ return *this;
+ }
+
/**
- * Path trust category
+ * Called when a packet is sent to this remote path
*
- * Note that this is NOT peer trust and has nothing to do with root server
- * designations or other trust metrics. This indicates how much we trust
- * this path to be secure and/or private. A trust level of normal means
- * encrypt and authenticate all traffic. Privacy trust means we can send
- * traffic in the clear. Ultimate trust means we don't even need
- * authentication. Generally a private path would be a hard-wired local
- * LAN, while an ultimate trust path would be a physically isolated private
- * server backplane.
+ * This is called automatically by Path::send().
*
- * Nearly all paths will be normal trust. The other levels are for high
- * performance local SDN use only.
+ * @param t Time of send
+ */
+ inline void sent(uint64_t t) { _lastSend = t; }
+
+ /**
+ * Called when a packet is received from this remote path
*
- * These values MUST match ZT1_LocalInterfaceAddressTrust in ZeroTierOne.h
+ * @param t Time of receive
*/
- enum Trust
- {
- TRUST_NORMAL = 0,
- TRUST_PRIVACY = 1,
- TRUST_ULTIMATE = 2
- };
+ inline void received(uint64_t t) { _lastReceived = t; }
- Path() :
- _addr(),
- _ipScope(InetAddress::IP_SCOPE_NONE),
- _trust(TRUST_NORMAL)
+ /**
+ * @param now Current time
+ * @return True if this path appears active
+ */
+ inline bool active(uint64_t now) const
+ throw()
{
+ return ((now - _lastReceived) < ZT_PEER_ACTIVITY_TIMEOUT);
}
- Path(const InetAddress &addr,int metric,Trust trust) :
- _addr(addr),
- _ipScope(addr.ipScope()),
- _trust(trust)
- {
- }
+ /**
+ * Send a packet via this path
+ *
+ * @param RR Runtime environment
+ * @param data Packet data
+ * @param len Packet length
+ * @param now Current time
+ * @return True if transport reported success
+ */
+ bool send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now);
+
+ /**
+ * @return Address of local side of this path or NULL if unspecified
+ */
+ inline const InetAddress &localAddress() const throw() { return _localAddress; }
+
+ /**
+ * @return Time of last send to this path
+ */
+ inline uint64_t lastSend() const throw() { return _lastSend; }
+
+ /**
+ * @return Time of last receive from this path
+ */
+ inline uint64_t lastReceived() const throw() { return _lastReceived; }
/**
* @return Physical address
@@ -93,19 +151,25 @@ public:
/**
* @return Preference rank, higher == better
*/
- inline int preferenceRank() const throw() { return (int)_ipScope; } // IP scopes are in ascending rank order in InetAddress.hpp
-
- /**
- * @return Path trust level
- */
- inline Trust trust() const throw() { return _trust; }
+ inline int preferenceRank() const throw()
+ {
+ // First, since the scope enum values in InetAddress.hpp are in order of
+ // use preference rank, we take that. Then we multiple by two, yielding
+ // a sequence like 0, 2, 4, 6, etc. Then if it's IPv6 we add one. This
+ // makes IPv6 addresses of a given scope outrank IPv4 addresses of the
+ // same scope -- e.g. 1 outranks 0. This makes us prefer IPv6, but not
+ // if the address scope/class is of a fundamentally lower rank.
+ return ( ((int)_ipScope * 2) + ((_addr.ss_family == AF_INET6) ? 1 : 0) );
+ }
/**
* @return True if path is considered reliable (no NAT keepalives etc. are needed)
*/
inline bool reliable() const throw()
{
- return ((_ipScope != InetAddress::IP_SCOPE_GLOBAL)&&(_ipScope != InetAddress::IP_SCOPE_PSEUDOPRIVATE));
+ if (_addr.ss_family == AF_INET)
+ return ((_ipScope != InetAddress::IP_SCOPE_GLOBAL)&&(_ipScope != InetAddress::IP_SCOPE_PSEUDOPRIVATE));
+ return true;
}
/**
@@ -113,14 +177,6 @@ public:
*/
inline operator bool() const throw() { return (_addr); }
- // Comparisons are by address only
- inline bool operator==(const Path &p) const throw() { return (_addr == p._addr); }
- inline bool operator!=(const Path &p) const throw() { return (_addr != p._addr); }
- inline bool operator<(const Path &p) const throw() { return (_addr < p._addr); }
- inline bool operator>(const Path &p) const throw() { return (_addr > p._addr); }
- inline bool operator<=(const Path &p) const throw() { return (_addr <= p._addr); }
- inline bool operator>=(const Path &p) const throw() { return (_addr >= p._addr); }
-
/**
* Check whether this address is valid for a ZeroTier path
*
@@ -154,10 +210,51 @@ public:
return false;
}
+#ifdef ZT_ENABLE_CLUSTER
+ /**
+ * @param f New value of ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL
+ */
+ inline void setClusterSuboptimal(bool f) { _flags = ((f) ? (_flags | ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) : (_flags & (~ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL))); }
+
+ /**
+ * @return True if ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL is set
+ */
+ inline bool isClusterSuboptimal() const { return ((_flags & ZT_PATH_FLAG_CLUSTER_SUBOPTIMAL) != 0); }
+#endif
+
+ template<unsigned int C>
+ inline void serialize(Buffer<C> &b) const
+ {
+ b.append((uint8_t)0); // version
+ b.append((uint64_t)_lastSend);
+ b.append((uint64_t)_lastReceived);
+ _addr.serialize(b);
+ _localAddress.serialize(b);
+ b.append((uint16_t)_flags);
+ }
+
+ template<unsigned int C>
+ inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
+ {
+ unsigned int p = startAt;
+ if (b[p++] != 0)
+ throw std::invalid_argument("invalid serialized Path");
+ _lastSend = b.template at<uint64_t>(p); p += 8;
+ _lastReceived = b.template at<uint64_t>(p); p += 8;
+ p += _addr.deserialize(b,p);
+ p += _localAddress.deserialize(b,p);
+ _flags = b.template at<uint16_t>(p); p += 2;
+ _ipScope = _addr.ipScope();
+ return (p - startAt);
+ }
+
private:
+ uint64_t _lastSend;
+ uint64_t _lastReceived;
InetAddress _addr;
+ InetAddress _localAddress;
+ unsigned int _flags;
InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often
- Trust _trust;
};
} // namespace ZeroTier