Skip subtype PTR records in announcements/offload
Skip including the subtype PTR query for both announcement and offload packets. This is necessary because devices like Googlecast have numerous subtypes. Including these subtypes in the packets can easily exceed the MTU limit. Furthermore, the Wi-Fi firmware has limited RAM available for hardware offload, and including subtypes would consume excessive memory resources needed for the offload code. Test: TH Flag: EXEMPT bug fix Change-Id: I2575659983579da0bbf4ff104ba5b8111ee9585e
This commit is contained in:
parent
bb2c4e66ef
commit
e41b66393c
9 changed files with 423 additions and 74 deletions
|
|
@ -52,6 +52,12 @@ public final class AdvertisingRequest implements Parcelable {
|
|||
*/
|
||||
public static final long FLAG_SKIP_PROBING = 1 << 1;
|
||||
|
||||
/**
|
||||
* Don't announce the subtype of the service.
|
||||
* @hide
|
||||
*/
|
||||
public static final long FLAG_SKIP_SUBTYPE_ANNOUNCEMENTS = 1L << 63;
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@LongDef(flag = true, prefix = {"FLAG_"}, value = {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
|||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
|
||||
import static android.net.nsd.AdvertisingRequest.FLAG_SKIP_PROBING;
|
||||
import static android.net.nsd.AdvertisingRequest.FLAG_SKIP_SUBTYPE_ANNOUNCEMENTS;
|
||||
import static android.net.nsd.NsdManager.MDNS_DISCOVERY_MANAGER_EVENT;
|
||||
import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
|
||||
import static android.net.nsd.NsdManager.RESOLVE_SERVICE_SUCCEEDED;
|
||||
|
|
@ -1048,12 +1049,15 @@ public class NsdService extends INsdManager.Stub {
|
|||
serviceInfo.setSubtypes(subtypes);
|
||||
maybeStartMonitoringSockets();
|
||||
final boolean skipProbing = (advertisingRequest.getFlags()
|
||||
& FLAG_SKIP_PROBING) > 0;
|
||||
& FLAG_SKIP_PROBING) != 0;
|
||||
final boolean skipSubtypeAnnouncements = (advertisingRequest.getFlags()
|
||||
& FLAG_SKIP_SUBTYPE_ANNOUNCEMENTS) != 0;
|
||||
final MdnsAdvertisingOptions mdnsAdvertisingOptions =
|
||||
MdnsAdvertisingOptions.newBuilder()
|
||||
.setIsOnlyUpdate(isUpdateOnly)
|
||||
.setSkipProbing(skipProbing)
|
||||
.setTtl(advertisingRequest.getTtl())
|
||||
.setSkipSubtypeAnnouncements(skipSubtypeAnnouncements)
|
||||
.build();
|
||||
mAdvertiser.addOrUpdateService(transactionId, serviceInfo,
|
||||
mdnsAdvertisingOptions, clientInfo.mUid);
|
||||
|
|
|
|||
|
|
@ -1027,17 +1027,13 @@ public class MdnsAdvertiser {
|
|||
});
|
||||
}
|
||||
|
||||
private List<String> getOffloadSubtype(@NonNull NsdServiceInfo nsdServiceInfo) {
|
||||
// Workaround: Google Cast doesn't announce subtypes per DNS-SD/mDNS spec.
|
||||
// Thus, subtypes aren't offloaded; only "_googlecast._tcp" is.
|
||||
// Subtype responses occur when hardware offload is off.
|
||||
// This solution works because Google Cast doesn't follow the intended usage of subtypes in
|
||||
// the spec, as it always discovers for both the subtype+base type, and only uses the mDNS
|
||||
// subtype as an optimization.
|
||||
if (nsdServiceInfo.getServiceType().equals("_googlecast._tcp")) {
|
||||
private List<String> getOffloadSubtype(@NonNull Registration registration) {
|
||||
final NsdServiceInfo serviceInfo = registration.getServiceInfo();
|
||||
// If skipSubtypeAnnouncements is set, we should not offload subtypes.
|
||||
if (registration.mAdvertisingOptions.skipSubtypeAnnouncements()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>(nsdServiceInfo.getSubtypes());
|
||||
return new ArrayList<>(serviceInfo.getSubtypes());
|
||||
}
|
||||
|
||||
private OffloadServiceInfoWrapper createOffloadService(int serviceId,
|
||||
|
|
@ -1050,7 +1046,7 @@ public class MdnsAdvertiser {
|
|||
final OffloadServiceInfo offloadServiceInfo = new OffloadServiceInfo(
|
||||
new OffloadServiceInfo.Key(nsdServiceInfo.getServiceName(),
|
||||
nsdServiceInfo.getServiceType()),
|
||||
getOffloadSubtype(nsdServiceInfo),
|
||||
getOffloadSubtype(registration),
|
||||
String.join(".", mDeviceHostName),
|
||||
rawOffloadPacket,
|
||||
priority,
|
||||
|
|
|
|||
|
|
@ -35,14 +35,17 @@ public class MdnsAdvertisingOptions {
|
|||
@Nullable
|
||||
private final Duration mTtl;
|
||||
private final boolean mSkipProbing;
|
||||
private final boolean mSkipSubtypeAnnouncements;
|
||||
|
||||
/**
|
||||
* Parcelable constructs for a {@link MdnsAdvertisingOptions}.
|
||||
*/
|
||||
MdnsAdvertisingOptions(boolean isOnlyUpdate, @Nullable Duration ttl, boolean skipProbing) {
|
||||
MdnsAdvertisingOptions(boolean isOnlyUpdate, @Nullable Duration ttl, boolean skipProbing,
|
||||
boolean skipSubtypeAnnouncements) {
|
||||
this.mIsOnlyUpdate = isOnlyUpdate;
|
||||
this.mTtl = ttl;
|
||||
this.mSkipProbing = skipProbing;
|
||||
this.mSkipSubtypeAnnouncements = skipSubtypeAnnouncements;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -84,6 +87,13 @@ public class MdnsAdvertisingOptions {
|
|||
return mTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if subtype announcements should be skipped.
|
||||
*/
|
||||
public boolean skipSubtypeAnnouncements() {
|
||||
return mSkipSubtypeAnnouncements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
|
|
@ -93,19 +103,36 @@ public class MdnsAdvertisingOptions {
|
|||
} else {
|
||||
final MdnsAdvertisingOptions otherOptions = (MdnsAdvertisingOptions) other;
|
||||
return mIsOnlyUpdate == otherOptions.mIsOnlyUpdate
|
||||
&& mSkipProbing == otherOptions.mSkipProbing
|
||||
&& mSkipSubtypeAnnouncements == otherOptions.mSkipSubtypeAnnouncements
|
||||
&& Objects.equals(mTtl, otherOptions.mTtl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mIsOnlyUpdate, mTtl);
|
||||
return Objects.hash(mIsOnlyUpdate, mTtl, mSkipProbing, mSkipSubtypeAnnouncements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MdnsAdvertisingOptions{" + "mIsOnlyUpdate=" + mIsOnlyUpdate + ", mTtl=" + mTtl
|
||||
+ '}';
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("MdnsAdvertisingOptions{");
|
||||
if (mIsOnlyUpdate) {
|
||||
sb.append(" isOnlyUpdate");
|
||||
}
|
||||
if (mSkipProbing) {
|
||||
sb.append(" skipProbing");
|
||||
}
|
||||
if (mSkipSubtypeAnnouncements) {
|
||||
sb.append(" skipSubtypeAnnouncements");
|
||||
}
|
||||
if (mTtl != null) {
|
||||
sb.append(" ttl=");
|
||||
sb.append(mTtl);
|
||||
}
|
||||
sb.append(" }");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -114,6 +141,7 @@ public class MdnsAdvertisingOptions {
|
|||
public static final class Builder {
|
||||
private boolean mIsOnlyUpdate = false;
|
||||
private boolean mSkipProbing = false;
|
||||
private boolean mSkipSubtypeAnnouncements = false;
|
||||
@Nullable
|
||||
private Duration mTtl;
|
||||
|
||||
|
|
@ -144,11 +172,20 @@ public class MdnsAdvertisingOptions {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to skip subtype announcements.
|
||||
*/
|
||||
public Builder setSkipSubtypeAnnouncements(boolean skipSubtypeAnnouncements) {
|
||||
this.mSkipSubtypeAnnouncements = skipSubtypeAnnouncements;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link MdnsAdvertisingOptions} with the arguments supplied to this builder.
|
||||
*/
|
||||
public MdnsAdvertisingOptions build() {
|
||||
return new MdnsAdvertisingOptions(mIsOnlyUpdate, mTtl, mSkipProbing);
|
||||
return new MdnsAdvertisingOptions(mIsOnlyUpdate, mTtl, mSkipProbing,
|
||||
mSkipSubtypeAnnouncements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ public class MdnsInterfaceAdvertiser implements MulticastPacketReader.PacketHand
|
|||
public void addService(int id, NsdServiceInfo service,
|
||||
@NonNull MdnsAdvertisingOptions advertisingOptions) throws NameConflictException {
|
||||
final int replacedExitingService =
|
||||
mRecordRepository.addService(id, service, advertisingOptions.getTtl());
|
||||
mRecordRepository.addService(id, service, advertisingOptions);
|
||||
// Cancel announcements for the existing service. This only happens for exiting services
|
||||
// (so cancelling exiting announcements), as per RecordRepository.addService.
|
||||
if (replacedExitingService >= 0) {
|
||||
|
|
|
|||
|
|
@ -202,6 +202,8 @@ public class MdnsRecordRepository {
|
|||
public final List<RecordInfo<MdnsInetAddressRecord>> addressRecords;
|
||||
@NonNull
|
||||
public final NsdServiceInfo serviceInfo;
|
||||
@NonNull
|
||||
private final MdnsAdvertisingOptions mAdvertisingOptions;
|
||||
|
||||
/**
|
||||
* Whether the service is sending exit announcements and will be destroyed soon.
|
||||
|
|
@ -223,9 +225,6 @@ public class MdnsRecordRepository {
|
|||
*/
|
||||
private boolean isProbing;
|
||||
|
||||
@Nullable
|
||||
private Duration ttl;
|
||||
|
||||
/**
|
||||
* Create a ServiceRegistration with only update the subType.
|
||||
*/
|
||||
|
|
@ -234,17 +233,38 @@ public class MdnsRecordRepository {
|
|||
NsdServiceInfo newServiceInfo = new NsdServiceInfo(serviceInfo);
|
||||
newServiceInfo.setSubtypes(newSubtypes);
|
||||
return new ServiceRegistration(srvRecord.record.getServiceHost(), newServiceInfo,
|
||||
repliedServiceCount, sentPacketCount, exiting, isProbing, ttl,
|
||||
repliedServiceCount, sentPacketCount, exiting, isProbing, mAdvertisingOptions,
|
||||
featureFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filtered all records of the service registration.
|
||||
*/
|
||||
List<RecordInfo<?>> getFilteredAllRecords() {
|
||||
return CollectionUtils.filter(allRecords,
|
||||
info -> !mAdvertisingOptions.skipSubtypeAnnouncements() || !isSubtypePtrRecord(
|
||||
info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filtered ptr records of the service registration.
|
||||
*/
|
||||
List<RecordInfo<MdnsPointerRecord>> getFilteredPtrRecords() {
|
||||
return CollectionUtils.filter(ptrRecords,
|
||||
info -> !mAdvertisingOptions.skipSubtypeAnnouncements() || !isSubtypePtrRecord(
|
||||
info));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a ServiceRegistration for dns-sd service registration (RFC6763).
|
||||
*/
|
||||
ServiceRegistration(@NonNull String[] deviceHostname, @NonNull NsdServiceInfo serviceInfo,
|
||||
int repliedServiceCount, int sentPacketCount, boolean exiting, boolean isProbing,
|
||||
@Nullable Duration ttl, @NonNull MdnsFeatureFlags featureFlags) {
|
||||
@NonNull MdnsAdvertisingOptions advertisingOptions,
|
||||
@NonNull MdnsFeatureFlags featureFlags) {
|
||||
this.serviceInfo = serviceInfo;
|
||||
this.mAdvertisingOptions = advertisingOptions;
|
||||
|
||||
final long nonNameRecordsTtlMillis;
|
||||
final long nameRecordsTtlMillis;
|
||||
|
|
@ -253,6 +273,7 @@ public class MdnsRecordRepository {
|
|||
// This is typically useful for SRP (Service Registration Protocol:
|
||||
// https://datatracker.ietf.org/doc/html/draft-ietf-dnssd-srp-24) Advertising Proxy
|
||||
// where all records in a single SRP are required the same TTL.
|
||||
final Duration ttl = advertisingOptions.getTtl();
|
||||
if (ttl != null) {
|
||||
nonNameRecordsTtlMillis = ttl.toMillis();
|
||||
nameRecordsTtlMillis = ttl.toMillis();
|
||||
|
|
@ -398,10 +419,11 @@ public class MdnsRecordRepository {
|
|||
* @param serviceInfo Service to advertise
|
||||
*/
|
||||
ServiceRegistration(@NonNull String[] deviceHostname, @NonNull NsdServiceInfo serviceInfo,
|
||||
int repliedServiceCount, int sentPacketCount, @Nullable Duration ttl,
|
||||
int repliedServiceCount, int sentPacketCount,
|
||||
@NonNull MdnsAdvertisingOptions advertisingOptions,
|
||||
@NonNull MdnsFeatureFlags featureFlags) {
|
||||
this(deviceHostname, serviceInfo,repliedServiceCount, sentPacketCount,
|
||||
false /* exiting */, true /* isProbing */, ttl, featureFlags);
|
||||
false /* exiting */, true /* isProbing */, advertisingOptions, featureFlags);
|
||||
}
|
||||
|
||||
void setProbing(boolean probing) {
|
||||
|
|
@ -467,12 +489,13 @@ public class MdnsRecordRepository {
|
|||
* This may remove/replace any existing service that used the name added but is exiting.
|
||||
* @param serviceId A unique service ID.
|
||||
* @param serviceInfo Service info to add.
|
||||
* @param ttl the TTL duration for all records of {@code serviceInfo} or {@code null}
|
||||
* @param advertisingOptions the advertiser options for this service.
|
||||
* @return If the added service replaced another with a matching name (which was exiting), the
|
||||
* ID of the replaced service.
|
||||
* @throws NameConflictException There is already a (non-exiting) service using the name.
|
||||
*/
|
||||
public int addService(int serviceId, NsdServiceInfo serviceInfo, @Nullable Duration ttl)
|
||||
public int addService(int serviceId, NsdServiceInfo serviceInfo,
|
||||
@NonNull MdnsAdvertisingOptions advertisingOptions)
|
||||
throws NameConflictException {
|
||||
if (mServices.contains(serviceId)) {
|
||||
throw new IllegalArgumentException(
|
||||
|
|
@ -488,7 +511,7 @@ public class MdnsRecordRepository {
|
|||
|
||||
final ServiceRegistration registration = new ServiceRegistration(
|
||||
mDeviceHostname, serviceInfo, NO_PACKET /* repliedServiceCount */,
|
||||
NO_PACKET /* sentPacketCount */, ttl,
|
||||
NO_PACKET /* sentPacketCount */, advertisingOptions,
|
||||
mMdnsFeatureFlags);
|
||||
mServices.put(serviceId, registration);
|
||||
|
||||
|
|
@ -588,14 +611,14 @@ public class MdnsRecordRepository {
|
|||
if (registration == null) return null;
|
||||
if (registration.exiting) return null;
|
||||
|
||||
// Send exit (TTL 0) for the PTR records, if at least one was sent (in particular don't send
|
||||
// if still probing)
|
||||
if (CollectionUtils.all(registration.ptrRecords, r -> r.lastSentTimeMs == 0L)) {
|
||||
registration.exiting = true;
|
||||
final List<RecordInfo<MdnsPointerRecord>> filteredRecords = CollectionUtils.filter(
|
||||
registration.getFilteredPtrRecords(), r -> r.lastSentTimeMs != 0L);
|
||||
if (filteredRecords.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
registration.exiting = true;
|
||||
final List<MdnsRecord> expiredRecords = CollectionUtils.map(registration.ptrRecords,
|
||||
final List<MdnsRecord> expiredRecords = CollectionUtils.map(
|
||||
filteredRecords,
|
||||
r -> new MdnsPointerRecord(
|
||||
r.record.getName(),
|
||||
0L /* receiptTimeMillis */,
|
||||
|
|
@ -1100,6 +1123,14 @@ public class MdnsRecordRepository {
|
|||
return makeAnnouncementInfo(serviceId, registration);
|
||||
}
|
||||
|
||||
private static boolean isSubtypePtrRecord(@NonNull RecordInfo<?> info) {
|
||||
if (!(info.record instanceof MdnsPointerRecord)) {
|
||||
return false;
|
||||
}
|
||||
final String[] recordName = info.record.getName();
|
||||
return recordName.length > 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the announcement info of the given service ID.
|
||||
*
|
||||
|
|
@ -1132,13 +1163,15 @@ public class MdnsRecordRepository {
|
|||
});
|
||||
}
|
||||
|
||||
final List<RecordInfo<?>> filteredAllRecords = registration.getFilteredAllRecords();
|
||||
// All service records
|
||||
for (RecordInfo<?> info : registration.allRecords) {
|
||||
for (RecordInfo<?> info : filteredAllRecords) {
|
||||
answersSet.add(info.record);
|
||||
}
|
||||
|
||||
// ignore all the PTR query with subtype
|
||||
addNsecRecordsForUniqueNames(additionalAnswers,
|
||||
mGeneralRecords.iterator(), registration.allRecords.iterator());
|
||||
mGeneralRecords.iterator(), filteredAllRecords.iterator());
|
||||
|
||||
return new MdnsAnnouncer.AnnouncementInfo(serviceId,
|
||||
new ArrayList<>(answersSet), additionalAnswers);
|
||||
|
|
@ -1158,6 +1191,10 @@ public class MdnsRecordRepository {
|
|||
|
||||
// Adds all PTR, SRV, TXT, A/AAAA records.
|
||||
for (RecordInfo<MdnsPointerRecord> ptrRecord : registration.ptrRecords) {
|
||||
if (registration.mAdvertisingOptions.skipSubtypeAnnouncements() && isSubtypePtrRecord(
|
||||
ptrRecord)) {
|
||||
continue;
|
||||
}
|
||||
answers.add(ptrRecord.record);
|
||||
}
|
||||
if (registration.srvRecord != null) {
|
||||
|
|
@ -1424,8 +1461,8 @@ public class MdnsRecordRepository {
|
|||
if (existing == null) return null;
|
||||
|
||||
final ServiceRegistration newService = new ServiceRegistration(mDeviceHostname, newInfo,
|
||||
existing.repliedServiceCount, existing.sentPacketCount, existing.ttl,
|
||||
mMdnsFeatureFlags);
|
||||
existing.repliedServiceCount, existing.sentPacketCount,
|
||||
existing.mAdvertisingOptions, mMdnsFeatureFlags);
|
||||
mServices.put(serviceId, newService);
|
||||
return makeProbingInfo(serviceId, newService);
|
||||
}
|
||||
|
|
@ -1438,7 +1475,7 @@ public class MdnsRecordRepository {
|
|||
if (registration == null) return;
|
||||
|
||||
final long now = mDeps.elapsedRealTime();
|
||||
for (RecordInfo<?> record : registration.allRecords) {
|
||||
for (RecordInfo<?> record : registration.getFilteredAllRecords()) {
|
||||
record.lastSentTimeMs = now;
|
||||
record.lastAdvertisedOnIpv4TimeMs = now;
|
||||
record.lastAdvertisedOnIpv6TimeMs = now;
|
||||
|
|
|
|||
|
|
@ -576,14 +576,14 @@ class MdnsAdvertiserTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun testAddService_NoSubtypeForGoogleCastOffload() {
|
||||
fun testAddService_NoSubtypeForOffloadWhenSkipAnnouncements() {
|
||||
val advertiser =
|
||||
MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps, sharedlog, flags, context)
|
||||
postSync {
|
||||
advertiser.addOrUpdateService(
|
||||
SERVICE_ID_1,
|
||||
GOOGLECAST_SERVICE,
|
||||
DEFAULT_ADVERTISING_OPTION,
|
||||
MdnsAdvertisingOptions.newBuilder().setSkipSubtypeAnnouncements(true).build(),
|
||||
TEST_CLIENT_UID_1
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -575,7 +575,11 @@ class MdnsInterfaceAdvertiserTest {
|
|||
doReturn(testProbingInfo).`when`(repository).setServiceProbing(serviceId)
|
||||
|
||||
advertiser.addService(serviceId, serviceInfo, MdnsAdvertisingOptions.getDefaultOptions())
|
||||
verify(repository).addService(serviceId, serviceInfo, null /* ttl */)
|
||||
verify(repository).addService(
|
||||
serviceId,
|
||||
serviceInfo,
|
||||
MdnsAdvertisingOptions.newBuilder().build()
|
||||
)
|
||||
verify(prober).startProbing(testProbingInfo)
|
||||
|
||||
return testProbingInfo
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@ private val TEST_TEMPORARY_IPV6_ADDRESS = LinkAddress(
|
|||
0 /* lifetime */
|
||||
)
|
||||
|
||||
private val GOOGLECAST_SERVICE = NsdServiceInfo().apply {
|
||||
serviceType = "_googlecast._tcp"
|
||||
serviceName = "MyTestService"
|
||||
port = TEST_PORT
|
||||
}
|
||||
|
||||
private val TEST_SERVICE_1 = NsdServiceInfo().apply {
|
||||
serviceType = "_testservice._tcp"
|
||||
serviceName = "MyTestService"
|
||||
|
|
@ -147,6 +153,8 @@ private val TEST_PUBLIC_KEY_2 = hexStringToByteArray(
|
|||
"270962d4"
|
||||
)
|
||||
|
||||
private val DEFAULT_OPTION = MdnsAdvertisingOptions.newBuilder().build()
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
class MdnsRecordRepositoryTest {
|
||||
|
|
@ -195,10 +203,13 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testAddServiceAndProbe() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
val option = MdnsAdvertisingOptions.newBuilder()
|
||||
.setTtl(Duration.ofSeconds(50))
|
||||
.build()
|
||||
assertEquals(0, repository.servicesCount)
|
||||
assertEquals(
|
||||
-1,
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, Duration.ofSeconds(50))
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, option)
|
||||
)
|
||||
assertEquals(1, repository.servicesCount)
|
||||
|
||||
|
|
@ -238,10 +249,10 @@ class MdnsRecordRepositoryTest {
|
|||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.initWithService(TEST_SERVICE_ID_1, TEST_SERVICE_1)
|
||||
assertFailsWith(NameConflictException::class) {
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
}
|
||||
assertFailsWith(NameConflictException::class) {
|
||||
repository.addService(TEST_SERVICE_ID_3, TEST_SERVICE_3, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_3, TEST_SERVICE_3, DEFAULT_OPTION)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -288,9 +299,9 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testInvalidReuseOfServiceId() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_2, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_2, DEFAULT_OPTION)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +310,7 @@ class MdnsRecordRepositoryTest {
|
|||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
assertFalse(repository.hasActiveService(TEST_SERVICE_ID_1))
|
||||
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
assertTrue(repository.hasActiveService(TEST_SERVICE_ID_1))
|
||||
|
||||
val probingInfo = repository.setServiceProbing(TEST_SERVICE_ID_1)
|
||||
|
|
@ -391,6 +402,258 @@ class MdnsRecordRepositoryTest {
|
|||
assertEquals(0, repository.servicesCount)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnnouncementsWithOutSubtypes() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
val option = MdnsAdvertisingOptions.newBuilder().setSkipSubtypeAnnouncements(true).build()
|
||||
val announcementInfo = repository.initWithService(
|
||||
TEST_SERVICE_ID_1,
|
||||
GOOGLECAST_SERVICE,
|
||||
setOf(TEST_SUBTYPE, TEST_SUBTYPE2),
|
||||
option = option
|
||||
)
|
||||
repository.onAdvertisementSent(TEST_SERVICE_ID_1, 2 /* sentPacketCount */)
|
||||
val packet = announcementInfo.getPacket(0)
|
||||
|
||||
assertEquals(0, packet.transactionId)
|
||||
assertEquals(0x8400 /* response, authoritative */, packet.flags)
|
||||
assertEquals(0, packet.questions.size)
|
||||
assertEquals(0, packet.authorityRecords.size)
|
||||
|
||||
val serviceType = arrayOf("_googlecast", "_tcp", "local")
|
||||
val serviceName = arrayOf("MyTestService", "_googlecast", "_tcp", "local")
|
||||
val v4AddrRev = getReverseDnsAddress(TEST_ADDRESSES[0].address)
|
||||
val v6Addr1Rev = getReverseDnsAddress(TEST_ADDRESSES[1].address)
|
||||
val v6Addr2Rev = getReverseDnsAddress(TEST_ADDRESSES[2].address)
|
||||
|
||||
assertThat(packet.answers).containsExactly(
|
||||
// Reverse address and address records for the hostname
|
||||
MdnsPointerRecord(
|
||||
v4AddrRev,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_HOSTNAME
|
||||
),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_ADDRESSES[0].address
|
||||
),
|
||||
MdnsPointerRecord(
|
||||
v6Addr1Rev,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_HOSTNAME
|
||||
),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_ADDRESSES[1].address
|
||||
),
|
||||
MdnsPointerRecord(
|
||||
v6Addr2Rev,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_HOSTNAME
|
||||
),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_ADDRESSES[2].address
|
||||
),
|
||||
// Service registration records (RFC6763)
|
||||
MdnsPointerRecord(
|
||||
serviceType,
|
||||
0L /* receiptTimeMillis */,
|
||||
// Not a unique name owned by the announcer, so cacheFlush=false
|
||||
false /* cacheFlush */,
|
||||
4500000L /* ttlMillis */,
|
||||
serviceName
|
||||
),
|
||||
MdnsServiceRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT /* servicePort */,
|
||||
TEST_HOSTNAME
|
||||
),
|
||||
MdnsTextRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
4500000L /* ttlMillis */,
|
||||
emptyList() /* entries */
|
||||
),
|
||||
// Service type enumeration record (RFC6763 9.)
|
||||
MdnsPointerRecord(
|
||||
arrayOf("_services", "_dns-sd", "_udp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
4500000L /* ttlMillis */,
|
||||
serviceType
|
||||
))
|
||||
|
||||
assertContentEquals(listOf(
|
||||
MdnsNsecRecord(
|
||||
v4AddrRev,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
v4AddrRev,
|
||||
intArrayOf(TYPE_PTR)
|
||||
),
|
||||
MdnsNsecRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_HOSTNAME,
|
||||
intArrayOf(TYPE_A, TYPE_AAAA)
|
||||
),
|
||||
MdnsNsecRecord(
|
||||
v6Addr1Rev,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
v6Addr1Rev,
|
||||
intArrayOf(TYPE_PTR)
|
||||
),
|
||||
MdnsNsecRecord(
|
||||
v6Addr2Rev,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
v6Addr2Rev,
|
||||
intArrayOf(TYPE_PTR)
|
||||
),
|
||||
MdnsNsecRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
4500000L /* ttlMillis */,
|
||||
serviceName,
|
||||
intArrayOf(TYPE_TXT, TYPE_SRV)
|
||||
)
|
||||
), packet.additionalRecords)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExitAnnouncementsWithOutSubtypes() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
val option = MdnsAdvertisingOptions.newBuilder().setSkipSubtypeAnnouncements(true).build()
|
||||
repository.initWithService(
|
||||
TEST_SERVICE_ID_1,
|
||||
TEST_SERVICE_1,
|
||||
setOf(TEST_SUBTYPE, TEST_SUBTYPE2),
|
||||
option = option
|
||||
)
|
||||
repository.onAdvertisementSent(TEST_SERVICE_ID_1, 2 /* sentPacketCount */)
|
||||
|
||||
val exitAnnouncement = repository.exitService(TEST_SERVICE_ID_1)
|
||||
assertNotNull(exitAnnouncement)
|
||||
assertEquals(1, repository.servicesCount)
|
||||
val packet = exitAnnouncement.getPacket(0)
|
||||
|
||||
assertEquals(0, packet.transactionId)
|
||||
assertEquals(0x8400 /* response, authoritative */, packet.flags)
|
||||
assertEquals(0, packet.questions.size)
|
||||
assertEquals(0, packet.authorityRecords.size)
|
||||
assertEquals(0, packet.additionalRecords.size)
|
||||
|
||||
assertThat(packet.answers).containsExactly(
|
||||
MdnsPointerRecord(
|
||||
arrayOf("_testservice", "_tcp", "local"),
|
||||
0L /* receiptTimeMillis */,
|
||||
false /* cacheFlush */,
|
||||
0L /* ttlMillis */,
|
||||
arrayOf("MyTestService", "_testservice", "_tcp", "local")
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetOffloadPacketWithoutSubtype() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
val ipAddress = TEST_ADDRESSES.toMutableList()
|
||||
ipAddress.add(TEST_TEMPORARY_IPV6_ADDRESS)
|
||||
val option = MdnsAdvertisingOptions.newBuilder().setSkipSubtypeAnnouncements(true).build()
|
||||
repository.initWithService(
|
||||
TEST_SERVICE_ID_1,
|
||||
GOOGLECAST_SERVICE,
|
||||
setOf(TEST_SUBTYPE, TEST_SUBTYPE2),
|
||||
addresses = ipAddress,
|
||||
option = option
|
||||
)
|
||||
val serviceName = arrayOf("MyTestService", "_googlecast", "_tcp", "local")
|
||||
val serviceType = arrayOf("_googlecast", "_tcp", "local")
|
||||
val offloadPacket = repository.getOffloadPacket(TEST_SERVICE_ID_1)
|
||||
assertEquals(0, offloadPacket.transactionId)
|
||||
assertEquals(0x8400, offloadPacket.flags)
|
||||
assertEquals(0, offloadPacket.questions.size)
|
||||
assertEquals(0, offloadPacket.additionalRecords.size)
|
||||
assertEquals(0, offloadPacket.authorityRecords.size)
|
||||
assertContentEquals(listOf(
|
||||
MdnsPointerRecord(
|
||||
serviceType,
|
||||
0L /* receiptTimeMillis */,
|
||||
// Not a unique name owned by the announcer, so cacheFlush=false
|
||||
false /* cacheFlush */,
|
||||
4500000L /* ttlMillis */,
|
||||
serviceName
|
||||
),
|
||||
MdnsServiceRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
0 /* servicePriority */,
|
||||
0 /* serviceWeight */,
|
||||
TEST_PORT /* servicePort */,
|
||||
TEST_HOSTNAME
|
||||
),
|
||||
MdnsTextRecord(
|
||||
serviceName,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
4500000L /* ttlMillis */,
|
||||
emptyList() /* entries */
|
||||
),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_ADDRESSES[0].address
|
||||
),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_ADDRESSES[1].address
|
||||
),
|
||||
MdnsInetAddressRecord(
|
||||
TEST_HOSTNAME,
|
||||
0L /* receiptTimeMillis */,
|
||||
true /* cacheFlush */,
|
||||
120000L /* ttlMillis */,
|
||||
TEST_ADDRESSES[2].address
|
||||
),
|
||||
), offloadPacket.answers)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExitingServiceReAdded() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
|
|
@ -400,7 +663,7 @@ class MdnsRecordRepositoryTest {
|
|||
|
||||
assertEquals(
|
||||
TEST_SERVICE_ID_1,
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
)
|
||||
assertEquals(1, repository.servicesCount)
|
||||
|
||||
|
|
@ -1188,7 +1451,7 @@ class MdnsRecordRepositoryTest {
|
|||
subtypes = setOf(),
|
||||
listOf(LinkAddress(parseNumericAddress("192.0.2.111"), 24))
|
||||
)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_2, TEST_CUSTOM_HOST_2, null /* ttl */)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_2, TEST_CUSTOM_HOST_2, DEFAULT_OPTION)
|
||||
val src = InetSocketAddress(parseNumericAddress("fe80::123"), 5353)
|
||||
|
||||
val query = makeQuery(TYPE_AAAA to TEST_CUSTOM_HOST_1_NAME)
|
||||
|
|
@ -1498,7 +1761,7 @@ class MdnsRecordRepositoryTest {
|
|||
repository.addService(
|
||||
TEST_SERVICE_CUSTOM_HOST_ID_1,
|
||||
TEST_SERVICE_CUSTOM_HOST_1,
|
||||
null /* ttl */
|
||||
DEFAULT_OPTION
|
||||
)
|
||||
repository.removeService(TEST_CUSTOM_HOST_ID_1)
|
||||
repository.removeService(TEST_SERVICE_CUSTOM_HOST_ID_1)
|
||||
|
|
@ -1744,8 +2007,8 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testGetConflictingServices() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, DEFAULT_OPTION)
|
||||
|
||||
val packet = MdnsPacket(
|
||||
0 /* flags */,
|
||||
|
|
@ -1785,8 +2048,8 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testGetConflictingServicesCaseInsensitive() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, DEFAULT_OPTION)
|
||||
|
||||
val packet = MdnsPacket(
|
||||
0 /* flags */,
|
||||
|
|
@ -1826,8 +2089,8 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testGetConflictingServices_customHosts_differentAddresses() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_1, TEST_CUSTOM_HOST_1, null /* ttl */)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_2, TEST_CUSTOM_HOST_2, null /* ttl */)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_1, TEST_CUSTOM_HOST_1, DEFAULT_OPTION)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_2, TEST_CUSTOM_HOST_2, DEFAULT_OPTION)
|
||||
|
||||
val packet = MdnsPacket(
|
||||
0, /* flags */
|
||||
|
|
@ -1861,8 +2124,8 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testGetConflictingServices_customHosts_moreAddressesThanUs_conflict() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_1, TEST_CUSTOM_HOST_1, null /* ttl */)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_2, TEST_CUSTOM_HOST_2, null /* ttl */)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_1, TEST_CUSTOM_HOST_1, DEFAULT_OPTION)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_2, TEST_CUSTOM_HOST_2, DEFAULT_OPTION)
|
||||
|
||||
val packet = MdnsPacket(
|
||||
0, /* flags */
|
||||
|
|
@ -1931,7 +2194,7 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testGetConflictingServices_customHostsReplyHasSameNameRecord_conflictDuringProbing() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_1, TEST_CUSTOM_HOST_1, null /* ttl */)
|
||||
repository.addService(TEST_CUSTOM_HOST_ID_1, TEST_CUSTOM_HOST_1, DEFAULT_OPTION)
|
||||
repository.addServiceAndFinishProbing(TEST_CUSTOM_HOST_ID_2, TEST_CUSTOM_HOST_2)
|
||||
|
||||
val packet = MdnsPacket(
|
||||
|
|
@ -2035,7 +2298,7 @@ class MdnsRecordRepositoryTest {
|
|||
serviceName = "MyTestService"
|
||||
port = TEST_PORT
|
||||
publicKey = TEST_PUBLIC_KEY
|
||||
}, null /* ttl */)
|
||||
}, DEFAULT_OPTION)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
|
|
@ -2069,7 +2332,7 @@ class MdnsRecordRepositoryTest {
|
|||
serviceName = "MyTestService"
|
||||
port = TEST_PORT
|
||||
publicKey = TEST_PUBLIC_KEY
|
||||
}, null /* null */)
|
||||
}, DEFAULT_OPTION)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
|
|
@ -2137,7 +2400,7 @@ class MdnsRecordRepositoryTest {
|
|||
repository.addService(TEST_SERVICE_ID_1, NsdServiceInfo().apply {
|
||||
hostname = "MyHost"
|
||||
publicKey = TEST_PUBLIC_KEY
|
||||
}, null /* ttl */)
|
||||
}, DEFAULT_OPTION)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
|
|
@ -2172,7 +2435,7 @@ class MdnsRecordRepositoryTest {
|
|||
parseNumericAddress("2001:db8::1"),
|
||||
parseNumericAddress("2001:db8::2"))
|
||||
publicKey = TEST_PUBLIC_KEY
|
||||
}, null /* ttl */)
|
||||
}, DEFAULT_OPTION)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
|
|
@ -2214,7 +2477,7 @@ class MdnsRecordRepositoryTest {
|
|||
port = TEST_PORT
|
||||
hostname = "MyHost"
|
||||
publicKey = TEST_PUBLIC_KEY
|
||||
}, null /* ttl */)
|
||||
}, DEFAULT_OPTION)
|
||||
|
||||
// Although there's a KEY RR in the second registration being probed, it shouldn't conflict
|
||||
// with an address record which is from a probed registration in the repository.
|
||||
|
|
@ -2241,8 +2504,8 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testGetConflictingServices_IdenticalService() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, DEFAULT_OPTION)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
|
|
@ -2278,8 +2541,8 @@ class MdnsRecordRepositoryTest {
|
|||
@Test
|
||||
fun testGetConflictingServicesCaseInsensitive_IdenticalService() {
|
||||
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
repository.addService(TEST_SERVICE_ID_2, TEST_SERVICE_2, DEFAULT_OPTION)
|
||||
|
||||
val otherTtlMillis = 1234L
|
||||
val packet = MdnsPacket(
|
||||
|
|
@ -2382,7 +2645,7 @@ class MdnsRecordRepositoryTest {
|
|||
assertEquals(0, repository.servicesCount)
|
||||
assertEquals(
|
||||
-1,
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */)
|
||||
repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, DEFAULT_OPTION)
|
||||
)
|
||||
assertEquals(1, repository.servicesCount)
|
||||
|
||||
|
|
@ -2939,7 +3202,7 @@ class MdnsRecordRepositoryTest {
|
|||
repository.addService(
|
||||
TEST_SERVICE_CUSTOM_HOST_ID_1,
|
||||
TEST_SERVICE_CUSTOM_HOST_NO_ADDRESSES,
|
||||
null
|
||||
DEFAULT_OPTION
|
||||
)
|
||||
repository.setServiceProbing(TEST_SERVICE_CUSTOM_HOST_ID_1)
|
||||
repository.removeService(TEST_CUSTOM_HOST_ID_1)
|
||||
|
|
@ -3083,18 +3346,20 @@ private fun MdnsRecordRepository.initWithService(
|
|||
serviceId: Int,
|
||||
serviceInfo: NsdServiceInfo,
|
||||
subtypes: Set<String> = setOf(),
|
||||
addresses: List<LinkAddress> = TEST_ADDRESSES
|
||||
addresses: List<LinkAddress> = TEST_ADDRESSES,
|
||||
option: MdnsAdvertisingOptions = DEFAULT_OPTION
|
||||
): AnnouncementInfo {
|
||||
updateAddresses(addresses)
|
||||
serviceInfo.setSubtypes(subtypes)
|
||||
return addServiceAndFinishProbing(serviceId, serviceInfo)
|
||||
return addServiceAndFinishProbing(serviceId, serviceInfo, option)
|
||||
}
|
||||
|
||||
private fun MdnsRecordRepository.addServiceAndFinishProbing(
|
||||
serviceId: Int,
|
||||
serviceInfo: NsdServiceInfo
|
||||
serviceInfo: NsdServiceInfo,
|
||||
option: MdnsAdvertisingOptions = DEFAULT_OPTION
|
||||
): AnnouncementInfo {
|
||||
addService(serviceId, serviceInfo, null /* ttl */)
|
||||
addService(serviceId, serviceInfo, option)
|
||||
val probingInfo = setServiceProbing(serviceId)
|
||||
assertNotNull(probingInfo)
|
||||
return onProbingSucceeded(probingInfo)
|
||||
|
|
|
|||
Loading…
Reference in a new issue