Compare commits

...

6 Commits

Author SHA1 Message Date
akwizgran
66d907d1b2 Add comment explaining relationship between constants. 2022-06-13 11:26:07 +01:00
akwizgran
7d336c98e4 Raise stability threshold and poll less often when network is stable. 2022-06-13 11:26:07 +01:00
akwizgran
963e510c3b Fix PollerImplTest expectations. 2022-06-13 11:26:07 +01:00
akwizgran
213d2f1da4 Disable and re-enable network if we can't reach our own HS. 2022-06-13 11:26:07 +01:00
akwizgran
3038b92dbc Poll less frequently when own hidden service is stable. 2022-06-13 11:26:06 +01:00
akwizgran
7cd3c2890b Remove backoff for polling Tor plugin. 2022-06-13 11:26:06 +01:00
28 changed files with 315 additions and 163 deletions

View File

@@ -86,8 +86,8 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
BluetoothConnectionFactory<BluetoothSocket> connectionFactory = BluetoothConnectionFactory<BluetoothSocket> connectionFactory =
new AndroidBluetoothConnectionFactory(connectionLimiter, new AndroidBluetoothConnectionFactory(connectionLimiter,
wakeLockManager, timeoutMonitor); wakeLockManager, timeoutMonitor);
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(eventBus, ID,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin( AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
connectionLimiter, connectionFactory, ioExecutor, connectionLimiter, connectionFactory, ioExecutor,
wakefulIoExecutor, secureRandom, androidExecutor, app, wakefulIoExecutor, secureRandom, androidExecutor, app,

View File

@@ -61,8 +61,8 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
@Override @Override
public DuplexPlugin createPlugin(PluginCallback callback) { public DuplexPlugin createPlugin(PluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(eventBus, ID,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor, AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor,
wakefulIoExecutor, app, backoff, callback, wakefulIoExecutor, app, backoff, callback,
MAX_LATENCY, MAX_IDLE_TIME, CONNECTION_TIMEOUT); MAX_LATENCY, MAX_IDLE_TIME, CONNECTION_TIMEOUT);

View File

@@ -9,7 +9,6 @@ import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.AndroidWakeLock; import org.briarproject.bramble.api.system.AndroidWakeLock;
import org.briarproject.bramble.api.system.AndroidWakeLockManager; import org.briarproject.bramble.api.system.AndroidWakeLockManager;
@@ -64,7 +63,6 @@ class AndroidTorPlugin extends TorPlugin {
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
AndroidWakeLockManager wakeLockManager, AndroidWakeLockManager wakeLockManager,
Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, PluginCallback callback,
String architecture, String architecture,
@@ -75,7 +73,7 @@ class AndroidTorPlugin extends TorPlugin {
int torControlPort) { int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager,
torRendezvousCrypto, callback, architecture, maxLatency, torRendezvousCrypto, callback, architecture, maxLatency,
maxIdleTime, torDirectory, torSocksPort, torControlPort); maxIdleTime, torDirectory, torSocksPort, torControlPort);
this.app = app; this.app = app;

View File

@@ -8,8 +8,6 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorControlPort; import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory; import org.briarproject.bramble.api.plugin.TorDirectory;
@@ -44,7 +42,6 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
LocationUtils locationUtils, LocationUtils locationUtils,
EventBus eventBus, EventBus eventBus,
SocketFactory torSocketFactory, SocketFactory torSocketFactory,
BackoffFactory backoffFactory,
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
@@ -56,7 +53,7 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
Application app, Application app,
AndroidWakeLockManager wakeLockManager) { AndroidWakeLockManager wakeLockManager) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
eventBus, torSocketFactory, backoffFactory, resourceProvider, eventBus, torSocketFactory, resourceProvider,
circumventionProvider, batteryManager, clock, crypto, circumventionProvider, batteryManager, clock, crypto,
torDirectory, torSocksPort, torControlPort); torDirectory, torSocksPort, torControlPort);
this.app = app; this.app = app;
@@ -76,14 +73,14 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
} }
@Override @Override
TorPlugin createPluginInstance(Backoff backoff, TorPlugin createPluginInstance(TorRendezvousCrypto torRendezvousCrypto,
TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback, PluginCallback callback,
String architecture) { String architecture) {
return new AndroidTorPlugin(ioExecutor, return new AndroidTorPlugin(ioExecutor,
wakefulIoExecutor, app, networkManager, locationUtils, wakefulIoExecutor, app, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, wakeLockManager, circumventionProvider, batteryManager, wakeLockManager,
backoff, torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort, MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort,
torControlPort); torControlPort);
} }

View File

@@ -1,7 +1,9 @@
package org.briarproject.bramble.api.plugin; package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.event.EventBus;
public interface BackoffFactory { public interface BackoffFactory {
Backoff createBackoff(int minInterval, int maxInterval, Backoff createBackoff(EventBus eventBus, TransportId transportId,
double base); int minInterval, int maxInterval, double base);
} }

View File

@@ -56,4 +56,9 @@ public interface PluginCallback extends ConnectionHandler {
* This method can safely be called while holding a lock. * This method can safely be called while holding a lock.
*/ */
void pluginStateChanged(State state); void pluginStateChanged(State state);
/**
* Informs the callback that the plugin's polling interval has decreased.
*/
void pollingIntervalDecreased();
} }

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a plugin's polling interval decreases.
*/
@Immutable
@NotNullByDefault
public class PollingIntervalDecreasedEvent extends Event {
private final TransportId transportId;
public PollingIntervalDecreasedEvent(TransportId transportId) {
this.transportId = transportId;
}
public TransportId getTransportId() {
return transportId;
}
}

