Browse Source

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

Adam Ierymenko 11 years ago
parent
commit
daaec84c6b
7 changed files with 46 additions and 38 deletions
  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;
 }