From 3038b92dbc6857f4ee708d2942a7e908044250c3 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Sat, 16 Apr 2022 13:33:48 +0100 Subject: [PATCH] Poll less frequently when own hidden service is stable. --- .../AndroidBluetoothPluginFactory.java | 4 +- .../tcp/AndroidLanTcpPluginFactory.java | 4 +- .../bramble/api/plugin/BackoffFactory.java | 6 +- .../bramble/api/plugin/PluginCallback.java | 5 + .../event/PollingIntervalDecreasedEvent.java | 25 ++++ .../bramble/plugin/BackoffFactoryImpl.java | 9 +- .../bramble/plugin/BackoffImpl.java | 15 ++- .../bramble/plugin/PluginManagerImpl.java | 6 + .../bramble/plugin/PollerImpl.java | 16 ++- .../bluetooth/AbstractBluetoothPlugin.java | 2 +- .../plugin/tcp/LanTcpPluginFactory.java | 4 +- .../bramble/plugin/tcp/TcpPlugin.java | 2 +- .../plugin/tcp/WanTcpPluginFactory.java | 4 +- .../bramble/plugin/tor/TorPlugin.java | 113 +++++++++++++++++- .../bramble/plugin/BackoffImplTest.java | 51 ++++++-- .../bramble/plugin/tcp/LanTcpPluginTest.java | 4 + .../bluetooth/JavaBluetoothPluginFactory.java | 4 +- .../plugin/tor/TestPluginCallback.java | 4 + 18 files changed, 237 insertions(+), 41 deletions(-) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/PollingIntervalDecreasedEvent.java diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java index e3a274574..43fff15f5 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPluginFactory.java @@ -86,8 +86,8 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { BluetoothConnectionFactory connectionFactory = new AndroidBluetoothConnectionFactory(connectionLimiter, wakeLockManager, timeoutMonitor); - Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, - MAX_POLLING_INTERVAL, BACKOFF_BASE); + Backoff backoff = backoffFactory.createBackoff(eventBus, ID, + MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin( connectionLimiter, connectionFactory, ioExecutor, wakefulIoExecutor, secureRandom, androidExecutor, app, diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java index de3098113..a630b91dd 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java @@ -61,8 +61,8 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory { @Override public DuplexPlugin createPlugin(PluginCallback callback) { - Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, - MAX_POLLING_INTERVAL, BACKOFF_BASE); + Backoff backoff = backoffFactory.createBackoff(eventBus, ID, + MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor, wakefulIoExecutor, app, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME, CONNECTION_TIMEOUT); diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BackoffFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BackoffFactory.java index 0a60b5626..685d695c6 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BackoffFactory.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BackoffFactory.java @@ -1,7 +1,9 @@ package org.briarproject.bramble.api.plugin; +import org.briarproject.bramble.api.event.EventBus; + public interface BackoffFactory { - Backoff createBackoff(int minInterval, int maxInterval, - double base); + Backoff createBackoff(EventBus eventBus, TransportId transportId, + int minInterval, int maxInterval, double base); } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginCallback.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginCallback.java index 3c0f3ca4d..f2467056e 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginCallback.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/PluginCallback.java @@ -56,4 +56,9 @@ public interface PluginCallback extends ConnectionHandler { * This method can safely be called while holding a lock. */ void pluginStateChanged(State state); + + /** + * Informs the callback that the plugin's polling interval has decreased. + */ + void pollingIntervalDecreased(); } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/PollingIntervalDecreasedEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/PollingIntervalDecreasedEvent.java new file mode 100644 index 000000000..084808388 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/event/PollingIntervalDecreasedEvent.java @@ -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; + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java index 7640a9571..f0959dab9 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffFactoryImpl.java @@ -1,8 +1,10 @@ package org.briarproject.bramble.plugin; +import org.briarproject.bramble.api.event.EventBus; 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.TransportId; import javax.annotation.concurrent.Immutable; @@ -11,8 +13,9 @@ import javax.annotation.concurrent.Immutable; class BackoffFactoryImpl implements BackoffFactory { @Override - public Backoff createBackoff(int minInterval, int maxInterval, - double base) { - return new BackoffImpl(minInterval, maxInterval, base); + public Backoff createBackoff(EventBus eventBus, TransportId transportId, + int minInterval, int maxInterval, double base) { + return new BackoffImpl(eventBus, transportId, minInterval, maxInterval, + base); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffImpl.java index a4522cbb4..47d809a94 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/BackoffImpl.java @@ -1,7 +1,10 @@ package org.briarproject.bramble.plugin; +import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; 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; @@ -11,11 +14,16 @@ import javax.annotation.concurrent.ThreadSafe; @NotNullByDefault class BackoffImpl implements Backoff { + private final EventBus eventBus; + private final TransportId transportId; private final int minInterval, maxInterval; private final double base; 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.maxInterval = maxInterval; this.base = base; @@ -37,6 +45,9 @@ class BackoffImpl implements Backoff { @Override public void reset() { - backoff.set(0); + int old = backoff.getAndSet(0); + if (old > 0) { + eventBus.broadcast(new PollingIntervalDecreasedEvent(transportId)); + } } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java index ef03a78fd..63f9f74d2 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java @@ -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.DuplexPluginFactory; 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.TransportInactiveEvent; 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 public void handleConnection(DuplexTransportConnection d) { connectionManager.manageIncomingConnection(id, d); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java index 873a19e7a..493efee6f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PollerImpl.java @@ -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.DuplexTransportConnection; 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.TransportInactiveEvent; import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin; @@ -107,10 +107,14 @@ class PollerImpl implements Poller, EventListener { if (!c.isIncoming() && c.isException()) { connectToContact(c.getContactId(), c.getTransportId()); } - } else if (e instanceof ConnectionOpenedEvent) { - ConnectionOpenedEvent c = (ConnectionOpenedEvent) e; - // Reschedule polling, the polling interval may have decreased - reschedule(c.getTransportId()); + } else if (e instanceof PollingIntervalDecreasedEvent) { + PollingIntervalDecreasedEvent p = (PollingIntervalDecreasedEvent) e; + TransportId t = p.getTransportId(); + if (LOG.isLoggable(INFO)) { + LOG.info("Polling interval decreased for " + t); + } + // Reschedule polling + reschedule(t); } else if (e instanceof TransportActiveEvent) { TransportActiveEvent t = (TransportActiveEvent) e; // Poll the newly activated transport @@ -228,7 +232,7 @@ class PollerImpl implements Poller, EventListener { if (!connected.contains(c)) properties.add(new Pair<>(e.getValue(), new Handler(c, t))); } - if (!properties.isEmpty()) p.poll(properties); + p.poll(properties); } catch (DbException e) { logException(LOG, WARNING, e); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java index 1af124561..527626494 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/AbstractBluetoothPlugin.java @@ -335,7 +335,7 @@ abstract class AbstractBluetoothPlugin implements BluetoothPlugin, @Override public void poll(Collection> properties) { - if (getState() != ACTIVE) return; + if (properties.isEmpty() || getState() != ACTIVE) return; backoff.increment(); for (Pair p : properties) { connect(p.getFirst(), p.getSecond()); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java index 80f4fa1d0..783621af0 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java @@ -56,8 +56,8 @@ public class LanTcpPluginFactory implements DuplexPluginFactory { @Override public DuplexPlugin createPlugin(PluginCallback callback) { - Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, - MAX_POLLING_INTERVAL, BACKOFF_BASE); + Backoff backoff = backoffFactory.createBackoff(eventBus, ID, + MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); LanTcpPlugin plugin = new LanTcpPlugin(ioExecutor, wakefulIoExecutor, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME, CONNECTION_TIMEOUT); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java index baa050255..645197023 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java @@ -246,7 +246,7 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener { @Override public void poll(Collection> properties) { - if (getState() != ACTIVE) return; + if (properties.isEmpty() || getState() != ACTIVE) return; backoff.increment(); for (Pair p : properties) { connect(p.getFirst(), p.getSecond()); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java index 9468d6823..c2a476b10 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java @@ -60,8 +60,8 @@ public class WanTcpPluginFactory implements DuplexPluginFactory { @Override public DuplexPlugin createPlugin(PluginCallback callback) { - Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, - MAX_POLLING_INTERVAL, BACKOFF_BASE); + Backoff backoff = backoffFactory.createBackoff(eventBus, ID, + MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); PortMapper portMapper = new PortMapperImpl(shutdownManager); WanTcpPlugin plugin = new WanTcpPlugin(ioExecutor, wakefulIoExecutor, backoff, portMapper, callback, MAX_LATENCY, MAX_IDLE_TIME, diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java index a4f6e566d..76e0ee8c5 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java @@ -25,6 +25,7 @@ import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; 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.rendezvous.KeyMaterialSource; import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint; @@ -66,6 +67,7 @@ import javax.net.SocketFactory; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; 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.WARNING; import static java.util.logging.Logger.getLogger; @@ -123,6 +125,26 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private static final int COOKIE_POLLING_INTERVAL_MS = 200; private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}"); + /** + * After this many successful connections to our own hidden service we + * consider the network to be stable. + */ + private static final int STABILITY_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(5); + + /** + * 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; private final Executor wakefulIoExecutor; private final Executor connectionStatusExecutor; @@ -150,6 +172,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { private volatile Socket controlSocket = null; private volatile TorControlConnection controlConnection = null; private volatile Settings settings = null; + private volatile String ownOnion = null; protected abstract int getProcessId(); @@ -508,6 +531,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { return; } String onion3 = response.get(HS_ADDRESS); + ownOnion = onion3; if (LOG.isLoggable(INFO)) { LOG.info("V3 hidden service " + scrubOnion(onion3)); } @@ -612,13 +636,58 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { @Override public int getPollingInterval() { - return 120_000; // FIXME + 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 public void poll(Collection> properties) { if (getState() != ACTIVE) return; + 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.resetNetworkStability(); + // 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.incrementNetworkStability(); + } + }); + } + } + + private void pollContacts( + Collection> properties) { + if (properties.isEmpty() || getState() != ACTIVE) return; for (Pair p : properties) { connect(p.getFirst(), p.getSecond()); } @@ -776,6 +845,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { @Override public void message(String severity, String msg) { if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg); + if (msg.startsWith("Switching to guard context")) { + state.resetNetworkStability(); + } } @Override @@ -848,7 +920,15 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { @Override 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; if (s.getNamespace().equals(ID.getString())) { LOG.info("Tor settings updated"); @@ -991,7 +1071,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { settingsChecked = false; @GuardedBy("this") - private int reasonsDisabled = 0; + private int reasonsDisabled = 0, networkStability = 0; @GuardedBy("this") @Nullable @@ -1087,6 +1167,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { } logOrConnections(); if (orConnectionsConnected == 0 && oldConnected != 0) { + resetNetworkStability(); callback.pluginStateChanged(getState()); } } @@ -1097,5 +1178,31 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { LOG.info(orConnectionsConnected + " OR connections connected"); } } + + private synchronized boolean isNetworkStable() { + return networkStability >= STABILITY_THRESHOLD; + } + + private synchronized void incrementNetworkStability() { + networkStability++; + logNetworkStability(); + } + + private synchronized void resetNetworkStability() { + int old = networkStability; + networkStability = 0; + logNetworkStability(); + if (old >= STABILITY_THRESHOLD) { + callback.pollingIntervalDecreased(); + } + } + + @GuardedBy("this") + private void logNetworkStability() { + if (LOG.isLoggable(INFO)) { + LOG.info(networkStability + + " successful connections to own hidden service"); + } + } } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/BackoffImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/BackoffImplTest.java index 09bf49726..e1cdad011 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/BackoffImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/BackoffImplTest.java @@ -1,45 +1,69 @@ 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 static org.briarproject.bramble.test.TestUtils.getTransportId; import static org.junit.Assert.assertEquals; 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 MAX_INTERVAL = 60 * 60 * 1000; private static final double BASE = 1.2; @Test 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()); } @Test - public void testIncrementIncreasesPollingInterval() { - BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE); + public void testIncrementMethodIncreasesPollingInterval() { + BackoffImpl b = new BackoffImpl(eventBus, transportId, + MIN_INTERVAL, MAX_INTERVAL, BASE); b.increment(); assertTrue(b.getPollingInterval() > MIN_INTERVAL); } @Test - public void testResetResetsPollingInterval() { - BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, BASE); - b.increment(); + public void testResetMethodResetsPollingInterval() { + BackoffImpl b = new BackoffImpl(eventBus, transportId, + MIN_INTERVAL, MAX_INTERVAL, BASE); 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(); assertEquals(MIN_INTERVAL, b.getPollingInterval()); } @Test 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(); 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(); int interval1 = b1.getPollingInterval(); assertTrue(interval < interval1); @@ -47,15 +71,16 @@ public class BackoffImplTest extends BrambleTestCase { @Test 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(); assertEquals(MAX_INTERVAL, b.getPollingInterval()); } @Test public void testIntervalDoesNotExceedMaxIntervalWithInfiniteMultiplier() { - BackoffImpl b = new BackoffImpl(MIN_INTERVAL, MAX_INTERVAL, - Double.POSITIVE_INFINITY); + BackoffImpl b = new BackoffImpl(eventBus, transportId, + MIN_INTERVAL, MAX_INTERVAL, Double.POSITIVE_INFINITY); b.increment(); assertEquals(MAX_INTERVAL, b.getPollingInterval()); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java index cd560e3a6..7d0f8eb39 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java @@ -342,6 +342,10 @@ public class LanTcpPluginTest extends BrambleTestCase { public void pluginStateChanged(State newState) { } + @Override + public void pollingIntervalDecreased() { + } + @Override public void handleConnection(DuplexTransportConnection d) { connectionsLatch.countDown(); diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java index d7dbcfd11..fab1ffabe 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPluginFactory.java @@ -69,8 +69,8 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory { BluetoothConnectionFactory connectionFactory = new JavaBluetoothConnectionFactory(connectionLimiter, timeoutMonitor); - Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, - MAX_POLLING_INTERVAL, BACKOFF_BASE); + Backoff backoff = backoffFactory.createBackoff(eventBus, ID, + MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); JavaBluetoothPlugin plugin = new JavaBluetoothPlugin(connectionLimiter, connectionFactory, ioExecutor, wakefulIoExecutor, secureRandom, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME); diff --git a/bramble-java/src/test/java/org/briarproject/bramble/plugin/tor/TestPluginCallback.java b/bramble-java/src/test/java/org/briarproject/bramble/plugin/tor/TestPluginCallback.java index b25038bc8..d05de6c67 100644 --- a/bramble-java/src/test/java/org/briarproject/bramble/plugin/tor/TestPluginCallback.java +++ b/bramble-java/src/test/java/org/briarproject/bramble/plugin/tor/TestPluginCallback.java @@ -43,6 +43,10 @@ public class TestPluginCallback implements PluginCallback { public void pluginStateChanged(State state) { } + @Override + public void pollingIntervalDecreased() { + } + @Override public void handleConnection(DuplexTransportConnection c) { }