From daaec84c6be11b57572ff57c97efd993385890fd Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 26 Mar 2014 15:35:15 -0700 Subject: [PATCH] Add TCP channel support for supernode list, make Peer pick the first path if all paths are equally dead. --- node/Defaults.cpp | 17 +++++++++-------- node/Defaults.hpp | 4 ++-- node/Peer.cpp | 28 ++++++++++++++++++---------- node/Switch.cpp | 4 ++-- node/Topology.cpp | 9 ++++----- node/Topology.hpp | 13 ++----------- node/UdpSocket.cpp | 9 +++++++++ 7 files changed, 46 insertions(+), 38 deletions(-) diff --git a/node/Defaults.cpp b/node/Defaults.cpp index 3e0727da1..44d5aa053 100644 --- a/node/Defaults.cpp +++ b/node/Defaults.cpp @@ -43,11 +43,11 @@ namespace ZeroTier { const Defaults ZT_DEFAULTS; -static inline std::map< Identity,std::vector > _mkSupernodeMap() +static inline std::map< Identity,std::vector< std::pair > > _mkSupernodeMap() { - std::map< Identity,std::vector > sn; + std::map< Identity,std::vector< std::pair > > sn; Identity id; - std::vector addrs; + std::vector< std::pair > 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 > _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("162.243.77.111",ZT_DEFAULT_PORT),false)); + addrs.push_back(std::pair(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("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("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("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("108.61.200.101",ZT_DEFAULT_PORT),false)); sn[id] = addrs; return sn; diff --git a/node/Defaults.hpp b/node/Defaults.hpp index 0c640df79..50c2dce5e 100644 --- a/node/Defaults.hpp +++ b/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 > supernodes; + const std::map< Identity,std::vector< std::pair > > supernodes; /** * Identities permitted to sign software updates diff --git a/node/Peer.cpp b/node/Peer.cpp index b9b9b0c71..dcc8d4ea6 100644 --- a/node/Peer.cpp +++ b/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(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::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::iterator bestPath; - for(std::vector::iterator p(_paths.begin());p!=_paths.end();++p) { + } + uint64_t bestPathLastReceived = p->lastReceived(); + std::vector::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 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::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::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); diff --git a/node/Switch.cpp b/node/Switch.cpp index 2e021a5f9..0e58c7445 100644 --- a/node/Switch.cpp +++ b/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; } diff --git a/node/Topology.cpp b/node/Topology.cpp index 2211d1266..75784849e 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -50,7 +50,7 @@ Topology::~Topology() _dumpPeers(); } -void Topology::setSupernodes(const std::map< Identity,std::vector > &sn) +void Topology::setSupernodes(const std::map< Identity,std::vector< std::pair > > &sn) { Mutex::Lock _l(_supernodes_m); @@ -59,14 +59,13 @@ void Topology::setSupernodes(const std::map< Identity,std::vector > _supernodePeers.clear(); uint64_t now = Utils::now(); - for(std::map< Identity,std::vector >::const_iterator i(sn.begin());i!=sn.end();++i) { + for(std::map< Identity,std::vector< std::pair > >::const_iterator i(sn.begin());i!=sn.end();++i) { if (i->first != _r->identity) { SharedPtr p(getPeer(i->first.address())); if (!p) p = addPeer(SharedPtr(new Peer(_r->identity,i->first))); - for(std::vector::const_iterator j(i->second.begin());j!=i->second.end();++j) { - p->addPath(Path(*j,false,true)); - } + for(std::vector< std::pair >::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); } diff --git a/node/Topology.hpp b/node/Topology.hpp index 0b72197dd..bd39d0ec7 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -63,7 +63,7 @@ public: * * @param sn Supernodes for this network */ - void setSupernodes(const std::map< Identity,std::vector > &sn); + void setSupernodes(const std::map< Identity,std::vector< std::pair > > &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 > 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 > _activePeers; Mutex _activePeers_m; - std::map< Identity,std::vector > _supernodes; + std::map< Identity,std::vector< std::pair > > _supernodes; std::set< Address > _supernodeAddresses; std::vector< SharedPtr > _supernodePeers; Mutex _supernodes_m; diff --git a/node/UdpSocket.cpp b/node/UdpSocket.cpp index 8fce9588c..115298e9b 100644 --- a/node/UdpSocket.cpp +++ b/node/UdpSocket.cpp @@ -48,6 +48,9 @@ #include #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 &self,SocketManager *sm) @@ -97,7 +104,9 @@ bool UdpSocket::notifyAvailableForRead(const SharedPtr &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; }