Merge "De-duplicate questions with multiple listeners" into main

This commit is contained in:
Treehugger Robot 2024-02-28 15:45:55 +00:00 • committed by Gerrit Code Review
commit d4b802064b
2 changed files with 43 additions and 6 deletions

View file

@ -140,8 +140,7 @@ public class MdnsServiceTypeClient {
// before sending the query, it needs to be called just before sending it.
final List<MdnsResponse> servicesToResolve = makeResponsesForResolve(socketKey);
final QueryTask queryTask = new QueryTask(taskArgs, servicesToResolve,
getAllDiscoverySubtypes(),
servicesToResolve.size() < listeners.size() /* sendDiscoveryQueries */);
getAllDiscoverySubtypes(), needSendDiscoveryQueries(listeners));
executor.submit(queryTask);
break;
}
@ -388,8 +387,7 @@ public class MdnsServiceTypeClient {
final QueryTask queryTask = new QueryTask(
mdnsQueryScheduler.scheduleFirstRun(taskConfig, now,
minRemainingTtl, currentSessionId), servicesToResolve,
getAllDiscoverySubtypes(),
servicesToResolve.size() < listeners.size() /* sendDiscoveryQueries */);
getAllDiscoverySubtypes(), needSendDiscoveryQueries(listeners));
executor.submit(queryTask);
}
@ -627,6 +625,10 @@ public class MdnsServiceTypeClient {
if (resolveName == null) {
continue;
}
if (CollectionUtils.any(resolveResponses,
r -> MdnsUtils.equalsIgnoreDnsCase(resolveName, r.getServiceInstanceName()))) {
continue;
}
MdnsResponse knownResponse =
serviceCache.getCachedService(resolveName, cacheKey);
if (knownResponse == null) {
@ -643,6 +645,17 @@ public class MdnsServiceTypeClient {
return resolveResponses;
}
private static boolean needSendDiscoveryQueries(
@NonNull ArrayMap<MdnsServiceBrowserListener, ListenerInfo> listeners) {
// Note iterators are discouraged on ArrayMap as per its documentation
for (int i = 0; i < listeners.size(); i++) {
if (listeners.valueAt(i).searchOptions.getResolveInstanceName() == null) {
return true;
}
}
return false;
}
private void tryRemoveServiceAfterTtlExpires() {
if (!shouldRemoveServiceAfterTtlExpires()) return;

View file

@ -43,6 +43,7 @@ import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static java.nio.charset.StandardCharsets.UTF_8;
@ -1207,10 +1208,14 @@ public class MdnsServiceTypeClientTests {
final String ipV4Address = "192.0.2.0";
final String ipV6Address = "2001:db8::";
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
final MdnsSearchOptions resolveOptions1 = MdnsSearchOptions.newBuilder()
.setResolveInstanceName(instanceName).build();
final MdnsSearchOptions resolveOptions2 = MdnsSearchOptions.newBuilder()
.setResolveInstanceName(instanceName).build();
startSendAndReceive(mockListenerOne, resolveOptions);
startSendAndReceive(mockListenerOne, resolveOptions1);
startSendAndReceive(mockListenerTwo, resolveOptions2);
// No need to verify order for both listeners; and order is not guaranteed between them
InOrder inOrder = inOrder(mockListenerOne, mockSocketClient);
// Verify a query for SRV/TXT was sent, but no PTR query
@ -1223,13 +1228,19 @@ public class MdnsServiceTypeClientTests {
eq(socketKey), eq(false));
verify(mockDeps, times(1)).sendMessage(any(), any(Message.class));
assertNotNull(delayMessage);
inOrder.verify(mockListenerOne).onDiscoveryQuerySent(any(), anyInt());
verify(mockListenerTwo).onDiscoveryQuerySent(any(), anyInt());
final MdnsPacket srvTxtQueryPacket = MdnsPacket.parse(
new MdnsPacketReader(srvTxtQueryCaptor.getValue()));
final String[] serviceName = getTestServiceName(instanceName);
assertEquals(1, srvTxtQueryPacket.questions.size());
assertFalse(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_PTR));
assertTrue(hasQuestion(srvTxtQueryPacket, MdnsRecord.TYPE_ANY, serviceName));
assertEquals(0, srvTxtQueryPacket.answers.size());
assertEquals(0, srvTxtQueryPacket.authorityRecords.size());
assertEquals(0, srvTxtQueryPacket.additionalRecords.size());
// Process a response with SRV+TXT
final MdnsPacket srvTxtResponse = new MdnsPacket(
@ -1246,6 +1257,10 @@ public class MdnsServiceTypeClientTests {
Collections.emptyList() /* additionalRecords */);
processResponse(srvTxtResponse, socketKey);
inOrder.verify(mockListenerOne).onServiceNameDiscovered(
matchServiceName(instanceName), eq(false) /* isServiceFromCache */);
verify(mockListenerTwo).onServiceNameDiscovered(
matchServiceName(instanceName), eq(false) /* isServiceFromCache */);
// Expect a query for A/AAAA
dispatchMessage();
@ -1255,11 +1270,18 @@ public class MdnsServiceTypeClientTests {
inOrder.verify(mockSocketClient, times(2)).sendPacketRequestingMulticastResponse(
addressQueryCaptor.capture(),
eq(socketKey), eq(false));
inOrder.verify(mockListenerOne).onDiscoveryQuerySent(any(), anyInt());
// onDiscoveryQuerySent was called 2 times in total
verify(mockListenerTwo, times(2)).onDiscoveryQuerySent(any(), anyInt());
final MdnsPacket addressQueryPacket = MdnsPacket.parse(
new MdnsPacketReader(addressQueryCaptor.getValue()));
assertEquals(2, addressQueryPacket.questions.size());
assertTrue(hasQuestion(addressQueryPacket, MdnsRecord.TYPE_A, hostname));
assertTrue(hasQuestion(addressQueryPacket, MdnsRecord.TYPE_AAAA, hostname));
assertEquals(0, addressQueryPacket.answers.size());
assertEquals(0, addressQueryPacket.authorityRecords.size());
assertEquals(0, addressQueryPacket.additionalRecords.size());
// Process a response with address records
final MdnsPacket addressResponse = new MdnsPacket(
@ -1276,10 +1298,12 @@ public class MdnsServiceTypeClientTests {
Collections.emptyList() /* additionalRecords */);
inOrder.verify(mockListenerOne, never()).onServiceNameDiscovered(any(), anyBoolean());
verifyNoMoreInteractions(mockListenerTwo);
processResponse(addressResponse, socketKey);
inOrder.verify(mockListenerOne).onServiceFound(
serviceInfoCaptor.capture(), eq(false) /* isServiceFromCache */);
verify(mockListenerTwo).onServiceFound(any(), anyBoolean());
verifyServiceInfo(serviceInfoCaptor.getValue(),
instanceName,
SERVICE_TYPE_LABELS,