diff options
-rw-r--r-- | make-linux.mk | 1 | ||||
-rw-r--r-- | make-mac.mk | 48 | ||||
-rw-r--r-- | node/Switch.cpp | 29 | ||||
-rw-r--r-- | node/Topology.cpp | 119 |
4 files changed, 107 insertions, 90 deletions
diff --git a/make-linux.mk b/make-linux.mk index 84089c91..798fd4b5 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -35,7 +35,6 @@ endif #LDFLAGS= #STRIP=echo -# Our code doesn't use rtti, so don't bloat the binary with it. CXXFLAGS=$(CFLAGS) -fno-rtti include objects.mk diff --git a/make-mac.mk b/make-mac.mk index a734f637..e16ce2ce 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -15,7 +15,6 @@ ifeq ($(ZT_OFFICIAL_RELEASE),1) CODESIGN=codesign CODESIGN_CERT="Developer ID Application: ZeroTier Networks LLC (8ZD9JUCZ4V)" endif - ifeq ($(ZT_AUTO_UPDATE),1) DEFS+=-DZT_AUTO_UPDATE endif @@ -23,34 +22,34 @@ endif # Enable SSE-optimized Salsa20 DEFS+=-DZT_SALSA20_SSE -# Uncomment to dump trace and log info to stdout (useful for debug/test) -#DEFS+=-DZT_TRACE -DZT_LOG_STDOUT - -# Uncomment for a release optimized universal binary build -CFLAGS=-arch i386 -arch x86_64 -Wall -O3 -flto -fPIE -fvectorize -fstack-protector -pthread -mmacosx-version-min=10.6 -DNDEBUG -Wno-unused-private-field $(INCLUDES) $(DEFS) -STRIP=strip - -# Uncomment for a debug build -#CFLAGS=-Wall -g -pthread -DZT_TRACE -DZT_LOG_STDOUT $(INCLUDES) $(DEFS) -#STRIP=echo +# "make debug" is a shortcut for this +ifeq ($(ZT_DEBUG),1) + CFLAGS=-Wall -g -pthread -DZT_TRACE -DZT_LOG_STDOUT $(INCLUDES) $(DEFS) + STRIP=echo + DEFS+=-DZT_TRACE -DZT_LOG_STDOUT +else + CFLAGS=-arch i386 -arch x86_64 -Wall -O3 -flto -fPIE -fvectorize -fstack-protector -pthread -mmacosx-version-min=10.6 -DNDEBUG -Wno-unused-private-field $(INCLUDES) $(DEFS) + STRIP=strip +endif CXXFLAGS=$(CFLAGS) -fno-rtti include objects.mk -OBJS+=osnet/BSDRoutingTable.o osnet/OSXEthernetTap.o osnet/OSXEthernetTapFactory.o +OBJS+=main.o osnet/BSDRoutingTable.o osnet/OSXEthernetTap.o osnet/OSXEthernetTapFactory.o all: one one: $(OBJS) - $(CXX) $(CXXFLAGS) -o zerotier-one main.cpp $(OBJS) $(LIBS) + $(CXX) $(CXXFLAGS) -o zerotier-one $(OBJS) $(LIBS) $(STRIP) zerotier-one ln -sf zerotier-one zerotier-cli ln -sf zerotier-one zerotier-idtool -selftest: $(OBJS) - $(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.cpp $(OBJS) $(LIBS) +selftest: $(OBJS) selftest.o + $(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.o $(OBJS) $(LIBS) $(STRIP) zerotier-selftest +# Requires that ../Qt be symlinked to the Qt root to use for UI build mac-ui: FORCE mkdir -p build-ZeroTierUI-release cd build-ZeroTierUI-release ; ../../Qt/bin/qmake ../ZeroTierUI/ZeroTierUI.pro ; make -j 4 @@ -59,15 +58,13 @@ mac-ui: FORCE $(CODESIGN) -f -s $(CODESIGN_CERT) "build-ZeroTierUI-release/ZeroTier One.app" $(CODESIGN) -vvv "build-ZeroTierUI-release/ZeroTier One.app" -install-mac-tap: FORCE - mkdir -p /Library/Application\ Support/ZeroTier/One - rm -rf /Library/Application\ Support/ZeroTier/One/tap.kext - cp -R ext/bin/tap-mac/tap.kext /Library/Application\ Support/ZeroTier/One - chown -R root:wheel /Library/Application\ Support/ZeroTier/One/tap.kext - clean: - rm -rf *.dSYM build-* $(OBJS) zerotier-* ZeroTierOneInstaller-* "ZeroTier One.zip" "ZeroTier One.dmg" + rm -rf *.dSYM main.o selftest.o build-* $(OBJS) zerotier-* ZeroTierOneInstaller-* "ZeroTier One.zip" "ZeroTier One.dmg" + +debug: FORCE + make -j 4 ZT_DEBUG=1 +# For our use -- builds official signed binary, packages in installer and download DMG official: FORCE make -j 4 ZT_OFFICIAL_RELEASE=1 make mac-ui ZT_OFFICIAL_RELEASE=1 @@ -80,4 +77,11 @@ official: FORCE hdiutil convert /tmp/tmp.dmg -format UDZO -o "ZeroTier One.dmg" rm -f /tmp/tmp.dmg +# For those building from source -- installs signed binary tap driver in system ZT home +install-mac-tap: FORCE + mkdir -p /Library/Application\ Support/ZeroTier/One + rm -rf /Library/Application\ Support/ZeroTier/One/tap.kext + cp -R ext/bin/tap-mac/tap.kext /Library/Application\ Support/ZeroTier/One + chown -R root:wheel /Library/Application\ Support/ZeroTier/One/tap.kext + FORCE: diff --git a/node/Switch.cpp b/node/Switch.cpp index 1a28d4a5..fa8a22c0 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -639,12 +639,12 @@ void Switch::cancelWhoisRequest(const Address &addr) void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer) { - { + { // cancel pending WHOIS since we now know this peer Mutex::Lock _l(_outstandingWhoisRequests_m); _outstandingWhoisRequests.erase(peer->address()); } - { + { // finish processing any packets waiting on peer's public key / identity Mutex::Lock _l(_rxQueue_m); for(std::list< SharedPtr<PacketDecoder> >::iterator rxi(_rxQueue.begin());rxi!=_rxQueue.end();) { if ((*rxi)->tryDecode(_r)) @@ -653,7 +653,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer) } } - { + { // finish sending any packets waiting on peer's public key / identity Mutex::Lock _l(_txQueue_m); std::pair< std::multimap< Address,TXQueueEntry >::iterator,std::multimap< Address,TXQueueEntry >::iterator > waitingTxQueueItems(_txQueue.equal_range(peer->address())); for(std::multimap< Address,TXQueueEntry >::iterator txi(waitingTxQueueItems.first);txi!=waitingTxQueueItems.second;) { @@ -690,8 +690,11 @@ void Switch::_handleRemotePacketFragment(const SharedPtr<Socket> &fromSock,const if (fragment.hops() < ZT_RELAY_MAX_HOPS) { fragment.incrementHops(); + // Note: we don't bother initiating NAT-t for fragments, since heads will set that off. + // It wouldn't hurt anything, just redundant and unnecessary. SharedPtr<Peer> relayTo = _r->topology->getPeer(destination); if ((!relayTo)||(relayTo->send(_r,fragment.data(),fragment.size(),Utils::now()) == Path::PATH_TYPE_NULL)) { + // Don't know peer or no direct path -- so relay via supernode relayTo = _r->topology->getBestSupernode(); if (relayTo) relayTo->send(_r,fragment.data(),fragment.size(),Utils::now()); @@ -772,11 +775,7 @@ void Switch::_handleRemotePacketHead(const SharedPtr<Socket> &fromSock,const Ine if ((fromSock->udp())&&(relayedVia == Path::PATH_TYPE_UDP)) unite(source,destination,false); } else { - // If we've received a packet not for us and we don't have - // a direct path to its recipient, pass it to (another) - // supernode. This can happen due to Internet weather -- the - // most direct supernode may not be reachable, yet another - // further away may be. + // Don't know peer or no direct path -- so relay via supernode relayTo = _r->topology->getBestSupernode(&source,1,true); if (relayTo) relayTo->send(_r,packet->data(),packet->size(),Utils::now()); @@ -903,21 +902,9 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) remaining -= chunkSize; } } - -/* #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 */ - return true; } - return false; - } - - requestWhois(packet.destination()); + } else requestWhois(packet.destination()); return false; } diff --git a/node/Topology.cpp b/node/Topology.cpp index 109cbca2..183ee06a 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -161,65 +161,92 @@ void Topology::saveIdentity(const Identity &id) SharedPtr<Peer> Topology::getBestSupernode(const Address *avoid,unsigned int avoidCount,bool strictAvoid) const { SharedPtr<Peer> bestSupernode; - unsigned int l,bestSupernodeLatency = 65536; uint64_t now = Utils::now(); - uint64_t lds,ldr; - Mutex::Lock _l(_supernodes_m); - // First look for a best supernode by comparing latencies, but exclude - // supernodes that have not responded to direct messages in order to - // try to exclude any that are dead or unreachable. - for(std::vector< SharedPtr<Peer> >::const_iterator sn(_supernodePeers.begin());sn!=_supernodePeers.end();) { - // Skip explicitly avoided relays - for(unsigned int i=0;i<avoidCount;++i) { - if (avoid[i] == (*sn)->address()) - goto keep_searching_for_supernodes; + if (_amSupernode) { + /* If I am a supernode, the "best" supernode is the one whose address + * is numerically greater than mine (with wrap at top of list). This + * causes packets searching for a route to pretty much literally + * circumnavigate the globe rather than bouncing between just two. */ + + if (_supernodeAddresses.size() > 1) { // gotta be one other than me for this to work + std::set<Address>::const_iterator sna(_supernodeAddresses.find(_r->identity.address())); + if (sna != _supernodeAddresses.end()) { // sanity check -- _amSupernode should've been false in this case + for(;;) { + if (++sna == _supernodeAddresses.end()) + sna = _supernodeAddresses.begin(); // wrap around at end + if (*sna != _r->identity.address()) { // pick one other than us -- starting from me+1 in sorted set order + SharedPtr<Peer> p(getPeer(*sna)); + if ((p)&&(p->hasActiveDirectPath(now))) { + bestSupernode = p; + break; + } + } + } + } } + } else { + /* If I am not a supernode, the best supernode is the active one with + * the lowest latency. */ + + unsigned int l,bestSupernodeLatency = 65536; + uint64_t lds,ldr; + + // First look for a best supernode by comparing latencies, but exclude + // supernodes that have not responded to direct messages in order to + // try to exclude any that are dead or unreachable. + for(std::vector< SharedPtr<Peer> >::const_iterator sn(_supernodePeers.begin());sn!=_supernodePeers.end();) { + // Skip explicitly avoided relays + for(unsigned int i=0;i<avoidCount;++i) { + if (avoid[i] == (*sn)->address()) + goto keep_searching_for_supernodes; + } + + // Skip possibly comatose or unreachable relays + lds = (*sn)->lastDirectSend(); + ldr = (*sn)->lastDirectReceive(); + if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD)) + goto keep_searching_for_supernodes; - // Skip possibly comatose or unreachable relays - lds = (*sn)->lastDirectSend(); - ldr = (*sn)->lastDirectReceive(); - if ((lds)&&(lds > ldr)&&((lds - ldr) > ZT_PEER_RELAY_CONVERSATION_LATENCY_THRESHOLD)) - goto keep_searching_for_supernodes; - - if ((*sn)->hasActiveDirectPath(now)) { - l = (*sn)->latency(); - if (bestSupernode) { - if ((l)&&(l < bestSupernodeLatency)) { - bestSupernodeLatency = l; + if ((*sn)->hasActiveDirectPath(now)) { + l = (*sn)->latency(); + if (bestSupernode) { + if ((l)&&(l < bestSupernodeLatency)) { + bestSupernodeLatency = l; + bestSupernode = *sn; + } + } else { + if (l) + bestSupernodeLatency = l; bestSupernode = *sn; } - } else { - if (l) - bestSupernodeLatency = l; - bestSupernode = *sn; } - } keep_searching_for_supernodes: - ++sn; - } - - if (bestSupernode) { - bestSupernode->use(now); - return bestSupernode; - } else if (strictAvoid) - return SharedPtr<Peer>(); + ++sn; + } - // If we have nothing from above, just pick one without avoidance criteria. - for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) { - if ((*sn)->hasActiveDirectPath(now)) { - unsigned int l = (*sn)->latency(); - if (bestSupernode) { - if ((l)&&(l < bestSupernodeLatency)) { - bestSupernodeLatency = l; + if (bestSupernode) { + bestSupernode->use(now); + return bestSupernode; + } else if (strictAvoid) + return SharedPtr<Peer>(); + + // If we have nothing from above, just pick one without avoidance criteria. + for(std::vector< SharedPtr<Peer> >::const_iterator sn=_supernodePeers.begin();sn!=_supernodePeers.end();++sn) { + if ((*sn)->hasActiveDirectPath(now)) { + unsigned int l = (*sn)->latency(); + if (bestSupernode) { + if ((l)&&(l < bestSupernodeLatency)) { + bestSupernodeLatency = l; + bestSupernode = *sn; + } + } else { + if (l) + bestSupernodeLatency = l; bestSupernode = *sn; } - } else { - if (l) - bestSupernodeLatency = l; - bestSupernode = *sn; } } } |