Browse Source

Merge branch 'adamierymenko-dev' into android-jni

Adam Ierymenko 10 years ago
parent
commit
3d6c1860ca

+ 30 - 30
ext/installfiles/mac/ZeroTier One.pkgproj

@@ -37,9 +37,9 @@
 								<key>GID</key>
 								<integer>80</integer>
 								<key>PATH</key>
-								<string>/Users/api/Code/ZeroTierOne/ext/mac-ui-macgap1-wrapper/bin/ZeroTier One.app</string>
+								<string>../../mac-ui-macgap1-wrapper/bin/ZeroTier One.app</string>
 								<key>PATH_TYPE</key>
-								<integer>0</integer>
+								<integer>1</integer>
 								<key>PERMISSIONS</key>
 								<integer>493</integer>
 								<key>TYPE</key>
@@ -79,9 +79,9 @@
 														<key>GID</key>
 														<integer>0</integer>
 														<key>PATH</key>
-														<string>/Users/api/Code/ZeroTierOne/ext/installfiles/mac/get-proxy-settings.sh</string>
+														<string>get-proxy-settings.sh</string>
 														<key>PATH_TYPE</key>
-														<integer>0</integer>
+														<integer>1</integer>
 														<key>PERMISSIONS</key>
 														<integer>493</integer>
 														<key>TYPE</key>
@@ -95,9 +95,9 @@
 														<key>GID</key>
 														<integer>0</integer>
 														<key>PATH</key>
-														<string>/Users/api/Code/ZeroTierOne/ext/installfiles/mac/launch.sh</string>
+														<string>launch.sh</string>
 														<key>PATH_TYPE</key>
-														<integer>0</integer>
+														<integer>1</integer>
 														<key>PERMISSIONS</key>
 														<integer>493</integer>
 														<key>TYPE</key>
@@ -111,9 +111,9 @@
 														<key>GID</key>
 														<integer>0</integer>
 														<key>PATH</key>
-														<string>/Users/api/Code/ZeroTierOne/ext/bin/tap-mac/tap.kext</string>
+														<string>../../bin/tap-mac/tap.kext</string>
 														<key>PATH_TYPE</key>
-														<integer>0</integer>
+														<integer>1</integer>
 														<key>PERMISSIONS</key>
 														<integer>493</integer>
 														<key>TYPE</key>
@@ -130,9 +130,9 @@
 																<key>GID</key>
 																<integer>0</integer>
 																<key>PATH</key>
-																<string>/Users/api/Code/ZeroTierOne/ui/index.html</string>
+																<string>../../../ui/index.html</string>
 																<key>PATH_TYPE</key>
-																<integer>0</integer>
+																<integer>1</integer>
 																<key>PERMISSIONS</key>
 																<integer>420</integer>
 																<key>TYPE</key>
@@ -146,9 +146,9 @@
 																<key>GID</key>
 																<integer>0</integer>
 																<key>PATH</key>
-																<string>/Users/api/Code/ZeroTierOne/ui/main.js</string>
+																<string>../../../ui/main.js</string>
 																<key>PATH_TYPE</key>
-																<integer>0</integer>
+																<integer>1</integer>
 																<key>PERMISSIONS</key>
 																<integer>420</integer>
 																<key>TYPE</key>
@@ -162,9 +162,9 @@
 																<key>GID</key>
 																<integer>0</integer>
 																<key>PATH</key>
-																<string>/Users/api/Code/ZeroTierOne/ui/react.min.js</string>
+																<string>../../../ui/react.min.js</string>
 																<key>PATH_TYPE</key>
-																<integer>0</integer>
+																<integer>1</integer>
 																<key>PERMISSIONS</key>
 																<integer>420</integer>
 																<key>TYPE</key>
@@ -178,9 +178,9 @@
 																<key>GID</key>
 																<integer>0</integer>
 																<key>PATH</key>
-																<string>/Users/api/Code/ZeroTierOne/ui/simpleajax.min.js</string>
+																<string>../../../ui/simpleajax.min.js</string>
 																<key>PATH_TYPE</key>
