diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/IncomingPacket.cpp | 3 | ||||
-rw-r--r-- | node/Node.cpp | 49 | ||||
-rw-r--r-- | node/Node.hpp | 2 | ||||
-rw-r--r-- | node/Peer.cpp | 9 | ||||
-rw-r--r-- | node/Topology.cpp | 120 | ||||
-rw-r--r-- | node/Topology.hpp | 39 |
6 files changed, 192 insertions, 30 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 28b845b4..93bf4590 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -444,7 +444,8 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p TRACE("%s(%s): OK(HELLO), version %u.%u.%u, latency %u, reported external address %s",source().toString().c_str(),_path->address().toString().c_str(),vMajor,vMinor,vRevision,latency,((externalSurfaceAddress) ? externalSurfaceAddress.toString().c_str() : "(none)")); - peer->addDirectLatencyMeasurment(latency); + if (!hops()) + peer->addDirectLatencyMeasurment(latency); peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); if ((externalSurfaceAddress)&&(hops() == 0)) diff --git a/node/Node.cpp b/node/Node.cpp index 23271cca..f5ee1f9d 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -168,26 +168,35 @@ public: inline void operator()(Topology &t,const SharedPtr<Peer> &p) { - const std::vector<InetAddress> *upstreamStableEndpoints = _upstreams.get(p->address()); - if ((upstreamStableEndpoints)&&(upstreamStableEndpoints->size() > 0)) { + const std::vector<InetAddress> *const upstreamStableEndpoints = _upstreams.get(p->address()); + if (upstreamStableEndpoints) { + bool contacted = false; + if (!p->doPingAndKeepalive(_now,AF_INET)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET) { p->sendHELLO(InetAddress(),addr,_now); + contacted = true; break; } } - } + } else contacted = true; + if (!p->doPingAndKeepalive(_now,AF_INET6)) { for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) { const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()]; if (addr.ss_family == AF_INET6) { p->sendHELLO(InetAddress(),addr,_now); + contacted = true; break; } } - } + } else contacted = true; + + if (!contacted) + p->sendHELLO(InetAddress(),InetAddress(),_now); + lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream); } else if (p->isActive(_now)) { p->doPingAndKeepalive(_now,-1); @@ -224,7 +233,7 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB for(std::vector< SharedPtr<Network> >::const_iterator n(needConfig.begin());n!=needConfig.end();++n) (*n)->requestConfiguration(); - // Run WHOIS on upstreams we don't know about + // Attempt to get identity for any unknown upstreams const std::vector<Address> upstreams(RR->topology->upstreamAddresses()); for(std::vector<Address>::const_iterator a(upstreams.begin());a!=upstreams.end();++a) { if (!RR->topology->getPeer(*a)) @@ -323,6 +332,18 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } +ZT_ResultCode Node::orbit(uint64_t moonWorldId) +{ + RR->topology->addMoon(moonWorldId); + return ZT_RESULT_OK; +} + +ZT_ResultCode Node::deorbit(uint64_t moonWorldId) +{ + RR->topology->removeMoon(moonWorldId); + return ZT_RESULT_OK; +} + uint64_t Node::address() const { return RR->identity.address().toInt(); @@ -893,6 +914,24 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint } } +enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,uint64_t moonWorldId) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->orbit(moonWorldId); + } catch ( ... ) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + +ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,uint64_t moonWorldId) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->deorbit(moonWorldId); + } catch ( ... ) { + return ZT_RESULT_FATAL_ERROR_INTERNAL; + } +} + uint64_t ZT_Node_address(ZT_Node *node) { return reinterpret_cast<ZeroTier::Node *>(node)->address(); diff --git a/node/Node.hpp b/node/Node.hpp index 662abcb4..3e742092 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -95,6 +95,8 @@ public: ZT_ResultCode leave(uint64_t nwid,void **uptr); ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); + ZT_ResultCode orbit(uint64_t moonWorldId); + ZT_ResultCode deorbit(uint64_t moonWorldId); uint64_t address() const; void status(ZT_NodeStatus *status) const; ZT_PeerList *peers() const; diff --git a/node/Peer.cpp b/node/Peer.cpp index 441a5b33..50135b9f 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -366,8 +366,13 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u } RR->node->expectReplyTo(outp.packetId()); - outp.armor(_key,false); // HELLO is sent in the clear - RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); + + if (atAddress) { + outp.armor(_key,false); + RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); + } else { + RR->sw->send(outp,false); + } } void Peer::attemptToContactAt(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now) diff --git a/node/Topology.cpp b/node/Topology.cpp index be6807da..38afacb0 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -48,13 +48,6 @@ Topology::Topology(const RuntimeEnvironment *renv) : _trustedPathCount(0), _amRoot(false) { - World defaultPlanet; - { - Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH); - defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top - } - addWorld(defaultPlanet,false); - try { World cachedPlanet; std::string buf(RR->node->dataStoreGet("planet")); @@ -64,6 +57,13 @@ Topology::Topology(const RuntimeEnvironment *renv) : } addWorld(cachedPlanet,false); } catch ( ... ) {} + + World defaultPlanet; + { + Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH); + defaultPlanet.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top + } + addWorld(defaultPlanet,false); } SharedPtr<Peer> Topology::addPeer(const SharedPtr<Peer> &peer) @@ -287,7 +287,7 @@ bool Topology::addWorld(const World &newWorld,bool updateOnly) char savePath[64]; if (existing->type() == World::TYPE_MOON) - Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx",existing->id()); + Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",existing->id()); else Utils::scopy(savePath,sizeof(savePath),"planet"); try { Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp; @@ -297,22 +297,71 @@ bool Topology::addWorld(const World &newWorld,bool updateOnly) RR->node->dataStoreDelete(savePath); } - _upstreamAddresses.clear(); - _amRoot = false; - for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { - if (i->identity == RR->identity) - _amRoot = true; - else _upstreamAddresses.push_back(i->identity.address()); + if (existing->type() == World::TYPE_MOON) { + std::vector<Address> cm; + for(std::vector<Address>::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) { + if (m->toInt() != ((existing->id() >> 24) & 0xffffffffffULL)) + cm.push_back(*m); + } + _contacingMoons.swap(cm); } + + _memoizeUpstreams(); + + return true; +} + +void Topology::addMoon(const uint64_t id) +{ + char savePath[64]; + Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id); + + try { + std::string moonBin(RR->node->dataStoreGet(savePath)); + if (moonBin.length() > 1) { + Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> wtmp(moonBin.data(),(unsigned int)moonBin.length()); + World w; + w.deserialize(wtmp); + if (w.type() == World::TYPE_MOON) { + addWorld(w,false); + return; + } + } + } catch ( ... ) {} + + { + const Address a(id >> 24); + Mutex::Lock _l(_lock); + if (std::find(_contacingMoons.begin(),_contacingMoons.end(),a) == _contacingMoons.end()) + _contacingMoons.push_back(a); + } + RR->node->dataStorePut(savePath,"\0",1,false); // persist that we want to be a member +} + +void Topology::removeMoon(const uint64_t id) +{ + Mutex::Lock _l(_lock); + + std::vector<World> nm; for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) { - for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { - if (i->identity == RR->identity) - _amRoot = true; - else _upstreamAddresses.push_back(i->identity.address()); + if (m->id() != id) { + nm.push_back(*m); + } else { + char savePath[64]; + Utils::snprintf(savePath,sizeof(savePath),"moons.d/%.16llx.moon",id); + RR->node->dataStoreDelete(savePath); } } + _moons.swap(nm); - return false; + std::vector<Address> cm; + for(std::vector<Address>::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) { + if (m->toInt() != ((id >> 24) & 0xffffffffffULL)) + cm.push_back(*m); + } + _contacingMoons.swap(cm); + + _memoizeUpstreams(); } void Topology::clean(uint64_t now) @@ -351,4 +400,37 @@ Identity Topology::_getIdentity(const Address &zta) return Identity(); } +void Topology::_memoizeUpstreams() +{ + // assumes _lock is locked + _upstreamAddresses.clear(); + _amRoot = false; + for(std::vector<World::Root>::const_iterator i(_planet.roots().begin());i!=_planet.roots().end();++i) { + if (i->identity == RR->identity) { + _amRoot = true; + } else { + _upstreamAddresses.push_back(i->identity.address()); + SharedPtr<Peer> &hp = _peers[i->identity.address()]; + if (!hp) { + hp = new Peer(RR,RR->identity,i->identity); + saveIdentity(i->identity); + } + } + } + for(std::vector<World>::const_iterator m(_moons.begin());m!=_moons.end();++m) { + for(std::vector<World::Root>::const_iterator i(m->roots().begin());i!=m->roots().end();++i) { + if (i->identity == RR->identity) { + _amRoot = true; + } else { + _upstreamAddresses.push_back(i->identity.address()); + SharedPtr<Peer> &hp = _peers[i->identity.address()]; + if (!hp) { + hp = new Peer(RR,RR->identity,i->identity); + saveIdentity(i->identity); + } + } + } + } +} + } // namespace ZeroTier diff --git a/node/Topology.hpp b/node/Topology.hpp index 6369c5cd..693ae12c 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -169,6 +169,11 @@ public: bool isProhibitedEndpoint(const Address &ztaddr,const InetAddress &ipaddr) const; /** + * This gets the known stable endpoints for any upstream + * + * It also adds empty entries for any upstreams we are attempting to + * contact. + * * @param eps Hash table to fill with addresses and their stable endpoints */ inline void getUpstreamStableEndpoints(Hashtable< Address,std::vector<InetAddress> > &eps) const @@ -190,6 +195,8 @@ public: } } } + for(std::vector<Address>::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) + eps[*m]; } /** @@ -198,7 +205,12 @@ public: inline std::vector<Address> upstreamAddresses() const { Mutex::Lock _l(_lock); - return _upstreamAddresses; + std::vector<Address> u(_upstreamAddresses); + for(std::vector<Address>::const_iterator m(_contacingMoons.begin());m!=_contacingMoons.end();++m) { + if (std::find(u.begin(),u.end(),*m) == u.end()) + u.push_back(*m); + } + return u; } /** @@ -245,6 +257,25 @@ public: bool addWorld(const World &newWorld,bool updateOnly); /** + * Add a moon + * + * This loads it from moons.d if present, and if not adds it to + * a list of moons that we want to contact. It does not actually + * send anything, though this will happen on the next background + * task loop where pings etc. are checked. + * + * @param id Moon ID + */ + void addMoon(const uint64_t id); + + /** + * Remove a moon + * + * @param id Moon's world ID + */ + void removeMoon(const uint64_t id); + + /** * Clean and flush database */ void clean(uint64_t now); @@ -362,6 +393,7 @@ public: private: Identity _getIdentity(const Address &zta); + void _memoizeUpstreams(); const RuntimeEnvironment *const RR; @@ -375,8 +407,9 @@ private: Hashtable< Address,SharedPtr<Peer> > _peers; Hashtable< Path::HashKey,SharedPtr<Path> > _paths; - std::vector< Address > _upstreamAddresses; // includes root addresses of both planets and moons - bool _amRoot; // am I a root in a planet or moon? + std::vector<Address> _contacingMoons; + std::vector<Address> _upstreamAddresses; + bool _amRoot; Mutex _lock; }; |