From 49cb1d061276387e991641f3c4c593d5124f9784 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 14 Feb 2020 13:49:16 +0000 Subject: [PATCH] Choose port in advance when providing wifi access point. --- .../network/AndroidNetworkManager.java | 6 +- .../plugin/tcp/AndroidLanTcpPlugin.java | 27 ++---- .../tcp/AndroidLanTcpPluginFactory.java | 12 ++- .../bramble/api/plugin/LanTcpConstants.java | 6 +- .../bramble/plugin/tcp/LanTcpPlugin.java | 97 ++++++++++++++++--- .../plugin/tcp/LanTcpPluginFactory.java | 11 ++- .../bramble/plugin/tcp/TcpPlugin.java | 19 +++- .../bramble/plugin/tcp/WanTcpPlugin.java | 6 +- .../plugin/tcp/WanTcpPluginFactory.java | 11 ++- .../bramble/plugin/tcp/LanTcpPluginTest.java | 56 +++++------ .../briar/test/TestDataCreatorImpl.java | 13 ++- 11 files changed, 173 insertions(+), 91 deletions(-) diff --git a/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java b/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java index af0e9a881..94e0609ed 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java @@ -32,6 +32,7 @@ import static android.content.Intent.ACTION_SCREEN_OFF; import static android.content.Intent.ACTION_SCREEN_ON; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION; import static android.os.Build.VERSION.SDK_INT; import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; import static java.util.concurrent.TimeUnit.MINUTES; @@ -76,9 +77,9 @@ class AndroidNetworkManager implements NetworkManager, Service { filter.addAction(ACTION_SCREEN_ON); filter.addAction(ACTION_SCREEN_OFF); filter.addAction(WIFI_AP_STATE_CHANGED_ACTION); + filter.addAction(WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED); appContext.registerReceiver(networkStateReceiver, filter); - } @Override @@ -136,7 +137,8 @@ class AndroidNetworkManager implements NetworkManager, Service { } private boolean isApEvent(@Nullable String action) { - return WIFI_AP_STATE_CHANGED_ACTION.equals(action); + return WIFI_AP_STATE_CHANGED_ACTION.equals(action) || + WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action); } } } diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java index ef6cb8efa..2511aa3dc 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java @@ -40,19 +40,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener { private static final Logger LOG = getLogger(AndroidLanTcpPlugin.class.getName()); - private static final byte[] WIFI_AP_ADDRESS_BYTES = - {(byte) 192, (byte) 168, 43, 1}; - private static final InetAddress WIFI_AP_ADDRESS; - - static { - try { - WIFI_AP_ADDRESS = InetAddress.getByAddress(WIFI_AP_ADDRESS_BYTES); - } catch (UnknownHostException e) { - // Should only be thrown if the address has an illegal length - throw new AssertionError(e); - } - } - private final Executor connectionStatusExecutor; private final ConnectivityManager connectivityManager; @Nullable @@ -62,8 +49,9 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener { AndroidLanTcpPlugin(Executor ioExecutor, Context appContext, Backoff backoff, PluginCallback callback, int maxLatency, - int maxIdleTime) { - super(ioExecutor, backoff, callback, maxLatency, maxIdleTime); + int maxIdleTime, int connectionTimeout) { + super(ioExecutor, backoff, callback, maxLatency, maxIdleTime, + connectionTimeout); // Don't execute more than one connection status check at a time connectionStatusExecutor = new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1); @@ -79,6 +67,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener { @Override public void start() { if (used.getAndSet(true)) throw new IllegalStateException(); + initialisePortProperty(); running = true; updateConnectionStatus(); } @@ -103,8 +92,11 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener { if (info != null && info.getIpAddress() != 0) return singletonList(intToInetAddress(info.getIpAddress())); // If we're running an access point, return its address - if (super.getLocalIpAddresses().contains(WIFI_AP_ADDRESS)) + Collection all = super.getLocalIpAddresses(); + if (all.contains(WIFI_AP_ADDRESS)) return singletonList(WIFI_AP_ADDRESS); + if (all.contains(WIFI_DIRECT_AP_ADDRESS)) + return singletonList(WIFI_DIRECT_AP_ADDRESS); // No suitable addresses return emptyList(); } @@ -145,7 +137,8 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener { connectionStatusExecutor.execute(() -> { if (!running) return; Collection addrs = getLocalIpAddresses(); - if (addrs.contains(WIFI_AP_ADDRESS)) { + if (addrs.contains(WIFI_AP_ADDRESS) + || addrs.contains(WIFI_DIRECT_AP_ADDRESS)) { LOG.info("Providing wifi hotspot"); // There's no corresponding Network object and thus no way // to get a suitable socket factory, so we won't be able to diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java index 9562af560..6326dfc60 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPluginFactory.java @@ -21,10 +21,11 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID; @NotNullByDefault public class AndroidLanTcpPluginFactory implements DuplexPluginFactory { - private static final int MAX_LATENCY = 30 * 1000; // 30 seconds - private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds - private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute - private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins + private static final int MAX_LATENCY = 30_000; // 30 seconds + private static final int MAX_IDLE_TIME = 30_000; // 30 seconds + private static final int CONNECTION_TIMEOUT = 3_000; // 3 seconds + private static final int MIN_POLLING_INTERVAL = 60_000; // 1 minute + private static final int MAX_POLLING_INTERVAL = 600_000; // 10 mins private static final double BACKOFF_BASE = 1.2; private final Executor ioExecutor; @@ -55,7 +56,8 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory { Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor, - appContext, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME); + appContext, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME, + CONNECTION_TIMEOUT); eventBus.addListener(plugin); return plugin; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java index 506bd7589..d546a60cd 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java @@ -4,10 +4,10 @@ public interface LanTcpConstants { TransportId ID = new TransportId("org.briarproject.bramble.lan"); - // a transport property (shared with contacts) + // Transport properties (shared with contacts) String PROP_IP_PORTS = "ipPorts"; + String PROP_PORT = "port"; - // a local setting + // A local setting String PREF_LAN_IP_PORTS = "ipPorts"; - } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java index 78ea1a7cd..230647f6d 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java @@ -24,11 +24,14 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.Random; import java.util.concurrent.Executor; import java.util.logging.Logger; +import javax.annotation.Nullable; + +import static java.lang.Integer.parseInt; import static java.util.Collections.addAll; -import static java.util.Collections.emptyList; import static java.util.Collections.sort; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; @@ -37,6 +40,7 @@ import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TR import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID; import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS; import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS; +import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_PORT; import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED; import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; @@ -53,9 +57,33 @@ class LanTcpPlugin extends TcpPlugin { private static final int MAX_ADDRESSES = 4; private static final String SEPARATOR = ","; + /** + * The IP address of an Android device providing a wifi access point. + */ + protected static final InetAddress WIFI_AP_ADDRESS; + + /** + * The IP address of an Android device providing a wifi direct + * legacy mode access point. + */ + protected static final InetAddress WIFI_DIRECT_AP_ADDRESS; + + static { + try { + WIFI_AP_ADDRESS = InetAddress.getByAddress( + new byte[] {(byte) 192, (byte) 168, 43, 1}); + WIFI_DIRECT_AP_ADDRESS = InetAddress.getByAddress( + new byte[] {(byte) 192, (byte) 168, 49, 1}); + } catch (UnknownHostException e) { + // Should only be thrown if the address has an illegal length + throw new AssertionError(e); + } + } + LanTcpPlugin(Executor ioExecutor, Backoff backoff, PluginCallback callback, - int maxLatency, int maxIdleTime) { - super(ioExecutor, backoff, callback, maxLatency, maxIdleTime); + int maxLatency, int maxIdleTime, int connectionTimeout) { + super(ioExecutor, backoff, callback, maxLatency, maxIdleTime, + connectionTimeout); } @Override @@ -64,19 +92,43 @@ class LanTcpPlugin extends TcpPlugin { } @Override - protected List getLocalSocketAddresses() { - // Use the same address and port as last time if available + public void start() { + if (used.getAndSet(true)) throw new IllegalStateException(); + initialisePortProperty(); + running = true; + bind(); + } + + protected void initialisePortProperty() { TransportProperties p = callback.getLocalProperties(); + if (isNullOrEmpty(p.get(PROP_PORT))) { + int port = new Random().nextInt(32768) + 32768; + p.put(PROP_PORT, String.valueOf(port)); + callback.mergeLocalProperties(p); + } + } + + @Override + protected List getLocalSocketAddresses() { + TransportProperties p = callback.getLocalProperties(); + int port = parsePortProperty(p.get(PROP_PORT)); String oldIpPorts = p.get(PROP_IP_PORTS); List olds = parseSocketAddresses(oldIpPorts); List locals = new ArrayList<>(); for (InetAddress local : getLocalIpAddresses()) { if (isAcceptableAddress(local)) { - // If this is the old address, try to use the same port + // If we've used this address before, try to use the same port + boolean reused = false; for (InetSocketAddress old : olds) { - if (old.getAddress().equals(local)) + if (old.getAddress().equals(local)) { locals.add(new InetSocketAddress(local, old.getPort())); + reused = true; + break; + } } + // Otherwise try to use our preferred port + if (!reused) locals.add(new InetSocketAddress(local, port)); + // Fall back to any available port locals.add(new InetSocketAddress(local, 0)); } } @@ -84,11 +136,19 @@ class LanTcpPlugin extends TcpPlugin { return locals; } + private int parsePortProperty(@Nullable String portProperty) { + if (isNullOrEmpty(portProperty)) return 0; + try { + return parseInt(portProperty); + } catch (NumberFormatException e) { + return 0; + } + } + private List parseSocketAddresses(String ipPorts) { - if (isNullOrEmpty(ipPorts)) return emptyList(); - String[] split = ipPorts.split(SEPARATOR); List addresses = new ArrayList<>(); - for (String ipPort : split) { + if (isNullOrEmpty(ipPorts)) return addresses; + for (String ipPort : ipPorts.split(SEPARATOR)) { InetSocketAddress a = parseSocketAddress(ipPort); if (a != null) addresses.add(a); } @@ -132,7 +192,20 @@ class LanTcpPlugin extends TcpPlugin { @Override protected List getRemoteSocketAddresses( TransportProperties p) { - return parseSocketAddresses(p.get(PROP_IP_PORTS)); + String ipPorts = p.get(PROP_IP_PORTS); + List remotes = parseSocketAddresses(ipPorts); + int port = parsePortProperty(p.get(PROP_PORT)); + // If the contact has a preferred port, we can guess their IP:port when + // they're providing a wifi access point + if (port != 0) { + InetSocketAddress wifiAp = + new InetSocketAddress(WIFI_AP_ADDRESS, port); + if (!remotes.contains(wifiAp)) remotes.add(wifiAp); + InetSocketAddress wifiDirectAp = + new InetSocketAddress(WIFI_DIRECT_AP_ADDRESS, port); + if (!remotes.contains(wifiDirectAp)) remotes.add(wifiDirectAp); + } + return remotes; } private boolean isAcceptableAddress(InetAddress a) { @@ -250,7 +323,7 @@ class LanTcpPlugin extends TcpPlugin { LOG.info("Connecting to " + scrubSocketAddress(remote)); Socket s = createSocket(); s.bind(new InetSocketAddress(socket.getInetAddress(), 0)); - s.connect(remote); + s.connect(remote, connectionTimeout); s.setSoTimeout(socketTimeout); if (LOG.isLoggable(INFO)) LOG.info("Connected to " + scrubSocketAddress(remote)); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java index caa4c6a2e..cfbdcea80 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginFactory.java @@ -18,10 +18,11 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID; @NotNullByDefault public class LanTcpPluginFactory implements DuplexPluginFactory { - private static final int MAX_LATENCY = 30 * 1000; // 30 seconds - private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds - private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute - private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins + private static final int MAX_LATENCY = 30_000; // 30 seconds + private static final int MAX_IDLE_TIME = 30_000; // 30 seconds + private static final int CONNECTION_TIMEOUT = 3_000; // 3 seconds + private static final int MIN_POLLING_INTERVAL = 60_000; // 1 minute + private static final int MAX_POLLING_INTERVAL = 600_000; // 10 mins private static final double BACKOFF_BASE = 1.2; private final Executor ioExecutor; @@ -48,6 +49,6 @@ public class LanTcpPluginFactory implements DuplexPluginFactory { Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, MAX_POLLING_INTERVAL, BACKOFF_BASE); return new LanTcpPlugin(ioExecutor, backoff, callback, MAX_LATENCY, - MAX_IDLE_TIME); + MAX_IDLE_TIME, CONNECTION_TIMEOUT); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java index 4ca15d0b9..64ca4d8f4 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java @@ -58,7 +58,8 @@ abstract class TcpPlugin implements DuplexPlugin { protected final Executor ioExecutor, bindExecutor; protected final Backoff backoff; protected final PluginCallback callback; - protected final int maxLatency, maxIdleTime, socketTimeout; + protected final int maxLatency, maxIdleTime; + protected final int connectionTimeout, socketTimeout; protected final AtomicBoolean used = new AtomicBoolean(false); protected volatile boolean running = false; @@ -86,15 +87,17 @@ abstract class TcpPlugin implements DuplexPlugin { /** * Returns true if connections to the given address can be attempted. */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") protected abstract boolean isConnectable(InetSocketAddress remote); TcpPlugin(Executor ioExecutor, Backoff backoff, PluginCallback callback, - int maxLatency, int maxIdleTime) { + int maxLatency, int maxIdleTime, int connectionTimeout) { this.ioExecutor = ioExecutor; this.backoff = backoff; this.callback = callback; this.maxLatency = maxLatency; this.maxIdleTime = maxIdleTime; + this.connectionTimeout = connectionTimeout; if (maxIdleTime > Integer.MAX_VALUE / 2) socketTimeout = Integer.MAX_VALUE; else socketTimeout = maxIdleTime * 2; @@ -231,6 +234,11 @@ abstract class TcpPlugin implements DuplexPlugin { public DuplexTransportConnection createConnection(TransportProperties p) { if (!isRunning()) return null; for (InetSocketAddress remote : getRemoteSocketAddresses(p)) { + // Don't try to connect to our own address + if (!canConnectToOwnAddress() && + remote.getAddress().equals(socket.getInetAddress())) { + continue; + } if (!isConnectable(remote)) { if (LOG.isLoggable(INFO)) { SocketAddress local = socket.getLocalSocketAddress(); @@ -245,7 +253,7 @@ abstract class TcpPlugin implements DuplexPlugin { LOG.info("Connecting to " + scrubSocketAddress(remote)); Socket s = createSocket(); s.bind(new InetSocketAddress(socket.getInetAddress(), 0)); - s.connect(remote); + s.connect(remote, connectionTimeout); s.setSoTimeout(socketTimeout); if (LOG.isLoggable(INFO)) LOG.info("Connected to " + scrubSocketAddress(remote)); @@ -259,6 +267,11 @@ abstract class TcpPlugin implements DuplexPlugin { return null; } + // Override for testing + protected boolean canConnectToOwnAddress() { + return false; + } + protected Socket createSocket() throws IOException { return new Socket(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPlugin.java index 0450820dc..6c415428c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPlugin.java @@ -29,8 +29,10 @@ class WanTcpPlugin extends TcpPlugin { private volatile MappingResult mappingResult; WanTcpPlugin(Executor ioExecutor, Backoff backoff, PortMapper portMapper, - PluginCallback callback, int maxLatency, int maxIdleTime) { - super(ioExecutor, backoff, callback, maxLatency, maxIdleTime); + PluginCallback callback, int maxLatency, int maxIdleTime, + int connectionTimeout) { + super(ioExecutor, backoff, callback, maxLatency, maxIdleTime, + connectionTimeout); this.portMapper = portMapper; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java index 440b208f1..079697319 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/WanTcpPluginFactory.java @@ -19,10 +19,11 @@ import static org.briarproject.bramble.api.plugin.WanTcpConstants.ID; @NotNullByDefault public class WanTcpPluginFactory implements DuplexPluginFactory { - private static final int MAX_LATENCY = 30 * 1000; // 30 seconds - private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds - private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute - private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins + private static final int MAX_LATENCY = 30_000; // 30 seconds + private static final int MAX_IDLE_TIME = 30_000; // 30 seconds + private static final int CONNECTION_TIMEOUT = 30_000; // 30 seconds + private static final int MIN_POLLING_INTERVAL = 60_000; // 1 minute + private static final int MAX_POLLING_INTERVAL = 600_000; // 10 mins private static final double BACKOFF_BASE = 1.2; private final Executor ioExecutor; @@ -52,6 +53,6 @@ public class WanTcpPluginFactory implements DuplexPluginFactory { MAX_POLLING_INTERVAL, BACKOFF_BASE); return new WanTcpPlugin(ioExecutor, backoff, new PortMapperImpl(shutdownManager), callback, MAX_LATENCY, - MAX_IDLE_TIME); + MAX_IDLE_TIME, CONNECTION_TIMEOUT); } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java index 12ccaf1e8..ac3c169bb 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java @@ -7,12 +7,12 @@ import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.TransportConnectionReader; import org.briarproject.bramble.api.plugin.TransportConnectionWriter; -import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.plugin.tcp.LanTcpPlugin.LanAddressComparator; import org.briarproject.bramble.test.BrambleTestCase; +import org.junit.Before; import org.junit.Test; import java.io.IOException; @@ -37,17 +37,29 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; public class LanTcpPluginTest extends BrambleTestCase { private final Backoff backoff = new TestBackoff(); private final ExecutorService ioExecutor = newCachedThreadPool(); + private Callback callback = null; + private LanTcpPlugin plugin = null; + + @Before + public void setUp() { + callback = new Callback(); + plugin = new LanTcpPlugin(ioExecutor, backoff, callback, 0, 0, 1000) { + @Override + protected boolean canConnectToOwnAddress() { + return true; + } + }; + } + @Test public void testAddressesAreOnSameLan() { - Callback callback = new Callback(); - LanTcpPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback, - 0, 0); // Local and remote in 10.0.0.0/8 should return true assertTrue(plugin.addressesAreOnSameLan(makeAddress(10, 0, 0, 0), makeAddress(10, 255, 255, 255))); @@ -93,13 +105,7 @@ public class LanTcpPluginTest extends BrambleTestCase { @Test public void testIncomingConnection() throws Exception { - if (!systemHasLocalIpv4Address()) { - System.err.println("WARNING: Skipping test, no local IPv4 address"); - return; - } - Callback callback = new Callback(); - DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback, - 0, 0); + assumeTrue(systemHasLocalIpv4Address()); plugin.start(); // The plugin should have bound a socket and stored the port number assertTrue(callback.propertiesLatch.await(5, SECONDS)); @@ -128,13 +134,7 @@ public class LanTcpPluginTest extends BrambleTestCase { @Test public void testOutgoingConnection() throws Exception { - if (!systemHasLocalIpv4Address()) { - System.err.println("WARNING: Skipping test, no local IPv4 address"); - return; - } - Callback callback = new Callback(); - DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback, - 0, 0); + assumeTrue(systemHasLocalIpv4Address()); plugin.start(); // The plugin should have bound a socket and stored the port number assertTrue(callback.propertiesLatch.await(5, SECONDS)); @@ -177,13 +177,7 @@ public class LanTcpPluginTest extends BrambleTestCase { @Test public void testIncomingKeyAgreementConnection() throws Exception { - if (!systemHasLocalIpv4Address()) { - System.err.println("WARNING: Skipping test, no local IPv4 address"); - return; - } - Callback callback = new Callback(); - DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback, - 0, 0); + assumeTrue(systemHasLocalIpv4Address()); plugin.start(); assertTrue(callback.propertiesLatch.await(5, SECONDS)); KeyAgreementListener kal = @@ -225,13 +219,7 @@ public class LanTcpPluginTest extends BrambleTestCase { @Test public void testOutgoingKeyAgreementConnection() throws Exception { - if (!systemHasLocalIpv4Address()) { - System.err.println("WARNING: Skipping test, no local IPv4 address"); - return; - } - Callback callback = new Callback(); - DuplexPlugin plugin = new LanTcpPlugin(ioExecutor, backoff, callback, - 0, 0); + assumeTrue(systemHasLocalIpv4Address()); plugin.start(); // The plugin should have bound a socket and stored the port number assertTrue(callback.propertiesLatch.await(5, SECONDS)); @@ -340,7 +328,9 @@ public class LanTcpPluginTest extends BrambleTestCase { @NotNullByDefault private static class Callback implements PluginCallback { - private final CountDownLatch propertiesLatch = new CountDownLatch(1); + // Properties will be stored twice: the preferred port at startup, + // and the IP:port when the server socket is bound + private final CountDownLatch propertiesLatch = new CountDownLatch(2); private final CountDownLatch connectionsLatch = new CountDownLatch(1); private final TransportProperties local = new TransportProperties(); diff --git a/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java index cc9c67824..ebd45cfcb 100644 --- a/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java @@ -230,6 +230,8 @@ public class TestDataCreatorImpl implements TestDataCreator { sb.append(getRandomLanAddress()); } lan.put(LanTcpConstants.PROP_IP_PORTS, sb.toString()); + String port = String.valueOf(getRandomPortNumber()); + lan.put(LanTcpConstants.PROP_PORT, port); props.put(LanTcpConstants.ID, lan); // Tor @@ -266,18 +268,21 @@ public class TestDataCreatorImpl implements TestDataCreator { sb.append("10."); sb.append(random.nextInt(2)).append('.'); sb.append(random.nextInt(2)).append('.'); - sb.append(random.nextInt(256)); + sb.append(random.nextInt(255)); } else { sb.append("192.168."); sb.append(random.nextInt(2)).append('.'); - sb.append(random.nextInt(256)); + sb.append(random.nextInt(255)); } // port - sb.append(":"); - sb.append(1024 + random.nextInt(50000)); + sb.append(':').append(getRandomPortNumber()); return sb.toString(); } + private int getRandomPortNumber() { + return 32768 + random.nextInt(32768); + } + private String getRandomTorAddress() { StringBuilder sb = new StringBuilder(); // address