diff --git a/src/net/sf/briar/api/plugins/Plugin.java b/src/net/sf/briar/api/plugins/Plugin.java index 4debef1e2984059d4fd8d3d3f054e16112b9c962..c6284ca92dd33575311fa07a251b7e65ce9d9a5d 100644 --- a/src/net/sf/briar/api/plugins/Plugin.java +++ b/src/net/sf/briar/api/plugins/Plugin.java @@ -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; diff --git a/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java index a46a9b8cad395f68d82e9383ac11714d4f964e1f..5fac5810c34649c686f65ec0a6800188cf17c1c8 100644 --- a/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java +++ b/src/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java @@ -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) { diff --git a/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java b/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java index df250dede35cad9c12c3df79b57900dd89c062f9..9f134200b51134ef6a66eae9196b7de3bff14fa6 100644 --- a/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java +++ b/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java @@ -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; diff --git a/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java b/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java index 90c00821733710d0f61e7910930495d66d8ef47f..15914a70d6f3175d307cdc2af3a7d96fb5cdbf7a 100644 --- a/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java +++ b/src/net/sf/briar/plugins/file/RemovableDrivePlugin.java @@ -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 { diff --git a/src/net/sf/briar/plugins/modem/ModemPlugin.java b/src/net/sf/briar/plugins/modem/ModemPlugin.java index b985fbb644d41ef7f2ae5e4439650917162a98ae..d97d6232ee4ed5c2cba91c8f31dd34a99ce8eb8f 100644 --- a/src/net/sf/briar/plugins/modem/ModemPlugin.java +++ b/src/net/sf/briar/plugins/modem/ModemPlugin.java @@ -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 { diff --git a/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java b/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java index 47bf16d7ec2fa1d888ee4944d9b430bfcca3d15e..ecfbfcb3f92c08fc903d2dfda46ed896d793e3c1 100644 --- a/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java +++ b/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java @@ -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"); diff --git a/src/net/sf/briar/plugins/tcp/TcpPlugin.java b/src/net/sf/briar/plugins/tcp/TcpPlugin.java index 0ca380a0109128216fc1910a7adeb130a5e88581..b0b77ca59bfac40f88bdf485aae1ba5ad9780726 100644 --- a/src/net/sf/briar/plugins/tcp/TcpPlugin.java +++ b/src/net/sf/briar/plugins/tcp/TcpPlugin.java @@ -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; diff --git a/src/net/sf/briar/plugins/tor/TorPlugin.java b/src/net/sf/briar/plugins/tor/TorPlugin.java index ad555b45bd644512f73e79ffd953e71e246b2664..034603232fb1c43ca37b46a33409b654c57085f9 100644 --- a/src/net/sf/briar/plugins/tor/TorPlugin.java +++ b/src/net/sf/briar/plugins/tor/TorPlugin.java @@ -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() {