Some cleanup, docs, and Path -> Path > RemotePath refactor.

This commit is contained in:
Adam Ierymenko 2015-07-06 14:08:13 -07:00
parent feddd946f9
commit 93bb934d4e
9 changed files with 198 additions and 109 deletions

View File

@ -388,10 +388,10 @@ ZT1_PeerList *Node::peers() const
p->latency = pi->second->latency(); p->latency = pi->second->latency();
p->role = RR->topology->isRoot(pi->second->identity()) ? ZT1_PEER_ROLE_ROOT : ZT1_PEER_ROLE_LEAF; p->role = RR->topology->isRoot(pi->second->identity()) ? ZT1_PEER_ROLE_ROOT : ZT1_PEER_ROLE_LEAF;
std::vector<Path> paths(pi->second->paths()); std::vector<RemotePath> paths(pi->second->paths());
Path *bestPath = pi->second->getBestPath(_now); RemotePath *bestPath = pi->second->getBestPath(_now);
p->pathCount = 0; p->pathCount = 0;
for(std::vector<Path>::iterator path(paths.begin());path!=paths.end();++path) { for(std::vector<RemotePath>::iterator path(paths.begin());path!=paths.end();++path) {
memcpy(&(p->paths[p->pathCount].address),&(path->address()),sizeof(struct sockaddr_storage)); memcpy(&(p->paths[p->pathCount].address),&(path->address()),sizeof(struct sockaddr_storage));
p->paths[p->pathCount].lastSend = path->lastSend(); p->paths[p->pathCount].lastSend = path->lastSend();
p->paths[p->pathCount].lastReceive = path->lastReceived(); p->paths[p->pathCount].lastReceive = path->lastReceived();

View File

@ -899,16 +899,17 @@ public:
* Path record format: * Path record format:
* <[1] flags> * <[1] flags>
* <[1] metric from 0 (highest priority) to 255 (lowest priority)> * <[1] metric from 0 (highest priority) to 255 (lowest priority)>
* <[2] length of extended path characteristics or 0 for none>
* <[...] extended path characteristics>
* <[1] address type> * <[1] address type>
* <[...] address> * <[...] address>
* *
* Path record flags: * Path record flags:
* 0x01 - Blacklist this path, do not use * 0x01 - Forget this path if it is currently known
* 0x02 - Reliable path (no keepalives, etc. necessary) * 0x02 - Blacklist this path, do not use
* 0x04 - Trusted path (encryption and authentication optional) * 0x04 - Reliable path (no NAT keepalives, etc. are necessary)
* * 0x08 - Disable encryption (trust: privacy)
* None of the above flags are implemented yet as of 1.0.4. They're * 0x10 - Disable encryption and authentication (trust: ultimate)
* reserved for future use.
* *
* Address types and addresses are of the same format as the destination * Address types and addresses are of the same format as the destination
* address type and address in HELLO. * address type and address in HELLO.
@ -916,9 +917,24 @@ public:
* The receiver may, upon receiving a push, attempt to establish a * The receiver may, upon receiving a push, attempt to establish a
* direct link to one or more of the indicated addresses. It is the * direct link to one or more of the indicated addresses. It is the
* responsibility of the sender to limit which peers it pushes direct * responsibility of the sender to limit which peers it pushes direct
* paths to to those with whom it has a trust relationship. * paths to to those with whom it has a trust relationship. The receiver
* must obey any restrictions provided such as exclusivity or blacklists.
* OK responses to this message are optional.
* *
* OK/ERROR are not generated. * Note that a direct path push does not imply that learned paths can't
* be used unless they are blacklisted explicitly or unless flag 0x01
* is set.
*
* Only a subset of this functionality is currently implemented: basic
* path pushing and learning. Metrics, most flags, and OK responses are
* not yet implemented as of 1.0.4.
*
* OK response payload:
* <[2] 16-bit number of active direct paths we already have>
* <[2] 16-bit number of paths in push that we don't already have>
* <[2] 16-bit number of new paths we are trying (or will try)>
*
* ERROR is presently not sent.
*/ */
VERB_PUSH_DIRECT_PATHS = 16 VERB_PUSH_DIRECT_PATHS = 16
}; };

113
node/Path.hpp Normal file
View File

