Skip to content

Commit

Permalink
TorService: Migrate to new TorController
Browse files Browse the repository at this point in the history
  • Loading branch information
alvasw committed Jun 11, 2024
1 parent 51a8fcd commit f148cd9
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
import bisq.network.identity.NetworkId;
import bisq.network.p2p.node.ConnectionException;
import bisq.security.keys.KeyBundle;
import bisq.security.keys.TorKeyPair;
import bisq.tor.TorService;
import bisq.tor.TorTransportConfig;
import bisq.tor.onionservice.CreateOnionServiceResponse;
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -81,14 +82,19 @@ public ServerSocketResult getServerSocket(NetworkId networkId, KeyBundle keyBund
bootstrapInfo.getBootstrapProgress().set(0.25);
bootstrapInfo.getBootstrapDetails().set("Create Onion service for node ID '" + networkId + "'");

CreateOnionServiceResponse response = torService.createOnionService(port, keyBundle.getTorKeyPair())
TorKeyPair torKeyPair = keyBundle.getTorKeyPair();
ServerSocket serverSocket = torService.createOnionService(port, torKeyPair)
.get(2, TimeUnit.MINUTES);

bootstrapInfo.getBootstrapState().set(BootstrapState.SERVICE_PUBLISHED);
bootstrapInfo.getBootstrapProgress().set(0.5);
bootstrapInfo.getBootstrapDetails().set("My Onion service address: " + response.getOnionAddress().toString());

return new ServerSocketResult(response);
String onionAddress = torKeyPair.getOnionAddress();
bootstrapInfo.getBootstrapDetails().set("My Onion service address: " + onionAddress);

Address address = new Address(onionAddress);
return new ServerSocketResult(serverSocket, address);

} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
throw new ConnectionException(e);
Expand Down
68 changes: 35 additions & 33 deletions network/tor/tor/src/main/java/bisq/tor/TorService.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@
import bisq.network.tor.common.torrc.BaseTorrcGenerator;
import bisq.network.tor.common.torrc.TorrcFileGenerator;
import bisq.security.keys.TorKeyPair;
import bisq.tor.controller.NativeTorController;
import bisq.tor.controller.TorController;
import bisq.tor.controller.events.events.BootstrapEvent;
import bisq.tor.installer.TorInstaller;
import bisq.tor.onionservice.CreateOnionServiceResponse;
import bisq.tor.onionservice.OnionServicePublishService;
import bisq.tor.process.NativeTorProcess;
import bisq.tor.process.control_port.ControlPortFilePoller;
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
Expand All @@ -40,7 +38,8 @@
import java.nio.file.Path;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
Expand All @@ -49,8 +48,8 @@ public class TorService implements Service {

private final TorTransportConfig transportConfig;
private final Path torDataDirPath;
private final NativeTorController nativeTorController;
private final OnionServicePublishService onionServicePublishService;
private final TorController torController;
private final Set<String> publishedOnionServices = new CopyOnWriteArraySet<>();

private final AtomicBoolean isRunning = new AtomicBoolean();

Expand All @@ -60,9 +59,7 @@ public class TorService implements Service {
public TorService(TorTransportConfig transportConfig) {
this.transportConfig = transportConfig;
this.torDataDirPath = transportConfig.getDataDir();
nativeTorController = new NativeTorController(transportConfig.getBootstrapTimeout(),
transportConfig.getHsUploadTimeout());
this.onionServicePublishService = new OnionServicePublishService(nativeTorController);
torController = new TorController(transportConfig.getBootstrapTimeout(), transportConfig.getHsUploadTimeout());
}

@Override
Expand All @@ -89,19 +86,16 @@ public CompletableFuture<Boolean> initialize() {
return new ControlPortFilePoller(controlPortFilePath)
.parsePort()
.thenAccept(controlPort -> {
nativeTorController.connect(controlPort, Optional.of(hashedControlPassword));
nativeTorController.bindTorToConnection();
torController.initialize(controlPort, hashedControlPassword);
torController.bootstrapTor();

nativeTorController.enableTorNetworking();
nativeTorController.waitUntilBootstrapped();

int port = nativeTorController.getSocksPort().orElseThrow();
int port = torController.getSocksPort();
torSocksProxyFactory = Optional.of(new TorSocksProxyFactory(port));
})
.thenApply(unused -> true);
} else {
return CompletableFuture.supplyAsync(() -> {
nativeTorController.connect(9051, Optional.empty());
torController.initialize(9051);
torSocksProxyFactory = Optional.of(new TorSocksProxyFactory(9050));
return true;
});
Expand All @@ -112,38 +106,46 @@ public CompletableFuture<Boolean> initialize() {
public CompletableFuture<Boolean> shutdown() {
log.info("shutdown");
return CompletableFuture.supplyAsync(() -> {
nativeTorController.shutdown();
torController.shutdown();
torProcess.ifPresent(NativeTorProcess::waitUntilExited);
return true;
});
}

public Observable<BootstrapEvent> getBootstrapEvent() {
return nativeTorController.getBootstrapEvent();
}

public CompletableFuture<CreateOnionServiceResponse> createOnionService(int port, TorKeyPair torKeyPair) {
public CompletableFuture<ServerSocket> createOnionService(int port, TorKeyPair torKeyPair) {
log.info("Start hidden service with port {}", port);
long ts = System.currentTimeMillis();
try {
@SuppressWarnings("resource") ServerSocket localServerSocket = new ServerSocket(RANDOM_PORT);
var localServerSocket = new ServerSocket(RANDOM_PORT);
int localPort = localServerSocket.getLocalPort();
return onionServicePublishService.publish(torKeyPair, port, localPort)
.thenApply(onionAddress -> {
log.info("Tor hidden service Ready. Took {} ms. Onion address={}",
System.currentTimeMillis() - ts, onionAddress);
return new CreateOnionServiceResponse(localServerSocket, onionAddress);
}
);

} catch (IOException e) {

String onionAddress = torKeyPair.getOnionAddress();
if (!publishedOnionServices.contains(onionAddress)) {
torController.publish(torKeyPair, port, localPort);
publishedOnionServices.add(onionAddress);
}

log.info("Tor hidden service Ready. Took {} ms. Onion address={}",
System.currentTimeMillis() - ts, onionAddress);

return CompletableFuture.completedFuture(localServerSocket);

} catch (IOException | InterruptedException e) {
log.error("Can't create onion service", e);
return CompletableFuture.failedFuture(e);
}
}

public boolean isOnionServiceOnline(String onionUrl) {
return nativeTorController.isHiddenServiceAvailable(onionUrl);
try {
return torController.isOnionServiceOnline(onionUrl).get(1, TimeUnit.MINUTES);
} catch (ExecutionException | InterruptedException | TimeoutException e) {
throw new RuntimeException(e);
}
}

public Observable<BootstrapEvent> getBootstrapEvent() {
return torController.getBootstrapEvent();
}

public Socket getSocket(String streamId) throws IOException {
Expand Down

0 comments on commit f148cd9

Please sign in to comment.