mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
Permanently retire peers.persist, but make iddb.d always enabled instead since identities are what we really want to cache.
This commit is contained in:
parent
6e23986bb3
commit
2416491cbc
6 changed files with 74 additions and 260 deletions
|
@ -181,12 +181,8 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we already have this peer?
|
|
||||||
SharedPtr<Peer> peer(RR->topology->getPeer(id.address()));
|
SharedPtr<Peer> peer(RR->topology->getPeer(id.address()));
|
||||||
if (peer) {
|
if (peer) {
|
||||||
// Check to make sure this isn't a colliding identity (different key,
|
|
||||||
// but same address). The odds are spectacularly low but it could happen.
|
|
||||||
// Could also be a sign of someone doing something nasty.
|
|
||||||
if (peer->identity() != id) {
|
if (peer->identity() != id) {
|
||||||
unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
|
unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
|
||||||
if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
|
if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
|
||||||
|
@ -208,33 +204,8 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
|
||||||
} else if (!dearmor(peer->key())) {
|
} else if (!dearmor(peer->key())) {
|
||||||
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
|
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
return true;
|
return true;
|
||||||
} // else continue and respond
|
}
|
||||||
} else {
|
} else {
|
||||||
// If we don't have a peer record on file, check the identity cache (if
|
|
||||||
// we have one) to see if we have a cached identity. Then check that for
|
|
||||||
// collision before adding a new peer.
|
|
||||||
Identity alreadyHaveCachedId(RR->topology->getIdentity(id.address()));
|
|
||||||
if ((alreadyHaveCachedId)&&(id != alreadyHaveCachedId)) {
|
|
||||||
unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
|
|
||||||
if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
|
|
||||||
if (dearmor(key)) { // ensure packet is authentic, otherwise drop
|
|
||||||
LOG("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str());
|
|
||||||
Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);
|
|
||||||
outp.append((unsigned char)Packet::VERB_HELLO);
|
|
||||||
outp.append(packetId());
|
|
||||||
outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION);
|
|
||||||
outp.armor(key,true);
|
|
||||||
_fromSock->send(_remoteAddress,outp.data(),outp.size());
|
|
||||||
} else {
|
|
||||||
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG("rejected HELLO from %s(%s): key agreement failed",source().toString().c_str(),_remoteAddress.toString().c_str());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} // else continue since identity is already known and matches
|
|
||||||
|
|
||||||
// If this is a new peer, learn it
|
|
||||||
SharedPtr<Peer> newPeer(new Peer(RR->identity,id));
|
SharedPtr<Peer> newPeer(new Peer(RR->identity,id));
|
||||||
if (!dearmor(newPeer->key())) {
|
if (!dearmor(newPeer->key())) {
|
||||||
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
|
LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
|
@ -376,29 +347,26 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer>
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (payloadLength() == ZT_ADDRESS_LENGTH) {
|
if (payloadLength() == ZT_ADDRESS_LENGTH) {
|
||||||
Identity id(RR->topology->getIdentity(Address(payload(),ZT_ADDRESS_LENGTH)));
|
SharedPtr<Peer> queried(RR->topology->getPeer(Address(payload(),ZT_ADDRESS_LENGTH)));
|
||||||
if (id) {
|
if (queried) {
|
||||||
Packet outp(source(),RR->identity.address(),Packet::VERB_OK);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
||||||
outp.append((unsigned char)Packet::VERB_WHOIS);
|
outp.append((unsigned char)Packet::VERB_WHOIS);
|
||||||
outp.append(packetId());
|
outp.append(packetId());
|
||||||
id.serialize(outp,false);
|
queried->identity().serialize(outp,false);
|
||||||
outp.armor(peer->key(),true);
|
outp.armor(peer->key(),true);
|
||||||
_fromSock->send(_remoteAddress,outp.data(),outp.size());
|
_fromSock->send(_remoteAddress,outp.data(),outp.size());
|
||||||
//TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str());
|
|
||||||
} else {
|
} else {
|
||||||
Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);
|
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
|
||||||
outp.append((unsigned char)Packet::VERB_WHOIS);
|
outp.append((unsigned char)Packet::VERB_WHOIS);
|
||||||
outp.append(packetId());
|
outp.append(packetId());
|
||||||
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
|
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
|
||||||
outp.append(payload(),ZT_ADDRESS_LENGTH);
|
outp.append(payload(),ZT_ADDRESS_LENGTH);
|
||||||
outp.armor(peer->key(),true);
|
outp.armor(peer->key(),true);
|
||||||
_fromSock->send(_remoteAddress,outp.data(),outp.size());
|
_fromSock->send(_remoteAddress,outp.data(),outp.size());
|
||||||
//TRACE("sent WHOIS ERROR to %s for %s (not found)",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str());
|
TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now());
|
peer->receive(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now());
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str());
|
TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
|
|
|
@ -377,7 +377,7 @@ Node::ReasonForTermination Node::run()
|
||||||
Utils::lockDownFile(identitySecretPath.c_str(),false);
|
Utils::lockDownFile(identitySecretPath.c_str(),false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure networks.d exists
|
// Make sure networks.d exists (used by NodeConfig to remember networks)
|
||||||
{
|
{
|
||||||
std::string networksDotD(RR->homePath + ZT_PATH_SEPARATOR_S + "networks.d");
|
std::string networksDotD(RR->homePath + ZT_PATH_SEPARATOR_S + "networks.d");
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
@ -386,13 +386,22 @@ Node::ReasonForTermination Node::run()
|
||||||
mkdir(networksDotD.c_str(),0700);
|
mkdir(networksDotD.c_str(),0700);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
// Make sure iddb.d exists (used by Topology to remember identities)
|
||||||
|
{
|
||||||
|
std::string iddbDotD(RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d");
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
CreateDirectoryA(iddbDotD.c_str(),NULL);
|
||||||
|
#else
|
||||||
|
mkdir(iddbDotD.c_str(),0700);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
RR->http = new HttpClient();
|
RR->http = new HttpClient();
|
||||||
RR->antiRec = new AntiRecursion();
|
RR->antiRec = new AntiRecursion();
|
||||||
RR->mc = new Multicaster(RR);
|
RR->mc = new Multicaster(RR);
|
||||||
RR->sw = new Switch(RR);
|
RR->sw = new Switch(RR);
|
||||||
RR->sm = new SocketManager(impl->udpPort,impl->tcpPort,&_CBztTraffic,RR);
|
RR->sm = new SocketManager(impl->udpPort,impl->tcpPort,&_CBztTraffic,RR);
|
||||||
RR->topology = new Topology(RR,Utils::fileExists((RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d").c_str()));
|
RR->topology = new Topology(RR);
|
||||||
try {
|
try {
|
||||||
RR->nc = new NodeConfig(RR);
|
RR->nc = new NodeConfig(RR);
|
||||||
} catch (std::exception &exc) {
|
} catch (std::exception &exc) {
|
||||||
|
@ -443,6 +452,9 @@ Node::ReasonForTermination Node::run()
|
||||||
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"invalid root-topology format");
|
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"invalid root-topology format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete peers.persist if it exists -- legacy file, just takes up space
|
||||||
|
Utils::rm(std::string(RR->homePath + ZT_PATH_SEPARATOR_S + "peers.persist").c_str());
|
||||||
} catch (std::bad_alloc &exc) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"memory allocation failure");
|
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"memory allocation failure");
|
||||||
} catch (std::runtime_error &exc) {
|
} catch (std::runtime_error &exc) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ Peer::Peer() :
|
||||||
_lastReceive(0),
|
_lastReceive(0),
|
||||||
_lastUnicastFrame(0),
|
_lastUnicastFrame(0),
|
||||||
_lastMulticastFrame(0),
|
_lastMulticastFrame(0),
|
||||||
__lastAnnouncedTo(0),
|
_lastAnnouncedTo(0),
|
||||||
_vMajor(0),
|
_vMajor(0),
|
||||||
_vMinor(0),
|
_vMinor(0),
|
||||||
_vRevision(0),
|
_vRevision(0),
|
||||||
|
@ -55,7 +55,7 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity)
|
||||||
_lastReceive(0),
|
_lastReceive(0),
|
||||||
_lastUnicastFrame(0),
|
_lastUnicastFrame(0),
|
||||||
_lastMulticastFrame(0),
|
_lastMulticastFrame(0),
|
||||||
__lastAnnouncedTo(0),
|
_lastAnnouncedTo(0),
|
||||||
_vMajor(0),
|
_vMajor(0),
|
||||||
_vMinor(0),
|
_vMinor(0),
|
||||||
_vRevision(0),
|
_vRevision(0),
|
||||||
|
@ -118,8 +118,8 @@ void Peer::receive(
|
||||||
* supernodes and network controllers. The other place this is done
|
* supernodes and network controllers. The other place this is done
|
||||||
* is in rescanMulticastGroups() in Network, but that only sends something
|
* is in rescanMulticastGroups() in Network, but that only sends something
|
||||||
* if a network's multicast groups change. */
|
* if a network's multicast groups change. */
|
||||||
if ((now - __lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
|
if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
|
||||||
__lastAnnouncedTo = now;
|
_lastAnnouncedTo = now;
|
||||||
|
|
||||||
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE);
|
||||||
std::vector< SharedPtr<Network> > networks(RR->nc->networks());
|
std::vector< SharedPtr<Network> > networks(RR->nc->networks());
|
||||||
|
|
|
@ -50,9 +50,6 @@
|
||||||
#include "NonCopyable.hpp"
|
#include "NonCopyable.hpp"
|
||||||
#include "Mutex.hpp"
|
#include "Mutex.hpp"
|
||||||
|
|
||||||
// Comment out to disable peers.persist
|
|
||||||
//#define ZT_PEER_SERIALIZATION_VERSION 13
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,7 +245,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @return Time we last announced state TO this peer, such as multicast LIKEs
|
* @return Time we last announced state TO this peer, such as multicast LIKEs
|
||||||
*/
|
*/
|
||||||
inline uint64_t lastAnnouncedTo() const throw() { return __lastAnnouncedTo; }
|
inline uint64_t lastAnnouncedTo() const throw() { return _lastAnnouncedTo; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param now Current time
|
* @param now Current time
|
||||||
|
@ -405,61 +402,6 @@ public:
|
||||||
else return std::pair<InetAddress,InetAddress>();
|
else return std::pair<InetAddress,InetAddress>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ZT_PEER_SERIALIZATION_VERSION
|
|
||||||
template<unsigned int C>
|
|
||||||
inline void serialize(Buffer<C> &b) const
|
|
||||||
{
|
|
||||||
Mutex::Lock _l(_lock);
|
|
||||||
|
|
||||||
b.append((unsigned char)ZT_PEER_SERIALIZATION_VERSION);
|
|
||||||
_id.serialize(b,false);
|
|
||||||
b.append(_key,sizeof(_key));
|
|
||||||
b.append(_lastUsed);
|
|
||||||
b.append(_lastReceive);
|
|
||||||
b.append(_lastUnicastFrame);
|
|
||||||
b.append(_lastMulticastFrame);
|
|
||||||
b.append((uint16_t)_vProto);
|
|
||||||
b.append((uint16_t)_vMajor);
|
|
||||||
b.append((uint16_t)_vMinor);
|
|
||||||
b.append((uint16_t)_vRevision);
|
|
||||||
b.append((uint16_t)_latency);
|
|
||||||
b.append((uint16_t)_paths.size());
|
|
||||||
for(std::vector<Path>::const_iterator p(_paths.begin());p!=_paths.end();++p)
|
|
||||||
p->serialize(b);
|
|
||||||
}
|
|
||||||
template<unsigned int C>
|
|
||||||
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
|
|
||||||
{
|
|
||||||
unsigned int p = startAt;
|
|
||||||
|
|
||||||
if (b[p++] != ZT_PEER_SERIALIZATION_VERSION)
|
|
||||||
throw std::invalid_argument("Peer: deserialize(): version mismatch");
|
|
||||||
|
|
||||||
Mutex::Lock _l(_lock);
|
|
||||||
|
|
||||||
p += _id.deserialize(b,p);
|
|
||||||
memcpy(_key,b.field(p,sizeof(_key)),sizeof(_key)); p += sizeof(_key);
|
|
||||||
_lastUsed = b.template at<uint64_t>(p); p += sizeof(uint64_t);
|
|
||||||
_lastReceive = b.template at<uint64_t>(p); p += sizeof(uint64_t);
|
|
||||||
_lastUnicastFrame = b.template at<uint64_t>(p); p += sizeof(uint64_t);
|
|
||||||
_lastMulticastFrame = b.template at<uint64_t>(p); p += sizeof(uint64_t);
|
|
||||||
__lastAnnouncedTo = 0;
|
|
||||||
_vProto = b.template at<uint16_t>(p); p += sizeof(uint16_t);
|
|
||||||
_vMajor = b.template at<uint16_t>(p); p += sizeof(uint16_t);
|
|
||||||
_vMinor = b.template at<uint16_t>(p); p += sizeof(uint16_t);
|
|
||||||
_vRevision = b.template at<uint16_t>(p); p += sizeof(uint16_t);
|
|
||||||
_latency = b.template at<uint16_t>(p); p += sizeof(uint16_t);
|
|
||||||
unsigned int npaths = (unsigned int)b.template at<uint16_t>(p); p += sizeof(uint16_t);
|
|
||||||
_paths.clear();
|
|
||||||
for(unsigned int i=0;i<npaths;++i) {
|
|
||||||
_paths.push_back(Path());
|
|
||||||
p += _paths.back().deserialize(b,p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (p - startAt);
|
|
||||||
}
|
|
||||||
#endif // ZT_PEER_SERIALIZATION_VERSION
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _announceMulticastGroups(const RuntimeEnvironment *RR,uint64_t now);
|
void _announceMulticastGroups(const RuntimeEnvironment *RR,uint64_t now);
|
||||||
|
|
||||||
|
@ -472,7 +414,7 @@ private:
|
||||||
volatile uint64_t _lastReceive; // direct or indirect
|
volatile uint64_t _lastReceive; // direct or indirect
|
||||||
volatile uint64_t _lastUnicastFrame;
|
volatile uint64_t _lastUnicastFrame;
|
||||||
volatile uint64_t _lastMulticastFrame;
|
volatile uint64_t _lastMulticastFrame;
|
||||||
volatile uint64_t __lastAnnouncedTo; // not persisted -- shouldn't be unless Multicaster state is also persisted
|
volatile uint64_t _lastAnnouncedTo;
|
||||||
volatile uint16_t _vProto;
|
volatile uint16_t _vProto;
|
||||||
volatile uint16_t _vMajor;
|
volatile uint16_t _vMajor;
|
||||||
volatile uint16_t _vMinor;
|
volatile uint16_t _vMinor;
|
||||||
|
|
|
@ -38,19 +38,15 @@
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
Topology::Topology(const RuntimeEnvironment *renv,bool enablePermanentIdCaching) :
|
Topology::Topology(const RuntimeEnvironment *renv) :
|
||||||
RR(renv),
|
RR(renv),
|
||||||
|
_idCacheBase(renv->homePath + ZT_PATH_SEPARATOR_S + "iddb.d"),
|
||||||
_amSupernode(false)
|
_amSupernode(false)
|
||||||
{
|
{
|
||||||
if (enablePermanentIdCaching)
|
|
||||||
_idCacheBase = (RR->homePath + ZT_PATH_SEPARATOR_S + "iddb.d");
|
|
||||||
_loadPeers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Topology::~Topology()
|
Topology::~Topology()
|
||||||
{
|
{
|
||||||
clean(Utils::now());
|
|
||||||
_dumpPeers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::setSupernodes(const std::map< Identity,std::vector< std::pair<InetAddress,bool> > > &sn)
|
void Topology::setSupernodes(const std::map< Identity,std::vector< std::pair<InetAddress,bool> > > &sn)
|
||||||
|
@ -108,57 +104,49 @@ SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer)
|
||||||
TRACE("BUG: addNewPeer() caught and ignored attempt to add peer for self");
|
TRACE("BUG: addNewPeer() caught and ignored attempt to add peer for self");
|
||||||
throw std::logic_error("cannot add peer for self");
|
throw std::logic_error("cannot add peer for self");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t now = Utils::now();
|
uint64_t now = Utils::now();
|
||||||
Mutex::Lock _l(_activePeers_m);
|
Mutex::Lock _l(_activePeers_m);
|
||||||
|
|
||||||
SharedPtr<Peer> p(_activePeers.insert(std::pair< Address,SharedPtr<Peer> >(peer->address(),peer)).first->second);
|
SharedPtr<Peer> p(_activePeers.insert(std::pair< Address,SharedPtr<Peer> >(peer->address(),peer)).first->second);
|
||||||
p->use(now);
|
p->use(now);
|
||||||
saveIdentity(p->identity());
|
_saveIdentity(p->identity());
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPtr<Peer> Topology::getPeer(const Address &zta) const
|
SharedPtr<Peer> Topology::getPeer(const Address &zta)
|
||||||
{
|
{
|
||||||
if (zta == RR->identity.address()) {
|
if (zta == RR->identity.address()) {
|
||||||
TRACE("BUG: ignored attempt to getPeer() for self, returned NULL");
|
TRACE("BUG: ignored attempt to getPeer() for self, returned NULL");
|
||||||
return SharedPtr<Peer>();
|
return SharedPtr<Peer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t now = Utils::now();
|
uint64_t now = Utils::now();
|
||||||
Mutex::Lock _l(_activePeers_m);
|
Mutex::Lock _l(_activePeers_m);
|
||||||
std::map< Address,SharedPtr<Peer> >::const_iterator ap(_activePeers.find(zta));
|
|
||||||
if ((ap != _activePeers.end())&&(ap->second)) {
|
SharedPtr<Peer> &ap = _activePeers[zta];
|
||||||
ap->second->use(now);
|
|
||||||
return ap->second;
|
if (ap) {
|
||||||
|
ap->use(now);
|
||||||
|
return ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Identity id(_getIdentity(zta));
|
||||||
|
if (id) {
|
||||||
|
try {
|
||||||
|
ap = SharedPtr<Peer>(new Peer(RR->identity,id));
|
||||||
|
ap->use(now);
|
||||||
|
return ap;
|
||||||
|
} catch ( ... ) {} // invalid identity?
|
||||||
|
}
|
||||||
|
|
||||||
|
_activePeers.erase(zta);
|
||||||
|
|
||||||
return SharedPtr<Peer>();
|
return SharedPtr<Peer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Identity Topology::getIdentity(const Address &zta)
|
SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid)
|
||||||
{
|
|
||||||
SharedPtr<Peer> p(getPeer(zta));
|
|
||||||
if (p)
|
|
||||||
return p->identity();
|
|
||||||
if (_idCacheBase.length()) {
|
|
||||||
std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + zta.toString());
|
|
||||||
std::string ids;
|
|
||||||
if (Utils::readFile(idcPath.c_str(),ids)) {
|
|
||||||
try {
|
|
||||||
return Identity(ids);
|
|
||||||
} catch ( ... ) {} // ignore invalid IDs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Topology::saveIdentity(const Identity &id)
|
|
||||||
{
|
|
||||||
if ((id)&&(_idCacheBase.length())) {
|
|
||||||
std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + id.address().toString());
|
|
||||||
if (!Utils::fileExists(idcPath.c_str()))
|
|
||||||
Utils::writeFile(idcPath.c_str(),id.toString(false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const
|
|
||||||
{
|
{
|
||||||
SharedPtr<Peer> bestSupernode;
|
SharedPtr<Peer> bestSupernode;
|
||||||
uint64_t now = Utils::now();
|
uint64_t now = Utils::now();
|
||||||
|
@ -261,9 +249,9 @@ void Topology::clean(uint64_t now)
|
||||||
Mutex::Lock _l(_activePeers_m);
|
Mutex::Lock _l(_activePeers_m);
|
||||||
Mutex::Lock _l2(_supernodes_m);
|
Mutex::Lock _l2(_supernodes_m);
|
||||||
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();) {
|
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();) {
|
||||||
if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(!_supernodeAddresses.count(p->second->address())))
|
if (((now - p->second->lastUsed()) >= ZT_PEER_IN_MEMORY_EXPIRATION)&&(!_supernodeAddresses.count(p->second->address()))) {
|
||||||
_activePeers.erase(p++);
|
_activePeers.erase(p++);
|
||||||
else {
|
} else {
|
||||||
p->second->clean(now);
|
p->second->clean(now);
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
@ -288,101 +276,24 @@ bool Topology::authenticateRootTopology(const Dictionary &rt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::_dumpPeers()
|
Identity Topology::_getIdentity(const Address &zta)
|
||||||
{
|
{
|
||||||
#ifdef ZT_PEER_SERIALIZATION_VERSION
|
std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + zta.toString());
|
||||||
Buffer<ZT_PEER_WRITE_BUF_SIZE> buf;
|
std::string ids;
|
||||||
std::string pdpath(RR->homePath + ZT_PATH_SEPARATOR_S + "peers.persist");
|
if (Utils::readFile(idcPath.c_str(),ids)) {
|
||||||
Mutex::Lock _l(_activePeers_m);
|
|
||||||
|
|
||||||
FILE *pd = fopen(pdpath.c_str(),"wb");
|
|
||||||
if (!pd)
|
|
||||||
return;
|
|
||||||
if (fwrite("ZTPD0",5,1,pd) != 1) {
|
|
||||||
fclose(pd);
|
|
||||||
Utils::rm(pdpath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::map< Address,SharedPtr<Peer> >::iterator p(_activePeers.begin());p!=_activePeers.end();++p) {
|
|
||||||
try {
|
try {
|
||||||
p->second->serialize(buf);
|
return Identity(ids);
|
||||||
if (buf.size() >= (ZT_PEER_WRITE_BUF_SIZE / 2)) {
|
} catch ( ... ) {} // ignore invalid IDs
|
||||||
if (fwrite(buf.data(),buf.size(),1,pd) != 1) {
|
|
||||||
fclose(pd);
|
|
||||||
Utils::rm(pdpath);
|
|
||||||
buf.burn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
buf.clear();
|
|
||||||
buf.burn();
|
|
||||||
}
|
|
||||||
} catch ( ... ) {
|
|
||||||
fclose(pd);
|
|
||||||
Utils::rm(pdpath);
|
|
||||||
buf.burn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return Identity();
|
||||||
if (buf.size()) {
|
|
||||||
if (fwrite(buf.data(),buf.size(),1,pd) != 1) {
|
|
||||||
fclose(pd);
|
|
||||||
Utils::rm(pdpath);
|
|
||||||
buf.burn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
buf.burn();
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(pd);
|
|
||||||
buf.burn();
|
|
||||||
|
|
||||||
Utils::lockDownFile(pdpath.c_str(),false);
|
|
||||||
#endif // ZT_PEER_SERIALIZATION_VERSION
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Topology::_loadPeers()
|
void Topology::_saveIdentity(const Identity &id)
|
||||||
{
|
{
|
||||||
std::string pdpath(RR->homePath + ZT_PATH_SEPARATOR_S + "peers.persist");
|
if (id) {
|
||||||
|
std::string idcPath(_idCacheBase + ZT_PATH_SEPARATOR_S + id.address().toString());
|
||||||
#ifdef ZT_PEER_SERIALIZATION_VERSION
|
Utils::writeFile(idcPath.c_str(),id.toString(false));
|
||||||
Buffer<ZT_PEER_WRITE_BUF_SIZE> buf;
|
|
||||||
Mutex::Lock _l(_activePeers_m);
|
|
||||||
|
|
||||||
_activePeers.clear();
|
|
||||||
|
|
||||||
FILE *pd = fopen(pdpath.c_str(),"rb");
|
|
||||||
if (!pd)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
char magic[5];
|
|
||||||
if ((fread(magic,5,1,pd) == 1)&&(!memcmp("ZTPD0",magic,5))) {
|
|
||||||
long rlen = 0;
|
|
||||||
do {
|
|
||||||
long rlen = (long)fread(const_cast<char *>(static_cast<const char *>(buf.data())) + buf.size(),1,ZT_PEER_WRITE_BUF_SIZE - buf.size(),pd);
|
|
||||||
if (rlen < 0) rlen = 0;
|
|
||||||
buf.setSize(buf.size() + (unsigned int)rlen);
|
|
||||||
unsigned int ptr = 0;
|
|
||||||
while ((ptr < (ZT_PEER_WRITE_BUF_SIZE / 2))&&(ptr < buf.size())) {
|
|
||||||
SharedPtr<Peer> p(new Peer());
|
|
||||||
ptr += p->deserialize(buf,ptr);
|
|
||||||
_activePeers[p->address()] = p;
|
|
||||||
saveIdentity(p->identity());
|
|
||||||
}
|
|
||||||
buf.behead(ptr);
|
|
||||||
} while (rlen > 0);
|
|
||||||
}
|
|
||||||
} catch ( ... ) {
|
|
||||||
_activePeers.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(pd);
|
|
||||||
buf.burn();
|
|
||||||
#endif // ZT_PEER_SERIALIZATION_VERSION
|
|
||||||
|
|
||||||
Utils::rm(pdpath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -58,7 +58,7 @@ class RuntimeEnvironment;
|
||||||
class Topology
|
class Topology
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Topology(const RuntimeEnvironment *renv,bool enablePermanentIdCaching);
|
Topology(const RuntimeEnvironment *renv);
|
||||||
~Topology();
|
~Topology();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,26 +95,7 @@ public:
|
||||||
* @param zta ZeroTier address of peer
|
* @param zta ZeroTier address of peer
|
||||||
* @return Peer or NULL if not found
|
* @return Peer or NULL if not found
|
||||||
*/
|
*/
|
||||||
SharedPtr<Peer> getPeer(const Address &zta) const;
|
SharedPtr<Peer> getPeer(const Address &zta);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an identity if cached or available in a peer record
|
|
||||||
*
|
|
||||||
* @param zta ZeroTier address
|
|
||||||
* @return Identity or NULL-identity if not found
|
|
||||||
*/
|
|
||||||
Identity getIdentity(const Address &zta);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save identity in permanent store, or do nothing if disabled
|
|
||||||
*
|
|
||||||
* This is called automatically by addPeer(), so it should not need to be
|
|
||||||
* called manually anywhere else. The private part of the identity, if
|
|
||||||
* present, is NOT cached by this.
|
|
||||||
*
|
|
||||||
* @param id Identity to save
|
|
||||||
*/
|
|
||||||
void saveIdentity(const Identity &id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Vector of peers that are supernodes
|
* @return Vector of peers that are supernodes
|
||||||
|
@ -139,7 +120,7 @@ public:
|
||||||
*
|
*
|
||||||
* @return Supernode with lowest latency or NULL if none
|
* @return Supernode with lowest latency or NULL if none
|
||||||
*/
|
*/
|
||||||
inline SharedPtr<Peer> getBestSupernode() const
|
inline SharedPtr<Peer> getBestSupernode()
|
||||||
{
|
{
|
||||||
return getBestSupernode((const Address *)0,0,false);
|
return getBestSupernode((const Address *)0,0,false);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +137,7 @@ public:
|
||||||
* @param strictAvoid If false, consider avoided supernodes anyway if no non-avoid supernodes are available
|
* @param strictAvoid If false, consider avoided supernodes anyway if no non-avoid supernodes are available
|
||||||
* @return Supernode or NULL if none
|
* @return Supernode or NULL if none
|
||||||
*/
|
*/
|
||||||
SharedPtr<Peer> getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const;
|
SharedPtr<Peer> getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param zta ZeroTier address
|
* @param zta ZeroTier address
|
||||||
|
@ -373,12 +354,12 @@ public:
|
||||||
static bool authenticateRootTopology(const Dictionary &rt);
|
static bool authenticateRootTopology(const Dictionary &rt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Identity _getIdentity(const Address &zta);
|
||||||
|
void _saveIdentity(const Identity &id);
|
||||||
|
|
||||||
const RuntimeEnvironment *RR;
|
const RuntimeEnvironment *RR;
|
||||||
|
|
||||||
void _dumpPeers();
|
std::string _idCacheBase;
|
||||||
void _loadPeers();
|
|
||||||
|
|
||||||
std::string _idCacheBase; // empty if identity caching disabled
|
|
||||||
|
|
||||||
std::map< Address,SharedPtr<Peer> > _activePeers;
|
std::map< Address,SharedPtr<Peer> > _activePeers;
|
||||||
Mutex _activePeers_m;
|
Mutex _activePeers_m;
|
||||||
|
|
Loading…
Add table
Reference in a new issue