Merge "[Feature sync] Propagate network interface index to MdnsServiceInfo"
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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(
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user