Added null safety annotations to plugin interfaces.

This commit is contained in:
akwizgran
2016-11-08 16:59:56 +00:00
parent 04d4ecad05
commit d2a3804cfe
14 changed files with 119 additions and 42 deletions

View File

@@ -18,6 +18,8 @@ import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.keyagreement.KeyAgreementConnection;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
@@ -25,6 +27,7 @@ import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.properties.TransportProperties;
import org.briarproject.util.StringUtils;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
@@ -63,6 +66,8 @@ import static java.util.logging.Level.WARNING;
import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
import static org.briarproject.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class DroidtoothPlugin implements DuplexPlugin {
// Share an ID with the J2SE Bluetooth plugin
@@ -221,7 +226,7 @@ class DroidtoothPlugin implements DuplexPlugin {
return UUID.fromString(uuid);
}
private void tryToClose(BluetoothServerSocket ss) {
private void tryToClose(@Nullable BluetoothServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
@@ -344,9 +349,9 @@ class DroidtoothPlugin implements DuplexPlugin {
}
}
private void tryToClose(BluetoothSocket s) {
private void tryToClose(@Nullable Closeable c) {
try {
if (s != null) s.close();
if (c != null) c.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
@@ -424,7 +429,7 @@ class DroidtoothPlugin implements DuplexPlugin {
}
private void closeSockets(final List<Future<BluetoothSocket>> futures,
final BluetoothSocket chosen) {
@Nullable final BluetoothSocket chosen) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
@@ -458,6 +463,9 @@ class DroidtoothPlugin implements DuplexPlugin {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
if (!isRunning()) return null;
// There's no point listening if we can't discover our own address
String address = AndroidUtils.getBluetoothAddress(appContext, adapter);
if (address.isEmpty()) return null;
// No truncation necessary because COMMIT_LENGTH = 16
UUID uuid = UUID.nameUUIDFromBytes(commitment);
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
@@ -472,8 +480,7 @@ class DroidtoothPlugin implements DuplexPlugin {
}
BdfList descriptor = new BdfList();
descriptor.add(TRANSPORT_ID_BLUETOOTH);
String address = AndroidUtils.getBluetoothAddress(appContext, adapter);
if (!address.isEmpty()) descriptor.add(StringUtils.macToBytes(address));
descriptor.add(StringUtils.macToBytes(address));
return new BluetoothKeyAgreementListener(descriptor, ss);
}
@@ -488,7 +495,6 @@ class DroidtoothPlugin implements DuplexPlugin {
LOG.info("Invalid address in key agreement descriptor");
return null;
}
if (address == null) return null;
// No truncation necessary because COMMIT_LENGTH = 16
UUID uuid = UUID.nameUUIDFromBytes(commitment);
if (LOG.isLoggable(INFO))
@@ -498,9 +504,7 @@ class DroidtoothPlugin implements DuplexPlugin {
return new DroidtoothTransportConnection(this, s);
}
@Nullable
private String parseAddress(BdfList descriptor) throws FormatException {
if (descriptor.size() < 2) return null;
byte[] mac = descriptor.getRaw(1);
if (mac.length != 6) throw new FormatException();
return StringUtils.macToString(mac);

View File

@@ -7,16 +7,20 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
@NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin {
private static final Logger LOG =
@@ -24,6 +28,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
private final Context appContext;
@Nullable
private volatile BroadcastReceiver networkStateReceiver = null;
AndroidLanTcpPlugin(Executor ioExecutor, Backoff backoff,

View File

@@ -24,6 +24,7 @@ import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.SettingsUpdatedEvent;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.TorConstants;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
@@ -60,6 +61,7 @@ import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import javax.net.SocketFactory;
import static android.content.Context.CONNECTIVITY_SERVICE;
@@ -76,6 +78,7 @@ import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
import static org.briarproject.api.plugins.TorConstants.CONTROL_PORT;
import static org.briarproject.util.PrivacyUtils.scrubOnion;
@NotNullByDefault
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final String PROP_ONION = "onion";
@@ -104,9 +107,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false;
@Nullable
private volatile ServerSocket socket = null;
@Nullable
private volatile Socket controlSocket = null;
@Nullable
private volatile TorControlConnection controlConnection = null;
@Nullable
private volatile BroadcastReceiver networkStateReceiver = null;
TorPlugin(Executor ioExecutor, Context appContext,
@@ -289,7 +296,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return appContext.getResources().getAssets().open("torrc");
}
private void tryToClose(Closeable c) {
private void tryToClose(@Nullable Closeable c) {
try {
if (c != null) c.close();
} catch (IOException e) {
@@ -297,7 +304,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
private void tryToClose(Socket s) {
private void tryToClose(@Nullable Socket s) {
try {
if (s != null) s.close();
} catch (IOException e) {
@@ -385,7 +392,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
});
}
private void tryToClose(ServerSocket ss) {
private void tryToClose(@Nullable ServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {

View File

@@ -2,28 +2,42 @@ package org.briarproject.api.plugins;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.util.Collection;
@NotNullByDefault
public interface Plugin {
/** Returns the plugin's transport identifier. */
/**
* Returns the plugin's transport identifier.
*/
TransportId getId();
/** Returns the transport's maximum latency in milliseconds. */
/**
* Returns the transport's maximum latency in milliseconds.
*/
int getMaxLatency();
/** Returns the transport's maximum idle time in milliseconds. */
/**
* Returns the transport's maximum idle time in milliseconds.
*/
int getMaxIdleTime();
/** Starts the plugin and returns true if it started successfully. */
/**
* Starts the plugin and returns true if it started successfully.
*/
boolean start() throws IOException;
/** Stops the plugin. */
/**
* Stops the plugin.
*/
void stop() throws IOException;
/** Returns true if the plugin is running. */
/**
* Returns true if the plugin is running.
*/
boolean isRunning();
/**

View File

@@ -4,19 +4,28 @@ import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.Plugin;
/** An interface for transport plugins that support duplex communication. */
import javax.annotation.Nullable;
/**
* An interface for transport plugins that support duplex communication.
*/
@NotNullByDefault
public interface DuplexPlugin extends Plugin {
/**
* Attempts to create and return a connection to the given contact using
* the current transport and configuration properties. Returns null if a
* connection could not be created.
* connection cannot be created.
*/
@Nullable
DuplexTransportConnection createConnection(ContactId c);
/** Returns true if the plugin supports exchanging invitations. */
/**
* Returns true if the plugin supports exchanging invitations.
*/
boolean supportsInvitations();
/**
@@ -24,21 +33,27 @@ public interface DuplexPlugin extends Plugin {
* peer. Returns null if no connection can be established within the given
* time.
*/
@Nullable
DuplexTransportConnection createInvitationConnection(PseudoRandom r,
long timeout, boolean alice);
/** Returns true if the plugin supports short-range key agreement. */
/**
* Returns true if the plugin supports short-range key agreement.
*/
boolean supportsKeyAgreement();
/**
* Returns a listener that can be used to perform key agreement.
* Attempts to create and return a listener that can be used to perform key
* agreement. Returns null if a listener cannot be created.
*/
@Nullable
KeyAgreementListener createKeyAgreementListener(byte[] localCommitment);
/**
* Attempts to connect to the remote peer specified in the given descriptor.
* Returns null if no connection can be established within the given time.
*/
@Nullable
DuplexTransportConnection createKeyAgreementConnection(
byte[] remoteCommitment, BdfList descriptor, long timeout);
}

View File

@@ -1,24 +1,32 @@
package org.briarproject.api.plugins.simplex;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.TransportConnectionReader;
import org.briarproject.api.plugins.TransportConnectionWriter;
/** An interface for transport plugins that support simplex communication. */
import javax.annotation.Nullable;
/**
* An interface for transport plugins that support simplex communication.
*/
@NotNullByDefault
public interface SimplexPlugin extends Plugin {
/**
* Attempts to create and return a reader for the given contact using the
* current transport and configuration properties. Returns null if a reader
* could not be created.
* cannot be created.
*/
@Nullable
TransportConnectionReader createReader(ContactId c);
/**
* Attempts to create and return a writer for the given contact using the
* current transport and configuration properties. Returns null if a writer
* could not be created.
* cannot be created.
*/
@Nullable
TransportConnectionWriter createWriter(ContactId c);
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.plugins.file;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.TransportConnectionReader;
import org.briarproject.api.plugins.TransportConnectionWriter;
import org.briarproject.api.plugins.simplex.SimplexPlugin;
@@ -17,10 +18,13 @@ import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.transport.TransportConstants.MIN_STREAM_LENGTH;
public abstract class FilePlugin implements SimplexPlugin {
@NotNullByDefault
abstract class FilePlugin implements SimplexPlugin {
private static final Logger LOG =
Logger.getLogger(FilePlugin.class.getName());
@@ -32,6 +36,7 @@ public abstract class FilePlugin implements SimplexPlugin {
protected volatile boolean running = false;
@Nullable
protected abstract File chooseOutputDirectory();
protected abstract Collection<File> findFilesByName(String filename);
protected abstract void writerFinished(File f);
@@ -82,6 +87,7 @@ public abstract class FilePlugin implements SimplexPlugin {
return filename.toLowerCase(Locale.US).matches("[a-z]{8}\\.dat");
}
@Nullable
private TransportConnectionWriter createWriter(String filename) {
if (!running) return null;
File dir = chooseOutputDirectory();

View File

@@ -6,6 +6,7 @@ import org.briarproject.api.contact.ContactId;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.keyagreement.KeyAgreementConnection;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
@@ -29,14 +30,13 @@ import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
import static org.briarproject.util.ByteUtils.MAX_16_BIT_UNSIGNED;
import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
@NotNullByDefault
class LanTcpPlugin extends TcpPlugin {
static final TransportId ID = new TransportId("lan");
@@ -211,7 +211,6 @@ class LanTcpPlugin extends TcpPlugin {
LOG.info("Invalid IP/port in key agreement descriptor");
return null;
}
if (remote == null) return null;
if (!isConnectable(remote)) {
if (LOG.isLoggable(INFO)) {
SocketAddress local = socket.getLocalSocketAddress();
@@ -237,10 +236,8 @@ class LanTcpPlugin extends TcpPlugin {
}
}
@Nullable
private InetSocketAddress parseSocketAddress(BdfList descriptor)
throws FormatException {
if (descriptor.size() < 3) return null;
byte[] address = descriptor.getRaw(1);
int port = descriptor.getLong(2).intValue();
if (port < 1 || port > MAX_16_BIT_UNSIGNED) throw new FormatException();

View File

@@ -4,6 +4,8 @@ import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
@@ -28,10 +30,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.util.PrivacyUtils.scrubSocketAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
abstract class TcpPlugin implements DuplexPlugin {
private static final Pattern DOTTED_QUAD =
@@ -141,7 +147,7 @@ abstract class TcpPlugin implements DuplexPlugin {
});
}
protected void tryToClose(ServerSocket ss) {
protected void tryToClose(@Nullable ServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
@@ -252,6 +258,7 @@ abstract class TcpPlugin implements DuplexPlugin {
return null;
}
@Nullable
protected InetSocketAddress parseSocketAddress(String ipPort) {
if (StringUtils.isNullOrEmpty(ipPort)) return null;
String[] split = ipPort.split(":");

View File

@@ -2,6 +2,8 @@ package org.briarproject.plugins.tcp;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.properties.TransportProperties;
@@ -14,6 +16,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class WanTcpPlugin extends TcpPlugin {
static final TransportId ID = new TransportId("wan");

View File

@@ -7,6 +7,8 @@ import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.keyagreement.KeyAgreementConnection;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
@@ -48,6 +50,8 @@ import static java.util.logging.Level.WARNING;
import static javax.bluetooth.DiscoveryAgent.GIAC;
import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class BluetoothPlugin implements DuplexPlugin {
// Share an ID with the Android Bluetooth plugin
@@ -164,7 +168,7 @@ class BluetoothPlugin implements DuplexPlugin {
return uuid;
}
private void tryToClose(StreamConnectionNotifier ss) {
private void tryToClose(@Nullable StreamConnectionNotifier ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
@@ -333,7 +337,7 @@ class BluetoothPlugin implements DuplexPlugin {
}
private void closeSockets(final List<Future<StreamConnection>> futures,
final StreamConnection chosen) {
@Nullable final StreamConnection chosen) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
@@ -388,7 +392,7 @@ class BluetoothPlugin implements DuplexPlugin {
BdfList descriptor = new BdfList();
descriptor.add(TRANSPORT_ID_BLUETOOTH);
String address = localDevice.getBluetoothAddress();
if (!address.isEmpty()) descriptor.add(StringUtils.macToBytes(address));
descriptor.add(StringUtils.macToBytes(address));
return new BluetoothKeyAgreementListener(descriptor, ss);
}
@@ -403,7 +407,6 @@ class BluetoothPlugin implements DuplexPlugin {
LOG.info("Invalid address in key agreement descriptor");
return null;
}
if (address == null) return null;
// No truncation necessary because COMMIT_LENGTH = 16
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
if (LOG.isLoggable(INFO))
@@ -414,9 +417,7 @@ class BluetoothPlugin implements DuplexPlugin {
return new BluetoothTransportConnection(this, s);
}
@Nullable
private String parseAddress(BdfList descriptor) throws FormatException {
if (descriptor.size() < 2) return null;
byte[] mac = descriptor.getRaw(1);
if (mac.length != 6) throw new FormatException();
return StringUtils.macToString(mac);

View File

@@ -2,6 +2,7 @@ package org.briarproject.plugins.file;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
import java.io.File;
@@ -15,6 +16,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
@NotNullByDefault
class RemovableDrivePlugin extends FilePlugin
implements RemovableDriveMonitor.Callback {

View File

@@ -5,6 +5,8 @@ import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
@@ -22,6 +24,8 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class ModemPlugin implements DuplexPlugin, Modem.Callback {
static final TransportId ID = new TransportId("modem");

View File

@@ -31,6 +31,7 @@ import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -188,7 +189,9 @@ public class LanTcpPluginTest extends BriarTestCase {
0, 0);
plugin.start();
assertTrue(callback.propertiesLatch.await(5, SECONDS));
KeyAgreementListener kal = plugin.createKeyAgreementListener(null);
KeyAgreementListener kal =
plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]);
assertNotNull(kal);
Callable<KeyAgreementConnection> c = kal.listen();
FutureTask<KeyAgreementConnection> f = new FutureTask<>(c);
new Thread(f).start();
@@ -258,8 +261,8 @@ public class LanTcpPluginTest extends BriarTestCase {
descriptor.add(local.getAddress().getAddress());
descriptor.add(local.getPort());
// Connect to the port
DuplexTransportConnection d =
plugin.createKeyAgreementConnection(null, descriptor, 5000);
DuplexTransportConnection d = plugin.createKeyAgreementConnection(
new byte[COMMIT_LENGTH], descriptor, 5000);
assertNotNull(d);
// Check that the connection was accepted
assertTrue(latch.await(5, SECONDS));