Move buildMdnsServiceInfoFromResponse to MdnsUtils.

Move this utility method buildMdnsServiceInfoFromResponse from
MdnsServiceTypeClient to MdnsUtils so it can be used by other
classes.

Bug: 355421878
Test: atest FrameworksNetTests NsdManagerTest
Change-Id: I8ce1028de325da46f112a5ec58516453727151fe
This commit is contained in:
Paul Hu 2024-07-26 03:28:28 +00:00
commit f311b43bef
3 changed files with 123 additions and 56 deletions

View file

@ -20,6 +20,7 @@ import static com.android.server.connectivity.mdns.MdnsSearchOptions.AGGRESSIVE_
import static com.android.server.connectivity.mdns.MdnsServiceCache.ServiceExpiredCallback;
import static com.android.server.connectivity.mdns.MdnsServiceCache.findMatchedResponse;
import static com.android.server.connectivity.mdns.util.MdnsUtils.Clock;
import static com.android.server.connectivity.mdns.util.MdnsUtils.buildMdnsServiceInfoFromResponse;
import static com.android.server.connectivity.mdns.util.MdnsUtils.ensureRunningOnHandlerThread;
import android.annotation.NonNull;
@ -41,10 +42,7 @@ import com.android.server.connectivity.mdns.util.MdnsUtils;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -309,57 +307,6 @@ public class MdnsServiceTypeClient {
serviceCache.unregisterServiceExpiredCallback(cacheKey);
}
private static MdnsServiceInfo buildMdnsServiceInfoFromResponse(@NonNull MdnsResponse response,
@NonNull String[] serviceTypeLabels, long elapsedRealtimeMillis) {
String[] hostName = null;
int port = 0;
if (response.hasServiceRecord()) {
hostName = response.getServiceRecord().getServiceHost();
port = response.getServiceRecord().getServicePort();
}
final List<String> ipv4Addresses = new ArrayList<>();
final List<String> ipv6Addresses = new ArrayList<>();
if (response.hasInet4AddressRecord()) {
for (MdnsInetAddressRecord inetAddressRecord : response.getInet4AddressRecords()) {
final Inet4Address inet4Address = inetAddressRecord.getInet4Address();
ipv4Addresses.add((inet4Address == null) ? null : inet4Address.getHostAddress());
}
}
if (response.hasInet6AddressRecord()) {
for (MdnsInetAddressRecord inetAddressRecord : response.getInet6AddressRecords()) {
final Inet6Address inet6Address = inetAddressRecord.getInet6Address();
ipv6Addresses.add((inet6Address == null) ? null : inet6Address.getHostAddress());
}
}
String serviceInstanceName = response.getServiceInstanceName();
if (serviceInstanceName == null) {
throw new IllegalStateException(
"mDNS response must have non-null service instance name");
}
List<String> textStrings = null;
List<MdnsServiceInfo.TextEntry> textEntries = null;
if (response.hasTextRecord()) {
textStrings = response.getTextRecord().getStrings();
textEntries = response.getTextRecord().getEntries();
}
Instant now = Instant.now();
// TODO: Throw an error message if response doesn't have Inet6 or Inet4 address.
return new MdnsServiceInfo(
serviceInstanceName,
serviceTypeLabels,
response.getSubtypes(),
hostName,
port,
ipv4Addresses,
ipv6Addresses,
textStrings,
textEntries,
response.getInterfaceIndex(),
response.getNetwork(),
now.plusMillis(response.getMinRemainingTtl(elapsedRealtimeMillis)));
}
private List<MdnsResponse> getExistingServices() {
return featureFlags.isQueryWithKnownAnswerEnabled()
? serviceCache.getCachedServices(cacheKey) : Collections.emptyList();

View file

@ -30,12 +30,17 @@ import android.util.ArraySet;
import android.util.Pair;
import com.android.server.connectivity.mdns.MdnsConstants;
import com.android.server.connectivity.mdns.MdnsInetAddressRecord;
import com.android.server.connectivity.mdns.MdnsPacket;
import com.android.server.connectivity.mdns.MdnsPacketWriter;
import com.android.server.connectivity.mdns.MdnsRecord;
import com.android.server.connectivity.mdns.MdnsResponse;
import com.android.server.connectivity.mdns.MdnsServiceInfo;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
@ -43,6 +48,7 @@ import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -318,4 +324,62 @@ public class MdnsUtils {
}
return true;
}
/**
* Build MdnsServiceInfo object from given MdnsResponse, service type labels and current time.
*
* @param response target service response
* @param serviceTypeLabels service type labels
* @param elapsedRealtimeMillis current time.
*/
public static MdnsServiceInfo buildMdnsServiceInfoFromResponse(@NonNull MdnsResponse response,
@NonNull String[] serviceTypeLabels, long elapsedRealtimeMillis) {
String[] hostName = null;
int port = 0;
if (response.hasServiceRecord()) {
hostName = response.getServiceRecord().getServiceHost();
port = response.getServiceRecord().getServicePort();
}
final List<String> ipv4Addresses = new ArrayList<>();
final List<String> ipv6Addresses = new ArrayList<>();
if (response.hasInet4AddressRecord()) {
for (MdnsInetAddressRecord inetAddressRecord : response.getInet4AddressRecords()) {
final Inet4Address inet4Address = inetAddressRecord.getInet4Address();
ipv4Addresses.add((inet4Address == null) ? null : inet4Address.getHostAddress());
}
}
if (response.hasInet6AddressRecord()) {
for (MdnsInetAddressRecord inetAddressRecord : response.getInet6AddressRecords()) {
final Inet6Address inet6Address = inetAddressRecord.getInet6Address();
ipv6Addresses.add((inet6Address == null) ? null : inet6Address.getHostAddress());
}
}
String serviceInstanceName = response.getServiceInstanceName();
if (serviceInstanceName == null) {
throw new IllegalStateException(
"mDNS response must have non-null service instance name");
}
List<String> textStrings = null;
List<MdnsServiceInfo.TextEntry> textEntries = null;
if (response.hasTextRecord()) {
textStrings = response.getTextRecord().getStrings();
textEntries = response.getTextRecord().getEntries();
}
Instant now = Instant.now();
// TODO: Throw an error message if response doesn't have Inet6 or Inet4 address.
return new MdnsServiceInfo(
serviceInstanceName,
serviceTypeLabels,
response.getSubtypes(),
hostName,
port,
ipv4Addresses,
ipv6Addresses,
textStrings,
textEntries,
response.getInterfaceIndex(),
response.getNetwork(),
now.plusMillis(response.getMinRemainingTtl(elapsedRealtimeMillis)));
}
}

