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 9bb4f9aded3ef95780d465a1a9cb5f57b18a4ea9..22dfbe8dfde708b49815e9579ea6fd6414f194a5 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 @@ -29,6 +29,7 @@ import java.net.UnknownHostException; import java.util.List; import java.util.concurrent.Executor; import java.util.logging.Logger; +import java.util.regex.Pattern; import javax.annotation.Nullable; import javax.net.SocketFactory; @@ -48,6 +49,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.util.IoUtils.tryToClose; import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces; @NotNullByDefault class AndroidLanTcpPlugin extends LanTcpPlugin { @@ -55,6 +57,13 @@ class AndroidLanTcpPlugin extends LanTcpPlugin { private static final Logger LOG = getLogger(AndroidLanTcpPlugin.class.getName()); + /** + * The interface name is used as a heuristic for deciding whether the + * device is providing a wifi access point. + */ + private static final Pattern AP_INTERFACE_NAME = + Pattern.compile("^(wlan|ap|p2p)[-0-9]"); + private final Executor connectionStatusExecutor; private final ConnectivityManager connectivityManager; @Nullable @@ -130,17 +139,14 @@ class AndroidLanTcpPlugin extends LanTcpPlugin { if (info != null && info.getIpAddress() != 0) { return new Pair<>(intToInetAddress(info.getIpAddress()), false); } - List<InterfaceAddress> ifAddrs = getLocalInterfaceAddresses(); - // If we're providing a normal access point, return its address - for (InterfaceAddress ifAddr : ifAddrs) { - if (isAndroidWifiApAddress(ifAddr)) { - return new Pair<>(ifAddr.getAddress(), true); - } - } - // If we're providing a wifi direct access point, return its address - for (InterfaceAddress ifAddr : ifAddrs) { - if (isAndroidWifiDirectApAddress(ifAddr)) { - return new Pair<>(ifAddr.getAddress(), true); + // If we're providing an access point, return its address + for (NetworkInterface iface : getNetworkInterfaces()) { + if (AP_INTERFACE_NAME.matcher(iface.getName()).find()) { + for (InterfaceAddress ifAddr : iface.getInterfaceAddresses()) { + if (isPossibleWifiApInterface(ifAddr)) { + return new Pair<>(ifAddr.getAddress(), true); + } + } } } // Not connected to wifi @@ -148,33 +154,18 @@ class AndroidLanTcpPlugin extends LanTcpPlugin { } /** - * Returns true if the given address belongs to a network provided by an - * Android access point (including the access point's own address). + * Returns true if the given address may belong to an interface providing + * a wifi access point (including wifi direct legacy mode access points). * <p> - * The access point's address is usually 192.168.43.1, but at least one - * device (Honor 8A) may use other addresses in the range 192.168.43.0/24. - */ - private boolean isAndroidWifiApAddress(InterfaceAddress ifAddr) { - if (ifAddr.getNetworkPrefixLength() != 24) return false; - byte[] ip = ifAddr.getAddress().getAddress(); - return ip.length == 4 - && ip[0] == (byte) 192 - && ip[1] == (byte) 168 - && ip[2] == (byte) 43; - } - - /** - * Returns true if the given address belongs to a network provided by an - * Android wifi direct legacy mode access point (including the access - * point's own address). + * This method may return true for wifi client interfaces as well, but + * we've already checked for a wifi client connection above. */ - private boolean isAndroidWifiDirectApAddress(InterfaceAddress ifAddr) { + private boolean isPossibleWifiApInterface(InterfaceAddress ifAddr) { if (ifAddr.getNetworkPrefixLength() != 24) return false; byte[] ip = ifAddr.getAddress().getAddress(); return ip.length == 4 && ip[0] == (byte) 192 - && ip[1] == (byte) 168 - && ip[2] == (byte) 49; + && ip[1] == (byte) 168; } /** diff --git a/bramble-api/src/main/java/org/briarproject/bramble/util/NetworkUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/NetworkUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..d2ad5ef883c611b9b2eb8736156c96949e5fef5f --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/util/NetworkUtils.java @@ -0,0 +1,34 @@ +package org.briarproject.bramble.util; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; +import java.util.List; +import java.util.logging.Logger; + +import static java.util.Collections.emptyList; +import static java.util.Collections.list; +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.util.LogUtils.logException; + +@NotNullByDefault +public class NetworkUtils { + + private static final Logger LOG = getLogger(NetworkUtils.class.getName()); + + public static List<NetworkInterface> getNetworkInterfaces() { + try { + Enumeration<NetworkInterface> ifaces = + NetworkInterface.getNetworkInterfaces(); + // Despite what the docs say, the return value can be null + //noinspection ConstantConditions + return ifaces == null ? emptyList() : list(ifaces); + } catch (SocketException e) { + logException(LOG, WARNING, e); + return emptyList(); + } + } +} 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 5b1acb376a206da847b9641230a29c06fbae4728..baa0502550c4a2207446cf59c5931ae34e2cab77 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 @@ -28,11 +28,9 @@ import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.ServerSocket; import java.net.Socket; -import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; @@ -53,7 +51,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.util.IoUtils.tryToClose; -import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces; import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; @@ -98,7 +96,6 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener { /** * Returns true if connections to the given address can be attempted. */ - @SuppressWarnings("BooleanMethodIsAlwaysInverted") protected abstract boolean isConnectable(InterfaceAddress local, InetSocketAddress remote); @@ -398,17 +395,6 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener { return addrs; } - private List<NetworkInterface> getNetworkInterfaces() { - try { - Enumeration<NetworkInterface> ifaces = - NetworkInterface.getNetworkInterfaces(); - return ifaces == null ? emptyList() : list(ifaces); - } catch (SocketException e) { - logException(LOG, WARNING, e); - return emptyList(); - } - } - @Override public void eventOccurred(Event e) { if (e instanceof SettingsUpdatedEvent) { diff --git a/bramble-java/src/main/java/org/briarproject/bramble/network/JavaNetworkManager.java b/bramble-java/src/main/java/org/briarproject/bramble/network/JavaNetworkManager.java index ee46bd11bc45115c403bf1f7e107321bc695f3be..72ccbab2f48e1fee26aca9398e5a1a066f783627 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/network/JavaNetworkManager.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/network/JavaNetworkManager.java @@ -9,16 +9,15 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; -import java.util.Enumeration; import java.util.logging.Logger; import javax.inject.Inject; -import static java.net.NetworkInterface.getNetworkInterfaces; import static java.util.Collections.list; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces; @MethodsNotNullByDefault @ParametersNotNullByDefault @@ -35,19 +34,14 @@ class JavaNetworkManager implements NetworkManager { public NetworkStatus getNetworkStatus() { boolean connected = false, hasIpv4 = false, hasIpv6Unicast = false; try { - Enumeration<NetworkInterface> interfaces = getNetworkInterfaces(); - if (interfaces == null) { - LOG.info("No network interfaces"); - } else { - for (NetworkInterface i : list(interfaces)) { - if (i.isLoopback() || !i.isUp()) continue; - for (InetAddress addr : list(i.getInetAddresses())) { - connected = true; - if (addr instanceof Inet4Address) { - hasIpv4 = true; - } else if (!addr.isMulticastAddress()) { - hasIpv6Unicast = true; - } + for (NetworkInterface i : getNetworkInterfaces()) { + if (i.isLoopback() || !i.isUp()) continue; + for (InetAddress addr : list(i.getInetAddresses())) { + connected = true; + if (addr instanceof Inet4Address) { + hasIpv4 = true; + } else if (!addr.isMulticastAddress()) { + hasIpv6Unicast = true; } } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/WebServerManager.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/WebServerManager.java index c5a720b37ed07b5b11d2b1987fd0f23799b958da..60240a9968cdacc13da3cb70b063e4f5542e83bc 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/WebServerManager.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/WebServerManager.java @@ -14,9 +14,6 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Enumeration; -import java.util.List; import java.util.logging.Logger; import javax.inject.Inject; @@ -24,12 +21,11 @@ import javax.inject.Inject; import androidx.annotation.Nullable; import androidx.annotation.UiThread; -import static java.util.Collections.emptyList; -import static java.util.Collections.list; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces; import static org.briarproject.briar.android.hotspot.WebServer.PORT; @MethodsNotNullByDefault @@ -112,16 +108,4 @@ class WebServerManager { } return null; } - - private static List<NetworkInterface> getNetworkInterfaces() { - try { - Enumeration<NetworkInterface> ifaces = - NetworkInterface.getNetworkInterfaces(); - return ifaces == null ? emptyList() : list(ifaces); - } catch (SocketException e) { - logException(LOG, WARNING, e); - return emptyList(); - } - } - }