From 004467e84e32147876f3906b2ed68627b7218850 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 2 Aug 2018 16:59:03 +0100 Subject: [PATCH] Factor out remaining Android code from Tor plugin. --- bramble-android/build.gradle | 2 - .../bramble/plugin/tor/BridgeTest.java | 48 +++++----- .../bramble/test/ApplicationModule.java | 6 +- .../bramble/BrambleAndroidModule.java | 15 +-- .../tor/AndroidCircumventionModule.java | 17 ++++ .../tor/AndroidCircumventionProvider.java | 26 +++++ .../bramble/plugin/tor/AndroidTorPlugin.java | 95 +++++++++++++++++++ ...tory.java => AndroidTorPluginFactory.java} | 9 +- bramble-core/build.gradle | 2 + .../plugin/tor/CircumventionProvider.java | 0 .../plugin/tor/CircumventionProviderImpl.java | 30 ++---- .../bramble/plugin/tor/TorPlugin.java | 83 +++++----------- .../plugin/tor/TorTransportConnection.java | 0 .../briarproject/briar/android/AppModule.java | 6 +- 14 files changed, 211 insertions(+), 128 deletions(-) create mode 100644 bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionModule.java create mode 100644 bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionProvider.java create mode 100644 bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java rename bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/{TorPluginFactory.java => AndroidTorPluginFactory.java} (92%) rename {bramble-android => bramble-core}/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProvider.java (100%) rename {bramble-android => bramble-core}/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java (64%) rename {bramble-android => bramble-core}/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java (90%) rename {bramble-android => bramble-core}/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java (100%) diff --git a/bramble-android/build.gradle b/bramble-android/build.gradle index f7c9415ed..758fe7a42 100644 --- a/bramble-android/build.gradle +++ b/bramble-android/build.gradle @@ -27,7 +27,6 @@ configurations { dependencies { implementation project(path: ':bramble-core', configuration: 'default') - implementation 'org.briarproject:jtorctl:0.3' tor 'org.briarproject:tor-android:0.2.9.16@zip' annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2' @@ -115,7 +114,6 @@ dependencyVerification { 'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8', 'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca', 'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', - 'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864', 'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae', 'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4', 'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d', diff --git a/bramble-android/src/androidTest/java/org/briarproject/bramble/plugin/tor/BridgeTest.java b/bramble-android/src/androidTest/java/org/briarproject/bramble/plugin/tor/BridgeTest.java index 53fdc4a18..ebd0dc0b9 100644 --- a/bramble-android/src/androidTest/java/org/briarproject/bramble/plugin/tor/BridgeTest.java +++ b/bramble-android/src/androidTest/java/org/briarproject/bramble/plugin/tor/BridgeTest.java @@ -45,21 +45,35 @@ public class BridgeTest extends BrambleTestCase { @Inject NetworkManager networkManager; @Inject + CircumventionProvider circumventionProvider; + @Inject EventBus eventBus; @Inject BackoffFactory backoffFactory; @Inject Clock clock; - private final Context appContext = getTargetContext(); - private final CircumventionProvider circumventionProvider; - private final List bridges; - private TorPluginFactory factory; + private final Context appContext = + getTargetContext().getApplicationContext(); + + private List bridges; + private AndroidTorPluginFactory factory; + private volatile int currentBridge = 0; - public BridgeTest() { - super(); - circumventionProvider = new CircumventionProvider() { + @Before + public void setUp() { + BrambleAndroidIntegrationTestComponent component = + DaggerBrambleAndroidIntegrationTestComponent.builder().build(); + component.inject(this); + + Executor ioExecutor = Executors.newCachedThreadPool(); + ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); + LocationUtils locationUtils = () -> "US"; + SocketFactory torSocketFactory = SocketFactory.getDefault(); + + bridges = circumventionProvider.getBridges(); + CircumventionProvider testProvider = new CircumventionProvider() { @Override public boolean isTorProbablyBlocked(String countryCode) { return true; @@ -75,23 +89,9 @@ public class BridgeTest extends BrambleTestCase { return singletonList(bridges.get(currentBridge)); } }; - bridges = new CircumventionProviderImpl(appContext).getBridges(); - } - - @Before - public void setUp() { - BrambleAndroidIntegrationTestComponent component = - DaggerBrambleAndroidIntegrationTestComponent.builder().build(); - component.inject(this); - - Executor ioExecutor = Executors.newCachedThreadPool(); - ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); - LocationUtils locationUtils = () -> "US"; - SocketFactory torSocketFactory = SocketFactory.getDefault(); - - factory = new TorPluginFactory(ioExecutor, scheduler, appContext, + factory = new AndroidTorPluginFactory(ioExecutor, scheduler, appContext, networkManager, locationUtils, eventBus, torSocketFactory, - backoffFactory, circumventionProvider, clock); + backoffFactory, testProvider, clock); } @Test @@ -107,7 +107,7 @@ public class BridgeTest extends BrambleTestCase { DuplexPlugin duplexPlugin = factory.createPlugin(new TorPluginCallBack()); assertNotNull(duplexPlugin); - TorPlugin plugin = (TorPlugin) duplexPlugin; + AndroidTorPlugin plugin = (AndroidTorPlugin) duplexPlugin; currentBridge = bridge; LOG.warning("Testing " + bridges.get(currentBridge)); diff --git a/bramble-android/src/androidTest/java/org/briarproject/bramble/test/ApplicationModule.java b/bramble-android/src/androidTest/java/org/briarproject/bramble/test/ApplicationModule.java index f67f32edb..df642cf95 100644 --- a/bramble-android/src/androidTest/java/org/briarproject/bramble/test/ApplicationModule.java +++ b/bramble-android/src/androidTest/java/org/briarproject/bramble/test/ApplicationModule.java @@ -1,20 +1,20 @@ package org.briarproject.bramble.test; import android.app.Application; -import android.support.test.InstrumentationRegistry; import javax.inject.Singleton; import dagger.Module; import dagger.Provides; +import static android.support.test.InstrumentationRegistry.getTargetContext; + @Module class ApplicationModule { @Provides @Singleton Application provideApplication() { - return (Application) InstrumentationRegistry.getTargetContext() - .getApplicationContext(); + return (Application) getTargetContext().getApplicationContext(); } } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java index 48c49794e..bde183ba6 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/BrambleAndroidModule.java @@ -1,27 +1,16 @@ package org.briarproject.bramble; -import android.app.Application; - import org.briarproject.bramble.network.AndroidNetworkModule; -import org.briarproject.bramble.plugin.tor.CircumventionProvider; -import org.briarproject.bramble.plugin.tor.CircumventionProviderImpl; +import org.briarproject.bramble.plugin.tor.AndroidCircumventionModule; import org.briarproject.bramble.system.AndroidSystemModule; -import javax.inject.Singleton; - import dagger.Module; -import dagger.Provides; @Module(includes = { + AndroidCircumventionModule.class, AndroidNetworkModule.class, AndroidSystemModule.class }) public class BrambleAndroidModule { - @Provides - @Singleton - CircumventionProvider provideCircumventionProvider(Application app) { - return new CircumventionProviderImpl(app.getApplicationContext()); - } - } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionModule.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionModule.java new file mode 100644 index 000000000..656b20ad3 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionModule.java @@ -0,0 +1,17 @@ +package org.briarproject.bramble.plugin.tor; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class AndroidCircumventionModule { + + @Provides + @Singleton + CircumventionProvider provideCircumventionProvider( + AndroidCircumventionProvider circumventionProvider) { + return circumventionProvider; + } +} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionProvider.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionProvider.java new file mode 100644 index 000000000..39a44c3b9 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidCircumventionProvider.java @@ -0,0 +1,26 @@ +package org.briarproject.bramble.plugin.tor; + +import android.app.Application; +import android.content.Context; +import android.content.res.Resources; + +import java.io.InputStream; + +import javax.inject.Inject; + +class AndroidCircumventionProvider extends CircumventionProviderImpl { + + private final Context appContext; + + @Inject + AndroidCircumventionProvider(Application app) { + this.appContext = app.getApplicationContext(); + } + + @Override + protected InputStream getResourceInputStream(String name) { + Resources res = appContext.getResources(); + int resId = res.getIdentifier(name, "raw", appContext.getPackageName()); + return res.openRawResource(resId); + } +} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java new file mode 100644 index 000000000..b7e1c96c6 --- /dev/null +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPlugin.java @@ -0,0 +1,95 @@ +package org.briarproject.bramble.plugin.tor; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.os.PowerManager; + +import org.briarproject.bramble.api.network.NetworkManager; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.bramble.api.plugin.Backoff; +import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.bramble.api.system.LocationUtils; +import org.briarproject.bramble.util.RenewableWakeLock; + +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; + +import javax.net.SocketFactory; + +import static android.content.Context.MODE_PRIVATE; +import static android.content.Context.POWER_SERVICE; +import static android.os.PowerManager.PARTIAL_WAKE_LOCK; +import static java.util.concurrent.TimeUnit.MINUTES; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault +class AndroidTorPlugin extends TorPlugin { + + // This tag may prevent Huawei's power manager from killing us + private static final String WAKE_LOCK_TAG = "LocationManagerService"; + + private final Context appContext; + private final RenewableWakeLock wakeLock; + + AndroidTorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler, + Context appContext, NetworkManager networkManager, + LocationUtils locationUtils, SocketFactory torSocketFactory, + Clock clock, CircumventionProvider circumventionProvider, + Backoff backoff, DuplexPluginCallback callback, + String architecture, int maxLatency, int maxIdleTime) { + super(ioExecutor, networkManager, locationUtils, torSocketFactory, + clock, circumventionProvider, backoff, callback, architecture, + maxLatency, maxIdleTime, + appContext.getDir("tor", MODE_PRIVATE)); + this.appContext = appContext; + PowerManager pm = (PowerManager) + appContext.getSystemService(POWER_SERVICE); + assert pm != null; + wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK, + WAKE_LOCK_TAG, 1, MINUTES); + } + + @Override + protected int getProcessId() { + return android.os.Process.myPid(); + } + + @Override + protected long getLastUpdateTime() { + try { + PackageManager pm = appContext.getPackageManager(); + PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0); + return pi.lastUpdateTime; + } catch (NameNotFoundException e) { + throw new AssertionError(e); + } + } + + @Override + protected InputStream getResourceInputStream(String name) { + Resources res = appContext.getResources(); + int resId = res.getIdentifier(name, "raw", appContext.getPackageName()); + return res.openRawResource(resId); + } + + @Override + protected void enableNetwork(boolean enable) throws IOException { + if (!running) return; + if (enable) wakeLock.acquire(); + super.enableNetwork(enable); + if (!enable) wakeLock.release(); + } + + @Override + public void stop() { + super.stop(); + wakeLock.release(); + } +} diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPluginFactory.java similarity index 92% rename from bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPluginFactory.java rename to bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPluginFactory.java index 1055a03a7..854c2bcea 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPluginFactory.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/AndroidTorPluginFactory.java @@ -26,10 +26,10 @@ import javax.net.SocketFactory; @Immutable @NotNullByDefault -public class TorPluginFactory implements DuplexPluginFactory { +public class AndroidTorPluginFactory implements DuplexPluginFactory { private static final Logger LOG = - Logger.getLogger(TorPluginFactory.class.getName()); + Logger.getLogger(AndroidTorPluginFactory.class.getName()); private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds @@ -48,7 +48,7 @@ public class TorPluginFactory implements DuplexPluginFactory { private final CircumventionProvider circumventionProvider; private final Clock clock; - public TorPluginFactory(Executor ioExecutor, + public AndroidTorPluginFactory(Executor ioExecutor, ScheduledExecutorService scheduler, Context appContext, NetworkManager networkManager, LocationUtils locationUtils, EventBus eventBus, SocketFactory torSocketFactory, @@ -99,7 +99,8 @@ public class TorPluginFactory implements DuplexPluginFactory { Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); - TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext, + AndroidTorPlugin + plugin = new AndroidTorPlugin(ioExecutor, scheduler, appContext, networkManager, locationUtils, torSocketFactory, clock, circumventionProvider, backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME); diff --git a/bramble-core/build.gradle b/bramble-core/build.gradle index ea5b426d3..abc85106e 100644 --- a/bramble-core/build.gradle +++ b/bramble-core/build.gradle @@ -14,6 +14,7 @@ dependencies { implementation 'org.bitlet:weupnp:0.1.4' implementation 'net.i2p.crypto:eddsa:0.2.0' implementation 'org.whispersystems:curve25519-java:0.4.1' + implementation 'org.briarproject:jtorctl:0.3' apt 'com.google.dagger:dagger-compiler:2.0.2' @@ -47,6 +48,7 @@ dependencyVerification { 'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8', 'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8', 'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb', + 'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864', 'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90', 'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52', diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProvider.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProvider.java similarity index 100% rename from bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProvider.java rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProvider.java diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java similarity index 64% rename from bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java index bf194fa4e..e4c00738c 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java @@ -1,40 +1,31 @@ package org.briarproject.bramble.plugin.tor; -import android.content.Context; -import android.content.res.Resources; - import org.briarproject.bramble.api.lifecycle.IoExecutor; import java.io.InputStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Scanner; import java.util.Set; import javax.annotation.Nullable; -import javax.inject.Inject; -// TODO: Create a module for this so it doesn't need to be public +import static java.util.Arrays.asList; -public class CircumventionProviderImpl implements CircumventionProvider { +abstract class CircumventionProviderImpl implements CircumventionProvider { private final static String BRIDGE_FILE_NAME = "bridges"; - private final Context ctx; + private static final Set BLOCKED_IN_COUNTRIES = + new HashSet<>(asList(BLOCKED)); + private static final Set BRIDGES_WORK_IN_COUNTRIES = + new HashSet<>(asList(BRIDGES)); + @Nullable private volatile List bridges = null; - @Inject - public CircumventionProviderImpl(Context ctx) { - this.ctx = ctx; - } - - private static final Set BLOCKED_IN_COUNTRIES = - new HashSet<>(Arrays.asList(BLOCKED)); - private static final Set BRIDGES_WORK_IN_COUNTRIES = - new HashSet<>(Arrays.asList(BRIDGES)); + protected abstract InputStream getResourceInputStream(String name); @Override public boolean isTorProbablyBlocked(String countryCode) { @@ -51,10 +42,7 @@ public class CircumventionProviderImpl implements CircumventionProvider { public List getBridges() { if (this.bridges != null) return this.bridges; - Resources res = ctx.getResources(); - int resId = res.getIdentifier(BRIDGE_FILE_NAME, "raw", - ctx.getPackageName()); - InputStream is = ctx.getResources().openRawResource(resId); + InputStream is = getResourceInputStream(BRIDGE_FILE_NAME); Scanner scanner = new Scanner(is); List bridges = new ArrayList<>(); diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java similarity index 90% rename from bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java index fa7d2fac2..707e118ed 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java @@ -1,12 +1,5 @@ package org.briarproject.bramble.plugin.tor; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; -import android.os.PowerManager; - import net.freehaven.tor.control.EventHandler; import net.freehaven.tor.control.TorControlConnection; @@ -34,7 +27,6 @@ import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.util.IoUtils; -import org.briarproject.bramble.util.RenewableWakeLock; import org.briarproject.bramble.util.StringUtils; import java.io.Closeable; @@ -57,7 +49,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Scanner; import java.util.concurrent.Executor; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; import java.util.regex.Pattern; @@ -66,10 +57,6 @@ import java.util.zip.ZipInputStream; import javax.annotation.Nullable; import javax.net.SocketFactory; -import static android.content.Context.MODE_PRIVATE; -import static android.content.Context.POWER_SERVICE; -import static android.os.PowerManager.PARTIAL_WAKE_LOCK; -import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS; @@ -88,7 +75,10 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion; @MethodsNotNullByDefault @ParametersNotNullByDefault -class TorPlugin implements DuplexPlugin, EventHandler, EventListener { +abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { + + private static final Logger LOG = + Logger.getLogger(TorPlugin.class.getName()); private static final String[] EVENTS = { "CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR" @@ -97,13 +87,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private static final int COOKIE_TIMEOUT_MS = 3000; private static final int COOKIE_POLLING_INTERVAL_MS = 200; private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}"); - // This tag may prevent Huawei's power manager from killing us - private static final String WAKE_LOCK_TAG = "LocationManagerService"; - private static final Logger LOG = - Logger.getLogger(TorPlugin.class.getName()); private final Executor ioExecutor, connectionStatusExecutor; - private final Context appContext; private final NetworkManager networkManager; private final LocationUtils locationUtils; private final SocketFactory torSocketFactory; @@ -113,25 +98,30 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private final String architecture; private final CircumventionProvider circumventionProvider; private final int maxLatency, maxIdleTime, socketTimeout; - private final ConnectionStatus connectionStatus; private final File torDirectory, torFile, geoIpFile, configFile; private final File doneFile, cookieFile; - private final RenewableWakeLock wakeLock; + private final ConnectionStatus connectionStatus; private final AtomicBoolean used = new AtomicBoolean(false); - private volatile boolean running = false; private volatile ServerSocket socket = null; private volatile Socket controlSocket = null; private volatile TorControlConnection controlConnection = null; - TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler, - Context appContext, NetworkManager networkManager, + protected volatile boolean running = false; + + protected abstract int getProcessId(); + + protected abstract long getLastUpdateTime(); + + protected abstract InputStream getResourceInputStream(String name); + + TorPlugin(Executor ioExecutor, NetworkManager networkManager, LocationUtils locationUtils, SocketFactory torSocketFactory, Clock clock, CircumventionProvider circumventionProvider, Backoff backoff, DuplexPluginCallback callback, - String architecture, int maxLatency, int maxIdleTime) { + String architecture, int maxLatency, int maxIdleTime, + File torDirectory) { this.ioExecutor = ioExecutor; - this.appContext = appContext; this.networkManager = networkManager; this.locationUtils = locationUtils; this.torSocketFactory = torSocketFactory; @@ -145,20 +135,16 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { if (maxIdleTime > Integer.MAX_VALUE / 2) socketTimeout = Integer.MAX_VALUE; else socketTimeout = maxIdleTime * 2; - connectionStatus = new ConnectionStatus(); - torDirectory = appContext.getDir("tor", MODE_PRIVATE); + this.torDirectory = torDirectory; torFile = new File(torDirectory, "tor"); geoIpFile = new File(torDirectory, "geoip"); configFile = new File(torDirectory, "torrc"); doneFile = new File(torDirectory, "done"); cookieFile = new File(torDirectory, ".tor/control_auth_cookie"); + connectionStatus = new ConnectionStatus(); // Don't execute more than one connection status check at a time connectionStatusExecutor = new PoliteExecutor("TorPlugin", ioExecutor, 1); - PowerManager pm = (PowerManager) - appContext.getSystemService(POWER_SERVICE); - wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK, - WAKE_LOCK_TAG, 1, MINUTES); } @Override @@ -187,7 +173,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { LOG.info("Starting Tor"); String torPath = torFile.getAbsolutePath(); String configPath = configFile.getAbsolutePath(); - String pid = String.valueOf(android.os.Process.myPid()); + String pid = String.valueOf(getProcessId()); Process torProcess; ProcessBuilder pb = new ProcessBuilder(torPath, "-f", configPath, OWNER, pid); @@ -266,13 +252,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { } private boolean assetsAreUpToDate() { - try { - PackageManager pm = appContext.getPackageManager(); - PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0); - return doneFile.lastModified() > pi.lastUpdateTime; - } catch (NameNotFoundException e) { - throw new RuntimeException(e); - } + return doneFile.lastModified() > getLastUpdateTime(); } private void installAssets() throws PluginException { @@ -305,29 +285,21 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private InputStream getTorInputStream() throws IOException { if (LOG.isLoggable(INFO)) LOG.info("Installing Tor binary for " + architecture); - int resId = getResourceId("tor_" + architecture); - InputStream in = appContext.getResources().openRawResource(resId); + InputStream in = getResourceInputStream("tor_" + architecture); ZipInputStream zin = new ZipInputStream(in); if (zin.getNextEntry() == null) throw new IOException(); return zin; } private InputStream getGeoIpInputStream() throws IOException { - int resId = getResourceId("geoip"); - InputStream in = appContext.getResources().openRawResource(resId); + InputStream in = getResourceInputStream("geoip"); ZipInputStream zin = new ZipInputStream(in); if (zin.getNextEntry() == null) throw new IOException(); return zin; } private InputStream getConfigInputStream() { - int resId = getResourceId("torrc"); - return appContext.getResources().openRawResource(resId); - } - - private int getResourceId(String filename) { - Resources res = appContext.getResources(); - return res.getIdentifier(filename, "raw", appContext.getPackageName()); + return getResourceInputStream("torrc"); } private void tryToClose(@Nullable Closeable c) { @@ -473,15 +445,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { } } - private void enableNetwork(boolean enable) throws IOException { + protected void enableNetwork(boolean enable) throws IOException { if (!running) return; - if (enable) wakeLock.acquire(); connectionStatus.enableNetwork(enable); controlConnection.setConf("DisableNetwork", enable ? "0" : "1"); - if (!enable) { - callback.transportDisabled(); - wakeLock.release(); - } + if (!enable) callback.transportDisabled(); } private void enableBridges(boolean enable) throws IOException { @@ -509,7 +477,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { logException(LOG, WARNING, e); } } - wakeLock.release(); } @Override diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java similarity index 100% rename from bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java rename to bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorTransportConnection.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index 06d275767..8938c3c22 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -24,8 +24,8 @@ import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.Scheduler; import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory; import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory; +import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory; import org.briarproject.bramble.plugin.tor.CircumventionProvider; -import org.briarproject.bramble.plugin.tor.TorPluginFactory; import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.StringUtils; import org.briarproject.briar.api.android.AndroidNotificationManager; @@ -100,8 +100,8 @@ public class AppModule { DuplexPluginFactory bluetooth = new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor, appContext, random, eventBus, backoffFactory); - DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, scheduler, - appContext, networkManager, locationUtils, eventBus, + DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor, + scheduler, appContext, networkManager, locationUtils, eventBus, torSocketFactory, backoffFactory, circumventionProvider, clock); DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, eventBus, backoffFactory, appContext);