Merge "[Feature sync] Propagate network interface index to MdnsServiceInfo"

This commit is contained in:
Paul Hu
2022-10-26 01:17:10 +00:00
committed by Gerrit Code Review
12 changed files with 255 additions and 24 deletions

View File

@@ -97,4 +97,8 @@ public class MdnsConfigs {
public static boolean allowSearchOptionsToRemoveExpiredService() { public static boolean allowSearchOptionsToRemoveExpiredService() {
return false; return false;
} }
public static boolean allowNetworkInterfaceIndexPropagation() {
return true;
}
} }

View File

@@ -35,6 +35,7 @@ public class MdnsResponse {
private MdnsInetAddressRecord inet4AddressRecord; private MdnsInetAddressRecord inet4AddressRecord;
private MdnsInetAddressRecord inet6AddressRecord; private MdnsInetAddressRecord inet6AddressRecord;
private long lastUpdateTime; private long lastUpdateTime;
private int interfaceIndex = MdnsSocket.INTERFACE_INDEX_UNSPECIFIED;
/** Constructs a new, empty response. */ /** Constructs a new, empty response. */
public MdnsResponse(long now) { public MdnsResponse(long now) {
@@ -203,6 +204,21 @@ public class MdnsResponse {
return true; return true;
} }
/**
* Updates the index of the network interface at which this response was received. Can be set to
* {@link MdnsSocket#INTERFACE_INDEX_UNSPECIFIED} if unset.
*/
public synchronized void setInterfaceIndex(int interfaceIndex) {
this.interfaceIndex = interfaceIndex;
}
/**
* Returns the index of the network interface at which this response was received. Can be set to
* {@link MdnsSocket#INTERFACE_INDEX_UNSPECIFIED} if unset.
*/
public synchronized int getInterfaceIndex() {
return interfaceIndex;
}
/** Gets the IPv6 address record. */ /** Gets the IPv6 address record. */
public synchronized MdnsInetAddressRecord getInet6AddressRecord() { public synchronized MdnsInetAddressRecord getInet6AddressRecord() {

View File

@@ -92,9 +92,12 @@ public class MdnsResponseDecoder {
* the responses for completeness; the caller should do that. * the responses for completeness; the caller should do that.
* *
* @param packet The packet to read from. * @param packet The packet to read from.
* @param interfaceIndex the network interface index (or {@link
* MdnsSocket#INTERFACE_INDEX_UNSPECIFIED} if not known) at which the packet was received
* @return A list of mDNS responses, or null if the packet contained no appropriate responses. * @return A list of mDNS responses, or null if the packet contained no appropriate responses.
*/ */
public int decode(@NonNull DatagramPacket packet, @NonNull List<MdnsResponse> responses) { public int decode(@NonNull DatagramPacket packet, @NonNull List<MdnsResponse> responses,
int interfaceIndex) {
MdnsPacketReader reader = new MdnsPacketReader(packet); MdnsPacketReader reader = new MdnsPacketReader(packet);
List<MdnsRecord> records; List<MdnsRecord> records;
@@ -281,8 +284,10 @@ public class MdnsResponseDecoder {
MdnsResponse response = findResponseWithHostName(responses, inetRecord.getName()); MdnsResponse response = findResponseWithHostName(responses, inetRecord.getName());
if (inetRecord.getInet4Address() != null && response != null) { if (inetRecord.getInet4Address() != null && response != null) {
response.setInet4AddressRecord(inetRecord); response.setInet4AddressRecord(inetRecord);
response.setInterfaceIndex(interfaceIndex);
} else if (inetRecord.getInet6Address() != null && response != null) { } else if (inetRecord.getInet6Address() != null && response != null) {
response.setInet6AddressRecord(inetRecord); response.setInet6AddressRecord(inetRecord);
response.setInterfaceIndex(interfaceIndex);
} }
} }
} }

View File

@@ -57,7 +57,8 @@ public class MdnsServiceInfo implements Parcelable {
source.readString(), source.readString(),
source.readString(), source.readString(),
source.createStringArrayList(), source.createStringArrayList(),
source.createTypedArrayList(TextEntry.CREATOR)); source.createTypedArrayList(TextEntry.CREATOR),
source.readInt());
} }
@Override @Override
@@ -76,6 +77,7 @@ public class MdnsServiceInfo implements Parcelable {
final List<String> textStrings; final List<String> textStrings;
@Nullable @Nullable
final List<TextEntry> textEntries; final List<TextEntry> textEntries;
private final int interfaceIndex;
private final Map<String, byte[]> attributes; private final Map<String, byte[]> attributes;
@@ -98,7 +100,32 @@ public class MdnsServiceInfo implements Parcelable {
ipv4Address, ipv4Address,
ipv6Address, ipv6Address,
textStrings, textStrings,
/* textEntries= */ null); /* textEntries= */ null,
/* interfaceIndex= */ -1);
}
/** Constructs a {@link MdnsServiceInfo} object with default values. */
public MdnsServiceInfo(
String serviceInstanceName,
String[] serviceType,
List<String> subtypes,
String[] hostName,
int port,
String ipv4Address,
String ipv6Address,
List<String> textStrings,
@Nullable List<TextEntry> textEntries) {
this(
serviceInstanceName,
serviceType,
subtypes,
hostName,
port,
ipv4Address,
ipv6Address,
textStrings,
textEntries,
/* interfaceIndex= */ -1);
} }
/** /**
@@ -115,7 +142,8 @@ public class MdnsServiceInfo implements Parcelable {
String ipv4Address, String ipv4Address,
String ipv6Address, String ipv6Address,
List<String> textStrings, List<String> textStrings,
@Nullable List<TextEntry> textEntries) { @Nullable List<TextEntry> textEntries,
int interfaceIndex) {
this.serviceInstanceName = serviceInstanceName; this.serviceInstanceName = serviceInstanceName;
this.serviceType = serviceType; this.serviceType = serviceType;
this.subtypes = new ArrayList<>(); this.subtypes = new ArrayList<>();
@@ -149,6 +177,7 @@ public class MdnsServiceInfo implements Parcelable {
} }
} }
this.attributes = Collections.unmodifiableMap(attributes); this.attributes = Collections.unmodifiableMap(attributes);
this.interfaceIndex = interfaceIndex;
} }
private static List<TextEntry> parseTextStrings(List<String> textStrings) { private static List<TextEntry> parseTextStrings(List<String> textStrings) {
@@ -205,6 +234,14 @@ public class MdnsServiceInfo implements Parcelable {
return ipv6Address; return ipv6Address;
} }
/**
* Returns the index of the network interface at which this response was received, or -1 if the
* index is not known.
*/
public int getInterfaceIndex() {
return interfaceIndex;
}
/** /**
* Returns attribute value for {@code key} as a UTF-8 string. It's the caller who must make sure * Returns attribute value for {@code key} as a UTF-8 string. It's the caller who must make sure
* that the value of {@code key} is indeed a UTF-8 string. {@code null} will be returned if no * that the value of {@code key} is indeed a UTF-8 string. {@code null} will be returned if no
@@ -253,6 +290,7 @@ public class MdnsServiceInfo implements Parcelable {
out.writeString(ipv6Address); out.writeString(ipv6Address);
out.writeStringList(textStrings); out.writeStringList(textStrings);
out.writeTypedList(textEntries); out.writeTypedList(textEntries);
out.writeInt(interfaceIndex);
} }
@Override @Override

View File

@@ -111,7 +111,8 @@ public class MdnsServiceTypeClient {
ipv4Address, ipv4Address,
ipv6Address, ipv6Address,
response.getTextRecord().getStrings(), response.getTextRecord().getStrings(),
response.getTextRecord().getEntries()); response.getTextRecord().getEntries(),
response.getInterfaceIndex());
} }
/** /**

View File

@@ -19,11 +19,13 @@ package com.android.server.connectivity.mdns;
import android.annotation.NonNull; import android.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.server.connectivity.mdns.util.MdnsLogger;
import java.io.IOException; import java.io.IOException;
import java.net.DatagramPacket; import java.net.DatagramPacket;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.MulticastSocket; import java.net.MulticastSocket;
import java.net.SocketException;
import java.util.List; import java.util.List;
/** /**
@@ -35,6 +37,9 @@ import java.util.List;
// TODO(b/242631897): Resolve nullness suppression. // TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness") @SuppressWarnings("nullness")
public class MdnsSocket { public class MdnsSocket {
private static final MdnsLogger LOGGER = new MdnsLogger("MdnsSocket");
static final int INTERFACE_INDEX_UNSPECIFIED = -1;
private static final InetSocketAddress MULTICAST_IPV4_ADDRESS = private static final InetSocketAddress MULTICAST_IPV4_ADDRESS =
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT); new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT);
private static final InetSocketAddress MULTICAST_IPV6_ADDRESS = private static final InetSocketAddress MULTICAST_IPV6_ADDRESS =
@@ -103,6 +108,19 @@ public class MdnsSocket {
multicastNetworkInterfaceProvider.stopWatchingConnectivityChanges(); multicastNetworkInterfaceProvider.stopWatchingConnectivityChanges();
} }
/**
* Returns the index of the network interface that this socket is bound to. If the interface
* cannot be determined, returns -1.
*/
public int getInterfaceIndex() {
try {
return multicastSocket.getNetworkInterface().getIndex();
} catch (SocketException e) {
LOGGER.e("Failed to retrieve interface index for socket.", e);
return -1;
}
}
@VisibleForTesting @VisibleForTesting
MulticastSocket createMulticastSocket(int port) throws IOException { MulticastSocket createMulticastSocket(int port) throws IOException {
return new MulticastSocket(port); return new MulticastSocket(port);

View File

@@ -79,6 +79,8 @@ public class MdnsSocketClient {
private final boolean checkMulticastResponse = MdnsConfigs.checkMulticastResponse(); private final boolean checkMulticastResponse = MdnsConfigs.checkMulticastResponse();
private final long checkMulticastResponseIntervalMs = private final long checkMulticastResponseIntervalMs =
MdnsConfigs.checkMulticastResponseIntervalMs(); MdnsConfigs.checkMulticastResponseIntervalMs();
private final boolean propagateInterfaceIndex =
MdnsConfigs.allowNetworkInterfaceIndexPropagation();
private final Object socketLock = new Object(); private final Object socketLock = new Object();
private final Object timerObject = new Object(); private final Object timerObject = new Object();
// If multicast response was received in the current session. The value is reset in the // If multicast response was received in the current session. The value is reset in the
@@ -382,7 +384,12 @@ public class MdnsSocketClient {
if (!shouldStopSocketLoop) { if (!shouldStopSocketLoop) {
String responseType = socket == multicastSocket ? MULTICAST_TYPE : UNICAST_TYPE; String responseType = socket == multicastSocket ? MULTICAST_TYPE : UNICAST_TYPE;
processResponsePacket(packet, responseType); processResponsePacket(
packet,
responseType,
/* interfaceIndex= */ (socket == null || !propagateInterfaceIndex)
? MdnsSocket.INTERFACE_INDEX_UNSPECIFIED
: socket.getInterfaceIndex());
} }
} catch (IOException e) { } catch (IOException e) {
if (!shouldStopSocketLoop) { if (!shouldStopSocketLoop) {
@@ -393,12 +400,12 @@ public class MdnsSocketClient {
LOGGER.log("Receive thread stopped."); LOGGER.log("Receive thread stopped.");
} }
private int processResponsePacket(@NonNull DatagramPacket packet, String responseType) private int processResponsePacket(
throws IOException { @NonNull DatagramPacket packet, String responseType, int interfaceIndex) {
int packetNumber = ++receivedPacketNumber; int packetNumber = ++receivedPacketNumber;
List<MdnsResponse> responses = new LinkedList<>(); List<MdnsResponse> responses = new LinkedList<>();
int errorCode = responseDecoder.decode(packet, responses); int errorCode = responseDecoder.decode(packet, responses, interfaceIndex);
if (errorCode == MdnsResponseDecoder.SUCCESS) { if (errorCode == MdnsResponseDecoder.SUCCESS) {
if (responseType.equals(MULTICAST_TYPE)) { if (responseType.equals(MULTICAST_TYPE)) {
receivedMulticastResponse = true; receivedMulticastResponse = true;
@@ -414,7 +421,8 @@ public class MdnsSocketClient {
} }
for (MdnsResponse response : responses) { for (MdnsResponse response : responses) {
String serviceInstanceName = response.getServiceInstanceName(); String serviceInstanceName = response.getServiceInstanceName();
LOGGER.log("mDNS %s response received: %s", responseType, serviceInstanceName); LOGGER.log("mDNS %s response received: %s at ifIndex %d", responseType,
serviceInstanceName, interfaceIndex);
if (callback != null) { if (callback != null) {
callback.onResponseReceived(response); callback.onResponseReceived(response);
} }

View File

@@ -106,9 +106,9 @@ public class MdnsResponseDecoderTests {
+ "63616C0000018001000000780004C0A8010A000001800100000078" + "63616C0000018001000000780004C0A8010A000001800100000078"
+ "0004C0A8010A00000000000000"); + "0004C0A8010A00000000000000");
private static final String DUMMY_CAST_SERVICE_NAME = "_googlecast"; private static final String CAST_SERVICE_NAME = "_googlecast";
private static final String[] DUMMY_CAST_SERVICE_TYPE = private static final String[] CAST_SERVICE_TYPE =
new String[] {DUMMY_CAST_SERVICE_NAME, "_tcp", "local"}; new String[] {CAST_SERVICE_NAME, "_tcp", "local"};
private final List<MdnsResponse> responses = new LinkedList<>(); private final List<MdnsResponse> responses = new LinkedList<>();
@@ -116,13 +116,13 @@ public class MdnsResponseDecoderTests {
@Before @Before
public void setUp() { public void setUp() {
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, DUMMY_CAST_SERVICE_TYPE); MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
assertNotNull(data); assertNotNull(data);
DatagramPacket packet = new DatagramPacket(data, data.length); DatagramPacket packet = new DatagramPacket(data, data.length);
packet.setSocketAddress( packet.setSocketAddress(
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT)); new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT));
responses.clear(); responses.clear();
int errorCode = decoder.decode(packet, responses); int errorCode = decoder.decode(packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED);
assertEquals(MdnsResponseDecoder.SUCCESS, errorCode); assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
assertEquals(1, responses.size()); assertEquals(1, responses.size());
} }
@@ -135,7 +135,7 @@ public class MdnsResponseDecoderTests {
packet.setSocketAddress( packet.setSocketAddress(
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT)); new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT));
responses.clear(); responses.clear();
int errorCode = decoder.decode(packet, responses); int errorCode = decoder.decode(packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED);
assertEquals(MdnsResponseDecoder.SUCCESS, errorCode); assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
assertEquals(2, responses.size()); assertEquals(2, responses.size());
} }
@@ -153,7 +153,7 @@ public class MdnsResponseDecoderTests {
MdnsServiceRecord serviceRecord = response.getServiceRecord(); MdnsServiceRecord serviceRecord = response.getServiceRecord();
String serviceName = serviceRecord.getServiceName(); String serviceName = serviceRecord.getServiceName();
assertEquals(DUMMY_CAST_SERVICE_NAME, serviceName); assertEquals(CAST_SERVICE_NAME, serviceName);
String serviceInstanceName = serviceRecord.getServiceInstanceName(); String serviceInstanceName = serviceRecord.getServiceInstanceName();
assertEquals("Johnny's Chromecast", serviceInstanceName); assertEquals("Johnny's Chromecast", serviceInstanceName);
@@ -187,14 +187,14 @@ public class MdnsResponseDecoderTests {
@Test @Test
public void testDecodeIPv6AnswerPacket() throws IOException { public void testDecodeIPv6AnswerPacket() throws IOException {
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, DUMMY_CAST_SERVICE_TYPE); MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
assertNotNull(data6); assertNotNull(data6);
DatagramPacket packet = new DatagramPacket(data6, data6.length); DatagramPacket packet = new DatagramPacket(data6, data6.length);
packet.setSocketAddress( packet.setSocketAddress(
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT)); new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
responses.clear(); responses.clear();
int errorCode = decoder.decode(packet, responses); int errorCode = decoder.decode(packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED);
assertEquals(MdnsResponseDecoder.SUCCESS, errorCode); assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
MdnsResponse response = responses.get(0); MdnsResponse response = responses.get(0);
@@ -234,4 +234,19 @@ public class MdnsResponseDecoderTests {
response.setTextRecord(null); response.setTextRecord(null);
assertFalse(response.isComplete()); assertFalse(response.isComplete());
} }
@Test
public void decode_withInterfaceIndex_populatesInterfaceIndex() {
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
assertNotNull(data6);
DatagramPacket packet = new DatagramPacket(data6, data6.length);
packet.setSocketAddress(
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
responses.clear();
int errorCode = decoder.decode(packet, responses, /* interfaceIndex= */ 10);
assertEquals(errorCode, MdnsResponseDecoder.SUCCESS);
assertEquals(responses.size(), 1);
assertEquals(responses.get(0).getInterfaceIndex(), 10);
}
} }

View File

@@ -221,6 +221,19 @@ public class MdnsResponseTests {
assertEquals(response.getTextRecord(), record); assertEquals(response.getTextRecord(), record);
} }
@Test
public void getInterfaceIndex_returnsDefaultValue() {
MdnsResponse response = new MdnsResponse(/* now= */ 0);
assertEquals(response.getInterfaceIndex(), -1);
}
@Test
public void getInterfaceIndex_afterSet_returnsValue() {
MdnsResponse response = new MdnsResponse(/* now= */ 0);
response.setInterfaceIndex(5);
assertEquals(response.getInterfaceIndex(), 5);
}
@Test @Test
public void mergeRecordsFrom_indicates_change_on_ipv4_address() throws IOException { public void mergeRecordsFrom_indicates_change_on_ipv4_address() throws IOException {
MdnsResponse response = makeMdnsResponse( MdnsResponse response = makeMdnsResponse(

View File

@@ -115,6 +115,40 @@ public class MdnsServiceInfoTest {
info.getAttributes()); info.getAttributes());
} }
@Test
public void getInterfaceIndex_constructorWithDefaultValues_returnsMinusOne() {
MdnsServiceInfo info =
new MdnsServiceInfo(
"my-mdns-service",
new String[] {"_googlecast", "_tcp"},
List.of(),
new String[] {"my-host", "local"},
12345,
"192.168.1.1",
"2001::1",
List.of());
assertEquals(info.getInterfaceIndex(), -1);
}
@Test
public void getInterfaceIndex_constructorWithInterfaceIndex_returnsProvidedIndex() {
MdnsServiceInfo info =
new MdnsServiceInfo(
"my-mdns-service",
new String[] {"_googlecast", "_tcp"},
List.of(),
new String[] {"my-host", "local"},
12345,
"192.168.1.1",
"2001::1",
List.of(),
/* textEntries= */ null,
/* interfaceIndex= */ 20);
assertEquals(info.getInterfaceIndex(), 20);
}
@Test @Test
public void parcelable_canBeParceledAndUnparceled() { public void parcelable_canBeParceledAndUnparceled() {
Parcel parcel = Parcel.obtain(); Parcel parcel = Parcel.obtain();

View File

@@ -401,7 +401,8 @@ public class MdnsServiceTypeClientTests {
ipV4Address, ipV4Address,
5353, 5353,
Collections.singletonList("ABCDE"), Collections.singletonList("ABCDE"),
Collections.emptyMap()); Collections.emptyMap(),
/* interfaceIndex= */ 20);
client.processResponse(initialResponse); client.processResponse(initialResponse);
// Process a second response with a different port and updated text attributes. // Process a second response with a different port and updated text attributes.
@@ -411,7 +412,8 @@ public class MdnsServiceTypeClientTests {
ipV4Address, ipV4Address,
5354, 5354,
Collections.singletonList("ABCDE"), Collections.singletonList("ABCDE"),
Collections.singletonMap("key", "value")); Collections.singletonMap("key", "value"),
/* interfaceIndex= */ 20);
client.processResponse(secondResponse); client.processResponse(secondResponse);
// Verify onServiceFound was called once for the initial response. // Verify onServiceFound was called once for the initial response.
@@ -422,6 +424,7 @@ public class MdnsServiceTypeClientTests {
assertEquals(initialServiceInfo.getPort(), 5353); assertEquals(initialServiceInfo.getPort(), 5353);
assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE")); assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
assertNull(initialServiceInfo.getAttributeByKey("key")); assertNull(initialServiceInfo.getAttributeByKey("key"));
assertEquals(initialServiceInfo.getInterfaceIndex(), 20);
// Verify onServiceUpdated was called once for the second response. // Verify onServiceUpdated was called once for the second response.
verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
@@ -432,6 +435,7 @@ public class MdnsServiceTypeClientTests {
assertTrue(updatedServiceInfo.hasSubtypes()); assertTrue(updatedServiceInfo.hasSubtypes());
assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE")); assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value"); assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value");
assertEquals(updatedServiceInfo.getInterfaceIndex(), 20);
} }
@Test @Test
@@ -446,7 +450,8 @@ public class MdnsServiceTypeClientTests {
ipV6Address, ipV6Address,
5353, 5353,
Collections.singletonList("ABCDE"), Collections.singletonList("ABCDE"),
Collections.emptyMap()); Collections.emptyMap(),
/* interfaceIndex= */ 20);
client.processResponse(initialResponse); client.processResponse(initialResponse);
// Process a second response with a different port and updated text attributes. // Process a second response with a different port and updated text attributes.
@@ -456,7 +461,8 @@ public class MdnsServiceTypeClientTests {
ipV6Address, ipV6Address,
5354, 5354,
Collections.singletonList("ABCDE"), Collections.singletonList("ABCDE"),
Collections.singletonMap("key", "value")); Collections.singletonMap("key", "value"),
/* interfaceIndex= */ 20);
client.processResponse(secondResponse); client.processResponse(secondResponse);
System.out.println("secondResponses ip" System.out.println("secondResponses ip"
@@ -470,6 +476,7 @@ public class MdnsServiceTypeClientTests {
assertEquals(initialServiceInfo.getPort(), 5353); assertEquals(initialServiceInfo.getPort(), 5353);
assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE")); assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
assertNull(initialServiceInfo.getAttributeByKey("key")); assertNull(initialServiceInfo.getAttributeByKey("key"));
assertEquals(initialServiceInfo.getInterfaceIndex(), 20);
// Verify onServiceUpdated was called once for the second response. // Verify onServiceUpdated was called once for the second response.
verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture()); verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
@@ -480,6 +487,7 @@ public class MdnsServiceTypeClientTests {
assertTrue(updatedServiceInfo.hasSubtypes()); assertTrue(updatedServiceInfo.hasSubtypes());
assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE")); assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value"); assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value");
assertEquals(updatedServiceInfo.getInterfaceIndex(), 20);
} }
@Test @Test
@@ -727,7 +735,6 @@ public class MdnsServiceTypeClientTests {
} }
} }
// Creates a complete mDNS response.
private MdnsResponse createResponse( private MdnsResponse createResponse(
@NonNull String serviceInstanceName, @NonNull String serviceInstanceName,
@NonNull String host, @NonNull String host,
@@ -735,6 +742,19 @@ public class MdnsServiceTypeClientTests {
@NonNull List<String> subtypes, @NonNull List<String> subtypes,
@NonNull Map<String, String> textAttributes) @NonNull Map<String, String> textAttributes)
throws Exception { throws Exception {
return createResponse(serviceInstanceName, host, port, subtypes, textAttributes,
/* interfaceIndex= */ -1);
}
// Creates a complete mDNS response.
private MdnsResponse createResponse(
@NonNull String serviceInstanceName,
@NonNull String host,
int port,
@NonNull List<String> subtypes,
@NonNull Map<String, String> textAttributes,
int interfaceIndex)
throws Exception {
String[] hostName = new String[]{"hostname"}; String[] hostName = new String[]{"hostname"};
MdnsServiceRecord serviceRecord = mock(MdnsServiceRecord.class); MdnsServiceRecord serviceRecord = mock(MdnsServiceRecord.class);
when(serviceRecord.getServiceHost()).thenReturn(hostName); when(serviceRecord.getServiceHost()).thenReturn(hostName);
@@ -747,10 +767,12 @@ public class MdnsServiceTypeClientTests {
when(inetAddressRecord.getInet6Address()) when(inetAddressRecord.getInet6Address())
.thenReturn((Inet6Address) Inet6Address.getByName(host)); .thenReturn((Inet6Address) Inet6Address.getByName(host));
response.setInet6AddressRecord(inetAddressRecord); response.setInet6AddressRecord(inetAddressRecord);
response.setInterfaceIndex(interfaceIndex);
} else { } else {
when(inetAddressRecord.getInet4Address()) when(inetAddressRecord.getInet4Address())
.thenReturn((Inet4Address) Inet4Address.getByName(host)); .thenReturn((Inet4Address) Inet4Address.getByName(host));
response.setInet4AddressRecord(inetAddressRecord); response.setInet4AddressRecord(inetAddressRecord);
response.setInterfaceIndex(interfaceIndex);
} }
MdnsTextRecord textRecord = mock(MdnsTextRecord.class); MdnsTextRecord textRecord = mock(MdnsTextRecord.class);

View File

@@ -18,6 +18,7 @@ package com.android.server.connectivity.mdns;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@@ -25,6 +26,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -45,6 +47,7 @@ import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers; import org.mockito.ArgumentMatchers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -490,4 +493,58 @@ public class MdnsSocketClientTests {
assertFalse(mdnsClient.receivedUnicastResponse); assertFalse(mdnsClient.receivedUnicastResponse);
assertFalse(mdnsClient.cannotReceiveMulticastResponse.get()); assertFalse(mdnsClient.cannotReceiveMulticastResponse.get());
} }
@Test
public void startDiscovery_andPropagateInterfaceIndex_includesInterfaceIndex()
throws Exception {
//MdnsConfigsFlagsImpl.allowNetworkInterfaceIndexPropagation.override(true);
when(mockMulticastSocket.getInterfaceIndex()).thenReturn(21);
mdnsClient =
new MdnsSocketClient(mContext, mockMulticastLock) {
@Override
MdnsSocket createMdnsSocket(int port) {
if (port == MdnsConstants.MDNS_PORT) {
return mockMulticastSocket;
}
return mockUnicastSocket;
}
};
mdnsClient.setCallback(mockCallback);
mdnsClient.startDiscovery();
ArgumentCaptor<MdnsResponse> mdnsResponseCaptor =
ArgumentCaptor.forClass(MdnsResponse.class);
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
.onResponseReceived(mdnsResponseCaptor.capture());
assertEquals(21, mdnsResponseCaptor.getValue().getInterfaceIndex());
}
@Test
@Ignore("MdnsConfigs is not configurable currently.")
public void startDiscovery_andDoNotPropagateInterfaceIndex_doesNotIncludeInterfaceIndex()
throws Exception {
//MdnsConfigsFlagsImpl.allowNetworkInterfaceIndexPropagation.override(false);
when(mockMulticastSocket.getInterfaceIndex()).thenReturn(21);
mdnsClient =
new MdnsSocketClient(mContext, mockMulticastLock) {
@Override
MdnsSocket createMdnsSocket(int port) {
if (port == MdnsConstants.MDNS_PORT) {
return mockMulticastSocket;
}
return mockUnicastSocket;
}
};
mdnsClient.setCallback(mockCallback);
mdnsClient.startDiscovery();
ArgumentCaptor<MdnsResponse> mdnsResponseCaptor =
ArgumentCaptor.forClass(MdnsResponse.class);
verify(mockMulticastSocket, never()).getInterfaceIndex();
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
.onResponseReceived(mdnsResponseCaptor.capture());
assertEquals(-1, mdnsResponseCaptor.getValue().getInterfaceIndex());
}
} }