Merge "Adds option to control whethert to send IPv6 packet on IPv6 only network" am: 454c06e956 am: 882e74b042
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2613049 Change-Id: I7506d242c693deae1539629a93f95f188286c430 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -29,7 +29,6 @@ import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -78,6 +77,7 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str
|
||||
private final List<MdnsResponse> servicesToResolve;
|
||||
@NonNull
|
||||
private final MdnsResponseDecoder.Clock clock;
|
||||
private final boolean onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
|
||||
EnqueueMdnsQueryCallable(
|
||||
@NonNull MdnsSocketClientBase requestSender,
|
||||
@@ -87,6 +87,7 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str
|
||||
boolean expectUnicastResponse,
|
||||
int transactionId,
|
||||
@Nullable Network network,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks,
|
||||
boolean sendDiscoveryQueries,
|
||||
@NonNull Collection<MdnsResponse> servicesToResolve,
|
||||
@NonNull MdnsResponseDecoder.Clock clock) {
|
||||
@@ -97,6 +98,7 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str
|
||||
this.expectUnicastResponse = expectUnicastResponse;
|
||||
this.transactionId = transactionId;
|
||||
this.network = network;
|
||||
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
this.sendDiscoveryQueries = sendDiscoveryQueries;
|
||||
this.servicesToResolve = new ArrayList<>(servicesToResolve);
|
||||
this.clock = clock;
|
||||
@@ -128,24 +130,29 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str
|
||||
for (MdnsResponse response : servicesToResolve) {
|
||||
final String[] serviceName = response.getServiceName();
|
||||
if (serviceName == null) continue;
|
||||
if (!response.hasTextRecord() || MdnsUtils.isRecordRenewalNeeded(
|
||||
response.getTextRecord(), now)) {
|
||||
missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_TXT));
|
||||
}
|
||||
if (!response.hasServiceRecord() || MdnsUtils.isRecordRenewalNeeded(
|
||||
response.getServiceRecord(), now)) {
|
||||
missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_SRV));
|
||||
// The hostname is not yet known, so queries for address records will be sent
|
||||
// the next time the EnqueueMdnsQueryCallable is enqueued if the reply does not
|
||||
// contain them. In practice, advertisers should include the address records
|
||||
// when queried for SRV, although it's not a MUST requirement (RFC6763 12.2).
|
||||
// TODO: Figure out how to renew the A/AAAA record. Usually A/AAAA record will
|
||||
// be included in the response to the SRV record so in high chances there is
|
||||
// no need to renew them individually.
|
||||
} else if (!response.hasInet4AddressRecord() && !response.hasInet6AddressRecord()) {
|
||||
final String[] host = response.getServiceRecord().getServiceHost();
|
||||
missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_A));
|
||||
missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_AAAA));
|
||||
boolean renewTxt = !response.hasTextRecord() || MdnsUtils.isRecordRenewalNeeded(
|
||||
response.getTextRecord(), now);
|
||||
boolean renewSrv = !response.hasServiceRecord() || MdnsUtils.isRecordRenewalNeeded(
|
||||
response.getServiceRecord(), now);
|
||||
if (renewSrv && renewTxt) {
|
||||
missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_ANY));
|
||||
} else {
|
||||
if (renewTxt) {
|
||||
missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_TXT));
|
||||
}
|
||||
if (renewSrv) {
|
||||
missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_SRV));
|
||||
// The hostname is not yet known, so queries for address records will be
|
||||
// sent the next time the EnqueueMdnsQueryCallable is enqueued if the reply
|
||||
// does not contain them. In practice, advertisers should include the
|
||||
// address records when queried for SRV, although it's not a MUST
|
||||
// requirement (RFC6763 12.2).
|
||||
} else if (!response.hasInet4AddressRecord()
|
||||
&& !response.hasInet6AddressRecord()) {
|
||||
final String[] host = response.getServiceRecord().getServiceHost();
|
||||
missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_A));
|
||||
missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_AAAA));
|
||||
}
|
||||
}
|
||||
}
|
||||
numQuestions += missingKnownAnswerRecords.size();
|
||||
@@ -183,24 +190,9 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str
|
||||
writeQuestion(serviceTypeLabels, MdnsRecord.TYPE_PTR);
|
||||
}
|
||||
|
||||
if (requestSender instanceof MdnsMultinetworkSocketClient) {
|
||||
sendPacketToIpv4AndIpv6(requestSender, MdnsConstants.MDNS_PORT, network);
|
||||
for (Integer emulatorPort : castShellEmulatorMdnsPorts) {
|
||||
sendPacketToIpv4AndIpv6(requestSender, emulatorPort, network);
|
||||
}
|
||||
} else if (requestSender instanceof MdnsSocketClient) {
|
||||
final MdnsSocketClient client = (MdnsSocketClient) requestSender;
|
||||
InetAddress mdnsAddress = MdnsConstants.getMdnsIPv4Address();
|
||||
if (client.isOnIPv6OnlyNetwork()) {
|
||||
mdnsAddress = MdnsConstants.getMdnsIPv6Address();
|
||||
}
|
||||
|
||||
sendPacketTo(client, new InetSocketAddress(mdnsAddress, MdnsConstants.MDNS_PORT));
|
||||
for (Integer emulatorPort : castShellEmulatorMdnsPorts) {
|
||||
sendPacketTo(client, new InetSocketAddress(mdnsAddress, emulatorPort));
|
||||
}
|
||||
} else {
|
||||
throw new IOException("Unknown socket client type: " + requestSender.getClass());
|
||||
sendPacketToIpv4AndIpv6(requestSender, MdnsConstants.MDNS_PORT);
|
||||
for (Integer emulatorPort : castShellEmulatorMdnsPorts) {
|
||||
sendPacketToIpv4AndIpv6(requestSender, emulatorPort);
|
||||
}
|
||||
return Pair.create(transactionId, subtypes);
|
||||
} catch (IOException e) {
|
||||
@@ -218,38 +210,39 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str
|
||||
| (expectUnicastResponse ? MdnsConstants.QCLASS_UNICAST : 0));
|
||||
}
|
||||
|
||||
private void sendPacketTo(MdnsSocketClient requestSender, InetSocketAddress address)
|
||||
private void sendPacket(MdnsSocketClientBase requestSender, InetSocketAddress address)
|
||||
throws IOException {
|
||||
DatagramPacket packet = packetWriter.getPacket(address);
|
||||
if (expectUnicastResponse) {
|
||||
requestSender.sendUnicastPacket(packet);
|
||||
if (requestSender instanceof MdnsMultinetworkSocketClient) {
|
||||
((MdnsMultinetworkSocketClient) requestSender).sendPacketRequestingUnicastResponse(
|
||||
packet, network, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
} else {
|
||||
requestSender.sendPacketRequestingUnicastResponse(
|
||||
packet, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
} else {
|
||||
requestSender.sendMulticastPacket(packet);
|
||||
if (requestSender instanceof MdnsMultinetworkSocketClient) {
|
||||
((MdnsMultinetworkSocketClient) requestSender)
|
||||
.sendPacketRequestingMulticastResponse(
|
||||
packet, network, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
} else {
|
||||
requestSender.sendPacketRequestingMulticastResponse(
|
||||
packet, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacketFromNetwork(MdnsSocketClientBase requestSender,
|
||||
InetSocketAddress address, Network network)
|
||||
throws IOException {
|
||||
DatagramPacket packet = packetWriter.getPacket(address);
|
||||
if (expectUnicastResponse) {
|
||||
requestSender.sendUnicastPacket(packet, network);
|
||||
} else {
|
||||
requestSender.sendMulticastPacket(packet, network);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacketToIpv4AndIpv6(MdnsSocketClientBase requestSender, int port,
|
||||
Network network) {
|
||||
private void sendPacketToIpv4AndIpv6(MdnsSocketClientBase requestSender, int port) {
|
||||
try {
|
||||
sendPacketFromNetwork(requestSender,
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), port), network);
|
||||
sendPacket(requestSender,
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), port));
|
||||
} catch (IOException e) {
|
||||
Log.i(TAG, "Can't send packet to IPv4", e);
|
||||
}
|
||||
try {
|
||||
sendPacketFromNetwork(requestSender,
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), port), network);
|
||||
sendPacket(requestSender,
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), port));
|
||||
} catch (IOException e) {
|
||||
Log.i(TAG, "Can't send packet to IPv6", e);
|
||||
}
|
||||
|
||||
@@ -213,17 +213,21 @@ public class MdnsMultinetworkSocketClient implements MdnsSocketClientBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendMdnsPacket(@NonNull DatagramPacket packet, @Nullable Network targetNetwork) {
|
||||
private void sendMdnsPacket(@NonNull DatagramPacket packet, @Nullable Network targetNetwork,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
final boolean isIpv6 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
|
||||
instanceof Inet6Address;
|
||||
final boolean isIpv4 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
|
||||
instanceof Inet4Address;
|
||||
final ArrayMap<MdnsInterfaceSocket, SocketKey> activeSockets = getActiveSockets();
|
||||
boolean shouldQueryIpv6 = !onlyUseIpv6OnIpv6OnlyNetworks || isIpv6OnlyNetworks(
|
||||
activeSockets, targetNetwork);
|
||||
for (int i = 0; i < activeSockets.size(); i++) {
|
||||
final MdnsInterfaceSocket socket = activeSockets.keyAt(i);
|
||||
final Network network = activeSockets.valueAt(i).getNetwork();
|
||||
// Check ip capability and network before sending packet
|
||||
if (((isIpv6 && socket.hasJoinedIpv6()) || (isIpv4 && socket.hasJoinedIpv4()))
|
||||
if (((isIpv6 && socket.hasJoinedIpv6() && shouldQueryIpv6)
|
||||
|| (isIpv4 && socket.hasJoinedIpv4()))
|
||||
// Contrary to MdnsUtils.isNetworkMatched, only send packets targeting
|
||||
// the null network to interfaces that have the null network (tethering
|
||||
// downstream interfaces).
|
||||
@@ -237,6 +241,19 @@ public class MdnsMultinetworkSocketClient implements MdnsSocketClientBase {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isIpv6OnlyNetworks(
|
||||
@NonNull ArrayMap<MdnsInterfaceSocket, SocketKey> activeSockets,
|
||||
@Nullable Network targetNetwork) {
|
||||
for (int i = 0; i < activeSockets.size(); i++) {
|
||||
final MdnsInterfaceSocket socket = activeSockets.keyAt(i);
|
||||
final Network network = activeSockets.valueAt(i).getNetwork();
|
||||
if (Objects.equals(network, targetNetwork) && socket.hasJoinedIpv4()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void processResponsePacket(byte[] recvbuf, int length, @NonNull SocketKey socketKey) {
|
||||
int packetNumber = ++mReceivedPacketNumber;
|
||||
|
||||
@@ -259,21 +276,38 @@ public class MdnsMultinetworkSocketClient implements MdnsSocketClientBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a mDNS request packet via given network that asks for multicast response. Null network
|
||||
* means sending packet via all networks.
|
||||
* Send a mDNS request packet via given network that asks for multicast response.
|
||||
*
|
||||
* <p>The socket client may use a null network to identify some or all interfaces, in which case
|
||||
* passing null sends the packet to these.
|
||||
*/
|
||||
public void sendPacketRequestingMulticastResponse(@NonNull DatagramPacket packet,
|
||||
@Nullable Network network, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
mHandler.post(() -> sendMdnsPacket(packet, network, onlyUseIpv6OnIpv6OnlyNetworks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
|
||||
mHandler.post(() -> sendMdnsPacket(packet, network));
|
||||
public void sendPacketRequestingMulticastResponse(
|
||||
@NonNull DatagramPacket packet, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
sendPacketRequestingMulticastResponse(
|
||||
packet, null /* network */, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a mDNS request packet via given network that asks for unicast response. Null network
|
||||
* means sending packet via all networks.
|
||||
* Send a mDNS request packet via given network that asks for unicast response.
|
||||
*
|
||||
* <p>The socket client may use a null network to identify some or all interfaces, in which case
|
||||
* passing null sends the packet to these.
|
||||
*/
|
||||
public void sendPacketRequestingUnicastResponse(@NonNull DatagramPacket packet,
|
||||
@Nullable Network network, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
mHandler.post(() -> sendMdnsPacket(packet, network, onlyUseIpv6OnIpv6OnlyNetworks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
|
||||
// TODO: Separate unicast packet.
|
||||
mHandler.post(() -> sendMdnsPacket(packet, network));
|
||||
public void sendPacketRequestingUnicastResponse(
|
||||
@NonNull DatagramPacket packet, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
sendPacketRequestingUnicastResponse(
|
||||
packet, null /* network */, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
}
|
||||
@@ -44,10 +44,13 @@ public class MdnsSearchOptions implements Parcelable {
|
||||
new Parcelable.Creator<MdnsSearchOptions>() {
|
||||
@Override
|
||||
public MdnsSearchOptions createFromParcel(Parcel source) {
|
||||
return new MdnsSearchOptions(source.createStringArrayList(),
|
||||
source.readBoolean(), source.readBoolean(),
|
||||
return new MdnsSearchOptions(
|
||||
source.createStringArrayList(),
|
||||
source.readBoolean(),
|
||||
source.readBoolean(),
|
||||
source.readParcelable(null),
|
||||
source.readString());
|
||||
source.readString(),
|
||||
(source.dataAvail() > 0) ? source.readBoolean() : false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,18 +64,25 @@ public class MdnsSearchOptions implements Parcelable {
|
||||
private final String resolveInstanceName;
|
||||
|
||||
private final boolean isPassiveMode;
|
||||
private final boolean onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
private final boolean removeExpiredService;
|
||||
// The target network for searching. Null network means search on all possible interfaces.
|
||||
@Nullable private final Network mNetwork;
|
||||
|
||||
/** Parcelable constructs for a {@link MdnsSearchOptions}. */
|
||||
MdnsSearchOptions(List<String> subtypes, boolean isPassiveMode, boolean removeExpiredService,
|
||||
@Nullable Network network, @Nullable String resolveInstanceName) {
|
||||
MdnsSearchOptions(
|
||||
List<String> subtypes,
|
||||
boolean isPassiveMode,
|
||||
boolean removeExpiredService,
|
||||
@Nullable Network network,
|
||||
@Nullable String resolveInstanceName,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
this.subtypes = new ArrayList<>();
|
||||
if (subtypes != null) {
|
||||
this.subtypes.addAll(subtypes);
|
||||
}
|
||||
this.isPassiveMode = isPassiveMode;
|
||||
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
this.removeExpiredService = removeExpiredService;
|
||||
mNetwork = network;
|
||||
this.resolveInstanceName = resolveInstanceName;
|
||||
@@ -104,6 +114,14 @@ public class MdnsSearchOptions implements Parcelable {
|
||||
return isPassiveMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if only the IPv4 mDNS host should be queried on network that supports
|
||||
* both IPv6 as well as IPv4. On an IPv6-only network, this is ignored.
|
||||
*/
|
||||
public boolean onlyUseIpv6OnIpv6OnlyNetworks() {
|
||||
return onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if service will be removed after its TTL expires. */
|
||||
public boolean removeExpiredService() {
|
||||
return removeExpiredService;
|
||||
@@ -140,12 +158,14 @@ public class MdnsSearchOptions implements Parcelable {
|
||||
out.writeBoolean(removeExpiredService);
|
||||
out.writeParcelable(mNetwork, 0);
|
||||
out.writeString(resolveInstanceName);
|
||||
out.writeBoolean(onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
|
||||
/** A builder to create {@link MdnsSearchOptions}. */
|
||||
public static final class Builder {
|
||||
private final Set<String> subtypes;
|
||||
private boolean isPassiveMode = true;
|
||||
private boolean onlyUseIpv6OnIpv6OnlyNetworks = false;
|
||||
private boolean removeExpiredService;
|
||||
private Network mNetwork;
|
||||
private String resolveInstanceName;
|
||||
@@ -189,6 +209,15 @@ public class MdnsSearchOptions implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if only the IPv4 mDNS host should be queried on a network that is both IPv4 & IPv6.
|
||||
* On an IPv6-only network, this is ignored.
|
||||
*/
|
||||
public Builder setOnlyUseIpv6OnIpv6OnlyNetworks(boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the service should be removed after TTL.
|
||||
*
|
||||
@@ -223,8 +252,13 @@ public class MdnsSearchOptions implements Parcelable {
|
||||
|
||||
/** Builds a {@link MdnsSearchOptions} with the arguments supplied to this builder. */
|
||||
public MdnsSearchOptions build() {
|
||||
return new MdnsSearchOptions(new ArrayList<>(subtypes), isPassiveMode,
|
||||
removeExpiredService, mNetwork, resolveInstanceName);
|
||||
return new MdnsSearchOptions(
|
||||
new ArrayList<>(subtypes),
|
||||
isPassiveMode,
|
||||
removeExpiredService,
|
||||
mNetwork,
|
||||
resolveInstanceName,
|
||||
onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,6 +198,7 @@ public class MdnsServiceTypeClient {
|
||||
final QueryTaskConfig taskConfig = new QueryTaskConfig(
|
||||
searchOptions.getSubtypes(),
|
||||
searchOptions.isPassiveMode(),
|
||||
searchOptions.onlyUseIpv6OnIpv6OnlyNetworks(),
|
||||
currentSessionId,
|
||||
socketKey);
|
||||
if (hadReply) {
|
||||
@@ -220,7 +221,7 @@ public class MdnsServiceTypeClient {
|
||||
final boolean matchesInstanceName = options.getResolveInstanceName() == null
|
||||
// DNS is case-insensitive, so ignore case in the comparison
|
||||
|| MdnsUtils.equalsIgnoreDnsCase(options.getResolveInstanceName(),
|
||||
response.getServiceInstanceName());
|
||||
response.getServiceInstanceName());
|
||||
|
||||
// If discovery is requiring some subtypes, the response must have one that matches a
|
||||
// requested one.
|
||||
@@ -427,6 +428,7 @@ public class MdnsServiceTypeClient {
|
||||
private final boolean alwaysAskForUnicastResponse =
|
||||
MdnsConfigs.alwaysAskForUnicastResponseInEachBurst();
|
||||
private final boolean usePassiveMode;
|
||||
private final boolean onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
private final long sessionId;
|
||||
@VisibleForTesting
|
||||
int transactionId;
|
||||
@@ -439,9 +441,13 @@ public class MdnsServiceTypeClient {
|
||||
private boolean isFirstBurst;
|
||||
@NonNull private final SocketKey socketKey;
|
||||
|
||||
QueryTaskConfig(@NonNull Collection<String> subtypes, boolean usePassiveMode,
|
||||
long sessionId, @NonNull SocketKey socketKey) {
|
||||
QueryTaskConfig(@NonNull Collection<String> subtypes,
|
||||
boolean usePassiveMode,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks,
|
||||
long sessionId,
|
||||
@Nullable SocketKey socketKey) {
|
||||
this.usePassiveMode = usePassiveMode;
|
||||
this.onlyUseIpv6OnIpv6OnlyNetworks = onlyUseIpv6OnIpv6OnlyNetworks;
|
||||
this.subtypes = new ArrayList<>(subtypes);
|
||||
this.queriesPerBurst = QUERIES_PER_BURST;
|
||||
this.burstCounter = 0;
|
||||
@@ -559,6 +565,7 @@ public class MdnsServiceTypeClient {
|
||||
config.expectUnicastResponse,
|
||||
config.transactionId,
|
||||
config.socketKey.getNetwork(),
|
||||
config.onlyUseIpv6OnIpv6OnlyNetworks,
|
||||
sendDiscoveryQueries,
|
||||
servicesToResolve,
|
||||
clock)
|
||||
|
||||
@@ -93,6 +93,10 @@ public class MdnsSocket {
|
||||
}
|
||||
for (NetworkInterfaceWrapper networkInterface : networkInterfaces) {
|
||||
multicastSocket.joinGroup(multicastAddress, networkInterface.getNetworkInterface());
|
||||
if (!isOnIPv6OnlyNetwork) {
|
||||
multicastSocket.joinGroup(
|
||||
MULTICAST_IPV6_ADDRESS, networkInterface.getNetworkInterface());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +109,10 @@ public class MdnsSocket {
|
||||
}
|
||||
for (NetworkInterfaceWrapper networkInterface : networkInterfaces) {
|
||||
multicastSocket.leaveGroup(multicastAddress, networkInterface.getNetworkInterface());
|
||||
if (!isOnIPv6OnlyNetwork) {
|
||||
multicastSocket.leaveGroup(
|
||||
MULTICAST_IPV6_ADDRESS, networkInterface.getNetworkInterface());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ import com.android.server.connectivity.mdns.util.MdnsLogger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -194,38 +197,22 @@ public class MdnsSocketClient implements MdnsSocketClientBase {
|
||||
}
|
||||
}
|
||||
|
||||
/** Sends a mDNS request packet that asks for multicast response. */
|
||||
public void sendMulticastPacket(@NonNull DatagramPacket packet) {
|
||||
sendMdnsPacket(packet, multicastPacketQueue);
|
||||
@Override
|
||||
public void sendPacketRequestingMulticastResponse(@NonNull DatagramPacket packet,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
sendMdnsPacket(packet, multicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
|
||||
/** Sends a mDNS request packet that asks for unicast response. */
|
||||
public void sendUnicastPacket(DatagramPacket packet) {
|
||||
@Override
|
||||
public void sendPacketRequestingUnicastResponse(@NonNull DatagramPacket packet,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
if (useSeparateSocketForUnicast) {
|
||||
sendMdnsPacket(packet, unicastPacketQueue);
|
||||
sendMdnsPacket(packet, unicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
} else {
|
||||
sendMdnsPacket(packet, multicastPacketQueue);
|
||||
sendMdnsPacket(packet, multicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
|
||||
if (network != null) {
|
||||
throw new IllegalArgumentException("This socket client does not support sending to "
|
||||
+ "specific networks");
|
||||
}
|
||||
sendMulticastPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network) {
|
||||
if (network != null) {
|
||||
throw new IllegalArgumentException("This socket client does not support sending to "
|
||||
+ "specific networks");
|
||||
}
|
||||
sendUnicastPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNetworkRequested(
|
||||
@NonNull MdnsServiceBrowserListener listener,
|
||||
@@ -243,11 +230,25 @@ public class MdnsSocketClient implements MdnsSocketClientBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void sendMdnsPacket(DatagramPacket packet, Queue<DatagramPacket> packetQueueToUse) {
|
||||
private void sendMdnsPacket(DatagramPacket packet, Queue<DatagramPacket> packetQueueToUse,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
if (shouldStopSocketLoop && !MdnsConfigs.allowAddMdnsPacketAfterDiscoveryStops()) {
|
||||
LOGGER.w("sendMdnsPacket() is called after discovery already stopped");
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean isIpv4 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
|
||||
instanceof Inet4Address;
|
||||
final boolean isIpv6 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
|
||||
instanceof Inet6Address;
|
||||
final boolean ipv6Only = multicastSocket != null && multicastSocket.isOnIPv6OnlyNetwork();
|
||||
if (isIpv4 && ipv6Only) {
|
||||
return;
|
||||
}
|
||||
if (isIpv6 && !ipv6Only && onlyUseIpv6OnIpv6OnlyNetworks) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (packetQueueToUse) {
|
||||
while (packetQueueToUse.size() >= MdnsConfigs.mdnsPacketQueueMaxSize()) {
|
||||
packetQueueToUse.remove();
|
||||
@@ -535,8 +536,4 @@ public class MdnsSocketClient implements MdnsSocketClientBase {
|
||||
}
|
||||
packets.clear();
|
||||
}
|
||||
|
||||
public boolean isOnIPv6OnlyNetwork() {
|
||||
return multicastSocket != null && multicastSocket.isOnIPv6OnlyNetwork();
|
||||
}
|
||||
}
|
||||
@@ -41,19 +41,15 @@ public interface MdnsSocketClientBase {
|
||||
|
||||
/**
|
||||
* Send a mDNS request packet via given network that asks for multicast response.
|
||||
*
|
||||
* <p>The socket client may use a null network to identify some or all interfaces, in which case
|
||||
* passing null sends the packet to these.
|
||||
*/
|
||||
void sendMulticastPacket(@NonNull DatagramPacket packet, @Nullable Network network);
|
||||
void sendPacketRequestingMulticastResponse(@NonNull DatagramPacket packet,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
|
||||
/**
|
||||
* Send a mDNS request packet via given network that asks for unicast response.
|
||||
*
|
||||
* <p>The socket client may use a null network to identify some or all interfaces, in which case
|
||||
* passing null sends the packet to these.
|
||||
*/
|
||||
void sendUnicastPacket(@NonNull DatagramPacket packet, @Nullable Network network);
|
||||
void sendPacketRequestingUnicastResponse(@NonNull DatagramPacket packet,
|
||||
boolean onlyUseIpv6OnIpv6OnlyNetworks);
|
||||
|
||||
/*** Notify that the given network is requested for mdns discovery / resolution */
|
||||
void notifyNetworkRequested(@NonNull MdnsServiceBrowserListener listener,
|
||||
|
||||
@@ -138,18 +138,38 @@ public class MdnsMultinetworkSocketClientTest {
|
||||
verify(mSocketCreationCallback).onSocketCreated(tetherSocketKey2);
|
||||
|
||||
// Send packet to IPv4 with target network and verify sending has been called.
|
||||
mSocketClient.sendMulticastPacket(ipv4Packet, mNetwork);
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, mNetwork,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
verify(mSocket).send(ipv4Packet);
|
||||
verify(tetherIfaceSock1, never()).send(any());
|
||||
verify(tetherIfaceSock2, never()).send(any());
|
||||
|
||||
// Send packet to IPv4 with onlyUseIpv6OnIpv6OnlyNetworks = true, the packet will be sent.
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, mNetwork,
|
||||
true /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
verify(mSocket, times(2)).send(ipv4Packet);
|
||||
verify(tetherIfaceSock1, never()).send(any());
|
||||
verify(tetherIfaceSock2, never()).send(any());
|
||||
|
||||
// Send packet to IPv6 without target network and verify sending has been called.
|
||||
mSocketClient.sendMulticastPacket(ipv6Packet, null);
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv6Packet, null,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
verify(mSocket, never()).send(ipv6Packet);
|
||||
verify(tetherIfaceSock1).send(ipv6Packet);
|
||||
verify(tetherIfaceSock2).send(ipv6Packet);
|
||||
|
||||
// Send packet to IPv6 with onlyUseIpv6OnIpv6OnlyNetworks = true, the packet will not be
|
||||
// sent. Therefore, the tetherIfaceSock1.send() and tetherIfaceSock2.send() are still be
|
||||
// called once.
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv6Packet, null,
|
||||
true /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
verify(mSocket, never()).send(ipv6Packet);
|
||||
verify(tetherIfaceSock1, times(1)).send(ipv6Packet);
|
||||
verify(tetherIfaceSock2, times(1)).send(ipv6Packet);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -230,7 +250,8 @@ public class MdnsMultinetworkSocketClientTest {
|
||||
verify(mSocketCreationCallback).onSocketCreated(socketKey3);
|
||||
|
||||
// Send IPv4 packet on the non-null Network and verify sending has been called.
|
||||
mSocketClient.sendMulticastPacket(ipv4Packet, mNetwork);
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, mNetwork,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
verify(mSocket).send(ipv4Packet);
|
||||
verify(socket2, never()).send(any());
|
||||
@@ -258,7 +279,8 @@ public class MdnsMultinetworkSocketClientTest {
|
||||
verify(socketCreationCb2).onSocketCreated(socketKey3);
|
||||
|
||||
// Send IPv4 packet to null network and verify sending to the 2 tethered interface sockets.
|
||||
mSocketClient.sendMulticastPacket(ipv4Packet, null);
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, null,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
// ipv4Packet still sent only once on mSocket: times(1) matches the packet sent earlier on
|
||||
// mNetwork
|
||||
@@ -271,7 +293,8 @@ public class MdnsMultinetworkSocketClientTest {
|
||||
verify(mProvider, timeout(DEFAULT_TIMEOUT)).unrequestSocket(callback2);
|
||||
|
||||
// Send IPv4 packet again and verify it's still sent a second time
|
||||
mSocketClient.sendMulticastPacket(ipv4Packet, null);
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, null,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
verify(socket2, times(2)).send(ipv4Packet);
|
||||
verify(socket3, times(2)).send(ipv4Packet);
|
||||
@@ -281,7 +304,8 @@ public class MdnsMultinetworkSocketClientTest {
|
||||
verify(mProvider, timeout(DEFAULT_TIMEOUT)).unrequestSocket(callback);
|
||||
|
||||
// Send IPv4 packet and verify no more sending.
|
||||
mSocketClient.sendMulticastPacket(ipv4Packet, null);
|
||||
mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, null,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
|
||||
verify(mSocket, times(1)).send(ipv4Packet);
|
||||
verify(socket2, times(2)).send(ipv4Packet);
|
||||
|
||||
@@ -327,7 +327,8 @@ public class MdnsServiceTypeClientTests {
|
||||
MdnsSearchOptions searchOptions =
|
||||
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
|
||||
QueryTaskConfig config = new QueryTaskConfig(
|
||||
searchOptions.getSubtypes(), searchOptions.isPassiveMode(), 1, socketKey);
|
||||
searchOptions.getSubtypes(), searchOptions.isPassiveMode(),
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */, 1, socketKey);
|
||||
|
||||
// This is the first query. We will ask for unicast response.
|
||||
assertTrue(config.expectUnicastResponse);
|
||||
@@ -356,7 +357,8 @@ public class MdnsServiceTypeClientTests {
|
||||
MdnsSearchOptions searchOptions =
|
||||
MdnsSearchOptions.newBuilder().addSubtype("12345").setIsPassiveMode(false).build();
|
||||
QueryTaskConfig config = new QueryTaskConfig(
|
||||
searchOptions.getSubtypes(), searchOptions.isPassiveMode(), 1, socketKey);
|
||||
searchOptions.getSubtypes(), searchOptions.isPassiveMode(),
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */, 1, socketKey);
|
||||
|
||||
// This is the first query. We will ask for unicast response.
|
||||
assertTrue(config.expectUnicastResponse);
|
||||
@@ -928,16 +930,16 @@ public class MdnsServiceTypeClientTests {
|
||||
ArgumentCaptor.forClass(DatagramPacket.class);
|
||||
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
|
||||
// Send twice for IPv4 and IPv6
|
||||
inOrder.verify(mockSocketClient, times(2)).sendUnicastPacket(srvTxtQueryCaptor.capture(),
|
||||
eq(mockNetwork));
|
||||
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
|
||||
srvTxtQueryCaptor.capture(),
|
||||
eq(mockNetwork), eq(false));
|
||||
|
||||
final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse(
|
||||
new MdnsPacketReader(srvTxtQueryCaptor.getValue()));
|
||||
|
||||
final String[] serviceName = getTestServiceName(instanceName);
|
||||
assertFalse(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_PTR));
|
||||
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_SRV, serviceName));
|
||||
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_TXT, serviceName));
|
||||
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_ANY, serviceName));
|
||||
|
||||
// Process a response with SRV+TXT
|
||||
final MdnsPacket srvTxtResponse = new MdnsPacket(
|
||||
@@ -959,8 +961,9 @@ public class MdnsServiceTypeClientTests {
|
||||
final ArgumentCaptor<DatagramPacket> addressQueryCaptor =
|
||||
ArgumentCaptor.forClass(DatagramPacket.class);
|
||||
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
|
||||
inOrder.verify(mockSocketClient, times(2)).sendMulticastPacket(addressQueryCaptor.capture(),
|
||||
eq(mockNetwork));
|
||||
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
|
||||
addressQueryCaptor.capture(),
|
||||
eq(mockNetwork), eq(false));
|
||||
|
||||
final MdnsPacket addressQueryPacket = MdnsPacket.parse(
|
||||
new MdnsPacketReader(addressQueryCaptor.getValue()));
|
||||
@@ -1018,15 +1021,15 @@ public class MdnsServiceTypeClientTests {
|
||||
ArgumentCaptor.forClass(DatagramPacket.class);
|
||||
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
|
||||
// Send twice for IPv4 and IPv6
|
||||
inOrder.verify(mockSocketClient, times(2)).sendUnicastPacket(srvTxtQueryCaptor.capture(),
|
||||
eq(mockNetwork));
|
||||
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
|
||||
srvTxtQueryCaptor.capture(),
|
||||
eq(mockNetwork), eq(false));
|
||||
|
||||
final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse(
|
||||
new MdnsPacketReader(srvTxtQueryCaptor.getValue()));
|
||||
|
||||
final String[] serviceName = getTestServiceName(instanceName);
|
||||
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_SRV, serviceName));
|
||||
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_TXT, serviceName));
|
||||
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_ANY, serviceName));
|
||||
|
||||
// Process a response with all records
|
||||
final MdnsPacket srvTxtResponse = new MdnsPacket(
|
||||
@@ -1064,13 +1067,13 @@ public class MdnsServiceTypeClientTests {
|
||||
final ArgumentCaptor<DatagramPacket> renewalQueryCaptor =
|
||||
ArgumentCaptor.forClass(DatagramPacket.class);
|
||||
// Second and later sends are sent as "expect multicast response" queries
|
||||
inOrder.verify(mockSocketClient, times(2)).sendMulticastPacket(renewalQueryCaptor.capture(),
|
||||
eq(mockNetwork));
|
||||
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
|
||||
renewalQueryCaptor.capture(),
|
||||
eq(mockNetwork), eq(false));
|
||||
inOrder.verify(mockListenerOne).onDiscoveryQuerySent(any(), anyInt());
|
||||
final MdnsPacket renewalPacket = MdnsPacket.parse(
|
||||
new MdnsPacketReader(renewalQueryCaptor.getValue()));
|
||||
assertTrue(hasQuestion(renewalPacket, MdnsRecord.TYPE_SRV, serviceName));
|
||||
assertTrue(hasQuestion(renewalPacket, MdnsRecord.TYPE_TXT, serviceName));
|
||||
assertTrue(hasQuestion(renewalPacket, MdnsRecord.TYPE_ANY, serviceName));
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
|
||||
long updatedReceiptTime = TEST_ELAPSED_REALTIME + TEST_TTL;
|
||||
@@ -1328,18 +1331,18 @@ public class MdnsServiceTypeClientTests {
|
||||
assertEquals(currentThreadExecutor.getAndClearLastScheduledDelayInMs(), timeInMs);
|
||||
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
|
||||
if (expectsUnicastResponse) {
|
||||
verify(mockSocketClient).sendUnicastPacket(
|
||||
expectedIPv4Packets[index], mockNetwork);
|
||||
verify(mockSocketClient).sendPacketRequestingUnicastResponse(
|
||||
expectedIPv4Packets[index], mockNetwork, false);
|
||||
if (multipleSocketDiscovery) {
|
||||
verify(mockSocketClient).sendUnicastPacket(
|
||||
expectedIPv6Packets[index], mockNetwork);
|
||||
verify(mockSocketClient).sendPacketRequestingUnicastResponse(
|
||||
expectedIPv6Packets[index], mockNetwork, false);
|
||||
}
|
||||
} else {
|
||||
verify(mockSocketClient).sendMulticastPacket(
|
||||
expectedIPv4Packets[index], mockNetwork);
|
||||
verify(mockSocketClient).sendPacketRequestingMulticastResponse(
|
||||
expectedIPv4Packets[index], mockNetwork, false);
|
||||
if (multipleSocketDiscovery) {
|
||||
verify(mockSocketClient).sendMulticastPacket(
|
||||
expectedIPv6Packets[index], mockNetwork);
|
||||
verify(mockSocketClient).sendPacketRequestingMulticastResponse(
|
||||
expectedIPv6Packets[index], mockNetwork, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.mockito.invocation.InvocationOnMock;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -221,15 +222,17 @@ public class MdnsSocketClientTests {
|
||||
assertTrue(unicastReceiverThread.isAlive());
|
||||
|
||||
// Sends a packet.
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0, 5);
|
||||
mdnsClient.sendMulticastPacket(packet);
|
||||
DatagramPacket packet = getTestDatagramPacket();
|
||||
mdnsClient.sendPacketRequestingMulticastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
// mockMulticastSocket.send() will be called on another thread. If we verify it immediately,
|
||||
// it may not be called yet. So timeout is added.
|
||||
verify(mockMulticastSocket, timeout(TIMEOUT).times(1)).send(packet);
|
||||
verify(mockUnicastSocket, timeout(TIMEOUT).times(0)).send(packet);
|
||||
|
||||
// Verify the packet is sent by the unicast socket.
|
||||
mdnsClient.sendUnicastPacket(packet);
|
||||
mdnsClient.sendPacketRequestingUnicastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
verify(mockMulticastSocket, timeout(TIMEOUT).times(1)).send(packet);
|
||||
verify(mockUnicastSocket, timeout(TIMEOUT).times(1)).send(packet);
|
||||
|
||||
@@ -272,15 +275,17 @@ public class MdnsSocketClientTests {
|
||||
assertNull(unicastReceiverThread);
|
||||
|
||||
// Sends a packet.
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0, 5);
|
||||
mdnsClient.sendMulticastPacket(packet);
|
||||
DatagramPacket packet = getTestDatagramPacket();
|
||||
mdnsClient.sendPacketRequestingMulticastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
// mockMulticastSocket.send() will be called on another thread. If we verify it immediately,
|
||||
// it may not be called yet. So timeout is added.
|
||||
verify(mockMulticastSocket, timeout(TIMEOUT).times(1)).send(packet);
|
||||
verify(mockUnicastSocket, timeout(TIMEOUT).times(0)).send(packet);
|
||||
|
||||
// Verify the packet is sent by the multicast socket as well.
|
||||
mdnsClient.sendUnicastPacket(packet);
|
||||
mdnsClient.sendPacketRequestingUnicastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
verify(mockMulticastSocket, timeout(TIMEOUT).times(2)).send(packet);
|
||||
verify(mockUnicastSocket, timeout(TIMEOUT).times(0)).send(packet);
|
||||
|
||||
@@ -332,7 +337,8 @@ public class MdnsSocketClientTests {
|
||||
public void testStopDiscovery_queueIsCleared() throws IOException {
|
||||
mdnsClient.startDiscovery();
|
||||
mdnsClient.stopDiscovery();
|
||||
mdnsClient.sendMulticastPacket(new DatagramPacket(buf, 0, 5));
|
||||
mdnsClient.sendPacketRequestingMulticastResponse(getTestDatagramPacket(),
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
|
||||
synchronized (mdnsClient.multicastPacketQueue) {
|
||||
assertTrue(mdnsClient.multicastPacketQueue.isEmpty());
|
||||
@@ -343,7 +349,8 @@ public class MdnsSocketClientTests {
|
||||
public void testSendPacket_afterDiscoveryStops() throws IOException {
|
||||
mdnsClient.startDiscovery();
|
||||
mdnsClient.stopDiscovery();
|
||||
mdnsClient.sendMulticastPacket(new DatagramPacket(buf, 0, 5));
|
||||
mdnsClient.sendPacketRequestingMulticastResponse(getTestDatagramPacket(),
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
|
||||
synchronized (mdnsClient.multicastPacketQueue) {
|
||||
assertTrue(mdnsClient.multicastPacketQueue.isEmpty());
|
||||
@@ -356,7 +363,8 @@ public class MdnsSocketClientTests {
|
||||
//MdnsConfigsFlagsImpl.mdnsPacketQueueMaxSize.override(2L);
|
||||
mdnsClient.startDiscovery();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mdnsClient.sendMulticastPacket(new DatagramPacket(buf, 0, 5));
|
||||
mdnsClient.sendPacketRequestingMulticastResponse(getTestDatagramPacket(),
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
}
|
||||
|
||||
synchronized (mdnsClient.multicastPacketQueue) {
|
||||
@@ -452,9 +460,11 @@ public class MdnsSocketClientTests {
|
||||
enableUnicastResponse.set(true);
|
||||
|
||||
mdnsClient.startDiscovery();
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0, 5);
|
||||
mdnsClient.sendUnicastPacket(packet);
|
||||
mdnsClient.sendMulticastPacket(packet);
|
||||
DatagramPacket packet = getTestDatagramPacket();
|
||||
mdnsClient.sendPacketRequestingUnicastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
mdnsClient.sendPacketRequestingMulticastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
|
||||
// Wait for the timer to be triggered.
|
||||
Thread.sleep(MdnsConfigs.checkMulticastResponseIntervalMs() * 2);
|
||||
@@ -484,8 +494,10 @@ public class MdnsSocketClientTests {
|
||||
assertFalse(mdnsClient.receivedUnicastResponse);
|
||||
assertFalse(mdnsClient.cannotReceiveMulticastResponse.get());
|
||||
|
||||
mdnsClient.sendUnicastPacket(packet);
|
||||
mdnsClient.sendMulticastPacket(packet);
|
||||
mdnsClient.sendPacketRequestingUnicastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
mdnsClient.sendPacketRequestingMulticastResponse(packet,
|
||||
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
|
||||
Thread.sleep(MdnsConfigs.checkMulticastResponseIntervalMs() * 2);
|
||||
|
||||
// Verify cannotReceiveMulticastResponse is not set the true because we didn't receive the
|
||||
@@ -540,4 +552,9 @@ public class MdnsSocketClientTests {
|
||||
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
|
||||
.onResponseReceived(any(), argThat(key -> key.getInterfaceIndex() == -1));
|
||||
}
|
||||
|
||||
private DatagramPacket getTestDatagramPacket() {
|
||||
return new DatagramPacket(buf, 0, 5,
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), 5353 /* port */));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user