diff --git a/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/AbstractTorWrapper.java b/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/AbstractTorWrapper.java index a92b8cbcc11e29efc6950bb5162d6bb609889180..3916c221a73ffbbe79bfc5f34ff0690a5b07b639 100644 --- a/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/AbstractTorWrapper.java +++ b/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/AbstractTorWrapper.java @@ -50,7 +50,6 @@ import static org.briarproject.onionwrapper.TorWrapper.TorState.STARTED; import static org.briarproject.onionwrapper.TorWrapper.TorState.STARTING; import static org.briarproject.onionwrapper.TorWrapper.TorState.STOPPED; import static org.briarproject.onionwrapper.TorWrapper.TorState.STOPPING; -import static org.briarproject.onionwrapper.util.OsUtils.isMac; @InterfaceNotNullByDefault abstract class AbstractTorWrapper implements EventHandler, TorWrapper { @@ -73,8 +72,9 @@ abstract class AbstractTorWrapper implements EventHandler, TorWrapper { protected final Executor ioExecutor; protected final Executor eventExecutor; - private final String architecture; - private final File torDirectory, configFile, doneFile, cookieFile; + protected final String architecture; + protected final File torDirectory; + private final File configFile, doneFile, cookieFile; private final int torSocksPort; private final int torControlPort; @@ -111,10 +111,6 @@ abstract class AbstractTorWrapper implements EventHandler, TorWrapper { return new File(torDirectory, "tor"); } - protected File getLibEventFile() { - return new File(torDirectory, "libevent-2.1.7.dylib"); - } - @Override public File getObfs4ExecutableFile() { return new File(torDirectory, "obfs4proxy"); @@ -207,9 +203,6 @@ abstract class AbstractTorWrapper implements EventHandler, TorWrapper { //noinspection ResultOfMethodCallIgnored doneFile.delete(); installTorExecutable(); - if (isMac()) { - installLibEvent(); - } installObfs4Executable(); installSnowflakeExecutable(); extract(getConfigInputStream(), configFile); @@ -229,31 +222,15 @@ abstract class AbstractTorWrapper implements EventHandler, TorWrapper { LOG.info("Installing Tor binary for " + architecture); } File torFile = getTorExecutableFile(); - // Important: delete file here and with other binaries below to prevent - // problems on macOS in case the file signature changed. - //noinspection ResultOfMethodCallIgnored - torFile.delete(); extract(getExecutableInputStream("tor"), torFile); if (!torFile.setExecutable(true, true)) throw new IOException(); } - protected void installLibEvent() throws IOException { - if (LOG.isLoggable(INFO)) { - LOG.info("Installing libevent binary for " + architecture); - } - File libEventFile = getLibEventFile(); - //noinspection ResultOfMethodCallIgnored - libEventFile.delete(); - extract(getExecutableInputStream("libevent-2.1.7.dylib"), libEventFile); - } - protected void installObfs4Executable() throws IOException { if (LOG.isLoggable(INFO)) { LOG.info("Installing obfs4proxy binary for " + architecture); } File obfs4File = getObfs4ExecutableFile(); - //noinspection ResultOfMethodCallIgnored - obfs4File.delete(); extract(getExecutableInputStream("obfs4proxy"), obfs4File); if (!obfs4File.setExecutable(true, true)) throw new IOException(); } @@ -263,13 +240,11 @@ abstract class AbstractTorWrapper implements EventHandler, TorWrapper { LOG.info("Installing snowflake binary for " + architecture); } File snowflakeFile = getSnowflakeExecutableFile(); - //noinspection ResultOfMethodCallIgnored - snowflakeFile.delete(); extract(getExecutableInputStream("snowflake"), snowflakeFile); if (!snowflakeFile.setExecutable(true, true)) throw new IOException(); } - private InputStream getExecutableInputStream(String basename) { + protected InputStream getExecutableInputStream(String basename) { String ext = getExecutableExtension(); return requireNonNull(getResourceInputStream(architecture + "/" + basename, ext)); } diff --git a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java index 02c5136e733af07b6c4cca6a9d3e4c8d6ac3f4ee..9c7d1de34473a8cc1a1c6392c53bd0cf7aeedd94 100644 --- a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java +++ b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java @@ -60,11 +60,13 @@ public class TestUtils { public static String getArchitectureForTorBinary() { String arch = System.getProperty("os.arch"); if (arch == null) return null; - if (isLinux() || isWindows()) { + if (isLinux()) { //noinspection IfCanBeSwitch if (arch.equals("amd64")) return "x86_64"; else if (arch.equals("aarch64")) return "aarch64"; else if (arch.equals("arm")) return "armhf"; + } else if (isWindows()) { + if (arch.equals("amd64")) return "x86_64"; } else if (isMac()) { if (arch.equals("amd64")) return "x86_64"; else if (arch.equals("aarch64")) return "aarch64"; diff --git a/onionwrapper-java/build.gradle b/onionwrapper-java/build.gradle index 3b10d4320579689c55a28b0ba4803f382fab3093..5d742636a2c8de9c021c2ca8c4652b3b73b13132 100644 --- a/onionwrapper-java/build.gradle +++ b/onionwrapper-java/build.gradle @@ -1,4 +1,3 @@ -import static org.briarproject.onionwrapper.OS.* import static org.briarproject.onionwrapper.OsUtils.currentOS plugins { @@ -18,21 +17,15 @@ checkstyle { dependencies { api project(':onionwrapper-core') - def jna_version = '5.10.0' + def jna_version = '5.13.0' implementation "net.java.dev.jna:jna:$jna_version" implementation "net.java.dev.jna:jna-platform:$jna_version" testImplementation project(path: ':onionwrapper-core', configuration: 'testOutput') testImplementation 'junit:junit:4.13.2' - if (currentOS == Linux || currentOS == Windows) { - testImplementation "org.briarproject:tor-$currentOS.id:0.4.7.13-2" - testImplementation "org.briarproject:obfs4proxy-$currentOS.id:0.0.14-tor2" - testImplementation "org.briarproject:snowflake-$currentOS.id:2.5.1" - } else if (currentOS == MacOS) { - testImplementation "org.briarproject:tor-macos:0.4.7.13-2" - testImplementation "org.briarproject:obfs4proxy-macos:0.0.14-tor2" - testImplementation "org.briarproject:snowflake-macos:2.5.1" - } + testImplementation "org.briarproject:tor-$currentOS.id:0.4.7.13-2" + testImplementation "org.briarproject:obfs4proxy-$currentOS.id:0.0.14-tor2" + testImplementation "org.briarproject:snowflake-$currentOS.id:2.5.1" } mavenPublishing { diff --git a/onionwrapper-java/src/main/java/org/briarproject/onionwrapper/MacTorWrapper.java b/onionwrapper-java/src/main/java/org/briarproject/onionwrapper/MacTorWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..48fe817da0fa4493d658b3b9491f36d2d2ba9e23 --- /dev/null +++ b/onionwrapper-java/src/main/java/org/briarproject/onionwrapper/MacTorWrapper.java @@ -0,0 +1,68 @@ +package org.briarproject.onionwrapper; + +import org.briarproject.nullsafety.NotNullByDefault; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.Executor; + +import static java.util.logging.Level.INFO; + +@NotNullByDefault +public class MacTorWrapper extends UnixTorWrapper { + + static final String LIB_EVENT_VERSION = "2.1.7"; + + /** + * @param ioExecutor The wrapper will use this executor to run IO tasks, + * some of which may run for the lifetime of the wrapper, so the executor + * should have an unlimited thread pool. + * @param eventExecutor The wrapper will use this executor to call the + * {@link Observer observer} (if any). To ensure that events are observed + * in the order they occur, this executor should have a single thread (eg + * the app's main thread). + * @param architecture The processor architecture of the Tor and pluggable + * transport binaries. + * @param torDirectory The directory where the Tor process should keep its + * state. + * @param torSocksPort The port number to use for Tor's SOCKS port. + * @param torControlPort The port number to use for Tor's control port. + */ + public MacTorWrapper(Executor ioExecutor, + Executor eventExecutor, + String architecture, + File torDirectory, + int torSocksPort, + int torControlPort) { + super(ioExecutor, eventExecutor, architecture, torDirectory, torSocksPort, torControlPort); + } + + @Override + protected void installTorExecutable() throws IOException { + super.installTorExecutable(); + installLibEvent(); + } + + private void installLibEvent() throws IOException { + if (LOG.isLoggable(INFO)) { + LOG.info("Installing libevent binary for " + architecture); + } + File libEventFile = getLibEventFile(); + extract(getExecutableInputStream("libevent-" + LIB_EVENT_VERSION + ".dylib"), + libEventFile); + } + + private File getLibEventFile() { + return new File(torDirectory, "libevent-" + LIB_EVENT_VERSION + ".dylib"); + } + + @Override + protected void extract(InputStream in, File dest) throws IOException { + // Important: delete file to prevent problems on macOS in case the file signature changed + // for binaries. + //noinspection ResultOfMethodCallIgnored + dest.delete(); + super.extract(in, dest); + } +} diff --git a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java index e8d9cc6ee1334841e7349396ce91f5b677a7b34a..98bb14658c83423ecb0fa4c54a27e50b7903de8c 100644 --- a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java +++ b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java @@ -53,9 +53,12 @@ public class BootstrapTest extends BaseTest { public void testBootstrapping() throws Exception { String architecture = requireNonNull(getArchitectureForTorBinary()); TorWrapper tor; - if (isLinux() || isMac()) { + if (isLinux()) { tor = new UnixTorWrapper(executor, executor, architecture, torDir, CONTROL_PORT, SOCKS_PORT); + } else if (isMac()) { + tor = new MacTorWrapper(executor, executor, architecture, torDir, + CONTROL_PORT, SOCKS_PORT); } else if (isWindows()) { tor = new WindowsTorWrapper(executor, executor, architecture, torDir, CONTROL_PORT, SOCKS_PORT); diff --git a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesMacTest.java b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesMacTest.java index b8bd2fccc87eea64419af7f9d4f482c693ac1233..213f2f62020e71fa57da523b6e37e97a3f3c4d84 100644 --- a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesMacTest.java +++ b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesMacTest.java @@ -3,6 +3,7 @@ package org.briarproject.onionwrapper; import org.junit.Before; import org.junit.Test; +import static org.briarproject.onionwrapper.MacTorWrapper.LIB_EVENT_VERSION; import static org.briarproject.onionwrapper.util.OsUtils.isMac; import static org.junit.Assert.assertNotNull; import static org.junit.Assume.assumeTrue; @@ -21,7 +22,7 @@ public class ResourcesMacTest { @Test public void testCanLoadLibEvent() { - testCanLoadResource("x86_64/libevent-2.1.7.dylib"); + testCanLoadResource("x86_64/libevent-" + LIB_EVENT_VERSION + ".dylib"); } @Test