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 a5dd5363c1..b0e3ba42cb 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java @@ -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 ipv4Addresses = new ArrayList<>(); - final List 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 textStrings = null; - List 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 getExistingServices() { return featureFlags.isQueryWithKnownAnswerEnabled() ? serviceCache.getCachedServices(cacheKey) : Collections.emptyList(); diff --git a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java index 8745941fed..85a8961d69 100644 --- a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java +++ b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java @@ -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 ipv4Addresses = new ArrayList<>(); + final List 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 textStrings = null; + List 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))); + } } \ No newline at end of file diff --git a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt index 5c3ad22a62..efae244e48 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt +++ b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt @@ -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) + } }