View File

@@ -1,8 +1,10 @@
package org.briarproject.bramble.plugin; package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory; import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
@@ -11,8 +13,9 @@ import javax.annotation.concurrent.Immutable;
class BackoffFactoryImpl implements BackoffFactory { class BackoffFactoryImpl implements BackoffFactory {
@Override @Override
public Backoff createBackoff(int minInterval, int maxInterval, public Backoff createBackoff(EventBus eventBus, TransportId transportId,
double base) { int minInterval, int maxInterval, double base) {
return new BackoffImpl(minInterval, maxInterval, base); return new BackoffImpl(eventBus, transportId, minInterval, maxInterval,
base);
} }
} }

View File

@@ -1,7 +1,10 @@
package org.briarproject.bramble.plugin; package org.briarproject.bramble.plugin;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.event.PollingIntervalDecreasedEvent;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@@ -11,11 +14,16 @@ import javax.annotation.concurrent.ThreadSafe;
@NotNullByDefault @NotNullByDefault
class BackoffImpl implements Backoff { class BackoffImpl implements Backoff {
private final EventBus eventBus;
private final TransportId transportId;
private final int minInterval, maxInterval; private final int minInterval, maxInterval;
private final double base; private final double base;
private final AtomicInteger backoff; private final AtomicInteger backoff;
BackoffImpl(int minInterval, int maxInterval, double base) { BackoffImpl(EventBus eventBus, TransportId transportId,
int minInterval, int maxInterval, double base) {
this.eventBus = eventBus;
this.transportId = transportId;
this.minInterval = minInterval; this.minInterval = minInterval;
this.maxInterval = maxInterval; this.maxInterval = maxInterval;
this.base = base; this.base = base;
@@ -37,6 +45,9 @@ class BackoffImpl implements Backoff {
@Override @Override
public void reset() { public void reset() {
backoff.set(0); int old = backoff.getAndSet(0);
if (old > 0) {
eventBus.broadcast(new PollingIntervalDecreasedEvent(transportId));
}
} }
} }

View File

@@ -20,6 +20,7 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.PollingIntervalDecreasedEvent;
import org.briarproject.bramble.api.plugin.event.TransportActiveEvent; import org.briarproject.bramble.api.plugin.event.TransportActiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent; import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportStateEvent; import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
@@ -362,6 +363,11 @@ class PluginManagerImpl implements PluginManager, Service {
} }
} }
@Override
public void pollingIntervalDecreased() {
eventBus.broadcast(new PollingIntervalDecreasedEvent(id));
}
@Override @Override
public void handleConnection(DuplexTransportConnection d) { public void handleConnection(DuplexTransportConnection d) {
connectionManager.manageIncomingConnection(id, d); connectionManager.manageIncomingConnection(id, d);

View File

@@ -20,7 +20,7 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent; import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent; import org.briarproject.bramble.api.plugin.event.PollingIntervalDecreasedEvent;
import org.briarproject.bramble.api.plugin.event.TransportActiveEvent; import org.briarproject.bramble.api.plugin.event.TransportActiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent; import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin; import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
@@ -107,10 +107,14 @@ class PollerImpl implements Poller, EventListener {
if (!c.isIncoming() && c.isException()) { if (!c.isIncoming() && c.isException()) {
connectToContact(c.getContactId(), c.getTransportId()); connectToContact(c.getContactId(), c.getTransportId());
} }
} else if (e instanceof ConnectionOpenedEvent) { } else if (e instanceof PollingIntervalDecreasedEvent) {
ConnectionOpenedEvent c = (ConnectionOpenedEvent) e; PollingIntervalDecreasedEvent p = (PollingIntervalDecreasedEvent) e;
// Reschedule polling, the polling interval may have decreased TransportId t = p.getTransportId();
reschedule(c.getTransportId()); if (LOG.isLoggable(INFO)) {
LOG.info("Polling interval decreased for " + t);
}
// Reschedule polling
reschedule(t);
} else if (e instanceof TransportActiveEvent) { } else if (e instanceof TransportActiveEvent) {
TransportActiveEvent t = (TransportActiveEvent) e; TransportActiveEvent t = (TransportActiveEvent) e;
// Poll the newly activated transport // Poll the newly activated transport
@@ -228,7 +232,7 @@ class PollerImpl implements Poller, EventListener {
if (!connected.contains(c)) if (!connected.contains(c))
properties.add(new Pair<>(e.getValue(), new Handler(c, t))); properties.add(new Pair<>(e.getValue(), new Handler(c, t)));
} }
if (!properties.isEmpty()) p.poll(properties); p.poll(properties);
} catch (DbException e) { } catch (DbException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
} }

View File