-																<integer>0</integer>
+																<integer>1</integer>
 																<key>PERMISSIONS</key>
 																<integer>420</integer>
 																<key>TYPE</key>
@@ -194,9 +194,9 @@
 																<key>GID</key>
 																<integer>0</integer>
 																<key>PATH</key>
-																<string>/Users/api/Code/ZeroTierOne/ui/zerotier.css</string>
+																<string>../../../ui/zerotier.css</string>
 																<key>PATH_TYPE</key>
-																<integer>0</integer>
+																<integer>1</integer>
 																<key>PERMISSIONS</key>
 																<integer>420</integer>
 																<key>TYPE</key>
@@ -210,9 +210,9 @@
 																<key>GID</key>
 																<integer>0</integer>
 																<key>PATH</key>
-																<string>/Users/api/Code/ZeroTierOne/ui/ztui.min.js</string>
+																<string>../../../ui/ztui.min.js</string>
 																<key>PATH_TYPE</key>
-																<integer>0</integer>
+																<integer>1</integer>
 																<key>PERMISSIONS</key>
 																<integer>420</integer>
 																<key>TYPE</key>
@@ -240,9 +240,9 @@
 														<key>GID</key>
 														<integer>0</integer>
 														<key>PATH</key>
-														<string>/Users/api/Code/ZeroTierOne/ext/installfiles/mac/uninstall.sh</string>
+														<string>uninstall.sh</string>
 														<key>PATH_TYPE</key>
-														<integer>0</integer>
+														<integer>1</integer>
 														<key>PERMISSIONS</key>
 														<integer>493</integer>
 														<key>TYPE</key>
@@ -256,9 +256,9 @@
 														<key>GID</key>
 														<integer>0</integer>
 														<key>PATH</key>
-														<string>/Users/api/Code/ZeroTierOne/zerotier-one</string>
+														<string>../../../zerotier-one</string>
 														<key>PATH_TYPE</key>
-														<integer>0</integer>
+														<integer>1</integer>
 														<key>PERMISSIONS</key>
 														<integer>493</integer>
 														<key>TYPE</key>
@@ -429,9 +429,9 @@
 										<key>GID</key>
 										<integer>0</integer>
 										<key>PATH</key>
-										<string>/Users/api/Code/ZeroTierOne/ext/installfiles/mac/com.zerotier.one.plist</string>
+										<string>com.zerotier.one.plist</string>
 										<key>PATH_TYPE</key>
-										<integer>0</integer>
+										<integer>1</integer>
 										<key>PERMISSIONS</key>
 										<integer>420</integer>
 										<key>TYPE</key>
@@ -734,16 +734,16 @@
 			<key>POSTINSTALL_PATH</key>
 			<dict>
 				<key>PATH</key>
-				<string>/Users/api/Code/ZeroTierOne/ext/installfiles/mac/postinst.sh</string>
+				<string>postinst.sh</string>
 				<key>PATH_TYPE</key>
-				<integer>0</integer>
+				<integer>1</integer>
 			</dict>
 			<key>PREINSTALL_PATH</key>
 			<dict>
 				<key>PATH</key>
-				<string>/Users/api/Code/ZeroTierOne/ext/installfiles/mac/preinst.sh</string>
+				<string>preinst.sh</string>
 				<key>PATH_TYPE</key>
-				<integer>0</integer>
+				<integer>1</integer>
 			</dict>
 			<key>RESOURCES</key>
 			<array/>

+ 0 - 21
make-freebsd.mk

@@ -8,27 +8,6 @@ LIBS=
 include objects.mk
 OBJS+=osdep/BSDEthernetTap.o 
 
-# Enable SSE-optimized Salsa20 on x86 and x86_64 machines
-MACHINE=$(shell uname -m)
-ifeq ($(MACHINE),x86_64)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),amd64)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),i686)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),i586)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),i386)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),x86)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-
 # "make official" is a shortcut for this
 ifeq ($(ZT_OFFICIAL_RELEASE),1)
 	ZT_AUTO_UPDATE=1