@ -0,0 +1,113 @@
/*
* ZeroTier One - Network Virtualization Everywhere
* Copyright (C) 2011-2015 ZeroTier, Inc.
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* --
*
* ZeroTier may be used and distributed under the terms of the GPLv3, which
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
*
* If you would like to embed ZeroTier into a commercial application or
* redistribute it in a modified binary form, please contact ZeroTier Networks
* LLC. Start here: http://www.zerotier.com/
*/
#ifndef ZT_PATH_HPP
#define ZT_PATH_HPP
#include "Constants.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
namespace ZeroTier {
class Path
{
public:
enum Trust
{
TRUST_NORMAL,
TRUST_PRIVACY,
TRUST_ULTIMATE
};
Path() :
_addr(),
_metric(0),
_trust(TRUST_NORMAL),
_reliable(false),
_fixed(false)
{
}
Path(const InetAddress &addr,int metric,Trust trust,bool reliable,bool fixed) :
_addr(addr),
_metric(metric),
_trust(trust),
_reliable(reliable),
_fixed(fixed)
{
}
/**
* @return Physical address
*/
inline const InetAddress &address() const throw() { return _addr; }
/**
* @return Metric (higher == worse) or negative if path is blacklisted
*/
inline int metric() const throw() { return _metric; }
/**
* @return Path trust level
*/
inline Trust trust() const throw() { return _trust; }
/**
* @return True if path is considered reliable (no NAT keepalives etc. are needed)
*/
inline bool reliable() const throw() { return _reliable; }
/**
* @return Is this a fixed path?
*/
inline bool fixed() const throw() { return _fixed; }
/**
* @return True if address is non-NULL
*/
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); }
protected:
InetAddress _addr;
int _metric; // negative == blacklisted
Trust _trust;
bool _reliable;
bool _fixed;
};
} // namespace ZeroTier
#endif

View File

