瀏覽代碼

World stuff...

Adam Ierymenko 9 年之前
父節點
當前提交
5d2f523e81
共有 15 個文件被更改,包括 92 次插入175 次删除
  1. 2 1
      .gitignore
  2. 0 5
      include/ZeroTierOne.h
  3. 0 4
      make-mac.mk
  4. 29 5
      node/IncomingPacket.cpp
  5. 24 15
      node/Node.cpp
  6. 3 32
      node/Packet.hpp
  7. 9 62
      node/Peer.cpp
  8. 4 21
      node/Peer.hpp
  9. 4 22
      node/RemotePath.hpp
  10. 1 2
      node/Topology.cpp
  11. 11 4
      node/Topology.hpp
  12. 0 2
      service/ControlPlane.cpp
  13. 二進制
      world/2015-10-13.bin
  14. 5 0
      world/2015-10-13.out
  15. 0 0
      world/mkworld.cpp

+ 2 - 1
.gitignore

@@ -31,7 +31,8 @@ Thumbs.db
 /ZeroTierOneInstaller-*
 /examples/docker/zerotier-one
 /examples/docker/test-*.env
-/mkworld
+/world/mkworld
+/world/*.c25519
 
 # Miscellaneous file types that we don't want to check in
 *.log

+ 0 - 5
include/ZeroTierOne.h

@@ -582,11 +582,6 @@ typedef struct
 	 */
 	uint64_t lastReceive;
 
-	/**
-	 * Is path fixed? (i.e. not learned, static)
-	 */
-	int fixed;
-
 	/**
 	 * Is path active?
 	 */

+ 0 - 4
make-mac.mk

@@ -79,10 +79,6 @@ selftest: $(OBJS) selftest.o
 	$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS)
 	$(STRIP) zerotier-selftest
 
-mkworld: $(OBJS)
-	rm -f mkworld
-	$(CXX) $(CXXFLAGS) -o mkworld mkworld.cpp $(OBJS) $(LIBS)
-
 # Requires Packages: http://s.sudre.free.fr/Software/Packages/about.html
 mac-dist-pkg: FORCE
 	packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj"

+ 29 - 5
node/IncomingPacket.cpp

@@ -42,6 +42,7 @@
 #include "SelfAwareness.hpp"
 #include "Salsa20.hpp"
 #include "SHA512.hpp"
+#include "World.hpp"
 
 namespace ZeroTier {
 
@@ -199,10 +200,18 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
 		const uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP);
 
 		Identity id;
-		const unsigned int destAddrPtr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
 		InetAddress destAddr;
-		if (destAddrPtr < size()) // ZeroTier One < 1.0.3 did not include this field
-			destAddr.deserialize(*this,destAddrPtr);
+		uint64_t worldId = ZT_WORLD_ID_NULL;
+		uint64_t worldTimestamp = 0;
+		{
+			unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
+			if (ptr < size()) // ZeroTier One < 1.0.3 did not include physical destination address info
+				ptr += destAddr.deserialize(*this,ptr);
+			if ((ptr + 16) <= size()) { // older versions also did not include World IDs or timestamps
+				worldId = at<uint64_t>(ptr); ptr += 8;
+				worldTimestamp = at<uint64_t>(ptr);
+			}
+		}
 
 		if (protoVersion < ZT_PROTO_VERSION_MIN) {
 			TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str());
@@ -286,8 +295,23 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
 		outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
 		outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
 		_remoteAddress.serialize(outp);