+ 1 - 22
make-linux.mk

@@ -9,27 +9,6 @@ LIBS=
 include objects.mk
 OBJS+=osdep/LinuxEthernetTap.o 
 
-# Enable SSE-optimized Salsa20 on x86 and x86_64 machines
-MACHINE=$(shell uname -m)
-ifeq ($(MACHINE),x86_64)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),amd64)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),i686)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),i586)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),i386)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-ifeq ($(MACHINE),x86)
-	DEFS+=-DZT_SALSA20_SSE 
-endif
-
 # "make official" is a shortcut for this
 ifeq ($(ZT_OFFICIAL_RELEASE),1)
 	ZT_AUTO_UPDATE=1
@@ -91,6 +70,6 @@ debug:	FORCE
 
 official: FORCE
 	make -j 4 ZT_OFFICIAL_RELEASE=1
-	./buildinstaller.sh
+	make ZT_OFFICIAL_RELEASE=1 installer
 
 FORCE:

+ 1 - 4
make-mac.mk

@@ -31,9 +31,6 @@ ifeq ($(ZT_ENABLE_NETWORK_CONTROLLER),1)
 	OBJS+=controller/SqliteNetworkController.o 
 endif
 
-# Enable SSE-optimized Salsa20 -- all Intel macs support SSE2
-DEFS+=-DZT_SALSA20_SSE
-
 # Debug mode -- dump trace output, build binary with -g
 ifeq ($(ZT_DEBUG),1)
 	DEFS+=-DZT_TRACE 
@@ -65,7 +62,7 @@ selftest: $(OBJS) selftest.o
 
 # Requires Packages: http://s.sudre.free.fr/Software/Packages/about.html
 mac-dist-pkg: FORCE
-	cd ext/installfiles/mac ; packagesbuild "ZeroTier One.pkgproj"
+	packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj"
 	$(CODESIGN) -f -s $(CODESIGN_CERT) "ZeroTier One.pkg"
 	$(CODESIGN) -vvv "ZeroTier One.pkg"
 

+ 12 - 29
node/IncomingPacket.cpp

@@ -486,38 +486,21 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer>
 bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
 {
 	try {
-		/*
-		 * At the moment, we only obey RENDEZVOUS if it comes from a designated
-		 * supernode. If relay offloading is implemented to scale the net, this
-		 * will need reconsideration.
-		 *
-		 * The reason is that RENDEZVOUS could technically be used to cause a
-		 * peer to send a weird encrypted UDP packet to an arbitrary IP:port.
-		 * The sender of RENDEZVOUS has no control over the content of this
-		 * packet, but it's still maybe something we want to not allow just
-		 * anyone to order due to possible DDOS or network forensic implications.
-		 * So if we diversify relays, we'll need some way of deciding whether the
-		 * sender is someone we should trust with a RENDEZVOUS hint.
-		 */
-		if (RR->topology->isSupernode(peer->address())) {
-			const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
-			const SharedPtr<Peer> withPeer(RR->topology->getPeer(with));
-			if (withPeer) {
-				const unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT);
-				const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
-				if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
-					InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
-					TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
-					peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP);
-					RR->sw->contact(withPeer,atAddr);
-				} else {
-					TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
-				}
+		const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH);
+		const SharedPtr<Peer> withPeer(RR->topology->getPeer(with));
+		if (withPeer) {
+			const unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT);
+			const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
+			if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
+				InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
+				TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
+				peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP);
+				RR->sw->contact(withPeer,atAddr);
 			} else {
-				TRACE("ignored RENDEZVOUS from %s(%s) to meet unknown peer %s",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),with.toString().c_str());
+				TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
 			}
 		} else {
-			TRACE("ignored RENDEZVOUS from %s(%s): source not supernode",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
+			TRACE("ignored RENDEZVOUS from %s(%s) to meet unknown peer %s",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),with.toString().c_str());
 		}
 	} catch (std::exception &ex) {
 		TRACE("dropped RENDEZVOUS from %s(%s): %s",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());

+ 6 - 7
node/Network.cpp

@@ -264,7 +264,7 @@ void Network::requestConfiguration()
 			outp.append((uint64_t)_config->revision());
 		else outp.append((uint64_t)0);
 	}
