Ensure that Plugin instances aren't reused.

This commit is contained in:
akwizgran
2016-05-05 18:05:53 +01:00
parent 69f23ead9b
commit 2ecccc66d1
11 changed files with 153 additions and 35 deletions

View File

@@ -282,8 +282,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
public void showForumPostNotification(final GroupId g) {
androidExecutor.execute(new Runnable() {
@Override
public void
run() {
public void run() {
Integer count = forumCounts.get(g);
if (count == null) forumCounts.put(g, 1);
else forumCounts.put(g, count + 1);

View File

@@ -9,9 +9,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.keyagreement.KeyAgreementConnection;
@@ -41,6 +41,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
@@ -80,6 +81,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private final Backoff backoff;
private final DuplexPluginCallback callback;
private final int maxLatency;
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false;
private volatile boolean wasEnabledByUs = false;
@@ -101,24 +103,30 @@ class DroidtoothPlugin implements DuplexPlugin {
this.maxLatency = maxLatency;
}
@Override
public TransportId getId() {
return ID;
}
@Override
public int getMaxLatency() {
return maxLatency;
}
@Override
public int getMaxIdleTime() {
// Bluetooth detects dead connections so we don't need keepalives
return Integer.MAX_VALUE;
}
@Override
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
// with a message queue, so submit it to the AndroidExecutor
try {
adapter = androidExecutor.submit(new Callable<BluetoothAdapter>() {
@Override
public BluetoothAdapter call() throws Exception {
return BluetoothAdapter.getDefaultAdapter();
}
@@ -158,6 +166,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private void bind() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
if (!isRunning()) return;
String address = AndroidUtils.getBluetoothAddress(appContext,
@@ -238,6 +247,7 @@ class DroidtoothPlugin implements DuplexPlugin {
return new DroidtoothTransportConnection(this, s);
}
@Override
public void stop() {
running = false;
if (receiver != null) appContext.unregisterReceiver(receiver);
@@ -249,18 +259,22 @@ class DroidtoothPlugin implements DuplexPlugin {
}
}
@Override
public boolean isRunning() {
return running && adapter.isEnabled();
}
@Override
public boolean shouldPoll() {
return true;
}
@Override
public int getPollingInterval() {
return backoff.getPollingInterval();
}
@Override
public void poll(Collection<ContactId> connected) {
if (!isRunning()) return;
backoff.increment();
@@ -275,6 +289,7 @@ class DroidtoothPlugin implements DuplexPlugin {
final String uuid = e.getValue().get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) continue;
ioExecutor.execute(new Runnable() {
@Override
public void run() {
if (!running) return;
BluetoothSocket s = connect(address, uuid);
@@ -327,6 +342,7 @@ class DroidtoothPlugin implements DuplexPlugin {
}
}
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
@@ -340,10 +356,12 @@ class DroidtoothPlugin implements DuplexPlugin {
return new DroidtoothTransportConnection(this, s);
}
@Override
public boolean supportsInvitations() {
return true;
}
@Override
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
long timeout, boolean alice) {
if (!isRunning()) return null;
@@ -361,9 +379,8 @@ class DroidtoothPlugin implements DuplexPlugin {
}
// Create the background tasks
CompletionService<BluetoothSocket> complete =
new ExecutorCompletionService<BluetoothSocket>(ioExecutor);
List<Future<BluetoothSocket>> futures =
new ArrayList<Future<BluetoothSocket>>();
new ExecutorCompletionService<>(ioExecutor);
List<Future<BluetoothSocket>> futures = new ArrayList<>();
if (alice) {
// Return the first connected socket
futures.add(complete.submit(new ListeningTask(ss)));
@@ -398,6 +415,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private void closeSockets(final List<Future<BluetoothSocket>> futures,
final BluetoothSocket chosen) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
for (Future<BluetoothSocket> f : futures) {
try {
@@ -413,9 +431,7 @@ class DroidtoothPlugin implements DuplexPlugin {
} catch (InterruptedException e) {
LOG.info("Interrupted while closing sockets");
return;
} catch (ExecutionException e) {
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
} catch (IOException e) {
} catch (ExecutionException | IOException e) {
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
}
}
@@ -423,14 +439,15 @@ class DroidtoothPlugin implements DuplexPlugin {
});
}
@Override
public boolean supportsKeyAgreement() {
return true;
}
public KeyAgreementListener createKeyAgreementListener(
byte[] localCommitment) {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
// No truncation necessary because COMMIT_LENGTH = 16
UUID uuid = UUID.nameUUIDFromBytes(localCommitment);
UUID uuid = UUID.nameUUIDFromBytes(commitment);
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
// Bind a server socket for receiving invitation connections
BluetoothServerSocket ss;
@@ -448,8 +465,9 @@ class DroidtoothPlugin implements DuplexPlugin {
return new BluetoothKeyAgreementListener(d, ss);
}
@Override
public DuplexTransportConnection createKeyAgreementConnection(
byte[] remoteCommitment, TransportDescriptor d, long timeout) {
byte[] commitment, TransportDescriptor d, long timeout) {
if (!isRunning()) return null;
if (!ID.equals(d.getIdentifier())) return null;
TransportProperties p = d.getProperties();
@@ -457,7 +475,7 @@ class DroidtoothPlugin implements DuplexPlugin {
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
// No truncation necessary because COMMIT_LENGTH = 16
UUID uuid = UUID.nameUUIDFromBytes(remoteCommitment);
UUID uuid = UUID.nameUUIDFromBytes(commitment);
if (LOG.isLoggable(INFO))
LOG.info("Connecting to key agreement UUID " + uuid);
BluetoothSocket s = connect(address, uuid.toString());
@@ -533,7 +551,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private static class DiscoveryReceiver extends BroadcastReceiver {
private final CountDownLatch finished = new CountDownLatch(1);
private final List<String> addresses = new ArrayList<String>();
private final List<String> addresses = new ArrayList<>();
@Override
public void onReceive(Context ctx, Intent intent) {

View File

@@ -35,6 +35,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
@Override
public boolean start() {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();

View File

@@ -51,6 +51,7 @@ import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.zip.ZipInputStream;
@@ -94,6 +95,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile;
private final PowerManager.WakeLock wakeLock;
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false;
private volatile ServerSocket socket = null;
@@ -130,19 +132,24 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
wakeLock.setReferenceCounted(false);
}
@Override
public TransportId getId() {
return ID;
}
@Override
public int getMaxLatency() {
return maxLatency;
}
@Override
public int getMaxIdleTime() {
return maxIdleTime;
}
@Override
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
// Try to connect to an existing Tor process if there is one
boolean startProcess = false;
try {
@@ -369,6 +376,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void bind() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
// If there's already a port number stored in config, reuse it
String portString = callback.getSettings().get("port");
@@ -398,6 +406,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
callback.mergeSettings(s);
// Create a hidden service if necessary
ioExecutor.execute(new Runnable() {
@Override
public void run() {
publishHiddenService(localPort);
}
@@ -486,6 +495,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
@Override
public void stop() throws IOException {
running = false;
tryToClose(socket);
@@ -508,18 +518,22 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
wakeLock.release();
}
@Override
public boolean isRunning() {
return running && connectionStatus.isConnected();
}
@Override
public boolean shouldPoll() {
return true;
}
@Override
public int getPollingInterval() {
return backoff.getPollingInterval();
}
@Override
public void poll(Collection<ContactId> connected) {
if (!isRunning()) return;
backoff.increment();
@@ -530,6 +544,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void connectAndCallBack(final ContactId c) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
DuplexTransportConnection d = createConnection(c);
if (d != null) {
@@ -540,6 +555,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
});
}
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
@@ -566,29 +582,34 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
@Override
public boolean supportsInvitations() {
return false;
}
@Override
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
long timeout, boolean alice) {
throw new UnsupportedOperationException();
}
@Override
public boolean supportsKeyAgreement() {
return false;
}
public KeyAgreementListener createKeyAgreementListener(
byte[] commitment) {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
throw new UnsupportedOperationException();
}
@Override
public DuplexTransportConnection createKeyAgreementConnection(
byte[] commitment, TransportDescriptor d, long timeout) {
throw new UnsupportedOperationException();
}
@Override
public void circuitStatus(String status, String id, String path) {
if (status.equals("BUILT") &&
connectionStatus.getAndSetCircuitBuilt()) {
@@ -598,19 +619,24 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
@Override
public void streamStatus(String status, String id, String target) {
}
@Override
public void orConnStatus(String status, String orName) {
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
}
@Override
public void bandwidthUsed(long read, long written) {
}
@Override
public void newDescriptors(List<String> orList) {
}
@Override
public void message(String severity, String msg) {
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) {
@@ -621,6 +647,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
@Override
public void unrecognized(String type, String msg) {
if (type.equals("HS_DESC") && msg.startsWith("UPLOADED"))
LOG.info("Descriptor uploaded");
@@ -642,6 +669,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
@Override
public void eventOccurred(Event e) {
if (e instanceof SettingsUpdatedEvent) {
if (((SettingsUpdatedEvent) e).getNamespace().equals("tor")) {
@@ -653,6 +681,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void updateConnectionStatus() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
if (!running) return;

View File

@@ -14,6 +14,7 @@ import java.io.OutputStream;
import java.util.Collection;
import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
@@ -27,6 +28,7 @@ public abstract class FilePlugin implements SimplexPlugin {
protected final Executor ioExecutor;
protected final SimplexPluginCallback callback;
protected final int maxLatency;
protected final AtomicBoolean used = new AtomicBoolean(false);
protected volatile boolean running = false;
@@ -42,22 +44,27 @@ public abstract class FilePlugin implements SimplexPlugin {
this.maxLatency = maxLatency;
}
@Override
public int getMaxLatency() {
return maxLatency;
}
@Override
public int getMaxIdleTime() {
return Integer.MAX_VALUE; // We don't need keepalives
}
@Override
public boolean isRunning() {
return running;
}
@Override
public TransportConnectionReader createReader(ContactId c) {
return null;
}
@Override
public TransportConnectionWriter createWriter(ContactId c) {
if (!running) return null;
return createWriter(createConnectionFilename());
@@ -105,6 +112,7 @@ public abstract class FilePlugin implements SimplexPlugin {
this.file = file;
}
@Override
public void run() {
if (isPossibleConnectionFilename(file.getName())) {
try {

View File

@@ -22,6 +22,7 @@ class LanTcpPlugin extends TcpPlugin {
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
}
@Override
public TransportId getId() {
return ID;
}

View File

@@ -25,6 +25,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import java.util.regex.Pattern;
@@ -42,6 +43,7 @@ abstract class TcpPlugin implements DuplexPlugin {
protected final Backoff backoff;
protected final DuplexPluginCallback callback;
protected final int maxLatency, maxIdleTime, socketTimeout;
protected final AtomicBoolean used = new AtomicBoolean(false);
protected volatile boolean running = false;
protected volatile ServerSocket socket = null;
@@ -67,15 +69,19 @@ abstract class TcpPlugin implements DuplexPlugin {
else socketTimeout = maxIdleTime * 2;
}
@Override
public int getMaxLatency() {
return maxLatency;
}
@Override
public int getMaxIdleTime() {
return maxIdleTime;
}
@Override
public boolean start() {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
bind();
return true;
@@ -83,6 +89,7 @@ abstract class TcpPlugin implements DuplexPlugin {
protected void bind() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
if (!running) return;
ServerSocket ss = null;
@@ -158,23 +165,28 @@ abstract class TcpPlugin implements DuplexPlugin {
}
}
@Override
public void stop() {
running = false;
tryToClose(socket);
}
@Override
public boolean isRunning() {
return running && socket != null && !socket.isClosed();
}
@Override
public boolean shouldPoll() {
return true;
}
@Override
public int getPollingInterval() {
return backoff.getPollingInterval();
}
@Override
public void poll(Collection<ContactId> connected) {
if (!isRunning()) return;
backoff.increment();
@@ -185,6 +197,7 @@ abstract class TcpPlugin implements DuplexPlugin {
private void connectAndCallBack(final ContactId c) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
DuplexTransportConnection d = createConnection(c);
if (d != null) {
@@ -195,6 +208,7 @@ abstract class TcpPlugin implements DuplexPlugin {
});
}
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!isRunning()) return null;
InetSocketAddress remote = getRemoteSocketAddress(c);
@@ -243,24 +257,28 @@ abstract class TcpPlugin implements DuplexPlugin {
}
}
@Override
public boolean supportsInvitations() {
return false;
}
@Override
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
long timeout, boolean alice) {
throw new UnsupportedOperationException();
}
@Override
public boolean supportsKeyAgreement() {
return false;
}
public KeyAgreementListener createKeyAgreementListener(
byte[] commitment) {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
throw new UnsupportedOperationException();
}
@Override
public DuplexTransportConnection createKeyAgreementConnection(
byte[] commitment, TransportDescriptor d, long timeout) {
throw new UnsupportedOperationException();

View File

@@ -27,6 +27,7 @@ class WanTcpPlugin extends TcpPlugin {
this.portMapper = portMapper;
}
@Override
public TransportId getId() {
return ID;
}

View File

@@ -30,6 +30,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.bluetooth.BluetoothStateException;
@@ -62,6 +63,7 @@ class BluetoothPlugin implements DuplexPlugin {
private final DuplexPluginCallback callback;
private final int maxLatency;
private final Semaphore discoverySemaphore = new Semaphore(1);
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false;
private volatile StreamConnectionNotifier socket = null;
@@ -76,20 +78,25 @@ class BluetoothPlugin implements DuplexPlugin {
this.maxLatency = maxLatency;
}
@Override
public TransportId getId() {
return ID;
}
@Override
public int getMaxLatency() {
return maxLatency;
}
@Override
public int getMaxIdleTime() {
// Bluetooth detects dead connections so we don't need keepalives
return Integer.MAX_VALUE;
}
@Override
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
// Initialise the Bluetooth stack
try {
localDevice = LocalDevice.getLocalDevice();
@@ -108,6 +115,7 @@ class BluetoothPlugin implements DuplexPlugin {
private void bind() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
if (!running) return;
// Advertise the Bluetooth address to contacts
@@ -183,23 +191,28 @@ class BluetoothPlugin implements DuplexPlugin {
return new BluetoothTransportConnection(this, s);
}
@Override
public void stop() {
running = false;
tryToClose(socket);
}
@Override
public boolean isRunning() {
return running;
}
@Override
public boolean shouldPoll() {
return true;
}
@Override
public int getPollingInterval() {
return backoff.getPollingInterval();
}
@Override
public void poll(final Collection<ContactId> connected) {
if (!running) return;
backoff.increment();
@@ -214,6 +227,7 @@ class BluetoothPlugin implements DuplexPlugin {
final String uuid = e.getValue().get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) continue;
ioExecutor.execute(new Runnable() {
@Override
public void run() {
if (!running) return;
StreamConnection s = connect(makeUrl(address, uuid));
@@ -238,6 +252,7 @@ class BluetoothPlugin implements DuplexPlugin {
}
}
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!running) return null;
TransportProperties p = callback.getRemoteProperties().get(c);
@@ -252,10 +267,12 @@ class BluetoothPlugin implements DuplexPlugin {
return new BluetoothTransportConnection(this, s);
}
@Override
public boolean supportsInvitations() {
return true;
}
@Override
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
long timeout, boolean alice) {
if (!running) return null;
@@ -279,9 +296,8 @@ class BluetoothPlugin implements DuplexPlugin {
}
// Create the background tasks
CompletionService<StreamConnection> complete =
new ExecutorCompletionService<StreamConnection>(ioExecutor);
List<Future<StreamConnection>> futures =
new ArrayList<Future<StreamConnection>>();
new ExecutorCompletionService<>(ioExecutor);
List<Future<StreamConnection>> futures = new ArrayList<>();
if (alice) {
// Return the first connected socket
futures.add(complete.submit(new ListeningTask(ss)));
@@ -316,6 +332,7 @@ class BluetoothPlugin implements DuplexPlugin {
private void closeSockets(final List<Future<StreamConnection>> futures,
final StreamConnection chosen) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
for (Future<StreamConnection> f : futures) {
try {
@@ -331,9 +348,7 @@ class BluetoothPlugin implements DuplexPlugin {
} catch (InterruptedException e) {
LOG.info("Interrupted while closing sockets");
return;
} catch (ExecutionException e) {
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
} catch (IOException e) {
} catch (ExecutionException | IOException e) {
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
}
}
@@ -341,14 +356,15 @@ class BluetoothPlugin implements DuplexPlugin {
});
}
@Override
public boolean supportsKeyAgreement() {
return true;
}
public KeyAgreementListener createKeyAgreementListener(
byte[] localCommitment) {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
// No truncation necessary because COMMIT_LENGTH = 16
String uuid = UUID.nameUUIDFromBytes(localCommitment).toString();
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
String url = makeUrl("localhost", uuid);
// Make the device discoverable if possible
@@ -371,8 +387,9 @@ class BluetoothPlugin implements DuplexPlugin {
return new BluetoothKeyAgreementListener(d, ss);
}
@Override
public DuplexTransportConnection createKeyAgreementConnection(
byte[] remoteCommitment, TransportDescriptor d, long timeout) {
byte[] commitment, TransportDescriptor d, long timeout) {
if (!isRunning()) return null;
if (!ID.equals(d.getIdentifier())) return null;
TransportProperties p = d.getProperties();
@@ -380,7 +397,7 @@ class BluetoothPlugin implements DuplexPlugin {
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
// No truncation necessary because COMMIT_LENGTH = 16
String uuid = UUID.nameUUIDFromBytes(remoteCommitment).toString();
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
if (LOG.isLoggable(INFO))
LOG.info("Connecting to key agreement UUID " + uuid);
String url = makeUrl(address, uuid);

View File

@@ -34,29 +34,36 @@ implements RemovableDriveMonitor.Callback {
this.monitor = monitor;
}
@Override
public TransportId getId() {
return ID;
}
@Override
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
monitor.start(this);
return true;
}
@Override
public void stop() throws IOException {
running = false;
monitor.stop();
}
@Override
public boolean shouldPoll() {
return false;
}
@Override
public int getPollingInterval() {
throw new UnsupportedOperationException();
}
@Override
public void poll(Collection<ContactId> connected) {
throw new UnsupportedOperationException();
}
@@ -64,8 +71,7 @@ implements RemovableDriveMonitor.Callback {
@Override
protected File chooseOutputDirectory() {
try {
List<File> drives =
new ArrayList<File>(finder.findRemovableDrives());
List<File> drives = new ArrayList<>(finder.findRemovableDrives());
if (drives.isEmpty()) return null;
String[] paths = new String[drives.size()];
for (int i = 0; i < paths.length; i++) {
@@ -92,7 +98,7 @@ implements RemovableDriveMonitor.Callback {
@Override
protected Collection<File> findFilesByName(String filename) {
List<File> matches = new ArrayList<File>();
List<File> matches = new ArrayList<>();
try {
for (File drive : finder.findRemovableDrives()) {
File[] files = drive.listFiles();
@@ -109,6 +115,7 @@ implements RemovableDriveMonitor.Callback {
return Collections.unmodifiableList(matches);
}
@Override
public void driveInserted(File root) {
File[] files = root.listFiles();
if (files != null) {
@@ -116,6 +123,7 @@ implements RemovableDriveMonitor.Callback {
}
}
@Override
public void exceptionThrown(IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}

View File

@@ -16,6 +16,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
@@ -32,6 +33,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private final SerialPortList serialPortList;
private final DuplexPluginCallback callback;
private final int maxLatency;
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false;
private volatile Modem modem = null;
@@ -44,20 +46,25 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
this.maxLatency = maxLatency;
}
@Override
public TransportId getId() {
return ID;
}
@Override
public int getMaxLatency() {
return maxLatency;
}
@Override
public int getMaxIdleTime() {
// FIXME: Do we need keepalives for this transport?
return Integer.MAX_VALUE;
}
@Override
public boolean start() {
if (used.getAndSet(true)) throw new IllegalStateException();
for (String portName : serialPortList.getPortNames()) {
if (LOG.isLoggable(INFO))
LOG.info("Trying to initialise modem on " + portName);
@@ -75,6 +82,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
return false;
}
@Override
public void stop() {
running = false;
if (modem != null) {
@@ -86,18 +94,22 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
}
}
@Override
public boolean isRunning() {
return running;
}
@Override
public boolean shouldPoll() {
return false;
}
@Override
public int getPollingInterval() {
throw new UnsupportedOperationException();
}
@Override
public void poll(Collection<ContactId> connected) {
throw new UnsupportedOperationException();
}
@@ -121,6 +133,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
return false;
}
@Override
public DuplexTransportConnection createConnection(ContactId c) {
if (!running) return null;
// Get the ISO 3166 code for the caller's country
@@ -148,29 +161,34 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
return new ModemTransportConnection();
}
@Override
public boolean supportsInvitations() {
return false;
}
@Override
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
long timeout, boolean alice) {
throw new UnsupportedOperationException();
}
@Override
public boolean supportsKeyAgreement() {
return false;
}
public KeyAgreementListener createKeyAgreementListener(
byte[] commitment) {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
throw new UnsupportedOperationException();
}
@Override
public DuplexTransportConnection createKeyAgreementConnection(
byte[] commitment, TransportDescriptor d, long timeout) {
throw new UnsupportedOperationException();
}
@Override
public void incomingCallConnected() {
LOG.info("Incoming call connected");
callback.incomingConnectionCreated(new ModemTransportConnection());