diff --git a/src/platform/Darwin/DnssdImpl.cpp b/src/platform/Darwin/DnssdImpl.cpp index 98fdd0e19d3b74..b30e2d28cf5135 100644 --- a/src/platform/Darwin/DnssdImpl.cpp +++ b/src/platform/Darwin/DnssdImpl.cpp @@ -18,6 +18,7 @@ #include "MdnsError.h" #include +#include #include #include @@ -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; @@ -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(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, @@ -188,12 +208,69 @@ CHIP_ERROR Register(void * context, DnssdPublishCallback callback, uint32_t inte sdCtx = chip::Platform::New(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) @@ -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()