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