|
|
@ -317,80 +317,102 @@ public class ArbitraryDataFileManager extends Thread { |
|
|
|
public boolean fetchDataFilesFromPeersForSignature(byte[] signature) { |
|
|
|
public boolean fetchDataFilesFromPeersForSignature(byte[] signature) { |
|
|
|
String signature58 = Base58.encode(signature); |
|
|
|
String signature58 = Base58.encode(signature); |
|
|
|
|
|
|
|
|
|
|
|
// Firstly fetch peers that claim to be hosting files for this signature
|
|
|
|
boolean success = false; |
|
|
|
List<ArbitraryDirectConnectionInfo> connectionInfoList = getDirectConnectionInfoForSignature(signature); |
|
|
|
|
|
|
|
if (connectionInfoList == null || connectionInfoList.isEmpty()) { |
|
|
|
|
|
|
|
LOGGER.debug("No direct connection peers found for signature {}", signature58); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOGGER.debug("Attempting a direct peer connection for signature {}...", signature58); |
|
|
|
try { |
|
|
|
|
|
|
|
while (!success) { |
|
|
|
|
|
|
|
if (isStopping) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Thread.sleep(500L); |
|
|
|
|
|
|
|
|
|
|
|
// Peers found, so pick one with the highest number of chunks
|
|
|
|
// Firstly fetch peers that claim to be hosting files for this signature
|
|
|
|
Comparator<ArbitraryDirectConnectionInfo> highestChunkCountFirstComparator = |
|
|
|
List<ArbitraryDirectConnectionInfo> connectionInfoList = getDirectConnectionInfoForSignature(signature); |
|
|
|
Comparator.comparingInt(ArbitraryDirectConnectionInfo::getHashCount).reversed(); |
|
|
|
if (connectionInfoList == null || connectionInfoList.isEmpty()) { |
|
|
|
ArbitraryDirectConnectionInfo directConnectionInfo = connectionInfoList.stream() |
|
|
|
LOGGER.debug("No remaining direct connection peers found for signature {}", signature58); |
|
|
|
.sorted(highestChunkCountFirstComparator).findFirst().orElse(null); |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (directConnectionInfo == null) { |
|
|
|
LOGGER.debug("Attempting a direct peer connection for signature {}...", signature58); |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove from the list so that a different peer is tried next time
|
|
|
|
// Peers found, so pick one with the highest number of chunks
|
|
|
|
removeDirectConnectionInfo(directConnectionInfo); |
|
|
|
Comparator<ArbitraryDirectConnectionInfo> highestChunkCountFirstComparator = |
|
|
|
|
|
|
|
Comparator.comparingInt(ArbitraryDirectConnectionInfo::getHashCount).reversed(); |
|
|
|
|
|
|
|
ArbitraryDirectConnectionInfo directConnectionInfo = connectionInfoList.stream() |
|
|
|
|
|
|
|
.sorted(highestChunkCountFirstComparator).findFirst().orElse(null); |
|
|
|
|
|
|
|
|
|
|
|
String peerAddressString = directConnectionInfo.getPeerAddress(); |
|
|
|
if (directConnectionInfo == null) { |
|
|
|
boolean success = Network.getInstance().requestDataFromPeer(peerAddressString, signature); |
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Parse the peer address to find the host and port
|
|
|
|
// Remove from the list so that a different peer is tried next time
|
|
|
|
String host = null; |
|
|
|
removeDirectConnectionInfo(directConnectionInfo); |
|
|
|
int port = -1; |
|
|
|
|
|
|
|
String[] parts = peerAddressString.split(":"); |
|
|
|
String peerAddressString = directConnectionInfo.getPeerAddress(); |
|
|
|
if (parts.length > 1) { |
|
|
|
|
|
|
|
host = parts[0]; |
|
|
|
// Parse the peer address to find the host and port
|
|
|
|
port = Integer.parseInt(parts[1]); |
|
|
|
String host = null; |
|
|
|
} |
|
|
|
int port = -1; |
|
|
|
else { |
|
|
|
String[] parts = peerAddressString.split(":"); |
|
|
|
// Use default listen port
|
|
|
|
if (parts.length > 1) { |
|
|
|
port = Settings.getInstance().getDefaultListenPort(); |
|
|
|
host = parts[0]; |
|
|
|
} |
|
|
|
port = Integer.parseInt(parts[1]); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Assume no port included
|
|
|
|
|
|
|
|
host = peerAddressString; |
|
|
|
|
|
|
|
// Use default listen port
|
|
|
|
|
|
|
|
port = Settings.getInstance().getDefaultListenPort(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String peerAddressStringWithPort = String.format("%s:%d", host, port); |
|
|
|
|
|
|
|
success = Network.getInstance().requestDataFromPeer(peerAddressStringWithPort, signature); |
|
|
|
|
|
|
|
|
|
|
|
// 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(); |
|
|
|
int defaultPort = Settings.getInstance().getDefaultListenPort(); |
|
|
|
if (port != defaultPort) { |
|
|
|
|
|
|
|
String newPeerAddressString = String.format("%s:%d", host, defaultPort); |
|
|
|
// If unsuccessful, and using a non-standard port, try a second connection with the default listen port,
|
|
|
|
success = Network.getInstance().requestDataFromPeer(newPeerAddressString, signature); |
|
|
|
// 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) { |
|
|
|
|
|
|
|
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
|
|
|
|
// 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.
|
|
|
|
// to each of those in turn until one succeeds.
|
|
|
|
if (!success) { |
|
|
|
if (!success) { |
|
|
|
if (host != null) { |
|
|
|
if (host != null) { |
|
|
|
final String finalHost = host; |
|
|
|
final String finalHost = host; |
|
|
|
List<PeerData> knownPeers = Network.getInstance().getAllKnownPeers().stream() |
|
|
|
List<PeerData> knownPeers = Network.getInstance().getAllKnownPeers().stream() |
|
|
|
.filter(knownPeerData -> knownPeerData.getAddress().getHost().equals(finalHost)) |
|
|
|
.filter(knownPeerData -> knownPeerData.getAddress().getHost().equals(finalHost)) |
|
|
|
.collect(Collectors.toList()); |
|
|
|
.collect(Collectors.toList()); |
|
|
|
// Loop through each match and attempt a connection
|
|
|
|
// Loop through each match and attempt a connection
|
|
|
|
for (PeerData matchingPeer : knownPeers) { |
|
|
|
for (PeerData matchingPeer : knownPeers) { |
|
|
|
String matchingPeerAddress = matchingPeer.getAddress().toString(); |
|
|
|
String matchingPeerAddress = matchingPeer.getAddress().toString(); |
|
|
|
success = Network.getInstance().requestDataFromPeer(matchingPeerAddress, signature); |
|
|
|
int matchingPeerPort = matchingPeer.getAddress().getPort(); |
|
|
|
if (success) { |
|
|
|
// Make sure that it's not a port we've already tried
|
|
|
|
// Successfully connected, so stop making connections
|
|
|
|
if (matchingPeerPort != port && matchingPeerPort != defaultPort) { |
|
|
|
break; |
|
|
|
success = Network.getInstance().requestDataFromPeer(matchingPeerAddress, signature); |
|
|
|
|
|
|
|
if (success) { |
|
|
|
|
|
|
|
// Successfully connected, so stop making connections
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (success) { |
|
|
|
if (success) { |
|
|
|
// We were able to connect with a peer, so track the request
|
|
|
|
// We were able to connect with a peer, so track the request
|
|
|
|
ArbitraryDataFileListManager.getInstance().addToSignatureRequests(signature58, false, true); |
|
|
|
ArbitraryDataFileListManager.getInstance().addToSignatureRequests(signature58, false, true); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} catch (InterruptedException e) { |
|
|
|
|
|
|
|
// Do nothing
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return success; |
|
|
|
return success; |
|
|
|