/* * * Copyright (c) 2020 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * This file defines the platform API to publish and subscribe mDNS * services. * * You can find the implementation in src/platform/\/DnssdImpl.cpp. */ #pragma once #include #include #include #include #include #include #include #include #include #include "DnssdBrowseDelegate.h" namespace chip { namespace Dnssd { // None of these sizes include an null character at the end. static constexpr size_t kDnssdProtocolTextMaxSize = std::max(sizeof(kOperationalProtocol), sizeof(kCommissionProtocol)) - 1; static constexpr size_t kDnssdTypeMaxSize = std::max({ sizeof(kCommissionableServiceName), sizeof(kOperationalServiceName), sizeof(kCommissionerServiceName) }) - 1; static constexpr uint8_t kDnssdTypeAndProtocolMaxSize = kDnssdTypeMaxSize + kDnssdProtocolTextMaxSize + 1; // . static constexpr uint16_t kDnssdTextMaxSize = 64; static constexpr uint8_t kDnssdFullTypeAndProtocolMaxSize = Common::kSubTypeMaxLength + /* '.' */ 1 + kDnssdTypeAndProtocolMaxSize; enum class DnssdServiceProtocol : uint8_t { kDnssdProtocolUdp = 0, kDnssdProtocolTcp, kDnssdProtocolUnknown = 255, }; struct TextEntry { const char * mKey; const uint8_t * mData; size_t mDataSize; }; struct DnssdService { char mName[Common::kInstanceNameMaxLength + 1]; char mHostName[kHostNameMaxLength + 1] = ""; char mType[kDnssdTypeMaxSize + 1]; DnssdServiceProtocol mProtocol; Inet::IPAddressType mAddressType; // Address record type to query or publish (A or AAAA) Inet::IPAddressType mTransportType; // Transport to use for the query. uint16_t mPort; chip::Inet::InterfaceId mInterface; TextEntry * mTextEntries; size_t mTextEntrySize; const char ** mSubTypes; size_t mSubTypeSize; std::optional mAddress; // Time to live in seconds. Per rfc6762 section 10, because we have a hostname, our default TTL is 120 seconds uint32_t mTtlSeconds = 120; void ToDiscoveredCommissionNodeData(const Span & addresses, DiscoveredNodeData & nodeData); void ToDiscoveredOperationalNodeBrowseData(DiscoveredNodeData & nodeData); }; /** * The callback function for mDNS resolve. * * The callback function SHALL NOT take the ownership of the service pointer or * any pointer inside this structure. * * @param[in] context The context passed to ChipDnssdBrowse or ChipDnssdResolve. * @param[in] result The mDNS resolve result, can be nullptr if error * happens. The mAddress of this object will be ignored. * @param[in] addresses IP addresses that we resolved. * @param[in] error The error code. * */ using DnssdResolveCallback = void (*)(void * context, DnssdService * result, const Span & addresses, CHIP_ERROR error); /** * The callback function for mDNS browse. * * The callback function SHALL NOT take the ownership of the service pointer or * any pointer inside this structure. * * The callback function SHALL release its internal resources only when the * finalBrowse is true or when the error is not CHIP_NO_ERROR. Calling this * callback function again in either case is a programming error. * * @param[in] context The context passed to ChipDnssdBrowse or ChipDnssdResolve. * @param[in] services The service list, can be nullptr. * @param[in] servicesSize The size of the service list. * @param[in] finalBrowse When true, this is the last callback for this browse. * @param[in] error The error code. * */ using DnssdBrowseCallback = void (*)(void * context, DnssdService * services, size_t servicesSize, bool finalBrowse, CHIP_ERROR error); /** * The callback function for mDNS publish. * * Will be called when publishing succeeds or fails. * * The callback function SHALL NOT take the ownership of the service pointer or * any pointer inside this structure. * * @param[in] context The context passed to ChipDnssdPublishService. * @param[in] type The published type if no errors have occured, nullptr otherwise. * @param[in] instanceName The published instance name if no errors have occured, nullptr otherwise. * @param[in] error The error code. * */ using DnssdPublishCallback = void (*)(void * context, const char * type, const char * instanceName, CHIP_ERROR error); using DnssdAsyncReturnCallback = void (*)(void * context, CHIP_ERROR error); /** * This function initializes the mDNS module * * @param[in] initCallback The callback for notifying the initialization result. * @param[in] errorCallback The callback for notifying internal errors. * @param[in] context The context passed to the callbacks. * * @retval CHIP_NO_ERROR The initialization succeeds. * @retval Error code The initialization fails * */ CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context); /** * This function shuts down the mDNS module */ void ChipDnssdShutdown(); /** * Removes or marks all services being advertised for removal. * * Depending on the implementation, the function may either stop advertising existing services * immediately, or mark them for removal upon the subsequent `ChipDnssdFinalizeServiceUpdate` call. * * @retval CHIP_NO_ERROR The removal succeeds. * @retval Error code The removal fails. */ CHIP_ERROR ChipDnssdRemoveServices(); /** * This function publishes a service via DNS-SD. * * Calling the function again with the same service name, type, protocol, * interface and port but different text will update the text published. * This function will NOT take the ownership of service->mTextEntries memory. * * @param[in] service The service entry. * @param[in] callback The callback to call when the service is published. * @param[in] context The context passed to the callback. * * @retval CHIP_NO_ERROR The publish succeeds. * @retval CHIP_ERROR_INVALID_ARGUMENT The service is nullptr. * @retval Error code The publish fails. * */ CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback = nullptr, void * context = nullptr); /** * Finalizes updating advertised services. * * This function can be used by some implementations to apply changes made with the * `ChipDnssdRemoveServices` and `ChipDnssdPublishService` functions in case they could * not be applied immediately (like in case of, but not limited to, implementations * using SRP or requiring asynchronous interactions with a DNS-SD implementation). * * @retval CHIP_NO_ERROR The service update finalization succeeds. * @retval Error code The service update finalization fails. */ CHIP_ERROR ChipDnssdFinalizeServiceUpdate(); /** * This function browses the services published by mDNS * * @param[in] type The service type. * @param[in] protocol The service protocol. * @param[in] addressType The protocol version of the IP address. * @param[in] interface The interface to send queries. * @param[in] callback The callback for found services. * @param[in] context The user context. * @param[out] browseIdentifier an identifier for this browse operation. This * can be used to call ChipDnssdStopBrowse. Only * set on success. This value remains valid until * the browse callback is called with an error or * is called with finalBrowse set to true. * * @retval CHIP_NO_ERROR The browse succeeds. * @retval CHIP_ERROR_INVALID_ARGUMENT The type or callback is nullptr. * @retval Error code The browse fails. * */ CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, intptr_t * browseIdentifier); /** * Stop an ongoing browse, if supported by this backend. If successful, this * will trigger a final callback, with either an error status or finalBrowse set * to true, to the DnssdBrowseCallback that was passed to the ChipDnssdBrowse * call that handed back this browseIdentifier. * * @param browseIdentifier an identifier for a browse operation that came from * ChipDnssdBrowse. */ CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier); #if CHIP_DEVICE_LAYER_TARGET_DARWIN /** * This function continuously browses the services published by mDNS * and reports any addition/removal of services. * * @param[in] type The service type. * @param[in] protocol The service protocol. * @param[in] addressType The protocol version of the IP address. * @param[in] interface The interface to send queries. * @param[in] delegate The delegate to notify when a service is found/removed. * * @retval CHIP_NO_ERROR The browse succeeds. * @retval CHIP_ERROR_INVALID_ARGUMENT The type or the delegate is nullptr. * @retval Error code The browse fails. * */ CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType, chip::Inet::InterfaceId interface, DnssdBrowseDelegate * delegate); /** * Stop an ongoing browse, if supported by this backend. If successful, this * will call the OnBrowseStop method of the delegate. */ CHIP_ERROR ChipDnssdStopBrowse(DnssdBrowseDelegate * delegate); #endif // CHIP_DEVICE_LAYER_TARGET_DARWIN /** * This function resolves the services published by mDNS * * @param[in] browseResult The service entry returned by @ref ChipDnssdBrowse * @param[in] interface The interface to send queries. * @param[in] callback The callback for found services. * @param[in] context The user context. * * @retval CHIP_NO_ERROR The resolve succeeds. * @retval CHIP_ERROR_INVALID_ARGUMENT The name, type or callback is nullptr. * @retval Error code The resolve fails. * */ CHIP_ERROR ChipDnssdResolve(DnssdService * browseResult, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, void * context); #if CHIP_DEVICE_LAYER_TARGET_DARWIN /** * This function resolves the services published by mDNS * * @param[in] browseResult The service entry returned by @ref ChipDnssdBrowse * @param[in] interface The interface to send queries. * @param[in] delegate The delegate to notify when a service is resolved. * * @retval CHIP_NO_ERROR The resolve succeeds. * @retval CHIP_ERROR_INVALID_ARGUMENT The name, type or delegate is nullptr. * @retval Error code The resolve fails. * */ CHIP_ERROR ChipDnssdResolve(DnssdService * browseResult, chip::Inet::InterfaceId interface, DiscoverNodeDelegate * delegate); #endif // CHIP_DEVICE_LAYER_TARGET_DARWIN /** * This function notifies the implementation that a resolve result is no longer * needed by some consumer, to allow implementations to stop unnecessary resolve * work. */ void ChipDnssdResolveNoLongerNeeded(const char * instanceName); /** * This function asks the mdns daemon to asynchronously reconfirm an address that appears to be out of date. * * @param[in] hostname The hostname the address belongs to. * @param[in] address The address to reconfirm. * @param[in] interface The interfaceId of the address. * */ CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress address, chip::Inet::InterfaceId interface); } // namespace Dnssd } // namespace chip