-	RR->sw->send(outp,true);
+	RR->sw->send(outp,true,_id);
 }
 
 void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool forceAccept)
@@ -498,12 +498,11 @@ bool Network::_isAllowed(const Address &peer) const
 std::vector<MulticastGroup> Network::_allMulticastGroups() const
 {
 	// Assumes _lock is locked
-	std::vector<MulticastGroup> mgs(_myMulticastGroups);
-	std::vector<MulticastGroup>::iterator oldend(mgs.end());
-	for(std::map< MulticastGroup,uint64_t >::const_iterator i(_multicastGroupsBehindMe.begin());i!=_multicastGroupsBehindMe.end();++i) {
-		if (!std::binary_search(mgs.begin(),oldend,i->first))
-			mgs.push_back(i->first);
-	}
+	std::vector<MulticastGroup> mgs;
+	mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1);
+	mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end());
+	for(std::map< MulticastGroup,uint64_t >::const_iterator i(_multicastGroupsBehindMe.begin());i!=_multicastGroupsBehindMe.end();++i)
+		mgs.push_back(i->first);
 	if ((_config)&&(_config->enableBroadcast()))
 		mgs.push_back(Network::BROADCAST);
 	std::sort(mgs.begin(),mgs.end());

+ 5 - 3
node/NetworkConfig.cpp

@@ -184,9 +184,11 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
 	std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","",""));
 	for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) {
 		std::size_t semi(r->find(';')); // address;ip/port,...
-		if ((semi == ZT_ADDRESS_LENGTH)&&(r->length() > (ZT_ADDRESS_LENGTH + 1))) {
-			std::pair<Address,InetAddress> relay(Address(r->substr(0,semi)),InetAddress(r->substr(semi+1)));
-			if ((relay.first)&&(relay.second))
+		if (semi == ZT_ADDRESS_LENGTH_HEX) {
+			std::pair<Address,InetAddress> relay(
+				Address(r->substr(0,semi)),
+				((r->length() > (semi + 1)) ? InetAddress(r->substr(semi + 1)) : InetAddress()) );
+			if ((relay.first)&&(!relay.first.isReserved()))
 				_relays.push_back(relay);
 		}
 	}

+ 65 - 35
node/Node.cpp

@@ -184,27 +184,41 @@ ZT1_ResultCode Node::processVirtualNetworkFrame(
 class _PingPeersThatNeedPing
 {
 public:
-	_PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) :
+	_PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now,const std::vector< std::pair<Address,InetAddress> > &relays) :
 		lastReceiveFromUpstream(0),
 		RR(renv),
 		_now(now),
-		_supernodes(RR->topology->supernodeAddresses()) {}
+		_relays(relays),
+		_supernodes(RR->topology->supernodeAddresses())
+	{
+	}
 
 	uint64_t lastReceiveFromUpstream;
 
 	inline void operator()(Topology &t,const SharedPtr<Peer> &p)
 	{
-		if (std::find(_supernodes.begin(),_supernodes.end(),p->address()) != _supernodes.end()) {
+		bool isRelay = false;
+		for(std::vector< std::pair<Address,InetAddress> >::const_iterator r(_relays.begin());r!=_relays.end();++r) {
+			if (r->first == p->address()) {
+				isRelay = true;
+				break;
+			}
+		}
+
+		if ((isRelay)||(std::find(_supernodes.begin(),_supernodes.end(),p->address()) != _supernodes.end())) {
 			p->doPingAndKeepalive(RR,_now);
 			if (p->lastReceive() > lastReceiveFromUpstream)
 				lastReceiveFromUpstream = p->lastReceive();
-		} else if (p->alive(_now)) {
-			p->doPingAndKeepalive(RR,_now);
+		} else {
+			if (p->alive(_now))
+				p->doPingAndKeepalive(RR,_now);
 		}
 	}
+
 private:
 	const RuntimeEnvironment *RR;
 	uint64_t _now;
+	const std::vector< std::pair<Address,InetAddress> > &_relays;
 	std::vector<Address> _supernodes;
 };
 
@@ -214,54 +228,70 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next
 	Mutex::Lock bl(_backgroundTasksLock);
 
 	if ((now - _lastPingCheck) >= ZT_PING_CHECK_INVERVAL) {
-		_lastPingCheck = now;
-
 		try {
-			_PingPeersThatNeedPing pfunc(RR,now);
+			_lastPingCheck = now;
+
+			// Get relays and networks that need config without leaving the mutex locked
+			std::vector< std::pair<Address,InetAddress> > networkRelays;
+			std::vector< SharedPtr<Network> > needConfig;
+			{
+				Mutex::Lock _l(_networks_m);
+				for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
+					SharedPtr<NetworkConfig> nc(n->second->config2());
+					if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc))
+						needConfig.push_back(n->second);
+					if (nc)
+						networkRelays.insert(networkRelays.end(),nc->relays().begin(),nc->relays().end());
+				}
+			}
+
+			// Request updated configuration for networks that need it
+			for(std::vector< SharedPtr<Network> >::const_iterator n(needConfig.begin());n!=needConfig.end();++n)
+				(*n)->requestConfiguration();
+
+			// Attempt to contact network preferred relays that we don't have direct links to
+			std::sort(networkRelays.begin(),networkRelays.end());
+			std::unique(networkRelays.begin(),networkRelays.end());
+			for(std::vector< std::pair<Address,InetAddress> >::const_iterator nr(networkRelays.begin());nr!=networkRelays.end();++nr) {
+				if (nr->second) {
+					SharedPtr<Peer> rp(RR->topology->getPeer(nr->first));
+					if ((rp)&&(!rp->hasActiveDirectPath(now)))
+						rp->attemptToContactAt(RR,nr->second,now);
+				}
+			}
+
+			// Ping living or supernode/relay peers
+			_PingPeersThatNeedPing pfunc(RR,now,networkRelays);
 			RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
 
