Adam Ierymenko 8 years ago
parent
commit
b378f5dcd7
3 changed files with 27 additions and 18 deletions
  1. 2 2
      node/Cluster.cpp
  2. 3 2
      node/Cluster.hpp
  3. 22 14
      node/Switch.cpp

+ 2 - 2
node/Cluster.cpp

@@ -516,10 +516,10 @@ void Cluster::broadcastNetworkConfigChunk(const void *chunk,unsigned int len)
 	}
 }
 
-int Cluster::prepSendViaCluster(const Address &toPeerAddress,void *peerSecret)
+int Cluster::prepSendViaCluster(const Address &toPeerAddress,uint64_t &mostRecentTs,void *peerSecret)
 {
 	const uint64_t now = RR->node->now();
-	uint64_t mostRecentTs = 0;
+	mostRecentTs = 0;
 	int mostRecentMemberId = -1;
 	{
 		Mutex::Lock _l2(_remotePeers_m);

+ 3 - 2
node/Cluster.hpp

@@ -285,10 +285,11 @@ public:
 	 * Note that outp is only armored (or modified at all) if the return value is a member ID.
 	 *
 	 * @param toPeerAddress Value of outp.destination(), simply to save additional lookup
-	 * @param peerSecret Buffer to fill with peer secret on valid return value, must be at least ZT_PEER_SECRET_KEY_LENGTH bytes
+	 * @param ts Result: set to time of last HAVE_PEER from the cluster
+	 * @param peerSecret Result: Buffer to fill with peer secret on valid return value, must be at least ZT_PEER_SECRET_KEY_LENGTH bytes
 	 * @return -1 if cluster does not know this peer, or a member ID to pass to sendViaCluster()
 	 */
-	int prepSendViaCluster(const Address &toPeerAddress,void *peerSecret);
+	int prepSendViaCluster(const Address &toPeerAddress,uint64_t &mostRecentTs,void *peerSecret);
 
 	/**
 	 * Send data via cluster front plane (packet head or fragment)

+ 22 - 14
node/Switch.cpp

@@ -692,6 +692,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
 	const uint64_t now = RR->node->now();
 	const Address destination(packet.destination());
 #ifdef ZT_ENABLE_CLUSTER
+	uint64_t clusterMostRecentTs = 0;
 	int clusterMostRecentMemberId = -1;
 	uint8_t clusterPeerSecret[ZT_PEER_SECRET_KEY_LENGTH];
 #endif
@@ -713,25 +714,31 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
 		}
 
 		if (!viaPath) {
+			const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
+			if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) )
+				viaPath = peer->getBestPath(now,true);
+		}
+
 #ifdef ZT_ENABLE_CLUSTER
-			if (RR->cluster)
-				clusterMostRecentMemberId = RR->cluster->prepSendViaCluster(destination,clusterPeerSecret);
-			if (clusterMostRecentMemberId < 0) {
-#endif
-				peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known
-				const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
-				if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) {
-					if (!(viaPath = peer->getBestPath(now,true))) // last resort: try an expired path... we usually can never get here
-						return false;
-				}
-#ifdef ZT_ENABLE_CLUSTER
-			}
-#endif
+		if (RR->cluster)
+			clusterMostRecentMemberId = RR->cluster->prepSendViaCluster(destination,clusterMostRecentTs,clusterPeerSecret);
+		if (clusterMostRecentMemberId >= 0) {
+			if ((viaPath)&&(viaPath->lastIn() < clusterMostRecentTs))
+				viaPath.zero();
+		} else if (!viaPath) {
+			peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known
+			return false;
 		}
+#else
+		if (!viaPath) {
+			peer->tryMemorizedPath(now); // periodically attempt memorized or statically defined paths, if any are known
+			return false;
+		}
+#endif
 	} else {
 #ifdef ZT_ENABLE_CLUSTER
 		if (RR->cluster)
-			clusterMostRecentMemberId = RR->cluster->prepSendViaCluster(destination,clusterPeerSecret);
+			clusterMostRecentMemberId = RR->cluster->prepSendViaCluster(destination,clusterMostRecentTs,clusterPeerSecret);
 		if (clusterMostRecentMemberId < 0) {
 #else
 			requestWhois(destination);
@@ -742,6 +749,7 @@ bool Switch::_trySend(Packet &packet,bool encrypt)
 #endif
 	}
 
+	// Sanity checks
 #ifdef ZT_ENABLE_CLUSTER
 	if ((!viaPath)&&(clusterMostRecentMemberId < 0))
 		return false;