diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java index db444532804438ea440c851f884fe1eae47caa5a..abed7f40ebdb9419fcb1f8d71da406f8aa1ef412 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java +++ b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPlugin.java @@ -2,15 +2,15 @@ package org.briarproject.plugins.tcp; import static java.util.logging.Level.WARNING; -import java.net.Inet6Address; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.SocketAddress; import java.net.SocketException; import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -20,7 +20,7 @@ import org.briarproject.api.TransportProperties; import org.briarproject.api.plugins.duplex.DuplexPluginCallback; import org.briarproject.util.StringUtils; -/** A socket plugin that supports exchanging invitations over a LAN. */ +/** A TCP plugin that supports exchanging invitations over a LAN. */ class LanTcpPlugin extends TcpPlugin { static final TransportId ID = new TransportId("lan"); @@ -40,23 +40,23 @@ class LanTcpPlugin extends TcpPlugin { @Override protected List<SocketAddress> getLocalSocketAddresses() { - List<SocketAddress> addrs = new ArrayList<SocketAddress>(); - // Prefer a previously used address and port if available + // Use the same address and port as last time if available TransportProperties p = callback.getLocalProperties(); - String addrString = p.get("address"); + String addressString = p.get("address"); String portString = p.get("port"); - InetAddress addr = null; - if(!StringUtils.isNullOrEmpty(addrString) && + InetAddress oldAddress = null; + int oldPort = 0; + if(!StringUtils.isNullOrEmpty(addressString) && !StringUtils.isNullOrEmpty(portString)) { try { - addr = InetAddress.getByName(addrString); - int port = Integer.parseInt(portString); - addrs.add(new InetSocketAddress(addr, port)); - addrs.add(new InetSocketAddress(addr, 0)); + oldAddress = InetAddress.getByName(addressString); + oldPort = Integer.parseInt(portString); } catch(NumberFormatException e) { - if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + if(LOG.isLoggable(WARNING)) + LOG.warning("Invalid port: " + portString); } catch(UnknownHostException e) { - if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + if(LOG.isLoggable(WARNING)) + LOG.warning("Invalid address: " + addressString); } } List<NetworkInterface> ifaces; @@ -64,30 +64,23 @@ class LanTcpPlugin extends TcpPlugin { ifaces = Collections.list(NetworkInterface.getNetworkInterfaces()); } catch(SocketException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - return addrs; + return Collections.emptyList(); } - // Prefer interfaces with link-local or site-local addresses + List<SocketAddress> addresses = new LinkedList<SocketAddress>(); + // Accept interfaces with link-local or site-local addresses for(NetworkInterface iface : ifaces) { for(InetAddress a : Collections.list(iface.getInetAddresses())) { - if(addr != null && a.equals(addr)) continue; - if(a instanceof Inet6Address) continue; - if(a.isLoopbackAddress()) continue; + boolean ipv4 = a instanceof Inet4Address; + boolean loop = a.isLoopbackAddress(); boolean link = a.isLinkLocalAddress(); boolean site = a.isSiteLocalAddress(); - if(link || site) addrs.add(new InetSocketAddress(a, 0)); + if(ipv4 && !loop && (link || site)) { + if(a.equals(oldAddress)) + addresses.add(0, new InetSocketAddress(a, oldPort)); + addresses.add(new InetSocketAddress(a, 0)); + } } } - // Accept interfaces without link-local or site-local addresses - for(NetworkInterface iface : ifaces) { - for(InetAddress a : Collections.list(iface.getInetAddresses())) { - if(addr != null && a.equals(addr)) continue; - if(a instanceof Inet6Address) continue; - if(a.isLoopbackAddress()) continue; - boolean link = a.isLinkLocalAddress(); - boolean site = a.isSiteLocalAddress(); - if(!link && !site) addrs.add(new InetSocketAddress(a, 0)); - } - } - return addrs; + return addresses; } } \ No newline at end of file diff --git a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java index 9b3e32d749dfe14dc4233bac5fcd0ff20d192946..100962902f47d373dd3f8d1216ff907e6a500ac6 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java +++ b/briar-core/src/org/briarproject/plugins/tcp/WanTcpPlugin.java @@ -2,15 +2,15 @@ package org.briarproject.plugins.tcp; import static java.util.logging.Level.WARNING; -import java.net.Inet6Address; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.SocketAddress; import java.net.SocketException; import java.net.UnknownHostException; -import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -45,24 +45,23 @@ class WanTcpPlugin extends TcpPlugin { @Override protected List<SocketAddress> getLocalSocketAddresses() { - List<SocketAddress> addrs = new ArrayList<SocketAddress>(); - // Prefer a previously used address and port if available + // Use the same address and port as last time if available TransportProperties p = callback.getLocalProperties(); - String addrString = p.get("address"); + String addressString = p.get("address"); String portString = p.get("port"); - InetAddress addr = null; - int port = 0; - if(!StringUtils.isNullOrEmpty(addrString) && + InetAddress oldAddress = null; + int oldPort = 0; + if(!StringUtils.isNullOrEmpty(addressString) && !StringUtils.isNullOrEmpty(portString)) { try { - addr = InetAddress.getByName(addrString); - port = Integer.parseInt(portString); - addrs.add(new InetSocketAddress(addr, port)); - addrs.add(new InetSocketAddress(addr, 0)); + oldAddress = InetAddress.getByName(addressString); + oldPort = Integer.parseInt(portString); } catch(NumberFormatException e) { - if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + if(LOG.isLoggable(WARNING)) + LOG.warning("Invalid port: " + portString); } catch(UnknownHostException e) { - if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + if(LOG.isLoggable(WARNING)) + LOG.warning("Invalid address: " + addressString); } } // Get a list of the device's network interfaces @@ -71,27 +70,31 @@ class WanTcpPlugin extends TcpPlugin { ifaces = Collections.list(NetworkInterface.getNetworkInterfaces()); } catch(SocketException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - return addrs; + return Collections.emptyList(); } + List<SocketAddress> addresses = new LinkedList<SocketAddress>(); // Accept interfaces without link-local or site-local addresses for(NetworkInterface iface : ifaces) { for(InetAddress a : Collections.list(iface.getInetAddresses())) { - if(addr != null && a.equals(addr)) continue; - if(a instanceof Inet6Address) continue; - if(a.isLoopbackAddress()) continue; + boolean ipv4 = a instanceof Inet4Address; + boolean loop = a.isLoopbackAddress(); boolean link = a.isLinkLocalAddress(); boolean site = a.isSiteLocalAddress(); - if(!link && !site) addrs.add(new InetSocketAddress(a, 0)); + if(ipv4 && !loop && !link && !site) { + if(a.equals(oldAddress)) + addresses.add(0, new InetSocketAddress(a, oldPort)); + addresses.add(new InetSocketAddress(a, 0)); + } } } // Accept interfaces with local addresses that can be port-mapped - if(port == 0) port = chooseEphemeralPort(); - mappingResult = portMapper.map(port); + if(oldPort == 0) oldPort = chooseEphemeralPort(); + mappingResult = portMapper.map(oldPort); if(mappingResult != null && mappingResult.isUsable()) { InetSocketAddress a = mappingResult.getInternal(); - if(!(a.getAddress() instanceof Inet6Address)) addrs.add(a); + if(a.getAddress() instanceof Inet4Address) addresses.add(a); } - return addrs; + return addresses; } private int chooseEphemeralPort() { diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java index 9094e7503edd5b914d3076956ab78d2d34e4bc52..afa1dde1a2693cfe656d5e1e8c79a88d70c4d679 100644 --- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java +++ b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java @@ -3,6 +3,8 @@ package org.briarproject.plugins.tcp; import static java.util.concurrent.TimeUnit.SECONDS; import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; @@ -29,24 +31,25 @@ public class LanTcpPluginTest extends BriarTestCase { @Test public void testIncomingConnection() throws Exception { Callback callback = new Callback(); - callback.local.put("address", "127.0.0.1"); - callback.local.put("port", "0"); Executor executor = Executors.newCachedThreadPool(); DuplexPlugin plugin = new LanTcpPlugin(executor, callback, 0, 0, 0); plugin.start(); // The plugin should have bound a socket and stored the port number assertTrue(callback.propertiesLatch.await(5, SECONDS)); - String host = callback.local.get("address"); - assertNotNull(host); - assertEquals("127.0.0.1", host); + String addrString = callback.local.get("address"); + assertNotNull(addrString); + InetAddress addr = InetAddress.getByName(addrString); + assertTrue(addr instanceof Inet4Address); + assertFalse(addr.isLoopbackAddress()); + assertTrue(addr.isLinkLocalAddress() || addr.isSiteLocalAddress()); String portString = callback.local.get("port"); assertNotNull(portString); int port = Integer.parseInt(portString); assertTrue(port > 0 && port < 65536); // The plugin should be listening on the port - InetSocketAddress addr = new InetSocketAddress(host, port); + InetSocketAddress socketAddr = new InetSocketAddress(addr, port); Socket s = new Socket(); - s.connect(addr, 100); + s.connect(socketAddr, 100); assertTrue(callback.connectionsLatch.await(5, SECONDS)); s.close(); // Stop the plugin