summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--make-linux.mk1
-rw-r--r--make-mac.mk48
-rw-r--r--node/Switch.cpp29
-rw-r--r--node/Topology.cpp119
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;
}
}
}