From 7065f54a570a7c638315dbbb484438e7afb39407 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Sun, 30 Oct 2011 22:26:23 +0000
Subject: [PATCH] Prefer LAN interfaces for invitations, WAN for connections.

---
 .../plugins/bluetooth/BluetoothPlugin.java    |  5 +-
 .../briar/plugins/socket/LanSocketPlugin.java | 27 ++++++++---
 .../plugins/socket/SimpleSocketPlugin.java    | 48 ++++++++++++++++++-
 3 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
index d1efb602e7..1fe994a921 100644
--- a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
+++ b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
@@ -175,8 +175,9 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
 				if(LOG.isLoggable(Level.INFO)) LOG.info(e.getMessage());
 				return;
 			}
-			callback.incomingConnectionCreated(
-					new BluetoothTransportConnection(s));
+			BluetoothTransportConnection conn =
+				new BluetoothTransportConnection(s);
+			callback.incomingConnectionCreated(conn);
 		}
 	}
 
diff --git a/components/net/sf/briar/plugins/socket/LanSocketPlugin.java b/components/net/sf/briar/plugins/socket/LanSocketPlugin.java
index cef5592951..3e01734138 100644
--- a/components/net/sf/briar/plugins/socket/LanSocketPlugin.java
+++ b/components/net/sf/briar/plugins/socket/LanSocketPlugin.java
@@ -44,8 +44,9 @@ public class LanSocketPlugin extends SimpleSocketPlugin {
 		// Bind a multicast socket for receiving packets
 		MulticastSocket ms = null;
 		try {
+			InetAddress iface = chooseMulticastInterface();
 			ms = new MulticastSocket(mcast.getPort());
-			ms.setInterface(chooseInterface());
+			ms.setInterface(iface);
 			ms.joinGroup(mcast.getAddress());
 		} catch(IOException e) {
 			if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
@@ -133,7 +134,7 @@ public class LanSocketPlugin extends SimpleSocketPlugin {
 		return b;
 	}
 
-	private InetAddress chooseInterface() throws IOException {
+	private InetAddress chooseMulticastInterface() throws IOException {
 		// Try to find a LAN interface that supports multicast
 		Enumeration<NetworkInterface> ifaces =
 			NetworkInterface.getNetworkInterfaces();
@@ -149,8 +150,20 @@ public class LanSocketPlugin extends SimpleSocketPlugin {
 				}
 			}
 		}
-		// Bind to 0.0.0.0
-		return InetAddress.getByName("0.0.0.0");
+		// Settle for a WAN interface that supports multicast
+		for(NetworkInterface iface : Collections.list(ifaces)) {
+			if(iface.supportsMulticast()) {
+				Enumeration<InetAddress> addrs = iface.getInetAddresses();
+				for(InetAddress addr : Collections.list(addrs)) {
+					if(!addr.isLoopbackAddress()) {
+						if(LOG.isLoggable(Level.INFO))
+							LOG.info("Binding to " + addr.getHostAddress());
+						return addr;
+					}
+				}
+			}
+		}
+		throw new IOException("No suitable interfaces for multicast");
 	}
 
 	private int parsePacket(byte[] b, int off, int len) {
@@ -165,8 +178,9 @@ public class LanSocketPlugin extends SimpleSocketPlugin {
 		// Bind a TCP socket for receiving connections
 		ServerSocket ss = null;
 		try {
+			InetAddress iface = chooseTcpInterface(true);
 			ss = new ServerSocket();
-			ss.bind(new InetSocketAddress(chooseInterface(), 0));
+			ss.bind(new InetSocketAddress(iface, 0));
 		} catch(IOException e) {
 			if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
 			if(ss != null) {
@@ -182,8 +196,9 @@ public class LanSocketPlugin extends SimpleSocketPlugin {
 		// Bind a multicast socket for sending packets
 		MulticastSocket ms = null;
 		try {
+			InetAddress iface = chooseMulticastInterface();
 			ms = new MulticastSocket();
-			ms.setInterface(chooseInterface());
+			ms.setInterface(iface);
 		} catch(IOException e) {
 			if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
 			if(ms != null) ms.close();
diff --git a/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java b/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
index cadde9c89d..ac97cbcfff 100644
--- a/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
+++ b/components/net/sf/briar/plugins/socket/SimpleSocketPlugin.java
@@ -3,10 +3,15 @@ package net.sf.briar.plugins.socket;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketAddress;
+import java.util.Collections;
+import java.util.Enumeration;
 import java.util.concurrent.Executor;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportId;
@@ -19,6 +24,8 @@ class SimpleSocketPlugin extends SocketPlugin {
 	public static final int TRANSPORT_ID = 1;
 
 	private static final TransportId id = new TransportId(TRANSPORT_ID);
+	private static final Logger LOG =
+		Logger.getLogger(SimpleSocketPlugin.class.getName());
 
 	private final long pollingInterval;
 
@@ -56,7 +63,46 @@ class SimpleSocketPlugin extends SocketPlugin {
 	protected synchronized SocketAddress getLocalSocketAddress() {
 		assert started;
 		SocketAddress addr = createSocketAddress(callback.getLocalProperties());
-		return addr == null ? new InetSocketAddress(0) : addr;
+		if(addr == null) {
+			try {
+				return new InetSocketAddress(chooseTcpInterface(false), 0);
+			} catch(IOException e) {
+				if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
+			}
+		}
+		return addr;
+	}
+
+	protected InetAddress chooseTcpInterface(boolean lan) throws IOException {
+		Enumeration<NetworkInterface> ifaces =
+			NetworkInterface.getNetworkInterfaces();
+		// Try to find an interface of the preferred type (LAN or WAN)
+		for(NetworkInterface iface : Collections.list(ifaces)) {
+			Enumeration<InetAddress> addrs = iface.getInetAddresses();
+			for(InetAddress addr : Collections.list(addrs)) {
+				if(!addr.isLoopbackAddress()) {
+					boolean link = addr.isLinkLocalAddress();
+					boolean site = addr.isSiteLocalAddress();
+					if(lan == (link || site)) {
+						if(LOG.isLoggable(Level.INFO))
+							LOG.info("Binding to " + addr.getHostAddress());
+						return addr;
+					}
+				}
+			}
+		}
+		// Settle for an interface that's not of the preferred type
+		for(NetworkInterface iface : Collections.list(ifaces)) {
+			Enumeration<InetAddress> addrs = iface.getInetAddresses();
+			for(InetAddress addr : Collections.list(addrs)) {
+				if(!addr.isLoopbackAddress()) {
+					if(LOG.isLoggable(Level.INFO))
+						LOG.info("Binding to " + addr.getHostAddress());
+					return addr;
+				}
+			}
+		}
+		throw new IOException("No suitable interfaces for TCP");
 	}
 
 	@Override
-- 
GitLab