From 72fcf79b9c9631f06678283c0747a210e66352f7 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 6 Sep 2023 14:05:47 -0700 Subject: [PATCH] [mdns] add `PublishKey()` & `UnpublishKey()` methods This commit adds new methods in `Mdns::Publisher` to publish or unpublish a key record for a given (host or service instance) name. New methods are implemented for both MDNSResponder and Avahi sub-classes. --- src/common/types.hpp | 2 + src/mdns/mdns.cpp | 123 ++++++++++++++++++++++++++++++++++++++- src/mdns/mdns.hpp | 69 +++++++++++++++++++++- src/mdns/mdns_avahi.cpp | 92 +++++++++++++++++++++++++++++ src/mdns/mdns_avahi.hpp | 24 ++++++++ src/mdns/mdns_mdnssd.cpp | 4 ++ src/mdns/mdns_mdnssd.hpp | 28 +++++++++ tests/mdns/main.cpp | 16 +++-- 8 files changed, 351 insertions(+), 7 deletions(-) diff --git a/src/common/types.hpp b/src/common/types.hpp index 649f0b6371d..7ba0065ba33 100644 --- a/src/common/types.hpp +++ b/src/common/types.hpp @@ -402,11 +402,13 @@ struct MdnsTelemetryInfo "kEmaFactorDenominator must be greater than kEmaFactorNumerator"); MdnsResponseCounters mHostRegistrations; + MdnsResponseCounters mKeyRegistrations; MdnsResponseCounters mServiceRegistrations; MdnsResponseCounters mHostResolutions; MdnsResponseCounters mServiceResolutions; uint32_t mHostRegistrationEmaLatency; ///< The EMA latency of host registrations in milliseconds + uint32_t mKeyRegistrationEmaLatency; ///< The EMA latency of key registrations in milliseconds uint32_t mServiceRegistrationEmaLatency; ///< The EMA latency of service registrations in milliseconds uint32_t mHostResolutionEmaLatency; ///< The EMA latency of host resolutions in milliseconds uint32_t mServiceResolutionEmaLatency; ///< The EMA latency of service resolutions in milliseconds diff --git a/src/mdns/mdns.cpp b/src/mdns/mdns.cpp index d7e093531a5..8c5db278a47 100644 --- a/src/mdns/mdns.cpp +++ b/src/mdns/mdns.cpp @@ -79,6 +79,19 @@ void Publisher::PublishHost(const std::string &aName, const AddressList &aAddres } } +void Publisher::PublishKey(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) +{ + otbrError error; + + mKeyRegistrationBeginTime[aName] = Clock::now(); + + error = PublishKeyImpl(aName, aKeyData, std::move(aCallback)); + if (error != OTBR_ERROR_NONE) + { + UpdateMdnsResponseCounters(mTelemetryInfo.mKeyRegistrations, error); + } +} + void Publisher::OnServiceResolveFailed(std::string aType, std::string aInstanceName, int32_t aErrorCode) { UpdateMdnsResponseCounters(mTelemetryInfo.mServiceResolutions, DnsErrorToOtbrError(aErrorCode)); @@ -289,7 +302,7 @@ std::string Publisher::MakeFullServiceName(const std::string &aName, const std:: return aName + "." + aType + ".local"; } -std::string Publisher::MakeFullHostName(const std::string &aName) +std::string Publisher::MakeFullName(const std::string &aName) { return aName + ".local"; } @@ -320,7 +333,12 @@ void Publisher::RemoveServiceRegistration(const std::string &aName, const std::s Publisher::ServiceRegistration *Publisher::FindServiceRegistration(const std::string &aName, const std::string &aType) { - auto it = mServiceRegistrations.find(MakeFullServiceName(aName, aType)); + return FindServiceRegistration(MakeFullServiceName(aName, aType)); +} + +Publisher::ServiceRegistration *Publisher::FindServiceRegistration(const std::string &aNameAndType) +{ + auto it = mServiceRegistrations.find(MakeFullName(aNameAndType)); return it != mServiceRegistrations.end() ? it->second.get() : nullptr; } @@ -435,6 +453,75 @@ Publisher::HostRegistration *Publisher::FindHostRegistration(const std::string & return it != mHostRegistrations.end() ? it->second.get() : nullptr; } +Publisher::ResultCallback Publisher::HandleDuplicateKeyRegistration(const std::string &aName, + const KeyData &aKeyData, + ResultCallback &&aCallback) +{ + KeyRegistration *keyReg = FindKeyRegistration(aName); + + VerifyOrExit(keyReg != nullptr); + + if (keyReg->IsOutdated(aName, aKeyData)) + { + otbrLogInfo("Removing existing key %s: outdated", aName.c_str()); + RemoveKeyRegistration(keyReg->mName, OTBR_ERROR_ABORTED); + } + else if (keyReg->IsCompleted()) + { + // Returns success if the same key has already been + // registered with exactly the same parameters. + std::move(aCallback)(OTBR_ERROR_NONE); + } + else + { + // If the same key is being registered with the same parameters, + // let's join the waiting queue for the result. + keyReg->mCallback = std::bind( + [](std::shared_ptr aExistingCallback, std::shared_ptr aNewCallback, + otbrError aError) { + std::move (*aExistingCallback)(aError); + std::move (*aNewCallback)(aError); + }, + std::make_shared(std::move(keyReg->mCallback)), + std::make_shared(std::move(aCallback)), std::placeholders::_1); + } + +exit: + return std::move(aCallback); +} + +void Publisher::AddKeyRegistration(KeyRegistrationPtr &&aKeyReg) +{ + mKeyRegistrations.emplace(MakeFullKeyName(aKeyReg->mName), std::move(aKeyReg)); +} + +void Publisher::RemoveKeyRegistration(const std::string &aName, otbrError aError) +{ + auto it = mKeyRegistrations.find(MakeFullKeyName(aName)); + KeyRegistrationPtr keyReg; + + otbrLogInfo("Removing key %s", aName.c_str()); + VerifyOrExit(it != mKeyRegistrations.end()); + + // Keep the KeyRegistration around before calling `Complete` + // to invoke the callback. This is for avoiding invalid access + // to the KeyRegistration when it's freed from the callback. + keyReg = std::move(it->second); + mKeyRegistrations.erase(it); + keyReg->Complete(aError); + otbrLogInfo("Removed key %s", aName.c_str()); + +exit: + return; +} + +Publisher::KeyRegistration *Publisher::FindKeyRegistration(const std::string &aName) +{ + auto it = mKeyRegistrations.find(MakeFullKeyName(aName)); + + return it != mKeyRegistrations.end() ? it->second.get() : nullptr; +} + Publisher::Registration::~Registration(void) { TriggerCompleteCallback(OTBR_ERROR_ABORTED); @@ -486,6 +573,26 @@ void Publisher::HostRegistration::OnComplete(otbrError aError) } } +bool Publisher::KeyRegistration::IsOutdated(const std::string &aName, const KeyData &aKeyData) const +{ + return !(mName == aName && mKeyData == aKeyData); +} + +void Publisher::KeyRegistration::Complete(otbrError aError) +{ + OnComplete(aError); + Registration::TriggerCompleteCallback(aError); +} + +void Publisher::KeyRegistration::OnComplete(otbrError aError) +{ + if (!IsCompleted()) + { + mPublisher->UpdateMdnsResponseCounters(mPublisher->mTelemetryInfo.mKeyRegistrations, aError); + mPublisher->UpdateKeyRegistrationEmaLatency(mName, aError); + } +} + void Publisher::UpdateMdnsResponseCounters(otbr::MdnsResponseCounters &aCounters, otbrError aError) { switch (aError) @@ -564,6 +671,18 @@ void Publisher::UpdateHostRegistrationEmaLatency(const std::string &aHostName, o } } +void Publisher::UpdateKeyRegistrationEmaLatency(const std::string &aKeyName, otbrError aError) +{ + auto it = mKeyRegistrationBeginTime.find(aKeyName); + + if (it != mKeyRegistrationBeginTime.end()) + { + uint32_t latency = std::chrono::duration_cast(Clock::now() - it->second).count(); + UpdateEmaLatency(mTelemetryInfo.mKeyRegistrationEmaLatency, latency, aError); + mKeyRegistrationBeginTime.erase(it); + } +} + void Publisher::UpdateServiceInstanceResolutionEmaLatency(const std::string &aInstanceName, const std::string &aType, otbrError aError) diff --git a/src/mdns/mdns.hpp b/src/mdns/mdns.hpp index 9a28b884cda..befda79f289 100644 --- a/src/mdns/mdns.hpp +++ b/src/mdns/mdns.hpp @@ -118,6 +118,7 @@ class Publisher : private NonCopyable typedef std::vector TxtList; typedef std::vector SubTypeList; typedef std::vector AddressList; + typedef std::vector KeyData; /** * This structure represents information of a discovered service instance. @@ -266,6 +267,29 @@ class Publisher : private NonCopyable */ virtual void UnpublishHost(const std::string &aName, ResultCallback &&aCallback) = 0; + /** + * This method publishes or updates a key record for a name. + * + * @param[in] aName The name associated with key record (can be host name or service instance name). + * @param[in] aKeyData The key data to publish. + * @param[in] aCallback The callback for receiving the publishing result.`OTBR_ERROR_NONE` will be + * returned if the operation is successful and all other values indicate a + * failure. Specifically, `OTBR_ERROR_DUPLICATED` indicates that the name has + * already been published and the caller can re-publish with a new name if an + * alternative name is available/acceptable. + * + */ + void PublishKey(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback); + + /** + * This method un-publishes a key record + * + * @param[in] aName The name associated with key record. + * @param[in] aCallback The callback for receiving the publishing result. + * + */ + virtual void UnpublishKey(const std::string &aName, ResultCallback &&aCallback) = 0; + /** * This method subscribes a given service or service instance. * @@ -501,15 +525,43 @@ class Publisher : private NonCopyable void OnComplete(otbrError aError); }; + class KeyRegistration : public Registration + { + public: + std::string mName; + KeyData mKeyData; + + KeyRegistration(std::string aName, KeyData aKeyData, ResultCallback &&aCallback, Publisher *aPublisher) + : Registration(std::move(aCallback), aPublisher) + , mName(std::move(aName)) + , mKeyData(std::move(aKeyData)) + { + } + + ~KeyRegistration(void) { OnComplete(OTBR_ERROR_ABORTED); } + + void Complete(otbrError aError); + + // Tells whether this `KeyRegistration` object is outdated comparing to the given parameters. + bool IsOutdated(const std::string &aName, const KeyData &aKeyData) const; + + private: + void OnComplete(otbrError aError); + }; + using ServiceRegistrationPtr = std::unique_ptr; using ServiceRegistrationMap = std::map; using HostRegistrationPtr = std::unique_ptr; using HostRegistrationMap = std::map; + using KeyRegistrationPtr = std::unique_ptr; + using KeyRegistrationMap = std::map; static SubTypeList SortSubTypeList(SubTypeList aSubTypeList); static AddressList SortAddressList(AddressList aAddressList); + static std::string MakeFullName(const std::string &aName); static std::string MakeFullServiceName(const std::string &aName, const std::string &aType); - static std::string MakeFullHostName(const std::string &aName); + static std::string MakeFullHostName(const std::string &aName) { return MakeFullName(aName); } + static std::string MakeFullKeyName(const std::string &aName) { return MakeFullName(aName); } virtual otbrError PublishServiceImpl(const std::string &aHostName, const std::string &aName, @@ -523,6 +575,8 @@ class Publisher : private NonCopyable const AddressList &aAddresses, ResultCallback &&aCallback) = 0; + virtual otbrError PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) = 0; + virtual void OnServiceResolveFailedImpl(const std::string &aType, const std::string &aInstanceName, int32_t aErrorCode) = 0; @@ -534,6 +588,7 @@ class Publisher : private NonCopyable void AddServiceRegistration(ServiceRegistrationPtr &&aServiceReg); void RemoveServiceRegistration(const std::string &aName, const std::string &aType, otbrError aError); ServiceRegistration *FindServiceRegistration(const std::string &aName, const std::string &aType); + ServiceRegistration *FindServiceRegistration(const std::string &aNameAndType); void OnServiceResolved(std::string aType, DiscoveredInstanceInfo aInstanceInfo); void OnServiceResolveFailed(std::string aType, std::string aInstanceName, int32_t aErrorCode); @@ -556,10 +611,18 @@ class Publisher : private NonCopyable const AddressList &aAddresses, ResultCallback &&aCallback); + ResultCallback HandleDuplicateKeyRegistration(const std::string &aName, + const KeyData &aKeyData, + ResultCallback &&aCallback); + void AddHostRegistration(HostRegistrationPtr &&aHostReg); void RemoveHostRegistration(const std::string &aName, otbrError aError); HostRegistration *FindHostRegistration(const std::string &aName); + void AddKeyRegistration(KeyRegistrationPtr &&aKeyReg); + void RemoveKeyRegistration(const std::string &aName, otbrError aError); + KeyRegistration *FindKeyRegistration(const std::string &aName); + static void UpdateMdnsResponseCounters(MdnsResponseCounters &aCounters, otbrError aError); static void UpdateEmaLatency(uint32_t &aEmaLatency, uint32_t aLatency, otbrError aError); @@ -567,6 +630,7 @@ class Publisher : private NonCopyable const std::string &aType, otbrError aError); void UpdateHostRegistrationEmaLatency(const std::string &aHostName, otbrError aError); + void UpdateKeyRegistrationEmaLatency(const std::string &aKeyName, otbrError aError); void UpdateServiceInstanceResolutionEmaLatency(const std::string &aInstanceName, const std::string &aType, otbrError aError); @@ -574,6 +638,7 @@ class Publisher : private NonCopyable ServiceRegistrationMap mServiceRegistrations; HostRegistrationMap mHostRegistrations; + KeyRegistrationMap mKeyRegistrations; uint64_t mNextSubscriberId = 1; @@ -582,6 +647,8 @@ class Publisher : private NonCopyable std::map, Timepoint> mServiceRegistrationBeginTime; // host name -> the timepoint to begin host registration std::map mHostRegistrationBeginTime; + // key name -> the timepoint to begin key registration + std::map mKeyRegistrationBeginTime; // {instance name, service type} -> the timepoint to begin service resolution std::map, Timepoint> mServiceInstanceResolutionBeginTime; // host name -> the timepoint to begin host resolution diff --git a/src/mdns/mdns_avahi.cpp b/src/mdns/mdns_avahi.cpp index 613be8dec9b..b2e1b10980d 100644 --- a/src/mdns/mdns_avahi.cpp +++ b/src/mdns/mdns_avahi.cpp @@ -440,6 +440,11 @@ PublisherAvahi::AvahiHostRegistration::~AvahiHostRegistration(void) ReleaseGroup(mEntryGroup); } +PublisherAvahi::AvahiKeyRegistration::~AvahiKeyRegistration(void) +{ + ReleaseGroup(mEntryGroup); +} + otbrError PublisherAvahi::Start(void) { otbrError error = OTBR_ERROR_NONE; @@ -524,6 +529,7 @@ void PublisherAvahi::CallHostOrServiceCallback(AvahiEntryGroup *aGroup, otbrErro { ServiceRegistration *serviceReg; HostRegistration *hostReg; + KeyRegistration *keyReg; if ((serviceReg = FindServiceRegistration(aGroup)) != nullptr) { @@ -547,6 +553,17 @@ void PublisherAvahi::CallHostOrServiceCallback(AvahiEntryGroup *aGroup, otbrErro RemoveHostRegistration(hostReg->mName, aError); } } + else if ((keyReg = FindKeyRegistration(aGroup)) != nullptr) + { + if (aError == OTBR_ERROR_NONE) + { + keyReg->Complete(aError); + } + else + { + RemoveKeyRegistration(keyReg->mName, aError); + } + } else { otbrLogWarning("No registered service or host matches avahi group @%p", aGroup); @@ -789,6 +806,64 @@ void PublisherAvahi::UnpublishHost(const std::string &aName, ResultCallback &&aC std::move(aCallback)(error); } +otbrError PublisherAvahi::PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) +{ + otbrError error = OTBR_ERROR_NONE; + int avahiError = AVAHI_OK; + std::string fullKeyName; + AvahiEntryGroup *group = nullptr; + + VerifyOrExit(mState == State::kReady, error = OTBR_ERROR_INVALID_STATE); + VerifyOrExit(mClient != nullptr, error = OTBR_ERROR_INVALID_STATE); + + aCallback = HandleDuplicateKeyRegistration(aName, aKeyData, std::move(aCallback)); + VerifyOrExit(!aCallback.IsNull()); + + VerifyOrExit((group = CreateGroup(mClient)) != nullptr, error = OTBR_ERROR_MDNS); + + fullKeyName = MakeFullKeyName(aName); + + avahiError = avahi_entry_group_add_record(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_PUBLISH_UNIQUE, + fullKeyName.c_str(), AVAHI_DNS_CLASS_IN, kDnsKeyRecordType, kDefaultTtl, + aKeyData.data(), aKeyData.size()); + VerifyOrExit(avahiError == AVAHI_OK); + + otbrLogInfo("Commit avahi key record for %s", aName.c_str()); + avahiError = avahi_entry_group_commit(group); + VerifyOrExit(avahiError == AVAHI_OK); + + AddKeyRegistration(std::unique_ptr( + new AvahiKeyRegistration(aName, aKeyData, std::move(aCallback), group, this))); + +exit: + if (avahiError != AVAHI_OK || error != OTBR_ERROR_NONE) + { + if (avahiError != AVAHI_OK) + { + error = OTBR_ERROR_MDNS; + otbrLogErr("Failed to publish key record - avahi error: %s!", avahi_strerror(avahiError)); + } + + if (group != nullptr) + { + ReleaseGroup(group); + } + std::move(aCallback)(error); + } + return error; +} + +void PublisherAvahi::UnpublishKey(const std::string &aName, ResultCallback &&aCallback) +{ + otbrError error = OTBR_ERROR_NONE; + + VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE); + RemoveKeyRegistration(aName, OTBR_ERROR_ABORTED); + +exit: + std::move(aCallback)(error); +} + otbrError PublisherAvahi::TxtDataToAvahiStringList(const TxtData &aTxtData, AvahiStringList *aBuffer, size_t aBufferSize, @@ -870,6 +945,23 @@ Publisher::HostRegistration *PublisherAvahi::FindHostRegistration(const AvahiEnt return result; } +Publisher::KeyRegistration *PublisherAvahi::FindKeyRegistration(const AvahiEntryGroup *aEntryGroup) +{ + KeyRegistration *result = nullptr; + + for (const auto &entry : mKeyRegistrations) + { + const auto &keyReg = static_cast(*entry.second); + if (keyReg.GetEntryGroup() == aEntryGroup) + { + result = entry.second.get(); + break; + } + } + + return result; +} + void PublisherAvahi::SubscribeService(const std::string &aType, const std::string &aInstanceName) { auto service = MakeUnique(*this, aType, aInstanceName); diff --git a/src/mdns/mdns_avahi.hpp b/src/mdns/mdns_avahi.hpp index 844e242949f..d42f9a2b595 100644 --- a/src/mdns/mdns_avahi.hpp +++ b/src/mdns/mdns_avahi.hpp @@ -78,6 +78,7 @@ class PublisherAvahi : public Publisher void UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback) override; void UnpublishHost(const std::string &aName, ResultCallback &&aCallback) override; + void UnpublishKey(const std::string &aName, ResultCallback &&aCallback) override; void SubscribeService(const std::string &aType, const std::string &aInstanceName) override; void UnsubscribeService(const std::string &aType, const std::string &aInstanceName) override; void SubscribeHost(const std::string &aHostName) override; @@ -97,6 +98,7 @@ class PublisherAvahi : public Publisher otbrError PublishHostImpl(const std::string &aName, const AddressList &aAddresses, ResultCallback &&aCallback) override; + otbrError PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) override; void OnServiceResolveFailedImpl(const std::string &aType, const std::string &aInstanceName, int32_t aErrorCode) override; @@ -106,6 +108,7 @@ class PublisherAvahi : public Publisher private: static constexpr size_t kMaxSizeOfTxtRecord = 1024; static constexpr uint32_t kDefaultTtl = 10; // In seconds. + static constexpr uint16_t kDnsKeyRecordType = 25; class AvahiServiceRegistration : public ServiceRegistration { @@ -158,6 +161,26 @@ class PublisherAvahi : public Publisher AvahiEntryGroup *mEntryGroup; }; + class AvahiKeyRegistration : public KeyRegistration + { + public: + AvahiKeyRegistration(const std::string &aName, + const KeyData &aKeyData, + ResultCallback &&aCallback, + AvahiEntryGroup *aEntryGroup, + PublisherAvahi *aPublisher) + : KeyRegistration(aName, aKeyData, std::move(aCallback), aPublisher) + , mEntryGroup(aEntryGroup) + { + } + + ~AvahiKeyRegistration(void) override; + const AvahiEntryGroup *GetEntryGroup(void) const { return mEntryGroup; } + + private: + AvahiEntryGroup *mEntryGroup; + }; + struct Subscription : private ::NonCopyable { PublisherAvahi *mPublisherAvahi; @@ -347,6 +370,7 @@ class PublisherAvahi : public Publisher ServiceRegistration *FindServiceRegistration(const AvahiEntryGroup *aEntryGroup); HostRegistration *FindHostRegistration(const AvahiEntryGroup *aEntryGroup); + KeyRegistration *FindKeyRegistration(const AvahiEntryGroup *aEntryGroup); AvahiClient *mClient; std::unique_ptr mPoller; diff --git a/src/mdns/mdns_mdnssd.cpp b/src/mdns/mdns_mdnssd.cpp index 101313cedba..edbd671c3bc 100644 --- a/src/mdns/mdns_mdnssd.cpp +++ b/src/mdns/mdns_mdnssd.cpp @@ -259,6 +259,7 @@ void PublisherMDnsSd::Stop(StopMode aStopMode) mServiceRegistrations.clear(); mHostRegistrations.clear(); + mKeyRegistrations.clear(); DeallocateHostsRef(); mSubscribedServices.clear(); @@ -668,6 +669,9 @@ void PublisherMDnsSd::UnpublishService(const std::string &aName, const std::stri otbrError error = OTBR_ERROR_NONE; VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE); + + // TODO: check if we have an key ref and if so, switch it to use other API? + RemoveServiceRegistration(aName, aType, OTBR_ERROR_ABORTED); exit: diff --git a/src/mdns/mdns_mdnssd.hpp b/src/mdns/mdns_mdnssd.hpp index fa4bf4d1a73..a43d66d58dd 100644 --- a/src/mdns/mdns_mdnssd.hpp +++ b/src/mdns/mdns_mdnssd.hpp @@ -70,6 +70,7 @@ class PublisherMDnsSd : public MainloopProcessor, public Publisher void UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback) override; void UnpublishHost(const std::string &aName, ResultCallback &&aCallback) override; + void UnpublishKey(const std::string &aName, ResultCallback &&aCallback) override; void SubscribeService(const std::string &aType, const std::string &aInstanceName) override; void UnsubscribeService(const std::string &aType, const std::string &aInstanceName) override; void SubscribeHost(const std::string &aHostName) override; @@ -94,6 +95,7 @@ class PublisherMDnsSd : public MainloopProcessor, public Publisher otbrError PublishHostImpl(const std::string &aName, const AddressList &aAddress, ResultCallback &&aCallback) override; + otbrError PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) override; void OnServiceResolveFailedImpl(const std::string &aType, const std::string &aInstanceName, int32_t aErrorCode) override; @@ -135,6 +137,8 @@ class PublisherMDnsSd : public MainloopProcessor, public Publisher DNSServiceRef mServiceRef = nullptr; }; + class DnssdKeyRegistration; + class DnssdHostRegistration : public HostRegistration { public: @@ -156,6 +160,30 @@ class PublisherMDnsSd : public MainloopProcessor, public Publisher std::vector mAddrRecordRefs; std::vector mAddrRegistered; + DnssdKeyRegistration * mKeyRegistration; + }; + + class DnssdKeyRegistration : public KeyRegistration + { + public: + DnssdKeyRegistration(const std::string &aName, + const KeyData &aKeyData, + ResultCallback &&aCallback, + DNSServiceRef aServiceRef, + DNSRecordRef aRecordRef, + Publisher *aPublisher) + : KeyRegistration(aName, aKeyData, std::move(aCallback), aPublisher) + , mServiceRegistration(nullptr) + , mServiceRef(aServiceRef) + , mRecordRef(aRecordRef) + { + } + + ~DnssdKeyRegistration(void) override; + + DnssdServiceRegistration *mServiceRegistration; + DNSServiceRef mServiceRef; + DNSRecordRef mRecordRef; }; struct ServiceRef : private ::NonCopyable diff --git a/tests/mdns/main.cpp b/tests/mdns/main.cpp index 66f6366c5c7..215a8327740 100644 --- a/tests/mdns/main.cpp +++ b/tests/mdns/main.cpp @@ -84,10 +84,11 @@ int RunMainloop(void) void PublishSingleServiceWithCustomHost(void *aContext, Mdns::Publisher::State aState) { - uint8_t xpanid[kSizeExtPanId] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}; - uint8_t extAddr[kSizeExtAddr] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}; - uint8_t hostAddr[OTBR_IP6_ADDRESS_SIZE] = {0}; - const char hostName[] = "custom-host"; + uint8_t xpanid[kSizeExtPanId] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}; + uint8_t extAddr[kSizeExtAddr] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48}; + uint8_t hostAddr[OTBR_IP6_ADDRESS_SIZE] = {0}; + const char hostName[] = "custom-host"; + std::vector keyData = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; hostAddr[0] = 0x20; hostAddr[1] = 0x02; @@ -102,12 +103,19 @@ void PublishSingleServiceWithCustomHost(void *aContext, Mdns::Publisher::State a Mdns::Publisher::EncodeTxtData(txtList, txtData); + sContext.mPublisher->PublishKey(hostName, keyData, + [](otbrError aError) { SuccessOrDie(aError, "cannot publish key for host"); }); + sContext.mPublisher->PublishHost(hostName, {Ip6Address(hostAddr)}, [](otbrError aError) { SuccessOrDie(aError, "cannot publish the host"); }); sContext.mPublisher->PublishService( hostName, "SingleService", "_meshcop._udp", Mdns::Publisher::SubTypeList{}, 12345, txtData, [](otbrError aError) { SuccessOrDie(aError, "cannot publish the service"); }); + + sContext.mPublisher->PublishKey("SingleService._meshcop._udp", keyData, [](otbrError aError) { + SuccessOrDie(aError, "cannot publish key for service"); + }); } }