Merge "Add test for partial responses" into main am: d292cff70e
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2437173 Change-Id: I5f68885adf0083c3cea1de67fd5ce95749246915 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -233,46 +233,51 @@ class NsdServiceInfoCallbackRecord : NsdManager.ServiceInfoCallback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getMdnsPayload(packet: ByteArray) = packet.copyOfRange(
|
||||||
|
ETHER_HEADER_LEN + IPV6_HEADER_LEN + UDP_HEADER_LEN, packet.size)
|
||||||
|
|
||||||
fun TapPacketReader.pollForMdnsPacket(
|
fun TapPacketReader.pollForMdnsPacket(
|
||||||
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS,
|
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS,
|
||||||
predicate: (TestDnsPacket) -> Boolean
|
predicate: (TestDnsPacket) -> Boolean
|
||||||
): ByteArray? {
|
): TestDnsPacket? {
|
||||||
val mdnsProbeFilter = IPv6UdpFilter(srcPort = MDNS_PORT, dstPort = MDNS_PORT).and {
|
val mdnsProbeFilter = IPv6UdpFilter(srcPort = MDNS_PORT, dstPort = MDNS_PORT).and {
|
||||||
val mdnsPayload = it.copyOfRange(
|
val mdnsPayload = getMdnsPayload(it)
|
||||||
ETHER_HEADER_LEN + IPV6_HEADER_LEN + UDP_HEADER_LEN, it.size
|
|
||||||
)
|
|
||||||
try {
|
try {
|
||||||
predicate(TestDnsPacket(mdnsPayload))
|
predicate(TestDnsPacket(mdnsPayload))
|
||||||
} catch (e: DnsPacket.ParseException) {
|
} catch (e: DnsPacket.ParseException) {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return poll(timeoutMs, mdnsProbeFilter)
|
return poll(timeoutMs, mdnsProbeFilter)?.let { TestDnsPacket(getMdnsPayload(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TapPacketReader.pollForProbe(
|
fun TapPacketReader.pollForProbe(
|
||||||
serviceName: String,
|
serviceName: String,
|
||||||
serviceType: String,
|
serviceType: String,
|
||||||
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
||||||
): ByteArray? = pollForMdnsPacket(timeoutMs) { it.isProbeFor("$serviceName.$serviceType.local") }
|
): TestDnsPacket? = pollForMdnsPacket(timeoutMs) {
|
||||||
|
it.isProbeFor("$serviceName.$serviceType.local")
|
||||||
|
}
|
||||||
|
|
||||||
fun TapPacketReader.pollForAdvertisement(
|
fun TapPacketReader.pollForAdvertisement(
|
||||||
serviceName: String,
|
serviceName: String,
|
||||||
serviceType: String,
|
serviceType: String,
|
||||||
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
||||||
): ByteArray? = pollForMdnsPacket(timeoutMs) { it.isReplyFor("$serviceName.$serviceType.local") }
|
): TestDnsPacket? = pollForMdnsPacket(timeoutMs) {
|
||||||
|
it.isReplyFor("$serviceName.$serviceType.local")
|
||||||
|
}
|
||||||
|
|
||||||
fun TapPacketReader.pollForQuery(
|
fun TapPacketReader.pollForQuery(
|
||||||
recordName: String,
|
recordName: String,
|
||||||
recordType: Int,
|
vararg requiredTypes: Int,
|
||||||
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
||||||
): ByteArray? = pollForMdnsPacket(timeoutMs) { it.isQueryFor(recordName, recordType) }
|
): TestDnsPacket? = pollForMdnsPacket(timeoutMs) { it.isQueryFor(recordName, *requiredTypes) }
|
||||||
|
|
||||||
fun TapPacketReader.pollForReply(
|
fun TapPacketReader.pollForReply(
|
||||||
serviceName: String,
|
serviceName: String,
|
||||||
serviceType: String,
|
serviceType: String,
|
||||||
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
timeoutMs: Long = MDNS_REGISTRATION_TIMEOUT_MS
|
||||||
): ByteArray? = pollForMdnsPacket(timeoutMs) {
|
): TestDnsPacket? = pollForMdnsPacket(timeoutMs) {
|
||||||
it.isReplyFor("$serviceName.$serviceType.local")
|
it.isReplyFor("$serviceName.$serviceType.local")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +294,9 @@ class TestDnsPacket(data: ByteArray) : DnsPacket(data) {
|
|||||||
it.dName == name && it.nsType == DnsResolver.TYPE_SRV
|
it.dName == name && it.nsType == DnsResolver.TYPE_SRV
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isQueryFor(name: String, type: Int): Boolean = mRecords[QDSECTION].any {
|
fun isQueryFor(name: String, vararg requiredTypes: Int): Boolean = requiredTypes.all { type ->
|
||||||
|
mRecords[QDSECTION].any {
|
||||||
it.dName == name && it.nsType == type
|
it.dName == name && it.nsType == type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.Manifest.permission.NETWORK_SETTINGS
|
|||||||
import android.app.compat.CompatChanges
|
import android.app.compat.CompatChanges
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.ConnectivityManager.NetworkCallback
|
import android.net.ConnectivityManager.NetworkCallback
|
||||||
|
import android.net.DnsResolver
|
||||||
import android.net.InetAddresses.parseNumericAddress
|
import android.net.InetAddresses.parseNumericAddress
|
||||||
import android.net.LinkAddress
|
import android.net.LinkAddress
|
||||||
import android.net.LinkProperties
|
import android.net.LinkProperties
|
||||||
@@ -87,6 +88,7 @@ import com.android.testutils.TapPacketReader
|
|||||||
import com.android.testutils.TestableNetworkAgent
|
import com.android.testutils.TestableNetworkAgent
|
||||||
import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
|
import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnNetworkCreated
|
||||||
import com.android.testutils.TestableNetworkCallback
|
import com.android.testutils.TestableNetworkCallback
|
||||||
|
import com.android.testutils.assertEmpty
|
||||||
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk30
|
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk30
|
||||||
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk33
|
import com.android.testutils.filters.CtsNetTestCasesMaxTargetSdk33
|
||||||
import com.android.testutils.runAsShell
|
import com.android.testutils.runAsShell
|
||||||
@@ -424,11 +426,7 @@ class NsdManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNsdManager_DiscoverOnNetwork() {
|
fun testNsdManager_DiscoverOnNetwork() {
|
||||||
val si = NsdServiceInfo()
|
val si = makeTestServiceInfo()
|
||||||
si.serviceType = serviceType
|
|
||||||
si.serviceName = this.serviceName
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
val registrationRecord = NsdRegistrationRecord()
|
val registrationRecord = NsdRegistrationRecord()
|
||||||
val registeredInfo = registerService(registrationRecord, si)
|
val registeredInfo = registerService(registrationRecord, si)
|
||||||
|
|
||||||
@@ -455,11 +453,7 @@ class NsdManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNsdManager_DiscoverWithNetworkRequest() {
|
fun testNsdManager_DiscoverWithNetworkRequest() {
|
||||||
val si = NsdServiceInfo()
|
val si = makeTestServiceInfo()
|
||||||
si.serviceType = serviceType
|
|
||||||
si.serviceName = this.serviceName
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
val handler = Handler(handlerThread.looper)
|
val handler = Handler(handlerThread.looper)
|
||||||
val executor = Executor { handler.post(it) }
|
val executor = Executor { handler.post(it) }
|
||||||
|
|
||||||
@@ -524,11 +518,6 @@ class NsdManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNsdManager_DiscoverWithNetworkRequest_NoMatchingNetwork() {
|
fun testNsdManager_DiscoverWithNetworkRequest_NoMatchingNetwork() {
|
||||||
val si = NsdServiceInfo()
|
|
||||||
si.serviceType = serviceType
|
|
||||||
si.serviceName = this.serviceName
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
val handler = Handler(handlerThread.looper)
|
val handler = Handler(handlerThread.looper)
|
||||||
val executor = Executor { handler.post(it) }
|
val executor = Executor { handler.post(it) }
|
||||||
|
|
||||||
@@ -568,11 +557,7 @@ class NsdManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNsdManager_ResolveOnNetwork() {
|
fun testNsdManager_ResolveOnNetwork() {
|
||||||
val si = NsdServiceInfo()
|
val si = makeTestServiceInfo()
|
||||||
si.serviceType = serviceType
|
|
||||||
si.serviceName = this.serviceName
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
val registrationRecord = NsdRegistrationRecord()
|
val registrationRecord = NsdRegistrationRecord()
|
||||||
val registeredInfo = registerService(registrationRecord, si)
|
val registeredInfo = registerService(registrationRecord, si)
|
||||||
tryTest {
|
tryTest {
|
||||||
@@ -610,12 +595,7 @@ class NsdManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNsdManager_RegisterOnNetwork() {
|
fun testNsdManager_RegisterOnNetwork() {
|
||||||
val si = NsdServiceInfo()
|
val si = makeTestServiceInfo(testNetwork1.network)
|
||||||
si.serviceType = serviceType
|
|
||||||
si.serviceName = this.serviceName
|
|
||||||
si.network = testNetwork1.network
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
// Register service on testNetwork1
|
// Register service on testNetwork1
|
||||||
val registrationRecord = NsdRegistrationRecord()
|
val registrationRecord = NsdRegistrationRecord()
|
||||||
registerService(registrationRecord, si)
|
registerService(registrationRecord, si)
|
||||||
@@ -889,11 +869,7 @@ class NsdManagerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testStopServiceResolution() {
|
fun testStopServiceResolution() {
|
||||||
val si = NsdServiceInfo()
|
val si = makeTestServiceInfo()
|
||||||
si.serviceType = this@NsdManagerTest.serviceType
|
|
||||||
si.serviceName = this@NsdManagerTest.serviceName
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
val resolveRecord = NsdResolveRecord()
|
val resolveRecord = NsdResolveRecord()
|
||||||
// Try to resolve an unknown service then stop it immediately.
|
// Try to resolve an unknown service then stop it immediately.
|
||||||
// Expected ResolutionStopped callback.
|
// Expected ResolutionStopped callback.
|
||||||
@@ -911,12 +887,7 @@ class NsdManagerTest {
|
|||||||
val addresses = lp.addresses
|
val addresses = lp.addresses
|
||||||
assertFalse(addresses.isEmpty())
|
assertFalse(addresses.isEmpty())
|
||||||
|
|
||||||
val si = NsdServiceInfo().apply {
|
val si = makeTestServiceInfo(testNetwork1.network)
|
||||||
serviceType = this@NsdManagerTest.serviceType
|
|
||||||
serviceName = this@NsdManagerTest.serviceName
|
|
||||||
network = testNetwork1.network
|
|
||||||
port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register service on the network
|
// Register service on the network
|
||||||
val registrationRecord = NsdRegistrationRecord()
|
val registrationRecord = NsdRegistrationRecord()
|
||||||
@@ -1022,11 +993,7 @@ class NsdManagerTest {
|
|||||||
// This test requires shims supporting T+ APIs (NsdServiceInfo.network)
|
// This test requires shims supporting T+ APIs (NsdServiceInfo.network)
|
||||||
assumeTrue(TestUtils.shouldTestTApis())
|
assumeTrue(TestUtils.shouldTestTApis())
|
||||||
|
|
||||||
val si = NsdServiceInfo()
|
val si = makeTestServiceInfo(testNetwork1.network)
|
||||||
si.serviceType = serviceType
|
|
||||||
si.serviceName = serviceName
|
|
||||||
si.network = testNetwork1.network
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
val packetReader = TapPacketReader(Handler(handlerThread.looper),
|
val packetReader = TapPacketReader(Handler(handlerThread.looper),
|
||||||
testNetwork1.iface.fileDescriptor.fileDescriptor, 1500 /* maxPacketSize */)
|
testNetwork1.iface.fileDescriptor.fileDescriptor, 1500 /* maxPacketSize */)
|
||||||
@@ -1063,11 +1030,7 @@ class NsdManagerTest {
|
|||||||
// This test requires shims supporting T+ APIs (NsdServiceInfo.network)
|
// This test requires shims supporting T+ APIs (NsdServiceInfo.network)
|
||||||
assumeTrue(TestUtils.shouldTestTApis())
|
assumeTrue(TestUtils.shouldTestTApis())
|
||||||
|
|
||||||
val si = NsdServiceInfo()
|
val si = makeTestServiceInfo(testNetwork1.network)
|
||||||
si.serviceType = serviceType
|
|
||||||
si.serviceName = serviceName
|
|
||||||
si.network = testNetwork1.network
|
|
||||||
si.port = 12345 // Test won't try to connect so port does not matter
|
|
||||||
|
|
||||||
// Register service on testNetwork1
|
// Register service on testNetwork1
|
||||||
val registrationRecord = NsdRegistrationRecord()
|
val registrationRecord = NsdRegistrationRecord()
|
||||||
@@ -1137,6 +1100,127 @@ class NsdManagerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that even if only a PTR record is received as a reply when discovering, without the
|
||||||
|
// SRV, TXT, address records as recommended (but not mandated) by RFC 6763 12, the service can
|
||||||
|
// still be discovered.
|
||||||
|
@Test
|
||||||
|
fun testDiscoveryWithPtrOnlyResponse_ServiceIsFound() {
|
||||||
|
// Register service on testNetwork1
|
||||||
|
val discoveryRecord = NsdDiscoveryRecord()
|
||||||
|
val packetReader = TapPacketReader(Handler(handlerThread.looper),
|
||||||
|
testNetwork1.iface.fileDescriptor.fileDescriptor, 1500 /* maxPacketSize */)
|
||||||
|
packetReader.startAsyncForTest()
|
||||||
|
handlerThread.waitForIdle(TIMEOUT_MS)
|
||||||
|
|
||||||
|
nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD,
|
||||||
|
testNetwork1.network, { it.run() }, discoveryRecord)
|
||||||
|
|
||||||
|
tryTest {
|
||||||
|
discoveryRecord.expectCallback<DiscoveryStarted>()
|
||||||
|
assertNotNull(packetReader.pollForQuery("$serviceType.local", DnsResolver.TYPE_PTR))
|
||||||
|
/*
|
||||||
|
Generated with:
|
||||||
|
scapy.raw(scapy.DNS(rd=0, qr=1, aa=1, qd = None, an =
|
||||||
|
scapy.DNSRR(rrname='_nmt123456789._tcp.local', type='PTR', ttl=120,
|
||||||
|
rdata='NsdTest123456789._nmt123456789._tcp.local'))).hex()
|
||||||
|
*/
|
||||||
|
val ptrResponsePayload = HexDump.hexStringToByteArray("0000840000000001000000000d5f6e" +
|
||||||
|
"6d74313233343536373839045f746370056c6f63616c00000c000100000078002b104e736454" +
|
||||||
|
"6573743132333435363738390d5f6e6d74313233343536373839045f746370056c6f63616c00")
|
||||||
|
|
||||||
|
replaceServiceNameAndTypeWithTestSuffix(ptrResponsePayload)
|
||||||
|
packetReader.sendResponse(buildMdnsPacket(ptrResponsePayload))
|
||||||
|
|
||||||
|
val serviceFound = discoveryRecord.expectCallback<ServiceFound>()
|
||||||
|
serviceFound.serviceInfo.let {
|
||||||
|
assertEquals(serviceName, it.serviceName)
|
||||||
|
// Discovered service types have a dot at the end
|
||||||
|
assertEquals("$serviceType.", it.serviceType)
|
||||||
|
assertEquals(testNetwork1.network, it.network)
|
||||||
|
// ServiceFound does not provide port, address or attributes (only information
|
||||||
|
// available in the PTR record is included in that callback, regardless of whether
|
||||||
|
// other records exist).
|
||||||
|
assertEquals(0, it.port)
|
||||||
|
assertEmpty(it.hostAddresses)
|
||||||
|
assertEquals(0, it.attributes.size)
|
||||||
|
}
|
||||||
|
} cleanup {
|
||||||
|
nsdManager.stopServiceDiscovery(discoveryRecord)
|
||||||
|
discoveryRecord.expectCallback<DiscoveryStopped>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test RFC 6763 12. "Clients MUST be capable of functioning correctly with DNS servers [...]
|
||||||
|
// that fail to generate these additional records automatically, by issuing subsequent queries
|
||||||
|
// for any further record(s) they require"
|
||||||
|
@Test
|
||||||
|
fun testResolveWhenServerSendsNoAdditionalRecord() {
|
||||||
|
// Resolve service on testNetwork1
|
||||||
|
val resolveRecord = NsdResolveRecord()
|
||||||
|
val packetReader = TapPacketReader(Handler(handlerThread.looper),
|
||||||
|
testNetwork1.iface.fileDescriptor.fileDescriptor, 1500 /* maxPacketSize */)
|
||||||
|
packetReader.startAsyncForTest()
|
||||||
|
handlerThread.waitForIdle(TIMEOUT_MS)
|
||||||
|
|
||||||
|
val si = makeTestServiceInfo(testNetwork1.network)
|
||||||
|
nsdManager.resolveService(si, { it.run() }, resolveRecord)
|
||||||
|
|
||||||
|
val serviceFullName = "$serviceName.$serviceType.local"
|
||||||
|
// The query should ask for ANY, since both SRV and TXT are requested. Note legacy
|
||||||
|
// mdnsresponder will ask for SRV and TXT separately, and will not proceed to asking for
|
||||||
|
// address records without an answer for both.
|
||||||
|
val srvTxtQuery = packetReader.pollForQuery(serviceFullName, DnsResolver.TYPE_ANY)
|
||||||
|
assertNotNull(srvTxtQuery)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generated with:
|
||||||
|
scapy.raw(scapy.dns_compress(scapy.DNS(rd=0, qr=1, aa=1, qd = None, an =
|
||||||
|
scapy.DNSRRSRV(rrname='NsdTest123456789._nmt123456789._tcp.local',
|
||||||
|
rclass=0x8001, port=31234, target='testhost.local', ttl=120) /
|
||||||
|
scapy.DNSRR(rrname='NsdTest123456789._nmt123456789._tcp.local', type='TXT', ttl=120,
|
||||||
|
rdata='testkey=testvalue')
|
||||||
|
))).hex()
|
||||||
|
*/
|
||||||
|
val srvTxtResponsePayload = HexDump.hexStringToByteArray("000084000000000200000000104" +
|
||||||
|
"e7364546573743132333435363738390d5f6e6d74313233343536373839045f746370056c6f6" +
|
||||||
|
"3616c0000218001000000780011000000007a020874657374686f7374c030c00c00100001000" +
|
||||||
|
"00078001211746573746b65793d7465737476616c7565")
|
||||||
|
replaceServiceNameAndTypeWithTestSuffix(srvTxtResponsePayload)
|
||||||
|
packetReader.sendResponse(buildMdnsPacket(srvTxtResponsePayload))
|
||||||
|
|
||||||
|
val testHostname = "testhost.local"
|
||||||
|
val addressQuery = packetReader.pollForQuery(testHostname,
|
||||||
|
DnsResolver.TYPE_A, DnsResolver.TYPE_AAAA)
|
||||||
|
assertNotNull(addressQuery)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generated with:
|
||||||
|
scapy.raw(scapy.dns_compress(scapy.DNS(rd=0, qr=1, aa=1, qd = None, an =
|
||||||
|
scapy.DNSRR(rrname='testhost.local', type='A', ttl=120,
|
||||||
|
rdata='192.0.2.123') /
|
||||||
|
scapy.DNSRR(rrname='testhost.local', type='AAAA', ttl=120,
|
||||||
|
rdata='2001:db8::123')
|
||||||
|
))).hex()
|
||||||
|
*/
|
||||||
|
val addressPayload = HexDump.hexStringToByteArray("0000840000000002000000000874657374" +
|
||||||
|
"686f7374056c6f63616c0000010001000000780004c000027bc00c001c000100000078001020" +
|
||||||
|
"010db8000000000000000000000123")
|
||||||
|
packetReader.sendResponse(buildMdnsPacket(addressPayload))
|
||||||
|
|
||||||
|
val serviceResolved = resolveRecord.expectCallback<ServiceResolved>()
|
||||||
|
serviceResolved.serviceInfo.let {
|
||||||
|
assertEquals(serviceName, it.serviceName)
|
||||||
|
assertEquals(".$serviceType", it.serviceType)
|
||||||
|
assertEquals(testNetwork1.network, it.network)
|
||||||
|
assertEquals(31234, it.port)
|
||||||
|
assertEquals(1, it.attributes.size)
|
||||||
|
assertArrayEquals("testvalue".encodeToByteArray(), it.attributes["testkey"])
|
||||||
|
}
|
||||||
|
assertEquals(
|
||||||
|
setOf(parseNumericAddress("192.0.2.123"), parseNumericAddress("2001:db8::123")),
|
||||||
|
serviceResolved.serviceInfo.hostAddresses.toSet())
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildConflictingAnnouncement(): ByteBuffer {
|
private fun buildConflictingAnnouncement(): ByteBuffer {
|
||||||
/*
|
/*
|
||||||
Generated with:
|
Generated with:
|
||||||
@@ -1148,21 +1232,37 @@ class NsdManagerTest {
|
|||||||
val mdnsPayload = HexDump.hexStringToByteArray("000084000000000100000000104e736454657" +
|
val mdnsPayload = HexDump.hexStringToByteArray("000084000000000100000000104e736454657" +
|
||||||
"3743132333435363738390d5f6e6d74313233343536373839045f746370056c6f63616c00002" +
|
"3743132333435363738390d5f6e6d74313233343536373839045f746370056c6f63616c00002" +
|
||||||
"18001000000780016000000007a0208636f6e666c696374056c6f63616c00")
|
"18001000000780016000000007a0208636f6e666c696374056c6f63616c00")
|
||||||
val packetBuffer = ByteBuffer.wrap(mdnsPayload)
|
replaceServiceNameAndTypeWithTestSuffix(mdnsPayload)
|
||||||
// Replace service name and types in the packet with the random ones used in the test.
|
|
||||||
|
return buildMdnsPacket(mdnsPayload)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces occurrences of "NsdTest123456789" and "_nmt123456789" in mDNS payload with the
|
||||||
|
* actual random name and type that are used by the test.
|
||||||
|
*/
|
||||||
|
private fun replaceServiceNameAndTypeWithTestSuffix(mdnsPayload: ByteArray) {
|
||||||
// Test service name and types have consistent length and are always ASCII
|
// Test service name and types have consistent length and are always ASCII
|
||||||
val testPacketName = "NsdTest123456789".encodeToByteArray()
|
val testPacketName = "NsdTest123456789".encodeToByteArray()
|
||||||
val testPacketTypePrefix = "_nmt123456789".encodeToByteArray()
|
val testPacketTypePrefix = "_nmt123456789".encodeToByteArray()
|
||||||
val encodedServiceName = serviceName.encodeToByteArray()
|
val encodedServiceName = serviceName.encodeToByteArray()
|
||||||
val encodedTypePrefix = serviceType.split('.')[0].encodeToByteArray()
|
val encodedTypePrefix = serviceType.split('.')[0].encodeToByteArray()
|
||||||
assertEquals(testPacketName.size, encodedServiceName.size)
|
|
||||||
assertEquals(testPacketTypePrefix.size, encodedTypePrefix.size)
|
|
||||||
packetBuffer.position(mdnsPayload.indexOf(testPacketName))
|
|
||||||
packetBuffer.put(encodedServiceName)
|
|
||||||
packetBuffer.position(mdnsPayload.indexOf(testPacketTypePrefix))
|
|
||||||
packetBuffer.put(encodedTypePrefix)
|
|
||||||
|
|
||||||
return buildMdnsPacket(mdnsPayload)
|
val packetBuffer = ByteBuffer.wrap(mdnsPayload)
|
||||||
|
replaceAll(packetBuffer, testPacketName, encodedServiceName)
|
||||||
|
replaceAll(packetBuffer, testPacketTypePrefix, encodedTypePrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
private tailrec fun replaceAll(buffer: ByteBuffer, source: ByteArray, replacement: ByteArray) {
|
||||||
|
assertEquals(source.size, replacement.size)
|
||||||
|
val index = buffer.array().indexOf(source)
|
||||||
|
if (index < 0) return
|
||||||
|
|
||||||
|
val origPosition = buffer.position()
|
||||||
|
buffer.position(index)
|
||||||
|
buffer.put(replacement)
|
||||||
|
buffer.position(origPosition)
|
||||||
|
replaceAll(buffer, source, replacement)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildMdnsPacket(mdnsPayload: ByteArray): ByteBuffer {
|
private fun buildMdnsPacket(mdnsPayload: ByteArray): ByteBuffer {
|
||||||
|
|||||||
Reference in New Issue
Block a user