Support multiple query packets
If the query with known answer feature is enabled and the
MdnsPacket is too large for a single DatagramPacket, it
will be split into multiple DatagramPackets.
Bug: 312657709
Test: atest FrameworksNetTests NsdManagerTest
Change-Id: I831fb6035cc0ad03078fbd3b9c550b56ddca07fb
diff --git a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
index e61555a..54943c7 100644
--- a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
+++ b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
@@ -84,6 +84,7 @@
private final byte[] packetCreationBuffer = new byte[1500]; // TODO: use interface MTU
@NonNull
private final List<MdnsResponse> existingServices;
+ private final boolean isQueryWithKnownAnswer;
EnqueueMdnsQueryCallable(
@NonNull MdnsSocketClientBase requestSender,
@@ -98,7 +99,8 @@
@NonNull MdnsUtils.Clock clock,
@NonNull SharedLog sharedLog,
@NonNull MdnsServiceTypeClient.Dependencies dependencies,
- @NonNull Collection<MdnsResponse> existingServices) {
+ @NonNull Collection<MdnsResponse> existingServices,
+ boolean isQueryWithKnownAnswer) {
weakRequestSender = new WeakReference<>(requestSender);
serviceTypeLabels = TextUtils.split(serviceType, "\\.");
this.subtypes = new ArrayList<>(subtypes);
@@ -112,6 +114,7 @@
this.sharedLog = sharedLog;
this.dependencies = dependencies;
this.existingServices = new ArrayList<>(existingServices);
+ this.isQueryWithKnownAnswer = isQueryWithKnownAnswer;
}
/**
@@ -226,27 +229,27 @@
private void sendPacket(MdnsSocketClientBase requestSender, InetSocketAddress address,
MdnsPacket mdnsPacket) throws IOException {
- final DatagramPacket packet = dependencies.getDatagramPacketFromMdnsPacket(
- packetCreationBuffer, mdnsPacket, address);
+ final List<DatagramPacket> packets = dependencies.getDatagramPacketsFromMdnsPacket(
+ packetCreationBuffer, mdnsPacket, address, isQueryWithKnownAnswer);
if (expectUnicastResponse) {
// MdnsMultinetworkSocketClient is only available on T+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& requestSender instanceof MdnsMultinetworkSocketClient) {
((MdnsMultinetworkSocketClient) requestSender).sendPacketRequestingUnicastResponse(
- packet, socketKey, onlyUseIpv6OnIpv6OnlyNetworks);
+ packets, socketKey, onlyUseIpv6OnIpv6OnlyNetworks);
} else {
requestSender.sendPacketRequestingUnicastResponse(
- packet, onlyUseIpv6OnIpv6OnlyNetworks);
+ packets, onlyUseIpv6OnIpv6OnlyNetworks);
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& requestSender instanceof MdnsMultinetworkSocketClient) {
((MdnsMultinetworkSocketClient) requestSender)
.sendPacketRequestingMulticastResponse(
- packet, socketKey, onlyUseIpv6OnIpv6OnlyNetworks);
+ packets, socketKey, onlyUseIpv6OnIpv6OnlyNetworks);
} else {
requestSender.sendPacketRequestingMulticastResponse(
- packet, onlyUseIpv6OnIpv6OnlyNetworks);
+ packets, onlyUseIpv6OnIpv6OnlyNetworks);
}
}
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
index 869ac9b..fcfb15f 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClient.java
@@ -27,6 +27,7 @@
import android.os.Handler;
import android.os.Looper;
import android.util.ArrayMap;
+import android.util.Log;
import com.android.net.module.util.SharedLog;
@@ -213,24 +214,30 @@
return true;
}
- private void sendMdnsPacket(@NonNull DatagramPacket packet, @NonNull SocketKey targetSocketKey,
- boolean onlyUseIpv6OnIpv6OnlyNetworks) {
+ private void sendMdnsPackets(@NonNull List<DatagramPacket> packets,
+ @NonNull SocketKey targetSocketKey, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
final MdnsInterfaceSocket socket = getTargetSocket(targetSocketKey);
if (socket == null) {
mSharedLog.e("No socket matches targetSocketKey=" + targetSocketKey);
return;
}
+ if (packets.isEmpty()) {
+ Log.wtf(TAG, "No mDns packets to send");
+ return;
+ }
- final boolean isIpv6 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
- instanceof Inet6Address;
- final boolean isIpv4 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
- instanceof Inet4Address;
+ final boolean isIpv6 = ((InetSocketAddress) packets.get(0).getSocketAddress())
+ .getAddress() instanceof Inet6Address;
+ final boolean isIpv4 = ((InetSocketAddress) packets.get(0).getSocketAddress())
+ .getAddress() instanceof Inet4Address;
final boolean shouldQueryIpv6 = !onlyUseIpv6OnIpv6OnlyNetworks || !socket.hasJoinedIpv4();
// Check ip capability and network before sending packet
if ((isIpv6 && socket.hasJoinedIpv6() && shouldQueryIpv6)
|| (isIpv4 && socket.hasJoinedIpv4())) {
try {
- socket.send(packet);
+ for (DatagramPacket packet : packets) {
+ socket.send(packet);
+ }
} catch (IOException e) {
mSharedLog.e("Failed to send a mDNS packet.", e);
}
@@ -259,34 +266,34 @@
}
/**
- * Send a mDNS request packet via given socket key that asks for multicast response.
+ * Send mDNS request packets via given socket key that asks for multicast response.
*/
- public void sendPacketRequestingMulticastResponse(@NonNull DatagramPacket packet,
+ public void sendPacketRequestingMulticastResponse(@NonNull List<DatagramPacket> packets,
@NonNull SocketKey socketKey, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
- mHandler.post(() -> sendMdnsPacket(packet, socketKey, onlyUseIpv6OnIpv6OnlyNetworks));
+ mHandler.post(() -> sendMdnsPackets(packets, socketKey, onlyUseIpv6OnIpv6OnlyNetworks));
}
@Override
public void sendPacketRequestingMulticastResponse(
- @NonNull DatagramPacket packet, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
+ @NonNull List<DatagramPacket> packets, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
throw new UnsupportedOperationException("This socket client need to specify the socket to"
+ "send packet");
}
/**
- * Send a mDNS request packet via given socket key that asks for unicast response.
+ * Send mDNS request packets via given socket key 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,
+ public void sendPacketRequestingUnicastResponse(@NonNull List<DatagramPacket> packets,
@NonNull SocketKey socketKey, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
- mHandler.post(() -> sendMdnsPacket(packet, socketKey, onlyUseIpv6OnIpv6OnlyNetworks));
+ mHandler.post(() -> sendMdnsPackets(packets, socketKey, onlyUseIpv6OnIpv6OnlyNetworks));
}
@Override
public void sendPacketRequestingUnicastResponse(
- @NonNull DatagramPacket packet, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
+ @NonNull List<DatagramPacket> packets, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
throw new UnsupportedOperationException("This socket client need to specify the socket to"
+ "send packet");
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index bfcd0b4..f0f3ffb 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
@@ -227,13 +227,22 @@
}
/**
- * Generate a DatagramPacket from given MdnsPacket and InetSocketAddress.
+ * Generate the DatagramPackets from given MdnsPacket and InetSocketAddress.
+ *
+ * <p> If the query with known answer feature is enabled and the MdnsPacket is too large for
+ * a single DatagramPacket, it will be split into multiple DatagramPackets.
*/
- public DatagramPacket getDatagramPacketFromMdnsPacket(@NonNull byte[] packetCreationBuffer,
- @NonNull MdnsPacket packet, @NonNull InetSocketAddress address) throws IOException {
- final byte[] queryBuffer =
- MdnsUtils.createRawDnsPacket(packetCreationBuffer, packet);
- return new DatagramPacket(queryBuffer, 0, queryBuffer.length, address);
+ public List<DatagramPacket> getDatagramPacketsFromMdnsPacket(
+ @NonNull byte[] packetCreationBuffer, @NonNull MdnsPacket packet,
+ @NonNull InetSocketAddress address, boolean isQueryWithKnownAnswer)
+ throws IOException {
+ if (isQueryWithKnownAnswer) {
+ return MdnsUtils.createQueryDatagramPackets(packetCreationBuffer, packet, address);
+ } else {
+ final byte[] queryBuffer =
+ MdnsUtils.createRawDnsPacket(packetCreationBuffer, packet);
+ return List.of(new DatagramPacket(queryBuffer, 0, queryBuffer.length, address));
+ }
}
}
@@ -742,7 +751,8 @@
clock,
sharedLog,
dependencies,
- existingServices)
+ existingServices,
+ featureFlags.isQueryWithKnownAnswerEnabled())
.call();
} catch (RuntimeException e) {
sharedLog.e(String.format("Failed to run EnqueueMdnsQueryCallable for subtype: %s",
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
index 7b71e43..9cfcba1 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClient.java
@@ -25,6 +25,7 @@
import android.net.wifi.WifiManager.MulticastLock;
import android.os.SystemClock;
import android.text.format.DateUtils;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.SharedLog;
@@ -206,18 +207,18 @@
}
@Override
- public void sendPacketRequestingMulticastResponse(@NonNull DatagramPacket packet,
+ public void sendPacketRequestingMulticastResponse(@NonNull List<DatagramPacket> packets,
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
- sendMdnsPacket(packet, multicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
+ sendMdnsPackets(packets, multicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
}
@Override
- public void sendPacketRequestingUnicastResponse(@NonNull DatagramPacket packet,
+ public void sendPacketRequestingUnicastResponse(@NonNull List<DatagramPacket> packets,
boolean onlyUseIpv6OnIpv6OnlyNetworks) {
if (useSeparateSocketForUnicast) {
- sendMdnsPacket(packet, unicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
+ sendMdnsPackets(packets, unicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
} else {
- sendMdnsPacket(packet, multicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
+ sendMdnsPackets(packets, multicastPacketQueue, onlyUseIpv6OnIpv6OnlyNetworks);
}
}
@@ -238,17 +239,21 @@
return false;
}
- private void sendMdnsPacket(DatagramPacket packet, Queue<DatagramPacket> packetQueueToUse,
- boolean onlyUseIpv6OnIpv6OnlyNetworks) {
+ private void sendMdnsPackets(List<DatagramPacket> packets,
+ Queue<DatagramPacket> packetQueueToUse, boolean onlyUseIpv6OnIpv6OnlyNetworks) {
if (shouldStopSocketLoop && !MdnsConfigs.allowAddMdnsPacketAfterDiscoveryStops()) {
sharedLog.w("sendMdnsPacket() is called after discovery already stopped");
return;
}
+ if (packets.isEmpty()) {
+ Log.wtf(TAG, "No mDns packets to send");
+ return;
+ }
- final boolean isIpv4 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
- instanceof Inet4Address;
- final boolean isIpv6 = ((InetSocketAddress) packet.getSocketAddress()).getAddress()
- instanceof Inet6Address;
+ final boolean isIpv4 = ((InetSocketAddress) packets.get(0).getSocketAddress())
+ .getAddress() instanceof Inet4Address;
+ final boolean isIpv6 = ((InetSocketAddress) packets.get(0).getSocketAddress())
+ .getAddress() instanceof Inet6Address;
final boolean ipv6Only = multicastSocket != null && multicastSocket.isOnIPv6OnlyNetwork();
if (isIpv4 && ipv6Only) {
return;
@@ -258,10 +263,11 @@
}
synchronized (packetQueueToUse) {
- while (packetQueueToUse.size() >= MdnsConfigs.mdnsPacketQueueMaxSize()) {
+ while ((packetQueueToUse.size() + packets.size())
+ > MdnsConfigs.mdnsPacketQueueMaxSize()) {
packetQueueToUse.remove();
}
- packetQueueToUse.add(packet);
+ packetQueueToUse.addAll(packets);
}
triggerSendThread();
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
index b6000f0..b1a543a 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketClientBase.java
@@ -23,6 +23,7 @@
import java.io.IOException;
import java.net.DatagramPacket;
+import java.util.List;
/**
* Base class for multicast socket client.
@@ -40,15 +41,15 @@
void setCallback(@Nullable Callback callback);
/**
- * Send a mDNS request packet via given network that asks for multicast response.
+ * Send mDNS request packets via given network that asks for multicast response.
*/
- void sendPacketRequestingMulticastResponse(@NonNull DatagramPacket packet,
+ void sendPacketRequestingMulticastResponse(@NonNull List<DatagramPacket> packets,
boolean onlyUseIpv6OnIpv6OnlyNetworks);
/**
- * Send a mDNS request packet via given network that asks for unicast response.
+ * Send mDNS request packets via given network that asks for unicast response.
*/
- void sendPacketRequestingUnicastResponse(@NonNull DatagramPacket packet,
+ void sendPacketRequestingUnicastResponse(@NonNull List<DatagramPacket> packets,
boolean onlyUseIpv6OnIpv6OnlyNetworks);
/*** Notify that the given network is requested for mdns discovery / resolution */
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
index 9474464..fb3d183 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
@@ -47,6 +48,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -55,6 +57,7 @@
import java.net.DatagramPacket;
import java.net.NetworkInterface;
import java.net.SocketException;
+import java.util.ArrayList;
import java.util.List;
@RunWith(DevSdkIgnoreRunner.class)
@@ -154,7 +157,7 @@
verify(mSocketCreationCallback).onSocketCreated(tetherSocketKey2);
// Send packet to IPv4 with mSocketKey and verify sending has been called.
- mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, mSocketKey,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv4Packet), mSocketKey,
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(mSocket).send(ipv4Packet);
@@ -162,7 +165,7 @@
verify(tetherIfaceSock2, never()).send(any());
// Send packet to IPv4 with onlyUseIpv6OnIpv6OnlyNetworks = true, the packet will be sent.
- mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, mSocketKey,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv4Packet), mSocketKey,
true /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(mSocket, times(2)).send(ipv4Packet);
@@ -170,7 +173,7 @@
verify(tetherIfaceSock2, never()).send(any());
// Send packet to IPv6 with tetherSocketKey1 and verify sending has been called.
- mSocketClient.sendPacketRequestingMulticastResponse(ipv6Packet, tetherSocketKey1,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv6Packet), tetherSocketKey1,
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(mSocket, never()).send(ipv6Packet);
@@ -180,7 +183,7 @@
// 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, tetherSocketKey1,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv6Packet), tetherSocketKey1,
true /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(mSocket, never()).send(ipv6Packet);
@@ -266,7 +269,7 @@
verify(mSocketCreationCallback).onSocketCreated(socketKey3);
// Send IPv4 packet on the mSocketKey and verify sending has been called.
- mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, mSocketKey,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv4Packet), mSocketKey,
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(mSocket).send(ipv4Packet);
@@ -295,7 +298,7 @@
verify(socketCreationCb2).onSocketCreated(socketKey3);
// Send IPv4 packet on socket2 and verify sending to the socket2 only.
- mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, socketKey2,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv4Packet), socketKey2,
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
// ipv4Packet still sent only once on mSocket: times(1) matches the packet sent earlier on
@@ -309,7 +312,7 @@
verify(mProvider, timeout(DEFAULT_TIMEOUT)).unrequestSocket(callback2);
// Send IPv4 packet again and verify it's still sent a second time
- mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, socketKey2,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv4Packet), socketKey2,
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(socket2, times(2)).send(ipv4Packet);
@@ -320,7 +323,7 @@
verify(mProvider, timeout(DEFAULT_TIMEOUT)).unrequestSocket(callback);
// Send IPv4 packet and verify no more sending.
- mSocketClient.sendPacketRequestingMulticastResponse(ipv4Packet, mSocketKey,
+ mSocketClient.sendPacketRequestingMulticastResponse(List.of(ipv4Packet), mSocketKey,
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
verify(mSocket, times(1)).send(ipv4Packet);
@@ -407,4 +410,31 @@
verify(creationCallback3).onSocketDestroyed(mSocketKey);
verify(creationCallback3, never()).onSocketDestroyed(socketKey2);
}
+
+ @Test
+ public void testSendPacketWithMultipleDatagramPacket() throws IOException {
+ final SocketCallback callback = expectSocketCallback();
+ final List<DatagramPacket> packets = new ArrayList<>();
+ for (int i = 0; i < 10; i++) {
+ packets.add(new DatagramPacket(new byte[10 + i] /* buff */, 0 /* offset */,
+ 10 + i /* length */, MdnsConstants.IPV4_SOCKET_ADDR));
+ }
+ doReturn(true).when(mSocket).hasJoinedIpv4();
+ doReturn(true).when(mSocket).hasJoinedIpv6();
+ doReturn(createEmptyNetworkInterface()).when(mSocket).getInterface();
+
+ // Notify socket created
+ callback.onSocketCreated(mSocketKey, mSocket, List.of());
+ verify(mSocketCreationCallback).onSocketCreated(mSocketKey);
+
+ // Send packets to IPv4 with mSocketKey then verify sending has been called and the
+ // sequence is correct.
+ mSocketClient.sendPacketRequestingMulticastResponse(packets, mSocketKey,
+ false /* onlyUseIpv6OnIpv6OnlyNetworks */);
+ HandlerUtils.waitForIdle(mHandler, DEFAULT_TIMEOUT);
+ InOrder inOrder = inOrder(mSocket);
+ for (int i = 0; i < 10; i++) {
+ inOrder.verify(mSocket).send(packets.get(i));
+ }
+ }
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
index 2eb9440..44fa55c 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceTypeClientTests.java
@@ -162,59 +162,59 @@
expectedIPv6Packets[i] = new DatagramPacket(buf, 0 /* offset */, 5 /* length */,
MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
}
- when(mockDeps.getDatagramPacketFromMdnsPacket(
- any(), any(MdnsPacket.class), eq(IPV4_ADDRESS)))
- .thenReturn(expectedIPv4Packets[0])
- .thenReturn(expectedIPv4Packets[1])
- .thenReturn(expectedIPv4Packets[2])
- .thenReturn(expectedIPv4Packets[3])
- .thenReturn(expectedIPv4Packets[4])
- .thenReturn(expectedIPv4Packets[5])
- .thenReturn(expectedIPv4Packets[6])
- .thenReturn(expectedIPv4Packets[7])
- .thenReturn(expectedIPv4Packets[8])
- .thenReturn(expectedIPv4Packets[9])
- .thenReturn(expectedIPv4Packets[10])
- .thenReturn(expectedIPv4Packets[11])
- .thenReturn(expectedIPv4Packets[12])
- .thenReturn(expectedIPv4Packets[13])
- .thenReturn(expectedIPv4Packets[14])
- .thenReturn(expectedIPv4Packets[15])
- .thenReturn(expectedIPv4Packets[16])
- .thenReturn(expectedIPv4Packets[17])
- .thenReturn(expectedIPv4Packets[18])
- .thenReturn(expectedIPv4Packets[19])
- .thenReturn(expectedIPv4Packets[20])
- .thenReturn(expectedIPv4Packets[21])
- .thenReturn(expectedIPv4Packets[22])
- .thenReturn(expectedIPv4Packets[23]);
+ when(mockDeps.getDatagramPacketsFromMdnsPacket(
+ any(), any(MdnsPacket.class), eq(IPV4_ADDRESS), anyBoolean()))
+ .thenReturn(List.of(expectedIPv4Packets[0]))
+ .thenReturn(List.of(expectedIPv4Packets[1]))
+ .thenReturn(List.of(expectedIPv4Packets[2]))
+ .thenReturn(List.of(expectedIPv4Packets[3]))
+ .thenReturn(List.of(expectedIPv4Packets[4]))
+ .thenReturn(List.of(expectedIPv4Packets[5]))
+ .thenReturn(List.of(expectedIPv4Packets[6]))
+ .thenReturn(List.of(expectedIPv4Packets[7]))
+ .thenReturn(List.of(expectedIPv4Packets[8]))
+ .thenReturn(List.of(expectedIPv4Packets[9]))
+ .thenReturn(List.of(expectedIPv4Packets[10]))
+ .thenReturn(List.of(expectedIPv4Packets[11]))
+ .thenReturn(List.of(expectedIPv4Packets[12]))
+ .thenReturn(List.of(expectedIPv4Packets[13]))
+ .thenReturn(List.of(expectedIPv4Packets[14]))
+ .thenReturn(List.of(expectedIPv4Packets[15]))
+ .thenReturn(List.of(expectedIPv4Packets[16]))
+ .thenReturn(List.of(expectedIPv4Packets[17]))
+ .thenReturn(List.of(expectedIPv4Packets[18]))
+ .thenReturn(List.of(expectedIPv4Packets[19]))
+ .thenReturn(List.of(expectedIPv4Packets[20]))
+ .thenReturn(List.of(expectedIPv4Packets[21]))
+ .thenReturn(List.of(expectedIPv4Packets[22]))
+ .thenReturn(List.of(expectedIPv4Packets[23]));
- when(mockDeps.getDatagramPacketFromMdnsPacket(
- any(), any(MdnsPacket.class), eq(IPV6_ADDRESS)))
- .thenReturn(expectedIPv6Packets[0])
- .thenReturn(expectedIPv6Packets[1])
- .thenReturn(expectedIPv6Packets[2])
- .thenReturn(expectedIPv6Packets[3])
- .thenReturn(expectedIPv6Packets[4])
- .thenReturn(expectedIPv6Packets[5])
- .thenReturn(expectedIPv6Packets[6])
- .thenReturn(expectedIPv6Packets[7])
- .thenReturn(expectedIPv6Packets[8])
- .thenReturn(expectedIPv6Packets[9])
- .thenReturn(expectedIPv6Packets[10])
- .thenReturn(expectedIPv6Packets[11])
- .thenReturn(expectedIPv6Packets[12])
- .thenReturn(expectedIPv6Packets[13])
- .thenReturn(expectedIPv6Packets[14])
- .thenReturn(expectedIPv6Packets[15])
- .thenReturn(expectedIPv6Packets[16])
- .thenReturn(expectedIPv6Packets[17])
- .thenReturn(expectedIPv6Packets[18])
- .thenReturn(expectedIPv6Packets[19])
- .thenReturn(expectedIPv6Packets[20])
- .thenReturn(expectedIPv6Packets[21])
- .thenReturn(expectedIPv6Packets[22])
- .thenReturn(expectedIPv6Packets[23]);
+ when(mockDeps.getDatagramPacketsFromMdnsPacket(
+ any(), any(MdnsPacket.class), eq(IPV6_ADDRESS), anyBoolean()))
+ .thenReturn(List.of(expectedIPv6Packets[0]))
+ .thenReturn(List.of(expectedIPv6Packets[1]))
+ .thenReturn(List.of(expectedIPv6Packets[2]))
+ .thenReturn(List.of(expectedIPv6Packets[3]))
+ .thenReturn(List.of(expectedIPv6Packets[4]))
+ .thenReturn(List.of(expectedIPv6Packets[5]))
+ .thenReturn(List.of(expectedIPv6Packets[6]))
+ .thenReturn(List.of(expectedIPv6Packets[7]))
+ .thenReturn(List.of(expectedIPv6Packets[8]))
+ .thenReturn(List.of(expectedIPv6Packets[9]))
+ .thenReturn(List.of(expectedIPv6Packets[10]))
+ .thenReturn(List.of(expectedIPv6Packets[11]))
+ .thenReturn(List.of(expectedIPv6Packets[12]))
+ .thenReturn(List.of(expectedIPv6Packets[13]))
+ .thenReturn(List.of(expectedIPv6Packets[14]))
+ .thenReturn(List.of(expectedIPv6Packets[15]))
+ .thenReturn(List.of(expectedIPv6Packets[16]))
+ .thenReturn(List.of(expectedIPv6Packets[17]))
+ .thenReturn(List.of(expectedIPv6Packets[18]))
+ .thenReturn(List.of(expectedIPv6Packets[19]))
+ .thenReturn(List.of(expectedIPv6Packets[20]))
+ .thenReturn(List.of(expectedIPv6Packets[21]))
+ .thenReturn(List.of(expectedIPv6Packets[22]))
+ .thenReturn(List.of(expectedIPv6Packets[23]));
thread = new HandlerThread("MdnsServiceTypeClientTests");
thread.start();
@@ -694,23 +694,23 @@
.addSubtype("subtype1").build();
final MdnsSearchOptions searchOptions2 = MdnsSearchOptions.newBuilder()
.addSubtype("subtype2").build();
- doCallRealMethod().when(mockDeps).getDatagramPacketFromMdnsPacket(
- any(), any(MdnsPacket.class), any(InetSocketAddress.class));
+ doCallRealMethod().when(mockDeps).getDatagramPacketsFromMdnsPacket(
+ any(), any(MdnsPacket.class), any(InetSocketAddress.class), anyBoolean());
startSendAndReceive(mockListenerOne, searchOptions1);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient, mockDeps);
// Verify the query asks for subtype1
- final ArgumentCaptor<DatagramPacket> subtype1QueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> subtype1QueryCaptor =
+ ArgumentCaptor.forClass(List.class);
// Send twice for IPv4 and IPv6
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
subtype1QueryCaptor.capture(),
eq(socketKey), eq(false));
final MdnsPacket subtype1Query = MdnsPacket.parse(
- new MdnsPacketReader(subtype1QueryCaptor.getValue()));
+ new MdnsPacketReader(subtype1QueryCaptor.getValue().get(0)));
assertEquals(2, subtype1Query.questions.size());
assertTrue(hasQuestion(subtype1Query, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
@@ -722,8 +722,8 @@
inOrder.verify(mockDeps).removeMessages(any(), eq(EVENT_START_QUERYTASK));
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
- final ArgumentCaptor<DatagramPacket> combinedSubtypesQueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> combinedSubtypesQueryCaptor =
+ ArgumentCaptor.forClass(List.class);
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
combinedSubtypesQueryCaptor.capture(),
eq(socketKey), eq(false));
@@ -731,7 +731,7 @@
inOrder.verify(mockDeps).sendMessageDelayed(any(), any(), anyLong());
final MdnsPacket combinedSubtypesQuery = MdnsPacket.parse(
- new MdnsPacketReader(combinedSubtypesQueryCaptor.getValue()));
+ new MdnsPacketReader(combinedSubtypesQueryCaptor.getValue().get(0)));
assertEquals(3, combinedSubtypesQuery.questions.size());
assertTrue(hasQuestion(combinedSubtypesQuery, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
@@ -747,15 +747,15 @@
dispatchMessage();
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
- final ArgumentCaptor<DatagramPacket> subtype2QueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> subtype2QueryCaptor =
+ ArgumentCaptor.forClass(List.class);
// Send twice for IPv4 and IPv6
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
subtype2QueryCaptor.capture(),
eq(socketKey), eq(false));
final MdnsPacket subtype2Query = MdnsPacket.parse(
- new MdnsPacketReader(subtype2QueryCaptor.getValue()));
+ new MdnsPacketReader(subtype2QueryCaptor.getValue().get(0)));
assertEquals(2, subtype2Query.questions.size());
assertTrue(hasQuestion(subtype2Query, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
@@ -1201,8 +1201,8 @@
final MdnsSearchOptions resolveOptions2 = MdnsSearchOptions.newBuilder()
.setResolveInstanceName(instanceName).build();
- doCallRealMethod().when(mockDeps).getDatagramPacketFromMdnsPacket(
- any(), any(MdnsPacket.class), any(InetSocketAddress.class));
+ doCallRealMethod().when(mockDeps).getDatagramPacketsFromMdnsPacket(
+ any(), any(MdnsPacket.class), any(InetSocketAddress.class), anyBoolean());
startSendAndReceive(mockListenerOne, resolveOptions1);
startSendAndReceive(mockListenerTwo, resolveOptions2);
@@ -1210,8 +1210,8 @@
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
// Verify a query for SRV/TXT was sent, but no PTR query
- final ArgumentCaptor<DatagramPacket> srvTxtQueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> srvTxtQueryCaptor =
+ ArgumentCaptor.forClass(List.class);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
// Send twice for IPv4 and IPv6
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
@@ -1223,7 +1223,7 @@
verify(mockListenerTwo).onDiscoveryQuerySent(any(), anyInt());
final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse(
- new MdnsPacketReader(srvTxtQueryCaptor.getValue()));
+ new MdnsPacketReader(srvTxtQueryCaptor.getValue().get(0)));
final String[] serviceName = getTestServiceName(instanceName);
assertEquals(1, srvTxtQueryPacket.questions.size());
@@ -1255,8 +1255,8 @@
// Expect a query for A/AAAA
dispatchMessage();
- final ArgumentCaptor<DatagramPacket> addressQueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> addressQueryCaptor =
+ ArgumentCaptor.forClass(List.class);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
addressQueryCaptor.capture(),
@@ -1266,7 +1266,7 @@
verify(mockListenerTwo, times(2)).onDiscoveryQuerySent(any(), anyInt());
final MdnsPacket addressQueryPacket = MdnsPacket.parse(
- new MdnsPacketReader(addressQueryCaptor.getValue()));
+ new MdnsPacketReader(addressQueryCaptor.getValue().get(0)));
assertEquals(2, addressQueryPacket.questions.size());
assertTrue(hasQuestion(addressQueryPacket, MdnsRecord.TYPE_A, hostname));
assertTrue(hasQuestion(addressQueryPacket, MdnsRecord.TYPE_AAAA, hostname));
@@ -1316,15 +1316,15 @@
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
.setResolveInstanceName(instanceName).build();
- doCallRealMethod().when(mockDeps).getDatagramPacketFromMdnsPacket(
- any(), any(MdnsPacket.class), any(InetSocketAddress.class));
+ doCallRealMethod().when(mockDeps).getDatagramPacketsFromMdnsPacket(
+ any(), any(MdnsPacket.class), any(InetSocketAddress.class), anyBoolean());
startSendAndReceive(mockListenerOne, resolveOptions);
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
// Get the query for SRV/TXT
- final ArgumentCaptor<DatagramPacket> srvTxtQueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> srvTxtQueryCaptor =
+ ArgumentCaptor.forClass(List.class);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
// Send twice for IPv4 and IPv6
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
@@ -1334,7 +1334,7 @@
assertNotNull(delayMessage);
final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse(
- new MdnsPacketReader(srvTxtQueryCaptor.getValue()));
+ new MdnsPacketReader(srvTxtQueryCaptor.getValue().get(0)));
final String[] serviceName = getTestServiceName(instanceName);
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_ANY, serviceName));
@@ -1378,8 +1378,8 @@
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
// Expect a renewal query
- final ArgumentCaptor<DatagramPacket> renewalQueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> renewalQueryCaptor =
+ ArgumentCaptor.forClass(List.class);
// Second and later sends are sent as "expect multicast response" queries
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
renewalQueryCaptor.capture(),
@@ -1388,7 +1388,7 @@
assertNotNull(delayMessage);
inOrder.verify(mockListenerOne).onDiscoveryQuerySent(any(), anyInt());
final MdnsPacket renewalPacket = MdnsPacket.parse(
- new MdnsPacketReader(renewalQueryCaptor.getValue()));
+ new MdnsPacketReader(renewalQueryCaptor.getValue().get(0)));
assertTrue(hasQuestion(renewalPacket, MdnsRecord.TYPE_ANY, serviceName));
inOrder.verifyNoMoreInteractions();
@@ -1937,14 +1937,14 @@
serviceCache,
MdnsFeatureFlags.newBuilder().setIsQueryWithKnownAnswerEnabled(true).build());
- doCallRealMethod().when(mockDeps).getDatagramPacketFromMdnsPacket(
- any(), any(MdnsPacket.class), any(InetSocketAddress.class));
+ doCallRealMethod().when(mockDeps).getDatagramPacketsFromMdnsPacket(
+ any(), any(MdnsPacket.class), any(InetSocketAddress.class), anyBoolean());
startSendAndReceive(mockListenerOne, MdnsSearchOptions.getDefaultOptions());
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
- final ArgumentCaptor<DatagramPacket> queryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> queryCaptor =
+ ArgumentCaptor.forClass(List.class);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
// Send twice for IPv4 and IPv6
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
@@ -1953,7 +1953,7 @@
assertNotNull(delayMessage);
final MdnsPacket queryPacket = MdnsPacket.parse(
- new MdnsPacketReader(queryCaptor.getValue()));
+ new MdnsPacketReader(queryCaptor.getValue().get(0)));
assertTrue(hasQuestion(queryPacket, MdnsRecord.TYPE_PTR));
// Process a response
@@ -1981,14 +1981,14 @@
// Expect a query with known answers
dispatchMessage();
- final ArgumentCaptor<DatagramPacket> knownAnswersQueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> knownAnswersQueryCaptor =
+ ArgumentCaptor.forClass(List.class);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
knownAnswersQueryCaptor.capture(), eq(socketKey), eq(false));
final MdnsPacket knownAnswersQueryPacket = MdnsPacket.parse(
- new MdnsPacketReader(knownAnswersQueryCaptor.getValue()));
+ new MdnsPacketReader(knownAnswersQueryCaptor.getValue().get(0)));
assertTrue(hasQuestion(knownAnswersQueryPacket, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
assertTrue(hasAnswer(knownAnswersQueryPacket, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
assertFalse(hasAnswer(knownAnswersQueryPacket, MdnsRecord.TYPE_PTR, subtypeLabels));
@@ -2001,16 +2001,16 @@
serviceCache,
MdnsFeatureFlags.newBuilder().setIsQueryWithKnownAnswerEnabled(true).build());
- doCallRealMethod().when(mockDeps).getDatagramPacketFromMdnsPacket(
- any(), any(MdnsPacket.class), any(InetSocketAddress.class));
+ doCallRealMethod().when(mockDeps).getDatagramPacketsFromMdnsPacket(
+ any(), any(MdnsPacket.class), any(InetSocketAddress.class), anyBoolean());
final MdnsSearchOptions options = MdnsSearchOptions.newBuilder()
.addSubtype("subtype").build();
startSendAndReceive(mockListenerOne, options);
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
- final ArgumentCaptor<DatagramPacket> queryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> queryCaptor =
+ ArgumentCaptor.forClass(List.class);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
// Send twice for IPv4 and IPv6
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingUnicastResponse(
@@ -2019,7 +2019,7 @@
assertNotNull(delayMessage);
final MdnsPacket queryPacket = MdnsPacket.parse(
- new MdnsPacketReader(queryCaptor.getValue()));
+ new MdnsPacketReader(queryCaptor.getValue().get(0)));
final String[] subtypeLabels = Stream.concat(Stream.of("_subtype", "_sub"),
Arrays.stream(SERVICE_TYPE_LABELS)).toArray(String[]::new);
assertTrue(hasQuestion(queryPacket, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
@@ -2048,14 +2048,14 @@
// Expect a query with known answers
dispatchMessage();
- final ArgumentCaptor<DatagramPacket> knownAnswersQueryCaptor =
- ArgumentCaptor.forClass(DatagramPacket.class);
+ final ArgumentCaptor<List<DatagramPacket>> knownAnswersQueryCaptor =
+ ArgumentCaptor.forClass(List.class);
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
knownAnswersQueryCaptor.capture(), eq(socketKey), eq(false));
final MdnsPacket knownAnswersQueryPacket = MdnsPacket.parse(
- new MdnsPacketReader(knownAnswersQueryCaptor.getValue()));
+ new MdnsPacketReader(knownAnswersQueryCaptor.getValue().get(0)));
assertTrue(hasQuestion(knownAnswersQueryPacket, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
assertTrue(hasQuestion(knownAnswersQueryPacket, MdnsRecord.TYPE_PTR, subtypeLabels));
assertTrue(hasAnswer(knownAnswersQueryPacket, MdnsRecord.TYPE_PTR, SERVICE_TYPE_LABELS));
@@ -2083,17 +2083,21 @@
currentThreadExecutor.getAndClearLastScheduledRunnable().run();
if (expectsUnicastResponse) {
verify(mockSocketClient).sendPacketRequestingUnicastResponse(
- expectedIPv4Packets[index], socketKey, false);
+ argThat(pkts -> pkts.get(0).equals(expectedIPv4Packets[index])),
+ eq(socketKey), eq(false));
if (multipleSocketDiscovery) {
verify(mockSocketClient).sendPacketRequestingUnicastResponse(
- expectedIPv6Packets[index], socketKey, false);
+ argThat(pkts -> pkts.get(0).equals(expectedIPv6Packets[index])),
+ eq(socketKey), eq(false));
}
} else {
verify(mockSocketClient).sendPacketRequestingMulticastResponse(
- expectedIPv4Packets[index], socketKey, false);
+ argThat(pkts -> pkts.get(0).equals(expectedIPv4Packets[index])),
+ eq(socketKey), eq(false));
if (multipleSocketDiscovery) {
verify(mockSocketClient).sendPacketRequestingMulticastResponse(
- expectedIPv6Packets[index], socketKey, false);
+ argThat(pkts -> pkts.get(0).equals(expectedIPv6Packets[index])),
+ eq(socketKey), eq(false));
}
}
verify(mockDeps, times(index + 1))
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java
index 7ced1cb..1989ed3 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketClientTests.java
@@ -27,6 +27,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
@@ -53,6 +54,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
@@ -60,6 +62,8 @@
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -234,7 +238,7 @@
// Sends a packet.
DatagramPacket packet = getTestDatagramPacket();
- mdnsClient.sendPacketRequestingMulticastResponse(packet,
+ mdnsClient.sendPacketRequestingMulticastResponse(List.of(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.
@@ -242,7 +246,7 @@
verify(mockUnicastSocket, timeout(TIMEOUT).times(0)).send(packet);
// Verify the packet is sent by the unicast socket.
- mdnsClient.sendPacketRequestingUnicastResponse(packet,
+ mdnsClient.sendPacketRequestingUnicastResponse(List.of(packet),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
verify(mockMulticastSocket, timeout(TIMEOUT).times(1)).send(packet);
verify(mockUnicastSocket, timeout(TIMEOUT).times(1)).send(packet);
@@ -287,7 +291,7 @@
// Sends a packet.
DatagramPacket packet = getTestDatagramPacket();
- mdnsClient.sendPacketRequestingMulticastResponse(packet,
+ mdnsClient.sendPacketRequestingMulticastResponse(List.of(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.
@@ -295,7 +299,7 @@
verify(mockUnicastSocket, timeout(TIMEOUT).times(0)).send(packet);
// Verify the packet is sent by the multicast socket as well.
- mdnsClient.sendPacketRequestingUnicastResponse(packet,
+ mdnsClient.sendPacketRequestingUnicastResponse(List.of(packet),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
verify(mockMulticastSocket, timeout(TIMEOUT).times(2)).send(packet);
verify(mockUnicastSocket, timeout(TIMEOUT).times(0)).send(packet);
@@ -354,7 +358,7 @@
public void testStopDiscovery_queueIsCleared() throws IOException {
mdnsClient.startDiscovery();
mdnsClient.stopDiscovery();
- mdnsClient.sendPacketRequestingMulticastResponse(getTestDatagramPacket(),
+ mdnsClient.sendPacketRequestingMulticastResponse(List.of(getTestDatagramPacket()),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
synchronized (mdnsClient.multicastPacketQueue) {
@@ -366,7 +370,7 @@
public void testSendPacket_afterDiscoveryStops() throws IOException {
mdnsClient.startDiscovery();
mdnsClient.stopDiscovery();
- mdnsClient.sendPacketRequestingMulticastResponse(getTestDatagramPacket(),
+ mdnsClient.sendPacketRequestingMulticastResponse(List.of(getTestDatagramPacket()),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
synchronized (mdnsClient.multicastPacketQueue) {
@@ -380,7 +384,7 @@
//MdnsConfigsFlagsImpl.mdnsPacketQueueMaxSize.override(2L);
mdnsClient.startDiscovery();
for (int i = 0; i < 100; i++) {
- mdnsClient.sendPacketRequestingMulticastResponse(getTestDatagramPacket(),
+ mdnsClient.sendPacketRequestingMulticastResponse(List.of(getTestDatagramPacket()),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
}
@@ -478,9 +482,9 @@
mdnsClient.startDiscovery();
DatagramPacket packet = getTestDatagramPacket();
- mdnsClient.sendPacketRequestingUnicastResponse(packet,
+ mdnsClient.sendPacketRequestingUnicastResponse(List.of(packet),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
- mdnsClient.sendPacketRequestingMulticastResponse(packet,
+ mdnsClient.sendPacketRequestingMulticastResponse(List.of(packet),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
// Wait for the timer to be triggered.
@@ -511,9 +515,9 @@
assertFalse(mdnsClient.receivedUnicastResponse);
assertFalse(mdnsClient.cannotReceiveMulticastResponse.get());
- mdnsClient.sendPacketRequestingUnicastResponse(packet,
+ mdnsClient.sendPacketRequestingUnicastResponse(List.of(packet),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
- mdnsClient.sendPacketRequestingMulticastResponse(packet,
+ mdnsClient.sendPacketRequestingMulticastResponse(List.of(packet),
false /* onlyUseIpv6OnIpv6OnlyNetworks */);
Thread.sleep(MdnsConfigs.checkMulticastResponseIntervalMs() * 2);
@@ -570,6 +574,26 @@
.onResponseReceived(any(), argThat(key -> key.getInterfaceIndex() == -1));
}
+ @Test
+ public void testSendPacketWithMultipleDatagramPacket() throws IOException {
+ mdnsClient.startDiscovery();
+ final List<DatagramPacket> packets = new ArrayList<>();
+ for (int i = 0; i < 10; i++) {
+ packets.add(new DatagramPacket(new byte[10 + i] /* buff */, 0 /* offset */,
+ 10 + i /* length */, MdnsConstants.IPV4_SOCKET_ADDR));
+ }
+
+ // Sends packets.
+ mdnsClient.sendPacketRequestingMulticastResponse(packets,
+ false /* onlyUseIpv6OnIpv6OnlyNetworks */);
+ InOrder inOrder = inOrder(mockMulticastSocket);
+ for (int i = 0; i < 10; i++) {
+ // mockMulticastSocket.send() will be called on another thread. If we verify it
+ // immediately, it may not be called yet. So timeout is added.
+ inOrder.verify(mockMulticastSocket, timeout(TIMEOUT)).send(packets.get(i));
+ }
+ }
+
private DatagramPacket getTestDatagramPacket() {
return new DatagramPacket(buf, 0, 5,
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), 5353 /* port */));