-		outp.armor(peer->key(),true);
-		RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
+
+		if ((worldId != ZT_WORLD_ID_NULL)&&(worldId == RR->topology->worldId())) {
+			if (RR->topology->worldTimestamp() > worldTimestamp) {
+				World w(RR->topology->world());
+				const unsigned int sizeAt = outp.size();
+				outp.addSize(2); // make room for 16-bit size field
+				w.serialize(outp,false);
+				outp.setAt<uint16_t>(sizeAt,(uint16_t)(outp.size() - sizeAt));
+			} else {
+				outp.append((uint16_t)0); // no world update needed
+			}
+
+			outp.armor(peer->key(),true);
+			RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
+		} else {
+			TRACE("dropped HELLO from %s(%s): world ID mismatch: peer is %llu and we are %llu",source().toString().c_str(),_remoteAddress.toString().c_str(),worldId,RR->topology->worldId());
+		}
 	} catch ( ... ) {
 		TRACE("dropped HELLO from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str());
 	}

+ 24 - 15
node/Node.cpp

@@ -177,37 +177,47 @@ public:
 		RR(renv),
 		_now(now),
 		_relays(relays),
-		_rootAddresses(RR->topology->rootAddresses())
+		_world(RR->topology->world())
 	{
 	}
 
-	uint64_t lastReceiveFromUpstream;
+	uint64_t lastReceiveFromUpstream; // tracks last time we got a packet from an 'upstream' peer like a root or a relay
 
 	inline void operator()(Topology &t,const SharedPtr<Peer> &p)
 	{
-		bool isRelay = false;
-		for(std::vector< std::pair<Address,InetAddress> >::const_iterator r(_relays.begin());r!=_relays.end();++r) {
-			if (r->first == p->address()) {
-				isRelay = true;
+		bool upstream = false;
+		InetAddress stableEndpoint;
+		for(std::vector<World::Root>::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) {
+			if (r->identity.address() == p->address()) {
+				if (r->stableEndpoints.size() > 0)
+					stableEndpoint = r->stableEndpoints[(unsigned long)RR->node->prng() % r->stableEndpoints.size()];
+				upstream = true;
 				break;
 			}
 		}
 
-		if ((isRelay)||(std::find(_rootAddresses.begin(),_rootAddresses.end(),p->address()) != _rootAddresses.end())) {
-			p->doPingAndKeepalive(RR,_now);
-			if (p->lastReceive() > lastReceiveFromUpstream)
-				lastReceiveFromUpstream = p->lastReceive();
-		} else {
-			if (p->alive(_now))
-				p->doPingAndKeepalive(RR,_now);
+		if (!upstream) {
+			for(std::vector< std::pair<Address,InetAddress> >::const_iterator r(_relays.begin());r!=_relays.end();++r) {
+				if (r->first == p->address()) {
+					stableEndpoint = r->second;
+					upstream = true;
+					break;
+				}
+			}
 		}
+
+		if ((!p->doPingAndKeepalive(RR,_now))&&(stableEndpoint))
+			p->attemptToContactAt(RR,InetAddress(),stableEndpoint,_now);
+
+		if (upstream)
+			lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream);
 	}
 
 private:
 	const RuntimeEnvironment *RR;
 	uint64_t _now;
 	const std::vector< std::pair<Address,InetAddress> > &_relays;
-	std::vector<Address> _rootAddresses;
+	World _world;
 };
 
 ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
@@ -376,7 +386,6 @@ ZT_PeerList *Node::peers() const
 			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();
-			p->paths[p->pathCount].fixed = path->fixed() ? 1 : 0;
 			p->paths[p->pathCount].active = path->active(_now) ? 1 : 0;
 			p->paths[p->pathCount].preferred = ((bestPath)&&(*path == *bestPath)) ? 1 : 0;
 			++p->pathCount;

+ 3 - 32
node/Packet.hpp

@@ -566,8 +566,8 @@ public:
 		 *   <[2] software revision (of responder)>
 		 *   <[1] destination address type (for this OK, not copied from HELLO)>
 		 *   [<[...] destination address>]
-		 *   <[8] 64-bit world ID of current world (of responder)>
-		 *   <[8] 64-bit timestamp of current world (of responder)>
+		 *   <[2] 16-bit length of world update or 0 if none>
+		 *   [[...] world update]
 		 *
 		 * ERROR has no payload.
 		 */
@@ -1098,36 +1098,7 @@ public:
 		 *
 		 * ERROR has no payload.
 		 */
-		VERB_REQUEST_PROOF_OF_WORK = 19,
-
-		/**
-		 * Generic binary object access:
-		 *   <[8] 64-bit request ID>
-		 *   <[4] 32-bit index in blob to retrieve>
-		 *   <[2] 16-bit max length of block to retrieve>
-		 *   <[2] 16-bit length of blob identifier>
-		 *   <[...] blob identifier>
-		 *
-		 * This is used as a generic remote object retrieval mechanism. It returns
-		 * OK if the object is accessible, INVALID_REQUEST if the index is beyond
-		 * the size of the blob or another element is invalid, and OBJ_NOT_FOUND
-		 * if no blob with the given identifier is available.
-		 *
-		 * Blob identifiers follow a de facto path-like schema, with the following
-		 * names reserved:
-		 *   world - Current world definition (see World.hpp)
-		 *   updates.d/<any> - Software updates (not used yet, but reserved)
-		 *
-		 * OK payload:
-		 *   <[8] 64-bit request ID>
-		 *   <[4] 32-bit total length of blob>
-		 *   <[4] 32-bit index of this data in blob>
-		 *   <[...] data>
-		 *
-		 * ERROR payload:
-		 *   <[8] 64-bit request ID>
-		 */
-		VERB_GET_OBJECT = 20
+		VERB_REQUEST_PROOF_OF_WORK = 19
 	};
 
 	/**

+ 9 - 62
node/Peer.cpp

@@ -108,17 +108,16 @@ void Peer::received(
 							// Add new path
 							slot = &(_paths[np++]);
 						} else {
-							// Replace oldest non-fixed path
 							uint64_t slotLRmin = 0xffffffffffffffffULL;
 							for(unsigned int p=0;p<ZT_MAX_PEER_NETWORK_PATHS;++p) {
-								if ((!_paths[p].fixed())&&(_paths[p].lastReceived() <= slotLRmin)) {
+								if (_paths[p].lastReceived() <= slotLRmin) {
 									slotLRmin = _paths[p].lastReceived();
 									slot = &(_paths[p]);
 								}
 							}
 						}
 						if (slot) {
-							*slot = RemotePath(localAddr,remoteAddr,false);
+							*slot = RemotePath(localAddr,remoteAddr);
 							slot->received(now);
 							_numPaths = np;
 							pathIsConfirmed = true;
@@ -172,12 +171,15 @@ void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &lo
 	outp.append(now);
 	RR->identity.serialize(outp,false);
 	atAddress.serialize(outp);
+	outp.append((uint64_t)RR->topology->worldId());
+	outp.append((uint64_t)RR->topology->worldTimestamp());
+
 	outp.armor(_key,false); // HELLO is sent in the clear
 	RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 	RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size());
 }
 
-void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)
+RemotePath *Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)
 {
 	Mutex::Lock _l(_lock);
 	RemotePath *const bestPath = _getBestPath(now);
@@ -193,6 +195,7 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)
 			bestPath->sent(now);
 		}
 	}
+	return bestPath;
 }
 
 void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_t now,bool force)
@@ -269,59 +272,6 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_
 	}
 }
 
-void Peer::addPath(const RemotePath &newp,uint64_t now)
-{
-	Mutex::Lock _l(_lock);
-
-	unsigned int np = _numPaths;
-
-	for(unsigned int p=0;p<np;++p) {
-		if (_paths[p].address() == newp.address()) {
-			_paths[p].setFixed(newp.fixed());
-			_sortPaths(now);
-			return;
-		}
-	}
-
-	RemotePath *slot = (RemotePath *)0;
-	if (np < ZT_MAX_PEER_NETWORK_PATHS) {
-		// Add new path
-		slot = &(_paths[np++]);
-	} else {
-		// Replace oldest non-fixed path
-		uint64_t slotLRmin = 0xffffffffffffffffULL;
-		for(unsigned int p=0;p<ZT_MAX_PEER_NETWORK_PATHS;++p) {
-			if ((!_paths[p].fixed())&&(_paths[p].lastReceived() <= slotLRmin)) {
-				slotLRmin = _paths[p].lastReceived();
-				slot = &(_paths[p]);
-			}
-		}
-	}
-	if (slot) {
-		*slot = newp;
-		_numPaths = np;
-	}
-
-	_sortPaths(now);
-}
-
-void Peer::clearPaths(bool fixedToo)
-{
-	if (fixedToo) {
-		_numPaths = 0;
-	} else {
-		unsigned int np = _numPaths;
-		unsigned int x = 0;
-		unsigned int y = 0;
-		while (x < np) {
-			if (_paths[x].fixed())
-				_paths[y++] = _paths[x];
-			++x;
-		}
-		_numPaths = y;
-	}
-}
-
 bool Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope scope,uint64_t now)
 {
 	Mutex::Lock _l(_lock);
@@ -330,12 +280,9 @@ bool Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope sc
 	unsigned int y = 0;
 	while (x < np) {
 		if (_paths[x].address().ipScope() == scope) {
-			if (_paths[x].fixed()) {
-				attemptToContactAt(RR,_paths[x].localAddress(),_paths[x].address(),now);
-				_paths[y++] = _paths[x]; // keep fixed paths
-			}
+			attemptToContactAt(RR,_paths[x].localAddress(),_paths[x].address(),now);
 		} else {
-			_paths[y++] = _paths[x]; // keep paths not in this scope
+			_paths[y++] = _paths[x];
 		}
 		++x;
 	}

+ 4 - 21
node/Peer.hpp

@@ -133,7 +133,7 @@ public:
 	 * Get the best direct path to this peer
 	 *
 	 * @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 direct paths
 	 */
 	inline RemotePath *getBestPath(uint64_t now)
 	{
@@ -178,8 +178,9 @@ public:
 	 *
 	 * @param RR Runtime environment
 	 * @param now Current time
+	 * @return Current best path or NULL if no active paths
 	 */
-	void doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now);
+	RemotePath *doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now);
 
 	/**
 	 * Push direct paths if we haven't done so in [rate limit] milliseconds
@@ -290,7 +291,7 @@ public:
 
 	/**
 	 * @param now Current time
-	 * @return True if this peer has at least one active or fixed direct path
+	 * @return True if this peer has at least one active direct path
 	 */
 	inline bool hasActiveDirectPath(uint64_t now) const
 		throw()
