Ensure service type ends with a dot in discovery

Historical behavior of onServiceFound is to include a dot at the end of
the service type. To avoid inconsistencies between behavior of new and
older backend, which would be hard to predict/handle for apps, ensure
that the same format is used. This means a dot must be added when using
the new backend.

Implement this by creating the callback service types based on
MdnsServiceInfo obtained from MdnsDiscoveryManager, rather than the
service type that was provided by the calling app. This avoids
inconsistencies as the calling app may or may not include dots
originally, and it may use subtypes ("_sub._type._tcp.local" or even
"_type._tcp.local,_sub"), which would result in callbacks giving invalid
service types, or inconsistent with S/T behavior.

Fixes: 281776253
Test: atest
Change-Id: I677ee885d1ee8e6a09773f21e4dd53e96faee748
This commit is contained in:
Remi NGUYEN VAN
2023-05-10 13:24:53 +09:00
parent 6f47b7d501
commit 2f82fcdd6c
3 changed files with 80 additions and 30 deletions

View File

@@ -19,6 +19,7 @@ package com.android.server;
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.nsd.NsdManager.MDNS_DISCOVERY_MANAGER_EVENT;
import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
import static android.net.nsd.NsdManager.RESOLVE_SERVICE_SUCCEEDED;
import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
@@ -83,6 +84,7 @@ import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -242,14 +244,14 @@ public class NsdService extends INsdManager.Stub {
public void onServiceNameDiscovered(@NonNull MdnsServiceInfo serviceInfo) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_FOUND,
new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
new MdnsEvent(mClientId, serviceInfo));
}
@Override
public void onServiceNameRemoved(@NonNull MdnsServiceInfo serviceInfo) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_LOST,
new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
new MdnsEvent(mClientId, serviceInfo));
}
}
@@ -264,7 +266,7 @@ public class NsdService extends INsdManager.Stub {
public void onServiceFound(MdnsServiceInfo serviceInfo) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.RESOLVE_SERVICE_SUCCEEDED,
new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
new MdnsEvent(mClientId, serviceInfo));
}
}
@@ -279,21 +281,21 @@ public class NsdService extends INsdManager.Stub {
public void onServiceFound(@NonNull MdnsServiceInfo serviceInfo) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_UPDATED,
new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
new MdnsEvent(mClientId, serviceInfo));
}
@Override
public void onServiceUpdated(@NonNull MdnsServiceInfo serviceInfo) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_UPDATED,
new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
new MdnsEvent(mClientId, serviceInfo));
}
@Override
public void onServiceRemoved(@NonNull MdnsServiceInfo serviceInfo) {
mNsdStateMachine.sendMessage(MDNS_DISCOVERY_MANAGER_EVENT, mTransactionId,
NsdManager.SERVICE_UPDATED_LOST,
new MdnsEvent(mClientId, mReqServiceInfo.getServiceType(), serviceInfo));
new MdnsEvent(mClientId, serviceInfo));
}
}
@@ -303,14 +305,10 @@ public class NsdService extends INsdManager.Stub {
private static class MdnsEvent {
final int mClientId;
@NonNull
final String mRequestedServiceType;
@NonNull
final MdnsServiceInfo mMdnsServiceInfo;
MdnsEvent(int clientId, @NonNull String requestedServiceType,
@NonNull MdnsServiceInfo mdnsServiceInfo) {
MdnsEvent(int clientId, @NonNull MdnsServiceInfo mdnsServiceInfo) {
mClientId = clientId;
mRequestedServiceType = requestedServiceType;
mMdnsServiceInfo = mdnsServiceInfo;
}
}
@@ -1104,9 +1102,38 @@ public class NsdService extends INsdManager.Stub {
return true;
}
private NsdServiceInfo buildNsdServiceInfoFromMdnsEvent(final MdnsEvent event) {
@Nullable
private NsdServiceInfo buildNsdServiceInfoFromMdnsEvent(
final MdnsEvent event, int code) {
final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo;
final String serviceType = event.mRequestedServiceType;
final String[] typeArray = serviceInfo.getServiceType();
final String joinedType;
if (typeArray.length == 0
|| !typeArray[typeArray.length - 1].equals(LOCAL_DOMAIN_NAME)) {
Log.wtf(TAG, "MdnsServiceInfo type does not end in .local: "
+ Arrays.toString(typeArray));
return null;
} else {
joinedType = TextUtils.join(".",
Arrays.copyOfRange(typeArray, 0, typeArray.length - 1));
}
final String serviceType;
switch (code) {
case NsdManager.SERVICE_FOUND:
case NsdManager.SERVICE_LOST:
// For consistency with historical behavior, discovered service types have
// a dot at the end.
serviceType = joinedType + ".";
break;
case RESOLVE_SERVICE_SUCCEEDED:
// For consistency with historical behavior, resolved service types have
// a dot at the beginning.
serviceType = "." + joinedType;
break;
default:
serviceType = joinedType;
break;
}
final String serviceName = serviceInfo.getServiceInstanceName();
final NsdServiceInfo servInfo = new NsdServiceInfo(serviceName, serviceType);
final Network network = serviceInfo.getNetwork();
@@ -1131,7 +1158,9 @@ public class NsdService extends INsdManager.Stub {
final MdnsEvent event = (MdnsEvent) obj;
final int clientId = event.mClientId;
final NsdServiceInfo info = buildNsdServiceInfoFromMdnsEvent(event);
final NsdServiceInfo info = buildNsdServiceInfoFromMdnsEvent(event, code);
// Errors are already logged if null
if (info == null) return false;
if (DBG) {
Log.d(TAG, String.format("MdnsDiscoveryManager event code=%s transactionId=%d",
NsdManager.nameOf(code), transactionId));
@@ -1150,8 +1179,6 @@ public class NsdService extends INsdManager.Stub {
break;
}
final MdnsServiceInfo serviceInfo = event.mMdnsServiceInfo;
// Add '.' in front of the service type that aligns with historical behavior
info.setServiceType("." + event.mRequestedServiceType);
info.setPort(serviceInfo.getPort());
Map<String, String> attrs = serviceInfo.getAttributes();