Skip to content

Commit 9ea1ed0

Browse files
committed
Dnssd changes to browse and resolve using open thread domain along with the local domain
1 parent 27a478f commit 9ea1ed0

File tree

3 files changed

+142
-35
lines changed

3 files changed

+142
-35
lines changed

src/platform/Darwin/DnssdContexts.cpp

+14-16
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ namespace {
3030

3131
constexpr uint8_t kDnssdKeyMaxSize = 32;
3232
constexpr uint8_t kDnssdTxtRecordMaxEntries = 20;
33-
constexpr char kLocalDot[] = "local.";
34-
35-
bool IsLocalDomain(const char * domain)
36-
{
37-
return strcmp(kLocalDot, domain) == 0;
38-
}
3933

4034
std::string GetHostNameWithoutDomain(const char * hostnameWithDomain)
4135
{
@@ -252,6 +246,7 @@ void MdnsContexts::Delete(GenericContext * context)
252246
{
253247
DNSServiceRefDeallocate(context->serviceRef);
254248
}
249+
255250
chip::Platform::Delete(context);
256251
}
257252

@@ -388,7 +383,6 @@ void BrowseContext::OnBrowseAdd(const char * name, const char * type, const char
388383
ChipLogProgress(Discovery, "Mdns: %s name: %s, type: %s, domain: %s, interface: %" PRIu32, __func__, StringOrNullMarker(name),
389384
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
390385

391-
VerifyOrReturn(IsLocalDomain(domain));
392386
auto service = GetService(name, type, protocol, interfaceId);
393387
services.push_back(service);
394388
}
@@ -399,7 +393,6 @@ void BrowseContext::OnBrowseRemove(const char * name, const char * type, const c
399393
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
400394

401395
VerifyOrReturn(name != nullptr);
402-
VerifyOrReturn(IsLocalDomain(domain));
403396

404397
services.erase(std::remove_if(services.begin(), services.end(),
405398
[name, type, interfaceId](const DnssdService & service) {
@@ -443,7 +436,6 @@ void BrowseWithDelegateContext::OnBrowseAdd(const char * name, const char * type
443436
ChipLogProgress(Discovery, "Mdns: %s name: %s, type: %s, domain: %s, interface: %" PRIu32, __func__, StringOrNullMarker(name),
444437
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
445438

446-
VerifyOrReturn(IsLocalDomain(domain));
447439

448440
auto delegate = static_cast<DnssdBrowseDelegate *>(context);
449441
auto service = GetService(name, type, protocol, interfaceId);
@@ -456,7 +448,6 @@ void BrowseWithDelegateContext::OnBrowseRemove(const char * name, const char * t
456448
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
457449

458450
VerifyOrReturn(name != nullptr);
459-
VerifyOrReturn(IsLocalDomain(domain));
460451

461452
auto delegate = static_cast<DnssdBrowseDelegate *>(context);
462453
auto service = GetService(name, type, protocol, interfaceId);
@@ -473,6 +464,7 @@ ResolveContext::ResolveContext(void * cbContext, DnssdResolveCallback cb, chip::
473464
callback = cb;
474465
protocol = GetProtocol(cbAddressType);
475466
instanceName = instanceNameToResolve;
467+
domainName = std::string(kLocalDot);
476468
consumerCounter = std::move(consumerCounterToUse);
477469
}
478470

@@ -485,6 +477,7 @@ ResolveContext::ResolveContext(CommissioningResolveDelegate * delegate, chip::In
485477
callback = nullptr;
486478
protocol = GetProtocol(cbAddressType);
487479
instanceName = instanceNameToResolve;
480+
domainName = std::string(kLocalDot);
488481
consumerCounter = std::move(consumerCounterToUse);
489482
}
490483

@@ -548,7 +541,7 @@ void ResolveContext::DispatchSuccess()
548541

549542
for (auto & interface : interfaces)
550543
{
551-
if (TryReportingResultsForInterfaceIndex(interface.first))
544+
if (TryReportingResultsForInterfaceIndex(interface.first.first))
552545
{
553546
break;
554547
}
@@ -568,7 +561,8 @@ bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceInde
568561
return false;
569562
}
570563

571-
auto & interface = interfaces[interfaceIndex];
564+
std::pair<uint32_t, std::string> interfaceKey = std::make_pair(interfaceIndex, this->domainName);
565+
auto & interface = interfaces[interfaceKey];
572566
auto & ips = interface.addresses;
573567

574568
// Some interface may not have any ips, just ignore them.
@@ -596,15 +590,17 @@ bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceInde
596590
return true;
597591
}
598592

599-
CHIP_ERROR ResolveContext::OnNewAddress(uint32_t interfaceId, const struct sockaddr * address)
593+
CHIP_ERROR ResolveContext::OnNewAddress(const std::pair<uint32_t, std::string> interfaceKey, const struct sockaddr * address)
600594
{
601595
// If we don't have any information about this interfaceId, just ignore the
602596
// address, since it won't be usable anyway without things like the port.
603597
// This can happen if "local" is set up as a search domain in the DNS setup
604598
// on the system, because the hostnames we are looking up all end in
605599
// ".local". In other words, we can get regular DNS results in here, not
606600
// just DNS-SD ones.
607-
if (interfaces.find(interfaceId) == interfaces.end())
601+
uint32_t interfaceId = interfaceKey.first;
602+
603+
if (interfaces.find(interfaceKey) == interfaces.end())
608604
{
609605
return CHIP_NO_ERROR;
610606
}
@@ -627,7 +623,7 @@ CHIP_ERROR ResolveContext::OnNewAddress(uint32_t interfaceId, const struct socka
627623
return CHIP_NO_ERROR;
628624
}
629625

630-
interfaces[interfaceId].addresses.push_back(ip);
626+
interfaces[interfaceKey].addresses.push_back(ip);
631627

632628
return CHIP_NO_ERROR;
633629
}
@@ -709,7 +705,9 @@ void ResolveContext::OnNewInterface(uint32_t interfaceId, const char * fullname,
709705
// resolving.
710706
interface.fullyQualifiedDomainName = hostnameWithDomain;
711707

712-
interfaces.insert(std::make_pair(interfaceId, std::move(interface)));
708+
std::pair<uint32_t, std::string> interfaceKey = std::make_pair(interfaceId, GetDomainNameFromHostName(hostnameWithDomain));
709+
710+
interfaces.insert(std::make_pair(interfaceKey, std::move(interface)));
713711
}
714712

715713
bool ResolveContext::HasInterface()

src/platform/Darwin/DnssdImpl.cpp

+118-17
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@
2626
#include <lib/support/logging/CHIPLogging.h>
2727
#include <platform/CHIPDeviceLayer.h>
2828

29+
using namespace chip;
2930
using namespace chip::Dnssd;
3031
using namespace chip::Dnssd::Internal;
3132

3233
namespace {
3334

34-
constexpr char kLocalDot[] = "local.";
35+
// The extra time in milliseconds that we will wait for the resolution on the open thread domain to complete.
36+
constexpr uint16_t kOpenThreadTimeoutInMsec = 250;
37+
38+
static bool hasOpenThreadTimerStarted = false;
3539

3640
constexpr DNSServiceFlags kRegisterFlags = kDNSServiceFlagsNoAutoRename;
37-
constexpr DNSServiceFlags kBrowseFlags = 0;
41+
constexpr DNSServiceFlags kBrowseFlags = kDNSServiceFlagsShareConnection;
3842
constexpr DNSServiceFlags kGetAddrInfoFlags = kDNSServiceFlagsTimeout | kDNSServiceFlagsShareConnection;
3943
constexpr DNSServiceFlags kResolveFlags = kDNSServiceFlagsShareConnection;
4044
constexpr DNSServiceFlags kReconfirmRecordFlags = 0;
@@ -49,11 +53,27 @@ uint32_t GetInterfaceId(chip::Inet::InterfaceId interfaceId)
4953
return interfaceId.IsPresent() ? interfaceId.GetPlatformInterface() : kDNSServiceInterfaceIndexAny;
5054
}
5155

52-
std::string GetHostNameWithDomain(const char * hostname)
56+
std::string GetHostNameWithLocalDomain(const char * hostname)
5357
{
5458
return std::string(hostname) + '.' + kLocalDot;
5559
}
5660

61+
bool HostNameHasDomain(const char * hostname, const char * domain)
62+
{
63+
size_t domainLength = strlen(domain);
64+
size_t hostnameLength = strlen(hostname);
65+
if (domainLength > hostnameLength)
66+
{
67+
return false;
68+
}
69+
const char * found = strstr(hostname, domain);
70+
if (found == nullptr)
71+
{
72+
return false;
73+
}
74+
return (strncmp(found, domain, domainLength) == 0);
75+
}
76+
5777
void LogOnFailure(const char * name, DNSServiceErrorType err)
5878
{
5979
if (kDNSServiceErr_NoError != err)
@@ -131,10 +151,54 @@ std::shared_ptr<uint32_t> GetCounterHolder(const char * name)
131151
namespace chip {
132152
namespace Dnssd {
133153

154+
155+
std::string GetDomainNameFromHostName(const char * hostname)
156+
{
157+
if (HostNameHasDomain(hostname, kLocalDot))
158+
{
159+
return std::string(kLocalDot);
160+
}
161+
else if (HostNameHasDomain(hostname, kOpenThreadDot))
162+
{
163+
return std::string(kOpenThreadDot);
164+
}
165+
return std::string();
166+
}
167+
134168
Global<MdnsContexts> MdnsContexts::sInstance;
135169

136170
namespace {
137171

172+
/**
173+
* @brief Callback that is called when the timeout for resolving on the kOpenThreadDot domain has expired.
174+
*
175+
* @param[in] systemLayer The system layer.
176+
* @param[in] callbackContext The context passed to the timer callback.
177+
*/
178+
void OpenThreadTimerExpiredCallback(System::Layer * systemLayer, void * callbackContext)
179+
{
180+
ChipLogProgress(Discovery, "Mdns: Resolve completed on the open thread domain.");
181+
VerifyOrReturn(callbackContext != nullptr && systemLayer != nullptr, ChipLogError(Discovery, "Open thread timer callback context is null"));
182+
183+
auto sdCtx = reinterpret_cast<ResolveContext *>(callbackContext);
184+
VerifyOrReturn(sdCtx != nullptr, ChipLogError(Discovery, "Resolve Context is null"));
185+
sdCtx->Finalize();
186+
hasOpenThreadTimerStarted = false;
187+
}
188+
189+
/**
190+
* @brief Starts a timer to wait for the resolution on the kOpenThreadDot domain to happen.
191+
*
192+
* @param[in] timeoutSeconds The timeout in seconds.
193+
* @param[in] ResolveContext The resolve context.
194+
*/
195+
void StartOpenThreadTimer(uint16_t timeoutInMSecs, ResolveContext * ctx)
196+
{
197+
VerifyOrReturn(ctx != nullptr, ChipLogError(Discovery, "Can't schedule open thread timer since context is null"));
198+
DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds16(timeoutInMSecs),
199+
OpenThreadTimerExpiredCallback, reinterpret_cast<void*>(ctx));
200+
}
201+
138202
static void OnRegister(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType err, const char * name, const char * type,
139203
const char * domain, void * context)
140204
{
@@ -183,14 +247,24 @@ static void OnBrowse(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interf
183247

184248
CHIP_ERROR Browse(BrowseHandler * sdCtx, uint32_t interfaceId, const char * type)
185249
{
186-
ChipLogProgress(Discovery, "Browsing for: %s", StringOrNullMarker(type));
187-
DNSServiceRef sdRef;
188-
auto err = DNSServiceBrowse(&sdRef, kBrowseFlags, interfaceId, type, kLocalDot, OnBrowse, sdCtx);
250+
auto err = DNSServiceCreateConnection(&sdCtx->serviceRef);
189251
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
190252

191-
return MdnsContexts::GetInstance().Add(sdCtx, sdRef);
192-
}
253+
// We will browse on both the local domain and the open thread domain.
254+
ChipLogProgress(Discovery, "Browsing for: %s on domain %s", StringOrNullMarker(type), kLocalDot);
255+
256+
auto sdRefLocal = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
257+
err = DNSServiceBrowse(&sdRefLocal, kBrowseFlags, interfaceId, type, kLocalDot, OnBrowse, sdCtx);
258+
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
259+
260+
ChipLogProgress(Discovery, "Browsing for: %s on domain %s", StringOrNullMarker(type), kOpenThreadDot);
261+
262+
DNSServiceRef sdRefOpenThread = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
263+
err = DNSServiceBrowse(&sdRefOpenThread, kBrowseFlags, interfaceId, type, kOpenThreadDot, OnBrowse, sdCtx);
264+
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
193265

266+
return MdnsContexts::GetInstance().Add(sdCtx, sdCtx->serviceRef);
267+
}
194268
CHIP_ERROR Browse(void * context, DnssdBrowseCallback callback, uint32_t interfaceId, const char * type,
195269
DnssdServiceProtocol protocol, intptr_t * browseIdentifier)
196270
{
@@ -219,25 +293,41 @@ static void OnGetAddrInfo(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t i
219293
ReturnOnFailure(MdnsContexts::GetInstance().Has(sdCtx));
220294
LogOnFailure(__func__, err);
221295

296+
sdCtx->domainName = GetDomainNameFromHostName(hostname);
222297
if (kDNSServiceErr_NoError == err)
223298
{
224-
sdCtx->OnNewAddress(interfaceId, address);
299+
std::pair<uint32_t, std::string> key = std::make_pair(interfaceId, sdCtx->domainName);
300+
sdCtx->OnNewAddress(key, address);
225301
}
226302

227303
if (!(flags & kDNSServiceFlagsMoreComing))
228304
{
229305
VerifyOrReturn(sdCtx->HasAddress(), sdCtx->Finalize(kDNSServiceErr_BadState));
230-
sdCtx->Finalize();
306+
307+
if (sdCtx->domainName.compare(kOpenThreadDot) == 0)
308+
{
309+
ChipLogProgress(Discovery, "Mdns: Resolve completed on the open thread domain.");
310+
sdCtx->Finalize();
311+
}
312+
else if (sdCtx->domainName.compare(kLocalDot) == 0)
313+
{
314+
ChipLogProgress(Discovery, "Mdns: Resolve completed on the local domain. Starting a timer for the open thread resolve to come back");
315+
if (!hasOpenThreadTimerStarted)
316+
{
317+
// Schedule a timer to allow the resolve on OpenThread domain to complete.
318+
StartOpenThreadTimer(kOpenThreadTimeoutInMsec, sdCtx);
319+
hasOpenThreadTimerStarted = true;
320+
}
321+
}
231322
}
232323
}
233324

234325
static void GetAddrInfo(ResolveContext * sdCtx)
235326
{
236327
auto protocol = sdCtx->protocol;
237-
238328
for (auto & interface : sdCtx->interfaces)
239329
{
240-
auto interfaceId = interface.first;
330+
auto interfaceId = interface.first.first;
241331
auto hostname = interface.second.fullyQualifiedDomainName.c_str();
242332
auto sdRefCopy = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
243333
auto err = DNSServiceGetAddrInfo(&sdRefCopy, kGetAddrInfoFlags, interfaceId, protocol, hostname, OnGetAddrInfo, sdCtx);
@@ -263,7 +353,13 @@ static void OnResolve(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t inter
263353
if (!(flags & kDNSServiceFlagsMoreComing))
264354
{
265355
VerifyOrReturn(sdCtx->HasInterface(), sdCtx->Finalize(kDNSServiceErr_BadState));
266-
GetAddrInfo(sdCtx);
356+
357+
// If a resolve was not requested on this context, call GetAddrInfo and set the isResolveRequested flag to true.
358+
if (!sdCtx->isResolveRequested)
359+
{
360+
GetAddrInfo(sdCtx);
361+
sdCtx->isResolveRequested = true;
362+
}
267363
}
268364
}
269365

@@ -276,8 +372,13 @@ static CHIP_ERROR Resolve(ResolveContext * sdCtx, uint32_t interfaceId, chip::In
276372
auto err = DNSServiceCreateConnection(&sdCtx->serviceRef);
277373
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
278374

279-
auto sdRefCopy = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
280-
err = DNSServiceResolve(&sdRefCopy, kResolveFlags, interfaceId, name, type, kLocalDot, OnResolve, sdCtx);
375+
// Similar to browse, will try to resolve using both the local domain and the open thread domain.
376+
auto sdRefLocal = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
377+
err = DNSServiceResolve(&sdRefLocal, kResolveFlags, interfaceId, name, type, kLocalDot, OnResolve, sdCtx);
378+
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
379+
380+
auto sdRefOpenThread = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
381+
err = DNSServiceResolve(&sdRefOpenThread, kResolveFlags, interfaceId, name, type, kOpenThreadDot, OnResolve, sdCtx);
281382
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
282383

283384
auto retval = MdnsContexts::GetInstance().Add(sdCtx, sdCtx->serviceRef);
@@ -339,7 +440,7 @@ CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCal
339440

340441
auto regtype = GetFullTypeWithSubTypes(service);
341442
auto interfaceId = GetInterfaceId(service->mInterface);
342-
auto hostname = GetHostNameWithDomain(service->mHostName);
443+
auto hostname = GetHostNameWithLocalDomain(service->mHostName);
343444

344445
return Register(context, callback, interfaceId, regtype.c_str(), service->mName, service->mPort, record, service->mAddressType,
345446
hostname.c_str());
@@ -485,7 +586,7 @@ CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress
485586

486587
auto interfaceId = interface.GetPlatformInterface();
487588
auto rrclass = kDNSServiceClass_IN;
488-
auto fullname = GetHostNameWithDomain(hostname);
589+
auto fullname = GetHostNameWithLocalDomain(hostname);
489590

490591
uint16_t rrtype;
491592
uint16_t rdlen;

src/platform/Darwin/DnssdImpl.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@
2727
#include <string>
2828
#include <vector>
2929

30+
constexpr char kLocalDot[] = "local.";
31+
32+
constexpr char kOpenThreadDot[] = "openthread.thread.home.arpa";
33+
3034
namespace chip {
3135
namespace Dnssd {
3236

37+
std::string GetDomainNameFromHostName(const char * hostname);
38+
3339
enum class ContextType
3440
{
3541
Register,
@@ -227,9 +233,11 @@ struct InterfaceInfo
227233
struct ResolveContext : public GenericContext
228234
{
229235
DnssdResolveCallback callback;
230-
std::map<uint32_t, InterfaceInfo> interfaces;
236+
std::map<std::pair<uint32_t, std::string>, InterfaceInfo> interfaces;
231237
DNSServiceProtocol protocol;
232238
std::string instanceName;
239+
std::string domainName;
240+
bool isResolveRequested = false;
233241
std::shared_ptr<uint32_t> consumerCounter;
234242
BrowseContext * const browseThatCausedResolve; // Can be null
235243

@@ -244,7 +252,7 @@ struct ResolveContext : public GenericContext
244252
void DispatchFailure(const char * errorStr, CHIP_ERROR err) override;
245253
void DispatchSuccess() override;
246254

247-
CHIP_ERROR OnNewAddress(uint32_t interfaceId, const struct sockaddr * address);
255+
CHIP_ERROR OnNewAddress(const std::pair<uint32_t, std::string> interfaceKey, const struct sockaddr * address);
248256
bool HasAddress();
249257

250258
void OnNewInterface(uint32_t interfaceId, const char * fullname, const char * hostname, uint16_t port, uint16_t txtLen,

0 commit comments

Comments
 (0)