diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityChecker.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityChecker.java index 921557027..d0a6ab57d 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityChecker.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityChecker.java @@ -22,10 +22,21 @@ interface ConnectivityChecker { * the check succeeds. If a check is already running then the observer is * called when the check succeeds. If a connectivity check has recently * succeeded then the observer is called immediately. + *

+ * Observers are removed after being called, or when the checker is + * {@link #destroy() destroyed}. */ void checkConnectivity(MailboxProperties properties, ConnectivityObserver o); + /** + * Removes an observer that was added via + * {@link #checkConnectivity(MailboxProperties, ConnectivityObserver)}. If + * there are no remaining observers and a connectivity check is running + * then the check will be cancelled. + */ + void removeObserver(ConnectivityObserver o); + interface ConnectivityObserver { void onConnectivityCheckSucceeded(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImpl.java index 1468c5db1..aa3e97930 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImpl.java @@ -80,8 +80,7 @@ abstract class ConnectivityCheckerImpl implements ConnectivityChecker { > CONNECTIVITY_CHECK_FRESHNESS_MS) { // The last connectivity check is stale, start a new one connectivityObservers.add(o); - ApiCall task = - createConnectivityCheckTask(properties); + ApiCall task = createConnectivityCheckTask(properties); connectivityCheck = mailboxApiCaller.retryWithBackoff(task); } else { // The last connectivity check is fresh @@ -108,4 +107,16 @@ abstract class ConnectivityCheckerImpl implements ConnectivityChecker { o.onConnectivityCheckSucceeded(); } } + + @Override + public void removeObserver(ConnectivityObserver o) { + synchronized (lock) { + if (destroyed) return; + connectivityObservers.remove(o); + if (connectivityObservers.isEmpty() && connectivityCheck != null) { + connectivityCheck.cancel(); + connectivityCheck = null; + } + } + } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitor.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitor.java index c6b86d88a..5dd10b365 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitor.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitor.java @@ -38,6 +38,12 @@ interface TorReachabilityMonitor { */ void addOneShotObserver(TorReachabilityObserver o); + /** + * Removes an observer that was added via + * {@link #addOneShotObserver(TorReachabilityObserver)}. + */ + void removeObserver(TorReachabilityObserver o); + interface TorReachabilityObserver { void onTorReachable(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitorImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitorImpl.java index fa16682b3..8620aee01 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitorImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/TorReachabilityMonitorImpl.java @@ -87,6 +87,14 @@ class TorReachabilityMonitorImpl if (callNow) o.onTorReachable(); } + @Override + public void removeObserver(TorReachabilityObserver o) { + synchronized (lock) { + if (destroyed) return; + observers.remove(o); + } + } + @Override public void eventOccurred(Event e) { if (e instanceof TransportActiveEvent) { diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImplTest.java index 09fb0df5b..a476ec552 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/ConnectivityCheckerImplTest.java @@ -187,6 +187,32 @@ public class ConnectivityCheckerImplTest extends BrambleMockTestCase { checker.onConnectivityCheckSucceeded(now); } + @Test + public void testCheckIsCancelledWhenObserverIsRemoved() { + ConnectivityCheckerImpl checker = createChecker(); + + // When checkConnectivity() is called a check should be started + context.checking(new Expectations() {{ + oneOf(clock).currentTimeMillis(); + will(returnValue(now)); + oneOf(mailboxApiCaller).retryWithBackoff(apiCall); + will(returnValue(task)); + }}); + + checker.checkConnectivity(properties, observer1); + + // When the observer is removed the check should be cancelled + context.checking(new Expectations() {{ + oneOf(task).cancel(); + }}); + + checker.removeObserver(observer1); + + // If the check runs anyway (cancellation came too late) the observer + // should not be called + checker.onConnectivityCheckSucceeded(now); + } + private ConnectivityCheckerImpl createChecker() { return new ConnectivityCheckerImpl(clock, mailboxApiCaller) {