Skip to content

Commit

Permalink
Register the DNS service for the accessory with a valid hostname
Browse files Browse the repository at this point in the history
- Call DNSServiceRegisterRecord to register a record for the hostname for all interfaces
  before calling DNSServiceRegister.
  • Loading branch information
nivi-apple committed Aug 17, 2022
1 parent 8cf3894 commit c0fb8da
Showing 1 changed file with 88 additions and 10 deletions.
98 changes: 88 additions & 10 deletions src/platform/Darwin/DnssdImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "MdnsError.h"

#include <cstdio>
#include <ifaddrs.h>
#include <sstream>
#include <string.h>

Expand All @@ -37,6 +38,7 @@ constexpr const char * kProtocolTcp = "._tcp";
constexpr const char * kProtocolUdp = "._udp";

constexpr DNSServiceFlags kRegisterFlags = kDNSServiceFlagsNoAutoRename;
constexpr DNSServiceFlags kRegisterRecordFlags = kDNSServiceFlagsShared;
constexpr DNSServiceFlags kBrowseFlags = 0;
constexpr DNSServiceFlags kGetAddrInfoFlags = kDNSServiceFlagsTimeout | kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kResolveFlags = kDNSServiceFlagsShareConnection;
Expand Down Expand Up @@ -162,16 +164,34 @@ MdnsContexts MdnsContexts::sInstance;