+			// Update online status, post status change as event
 			bool oldOnline = _online;
 			_online = ((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT);
 			if (oldOnline != _online)
 				postEvent(_online ? ZT1_EVENT_ONLINE : ZT1_EVENT_OFFLINE);
-		} catch ( ... ) {
-			return ZT1_RESULT_FATAL_ERROR_INTERNAL;
-		}
 
-		try {
-			Mutex::Lock _l(_networks_m);
-			for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
-				if ((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)
-					n->second->requestConfiguration();
+			// Send LAN beacons
+			if ((now - _lastBeacon) >= ZT_BEACON_INTERVAL) {
+				_lastBeacon = now;
+				char beacon[13];
+				void *p = beacon;
+				*(reinterpret_cast<uint32_t *>(p)) = RR->prng->next32();
+				p = beacon + 4;
+				*(reinterpret_cast<uint32_t *>(p)) = RR->prng->next32();
+				RR->identity.address().copyTo(beacon + 8,5);
+				RR->antiRec->logOutgoingZT(beacon,13);
+				putPacket(ZT_DEFAULTS.v4Broadcast,beacon,13);
 			}
 		} catch ( ... ) {
 			return ZT1_RESULT_FATAL_ERROR_INTERNAL;
 		}
-
-		if ((now - _lastBeacon) >= ZT_BEACON_INTERVAL) {
-			_lastBeacon = now;
-			char beacon[13];
-			void *p = beacon;
-			*(reinterpret_cast<uint32_t *>(p)) = RR->prng->next32();
-			p = beacon + 4;
-			*(reinterpret_cast<uint32_t *>(p)) = RR->prng->next32();
-			RR->identity.address().copyTo(beacon + 8,5);
-			RR->antiRec->logOutgoingZT(beacon,13);
-			putPacket(ZT_DEFAULTS.v4Broadcast,beacon,13);
-		}
 	}
 
 	if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
