Merge "Use case-insensitive matching in discovery/advertising"
This commit is contained in:
@@ -253,8 +253,9 @@ public class MdnsAdvertiser {
|
||||
int getConflictingService(@NonNull NsdServiceInfo info) {
|
||||
for (int i = 0; i < mPendingRegistrations.size(); i++) {
|
||||
final NsdServiceInfo other = mPendingRegistrations.valueAt(i).getServiceInfo();
|
||||
if (info.getServiceName().equals(other.getServiceName())
|
||||
&& info.getServiceType().equals(other.getServiceType())) {
|
||||
if (MdnsUtils.equalsIgnoreDnsCase(info.getServiceName(), other.getServiceName())
|
||||
&& MdnsUtils.equalsIgnoreDnsCase(info.getServiceType(),
|
||||
other.getServiceType())) {
|
||||
return mPendingRegistrations.keyAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.util.Pair;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -56,21 +57,26 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
||||
|
||||
public void put(@NonNull String serviceType, @Nullable Network network,
|
||||
@NonNull MdnsServiceTypeClient client) {
|
||||
final Pair<String, Network> perNetworkServiceType = new Pair<>(serviceType, network);
|
||||
final String dnsLowerServiceType = MdnsUtils.toDnsLowerCase(serviceType);
|
||||
final Pair<String, Network> perNetworkServiceType = new Pair<>(dnsLowerServiceType,
|
||||
network);
|
||||
clients.put(perNetworkServiceType, client);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MdnsServiceTypeClient get(@NonNull String serviceType, @Nullable Network network) {
|
||||
final Pair<String, Network> perNetworkServiceType = new Pair<>(serviceType, network);
|
||||
final String dnsLowerServiceType = MdnsUtils.toDnsLowerCase(serviceType);
|
||||
final Pair<String, Network> perNetworkServiceType = new Pair<>(dnsLowerServiceType,
|
||||
network);
|
||||
return clients.getOrDefault(perNetworkServiceType, null);
|
||||
}
|
||||
|
||||
public List<MdnsServiceTypeClient> getByServiceType(@NonNull String serviceType) {
|
||||
final String dnsLowerServiceType = MdnsUtils.toDnsLowerCase(serviceType);
|
||||
final List<MdnsServiceTypeClient> list = new ArrayList<>();
|
||||
for (int i = 0; i < clients.size(); i++) {
|
||||
final Pair<String, Network> perNetworkServiceType = clients.keyAt(i);
|
||||
if (serviceType.equals(perNetworkServiceType.first)) {
|
||||
if (dnsLowerServiceType.equals(perNetworkServiceType.first)) {
|
||||
list.add(clients.valueAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +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 java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -152,7 +153,8 @@ public class MdnsNsecRecord extends MdnsRecord {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(),
|
||||
Arrays.hashCode(mNextDomain), Arrays.hashCode(mTypes));
|
||||
Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(mNextDomain)),
|
||||
Arrays.hashCode(mTypes));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,7 +167,8 @@ public class MdnsNsecRecord extends MdnsRecord {
|
||||
}
|
||||
|
||||
return super.equals(other)
|
||||
&& Arrays.equals(mNextDomain, ((MdnsNsecRecord) other).mNextDomain)
|
||||
&& MdnsUtils.equalsDnsLabelIgnoreDnsCase(mNextDomain,
|
||||
((MdnsNsecRecord) other).mNextDomain)
|
||||
&& Arrays.equals(mTypes, ((MdnsNsecRecord) other).mTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
package com.android.server.connectivity.mdns;
|
||||
|
||||
import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -180,7 +180,7 @@ public class MdnsPacketWriter {
|
||||
int existingOffset = entry.getKey();
|
||||
String[] existingLabels = entry.getValue();
|
||||
|
||||
if (Arrays.equals(existingLabels, labels)) {
|
||||
if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(existingLabels, labels)) {
|
||||
writePointer(existingOffset);
|
||||
return;
|
||||
} else if (MdnsRecord.labelsAreSuffix(existingLabels, labels)) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.connectivity.mdns;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -60,7 +61,8 @@ public class MdnsPointerRecord extends MdnsRecord {
|
||||
}
|
||||
|
||||
public boolean hasSubtype() {
|
||||
return (name != null) && (name.length > 2) && name[1].equals(MdnsConstants.SUBTYPE_LABEL);
|
||||
return (name != null) && (name.length > 2) && MdnsUtils.equalsIgnoreDnsCase(name[1],
|
||||
MdnsConstants.SUBTYPE_LABEL);
|
||||
}
|
||||
|
||||
public String getSubtype() {
|
||||
@@ -74,7 +76,7 @@ public class MdnsPointerRecord extends MdnsRecord {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (super.hashCode() * 31) + Arrays.hashCode(pointer);
|
||||
return (super.hashCode() * 31) + Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(pointer));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,6 +88,7 @@ public class MdnsPointerRecord extends MdnsRecord {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.equals(other) && Arrays.equals(pointer, ((MdnsPointerRecord) other).pointer);
|
||||
return super.equals(other) && MdnsUtils.equalsDnsLabelIgnoreDnsCase(pointer,
|
||||
((MdnsPointerRecord) other).pointer);
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ import android.os.Looper;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -113,7 +113,8 @@ public class MdnsProber extends MdnsPacketRepeater<MdnsProber.ProbingInfo> {
|
||||
*/
|
||||
private static boolean containsName(@NonNull List<MdnsRecord> records,
|
||||
@NonNull String[] name) {
|
||||
return CollectionUtils.any(records, r -> Arrays.equals(name, r.getName()));
|
||||
return CollectionUtils.any(records,
|
||||
r -> MdnsUtils.equalsDnsLabelIgnoreDnsCase(name, r.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -136,7 +137,7 @@ public abstract class MdnsRecord {
|
||||
}
|
||||
|
||||
for (int i = 0; i < list1.length; ++i) {
|
||||
if (!list1[i].equals(list2[i + offset])) {
|
||||
if (!MdnsUtils.equalsIgnoreDnsCase(list1[i], list2[i + offset])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -271,12 +272,13 @@ public abstract class MdnsRecord {
|
||||
|
||||
MdnsRecord otherRecord = (MdnsRecord) other;
|
||||
|
||||
return Arrays.equals(name, otherRecord.name) && (type == otherRecord.type);
|
||||
return MdnsUtils.equalsDnsLabelIgnoreDnsCase(name, otherRecord.name) && (type
|
||||
== otherRecord.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(Arrays.hashCode(name), type);
|
||||
return Objects.hash(Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(name)), type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,7 +299,7 @@ public abstract class MdnsRecord {
|
||||
|
||||
public Key(int recordType, String[] recordName) {
|
||||
this.recordType = recordType;
|
||||
this.recordName = recordName;
|
||||
this.recordName = MdnsUtils.toDnsLabelsLowerCase(recordName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.util.SparseArray;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.net.module.util.HexDump;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
@@ -329,7 +330,8 @@ public class MdnsRecordRepository {
|
||||
private int getServiceByName(@NonNull String serviceName) {
|
||||
for (int i = 0; i < mServices.size(); i++) {
|
||||
final ServiceRegistration registration = mServices.valueAt(i);
|
||||
if (serviceName.equals(registration.serviceInfo.getServiceName())) {
|
||||
if (MdnsUtils.equalsIgnoreDnsCase(serviceName,
|
||||
registration.serviceInfo.getServiceName())) {
|
||||
return mServices.keyAt(i);
|
||||
}
|
||||
}
|
||||
@@ -545,7 +547,9 @@ 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 (!Arrays.equals(info.record.getName(), question.getName())) continue;
|
||||
if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(info.record.getName(), question.getName())) {
|
||||
continue;
|
||||
}
|
||||
hasFullyOwnedNameMatch |= !info.isSharedName;
|
||||
|
||||
// The repository does not store CNAME records
|
||||
@@ -747,7 +751,10 @@ public class MdnsRecordRepository {
|
||||
// happens. In fact probing is only done for the service name in the SRV record.
|
||||
// This means only SRV and TXT records need to be checked.
|
||||
final RecordInfo<MdnsServiceRecord> srvRecord = registration.srvRecord;
|
||||
if (!Arrays.equals(record.getName(), srvRecord.record.getName())) continue;
|
||||
if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(record.getName(),
|
||||
srvRecord.record.getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// As per RFC6762 9., it's fine if the "conflict" is an identical record with same
|
||||
// data.
|
||||
|
||||
@@ -21,10 +21,10 @@ import android.annotation.Nullable;
|
||||
import android.net.Network;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -103,7 +103,7 @@ public class MdnsResponse {
|
||||
* pointer record is already present in the response with the same TTL.
|
||||
*/
|
||||
public synchronized boolean addPointerRecord(MdnsPointerRecord pointerRecord) {
|
||||
if (!Arrays.equals(serviceName, pointerRecord.getPointer())) {
|
||||
if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceName, pointerRecord.getPointer())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Pointer records for different service names cannot be added");
|
||||
}
|
||||
@@ -301,13 +301,13 @@ public class MdnsResponse {
|
||||
boolean dropAddressRecords = false;
|
||||
|
||||
for (MdnsInetAddressRecord inetAddressRecord : getInet4AddressRecords()) {
|
||||
if (!Arrays.equals(
|
||||
if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(
|
||||
this.serviceRecord.getServiceHost(), inetAddressRecord.getName())) {
|
||||
dropAddressRecords = true;
|
||||
}
|
||||
}
|
||||
for (MdnsInetAddressRecord inetAddressRecord : getInet6AddressRecords()) {
|
||||
if (!Arrays.equals(
|
||||
if (!MdnsUtils.equalsDnsLabelIgnoreDnsCase(
|
||||
this.serviceRecord.getServiceHost(), inetAddressRecord.getName())) {
|
||||
dropAddressRecords = true;
|
||||
}
|
||||
|
||||
@@ -23,10 +23,10 @@ import android.os.SystemClock;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.android.server.connectivity.mdns.util.MdnsLogger;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -50,7 +50,7 @@ public class MdnsResponseDecoder {
|
||||
List<MdnsResponse> responses, String[] pointer) {
|
||||
if (responses != null) {
|
||||
for (MdnsResponse response : responses) {
|
||||
if (Arrays.equals(response.getServiceName(), pointer)) {
|
||||
if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(response.getServiceName(), pointer)) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,8 @@ public class MdnsResponseDecoder {
|
||||
if (serviceRecord == null) {
|
||||
continue;
|
||||
}
|
||||
if (Arrays.equals(serviceRecord.getServiceHost(), hostName)) {
|
||||
if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceRecord.getServiceHost(),
|
||||
hostName)) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -164,11 +165,8 @@ public class MdnsResponseDecoder {
|
||||
for (MdnsRecord record : records) {
|
||||
if (record instanceof MdnsPointerRecord) {
|
||||
String[] name = record.getName();
|
||||
if ((serviceType == null)
|
||||
|| Arrays.equals(name, serviceType)
|
||||
|| ((name.length == (serviceType.length + 2))
|
||||
&& name[1].equals(MdnsConstants.SUBTYPE_LABEL)
|
||||
&& MdnsRecord.labelsAreSuffix(serviceType, name))) {
|
||||
if ((serviceType == null) || MdnsUtils.typeEqualsOrIsSubtype(
|
||||
serviceType, name)) {
|
||||
MdnsPointerRecord pointerRecord = (MdnsPointerRecord) record;
|
||||
// Group PTR records that refer to the same service instance name into a single
|
||||
// response.
|
||||
@@ -296,7 +294,7 @@ public class MdnsResponseDecoder {
|
||||
if (serviceRecord == null) {
|
||||
continue;
|
||||
}
|
||||
if (Arrays.equals(serviceRecord.getServiceHost(), hostName)) {
|
||||
if (MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceRecord.getServiceHost(), hostName)) {
|
||||
if (result == null) {
|
||||
result = new ArrayList<>(/* initialCapacity= */ responses.size());
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.connectivity.mdns;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -142,7 +143,8 @@ public class MdnsServiceRecord extends MdnsRecord {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (super.hashCode() * 31)
|
||||
+ Objects.hash(servicePriority, serviceWeight, Arrays.hashCode(serviceHost),
|
||||
+ Objects.hash(servicePriority, serviceWeight,
|
||||
Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(serviceHost)),
|
||||
servicePort);
|
||||
}
|
||||
|
||||
@@ -159,7 +161,7 @@ public class MdnsServiceRecord extends MdnsRecord {
|
||||
return super.equals(other)
|
||||
&& (servicePriority == otherRecord.servicePriority)
|
||||
&& (serviceWeight == otherRecord.serviceWeight)
|
||||
&& Arrays.equals(serviceHost, otherRecord.serviceHost)
|
||||
&& MdnsUtils.equalsDnsLabelIgnoreDnsCase(serviceHost, otherRecord.serviceHost)
|
||||
&& (servicePort == otherRecord.servicePort);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ import android.annotation.Nullable;
|
||||
import android.net.Network;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.android.server.connectivity.mdns.MdnsConstants;
|
||||
import com.android.server.connectivity.mdns.MdnsRecord;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -49,6 +52,17 @@ public class MdnsUtils {
|
||||
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.
|
||||
*/
|
||||
@@ -62,6 +76,39 @@ public class MdnsUtils {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ private const val SERVICE_ID_1 = 1
|
||||
private const val SERVICE_ID_2 = 2
|
||||
private const val LONG_SERVICE_ID_1 = 3
|
||||
private const val LONG_SERVICE_ID_2 = 4
|
||||
private const val CASE_INSENSITIVE_TEST_SERVICE_ID = 5
|
||||
private const val TIMEOUT_MS = 10_000L
|
||||
private val TEST_ADDR = parseNumericAddress("2001:db8::123")
|
||||
private val TEST_LINKADDR = LinkAddress(TEST_ADDR, 64 /* prefixLength */)
|
||||
@@ -78,6 +79,13 @@ private val ALL_NETWORKS_SERVICE = NsdServiceInfo("TestServiceName", "_advertise
|
||||
network = null
|
||||
}
|
||||
|
||||
private val ALL_NETWORKS_SERVICE_2 =
|
||||
NsdServiceInfo("TESTSERVICENAME", "_ADVERTISERTEST._tcp").apply {
|
||||
port = 12345
|
||||
hostAddresses = listOf(TEST_ADDR)
|
||||
network = null
|
||||
}
|
||||
|
||||
private val LONG_ALL_NETWORKS_SERVICE =
|
||||
NsdServiceInfo("a".repeat(48) + "TestServiceName", "_longadvertisertest._tcp").apply {
|
||||
port = 12345
|
||||
@@ -228,6 +236,9 @@ class MdnsAdvertiserTest {
|
||||
postSync { advertiser.addService(LONG_SERVICE_ID_2, LONG_ALL_NETWORKS_SERVICE,
|
||||
null /* subtype */) }
|
||||
|
||||
postSync { advertiser.addService(CASE_INSENSITIVE_TEST_SERVICE_ID, ALL_NETWORKS_SERVICE_2,
|
||||
null /* subtype */) }
|
||||
|
||||
// Callbacks for matching network and all networks both get the socket
|
||||
postSync {
|
||||
oneNetSocketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR))
|
||||
@@ -249,6 +260,14 @@ class MdnsAdvertiserTest {
|
||||
network = LONG_ALL_NETWORKS_SERVICE.network
|
||||
}
|
||||
|
||||
val expectedCaseInsensitiveRenamed = NsdServiceInfo(
|
||||
"${ALL_NETWORKS_SERVICE_2.serviceName} (3)", ALL_NETWORKS_SERVICE_2.serviceType
|
||||
).apply {
|
||||
port = ALL_NETWORKS_SERVICE_2.port
|
||||
hostAddresses = ALL_NETWORKS_SERVICE_2.hostAddresses
|
||||
network = ALL_NETWORKS_SERVICE_2.network
|
||||
}
|
||||
|
||||
val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
|
||||
verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
|
||||
eq(thread.looper), any(), intAdvCbCaptor.capture(), eq(TEST_HOSTNAME), any()
|
||||
@@ -261,6 +280,8 @@ class MdnsAdvertiserTest {
|
||||
argThat { it.matches(LONG_SERVICE_1) }, eq(null))
|
||||
verify(mockInterfaceAdvertiser1).addService(eq(LONG_SERVICE_ID_2),
|
||||
argThat { it.matches(expectedLongRenamed) }, eq(null))
|
||||
verify(mockInterfaceAdvertiser1).addService(eq(CASE_INSENSITIVE_TEST_SERVICE_ID),
|
||||
argThat { it.matches(expectedCaseInsensitiveRenamed) }, eq(null))
|
||||
|
||||
doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
|
||||
postSync { intAdvCbCaptor.value.onRegisterServiceSucceeded(
|
||||
|
||||
@@ -31,7 +31,7 @@ class MdnsPacketWriterTest {
|
||||
@Test
|
||||
fun testNameCompression() {
|
||||
val writer = MdnsPacketWriter(ByteArray(1000))
|
||||
writer.writeLabels(arrayOf("my", "first", "name"))
|
||||
writer.writeLabels(arrayOf("my", "FIRST", "name"))
|
||||
writer.writeLabels(arrayOf("my", "second", "name"))
|
||||
writer.writeLabels(arrayOf("other", "first", "name"))
|
||||
writer.writeLabels(arrayOf("my", "second", "name"))
|
||||
@@ -41,7 +41,7 @@ class MdnsPacketWriterTest {
|
||||
InetSocketAddress(InetAddresses.parseNumericAddress("2001:db8::123"), 123))
|
||||
|
||||
// Each label takes length + 1. So "first.name" offset = 3, "name" offset = 9
|
||||
val expected = "my".label() + "first".label() + "name".label() + 0x00.toByte() +
|
||||
val expected = "my".label() + "FIRST".label() + "name".label() + 0x00.toByte() +
|
||||
// "my.second.name" offset = 15
|
||||
"my".label() + "second".label() + byteArrayOf(0xC0.toByte(), 9) +
|
||||
"other".label() + byteArrayOf(0xC0.toByte(), 3) +
|
||||
|
||||
@@ -48,6 +48,7 @@ private const val SHORT_TIMEOUT_MS = 200L
|
||||
|
||||
private val TEST_SERVICE_NAME_1 = arrayOf("testservice", "_nmt", "_tcp", "local")
|
||||
private val TEST_SERVICE_NAME_2 = arrayOf("testservice2", "_nmt", "_tcp", "local")
|
||||
private val TEST_SERVICE_NAME_3 = arrayOf("Testservice", "_nmt", "_tcp", "local")
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
@@ -128,6 +129,15 @@ class MdnsProberTest {
|
||||
assertProbesSent(probeInfo, expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateProberCaseInsensitive() {
|
||||
val probeInfo = TestProbeInfo(
|
||||
listOf(makeServiceRecord(TEST_SERVICE_NAME_1, 37890),
|
||||
makeServiceRecord(TEST_SERVICE_NAME_2, 37890),
|
||||
makeServiceRecord(TEST_SERVICE_NAME_3, 37890)))
|
||||
assertEquals(2, probeInfo.getPacket(0).questions.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testProbeMultipleRecords() {
|
||||
val replySender = MdnsReplySender("testiface", thread.looper, socket, buffer)
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.junit.runner.RunWith
|
||||
|
||||
private const val TEST_SERVICE_ID_1 = 42
|
||||
private const val TEST_SERVICE_ID_2 = 43
|
||||
private const val TEST_SERVICE_ID_3 = 44
|
||||
private const val TEST_PORT = 12345
|
||||
private const val TEST_SUBTYPE = "_subtype"
|
||||
private val TEST_HOSTNAME = arrayOf("Android_000102030405060708090A0B0C0D0E0F", "local")
|
||||
@@ -63,6 +64,12 @@ private val TEST_SERVICE_2 = NsdServiceInfo().apply {
|
||||
port = TEST_PORT
|
||||
}
|
||||
|
||||
private val TEST_SERVICE_3 = NsdServiceInfo().apply {
|
||||
serviceType = "_TESTSERVICE._tcp"
|
||||
serviceName = "MyTESTSERVICE"
|
||||
port = TEST_PORT
|
||||
}
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
class MdnsRecordRepositoryTest {
|
||||
@@ -124,6 +131,9 @@ class MdnsRecordRepositoryTest {
|
||||
assertFailsWith(NameConflictException::class) {
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1, null /* subtype */)
|
||||
}
|
||||
assertFailsWith(NameConflictException::class) {
|
||||
repository.addService(TEST_SERVICE_ID_3, TEST_SERVICE_3, null /* subtype */)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -364,6 +374,27 @@ class MdnsRecordRepositoryTest {
|
||||
assertContentEquals(expectedV4, getReverseDnsAddress(parseNumericAddress("192.0.2.123")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReplyCaseInsensitive() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
|
||||
val questionsCaseInSensitive =
|
||||
listOf(MdnsPointerRecord(arrayOf("_TESTSERVICE", "_TCP", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
// TTL and data is empty for a question
|
||||
0L /* ttlMillis */,
|
||||
null /* pointer */))
|
||||
val queryCaseInsensitive = MdnsPacket(0 /* flags */, questionsCaseInSensitive,
|
||||
listOf() /* answers */, listOf() /* authorityRecords */,
|
||||
listOf() /* additionalRecords */)
|
||||
val src = InetSocketAddress(parseNumericAddress("192.0.2.123"), 5353)
|
||||
val replyCaseInsensitive = repository.getReply(queryCaseInsensitive, src)
|
||||
assertNotNull(replyCaseInsensitive)
|
||||
assertEquals(1, replyCaseInsensitive.answers.size)
|
||||
assertEquals(7, replyCaseInsensitive.additionalAnswers.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReply() {
|
||||
doGetReplyTest(subtype = null)
|
||||
@@ -489,6 +520,34 @@ class MdnsRecordRepositoryTest {
|
||||
repository.getConflictingServices(packet))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetConflictingServicesCaseInsensitive() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* subtype */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* subtype */)
|
||||
|
||||
val packet = MdnsPacket(
|
||||
0 /* flags */,
|
||||
emptyList() /* questions */,
|
||||
listOf(
|
||||
MdnsServiceRecord(
|
||||
arrayOf("MYTESTSERVICE", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */, 0L /* ttlMillis */,
|
||||
0 /* servicePriority */, 0 /* serviceWeight */,
|
||||
TEST_SERVICE_1.port + 1,
|
||||
TEST_HOSTNAME),
|
||||
MdnsTextRecord(
|
||||
arrayOf("MYOTHERTESTSERVICE", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */, 0L /* ttlMillis */,
|
||||
listOf(TextEntry.fromString("somedifferent=entry"))),
|
||||
) /* answers */,
|
||||
emptyList() /* authorityRecords */,
|
||||
emptyList() /* additionalRecords */)
|
||||
|
||||
assertEquals(setOf(TEST_SERVICE_ID_1, TEST_SERVICE_ID_2),
|
||||
repository.getConflictingServices(packet))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetConflictingServices_IdenticalService() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
@@ -505,7 +564,7 @@ class MdnsRecordRepositoryTest {
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
otherTtlMillis, 0 /* servicePriority */, 0 /* serviceWeight */,
|
||||
TEST_SERVICE_1.port,
|
||||
TEST_HOSTNAME),
|
||||
arrayOf("ANDROID_000102030405060708090A0B0C0D0E0F", "local")),
|
||||
MdnsTextRecord(
|
||||
arrayOf("MyOtherTestService", "_testservice", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
@@ -517,6 +576,35 @@ class MdnsRecordRepositoryTest {
|
||||
// Above records are identical to the actual registrations: no conflict
|
||||
assertEquals(emptySet(), repository.getConflictingServices(packet))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetConflictingServicesCaseInsensitive_IdenticalService() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* subtype */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* subtype */)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
0 /* flags */,
|
||||
emptyList() /* questions */,
|
||||
listOf(
|
||||
MdnsServiceRecord(
|
||||
arrayOf("MYTESTSERVICE", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
otherTtlMillis, 0 /* servicePriority */, 0 /* serviceWeight */,
|
||||
TEST_SERVICE_1.port,
|
||||
TEST_HOSTNAME),
|
||||
MdnsTextRecord(
|
||||
arrayOf("MyOtherTestService", "_TESTSERVICE", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
otherTtlMillis, emptyList()),
|
||||
) /* answers */,
|
||||
emptyList() /* authorityRecords */,
|
||||
emptyList() /* additionalRecords */)
|
||||
|
||||
// Above records are identical to the actual registrations: no conflict
|
||||
assertEquals(emptySet(), repository.getConflictingServices(packet))
|
||||
}
|
||||
}
|
||||
|
||||
private fun MdnsRecordRepository.initWithService(
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.server.connectivity.mdns
|
||||
|
||||
import android.os.Build
|
||||
import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
class MdnsRecordTest {
|
||||
|
||||
@Test
|
||||
fun testPointerRecordHasSubType() {
|
||||
val ptrRecord1 = MdnsPointerRecord(
|
||||
arrayOf("_testtype", "_sub", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local")
|
||||
)
|
||||
val ptrRecord2 = MdnsPointerRecord(
|
||||
arrayOf("_testtype", "_SUB", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local")
|
||||
)
|
||||
assertTrue(ptrRecord1.hasSubtype())
|
||||
assertTrue(ptrRecord2.hasSubtype())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEqualsCaseInsensitive() {
|
||||
val ptrRecord1 = MdnsPointerRecord(
|
||||
arrayOf("_testtype", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local")
|
||||
)
|
||||
val ptrRecord2 = MdnsPointerRecord(
|
||||
arrayOf("_testType", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000 /* ttlMillis */,
|
||||
arrayOf("testsErvice", "_testtype", "_Tcp", "local")
|
||||
)
|
||||
assertEquals(ptrRecord1, ptrRecord2)
|
||||
assertEquals(ptrRecord1.hashCode(), ptrRecord2.hashCode())
|
||||
|
||||
val srvRecord1 = MdnsServiceRecord(
|
||||
arrayOf("testservice", "_testtype", "_tcp", "local"),
|
||||
123 /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
2000 /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
80 /* port */,
|
||||
arrayOf("hostname")
|
||||
)
|
||||
val srvRecord2 = MdnsServiceRecord(
|
||||
arrayOf("Testservice", "_testtype", "_tcp", "local"),
|
||||
123 /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
2000 /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
80 /* port */,
|
||||
arrayOf("Hostname")
|
||||
)
|
||||
assertEquals(srvRecord1, srvRecord2)
|
||||
assertEquals(srvRecord1.hashCode(), srvRecord2.hashCode())
|
||||
|
||||
val nsecRecord1 = MdnsNsecRecord(
|
||||
arrayOf("hostname"),
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
2000L, /* ttlMillis */
|
||||
arrayOf("hostname"),
|
||||
intArrayOf(1, 2, 3) /* types */
|
||||
)
|
||||
val nsecRecord2 = MdnsNsecRecord(
|
||||
arrayOf("HOSTNAME"),
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
2000L, /* ttlMillis */
|
||||
arrayOf("HOSTNAME"),
|
||||
intArrayOf(1, 2, 3) /* types */
|
||||
)
|
||||
assertEquals(nsecRecord1, nsecRecord2)
|
||||
assertEquals(nsecRecord1.hashCode(), nsecRecord2.hashCode())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLabelsAreSuffix() {
|
||||
val labels1 = arrayOf("a", "b", "c")
|
||||
val labels2 = arrayOf("B", "C")
|
||||
val labels3 = arrayOf("b", "c")
|
||||
val labels4 = arrayOf("b", "d")
|
||||
assertTrue(MdnsRecord.labelsAreSuffix(labels2, labels1))
|
||||
assertTrue(MdnsRecord.labelsAreSuffix(labels3, labels1))
|
||||
assertFalse(MdnsRecord.labelsAreSuffix(labels4, labels1))
|
||||
}
|
||||
}
|
||||
@@ -269,14 +269,9 @@ public class MdnsResponseDecoderTests {
|
||||
assertEquals("st=0", textStrings.get(6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeIPv6AnswerPacket() throws IOException {
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
|
||||
assertNotNull(data6);
|
||||
|
||||
responses = decode(decoder, data6);
|
||||
assertEquals(1, responses.size());
|
||||
MdnsResponse response = responses.valueAt(0);
|
||||
private void verifyResponse(ArraySet<MdnsResponse> responseArraySet) {
|
||||
assertEquals(1, responseArraySet.size());
|
||||
MdnsResponse response = responseArraySet.valueAt(0);
|
||||
assertTrue(response.isComplete());
|
||||
|
||||
MdnsInetAddressRecord inet6AddressRecord = response.getInet6AddressRecord();
|
||||
@@ -289,6 +284,22 @@ public class MdnsResponseDecoderTests {
|
||||
assertEquals(inet6Addr.getHostAddress(), "2000:3333::da6c:63ff:fe7c:7483");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeIPv6AnswerPacket() throws IOException {
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
|
||||
assertNotNull(data6);
|
||||
verifyResponse(decode(decoder, data6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeCaseInsensitiveMatch() throws IOException {
|
||||
final String[] castServiceTypeUpperCase =
|
||||
new String[] {"_GOOGLECAST", "_TCP", "LOCAL"};
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, castServiceTypeUpperCase);
|
||||
assertNotNull(data6);
|
||||
verifyResponse(decode(decoder, data6));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsComplete() {
|
||||
MdnsResponse response = new MdnsResponse(responses.valueAt(0));
|
||||
|
||||
@@ -228,6 +228,12 @@ public class MdnsResponseTests {
|
||||
final MdnsResponse response = makeCompleteResponse(TEST_TTL_MS);
|
||||
|
||||
assertFalse(response.addPointerRecord(response.getPointerRecords().get(0)));
|
||||
final String[] serviceName = new String[] { "MYSERVICE", "_TYPE", "_tcp", "local" };
|
||||
final String[] serviceType = new String[] { "_TYPE", "_tcp", "local" };
|
||||
MdnsPointerRecord pointerRecordCaseInsensitive =
|
||||
new MdnsPointerRecord(serviceType, 0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */, TEST_TTL_MS, serviceName);
|
||||
assertFalse(response.addPointerRecord(pointerRecordCaseInsensitive));
|
||||
assertFalse(response.addInet6AddressRecord(response.getInet6AddressRecord()));
|
||||
assertFalse(response.addInet4AddressRecord(response.getInet4AddressRecord()));
|
||||
assertFalse(response.setServiceRecord(response.getServiceRecord()));
|
||||
@@ -270,4 +276,30 @@ public class MdnsResponseTests {
|
||||
// All records were replaced, not added
|
||||
assertEquals(ttlZeroResponse.getRecords().size(), response.getRecords().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dropUnmatchedAddressRecords_caseInsensitive() {
|
||||
|
||||
final String[] hostname = new String[] { "MyHostname" };
|
||||
final String[] upperCaseHostName = new String[] { "MYHOSTNAME" };
|
||||
final String[] serviceName = new String[] { "MyService", "_type", "_tcp", "local" };
|
||||
final String[] serviceType = new String[] { "_type", "_tcp", "local" };
|
||||
final MdnsResponse response = new MdnsResponse(/* now= */ 0, serviceName, INTERFACE_INDEX,
|
||||
mNetwork);
|
||||
response.addPointerRecord(new MdnsPointerRecord(serviceType, 0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */, TEST_TTL_MS, serviceName));
|
||||
response.setServiceRecord(new MdnsServiceRecord(serviceName, 0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */, TEST_TTL_MS, 0 /* servicePriority */,
|
||||
0 /* serviceWeight */, 0 /* servicePort */, hostname));
|
||||
response.setTextRecord(new MdnsTextRecord(serviceName, 0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */, TEST_TTL_MS, emptyList() /* entries */));
|
||||
response.addInet4AddressRecord(new MdnsInetAddressRecord(
|
||||
upperCaseHostName , 0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
TEST_TTL_MS, parseNumericAddress("192.0.2.123")));
|
||||
response.addInet6AddressRecord(new MdnsInetAddressRecord(
|
||||
upperCaseHostName, 0L /* receiptTimeMillis */, true /* cacheFlush */,
|
||||
TEST_TTL_MS, parseNumericAddress("2001:db8::123")));
|
||||
|
||||
assertFalse(response.dropUnmatchedAddressRecords());
|
||||
}
|
||||
}
|
||||
@@ -1036,10 +1036,11 @@ public class MdnsServiceTypeClientTests {
|
||||
final String otherInstance = "instance2";
|
||||
final String ipV4Address = "192.0.2.0";
|
||||
final String ipV6Address = "2001:db8::";
|
||||
final String capitalizedRequestInstance = "Instance1";
|
||||
|
||||
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
|
||||
// Use different case in the options
|
||||
.setResolveInstanceName("Instance1").build();
|
||||
.setResolveInstanceName(capitalizedRequestInstance).build();
|
||||
|
||||
client.startSendAndReceive(mockListenerOne, resolveOptions);
|
||||
client.startSendAndReceive(mockListenerTwo, MdnsSearchOptions.getDefaultOptions());
|
||||
@@ -1067,8 +1068,9 @@ public class MdnsServiceTypeClientTests {
|
||||
Collections.emptyMap(), 0L /* ttl */), INTERFACE_INDEX, mockNetwork);
|
||||
|
||||
// mockListenerOne gets notified for the requested instance
|
||||
verify(mockListenerOne).onServiceNameDiscovered(matchServiceName(requestedInstance));
|
||||
verify(mockListenerOne).onServiceFound(matchServiceName(requestedInstance));
|
||||
verify(mockListenerOne).onServiceNameDiscovered(
|
||||
matchServiceName(capitalizedRequestInstance));
|
||||
verify(mockListenerOne).onServiceFound(matchServiceName(capitalizedRequestInstance));
|
||||
|
||||
// ...but does not get any callback for the other instance
|
||||
verify(mockListenerOne, never()).onServiceFound(matchServiceName(otherInstance));
|
||||
@@ -1079,8 +1081,9 @@ public class MdnsServiceTypeClientTests {
|
||||
// mockListenerTwo gets notified for both though
|
||||
final InOrder inOrder = inOrder(mockListenerTwo);
|
||||
inOrder.verify(mockListenerTwo).onServiceNameDiscovered(
|
||||
matchServiceName(requestedInstance));
|
||||
inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(requestedInstance));
|
||||
matchServiceName(capitalizedRequestInstance));
|
||||
inOrder.verify(mockListenerTwo).onServiceFound(
|
||||
matchServiceName(capitalizedRequestInstance));
|
||||
|
||||
inOrder.verify(mockListenerTwo).onServiceNameDiscovered(matchServiceName(otherInstance));
|
||||
inOrder.verify(mockListenerTwo).onServiceFound(matchServiceName(otherInstance));
|
||||
@@ -1179,8 +1182,7 @@ public class MdnsServiceTypeClientTests {
|
||||
final String ipV4Address = "192.0.2.0";
|
||||
|
||||
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
|
||||
// Use different case in the options
|
||||
.setResolveInstanceName("Instance1").build();
|
||||
.setResolveInstanceName("instance1").build();
|
||||
|
||||
client.startSendAndReceive(mockListenerOne, resolveOptions);
|
||||
// Ensure the first task is executed so it schedules a future task
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package com.android.server.connectivity.mdns.util
|
||||
|
||||
import android.os.Build
|
||||
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 org.junit.Assert.assertArrayEquals
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
@@ -49,6 +52,12 @@ class MdnsUtilsTest {
|
||||
"\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"))
|
||||
@@ -72,4 +81,25 @@ class MdnsUtilsTest {
|
||||
assertEquals(truncateServiceName("测试abcde", 7), "测试a")
|
||||
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(arrayOf("_type", "_tcp", "local"),
|
||||
arrayOf("_type", "_TCP", "local")))
|
||||
assertTrue(MdnsUtils.typeEqualsOrIsSubtype(arrayOf("_type", "_tcp", "local"),
|
||||
arrayOf("a", "_SUB", "_type", "_TCP", "local")))
|
||||
assertFalse(MdnsUtils.typeEqualsOrIsSubtype(arrayOf("_sub", "_type", "_tcp", "local"),
|
||||
arrayOf("_type", "_TCP", "local")))
|
||||
assertFalse(MdnsUtils.typeEqualsOrIsSubtype(
|
||||
arrayOf("a", "_other", "_type", "_tcp", "local"),
|
||||
arrayOf("a", "_SUB", "_type", "_TCP", "local")))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user