Explorar el Código

Add TCP channel support for supernode list, make Peer pick the first path if all paths are equally dead.

Adam Ierymenko hace 11 años
padre
commit
daaec84c6b
Se han modificado 7 ficheros con 46 adiciones y 38 borrados
  1. 9 8
      node/Defaults.cpp
  2. 2 2
      node/Defaults.hpp
  3. 18 10
      node/Peer.cpp
  4. 2 2
      node/Switch.cpp
  5. 4 5
      node/Topology.cpp
  6. 2 11
      node/Topology.hpp
  7. 9 0
      node/UdpSocket.cpp

+ 9 - 8
node/Defaults.cpp

@@ -43,11 +43,11 @@ namespace ZeroTier {
 
 const Defaults ZT_DEFAULTS;
 
-static inline std::map< Identity,std::vector<InetAddress> > _mkSupernodeMap()
+static inline std::map< Identity,std::vector< std::pair<InetAddress,bool> > > _mkSupernodeMap()
 {
-	std::map< Identity,std::vector<InetAddress> > sn;
+	std::map< Identity,std::vector< std::pair<InetAddress,bool> > > sn;
 	Identity id;
-	std::vector<InetAddress> addrs;
+	std::vector< std::pair<InetAddress,bool> > addrs;
 
 	// Nothing special about a supernode... except that they are
 	// designated as such and trusted to provide WHOIS lookup.
@@ -56,35 +56,36 @@ static inline std::map< Identity,std::vector<InetAddress> > _mkSupernodeMap()
 	addrs.clear();
 	if (!id.fromString("8acf059fe3:0:482f6ee5dfe902319b419de5bdc765209c0ecda38c4d6e4fcf0d33658398b4527dcd22f93112fb9befd02fd78bf7261b333fc105d192a623ca9e50fc60b374a5"))
 		throw std::runtime_error("invalid identity in Defaults");
-	addrs.push_back(InetAddress("162.243.77.111",ZT_DEFAULT_PORT));
+	addrs.push_back(std::pair<InetAddress,bool>(InetAddress("162.243.77.111",ZT_DEFAULT_PORT),false));
+	addrs.push_back(std::pair<InetAddress,bool>(InetAddress("162.243.77.111",443),true));
 	sn[id] = addrs;
 
 	// nyarlathotep.zerotier.com - San Francisco, California, USA
 	addrs.clear();
 	if (!id.fromString("7e19876aba:0:2a6e2b2318930f60eb097f70d0f4b028b2cd6d3d0c63c014b9039ff35390e41181f216fb2e6fa8d95c1ee9667156411905c3dccfea78d8c6dfafba688170b3fa"))
 		throw std::runtime_error("invalid identity in Defaults");
-	addrs.push_back(InetAddress("198.199.97.220",ZT_DEFAULT_PORT));
+	addrs.push_back(std::pair<InetAddress,bool>(InetAddress("198.199.97.220",ZT_DEFAULT_PORT),false));
 	sn[id] = addrs;
 
 	// shub-niggurath.zerotier.com - Amsterdam, Netherlands
 	addrs.clear();
 	if (!id.fromString("36f63d6574:0:67a776487a1a99b32f413329f2b67c43fbf6152e42c6b66e89043e69d93e48314c7d709b58a83016bd2612dd89400b856e18c553da94892f7d3ca16bf2c92c24"))
 		throw std::runtime_error("invalid identity in Defaults");
-	addrs.push_back(InetAddress("198.211.127.172",ZT_DEFAULT_PORT));
+	addrs.push_back(std::pair<InetAddress,bool>(InetAddress("198.211.127.172",ZT_DEFAULT_PORT),false));
 	sn[id] = addrs;
 
 	// mi-go.zerotier.com - Singapore
 	addrs.clear();
 	if (!id.fromString("abbb7f4622:0:89d2c6b2062b10f4ce314dfcb914c082566247090a6f74c8ba1c15c63b205f540758f0abae85287397152c9d8cf463cfe51e7a480946cd6a31495b24ca13253c"))
 		throw std::runtime_error("invalid identity in Defaults");
-	addrs.push_back(InetAddress("128.199.254.204",ZT_DEFAULT_PORT));
+	addrs.push_back(std::pair<InetAddress,bool>(InetAddress("128.199.254.204",ZT_DEFAULT_PORT),false));
 	sn[id] = addrs;
 
 	// shoggoth.zerotier.com - Tokyo, Japan
 	addrs.clear();
 	if (!id.fromString("48e8f875cb:0:5ca54f55e1094f65589f3e6d74158b6964d418ddac3570757128f1c6a2498322d92fcdcd47de459f4d1f9b38df2afd0c7b3fc247ba3d773c38ba35288f24988e"))
 		throw std::runtime_error("invalid identity in Defaults");
-	addrs.push_back(InetAddress("108.61.200.101",ZT_DEFAULT_PORT));
+	addrs.push_back(std::pair<InetAddress,bool>(InetAddress("108.61.200.101",ZT_DEFAULT_PORT),false));
 	sn[id] = addrs;
 
 	return sn;

+ 2 - 2
node/Defaults.hpp

@@ -64,9 +64,9 @@ public:
 	const std::string defaultHomePath;
 
 	/**
-	 * Supernodes on the ZeroTier network
+	 * Supernodes on the ZeroTier network (identity, address/tcp?)
 	 */
-	const std::map< Identity,std::vector<InetAddress> > supernodes;
+	const std::map< Identity,std::vector< std::pair<InetAddress,bool> > > supernodes;
 
 	/**
 	 * Identities permitted to sign software updates

+ 18 - 10
node/Peer.cpp

@@ -91,6 +91,7 @@ void Peer::receive(
 		}
 
 		// Announce multicast LIKEs to peers to whom we have a direct link
+		// Lock can't be locked here or it'll recurse and deadlock.
 		if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
 			_lastAnnouncedTo = now;
 			_r->sw->announceMulticastGroups(SharedPtr<Peer>(this));
@@ -107,12 +108,14 @@ bool Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int len,u
 {
 	Mutex::Lock _l(_lock);
 
-	if (_paths.empty())
+	std::vector<Path>::iterator p(_paths.begin());
+	if (p == _paths.end()) {
+		TRACE("send to %s failed: no paths available",_id.address().toString().c_str());
 		return false;
-
-	uint64_t bestPathLastReceived = 0;
-	std::vector<Path>::iterator bestPath;
-	for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
+	}
+	uint64_t bestPathLastReceived = p->lastReceived();
+	std::vector<Path>::iterator bestPath = p;
+	while (++p != _paths.end()) {
 		uint64_t lr = p->lastReceived();
 		if (lr >= bestPathLastReceived) {
 			bestPathLastReceived = lr;
@@ -120,6 +123,8 @@ bool Peer::send(const RuntimeEnvironment *_r,const void *data,unsigned int len,u
 		}
 	}
 
+	TRACE("send to %s: using path: %s",_id.address().toString().c_str(),bestPath->toString().c_str());
+
 	if (_r->sm->send(bestPath->address(),bestPath->tcp(),data,len)) {
 		bestPath->sent(now);
 		return true;
@@ -147,19 +152,22 @@ bool Peer::sendPing(const RuntimeEnvironment *_r,uint64_t now,bool firstSinceRes
 	SharedPtr<Peer> self(this);
 	Mutex::Lock _l(_lock);
 
-	bool allPingsUnanswered;
+	bool pingTcp;
 	if (!firstSinceReset) {
-		allPingsUnanswered = true;
+		// Do not use TCP if one of our UDP endpoints has answered recently.
+		pingTcp = true;
 		for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
 			if (!p->pingUnanswered(now)) {
-				allPingsUnanswered = false;
+				pingTcp = false;
 				break;
 			}
 		}
-	} else allPingsUnanswered = false;
+	} else pingTcp = false;
+
+	TRACE("PING %s (pingTcp==%d)",_id.address().toString().c_str(),(int)pingTcp);
 
 	for(std::vector<Path>::iterator p(_paths.begin());p!=_paths.end();++p) {
-		if ((allPingsUnanswered)||(!p->tcp())) {
+		if ((pingTcp)||(!p->tcp())) {
 			if (_r->sw->sendHELLO(self,p->address(),p->tcp())) {
 				p->sent(now);
 				p->pinged(now);

+ 2 - 2
node/Switch.cpp

@@ -752,13 +752,13 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
 				}
 			}
 
-#ifdef ZT_TRACE
+/* #ifdef ZT_TRACE
 			if (via != peer) {
 				TRACE(">> %s to %s via %s (%d)",Packet::verbString(packet.verb()),peer->address().toString().c_str(),via->address().toString().c_str(),(int)packet.size());
 			} else {
 				TRACE(">> %s to %s (%d)",Packet::verbString(packet.verb()),peer->address().toString().c_str(),(int)packet.size());
 			}
-#endif
+#endif */
 
 			return true;
 		}

+ 4 - 5
node/Topology.cpp

@@ -50,7 +50,7 @@ Topology::~Topology()
 	_dumpPeers();
 }
 
