From d851a04db4fc3e69d8f64f7db67e84587cef90c0 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Tue, 16 Jul 2024 18:48:43 +0900 Subject: [PATCH] Consolidate DNS label comparison functions in DnsUtils Moved common DNS label comparison functions from MdnsUtils.java to DnsUtils.java within the staticlib to facilitate reuse by both Connectivity and NetworkStack modules. Test: TH Change-Id: Ie839c5621d2c4b74e41987a0c6d1141d0d6e24f8 --- .../src/com/android/server/NsdService.java | 3 +- .../mdns/EnqueueMdnsQueryCallable.java | 3 +- .../connectivity/mdns/MdnsAdvertiser.java | 15 +-- .../mdns/MdnsDiscoveryManager.java | 7 +- .../connectivity/mdns/MdnsNsecRecord.java | 6 +- .../connectivity/mdns/MdnsPacketWriter.java | 4 +- .../connectivity/mdns/MdnsPointerRecord.java | 8 +- .../server/connectivity/mdns/MdnsProber.java | 4 +- .../server/connectivity/mdns/MdnsRecord.java | 10 +- .../mdns/MdnsRecordRepository.java | 13 +-- .../connectivity/mdns/MdnsResponse.java | 8 +- .../mdns/MdnsResponseDecoder.java | 7 +- .../connectivity/mdns/MdnsServiceCache.java | 4 +- .../connectivity/mdns/MdnsServiceRecord.java | 6 +- .../mdns/MdnsServiceTypeClient.java | 11 ++- .../connectivity/mdns/util/MdnsUtils.java | 85 +++-------------- staticlibs/Android.bp | 1 + .../com/android/net/module/util/DnsUtils.java | 95 +++++++++++++++++++ .../android/net/module/util/DnsUtilsTest.kt | 94 ++++++++++++++++++ .../connectivity/mdns/util/MdnsUtilsTest.kt | 66 ------------- 20 files changed, 259 insertions(+), 191 deletions(-) create mode 100644 staticlibs/framework/com/android/net/module/util/DnsUtils.java create mode 100644 staticlibs/tests/unit/src/com/android/net/module/util/DnsUtilsTest.kt diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java index 64624ae035..2f2a34265d 100644 --- a/service-t/src/com/android/server/NsdService.java +++ b/service-t/src/com/android/server/NsdService.java @@ -93,6 +93,7 @@ import com.android.metrics.NetworkNsdReportedMetrics; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.DeviceConfigUtils; +import com.android.net.module.util.DnsUtils; import com.android.net.module.util.HandlerUtils; import com.android.net.module.util.InetAddressUtils; import com.android.net.module.util.PermissionUtils; @@ -768,7 +769,7 @@ public class NsdService extends INsdManager.Stub { private Set dedupSubtypeLabels(Collection subtypes) { final Map subtypeMap = new LinkedHashMap<>(subtypes.size()); for (String subtype : subtypes) { - subtypeMap.put(MdnsUtils.toDnsLowerCase(subtype), subtype); + subtypeMap.put(DnsUtils.toDnsLowerCase(subtype), subtype); } return new ArraySet<>(subtypeMap.values()); } diff --git a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java index 54943c7eae..f55db93767 100644 --- a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java +++ b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java @@ -24,6 +24,7 @@ import android.text.TextUtils; import android.util.Pair; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.DnsUtils; import com.android.net.module.util.SharedLog; import com.android.server.connectivity.mdns.util.MdnsUtils; @@ -193,7 +194,7 @@ public class EnqueueMdnsQueryCallable implements Callable q instanceof MdnsPointerRecord - && MdnsUtils.equalsDnsLabelIgnoreDnsCase( + && DnsUtils.equalsDnsLabelIgnoreDnsCase( q.getName(), ptrRecord.getName()))) { continue; } diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java index b870477f3d..8d85f4eef6 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java @@ -41,6 +41,7 @@ import android.util.SparseArray; import com.android.connectivity.resources.R; import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.DnsUtils; import com.android.net.module.util.SharedLog; import com.android.server.connectivity.ConnectivityResources; import com.android.server.connectivity.mdns.util.MdnsUtils; @@ -272,7 +273,7 @@ public class MdnsAdvertiser { return true; } // Check if it conflicts with the default hostname. - return MdnsUtils.equalsIgnoreDnsCase(newInfo.getHostname(), mDeviceHostName[0]); + return DnsUtils.equalsIgnoreDnsCase(newInfo.getHostname(), mDeviceHostName[0]); } private void updateRegistrationUntilNoConflict( @@ -436,8 +437,8 @@ public class MdnsAdvertiser { continue; } final NsdServiceInfo other = mPendingRegistrations.valueAt(i).getServiceInfo(); - if (MdnsUtils.equalsIgnoreDnsCase(info.getServiceName(), other.getServiceName()) - && MdnsUtils.equalsIgnoreDnsCase(info.getServiceType(), + if (DnsUtils.equalsIgnoreDnsCase(info.getServiceName(), other.getServiceName()) + && DnsUtils.equalsIgnoreDnsCase(info.getServiceType(), other.getServiceType())) { return mPendingRegistrations.keyAt(i); } @@ -463,13 +464,13 @@ public class MdnsAdvertiser { final NsdServiceInfo otherInfo = otherRegistration.getServiceInfo(); final int otherServiceId = mPendingRegistrations.keyAt(i); if (clientUid != otherRegistration.mClientUid - && MdnsUtils.equalsIgnoreDnsCase( + && DnsUtils.equalsIgnoreDnsCase( info.getHostname(), otherInfo.getHostname())) { return otherServiceId; } if (!info.getHostAddresses().isEmpty() && !otherInfo.getHostAddresses().isEmpty() - && MdnsUtils.equalsIgnoreDnsCase( + && DnsUtils.equalsIgnoreDnsCase( info.getHostname(), otherInfo.getHostname())) { return otherServiceId; } @@ -849,7 +850,7 @@ public class MdnsAdvertiser { sharedLog.wtf("Invalid priority in config_nsdOffloadServicesPriority: " + entry); continue; } - priorities.put(MdnsUtils.toDnsLowerCase(priorityAndType[1]), priority); + priorities.put(DnsUtils.toDnsLowerCase(priorityAndType[1]), priority); } return priorities; } @@ -995,7 +996,7 @@ public class MdnsAdvertiser { @NonNull Registration registration, byte[] rawOffloadPacket) { final NsdServiceInfo nsdServiceInfo = registration.getServiceInfo(); final Integer mapPriority = mServiceTypeToOffloadPriority.get( - MdnsUtils.toDnsLowerCase(nsdServiceInfo.getServiceType())); + DnsUtils.toDnsLowerCase(nsdServiceInfo.getServiceType())); // Higher values of priority are less prioritized final int priority = mapPriority == null ? Integer.MAX_VALUE : mapPriority; final OffloadServiceInfo offloadServiceInfo = new OffloadServiceInfo( diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java index 0ab7a76edf..170ee9c953 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java @@ -30,6 +30,7 @@ import android.util.Pair; import androidx.annotation.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.DnsUtils; import com.android.net.module.util.SharedLog; import com.android.server.connectivity.mdns.util.MdnsUtils; @@ -66,7 +67,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback { public void put(@NonNull String serviceType, @NonNull SocketKey socketKey, @NonNull MdnsServiceTypeClient client) { - final String dnsLowerServiceType = MdnsUtils.toDnsLowerCase(serviceType); + final String dnsLowerServiceType = DnsUtils.toDnsLowerCase(serviceType); final Pair perSocketServiceType = new Pair<>(dnsLowerServiceType, socketKey); clients.put(perSocketServiceType, client); @@ -75,14 +76,14 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback { @Nullable public MdnsServiceTypeClient get( @NonNull String serviceType, @NonNull SocketKey socketKey) { - final String dnsLowerServiceType = MdnsUtils.toDnsLowerCase(serviceType); + final String dnsLowerServiceType = DnsUtils.toDnsLowerCase(serviceType); final Pair perSocketServiceType = new Pair<>(dnsLowerServiceType, socketKey); return clients.getOrDefault(perSocketServiceType, null); } public List getByServiceType(@NonNull String serviceType) { - final String dnsLowerServiceType = MdnsUtils.toDnsLowerCase(serviceType); + final String dnsLowerServiceType = DnsUtils.toDnsLowerCase(serviceType); final List list = new ArrayList<>(); for (int i = 0; i < clients.size(); i++) { final Pair perSocketServiceType = clients.keyAt(i); diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsNsecRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsNsecRecord.java index 1239180149..c168c60dd3 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsNsecRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsNsecRecord.java @@ -20,7 +20,7 @@ import android.net.DnsResolver; import android.text.TextUtils; import com.android.net.module.util.CollectionUtils; -import com.android.server.connectivity.mdns.util.MdnsUtils; +import com.android.net.module.util.DnsUtils; import java.io.IOException; import java.util.ArrayList; @@ -153,7 +153,7 @@ public class MdnsNsecRecord extends MdnsRecord { @Override public int hashCode() { return Objects.hash(super.hashCode(), - Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(mNextDomain)), + Arrays.hashCode(DnsUtils.toDnsLabelsLowerCase(mNextDomain)), Arrays.hashCode(mTypes)); } @@ -167,7 +167,7 @@ public class MdnsNsecRecord extends MdnsRecord { } return super.equals(other) - && MdnsUtils.equalsDnsLabelIgnoreDnsCase(mNextDomain, + && DnsUtils.equalsDnsLabelIgnoreDnsCase(mNextDomain, ((MdnsNsecRecord) other).mNextDomain) && Arrays.equals(mTypes, ((MdnsNsecRecord) other).mTypes); } diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsPacketWriter.java b/service-t/src/com/android/server/connectivity/mdns/MdnsPacketWriter.java index 6879a64daa..cf788be0d1 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsPacketWriter.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsPacketWriter.java @@ -16,8 +16,8 @@ package com.android.server.connectivity.mdns; +import com.android.net.module.util.DnsUtils; import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry; -import com.android.server.connectivity.mdns.util.MdnsUtils; import java.io.IOException; import java.net.DatagramPacket; @@ -180,7 +180,7 @@ public class MdnsPacketWriter { int existingOffset = entry.getKey(); String[] existingLabels = entry.getValue(); - if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(existingLabels, labels)) { + if (DnsUtils.equalsDnsLabelIgnoreDnsCase(existingLabels, labels)) { writePointer(existingOffset); return; } else if (MdnsRecord.labelsAreSuffix(existingLabels, labels)) { diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java index e5c90a46e8..5619e270ac 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java @@ -20,7 +20,7 @@ import android.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import com.android.server.connectivity.mdns.util.MdnsUtils; +import com.android.net.module.util.DnsUtils; import java.io.IOException; import java.util.Arrays; @@ -68,7 +68,7 @@ public class MdnsPointerRecord extends MdnsRecord { } public boolean hasSubtype() { - return (name != null) && (name.length > 2) && MdnsUtils.equalsIgnoreDnsCase(name[1], + return (name != null) && (name.length > 2) && DnsUtils.equalsIgnoreDnsCase(name[1], MdnsConstants.SUBTYPE_LABEL); } @@ -83,7 +83,7 @@ public class MdnsPointerRecord extends MdnsRecord { @Override public int hashCode() { - return (super.hashCode() * 31) + Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(pointer)); + return (super.hashCode() * 31) + Arrays.hashCode(DnsUtils.toDnsLabelsLowerCase(pointer)); } @Override @@ -95,7 +95,7 @@ public class MdnsPointerRecord extends MdnsRecord { return false; } - return super.equals(other) && MdnsUtils.equalsDnsLabelIgnoreDnsCase(pointer, + return super.equals(other) && DnsUtils.equalsDnsLabelIgnoreDnsCase(pointer, ((MdnsPointerRecord) other).pointer); } } \ No newline at end of file diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsProber.java b/service-t/src/com/android/server/connectivity/mdns/MdnsProber.java index e88947ab53..4a44fffa4f 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsProber.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsProber.java @@ -23,8 +23,8 @@ import android.os.Looper; import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.DnsUtils; import com.android.net.module.util.SharedLog; -import com.android.server.connectivity.mdns.util.MdnsUtils; import java.util.ArrayList; import java.util.Collections; @@ -114,7 +114,7 @@ public class MdnsProber extends MdnsPacketRepeater { private static boolean containsName(@NonNull List records, @NonNull String[] name) { return CollectionUtils.any(records, - r -> MdnsUtils.equalsDnsLabelIgnoreDnsCase(name, r.getName())); + r -> DnsUtils.equalsDnsLabelIgnoreDnsCase(name, r.getName())); } } diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java index b865319899..233545983f 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java @@ -25,7 +25,7 @@ import android.text.TextUtils; import androidx.annotation.VisibleForTesting; -import com.android.server.connectivity.mdns.util.MdnsUtils; +import com.android.net.module.util.DnsUtils; import java.io.IOException; import java.util.Arrays; @@ -139,7 +139,7 @@ public abstract class MdnsRecord { } for (int i = 0; i < list1.length; ++i) { - if (!MdnsUtils.equalsIgnoreDnsCase(list1[i], list2[i + offset])) { + if (!DnsUtils.equalsIgnoreDnsCase(list1[i], list2[i + offset])) { return false; } } @@ -284,13 +284,13 @@ public abstract class MdnsRecord { MdnsRecord otherRecord = (MdnsRecord) other; - return MdnsUtils.equalsDnsLabelIgnoreDnsCase(name, otherRecord.name) && (type + return DnsUtils.equalsDnsLabelIgnoreDnsCase(name, otherRecord.name) && (type == otherRecord.type); } @Override public int hashCode() { - return Objects.hash(Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(name)), type); + return Objects.hash(Arrays.hashCode(DnsUtils.toDnsLabelsLowerCase(name)), type); } /** @@ -311,7 +311,7 @@ public abstract class MdnsRecord { public Key(int recordType, String[] recordName) { this.recordType = recordType; - this.recordName = MdnsUtils.toDnsLabelsLowerCase(recordName); + this.recordName = DnsUtils.toDnsLabelsLowerCase(recordName); } @Override diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java b/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java index 36f3982940..0e847649f4 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsRecordRepository.java @@ -38,6 +38,7 @@ import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.DnsUtils; import com.android.net.module.util.HexDump; import com.android.server.connectivity.mdns.util.MdnsUtils; @@ -494,8 +495,8 @@ public class MdnsRecordRepository { } for (int i = 0; i < mServices.size(); i++) { final NsdServiceInfo info = mServices.valueAt(i).serviceInfo; - if (MdnsUtils.equalsIgnoreDnsCase(serviceName, info.getServiceName()) - && MdnsUtils.equalsIgnoreDnsCase(serviceType, info.getServiceType())) { + if (DnsUtils.equalsIgnoreDnsCase(serviceName, info.getServiceName()) + && DnsUtils.equalsIgnoreDnsCase(serviceType, info.getServiceType())) { return mServices.keyAt(i); } } @@ -821,7 +822,7 @@ public class MdnsRecordRepository { must match the question qtype unless the qtype is "ANY" (255) or the rrtype is "CNAME" (5), and the record rrclass must match the question qclass unless the qclass is "ANY" (255) */ - if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(info.record.getName(), question.getName())) { + if (!DnsUtils.equalsDnsLabelIgnoreDnsCase(info.record.getName(), question.getName())) { continue; } hasFullyOwnedNameMatch |= !info.isSharedName; @@ -1232,7 +1233,7 @@ public class MdnsRecordRepository { return RecordConflictType.NO_CONFLICT; } - if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(record.getName(), fullServiceName)) { + if (!DnsUtils.equalsDnsLabelIgnoreDnsCase(record.getName(), fullServiceName)) { return RecordConflictType.NO_CONFLICT; } @@ -1270,7 +1271,7 @@ public class MdnsRecordRepository { } // Different names. There won't be a conflict. - if (!MdnsUtils.equalsIgnoreDnsCase( + if (!DnsUtils.equalsIgnoreDnsCase( record.getName()[0], registration.serviceInfo.getHostname())) { return RecordConflictType.NO_CONFLICT; } @@ -1351,7 +1352,7 @@ public class MdnsRecordRepository { int id = mServices.keyAt(i); ServiceRegistration service = mServices.valueAt(i); if (service.exiting) continue; - if (MdnsUtils.equalsIgnoreDnsCase(service.serviceInfo.getHostname(), hostname)) { + if (DnsUtils.equalsIgnoreDnsCase(service.serviceInfo.getHostname(), hostname)) { consumer.accept(id, service); } } diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java index 05ad1bebfc..3636644f15 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java @@ -21,7 +21,7 @@ import android.annotation.Nullable; import android.net.Network; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.connectivity.mdns.util.MdnsUtils; +import com.android.net.module.util.DnsUtils; import java.io.IOException; import java.util.ArrayList; @@ -111,7 +111,7 @@ public class MdnsResponse { * pointer record is already present in the response with the same TTL. */ public synchronized boolean addPointerRecord(MdnsPointerRecord pointerRecord) { - if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceName, pointerRecord.getPointer())) { + if (!DnsUtils.equalsDnsLabelIgnoreDnsCase(serviceName, pointerRecord.getPointer())) { throw new IllegalArgumentException( "Pointer records for different service names cannot be added"); } @@ -305,13 +305,13 @@ public class MdnsResponse { boolean dropAddressRecords = false; for (MdnsInetAddressRecord inetAddressRecord : getInet4AddressRecords()) { - if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase( + if (!DnsUtils.equalsDnsLabelIgnoreDnsCase( this.serviceRecord.getServiceHost(), inetAddressRecord.getName())) { dropAddressRecords = true; } } for (MdnsInetAddressRecord inetAddressRecord : getInet6AddressRecords()) { - if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase( + if (!DnsUtils.equalsDnsLabelIgnoreDnsCase( this.serviceRecord.getServiceHost(), inetAddressRecord.getName())) { dropAddressRecords = true; } diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java index b812bb491b..52e76ada3e 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsResponseDecoder.java @@ -22,6 +22,7 @@ import android.net.Network; import android.util.ArrayMap; import android.util.Pair; +import com.android.net.module.util.DnsUtils; import com.android.server.connectivity.mdns.util.MdnsUtils; import java.io.EOFException; @@ -49,7 +50,7 @@ public class MdnsResponseDecoder { List responses, String[] pointer) { if (responses != null) { for (MdnsResponse response : responses) { - if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(response.getServiceName(), pointer)) { + if (DnsUtils.equalsDnsLabelIgnoreDnsCase(response.getServiceName(), pointer)) { return response; } } @@ -65,7 +66,7 @@ public class MdnsResponseDecoder { if (serviceRecord == null) { continue; } - if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceRecord.getServiceHost(), + if (DnsUtils.equalsDnsLabelIgnoreDnsCase(serviceRecord.getServiceHost(), hostName)) { return response; } @@ -318,7 +319,7 @@ public class MdnsResponseDecoder { if (serviceRecord == null) { continue; } - if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceRecord.getServiceHost(), hostName)) { + if (DnsUtils.equalsDnsLabelIgnoreDnsCase(serviceRecord.getServiceHost(), hostName)) { if (result == null) { result = new ArrayList<>(/* initialCapacity= */ responses.size()); } diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java index e9a41d1c83..7b304c8211 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java @@ -16,10 +16,10 @@ package com.android.server.connectivity.mdns; +import static com.android.net.module.util.DnsUtils.equalsIgnoreDnsCase; +import static com.android.net.module.util.DnsUtils.toDnsLowerCase; import static com.android.server.connectivity.mdns.MdnsResponse.EXPIRATION_NEVER; import static com.android.server.connectivity.mdns.util.MdnsUtils.ensureRunningOnHandlerThread; -import static com.android.server.connectivity.mdns.util.MdnsUtils.equalsIgnoreDnsCase; -import static com.android.server.connectivity.mdns.util.MdnsUtils.toDnsLowerCase; import static java.lang.Math.min; diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java index 0d6a9ec487..9fa1602394 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java @@ -20,7 +20,7 @@ import android.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import com.android.server.connectivity.mdns.util.MdnsUtils; +import com.android.net.module.util.DnsUtils; import java.io.IOException; import java.util.Arrays; @@ -151,7 +151,7 @@ public class MdnsServiceRecord extends MdnsRecord { public int hashCode() { return (super.hashCode() * 31) + Objects.hash(servicePriority, serviceWeight, - Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(serviceHost)), + Arrays.hashCode(DnsUtils.toDnsLabelsLowerCase(serviceHost)), servicePort); } @@ -168,7 +168,7 @@ public class MdnsServiceRecord extends MdnsRecord { return super.equals(other) && (servicePriority == otherRecord.servicePriority) && (serviceWeight == otherRecord.serviceWeight) - && MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceHost, otherRecord.serviceHost) + && DnsUtils.equalsDnsLabelIgnoreDnsCase(serviceHost, otherRecord.serviceHost) && (servicePort == otherRecord.servicePort); } } diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java index 643430ab88..09e5b7ff90 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java @@ -33,6 +33,7 @@ import android.util.Pair; import androidx.annotation.VisibleForTesting; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.DnsUtils; import com.android.net.module.util.SharedLog; import com.android.server.connectivity.mdns.util.MdnsUtils; @@ -120,11 +121,11 @@ public class MdnsServiceTypeClient { * @return true if the service name was not discovered before. */ boolean setServiceDiscovered(@NonNull String serviceName) { - return discoveredServiceNames.add(MdnsUtils.toDnsLowerCase(serviceName)); + return discoveredServiceNames.add(DnsUtils.toDnsLowerCase(serviceName)); } void unsetServiceDiscovered(@NonNull String serviceName) { - discoveredServiceNames.remove(MdnsUtils.toDnsLowerCase(serviceName)); + discoveredServiceNames.remove(DnsUtils.toDnsLowerCase(serviceName)); } } @@ -458,7 +459,7 @@ public class MdnsServiceTypeClient { @NonNull MdnsSearchOptions options) { final boolean matchesInstanceName = options.getResolveInstanceName() == null // DNS is case-insensitive, so ignore case in the comparison - || MdnsUtils.equalsIgnoreDnsCase(options.getResolveInstanceName(), + || DnsUtils.equalsIgnoreDnsCase(options.getResolveInstanceName(), response.getServiceInstanceName()); // If discovery is requiring some subtypes, the response must have one that matches a @@ -468,7 +469,7 @@ public class MdnsServiceTypeClient { final boolean matchesSubtype = options.getSubtypes().size() == 0 || CollectionUtils.any(options.getSubtypes(), requiredSub -> CollectionUtils.any(responseSubtypes, actualSub -> - MdnsUtils.equalsIgnoreDnsCase( + DnsUtils.equalsIgnoreDnsCase( MdnsConstants.SUBTYPE_PREFIX + requiredSub, actualSub))); return matchesInstanceName && matchesSubtype; @@ -658,7 +659,7 @@ public class MdnsServiceTypeClient { continue; } if (CollectionUtils.any(resolveResponses, - r -> MdnsUtils.equalsIgnoreDnsCase(resolveName, r.getServiceInstanceName()))) { + r -> DnsUtils.equalsIgnoreDnsCase(resolveName, r.getServiceInstanceName()))) { continue; } MdnsResponse knownResponse = diff --git a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java index 226867f1cd..8745941fed 100644 --- a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java +++ b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java @@ -16,6 +16,8 @@ package com.android.server.connectivity.mdns.util; +import static com.android.net.module.util.DnsUtils.equalsDnsLabelIgnoreDnsCase; +import static com.android.net.module.util.DnsUtils.equalsIgnoreDnsCase; import static com.android.server.connectivity.mdns.MdnsConstants.FLAG_TRUNCATED; import android.annotation.NonNull; @@ -56,18 +58,17 @@ public class MdnsUtils { private MdnsUtils() { } /** - * Convert the string to DNS case-insensitive lowercase + * Compare labels a equals b or a is suffix of b. * - * Per rfc6762#page-46, accented characters are not defined to be automatically equivalent to - * their unaccented counterparts. So the "DNS lowercase" should be if character is A-Z then they - * transform into a-z. Otherwise, they are kept as-is. + * @param a the type or subtype. + * @param b the base type */ - public static String toDnsLowerCase(@NonNull String string) { - final char[] outChars = new char[string.length()]; - for (int i = 0; i < string.length(); i++) { - outChars[i] = toDnsLowerCase(string.charAt(i)); - } - return new String(outChars); + public static boolean typeEqualsOrIsSubtype(@NonNull String[] a, + @NonNull String[] b) { + return equalsDnsLabelIgnoreDnsCase(a, b) + || ((b.length == (a.length + 2)) + && equalsIgnoreDnsCase(b[1], MdnsConstants.SUBTYPE_LABEL) + && MdnsRecord.labelsAreSuffix(a, b)); } /** @@ -81,70 +82,6 @@ public class MdnsUtils { } } - /** - * Convert the array of labels to DNS case-insensitive lowercase. - */ - public static String[] toDnsLabelsLowerCase(@NonNull String[] labels) { - final String[] outStrings = new String[labels.length]; - for (int i = 0; i < labels.length; ++i) { - outStrings[i] = toDnsLowerCase(labels[i]); - } - return outStrings; - } - - /** - * Compare two strings by DNS case-insensitive lowercase. - */ - public static boolean equalsIgnoreDnsCase(@Nullable String a, @Nullable String b) { - if (a == null || b == null) { - return a == null && b == null; - } - if (a.length() != b.length()) return false; - for (int i = 0; i < a.length(); i++) { - if (toDnsLowerCase(a.charAt(i)) != toDnsLowerCase(b.charAt(i))) { - return false; - } - } - return true; - } - - /** - * Compare two set of DNS labels by DNS case-insensitive lowercase. - */ - public static boolean equalsDnsLabelIgnoreDnsCase(@NonNull String[] a, @NonNull String[] b) { - if (a == b) { - return true; - } - int length = a.length; - if (b.length != length) { - return false; - } - for (int i = 0; i < length; i++) { - if (!equalsIgnoreDnsCase(a[i], b[i])) { - return false; - } - } - return true; - } - - /** - * Compare labels a equals b or a is suffix of b. - * - * @param a the type or subtype. - * @param b the base type - */ - public static boolean typeEqualsOrIsSubtype(@NonNull String[] a, - @NonNull String[] b) { - return MdnsUtils.equalsDnsLabelIgnoreDnsCase(a, b) - || ((b.length == (a.length + 2)) - && MdnsUtils.equalsIgnoreDnsCase(b[1], MdnsConstants.SUBTYPE_LABEL) - && MdnsRecord.labelsAreSuffix(a, b)); - } - - private static char toDnsLowerCase(char a) { - return a >= 'A' && a <= 'Z' ? (char) (a + ('a' - 'A')) : a; - } - /*** Ensure that current running thread is same as given handler thread */ public static void ensureRunningOnHandlerThread(@NonNull Handler handler) { if (!isRunningOnHandlerThread(handler)) { diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp index 14bd5df91c..c9c8be96e4 100644 --- a/staticlibs/Android.bp +++ b/staticlibs/Android.bp @@ -443,6 +443,7 @@ java_library { "device/com/android/net/module/util/SharedLog.java", "framework/com/android/net/module/util/ByteUtils.java", "framework/com/android/net/module/util/CollectionUtils.java", + "framework/com/android/net/module/util/DnsUtils.java", "framework/com/android/net/module/util/HexDump.java", "framework/com/android/net/module/util/LinkPropertiesUtils.java", ], diff --git a/staticlibs/framework/com/android/net/module/util/DnsUtils.java b/staticlibs/framework/com/android/net/module/util/DnsUtils.java new file mode 100644 index 0000000000..2c0dbe682b --- /dev/null +++ b/staticlibs/framework/com/android/net/module/util/DnsUtils.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * Dns common utility functions. + * + * @hide + */ +public class DnsUtils { + + private DnsUtils() { } + + /** + * Convert the string to DNS case-insensitive lowercase + * + * Per rfc6762#page-46, accented characters are not defined to be automatically equivalent to + * their unaccented counterparts. So the "DNS lowercase" should be if character is A-Z then they + * transform into a-z. Otherwise, they are kept as-is. + */ + public static String toDnsLowerCase(@NonNull String string) { + final char[] outChars = new char[string.length()]; + for (int i = 0; i < string.length(); i++) { + outChars[i] = toDnsLowerCase(string.charAt(i)); + } + return new String(outChars); + } + + /** + * Convert the array of labels to DNS case-insensitive lowercase. + */ + public static String[] toDnsLabelsLowerCase(@NonNull String[] labels) { + final String[] outStrings = new String[labels.length]; + for (int i = 0; i < labels.length; ++i) { + outStrings[i] = toDnsLowerCase(labels[i]); + } + return outStrings; + } + + /** + * Compare two strings by DNS case-insensitive lowercase. + */ + public static boolean equalsIgnoreDnsCase(@Nullable String a, @Nullable String b) { + if (a == null || b == null) { + return a == null && b == null; + } + if (a.length() != b.length()) return false; + for (int i = 0; i < a.length(); i++) { + if (toDnsLowerCase(a.charAt(i)) != toDnsLowerCase(b.charAt(i))) { + return false; + } + } + return true; + } + + /** + * Compare two set of DNS labels by DNS case-insensitive lowercase. + */ + public static boolean equalsDnsLabelIgnoreDnsCase(@NonNull String[] a, @NonNull String[] b) { + if (a == b) { + return true; + } + int length = a.length; + if (b.length != length) { + return false; + } + for (int i = 0; i < length; i++) { + if (!equalsIgnoreDnsCase(a[i], b[i])) { + return false; + } + } + return true; + } + + private static char toDnsLowerCase(char a) { + return a >= 'A' && a <= 'Z' ? (char) (a + ('a' - 'A')) : a; + } +} diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/DnsUtilsTest.kt b/staticlibs/tests/unit/src/com/android/net/module/util/DnsUtilsTest.kt new file mode 100644 index 0000000000..07e1128214 --- /dev/null +++ b/staticlibs/tests/unit/src/com/android/net/module/util/DnsUtilsTest.kt @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util + +import com.android.net.module.util.DnsUtils.equalsDnsLabelIgnoreDnsCase +import com.android.net.module.util.DnsUtils.equalsIgnoreDnsCase +import com.android.net.module.util.DnsUtils.toDnsLabelsLowerCase +import com.android.net.module.util.DnsUtils.toDnsLowerCase +import com.android.testutils.DevSdkIgnoreRunner +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(DevSdkIgnoreRunner::class) +class DnsUtilsTest { + @Test + fun testToDnsLowerCase() { + assertEquals("test", toDnsLowerCase("TEST")) + assertEquals("test", toDnsLowerCase("TeSt")) + assertEquals("test", toDnsLowerCase("test")) + assertEquals("tÉst", toDnsLowerCase("TÉST")) + assertEquals("ţést", toDnsLowerCase("ţést")) + // Unicode characters 0x10000 (𐀀), 0x10001 (𐀁), 0x10041 (𐁁) + // Note the last 2 bytes of 0x10041 are identical to 'A', but it should remain unchanged. + assertEquals( + "test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- ", + toDnsLowerCase("Test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- ") + ) + // Also test some characters where the first surrogate is not \ud800 + assertEquals( + "test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + + "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<", + toDnsLowerCase( + "Test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + + "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<" + ) + ) + } + + @Test + fun testToDnsLabelsLowerCase() { + assertArrayEquals( + arrayOf("test", "tÉst", "ţést"), + toDnsLabelsLowerCase(arrayOf("TeSt", "TÉST", "ţést")) + ) + } + + @Test + fun testEqualsIgnoreDnsCase() { + assertTrue(equalsIgnoreDnsCase("TEST", "Test")) + assertTrue(equalsIgnoreDnsCase("TEST", "test")) + assertTrue(equalsIgnoreDnsCase("test", "TeSt")) + assertTrue(equalsIgnoreDnsCase("Tést", "tést")) + assertFalse(equalsIgnoreDnsCase("ŢÉST", "ţést")) + // Unicode characters 0x10000 (𐀀), 0x10001 (𐀁), 0x10041 (𐁁) + // Note the last 2 bytes of 0x10041 are identical to 'A', but it should remain unchanged. + assertTrue(equalsIgnoreDnsCase( + "test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- ", + "Test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- " + )) + // Also test some characters where the first surrogate is not \ud800 + assertTrue(equalsIgnoreDnsCase( + "test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + + "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<", + "Test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + + "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<" + )) + } + + @Test + fun testEqualsLabelIgnoreDnsCase() { + assertTrue(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test", "test"))) + assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test"))) + assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("Test"), arrayOf("test", "test"))) + assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test", "tést"))) + } +} diff --git a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt index cf88d0597b..5c3ad22a62 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt +++ b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt @@ -27,16 +27,11 @@ import com.android.server.connectivity.mdns.MdnsPacketReader import com.android.server.connectivity.mdns.MdnsPointerRecord import com.android.server.connectivity.mdns.MdnsRecord import com.android.server.connectivity.mdns.util.MdnsUtils.createQueryDatagramPackets -import com.android.server.connectivity.mdns.util.MdnsUtils.equalsDnsLabelIgnoreDnsCase -import com.android.server.connectivity.mdns.util.MdnsUtils.equalsIgnoreDnsCase -import com.android.server.connectivity.mdns.util.MdnsUtils.toDnsLabelsLowerCase -import com.android.server.connectivity.mdns.util.MdnsUtils.toDnsLowerCase import com.android.server.connectivity.mdns.util.MdnsUtils.truncateServiceName import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.DevSdkIgnoreRunner import java.net.DatagramPacket import kotlin.test.assertContentEquals -import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -46,59 +41,6 @@ import org.junit.runner.RunWith @RunWith(DevSdkIgnoreRunner::class) @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) class MdnsUtilsTest { - @Test - fun testToDnsLowerCase() { - assertEquals("test", toDnsLowerCase("TEST")) - assertEquals("test", toDnsLowerCase("TeSt")) - assertEquals("test", toDnsLowerCase("test")) - assertEquals("tÉst", toDnsLowerCase("TÉST")) - assertEquals("ţést", toDnsLowerCase("ţést")) - // Unicode characters 0x10000 (𐀀), 0x10001 (𐀁), 0x10041 (𐁁) - // Note the last 2 bytes of 0x10041 are identical to 'A', but it should remain unchanged. - assertEquals( - "test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- ", - toDnsLowerCase("Test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- ") - ) - // Also test some characters where the first surrogate is not \ud800 - assertEquals( - "test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + - "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<", - toDnsLowerCase( - "Test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + - "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<" - ) - ) - } - - @Test - fun testToDnsLabelsLowerCase() { - assertArrayEquals( - arrayOf("test", "tÉst", "ţést"), - toDnsLabelsLowerCase(arrayOf("TeSt", "TÉST", "ţést")) - ) - } - - @Test - fun testEqualsIgnoreDnsCase() { - assertTrue(equalsIgnoreDnsCase("TEST", "Test")) - assertTrue(equalsIgnoreDnsCase("TEST", "test")) - assertTrue(equalsIgnoreDnsCase("test", "TeSt")) - assertTrue(equalsIgnoreDnsCase("Tést", "tést")) - assertFalse(equalsIgnoreDnsCase("ŢÉST", "ţést")) - // Unicode characters 0x10000 (𐀀), 0x10001 (𐀁), 0x10041 (𐁁) - // Note the last 2 bytes of 0x10041 are identical to 'A', but it should remain unchanged. - assertTrue(equalsIgnoreDnsCase( - "test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- ", - "Test: -->\ud800\udc00 \ud800\udc01 \ud800\udc41<-- " - )) - // Also test some characters where the first surrogate is not \ud800 - assertTrue(equalsIgnoreDnsCase( - "test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + - "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<", - "Test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" + - "\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<" - )) - } @Test fun testTruncateServiceName() { @@ -106,14 +48,6 @@ class MdnsUtilsTest { assertEquals(truncateServiceName("测试abcde", 100), "测试abcde") } - @Test - fun testEqualsLabelIgnoreDnsCase() { - assertTrue(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test", "test"))) - assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test"))) - assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("Test"), arrayOf("test", "test"))) - assertFalse(equalsDnsLabelIgnoreDnsCase(arrayOf("TEST", "Test"), arrayOf("test", "tést"))) - } - @Test fun testTypeEqualsOrIsSubtype() { assertTrue(MdnsUtils.typeEqualsOrIsSubtype(