-		_lastHousekeepingRun = now;
-
 		try {
+			_lastHousekeepingRun = now;
 			RR->topology->clean(now);
 			RR->sa->clean(now);
-		} catch ( ... ) {
-			return ZT1_RESULT_FATAL_ERROR_INTERNAL;
-		}
-
-		try {
 			RR->mc->clean(now);
 		} catch ( ... ) {
 			return ZT1_RESULT_FATAL_ERROR_INTERNAL;

+ 2 - 2
node/OutboundMulticast.cpp

@@ -108,14 +108,14 @@ void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,const Address &toA
 			_packetWithCom.newInitializationVector();
 			_packetWithCom.setDestination(toAddr);
 			//TRACE(">>MC %.16llx -> %s (with COM)",(unsigned long long)this,toAddr.toString().c_str());
-			RR->sw->send(_packetWithCom,true);
+			RR->sw->send(_packetWithCom,true,_nwid);
 			return;
 		}
 	}
 	//TRACE(">>MC %.16llx -> %s (without COM)",(unsigned long long)this,toAddr.toString().c_str());
 	_packetNoCom.newInitializationVector();
 	_packetNoCom.setDestination(toAddr);
-	RR->sw->send(_packetNoCom,true);
+	RR->sw->send(_packetNoCom,true,_nwid);
 }
 
 } // namespace ZeroTier

+ 6 - 0
node/Salsa20.hpp

@@ -7,10 +7,16 @@
 #ifndef ZT_SALSA20_HPP
 #define ZT_SALSA20_HPP
 
+#include <stdio.h>
 #include <stdint.h>
+#include <stdlib.h>
 
 #include "Constants.hpp"
 
+#if (!defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || defined(__WINDOWS__))
+#define ZT_SALSA20_SSE 1
+#endif
+
 #ifdef ZT_SALSA20_SSE
 #include <emmintrin.h>
 #endif // ZT_SALSA20_SSE

+ 35 - 16
node/Switch.cpp

@@ -114,8 +114,6 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 
 	if (to.isMulticast()) {
 		// Destination is a multicast address (including broadcast)
-
-		const uint64_t now = RR->node->now();
 		MulticastGroup mg(to,0);
 
 		if (to.isBroadcast()) {
@@ -145,7 +143,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 		 * multicast addresses on bridge interfaces and subscribing each slave.
 		 * But in that case this does no harm, as the sets are just merged. */
 		if (fromBridged)
-			network->learnBridgedMulticastGroup(mg,now);
+			network->learnBridgedMulticastGroup(mg,RR->node->now());
 
 		// Check multicast/broadcast bandwidth quotas and reject if quota exceeded
 		if (!network->updateAndCheckMulticastBalance(mg,len)) {
@@ -158,7 +156,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 		RR->mc->send(
 			((!nconf->isPublic())&&(nconf->com())) ? &(nconf->com()) : (const CertificateOfMembership *)0,
 			nconf->multicastLimit(),
-			now,
+			RR->node->now(),
 			network->id(),
 			nconf->activeBridges(),
 			mg,
@@ -180,7 +178,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 				// bundle this with EXT_FRAME instead of sending two packets.
 				Packet outp(toZT,RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
 				nconf->com().serialize(outp);
-				send(outp,true);
+				send(outp,true,network->id());
 			}
 
 			if (fromBridged) {
@@ -193,7 +191,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 				outp.append((uint16_t)etherType);
 				outp.append(data,len);
 				outp.compress();
-				send(outp,true);
+				send(outp,true,network->id());
 			} else {
 				// FRAME is a shorter version that can be used when there's no bridging and no COM
 				Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME);
@@ -201,7 +199,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 				outp.append((uint16_t)etherType);
 				outp.append(data,len);
 				outp.compress();
-				send(outp,true);
+				send(outp,true,network->id());
 			}
 
 			//TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged);
@@ -259,21 +257,21 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 			outp.append((uint16_t)etherType);
 			outp.append(data,len);
 			outp.compress();
-			send(outp,true);
+			send(outp,true,network->id());
 		}
 	}
 }
 