@@ -335,7 +335,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
@Override @Override
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>> public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) { properties) {
if (getState() != ACTIVE) return; if (properties.isEmpty() || getState() != ACTIVE) return;
backoff.increment(); backoff.increment();
for (Pair<TransportProperties, ConnectionHandler> p : properties) { for (Pair<TransportProperties, ConnectionHandler> p : properties) {
connect(p.getFirst(), p.getSecond()); connect(p.getFirst(), p.getSecond());

View File

@@ -56,8 +56,8 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
@Override @Override
public DuplexPlugin createPlugin(PluginCallback callback) { public DuplexPlugin createPlugin(PluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(eventBus, ID,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE);
LanTcpPlugin plugin = new LanTcpPlugin(ioExecutor, wakefulIoExecutor, LanTcpPlugin plugin = new LanTcpPlugin(ioExecutor, wakefulIoExecutor,
backoff, callback, MAX_LATENCY, MAX_IDLE_TIME, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME,
CONNECTION_TIMEOUT); CONNECTION_TIMEOUT);

View File

@@ -246,7 +246,7 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener {
@Override @Override
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>> public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) { properties) {
if (getState() != ACTIVE) return; if (properties.isEmpty() || getState() != ACTIVE) return;
backoff.increment(); backoff.increment();
for (Pair<TransportProperties, ConnectionHandler> p : properties) { for (Pair<TransportProperties, ConnectionHandler> p : properties) {
connect(p.getFirst(), p.getSecond()); connect(p.getFirst(), p.getSecond());

View File

@@ -60,8 +60,8 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
@Override @Override
public DuplexPlugin createPlugin(PluginCallback callback) { public DuplexPlugin createPlugin(PluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(eventBus, ID,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE);
PortMapper portMapper = new PortMapperImpl(shutdownManager); PortMapper portMapper = new PortMapperImpl(shutdownManager);
WanTcpPlugin plugin = new WanTcpPlugin(ioExecutor, wakefulIoExecutor, WanTcpPlugin plugin = new WanTcpPlugin(ioExecutor, wakefulIoExecutor,
backoff, portMapper, callback, MAX_LATENCY, MAX_IDLE_TIME, backoff, portMapper, callback, MAX_LATENCY, MAX_IDLE_TIME,

View File

@@ -18,7 +18,6 @@ import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.ConnectionHandler; import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException; import org.briarproject.bramble.api.plugin.PluginException;
@@ -26,6 +25,7 @@ import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource; import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint; import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint;
@@ -67,6 +67,7 @@ import javax.net.SocketFactory;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
@@ -124,6 +125,45 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final int COOKIE_POLLING_INTERVAL_MS = 200; private static final int COOKIE_POLLING_INTERVAL_MS = 200;
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}"); private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
/**
* After this many consecutive successful connections to our own hidden
* service we consider the network to be stable.
* <p>
* This constant times {@link #POLLING_INTERVAL_UNSTABLE} should be
* greater than {@link #POLLING_INTERVAL_STABLE}. This ensures that if
* we experience a network outage that isn't detected by the
* {@link NetworkManager}, and if one of our contacts comes online during
* the outage, then either the outage lasts longer than
* {@link #POLLING_INTERVAL_STABLE}, in which case we detect the outage
* by failing to connect to our own hidden service, or the outage ends
* before the contact considers their own network connection to be stable,
* in which case the contact is still trying to connect to us when the
* outage ends. Either way, we don't end up in a situation where both we
* and the contact consider our network connections to be stable and stop
* trying to connect to each other, despite both being online.
*/
private static final int STABLE_NETWORK_THRESHOLD = 10;
/**
* After this many consecutive failed connections to our own hidden service
* we consider our connection to the Tor network to be broken.
*/
private static final int BROKEN_NETWORK_THRESHOLD = 3;
/**
* How often to poll our own hidden service when the network is considered
* to be stable.
*/
private static final int POLLING_INTERVAL_STABLE =
(int) MINUTES.toMillis(10);
/**
* How often to poll our own hidden service and our contacts' hidden
* services when the network is considered to be unstable.
*/
private static final int POLLING_INTERVAL_UNSTABLE =
(int) MINUTES.toMillis(2);
protected final Executor ioExecutor; protected final Executor ioExecutor;
private final Executor wakefulIoExecutor; private final Executor wakefulIoExecutor;
private final Executor connectionStatusExecutor; private final Executor connectionStatusExecutor;
@@ -132,7 +172,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
private final Clock clock; private final Clock clock;
private final BatteryManager batteryManager; private final BatteryManager batteryManager;
private final Backoff backoff;
private final TorRendezvousCrypto torRendezvousCrypto; private final TorRendezvousCrypto torRendezvousCrypto;
private final PluginCallback callback; private final PluginCallback callback;
private final String architecture; private final String architecture;
@@ -152,6 +191,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private volatile Socket controlSocket = null; private volatile Socket controlSocket = null;
private volatile TorControlConnection controlConnection = null; private volatile TorControlConnection controlConnection = null;
private volatile Settings settings = null; private volatile Settings settings = null;
private volatile String ownOnion = null;
protected abstract int getProcessId(); protected abstract int getProcessId();
@@ -166,7 +206,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, PluginCallback callback,
String architecture, String architecture,
@@ -184,7 +223,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
this.resourceProvider = resourceProvider; this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider; this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager; this.batteryManager = batteryManager;
this.backoff = backoff;
this.torRendezvousCrypto = torRendezvousCrypto; this.torRendezvousCrypto = torRendezvousCrypto;
this.callback = callback; this.callback = callback;
this.architecture = architecture; this.architecture = architecture;
@@ -474,7 +512,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
callback.mergeSettings(s); callback.mergeSettings(s);
// Create a hidden service if necessary // Create a hidden service if necessary
ioExecutor.execute(() -> publishHiddenService(localPort)); ioExecutor.execute(() -> publishHiddenService(localPort));
backoff.reset();
// Accept incoming hidden service connections from Tor // Accept incoming hidden service connections from Tor
acceptContactConnections(ss); acceptContactConnections(ss);
}); });
@@ -513,6 +550,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return; return;
} }
String onion3 = response.get(HS_ADDRESS); String onion3 = response.get(HS_ADDRESS);
ownOnion = onion3;
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("V3 hidden service " + scrubOnion(onion3)); LOG.info("V3 hidden service " + scrubOnion(onion3));
} }
@@ -541,7 +579,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return; return;
} }
LOG.info("Connection received"); LOG.info("Connection received");
backoff.reset();
callback.handleConnection(new TorTransportConnection(this, s)); callback.handleConnection(new TorTransportConnection(this, s));
} }
} }
@@ -618,14 +655,58 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public int getPollingInterval() { public int getPollingInterval() {
return backoff.getPollingInterval(); if (state.isNetworkStable()) {
LOG.info("Using stable polling interval");
return POLLING_INTERVAL_STABLE;
} else {
LOG.info("Using unstable polling interval");
return POLLING_INTERVAL_UNSTABLE;
}
} }
@Override @Override
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>> public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) { properties) {
if (getState() != ACTIVE) return; if (getState() != ACTIVE) return;
backoff.increment(); String ownOnion = this.ownOnion;
if (ownOnion == null) {
// Our own hidden service hasn't been created yet
pollContacts(properties);
} else {
// If the network is unstable, poll our contacts
boolean stable = state.isNetworkStable();
if (!stable) pollContacts(properties);
// Poll our own hidden service to check if the network is stable
wakefulIoExecutor.execute(() -> {
LOG.info("Connecting to own hidden service");
TransportProperties p = new TransportProperties();
p.put(PROP_ONION_V3, ownOnion);
DuplexTransportConnection d = createConnection(p);
if (d == null) {
LOG.info("Could not connect to own hidden service");
state.onStabilityCheckFailed();
// If the network was previously considered stable then
// we didn't poll our contacts above, so poll them now
if (stable) pollContacts(properties);
} else {
LOG.info("Connected to own hidden service");
// Close the connection (this will cause the other end of
// the connection to log an EOFException)
try {
d.getWriter().dispose(false);
d.getReader().dispose(false, false);
} catch (IOException e) {
logException(LOG, WARNING, e);
}
state.onStabilityCheckSucceeded();
}
});
}
}
private void pollContacts(
Collection<Pair<TransportProperties, ConnectionHandler>> properties) {
if (properties.isEmpty() || getState() != ACTIVE) return;
for (Pair<TransportProperties, ConnectionHandler> p : properties) { for (Pair<TransportProperties, ConnectionHandler> p : properties) {
connect(p.getFirst(), p.getSecond()); connect(p.getFirst(), p.getSecond());
} }
@@ -634,10 +715,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void connect(TransportProperties p, ConnectionHandler h) { private void connect(TransportProperties p, ConnectionHandler h) {
wakefulIoExecutor.execute(() -> { wakefulIoExecutor.execute(() -> {
DuplexTransportConnection d = createConnection(p); DuplexTransportConnection d = createConnection(p);
if (d != null) { if (d != null) h.handleConnection(d);
backoff.reset();
h.handleConnection(d);
}
}); });
} }
@@ -760,7 +838,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
// DisableNetwork, set our circuitBuilt flag if not already set // DisableNetwork, set our circuitBuilt flag if not already set
if (status.equals("BUILT") && !state.getAndSetCircuitBuilt(true)) { if (status.equals("BUILT") && !state.getAndSetCircuitBuilt(true)) {
LOG.info("Circuit built"); LOG.info("Circuit built");
backoff.reset();
} }
} }
@@ -787,6 +864,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public void message(String severity, String msg) { public void message(String severity, String msg) {
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg); if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
if (msg.startsWith("Switching to guard context")) {
state.resetNetworkStability();
}
} }
@Override @Override
@@ -813,12 +893,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (msg.startsWith("BOOTSTRAP PROGRESS=100")) { if (msg.startsWith("BOOTSTRAP PROGRESS=100")) {
LOG.info("Bootstrapped"); LOG.info("Bootstrapped");
state.setBootstrapped(); state.setBootstrapped();
backoff.reset();
} else if (msg.startsWith("CIRCUIT_ESTABLISHED")) { } else if (msg.startsWith("CIRCUIT_ESTABLISHED")) {
if (!state.getAndSetCircuitBuilt(true)) { if (!state.getAndSetCircuitBuilt(true)) LOG.info("Circuit built");
LOG.info("Circuit built");
backoff.reset();
}
} else if (msg.startsWith("CIRCUIT_NOT_ESTABLISHED")) { } else if (msg.startsWith("CIRCUIT_NOT_ESTABLISHED")) {
if (state.getAndSetCircuitBuilt(false)) { if (state.getAndSetCircuitBuilt(false)) {
LOG.info("Circuit not built"); LOG.info("Circuit not built");
@@ -863,7 +939,15 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof SettingsUpdatedEvent) { if (e instanceof ConnectionClosedEvent) {
ConnectionClosedEvent c = (ConnectionClosedEvent) e;
if (c.getTransportId().equals(getId())
&& !c.isIncoming() && c.isException()) {
LOG.info("Outgoing connection closed with exception");
// The failure may indicate that the network is unstable
state.resetNetworkStability();
}
} else if (e instanceof SettingsUpdatedEvent) {
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e; SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
if (s.getNamespace().equals(ID.getString())) { if (s.getNamespace().equals(ID.getString())) {
LOG.info("Tor settings updated"); LOG.info("Tor settings updated");
@@ -880,6 +964,18 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
} }
private void disableAndReenableNetwork() {
connectionStatusExecutor.execute(() -> {
try {
if (state.isTorRunning()) enableNetwork(false);
} catch (IOException ex) {
logException(LOG, WARNING, ex);
}
});
updateConnectionStatus(networkManager.getNetworkStatus(),
batteryManager.isCharging());
}
private void updateConnectionStatus(NetworkStatus status, private void updateConnectionStatus(NetworkStatus status,
boolean charging) { boolean charging) {
connectionStatusExecutor.execute(() -> { connectionStatusExecutor.execute(() -> {
@@ -1008,6 +1104,13 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@GuardedBy("this") @GuardedBy("this")
private int reasonsDisabled = 0; private int reasonsDisabled = 0;
/**
* The number of consecutive successful (positive) or failed (negative)
* connections to our own hidden service.
*/
@GuardedBy("this")
private int networkStability = 0;
@GuardedBy("this") @GuardedBy("this")
@Nullable @Nullable
private ServerSocket serverSocket = null; private ServerSocket serverSocket = null;
@@ -1102,6 +1205,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
logOrConnections(); logOrConnections();
if (orConnectionsConnected == 0 && oldConnected != 0) { if (orConnectionsConnected == 0 && oldConnected != 0) {
resetNetworkStability();
callback.pluginStateChanged(getState()); callback.pluginStateChanged(getState());
} }
} }
@@ -1112,5 +1216,43 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
LOG.info(orConnectionsConnected + " OR connections connected"); LOG.info(orConnectionsConnected + " OR connections connected");
} }
} }
private synchronized boolean isNetworkStable() {
return networkStability >= STABLE_NETWORK_THRESHOLD;
}
private synchronized void onStabilityCheckSucceeded() {
if (networkStability <= 0) networkStability = 1;
else networkStability++;
logNetworkStability();
}
private synchronized void onStabilityCheckFailed() {
if (networkStability >= 0) networkStability = -1;
else networkStability--;
if (networkStability <= -BROKEN_NETWORK_THRESHOLD) {
LOG.warning("Connection to Tor appears to be broken");
resetNetworkStability();
disableAndReenableNetwork();
} else {
logNetworkStability();
}
}
private synchronized void resetNetworkStability() {
int old = networkStability;
networkStability = 0;
logNetworkStability();
if (old >= STABLE_NETWORK_THRESHOLD) {
callback.pollingIntervalDecreased();
}
}
@GuardedBy("this")
private void logNetworkStability() {
if (LOG.isLoggable(INFO)) {
LOG.info("Network stability score " + networkStability);
}
}
} }
} }

View File

@@ -6,8 +6,6 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TorControlPort; import org.briarproject.bramble.api.plugin.TorControlPort;
@@ -41,16 +39,12 @@ abstract class TorPluginFactory implements DuplexPluginFactory {
protected static final int MAX_LATENCY = 30 * 1000; // 30 seconds protected static final int MAX_LATENCY = 30 * 1000; // 30 seconds
protected static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds protected static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2;
protected final Executor ioExecutor, wakefulIoExecutor; protected final Executor ioExecutor, wakefulIoExecutor;
protected final NetworkManager networkManager; protected final NetworkManager networkManager;
protected final LocationUtils locationUtils; protected final LocationUtils locationUtils;
protected final EventBus eventBus; protected final EventBus eventBus;
protected final SocketFactory torSocketFactory; protected final SocketFactory torSocketFactory;
protected final BackoffFactory backoffFactory;
protected final ResourceProvider resourceProvider; protected final ResourceProvider resourceProvider;
protected final CircumventionProvider circumventionProvider; protected final CircumventionProvider circumventionProvider;
protected final BatteryManager batteryManager; protected final BatteryManager batteryManager;
@@ -66,7 +60,6 @@ abstract class TorPluginFactory implements DuplexPluginFactory {
LocationUtils locationUtils, LocationUtils locationUtils,
EventBus eventBus, EventBus eventBus,
SocketFactory torSocketFactory, SocketFactory torSocketFactory,
BackoffFactory backoffFactory,
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
@@ -81,7 +74,6 @@ abstract class TorPluginFactory implements DuplexPluginFactory {
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.eventBus = eventBus; this.eventBus = eventBus;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.backoffFactory = backoffFactory;
this.resourceProvider = resourceProvider; this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider; this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager; this.batteryManager = batteryManager;
@@ -95,7 +87,7 @@ abstract class TorPluginFactory implements DuplexPluginFactory {
@Nullable @Nullable
abstract String getArchitectureForTorBinary(); abstract String getArchitectureForTorBinary();
abstract TorPlugin createPluginInstance(Backoff backoff, abstract TorPlugin createPluginInstance(
TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback, TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback,
String architecture); String architecture);
@@ -122,11 +114,9 @@ abstract class TorPluginFactory implements DuplexPluginFactory {
LOG.info("The selected architecture for Tor is " + architecture); LOG.info("The selected architecture for Tor is " + architecture);
} }
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = TorRendezvousCrypto torRendezvousCrypto =
new TorRendezvousCryptoImpl(crypto); new TorRendezvousCryptoImpl(crypto);
TorPlugin plugin = createPluginInstance(backoff, torRendezvousCrypto, TorPlugin plugin = createPluginInstance(torRendezvousCrypto,
callback, architecture); callback, architecture);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;

View File

@@ -1,45 +1,69 @@
package org.briarproject.bramble.plugin; package org.briarproject.bramble.plugin;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.event.PollingIntervalDecreasedEvent;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
import static org.briarproject.bramble.test.TestUtils.getTransportId;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
public class BackoffImplTest extends BrambleTestCase { public class BackoffImplTest extends BrambleMockTestCase {
private final EventBus eventBus = context.mock(EventBus.class);
private final TransportId transportId = getTransportId();
private static final int MIN_INTERVAL = 60 * 1000; private static final int MIN_INTERVAL = 60 * 1000;
private static final int MAX_INTERVAL = 60 * 60 * 1000; private static final int MAX_INTERVAL = 60 * 60 * 1000;
private static final double BASE = 1.2; private static final double BASE = 1.2;
@Test @Test
public void testPollingIntervalStartsAtMinimum() { public void testPollingIntervalStartsAtMinimum() {
BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE); BackoffImpl b = new BackoffImpl(eventBus, transportId,
MIN_INTERVAL, MAX_INTERVAL, BASE);
assertEquals(MIN_INTERVAL, b.getPollingInterval()); assertEquals(MIN_INTERVAL, b.getPollingInterval());
} }
@Test @Test
public void testIncrementIncreasesPollingInterval() { public void testIncrementMethodIncreasesPollingInterval() {
BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE); BackoffImpl b = new BackoffImpl(eventBus, transportId,
MIN_INTERVAL, MAX_INTERVAL, BASE);
b.increment(); b.increment();
assertTrue(b.getPollingInterval() > MIN_INTERVAL); assertTrue(b.getPollingInterval() > MIN_INTERVAL);
} }
@Test @Test
public void testResetResetsPollingInterval() { public void testResetMethodResetsPollingInterval() {
BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE); BackoffImpl b = new BackoffImpl(eventBus, transportId,
b.increment(); MIN_INTERVAL, MAX_INTERVAL, BASE);
b.increment(); b.increment();
assertTrue(b.getPollingInterval() > MIN_INTERVAL);
context.checking(new Expectations() {{
oneOf(eventBus).broadcast(with(any(
PollingIntervalDecreasedEvent.class)));
}});
b.reset();
assertEquals(MIN_INTERVAL, b.getPollingInterval());
context.assertIsSatisfied();
// Resetting again should not broadcast another event
b.reset(); b.reset();
assertEquals(MIN_INTERVAL, b.getPollingInterval()); assertEquals(MIN_INTERVAL, b.getPollingInterval());
} }
@Test @Test
public void testBaseAffectsBackoffSpeed() { public void testBaseAffectsBackoffSpeed() {
BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE); BackoffImpl b = new BackoffImpl(eventBus, transportId,
MIN_INTERVAL, MAX_INTERVAL, BASE);
b.increment(); b.increment();
int interval = b.getPollingInterval(); int interval = b.getPollingInterval();
BackoffImpl b1 = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE * 2); BackoffImpl b1 = new BackoffImpl(eventBus, transportId, MIN_INTERVAL,
MAX_INTERVAL, BASE * 2);
b1.increment(); b1.increment();
int interval1 = b1.getPollingInterval(); int interval1 = b1.getPollingInterval();
assertTrue(interval < interval1); assertTrue(interval < interval1);
@@ -47,15 +71,16 @@ public class BackoffImplTest extends BrambleTestCase {
@Test @Test
public void testIntervalDoesNotExceedMaxInterval() { public void testIntervalDoesNotExceedMaxInterval() {
BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE); BackoffImpl b = new BackoffImpl(eventBus, transportId,
MIN_INTERVAL, MAX_INTERVAL, BASE);
for (int i = 0; i < 100; i++) b.increment(); for (int i = 0; i < 100; i++) b.increment();
assertEquals(MAX_INTERVAL, b.getPollingInterval()); assertEquals(MAX_INTERVAL, b.getPollingInterval());
} }
@Test @Test
public void testIntervalDoesNotExceedMaxIntervalWithInfiniteMultiplier() { public void testIntervalDoesNotExceedMaxIntervalWithInfiniteMultiplier() {
BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BackoffImpl b = new BackoffImpl(eventBus, transportId,
Double.POSITIVE_INFINITY); MIN_INTERVAL, MAX_INTERVAL, Double.POSITIVE_INFINITY);
b.increment(); b.increment();
assertEquals(MAX_INTERVAL, b.getPollingInterval()); assertEquals(MAX_INTERVAL, b.getPollingInterval());
} }

View File

@@ -13,7 +13,7 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent; import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent; import org.briarproject.bramble.api.plugin.event.PollingIntervalDecreasedEvent;
import org.briarproject.bramble.api.plugin.event.TransportActiveEvent; import org.briarproject.bramble.api.plugin.event.TransportActiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent; import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin; import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
@@ -35,7 +35,6 @@ import java.util.concurrent.Executor;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.bramble.test.CollectionMatcher.collectionOf; import static org.briarproject.bramble.test.CollectionMatcher.collectionOf;
@@ -217,7 +216,7 @@ public class PollerImplTest extends BrambleMockTestCase {
} }
@Test @Test
public void testRescheduleOnConnectionOpened() { public void testRescheduleOnPollingIntervalDecreased() {
Plugin plugin = context.mock(Plugin.class); Plugin plugin = context.mock(Plugin.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -240,8 +239,7 @@ public class PollerImplTest extends BrambleMockTestCase {
will(returnValue(cancellable)); will(returnValue(cancellable));
}}); }});
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId, poller.eventOccurred(new PollingIntervalDecreasedEvent(transportId));
false));
} }
@Test @Test
@@ -281,10 +279,8 @@ public class PollerImplTest extends BrambleMockTestCase {
will(returnValue(now + 1)); will(returnValue(now + 1));
}}); }});
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId, poller.eventOccurred(new PollingIntervalDecreasedEvent(transportId));
false)); poller.eventOccurred(new PollingIntervalDecreasedEvent(transportId));
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
false));
} }
@Test @Test
@@ -328,10 +324,8 @@ public class PollerImplTest extends BrambleMockTestCase {
with(MILLISECONDS)); with(MILLISECONDS));
}}); }});
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId, poller.eventOccurred(new PollingIntervalDecreasedEvent(transportId));
false)); poller.eventOccurred(new PollingIntervalDecreasedEvent(transportId));
poller.eventOccurred(new ConnectionOpenedEvent(contactId, transportId,
false));
} }
@Test @Test
@@ -378,48 +372,6 @@ public class PollerImplTest extends BrambleMockTestCase {
poller.eventOccurred(new TransportActiveEvent(transportId)); poller.eventOccurred(new TransportActiveEvent(transportId));
} }
@Test
public void testDoesNotPollIfAllContactsAreConnected() throws Exception {
DuplexPlugin plugin = context.mock(DuplexPlugin.class);
context.checking(new Expectations() {{
allowing(plugin).getId();
will(returnValue(transportId));
// Get the plugin
oneOf(pluginManager).getPlugin(transportId);
will(returnValue(plugin));
// The plugin supports polling
oneOf(plugin).shouldPoll();
will(returnValue(true));
// Schedule a polling task immediately
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(scheduler).schedule(with(any(Runnable.class)),
with(ioExecutor), with(0L), with(MILLISECONDS));
will(returnValue(cancellable));
will(new RunAction());
// Running the polling task schedules the next polling task
oneOf(plugin).getPollingInterval();
will(returnValue(pollingInterval));
oneOf(random).nextDouble();
will(returnValue(0.5));
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(scheduler).schedule(with(any(Runnable.class)),
with(ioExecutor), with((long) (pollingInterval * 0.5)),
with(MILLISECONDS));
will(returnValue(cancellable));
// Get the transport properties and connected contacts
oneOf(transportPropertyManager).getRemoteProperties(transportId);
will(returnValue(singletonMap(contactId, properties)));
oneOf(connectionRegistry).getConnectedOrBetterContacts(transportId);
will(returnValue(singletonList(contactId)));
// All contacts are connected, so don't poll the plugin
}});
poller.eventOccurred(new TransportActiveEvent(transportId));
}
@Test @Test
public void testCancelsPollingOnTransportDeactivated() { public void testCancelsPollingOnTransportDeactivated() {
Plugin plugin = context.mock(Plugin.class); Plugin plugin = context.mock(Plugin.class);

View File

@@ -342,6 +342,10 @@ public class LanTcpPluginTest extends BrambleTestCase {
public void pluginStateChanged(State newState) { public void pluginStateChanged(State newState) {
} }
@Override
public void pollingIntervalDecreased() {
}
@Override @Override
public void handleConnection(DuplexTransportConnection d) { public void handleConnection(DuplexTransportConnection d) {
connectionsLatch.countDown(); connectionsLatch.countDown();

View File

@@ -69,8 +69,8 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory {
BluetoothConnectionFactory<StreamConnection> connectionFactory = BluetoothConnectionFactory<StreamConnection> connectionFactory =
new JavaBluetoothConnectionFactory(connectionLimiter, new JavaBluetoothConnectionFactory(connectionLimiter,
timeoutMonitor); timeoutMonitor);
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(eventBus, ID,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE);
JavaBluetoothPlugin plugin = new JavaBluetoothPlugin(connectionLimiter, JavaBluetoothPlugin plugin = new JavaBluetoothPlugin(connectionLimiter,
connectionFactory, ioExecutor, wakefulIoExecutor, secureRandom, connectionFactory, ioExecutor, wakefulIoExecutor, secureRandom,
backoff, callback, MAX_LATENCY, MAX_IDLE_TIME); backoff, callback, MAX_LATENCY, MAX_IDLE_TIME);

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
@@ -29,7 +28,6 @@ abstract class JavaTorPlugin extends TorPlugin {
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, PluginCallback callback,
String architecture, String architecture,
@@ -40,7 +38,7 @@ abstract class JavaTorPlugin extends TorPlugin {
int torControlPort) { int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager,
torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory, torSocksPort, maxLatency, maxIdleTime, torDirectory, torSocksPort,
torControlPort); torControlPort);

View File

@@ -6,7 +6,6 @@ import com.sun.jna.Native;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
@@ -29,7 +28,6 @@ class UnixTorPlugin extends JavaTorPlugin {
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, PluginCallback callback,
String architecture, String architecture,
@@ -40,7 +38,7 @@ class UnixTorPlugin extends JavaTorPlugin {
int torControlPort) { int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager,
torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory, torSocksPort, maxLatency, maxIdleTime, torDirectory, torSocksPort,
torControlPort); torControlPort);

View File

@@ -6,8 +6,6 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorControlPort; import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory; import org.briarproject.bramble.api.plugin.TorDirectory;
@@ -39,7 +37,6 @@ public class UnixTorPluginFactory extends TorPluginFactory {
LocationUtils locationUtils, LocationUtils locationUtils,
EventBus eventBus, EventBus eventBus,
SocketFactory torSocketFactory, SocketFactory torSocketFactory,
BackoffFactory backoffFactory,
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
@@ -49,7 +46,7 @@ public class UnixTorPluginFactory extends TorPluginFactory {
@TorSocksPort int torSocksPort, @TorSocksPort int torSocksPort,
@TorControlPort int torControlPort) { @TorControlPort int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
eventBus, torSocketFactory, backoffFactory, resourceProvider, eventBus, torSocketFactory, resourceProvider,
circumventionProvider, batteryManager, clock, crypto, circumventionProvider, batteryManager, clock, crypto,
torDirectory, torSocksPort, torControlPort); torDirectory, torSocksPort, torControlPort);
} }
@@ -69,13 +66,13 @@ public class UnixTorPluginFactory extends TorPluginFactory {
} }
@Override @Override
TorPlugin createPluginInstance(Backoff backoff, TorPlugin createPluginInstance(TorRendezvousCrypto torRendezvousCrypto,
TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback, PluginCallback callback,
String architecture) { String architecture) {
return new UnixTorPlugin(ioExecutor, wakefulIoExecutor, return new UnixTorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory, clock, networkManager, locationUtils, torSocketFactory, clock,
resourceProvider, circumventionProvider, batteryManager, resourceProvider, circumventionProvider, batteryManager,
backoff, torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort, MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort,
torControlPort); torControlPort);
} }

View File

@@ -5,7 +5,6 @@ import com.sun.jna.platform.win32.Kernel32;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException; import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -34,7 +33,6 @@ class WindowsTorPlugin extends JavaTorPlugin {
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, PluginCallback callback,
String architecture, String architecture,
@@ -45,7 +43,7 @@ class WindowsTorPlugin extends JavaTorPlugin {
int torControlPort) { int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager,
torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory, torSocksPort, maxLatency, maxIdleTime, torDirectory, torSocksPort,
torControlPort); torControlPort);

View File

@@ -6,8 +6,6 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorControlPort; import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory; import org.briarproject.bramble.api.plugin.TorDirectory;
@@ -39,7 +37,6 @@ public class WindowsTorPluginFactory extends TorPluginFactory {
LocationUtils locationUtils, LocationUtils locationUtils,
EventBus eventBus, EventBus eventBus,
SocketFactory torSocketFactory, SocketFactory torSocketFactory,
BackoffFactory backoffFactory,
ResourceProvider resourceProvider, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
@@ -49,7 +46,7 @@ public class WindowsTorPluginFactory extends TorPluginFactory {
@TorSocksPort int torSocksPort, @TorSocksPort int torSocksPort,
@TorControlPort int torControlPort) { @TorControlPort int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
eventBus, torSocketFactory, backoffFactory, resourceProvider, eventBus, torSocketFactory, resourceProvider,
circumventionProvider, batteryManager, clock, crypto, circumventionProvider, batteryManager, clock, crypto,
torDirectory, torSocksPort, torControlPort); torDirectory, torSocksPort, torControlPort);
} }
@@ -67,13 +64,13 @@ public class WindowsTorPluginFactory extends TorPluginFactory {
} }
@Override @Override
TorPlugin createPluginInstance(Backoff backoff, TorPlugin createPluginInstance(TorRendezvousCrypto torRendezvousCrypto,
TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback, PluginCallback callback,
String architecture) { String architecture) {
return new WindowsTorPlugin(ioExecutor, wakefulIoExecutor, return new WindowsTorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory, clock, networkManager, locationUtils, torSocketFactory, clock,
resourceProvider, circumventionProvider, batteryManager, resourceProvider, circumventionProvider, batteryManager,
backoff, torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort, MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort,
torControlPort); torControlPort);
} }