@@ -303,27 +304,9 @@ public:
 		return false;
 	}
 
-	/**
-	 * Add a path (if we don't already have it)
-	 *
-	 * @param p New path to add
-	 * @param now Current time
-	 */
-	void addPath(const RemotePath &newp,uint64_t now);
-
-	/**
-	 * Clear paths
-	 *
-	 * @param fixedToo If true, clear fixed paths as well as learned ones
-	 */
-	void clearPaths(bool fixedToo);
-
 	/**
 	 * Reset paths within a given scope
 	 *
-	 * For fixed paths in this scope, a packet is sent. Non-fixed paths in this
-	 * scope are forgotten.
-	 *
 	 * @param RR Runtime environment
 	 * @param scope IP scope of paths to reset
 	 * @param now Current time

+ 4 - 22
node/RemotePath.hpp

@@ -39,8 +39,6 @@
 #include "AntiRecursion.hpp"
 #include "RuntimeEnvironment.hpp"
 
-#define ZT_REMOTEPATH_FLAG_FIXED 0x0001
-
 namespace ZeroTier {
 
 /**
@@ -58,34 +56,18 @@ public:
 		_localAddress(),
 		_flags(0) {}
 
-	RemotePath(const InetAddress &localAddress,const InetAddress &addr,bool fixed) :
+	RemotePath(const InetAddress &localAddress,const InetAddress &addr) :
 		Path(addr,0,TRUST_NORMAL),
 		_lastSend(0),
 		_lastReceived(0),
 		_localAddress(localAddress),
-		_flags(fixed ? ZT_REMOTEPATH_FLAG_FIXED : 0) {}
+		_flags(0) {}
 
 	inline const InetAddress &localAddress() const throw() { return _localAddress; }
 
 	inline uint64_t lastSend() const throw() { return _lastSend; }
 	inline uint64_t lastReceived() const throw() { return _lastReceived; }
 
-	/**
-	 * @return Is this a fixed path?
-	 */
-	inline bool fixed() const throw() { return ((_flags & ZT_REMOTEPATH_FLAG_FIXED) != 0); }
-
-	/**
-	 * @param f New value of fixed flag
-	 */
-	inline void setFixed(const bool f)
-		throw()
-	{
-		if (f)
-			_flags |= ZT_REMOTEPATH_FLAG_FIXED;
-		else _flags &= ~ZT_REMOTEPATH_FLAG_FIXED;
-	}
-
 	/**
 	 * Called when a packet is sent to this remote path
 	 *
@@ -112,12 +94,12 @@ public:
 
 	/**
 	 * @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 appears active
 	 */
 	inline bool active(uint64_t now) const
 		throw()
 	{
-		return ( ((_flags & ZT_REMOTEPATH_FLAG_FIXED) != 0) || ((now - _lastReceived) < ZT_PEER_ACTIVITY_TIMEOUT) );
+		return ((now - _lastReceived) < ZT_PEER_ACTIVITY_TIMEOUT);
 	}
 
 	/**

File diff suppressed because it is too large
+ 1 - 2
node/Topology.cpp


+ 11 - 4
node/Topology.hpp

@@ -147,12 +147,19 @@ public:
 	}
 
 	/**
-	 * @return Pair containing world ID and world timestamp (faster than world().id() etc.)
+	 * @return Current world ID
 	 */