namespace {

static void OnRegisterRecord(DNSServiceRef sdRef, DNSRecordRef recordRef, DNSServiceFlags flags, DNSServiceErrorType err, void *context)
{
ChipLogDetail(Discovery, "Mdns: %s Registered Record");
};

static void OnRegister(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType err, const char * name, const char * type,
const char * domain, void * context)
{
ChipLogDetail(Discovery, "Mdns: %s name: %s, type: %s, domain: %s, flags: %d", __func__, name, type, domain, flags);

auto sdCtx = reinterpret_cast<RegisterContext *>(context);
sdCtx->Finalize(err);
};

CHIP_ERROR Register(void * context, DnssdPublishCallback callback, uint32_t interfaceId, const char * type, const char * name,
CHIP_ERROR RegisterService(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceId, const char * name, const char * type, const char * domain,
const char * hostname, uint16_t port, uint16_t txtLen, const void *txtRecord, DNSServiceRegisterReply callback, RegisterContext * sdCtx)
{
auto err = DNSServiceRegister(&sdRef, flags, interfaceId, name, type, domain, hostname, ntohs(port), txtLen,
txtRecord, callback, sdCtx);
if (hostname) {
ChipLogProgress(Discovery, "Registering service %s on port %u with type: %s on interface id: %u hostname %s error: %d" PRIu32, name, port, type,
interfaceId, hostname, err);
} else {
ChipLogProgress(Discovery, "Registering service %s on port %u with type: %s on interface id: %u error: %d" PRIu32, name, port, type,
interfaceId, err);
}
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
return MdnsContexts::GetInstance().Add(sdCtx, sdRef);
}

CHIP_ERROR Register(void * context, DnssdPublishCallback callback, uint32_t interfaceId, const char * type, const char * name, const char * hostname,
uint16_t port, ScopedTXTRecord & record)
{
ChipLogProgress(Discovery, "Publishing service %s on port %u with type: %s on interface id: %" PRIu32, name, port, type,
Expand All @@ -188,12 +208,69 @@ CHIP_ERROR Register(void * context, DnssdPublishCallback callback, uint32_t inte
sdCtx = chip::Platform::New<RegisterContext>(type, callback, context);
VerifyOrReturnError(nullptr != sdCtx, CHIP_ERROR_NO_MEMORY);

DNSServiceRef sdRef;
auto err = DNSServiceRegister(&sdRef, kRegisterFlags, interfaceId, name, type, kLocalDot, nullptr, ntohs(port), record.size(),
record.data(), OnRegister, sdCtx);
VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
// Treat empty hostname as null.
if (hostname != nullptr && strcmp(hostname, "") == 0) {
hostname = nullptr;
}
std::string hostnameStr;
if (hostname != nullptr) {
hostnameStr = std::string(hostname) + '.' + kLocalDot;
hostname = hostnameStr.c_str();
}

return MdnsContexts::GetInstance().Add(sdCtx, sdRef);
DNSServiceRef sdRef = nullptr;
if (hostname) {
auto err = DNSServiceCreateConnection(&sdRef);
if (sdRef != nullptr && !err) {
DNSRecordRef dnsRecordRef;

// Get all the interface addresses
struct ifaddrs* ifaddr;
auto ret = getifaddrs(&ifaddr);
if (ret) {
ChipLogError(Discovery, "Getting interface addresses failed %d. Proceed registering service with default hostname", ret);
freeifaddrs(ifaddr);
return RegisterService(sdRef, kRegisterFlags, interfaceId, name, type, kLocalDot, nullptr, port, record.size(),
record.data(), OnRegister, sdCtx);
}

// Call DNSServiceRegisterRecord for each interface so we can register the address for each interface
for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in* inaddr = (struct sockaddr_in*) ifa->ifa_addr;
if (inaddr) {
ChipLogDetail(Discovery, "Registering Record for hostname %s interface %d", hostname, if_nametoindex(ifa->ifa_name));
err = DNSServiceRegisterRecord(sdRef, &dnsRecordRef, kRegisterRecordFlags, if_nametoindex(ifa->ifa_name), hostname,
kDNSServiceType_A, kDNSServiceClass_IN, 4, &inaddr->sin_addr, 0, OnRegisterRecord, sdCtx);
if (err) {
freeifaddrs(ifaddr);
return RegisterService(sdRef, kRegisterFlags, interfaceId, name, type, kLocalDot, nullptr, port, record.size(),
record.data(), OnRegister, sdCtx);
}
}
} else if (ifa->ifa_addr->sa_family == AF_INET6) {
struct sockaddr_in6* inaddr = (struct sockaddr_in6*) ifa->ifa_addr;
if (inaddr) {
ChipLogDetail(Discovery, "Registering Record for hostname %s interface %d", hostname, if_nametoindex(ifa->ifa_name));
err = DNSServiceRegisterRecord(sdRef, &dnsRecordRef, kRegisterRecordFlags, if_nametoindex(ifa->ifa_name), hostname,
kDNSServiceType_AAAA, kDNSServiceClass_IN, 16, &inaddr->sin6_addr, 0, OnRegisterRecord, sdCtx);
if (err) {
freeifaddrs(ifaddr);
return RegisterService(sdRef, kRegisterFlags, interfaceId, name, type, kLocalDot, nullptr, port, record.size(),
record.data(), OnRegister, sdCtx);
}
}
}
}
freeifaddrs(ifaddr);
}
return RegisterService(sdRef, kRegisterFlags, interfaceId, name, type, kLocalDot, hostname, port, record.size(),
record.data(), OnRegister, sdCtx);
} else {
return RegisterService(sdRef, kRegisterFlags, interfaceId, name, type, kLocalDot, nullptr, port, record.size(),
record.data(), OnRegister, sdCtx);
}
}

void OnBrowseAdd(BrowseContext * context, const char * name, const char * type, const char * domain, uint32_t interfaceId)
Expand Down Expand Up @@ -368,7 +445,8 @@ CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCal

auto regtype = GetFullTypeWithSubTypes(service);
auto interfaceId = GetInterfaceId(service->mInterface);
return Register(context, callback, interfaceId, regtype.c_str(), service->mName, service->mPort, record);

return Register(context, callback, interfaceId, regtype.c_str(), service->mName, service->mHostName, service->mPort, record);
}

CHIP_ERROR ChipDnssdRemoveServices()
Expand Down

0 comments on commit c0fb8da

Please sign in to comment.