-void Topology::setSupernodes(const std::map< Identity,std::vector<InetAddress> > &sn)
+void Topology::setSupernodes(const std::map< Identity,std::vector< std::pair<InetAddress,bool> > > &sn)
 {
 	Mutex::Lock _l(_supernodes_m);
 
@@ -59,14 +59,13 @@ void Topology::setSupernodes(const std::map< Identity,std::vector<InetAddress> >
 	_supernodePeers.clear();
 	uint64_t now = Utils::now();
 
-	for(std::map< Identity,std::vector<InetAddress> >::const_iterator i(sn.begin());i!=sn.end();++i) {
+	for(std::map< Identity,std::vector< std::pair<InetAddress,bool> > >::const_iterator i(sn.begin());i!=sn.end();++i) {
 		if (i->first != _r->identity) {
 			SharedPtr<Peer> p(getPeer(i->first.address()));
 			if (!p)
 				p = addPeer(SharedPtr<Peer>(new Peer(_r->identity,i->first)));
-			for(std::vector<InetAddress>::const_iterator j(i->second.begin());j!=i->second.end();++j) {
-				p->addPath(Path(*j,false,true));
-			}
+			for(std::vector< std::pair<InetAddress,bool> >::const_iterator j(i->second.begin());j!=i->second.end();++j)
+				p->addPath(Path(j->first,j->second,true));
 			p->use(now);
 			_supernodePeers.push_back(p);
 		}

+ 2 - 11
node/Topology.hpp

@@ -63,7 +63,7 @@ public:
 	 * 
 	 * @param sn Supernodes for this network
 	 */
-	void setSupernodes(const std::map< Identity,std::vector<InetAddress> > &sn);
+	void setSupernodes(const std::map< Identity,std::vector< std::pair<InetAddress,bool> > > &sn);
 
 	/**
 	 * Add a peer to database
@@ -103,15 +103,6 @@ public:
 	 */
 	void saveIdentity(const Identity &id);
 
-	/**
-	 * @return Current network supernodes
-	 */
-	inline std::map< Identity,std::vector<InetAddress> > supernodes() const
-	{
-		Mutex::Lock _l(_supernodes_m);
-		return _supernodes;
-	}
-
 	/**
 	 * @return Vector of peers that are supernodes
 	 */
@@ -313,7 +304,7 @@ private:
 	std::map< Address,SharedPtr<Peer> > _activePeers;
 	Mutex _activePeers_m;
 
-	std::map< Identity,std::vector<InetAddress> > _supernodes;
+	std::map< Identity,std::vector< std::pair<InetAddress,bool> > > _supernodes;
 	std::set< Address > _supernodeAddresses;
 	std::vector< SharedPtr<Peer> > _supernodePeers;
 	Mutex _supernodes_m;

+ 9 - 0
node/UdpSocket.cpp

@@ -48,6 +48,9 @@
 #include <signal.h>
 #endif
 
+// Uncomment to intentionally break UDP in order to test TCP fallback
+#define ZT_BREAK_UDP
+
 namespace ZeroTier {
 
 UdpSocket::~UdpSocket()
@@ -66,6 +69,9 @@ bool UdpSocket::send(const InetAddress &to,const void *msg,unsigned int msglen)
 
 bool UdpSocket::sendWithHopLimit(const InetAddress &to,const void *msg,unsigned int msglen,int hopLimit)
 {
+#ifdef ZT_BREAK_UDP
+	return true;
+#else
 	if (hopLimit <= 0)
 		hopLimit = 255;
 	if (to.isV6()) {
@@ -87,6 +93,7 @@ bool UdpSocket::sendWithHopLimit(const InetAddress &to,const void *msg,unsigned
 		return ((int)sendto(_sock,msg,msglen,0,to.saddr(),to.saddrLen()) == (int)msglen);
 #endif
 	}
+#endif
 }
 
 bool UdpSocket::notifyAvailableForRead(const SharedPtr<Socket> &self,SocketManager *sm)
@@ -97,7 +104,9 @@ bool UdpSocket::notifyAvailableForRead(const SharedPtr<Socket> &self,SocketManag
 	int n = (int)recvfrom(_sock,(char *)(buf.data()),ZT_SOCKET_MAX_MESSAGE_LEN,0,from.saddr(),&salen);
 	if (n > 0) {
 		buf.setSize((unsigned int)n);
+#ifndef ZT_BREAK_UDP
 		sm->handleReceivedPacket(self,from,buf);
+#endif
 	}
 	return true;
 }