mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-11-05 11:56:37 +00:00
upgrade internal tor to 0.4.8.15
This commit is contained in:
parent
be8b56e355
commit
71ac72e9f6
6 changed files with 128 additions and 299 deletions
156
build.gradle
156
build.gradle
|
|
@ -19,19 +19,6 @@ if(System.getProperty("os.arch") == "aarch64") {
|
|||
}
|
||||
def headless = "true".equals(System.getProperty("java.awt.headless"))
|
||||
|
||||
def vTor = '4.7.13-4'
|
||||
def vKmpTor = '1.4.3'
|
||||
def kmpOs = osName
|
||||
if(os.macOsX) {
|
||||
kmpOs = "macos"
|
||||
} else if(os.windows) {
|
||||
kmpOs = "mingw"
|
||||
}
|
||||
def kmpArch = "x64"
|
||||
if(System.getProperty("os.arch") == "aarch64") {
|
||||
kmpArch = "arm64"
|
||||
}
|
||||
|
||||
group "com.sparrowwallet"
|
||||
version "${sparrowVersion}"
|
||||
|
||||
|
|
@ -88,25 +75,9 @@ dependencies {
|
|||
implementation('com.sparrowwallet:hummingbird:1.7.4')
|
||||
implementation('co.nstant.in:cbor:0.9')
|
||||
implementation('org.openpnp:openpnp-capture-java:0.0.28-5')
|
||||
implementation("io.matthewnelson.kotlin-components:kmp-tor:${vTor}-${vKmpTor}") {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
|
||||
}
|
||||
if(kmpOs == "linux" && kmpArch == "arm64") {
|
||||
implementation("com.sparrowwallet.kmp-tor-binary:kmp-tor-binary-${kmpOs}${kmpArch}-jvm:${vTor}") {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
|
||||
}
|
||||
} else {
|
||||
implementation("io.matthewnelson.kotlin-components:kmp-tor-binary-${kmpOs}${kmpArch}:${vTor}") {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
|
||||
}
|
||||
}
|
||||
implementation("io.matthewnelson.kotlin-components:kmp-tor-binary-extract:${vTor}") {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
|
||||
}
|
||||
implementation("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-manager:${vKmpTor}") {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
|
||||
}
|
||||
implementation('org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.7.1') {
|
||||
implementation("io.matthewnelson.kmp-tor:runtime:2.2.0")
|
||||
implementation("io.matthewnelson.kmp-tor:resource-exec-tor-gpl:408.15.0")
|
||||
implementation('org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.10.1') {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-common'
|
||||
}
|
||||
implementation('de.codecentric.centerdevice:centerdevice-nsmenufx:2.1.7')
|
||||
|
|
@ -190,6 +161,10 @@ application {
|
|||
"--add-opens=java.base/java.net=com.sparrowwallet.sparrow",
|
||||
"--add-opens=java.base/java.io=com.google.gson",
|
||||
"--add-opens=java.smartcardio/sun.security.smartcardio=com.sparrowwallet.sparrow",
|
||||
"--add-opens=io.matthewnelson.kmp.tor.resource.geoip/io.matthewnelson.kmp.tor.resource.geoip=io.matthewnelson.kmp.tor.common.core",
|
||||
"--add-exports=io.matthewnelson.kmp.tor.runtime.ctrl/io.matthewnelson.kmp.tor.runtime.ctrl.internal=io.matthewnelson.kmp.tor.runtime",
|
||||
"--add-reads=io.matthewnelson.kmp.tor.runtime=io.matthewnelson.kmp.tor.common.core",
|
||||
"--add-reads=io.matthewnelson.kmp.tor.runtime.ctrl=io.matthewnelson.kmp.process",
|
||||
"--add-reads=kotlin.stdlib=kotlinx.coroutines.core",
|
||||
"--add-reads=org.flywaydb.core=java.desktop"]
|
||||
|
||||
|
|
@ -238,6 +213,10 @@ jlink {
|
|||
"--add-opens=java.base/java.net=com.sparrowwallet.sparrow",
|
||||
"--add-opens=java.base/java.io=com.google.gson",
|
||||
"--add-opens=java.smartcardio/sun.security.smartcardio=com.sparrowwallet.sparrow",
|
||||
"--add-opens=io.matthewnelson.kmp.tor.resource.geoip/io.matthewnelson.kmp.tor.resource.geoip=io.matthewnelson.kmp.tor.common.core",
|
||||
"--add-exports=io.matthewnelson.kmp.tor.runtime.ctrl/io.matthewnelson.kmp.tor.runtime.ctrl.internal=io.matthewnelson.kmp.tor.runtime",
|
||||
"--add-reads=io.matthewnelson.kmp.tor.runtime=io.matthewnelson.kmp.tor.common.core",
|
||||
"--add-reads=io.matthewnelson.kmp.tor.runtime.ctrl=io.matthewnelson.kmp.process",
|
||||
"--add-reads=com.sparrowwallet.merged.module=java.desktop",
|
||||
"--add-reads=com.sparrowwallet.merged.module=java.sql",
|
||||
"--add-reads=com.sparrowwallet.merged.module=com.sparrowwallet.sparrow",
|
||||
|
|
@ -472,119 +451,6 @@ extraJavaModuleInfo {
|
|||
exports('net.coobird.thumbnailator')
|
||||
requires('java.desktop')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-jvm", 'kmp.tor.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor')
|
||||
requires('kmp.tor.binary.extract.jvm')
|
||||
requires('kmp.tor.manager.jvm')
|
||||
requires('kmp.tor.manager.common.jvm')
|
||||
requires('kmp.tor.controller.common.jvm')
|
||||
requires('kotlin.stdlib')
|
||||
requires('kotlinx.coroutines.core')
|
||||
requires('java.management')
|
||||
}
|
||||
if(kmpOs == "linux" && kmpArch == "arm64") {
|
||||
module("com.sparrowwallet.kmp-tor-binary:kmp-tor-binary-${kmpOs}${kmpArch}-jvm", "kmp.tor.binary.${kmpOs}${kmpArch}") {
|
||||
exports("io.matthewnelson.kmp.tor.resource.${kmpOs}.${kmpArch}")
|
||||
exports("kmptor.${kmpOs}.${kmpArch}")
|
||||
}
|
||||
} else {
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-binary-${kmpOs}${kmpArch}-jvm", "kmp.tor.binary.${kmpOs}${kmpArch}") {
|
||||
exports("io.matthewnelson.kmp.tor.binary.${kmpOs}.${kmpArch}")
|
||||
exports("kmptor.${kmpOs}.${kmpArch}")
|
||||
}
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-binary-extract-jvm", 'kmp.tor.binary.extract.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.binary.extract')
|
||||
exports('io.matthewnelson.kmp.tor.binary.extract.internal')
|
||||
requires('kotlin.stdlib')
|
||||
requires("kmp.tor.binary.${kmpOs}${kmpArch}")
|
||||
requires('kmp.tor.binary.geoip.jvm')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-manager-jvm", 'kmp.tor.manager.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.manager')
|
||||
exports('io.matthewnelson.kmp.tor.manager.util')
|
||||
requires('kmp.tor.controller.common.jvm')
|
||||
requires('kmp.tor.manager.common.jvm')
|
||||
requires('kotlin.stdlib')
|
||||
requires('kotlinx.coroutines.core')
|
||||
requires('kotlinx.atomicfu')
|
||||
requires('kmp.tor.controller.jvm')
|
||||
requires('kmp.tor.common.jvm')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-manager-common-jvm", 'kmp.tor.manager.common.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.manager.common')
|
||||
exports('io.matthewnelson.kmp.tor.manager.common.event')
|
||||
exports('io.matthewnelson.kmp.tor.manager.common.state')
|
||||
requires('kmp.tor.controller.common.jvm')
|
||||
requires('kmp.tor.common.jvm')
|
||||
requires('kotlin.stdlib')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-controller-common-jvm", 'kmp.tor.controller.common.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.controller.common.config')
|
||||
exports('io.matthewnelson.kmp.tor.controller.common.file')
|
||||
exports('io.matthewnelson.kmp.tor.controller.common.control')
|
||||
exports('io.matthewnelson.kmp.tor.controller.common.control.usecase')
|
||||
exports('io.matthewnelson.kmp.tor.controller.common.events')
|
||||
exports('io.matthewnelson.kmp.tor.controller.common.exceptions')
|
||||
requires('kmp.tor.common.jvm')
|
||||
requires('kotlin.stdlib')
|
||||
requires('kotlinx.atomicfu')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-common-jvm", 'kmp.tor.common.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.common.address')
|
||||
requires('parcelize.jvm')
|
||||
requires('kotlin.stdlib')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-controller-jvm", 'kmp.tor.controller.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.controller.internal.controller')
|
||||
requires('kmp.tor.common.jvm')
|
||||
requires('kmp.tor.controller.common.jvm')
|
||||
requires('kotlinx.coroutines.core')
|
||||
requires('kotlin.stdlib')
|
||||
requires('kotlinx.atomicfu')
|
||||
requires('encoding.core.jvm')
|
||||
requires('encoding.base16.jvm')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-common-jvm", 'kmp.tor.ext.callback.common.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.ext.callback.common')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-manager-jvm", 'kmp.tor.ext.callback.manager.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.ext.callback.manager')
|
||||
requires('kmp.tor.manager.jvm')
|
||||
requires('kmp.tor.ext.callback.common.jvm')
|
||||
requires('kmp.tor.ext.callback.manager.common.jvm')
|
||||
requires('kmp.tor.ext.callback.controller.common.jvm')
|
||||
requires('kmp.tor.manager.common.jvm')
|
||||
requires('kmp.tor.controller.common.jvm')
|
||||
requires('kotlin.stdlib')
|
||||
requires('kotlinx.coroutines.core')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-manager-common-jvm", 'kmp.tor.ext.callback.manager.common.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.ext.callback.manager.common')
|
||||
requires('kmp.tor.ext.callback.controller.common.jvm')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-ext-callback-controller-common-jvm", 'kmp.tor.ext.callback.controller.common.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.ext.callback.controller.common.control')
|
||||
exports('io.matthewnelson.kmp.tor.ext.callback.controller.common.control.usecase')
|
||||
}
|
||||
module("io.matthewnelson.kotlin-components:kmp-tor-binary-geoip-jvm", 'kmp.tor.binary.geoip.jvm') {
|
||||
exports('io.matthewnelson.kmp.tor.binary.geoip')
|
||||
exports('kmptor')
|
||||
}
|
||||
module("base16-jvm-2.0.0.jar", 'encoding.base16.jvm', "2.0.0") {
|
||||
exports('io.matthewnelson.encoding.base16')
|
||||
requires('encoding.core.jvm')
|
||||
requires('kotlin.stdlib')
|
||||
}
|
||||
module("base32-jvm-2.0.0.jar", 'encoding.base32.jvm', "2.0.0")
|
||||
module("base64-jvm-2.0.0.jar", 'encoding.base64.jvm', "2.0.0")
|
||||
module("core-jvm-2.0.0.jar", 'encoding.core.jvm', "2.0.0") {
|
||||
exports('io.matthewnelson.encoding.core')
|
||||
requires('kotlin.stdlib')
|
||||
}
|
||||
module("parcelize-jvm-0.1.2.jar", 'parcelize.jvm', "0.1.2") {
|
||||
exports('io.matthewnelson.component.parcelize')
|
||||
}
|
||||
module('org.jcommander:jcommander', 'org.jcommander') {
|
||||
exports('com.beust.jcommander')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ public class AppServices {
|
|||
}
|
||||
|
||||
if(Tor.getDefault() != null) {
|
||||
Tor.getDefault().getTorManager().destroy(true, success -> {});
|
||||
Tor.getDefault().close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,134 +1,89 @@
|
|||
package com.sparrowwallet.sparrow.net;
|
||||
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.sparrowwallet.drongo.OsType;
|
||||
import com.sparrowwallet.drongo.IOUtils;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.event.TorStatusEvent;
|
||||
import com.sparrowwallet.sparrow.io.Storage;
|
||||
import io.matthewnelson.kmp.tor.KmpTorLoaderJvm;
|
||||
import io.matthewnelson.kmp.tor.PlatformInstaller;
|
||||
import io.matthewnelson.kmp.tor.TorConfigProviderJvm;
|
||||
import io.matthewnelson.kmp.tor.binary.extract.TorBinaryResource;
|
||||
import io.matthewnelson.kmp.tor.common.address.Port;
|
||||
import io.matthewnelson.kmp.tor.common.address.ProxyAddress;
|
||||
import io.matthewnelson.kmp.tor.controller.common.config.TorConfig;
|
||||
import io.matthewnelson.kmp.tor.controller.common.file.Path;
|
||||
import io.matthewnelson.kmp.tor.ext.callback.manager.CallbackTorManager;
|
||||
import io.matthewnelson.kmp.tor.manager.TorManager;
|
||||
import io.matthewnelson.kmp.tor.manager.common.event.TorManagerEvent;
|
||||
import io.matthewnelson.kmp.tor.manager.util.PortUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import io.matthewnelson.kmp.tor.resource.exec.tor.ResourceLoaderTorExec;
|
||||
import io.matthewnelson.kmp.tor.runtime.Action;
|
||||
import io.matthewnelson.kmp.tor.runtime.RuntimeEvent;
|
||||
import io.matthewnelson.kmp.tor.runtime.TorListeners;
|
||||
import io.matthewnelson.kmp.tor.runtime.TorRuntime;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.OnEvent;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.OnFailure;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.OnSuccess;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.TorEvent;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.ctrl.TorCmd;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.net.IPSocketAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.util.List;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class Tor {
|
||||
public class Tor implements Closeable {
|
||||
private static final Logger log = LoggerFactory.getLogger(Tor.class);
|
||||
|
||||
public static final String TOR_DIR = "tor";
|
||||
public static final String WORK_DIR = "work";
|
||||
public static final String CACHE_DIR = "cache";
|
||||
public static final String OLD_INSTALL_DIR = ".kmptor";
|
||||
public static final String TOR_ADDRESS_SUFFIX = ".onion";
|
||||
|
||||
private static Tor tor;
|
||||
|
||||
private final Path path = Path.invoke(Storage.getSparrowHome().getAbsolutePath()).builder().addSegment(TOR_DIR).build();
|
||||
private final CallbackTorManager instance;
|
||||
private ProxyAddress socksAddress;
|
||||
private final TorRuntime instance;
|
||||
private IPSocketAddress socksAddress;
|
||||
|
||||
public Tor() {
|
||||
OsType osType = OsType.getCurrent();
|
||||
String arch = System.getProperty("os.arch");
|
||||
PlatformInstaller installer;
|
||||
PlatformInstaller.InstallOption installOption = PlatformInstaller.InstallOption.CleanInstallIfMissing;
|
||||
|
||||
if(osType == OsType.MACOS) {
|
||||
if(arch.equals("aarch64")) {
|
||||
installer = PlatformInstaller.macosArm64(installOption);
|
||||
} else {
|
||||
installer = PlatformInstaller.macosX64(installOption);
|
||||
}
|
||||
} else if(osType == OsType.WINDOWS) {
|
||||
installer = PlatformInstaller.mingwX64(installOption);
|
||||
} else if(osType == OsType.UNIX) {
|
||||
if(arch.equals("aarch64")) {
|
||||
TorBinaryResource linuxArm64 = TorBinaryResource.from(TorBinaryResource.OS.Linux, "arm64",
|
||||
"588496f3164d52b91f17e4db3372d8dfefa6366a8df265eebd4a28d4128992aa",
|
||||
List.of("libevent-2.1.so.7.gz", "libstdc++.so.6.gz", "libcrypto.so.1.1.gz", "tor.gz", "libssl.so.1.1.gz"));
|
||||
installer = PlatformInstaller.custom(installOption, linuxArm64);
|
||||
} else {
|
||||
installer = PlatformInstaller.linuxX64(installOption);
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Sparrow's bundled Tor is not supported on " + osType + " " + arch);
|
||||
public Tor(OnEvent<TorListeners> listener) {
|
||||
Path path = Path.of(Storage.getSparrowHome().getAbsolutePath()).resolve(TOR_DIR);
|
||||
File oldInstallDir = path.resolve(WORK_DIR).resolve(OLD_INSTALL_DIR).toFile();
|
||||
if(oldInstallDir.exists()) {
|
||||
IOUtils.deleteDirectory(oldInstallDir);
|
||||
}
|
||||
|
||||
TorConfigProviderJvm torConfigProviderJvm = new TorConfigProviderJvm() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Path getWorkDir() {
|
||||
return path.builder().addSegment("work").build();
|
||||
}
|
||||
TorRuntime.Environment env = TorRuntime.Environment.Builder(
|
||||
path.resolve(WORK_DIR).toFile(),
|
||||
path.resolve(CACHE_DIR).toFile(),
|
||||
ResourceLoaderTorExec::getOrCreate
|
||||
);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Path getCacheDir() {
|
||||
return path.builder().addSegment("cache").build();
|
||||
}
|
||||
env.debug = true;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected TorConfig provide() {
|
||||
TorConfig.Builder builder = new TorConfig.Builder();
|
||||
|
||||
TorConfig.Setting.DormantCanceledByStartup dormantCanceledByStartup = new TorConfig.Setting.DormantCanceledByStartup();
|
||||
dormantCanceledByStartup.set(TorConfig.Option.AorTorF.getTrue());
|
||||
builder.put(dormantCanceledByStartup);
|
||||
|
||||
TorConfig.Setting.Ports.Control controlPort = new TorConfig.Setting.Ports.Control();
|
||||
controlPort.set(TorConfig.Option.AorDorPort.Auto.INSTANCE);
|
||||
builder.put(controlPort);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
};
|
||||
|
||||
KmpTorLoaderJvm jvmLoader = new KmpTorLoaderJvm(installer, torConfigProviderJvm);
|
||||
TorManager torManager = TorManager.newInstance(jvmLoader);
|
||||
|
||||
torManager.debug(true);
|
||||
torManager.addListener(new TorManagerEvent.Listener() {
|
||||
@Override
|
||||
public void managerEventWarn(@NotNull String message) {
|
||||
log.warn(message);
|
||||
EventManager.get().post(new TorStatusEvent(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void managerEventInfo(@NotNull String message) {
|
||||
log.info(message);
|
||||
EventManager.get().post(new TorStatusEvent(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void managerEventDebug(@NotNull String message) {
|
||||
log.debug(message);
|
||||
EventManager.get().post(new TorStatusEvent(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void managerEventAddressInfo(@NotNull TorManagerEvent.AddressInfo info) {
|
||||
if(info.isNull) {
|
||||
socksAddress = null;
|
||||
} else {
|
||||
socksAddress = info.socksInfoToProxyAddress().iterator().next();
|
||||
instance = TorRuntime.Builder(env, b -> {
|
||||
RuntimeEvent.entries().forEach(event -> {
|
||||
switch(event) {
|
||||
case RuntimeEvent.LOG.ERROR _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
|
||||
log.error(data.toString());
|
||||
EventManager.get().post(new TorStatusEvent(data.toString()));
|
||||
});
|
||||
case RuntimeEvent.LOG.WARN _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
|
||||
log.warn(data.toString());
|
||||
EventManager.get().post(new TorStatusEvent(data.toString()));
|
||||
});
|
||||
case RuntimeEvent.LOG.INFO _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
|
||||
log.info(data.toString());
|
||||
EventManager.get().post(new TorStatusEvent(data.toString()));
|
||||
});
|
||||
case RuntimeEvent.LOG.DEBUG _ -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
|
||||
log.debug(data.toString());
|
||||
EventManager.get().post(new TorStatusEvent(data.toString()));
|
||||
});
|
||||
case null, default -> b.observerStatic(event, OnEvent.Executor.Immediate.INSTANCE, data -> {
|
||||
log.trace(data.toString());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.instance = new CallbackTorManager(torManager, uncaughtException -> {
|
||||
log.error("Uncaught exception from CallbackTorManager", uncaughtException);
|
||||
b.observerStatic(RuntimeEvent.LISTENERS.INSTANCE, new TorSocksClient());
|
||||
b.observerStatic(RuntimeEvent.LISTENERS.INSTANCE, listener);
|
||||
|
||||
b.required(TorEvent.ERR.INSTANCE);
|
||||
b.required(TorEvent.WARN.INSTANCE);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +95,7 @@ public class Tor {
|
|||
Tor.tor = tor;
|
||||
}
|
||||
|
||||
public CallbackTorManager getTorManager() {
|
||||
public TorRuntime getTorRuntime() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
|
@ -149,14 +104,34 @@ public class Tor {
|
|||
throw new IllegalStateException("Tor socks proxy is not yet instantiated");
|
||||
}
|
||||
|
||||
return new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(socksAddress.address.getValue(), socksAddress.port.getValue()));
|
||||
return new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(socksAddress.address.value, socksAddress.port.value));
|
||||
}
|
||||
|
||||
public HostAndPort getProxyHostAndPort() {
|
||||
return HostAndPort.fromParts(socksAddress.address.getValue(), socksAddress.port.getValue());
|
||||
return HostAndPort.fromParts(socksAddress.address.value, socksAddress.port.value);
|
||||
}
|
||||
|
||||
public static boolean isRunningExternally() {
|
||||
return !PortUtil.isTcpPortAvailable(Port.invoke(9050));
|
||||
public void changeIdentity() {
|
||||
if(instance != null) {
|
||||
instance.enqueue(TorCmd.Signal.NewNym.INSTANCE, throwable -> {
|
||||
log.warn("Failed to signal newnym", throwable);
|
||||
}, _ -> {
|
||||
log.info("Signalled newnym for new Tor circuit");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if(instance != null) {
|
||||
instance.enqueue(Action.StopDaemon, OnFailure.noOp(), OnSuccess.noOp());
|
||||
}
|
||||
}
|
||||
|
||||
private class TorSocksClient implements OnEvent<TorListeners> {
|
||||
@Override
|
||||
public void invoke(TorListeners torListeners) {
|
||||
socksAddress = torListeners.socks.isEmpty() ? null : torListeners.socks.iterator().next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package com.sparrowwallet.sparrow.net;
|
||||
|
||||
import io.matthewnelson.kmp.tor.ext.callback.manager.CallbackTorManager;
|
||||
import io.matthewnelson.kmp.tor.manager.common.event.TorManagerEvent;
|
||||
import io.matthewnelson.kmp.tor.runtime.Action;
|
||||
import io.matthewnelson.kmp.tor.runtime.TorListeners;
|
||||
import io.matthewnelson.kmp.tor.runtime.TorRuntime;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.OnEvent;
|
||||
import io.matthewnelson.kmp.tor.runtime.core.ctrl.Reply;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -32,37 +34,25 @@ public class TorService extends ScheduledService<Tor> {
|
|||
protected Tor call() throws Exception {
|
||||
Tor tor = Tor.getDefault();
|
||||
if(tor == null) {
|
||||
tor = new Tor();
|
||||
CallbackTorManager callbackTorManager = tor.getTorManager();
|
||||
callbackTorManager.addListener(new TorManagerEvent.Listener() {
|
||||
@Override
|
||||
public void managerEventAddressInfo(@NotNull TorManagerEvent.AddressInfo info) {
|
||||
if(!info.isNull) {
|
||||
try {
|
||||
startupLock.lock();
|
||||
startupCondition.signalAll();
|
||||
} finally {
|
||||
startupLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
callbackTorManager.start(throwable -> {
|
||||
if(throwable instanceof Exception exception) {
|
||||
tor = new Tor(new StartupListener());
|
||||
TorRuntime torRuntime = tor.getTorRuntime();
|
||||
|
||||
torRuntime.enqueue(Action.StartDaemon, throwable -> {
|
||||
if(throwable instanceof Reply.Error replyError && !replyError.replies.isEmpty()) {
|
||||
startupException = new TorStartupException(replyError.replies.getFirst().message);
|
||||
} else if(throwable instanceof Exception exception) {
|
||||
startupException = exception;
|
||||
} else {
|
||||
startupException = new Exception(throwable);
|
||||
}
|
||||
log.error("Error", throwable);
|
||||
log.error("Error starting Tor daemon", throwable);
|
||||
try {
|
||||
startupLock.lock();
|
||||
startupCondition.signalAll();
|
||||
} finally {
|
||||
startupLock.unlock();
|
||||
}
|
||||
}, success -> {
|
||||
log.info("Tor daemon started successfully");
|
||||
});
|
||||
}, _ -> log.info("Tor daemon started successfully"));
|
||||
|
||||
try {
|
||||
startupLock.lock();
|
||||
|
|
@ -82,4 +72,18 @@ public class TorService extends ScheduledService<Tor> {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class StartupListener implements OnEvent<TorListeners> {
|
||||
@Override
|
||||
public void invoke(TorListeners torListeners) {
|
||||
if(!torListeners.socks.isEmpty()) {
|
||||
try {
|
||||
startupLock.lock();
|
||||
startupCondition.signalAll();
|
||||
} finally {
|
||||
startupLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.sparrowwallet.sparrow.net;
|
|||
import com.google.common.net.HostAndPort;
|
||||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.sparrow.AppServices;
|
||||
import io.matthewnelson.kmp.tor.controller.common.control.usecase.TorControlSignal;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -13,7 +12,6 @@ import java.net.SocketTimeoutException;
|
|||
import java.nio.file.AccessDeniedException;
|
||||
import java.nio.file.FileSystemException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
|
@ -24,11 +22,7 @@ public class TorUtils {
|
|||
|
||||
public static void changeIdentity(HostAndPort proxy) {
|
||||
if(AppServices.isTorRunning()) {
|
||||
Tor.getDefault().getTorManager().signal(TorControlSignal.Signal.NewNym, throwable -> {
|
||||
log.warn("Failed to signal newnym");
|
||||
}, successEvent -> {
|
||||
log.info("Signalled newnym for new Tor circuit");
|
||||
});
|
||||
Tor.getDefault().changeIdentity();
|
||||
} else {
|
||||
HostAndPort control = HostAndPort.fromParts(proxy.getHost(), proxy.getPort() + 1);
|
||||
try(Socket socket = new Socket(control.getHost(), control.getPort())) {
|
||||
|
|
|
|||
|
|
@ -20,18 +20,8 @@ open module com.sparrowwallet.sparrow {
|
|||
requires org.jetbrains.annotations;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires com.fasterxml.jackson.annotation;
|
||||
requires kotlin.stdlib;
|
||||
requires kmp.tor.jvm;
|
||||
requires kmp.tor.binary.extract.jvm;
|
||||
requires kmp.tor.common.jvm;
|
||||
requires kmp.tor.controller.common.jvm;
|
||||
requires kmp.tor.manager.jvm;
|
||||
requires kmp.tor.manager.common.jvm;
|
||||
requires kmp.tor.ext.callback.manager.jvm;
|
||||
requires kmp.tor.ext.callback.common.jvm;
|
||||
requires kmp.tor.ext.callback.manager.common.jvm;
|
||||
requires kmp.tor.ext.callback.controller.common.jvm;
|
||||
requires parcelize.jvm;
|
||||
requires io.matthewnelson.kmp.tor.runtime;
|
||||
requires io.matthewnelson.kmp.tor.resource.exec.tor;
|
||||
requires kotlinx.coroutines.javafx;
|
||||
requires org.slf4j;
|
||||
requires com.google.gson;
|
||||
|
|
|
|||
Loading…
Reference in a new issue