From 9e9522aaacb691c3157ff47577f3a4cb5df815e2 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 29 Apr 2025 14:07:16 -0700 Subject: [PATCH] [mdns] allow service registration for local host (#11450) This commit updates the mDNS service registration to allow services for the local host. The `mHostName` field in an `otMdnsService` structure can now be set to `NULL` to indicate that the service if for the local host. The `test_mdns` unit test is also updated to verify this new functionality. --- include/openthread/instance.h | 2 +- include/openthread/mdns.h | 3 ++- src/core/net/mdns.cpp | 7 +++++-- src/core/net/mdns.hpp | 3 ++- tests/unit/test_mdns.cpp | 25 ++++++++++++++++++++++++- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 818cf5175..f7d9685bb 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (502) +#define OPENTHREAD_API_VERSION (503) /** * @addtogroup api-instance diff --git a/include/openthread/mdns.h b/include/openthread/mdns.h index bb29a843c..a40cbb8e7 100644 --- a/include/openthread/mdns.h +++ b/include/openthread/mdns.h @@ -311,7 +311,8 @@ otError otMdnsUnregisterHost(otInstance *aInstance, const otMdnsHost *aHost); * contain dot `.` character which is allowed in a service instance label. * - The `mServiceType` specifies the service type (e.g., "_tst._udp"). It is treated as multiple dot `.` separated * labels. It MUST NOT contain the domain name. - * - The `mHostName` field specifies the host name of the service. MUST NOT contain the domain name. + * - The `mHostName` field specifies the host name of the service if it is not NULL. Otherwise, if it is NULL, it + * indicates that this service is for the local host (this device itself). * - The `mSubTypeLabels` is an array of strings representing sub-types associated with the service. Each array entry * is a sub-type label. The `mSubTypeLabels can be NULL if there is no sub-type. Otherwise, the array length is * specified by `mSubTypeLabelsLength`. diff --git a/src/core/net/mdns.cpp b/src/core/net/mdns.cpp index 245215778..c285e72f6 100644 --- a/src/core/net/mdns.cpp +++ b/src/core/net/mdns.cpp @@ -2332,7 +2332,8 @@ exit: void Core::ServiceEntry::Register(const Service &aService, const Callback &aCallback) { - uint32_t ttl = DetermineTtl(aService.mTtl, kDefaultTtl); + const char *hostName; + uint32_t ttl = DetermineTtl(aService.mTtl, kDefaultTtl); if (GetState() == kRemoving) { @@ -2377,8 +2378,10 @@ void Core::ServiceEntry::Register(const Service &aService, const Callback &aCall // Register SRV record info. + hostName = (aService.mHostName != nullptr) ? aService.mHostName : Get().mLocalHost.GetName(); + mSrvRecord.UpdateTtl(ttl); - mSrvRecord.UpdateProperty(mHostName, aService.mHostName); + mSrvRecord.UpdateProperty(mHostName, hostName); mSrvRecord.UpdateProperty(mPriority, aService.mPriority); mSrvRecord.UpdateProperty(mWeight, aService.mWeight); mSrvRecord.UpdateProperty(mPort, aService.mPort); diff --git a/src/core/net/mdns.hpp b/src/core/net/mdns.hpp index 0246603a9..13d5eaf88 100644 --- a/src/core/net/mdns.hpp +++ b/src/core/net/mdns.hpp @@ -301,7 +301,8 @@ public: * contain dot `.` character which is allowed in a service instance label. * - The `mServiceType` specifies the service type (e.g., "_tst._udp"). It is treated as multiple dot `.` separated * labels. It MUST NOT contain the domain name. - * - The `mHostName` field specifies the host name of the service. MUST NOT contain the domain name. + * - The `mHostName` field specifies the host name of the service if it is not `nullptr`. Otherwise, if it is + * `nullptr`, it indicates that this service is for the local host (this device itself). * - The `mSubTypeLabels` is an array of strings representing sub-types associated with the service. Each array * entry is a sub-type label. The `mSubTypeLabels can be `nullptr` if there are no sub-types. Otherwise, the * array length is specified by `mSubTypeLabelsLength`. diff --git a/tests/unit/test_mdns.cpp b/tests/unit/test_mdns.cpp index 16edace9a..9b2fbf9dc 100644 --- a/tests/unit/test_mdns.cpp +++ b/tests/unit/test_mdns.cpp @@ -481,7 +481,8 @@ struct DnsRecords : public OwningList bool contains = false; DnsNameString hostName; - hostName.Append("%s.local.", aService.mHostName); + hostName.Append("%s.local.", + aService.mHostName != nullptr ? aService.mHostName : sInstance->Get().GetLocalHostName()); for (const DnsRecord &record : *this) { @@ -3144,6 +3145,28 @@ void TestServiceReg(void) sDnsMessages.Clear(); } + Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); + Log("Update service host name to use local host and validate new announcements of SRV record"); + + service.mHostName = nullptr; + + sRegCallbacks[1].Reset(); + sDnsMessages.Clear(); + SuccessOrQuit(mdns->RegisterService(service, 1, HandleSuccessCallback)); + + for (uint8_t anncCount = 0; anncCount < kNumAnnounces; anncCount++) + { + AdvanceTime((anncCount == 0) ? 0 : (1U << (anncCount - 1)) * 1000); + VerifyOrQuit(sRegCallbacks[1].mWasCalled); + + VerifyOrQuit(!sDnsMessages.IsEmpty()); + dnsMsg = sDnsMessages.GetHead(); + dnsMsg->ValidateHeader(kMulticastResponse, /* Q */ 0, /* Ans */ 1, /* Auth */ 0, /* Addnl */ 1); + dnsMsg->Validate(service, kInAnswerSection, kCheckSrv); + VerifyOrQuit(dnsMsg->GetNext() == nullptr); + sDnsMessages.Clear(); + } + Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"); Log("Update service host name and validate new announcements of SRV record");