Add support to browse and resolve on both local and SRP domain (#32779)
* Add domain names matching the DnssdServices stored in Browse Context
This is needed to pass the domain returned from a call to Browse to the Resolve.
* Restyled by clang-format
* Add the domain names to the services vector
* Restyled by clang-format
* Add support to browse and resolve on both local and SRP domain
* Restyled by clang-format
* Fix the code that gets the domain name returned from browse and pass it into the resolve
* Restyled by clang-format
* Apply suggestions from code review
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
* Address review comments
* Updated the comment about shouldStartSRPTimerForResolve
* Restyled by clang-format
* Apply suggestions from code review
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
* Addressed more review comments
* Restyled by clang-format
* Add a null check for domain when erasing the contents of services
* Fix the check for domain name when erasing services and pass the correct ResolveContextWithType for the case where domain is not null during resolve
* Restyled by clang-format
---------
Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
diff --git a/src/platform/Darwin/DnssdContexts.cpp b/src/platform/Darwin/DnssdContexts.cpp
index 06b6e02..66dc4c1 100644
--- a/src/platform/Darwin/DnssdContexts.cpp
+++ b/src/platform/Darwin/DnssdContexts.cpp
@@ -30,12 +30,6 @@
constexpr uint8_t kDnssdKeyMaxSize = 32;
constexpr uint8_t kDnssdTxtRecordMaxEntries = 20;
-constexpr char kLocalDot[] = "local.";
-
-bool IsLocalDomain(const char * domain)
-{
- return strcmp(kLocalDot, domain) == 0;
-}
std::string GetHostNameWithoutDomain(const char * hostnameWithDomain)
{
@@ -341,7 +335,8 @@
mHostNameRegistrar.Register();
}
-BrowseContext * BrowseContext::sContextDispatchingSuccess = nullptr;
+BrowseContext * BrowseContext::sContextDispatchingSuccess = nullptr;
+std::vector<DnssdService> * BrowseContext::sDispatchedServices = nullptr;
BrowseContext::BrowseContext(void * cbContext, DnssdBrowseCallback cb, DnssdServiceProtocol cbContextProtocol)
{
@@ -373,7 +368,10 @@
{
dnsServices.push_back(std::move(iter.first));
}
+
+ sDispatchedServices = &dnsServices;
callback(context, dnsServices.data(), dnsServices.size(), false, CHIP_NO_ERROR);
+ sDispatchedServices = nullptr;
sContextDispatchingSuccess = nullptr;
services.clear();
}
@@ -393,7 +391,6 @@
ChipLogProgress(Discovery, "Mdns: %s name: %s, type: %s, domain: %s, interface: %" PRIu32, __func__, StringOrNullMarker(name),
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
- VerifyOrReturn(IsLocalDomain(domain));
auto service = GetService(name, type, protocol, interfaceId);
services.push_back(std::make_pair(std::move(service), std::string(domain)));
}
@@ -404,13 +401,13 @@
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
VerifyOrReturn(name != nullptr);
- VerifyOrReturn(IsLocalDomain(domain));
+ std::string domain_str(domain);
services.erase(std::remove_if(services.begin(), services.end(),
- [name, type, interfaceId, domain](const auto & service) {
+ [name, type, interfaceId, &domain_str](const auto & service) {
return strcmp(name, service.first.mName) == 0 && type == GetFullType(&service.first) &&
service.first.mInterface == chip::Inet::InterfaceId(interfaceId) &&
- strcmp(domain, service.second.c_str()) == 0;
+ service.second == domain_str;
}),
services.end());
}
@@ -449,8 +446,6 @@
ChipLogProgress(Discovery, "Mdns: %s name: %s, type: %s, domain: %s, interface: %" PRIu32, __func__, StringOrNullMarker(name),
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
- VerifyOrReturn(IsLocalDomain(domain));
-
auto delegate = static_cast<DnssdBrowseDelegate *>(context);
auto service = GetService(name, type, protocol, interfaceId);
delegate->OnBrowseAdd(service);
@@ -462,7 +457,6 @@
StringOrNullMarker(type), StringOrNullMarker(domain), interfaceId);
VerifyOrReturn(name != nullptr);
- VerifyOrReturn(IsLocalDomain(domain));
auto delegate = static_cast<DnssdBrowseDelegate *>(context);
auto service = GetService(name, type, protocol, interfaceId);
@@ -494,7 +488,13 @@
consumerCounter = std::move(consumerCounterToUse);
}
-ResolveContext::~ResolveContext() {}
+ResolveContext::~ResolveContext()
+{
+ if (isSRPTimerRunning)
+ {
+ CancelSRPTimer();
+ }
+}
void ResolveContext::DispatchFailure(const char * errorStr, CHIP_ERROR err)
{
@@ -554,7 +554,8 @@
for (auto & interface : interfaces)
{
- if (TryReportingResultsForInterfaceIndex(interface.first))
+ if (TryReportingResultsForInterfaceIndex(interface.first.interfaceId, interface.first.hostname,
+ interface.first.isSRPResult))
{
break;
}
@@ -566,7 +567,7 @@
}
}
-bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex)
+bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex, const std::string & hostname, bool isSRPResult)
{
if (interfaceIndex == 0)
{
@@ -574,8 +575,9 @@
return false;
}
- auto & interface = interfaces[interfaceIndex];
- auto & ips = interface.addresses;
+ InterfaceKey interfaceKey = { interfaceIndex, hostname, isSRPResult };
+ auto & interface = interfaces[interfaceKey];
+ auto & ips = interface.addresses;
// Some interface may not have any ips, just ignore them.
if (ips.size() == 0)
@@ -602,7 +604,35 @@
return true;
}
-CHIP_ERROR ResolveContext::OnNewAddress(uint32_t interfaceId, const struct sockaddr * address)
+bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex)
+{
+ for (auto & interface : interfaces)
+ {
+ if (interface.first.interfaceId == interfaceIndex)
+ {
+ if (TryReportingResultsForInterfaceIndex(interface.first.interfaceId, interface.first.hostname,
+ interface.first.isSRPResult))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void ResolveContext::SRPTimerExpiredCallback(chip::System::Layer * systemLayer, void * callbackContext)
+{
+ auto sdCtx = static_cast<ResolveContext *>(callbackContext);
+ VerifyOrDie(sdCtx != nullptr);
+ sdCtx->Finalize();
+}
+
+void ResolveContext::CancelSRPTimer()
+{
+ DeviceLayer::SystemLayer().CancelTimer(SRPTimerExpiredCallback, static_cast<void *>(this));
+}
+
+CHIP_ERROR ResolveContext::OnNewAddress(const InterfaceKey & interfaceKey, const struct sockaddr * address)
{
// If we don't have any information about this interfaceId, just ignore the
// address, since it won't be usable anyway without things like the port.
@@ -610,7 +640,9 @@
// on the system, because the hostnames we are looking up all end in
// ".local". In other words, we can get regular DNS results in here, not
// just DNS-SD ones.
- if (interfaces.find(interfaceId) == interfaces.end())
+ auto interfaceId = interfaceKey.interfaceId;
+
+ if (interfaces.find(interfaceKey) == interfaces.end())
{
return CHIP_NO_ERROR;
}
@@ -633,7 +665,7 @@
return CHIP_NO_ERROR;
}
- interfaces[interfaceId].addresses.push_back(ip);
+ interfaces[interfaceKey].addresses.push_back(ip);
return CHIP_NO_ERROR;
}
@@ -652,7 +684,7 @@
}
void ResolveContext::OnNewInterface(uint32_t interfaceId, const char * fullname, const char * hostnameWithDomain, uint16_t port,
- uint16_t txtLen, const unsigned char * txtRecord)
+ uint16_t txtLen, const unsigned char * txtRecord, bool isFromSRPResolve)
{
#if CHIP_PROGRESS_LOGGING
std::string txtString;
@@ -715,7 +747,8 @@
// resolving.
interface.fullyQualifiedDomainName = hostnameWithDomain;
- interfaces.insert(std::make_pair(interfaceId, std::move(interface)));
+ InterfaceKey interfaceKey = { interfaceId, hostnameWithDomain, isFromSRPResolve };
+ interfaces.insert(std::make_pair(std::move(interfaceKey), std::move(interface)));
}
bool ResolveContext::HasInterface()
@@ -731,7 +764,7 @@
InterfaceInfo::InterfaceInfo(InterfaceInfo && other) :
service(std::move(other.service)), addresses(std::move(other.addresses)),
- fullyQualifiedDomainName(std::move(other.fullyQualifiedDomainName))
+ fullyQualifiedDomainName(std::move(other.fullyQualifiedDomainName)), isDNSLookUpRequested(other.isDNSLookUpRequested)
{
// Make sure we're not trying to free any state from the other DnssdService,
// since we took over ownership of its allocated bits.
diff --git a/src/platform/Darwin/DnssdImpl.cpp b/src/platform/Darwin/DnssdImpl.cpp
index 7e9e7af..a6b1fd9 100644
--- a/src/platform/Darwin/DnssdImpl.cpp
+++ b/src/platform/Darwin/DnssdImpl.cpp
@@ -24,7 +24,6 @@
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>
-#include <platform/CHIPDeviceLayer.h>
using namespace chip::Dnssd;
using namespace chip::Dnssd::Internal;
@@ -33,8 +32,13 @@
constexpr char kLocalDot[] = "local.";
+constexpr char kSRPDot[] = "default.service.arpa.";
+
+// The extra time in milliseconds that we will wait for the resolution on the SRP domain to complete.
+constexpr uint16_t kSRPTimeoutInMsec = 250;
+
constexpr DNSServiceFlags kRegisterFlags = kDNSServiceFlagsNoAutoRename;
-constexpr DNSServiceFlags kBrowseFlags = 0;
+constexpr DNSServiceFlags kBrowseFlags = kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kGetAddrInfoFlags = kDNSServiceFlagsTimeout | kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kResolveFlags = kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kReconfirmRecordFlags = 0;
@@ -62,6 +66,19 @@
}
}
+/**
+ * @brief Starts a timer to wait for the resolution on the kSRPDot domain to happen.
+ *
+ * @param[in] timeoutSeconds The timeout in seconds.
+ * @param[in] ResolveContext The resolve context.
+ */
+CHIP_ERROR StartSRPTimer(uint16_t timeoutInMSecs, ResolveContext * ctx)
+{
+ VerifyOrReturnValue(ctx != nullptr, CHIP_ERROR_INCORRECT_STATE);
+ return chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds16(timeoutInMSecs),
+ ResolveContext::SRPTimerExpiredCallback, static_cast<void *>(ctx));
+}
+
class ScopedTXTRecord
{
public:
@@ -181,14 +198,28 @@
sdCtx->OnBrowse(flags, name, type, domain, interfaceId);
}
+CHIP_ERROR BrowseOnDomain(BrowseHandler * sdCtx, uint32_t interfaceId, const char * type, const char * domain)
+{
+ auto sdRef = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
+
+ auto err = DNSServiceBrowse(&sdRef, kBrowseFlags, interfaceId, type, domain, OnBrowse, sdCtx);
+ VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
+ return CHIP_NO_ERROR;
+}
+
CHIP_ERROR Browse(BrowseHandler * sdCtx, uint32_t interfaceId, const char * type)
{
- ChipLogProgress(Discovery, "Browsing for: %s", StringOrNullMarker(type));
- DNSServiceRef sdRef;
- auto err = DNSServiceBrowse(&sdRef, kBrowseFlags, interfaceId, type, kLocalDot, OnBrowse, sdCtx);
+ auto err = DNSServiceCreateConnection(&sdCtx->serviceRef);
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
- return MdnsContexts::GetInstance().Add(sdCtx, sdRef);
+ // We will browse on both the local domain and the SRP domain.
+ ChipLogProgress(Discovery, "Browsing for: %s on local domain", StringOrNullMarker(type));
+ ReturnErrorOnFailure(BrowseOnDomain(sdCtx, interfaceId, type, kLocalDot));
+
+ ChipLogProgress(Discovery, "Browsing for: %s on %s domain", StringOrNullMarker(type), kSRPDot);
+ ReturnErrorOnFailure(BrowseOnDomain(sdCtx, interfaceId, type, kSRPDot));
+
+ return MdnsContexts::GetInstance().Add(sdCtx, sdCtx->serviceRef);
}
CHIP_ERROR Browse(void * context, DnssdBrowseCallback callback, uint32_t interfaceId, const char * type,
@@ -215,20 +246,56 @@
{
ChipLogProgress(Discovery, "Mdns: %s flags: %d, interface: %u, hostname: %s", __func__, flags, (unsigned) interfaceId,
StringOrNullMarker(hostname));
- auto sdCtx = reinterpret_cast<ResolveContext *>(context);
+
+ auto contextWithType = reinterpret_cast<ResolveContextWithType *>(context);
+ VerifyOrReturn(contextWithType != nullptr, ChipLogError(Discovery, "ResolveContextWithType is null"));
+
+ auto sdCtx = contextWithType->context;
ReturnOnFailure(MdnsContexts::GetInstance().Has(sdCtx));
LogOnFailure(__func__, err);
if (kDNSServiceErr_NoError == err)
{
- sdCtx->OnNewAddress(interfaceId, address);
+ InterfaceKey interfaceKey = { interfaceId, hostname, contextWithType->isSRPResolve };
+ CHIP_ERROR error = sdCtx->OnNewAddress(interfaceKey, address);
+
+ // If we saw an address resolved on the SRP domain, we don't need to wait
+ // for SRP results, so don't bother with starting a timer to wait for those.
+ if (error == CHIP_NO_ERROR && contextWithType->isSRPResolve)
+ {
+ sdCtx->shouldStartSRPTimerForResolve = false;
+ }
}
- if (!(flags & kDNSServiceFlagsMoreComing))
+ if (flags & kDNSServiceFlagsMoreComing)
{
- VerifyOrReturn(sdCtx->HasAddress(), sdCtx->Finalize(kDNSServiceErr_BadState));
+ return;
+ }
+
+ VerifyOrReturn(sdCtx->HasAddress(), sdCtx->Finalize(kDNSServiceErr_BadState));
+
+ // If either we didn't start a resolve on the SRP domain or we started a resolve on the SRP domain and got an address,
+ // we are done. Otherwise start the timer to give the resolve on SRP domain some extra time to complete.
+ if (!sdCtx->shouldStartSRPTimerForResolve)
+ {
sdCtx->Finalize();
}
+ else
+ {
+ if (!sdCtx->isSRPTimerRunning)
+ {
+ CHIP_ERROR error = StartSRPTimer(kSRPTimeoutInMsec, sdCtx);
+
+ if (error != CHIP_NO_ERROR)
+ {
+ // If we failed to start the timer, just go ahead and report whatever information
+ // we have gotten so far.
+ sdCtx->Finalize();
+ return;
+ }
+ sdCtx->isSRPTimerRunning = true;
+ }
+ }
}
static void GetAddrInfo(ResolveContext * sdCtx)
@@ -237,11 +304,21 @@
for (auto & interface : sdCtx->interfaces)
{
- auto interfaceId = interface.first;
+ if (interface.second.isDNSLookUpRequested)
+ {
+ continue;
+ }
+
+ auto interfaceId = interface.first.interfaceId;
auto hostname = interface.second.fullyQualifiedDomainName.c_str();
auto sdRefCopy = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
- auto err = DNSServiceGetAddrInfo(&sdRefCopy, kGetAddrInfoFlags, interfaceId, protocol, hostname, OnGetAddrInfo, sdCtx);
+
+ ResolveContextWithType * contextWithType =
+ (interface.first.isSRPResult) ? &sdCtx->resolveContextWithSRPType : &sdCtx->resolveContextWithNonSRPType;
+ auto err =
+ DNSServiceGetAddrInfo(&sdRefCopy, kGetAddrInfoFlags, interfaceId, protocol, hostname, OnGetAddrInfo, contextWithType);
VerifyOrReturn(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
+ interface.second.isDNSLookUpRequested = true;
}
}
@@ -251,13 +328,17 @@
{
ChipLogProgress(Discovery, "Mdns: %s flags: %d, interface: %u, fullname: %s, hostname: %s, port: %u", __func__, flags,
(unsigned) interfaceId, StringOrNullMarker(fullname), StringOrNullMarker(hostname), ntohs(port));
- auto sdCtx = reinterpret_cast<ResolveContext *>(context);
+
+ auto contextWithType = reinterpret_cast<ResolveContextWithType *>(context);
+ VerifyOrReturn(contextWithType != nullptr, ChipLogError(Discovery, "ResolveContextWithType is null"));
+
+ auto sdCtx = contextWithType->context;
ReturnOnFailure(MdnsContexts::GetInstance().Has(sdCtx));
LogOnFailure(__func__, err);
if (kDNSServiceErr_NoError == err)
{
- sdCtx->OnNewInterface(interfaceId, fullname, hostname, port, txtLen, txtRecord);
+ sdCtx->OnNewInterface(interfaceId, fullname, hostname, port, txtLen, txtRecord, contextWithType->isSRPResolve);
}
if (!(flags & kDNSServiceFlagsMoreComing))
@@ -267,8 +348,18 @@
}
}
+static CHIP_ERROR ResolveWithContext(ResolveContext * sdCtx, uint32_t interfaceId, const char * type, const char * name,
+ const char * domain, ResolveContextWithType * contextWithType)
+{
+ auto sdRef = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
+
+ auto err = DNSServiceResolve(&sdRef, kResolveFlags, interfaceId, name, type, domain, OnResolve, contextWithType);
+ VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
+ return CHIP_NO_ERROR;
+}
+
static CHIP_ERROR Resolve(ResolveContext * sdCtx, uint32_t interfaceId, chip::Inet::IPAddressType addressType, const char * type,
- const char * name)
+ const char * name, const char * domain)
{
ChipLogProgress(Discovery, "Resolve type=%s name=%s interface=%" PRIu32, StringOrNullMarker(type), StringOrNullMarker(name),
interfaceId);
@@ -276,9 +367,23 @@
auto err = DNSServiceCreateConnection(&sdCtx->serviceRef);
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
- auto sdRefCopy = sdCtx->serviceRef; // Mandatory copy because of kDNSServiceFlagsShareConnection
- err = DNSServiceResolve(&sdRefCopy, kResolveFlags, interfaceId, name, type, kLocalDot, OnResolve, sdCtx);
- VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
+ // If we have a single domain from a browse, we will use that for the Resolve.
+ // Otherwise we will try to resolve using both the local domain and the SRP domain.
+ if (domain != nullptr)
+ {
+ ReturnErrorOnFailure(ResolveWithContext(sdCtx, interfaceId, type, name, domain, &sdCtx->resolveContextWithNonSRPType));
+ sdCtx->shouldStartSRPTimerForResolve = false;
+ }
+ else
+ {
+ ReturnErrorOnFailure(ResolveWithContext(sdCtx, interfaceId, type, name, kLocalDot, &sdCtx->resolveContextWithNonSRPType));
+
+ ReturnErrorOnFailure(ResolveWithContext(sdCtx, interfaceId, type, name, kSRPDot, &sdCtx->resolveContextWithNonSRPType));
+
+ // Set the flag to start the timer for resolve on SRP domain to complete since a resolve has been requested on the SRP
+ // domain.
+ sdCtx->shouldStartSRPTimerForResolve = true;
+ }
auto retval = MdnsContexts::GetInstance().Add(sdCtx, sdCtx->serviceRef);
if (retval == CHIP_NO_ERROR)
@@ -289,14 +394,14 @@
}
static CHIP_ERROR Resolve(void * context, DnssdResolveCallback callback, uint32_t interfaceId,
- chip::Inet::IPAddressType addressType, const char * type, const char * name)
+ chip::Inet::IPAddressType addressType, const char * type, const char * name, const char * domain)
{
auto counterHolder = GetCounterHolder(name);
auto sdCtx = chip::Platform::New<ResolveContext>(context, callback, addressType, name,
BrowseContext::sContextDispatchingSuccess, std::move(counterHolder));
VerifyOrReturnError(nullptr != sdCtx, CHIP_ERROR_NO_MEMORY);
- return Resolve(sdCtx, interfaceId, addressType, type, name);
+ return Resolve(sdCtx, interfaceId, addressType, type, name, domain);
}
static CHIP_ERROR Resolve(CommissioningResolveDelegate * delegate, uint32_t interfaceId, chip::Inet::IPAddressType addressType,
@@ -306,7 +411,7 @@
auto sdCtx = chip::Platform::New<ResolveContext>(delegate, addressType, name, std::move(counterHolder));
VerifyOrReturnError(nullptr != sdCtx, CHIP_ERROR_NO_MEMORY);
- return Resolve(sdCtx, interfaceId, addressType, type, name);
+ return Resolve(sdCtx, interfaceId, addressType, type, name, nullptr);
}
} // namespace
@@ -442,9 +547,23 @@
VerifyOrReturnError(service != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(IsSupportedProtocol(service->mProtocol), CHIP_ERROR_INVALID_ARGUMENT);
- auto regtype = GetFullType(service);
- auto interfaceId = GetInterfaceId(interface);
- return Resolve(context, callback, interfaceId, service->mAddressType, regtype.c_str(), service->mName);
+ auto regtype = GetFullType(service);
+ auto interfaceId = GetInterfaceId(interface);
+ const char * domain = nullptr;
+
+ if (BrowseContext::sContextDispatchingSuccess != nullptr)
+ {
+ for (size_t i = 0; i < BrowseContext::sDispatchedServices->size(); ++i)
+ {
+ if (service == &BrowseContext::sDispatchedServices->at(i))
+ {
+ domain = BrowseContext::sContextDispatchingSuccess->services[i].second.c_str();
+ break;
+ }
+ }
+ }
+
+ return Resolve(context, callback, interfaceId, service->mAddressType, regtype.c_str(), service->mName, domain);
}
CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, CommissioningResolveDelegate * delegate)
diff --git a/src/platform/Darwin/DnssdImpl.h b/src/platform/Darwin/DnssdImpl.h
index f095180..351926a 100644
--- a/src/platform/Darwin/DnssdImpl.h
+++ b/src/platform/Darwin/DnssdImpl.h
@@ -20,6 +20,7 @@
#include <dns_sd.h>
#include <lib/core/Global.h>
#include <lib/dnssd/platform/Dnssd.h>
+#include <platform/CHIPDeviceLayer.h>
#include "DnssdHostNameRegistrar.h"
@@ -194,6 +195,7 @@
// TODO: Consider fixing the higher-level APIs to make it possible to pass
// in multiple IPs for a successful browse result.
static BrowseContext * sContextDispatchingSuccess;
+ static std::vector<DnssdService> * sDispatchedServices;
};
struct BrowseWithDelegateContext : public BrowseHandler
@@ -222,17 +224,52 @@
DnssdService service;
std::vector<Inet::IPAddress> addresses;
std::string fullyQualifiedDomainName;
+ bool isDNSLookUpRequested = false;
+};
+
+struct InterfaceKey
+{
+ InterfaceKey() = default;
+ ~InterfaceKey() = default;
+ inline bool operator<(const InterfaceKey & other) const
+ {
+ return (this->interfaceId < other.interfaceId) ||
+ ((this->interfaceId == other.interfaceId) && (this->hostname < other.hostname)) ||
+ ((this->interfaceId == other.interfaceId) && (this->hostname == other.hostname) &&
+ (this->isSRPResult < other.isSRPResult));
+ }
+
+ uint32_t interfaceId;
+ std::string hostname;
+ bool isSRPResult = false;
+};
+
+struct ResolveContextWithType
+{
+ ResolveContextWithType() = delete;
+ ~ResolveContextWithType() = default;
+
+ ResolveContext * const context;
+ const bool isSRPResolve;
};
struct ResolveContext : public GenericContext
{
DnssdResolveCallback callback;
- std::map<uint32_t, InterfaceInfo> interfaces;
+ std::map<InterfaceKey, InterfaceInfo> interfaces;
DNSServiceProtocol protocol;
std::string instanceName;
std::shared_ptr<uint32_t> consumerCounter;
BrowseContext * const browseThatCausedResolve; // Can be null
+ // Indicates whether the timer for 250 msecs should be started
+ // to give the resolve on SRP domain some extra time to complete.
+ bool shouldStartSRPTimerForResolve = false;
+ bool isSRPTimerRunning = false;
+
+ ResolveContextWithType resolveContextWithSRPType = { this, true };
+ ResolveContextWithType resolveContextWithNonSRPType = { this, false };
+
// browseCausingResolve can be null.
ResolveContext(void * cbContext, DnssdResolveCallback cb, chip::Inet::IPAddressType cbAddressType,
const char * instanceNameToResolve, BrowseContext * browseCausingResolve,
@@ -244,21 +281,37 @@
void DispatchFailure(const char * errorStr, CHIP_ERROR err) override;
void DispatchSuccess() override;
- CHIP_ERROR OnNewAddress(uint32_t interfaceId, const struct sockaddr * address);
+ CHIP_ERROR OnNewAddress(const InterfaceKey & interfaceKey, const struct sockaddr * address);
bool HasAddress();
void OnNewInterface(uint32_t interfaceId, const char * fullname, const char * hostname, uint16_t port, uint16_t txtLen,
- const unsigned char * txtRecord);
+ const unsigned char * txtRecord, bool isSRPResult);
bool HasInterface();
bool Matches(const char * otherInstanceName) const { return instanceName == otherInstanceName; }
+ /**
+ * @brief Callback that is called when the timeout for resolving on the kSRPDot domain has expired.
+ *
+ * @param[in] systemLayer The system layer.
+ * @param[in] callbackContext The context passed to the timer callback.
+ */
+ static void SRPTimerExpiredCallback(chip::System::Layer * systemLayer, void * callbackContext);
+
private:
/**
* Try reporting the results we got on the provided interface index.
* Returns true if information was reported, false if not (e.g. if there
* were no IP addresses, etc).
*/
+ bool TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex, const std::string & hostname, bool isSRPResult);
+
bool TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex);
+
+ /**
+ * @brief Cancels the timer that was started to wait for the resolution on the kSRPDot domain to happen.
+ *
+ */
+ void CancelSRPTimer();
};
} // namespace Dnssd