Add missing SRV/TXT/address records to responses

MdnsResponses were only updated through
MdnsResponse.mergeRecordsFrom(MndsResponse), meaning that MdnsResponse
cannot be updated unless a MdnsResponse can be built from the update
packet.

Because a PTR record is required to build a MdnsResponse, this means
that it was not possible to add records to a MdnsResponse unless the
update packet contains a PTR record.

Fix this by having MdnsServiceTypeClient augment its current known
responses in addition to creating new responses from incoming
MdnsPackets.

Bug: 267570781
Test: atest NsdManagerTest#testPtrOnlyResponse with
      mdns_discovery_manager_version set to 1.
Change-Id: Iba293b4772fcd79e94ee6412c9af8225a3349f12
This commit is contained in:
Remi NGUYEN VAN
2023-02-16 16:48:14 +09:00
parent 36981e2352
commit 42b1042f36
5 changed files with 339 additions and 300 deletions

View File

@@ -21,17 +21,21 @@ import static android.net.InetAddresses.parseNumericAddress;
import static com.android.server.connectivity.mdns.MdnsResponseDecoder.Clock;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import android.net.InetAddresses;
import android.net.Network;
import android.util.ArraySet;
import com.android.net.module.util.HexDump;
import com.android.server.connectivity.mdns.MdnsResponseTests.MdnsInet4AddressRecord;
import com.android.server.connectivity.mdns.MdnsResponseTests.MdnsInet6AddressRecord;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -45,7 +49,11 @@ import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@RunWith(DevSdkIgnoreRunner.class)
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
@@ -148,6 +156,42 @@ public class MdnsResponseDecoderTests {
+ "010001000000780004C0A8018A0000000000000000000000000000"
+ "000000");
// MDNS record for name "testhost1" with an IPv4 address of 10.1.2.3
private static final byte[] DATAIN_IPV4_1 = HexDump.hexStringToByteArray(
"0974657374686f73743100000100010000007800040a010203");
// MDNS record for name "testhost1" with an IPv4 address of 10.1.2.4
private static final byte[] DATAIN_IPV4_2 = HexDump.hexStringToByteArray(
"0974657374686f73743100000100010000007800040a010204");
// MDNS record w/name "testhost1" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3040
private static final byte[] DATAIN_IPV6_1 = HexDump.hexStringToByteArray(
"0974657374686f73743100001c0001000000780010aabbccdd11223344a0b0c0d010203040");
// MDNS record w/name "testhost1" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3030
private static final byte[] DATAIN_IPV6_2 = HexDump.hexStringToByteArray(
"0974657374686f73743100001c0001000000780010aabbccdd11223344a0b0c0d010203030");
// MDNS record w/name "test" & PTR to foo.bar.quxx
private static final byte[] DATAIN_PTR_1 = HexDump.hexStringToByteArray(
"047465737400000C000100001194000E03666F6F03626172047175787800");
// MDNS record w/name "test" & PTR to foo.bar.quxy
private static final byte[] DATAIN_PTR_2 = HexDump.hexStringToByteArray(
"047465737400000C000100001194000E03666F6F03626172047175787900");
// SRV record for: scapy.DNSRRSRV(rrname='foo.bar.quxx', ttl=120, port=1234, target='testhost1')
private static final byte[] DATAIN_SERVICE_1 = HexDump.hexStringToByteArray(
"03666f6f03626172047175787800002100010000007800110000000004d20974657374686f73743100");
// SRV record for: scapy.DNSRRSRV(rrname='foo.bar.quxx', ttl=120, port=1234, target='testhost2')
private static final byte[] DATAIN_SERVICE_2 = HexDump.hexStringToByteArray(
"03666f6f03626172047175787800002100010000007800110000000004d20974657374686f73743200");
// TXT record for: scapy.DNSRR(rrname='foo.bar.quxx', type='TXT', ttl=120,
// rdata=[b'a=hello there', b'b=1234567890', b'xyz=!$$$'])
private static final byte[] DATAIN_TEXT_1 = HexDump.hexStringToByteArray(
"03666f6f03626172047175787800001000010000007800240d613d68656c6c6f2074686572650c623d3132"
+ "33343536373839300878797a3d21242424");
// TXT record for: scapy.DNSRR(rrname='foo.bar.quxx', type='TXT', ttl=120,
// rdata=[b'a=hello there', b'b=1234567890', b'xyz=!$$$'])
private static final byte[] DATAIN_TEXT_2 = HexDump.hexStringToByteArray(
"03666f6f03626172047175787800001000010000007800240d613d68656c6c6f2074686572650c623d3132"
+ "33343536373839300878797a3d21402324");
private static final String CAST_SERVICE_NAME = "_googlecast";
private static final String[] CAST_SERVICE_TYPE =
new String[] {CAST_SERVICE_NAME, "_tcp", "local"};
@@ -155,7 +199,7 @@ public class MdnsResponseDecoderTests {
private static final String[] MATTER_SERVICE_TYPE =
new String[] {MATTER_SERVICE_NAME, "_tcp", "local"};
private List<MdnsResponse> responses;
private ArraySet<MdnsResponse> responses;
private final Clock mClock = mock(Clock.class);
@@ -176,7 +220,7 @@ public class MdnsResponseDecoderTests {
@Test
public void testDecodeMultipleAnswerPacket() throws IOException {
MdnsResponse response = responses.get(0);
MdnsResponse response = responses.valueAt(0);
assertTrue(response.isComplete());
MdnsInetAddressRecord inet4AddressRecord = response.getInet4AddressRecord();
@@ -226,7 +270,7 @@ public class MdnsResponseDecoderTests {
responses = decode(decoder, data6);
assertEquals(1, responses.size());
MdnsResponse response = responses.get(0);
MdnsResponse response = responses.valueAt(0);
assertTrue(response.isComplete());
MdnsInetAddressRecord inet6AddressRecord = response.getInet6AddressRecord();
@@ -241,13 +285,13 @@ public class MdnsResponseDecoderTests {
@Test
public void testIsComplete() {
MdnsResponse response = new MdnsResponse(responses.get(0));
MdnsResponse response = new MdnsResponse(responses.valueAt(0));
assertTrue(response.isComplete());
response.clearPointerRecords();
assertFalse(response.isComplete());
response = new MdnsResponse(responses.get(0));
response = new MdnsResponse(responses.valueAt(0));
response.setInet4AddressRecord(null);
assertFalse(response.isComplete());
@@ -259,11 +303,11 @@ public class MdnsResponseDecoderTests {
response.setInet6AddressRecord(null);
assertFalse(response.isComplete());
response = new MdnsResponse(responses.get(0));
response = new MdnsResponse(responses.valueAt(0));
response.setServiceRecord(null);
assertFalse(response.isComplete());
response = new MdnsResponse(responses.get(0));
response = new MdnsResponse(responses.valueAt(0));
response.setTextRecord(null);
assertFalse(response.isComplete());
}
@@ -280,12 +324,13 @@ public class MdnsResponseDecoderTests {
assertNotNull(parsedPacket);
final Network network = mock(Network.class);
responses = decoder.buildResponses(parsedPacket,
responses = decoder.augmentResponses(parsedPacket,
/* existingResponses= */ Collections.emptyList(),
/* interfaceIndex= */ 10, network /* expireOnExit= */);
assertEquals(responses.size(), 1);
assertEquals(responses.get(0).getInterfaceIndex(), 10);
assertEquals(network, responses.get(0).getNetwork());
assertEquals(responses.valueAt(0).getInterfaceIndex(), 10);
assertEquals(network, responses.valueAt(0).getNetwork());
}
@Test
@@ -300,17 +345,17 @@ public class MdnsResponseDecoderTests {
// This should emit two records:
assertEquals(2, responses.size());
MdnsResponse response1 = responses.get(0);
MdnsResponse response2 = responses.get(0);
MdnsResponse response1 = responses.valueAt(0);
MdnsResponse response2 = responses.valueAt(0);
// Both of which are complete:
assertTrue(response1.isComplete());
assertTrue(response2.isComplete());
// And should both have the same IPv6 address:
assertEquals(InetAddresses.parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"),
assertEquals(parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"),
response1.getInet6AddressRecord().getInet6Address());
assertEquals(InetAddresses.parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"),
assertEquals(parseNumericAddress("2605:a601:a846:5700:3e61:5ff:fe0c:89f8"),
response2.getInet6AddressRecord().getInet6Address());
}
@@ -328,17 +373,206 @@ public class MdnsResponseDecoderTests {
assertEquals(2, responses.size());
// But only the first is complete:
assertTrue(responses.get(0).isComplete());
assertFalse(responses.get(1).isComplete());
assertTrue(responses.valueAt(0).isComplete());
assertFalse(responses.valueAt(1).isComplete());
}
@Test
public void testDecodeWithIpv4AddressChange() throws IOException {
MdnsResponse response = makeMdnsResponse(0, List.of(
new PacketAndRecordClass(DATAIN_PTR_1,
MdnsPointerRecord.class),
new PacketAndRecordClass(DATAIN_SERVICE_1,
MdnsServiceRecord.class),
new PacketAndRecordClass(DATAIN_IPV4_1,
MdnsInet4AddressRecord.class)));
// Now update the response with another address
final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
final ArraySet<MdnsResponse> updatedResponses = decode(
decoder, makeResponsePacket(DATAIN_IPV4_2), List.of(response));
assertEquals(1, updatedResponses.size());
assertEquals(parseNumericAddress("10.1.2.4"),
updatedResponses.valueAt(0).getInet4AddressRecord().getInet4Address());
assertEquals(parseNumericAddress("10.1.2.3"),
response.getInet4AddressRecord().getInet4Address());
}
@Test
public void testDecodeWithIpv6AddressChange() throws IOException {
MdnsResponse response = makeMdnsResponse(0, List.of(
new PacketAndRecordClass(DATAIN_PTR_1,
MdnsPointerRecord.class),
new PacketAndRecordClass(DATAIN_SERVICE_1,
MdnsServiceRecord.class),
new PacketAndRecordClass(DATAIN_IPV6_1,
MdnsInet6AddressRecord.class)));
// Now update the response with another address
final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
final ArraySet<MdnsResponse> updatedResponses = decode(
decoder, makeResponsePacket(DATAIN_IPV6_2), List.of(response));
assertEquals(1, updatedResponses.size());
assertEquals(parseNumericAddress("aabb:ccdd:1122:3344:a0b0:c0d0:1020:3030"),
updatedResponses.valueAt(0).getInet6AddressRecord().getInet6Address());
assertEquals(parseNumericAddress("aabb:ccdd:1122:3344:a0b0:c0d0:1020:3040"),
response.getInet6AddressRecord().getInet6Address());
}
@Test
public void testDecodeWithChangeOnText() throws IOException {
MdnsResponse response = makeMdnsResponse(0, List.of(
new PacketAndRecordClass(DATAIN_PTR_1,
MdnsPointerRecord.class),
new PacketAndRecordClass(DATAIN_SERVICE_1,
MdnsServiceRecord.class),
new PacketAndRecordClass(DATAIN_TEXT_1,
MdnsTextRecord.class)));
// Now update the response with another address
final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
final ArraySet<MdnsResponse> updatedResponses = decode(
decoder, makeResponsePacket(DATAIN_TEXT_2), List.of(response));
assertEquals(1, updatedResponses.size());
assertEquals(List.of(
new MdnsServiceInfo.TextEntry("a", "hello there"),
new MdnsServiceInfo.TextEntry("b", "1234567890"),
new MdnsServiceInfo.TextEntry("xyz", "!@#$")),
updatedResponses.valueAt(0).getTextRecord().getEntries());
}
@Test
public void testDecodeWithChangeOnService() throws IOException {
MdnsResponse response = makeMdnsResponse(0, List.of(
new PacketAndRecordClass(DATAIN_PTR_1,
MdnsPointerRecord.class),
new PacketAndRecordClass(DATAIN_SERVICE_1,
MdnsServiceRecord.class),
new PacketAndRecordClass(DATAIN_IPV4_1,
MdnsInet4AddressRecord.class)));
assertArrayEquals(new String[] { "testhost1" },
response.getServiceRecord().getServiceHost());
assertNotNull(response.getInet4AddressRecord());
// Now update the response with another hostname
final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
final ArraySet<MdnsResponse> updatedResponses = decode(
decoder, makeResponsePacket(DATAIN_SERVICE_2), List.of(response));
assertEquals(1, updatedResponses.size());
assertArrayEquals(new String[] { "testhost2" },
updatedResponses.valueAt(0).getServiceRecord().getServiceHost());
// Hostname changed, so address records are dropped
assertNull(updatedResponses.valueAt(0).getInet4AddressRecord());
}
@Test
public void testDecodeWithChangeOnPtr() throws IOException {
MdnsResponse response = makeMdnsResponse(0, List.of(
new PacketAndRecordClass(DATAIN_PTR_1,
MdnsPointerRecord.class),
new PacketAndRecordClass(DATAIN_SERVICE_1,
MdnsServiceRecord.class)));
// Now update the response with another address
final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
final ArraySet<MdnsResponse> updatedResponses = decode(
decoder, makeResponsePacket(DATAIN_PTR_2), List.of(response));
assertEquals(1, updatedResponses.size());
assertArrayEquals(new String[] { "foo", "bar", "quxy" },
updatedResponses.valueAt(0).getPointerRecords().get(0).getPointer());
}
@Test
public void testDecodeWithNoChange() throws IOException {
List<PacketAndRecordClass> recordList =
Arrays.asList(
new PacketAndRecordClass(DATAIN_IPV4_1, MdnsInet4AddressRecord.class),
new PacketAndRecordClass(DATAIN_IPV6_1, MdnsInet6AddressRecord.class),
new PacketAndRecordClass(DATAIN_PTR_1, MdnsPointerRecord.class),
new PacketAndRecordClass(DATAIN_SERVICE_2, MdnsServiceRecord.class),
new PacketAndRecordClass(DATAIN_TEXT_1, MdnsTextRecord.class));
// Create a two identical responses.
MdnsResponse response = makeMdnsResponse(0, recordList);
final MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, null);
final byte[] identicalResponse = makeResponsePacket(
recordList.stream().map(p -> p.packetData).collect(Collectors.toList()));
final ArraySet<MdnsResponse> changes = decode(
decoder, identicalResponse, List.of(response));
// Decoding should not indicate any change.
assertEquals(0, changes.size());
}
private static MdnsResponse makeMdnsResponse(long time, List<PacketAndRecordClass> responseList)
throws IOException {
final MdnsResponse response = new MdnsResponse(
time, 999 /* interfaceIndex */, mock(Network.class));
for (PacketAndRecordClass responseData : responseList) {
DatagramPacket packet =
new DatagramPacket(responseData.packetData, responseData.packetData.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
// Apply the right kind of record to the response.
if (responseData.recordClass == MdnsInet4AddressRecord.class) {
response.setInet4AddressRecord(new MdnsInet4AddressRecord(name, reader));
} else if (responseData.recordClass == MdnsInet6AddressRecord.class) {
response.setInet6AddressRecord(new MdnsInet6AddressRecord(name, reader));
} else if (responseData.recordClass == MdnsPointerRecord.class) {
response.addPointerRecord(new MdnsPointerRecord(name, reader));
} else if (responseData.recordClass == MdnsServiceRecord.class) {
response.setServiceRecord(new MdnsServiceRecord(name, reader));
} else if (responseData.recordClass == MdnsTextRecord.class) {
response.setTextRecord(new MdnsTextRecord(name, reader));
} else {
fail("Unsupported/unexpected MdnsRecord subtype used in test - invalid test!");
}
}
return response;
}
private static byte[] makeResponsePacket(byte[] responseRecord) throws IOException {
return makeResponsePacket(List.of(responseRecord));
}
private static byte[] makeResponsePacket(List<byte[]> responseRecords) throws IOException {
final MdnsPacketWriter writer = new MdnsPacketWriter(1500);
writer.writeUInt16(0); // Transaction ID (advertisement: 0)
writer.writeUInt16(0x8400); // Flags: response, authoritative
writer.writeUInt16(0); // questions count
writer.writeUInt16(responseRecords.size()); // answers count
writer.writeUInt16(0); // authority entries count
writer.writeUInt16(0); // additional records count
for (byte[] record : responseRecords) {
writer.writeBytes(record);
}
final DatagramPacket packet = writer.getPacket(new InetSocketAddress(0 /* port */));
return Arrays.copyOf(packet.getData(), packet.getLength());
}
private List<MdnsResponse> decode(MdnsResponseDecoder decoder, byte[] data)
// This helper class just wraps the data bytes of a response packet with the contained record
// type.
// Its only purpose is to make the test code a bit more readable.
private static class PacketAndRecordClass {
public final byte[] packetData;
public final Class<?> recordClass;
PacketAndRecordClass(byte[] data, Class<?> c) {
packetData = data;
recordClass = c;
}
}
private ArraySet<MdnsResponse> decode(MdnsResponseDecoder decoder, byte[] data)
throws MdnsPacket.ParseException {
return decode(decoder, data, Collections.emptyList());
}
private ArraySet<MdnsResponse> decode(MdnsResponseDecoder decoder, byte[] data,
Collection<MdnsResponse> existingResponses) throws MdnsPacket.ParseException {
final MdnsPacket parsedPacket = MdnsResponseDecoder.parseResponse(data, data.length);
assertNotNull(parsedPacket);
return decoder.buildResponses(parsedPacket,
return decoder.augmentResponses(parsedPacket,
existingResponses,
MdnsSocket.INTERFACE_INDEX_UNSPECIFIED, mock(Network.class));
}
}

View File

@@ -25,7 +25,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static java.util.Collections.emptyList;
@@ -36,13 +35,11 @@ import com.android.net.module.util.HexDump;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.net.DatagramPacket;
import java.util.Arrays;
import java.util.List;
// The record test data does not use compressed names (label pointers), since that would require
@@ -52,36 +49,24 @@ import java.util.List;
public class MdnsResponseTests {
private static final String TAG = "MdnsResponseTests";
// MDNS response packet for name "test" with an IPv4 address of 10.1.2.3
private static final byte[] dataIn_ipv4_1 = HexDump.hexStringToByteArray(
private static final byte[] DATAIN_IPV4 = HexDump.hexStringToByteArray(
"0474657374000001" + "0001000011940004" + "0A010203");
// MDNS response packet for name "tess" with an IPv4 address of 10.1.2.4
private static final byte[] dataIn_ipv4_2 = HexDump.hexStringToByteArray(
"0474657373000001" + "0001000011940004" + "0A010204");
// MDNS response w/name "test" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3040
private static final byte[] dataIn_ipv6_1 = HexDump.hexStringToByteArray(
private static final byte[] DATAIN_IPV6 = HexDump.hexStringToByteArray(
"047465737400001C" + "0001000011940010" + "AABBCCDD11223344" + "A0B0C0D010203040");
// MDNS response w/name "test" & IPv6 address of aabb:ccdd:1122:3344:a0b0:c0d0:1020:3030
private static final byte[] dataIn_ipv6_2 = HexDump.hexStringToByteArray(
"047465737400001C" + "0001000011940010" + "AABBCCDD11223344" + "A0B0C0D010203030");
// MDNS response w/name "test" & PTR to foo.bar.quxx
private static final byte[] dataIn_ptr_1 = HexDump.hexStringToByteArray(
private static final byte[] DATAIN_PTR = HexDump.hexStringToByteArray(
"047465737400000C" + "000100001194000E" + "03666F6F03626172" + "047175787800");
// MDNS response w/name "test" & PTR to foo.bar.quxy
private static final byte[] dataIn_ptr_2 = HexDump.hexStringToByteArray(
"047465737400000C" + "000100001194000E" + "03666F6F03626172" + "047175787900");
// MDNS response w/name "test" & Service for host foo.bar.quxx
private static final byte[] dataIn_service_1 = HexDump.hexStringToByteArray(
private static final byte[] DATAIN_SERVICE = HexDump.hexStringToByteArray(
"0474657374000021"
+ "0001000011940014"
+ "000100FF1F480366"
+ "6F6F036261720471"
+ "75787800");
// MDNS response w/name "test" & Service for host test
private static final byte[] dataIn_service_2 = HexDump.hexStringToByteArray(
"0474657374000021" + "000100001194000B" + "000100FF1F480474" + "657374");
// MDNS response w/name "test" & the following text strings:
// "a=hello there", "b=1234567890", and "xyz=!$$$"
private static final byte[] dataIn_text_1 = HexDump.hexStringToByteArray(
private static final byte[] DATAIN_TEXT = HexDump.hexStringToByteArray(
"0474657374000010"
+ "0001000011940024"
+ "0D613D68656C6C6F"
@@ -89,16 +74,6 @@ public class MdnsResponseTests {
+ "3D31323334353637"
+ "3839300878797A3D"
+ "21242424");
// MDNS response w/name "test" & the following text strings:
// "a=hello there", "b=1234567890", and "xyz=!@#$"
private static final byte[] dataIn_text_2 = HexDump.hexStringToByteArray(
"0474657374000010"
+ "0001000011940024"
+ "0D613D68656C6C6F"
+ "2074686572650C62"
+ "3D31323334353637"
+ "3839300878797A3D"
+ "21402324");
private static final int INTERFACE_INDEX = 999;
private static final int TEST_TTL_MS = 120_000;
@@ -118,52 +93,6 @@ public class MdnsResponseTests {
}
}
// This helper class just wraps the data bytes of a response packet with the contained record
// type.
// Its only purpose is to make the test code a bit more readable.
static class PacketAndRecordClass {
public final byte[] packetData;
public final Class<?> recordClass;
public PacketAndRecordClass() {
packetData = null;
recordClass = null;
}
public PacketAndRecordClass(byte[] data, Class<?> c) {
packetData = data;
recordClass = c;
}
}
// Construct an MdnsResponse with the specified data packets applied.
private MdnsResponse makeMdnsResponse(long time, List<PacketAndRecordClass> responseList)
throws IOException {
MdnsResponse response = new MdnsResponse(time, INTERFACE_INDEX, mNetwork);
for (PacketAndRecordClass responseData : responseList) {
DatagramPacket packet =
new DatagramPacket(responseData.packetData, responseData.packetData.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
// Apply the right kind of record to the response.
if (responseData.recordClass == MdnsInet4AddressRecord.class) {
response.setInet4AddressRecord(new MdnsInet4AddressRecord(name, reader));
} else if (responseData.recordClass == MdnsInet6AddressRecord.class) {
response.setInet6AddressRecord(new MdnsInet6AddressRecord(name, reader));
} else if (responseData.recordClass == MdnsPointerRecord.class) {
response.addPointerRecord(new MdnsPointerRecord(name, reader));
} else if (responseData.recordClass == MdnsServiceRecord.class) {
response.setServiceRecord(new MdnsServiceRecord(name, reader));
} else if (responseData.recordClass == MdnsTextRecord.class) {
response.setTextRecord(new MdnsTextRecord(name, reader));
} else {
fail("Unsupported/unexpected MdnsRecord subtype used in test - invalid test!");
}
}
return response;
}
private MdnsResponse makeCompleteResponse(int recordsTtlMillis) {
final MdnsResponse response = new MdnsResponse(/* now= */ 0, INTERFACE_INDEX, mNetwork);
final String[] hostname = new String[] { "MyHostname" };
@@ -187,7 +116,7 @@ public class MdnsResponseTests {
@Test
public void getInet4AddressRecord_returnsAddedRecord() throws IOException {
DatagramPacket packet = new DatagramPacket(dataIn_ipv4_1, dataIn_ipv4_1.length);
DatagramPacket packet = new DatagramPacket(DATAIN_IPV4, DATAIN_IPV4.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
@@ -200,7 +129,7 @@ public class MdnsResponseTests {
@Test
public void getInet6AddressRecord_returnsAddedRecord() throws IOException {
DatagramPacket packet = new DatagramPacket(dataIn_ipv6_1, dataIn_ipv6_1.length);
DatagramPacket packet = new DatagramPacket(DATAIN_IPV6, DATAIN_IPV6.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
@@ -214,7 +143,7 @@ public class MdnsResponseTests {
@Test
public void getPointerRecords_returnsAddedRecord() throws IOException {
DatagramPacket packet = new DatagramPacket(dataIn_ptr_1, dataIn_ptr_1.length);
DatagramPacket packet = new DatagramPacket(DATAIN_PTR, DATAIN_PTR.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
@@ -230,7 +159,7 @@ public class MdnsResponseTests {
@Test
public void getServiceRecord_returnsAddedRecord() throws IOException {
DatagramPacket packet = new DatagramPacket(dataIn_service_1, dataIn_service_1.length);
DatagramPacket packet = new DatagramPacket(DATAIN_SERVICE, DATAIN_SERVICE.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
@@ -243,7 +172,7 @@ public class MdnsResponseTests {
@Test
public void getTextRecord_returnsAddedRecord() throws IOException {
DatagramPacket packet = new DatagramPacket(dataIn_text_1, dataIn_text_1.length);
DatagramPacket packet = new DatagramPacket(DATAIN_TEXT, DATAIN_TEXT.length);
MdnsPacketReader reader = new MdnsPacketReader(packet);
String[] name = reader.readLabels();
reader.skip(2); // skip record type indication.
@@ -275,88 +204,6 @@ public class MdnsResponseTests {
assertEquals(mNetwork, response2.getNetwork());
}
@Test
public void mergeRecordsFrom_indicates_change_on_ipv4_address() throws IOException {
MdnsResponse response = makeMdnsResponse(
0,
Arrays.asList(
new PacketAndRecordClass(dataIn_ipv4_1, MdnsInet4AddressRecord.class)));
// Now create a new response that updates the address.
MdnsResponse response2 = makeMdnsResponse(
100,
Arrays.asList(
new PacketAndRecordClass(dataIn_ipv4_2, MdnsInet4AddressRecord.class)));
assertTrue(response.mergeRecordsFrom(response2));
}
@Test
public void mergeRecordsFrom_indicates_change_on_ipv6_address() throws IOException {
MdnsResponse response = makeMdnsResponse(
0,
Arrays.asList(
new PacketAndRecordClass(dataIn_ipv6_1, MdnsInet6AddressRecord.class)));
// Now create a new response that updates the address.
MdnsResponse response2 = makeMdnsResponse(
100,
Arrays.asList(
new PacketAndRecordClass(dataIn_ipv6_2, MdnsInet6AddressRecord.class)));
assertTrue(response.mergeRecordsFrom(response2));
}
@Test
public void mergeRecordsFrom_indicates_change_on_text() throws IOException {
MdnsResponse response = makeMdnsResponse(
0,
Arrays.asList(new PacketAndRecordClass(dataIn_text_1, MdnsTextRecord.class)));
// Now create a new response that updates the address.
MdnsResponse response2 = makeMdnsResponse(
100,
Arrays.asList(new PacketAndRecordClass(dataIn_text_2, MdnsTextRecord.class)));
assertTrue(response.mergeRecordsFrom(response2));
}
@Test
public void mergeRecordsFrom_indicates_change_on_service() throws IOException {
MdnsResponse response = makeMdnsResponse(
0,
Arrays.asList(new PacketAndRecordClass(dataIn_service_1, MdnsServiceRecord.class)));
// Now create a new response that updates the address.
MdnsResponse response2 = makeMdnsResponse(
100,
Arrays.asList(new PacketAndRecordClass(dataIn_service_2, MdnsServiceRecord.class)));
assertTrue(response.mergeRecordsFrom(response2));
}
@Test
public void mergeRecordsFrom_indicates_change_on_pointer() throws IOException {
MdnsResponse response = makeMdnsResponse(
0,
Arrays.asList(new PacketAndRecordClass(dataIn_ptr_1, MdnsPointerRecord.class)));
// Now create a new response that updates the address.
MdnsResponse response2 = makeMdnsResponse(
100,
Arrays.asList(new PacketAndRecordClass(dataIn_ptr_2, MdnsPointerRecord.class)));
assertTrue(response.mergeRecordsFrom(response2));
}
@Test
@Ignore("MdnsConfigs is not configurable currently.")
public void mergeRecordsFrom_indicates_noChange() throws IOException {
//MdnsConfigsFlagsImpl.useReducedMergeRecordUpdateEvents.override(true);
List<PacketAndRecordClass> recordList =
Arrays.asList(
new PacketAndRecordClass(dataIn_ipv4_1, MdnsInet4AddressRecord.class),
new PacketAndRecordClass(dataIn_ipv6_1, MdnsInet6AddressRecord.class),
new PacketAndRecordClass(dataIn_ptr_1, MdnsPointerRecord.class),
new PacketAndRecordClass(dataIn_service_2, MdnsServiceRecord.class),
new PacketAndRecordClass(dataIn_text_1, MdnsTextRecord.class));
// Create a two identical responses.
MdnsResponse response = makeMdnsResponse(0, recordList);
MdnsResponse response2 = makeMdnsResponse(100, recordList);
// Merging should not indicate any change.
assertFalse(response.mergeRecordsFrom(response2));
}
@Test
public void copyConstructor() {
final MdnsResponse response = makeCompleteResponse(TEST_TTL_MS);