-	inline std::pair<uint64_t,uint64_t> worldIdentification() const
+	inline uint64_t worldId() const
 	{
-		Mutex::Lock _l(_lock);
-		return std::pair<uint64_t,uint64_t>(_world.id(),_world.timestamp());
+		return _world.id(); // safe to read without lock, and used from within eachPeer() so don't lock
+	}
+
+	/**
+	 * @return Current world timestamp
+	 */
+	inline uint64_t worldTimestamp() const
+	{
+		return _world.timestamp(); // safe to read without lock, and used from within eachPeer() so don't lock
 	}
 
 	/**

+ 0 - 2
service/ControlPlane.cpp

@@ -182,14 +182,12 @@ static std::string _jsonEnumerate(unsigned int depth,const ZT_PeerPhysicalPath *
 			"%s\t\"address\": \"%s\",\n"
 			"%s\t\"lastSend\": %llu,\n"
 			"%s\t\"lastReceive\": %llu,\n"
-			"%s\t\"fixed\": %s,\n"
 			"%s\t\"active\": %s,\n"
 			"%s\t\"preferred\": %s\n"
 			"%s}",
 			prefix,_jsonEscape(reinterpret_cast<const InetAddress *>(&(pp[i].address))->toString()).c_str(),
 			prefix,pp[i].lastSend,
 			prefix,pp[i].lastReceive,
-			prefix,(pp[i].fixed == 0) ? "false" : "true",
 			prefix,(pp[i].active == 0) ? "false" : "true",
 			prefix,(pp[i].preferred == 0) ? "false" : "true",
 			prefix);

二進制
world/2015-10-13.bin


File diff suppressed because it is too large
+ 5 - 0
world/2015-10-13.out


+ 0 - 0
mkworld.cpp → world/mkworld.cpp


Some files were not shown because too many files changed in this diff