mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Allow Plugin.start() to fail gracefully; removed unnecessary locking.
This commit is contained in:
@@ -14,8 +14,8 @@ public interface Plugin {
|
||||
/** Returns a label for looking up the plugin's translated name. */
|
||||
String getName();
|
||||
|
||||
/** Starts the plugin. */
|
||||
void start() throws IOException;
|
||||
/** Starts the plugin and returns true if it started successfully. */
|
||||
boolean start() throws IOException;
|
||||
|
||||
/** Stops the plugin. */
|
||||
void stop() throws IOException;
|
||||
|
||||
@@ -53,8 +53,8 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
private final Object discoveryLock = new Object();
|
||||
private final ScheduledExecutorService scheduler;
|
||||
|
||||
private boolean running = false; // Locking: this
|
||||
private StreamConnectionNotifier socket = null; // Locking: this
|
||||
private volatile boolean running = false;
|
||||
private volatile StreamConnectionNotifier socket = null;
|
||||
|
||||
// Non-null if running has ever been true
|
||||
private volatile LocalDevice localDevice = null;
|
||||
@@ -76,7 +76,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
return "BLUETOOTH_PLUGIN_NAME";
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
public boolean start() throws IOException {
|
||||
// Initialise the Bluetooth stack
|
||||
try {
|
||||
localDevice = LocalDevice.getLocalDevice();
|
||||
@@ -84,24 +84,21 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
// On Linux the user may need to install libbluetooth-dev
|
||||
if(OsUtils.isLinux())
|
||||
callback.showMessage("BLUETOOTH_INSTALL_LIBS");
|
||||
throw new IOException(e.toString());
|
||||
return false;
|
||||
}
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Local address " + localDevice.getBluetoothAddress());
|
||||
synchronized(this) {
|
||||
running = true;
|
||||
}
|
||||
running = true;
|
||||
pluginExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
bind();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
// Advertise the Bluetooth address to contacts
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put("address", localDevice.getBluetoothAddress());
|
||||
@@ -114,13 +111,11 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
if(LOG.isLoggable(WARNING)) LOG.warning(e.toString());
|
||||
return;
|
||||
}
|
||||
synchronized(this) {
|
||||
if(!running) {
|
||||
tryToClose(scn);
|
||||
return;
|
||||
}
|
||||
socket = scn;
|
||||
if(!running) {
|
||||
tryToClose(scn);
|
||||
return;
|
||||
}
|
||||
socket = scn;
|
||||
acceptContactConnections(scn);
|
||||
}
|
||||
|
||||
@@ -155,20 +150,13 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
BluetoothTransportConnection conn =
|
||||
new BluetoothTransportConnection(s);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
synchronized(this) {
|
||||
running = false;
|
||||
if(socket != null) {
|
||||
tryToClose(socket);
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
running = false;
|
||||
if(socket != null) tryToClose(socket);
|
||||
scheduler.shutdownNow();
|
||||
}
|
||||
|
||||
@@ -181,9 +169,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
public void poll(final Collection<ContactId> connected) {
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
// Try to connect to known devices in parallel
|
||||
Map<ContactId, TransportProperties> remote =
|
||||
callback.getRemoteProperties();
|
||||
@@ -195,9 +181,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
if(address != null && uuid != null) {
|
||||
pluginExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
synchronized(BluetoothPlugin.this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
String url = makeUrl(address, uuid);
|
||||
DuplexTransportConnection conn = connect(url);
|
||||
if(conn != null)
|
||||
@@ -219,9 +203,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
public DuplexTransportConnection createConnection(ContactId c) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||
if(p == null) return null;
|
||||
String address = p.get("address");
|
||||
@@ -237,9 +219,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
|
||||
public DuplexTransportConnection sendInvitation(PseudoRandom r,
|
||||
long timeout) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
// Use the same pseudo-random UUID as the contact
|
||||
String uuid = generateUuid(r.nextBytes(16));
|
||||
// Discover nearby devices and connect to any with the right UUID
|
||||
@@ -265,9 +245,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
}
|
||||
if(url == null) return null;
|
||||
return connect(url);
|
||||
@@ -280,9 +258,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
|
||||
public DuplexTransportConnection acceptInvitation(PseudoRandom r,
|
||||
long timeout) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
// Use the same pseudo-random UUID as the contact
|
||||
String uuid = generateUuid(r.nextBytes(16));
|
||||
String url = makeUrl("localhost", uuid);
|
||||
@@ -296,11 +272,9 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
if(LOG.isLoggable(WARNING)) LOG.warning(e.toString());
|
||||
return null;
|
||||
}
|
||||
synchronized(this) {
|
||||
if(!running) {
|
||||
tryToClose(scn);
|
||||
return null;
|
||||
}
|
||||
if(!running) {
|
||||
tryToClose(scn);
|
||||
return null;
|
||||
}
|
||||
// Close the socket when the invitation times out
|
||||
Runnable close = new Runnable() {
|
||||
@@ -324,9 +298,7 @@ class BluetoothPlugin implements DuplexPlugin {
|
||||
|
||||
private void makeDeviceDiscoverable() {
|
||||
// Try to make the device discoverable (requires root on Linux)
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
try {
|
||||
localDevice.setDiscoverable(GIAC);
|
||||
} catch(BluetoothStateException e) {
|
||||
|
||||
@@ -61,8 +61,8 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
private final DuplexPluginCallback callback;
|
||||
private final long pollingInterval;
|
||||
|
||||
private boolean running = false; // Locking: this
|
||||
private BluetoothServerSocket socket = null; // Locking: this
|
||||
private volatile boolean running = false;
|
||||
private volatile BluetoothServerSocket socket = null;
|
||||
|
||||
// Non-null if running has ever been true
|
||||
private volatile BluetoothAdapter adapter = null;
|
||||
@@ -86,7 +86,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
return "BLUETOOTH_PLUGIN_NAME";
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
public boolean start() throws IOException {
|
||||
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
|
||||
// with a message queue, so submit it to the AndroidExecutor
|
||||
try {
|
||||
@@ -100,21 +100,18 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
} catch(ExecutionException e) {
|
||||
throw new IOException(e.toString());
|
||||
}
|
||||
if(adapter == null) throw new IOException(); // Bluetooth not supported
|
||||
synchronized(this) {
|
||||
running = true;
|
||||
}
|
||||
if(adapter == null) return false; // Bluetooth not supported
|
||||
running = true;
|
||||
pluginExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
bind();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
if(!enableBluetooth()) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Could not enable Bluetooth");
|
||||
return;
|
||||
@@ -133,20 +130,16 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
if(LOG.isLoggable(WARNING)) LOG.warning(e.toString());
|
||||
return;
|
||||
}
|
||||
synchronized(this) {
|
||||
if(!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
if(!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
acceptContactConnections(ss);
|
||||
}
|
||||
|
||||
private boolean enableBluetooth() {
|
||||
synchronized(this) {
|
||||
if(!running) return false;
|
||||
}
|
||||
if(!running) return false;
|
||||
if(adapter.isEnabled()) return true;
|
||||
// Try to enable the adapter and wait for the result
|
||||
IntentFilter filter = new IntentFilter(ACTION_STATE_CHANGED);
|
||||
@@ -190,20 +183,13 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
DroidtoothTransportConnection conn =
|
||||
new DroidtoothTransportConnection(s);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() throws IOException {
|
||||
synchronized(this) {
|
||||
running = false;
|
||||
if(socket != null) {
|
||||
tryToClose(socket);
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
running = false;
|
||||
if(socket != null) tryToClose(socket);
|
||||
}
|
||||
|
||||
public boolean shouldPoll() {
|
||||
@@ -215,9 +201,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
public void poll(Collection<ContactId> connected) {
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
// Try to connect to known devices in parallel
|
||||
Map<ContactId, TransportProperties> remote =
|
||||
callback.getRemoteProperties();
|
||||
@@ -229,9 +213,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
if(address != null && uuid != null) {
|
||||
pluginExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
synchronized(DroidtoothPlugin.this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
DuplexTransportConnection conn = connect(address, uuid);
|
||||
if(conn != null)
|
||||
callback.outgoingConnectionCreated(c, conn);
|
||||
@@ -269,9 +251,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
public DuplexTransportConnection createConnection(ContactId c) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||
if(p == null) return null;
|
||||
String address = p.get("address");
|
||||
@@ -286,9 +266,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
|
||||
public DuplexTransportConnection sendInvitation(PseudoRandom r,
|
||||
long timeout) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
// Use the same pseudo-random UUID as the contact
|
||||
String uuid = UUID.nameUUIDFromBytes(r.nextBytes(16)).toString();
|
||||
// Register to receive Bluetooth discovery intents
|
||||
@@ -311,9 +289,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
|
||||
public DuplexTransportConnection acceptInvitation(PseudoRandom r,
|
||||
long timeout) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
// Use the same pseudo-random UUID as the contact
|
||||
UUID uuid = UUID.nameUUIDFromBytes(r.nextBytes(16));
|
||||
// Bind a new server socket to accept the invitation connection
|
||||
@@ -394,9 +370,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
for(final String address : addresses) {
|
||||
pluginExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
synchronized(DroidtoothPlugin.this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
DuplexTransportConnection conn = connect(address, uuid);
|
||||
if(conn != null) {
|
||||
connection = conn;
|
||||
|
||||
@@ -47,9 +47,10 @@ implements RemovableDriveMonitor.Callback {
|
||||
return "REMOVABLE_DRIVE_PLUGIN_NAME";
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
public boolean start() throws IOException {
|
||||
running = true;
|
||||
monitor.start(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void stop() throws IOException {
|
||||
|
||||
@@ -43,8 +43,9 @@ class ModemPlugin implements DuplexPlugin {
|
||||
return "MODEM_PLUGIN_NAME";
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
public boolean start() throws IOException {
|
||||
// FIXME
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stop() throws IOException {
|
||||
|
||||
@@ -110,9 +110,7 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
|
||||
public DuplexTransportConnection sendInvitation(PseudoRandom r,
|
||||
long timeout) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
// Use the invitation code to choose the group address and port
|
||||
InetSocketAddress mcast = chooseMulticastGroup(r);
|
||||
// Bind a multicast socket for receiving packets
|
||||
@@ -157,9 +155,7 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
break;
|
||||
}
|
||||
now = System.currentTimeMillis();
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
}
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Timeout while sending invitation");
|
||||
@@ -242,9 +238,7 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
|
||||
public DuplexTransportConnection acceptInvitation(PseudoRandom r,
|
||||
long timeout) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
// Use the invitation code to choose the group address and port
|
||||
InetSocketAddress mcast = chooseMulticastGroup(r);
|
||||
// Bind a TCP socket for receiving connections
|
||||
@@ -299,9 +293,7 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
interval += 1000;
|
||||
}
|
||||
}
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
}
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Timeout while accepting invitation");
|
||||
|
||||
@@ -32,8 +32,8 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
protected final DuplexPluginCallback callback;
|
||||
protected final long pollingInterval;
|
||||
|
||||
protected boolean running = false; // Locking: this
|
||||
private ServerSocket socket = null; // Locking: this
|
||||
protected volatile boolean running = false;
|
||||
private volatile ServerSocket socket = null;
|
||||
|
||||
/**
|
||||
* Returns zero or more socket addresses on which the plugin should listen,
|
||||
@@ -48,15 +48,14 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
this.pollingInterval = pollingInterval;
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
synchronized(this) {
|
||||
running = true;
|
||||
}
|
||||
public boolean start() throws IOException {
|
||||
running = true;
|
||||
pluginExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
bind();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
@@ -83,13 +82,11 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Could not bind server socket");
|
||||
return;
|
||||
}
|
||||
synchronized(this) {
|
||||
if(!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
if(!running) {
|
||||
tryToClose(ss);
|
||||
return;
|
||||
}
|
||||
socket = ss;
|
||||
if(LOG.isLoggable(INFO)) {
|
||||
String addr = ss.getInetAddress().getHostAddress();
|
||||
int port = ss.getLocalPort();
|
||||
@@ -129,18 +126,13 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
}
|
||||
TcpTransportConnection conn = new TcpTransportConnection(s);
|
||||
callback.incomingConnectionCreated(conn);
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void stop() throws IOException {
|
||||
public void stop() throws IOException {
|
||||
running = false;
|
||||
if(socket != null) {
|
||||
tryToClose(socket);
|
||||
socket = null;
|
||||
}
|
||||
if(socket != null) tryToClose(socket);
|
||||
}
|
||||
|
||||
public boolean shouldPoll() {
|
||||
@@ -152,9 +144,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
public void poll(Collection<ContactId> connected) {
|
||||
synchronized(this) {
|
||||
if(!running) return;
|
||||
}
|
||||
if(!running) return;
|
||||
Map<ContactId, TransportProperties> remote =
|
||||
callback.getRemoteProperties();
|
||||
for(final ContactId c : remote.keySet()) {
|
||||
@@ -173,9 +163,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
public DuplexTransportConnection createConnection(ContactId c) {
|
||||
synchronized(this) {
|
||||
if(!running) return null;
|
||||
}
|
||||
if(!running) return null;
|
||||
SocketAddress addr = getRemoteSocketAddress(c);
|
||||
Socket s = new Socket();
|
||||
if(addr == null || s == null) return null;
|
||||
|
||||
@@ -66,7 +66,7 @@ class TorPlugin implements DuplexPlugin {
|
||||
return "TOR_PLUGIN_NAME";
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
public boolean start() throws IOException {
|
||||
synchronized(this) {
|
||||
running = true;
|
||||
}
|
||||
@@ -75,6 +75,7 @@ class TorPlugin implements DuplexPlugin {
|
||||
bind();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
|
||||
Reference in New Issue
Block a user