From a17349e0153531f55b97fe40e5694bbbc275bb96 Mon Sep 17 00:00:00 2001
From: akwizgran <michael@briarproject.org>
Date: Thu, 13 Jun 2013 12:40:19 +0100
Subject: [PATCH] Replaced redundant SocketReceiver classes with a generic
 class.

---
 .../plugins/droidtooth/DroidtoothPlugin.java  | 60 ++++++-------------
 .../sf/briar/plugins/tcp/LanTcpPlugin.java    | 48 ++++-----------
 .../net/sf/briar/util/LatchedReference.java   | 29 +++++++++
 3 files changed, 60 insertions(+), 77 deletions(-)
 create mode 100644 briar-core/src/net/sf/briar/util/LatchedReference.java

diff --git a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
index d20cb746a7..12c9aab68d 100644
--- a/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java
@@ -22,8 +22,6 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.Logger;
 
 import net.sf.briar.api.ContactId;
@@ -35,6 +33,7 @@ import net.sf.briar.api.crypto.PseudoRandom;
 import net.sf.briar.api.plugins.duplex.DuplexPlugin;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
+import net.sf.briar.util.LatchedReference;
 import net.sf.briar.util.StringUtils;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
@@ -361,12 +360,13 @@ class DroidtoothPlugin implements DuplexPlugin {
 			return null;
 		}
 		// Start the background threads
-		SocketReceiver receiver = new SocketReceiver();
-		new DiscoveryThread(receiver, uuid.toString(), timeout).start();
-		new BluetoothListenerThread(receiver, ss).start();
+		LatchedReference<BluetoothSocket> socketLatch =
+				new LatchedReference<BluetoothSocket>();
+		new DiscoveryThread(socketLatch, uuid.toString(), timeout).start();
+		new BluetoothListenerThread(socketLatch, ss).start();
 		// Wait for an incoming or outgoing connection
 		try {
-			BluetoothSocket s = receiver.waitForSocket(timeout);
+			BluetoothSocket s = socketLatch.waitForReference(timeout);
 			if(s != null) return new DroidtoothTransportConnection(this, s);
 		} catch(InterruptedException e) {
 			if(LOG.isLoggable(INFO))
@@ -409,40 +409,15 @@ class DroidtoothPlugin implements DuplexPlugin {
 		}
 	}
 
