From 307099b70f451b1447be0b016b5e831073cfa143 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Tue, 11 Jun 2024 14:43:21 +0000 Subject: [PATCH] Fix Tor startup issues on Windows On Windows Tor writes its control port number to a file before the port is accessible by other applications. Users reported that Bisq throws a ConnectException (ControlCommandFailedException) at startup. All logs, I received so far, are from Windows users. Fixes #2239, #2253 --- .../tor/controller/TorControlProtocol.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/network/tor/tor/src/main/java/bisq/tor/controller/TorControlProtocol.java b/network/tor/tor/src/main/java/bisq/tor/controller/TorControlProtocol.java index b4911b9084..7b72131e65 100644 --- a/network/tor/tor/src/main/java/bisq/tor/controller/TorControlProtocol.java +++ b/network/tor/tor/src/main/java/bisq/tor/controller/TorControlProtocol.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.OutputStream; +import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; @@ -20,6 +21,8 @@ import java.util.stream.Stream; public class TorControlProtocol implements AutoCloseable { + private static final int MAX_CONNECTION_ATTEMPTS = 10; + private final Socket controlSocket; private final WhonixTorControlReader whonixTorControlReader; private Optional outputStream = Optional.empty(); @@ -35,11 +38,10 @@ public TorControlProtocol() { public void initialize(int port) { try { - var socketAddress = new InetSocketAddress("127.0.0.1", port); - controlSocket.connect(socketAddress); + connectToTor(port); whonixTorControlReader.start(controlSocket.getInputStream()); outputStream = Optional.of(controlSocket.getOutputStream()); - } catch (IOException e) { + } catch (IOException | InterruptedException e) { throw new CannotConnectWithTorException(e); } } @@ -151,6 +153,22 @@ public void removeHsDescEventListener(HsDescEventListener listener) { whonixTorControlReader.removeHsDescEventListener(listener); } + private void connectToTor(int port) throws InterruptedException { + int connectionAttempt = 0; + while (connectionAttempt < MAX_CONNECTION_ATTEMPTS) { + try { + var socketAddress = new InetSocketAddress("127.0.0.1", port); + controlSocket.connect(socketAddress); + break; + } catch (ConnectException e) { + connectionAttempt++; + Thread.sleep(200); + } catch (IOException e) { + throw new CannotConnectWithTorException(e); + } + } + } + private void sendCommand(String command) { try { @SuppressWarnings("resource") OutputStream outputStream = this.outputStream.orElseThrow();