View File

@@ -8,7 +8,6 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
@@ -110,8 +109,6 @@ public class BridgeTest extends BrambleTestCase {
@Inject @Inject
EventBus eventBus; EventBus eventBus;
@Inject @Inject
BackoffFactory backoffFactory;
@Inject
Clock clock; Clock clock;
@Inject @Inject
CryptoComponent crypto; CryptoComponent crypto;
@@ -166,9 +163,8 @@ public class BridgeTest extends BrambleTestCase {
}; };
factory = new UnixTorPluginFactory(ioExecutor, wakefulIoExecutor, factory = new UnixTorPluginFactory(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, eventBus, torSocketFactory, networkManager, locationUtils, eventBus, torSocketFactory,
backoffFactory, resourceProvider, bridgeProvider, resourceProvider, bridgeProvider, batteryManager, clock,
batteryManager, clock, crypto, torDir, crypto, torDir, SOCKS_PORT, CONTROL_PORT);
SOCKS_PORT, CONTROL_PORT);
} }
@After @After

View File

@@ -43,6 +43,10 @@ public class TestPluginCallback implements PluginCallback {
public void pluginStateChanged(State state) { public void pluginStateChanged(State state) {
} }
@Override
public void pollingIntervalDecreased() {
}
@Override @Override
public void handleConnection(DuplexTransportConnection c) { public void handleConnection(DuplexTransportConnection c) {
} }