diff --git a/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java b/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java
index 9f696e733c1..82e26947209 100644
--- a/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java
+++ b/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java
@@ -53,7 +53,7 @@ public NetworkNodeProvider(NetworkProtoResolver networkProtoResolver,
@Named(NetworkOptionKeys.EXTERNAL_TOR_USE_SAFECOOKIE) boolean useSafeCookieAuthentication ) {
networkNode = useLocalhostForP2P ?
new LocalhostNetworkNode(address, port, networkProtoResolver) :
- new TorNetworkNode(port, torDir, networkProtoResolver,
+ new TorNetworkNode(port, networkProtoResolver,
!controlPort.isEmpty() ?
new RunningTor(torDir, Integer.parseInt(controlPort), password, cookieFile, useSafeCookieAuthentication) :
new NewTor(torDir, torrcFile, torrcOptions, bridgeAddressProvider.getBridgeAddresses()));
diff --git a/p2p/src/main/java/bisq/network/p2p/network/NewTor.java b/p2p/src/main/java/bisq/network/p2p/network/NewTor.java
index a5cdb1018cc..69c0461699b 100644
--- a/p2p/src/main/java/bisq/network/p2p/network/NewTor.java
+++ b/p2p/src/main/java/bisq/network/p2p/network/NewTor.java
@@ -30,8 +30,8 @@
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
import org.berndpruenster.netlayer.tor.Torrc;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import lombok.extern.slf4j.Slf4j;
/**
* This class creates a brand new instance of the Tor onion router.
@@ -44,20 +44,27 @@
* @author Florian Reimair
*
*/
+@Slf4j
public class NewTor extends TorMode {
- private static final Logger log = LoggerFactory.getLogger(NewTor.class);
+ /**
+ * Netlayer
stores its hidden service files in a custom
+ * subdirectory of $torDir/hiddenservice/
. Note that the
+ * {@link HiddenServiceSocket} does add this part on its own, hence,
+ * {@link NewTor#getHiddenServiceDirectory()} returns only the custom
+ * subdirectory (which happens to be ""
)
+ */
+ private static final String HIDDEN_SERVICE_DIRECTORY = "hiddenservice";
private final String torrcFile;
private final String torrcOptions;
private final Collection bridgeEntries;
- private final File torWorkikngDirectory;
public NewTor(File torWorkingDirectory, String torrcFile, String torrcOptions, Collection bridgeEntries) {
+ super(torWorkingDirectory, HIDDEN_SERVICE_DIRECTORY);
this.torrcFile = torrcFile;
this.torrcOptions = torrcOptions;
this.bridgeEntries = bridgeEntries;
- this.torWorkikngDirectory = torWorkingDirectory;
}
@Override
@@ -103,7 +110,7 @@ public Tor getTor() throws IOException, TorCtlException {
override = new Torrc(torrcOptionsMap);
log.info("Starting tor");
- NativeTor result = new NativeTor(torWorkikngDirectory, bridgeEntries, override);
+ NativeTor result = new NativeTor(torDir, bridgeEntries, override);
log.info(
"\n################################################################\n"
+ "Tor started after {} ms. Start publishing hidden service.\n"
diff --git a/p2p/src/main/java/bisq/network/p2p/network/RunningTor.java b/p2p/src/main/java/bisq/network/p2p/network/RunningTor.java
index 62c5f43b10a..88aae8c4870 100644
--- a/p2p/src/main/java/bisq/network/p2p/network/RunningTor.java
+++ b/p2p/src/main/java/bisq/network/p2p/network/RunningTor.java
@@ -24,8 +24,8 @@
import org.berndpruenster.netlayer.tor.ExternalTor;
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import lombok.extern.slf4j.Slf4j;
/**
* This class creates a brand new instance of the Tor onion router.
@@ -37,19 +37,19 @@
* @author Florian Reimair
*
*/
+@Slf4j
public class RunningTor extends TorMode {
- private static final Logger log = LoggerFactory.getLogger(RunningTor.class);
+ private static final String EXTERNAL_TOR_HIDDEN_SERVICE = "externalTorHiddenService";
private final int controlPort;
private final String password;
- private final String torDir;
private final File cookieFile;
private final boolean useSafeCookieAuthentication;
public RunningTor(final File torDir, final int controlPort, final String password, final String cookieFile,
final boolean useSafeCookieAuthentication) {
- this.torDir = torDir.getAbsolutePath();
+ super(torDir, EXTERNAL_TOR_HIDDEN_SERVICE);
this.controlPort = controlPort;
this.password = password;
this.cookieFile = new File(cookieFile);
@@ -72,7 +72,7 @@ else if (cookieFile.exists())
log.info(
"\n################################################################\n"
- + "Tor started after {} ms. Start publishing hidden service.\n"
+ + "Connecting to Tor successful after {} ms. Start publishing hidden service.\n"
+ "################################################################",
(new Date().getTime() - ts1)); // takes usually a few seconds
@@ -81,7 +81,7 @@ else if (cookieFile.exists())
@Override
public String getHiddenServiceDirectory() {
- return torDir + File.separator + "externalTorHiddenService";
+ return new File(torDir, EXTERNAL_TOR_HIDDEN_SERVICE).getAbsolutePath();
}
}
diff --git a/p2p/src/main/java/bisq/network/p2p/network/TorMode.java b/p2p/src/main/java/bisq/network/p2p/network/TorMode.java
index 594312d51fc..1ddcda3e281 100644
--- a/p2p/src/main/java/bisq/network/p2p/network/TorMode.java
+++ b/p2p/src/main/java/bisq/network/p2p/network/TorMode.java
@@ -23,6 +23,8 @@
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
+import bisq.common.storage.FileUtil;
+
/**
* Holds information on how tor should be created and delivers a respective
* {@link Tor} object when asked.
@@ -32,11 +34,31 @@
*/
public abstract class TorMode {
+ /**
+ * The directory where the private_key
file sits in. Kept private,
+ * because it is only valid for the {@link TorMode#doRollingBackup()} due to the
+ * inner workings of the Netlayer
dependency.
+ */
+ private final File hiddenServiceDirectory;
+ protected final File torDir;
+
+ /**
+ * @param torDir points to the place, where we will persist private
+ * key and address data
+ * @param hiddenServiceDir The directory where the private_key
file
+ * sits in. Note that, due to the inner workings of the
+ * Netlayer
dependency, it does not
+ * necessarily equal
+ * {@link TorMode#getHiddenServiceDirectory()}.
+ */
+ public TorMode(File torDir, String hiddenServiceDir) {
+ this.torDir = torDir;
+ this.hiddenServiceDirectory = new File(torDir, hiddenServiceDir);
+ }
+
/**
* Returns a fresh {@link Tor} object.
*
- * @param torDir points to the place, where we will persist private key and
- * address data
* @return a fresh instance of {@link Tor}
* @throws IOException
* @throws TorCtlException
@@ -49,12 +71,20 @@ public abstract class TorMode {
* ""
) as a hidden service directory is fine. {@link ExternalTor},
* however, does not have a Tor installation path and thus, takes the hidden
* service path literally. Hence, we set
- * "torDir/ephemeralHiddenService"
as the hidden service directory.
+ * "torDir/externalTorHiddenService"
as the hidden service
+ * directory.
*
* @return ""
in {@link NewTor} Mode,
- * "torDir/ephemeralHiddenService"
in {@link RunningTor}
+ * "torDir/externalTorHiddenService"
in {@link RunningTor}
* mode
*/
public abstract String getHiddenServiceDirectory();
+ /**
+ * Do a rolling backup of the "private_key" file.
+ */
+ protected void doRollingBackup() {
+ FileUtil.rollingBackup(hiddenServiceDirectory, "private_key", 20);
+ }
+
}
diff --git a/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java b/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java
index 940eec53176..c560cf409d3 100644
--- a/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java
+++ b/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java
@@ -24,7 +24,6 @@
import bisq.common.UserThread;
import bisq.common.app.Log;
import bisq.common.proto.network.NetworkProtoResolver;
-import bisq.common.storage.FileUtil;
import bisq.common.util.Utilities;
import org.berndpruenster.netlayer.tor.HiddenServiceSocket;
@@ -47,14 +46,9 @@
import java.net.Socket;
-import java.nio.file.Paths;
-
-import java.io.File;
import java.io.IOException;
import java.util.Date;
-import java.util.List;
import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -74,7 +68,6 @@ public class TorNetworkNode extends NetworkNode {
private HiddenServiceSocket hiddenServiceSocket;
- private final File torDir;
private Timer shutDownTimeoutTimer;
private int restartCounter;
@SuppressWarnings("FieldCanBeLocal")
@@ -87,9 +80,8 @@ public class TorNetworkNode extends NetworkNode {
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
- public TorNetworkNode(int servicePort, File torDir, NetworkProtoResolver networkProtoResolver, TorMode torMode) {
+ public TorNetworkNode(int servicePort, NetworkProtoResolver networkProtoResolver, TorMode torMode) {
super(servicePort, networkProtoResolver);
- this.torDir = torDir;
this.torMode = torMode;
}
@@ -100,8 +92,7 @@ public TorNetworkNode(int servicePort, File torDir, NetworkProtoResolver network
@Override
public void start(@Nullable SetupListener setupListener) {
- final File hiddenservice = new File(Paths.get(torDir.getAbsolutePath(), "hiddenservice").toString());
- FileUtil.rollingBackup(hiddenservice, "private_key", 20);
+ torMode.doRollingBackup();
if (setupListener != null)
addSetupListener(setupListener);
@@ -280,8 +271,8 @@ public void run() {
log.error("Could not connect to running Tor: "
+ e.getMessage());
- // Seems a bit harsh, but since we cannot connect to Tor, we cannot do nothing
- // furthermore, we have no hidden services started yet, so there is no graceful
+ // Seems a bit harsh, but since we cannot connect to Tor, we cannot do nothing.
+ // Furthermore, we have no hidden services started yet, so there is no graceful
// shutdown needed either
System.exit(1);
} catch (Throwable ignore) {
diff --git a/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java b/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java
index 8d29cc3d623..083195bde47 100644
--- a/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java
+++ b/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java
@@ -53,8 +53,7 @@ public class TorNetworkNodeTest {
public void testTorNodeBeforeSecondReady() throws InterruptedException, IOException {
latch = new CountDownLatch(1);
int port = 9001;
- TorNetworkNode node1 = new TorNetworkNode(port, new File("torNode_" + port),
- TestUtils.getNetworkProtoResolver(),
+ TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(),
new NewTor(new File("torNode_" + port), "", "", new ArrayList()));
node1.start(new SetupListener() {
@Override
@@ -81,8 +80,7 @@ public void onRequestCustomBridges() {
latch = new CountDownLatch(1);
int port2 = 9002;
- TorNetworkNode node2 = new TorNetworkNode(port2, new File("torNode_" + port2),
- TestUtils.getNetworkProtoResolver(),
+ TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(),
new NewTor(new File("torNode_" + port), "", "", new ArrayList()));
node2.start(new SetupListener() {
@Override
@@ -140,8 +138,7 @@ public void onFailure(@NotNull Throwable throwable) {
public void testTorNodeAfterBothReady() throws InterruptedException, IOException {
latch = new CountDownLatch(2);
int port = 9001;
- TorNetworkNode node1 = new TorNetworkNode(port, new File("torNode_" + port),
- TestUtils.getNetworkProtoResolver(),
+ TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(),
new NewTor(new File("torNode_" + port), "", "", new ArrayList()));
node1.start(new SetupListener() {
@Override
@@ -167,8 +164,7 @@ public void onRequestCustomBridges() {
});
int port2 = 9002;
- TorNetworkNode node2 = new TorNetworkNode(port2, new File("torNode_" + port),
- TestUtils.getNetworkProtoResolver(),
+ TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(),
new NewTor(new File("torNode_" + port), "", "", new ArrayList()));
node2.start(new SetupListener() {
@Override