Skip to content

Commit

Permalink
[android] handles unscoped ipv6 link-local address (#296)
Browse files Browse the repository at this point in the history
On Android devices before Android U, the scope ID of Ipv6 link-local
address is not set when it's returned to the caller via
NsdServiceInfo. To make the LLA usable, this commit sets the missing
scope ID to the interface ID of the current active default network.
  • Loading branch information
wgtdkp authored Aug 14, 2024
1 parent 1dac5e3 commit 64928ae
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 11 deletions.
2 changes: 1 addition & 1 deletion android/openthread_commissioner/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ dependencies {

implementation fileTree(dir: "libs", include: ["*.jar"])

implementation 'com.google.guava:guava:31.1-jre'
implementation 'com.google.guava:guava:33.2.1-android'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.concurrent:concurrent-futures:1.1.0"
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,17 @@

import android.Manifest.permission;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresPermission;
import com.google.common.net.InetAddresses;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
Expand All @@ -52,13 +57,14 @@ public class BorderAgentDiscoverer implements NsdManager.DiscoveryListener {
private static final String KEY_NETWORK_NAME = "nn";
private static final String KEY_EXTENDED_PAN_ID = "xp";

private WifiManager.MulticastLock wifiMulticastLock;
private NsdManager nsdManager;
private BorderAgentListener borderAgentListener;
private final WifiManager.MulticastLock wifiMulticastLock;
private final NsdManager nsdManager;
private final ConnectivityManager connManager;
private final BorderAgentListener borderAgentListener;

private ExecutorService executor = Executors.newSingleThreadExecutor();
private BlockingQueue<NsdServiceInfo> unresolvedServices = new ArrayBlockingQueue<>(256);
private AtomicBoolean isResolvingService = new AtomicBoolean(false);
private final BlockingQueue<NsdServiceInfo> unresolvedServices = new ArrayBlockingQueue<>(256);
private final AtomicBoolean isResolvingService = new AtomicBoolean(false);

private boolean isScanning = false;

Expand All @@ -74,7 +80,8 @@ public BorderAgentDiscoverer(Context context, BorderAgentListener borderAgentLis
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiMulticastLock = wifi.createMulticastLock("multicastLock");

nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
nsdManager = context.getSystemService(NsdManager.class);
connManager = context.getSystemService(ConnectivityManager.class);

this.borderAgentListener = borderAgentListener;
}
Expand Down Expand Up @@ -112,7 +119,7 @@ public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
public void onServiceResolved(NsdServiceInfo serviceInfo) {
BorderAgentInfo borderAgent = getBorderAgentInfo(serviceInfo);
if (borderAgent != null) {
Log.d(TAG, "successfully resolved service: " + serviceInfo.toString());
Log.d(TAG, "successfully resolved service: " + serviceInfo);
Log.d(
TAG,
"successfully resolved service: " + serviceInfo.getHost().getCanonicalHostName());
Expand Down Expand Up @@ -214,10 +221,42 @@ private BorderAgentInfo getBorderAgentInfo(NsdServiceInfo serviceInfo) {
id,
new String(attrs.get(KEY_NETWORK_NAME)),
attrs.get(KEY_EXTENDED_PAN_ID),
serviceInfo.getHost(),
handleNsdServiceAddress(serviceInfo.getHost()),
serviceInfo.getPort());
}

/**
* Properly handles the {@link InetAddress} within a discovered {@link NsdServiceInfo}.
*
* <p>For example, adds the scope ID to an IPv6 link-local address to make is usable.
*/
private InetAddress handleNsdServiceAddress(InetAddress address) {
if (!(address instanceof Inet6Address)) {
return address;
}

Inet6Address address6 = (Inet6Address) address;

if (!address6.isLinkLocalAddress() || address6.getScopeId() != 0) {
return address6;
}

// Sets the scope ID for IPv6 link-local address if it's missing. This can
// happen before Android U.

// Assume the mDNS service is discovered on the current active default network
Network network = connManager.getActiveNetwork();
if (network == null) {
return address6;
}
String interfaceName = connManager.getLinkProperties(network).getInterfaceName();
if (interfaceName == null) {
return address6;
}

return InetAddresses.forString(address6.getHostAddress() + "%" + interfaceName);
}

@Nullable
private byte[] getBorderAgentId(NsdServiceInfo serviceInfo) {
Map<String, byte[]> attrs = serviceInfo.getAttributes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ public BorderAgentInfo(
@NonNull byte[] extendedPanId,
@NonNull InetAddress host,
@NonNull int port) {
this.id = id == null ? null : id.clone();
this.id = (id == null ? null : id.clone());
this.networkName = networkName;
this.extendedPanId = extendedPanId == null ? null : extendedPanId.clone();
this.extendedPanId = (extendedPanId == null ? null : extendedPanId.clone());
this.host = host;
this.port = port;
}
Expand Down

0 comments on commit 64928ae

Please sign in to comment.