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 19, 2022
1 parent 67d6821 commit 5487073
Showing 1 changed file with 118 additions and 15 deletions.
133 changes: 118 additions & 15 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 @@ -36,10 +37,11 @@ constexpr const char * kLocalDot = "local.";
constexpr const char * kProtocolTcp = "._tcp";
constexpr const char * kProtocolUdp = "._udp";

constexpr DNSServiceFlags kRegisterFlags = kDNSServiceFlagsNoAutoRename;
constexpr DNSServiceFlags kBrowseFlags = 0;
constexpr DNSServiceFlags kGetAddrInfoFlags = kDNSServiceFlagsTimeout | kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kResolveFlags = kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kRegisterFlags = kDNSServiceFlagsNoAutoRename;
constexpr DNSServiceFlags kRegisterRecordFlags = kDNSServiceFlagsShared;
constexpr DNSServiceFlags kBrowseFlags = 0;
constexpr DNSServiceFlags kGetAddrInfoFlags = kDNSServiceFlagsTimeout | kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kResolveFlags = kDNSServiceFlagsShareConnection;

bool IsSupportedProtocol(DnssdServiceProtocol protocol)
{
Expand Down Expand Up @@ -162,17 +164,41 @@ MdnsContexts MdnsContexts::sInstance;

namespace {

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

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);
ChipLogDetail(Discovery, "Mdns: %s name: %s, type: %s, domain: %s, flags: %d err %d", __func__, name, type, domain, flags, err);
};

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,
uint16_t port, ScopedTXTRecord & record)
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,
interfaceId);
Expand All @@ -188,12 +214,88 @@ 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 +470,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 5487073

Please sign in to comment.