View file

@ -22,21 +22,27 @@ import com.android.server.connectivity.mdns.MdnsConstants
import com.android.server.connectivity.mdns.MdnsConstants.FLAG_TRUNCATED
import com.android.server.connectivity.mdns.MdnsConstants.IPV4_SOCKET_ADDR
import com.android.server.connectivity.mdns.MdnsConstants.IPV6_SOCKET_ADDR
import com.android.server.connectivity.mdns.MdnsInetAddressRecord
import com.android.server.connectivity.mdns.MdnsPacket
import com.android.server.connectivity.mdns.MdnsPacketReader
import com.android.server.connectivity.mdns.MdnsPointerRecord
import com.android.server.connectivity.mdns.MdnsRecord
import com.android.server.connectivity.mdns.MdnsResponse
import com.android.server.connectivity.mdns.MdnsServiceInfo
import com.android.server.connectivity.mdns.MdnsServiceRecord
import com.android.server.connectivity.mdns.MdnsTextRecord
import com.android.server.connectivity.mdns.util.MdnsUtils.createQueryDatagramPackets
import com.android.server.connectivity.mdns.util.MdnsUtils.truncateServiceName
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import java.net.DatagramPacket
import kotlin.test.assertContentEquals
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import java.net.DatagramPacket
import kotlin.test.assertContentEquals
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
@ -157,4 +163,54 @@ class MdnsUtilsTest {
assertFalse(MdnsUtils.checkAllPacketsWithSameAddress(listOf(v6Packet, otherV6Packet)))
assertFalse(MdnsUtils.checkAllPacketsWithSameAddress(listOf(v4Packet, v6Packet)))
}
@Test
fun testBuildMdnsServiceInfoFromResponse() {
val serviceInstanceName = "MyTestService"
val serviceType = "_testservice._tcp.local"
val hostName = "Android_000102030405060708090A0B0C0D0E0F.local"
val port = 12345
val ttlTime = 120000L
val testElapsedRealtime = 123L
val serviceName = "$serviceInstanceName.$serviceType".split(".").toTypedArray()
val v4Address = "192.0.2.1"
val v6Address = "2001:db8::1"
val interfaceIndex = 99
val response = MdnsResponse(0 /* now */, serviceName, interfaceIndex, null /* network */)
// Set PTR record
response.addPointerRecord(MdnsPointerRecord(serviceType.split(".").toTypedArray(),
testElapsedRealtime, false /* cacheFlush */, ttlTime, serviceName))
// Set SRV record.
response.serviceRecord = MdnsServiceRecord(serviceName, testElapsedRealtime,
false /* cacheFlush */, ttlTime, 0 /* servicePriority */, 0 /* serviceWeight */,
port, hostName.split(".").toTypedArray())
// Set TXT record.
response.textRecord = MdnsTextRecord(serviceName,
testElapsedRealtime, true /* cacheFlush */, 0L /* ttlMillis */,
listOf(MdnsServiceInfo.TextEntry.fromString("somedifferent=entry")))
// Set InetAddress record.
response.addInet4AddressRecord(MdnsInetAddressRecord(hostName.split(".").toTypedArray(),
testElapsedRealtime, true /* cacheFlush */,
0L /* ttlMillis */, InetAddresses.parseNumericAddress(v4Address)))
response.addInet6AddressRecord(MdnsInetAddressRecord(hostName.split(".").toTypedArray(),
testElapsedRealtime, true /* cacheFlush */,
0L /* ttlMillis */, InetAddresses.parseNumericAddress(v6Address)))
// Convert a MdnsResponse to a MdnsServiceInfo
val serviceInfo = MdnsUtils.buildMdnsServiceInfoFromResponse(
response, serviceType.split(".").toTypedArray(), testElapsedRealtime)
assertEquals(serviceInstanceName, serviceInfo.serviceInstanceName)
assertArrayEquals(serviceType.split(".").toTypedArray(), serviceInfo.serviceType)
assertArrayEquals(hostName.split(".").toTypedArray(), serviceInfo.hostName)
assertEquals(port, serviceInfo.port)
assertEquals(1, serviceInfo.ipv4Addresses.size)
assertEquals(v4Address, serviceInfo.ipv4Addresses[0])
assertEquals(1, serviceInfo.ipv6Addresses.size)
assertEquals(v6Address, serviceInfo.ipv6Addresses[0])
assertEquals(interfaceIndex, serviceInfo.interfaceIndex)
assertEquals(null, serviceInfo.network)
assertEquals(mapOf("somedifferent" to "entry"),
serviceInfo.attributes)
}
}