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->role = RR->topology->isRoot(pi->second->identity()) ? ZT1_PEER_ROLE_ROOT : ZT1_PEER_ROLE_LEAF;
std::vector<Path> paths(pi->second->paths());
Path *bestPath = pi->second->getBestPath(_now);
std::vector<RemotePath> paths(pi->second->paths());
RemotePath *bestPath = pi->second->getBestPath(_now);
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));
p->paths[p->pathCount].lastSend = path->lastSend();
p->paths[p->pathCount].lastReceive = path->lastReceived();

View File

@ -899,16 +899,17 @@ public:
* Path record format:
* <[1] flags>
* <[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>
* <[...] address>
*
* Path record flags:
* 0x01 - Blacklist this path, do not use
* 0x02 - Reliable path (no keepalives, etc. necessary)
* 0x04 - Trusted path (encryption and authentication optional)
*
* None of the above flags are implemented yet as of 1.0.4. They're
* reserved for future use.
* 0x01 - Forget this path if it is currently known
* 0x02 - Blacklist this path, do not use
* 0x04 - Reliable path (no NAT keepalives, etc. are necessary)
* 0x08 - Disable encryption (trust: privacy)
* 0x10 - Disable encryption and authentication (trust: ultimate)
*
* Address types and addresses are of the same format as the destination
* address type and address in HELLO.
@ -916,9 +917,24 @@ public:
* The receiver may, upon receiving a push, attempt to establish a
* direct link to one or more of the indicated addresses. It is the
* 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
};

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),
_lastAnnouncedTo(0),
_lastPathConfirmationSent(0),
_lastDirectPathPush(0),
_vMajor(0),
_vMinor(0),
_vRevision(0),
@ -86,7 +87,7 @@ void Peer::received(
if (!pathIsConfirmed) {
if ((verb == Packet::VERB_OK)&&(inReVerb == Packet::VERB_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) {
// Add new path
slot = &(_paths[np++]);
@ -101,7 +102,7 @@ void Peer::received(
}
}
if (slot) {
slot->init(remoteAddr,false);
*slot = RemotePath(remoteAddr,false);
slot->received(now);
_numPaths = np;
pathIsConfirmed = true;
@ -193,7 +194,7 @@ void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &at
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 ((now - bestPath->lastReceived()) >= ZT_PEER_DIRECT_PING_DELAY) {
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;
@ -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) {
// Add new path
slot = &(_paths[np++]);

View File

@ -40,7 +40,7 @@
#include "../include/ZeroTierOne.h"
#include "RuntimeEnvironment.hpp"
#include "Path.hpp"
#include "RemotePath.hpp"
#include "Address.hpp"
#include "Utils.hpp"
#include "Identity.hpp"
@ -53,11 +53,7 @@
namespace ZeroTier {
/**
* Peer on P2P Network
*
* 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.
* Peer on P2P Network (virtual layer 1)
*/
class Peer : NonCopyable
{
@ -130,9 +126,9 @@ public:
* @param now Current time
* @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;
for(unsigned int p=0,np=_numPaths;p<np;++p) {
if ((_paths[p].active(now))&&(_paths[p].lastReceived() >= lrMax)) {
@ -152,14 +148,14 @@ public:
* @param now Current time
* @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->send(RR,data,len,now))
return bestPath;
}
return (Path *)0;
return (RemotePath *)0;
}
/**
@ -182,12 +178,21 @@ public:
*/
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
*/
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)
pp.push_back(_paths[p]);
return pp;
@ -295,7 +300,7 @@ public:
*
* @param p New path to add
*/
void addPath(const Path &newp);
void addPath(const RemotePath &newp);
/**
* Clear paths
@ -412,12 +417,13 @@ private:
uint64_t _lastMulticastFrame;
uint64_t _lastAnnouncedTo;
uint64_t _lastPathConfirmationSent;
uint64_t _lastDirectPathPush;
uint16_t _vProto;
uint16_t _vMajor;
uint16_t _vMinor;
uint16_t _vRevision;
Identity _id;
Path _paths[ZT1_MAX_PEER_NETWORK_PATHS];
RemotePath _paths[ZT1_MAX_PEER_NETWORK_PATHS];
unsigned int _numPaths;
unsigned int _latency;

View File

@ -25,72 +25,56 @@
* LLC. Start here: http://www.zerotier.com/
*/
#ifndef ZT_PATH_HPP
#define ZT_PATH_HPP
#ifndef ZT_REMOTEPATH_HPP
#define ZT_REMOTEPATH_HPP
#include <stdint.h>
#include <string.h>
#include <stdexcept>
#include <string>
#include <algorithm>
#include "Constants.hpp"
#include "Path.hpp"
#include "Node.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "AntiRecursion.hpp"
#include "RuntimeEnvironment.hpp"
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
* InetAddress being similarly safe.
* This extends Path to include status information about path activity.
*/
class Path
class RemotePath : public Path
{
public:
Path() :
_addr(),
RemotePath() :
Path(),
_lastSend(0),
_lastReceived(0),
_fixed(false) {}
_lastReceived(0) {}
Path(const Path &p) throw() { memcpy(this,&p,sizeof(Path)); }
Path(const InetAddress &addr,bool fixed) :
_addr(addr),
RemotePath(const InetAddress &addr,bool fixed) :
Path(addr,0,TRUST_NORMAL,false,fixed),
_lastSend(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; }
_lastReceived(0) {}
inline uint64_t lastSend() const throw() { return _lastSend; }
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
*/
@ -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
*/
@ -111,16 +95,6 @@ public:
_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
* @return True if this path is fixed or has received data in last ACTIVITY_TIMEOUT ms
@ -150,34 +124,9 @@ public:
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:
InetAddress _addr;
uint64_t _lastSend;
uint64_t _lastReceived;
bool _fixed;
};
} // 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.
SharedPtr<Peer> sn(RR->topology->getBestRoot());
if (sn) {
Path *snp = sn->getBestPath(now);
RemotePath *snp = sn->getBestPath(now);
if (snp) {
for(std::vector< SharedPtr<Peer> >::const_iterator p(rset.peersReset.begin());p!=rset.peersReset.end();++p) {
if ((*p)->alive(now)) {

View File

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

View File

@ -62,7 +62,7 @@ void Topology::setRootServers(const std::map< Identity,std::vector<InetAddress>
if (!p)
p = SharedPtr<Peer>(new Peer(RR->identity,i->first));
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);
_rootPeers.push_back(p);
}