mirror of
https://github.com/Qortal/qortal.git
synced 2025-06-21 22:51:22 +00:00
Merge b1f26a4b00c454ddde9a941b74e650dd8b77d10c into d253d7753d73c23b4a49638cd15b203d9d04ca17
This commit is contained in:
commit
1b19c27310
@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata modelVersion="1.1.0">
|
|
||||||
<groupId>io.reticulum</groupId>
|
|
||||||
<artifactId>reticulum-network-stack</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
<versioning>
|
|
||||||
<snapshot>
|
|
||||||
<localCopy>true</localCopy>
|
|
||||||
</snapshot>
|
|
||||||
<lastUpdated>20250418180444</lastUpdated>
|
|
||||||
<snapshotVersions>
|
|
||||||
<snapshotVersion>
|
|
||||||
<extension>jar</extension>
|
|
||||||
<value>1.0-SNAPSHOT</value>
|
|
||||||
<updated>20250418180444</updated>
|
|
||||||
</snapshotVersion>
|
|
||||||
<snapshotVersion>
|
|
||||||
<extension>pom</extension>
|
|
||||||
<value>1.0-SNAPSHOT</value>
|
|
||||||
<updated>20241218212752</updated>
|
|
||||||
</snapshotVersion>
|
|
||||||
</snapshotVersions>
|
|
||||||
</versioning>
|
|
||||||
</metadata>
|
|
Binary file not shown.
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>io.reticulum</groupId>
|
|
||||||
<artifactId>reticulum-network-stack</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
<description>POM was created from install:install-file</description>
|
|
||||||
</project>
|
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<metadata>
|
|
||||||
<groupId>io.reticulum</groupId>
|
|
||||||
<artifactId>reticulum-network-stack</artifactId>
|
|
||||||
<versioning>
|
|
||||||
<versions>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
</versions>
|
|
||||||
<lastUpdated>20250418180444</lastUpdated>
|
|
||||||
</versioning>
|
|
||||||
</metadata>
|
|
13
pom.xml
13
pom.xml
@ -52,6 +52,7 @@
|
|||||||
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
|
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
|
||||||
<protobuf.version>3.25.3</protobuf.version>
|
<protobuf.version>3.25.3</protobuf.version>
|
||||||
<replacer.version>1.5.3</replacer.version>
|
<replacer.version>1.5.3</replacer.version>
|
||||||
|
<reticulum.version>ace00f8</reticulum.version>
|
||||||
<simplemagic.version>1.17</simplemagic.version>
|
<simplemagic.version>1.17</simplemagic.version>
|
||||||
<swagger-api.version>2.0.10</swagger-api.version>
|
<swagger-api.version>2.0.10</swagger-api.version>
|
||||||
<swagger-ui.version>5.18.2</swagger-ui.version>
|
<swagger-ui.version>5.18.2</swagger-ui.version>
|
||||||
@ -512,6 +513,12 @@
|
|||||||
<artifactId>altcoinj</artifactId>
|
<artifactId>altcoinj</artifactId>
|
||||||
<version>${altcoinj.version}</version>
|
<version>${altcoinj.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Build Reticulum from Source -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.sergst83</groupId>
|
||||||
|
<artifactId>reticulum-network-stack</artifactId>
|
||||||
|
<version>${reticulum.version}</version>
|
||||||
|
</dependency>
|
||||||
<!-- Utilities -->
|
<!-- Utilities -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.googlecode.json-simple</groupId>
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
@ -805,12 +812,6 @@
|
|||||||
<artifactId>jaxb-runtime</artifactId>
|
<artifactId>jaxb-runtime</artifactId>
|
||||||
<version>${jaxb-runtime.version}</version>
|
<version>${jaxb-runtime.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- reticulum_network_stack -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.reticulum</groupId>
|
|
||||||
<artifactId>reticulum-network-stack</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
@ -543,8 +543,8 @@ public class Controller extends Thread {
|
|||||||
LOGGER.info("Starting synchronizer");
|
LOGGER.info("Starting synchronizer");
|
||||||
Synchronizer.getInstance().start();
|
Synchronizer.getInstance().start();
|
||||||
|
|
||||||
//LOGGER.info("Starting synchronizer over Reticulum");
|
LOGGER.info("Starting synchronizer over Reticulum");
|
||||||
//RNSSynchronizer.getInstance().start();
|
RNSSynchronizer.getInstance().start();
|
||||||
|
|
||||||
LOGGER.info("Starting block minter");
|
LOGGER.info("Starting block minter");
|
||||||
blockMinter = new BlockMinter();
|
blockMinter = new BlockMinter();
|
||||||
@ -743,6 +743,73 @@ public class Controller extends Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 3*60*1000, 3*60*1000);
|
}, 3*60*1000, 3*60*1000);
|
||||||
|
//Timer syncFromGenesisRNS = new Timer();
|
||||||
|
//syncFromGenesisRNS.schedule(new TimerTask() {
|
||||||
|
// @Override
|
||||||
|
// public void run() {
|
||||||
|
// LOGGER.debug("Start sync from genesis check (RNS).");
|
||||||
|
// boolean canBootstrap = Settings.getInstance().getBootstrap();
|
||||||
|
// boolean needsArchiveRebuildRNS = false;
|
||||||
|
// int checkHeightRNS = 0;
|
||||||
|
//
|
||||||
|
// try (final Repository repository = RepositoryManager.getRepository()){
|
||||||
|
// needsArchiveRebuildRNS = (repository.getBlockArchiveRepository().fromHeight(2) == null);
|
||||||
|
// checkHeightRNS = repository.getBlockRepository().getBlockchainHeight();
|
||||||
|
// } catch (DataException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (canBootstrap || !needsArchiveRebuildRNS || checkHeightRNS > 3) {
|
||||||
|
// LOGGER.debug("Bootstrapping is enabled or we have more than 2 blocks, cancel sync from genesis check.");
|
||||||
|
// syncFromGenesisRNS.cancel();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (needsArchiveRebuildRNS && !canBootstrap) {
|
||||||
|
// LOGGER.info("Start syncing from genesis (RNS)!");
|
||||||
|
// List<RNSPeer> seeds = new ArrayList<>(RNSNetwork.getInstance().getActiveImmutableLinkedPeers());
|
||||||
|
//
|
||||||
|
// // Check if have a qualified peer to sync
|
||||||
|
// if (seeds.isEmpty()) {
|
||||||
|
// LOGGER.info("No connected RNSPeer(s), will try again later.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int index = new SecureRandom().nextInt(seeds.size());
|
||||||
|
// RNSPeer syncPeer = seeds.get(index);
|
||||||
|
// var syncPeerLinkAsString = syncPeer.getPeerLink().toString();
|
||||||
|
// //String syncNode = String.valueOf(seeds.get(index));
|
||||||
|
// //PeerAddress peerAddress = PeerAddress.fromString(syncNode);
|
||||||
|
// //InetSocketAddress resolvedAddress = null;
|
||||||
|
// //
|
||||||
|
// //try {
|
||||||
|
// // resolvedAddress = peerAddress.toSocketAddress();
|
||||||
|
// //} catch (UnknownHostException e) {
|
||||||
|
// // throw new RuntimeException(e);
|
||||||
|
// //}
|
||||||
|
// //
|
||||||
|
// //InetSocketAddress finalResolvedAddress = resolvedAddress;
|
||||||
|
// //Peer targetPeer = seeds.stream().filter(peer -> peer.getResolvedAddress().equals(finalResolvedAddress)).findFirst().orElse(null);
|
||||||
|
// //RNSPeer targetPeerRNS = seeds.stream().findFirst().orElse(null);
|
||||||
|
// RNSPeer targetPeerRNS = seeds.stream().filter(peer -> peer.getPeerLink().toString().equals(syncPeerLinkAsString)).findFirst().orElse(null);
|
||||||
|
// RNSSynchronizer.SynchronizationResult syncResultRNS;
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// do {
|
||||||
|
// try {
|
||||||
|
// syncResultRNS = RNSSynchronizer.getInstance().actuallySynchronize(targetPeerRNS, true);
|
||||||
|
// } catch (InterruptedException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// while (syncResultRNS == RNSSynchronizer.SynchronizationResult.OK);
|
||||||
|
// } finally {
|
||||||
|
// // We are syncing now, so can cancel the check
|
||||||
|
// syncFromGenesisRNS.cancel();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}, 3*60*1000, 3*60*1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called by AdvancedInstaller's launch EXE in single-instance mode, when an instance is already running. */
|
/** Called by AdvancedInstaller's launch EXE in single-instance mode, when an instance is already running. */
|
||||||
@ -858,29 +925,29 @@ public class Controller extends Thread {
|
|||||||
repositoryMaintenanceInterval = getRandomRepositoryMaintenanceInterval();
|
repositoryMaintenanceInterval = getRandomRepositoryMaintenanceInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Prune stuck/slow/old peers
|
// Prune stuck/slow/old peers
|
||||||
//if (now >= prunePeersTimestamp + prunePeersInterval) {
|
if (now >= prunePeersTimestamp + prunePeersInterval) {
|
||||||
// prunePeersTimestamp = now + prunePeersInterval;
|
prunePeersTimestamp = now + prunePeersInterval;
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// LOGGER.debug("Pruning peers...");
|
|
||||||
// Network.getInstance().prunePeers();
|
|
||||||
// } catch (DataException e) {
|
|
||||||
// LOGGER.warn(String.format("Repository issue when trying to prune peers: %s", e.getMessage()));
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// Q: Do we need global pruning?
|
try {
|
||||||
//if (now >= pruneRNSPeersTimestamp + pruneRNSPeersInterval) {
|
LOGGER.debug("Pruning peers...");
|
||||||
// pruneRNSPeersTimestamp = now + pruneRNSPeersInterval;
|
Network.getInstance().prunePeers();
|
||||||
//
|
} catch (DataException e) {
|
||||||
// try {
|
LOGGER.warn(String.format("Repository issue when trying to prune peers: %s", e.getMessage()));
|
||||||
// LOGGER.debug("Pruning Reticulum peers...");
|
}
|
||||||
// RNSNetwork.getInstance().prunePeers();
|
}
|
||||||
// } catch (DataException e) {
|
|
||||||
// LOGGER.warn(String.format("Repository issue when trying to prune Reticulum peers: %s", e.getMessage()));
|
// Q: Do we need global pruning?
|
||||||
// }
|
if (now >= pruneRNSPeersTimestamp + pruneRNSPeersInterval) {
|
||||||
//}
|
pruneRNSPeersTimestamp = now + pruneRNSPeersInterval;
|
||||||
|
|
||||||
|
try {
|
||||||
|
LOGGER.debug("Pruning Reticulum peers...");
|
||||||
|
RNSNetwork.getInstance().prunePeers();
|
||||||
|
} catch (DataException e) {
|
||||||
|
LOGGER.warn(String.format("Repository issue when trying to prune Reticulum peers: %s", e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete expired transactions
|
// Delete expired transactions
|
||||||
if (now >= deleteExpiredTimestamp) {
|
if (now >= deleteExpiredTimestamp) {
|
||||||
@ -1171,6 +1238,7 @@ public class Controller extends Thread {
|
|||||||
|
|
||||||
LOGGER.info("Shutting down synchronizer");
|
LOGGER.info("Shutting down synchronizer");
|
||||||
Synchronizer.getInstance().shutdown();
|
Synchronizer.getInstance().shutdown();
|
||||||
|
RNSSynchronizer.getInstance().shutdown();
|
||||||
|
|
||||||
LOGGER.info("Shutting down API");
|
LOGGER.info("Shutting down API");
|
||||||
ApiService.getInstance().stop();
|
ApiService.getInstance().stop();
|
||||||
@ -2311,22 +2379,22 @@ public class Controller extends Thread {
|
|||||||
// OnlineAccountsManager.getInstance().onNetworkOnlineAccountsV3Message(peer, message);
|
// OnlineAccountsManager.getInstance().onNetworkOnlineAccountsV3Message(peer, message);
|
||||||
// break;
|
// break;
|
||||||
|
|
||||||
//// TODO: Compiles but much of the Manager details need to be rethought for Reticulum
|
// TODO: Compiles but rethink for Reticulum
|
||||||
//case GET_ARBITRARY_DATA:
|
case GET_ARBITRARY_DATA:
|
||||||
// // Not currently supported
|
// Not currently supported
|
||||||
// break;
|
break;
|
||||||
////
|
|
||||||
//case ARBITRARY_DATA_FILE_LIST:
|
case ARBITRARY_DATA_FILE_LIST:
|
||||||
// RNSArbitraryDataFileListManager.getInstance().onNetworkArbitraryDataFileListMessage(peer, message);
|
RNSArbitraryDataFileListManager.getInstance().onNetworkArbitraryDataFileListMessage(peer, message);
|
||||||
// break;
|
break;
|
||||||
//
|
|
||||||
//case GET_ARBITRARY_DATA_FILE:
|
case GET_ARBITRARY_DATA_FILE:
|
||||||
// RNSArbitraryDataFileManager.getInstance().onNetworkGetArbitraryDataFileMessage(peer, message);
|
RNSArbitraryDataFileManager.getInstance().onNetworkGetArbitraryDataFileMessage(peer, message);
|
||||||
// break;
|
break;
|
||||||
//
|
|
||||||
//case GET_ARBITRARY_DATA_FILE_LIST:
|
case GET_ARBITRARY_DATA_FILE_LIST:
|
||||||
// RNSArbitraryDataFileListManager.getInstance().onNetworkGetArbitraryDataFileListMessage(peer, message);
|
RNSArbitraryDataFileListManager.getInstance().onNetworkGetArbitraryDataFileListMessage(peer, message);
|
||||||
// break;
|
break;
|
||||||
//
|
//
|
||||||
case ARBITRARY_SIGNATURES:
|
case ARBITRARY_SIGNATURES:
|
||||||
// Not currently supported
|
// Not currently supported
|
||||||
@ -2665,7 +2733,7 @@ public class Controller extends Thread {
|
|||||||
peer.setChainTipData(newChainTipData);
|
peer.setChainTipData(newChainTipData);
|
||||||
|
|
||||||
// Potentially synchronize
|
// Potentially synchronize
|
||||||
Synchronizer.getInstance().requestSync();
|
RNSSynchronizer.getInstance().requestSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onRNSNetworkBlockSummariesV2Message(RNSPeer peer, Message message) {
|
private void onRNSNetworkBlockSummariesV2Message(RNSPeer peer, Message message) {
|
||||||
@ -2696,7 +2764,7 @@ public class Controller extends Thread {
|
|||||||
peer.setChainTipSummaries(blockSummariesV2Message.getBlockSummaries());
|
peer.setChainTipSummaries(blockSummariesV2Message.getBlockSummaries());
|
||||||
|
|
||||||
// Potentially synchronize
|
// Potentially synchronize
|
||||||
Synchronizer.getInstance().requestSync();
|
RNSSynchronizer.getInstance().requestSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************
|
// ************
|
||||||
@ -2918,7 +2986,7 @@ public class Controller extends Thread {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Needs a mutable copy of the unmodifiableList
|
// Needs a mutable copy of the unmodifiableList
|
||||||
List<RNSPeer> peers = new ArrayList<>(RNSNetwork.getInstance().getImmutableActiveLinkedPeers());
|
List<RNSPeer> peers = new ArrayList<>(RNSNetwork.getInstance().getActiveImmutableLinkedPeers());
|
||||||
if (peers == null)
|
if (peers == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ public class RNSSynchronizer extends Thread {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Needs a mutable copy of the unmodifiableList
|
// Needs a mutable copy of the unmodifiableList
|
||||||
List<RNSPeer> peers = new ArrayList<>(RNSNetwork.getInstance().getImmutableActiveLinkedPeers());
|
List<RNSPeer> peers = new ArrayList<>(RNSNetwork.getInstance().getActiveImmutableLinkedPeers());
|
||||||
|
|
||||||
//// Disregard peers that have "misbehaved" recently
|
//// Disregard peers that have "misbehaved" recently
|
||||||
//peers.removeIf(Controller.hasMisbehaved);
|
//peers.removeIf(Controller.hasMisbehaved);
|
||||||
@ -395,7 +395,7 @@ public class RNSSynchronizer extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkRecoveryModeForPeers(List<RNSPeer> qualifiedPeers) {
|
private boolean checkRecoveryModeForPeers(List<RNSPeer> qualifiedPeers) {
|
||||||
List<RNSPeer> linkedPeers = RNSNetwork.getInstance().getImmutableActiveLinkedPeers();
|
List<RNSPeer> linkedPeers = RNSNetwork.getInstance().getActiveImmutableLinkedPeers();
|
||||||
|
|
||||||
if (!linkedPeers.isEmpty()) {
|
if (!linkedPeers.isEmpty()) {
|
||||||
// There is at least one handshaked peer
|
// There is at least one handshaked peer
|
||||||
|
@ -204,12 +204,12 @@ public class RNSArbitraryDataFileManager extends Thread {
|
|||||||
Message getArbitraryDataFileMessage = new GetArbitraryDataFileMessage(signature, hash);
|
Message getArbitraryDataFileMessage = new GetArbitraryDataFileMessage(signature, hash);
|
||||||
|
|
||||||
Message response = null;
|
Message response = null;
|
||||||
//// TODO - revisit (doesn't work with Reticulum)
|
// TODO - revisit with RNS
|
||||||
//try {
|
try {
|
||||||
// response = peer.getResponseWithTimeout(getArbitraryDataFileMessage, (int) ArbitraryDataManager.ARBITRARY_REQUEST_TIMEOUT);
|
response = peer.getResponseWithTimeout(getArbitraryDataFileMessage, (int) ArbitraryDataManager.ARBITRARY_REQUEST_TIMEOUT);
|
||||||
//} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// // Will return below due to null response
|
// Will return below due to null response
|
||||||
//}
|
}
|
||||||
arbitraryDataFileRequests.remove(hash58);
|
arbitraryDataFileRequests.remove(hash58);
|
||||||
LOGGER.trace(String.format("Removed hash %.8s from arbitraryDataFileRequests", hash58));
|
LOGGER.trace(String.format("Removed hash %.8s from arbitraryDataFileRequests", hash58));
|
||||||
|
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
package org.qortal.controller.arbitrary;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.qortal.controller.Controller;
|
||||||
|
import org.qortal.data.arbitrary.RNSArbitraryFileListResponseInfo;
|
||||||
|
import org.qortal.data.transaction.ArbitraryTransactionData;
|
||||||
|
import org.qortal.event.DataMonitorEvent;
|
||||||
|
import org.qortal.event.EventBus;
|
||||||
|
import org.qortal.network.RNSPeer;
|
||||||
|
import org.qortal.repository.DataException;
|
||||||
|
import org.qortal.repository.Repository;
|
||||||
|
import org.qortal.repository.RepositoryManager;
|
||||||
|
import org.qortal.utils.ArbitraryTransactionUtils;
|
||||||
|
import org.qortal.utils.Base58;
|
||||||
|
import org.qortal.utils.NTP;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import static java.lang.Thread.NORM_PRIORITY;
|
||||||
|
|
||||||
|
public class RNSArbitraryDataFileRequestThread implements Runnable {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataFileRequestThread.class);
|
||||||
|
|
||||||
|
public RNSArbitraryDataFileRequestThread() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Thread.currentThread().setName("Arbitrary Data File Request Thread");
|
||||||
|
Thread.currentThread().setPriority(NORM_PRIORITY);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (!Controller.isStopping()) {
|
||||||
|
Long now = NTP.getTime();
|
||||||
|
this.processFileHashes(now);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// Fall-through to exit thread...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFileHashes(Long now) throws InterruptedException {
|
||||||
|
if (Controller.isStopping()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RNSArbitraryDataFileManager arbitraryDataFileManager = RNSArbitraryDataFileManager.getInstance();
|
||||||
|
String signature58 = null;
|
||||||
|
String hash58 = null;
|
||||||
|
RNSPeer peer = null;
|
||||||
|
boolean shouldProcess = false;
|
||||||
|
|
||||||
|
synchronized (arbitraryDataFileManager.arbitraryDataFileHashResponses) {
|
||||||
|
if (!arbitraryDataFileManager.arbitraryDataFileHashResponses.isEmpty()) {
|
||||||
|
|
||||||
|
// Sort by lowest number of node hops first
|
||||||
|
Comparator<RNSArbitraryFileListResponseInfo> lowestHopsFirstComparator =
|
||||||
|
Comparator.comparingInt(RNSArbitraryFileListResponseInfo::getRequestHops);
|
||||||
|
arbitraryDataFileManager.arbitraryDataFileHashResponses.sort(lowestHopsFirstComparator);
|
||||||
|
|
||||||
|
Iterator iterator = arbitraryDataFileManager.arbitraryDataFileHashResponses.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
if (Controller.isStopping()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RNSArbitraryFileListResponseInfo responseInfo = (RNSArbitraryFileListResponseInfo) iterator.next();
|
||||||
|
if (responseInfo == null) {
|
||||||
|
iterator.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash58 = responseInfo.getHash58();
|
||||||
|
peer = responseInfo.getPeer();
|
||||||
|
signature58 = responseInfo.getSignature58();
|
||||||
|
Long timestamp = responseInfo.getTimestamp();
|
||||||
|
|
||||||
|
if (now - timestamp >= ArbitraryDataManager.ARBITRARY_RELAY_TIMEOUT || signature58 == null || peer == null) {
|
||||||
|
// Ignore - to be deleted
|
||||||
|
iterator.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if already requesting, but don't remove, as we might want to retry later
|
||||||
|
if (arbitraryDataFileManager.arbitraryDataFileRequests.containsKey(hash58)) {
|
||||||
|
// Already requesting - leave this attempt for later
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to process this file
|
||||||
|
shouldProcess = true;
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shouldProcess) {
|
||||||
|
// Nothing to do
|
||||||
|
Thread.sleep(1000L);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] hash = Base58.decode(hash58);
|
||||||
|
byte[] signature = Base58.decode(signature58);
|
||||||
|
|
||||||
|
// Fetch the transaction data
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
ArbitraryTransactionData arbitraryTransactionData = ArbitraryTransactionUtils.fetchTransactionData(repository, signature);
|
||||||
|
if (arbitraryTransactionData == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signature == null || hash == null || peer == null || arbitraryTransactionData == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.trace("Fetching file {} from peer {} via request thread...", hash58, peer);
|
||||||
|
arbitraryDataFileManager.fetchArbitraryDataFiles(repository, peer, signature, arbitraryTransactionData, Arrays.asList(hash));
|
||||||
|
|
||||||
|
} catch (DataException e) {
|
||||||
|
LOGGER.debug("Unable to process file hashes: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -61,7 +61,7 @@ public class RNSArbitraryRelayInfo {
|
|||||||
if (other == this)
|
if (other == this)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!(other instanceof ArbitraryRelayInfo))
|
if (!(other instanceof RNSArbitraryRelayInfo))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RNSArbitraryRelayInfo otherRelayInfo = (RNSArbitraryRelayInfo) other;
|
RNSArbitraryRelayInfo otherRelayInfo = (RNSArbitraryRelayInfo) other;
|
||||||
|
@ -24,7 +24,7 @@ import static io.reticulum.link.TeardownSession.TIMEOUT;
|
|||||||
import static io.reticulum.link.LinkStatus.ACTIVE;
|
import static io.reticulum.link.LinkStatus.ACTIVE;
|
||||||
import static io.reticulum.link.LinkStatus.STALE;
|
import static io.reticulum.link.LinkStatus.STALE;
|
||||||
import static io.reticulum.link.LinkStatus.CLOSED;
|
import static io.reticulum.link.LinkStatus.CLOSED;
|
||||||
//import static io.reticulum.link.LinkStatus.PENDING;
|
import static io.reticulum.link.LinkStatus.PENDING;
|
||||||
import static io.reticulum.link.LinkStatus.HANDSHAKE;
|
import static io.reticulum.link.LinkStatus.HANDSHAKE;
|
||||||
//import static io.reticulum.packet.PacketContextType.LINKCLOSE;
|
//import static io.reticulum.packet.PacketContextType.LINKCLOSE;
|
||||||
//import static io.reticulum.identity.IdentityKnownDestination.recall;
|
//import static io.reticulum.identity.IdentityKnownDestination.recall;
|
||||||
@ -72,7 +72,7 @@ import java.util.Objects;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import static org.apache.commons.codec.binary.Hex.encodeHexString;
|
||||||
import org.qortal.utils.ExecuteProduceConsume;
|
import org.qortal.utils.ExecuteProduceConsume;
|
||||||
import org.qortal.utils.ExecuteProduceConsume.StatsSnapshot;
|
import org.qortal.utils.ExecuteProduceConsume.StatsSnapshot;
|
||||||
import org.qortal.utils.NTP;
|
import org.qortal.utils.NTP;
|
||||||
@ -218,7 +218,7 @@ public class RNSNetwork {
|
|||||||
// APP_NAME,
|
// APP_NAME,
|
||||||
// "qdn"
|
// "qdn"
|
||||||
//);
|
//);
|
||||||
log.info("Destination {} {} running", Hex.encodeHexString(baseDestination.getHash()), baseDestination.getName());
|
log.info("Destination {} {} running", encodeHexString(baseDestination.getHash()), baseDestination.getName());
|
||||||
|
|
||||||
baseDestination.setProofStrategy(ProofStrategy.PROVE_ALL);
|
baseDestination.setProofStrategy(ProofStrategy.PROVE_ALL);
|
||||||
baseDestination.setAcceptLinkRequests(true);
|
baseDestination.setAcceptLinkRequests(true);
|
||||||
@ -228,7 +228,7 @@ public class RNSNetwork {
|
|||||||
log.debug("announceHandlers: {}", Transport.getInstance().getAnnounceHandlers());
|
log.debug("announceHandlers: {}", Transport.getInstance().getAnnounceHandlers());
|
||||||
// do a first announce
|
// do a first announce
|
||||||
baseDestination.announce();
|
baseDestination.announce();
|
||||||
log.debug("Sent initial announce from {} ({})", Hex.encodeHexString(baseDestination.getHash()), baseDestination.getName());
|
log.debug("Sent initial announce from {} ({})", encodeHexString(baseDestination.getHash()), baseDestination.getName());
|
||||||
|
|
||||||
// Start up first networking thread (the "server loop", the "Tasks engine")
|
// Start up first networking thread (the "server loop", the "Tasks engine")
|
||||||
rnsNetworkEPC.start();
|
rnsNetworkEPC.start();
|
||||||
@ -252,7 +252,7 @@ public class RNSNetwork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(Function<RNSPeer, Message> peerMessageBuilder) {
|
public void broadcast(Function<RNSPeer, Message> peerMessageBuilder) {
|
||||||
for (RNSPeer peer : getImmutableActiveLinkedPeers()) {
|
for (RNSPeer peer : getActiveImmutableLinkedPeers()) {
|
||||||
if (this.isShuttingDown) {
|
if (this.isShuttingDown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ public class RNSNetwork {
|
|||||||
}
|
}
|
||||||
// Disconnect peers gracefully and terminate Reticulum
|
// Disconnect peers gracefully and terminate Reticulum
|
||||||
for (RNSPeer p: linkedPeers) {
|
for (RNSPeer p: linkedPeers) {
|
||||||
log.info("shutting down peer: {}", Hex.encodeHexString(p.getDestinationHash()));
|
log.info("shutting down peer: {}", encodeHexString(p.getDestinationHash()));
|
||||||
//log.debug("peer: {}", p);
|
//log.debug("peer: {}", p);
|
||||||
p.shutdown();
|
p.shutdown();
|
||||||
try {
|
try {
|
||||||
@ -355,7 +355,7 @@ public class RNSNetwork {
|
|||||||
rttString = String.format("%d miliseconds", rtt);
|
rttString = String.format("%d miliseconds", rtt);
|
||||||
}
|
}
|
||||||
log.info("Shutdown packet confirmation received from {}, round-trip time is {}",
|
log.info("Shutdown packet confirmation received from {}, round-trip time is {}",
|
||||||
Hex.encodeHexString(receipt.getDestination().getHash()), rttString);
|
encodeHexString(receipt.getDestination().getHash()), rttString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,14 +366,14 @@ public class RNSNetwork {
|
|||||||
public void clientConnected(Link link) {
|
public void clientConnected(Link link) {
|
||||||
//link.setLinkClosedCallback(this::clientDisconnected);
|
//link.setLinkClosedCallback(this::clientDisconnected);
|
||||||
//link.setPacketCallback(this::serverPacketReceived);
|
//link.setPacketCallback(this::serverPacketReceived);
|
||||||
log.info("clientConnected - link hash: {}, {}", link.getHash(), Hex.encodeHexString(link.getHash()));
|
log.info("clientConnected - link hash: {}, {}", link.getHash(), encodeHexString(link.getHash()));
|
||||||
RNSPeer newPeer = new RNSPeer(link);
|
RNSPeer newPeer = new RNSPeer(link);
|
||||||
newPeer.setPeerLinkHash(link.getHash());
|
newPeer.setPeerLinkHash(link.getHash());
|
||||||
newPeer.setMessageMagic(getMessageMagic());
|
newPeer.setMessageMagic(getMessageMagic());
|
||||||
// make sure the peer has a channel and buffer
|
// make sure the peer has a channel and buffer
|
||||||
newPeer.getOrInitPeerBuffer();
|
newPeer.getOrInitPeerBuffer();
|
||||||
incomingPeers.add(newPeer);
|
addIncomingPeer(newPeer);
|
||||||
log.info("***> Client connected, link: {}", link);
|
log.info("***> Client connected, link: {}", encodeHexString(link.getLinkId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clientDisconnected(Link link) {
|
public void clientDisconnected(Link link) {
|
||||||
@ -382,7 +382,7 @@ public class RNSNetwork {
|
|||||||
|
|
||||||
public void serverPacketReceived(byte[] message, Packet packet) {
|
public void serverPacketReceived(byte[] message, Packet packet) {
|
||||||
var msgText = new String(message, StandardCharsets.UTF_8);
|
var msgText = new String(message, StandardCharsets.UTF_8);
|
||||||
log.info("Received data on link - message: {}, destinationHash: {}", msgText, Hex.encodeHexString(packet.getDestinationHash()));
|
log.info("Received data on link - message: {}, destinationHash: {}", msgText, encodeHexString(packet.getDestinationHash()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//public void announceBaseDestination () {
|
//public void announceBaseDestination () {
|
||||||
@ -401,7 +401,7 @@ public class RNSNetwork {
|
|||||||
var peerExists = false;
|
var peerExists = false;
|
||||||
var activePeerCount = 0;
|
var activePeerCount = 0;
|
||||||
|
|
||||||
log.info("Received an announce from {}", Hex.encodeHexString(destinationHash));
|
log.info("Received an announce from {}", encodeHexString(destinationHash));
|
||||||
|
|
||||||
if (nonNull(appData)) {
|
if (nonNull(appData)) {
|
||||||
log.debug("The announce contained the following app data: {}", new String(appData, UTF_8));
|
log.debug("The announce contained the following app data: {}", new String(appData, UTF_8));
|
||||||
@ -409,7 +409,7 @@ public class RNSNetwork {
|
|||||||
|
|
||||||
// add to peer list if we can use more peers
|
// add to peer list if we can use more peers
|
||||||
//synchronized (this) {
|
//synchronized (this) {
|
||||||
var lps = RNSNetwork.getInstance().getLinkedPeers();
|
var lps = RNSNetwork.getInstance().getImmutableLinkedPeers();
|
||||||
for (RNSPeer p: lps) {
|
for (RNSPeer p: lps) {
|
||||||
var pl = p.getPeerLink();
|
var pl = p.getPeerLink();
|
||||||
if ((nonNull(pl) && (pl.getStatus() == ACTIVE))) {
|
if ((nonNull(pl) && (pl.getStatus() == ACTIVE))) {
|
||||||
@ -421,7 +421,8 @@ public class RNSNetwork {
|
|||||||
if (Arrays.equals(p.getDestinationHash(), destinationHash)) {
|
if (Arrays.equals(p.getDestinationHash(), destinationHash)) {
|
||||||
log.info("QAnnounceHandler - peer exists - found peer matching destinationHash");
|
log.info("QAnnounceHandler - peer exists - found peer matching destinationHash");
|
||||||
if (nonNull(p.getPeerLink())) {
|
if (nonNull(p.getPeerLink())) {
|
||||||
log.info("peer link: {}, status: {}", p.getPeerLink(), p.getPeerLink().getStatus());
|
log.info("peer link: {}, status: {}",
|
||||||
|
encodeHexString(p.getPeerLink().getLinkId()), p.getPeerLink().getStatus());
|
||||||
}
|
}
|
||||||
peerExists = true;
|
peerExists = true;
|
||||||
if (p.getPeerLink().getStatus() != ACTIVE) {
|
if (p.getPeerLink().getStatus() != ACTIVE) {
|
||||||
@ -430,7 +431,12 @@ public class RNSNetwork {
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (nonNull(p.getPeerLink())) {
|
if (nonNull(p.getPeerLink())) {
|
||||||
log.info("QAnnounceHandler - other peer - link: {}, status: {}", p.getPeerLink(), p.getPeerLink().getStatus());
|
log.info("QAnnounceHandler - other peer - link: {}, status: {}",
|
||||||
|
encodeHexString(p.getPeerLink().getLinkId()), p.getPeerLink().getStatus());
|
||||||
|
if (p.getPeerLink().getStatus() == CLOSED) {
|
||||||
|
// mark peer for deletion on nexe pruning
|
||||||
|
p.setDeleteMe(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.info("QAnnounceHandler - peer link is null");
|
log.info("QAnnounceHandler - peer link is null");
|
||||||
}
|
}
|
||||||
@ -442,7 +448,7 @@ public class RNSNetwork {
|
|||||||
newPeer.setIsInitiator(true);
|
newPeer.setIsInitiator(true);
|
||||||
newPeer.setMessageMagic(getMessageMagic());
|
newPeer.setMessageMagic(getMessageMagic());
|
||||||
addLinkedPeer(newPeer);
|
addLinkedPeer(newPeer);
|
||||||
log.info("added new RNSPeer, destinationHash: {}", Hex.encodeHexString(destinationHash));
|
log.info("added new RNSPeer, destinationHash: {}", encodeHexString(destinationHash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Chance to announce instead of waiting for next pruning.
|
// Chance to announce instead of waiting for next pruning.
|
||||||
@ -488,12 +494,6 @@ public class RNSNetwork {
|
|||||||
|
|
||||||
final Long now = NTP.getTime();
|
final Long now = NTP.getTime();
|
||||||
|
|
||||||
// Prune stuck/slow/old peers (moved from Controller)
|
|
||||||
task = maybeProduceRNSPrunePeersTask(now);
|
|
||||||
if (task != null) {
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ping task (Link+Channel+Buffer)
|
// ping task (Link+Channel+Buffer)
|
||||||
task = maybeProducePeerPingTask(now);
|
task = maybeProducePeerPingTask(now);
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
@ -505,11 +505,11 @@ public class RNSNetwork {
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune stuck/slow/old peers (moved from Controller)
|
//// Prune stuck/slow/old peers (moved from Controller)
|
||||||
task = maybeProduceRNSPrunePeersTask(now);
|
//task = maybeProduceRNSPrunePeersTask(now);
|
||||||
if (task != null) {
|
//if (task != null) {
|
||||||
return task;
|
// return task;
|
||||||
}
|
//}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -531,7 +531,7 @@ public class RNSNetwork {
|
|||||||
//// Note: we might not need this. All messages handled asynchronously in Reticulum
|
//// Note: we might not need this. All messages handled asynchronously in Reticulum
|
||||||
//// (RNSPeer peerBufferReady callback)
|
//// (RNSPeer peerBufferReady callback)
|
||||||
//private Task maybeProducePeerMessageTask() {
|
//private Task maybeProducePeerMessageTask() {
|
||||||
// return getImmutableActiveLinkedPeers().stream()
|
// return getActiveImmutableLinkedPeers().stream()
|
||||||
// .map(RNSPeer::getMessageTask)
|
// .map(RNSPeer::getMessageTask)
|
||||||
// .filter(Objects::nonNull)
|
// .filter(Objects::nonNull)
|
||||||
// .findFirst()
|
// .findFirst()
|
||||||
@ -555,7 +555,7 @@ public class RNSNetwork {
|
|||||||
// log.info("ilp - {}", ilp);
|
// log.info("ilp - {}", ilp);
|
||||||
//}
|
//}
|
||||||
//return ilp;
|
//return ilp;
|
||||||
return getImmutableActiveLinkedPeers().stream()
|
return getActiveImmutableLinkedPeers().stream()
|
||||||
.map(peer -> peer.getPingTask(now))
|
.map(peer -> peer.getPingTask(now))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
@ -589,7 +589,7 @@ public class RNSNetwork {
|
|||||||
return SingletonContainer.INSTANCE;
|
return SingletonContainer.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RNSPeer> getImmutableActiveLinkedPeers() {
|
public List<RNSPeer> getActiveImmutableLinkedPeers() {
|
||||||
List<RNSPeer> activePeers = Collections.synchronizedList(new ArrayList<>());
|
List<RNSPeer> activePeers = Collections.synchronizedList(new ArrayList<>());
|
||||||
for (RNSPeer p: this.immutableLinkedPeers) {
|
for (RNSPeer p: this.immutableLinkedPeers) {
|
||||||
if (nonNull(p.getPeerLink()) && (p.getPeerLink().getStatus() == ACTIVE)) {
|
if (nonNull(p.getPeerLink()) && (p.getPeerLink().getStatus() == ACTIVE)) {
|
||||||
@ -599,9 +599,10 @@ public class RNSNetwork {
|
|||||||
return activePeers;
|
return activePeers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RNSPeer> getImmutableLinkedPeers() {
|
// note: we already have a lobok getter for this
|
||||||
return this.immutableLinkedPeers;
|
//public List<RNSPeer> getImmutableLinkedPeers() {
|
||||||
}
|
// return this.immutableLinkedPeers;
|
||||||
|
//}
|
||||||
|
|
||||||
public void addLinkedPeer(RNSPeer peer) {
|
public void addLinkedPeer(RNSPeer peer) {
|
||||||
this.linkedPeers.add(peer);
|
this.linkedPeers.add(peer);
|
||||||
@ -609,22 +610,23 @@ public class RNSNetwork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeLinkedPeer(RNSPeer peer) {
|
public void removeLinkedPeer(RNSPeer peer) {
|
||||||
if (nonNull(peer.getPeerBuffer())) {
|
//if (nonNull(peer.getPeerBuffer())) {
|
||||||
peer.getPeerBuffer().close();
|
// peer.getPeerBuffer().close();
|
||||||
}
|
//}
|
||||||
if (nonNull(peer.getPeerLink())) {
|
if (nonNull(peer.getPeerLink())) {
|
||||||
peer.getPeerLink().teardown();
|
peer.getPeerLink().teardown();
|
||||||
}
|
}
|
||||||
this.linkedPeers.remove(peer); // thread safe
|
var p = this.linkedPeers.remove(this.linkedPeers.indexOf(peer)); // thread safe
|
||||||
this.immutableLinkedPeers = List.copyOf(this.linkedPeers);
|
this.immutableLinkedPeers = List.copyOf(this.linkedPeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RNSPeer> getLinkedPeers() {
|
// note: we already have a lobok getter for this
|
||||||
//synchronized(this.linkedPeers) {
|
//public List<RNSPeer> getLinkedPeers() {
|
||||||
//return new ArrayList<>(this.linkedPeers);
|
// //synchronized(this.linkedPeers) {
|
||||||
return this.linkedPeers;
|
// //return new ArrayList<>(this.linkedPeers);
|
||||||
|
// return this.linkedPeers;
|
||||||
|
// //}
|
||||||
//}
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
public void addIncomingPeer(RNSPeer peer) {
|
public void addIncomingPeer(RNSPeer peer) {
|
||||||
this.incomingPeers.add(peer);
|
this.incomingPeers.add(peer);
|
||||||
@ -635,37 +637,20 @@ public class RNSNetwork {
|
|||||||
if (nonNull(peer.getPeerLink())) {
|
if (nonNull(peer.getPeerLink())) {
|
||||||
peer.getPeerLink().teardown();
|
peer.getPeerLink().teardown();
|
||||||
}
|
}
|
||||||
this.incomingPeers.remove(peer);
|
var p = this.incomingPeers.remove(this.incomingPeers.indexOf(peer));
|
||||||
this.immutableIncomingPeers = List.copyOf(this.incomingPeers);
|
this.immutableIncomingPeers = List.copyOf(this.incomingPeers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RNSPeer> getIncomingPeers() {
|
// note: we already have a lobok getter for this
|
||||||
return this.incomingPeers;
|
//public List<RNSPeer> getIncomingPeers() {
|
||||||
}
|
// return this.incomingPeers;
|
||||||
|
//}
|
||||||
public List<RNSPeer> getImmutableIncomingPeers() {
|
//public List<RNSPeer> getImmutableIncomingPeers() {
|
||||||
return this.immutableIncomingPeers;
|
// return this.immutableIncomingPeers;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// TODO, methods for: getAvailablePeer
|
// TODO, methods for: getAvailablePeer
|
||||||
|
|
||||||
// maintenance
|
|
||||||
//public void removePeer(RNSPeer peer) {
|
|
||||||
// synchronized(this) {
|
|
||||||
// List<RNSPeer> peerList = this.linkedPeers;
|
|
||||||
// log.info("removing peer {} on peer shutdown", peer);
|
|
||||||
// peerList.remove(peer);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public void pingPeer(RNSPeer peer) {
|
|
||||||
// if (nonNull(peer)) {
|
|
||||||
// peer.pingRemote();
|
|
||||||
// } else {
|
|
||||||
// log.error("peer argument is null");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
private Boolean isUnreachable(RNSPeer peer) {
|
private Boolean isUnreachable(RNSPeer peer) {
|
||||||
var result = peer.getDeleteMe();
|
var result = peer.getDeleteMe();
|
||||||
var now = Instant.now();
|
var now = Instant.now();
|
||||||
@ -693,7 +678,7 @@ public class RNSNetwork {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RNSPeer> incomingNonActivePeers() {
|
public List<RNSPeer> getNonActiveIncomingPeers() {
|
||||||
var ips = getIncomingPeers();
|
var ips = getIncomingPeers();
|
||||||
List<RNSPeer> result = Collections.synchronizedList(new ArrayList<>());
|
List<RNSPeer> result = Collections.synchronizedList(new ArrayList<>());
|
||||||
Link pl;
|
Link pl;
|
||||||
@ -712,76 +697,74 @@ public class RNSNetwork {
|
|||||||
|
|
||||||
//@Synchronized
|
//@Synchronized
|
||||||
public void prunePeers() throws DataException {
|
public void prunePeers() throws DataException {
|
||||||
// run periodically (by the Controller)
|
|
||||||
var peerList = getLinkedPeers();
|
|
||||||
var incomingPeerList = getIncomingPeers();
|
|
||||||
log.info("number of links (linkedPeers / incomingPeers) before prunig: {}, {}", peerList.size(),
|
|
||||||
incomingPeerList.size());
|
|
||||||
// prune initiator peers
|
// prune initiator peers
|
||||||
List<RNSPeer> lps = getLinkedPeers();
|
//var peerList = getImmutableLinkedPeers();
|
||||||
for (RNSPeer p : lps) {
|
var initiatorPeerList = getImmutableLinkedPeers();
|
||||||
var pLink = p.getPeerLink();
|
var initiatorActivePeerList = getActiveImmutableLinkedPeers();
|
||||||
if (nonNull(pLink)) {
|
var incomingPeerList = getImmutableIncomingPeers();
|
||||||
log.info("peer link: {}, status: {}", pLink, pLink.getStatus());
|
var numActiveIncomingPeers = incomingPeerList.size() - getNonActiveIncomingPeers().size();
|
||||||
if (pLink.getStatus() == ACTIVE) {
|
log.info("number of links (linkedPeers (active) / incomingPeers (active) before prunig: {} ({}), {} ({})",
|
||||||
|
initiatorPeerList.size(), getActiveImmutableLinkedPeers().size(),
|
||||||
|
incomingPeerList.size(), numActiveIncomingPeers);
|
||||||
|
for (RNSPeer p: initiatorActivePeerList) {
|
||||||
|
var pLink = p.getOrInitPeerLink();
|
||||||
p.pingRemote();
|
p.pingRemote();
|
||||||
}
|
}
|
||||||
|
for (RNSPeer p : initiatorPeerList) {
|
||||||
|
var pLink = p.getPeerLink();
|
||||||
|
if (nonNull(pLink)) {
|
||||||
if (p.getPeerTimedOut()) {
|
if (p.getPeerTimedOut()) {
|
||||||
|
// options: keep in case peer reconnects or remove => we'll remove it
|
||||||
|
removeLinkedPeer(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pLink.getStatus() == ACTIVE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((pLink.getStatus() == CLOSED) || (p.getDeleteMe())) {
|
||||||
|
removeLinkedPeer(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pLink.getStatus() == PENDING) {
|
||||||
|
pLink.teardown();
|
||||||
|
removeLinkedPeer(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// prune non-initiator peers
|
||||||
|
List<RNSPeer> inaps = getNonActiveIncomingPeers();
|
||||||
|
incomingPeerList = this.incomingPeers;
|
||||||
|
for (RNSPeer p: incomingPeerList) {
|
||||||
|
var pLink = p.getOrInitPeerLink();
|
||||||
|
if (nonNull(pLink) && (pLink.getStatus() == ACTIVE)) {
|
||||||
|
// make false active links to timeout (and teardown in timeout callback)
|
||||||
|
// note: actual removal of peer happens on the following pruning run.
|
||||||
|
p.pingRemote();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (RNSPeer p: inaps) {
|
||||||
|
var pLink = p.getPeerLink();
|
||||||
|
if (nonNull(pLink)) {
|
||||||
|
// could be eg. PENDING
|
||||||
pLink.teardown();
|
pLink.teardown();
|
||||||
}
|
}
|
||||||
|
removeIncomingPeer(p);
|
||||||
}
|
}
|
||||||
}
|
initiatorPeerList = getImmutableLinkedPeers();
|
||||||
//Link pLink;
|
initiatorActivePeerList = getActiveImmutableLinkedPeers();
|
||||||
//LinkStatus lStatus;
|
incomingPeerList = getImmutableIncomingPeers();
|
||||||
//var now = Instant.now();
|
numActiveIncomingPeers = incomingPeerList.size() - getNonActiveIncomingPeers().size();
|
||||||
//for (RNSPeer p: peerList) {
|
log.info("number of links (linkedPeers (active) / incomingPeers (active) after prunig: {} ({}), {} ({})",
|
||||||
// pLink = p.getPeerLink();
|
initiatorPeerList.size(), getActiveImmutableLinkedPeers().size(),
|
||||||
// var peerLastAccessTimestamp = p.getLastAccessTimestamp();
|
incomingPeerList.size(), numActiveIncomingPeers);
|
||||||
// var peerLastPingResponseReceived = p.getLastPingResponseReceived();
|
|
||||||
// log.info("peerLink: {}, status: {}", pLink, pLink.getStatus());
|
|
||||||
// log.info("prunePeers - pLink: {}, destinationHash: {}",
|
|
||||||
// pLink, Hex.encodeHexString(p.getDestinationHash()));
|
|
||||||
// log.debug("peer: {}", p);
|
|
||||||
// if (nonNull(pLink)) {
|
|
||||||
// if ((p.getPeerTimedOut()) && (peerLastPingResponseReceived.isBefore(now.minusMillis(LINK_UNREACHABLE_TIMEOUT)))) {
|
|
||||||
// // close peer link for now
|
|
||||||
// pLink.teardown();
|
|
||||||
// }
|
|
||||||
// lStatus = pLink.getStatus();
|
|
||||||
// log.info("Link {} status: {}", pLink, lStatus);
|
|
||||||
// // lStatus in: PENDING, HANDSHAKE, ACTIVE, STALE, CLOSED
|
|
||||||
// if ((lStatus == STALE) || (pLink.getTeardownReason() == TIMEOUT) || (isUnreachable(p))) {
|
|
||||||
// //p.shutdown();
|
|
||||||
// //peerList.remove(p);
|
|
||||||
// removeLinkedPeer(p);
|
|
||||||
// } else if (lStatus == HANDSHAKE) {
|
|
||||||
// // stuck in handshake state (do we need to shutdown/remove it?)
|
|
||||||
// log.info("peer status HANDSHAKE");
|
|
||||||
// //p.shutdown();
|
|
||||||
// //peerList.remove(p);
|
|
||||||
// removeLinkedPeer(p);
|
|
||||||
// }
|
|
||||||
// // either reach peer or disable link
|
|
||||||
// p.pingRemote();
|
|
||||||
// } else {
|
|
||||||
// if (peerLastPingResponseReceived.isBefore(now.minusMillis(LINK_UNREACHABLE_TIMEOUT))) {
|
|
||||||
// //peerList.remove(p);
|
|
||||||
// removeLinkedPeer(p);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
List<RNSPeer> inaps = incomingNonActivePeers();
|
|
||||||
//log.info("number of inactive incoming peers: {}", inaps.size());
|
|
||||||
for (RNSPeer p: inaps) {
|
|
||||||
incomingPeerList.remove(incomingPeerList.indexOf(p));
|
|
||||||
}
|
|
||||||
log.info("number of links (linkedPeers / incomingPeers) after prunig: {}, {}", peerList.size(),
|
|
||||||
incomingPeerList.size());
|
|
||||||
maybeAnnounce(getBaseDestination());
|
maybeAnnounce(getBaseDestination());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void maybeAnnounce(Destination d) {
|
public void maybeAnnounce(Destination d) {
|
||||||
if (getLinkedPeers().size() < MIN_DESIRED_PEERS) {
|
var activePeers = getActiveImmutableLinkedPeers().size();
|
||||||
|
if (activePeers <= MIN_DESIRED_PEERS) {
|
||||||
|
log.info("Active peers ({}) <= desired peers ({}). Announcing", activePeers, MIN_DESIRED_PEERS);
|
||||||
d.announce();
|
d.announce();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -798,7 +781,7 @@ public class RNSNetwork {
|
|||||||
var pLink = p.getPeerLink();
|
var pLink = p.getPeerLink();
|
||||||
if (nonNull(pLink)) {
|
if (nonNull(pLink)) {
|
||||||
if (Arrays.equals(pLink.getDestination().getHash(),link.getDestination().getHash())) {
|
if (Arrays.equals(pLink.getDestination().getHash(),link.getDestination().getHash())) {
|
||||||
log.info("found peer matching destinationHash: {}", Hex.encodeHexString(link.getDestination().getHash()));
|
log.info("found peer matching destinationHash: {}", encodeHexString(link.getDestination().getHash()));
|
||||||
peer = p;
|
peer = p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -813,7 +796,7 @@ public class RNSNetwork {
|
|||||||
RNSPeer peer = null;
|
RNSPeer peer = null;
|
||||||
for (RNSPeer p : lps) {
|
for (RNSPeer p : lps) {
|
||||||
if (Arrays.equals(p.getDestinationHash(), dhash)) {
|
if (Arrays.equals(p.getDestinationHash(), dhash)) {
|
||||||
log.info("found peer matching destinationHash: {}", Hex.encodeHexString(dhash));
|
log.info("found peer matching destinationHash: {}", encodeHexString(dhash));
|
||||||
peer = p;
|
peer = p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -832,6 +815,14 @@ public class RNSNetwork {
|
|||||||
return Settings.getInstance().isTestNet() ? TESTNET_MESSAGE_MAGIC : MAINNET_MESSAGE_MAGIC;
|
return Settings.getInstance().isTestNet() ? TESTNET_MESSAGE_MAGIC : MAINNET_MESSAGE_MAGIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOurNodeId() {
|
||||||
|
return this.serverIdentity.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] getOurPublicKey() {
|
||||||
|
return this.serverIdentity.getPublicKey();
|
||||||
|
}
|
||||||
|
|
||||||
// Network methods Reticulum implementation
|
// Network methods Reticulum implementation
|
||||||
|
|
||||||
/** Builds either (legacy) HeightV2Message or (newer) BlockSummariesV2Message, depending on peer version.
|
/** Builds either (legacy) HeightV2Message or (newer) BlockSummariesV2Message, depending on peer version.
|
||||||
|
@ -7,9 +7,7 @@ import static java.util.Objects.isNull;
|
|||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
//import java.io.IOException;
|
//import java.io.IOException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
//import io.reticulum.Reticulum;
|
//import io.reticulum.Reticulum;
|
||||||
//import org.qortal.network.RNSNetwork;
|
//import org.qortal.network.RNSNetwork;
|
||||||
@ -53,8 +51,7 @@ import org.qortal.utils.NTP;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -73,6 +70,7 @@ import lombok.AccessLevel;
|
|||||||
//import org.qortal.network.message.Message;
|
//import org.qortal.network.message.Message;
|
||||||
//import org.qortal.network.message.MessageException;
|
//import org.qortal.network.message.MessageException;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.LongAdder;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -99,17 +97,17 @@ public class RNSPeer {
|
|||||||
int sendStreamId = 0;
|
int sendStreamId = 0;
|
||||||
private Boolean isInitiator;
|
private Boolean isInitiator;
|
||||||
private Boolean deleteMe = false;
|
private Boolean deleteMe = false;
|
||||||
private Boolean isVacant = true;
|
//private Boolean isVacant = true;
|
||||||
private Long lastPacketRtt = null;
|
private Long lastPacketRtt = null;
|
||||||
private byte[] emptyBuffer = {0,0,0,0,0};
|
//private byte[] emptyBuffer = {0,0,0,0,0};
|
||||||
|
|
||||||
private Double requestResponseProgress;
|
private Double requestResponseProgress;
|
||||||
@Setter(AccessLevel.PACKAGE) private Boolean peerTimedOut = false;
|
@Setter(AccessLevel.PACKAGE) private Boolean peerTimedOut = false;
|
||||||
|
|
||||||
// for qortal networking
|
// for qortal networking
|
||||||
private static final int RESPONSE_TIMEOUT = 3000; // [ms]
|
private static final int RESPONSE_TIMEOUT = 3000; // [ms]
|
||||||
private static final int PING_INTERVAL = 34_000; // [ms]
|
private static final int PING_INTERVAL = 55_000; // [ms]
|
||||||
private static final long LINK_PING_INTERVAL = 34 * 1000L; // ms
|
private static final long LINK_PING_INTERVAL = 55 * 1000L; // ms
|
||||||
private byte[] messageMagic; // set in message creating classes
|
private byte[] messageMagic; // set in message creating classes
|
||||||
private Long lastPing = null; // last (packet) ping roundtrip time [ms]
|
private Long lastPing = null; // last (packet) ping roundtrip time [ms]
|
||||||
private Long lastPingSent = null; // time last (packet) ping was sent, or null if not started.
|
private Long lastPingSent = null; // time last (packet) ping was sent, or null if not started.
|
||||||
@ -117,11 +115,13 @@ public class RNSPeer {
|
|||||||
private Map<Integer, BlockingQueue<Message>> replyQueues;
|
private Map<Integer, BlockingQueue<Message>> replyQueues;
|
||||||
private LinkedBlockingQueue<Message> pendingMessages;
|
private LinkedBlockingQueue<Message> pendingMessages;
|
||||||
private boolean syncInProgress = false;
|
private boolean syncInProgress = false;
|
||||||
|
private RNSPeerData peerData = null;
|
||||||
|
private long linkEstablishedTime = -1L; // equivalent of (tcpip) Peer 'handshakeComplete'
|
||||||
// Versioning
|
// Versioning
|
||||||
public static final Pattern VERSION_PATTERN = Pattern.compile(Controller.VERSION_PREFIX
|
public static final Pattern VERSION_PATTERN = Pattern.compile(Controller.VERSION_PREFIX
|
||||||
+ "(\\d{1,3})\\.(\\d{1,5})\\.(\\d{1,5})");
|
+ "(\\d{1,3})\\.(\\d{1,5})\\.(\\d{1,5})");
|
||||||
|
/* Pending signature requests */
|
||||||
private RNSPeerData peerData = null;
|
private List<byte[]> pendingSignatureRequests = Collections.synchronizedList(new ArrayList<>());
|
||||||
/**
|
/**
|
||||||
* Latest block info as reported by peer.
|
* Latest block info as reported by peer.
|
||||||
*/
|
*/
|
||||||
@ -134,6 +134,20 @@ public class RNSPeer {
|
|||||||
* Last time we detected this peer as TOO_DIVERGENT
|
* Last time we detected this peer as TOO_DIVERGENT
|
||||||
*/
|
*/
|
||||||
private Long lastTooDivergentTime;
|
private Long lastTooDivergentTime;
|
||||||
|
///**
|
||||||
|
// * Known starting sequences for data received over buffer
|
||||||
|
// */
|
||||||
|
//private byte[] SEQ_REQUEST_CONFIRM_ID = new byte[]{0x53, 0x52, 0x65, 0x71, 0x43, 0x49, 0x44}; // SReqCID
|
||||||
|
//private byte[] SEQ_RESPONSE_CONFIRM_ID = new byte[]{0x53, 0x52, 0x65, 0x73, 0x70, 0x43, 0x49, 0x44}; // SRespCID
|
||||||
|
|
||||||
|
// Message stats
|
||||||
|
private static class MessageStats {
|
||||||
|
public final LongAdder count = new LongAdder();
|
||||||
|
public final LongAdder totalBytes = new LongAdder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<MessageType, RNSPeer.MessageStats> receivedMessageStats = new ConcurrentHashMap<>();
|
||||||
|
private final Map<MessageType, RNSPeer.MessageStats> sentMessageStats = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for initiator peers
|
* Constructor for initiator peers
|
||||||
@ -144,7 +158,7 @@ public class RNSPeer {
|
|||||||
initPeerLink();
|
initPeerLink();
|
||||||
//setCreationTimestamp(System.currentTimeMillis());
|
//setCreationTimestamp(System.currentTimeMillis());
|
||||||
this.creationTimestamp = Instant.now();
|
this.creationTimestamp = Instant.now();
|
||||||
this.isVacant = true;
|
//this.isVacant = true;
|
||||||
this.replyQueues = new ConcurrentHashMap<>();
|
this.replyQueues = new ConcurrentHashMap<>();
|
||||||
this.pendingMessages = new LinkedBlockingQueue<>();
|
this.pendingMessages = new LinkedBlockingQueue<>();
|
||||||
this.peerData = new RNSPeerData(dhash);
|
this.peerData = new RNSPeerData(dhash);
|
||||||
@ -164,7 +178,7 @@ public class RNSPeer {
|
|||||||
this.lastAccessTimestamp = Instant.now();
|
this.lastAccessTimestamp = Instant.now();
|
||||||
this.lastLinkProbeTimestamp = null;
|
this.lastLinkProbeTimestamp = null;
|
||||||
this.isInitiator = false;
|
this.isInitiator = false;
|
||||||
this.isVacant = false;
|
//this.isVacant = false;
|
||||||
|
|
||||||
//this.peerLink.setLinkEstablishedCallback(this::linkEstablished);
|
//this.peerLink.setLinkEstablishedCallback(this::linkEstablished);
|
||||||
//this.peerLink.setLinkClosedCallback(this::linkClosed);
|
//this.peerLink.setLinkClosedCallback(this::linkClosed);
|
||||||
@ -206,7 +220,7 @@ public class RNSPeer {
|
|||||||
public BufferedRWPair getOrInitPeerBuffer() {
|
public BufferedRWPair getOrInitPeerBuffer() {
|
||||||
var channel = this.peerLink.getChannel();
|
var channel = this.peerLink.getChannel();
|
||||||
if (nonNull(this.peerBuffer)) {
|
if (nonNull(this.peerBuffer)) {
|
||||||
log.info("peerBuffer exists: {}, link status: {}", this.peerBuffer, this.peerLink.getStatus());
|
//log.info("peerBuffer exists: {}, link status: {}", this.peerBuffer, this.peerLink.getStatus());
|
||||||
try {
|
try {
|
||||||
log.trace("peerBuffer exists: {}, link status: {}", this.peerBuffer, this.peerLink.getStatus());
|
log.trace("peerBuffer exists: {}, link status: {}", this.peerBuffer, this.peerLink.getStatus());
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
@ -223,8 +237,7 @@ public class RNSPeer {
|
|||||||
log.info("creating buffer - peerLink status: {}, channel: {}", this.peerLink.getStatus(), channel);
|
log.info("creating buffer - peerLink status: {}, channel: {}", this.peerLink.getStatus(), channel);
|
||||||
this.peerBuffer = Buffer.createBidirectionalBuffer(receiveStreamId, sendStreamId, channel, this::peerBufferReady);
|
this.peerBuffer = Buffer.createBidirectionalBuffer(receiveStreamId, sendStreamId, channel, this::peerBufferReady);
|
||||||
}
|
}
|
||||||
//return getPeerBuffer();
|
return getPeerBuffer();
|
||||||
return this.peerBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Link getOrInitPeerLink() {
|
public Link getOrInitPeerLink() {
|
||||||
@ -269,9 +282,10 @@ public class RNSPeer {
|
|||||||
|
|
||||||
/** Link callbacks */
|
/** Link callbacks */
|
||||||
public void linkEstablished(Link link) {
|
public void linkEstablished(Link link) {
|
||||||
|
this.linkEstablishedTime = System.currentTimeMillis();
|
||||||
link.setLinkClosedCallback(this::linkClosed);
|
link.setLinkClosedCallback(this::linkClosed);
|
||||||
log.info("peerLink {} established (link: {}) with peer: hash - {}, link destination hash: {}",
|
log.info("peerLink {} established (link: {}) with peer: hash - {}, link destination hash: {}",
|
||||||
peerLink, link, encodeHexString(destinationHash),
|
encodeHexString(peerLink.getLinkId()), encodeHexString(link.getLinkId()), encodeHexString(destinationHash),
|
||||||
encodeHexString(link.getDestination().getHash()));
|
encodeHexString(link.getDestination().getHash()));
|
||||||
if (isInitiator) {
|
if (isInitiator) {
|
||||||
startPings();
|
startPings();
|
||||||
@ -286,12 +300,12 @@ public class RNSPeer {
|
|||||||
} else if (link.getTeardownReason() == INITIATOR_CLOSED) {
|
} else if (link.getTeardownReason() == INITIATOR_CLOSED) {
|
||||||
log.info("Link closed callback: The initiator closed the link");
|
log.info("Link closed callback: The initiator closed the link");
|
||||||
log.info("peerLink {} closed (link: {}), link destination hash: {}",
|
log.info("peerLink {} closed (link: {}), link destination hash: {}",
|
||||||
peerLink, link, encodeHexString(link.getDestination().getHash()));
|
encodeHexString(peerLink.getLinkId()), encodeHexString(link.getLinkId()), encodeHexString(link.getDestination().getHash()));
|
||||||
this.peerBuffer = null;
|
this.peerBuffer = null;
|
||||||
} else if (link.getTeardownReason() == DESTINATION_CLOSED) {
|
} else if (link.getTeardownReason() == DESTINATION_CLOSED) {
|
||||||
log.info("Link closed callback: The link was closed by the peer, removing peer");
|
log.info("Link closed callback: The link was closed by the peer, removing peer");
|
||||||
log.info("peerLink {} closed (link: {}), link destination hash: {}",
|
log.info("peerLink {} closed (link: {}), link destination hash: {}",
|
||||||
peerLink, link, encodeHexString(link.getDestination().getHash()));
|
encodeHexString(peerLink.getLinkId()), encodeHexString(link.getLinkId()), encodeHexString(link.getDestination().getHash()));
|
||||||
this.peerBuffer = null;
|
this.peerBuffer = null;
|
||||||
} else {
|
} else {
|
||||||
log.info("Link closed callback");
|
log.info("Link closed callback");
|
||||||
@ -342,15 +356,27 @@ public class RNSPeer {
|
|||||||
//log.trace("peerBufferReady - data bytes: {}", data.length);
|
//log.trace("peerBufferReady - data bytes: {}", data.length);
|
||||||
this.lastAccessTimestamp = Instant.now();
|
this.lastAccessTimestamp = Instant.now();
|
||||||
|
|
||||||
if (ByteBuffer.wrap(data, 0, emptyBuffer.length).equals(ByteBuffer.wrap(emptyBuffer, 0, emptyBuffer.length))) {
|
//if (ByteBuffer.wrap(data, 0, emptyBuffer.length).equals(ByteBuffer.wrap(emptyBuffer, 0, emptyBuffer.length))) {
|
||||||
log.info("peerBufferReady - empty buffer detected (length: {})", data.length);
|
// log.info("peerBufferReady - empty buffer detected (length: {})", data.length);
|
||||||
}
|
//}
|
||||||
else {
|
//else {
|
||||||
|
//if (Arrays.equals(SEQ_REQUEST_CONFIRM_ID, Arrays.copyOfRange(data, 0, SEQ_REQUEST_CONFIRM_ID.length))) {
|
||||||
|
// // a non-initiator peer requested to confirm sending of a packet
|
||||||
|
// var messageId = subarray(data, SEQ_REQUEST_CONFIRM_ID.length + 1, data.length);
|
||||||
|
// log.info("received request to confirm message id, id: {}", messageId);
|
||||||
|
// var confirmData = concatArrays(SEQ_RESPONSE_CONFIRM_ID, "::",data.getBytes(UTF_8), messageId.getBytes(UTF_8));
|
||||||
|
// this.peerBuffer.write(confirmData);
|
||||||
|
// this.peerBuffer.flush();
|
||||||
|
//} else if (Arrays.equals(SEQ_RESPONSE_CONFIRM_ID, Arrays.copyOfRange(data, 0, SEQ_RESPONSE_CONFIRM_ID.lenth))) {
|
||||||
|
// // an initiator peer receiving the confirmation
|
||||||
|
// var messageId = subarray(data, SEQ_RESPONSE_CONFIRM_ID.length + 1, data.length);
|
||||||
|
// this.replyQueues.remove(messageId);
|
||||||
|
//} else {
|
||||||
try {
|
try {
|
||||||
//log.info("***> creating message from {} bytes", data.length);
|
//log.info("***> creating message from {} bytes", data.length);
|
||||||
Message message = Message.fromByteBuffer(bb);
|
Message message = Message.fromByteBuffer(bb);
|
||||||
//log.info("*=> type {} message received ({} bytes): {}", message.getType(), data.length, message);
|
//log.info("*=> type {} message received ({} bytes): {}", message.getType(), data.length, message);
|
||||||
log.info("*=> type {} message received ({} bytes)", message.getType(), data.length);
|
log.info("*=> type {} message received ({} bytes, id: {})", message.getType(), data.length, message.getId());
|
||||||
|
|
||||||
// Handle message based on type
|
// Handle message based on type
|
||||||
switch (message.getType()) {
|
switch (message.getType()) {
|
||||||
@ -365,12 +391,12 @@ public class RNSPeer {
|
|||||||
this.lastPingResponseReceived = Instant.now();
|
this.lastPingResponseReceived = Instant.now();
|
||||||
if (isFalse(this.isInitiator)) {
|
if (isFalse(this.isInitiator)) {
|
||||||
onPingMessage(this, message);
|
onPingMessage(this, message);
|
||||||
// Note: buffer flush done in onPingMessage method
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PONG:
|
case PONG:
|
||||||
//log.info("PONG received");
|
log.trace("PONG received");
|
||||||
|
addToQueue(message); // as response in blocking queue for ping getResponse
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Do we need this ? (no need to relay peer list...)
|
// Do we need this ? (no need to relay peer list...)
|
||||||
@ -381,45 +407,44 @@ public class RNSPeer {
|
|||||||
case BLOCK_SUMMARIES:
|
case BLOCK_SUMMARIES:
|
||||||
// from Synchronizer
|
// from Synchronizer
|
||||||
addToQueue(message);
|
addToQueue(message);
|
||||||
break;
|
|
||||||
|
|
||||||
case BLOCK_SUMMARIES_V2:
|
case BLOCK_SUMMARIES_V2:
|
||||||
// from Synchronizer
|
// from Synchronizer
|
||||||
addToQueue(message);
|
addToQueue(message);
|
||||||
break;
|
|
||||||
|
|
||||||
case SIGNATURES:
|
case SIGNATURES:
|
||||||
// from Synchronizer
|
// from Synchronizer
|
||||||
addToQueue(message);
|
addToQueue(message);
|
||||||
break;
|
|
||||||
|
|
||||||
case BLOCK:
|
case BLOCK:
|
||||||
// from Synchronizer
|
// from Synchronizer
|
||||||
addToQueue(message);
|
addToQueue(message);
|
||||||
break;
|
|
||||||
|
|
||||||
case BLOCK_V2:
|
case BLOCK_V2:
|
||||||
// from Synchronizer
|
// from Synchronizer
|
||||||
addToQueue(message);
|
addToQueue(message);
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.info("default - type {} message received ({} bytes)", message.getType(), data.length);
|
log.info("default - type {} message received ({} bytes)", message.getType(), data.length);
|
||||||
// Bump up to controller for possible action
|
// Bump up to controller for possible action
|
||||||
//Controller.getInstance().onNetworkMessage(peer, message);
|
addToQueue(message);
|
||||||
Controller.getInstance().onRNSNetworkMessage(this, message);
|
Controller.getInstance().onRNSNetworkMessage(this, message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (MessageException e) {
|
} catch (MessageException e) {
|
||||||
//log.error("{} from peer {}", e.getMessage(), this);
|
//log.error("{} from peer {}", e.getMessage(), this);
|
||||||
log.error("{} from peer {}", e, this);
|
log.error("{} from peer {}, closing link", e, this);
|
||||||
log.info("{} from peer {}", e, this);
|
//log.info("{} from peer {}", e, this);
|
||||||
}
|
// don't take any chances:
|
||||||
|
// can happen if link is closed by peer in which case we close this side of the link
|
||||||
|
this.peerData.setLastMisbehaved(NTP.getTime());
|
||||||
|
shutdown();
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* we need to queue all incomming messages that follow request/response
|
* we need to queue all incoming messages that follow request/response
|
||||||
* with explicit handling of the response message.
|
* with explicit handling of the response message.
|
||||||
*/
|
*/
|
||||||
public void addToQueue(Message message) {
|
public void addToQueue(Message message) {
|
||||||
@ -431,7 +456,8 @@ public class RNSPeer {
|
|||||||
if (queue != null) {
|
if (queue != null) {
|
||||||
// Adding message to queue will unblock thread waiting for response
|
// Adding message to queue will unblock thread waiting for response
|
||||||
this.replyQueues.get(message.getId()).add(message);
|
this.replyQueues.get(message.getId()).add(message);
|
||||||
// Consumed elsewhere
|
// Consumed elsewhere (getResponseWithTimeout)
|
||||||
|
log.info("addToQueue - queue size: {}, message type: {} (id: {})", queue.size(), message.getType(), message.getId());
|
||||||
}
|
}
|
||||||
else if (!this.pendingMessages.offer(message)) {
|
else if (!this.pendingMessages.offer(message)) {
|
||||||
log.info("[{}] Busy, no room to queue message from peer {} - discarding",
|
log.info("[{}] Busy, no room to queue message from peer {} - discarding",
|
||||||
@ -491,18 +517,24 @@ public class RNSPeer {
|
|||||||
} else {
|
} else {
|
||||||
rttString = String.format("%d milliseconds", rtt);
|
rttString = String.format("%d milliseconds", rtt);
|
||||||
}
|
}
|
||||||
|
if (getIsInitiator()) {
|
||||||
|
// reporting round trip time in one direction is enough
|
||||||
log.info("Valid reply received from {}, round-trip time is {}",
|
log.info("Valid reply received from {}, round-trip time is {}",
|
||||||
encodeHexString(receipt.getDestination().getHash()), rttString);
|
encodeHexString(receipt.getDestination().getHash()), rttString);
|
||||||
|
}
|
||||||
this.lastAccessTimestamp = Instant.now();
|
this.lastAccessTimestamp = Instant.now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void packetTimedOut(PacketReceipt receipt) {
|
public void packetTimedOut(PacketReceipt receipt) {
|
||||||
log.info("packet timed out, receipt status: {}", receipt.getStatus());
|
//log.info("packet timed out, receipt status: {}", receipt.getStatus());
|
||||||
if (receipt.getStatus() == PacketReceiptStatus.FAILED) {
|
if (receipt.getStatus() == PacketReceiptStatus.FAILED) {
|
||||||
|
log.info("packet timed out, receipt status: {}", PacketReceiptStatus.FAILED);
|
||||||
this.peerTimedOut = true;
|
this.peerTimedOut = true;
|
||||||
this.peerLink.teardown();
|
this.peerLink.teardown();
|
||||||
}
|
}
|
||||||
|
//this.peerTimedOut = true;
|
||||||
|
//this.peerLink.teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Link Request callbacks */
|
/** Link Request callbacks */
|
||||||
@ -532,27 +564,12 @@ public class RNSPeer {
|
|||||||
log.debug("Resource transfer complete");
|
log.debug("Resource transfer complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
///**
|
|
||||||
// * Send a message using the peer buffer
|
|
||||||
// */
|
|
||||||
//public Message getResponse(Message message) throws InterruptedException {
|
|
||||||
// var peerBuffer = getOrInitPeerBuffer();
|
|
||||||
//
|
|
||||||
// //// send message
|
|
||||||
// //peerBuffer.write(...);
|
|
||||||
// //peerBuffer.flush();
|
|
||||||
//
|
|
||||||
// // receive - peerBufferReady callback result
|
|
||||||
//}
|
|
||||||
|
|
||||||
/** Utility methods */
|
/** Utility methods */
|
||||||
public void pingRemote() {
|
public void pingRemote() {
|
||||||
var link = this.peerLink;
|
var link = this.peerLink;
|
||||||
//if (nonNull(link) & (isFalse(link.isInitiator()))) {
|
|
||||||
//if (nonNull(link) & link.isInitiator()) {
|
|
||||||
if (nonNull(link)) {
|
if (nonNull(link)) {
|
||||||
if (peerLink.getStatus() == ACTIVE) {
|
if (peerLink.getStatus() == ACTIVE) {
|
||||||
log.info("pinging remote (direct, 1 packet): {}", link);
|
log.info("pinging remote (direct, 1 packet): {}", encodeHexString(link.getLinkId()));
|
||||||
var data = "ping".getBytes(UTF_8);
|
var data = "ping".getBytes(UTF_8);
|
||||||
link.setPacketCallback(this::linkPacketReceived);
|
link.setPacketCallback(this::linkPacketReceived);
|
||||||
Packet pingPacket = new Packet(link, data);
|
Packet pingPacket = new Packet(link, data);
|
||||||
@ -584,7 +601,7 @@ public class RNSPeer {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
PongMessage pongMessage = new PongMessage();
|
PongMessage pongMessage = new PongMessage();
|
||||||
pongMessage.setId(message.getId()); // use the ping message id
|
pongMessage.setId(message.getId()); // use the ping message id (for ping getResponse)
|
||||||
this.peerBuffer.write(pongMessage.toBytes());
|
this.peerBuffer.write(pongMessage.toBytes());
|
||||||
this.peerBuffer.flush();
|
this.peerBuffer.flush();
|
||||||
this.lastAccessTimestamp = Instant.now();
|
this.lastAccessTimestamp = Instant.now();
|
||||||
@ -607,7 +624,7 @@ public class RNSPeer {
|
|||||||
* @throws InterruptedException if interrupted while waiting
|
* @throws InterruptedException if interrupted while waiting
|
||||||
*/
|
*/
|
||||||
public Message getResponse(Message message) throws InterruptedException {
|
public Message getResponse(Message message) throws InterruptedException {
|
||||||
log.info("RNSPingTask action - pinging peer {}", encodeHexString(getDestinationHash()));
|
//log.info("RNSPingTask action - pinging peer {}", encodeHexString(getDestinationHash()));
|
||||||
return getResponseWithTimeout(message, RESPONSE_TIMEOUT);
|
return getResponseWithTimeout(message, RESPONSE_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,7 +644,6 @@ public class RNSPeer {
|
|||||||
*/
|
*/
|
||||||
public Message getResponseWithTimeout(Message message, int timeout) throws InterruptedException {
|
public Message getResponseWithTimeout(Message message, int timeout) throws InterruptedException {
|
||||||
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<>(1);
|
BlockingQueue<Message> blockingQueue = new ArrayBlockingQueue<>(1);
|
||||||
// TODO: implement equivalent of Peer class...
|
|
||||||
// Assign random ID to this message
|
// Assign random ID to this message
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int id;
|
int id;
|
||||||
@ -638,17 +654,20 @@ public class RNSPeer {
|
|||||||
// If putIfAbsent() doesn't return null, then this ID is already taken
|
// If putIfAbsent() doesn't return null, then this ID is already taken
|
||||||
} while (this.replyQueues.putIfAbsent(id, blockingQueue) != null);
|
} while (this.replyQueues.putIfAbsent(id, blockingQueue) != null);
|
||||||
message.setId(id);
|
message.setId(id);
|
||||||
|
//log.info("getResponse - before send {} message, random id is {}", message.getType(), id);
|
||||||
|
|
||||||
// Try to send message
|
// Try to send message
|
||||||
if (!this.sendMessageWithTimeout(message, timeout)) {
|
if (!this.sendMessageWithTimeout(message, timeout)) {
|
||||||
this.replyQueues.remove(id);
|
this.replyQueues.remove(id);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
//log.info("getResponse - after send");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return blockingQueue.poll(timeout, TimeUnit.MILLISECONDS);
|
return blockingQueue.poll(timeout, TimeUnit.MILLISECONDS);
|
||||||
} finally {
|
} finally {
|
||||||
this.replyQueues.remove(id);
|
this.replyQueues.remove(id);
|
||||||
|
//log.info("getResponse - regular - id removed from replyQueues");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,10 +679,16 @@ public class RNSPeer {
|
|||||||
*/
|
*/
|
||||||
public boolean sendMessageWithTimeout(Message message, int timeout) {
|
public boolean sendMessageWithTimeout(Message message, int timeout) {
|
||||||
try {
|
try {
|
||||||
|
// send the message
|
||||||
log.trace("Sending {} message with ID {} to peer {}", message.getType().name(), message.getId(), this);
|
log.trace("Sending {} message with ID {} to peer {}", message.getType().name(), message.getId(), this);
|
||||||
var peerBuffer = getOrInitPeerBuffer();
|
var peerBuffer = getOrInitPeerBuffer();
|
||||||
this.peerBuffer.write(message.toBytes());
|
this.peerBuffer.write(message.toBytes());
|
||||||
this.peerBuffer.flush();
|
this.peerBuffer.flush();
|
||||||
|
//// send a message to confirm receipt over the buffer
|
||||||
|
//var messageId = message.getId();
|
||||||
|
//var confirmData = concatArrays(SEQ_REQUEST_CONFIRM_ID,"::".getBytes(UTF_8), messageId.getBytes(UTF_8));
|
||||||
|
//this.peerBuffer.write(confirmData);
|
||||||
|
//this.peerBuffer.flush();
|
||||||
return true;
|
return true;
|
||||||
//} catch (InterruptedException e) {
|
//} catch (InterruptedException e) {
|
||||||
// // Send failure
|
// // Send failure
|
||||||
@ -709,8 +734,8 @@ public class RNSPeer {
|
|||||||
//@Synchronized
|
//@Synchronized
|
||||||
public boolean sendMessage(Message message) {
|
public boolean sendMessage(Message message) {
|
||||||
try {
|
try {
|
||||||
log.trace("Sending {} message with ID {} to peer {}", message.getType().name(), message.getId(), this);
|
log.trace("Sending {} message with ID {} to peer {}", message.getType().name(), message.getId(), this.toString());
|
||||||
log.info("Sending {} message with ID {} to peer {}", message.getType().name(), message.getId(), this);
|
//log.info("Sending {} message with ID {} to peer {}", message.getType().name(), message.getId(), this.toString());
|
||||||
var peerBuffer = getOrInitPeerBuffer();
|
var peerBuffer = getOrInitPeerBuffer();
|
||||||
peerBuffer.write(message.toBytes());
|
peerBuffer.write(message.toBytes());
|
||||||
peerBuffer.flush();
|
peerBuffer.flush();
|
||||||
@ -728,7 +753,7 @@ public class RNSPeer {
|
|||||||
|
|
||||||
protected void startPings() {
|
protected void startPings() {
|
||||||
log.trace("[{}] Enabling pings for peer {}",
|
log.trace("[{}] Enabling pings for peer {}",
|
||||||
peerLink.getDestination().getHexHash(), this);
|
peerLink.getDestination().getHexHash(), this.toString());
|
||||||
this.lastPingSent = NTP.getTime();
|
this.lastPingSent = NTP.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,4 +854,41 @@ public class RNSPeer {
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pending signature requests
|
||||||
|
public void addPendingSignatureRequest(byte[] signature) {
|
||||||
|
// Check if we already have this signature in the list
|
||||||
|
for (byte[] existingSignature : this.pendingSignatureRequests) {
|
||||||
|
if (Arrays.equals(existingSignature, signature )) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.pendingSignatureRequests.add(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePendingSignatureRequest(byte[] signature) {
|
||||||
|
Iterator iterator = this.pendingSignatureRequests.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
byte[] existingSignature = (byte[]) iterator.next();
|
||||||
|
if (Arrays.equals(existingSignature, signature)) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<byte[]> getPendingSignatureRequests() {
|
||||||
|
return this.pendingSignatureRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Details used by API
|
||||||
|
public long getConnectionEstablishedTime() {
|
||||||
|
return linkEstablishedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getConnectionAge() {
|
||||||
|
if (linkEstablishedTime > 0L) {
|
||||||
|
return System.currentTimeMillis() - linkEstablishedTime;
|
||||||
|
}
|
||||||
|
return linkEstablishedTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,8 @@ public class RNSPingTask implements Task {
|
|||||||
// Note: Even though getResponse would work, we can use
|
// Note: Even though getResponse would work, we can use
|
||||||
// peer.sendMessage(pingMessage) using Reticulum buffer instead.
|
// peer.sendMessage(pingMessage) using Reticulum buffer instead.
|
||||||
// More efficient and saves room for other request/response tasks.
|
// More efficient and saves room for other request/response tasks.
|
||||||
//peer.getResponse(pingMessage);
|
peer.getResponse(pingMessage);
|
||||||
peer.sendMessage(pingMessage);
|
//peer.sendMessage(pingMessage);
|
||||||
|
|
||||||
//// task is not over here (Reticulum is asynchronous)
|
//// task is not over here (Reticulum is asynchronous)
|
||||||
//peer.setLastPing(NTP.getTime() - now);
|
//peer.setLastPing(NTP.getTime() - now);
|
||||||
|
@ -614,12 +614,14 @@ public class Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Related to Reticulum networking
|
// Related to mesh networking
|
||||||
|
|
||||||
|
/** Preferred network: "tcpip" or "reticulum" */
|
||||||
|
private String preferredNetwork = "reticulum";
|
||||||
/** Maximum number of Reticulum peers allowed. */
|
/** Maximum number of Reticulum peers allowed. */
|
||||||
private int reticulumMaxPeers = 55;
|
private int reticulumMaxPeers = 55;
|
||||||
/** Minimum number of Reticulum peers desired. */
|
/** Minimum number of Reticulum peers desired. */
|
||||||
private int reticulumMinDesiredPeers = 3;
|
private int reticulumMinDesiredPeers = 8;
|
||||||
/** Maximum number of task executor network threads */
|
/** Maximum number of task executor network threads */
|
||||||
private int reticulumMaxNetworkThreadPoolSize = 89;
|
private int reticulumMaxNetworkThreadPoolSize = 89;
|
||||||
|
|
||||||
@ -1380,6 +1382,10 @@ public class Settings {
|
|||||||
return connectionPoolMonitorEnabled;
|
return connectionPoolMonitorEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPreferredNetwork () {
|
||||||
|
return this.preferredNetwork.toLowerCase(Locale.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
public int getReticulumMaxPeers() {
|
public int getReticulumMaxPeers() {
|
||||||
return this.reticulumMaxPeers;
|
return this.reticulumMaxPeers;
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ interfaces:
|
|||||||
# local IPv6 is enabled in your operating system, which
|
# local IPv6 is enabled in your operating system, which
|
||||||
# should be enabled by default in almost any OS. See
|
# should be enabled by default in almost any OS. See
|
||||||
# the Reticulum Manual for more configuration options.
|
# the Reticulum Manual for more configuration options.
|
||||||
#"Default Interface":
|
"Default Interface":
|
||||||
# type: AutoInterface
|
type: AutoInterface
|
||||||
# enabled: true
|
enabled: true
|
||||||
|
|
||||||
# This interface enables communication with a "backbone"
|
# This interface enables communication with a "backbone"
|
||||||
# server over TCP.
|
# server over TCP.
|
||||||
@ -76,7 +76,7 @@ interfaces:
|
|||||||
enabled: true
|
enabled: true
|
||||||
target_host: phantom.mobilefabrik.com
|
target_host: phantom.mobilefabrik.com
|
||||||
target_port: 4242
|
target_port: 4242
|
||||||
#network_name: qortal
|
network_name: qortal
|
||||||
|
|
||||||
# This interface turns this Reticulum instance into a
|
# This interface turns this Reticulum instance into a
|
||||||
# server other clients can connect to over TCP.
|
# server other clients can connect to over TCP.
|
||||||
@ -88,6 +88,6 @@ interfaces:
|
|||||||
# type: TCPServerInterface
|
# type: TCPServerInterface
|
||||||
# enabled: true
|
# enabled: true
|
||||||
# listen_ip: 0.0.0.0
|
# listen_ip: 0.0.0.0
|
||||||
# listen_port: 3434
|
# listen_port: 4242
|
||||||
# #network_name: qortal
|
# network_name: qortal
|
||||||
|
|
||||||
|
@ -64,9 +64,9 @@ interfaces:
|
|||||||
# local IPv6 is enabled in your operating system, which
|
# local IPv6 is enabled in your operating system, which
|
||||||
# should be enabled by default in almost any OS. See
|
# should be enabled by default in almost any OS. See
|
||||||
# the Reticulum Manual for more configuration options.
|
# the Reticulum Manual for more configuration options.
|
||||||
#"Default Interface":
|
"Default Interface":
|
||||||
# type: AutoInterface
|
type: AutoInterface
|
||||||
# enabled: true
|
enabled: true
|
||||||
|
|
||||||
# This interface enables communication with a "backbone"
|
# This interface enables communication with a "backbone"
|
||||||
# server over TCP.
|
# server over TCP.
|
||||||
@ -75,8 +75,8 @@ interfaces:
|
|||||||
type: TCPClientInterface
|
type: TCPClientInterface
|
||||||
enabled: true
|
enabled: true
|
||||||
target_host: phantom.mobilefabrik.com
|
target_host: phantom.mobilefabrik.com
|
||||||
target_port: 3434
|
target_port: 4242
|
||||||
#network_name: qortal
|
network_name: qortaltest
|
||||||
|
|
||||||
# This interface turns this Reticulum instance into a
|
# This interface turns this Reticulum instance into a
|
||||||
# server other clients can connect to over TCP.
|
# server other clients can connect to over TCP.
|
||||||
@ -88,6 +88,6 @@ interfaces:
|
|||||||
# type: TCPServerInterface
|
# type: TCPServerInterface
|
||||||
# enabled: true
|
# enabled: true
|
||||||
# listen_ip: 0.0.0.0
|
# listen_ip: 0.0.0.0
|
||||||
# listen_port: 3434
|
# listen_port: 4242
|
||||||
# #network_name: qortal
|
# network_name: qortaltest
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user