2
0
Эх сурвалжийг харах

Rest of GitHub issue #140 implementation.

Adam Ierymenko 10 жил өмнө
parent
commit
960ceb4791

+ 1 - 1
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)

+ 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

+ 33 - 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,27 @@ 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) {
+							SharedPtr<Peer> rp(RR->topology->getPeer(r->first));
+							if ((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;