@ -46,6 +46,7 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
_lastMulticastFrame(0), _lastMulticastFrame(0),
_lastAnnouncedTo(0), _lastAnnouncedTo(0),
_lastPathConfirmationSent(0), _lastPathConfirmationSent(0),
_lastDirectPathPush(0),
_vMajor(0), _vMajor(0),
_vMinor(0), _vMinor(0),
_vRevision(0), _vRevision(0),
@ -86,7 +87,7 @@ void Peer::received(
if (!pathIsConfirmed) { if (!pathIsConfirmed) {
if ((verb == Packet::VERB_OK)&&(inReVerb == Packet::VERB_HELLO)) { if ((verb == Packet::VERB_OK)&&(inReVerb == Packet::VERB_HELLO)) {
// Learn paths if they've been confirmed via a HELLO // Learn paths if they've been confirmed via a HELLO
Path *slot = (Path *)0; RemotePath *slot = (RemotePath *)0;
if (np < ZT1_MAX_PEER_NETWORK_PATHS) { if (np < ZT1_MAX_PEER_NETWORK_PATHS) {
// Add new path // Add new path
slot = &(_paths[np++]); slot = &(_paths[np++]);
@ -101,7 +102,7 @@ void Peer::received(
} }
} }
if (slot) { if (slot) {
slot->init(remoteAddr,false); *slot = RemotePath(remoteAddr,false);
slot->received(now); slot->received(now);
_numPaths = np; _numPaths = np;
pathIsConfirmed = true; pathIsConfirmed = true;
@ -193,7 +194,7 @@ void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &at
void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)
{ {
Path *const bestPath = getBestPath(now); RemotePath *const bestPath = getBestPath(now);
if ((bestPath)&&(bestPath->active(now))) { if ((bestPath)&&(bestPath->active(now))) {
if ((now - bestPath->lastReceived()) >= ZT_PEER_DIRECT_PING_DELAY) { if ((now - bestPath->lastReceived()) >= ZT_PEER_DIRECT_PING_DELAY) {
TRACE("PING %s(%s)",_id.address().toString().c_str(),bestPath->address().toString().c_str()); TRACE("PING %s(%s)",_id.address().toString().c_str(),bestPath->address().toString().c_str());
@ -207,7 +208,11 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)
} }
} }
void Peer::addPath(const Path &newp) //void Peer::pushDirectPaths(const std::vector<Path> &dps,uint64_t now,bool force)
//{
//}
void Peer::addPath(const RemotePath &newp)
{ {
unsigned int np = _numPaths; unsigned int np = _numPaths;
@ -218,7 +223,7 @@ void Peer::addPath(const Path &newp)
} }
} }
Path *slot = (Path *)0; RemotePath *slot = (RemotePath *)0;
if (np < ZT1_MAX_PEER_NETWORK_PATHS) { if (np < ZT1_MAX_PEER_NETWORK_PATHS) {
// Add new path // Add new path
slot = &(_paths[np++]); slot = &(_paths[np++]);

View File

@ -40,7 +40,7 @@
#include "../include/ZeroTierOne.h" #include "../include/ZeroTierOne.h"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#include "Path.hpp" #include "RemotePath.hpp"
#include "Address.hpp" #include "Address.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Identity.hpp" #include "Identity.hpp"
@ -53,11 +53,7 @@
namespace ZeroTier { namespace ZeroTier {
/** /**
* Peer on P2P Network * Peer on P2P Network (virtual layer 1)
*
* This struture is not locked, volatile, and memcpy-able. NonCopyable
* semantics are just there to prevent bugs, not because it isn't safe
* to copy.
*/ */
class Peer : NonCopyable class Peer : NonCopyable
{ {
@ -130,9 +126,9 @@ public:
* @param now Current time * @param now Current time
* @return Best path or NULL if there are no active (or fixed) direct paths * @return Best path or NULL if there are no active (or fixed) direct paths
*/ */
inline Path *getBestPath(uint64_t now) inline RemotePath *getBestPath(uint64_t now)
{ {
Path *bestPath = (Path *)0; RemotePath *bestPath = (RemotePath *)0;
uint64_t lrMax = 0; uint64_t lrMax = 0;
for(unsigned int p=0,np=_numPaths;p<np;++p) { for(unsigned int p=0,np=_numPaths;p<np;++p) {
if ((_paths[p].active(now))&&(_paths[p].lastReceived() >= lrMax)) { if ((_paths[p].active(now))&&(_paths[p].lastReceived() >= lrMax)) {
@ -152,14 +148,14 @@ public:
* @param now Current time * @param now Current time
* @return Path used on success or NULL on failure * @return Path used on success or NULL on failure
*/ */
inline Path *send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now) inline RemotePath *send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
{ {
Path *bestPath = getBestPath(now); RemotePath *bestPath = getBestPath(now);
if (bestPath) { if (bestPath) {
if (bestPath->send(RR,data,len,now)) if (bestPath->send(RR,data,len,now))
return bestPath; return bestPath;
} }
return (Path *)0; return (RemotePath *)0;
} }
/** /**
@ -182,12 +178,21 @@ public:
*/ */
void doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now); void doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now);
/**
* Push direct paths (if within rate limit)
*
* @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<InetAddress> &dps,uint64_t now,bool force);
/** /**
* @return All known direct paths to this peer * @return All known direct paths to this peer
*/ */
inline std::vector<Path> paths() const inline std::vector<RemotePath> paths() const
{ {
std::vector<Path> pp; std::vector<RemotePath> pp;
for(unsigned int p=0,np=_numPaths;p<np;++p) for(unsigned int p=0,np=_numPaths;p<np;++p)
pp.push_back(_paths[p]); pp.push_back(_paths[p]);
return pp; return pp;
@ -295,7 +300,7 @@ public:
* *
* @param p New path to add * @param p New path to add
*/ */
void addPath(const Path &newp); void addPath(const RemotePath &newp);
/** /**
* Clear paths * Clear paths
@ -412,12 +417,13 @@ private:
uint64_t _lastMulticastFrame; uint64_t _lastMulticastFrame;
uint64_t _lastAnnouncedTo; uint64_t _lastAnnouncedTo;
uint64_t _lastPathConfirmationSent; uint64_t _lastPathConfirmationSent;
uint64_t _lastDirectPathPush;
uint16_t _vProto; uint16_t _vProto;
uint16_t _vMajor; uint16_t _vMajor;
uint16_t _vMinor; uint16_t _vMinor;
uint16_t _vRevision; uint16_t _vRevision;
Identity _id; Identity _id;
Path _paths[ZT1_MAX_PEER_NETWORK_PATHS]; RemotePath _paths[ZT1_MAX_PEER_NETWORK_PATHS];
unsigned int _numPaths; unsigned int _numPaths;
unsigned int _latency; unsigned int _latency;

View File

@ -25,72 +25,56 @@
* LLC. Start here: http://www.zerotier.com/ * LLC. Start here: http://www.zerotier.com/
*/ */
#ifndef ZT_PATH_HPP #ifndef ZT_REMOTEPATH_HPP
#define ZT_PATH_HPP #define ZT_REMOTEPATH_HPP
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <stdexcept> #include <stdexcept>
#include <string>
#include <algorithm> #include <algorithm>
#include "Constants.hpp" #include "Path.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "AntiRecursion.hpp" #include "AntiRecursion.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
namespace ZeroTier { namespace ZeroTier {
/** /**
* WAN address and protocol for reaching a peer * Path to a remote peer
* *
* This structure is volatile and memcpy-able, and depends on * This extends Path to include status information about path activity.
* InetAddress being similarly safe.
*/ */
class Path class RemotePath : public Path
{ {
public: public:
Path() : RemotePath() :
_addr(), Path(),
_lastSend(0), _lastSend(0),
_lastReceived(0), _lastReceived(0) {}
_fixed(false) {}
Path(const Path &p) throw() { memcpy(this,&p,sizeof(Path)); } RemotePath(const InetAddress &addr,bool fixed) :
Path(addr,0,TRUST_NORMAL,false,fixed),
Path(const InetAddress &addr,bool fixed) :
_addr(addr),
_lastSend(0), _lastSend(0),
_lastReceived(0), _lastReceived(0) {}
_fixed(fixed) {}
inline void init(const InetAddress &addr,bool fixed)
{
_addr = addr;
_lastSend = 0;
_lastReceived = 0;
_fixed = fixed;
}
inline Path &operator=(const Path &p)
{
if (this != &p)
memcpy(this,&p,sizeof(Path));
return *this;
}
inline const InetAddress &address() const throw() { return _addr; }
inline uint64_t lastSend() const throw() { return _lastSend; } inline uint64_t lastSend() const throw() { return _lastSend; }
inline uint64_t lastReceived() const throw() { return _lastReceived; } inline uint64_t lastReceived() const throw() { return _lastReceived; }
/** /**
* Called when a packet is sent to this path * @param f New value of parent 'fixed' field
*/
inline void setFixed(const bool f)
throw()
{
_fixed = f;
}
/**
* Called when a packet is sent to this remote path
* *
* This is called automatically by Path::send(). * This is called automatically by RemotePath::send().
* *
* @param t Time of send * @param t Time of send
*/ */
@ -101,7 +85,7 @@ public:
} }
/** /**
* Called when a packet is received from this path * Called when a packet is received from this remote path
* *
* @param t Time of receive * @param t Time of receive
*/ */
@ -111,16 +95,6 @@ public:
_lastReceived = t; _lastReceived = t;
} }
/**
* @return Is this a fixed path?
*/
inline bool fixed() const throw() { return _fixed; }
/**
* @param f New value of fixed path flag
*/
inline void setFixed(bool f) throw() { _fixed = f; }
/** /**
* @param now Current time * @param now Current time
* @return True if this path is fixed or has received data in last ACTIVITY_TIMEOUT ms * @return True if this path is fixed or has received data in last ACTIVITY_TIMEOUT ms
@ -150,34 +124,9 @@ public:
return false; return false;
} }
/**
* @param now Current time
* @return Human-readable address and other information about this path
*/
inline std::string toString(uint64_t now) const
{
char tmp[1024];
Utils::snprintf(tmp,sizeof(tmp),"%s(%s)",
_addr.toString().c_str(),
((_fixed) ? "fixed" : (active(now) ? "active" : "inactive"))
);
return std::string(tmp);
}
inline operator bool() const throw() { return (_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); }
inline bool operator>=(const Path &p) const throw() { return (_addr >= p._addr); }
private: private:
InetAddress _addr;
uint64_t _lastSend; uint64_t _lastSend;
uint64_t _lastReceived; uint64_t _lastReceived;
bool _fixed;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View File

@ -120,7 +120,7 @@ void SelfAwareness::iam(const Address &reporter,const InetAddress &reporterPhysi
// they are still considered alive so that we will re-establish direct links. // they are still considered alive so that we will re-establish direct links.
SharedPtr<Peer> sn(RR->topology->getBestRoot()); SharedPtr<Peer> sn(RR->topology->getBestRoot());
if (sn) { if (sn) {
Path *snp = sn->getBestPath(now); RemotePath *snp = sn->getBestPath(now);
if (snp) { if (snp) {
for(std::vector< SharedPtr<Peer> >::const_iterator p(rset.peersReset.begin());p!=rset.peersReset.end();++p) { for(std::vector< SharedPtr<Peer> >::const_iterator p(rset.peersReset.begin());p!=rset.peersReset.end();++p) {
if ((*p)->alive(now)) { if ((*p)->alive(now)) {

View File

@ -733,7 +733,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
if (peer) { if (peer) {
const uint64_t now = RR->node->now(); const uint64_t now = RR->node->now();
Path *viaPath = peer->getBestPath(now); RemotePath *viaPath = peer->getBestPath(now);
if (!viaPath) { if (!viaPath) {
SharedPtr<Peer> relay; SharedPtr<Peer> relay;

View File

@ -62,7 +62,7 @@ void Topology::setRootServers(const std::map< Identity,std::vector<InetAddress>
if (!p) if (!p)
p = SharedPtr<Peer>(new Peer(RR->identity,i->first)); p = SharedPtr<Peer>(new Peer(RR->identity,i->first));
for(std::vector<InetAddress>::const_iterator j(i->second.begin());j!=i->second.end();++j) for(std::vector<InetAddress>::const_iterator j(i->second.begin());j!=i->second.end();++j)
p->addPath(Path(*j,true)); p->addPath(RemotePath(*j,true));
p->use(now); p->use(now);
_rootPeers.push_back(p); _rootPeers.push_back(p);
} }