mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 22:29:53 +01:00
Plugin code cleanup.
This commit is contained in:
@@ -1,28 +0,0 @@
|
|||||||
package net.sf.briar.plugins;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import net.sf.briar.api.plugins.Plugin;
|
|
||||||
import net.sf.briar.api.plugins.PluginExecutor;
|
|
||||||
|
|
||||||
public abstract class AbstractPlugin implements Plugin {
|
|
||||||
|
|
||||||
protected final Executor pluginExecutor;
|
|
||||||
|
|
||||||
protected boolean running = false; // Locking: this
|
|
||||||
|
|
||||||
protected AbstractPlugin(@PluginExecutor Executor pluginExecutor) {
|
|
||||||
this.pluginExecutor = pluginExecutor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void start() throws IOException {
|
|
||||||
if(running) throw new IllegalStateException();
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void stop() throws IOException {
|
|
||||||
if(!running) throw new IllegalStateException();
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,11 +24,10 @@ import net.sf.briar.api.plugins.StreamPlugin;
|
|||||||
import net.sf.briar.api.plugins.StreamPluginCallback;
|
import net.sf.briar.api.plugins.StreamPluginCallback;
|
||||||
import net.sf.briar.api.protocol.TransportId;
|
import net.sf.briar.api.protocol.TransportId;
|
||||||
import net.sf.briar.api.transport.StreamTransportConnection;
|
import net.sf.briar.api.transport.StreamTransportConnection;
|
||||||
import net.sf.briar.plugins.AbstractPlugin;
|
|
||||||
import net.sf.briar.util.OsUtils;
|
import net.sf.briar.util.OsUtils;
|
||||||
import net.sf.briar.util.StringUtils;
|
import net.sf.briar.util.StringUtils;
|
||||||
|
|
||||||
class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
class BluetoothPlugin implements StreamPlugin {
|
||||||
|
|
||||||
public static final byte[] TRANSPORT_ID =
|
public static final byte[] TRANSPORT_ID =
|
||||||
StringUtils.fromHexString("d99c9313c04417dcf22fc60d12a187ea"
|
StringUtils.fromHexString("d99c9313c04417dcf22fc60d12a187ea"
|
||||||
@@ -38,16 +37,18 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(BluetoothPlugin.class.getName());
|
Logger.getLogger(BluetoothPlugin.class.getName());
|
||||||
|
|
||||||
private final Object discoveryLock = new Object();
|
private final Executor pluginExecutor;
|
||||||
private final StreamPluginCallback callback;
|
private final StreamPluginCallback callback;
|
||||||
private final long pollingInterval;
|
private final long pollingInterval;
|
||||||
|
private final Object discoveryLock = new Object();
|
||||||
|
|
||||||
|
private boolean running = false; // Locking: this
|
||||||
private LocalDevice localDevice = null; // Locking: this
|
private LocalDevice localDevice = null; // Locking: this
|
||||||
private StreamConnectionNotifier socket = null; // Locking: this
|
private StreamConnectionNotifier socket = null; // Locking: this
|
||||||
|
|
||||||
BluetoothPlugin(@PluginExecutor Executor pluginExecutor,
|
BluetoothPlugin(@PluginExecutor Executor pluginExecutor,
|
||||||
StreamPluginCallback callback, long pollingInterval) {
|
StreamPluginCallback callback, long pollingInterval) {
|
||||||
super(pluginExecutor);
|
this.pluginExecutor = pluginExecutor;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.pollingInterval = pollingInterval;
|
this.pollingInterval = pollingInterval;
|
||||||
}
|
}
|
||||||
@@ -56,43 +57,33 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() throws IOException {
|
public void start() throws IOException {
|
||||||
// Initialise the Bluetooth stack
|
// Initialise the Bluetooth stack
|
||||||
try {
|
try {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
super.start();
|
running = true;
|
||||||
localDevice = LocalDevice.getLocalDevice();
|
localDevice = LocalDevice.getLocalDevice();
|
||||||
if(LOG.isLoggable(Level.INFO))
|
}
|
||||||
LOG.info("Local address "
|
|
||||||
+ localDevice.getBluetoothAddress());
|
|
||||||
}
|
|
||||||
} catch(UnsatisfiedLinkError e) {
|
} catch(UnsatisfiedLinkError e) {
|
||||||
// On Linux the user may need to install libbluetooth-dev
|
// On Linux the user may need to install libbluetooth-dev
|
||||||
if(OsUtils.isLinux()) {
|
if(OsUtils.isLinux())
|
||||||
pluginExecutor.execute(new Runnable() {
|
callback.showMessage("BLUETOOTH_INSTALL_LIBS");
|
||||||
public void run() {
|
|
||||||
callback.showMessage("BLUETOOTH_INSTALL_LIBS");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw new IOException(e.toString());
|
throw new IOException(e.toString());
|
||||||
}
|
}
|
||||||
pluginExecutor.execute(new Runnable() {
|
pluginExecutor.execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
bindContactSocket();
|
bind();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindContactSocket() {
|
private void bind() {
|
||||||
String uuid;
|
String uuid;
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if(!running) return;
|
if(!running) return;
|
||||||
uuid = getUuid();
|
uuid = getUuid();
|
||||||
makeDeviceDiscoverable();
|
makeDeviceDiscoverable();
|
||||||
}
|
}
|
||||||
// Bind the socket
|
|
||||||
String url = "btspp://localhost:" + uuid + ";name=RFCOMM";
|
String url = "btspp://localhost:" + uuid + ";name=RFCOMM";
|
||||||
StreamConnectionNotifier scn;
|
StreamConnectionNotifier scn;
|
||||||
try {
|
try {
|
||||||
@@ -103,21 +94,12 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
}
|
}
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if(!running) {
|
if(!running) {
|
||||||
try {
|
tryToClose(scn);
|
||||||
scn.close();
|
|
||||||
} catch(IOException e) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
|
||||||
LOG.warning(e.toString());
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
socket = scn;
|
socket = scn;
|
||||||
}
|
}
|
||||||
pluginExecutor.execute(new Runnable() {
|
acceptContactConnections(scn);
|
||||||
public void run() {
|
|
||||||
acceptContactConnections();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized String getUuid() {
|
private synchronized String getUuid() {
|
||||||
@@ -151,30 +133,37 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void acceptContactConnections() {
|
private void tryToClose(StreamConnectionNotifier scn) {
|
||||||
|
try {
|
||||||
|
scn.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acceptContactConnections(StreamConnectionNotifier scn) {
|
||||||
while(true) {
|
while(true) {
|
||||||
StreamConnectionNotifier scn;
|
|
||||||
StreamConnection s;
|
StreamConnection s;
|
||||||
synchronized(this) {
|
|
||||||
if(!running) return;
|
|
||||||
scn = socket;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
s = scn.acceptAndOpen();
|
s = scn.acceptAndOpen();
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
// This is expected when the socket is closed
|
// This is expected when the socket is closed
|
||||||
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
||||||
|
tryToClose(scn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BluetoothTransportConnection conn =
|
BluetoothTransportConnection conn =
|
||||||
new BluetoothTransportConnection(s);
|
new BluetoothTransportConnection(s);
|
||||||
callback.incomingConnectionCreated(conn);
|
callback.incomingConnectionCreated(conn);
|
||||||
|
synchronized(this) {
|
||||||
|
if(!running) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void stop() throws IOException {
|
public synchronized void stop() throws IOException {
|
||||||
super.stop();
|
running = false;
|
||||||
|
localDevice = null;
|
||||||
if(socket != null) {
|
if(socket != null) {
|
||||||
socket.close();
|
socket.close();
|
||||||
socket = null;
|
socket = null;
|
||||||
@@ -201,11 +190,11 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void connectAndCallBack() {
|
private void connectAndCallBack() {
|
||||||
Map<ContactId, TransportProperties> remote;
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if(!running) return;
|
if(!running) return;
|
||||||
remote = callback.getRemoteProperties();
|
|
||||||
}
|
}
|
||||||
|
Map<ContactId, TransportProperties> remote =
|
||||||
|
callback.getRemoteProperties();
|
||||||
Map<ContactId, String> discovered = discoverContactUrls(remote);
|
Map<ContactId, String> discovered = discoverContactUrls(remote);
|
||||||
for(Entry<ContactId, String> e : discovered.entrySet()) {
|
for(Entry<ContactId, String> e : discovered.entrySet()) {
|
||||||
ContactId c = e.getKey();
|
ContactId c = e.getKey();
|
||||||
@@ -268,11 +257,11 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StreamTransportConnection createConnection(ContactId c) {
|
public StreamTransportConnection createConnection(ContactId c) {
|
||||||
Map<ContactId, TransportProperties> remote;
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
remote = callback.getRemoteProperties();
|
|
||||||
}
|
}
|
||||||
|
Map<ContactId, TransportProperties> remote =
|
||||||
|
callback.getRemoteProperties();
|
||||||
if(!remote.containsKey(c)) return null;
|
if(!remote.containsKey(c)) return null;
|
||||||
remote = Collections.singletonMap(c, remote.get(c));
|
remote = Collections.singletonMap(c, remote.get(c));
|
||||||
String url = discoverContactUrls(remote).get(c);
|
String url = discoverContactUrls(remote).get(c);
|
||||||
@@ -293,6 +282,9 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
|
|
||||||
private StreamTransportConnection createInvitationConnection(int code,
|
private StreamTransportConnection createInvitationConnection(int code,
|
||||||
long timeout) {
|
long timeout) {
|
||||||
|
synchronized(this) {
|
||||||
|
if(!running) return null;
|
||||||
|
}
|
||||||
// The invitee's device may not be discoverable, so both parties must
|
// The invitee's device may not be discoverable, so both parties must
|
||||||
// try to initiate connections
|
// try to initiate connections
|
||||||
String uuid = convertInvitationCodeToUuid(code);
|
String uuid = convertInvitationCodeToUuid(code);
|
||||||
@@ -370,7 +362,6 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
if(!running) return;
|
if(!running) return;
|
||||||
makeDeviceDiscoverable();
|
makeDeviceDiscoverable();
|
||||||
}
|
}
|
||||||
// Bind the socket
|
|
||||||
String url = "btspp://localhost:" + c.getUuid() + ";name=RFCOMM";
|
String url = "btspp://localhost:" + c.getUuid() + ";name=RFCOMM";
|
||||||
final StreamConnectionNotifier scn;
|
final StreamConnectionNotifier scn;
|
||||||
try {
|
try {
|
||||||
@@ -379,37 +370,26 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Close the socket when the invitation times out
|
||||||
pluginExecutor.execute(new Runnable() {
|
pluginExecutor.execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
acceptInvitationConnection(c, scn);
|
try {
|
||||||
|
Thread.sleep(c.getTimeout());
|
||||||
|
} catch(InterruptedException e) {
|
||||||
|
if(LOG.isLoggable(Level.INFO))
|
||||||
|
LOG.info("Interrupted while waiting for invitation");
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
tryToClose(scn);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Close the socket when the invitation times out
|
|
||||||
try {
|
|
||||||
Thread.sleep(c.getTimeout());
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
if(LOG.isLoggable(Level.INFO))
|
|
||||||
LOG.info("Interrupted while waiting for invitation timeout");
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
scn.close();
|
|
||||||
} catch(IOException e) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void acceptInvitationConnection(ConnectionCallback c,
|
|
||||||
StreamConnectionNotifier scn) {
|
|
||||||
synchronized(this) {
|
|
||||||
if(!running) return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
StreamConnection s = scn.acceptAndOpen();
|
StreamConnection s = scn.acceptAndOpen();
|
||||||
c.addConnection(s);
|
c.addConnection(s);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
// This is expected when the socket is closed
|
// This is expected when the socket is closed
|
||||||
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
||||||
|
tryToClose(scn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,21 @@ import net.sf.briar.api.plugins.PluginExecutor;
|
|||||||
import net.sf.briar.api.transport.BatchTransportReader;
|
import net.sf.briar.api.transport.BatchTransportReader;
|
||||||
import net.sf.briar.api.transport.BatchTransportWriter;
|
import net.sf.briar.api.transport.BatchTransportWriter;
|
||||||
import net.sf.briar.api.transport.TransportConstants;
|
import net.sf.briar.api.transport.TransportConstants;
|
||||||
import net.sf.briar.plugins.AbstractPlugin;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileSystemUtils;
|
import org.apache.commons.io.FileSystemUtils;
|
||||||
|
|
||||||
abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
|
abstract class FilePlugin implements BatchPlugin {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(FilePlugin.class.getName());
|
Logger.getLogger(FilePlugin.class.getName());
|
||||||
|
|
||||||
|
protected final Executor pluginExecutor;
|
||||||
protected final BatchPluginCallback callback;
|
protected final BatchPluginCallback callback;
|
||||||
|
|
||||||
|
protected volatile boolean running = false;
|
||||||
|
|
||||||
private final Object listenerLock = new Object();
|
private final Object listenerLock = new Object();
|
||||||
|
|
||||||
private FileListener listener = null; // Locking: listenerLock
|
private FileListener listener = null; // Locking: listenerLock
|
||||||
|
|
||||||
protected abstract File chooseOutputDirectory();
|
protected abstract File chooseOutputDirectory();
|
||||||
@@ -38,7 +41,7 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
|
|||||||
|
|
||||||
protected FilePlugin(@PluginExecutor Executor pluginExecutor,
|
protected FilePlugin(@PluginExecutor Executor pluginExecutor,
|
||||||
BatchPluginCallback callback) {
|
BatchPluginCallback callback) {
|
||||||
super(pluginExecutor);
|
this.pluginExecutor = pluginExecutor;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +50,7 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BatchTransportWriter createWriter(ContactId c) {
|
public BatchTransportWriter createWriter(ContactId c) {
|
||||||
|
if(!running) return null;
|
||||||
return createWriter(createConnectionFilename());
|
return createWriter(createConnectionFilename());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,9 +67,7 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private BatchTransportWriter createWriter(String filename) {
|
private BatchTransportWriter createWriter(String filename) {
|
||||||
synchronized(this) {
|
if(!running) return null;
|
||||||
if(!running) return null;
|
|
||||||
}
|
|
||||||
File dir = chooseOutputDirectory();
|
File dir = chooseOutputDirectory();
|
||||||
if(dir == null || !dir.exists() || !dir.isDirectory()) return null;
|
if(dir == null || !dir.exists() || !dir.isDirectory()) return null;
|
||||||
File f = new File(dir, filename);
|
File f = new File(dir, filename);
|
||||||
@@ -85,26 +87,30 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
|
|||||||
return FileSystemUtils.freeSpaceKb(path) * 1024L;
|
return FileSystemUtils.freeSpaceKb(path) * 1024L;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void createReaderFromFile(final File f) {
|
protected void createReaderFromFile(final File f) {
|
||||||
if(!running) return;
|
if(!running) return;
|
||||||
pluginExecutor.execute(new ReaderCreator(f));
|
pluginExecutor.execute(new ReaderCreator(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BatchTransportWriter sendInvitation(int code, long timeout) {
|
public BatchTransportWriter sendInvitation(int code, long timeout) {
|
||||||
|
if(!running) return null;
|
||||||
return createWriter(createInvitationFilename(code, false));
|
return createWriter(createInvitationFilename(code, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BatchTransportReader acceptInvitation(int code, long timeout) {
|
public BatchTransportReader acceptInvitation(int code, long timeout) {
|
||||||
|
if(!running) return null;
|
||||||
String filename = createInvitationFilename(code, false);
|
String filename = createInvitationFilename(code, false);
|
||||||
return createInvitationReader(filename, timeout);
|
return createInvitationReader(filename, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BatchTransportWriter sendInvitationResponse(int code, long timeout) {
|
public BatchTransportWriter sendInvitationResponse(int code, long timeout) {
|
||||||
|
if(!running) return null;
|
||||||
return createWriter(createInvitationFilename(code, true));
|
return createWriter(createInvitationFilename(code, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public BatchTransportReader acceptInvitationResponse(int code,
|
public BatchTransportReader acceptInvitationResponse(int code,
|
||||||
long timeout) {
|
long timeout) {
|
||||||
|
if(!running) return null;
|
||||||
String filename = createInvitationFilename(code, true);
|
String filename = createInvitationFilename(code, true);
|
||||||
return createInvitationReader(filename, timeout);
|
return createInvitationReader(filename, timeout);
|
||||||
}
|
}
|
||||||
@@ -155,23 +161,23 @@ abstract class FilePlugin extends AbstractPlugin implements BatchPlugin {
|
|||||||
|
|
||||||
private class ReaderCreator implements Runnable {
|
private class ReaderCreator implements Runnable {
|
||||||
|
|
||||||
private final File f;
|
private final File file;
|
||||||
|
|
||||||
private ReaderCreator(File f) {
|
private ReaderCreator(File file) {
|
||||||
this.f = f;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
String filename = f.getName();
|
String filename = file.getName();
|
||||||
if(isPossibleInvitationFilename(filename)) {
|
if(isPossibleInvitationFilename(filename)) {
|
||||||
synchronized(listenerLock) {
|
synchronized(listenerLock) {
|
||||||
if(listener != null) listener.addFile(f);
|
if(listener != null) listener.addFile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(isPossibleConnectionFilename(f.getName())) {
|
if(isPossibleConnectionFilename(file.getName())) {
|
||||||
try {
|
try {
|
||||||
FileInputStream in = new FileInputStream(f);
|
FileInputStream in = new FileInputStream(file);
|
||||||
callback.readerCreated(new FileTransportReader(f, in,
|
callback.readerCreated(new FileTransportReader(file, in,
|
||||||
FilePlugin.this));
|
FilePlugin.this));
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
if(LOG.isLoggable(Level.WARNING))
|
||||||
|
|||||||
@@ -41,15 +41,13 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void start() throws IOException {
|
||||||
public synchronized void start() throws IOException {
|
running = true;
|
||||||
super.start();
|
|
||||||
monitor.start(this);
|
monitor.start(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void stop() throws IOException {
|
||||||
public synchronized void stop() throws IOException {
|
running = false;
|
||||||
super.stop();
|
|
||||||
monitor.stop();
|
monitor.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamTransportConnection sendInvitation(int code, long timeout) {
|
public StreamTransportConnection sendInvitation(int code, long timeout) {
|
||||||
|
synchronized(this) {
|
||||||
|
if(!running) return null;
|
||||||
|
}
|
||||||
// Calculate the group address and port from the invitation code
|
// Calculate the group address and port from the invitation code
|
||||||
InetSocketAddress mcast = convertInvitationCodeToMulticastGroup(code);
|
InetSocketAddress mcast = convertInvitationCodeToMulticastGroup(code);
|
||||||
// Bind a multicast socket for receiving packets
|
// Bind a multicast socket for receiving packets
|
||||||
@@ -48,15 +51,7 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
ms.joinGroup(mcast.getAddress());
|
ms.joinGroup(mcast.getAddress());
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
if(ms != null) {
|
if(ms != null) tryToClose(ms, mcast.getAddress());
|
||||||
try {
|
|
||||||
ms.leaveGroup(mcast.getAddress());
|
|
||||||
} catch(IOException e1) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
|
||||||
LOG.warning(e1.toString());
|
|
||||||
}
|
|
||||||
ms.close();
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Listen until a valid packet is received or the timeout occurs
|
// Listen until a valid packet is received or the timeout occurs
|
||||||
@@ -77,8 +72,6 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
try {
|
try {
|
||||||
// Connect back on the advertised TCP port
|
// Connect back on the advertised TCP port
|
||||||
Socket s = new Socket(packet.getAddress(), port);
|
Socket s = new Socket(packet.getAddress(), port);
|
||||||
ms.leaveGroup(mcast.getAddress());
|
|
||||||
ms.close();
|
|
||||||
return new SocketTransportConnection(s);
|
return new SocketTransportConnection(s);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
if(LOG.isLoggable(Level.WARNING))
|
||||||
@@ -89,21 +82,29 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
now = System.currentTimeMillis();
|
now = System.currentTimeMillis();
|
||||||
|
synchronized(this) {
|
||||||
|
if(!running) return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(LOG.isLoggable(Level.INFO))
|
if(LOG.isLoggable(Level.INFO))
|
||||||
LOG.info("Timeout while sending invitation");
|
LOG.info("Timeout while sending invitation");
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
try {
|
} finally {
|
||||||
ms.leaveGroup(mcast.getAddress());
|
tryToClose(ms, mcast.getAddress());
|
||||||
} catch(IOException e1) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e1.toString());
|
|
||||||
}
|
|
||||||
ms.close();
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToClose(MulticastSocket ms, InetAddress addr) {
|
||||||
|
try {
|
||||||
|
ms.leaveGroup(addr);
|
||||||
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
|
}
|
||||||
|
ms.close();
|
||||||
|
}
|
||||||
|
|
||||||
private InetSocketAddress convertInvitationCodeToMulticastGroup(int code) {
|
private InetSocketAddress convertInvitationCodeToMulticastGroup(int code) {
|
||||||
Random r = new Random(code);
|
Random r = new Random(code);
|
||||||
byte[] b = new byte[5];
|
byte[] b = new byte[5];
|
||||||
@@ -139,6 +140,9 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamTransportConnection acceptInvitation(int code, long timeout) {
|
public StreamTransportConnection acceptInvitation(int code, long timeout) {
|
||||||
|
synchronized(this) {
|
||||||
|
if(!running) return null;
|
||||||
|
}
|
||||||
// Calculate the group address and port from the invitation code
|
// Calculate the group address and port from the invitation code
|
||||||
InetSocketAddress mcast = convertInvitationCodeToMulticastGroup(code);
|
InetSocketAddress mcast = convertInvitationCodeToMulticastGroup(code);
|
||||||
// Bind a TCP socket for receiving connections
|
// Bind a TCP socket for receiving connections
|
||||||
@@ -149,14 +153,7 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
ss.bind(new InetSocketAddress(iface, 0));
|
ss.bind(new InetSocketAddress(iface, 0));
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
if(ss != null) {
|
if(ss != null) tryToClose(ss);
|
||||||
try {
|
|
||||||
ss.close();
|
|
||||||
} catch(IOException e1) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
|
||||||
LOG.warning(e1.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Bind a multicast socket for sending packets
|
// Bind a multicast socket for sending packets
|
||||||
@@ -168,12 +165,7 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
if(ms != null) ms.close();
|
if(ms != null) ms.close();
|
||||||
try {
|
tryToClose(ss);
|
||||||
ss.close();
|
|
||||||
} catch(IOException e1) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
|
||||||
LOG.warning(e1.toString());
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Send packets until a connection is received or the timeout expires
|
// Send packets until a connection is received or the timeout expires
|
||||||
@@ -201,6 +193,9 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
interval += 1000;
|
interval += 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
synchronized(this) {
|
||||||
|
if(!running) return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(LOG.isLoggable(Level.INFO))
|
if(LOG.isLoggable(Level.INFO))
|
||||||
LOG.info("Timeout while accepting invitation");
|
LOG.info("Timeout while accepting invitation");
|
||||||
@@ -208,13 +203,16 @@ class LanSocketPlugin extends SimpleSocketPlugin {
|
|||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
} finally {
|
} finally {
|
||||||
ms.close();
|
ms.close();
|
||||||
try {
|
tryToClose(ss);
|
||||||
ss.close();
|
|
||||||
} catch(IOException e1) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
|
||||||
LOG.warning(e1.toString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToClose(ServerSocket ss) {
|
||||||
|
try {
|
||||||
|
ss.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,10 +63,8 @@ class SimpleSocketPlugin extends SocketPlugin {
|
|||||||
return new ServerSocket();
|
return new ServerSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locking: this
|
|
||||||
@Override
|
@Override
|
||||||
protected SocketAddress getLocalSocketAddress() {
|
protected SocketAddress getLocalSocketAddress() {
|
||||||
assert running;
|
|
||||||
SocketAddress addr = createSocketAddress(callback.getLocalProperties());
|
SocketAddress addr = createSocketAddress(callback.getLocalProperties());
|
||||||
if(addr == null) {
|
if(addr == null) {
|
||||||
try {
|
try {
|
||||||
@@ -112,17 +110,13 @@ class SimpleSocketPlugin extends SocketPlugin {
|
|||||||
throw new IOException("No suitable interfaces");
|
throw new IOException("No suitable interfaces");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locking: this
|
|
||||||
@Override
|
@Override
|
||||||
protected SocketAddress getRemoteSocketAddress(ContactId c) {
|
protected SocketAddress getRemoteSocketAddress(ContactId c) {
|
||||||
assert running;
|
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||||
return p == null ? null : createSocketAddress(p);
|
return p == null ? null : createSocketAddress(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locking: this
|
|
||||||
private SocketAddress createSocketAddress(TransportProperties p) {
|
private SocketAddress createSocketAddress(TransportProperties p) {
|
||||||
assert running;
|
|
||||||
assert p != null;
|
assert p != null;
|
||||||
String host = p.get("external");
|
String host = p.get("external");
|
||||||
if(host == null) host = p.get("internal");
|
if(host == null) host = p.get("internal");
|
||||||
@@ -137,10 +131,8 @@ class SimpleSocketPlugin extends SocketPlugin {
|
|||||||
return new InetSocketAddress(host, port);
|
return new InetSocketAddress(host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locking: this
|
|
||||||
@Override
|
@Override
|
||||||
protected void setLocalSocketAddress(SocketAddress s) {
|
protected void setLocalSocketAddress(SocketAddress s) {
|
||||||
assert running;
|
|
||||||
if(!(s instanceof InetSocketAddress))
|
if(!(s instanceof InetSocketAddress))
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
InetSocketAddress i = (InetSocketAddress) s;
|
InetSocketAddress i = (InetSocketAddress) s;
|
||||||
|
|||||||
@@ -15,21 +15,20 @@ import net.sf.briar.api.plugins.PluginExecutor;
|
|||||||
import net.sf.briar.api.plugins.StreamPlugin;
|
import net.sf.briar.api.plugins.StreamPlugin;
|
||||||
import net.sf.briar.api.plugins.StreamPluginCallback;
|
import net.sf.briar.api.plugins.StreamPluginCallback;
|
||||||
import net.sf.briar.api.transport.StreamTransportConnection;
|
import net.sf.briar.api.transport.StreamTransportConnection;
|
||||||
import net.sf.briar.plugins.AbstractPlugin;
|
|
||||||
|
|
||||||
abstract class SocketPlugin extends AbstractPlugin implements StreamPlugin {
|
abstract class SocketPlugin implements StreamPlugin {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(SocketPlugin.class.getName());
|
Logger.getLogger(SocketPlugin.class.getName());
|
||||||
|
|
||||||
|
protected final Executor pluginExecutor;
|
||||||
protected final StreamPluginCallback callback;
|
protected final StreamPluginCallback callback;
|
||||||
|
|
||||||
|
protected boolean running = false; // Locking: this
|
||||||
protected ServerSocket socket = null; // Locking: this
|
protected ServerSocket socket = null; // Locking: this
|
||||||
|
|
||||||
protected abstract void setLocalSocketAddress(SocketAddress s);
|
protected abstract void setLocalSocketAddress(SocketAddress s);
|
||||||
|
|
||||||
// These methods must only be called with this's lock held and
|
|
||||||
// started == true
|
|
||||||
protected abstract Socket createClientSocket() throws IOException;
|
protected abstract Socket createClientSocket() throws IOException;
|
||||||
protected abstract ServerSocket createServerSocket() throws IOException;
|
protected abstract ServerSocket createServerSocket() throws IOException;
|
||||||
protected abstract SocketAddress getLocalSocketAddress();
|
protected abstract SocketAddress getLocalSocketAddress();
|
||||||
@@ -37,13 +36,14 @@ abstract class SocketPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
|
|
||||||
protected SocketPlugin(@PluginExecutor Executor pluginExecutor,
|
protected SocketPlugin(@PluginExecutor Executor pluginExecutor,
|
||||||
StreamPluginCallback callback) {
|
StreamPluginCallback callback) {
|
||||||
super(pluginExecutor);
|
this.pluginExecutor = pluginExecutor;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void start() throws IOException {
|
||||||
public synchronized void start() throws IOException {
|
synchronized(this) {
|
||||||
super.start();
|
running = true;
|
||||||
|
}
|
||||||
pluginExecutor.execute(new Runnable() {
|
pluginExecutor.execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
bind();
|
bind();
|
||||||
@@ -55,78 +55,72 @@ abstract class SocketPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
SocketAddress addr;
|
SocketAddress addr;
|
||||||
ServerSocket ss = null;
|
ServerSocket ss = null;
|
||||||
try {
|
try {
|
||||||
synchronized(this) {
|
addr = getLocalSocketAddress();
|
||||||
if(!running) return;
|
ss = createServerSocket();
|
||||||
addr = getLocalSocketAddress();
|
|
||||||
ss = createServerSocket();
|
|
||||||
if(addr == null || ss == null) return;
|
|
||||||
}
|
|
||||||
ss.bind(addr);
|
|
||||||
if(LOG.isLoggable(Level.INFO)) {
|
|
||||||
LOG.info("Bound to " + ss.getInetAddress().getHostAddress()
|
|
||||||
+ ":" + ss.getLocalPort());
|
|
||||||
}
|
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
if(ss != null) {
|
return;
|
||||||
try {
|
}
|
||||||
ss.close();
|
if(addr == null || ss == null) return;
|
||||||
} catch(IOException e1) {
|
try {
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
ss.bind(addr);
|
||||||
LOG.warning(e1.toString());
|
} catch(IOException e) {
|
||||||
}
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
}
|
tryToClose(ss);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if(!running) {
|
if(!running) {
|
||||||
try {
|
tryToClose(ss);
|
||||||
ss.close();
|
|
||||||
} catch(IOException e) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
|
||||||
LOG.warning(e.toString());
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
socket = ss;
|
socket = ss;
|
||||||
setLocalSocketAddress(ss.getLocalSocketAddress());
|
|
||||||
}
|
}
|
||||||
// Accept connections until the socket is closed
|
setLocalSocketAddress(ss.getLocalSocketAddress());
|
||||||
|
acceptContactConnections(ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryToClose(ServerSocket ss) {
|
||||||
|
try {
|
||||||
|
ss.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void acceptContactConnections(ServerSocket ss) {
|
||||||
while(true) {
|
while(true) {
|
||||||
Socket s;
|
Socket s;
|
||||||
synchronized(this) {
|
|
||||||
if(!running) return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
s = ss.accept();
|
s = ss.accept();
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
// This is expected when the socket is closed
|
// This is expected when the socket is closed
|
||||||
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
||||||
try {
|
tryToClose(ss);
|
||||||
ss.close();
|
|
||||||
} catch(IOException e1) {
|
|
||||||
if(LOG.isLoggable(Level.WARNING))
|
|
||||||
LOG.warning(e1.toString());
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SocketTransportConnection conn = new SocketTransportConnection(s);
|
SocketTransportConnection conn = new SocketTransportConnection(s);
|
||||||
callback.incomingConnectionCreated(conn);
|
callback.incomingConnectionCreated(conn);
|
||||||
|
synchronized(this) {
|
||||||
|
if(!running) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void stop() throws IOException {
|
public synchronized void stop() throws IOException {
|
||||||
super.stop();
|
running = false;
|
||||||
if(socket != null) socket.close();
|
if(socket != null) {
|
||||||
|
socket.close();
|
||||||
|
socket = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void poll() {
|
public void poll() {
|
||||||
Map<ContactId, TransportProperties> remote;
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if(!running) return;
|
if(!running) return;
|
||||||
remote = callback.getRemoteProperties();
|
|
||||||
}
|
}
|
||||||
|
Map<ContactId, TransportProperties> remote =
|
||||||
|
callback.getRemoteProperties();
|
||||||
for(final ContactId c : remote.keySet()) {
|
for(final ContactId c : remote.keySet()) {
|
||||||
pluginExecutor.execute(new Runnable() {
|
pluginExecutor.execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -142,20 +136,18 @@ abstract class SocketPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StreamTransportConnection createConnection(ContactId c) {
|
public StreamTransportConnection createConnection(ContactId c) {
|
||||||
SocketAddress addr;
|
synchronized(this) {
|
||||||
Socket s;
|
if(!running) return null;
|
||||||
|
}
|
||||||
|
SocketAddress addr = getRemoteSocketAddress(c);
|
||||||
try {
|
try {
|
||||||
synchronized(this) {
|
Socket s = createClientSocket();
|
||||||
if(!running) return null;
|
if(addr == null || s == null) return null;
|
||||||
addr = getRemoteSocketAddress(c);
|
|
||||||
s = createClientSocket();
|
|
||||||
if(addr == null || s == null) return null;
|
|
||||||
}
|
|
||||||
s.connect(addr);
|
s.connect(addr);
|
||||||
|
return new SocketTransportConnection(s);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
if(LOG.isLoggable(Level.INFO)) LOG.info(e.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new SocketTransportConnection(s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user