Use interface name to decide whether we're providing a wifi hotspot.

This commit is contained in:
akwizgran
2021-08-16 11:55:41 +01:00
parent 48292d2e47
commit 32cbdff532
2 changed files with 25 additions and 34 deletions

View File

@@ -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;
@@ -55,6 +56,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 +138,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 +153,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.
* This method may return true for wifi client interfaces as well, but
* we've already checked for a wifi client connection above.
*/
private boolean isAndroidWifiApAddress(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) 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).
*/
private boolean isAndroidWifiDirectApAddress(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;
}
/**

View File

@@ -98,7 +98,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,10 +397,12 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener {
return addrs;
}
private List<NetworkInterface> getNetworkInterfaces() {
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);