-	private static class SocketReceiver {
-
-		private final CountDownLatch latch = new CountDownLatch(1);
-		private final AtomicReference<BluetoothSocket> socket =
-				new AtomicReference<BluetoothSocket>();
-
-		private boolean hasSocket() {
-			return socket.get() != null;
-		}
-
-		private boolean setSocket(BluetoothSocket s) {
-			if(socket.compareAndSet(null, s)) {
-				latch.countDown();
-				return true;
-			}
-			return false;
-		}
-
-		private BluetoothSocket waitForSocket(long timeout)
-				throws InterruptedException {
-			latch.await(timeout, TimeUnit.MILLISECONDS);
-			return socket.get();
-		}
-	}
-
 	private class DiscoveryThread extends Thread {
 
-		private final SocketReceiver receiver;
+		private final LatchedReference<BluetoothSocket> socketLatch;
 		private final String uuid;
 		private final long timeout;
 
-		private DiscoveryThread(SocketReceiver receiver, String uuid,
-				long timeout) {
-			this.receiver = receiver;
+		private DiscoveryThread(LatchedReference<BluetoothSocket> socketLatch,
+				String uuid, long timeout) {
+			this.socketLatch = socketLatch;
 			this.uuid = uuid;
 			this.timeout = timeout;
 		}
@@ -451,7 +426,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 		public void run() {
 			long now = clock.currentTimeMillis();
 			long end = now + timeout;
-			while(now < end && running && !receiver.hasSocket()) {
+			while(now < end && running && !socketLatch.isSet()) {
 				// Discover nearby devices
 				if(LOG.isLoggable(INFO)) LOG.info("Discovering nearby devices");
 				List<String> addresses;
@@ -465,12 +440,12 @@ class DroidtoothPlugin implements DuplexPlugin {
 				// Connect to any device with the right UUID
 				for(String address : addresses) {
 					now = clock.currentTimeMillis();
-					if(now < end  && running && !receiver.hasSocket()) {
+					if(now < end  && running && !socketLatch.isSet()) {
 						BluetoothSocket s = connect(address, uuid);
 						if(s == null) continue;
 						if(LOG.isLoggable(INFO))
 							LOG.info("Outgoing connection");
-						if(!receiver.setSocket(s)) {
+						if(!socketLatch.set(s)) {
 							if(LOG.isLoggable(INFO))
 								LOG.info("Closing redundant connection");
 							tryToClose(s);
@@ -519,12 +494,13 @@ class DroidtoothPlugin implements DuplexPlugin {
 
 	private static class BluetoothListenerThread extends Thread {
 
-		private final SocketReceiver receiver;
+		private final LatchedReference<BluetoothSocket> socketLatch;
 		private final BluetoothServerSocket serverSocket;
 
-		private BluetoothListenerThread(SocketReceiver receiver,
+		private BluetoothListenerThread(
+				LatchedReference<BluetoothSocket> socketLatch,
 				BluetoothServerSocket serverSocket) {
-			this.receiver = receiver;
+			this.socketLatch = socketLatch;
 			this.serverSocket = serverSocket;
 		}
 
@@ -533,7 +509,7 @@ class DroidtoothPlugin implements DuplexPlugin {
 			try {
 				BluetoothSocket s = serverSocket.accept();
 				if(LOG.isLoggable(INFO)) LOG.info("Incoming connection");
-				if(!receiver.setSocket(s)) {
+				if(!socketLatch.set(s)) {
 					if(LOG.isLoggable(INFO))
 						LOG.info("Closing redundant connection");
 					s.close();
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
index 4481c3724c..dff58aa677 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
@@ -18,10 +18,7 @@ import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
 import java.util.logging.Logger;
 
 import net.sf.briar.api.TransportId;
@@ -31,6 +28,7 @@ import net.sf.briar.api.crypto.PseudoRandom;
 import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
 import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
 import net.sf.briar.util.ByteUtils;
+import net.sf.briar.util.LatchedReference;
 import net.sf.briar.util.StringUtils;
 
 /** A socket plugin that supports exchanging invitations over a LAN. */
@@ -151,9 +149,9 @@ class LanTcpPlugin extends TcpPlugin {
 			return null;
 		}
 		// Start the listener threads
-		SocketReceiver receiver = new SocketReceiver();
-		new MulticastListenerThread(receiver, ms, iface).start();
-		new TcpListenerThread(receiver, ss).start();
+		LatchedReference<Socket> socketLatch = new LatchedReference<Socket>();
+		new MulticastListenerThread(socketLatch, ms, iface).start();
+		new TcpListenerThread(socketLatch, ss).start();
 		// Send packets until a connection is made or we run out of time
 		byte[] buffer = new byte[2];
 		ByteUtils.writeUint16(ss.getLocalPort(), buffer, 0);
@@ -169,7 +167,7 @@ class LanTcpPlugin extends TcpPlugin {
 				ms.send(packet);
 				// Wait for an incoming or outgoing connection
 				try {
-					Socket s = receiver.waitForSocket(MULTICAST_INTERVAL);
+					Socket s = socketLatch.waitForReference(MULTICAST_INTERVAL);
 					if(s != null) return new TcpTransportConnection(this, s);
 				} catch(InterruptedException e) {
 					if(LOG.isLoggable(INFO))
@@ -252,35 +250,15 @@ class LanTcpPlugin extends TcpPlugin {
 		return sendInvitation(r, timeout);
 	}
 
-	private static class SocketReceiver {
-
-		private final CountDownLatch latch = new CountDownLatch(1);
-		private final AtomicReference<Socket> socket =
-				new AtomicReference<Socket>();
-
-		private boolean setSocket(Socket s) {
-			if(socket.compareAndSet(null, s)) {
-				latch.countDown();
-				return true;
-			}
-			return false;
-		}
-
-		private Socket waitForSocket(long timeout) throws InterruptedException {
-			latch.await(timeout, TimeUnit.MILLISECONDS);
-			return socket.get();
-		}
-	}
-
 	private class MulticastListenerThread extends Thread {
 
-		private final SocketReceiver receiver;
+		private final LatchedReference<Socket> socketLatch;
 		private final MulticastSocket multicastSocket;
 		private final InetAddress localAddress;
 
-		private MulticastListenerThread(SocketReceiver receiver,
+		private MulticastListenerThread(LatchedReference<Socket> socketLatch,
 				MulticastSocket multicastSocket, InetAddress localAddress) {
-			this.receiver = receiver;
+			this.socketLatch = socketLatch;
 			this.multicastSocket = multicastSocket;
 			this.localAddress = localAddress;
 		}
@@ -329,7 +307,7 @@ class LanTcpPlugin extends TcpPlugin {
 				// Connect back on the advertised TCP port
 				Socket s = new Socket(addr, port);
 				if(LOG.isLoggable(INFO)) LOG.info("Outgoing connection");
-				if(!receiver.setSocket(s)) {
+				if(!socketLatch.set(s)) {
 					if(LOG.isLoggable(INFO))
 						LOG.info("Closing redundant connection");
 					s.close();
@@ -342,12 +320,12 @@ class LanTcpPlugin extends TcpPlugin {
 
 	private class TcpListenerThread extends Thread {
 
-		private final SocketReceiver receiver;
+		private final LatchedReference<Socket> socketLatch;
 		private final ServerSocket serverSocket;
 
-		private TcpListenerThread(SocketReceiver receiver,
+		private TcpListenerThread(LatchedReference<Socket> socketLatch,
 				ServerSocket serverSocket) {
-			this.receiver = receiver;
+			this.socketLatch = socketLatch;
 			this.serverSocket = serverSocket;
 		}
 
@@ -359,7 +337,7 @@ class LanTcpPlugin extends TcpPlugin {
 			try {
 				Socket s = serverSocket.accept();
 				if(LOG.isLoggable(INFO)) LOG.info("Incoming connection");
-				if(!receiver.setSocket(s)) {
+				if(!socketLatch.set(s)) {
 					if(LOG.isLoggable(INFO))
 						LOG.info("Closing redundant connection");
 					s.close();
diff --git a/briar-core/src/net/sf/briar/util/LatchedReference.java b/briar-core/src/net/sf/briar/util/LatchedReference.java
new file mode 100644
index 0000000000..98e7742bef
--- /dev/null
+++ b/briar-core/src/net/sf/briar/util/LatchedReference.java
@@ -0,0 +1,29 @@
+package net.sf.briar.util;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class LatchedReference<T> {
+
+	private final CountDownLatch latch = new CountDownLatch(1);
+	private final AtomicReference<T> reference = new AtomicReference<T>();
+
+	public boolean isSet() {
+		return reference.get() != null;
+	}
+
+	public boolean set(T t) {
+		if(t == null) throw new IllegalArgumentException();
+		if(reference.compareAndSet(null, t)) {
+			latch.countDown();
+			return true;
+		}
+		return false;
+	}
+
+	public T waitForReference(long timeout) throws InterruptedException {
+		latch.await(timeout, TimeUnit.MILLISECONDS);
+		return reference.get();
+	}
+}
-- 
GitLab