-void Switch::send(const Packet &packet,bool encrypt)
+void Switch::send(const Packet &packet,bool encrypt,uint64_t nwid)
 {
 	if (packet.destination() == RR->identity.address()) {
 		TRACE("BUG: caught attempt to send() to self, ignored");
 		return;
 	}
 
-	if (!_trySend(packet,encrypt)) {
+	if (!_trySend(packet,encrypt,nwid)) {
 		Mutex::Lock _l(_txQueue_m);
-		_txQueue.insert(std::pair< Address,TXQueueEntry >(packet.destination(),TXQueueEntry(RR->node->now(),packet,encrypt)));
+		_txQueue.insert(std::pair< Address,TXQueueEntry >(packet.destination(),TXQueueEntry(RR->node->now(),packet,encrypt,nwid)));
 	}
 }
 
@@ -423,7 +421,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
 		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;) {
-			if (_trySend(txi->second.packet,txi->second.encrypt))
+			if (_trySend(txi->second.packet,txi->second.encrypt,txi->second.nwid))
 				_txQueue.erase(txi++);
 			else ++txi;
 		}
@@ -505,7 +503,7 @@ unsigned long Switch::doTimerTasks(uint64_t now)
 	{	// Time out TX queue packets that never got WHOIS lookups or other info.
 		Mutex::Lock _l(_txQueue_m);
 		for(std::multimap< Address,TXQueueEntry >::iterator i(_txQueue.begin());i!=_txQueue.end();) {
-			if (_trySend(i->second.packet,i->second.encrypt))
+			if (_trySend(i->second.packet,i->second.encrypt,i->second.nwid))
 				_txQueue.erase(i++);
 			else if ((now - i->second.creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) {
 				TRACE("TX %s -> %s timed out",i->second.packet.source().toString().c_str(),i->second.packet.destination().toString().c_str());
@@ -725,7 +723,7 @@ Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlread
 	return Address();
 }
 
-bool Switch::_trySend(const Packet &packet,bool encrypt)
+bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
 {
 	SharedPtr<Peer> peer(RR->topology->getPeer(packet.destination()));
 
@@ -734,8 +732,29 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
 
 		Path *viaPath = peer->getBestPath(now);
 		if (!viaPath) {
-			SharedPtr<Peer> sn(RR->topology->getBestSupernode());
-			if (!(sn)||(!(viaPath = sn->getBestPath(now))))
+			SharedPtr<Peer> relay;
+
+			if (nwid) {
+				SharedPtr<Network> network(RR->node->network(nwid));
+				if (network) {
+					SharedPtr<NetworkConfig> nconf(network->config2());
+					if (nconf) {
+						unsigned int latency = ~((unsigned int)0);
+						for(std::vector< std::pair<Address,InetAddress> >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) {
+							if (r->first != peer->address()) {
+								SharedPtr<Peer> rp(RR->topology->getPeer(r->first));
+								if ((rp)&&(rp->hasActiveDirectPath(now))&&(rp->latency() <= latency))
+									rp.swap(relay);
+							}
+						}
+					}
+				}
+			}
+
+			if (!relay)
+				relay = RR->topology->getBestSupernode();
+
+			if (!(relay)||(!(viaPath = relay->getBestPath(now))))
 				return false;
 		}
 

+ 8 - 12
node/Switch.hpp

@@ -111,8 +111,9 @@ public:
 	 * 
 	 * @param packet Packet to send
 	 * @param encrypt Encrypt packet payload? (always true except for HELLO)
+	 * @param nwid Network ID or 0 if message is not related to a specific network
 	 */
-	void send(const Packet &packet,bool encrypt);
+	void send(const Packet &packet,bool encrypt,uint64_t nwid);
 
 	/**
 	 * Send RENDEZVOUS to two peers to permit them to directly connect
@@ -183,15 +184,8 @@ private:
 	void _handleRemotePacketFragment(const InetAddress &fromAddr,const void *data,unsigned int len);
 	void _handleRemotePacketHead(const InetAddress &fromAddr,const void *data,unsigned int len);
 	void _handleBeacon(const InetAddress &fromAddr,const Buffer<ZT_PROTO_BEACON_LENGTH> &data);
-
-	Address _sendWhoisRequest(
-		const Address &addr,
-		const Address *peersAlreadyConsulted,
-		unsigned int numPeersAlreadyConsulted);
-
-	bool _trySend(
-		const Packet &packet,
-		bool encrypt);
+	Address _sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted);
+	bool _trySend(const Packet &packet,bool encrypt,uint64_t nwid);
 
 	const RuntimeEnvironment *const RR;
 	volatile uint64_t _lastBeacon;
@@ -226,13 +220,15 @@ private:
 	struct TXQueueEntry
 	{
 		TXQueueEntry() {}
-		TXQueueEntry(uint64_t ct,const Packet &p,bool enc) :
+		TXQueueEntry(uint64_t ct,const Packet &p,bool enc,uint64_t nw) :
 			creationTime(ct),
+			nwid(nw),
 			packet(p),
 			encrypt(enc) {}
 
 		uint64_t creationTime;
-		Packet packet; // unencrypted/untagged for TX queue
+		uint64_t nwid;
+		Packet packet; // unencrypted/unMAC'd packet -- this is done at send time
 		bool encrypt;
 	};
 	std::multimap< Address,TXQueueEntry > _txQueue;

+ 0 - 5
node/Topology.hpp

@@ -156,11 +156,6 @@ public:
 		return _supernodeAddresses;
 	}
 
-	/**
-	 * @return True if this node's identity is in the supernode set
-	 */
-	inline bool amSupernode() const { return _amSupernode; }
-
 	/**
 	 * Clean and flush database
 	 */

+ 6 - 0
selftest.cpp

@@ -187,6 +187,12 @@ static int testCrypto()
 	}
 	std::cout << "PASS" << std::endl;
 
+#ifdef ZT_SALSA20_SSE
+	std::cout << "[crypto] Salsa20 SSE: ENABLED" << std::endl;
+#else
+	std::cout << "[crypto] Salsa20 SSE: DISABLED" << std::endl;
+#endif
+
 	std::cout << "[crypto] Benchmarking Salsa20/12... "; std::cout.flush();
 	{
 		unsigned char *bb = (unsigned char *)::malloc(1234567);

+ 2 - 0
windows/ZeroTierOne/ZeroTierOne.vcxproj

@@ -44,6 +44,7 @@
     <ClCompile Include="..\..\node\Topology.cpp" />
     <ClCompile Include="..\..\node\Utils.cpp" />
     <ClCompile Include="..\..\one.cpp" />
+    <ClCompile Include="..\..\osdep\BackgroundResolver.cpp" />
     <ClCompile Include="..\..\osdep\Http.cpp" />
     <ClCompile Include="..\..\osdep\OSUtils.cpp" />
     <ClCompile Include="..\..\osdep\WindowsEthernetTap.cpp" />
@@ -101,6 +102,7 @@
     <ClInclude Include="..\..\node\Switch.hpp" />
     <ClInclude Include="..\..\node\Topology.hpp" />
     <ClInclude Include="..\..\node\Utils.hpp" />
+    <ClInclude Include="..\..\osdep\BackgroundResolver.hpp" />
     <ClInclude Include="..\..\osdep\Http.hpp" />
     <ClInclude Include="..\..\osdep\OSUtils.hpp" />
     <ClInclude Include="..\..\osdep\Phy.hpp" />

+ 6 - 0
windows/ZeroTierOne/ZeroTierOne.vcxproj.filters

@@ -174,6 +174,9 @@
     <ClCompile Include="ZeroTierOneService.cpp">
       <Filter>Source Files\windows\ZeroTierOne</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\osdep\BackgroundResolver.cpp">
+      <Filter>Source Files\osdep</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="resource.h">
@@ -338,6 +341,9 @@
     <ClInclude Include="ZeroTierOneService.h">
       <Filter>Header Files\windows\ZeroTierOne</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\osdep\BackgroundResolver.hpp">
+      <Filter>Header Files\osdep</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="ZeroTierOne.rc">