From f2f278c3933ff22e789c16e3114af34a75639daf Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 8 May 2020 14:19:43 +0100 Subject: [PATCH] Add timeout monitor for Bluetooth connections. --- .../bluetooth/AndroidBluetoothPlugin.java | 20 ++--- .../AndroidBluetoothPluginFactory.java | 11 ++- .../AndroidBluetoothTransportConnection.java | 19 +++-- .../bramble/api/io/TimeoutMonitor.java | 8 ++ .../bramble/api/system/Clock.java | 5 ++ .../briarproject/bramble/test/ArrayClock.java | 5 ++ .../bramble/test/SettableClock.java | 5 ++ .../bramble/BrambleCoreModule.java | 2 + .../org/briarproject/bramble/io/IoModule.java | 18 +++++ .../bramble/io/TimeoutInputStream.java | 79 +++++++++++++++++++ .../bramble/io/TimeoutMonitorImpl.java | 71 +++++++++++++++++ .../plugin/bluetooth/BluetoothPlugin.java | 9 ++- .../bramble/system/SystemClock.java | 5 ++ .../bramble/db/JdbcDatabaseTest.java | 5 ++ .../bramble/plugin/DesktopPluginModule.java | 9 ++- .../plugin/bluetooth/JavaBluetoothPlugin.java | 17 ++-- .../bluetooth/JavaBluetoothPluginFactory.java | 13 +-- .../JavaBluetoothTransportConnection.java | 19 +++-- .../briarproject/briar/android/AppModule.java | 10 ++- 19 files changed, 280 insertions(+), 50 deletions(-) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/io/TimeoutMonitor.java create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/io/IoModule.java create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutInputStream.java create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java index 19fd8cb8c..9b121f09d 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothPlugin.java @@ -9,6 +9,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.plugin.Backoff; @@ -76,12 +77,12 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { private volatile BluetoothAdapter adapter = null; AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter, - Executor ioExecutor, AndroidExecutor androidExecutor, - Context appContext, SecureRandom secureRandom, Clock clock, - Backoff backoff, PluginCallback callback, int maxLatency, - int maxIdleTime) { - super(connectionLimiter, ioExecutor, secureRandom, backoff, callback, - maxLatency, maxIdleTime); + TimeoutMonitor timeoutMonitor, Executor ioExecutor, + SecureRandom secureRandom, AndroidExecutor androidExecutor, + Context appContext, Clock clock, Backoff backoff, + PluginCallback callback, int maxLatency, int maxIdleTime) { + super(connectionLimiter, timeoutMonitor, ioExecutor, secureRandom, + backoff, callback, maxLatency, maxIdleTime); this.androidExecutor = androidExecutor; this.appContext = appContext; this.clock = clock; @@ -173,9 +174,10 @@ class AndroidBluetoothPlugin extends BluetoothPlugin { return wrapSocket(ss.accept()); } - private DuplexTransportConnection wrapSocket(BluetoothSocket s) { - return new AndroidBluetoothTransportConnection(this, - connectionLimiter, s); + private DuplexTransportConnection wrapSocket(BluetoothSocket s) + throws IOException { + return new AndroidBluetoothTransportConnection(this, connectionLimiter, + timeoutMonitor, s); } @Override 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 f74967577..bbf2e2744 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 @@ -3,6 +3,7 @@ package org.briarproject.bramble.plugin.bluetooth; import android.content.Context; import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.BackoffFactory; @@ -36,18 +37,20 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { private final SecureRandom secureRandom; private final EventBus eventBus; private final Clock clock; + private final TimeoutMonitor timeoutMonitor; private final BackoffFactory backoffFactory; public AndroidBluetoothPluginFactory(Executor ioExecutor, AndroidExecutor androidExecutor, Context appContext, SecureRandom secureRandom, EventBus eventBus, Clock clock, - BackoffFactory backoffFactory) { + TimeoutMonitor timeoutMonitor, BackoffFactory backoffFactory) { this.ioExecutor = ioExecutor; this.androidExecutor = androidExecutor; this.appContext = appContext; this.secureRandom = secureRandom; this.eventBus = eventBus; this.clock = clock; + this.timeoutMonitor = timeoutMonitor; this.backoffFactory = backoffFactory; } @@ -68,9 +71,9 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin( - connectionLimiter, ioExecutor, androidExecutor, appContext, - secureRandom, clock, backoff, callback, MAX_LATENCY, - MAX_IDLE_TIME); + connectionLimiter, timeoutMonitor, ioExecutor, secureRandom, + androidExecutor, appContext, clock, backoff, + callback, MAX_LATENCY, MAX_IDLE_TIME); eventBus.addListener(plugin); return plugin; } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java index 226ad0330..bf6b3d69f 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/bluetooth/AndroidBluetoothTransportConnection.java @@ -2,6 +2,7 @@ package org.briarproject.bramble.plugin.bluetooth; import android.bluetooth.BluetoothSocket; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.Plugin; import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection; @@ -17,22 +18,26 @@ import static org.briarproject.bramble.util.AndroidUtils.isValidBluetoothAddress class AndroidBluetoothTransportConnection extends AbstractDuplexTransportConnection { - private final BluetoothConnectionLimiter connectionManager; + private final BluetoothConnectionLimiter connectionLimiter; private final BluetoothSocket socket; + private final InputStream in; AndroidBluetoothTransportConnection(Plugin plugin, - BluetoothConnectionLimiter connectionManager, - BluetoothSocket socket) { + BluetoothConnectionLimiter connectionLimiter, + TimeoutMonitor timeoutMonitor, BluetoothSocket socket) + throws IOException { super(plugin); - this.connectionManager = connectionManager; + this.connectionLimiter = connectionLimiter; this.socket = socket; + in = timeoutMonitor.createTimeoutInputStream( + socket.getInputStream(), plugin.getMaxIdleTime() * 2); String address = socket.getRemoteDevice().getAddress(); if (isValidBluetoothAddress(address)) remote.put(PROP_ADDRESS, address); } @Override - protected InputStream getInputStream() throws IOException { - return socket.getInputStream(); + protected InputStream getInputStream() { + return in; } @Override @@ -45,7 +50,7 @@ class AndroidBluetoothTransportConnection try { socket.close(); } finally { - connectionManager.connectionClosed(this); + connectionLimiter.connectionClosed(this); } } } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/io/TimeoutMonitor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/io/TimeoutMonitor.java new file mode 100644 index 000000000..04c1dc3cb --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/io/TimeoutMonitor.java @@ -0,0 +1,8 @@ +package org.briarproject.bramble.api.io; + +import java.io.InputStream; + +public interface TimeoutMonitor { + + InputStream createTimeoutInputStream(InputStream in, long timeoutMs); +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/system/Clock.java b/bramble-api/src/main/java/org/briarproject/bramble/api/system/Clock.java index 2b55c4196..a2b4fef41 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/system/Clock.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/system/Clock.java @@ -11,6 +11,11 @@ public interface Clock { */ long currentTimeMillis(); + /** + * @see System#nanoTime() + */ + long nanoTime(); + /** * @see Thread#sleep(long) */ diff --git a/bramble-api/src/test/java/org/briarproject/bramble/test/ArrayClock.java b/bramble-api/src/test/java/org/briarproject/bramble/test/ArrayClock.java index fc7c40e68..6b108bd82 100644 --- a/bramble-api/src/test/java/org/briarproject/bramble/test/ArrayClock.java +++ b/bramble-api/src/test/java/org/briarproject/bramble/test/ArrayClock.java @@ -16,6 +16,11 @@ public class ArrayClock implements Clock { return times[index++]; } + @Override + public long nanoTime() { + return times[index++] * 1_000_000; + } + @Override public void sleep(long milliseconds) throws InterruptedException { Thread.sleep(milliseconds); diff --git a/bramble-api/src/test/java/org/briarproject/bramble/test/SettableClock.java b/bramble-api/src/test/java/org/briarproject/bramble/test/SettableClock.java index 26f885de8..692465e41 100644 --- a/bramble-api/src/test/java/org/briarproject/bramble/test/SettableClock.java +++ b/bramble-api/src/test/java/org/briarproject/bramble/test/SettableClock.java @@ -17,6 +17,11 @@ public class SettableClock implements Clock { return time.get(); } + @Override + public long nanoTime() { + return time.get() * 1_000_000; + } + @Override public void sleep(long milliseconds) throws InterruptedException { Thread.sleep(milliseconds); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java index 6876c587a..d95b07e0a 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/BrambleCoreModule.java @@ -9,6 +9,7 @@ import org.briarproject.bramble.db.DatabaseExecutorModule; import org.briarproject.bramble.db.DatabaseModule; import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.identity.IdentityModule; +import org.briarproject.bramble.io.IoModule; import org.briarproject.bramble.keyagreement.KeyAgreementModule; import org.briarproject.bramble.lifecycle.LifecycleModule; import org.briarproject.bramble.plugin.PluginModule; @@ -35,6 +36,7 @@ import dagger.Module; DatabaseExecutorModule.class, EventModule.class, IdentityModule.class, + IoModule.class, KeyAgreementModule.class, LifecycleModule.class, PluginModule.class, diff --git a/bramble-core/src/main/java/org/briarproject/bramble/io/IoModule.java b/bramble-core/src/main/java/org/briarproject/bramble/io/IoModule.java new file mode 100644 index 000000000..f8aed8ae3 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/io/IoModule.java @@ -0,0 +1,18 @@ +package org.briarproject.bramble.io; + +import org.briarproject.bramble.api.io.TimeoutMonitor; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class IoModule { + + @Provides + @Singleton + TimeoutMonitor provideTimeoutMonitor(TimeoutMonitorImpl timeoutMonitor) { + return timeoutMonitor; + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutInputStream.java b/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutInputStream.java new file mode 100644 index 000000000..6ff8cf0e8 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutInputStream.java @@ -0,0 +1,79 @@ +package org.briarproject.bramble.io; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.system.Clock; + +import java.io.IOException; +import java.io.InputStream; + +import javax.annotation.concurrent.GuardedBy; + +@NotNullByDefault +class TimeoutInputStream extends InputStream { + + private final Clock clock; + private final InputStream in; + private final long timeoutNs; + private final CloseListener listener; + private final Object lock = new Object(); + @GuardedBy("lock") + private long readStartedNs = -1; + + TimeoutInputStream(Clock clock, InputStream in, long timeoutNs, + CloseListener listener) { + this.clock = clock; + this.in = in; + this.timeoutNs = timeoutNs; + this.listener = listener; + } + + @Override + public int read() throws IOException { + synchronized (lock) { + readStartedNs = clock.nanoTime(); + } + int input = in.read(); + synchronized (lock) { + readStartedNs = -1; + } + return input; + } + + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + synchronized (lock) { + readStartedNs = clock.nanoTime(); + } + int read = in.read(b, off, len); + synchronized (lock) { + readStartedNs = -1; + } + return read; + } + + @Override + public void close() throws IOException { + try { + in.close(); + } finally { + listener.onClose(this); + } + } + + boolean hasTimedOut() { + synchronized (lock) { + return readStartedNs != -1 && + clock.nanoTime() - readStartedNs > timeoutNs; + } + } + + interface CloseListener { + + void onClose(TimeoutInputStream closed); + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java new file mode 100644 index 000000000..0411e9c19 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/io/TimeoutMonitorImpl.java @@ -0,0 +1,71 @@ +package org.briarproject.bramble.io; + +import org.briarproject.bramble.api.io.TimeoutMonitor; +import org.briarproject.bramble.api.lifecycle.IoExecutor; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.bramble.api.system.Scheduler; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.logging.Level.INFO; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.util.LogUtils.logException; + +class TimeoutMonitorImpl implements TimeoutMonitor { + + private static final Logger LOG = + getLogger(TimeoutMonitorImpl.class.getName()); + + private static final long CHECK_INTERVAL_MS = SECONDS.toMillis(10); + + private final Executor ioExecutor; + private final Clock clock; + + private final List streams = + new CopyOnWriteArrayList<>(); + + @Inject + TimeoutMonitorImpl(@IoExecutor Executor ioExecutor, Clock clock, + @Scheduler ScheduledExecutorService scheduler) { + this.ioExecutor = ioExecutor; + this.clock = clock; + scheduler.scheduleWithFixedDelay(this::checkTimeouts, + CHECK_INTERVAL_MS, CHECK_INTERVAL_MS, MILLISECONDS); + } + + @Override + public InputStream createTimeoutInputStream(InputStream in, + long timeoutMs) { + TimeoutInputStream stream = new TimeoutInputStream(clock, in, + timeoutMs * 1_000_000, streams::remove); + streams.add(stream); + return stream; + } + + @Scheduler + private void checkTimeouts() { + ioExecutor.execute(() -> { + LOG.info("Checking input stream timeouts"); + for (TimeoutInputStream stream : streams) { + if (stream.hasTimedOut()) { + LOG.info("Input stream has timed out"); + try { + stream.close(); + } catch (IOException e) { + logException(LOG, INFO, e); + } + } + } + }); + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java index 1c574dd6b..cdee708a4 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java @@ -5,6 +5,7 @@ import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventListener; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection; import org.briarproject.bramble.api.keyagreement.KeyAgreementListener; import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent; @@ -60,6 +61,7 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { getLogger(BluetoothPlugin.class.getName()); final BluetoothConnectionLimiter connectionLimiter; + final TimeoutMonitor timeoutMonitor; private final Executor ioExecutor; private final SecureRandom secureRandom; @@ -105,10 +107,11 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { abstract DuplexTransportConnection discoverAndConnect(String uuid); BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter, - Executor ioExecutor, SecureRandom secureRandom, - Backoff backoff, PluginCallback callback, int maxLatency, - int maxIdleTime) { + TimeoutMonitor timeoutMonitor, Executor ioExecutor, + SecureRandom secureRandom, Backoff backoff, + PluginCallback callback, int maxLatency, int maxIdleTime) { this.connectionLimiter = connectionLimiter; + this.timeoutMonitor = timeoutMonitor; this.ioExecutor = ioExecutor; this.secureRandom = secureRandom; this.backoff = backoff; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/system/SystemClock.java b/bramble-core/src/main/java/org/briarproject/bramble/system/SystemClock.java index b1737ad80..648578a1a 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/system/SystemClock.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/system/SystemClock.java @@ -12,6 +12,11 @@ public class SystemClock implements Clock { return System.currentTimeMillis(); } + @Override + public long nanoTime() { + return System.nanoTime(); + } + @Override public void sleep(long milliseconds) throws InterruptedException { Thread.sleep(milliseconds); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index ac4231216..ef26a479c 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -2420,6 +2420,11 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { return time; } + @Override + public long nanoTime() { + return time * 1_000_000; + } + @Override public void sleep(long milliseconds) throws InterruptedException { Thread.sleep(milliseconds); diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java index 5b4cf7014..c00bd99d7 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/DesktopPluginModule.java @@ -1,6 +1,7 @@ package org.briarproject.bramble.plugin; import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.ShutdownManager; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -31,10 +32,10 @@ public class DesktopPluginModule extends PluginModule { PluginConfig getPluginConfig(@IoExecutor Executor ioExecutor, SecureRandom random, BackoffFactory backoffFactory, ReliabilityLayerFactory reliabilityFactory, - ShutdownManager shutdownManager, EventBus eventBus) { - DuplexPluginFactory bluetooth = - new JavaBluetoothPluginFactory(ioExecutor, random, eventBus, - backoffFactory); + ShutdownManager shutdownManager, EventBus eventBus, + TimeoutMonitor timeoutMonitor) { + DuplexPluginFactory bluetooth = new JavaBluetoothPluginFactory( + ioExecutor, random, eventBus, timeoutMonitor, backoffFactory); DuplexPluginFactory modem = new ModemPluginFactory(ioExecutor, reliabilityFactory); DuplexPluginFactory lan = new LanTcpPluginFactory(ioExecutor, diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java index 62fad72a8..ff9b7ee79 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothPlugin.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.plugin.bluetooth; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.plugin.Backoff; @@ -34,11 +35,11 @@ class JavaBluetoothPlugin extends BluetoothPlugin { private volatile LocalDevice localDevice = null; JavaBluetoothPlugin(BluetoothConnectionLimiter connectionManager, - Executor ioExecutor, SecureRandom secureRandom, - Backoff backoff, PluginCallback callback, int maxLatency, - int maxIdleTime) { - super(connectionManager, ioExecutor, secureRandom, backoff, callback, - maxLatency, maxIdleTime); + TimeoutMonitor timeoutMonitor, Executor ioExecutor, + SecureRandom secureRandom, Backoff backoff, + PluginCallback callback, int maxLatency, int maxIdleTime) { + super(connectionManager, timeoutMonitor, ioExecutor, secureRandom, + backoff, callback, maxLatency, maxIdleTime); } @Override @@ -120,7 +121,9 @@ class JavaBluetoothPlugin extends BluetoothPlugin { return "btspp://" + address + ":" + uuid + ";name=RFCOMM"; } - private DuplexTransportConnection wrapSocket(StreamConnection s) { - return new JavaBluetoothTransportConnection(this, connectionLimiter, s); + private DuplexTransportConnection wrapSocket(StreamConnection s) + throws IOException { + return new JavaBluetoothTransportConnection(this, connectionLimiter, + timeoutMonitor, s); } } 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 62e51c6c8..59fc25c86 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 @@ -1,6 +1,7 @@ package org.briarproject.bramble.plugin.bluetooth; import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.BackoffFactory; @@ -28,16 +29,18 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory { private final Executor ioExecutor; private final SecureRandom secureRandom; - private final BackoffFactory backoffFactory; private final EventBus eventBus; + private final TimeoutMonitor timeoutMonitor; + private final BackoffFactory backoffFactory; public JavaBluetoothPluginFactory(Executor ioExecutor, SecureRandom secureRandom, EventBus eventBus, - BackoffFactory backoffFactory) { + TimeoutMonitor timeoutMonitor, BackoffFactory backoffFactory) { this.ioExecutor = ioExecutor; this.secureRandom = secureRandom; - this.backoffFactory = backoffFactory; this.eventBus = eventBus; + this.timeoutMonitor = timeoutMonitor; + this.backoffFactory = backoffFactory; } @Override @@ -57,8 +60,8 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory { Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); JavaBluetoothPlugin plugin = new JavaBluetoothPlugin(connectionLimiter, - ioExecutor, secureRandom, backoff, callback, MAX_LATENCY, - MAX_IDLE_TIME); + timeoutMonitor, ioExecutor, secureRandom, backoff, callback, + MAX_LATENCY, MAX_IDLE_TIME); eventBus.addListener(plugin); return plugin; } diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java index 097c3c191..319d9af76 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/bluetooth/JavaBluetoothTransportConnection.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.plugin.bluetooth; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.Plugin; import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection; @@ -14,20 +15,24 @@ import javax.microedition.io.StreamConnection; class JavaBluetoothTransportConnection extends AbstractDuplexTransportConnection { - private final BluetoothConnectionLimiter connectionManager; + private final BluetoothConnectionLimiter connectionLimiter; private final StreamConnection stream; + private final InputStream in; JavaBluetoothTransportConnection(Plugin plugin, - BluetoothConnectionLimiter connectionManager, - StreamConnection stream) { + BluetoothConnectionLimiter connectionLimiter, + TimeoutMonitor timeoutMonitor, + StreamConnection stream) throws IOException { super(plugin); + this.connectionLimiter = connectionLimiter; this.stream = stream; - this.connectionManager = connectionManager; + in = timeoutMonitor.createTimeoutInputStream( + stream.openInputStream(), plugin.getMaxIdleTime() * 2); } @Override - protected InputStream getInputStream() throws IOException { - return stream.openInputStream(); + protected InputStream getInputStream() { + return in; } @Override @@ -40,7 +45,7 @@ class JavaBluetoothTransportConnection try { stream.close(); } finally { - connectionManager.connectionClosed(this); + connectionLimiter.connectionClosed(this); } } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index 07b37f2a8..b9e074897 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -14,6 +14,7 @@ import org.briarproject.bramble.api.crypto.KeyStrengthener; import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.io.TimeoutMonitor; import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.network.NetworkManager; @@ -122,11 +123,12 @@ public class AppModule { LocationUtils locationUtils, EventBus eventBus, ResourceProvider resourceProvider, CircumventionProvider circumventionProvider, - BatteryManager batteryManager, Clock clock) { + BatteryManager batteryManager, Clock clock, + TimeoutMonitor timeoutMonitor) { Context appContext = app.getApplicationContext(); - DuplexPluginFactory bluetooth = - new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor, - appContext, random, eventBus, clock, backoffFactory); + DuplexPluginFactory bluetooth = new AndroidBluetoothPluginFactory( + ioExecutor, androidExecutor, appContext, random, eventBus, + clock, timeoutMonitor, backoffFactory); DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor, scheduler, appContext, networkManager, locationUtils, eventBus, torSocketFactory, backoffFactory, resourceProvider,