mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 05:09:53 +01:00
Ensure that Plugin instances aren't reused.
This commit is contained in:
@@ -282,8 +282,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
public void showForumPostNotification(final GroupId g) {
|
public void showForumPostNotification(final GroupId g) {
|
||||||
androidExecutor.execute(new Runnable() {
|
androidExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void
|
public void run() {
|
||||||
run() {
|
|
||||||
Integer count = forumCounts.get(g);
|
Integer count = forumCounts.get(g);
|
||||||
if (count == null) forumCounts.put(g, 1);
|
if (count == null) forumCounts.put(g, 1);
|
||||||
else forumCounts.put(g, count + 1);
|
else forumCounts.put(g, count + 1);
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
|
||||||
|
import org.briarproject.android.api.AndroidExecutor;
|
||||||
import org.briarproject.android.util.AndroidUtils;
|
import org.briarproject.android.util.AndroidUtils;
|
||||||
import org.briarproject.api.TransportId;
|
import org.briarproject.api.TransportId;
|
||||||
import org.briarproject.android.api.AndroidExecutor;
|
|
||||||
import org.briarproject.api.contact.ContactId;
|
import org.briarproject.api.contact.ContactId;
|
||||||
import org.briarproject.api.crypto.PseudoRandom;
|
import org.briarproject.api.crypto.PseudoRandom;
|
||||||
import org.briarproject.api.keyagreement.KeyAgreementConnection;
|
import org.briarproject.api.keyagreement.KeyAgreementConnection;
|
||||||
@@ -41,6 +41,7 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorCompletionService;
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
||||||
@@ -80,6 +81,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
private final Backoff backoff;
|
private final Backoff backoff;
|
||||||
private final DuplexPluginCallback callback;
|
private final DuplexPluginCallback callback;
|
||||||
private final int maxLatency;
|
private final int maxLatency;
|
||||||
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
private volatile boolean wasEnabledByUs = false;
|
private volatile boolean wasEnabledByUs = false;
|
||||||
@@ -101,24 +103,30 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxLatency() {
|
public int getMaxLatency() {
|
||||||
return maxLatency;
|
return maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxIdleTime() {
|
public int getMaxIdleTime() {
|
||||||
// Bluetooth detects dead connections so we don't need keepalives
|
// Bluetooth detects dead connections so we don't need keepalives
|
||||||
return Integer.MAX_VALUE;
|
return Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean start() throws IOException {
|
public boolean start() throws IOException {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
|
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
|
||||||
// with a message queue, so submit it to the AndroidExecutor
|
// with a message queue, so submit it to the AndroidExecutor
|
||||||
try {
|
try {
|
||||||
adapter = androidExecutor.submit(new Callable<BluetoothAdapter>() {
|
adapter = androidExecutor.submit(new Callable<BluetoothAdapter>() {
|
||||||
|
@Override
|
||||||
public BluetoothAdapter call() throws Exception {
|
public BluetoothAdapter call() throws Exception {
|
||||||
return BluetoothAdapter.getDefaultAdapter();
|
return BluetoothAdapter.getDefaultAdapter();
|
||||||
}
|
}
|
||||||
@@ -158,6 +166,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
private void bind() {
|
private void bind() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!isRunning()) return;
|
if (!isRunning()) return;
|
||||||
String address = AndroidUtils.getBluetoothAddress(appContext,
|
String address = AndroidUtils.getBluetoothAddress(appContext,
|
||||||
@@ -238,6 +247,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
return new DroidtoothTransportConnection(this, s);
|
return new DroidtoothTransportConnection(this, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
if (receiver != null) appContext.unregisterReceiver(receiver);
|
if (receiver != null) appContext.unregisterReceiver(receiver);
|
||||||
@@ -249,18 +259,22 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running && adapter.isEnabled();
|
return running && adapter.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldPoll() {
|
public boolean shouldPoll() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getPollingInterval() {
|
public int getPollingInterval() {
|
||||||
return backoff.getPollingInterval();
|
return backoff.getPollingInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
if (!isRunning()) return;
|
if (!isRunning()) return;
|
||||||
backoff.increment();
|
backoff.increment();
|
||||||
@@ -275,6 +289,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
final String uuid = e.getValue().get(PROP_UUID);
|
final String uuid = e.getValue().get(PROP_UUID);
|
||||||
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
BluetoothSocket s = connect(address, uuid);
|
BluetoothSocket s = connect(address, uuid);
|
||||||
@@ -327,6 +342,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||||
@@ -340,10 +356,12 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
return new DroidtoothTransportConnection(this, s);
|
return new DroidtoothTransportConnection(this, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsInvitations() {
|
public boolean supportsInvitations() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||||
long timeout, boolean alice) {
|
long timeout, boolean alice) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
@@ -361,9 +379,8 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
// Create the background tasks
|
// Create the background tasks
|
||||||
CompletionService<BluetoothSocket> complete =
|
CompletionService<BluetoothSocket> complete =
|
||||||
new ExecutorCompletionService<BluetoothSocket>(ioExecutor);
|
new ExecutorCompletionService<>(ioExecutor);
|
||||||
List<Future<BluetoothSocket>> futures =
|
List<Future<BluetoothSocket>> futures = new ArrayList<>();
|
||||||
new ArrayList<Future<BluetoothSocket>>();
|
|
||||||
if (alice) {
|
if (alice) {
|
||||||
// Return the first connected socket
|
// Return the first connected socket
|
||||||
futures.add(complete.submit(new ListeningTask(ss)));
|
futures.add(complete.submit(new ListeningTask(ss)));
|
||||||
@@ -398,6 +415,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
private void closeSockets(final List<Future<BluetoothSocket>> futures,
|
private void closeSockets(final List<Future<BluetoothSocket>> futures,
|
||||||
final BluetoothSocket chosen) {
|
final BluetoothSocket chosen) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (Future<BluetoothSocket> f : futures) {
|
for (Future<BluetoothSocket> f : futures) {
|
||||||
try {
|
try {
|
||||||
@@ -413,9 +431,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.info("Interrupted while closing sockets");
|
LOG.info("Interrupted while closing sockets");
|
||||||
return;
|
return;
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException | IOException e) {
|
||||||
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,14 +439,15 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsKeyAgreement() {
|
public boolean supportsKeyAgreement() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyAgreementListener createKeyAgreementListener(
|
@Override
|
||||||
byte[] localCommitment) {
|
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||||
// No truncation necessary because COMMIT_LENGTH = 16
|
// 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);
|
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
|
||||||
// Bind a server socket for receiving invitation connections
|
// Bind a server socket for receiving invitation connections
|
||||||
BluetoothServerSocket ss;
|
BluetoothServerSocket ss;
|
||||||
@@ -448,8 +465,9 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
return new BluetoothKeyAgreementListener(d, ss);
|
return new BluetoothKeyAgreementListener(d, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createKeyAgreementConnection(
|
public DuplexTransportConnection createKeyAgreementConnection(
|
||||||
byte[] remoteCommitment, TransportDescriptor d, long timeout) {
|
byte[] commitment, TransportDescriptor d, long timeout) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
if (!ID.equals(d.getIdentifier())) return null;
|
if (!ID.equals(d.getIdentifier())) return null;
|
||||||
TransportProperties p = d.getProperties();
|
TransportProperties p = d.getProperties();
|
||||||
@@ -457,7 +475,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
String address = p.get(PROP_ADDRESS);
|
String address = p.get(PROP_ADDRESS);
|
||||||
if (StringUtils.isNullOrEmpty(address)) return null;
|
if (StringUtils.isNullOrEmpty(address)) return null;
|
||||||
// No truncation necessary because COMMIT_LENGTH = 16
|
// No truncation necessary because COMMIT_LENGTH = 16
|
||||||
UUID uuid = UUID.nameUUIDFromBytes(remoteCommitment);
|
UUID uuid = UUID.nameUUIDFromBytes(commitment);
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Connecting to key agreement UUID " + uuid);
|
LOG.info("Connecting to key agreement UUID " + uuid);
|
||||||
BluetoothSocket s = connect(address, uuid.toString());
|
BluetoothSocket s = connect(address, uuid.toString());
|
||||||
@@ -533,7 +551,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
private static class DiscoveryReceiver extends BroadcastReceiver {
|
private static class DiscoveryReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
private final CountDownLatch finished = new CountDownLatch(1);
|
private final CountDownLatch finished = new CountDownLatch(1);
|
||||||
private final List<String> addresses = new ArrayList<String>();
|
private final List<String> addresses = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context ctx, Intent intent) {
|
public void onReceive(Context ctx, Intent intent) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean start() {
|
public boolean start() {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
running = true;
|
running = true;
|
||||||
// Register to receive network status events
|
// Register to receive network status events
|
||||||
networkStateReceiver = new NetworkStateReceiver();
|
networkStateReceiver = new NetworkStateReceiver();
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import java.util.Map;
|
|||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.ZipInputStream;
|
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 torDirectory, torFile, geoIpFile, configFile;
|
||||||
private final File doneFile, cookieFile;
|
private final File doneFile, cookieFile;
|
||||||
private final PowerManager.WakeLock wakeLock;
|
private final PowerManager.WakeLock wakeLock;
|
||||||
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
private volatile ServerSocket socket = null;
|
private volatile ServerSocket socket = null;
|
||||||
@@ -130,19 +132,24 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
wakeLock.setReferenceCounted(false);
|
wakeLock.setReferenceCounted(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxLatency() {
|
public int getMaxLatency() {
|
||||||
return maxLatency;
|
return maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxIdleTime() {
|
public int getMaxIdleTime() {
|
||||||
return maxIdleTime;
|
return maxIdleTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean start() throws IOException {
|
public boolean start() throws IOException {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
// Try to connect to an existing Tor process if there is one
|
// Try to connect to an existing Tor process if there is one
|
||||||
boolean startProcess = false;
|
boolean startProcess = false;
|
||||||
try {
|
try {
|
||||||
@@ -369,6 +376,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
private void bind() {
|
private void bind() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// If there's already a port number stored in config, reuse it
|
// If there's already a port number stored in config, reuse it
|
||||||
String portString = callback.getSettings().get("port");
|
String portString = callback.getSettings().get("port");
|
||||||
@@ -398,6 +406,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
callback.mergeSettings(s);
|
callback.mergeSettings(s);
|
||||||
// Create a hidden service if necessary
|
// Create a hidden service if necessary
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
publishHiddenService(localPort);
|
publishHiddenService(localPort);
|
||||||
}
|
}
|
||||||
@@ -486,6 +495,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() throws IOException {
|
public void stop() throws IOException {
|
||||||
running = false;
|
running = false;
|
||||||
tryToClose(socket);
|
tryToClose(socket);
|
||||||
@@ -508,18 +518,22 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
wakeLock.release();
|
wakeLock.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running && connectionStatus.isConnected();
|
return running && connectionStatus.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldPoll() {
|
public boolean shouldPoll() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getPollingInterval() {
|
public int getPollingInterval() {
|
||||||
return backoff.getPollingInterval();
|
return backoff.getPollingInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
if (!isRunning()) return;
|
if (!isRunning()) return;
|
||||||
backoff.increment();
|
backoff.increment();
|
||||||
@@ -530,6 +544,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
private void connectAndCallBack(final ContactId c) {
|
private void connectAndCallBack(final ContactId c) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DuplexTransportConnection d = createConnection(c);
|
DuplexTransportConnection d = createConnection(c);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
@@ -540,6 +555,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||||
@@ -566,29 +582,34 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsInvitations() {
|
public boolean supportsInvitations() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||||
long timeout, boolean alice) {
|
long timeout, boolean alice) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsKeyAgreement() {
|
public boolean supportsKeyAgreement() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyAgreementListener createKeyAgreementListener(
|
@Override
|
||||||
byte[] commitment) {
|
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createKeyAgreementConnection(
|
public DuplexTransportConnection createKeyAgreementConnection(
|
||||||
byte[] commitment, TransportDescriptor d, long timeout) {
|
byte[] commitment, TransportDescriptor d, long timeout) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void circuitStatus(String status, String id, String path) {
|
public void circuitStatus(String status, String id, String path) {
|
||||||
if (status.equals("BUILT") &&
|
if (status.equals("BUILT") &&
|
||||||
connectionStatus.getAndSetCircuitBuilt()) {
|
connectionStatus.getAndSetCircuitBuilt()) {
|
||||||
@@ -598,19 +619,24 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void streamStatus(String status, String id, String target) {
|
public void streamStatus(String status, String id, String target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void orConnStatus(String status, String orName) {
|
public void orConnStatus(String status, String orName) {
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
|
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void bandwidthUsed(long read, long written) {
|
public void bandwidthUsed(long read, long written) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void newDescriptors(List<String> orList) {
|
public void newDescriptors(List<String> orList) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void message(String severity, String msg) {
|
public void message(String severity, String msg) {
|
||||||
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
|
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
|
||||||
if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) {
|
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) {
|
public void unrecognized(String type, String msg) {
|
||||||
if (type.equals("HS_DESC") && msg.startsWith("UPLOADED"))
|
if (type.equals("HS_DESC") && msg.startsWith("UPLOADED"))
|
||||||
LOG.info("Descriptor uploaded");
|
LOG.info("Descriptor uploaded");
|
||||||
@@ -642,6 +669,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
if (e instanceof SettingsUpdatedEvent) {
|
if (e instanceof SettingsUpdatedEvent) {
|
||||||
if (((SettingsUpdatedEvent) e).getNamespace().equals("tor")) {
|
if (((SettingsUpdatedEvent) e).getNamespace().equals("tor")) {
|
||||||
@@ -653,6 +681,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
|
|
||||||
private void updateConnectionStatus() {
|
private void updateConnectionStatus() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import java.io.OutputStream;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
@@ -27,6 +28,7 @@ public abstract class FilePlugin implements SimplexPlugin {
|
|||||||
protected final Executor ioExecutor;
|
protected final Executor ioExecutor;
|
||||||
protected final SimplexPluginCallback callback;
|
protected final SimplexPluginCallback callback;
|
||||||
protected final int maxLatency;
|
protected final int maxLatency;
|
||||||
|
protected final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
protected volatile boolean running = false;
|
protected volatile boolean running = false;
|
||||||
|
|
||||||
@@ -42,22 +44,27 @@ public abstract class FilePlugin implements SimplexPlugin {
|
|||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxLatency() {
|
public int getMaxLatency() {
|
||||||
return maxLatency;
|
return maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxIdleTime() {
|
public int getMaxIdleTime() {
|
||||||
return Integer.MAX_VALUE; // We don't need keepalives
|
return Integer.MAX_VALUE; // We don't need keepalives
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportConnectionReader createReader(ContactId c) {
|
public TransportConnectionReader createReader(ContactId c) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportConnectionWriter createWriter(ContactId c) {
|
public TransportConnectionWriter createWriter(ContactId c) {
|
||||||
if (!running) return null;
|
if (!running) return null;
|
||||||
return createWriter(createConnectionFilename());
|
return createWriter(createConnectionFilename());
|
||||||
@@ -105,6 +112,7 @@ public abstract class FilePlugin implements SimplexPlugin {
|
|||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (isPossibleConnectionFilename(file.getName())) {
|
if (isPossibleConnectionFilename(file.getName())) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
|
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
protected final Backoff backoff;
|
protected final Backoff backoff;
|
||||||
protected final DuplexPluginCallback callback;
|
protected final DuplexPluginCallback callback;
|
||||||
protected final int maxLatency, maxIdleTime, socketTimeout;
|
protected final int maxLatency, maxIdleTime, socketTimeout;
|
||||||
|
protected final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
protected volatile boolean running = false;
|
protected volatile boolean running = false;
|
||||||
protected volatile ServerSocket socket = null;
|
protected volatile ServerSocket socket = null;
|
||||||
@@ -67,15 +69,19 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
else socketTimeout = maxIdleTime * 2;
|
else socketTimeout = maxIdleTime * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxLatency() {
|
public int getMaxLatency() {
|
||||||
return maxLatency;
|
return maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxIdleTime() {
|
public int getMaxIdleTime() {
|
||||||
return maxIdleTime;
|
return maxIdleTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean start() {
|
public boolean start() {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
running = true;
|
running = true;
|
||||||
bind();
|
bind();
|
||||||
return true;
|
return true;
|
||||||
@@ -83,6 +89,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
protected void bind() {
|
protected void bind() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
ServerSocket ss = null;
|
ServerSocket ss = null;
|
||||||
@@ -158,23 +165,28 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
tryToClose(socket);
|
tryToClose(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running && socket != null && !socket.isClosed();
|
return running && socket != null && !socket.isClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldPoll() {
|
public boolean shouldPoll() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getPollingInterval() {
|
public int getPollingInterval() {
|
||||||
return backoff.getPollingInterval();
|
return backoff.getPollingInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
if (!isRunning()) return;
|
if (!isRunning()) return;
|
||||||
backoff.increment();
|
backoff.increment();
|
||||||
@@ -185,6 +197,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
private void connectAndCallBack(final ContactId c) {
|
private void connectAndCallBack(final ContactId c) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
DuplexTransportConnection d = createConnection(c);
|
DuplexTransportConnection d = createConnection(c);
|
||||||
if (d != null) {
|
if (d != null) {
|
||||||
@@ -195,6 +208,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
InetSocketAddress remote = getRemoteSocketAddress(c);
|
InetSocketAddress remote = getRemoteSocketAddress(c);
|
||||||
@@ -243,24 +257,28 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsInvitations() {
|
public boolean supportsInvitations() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||||
long timeout, boolean alice) {
|
long timeout, boolean alice) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsKeyAgreement() {
|
public boolean supportsKeyAgreement() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyAgreementListener createKeyAgreementListener(
|
@Override
|
||||||
byte[] commitment) {
|
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createKeyAgreementConnection(
|
public DuplexTransportConnection createKeyAgreementConnection(
|
||||||
byte[] commitment, TransportDescriptor d, long timeout) {
|
byte[] commitment, TransportDescriptor d, long timeout) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class WanTcpPlugin extends TcpPlugin {
|
|||||||
this.portMapper = portMapper;
|
this.portMapper = portMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import java.util.concurrent.Executor;
|
|||||||
import java.util.concurrent.ExecutorCompletionService;
|
import java.util.concurrent.ExecutorCompletionService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.bluetooth.BluetoothStateException;
|
import javax.bluetooth.BluetoothStateException;
|
||||||
@@ -62,6 +63,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
private final DuplexPluginCallback callback;
|
private final DuplexPluginCallback callback;
|
||||||
private final int maxLatency;
|
private final int maxLatency;
|
||||||
private final Semaphore discoverySemaphore = new Semaphore(1);
|
private final Semaphore discoverySemaphore = new Semaphore(1);
|
||||||
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
private volatile StreamConnectionNotifier socket = null;
|
private volatile StreamConnectionNotifier socket = null;
|
||||||
@@ -76,20 +78,25 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxLatency() {
|
public int getMaxLatency() {
|
||||||
return maxLatency;
|
return maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxIdleTime() {
|
public int getMaxIdleTime() {
|
||||||
// Bluetooth detects dead connections so we don't need keepalives
|
// Bluetooth detects dead connections so we don't need keepalives
|
||||||
return Integer.MAX_VALUE;
|
return Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean start() throws IOException {
|
public boolean start() throws IOException {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
// Initialise the Bluetooth stack
|
// Initialise the Bluetooth stack
|
||||||
try {
|
try {
|
||||||
localDevice = LocalDevice.getLocalDevice();
|
localDevice = LocalDevice.getLocalDevice();
|
||||||
@@ -108,6 +115,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
private void bind() {
|
private void bind() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
// Advertise the Bluetooth address to contacts
|
// Advertise the Bluetooth address to contacts
|
||||||
@@ -183,23 +191,28 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
return new BluetoothTransportConnection(this, s);
|
return new BluetoothTransportConnection(this, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
tryToClose(socket);
|
tryToClose(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldPoll() {
|
public boolean shouldPoll() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getPollingInterval() {
|
public int getPollingInterval() {
|
||||||
return backoff.getPollingInterval();
|
return backoff.getPollingInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void poll(final Collection<ContactId> connected) {
|
public void poll(final Collection<ContactId> connected) {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
backoff.increment();
|
backoff.increment();
|
||||||
@@ -214,6 +227,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
final String uuid = e.getValue().get(PROP_UUID);
|
final String uuid = e.getValue().get(PROP_UUID);
|
||||||
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
StreamConnection s = connect(makeUrl(address, uuid));
|
StreamConnection s = connect(makeUrl(address, uuid));
|
||||||
@@ -238,6 +252,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!running) return null;
|
if (!running) return null;
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||||
@@ -252,10 +267,12 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
return new BluetoothTransportConnection(this, s);
|
return new BluetoothTransportConnection(this, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsInvitations() {
|
public boolean supportsInvitations() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||||
long timeout, boolean alice) {
|
long timeout, boolean alice) {
|
||||||
if (!running) return null;
|
if (!running) return null;
|
||||||
@@ -279,9 +296,8 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
// Create the background tasks
|
// Create the background tasks
|
||||||
CompletionService<StreamConnection> complete =
|
CompletionService<StreamConnection> complete =
|
||||||
new ExecutorCompletionService<StreamConnection>(ioExecutor);
|
new ExecutorCompletionService<>(ioExecutor);
|
||||||
List<Future<StreamConnection>> futures =
|
List<Future<StreamConnection>> futures = new ArrayList<>();
|
||||||
new ArrayList<Future<StreamConnection>>();
|
|
||||||
if (alice) {
|
if (alice) {
|
||||||
// Return the first connected socket
|
// Return the first connected socket
|
||||||
futures.add(complete.submit(new ListeningTask(ss)));
|
futures.add(complete.submit(new ListeningTask(ss)));
|
||||||
@@ -316,6 +332,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
private void closeSockets(final List<Future<StreamConnection>> futures,
|
private void closeSockets(final List<Future<StreamConnection>> futures,
|
||||||
final StreamConnection chosen) {
|
final StreamConnection chosen) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (Future<StreamConnection> f : futures) {
|
for (Future<StreamConnection> f : futures) {
|
||||||
try {
|
try {
|
||||||
@@ -331,9 +348,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.info("Interrupted while closing sockets");
|
LOG.info("Interrupted while closing sockets");
|
||||||
return;
|
return;
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException | IOException e) {
|
||||||
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,14 +356,15 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsKeyAgreement() {
|
public boolean supportsKeyAgreement() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyAgreementListener createKeyAgreementListener(
|
@Override
|
||||||
byte[] localCommitment) {
|
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||||
// No truncation necessary because COMMIT_LENGTH = 16
|
// 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);
|
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
|
||||||
String url = makeUrl("localhost", uuid);
|
String url = makeUrl("localhost", uuid);
|
||||||
// Make the device discoverable if possible
|
// Make the device discoverable if possible
|
||||||
@@ -371,8 +387,9 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
return new BluetoothKeyAgreementListener(d, ss);
|
return new BluetoothKeyAgreementListener(d, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createKeyAgreementConnection(
|
public DuplexTransportConnection createKeyAgreementConnection(
|
||||||
byte[] remoteCommitment, TransportDescriptor d, long timeout) {
|
byte[] commitment, TransportDescriptor d, long timeout) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
if (!ID.equals(d.getIdentifier())) return null;
|
if (!ID.equals(d.getIdentifier())) return null;
|
||||||
TransportProperties p = d.getProperties();
|
TransportProperties p = d.getProperties();
|
||||||
@@ -380,7 +397,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
String address = p.get(PROP_ADDRESS);
|
String address = p.get(PROP_ADDRESS);
|
||||||
if (StringUtils.isNullOrEmpty(address)) return null;
|
if (StringUtils.isNullOrEmpty(address)) return null;
|
||||||
// No truncation necessary because COMMIT_LENGTH = 16
|
// No truncation necessary because COMMIT_LENGTH = 16
|
||||||
String uuid = UUID.nameUUIDFromBytes(remoteCommitment).toString();
|
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Connecting to key agreement UUID " + uuid);
|
LOG.info("Connecting to key agreement UUID " + uuid);
|
||||||
String url = makeUrl(address, uuid);
|
String url = makeUrl(address, uuid);
|
||||||
|
|||||||
@@ -34,29 +34,36 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
this.monitor = monitor;
|
this.monitor = monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean start() throws IOException {
|
public boolean start() throws IOException {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
running = true;
|
running = true;
|
||||||
monitor.start(this);
|
monitor.start(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() throws IOException {
|
public void stop() throws IOException {
|
||||||
running = false;
|
running = false;
|
||||||
monitor.stop();
|
monitor.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldPoll() {
|
public boolean shouldPoll() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getPollingInterval() {
|
public int getPollingInterval() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
@@ -64,8 +71,7 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
@Override
|
@Override
|
||||||
protected File chooseOutputDirectory() {
|
protected File chooseOutputDirectory() {
|
||||||
try {
|
try {
|
||||||
List<File> drives =
|
List<File> drives = new ArrayList<>(finder.findRemovableDrives());
|
||||||
new ArrayList<File>(finder.findRemovableDrives());
|
|
||||||
if (drives.isEmpty()) return null;
|
if (drives.isEmpty()) return null;
|
||||||
String[] paths = new String[drives.size()];
|
String[] paths = new String[drives.size()];
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (int i = 0; i < paths.length; i++) {
|
||||||
@@ -92,7 +98,7 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Collection<File> findFilesByName(String filename) {
|
protected Collection<File> findFilesByName(String filename) {
|
||||||
List<File> matches = new ArrayList<File>();
|
List<File> matches = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
for (File drive : finder.findRemovableDrives()) {
|
for (File drive : finder.findRemovableDrives()) {
|
||||||
File[] files = drive.listFiles();
|
File[] files = drive.listFiles();
|
||||||
@@ -109,6 +115,7 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
return Collections.unmodifiableList(matches);
|
return Collections.unmodifiableList(matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void driveInserted(File root) {
|
public void driveInserted(File root) {
|
||||||
File[] files = root.listFiles();
|
File[] files = root.listFiles();
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
@@ -116,6 +123,7 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void exceptionThrown(IOException e) {
|
public void exceptionThrown(IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
@@ -32,6 +33,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
|
|||||||
private final SerialPortList serialPortList;
|
private final SerialPortList serialPortList;
|
||||||
private final DuplexPluginCallback callback;
|
private final DuplexPluginCallback callback;
|
||||||
private final int maxLatency;
|
private final int maxLatency;
|
||||||
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
private volatile Modem modem = null;
|
private volatile Modem modem = null;
|
||||||
@@ -44,20 +46,25 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
|
|||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxLatency() {
|
public int getMaxLatency() {
|
||||||
return maxLatency;
|
return maxLatency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getMaxIdleTime() {
|
public int getMaxIdleTime() {
|
||||||
// FIXME: Do we need keepalives for this transport?
|
// FIXME: Do we need keepalives for this transport?
|
||||||
return Integer.MAX_VALUE;
|
return Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean start() {
|
public boolean start() {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
for (String portName : serialPortList.getPortNames()) {
|
for (String portName : serialPortList.getPortNames()) {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Trying to initialise modem on " + portName);
|
LOG.info("Trying to initialise modem on " + portName);
|
||||||
@@ -75,6 +82,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
if (modem != null) {
|
if (modem != null) {
|
||||||
@@ -86,18 +94,22 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldPoll() {
|
public boolean shouldPoll() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getPollingInterval() {
|
public int getPollingInterval() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
@@ -121,6 +133,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!running) return null;
|
if (!running) return null;
|
||||||
// Get the ISO 3166 code for the caller's country
|
// Get the ISO 3166 code for the caller's country
|
||||||
@@ -148,29 +161,34 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
|
|||||||
return new ModemTransportConnection();
|
return new ModemTransportConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsInvitations() {
|
public boolean supportsInvitations() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||||
long timeout, boolean alice) {
|
long timeout, boolean alice) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean supportsKeyAgreement() {
|
public boolean supportsKeyAgreement() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyAgreementListener createKeyAgreementListener(
|
@Override
|
||||||
byte[] commitment) {
|
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DuplexTransportConnection createKeyAgreementConnection(
|
public DuplexTransportConnection createKeyAgreementConnection(
|
||||||
byte[] commitment, TransportDescriptor d, long timeout) {
|
byte[] commitment, TransportDescriptor d, long timeout) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void incomingCallConnected() {
|
public void incomingCallConnected() {
|
||||||
LOG.info("Incoming call connected");
|
LOG.info("Incoming call connected");
|
||||||
callback.incomingConnectionCreated(new ModemTransportConnection());
|
callback.incomingConnectionCreated(new ModemTransportConnection());
|
||||||
|
|||||||
Reference in New Issue
Block a user