From 75c51aa61b32983125bfa2eda4f351e211a7834c Mon Sep 17 00:00:00 2001 From: CalDescent Date: Wed, 5 Jan 2022 19:03:41 +0000 Subject: [PATCH] If a direct connection can't be made to a peer over the original or default port, match the peer's host with any entries in knownPeers and try connecting to each of those until one succeeds. --- .../arbitrary/ArbitraryDataFileManager.java | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java index 344f9c75..17b204c7 100644 --- a/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java +++ b/src/main/java/org/qortal/controller/arbitrary/ArbitraryDataFileManager.java @@ -5,6 +5,7 @@ import org.apache.logging.log4j.Logger; import org.qortal.arbitrary.ArbitraryDataFile; import org.qortal.controller.Controller; import org.qortal.data.network.ArbitraryPeerData; +import org.qortal.data.network.PeerData; import org.qortal.data.transaction.ArbitraryTransactionData; import org.qortal.data.transaction.TransactionData; import org.qortal.network.Network; @@ -20,6 +21,7 @@ import org.qortal.utils.Triple; import java.security.SecureRandom; import java.util.*; +import java.util.stream.Collectors; public class ArbitraryDataFileManager { @@ -258,21 +260,49 @@ public class ArbitraryDataFileManager { String peerAddressString = arbitraryPeerData.getPeerAddress(); boolean success = Network.getInstance().requestDataFromPeer(peerAddressString, signature); - // If using a non-standard port, try a second connection with the default listen port, since almost all nodes use that - // This is a workaround to account for any ephemeral ports that may have made it into the dataset - boolean success2 = false; + // Parse the peer address to find the host and port + String host = null; + int port = -1; String[] parts = peerAddressString.split(":"); if (parts.length > 1) { - String host = parts[0]; - int port = Integer.parseInt(parts[1]); - int defaultPort = Settings.getInstance().getDefaultListenPort(); - if (port != defaultPort) { - String newPeerAddressString = String.format("%s:%d", host, defaultPort); - success2 = Network.getInstance().requestDataFromPeer(newPeerAddressString, signature); + host = parts[0]; + port = Integer.parseInt(parts[1]); + } + + // If unsuccessful, and using a non-standard port, try a second connection with the default listen port, + // since almost all nodes use that. This is a workaround to account for any ephemeral ports that may + // have made it into the dataset. + if (!success) { + if (host != null && port > 0) { + int defaultPort = Settings.getInstance().getDefaultListenPort(); + if (port != defaultPort) { + String newPeerAddressString = String.format("%s:%d", host, defaultPort); + success = Network.getInstance().requestDataFromPeer(newPeerAddressString, signature); + } + } + } + + // If _still_ unsuccessful, try matching the peer's IP address with some known peers, and then connect + // to each of those in turn until one succeeds. + if (!success) { + if (host != null) { + final String finalHost = host; + List knownPeers = Network.getInstance().getAllKnownPeers().stream() + .filter(knownPeerData -> knownPeerData.getAddress().getHost().equals(finalHost)) + .collect(Collectors.toList()); + // Loop through each match and attempt a connection + for (PeerData matchingPeer : knownPeers) { + String matchingPeerAddress = matchingPeer.getAddress().toString(); + success = Network.getInstance().requestDataFromPeer(matchingPeerAddress, signature); + if (success) { + // Successfully connected, so stop making connections + break; + } + } } } - return success || success2; + return success; } catch (DataException e) { LOGGER.debug("Unable to fetch peer list from repository");