diff --git a/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java b/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java index 4ebf3886e5d60bf67cbdb8a2480029902fa6d638..ca899bc8aed4e8a67cc0c13e3619426cbedd4c2a 100644 --- a/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java +++ b/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java @@ -38,7 +38,7 @@ public class AndroidPluginsModule { DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor, androidExecutor, appContext, random, backoffFactory); DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext, - locationUtils, reporter, eventBus); + locationUtils, reporter, eventBus, backoffFactory); DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, backoffFactory, appContext); final Collection<DuplexPluginFactory> duplex = diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java index e7852bff66fe9340f3c16b4d6f3744f0913ae88e..ec1f0ca0a073ff50432301304da4a74df183fba0 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java @@ -23,13 +23,13 @@ import org.briarproject.api.event.EventListener; import org.briarproject.api.event.SettingsUpdatedEvent; import org.briarproject.api.keyagreement.KeyAgreementListener; import org.briarproject.api.keyagreement.TransportDescriptor; +import org.briarproject.api.plugins.Backoff; import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexTransportConnection; import org.briarproject.api.properties.TransportProperties; import org.briarproject.api.reporting.DevReporter; import org.briarproject.api.settings.Settings; -import org.briarproject.api.system.Clock; import org.briarproject.api.system.LocationUtils; import org.briarproject.util.StringUtils; @@ -79,7 +79,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051; private static final int COOKIE_TIMEOUT = 3000; // Milliseconds private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}"); - private static final int MIN_DESCRIPTORS_PUBLISHED = 3; private static final Logger LOG = Logger.getLogger(TorPlugin.class.getName()); @@ -87,10 +86,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private final Context appContext; private final LocationUtils locationUtils; private final DevReporter reporter; - private final Clock clock; + private final Backoff backoff; private final DuplexPluginCallback callback; private final String architecture; - private final int maxLatency, maxIdleTime, pollingInterval, socketTimeout; + private final int maxLatency, maxIdleTime, socketTimeout; private final ConnectionStatus connectionStatus; private final File torDirectory, torFile, geoIpFile, configFile; private final File doneFile, cookieFile; @@ -103,23 +102,22 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private volatile BroadcastReceiver networkStateReceiver = null; TorPlugin(Executor ioExecutor, Context appContext, - LocationUtils locationUtils, DevReporter reporter, Clock clock, + LocationUtils locationUtils, DevReporter reporter, Backoff backoff, DuplexPluginCallback callback, String architecture, int maxLatency, - int maxIdleTime, int pollingInterval) { + int maxIdleTime) { this.ioExecutor = ioExecutor; this.appContext = appContext; this.locationUtils = locationUtils; this.reporter = reporter; - this.clock = clock; + this.backoff = backoff; this.callback = callback; this.architecture = architecture; this.maxLatency = maxLatency; this.maxIdleTime = maxIdleTime; - this.pollingInterval = pollingInterval; if (maxIdleTime > Integer.MAX_VALUE / 2) socketTimeout = Integer.MAX_VALUE; else socketTimeout = maxIdleTime * 2; - connectionStatus = new ConnectionStatus(pollingInterval); + connectionStatus = new ConnectionStatus(); torDirectory = appContext.getDir("tor", MODE_PRIVATE); torFile = new File(torDirectory, "tor"); geoIpFile = new File(torDirectory, "geoip"); @@ -228,7 +226,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { if (phase != null && phase.contains("PROGRESS=100")) { LOG.info("Tor has already bootstrapped"); connectionStatus.setBootstrapped(); - sendCrashReports(); + sendDevReports(); } } // Register to receive network status events @@ -359,12 +357,12 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { } } - private void sendCrashReports() { + private void sendDevReports() { ioExecutor.execute(new Runnable() { @Override public void run() { - reporter.sendReports( - AndroidUtils.getReportDir(appContext), SOCKS_PORT); + File reportDir = AndroidUtils.getReportDir(appContext); + reporter.sendReports(reportDir, SOCKS_PORT); } }); } @@ -404,6 +402,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { publishHiddenService(localPort); } }); + backoff.reset(); // Accept incoming hidden service connections from Tor acceptContactConnections(ss); } @@ -470,6 +469,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { return; } LOG.info("Connection received"); + backoff.reset(); TorTransportConnection conn = new TorTransportConnection(this, s); callback.incomingConnectionCreated(conn); } @@ -517,25 +517,25 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { } public int getPollingInterval() { - return pollingInterval; + return backoff.getPollingInterval(); } public void poll(Collection<ContactId> connected) { if (!isRunning()) return; - if (connectionStatus.shouldPoll(clock.currentTimeMillis())) { - // TODO: Pass properties to connectAndCallBack() - for (ContactId c : callback.getRemoteProperties().keySet()) - if (!connected.contains(c)) connectAndCallBack(c); - } else { - LOG.info("Hidden service descriptor published, not polling"); - } + backoff.increment(); + // TODO: Pass properties to connectAndCallBack() + for (ContactId c : callback.getRemoteProperties().keySet()) + if (!connected.contains(c)) connectAndCallBack(c); } private void connectAndCallBack(final ContactId c) { ioExecutor.execute(new Runnable() { public void run() { DuplexTransportConnection d = createConnection(c); - if (d != null) callback.outgoingConnectionCreated(c, d); + if (d != null) { + backoff.reset(); + callback.outgoingConnectionCreated(c, d); + } } }); } @@ -593,6 +593,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { if (status.equals("BUILT") && connectionStatus.getAndSetCircuitBuilt()) { LOG.info("First circuit built"); + backoff.reset(); if (isRunning()) callback.transportEnabled(); } } @@ -614,14 +615,15 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg); if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) { connectionStatus.setBootstrapped(); - sendCrashReports(); + sendDevReports(); + backoff.reset(); if (isRunning()) callback.transportEnabled(); } } public void unrecognized(String type, String msg) { if (type.equals("HS_DESC") && msg.startsWith("UPLOADED")) - connectionStatus.descriptorPublished(clock.currentTimeMillis()); + LOG.info("Descriptor uploaded"); } private static class WriteObserver extends FileObserver { @@ -707,17 +709,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private static class ConnectionStatus { - private final int pollingInterval; - // All of the following are locking: this private boolean networkEnabled = false; private boolean bootstrapped = false, circuitBuilt = false; - private int descriptorsPublished = 0; - private long descriptorsPublishedTime = Long.MAX_VALUE; - - private ConnectionStatus(int pollingInterval) { - this.pollingInterval = pollingInterval; - } private synchronized void setBootstrapped() { bootstrapped = true; @@ -729,26 +723,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener { return firstCircuit; } - private synchronized void descriptorPublished(long now) { - descriptorsPublished++; - if (descriptorsPublished == MIN_DESCRIPTORS_PUBLISHED) - descriptorsPublishedTime = now; - } - private synchronized void enableNetwork(boolean enable) { networkEnabled = enable; circuitBuilt = false; - descriptorsPublished = 0; - descriptorsPublishedTime = Long.MAX_VALUE; } private synchronized boolean isConnected() { return networkEnabled && bootstrapped && circuitBuilt; } - - private synchronized boolean shouldPoll(long now) { - return descriptorsPublished < MIN_DESCRIPTORS_PUBLISHED - || now - descriptorsPublishedTime < 2 * pollingInterval; - } } } diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java b/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java index edf0103da9fed1cb4ad300377d1044aad3097eee..958c45c4158bd30e20d7e3ae2c389fd7868e18a6 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPluginFactory.java @@ -6,13 +6,13 @@ import android.os.Build; import org.briarproject.android.util.AndroidUtils; import org.briarproject.api.TransportId; import org.briarproject.api.event.EventBus; +import org.briarproject.api.plugins.Backoff; +import org.briarproject.api.plugins.BackoffFactory; import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.api.plugins.duplex.DuplexPluginFactory; import org.briarproject.api.reporting.DevReporter; -import org.briarproject.api.system.Clock; import org.briarproject.api.system.LocationUtils; -import org.briarproject.system.SystemClock; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -24,24 +24,26 @@ public class TorPluginFactory implements DuplexPluginFactory { private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds - private static final int POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes + private static final int MIN_POLLING_INTERVAL = 2 * 60 * 1000; // 2 minutes + private static final int MAX_POLLING_INTERVAL = 60 * 60 * 1000; // 1 hour + private static final double BACKOFF_BASE = 1.2; private final Executor ioExecutor; private final Context appContext; private final LocationUtils locationUtils; private final DevReporter reporter; private final EventBus eventBus; - private final Clock clock; + private final BackoffFactory backoffFactory; public TorPluginFactory(Executor ioExecutor, Context appContext, LocationUtils locationUtils, DevReporter reporter, - EventBus eventBus) { + EventBus eventBus, BackoffFactory backoffFactory) { this.ioExecutor = ioExecutor; this.appContext = appContext; this.locationUtils = locationUtils; this.reporter = reporter; this.eventBus = eventBus; - clock = new SystemClock(); + this.backoffFactory = backoffFactory; } public TransportId getId() { @@ -72,10 +74,11 @@ public class TorPluginFactory implements DuplexPluginFactory { // Use position-independent executable for SDK >= 16 if (Build.VERSION.SDK_INT >= 16) architecture += "-pie"; - TorPlugin plugin = - new TorPlugin(ioExecutor, appContext, locationUtils, reporter, - clock, callback, architecture, MAX_LATENCY, - MAX_IDLE_TIME, POLLING_INTERVAL); + Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, + MAX_POLLING_INTERVAL, BACKOFF_BASE); + TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils, + reporter, backoff, callback, architecture, MAX_LATENCY, + MAX_IDLE_TIME); eventBus.addListener(plugin); return plugin; }