Merge "Support mDns Known-Answer Suppression" into main
This commit is contained in:
commit
0db97a6f93
4 changed files with 342 additions and 23 deletions
|
|
@ -1716,6 +1716,8 @@ public class NsdService extends INsdManager.Stub {
|
|||
mContext, MdnsFeatureFlags.NSD_EXPIRED_SERVICES_REMOVAL))
|
||||
.setIsLabelCountLimitEnabled(mDeps.isTetheringFeatureNotChickenedOut(
|
||||
mContext, MdnsFeatureFlags.NSD_LIMIT_LABEL_COUNT))
|
||||
.setIsKnownAnswerSuppressionEnabled(mDeps.isFeatureEnabled(
|
||||
mContext, MdnsFeatureFlags.NSD_KNOWN_ANSWER_SUPPRESSION))
|
||||
.build();
|
||||
mMdnsSocketClient =
|
||||
new MdnsMultinetworkSocketClient(handler.getLooper(), mMdnsSocketProvider,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,11 @@ public class MdnsFeatureFlags {
|
|||
*/
|
||||
public static final String NSD_LIMIT_LABEL_COUNT = "nsd_limit_label_count";
|
||||
|
||||
/**
|
||||
* A feature flag to control whether the known-answer suppression should be enabled.
|
||||
*/
|
||||
public static final String NSD_KNOWN_ANSWER_SUPPRESSION = "nsd_known_answer_suppression";
|
||||
|
||||
// Flag for offload feature
|
||||
public final boolean mIsMdnsOffloadFeatureEnabled;
|
||||
|
||||
|
|
@ -53,17 +58,22 @@ public class MdnsFeatureFlags {
|
|||
// Flag for label count limit
|
||||
public final boolean mIsLabelCountLimitEnabled;
|
||||
|
||||
// Flag for known-answer suppression
|
||||
public final boolean mIsKnownAnswerSuppressionEnabled;
|
||||
|
||||
/**
|
||||
* The constructor for {@link MdnsFeatureFlags}.
|
||||
*/
|
||||
public MdnsFeatureFlags(boolean isOffloadFeatureEnabled,
|
||||
boolean includeInetAddressRecordsInProbing,
|
||||
boolean isExpiredServicesRemovalEnabled,
|
||||
boolean isLabelCountLimitEnabled) {
|
||||
boolean isLabelCountLimitEnabled,
|
||||
boolean isKnownAnswerSuppressionEnabled) {
|
||||
mIsMdnsOffloadFeatureEnabled = isOffloadFeatureEnabled;
|
||||
mIncludeInetAddressRecordsInProbing = includeInetAddressRecordsInProbing;
|
||||
mIsExpiredServicesRemovalEnabled = isExpiredServicesRemovalEnabled;
|
||||
mIsLabelCountLimitEnabled = isLabelCountLimitEnabled;
|
||||
mIsKnownAnswerSuppressionEnabled = isKnownAnswerSuppressionEnabled;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -79,6 +89,7 @@ public class MdnsFeatureFlags {
|
|||
private boolean mIncludeInetAddressRecordsInProbing;
|
||||
private boolean mIsExpiredServicesRemovalEnabled;
|
||||
private boolean mIsLabelCountLimitEnabled;
|
||||
private boolean mIsKnownAnswerSuppressionEnabled;
|
||||
|
||||
/**
|
||||
* The constructor for {@link Builder}.
|
||||
|
|
@ -88,6 +99,7 @@ public class MdnsFeatureFlags {
|
|||
mIncludeInetAddressRecordsInProbing = false;
|
||||
mIsExpiredServicesRemovalEnabled = false;
|
||||
mIsLabelCountLimitEnabled = true; // Default enabled.
|
||||
mIsKnownAnswerSuppressionEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -131,6 +143,16 @@ public class MdnsFeatureFlags {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the known-answer suppression is enabled.
|
||||
*
|
||||
* @see #NSD_KNOWN_ANSWER_SUPPRESSION
|
||||
*/
|
||||
public Builder setIsKnownAnswerSuppressionEnabled(boolean isKnownAnswerSuppressionEnabled) {
|
||||
mIsKnownAnswerSuppressionEnabled = isKnownAnswerSuppressionEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link MdnsFeatureFlags} with the arguments supplied to this builder.
|
||||
*/
|
||||
|
|
@ -138,7 +160,8 @@ public class MdnsFeatureFlags {
|
|||
return new MdnsFeatureFlags(mIsMdnsOffloadFeatureEnabled,
|
||||
mIncludeInetAddressRecordsInProbing,
|
||||
mIsExpiredServicesRemovalEnabled,
|
||||
mIsLabelCountLimitEnabled);
|
||||
mIsLabelCountLimitEnabled,
|
||||
mIsKnownAnswerSuppressionEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public class MdnsRecordRepository {
|
|||
private final Looper mLooper;
|
||||
@NonNull
|
||||
private final String[] mDeviceHostname;
|
||||
@NonNull
|
||||
private final MdnsFeatureFlags mMdnsFeatureFlags;
|
||||
|
||||
public MdnsRecordRepository(@NonNull Looper looper, @NonNull String[] deviceHostname,
|
||||
|
|
@ -502,7 +503,7 @@ public class MdnsRecordRepository {
|
|||
// Add answers from general records
|
||||
addReplyFromService(question, mGeneralRecords, null /* servicePtrRecord */,
|
||||
null /* serviceSrvRecord */, null /* serviceTxtRecord */, replyUnicast, now,
|
||||
answerInfo, additionalAnswerRecords);
|
||||
answerInfo, additionalAnswerRecords, Collections.emptyList());
|
||||
|
||||
// Add answers from each service
|
||||
for (int i = 0; i < mServices.size(); i++) {
|
||||
|
|
@ -510,7 +511,7 @@ public class MdnsRecordRepository {
|
|||
if (registration.exiting || registration.isProbing) continue;
|
||||
if (addReplyFromService(question, registration.allRecords, registration.ptrRecords,
|
||||
registration.srvRecord, registration.txtRecord, replyUnicast, now,
|
||||
answerInfo, additionalAnswerRecords)) {
|
||||
answerInfo, additionalAnswerRecords, packet.answers)) {
|
||||
registration.repliedServiceCount++;
|
||||
registration.sentPacketCount++;
|
||||
}
|
||||
|
|
@ -563,6 +564,15 @@ public class MdnsRecordRepository {
|
|||
return new MdnsReplyInfo(answerRecords, additionalAnswerRecords, delayMs, dest);
|
||||
}
|
||||
|
||||
private boolean isKnownAnswer(MdnsRecord answer, @NonNull List<MdnsRecord> knownAnswerRecords) {
|
||||
for (MdnsRecord knownAnswer : knownAnswerRecords) {
|
||||
if (answer.equals(knownAnswer) && knownAnswer.getTtl() > (answer.getTtl() / 2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add answers and additional answers for a question, from a ServiceRegistration.
|
||||
*/
|
||||
|
|
@ -572,7 +582,8 @@ public class MdnsRecordRepository {
|
|||
@Nullable RecordInfo<MdnsServiceRecord> serviceSrvRecord,
|
||||
@Nullable RecordInfo<MdnsTextRecord> serviceTxtRecord,
|
||||
boolean replyUnicast, long now, @NonNull List<RecordInfo<?>> answerInfo,
|
||||
@NonNull List<MdnsRecord> additionalAnswerRecords) {
|
||||
@NonNull List<MdnsRecord> additionalAnswerRecords,
|
||||
@NonNull List<MdnsRecord> knownAnswerRecords) {
|
||||
boolean hasDnsSdPtrRecordAnswer = false;
|
||||
boolean hasDnsSdSrvRecordAnswer = false;
|
||||
boolean hasFullyOwnedNameMatch = false;
|
||||
|
|
@ -601,6 +612,20 @@ public class MdnsRecordRepository {
|
|||
}
|
||||
|
||||
hasKnownAnswer = true;
|
||||
|
||||
// RFC6762 7.1. Known-Answer Suppression:
|
||||
// A Multicast DNS responder MUST NOT answer a Multicast DNS query if
|
||||
// the answer it would give is already included in the Answer Section
|
||||
// with an RR TTL at least half the correct value. If the RR TTL of the
|
||||
// answer as given in the Answer Section is less than half of the true
|
||||
// RR TTL as known by the Multicast DNS responder, the responder MUST
|
||||
// send an answer so as to update the querier's cache before the record
|
||||
// becomes in danger of expiration.
|
||||
if (mMdnsFeatureFlags.mIsKnownAnswerSuppressionEnabled
|
||||
&& isKnownAnswer(info.record, knownAnswerRecords)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hasDnsSdPtrRecordAnswer |= (servicePtrRecords != null
|
||||
&& CollectionUtils.any(servicePtrRecords, r -> info == r));
|
||||
hasDnsSdSrvRecordAnswer |= (info == serviceSrvRecord);
|
||||
|
|
@ -612,8 +637,6 @@ public class MdnsRecordRepository {
|
|||
continue;
|
||||
}
|
||||
|
||||
// TODO: Don't reply if in known answers of the querier (7.1) if TTL is > half
|
||||
|
||||
answerInfo.add(info);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import kotlin.test.assertEquals
|
|||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
|
|
@ -48,6 +49,13 @@ private const val TEST_SERVICE_ID_3 = 44
|
|||
private const val TEST_PORT = 12345
|
||||
private const val TEST_SUBTYPE = "_subtype"
|
||||
private const val TEST_SUBTYPE2 = "_subtype2"
|
||||
// RFC6762 10. Resource Record TTL Values and Cache Coherency
|
||||
// The recommended TTL value for Multicast DNS resource records with a host name as the resource
|
||||
// record's name (e.g., A, AAAA, HINFO) or a host name contained within the resource record's rdata
|
||||
// (e.g., SRV, reverse mapping PTR record) SHOULD be 120 seconds. The recommended TTL value for
|
||||
// other Multicast DNS resource records is 75 minutes.
|
||||
private const val LONG_TTL = 4_500_000L
|
||||
private const val SHORT_TTL = 120_000L
|
||||
private val TEST_HOSTNAME = arrayOf("Android_000102030405060708090A0B0C0D0E0F", "local")
|
||||
private val TEST_ADDRESSES = listOf(
|
||||
LinkAddress(parseNumericAddress("192.0.2.111"), 24),
|
||||
|
|
@ -120,7 +128,7 @@ class MdnsRecordRepositoryTest {
|
|||
assertEquals(MdnsServiceRecord(expectedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120_000L /* ttlMillis */,
|
||||
SHORT_TTL /* ttlMillis */,
|
||||
0 /* servicePriority */, 0 /* serviceWeight */,
|
||||
TEST_PORT, TEST_HOSTNAME), packet.authorityRecords[0])
|
||||
|
||||
|
|
@ -524,9 +532,6 @@ class MdnsRecordRepositoryTest {
|
|||
assertEquals(MdnsConstants.getMdnsIPv4Address(), reply.destination.address)
|
||||
assertEquals(MdnsConstants.MDNS_PORT, reply.destination.port)
|
||||
|
||||
// TTLs as per RFC6762 10.
|
||||
val longTtl = 4_500_000L
|
||||
val shortTtl = 120_000L
|
||||
val serviceName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
|
||||
|
||||
assertEquals(listOf(
|
||||
|
|
@ -534,7 +539,7 @@ class MdnsRecordRepositoryTest {
|
|||
queriedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
longTtl,
|
||||
LONG_TTL,
|
||||
serviceName),
|
||||
), reply.answers)
|
||||
|
||||
|
|
@ -543,13 +548,13 @@ class MdnsRecordRepositoryTest {
|
|||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
longTtl,
|
||||
LONG_TTL,
|
||||
listOf() /* entries */),
|
||||
MdnsServiceRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
shortTtl,
|
||||
SHORT_TTL,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT,
|
||||
|
|
@ -558,32 +563,32 @@ class MdnsRecordRepositoryTest {
|
|||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
shortTtl,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[0].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
shortTtl,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[1].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
shortTtl,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[2].address),
|
||||
MdnsNsecRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
longTtl,
|
||||
LONG_TTL,
|
||||
serviceName /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_TXT, MdnsRecord.TYPE_SRV)),
|
||||
MdnsNsecRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
shortTtl,
|
||||
SHORT_TTL,
|
||||
TEST_HOSTNAME /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_A, MdnsRecord.TYPE_AAAA)),
|
||||
), reply.additionalAnswers)
|
||||
|
|
@ -760,7 +765,7 @@ class MdnsRecordRepositoryTest {
|
|||
expectedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120_000L /* ttlMillis */,
|
||||
SHORT_TTL /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT,
|
||||
|
|
@ -769,24 +774,290 @@ class MdnsRecordRepositoryTest {
|
|||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120_000L /* ttlMillis */,
|
||||
SHORT_TTL /* ttlMillis */,
|
||||
TEST_ADDRESSES[0].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120_000L /* ttlMillis */,
|
||||
SHORT_TTL /* ttlMillis */,
|
||||
TEST_ADDRESSES[1].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
120_000L /* ttlMillis */,
|
||||
SHORT_TTL /* ttlMillis */,
|
||||
TEST_ADDRESSES[2].address)
|
||||
), packet.authorityRecords)
|
||||
|
||||
assertContentEquals(intArrayOf(TEST_SERVICE_ID_1), repository.clearServices())
|
||||
}
|
||||
|
||||
private fun doGetReplyWithAnswersTest(
|
||||
questions: List<MdnsRecord>,
|
||||
knownAnswers: List<MdnsRecord>,
|
||||
replyAnswers: List<MdnsRecord>,
|
||||
additionalAnswers: List<MdnsRecord>,
|
||||
expectReply: Boolean
|
||||
) {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME,
|
||||
MdnsFeatureFlags.newBuilder().setIsKnownAnswerSuppressionEnabled(true).build())
|
||||
repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
|
||||
val query = MdnsPacket(0 /* flags */, questions, knownAnswers,
|
||||
listOf() /* authorityRecords */, listOf() /* additionalRecords */)
|
||||
val src = InetSocketAddress(parseNumericAddress("192.0.2.123"), 5353)
|
||||
val reply = repository.getReply(query, src)
|
||||
|
||||
if (!expectReply) {
|
||||
assertNull(reply)
|
||||
return
|
||||
}
|
||||
|
||||
assertNotNull(reply)
|
||||
// Source address is IPv4
|
||||
assertEquals(MdnsConstants.getMdnsIPv4Address(), reply.destination.address)
|
||||
assertEquals(MdnsConstants.MDNS_PORT, reply.destination.port)
|
||||
assertEquals(replyAnswers, reply.answers)
|
||||
assertEquals(additionalAnswers, reply.additionalAnswers)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReply_HasAnswers() {
|
||||
val queriedName = arrayOf("_testservice", "_tcp", "local")
|
||||
val questions = listOf(MdnsPointerRecord(queriedName, false /* isUnicast */))
|
||||
val knownAnswers = listOf(MdnsPointerRecord(
|
||||
arrayOf("_testservice", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
arrayOf("MyTestService", "_testservice", "_tcp", "local")))
|
||||
doGetReplyWithAnswersTest(questions, knownAnswers, listOf() /* replyAnswers */,
|
||||
listOf() /* additionalAnswers */, false /* expectReply */)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReply_HasAnswers_TtlLessThanHalf() {
|
||||
val queriedName = arrayOf("_testservice", "_tcp", "local")
|
||||
val serviceName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
|
||||
val questions = listOf(MdnsPointerRecord(queriedName, false /* isUnicast */))
|
||||
val knownAnswers = listOf(MdnsPointerRecord(
|
||||
arrayOf("_testservice", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
(LONG_TTL / 2 - 1000L),
|
||||
arrayOf("MyTestService", "_testservice", "_tcp", "local")))
|
||||
val replyAnswers = listOf(MdnsPointerRecord(
|
||||
queriedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
serviceName))
|
||||
val additionalAnswers = listOf(
|
||||
MdnsTextRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
listOf() /* entries */),
|
||||
MdnsServiceRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT,
|
||||
TEST_HOSTNAME),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[0].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[1].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[2].address),
|
||||
MdnsNsecRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
serviceName /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_TXT, MdnsRecord.TYPE_SRV)),
|
||||
MdnsNsecRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_HOSTNAME /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_A, MdnsRecord.TYPE_AAAA)))
|
||||
doGetReplyWithAnswersTest(questions, knownAnswers, replyAnswers, additionalAnswers,
|
||||
true /* expectReply */)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReply_HasAnotherAnswer() {
|
||||
val queriedName = arrayOf("_testservice", "_tcp", "local")
|
||||
val serviceName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
|
||||
val questions = listOf(MdnsPointerRecord(queriedName, false /* isUnicast */))
|
||||
val knownAnswers = listOf(MdnsPointerRecord(
|
||||
queriedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
arrayOf("MyOtherTestService", "_testservice", "_tcp", "local")))
|
||||
val replyAnswers = listOf(MdnsPointerRecord(
|
||||
queriedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
serviceName))
|
||||
val additionalAnswers = listOf(
|
||||
MdnsTextRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
listOf() /* entries */),
|
||||
MdnsServiceRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT,
|
||||
TEST_HOSTNAME),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[0].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[1].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[2].address),
|
||||
MdnsNsecRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
serviceName /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_TXT, MdnsRecord.TYPE_SRV)),
|
||||
MdnsNsecRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_HOSTNAME /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_A, MdnsRecord.TYPE_AAAA)))
|
||||
doGetReplyWithAnswersTest(questions, knownAnswers, replyAnswers, additionalAnswers,
|
||||
true /* expectReply */)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReply_HasAnswers_MultiQuestions() {
|
||||
val queriedName = arrayOf("_testservice", "_tcp", "local")
|
||||
val serviceName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
|
||||
val questions = listOf(
|
||||
MdnsPointerRecord(queriedName, false /* isUnicast */),
|
||||
MdnsServiceRecord(serviceName, false /* isUnicast */))
|
||||
val knownAnswers = listOf(MdnsPointerRecord(
|
||||
queriedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
LONG_TTL - 1000L,
|
||||
serviceName))
|
||||
val replyAnswers = listOf(MdnsServiceRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
SHORT_TTL /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT,
|
||||
TEST_HOSTNAME))
|
||||
val additionalAnswers = listOf(
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[0].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[1].address),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_ADDRESSES[2].address),
|
||||
MdnsNsecRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
LONG_TTL,
|
||||
serviceName /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_SRV)),
|
||||
MdnsNsecRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
SHORT_TTL,
|
||||
TEST_HOSTNAME /* nextDomain */,
|
||||
intArrayOf(MdnsRecord.TYPE_A, MdnsRecord.TYPE_AAAA)))
|
||||
doGetReplyWithAnswersTest(questions, knownAnswers, replyAnswers, additionalAnswers,
|
||||
true /* expectReply */)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetReply_HasAnswers_MultiQuestions_NoReply() {
|
||||
val queriedName = arrayOf("_testservice", "_tcp", "local")
|
||||
val serviceName = arrayOf("MyTestService", "_testservice", "_tcp", "local")
|
||||
val questions = listOf(
|
||||
MdnsPointerRecord(queriedName, false /* isUnicast */),
|
||||
MdnsServiceRecord(serviceName, false /* isUnicast */))
|
||||
val knownAnswers = listOf(
|
||||
MdnsPointerRecord(
|
||||
queriedName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
LONG_TTL - 1000L,
|
||||
serviceName),
|
||||
MdnsServiceRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
SHORT_TTL - 15_000L,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT,
|
||||
TEST_HOSTNAME))
|
||||
doGetReplyWithAnswersTest(questions, knownAnswers, listOf() /* replyAnswers */,
|
||||
listOf() /* additionalAnswers */, false /* expectReply */)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MdnsRecordRepository.initWithService(
|
||||
|
|
|
|||
Loading…
Reference in a new issue