1 /*
2  *  Copyright (c) 2023, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * @brief
32  *   This file includes the platform abstraction for DNS-SD (e.g., mDNS) on the infrastructure network.
33  *
34  */
35 
36 #ifndef OPENTHREAD_PLATFORM_DNSSD_H_
37 #define OPENTHREAD_PLATFORM_DNSSD_H_
38 
39 #include <stdint.h>
40 
41 #include <openthread/dns.h>
42 #include <openthread/error.h>
43 #include <openthread/instance.h>
44 #include <openthread/ip6.h>
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /**
51  * @addtogroup plat-dns-sd
52  *
53  * @brief
54  *   This module includes the platform abstraction for DNS-SD (e.g., mDNS) on the infrastructure network.
55  *
56  * @{
57  *
58  * The DNS-SD platform APIs are used only when `OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE` is enabled.
59  *
60  */
61 
62 /**
63  * Represents the state of the DNS-SD platform.
64  *
65  */
66 typedef enum otPlatDnssdState
67 {
68     OT_PLAT_DNSSD_STOPPED, ///< Stopped and unable to register any service or host, or start any browser/resolver.
69     OT_PLAT_DNSSD_READY,   ///< Running and ready to register service or host.
70 } otPlatDnssdState;
71 
72 /**
73  * Represents a request ID for registering/unregistering a service or host.
74  *
75  */
76 typedef uint32_t otPlatDnssdRequestId;
77 
78 /**
79  * Represents the callback function used when registering/unregistering a host or service.
80  *
81  * See `otPlatDnssdRegisterService()`, `otPlatDnssdUnregisterService()`, `otPlatDnssdRegisterHost()`, and
82  * `otPlatDnssdUnregisterHost()` for more details about when to invoke the callback and the `aError` values that can
83  * be returned in each case.
84  *
85  * @param[in] aInstance     The OpenThread instance.
86  * @param[in] aRequestId    The request ID.
87  * @param[in] aError        Error indicating the outcome of request.
88  *
89  */
90 typedef void (*otPlatDnssdRegisterCallback)(otInstance *aInstance, otPlatDnssdRequestId aRequestId, otError aError);
91 
92 /**
93  * Represents a DNS-SD service.
94  *
95  * See `otPlatDnssdRegisterService()`, `otPlatDnssdUnregisterService()` for more details about fields in each case.
96  *
97  */
98 typedef struct otPlatDnssdService
99 {
100     const char        *mHostName;            ///< The host name (does not include domain name).
101     const char        *mServiceInstance;     ///< The service instance name label (not the full name).
102     const char        *mServiceType;         ///< The service type (e.g., "_mt._udp", does not include domain name).
103     const char *const *mSubTypeLabels;       ///< Array of sub-type labels (can be NULL if no label).
104     uint16_t           mSubTypeLabelsLength; ///< Length of array of sub-type labels.
105     const uint8_t     *mTxtData;             ///< Encoded TXT data bytes.
106     uint16_t           mTxtDataLength;       ///< Length of TXT data.
107     uint16_t           mPort;                ///< The service port number.
108     uint16_t           mPriority;            ///< The service priority.
109     uint16_t           mWeight;              ///< The service weight.
110     uint32_t           mTtl;                 ///< The service TTL in seconds.
111     uint32_t           mInfraIfIndex;        ///< The infrastructure network interface index.
112 } otPlatDnssdService;
113 
114 /**
115  * Represents a DNS-SD host.
116  *
117  * See `otPlatDnssdRegisterHost()`, `otPlatDnssdUnregisterHost()` for more details about fields in each case.
118  *
119  */
120 typedef struct otPlatDnssdHost
121 {
122     const char         *mHostName;        ///< The host name (does not include domain name).
123     const otIp6Address *mAddresses;       ///< Array of IPv6 host addresses.
124     uint16_t            mAddressesLength; ///< Number of entries in @p mAddresses array.
125     uint32_t            mTtl;             ///< The host TTL in seconds.
126     uint32_t            mInfraIfIndex;    ///< The infrastructure network interface index.
127 } otPlatDnssdHost;
128 
129 /**
130  * Represents a DNS-SD key record.
131  *
132  * See `otPlatDnssdRegisterKey()`, `otPlatDnssdUnregisterKey()` for more details about fields in each case.
133  *
134  */
135 typedef struct otPlatDnssdKey
136 {
137     const char    *mName;          ///< A host or a service instance name (does not include domain name).
138     const char    *mServiceType;   ///< The service type if key is for a service (does not include domain name).
139     const uint8_t *mKeyData;       ///< Byte array containing the key record data.
140     uint16_t       mKeyDataLength; ///< Length of @p mKeyData in bytes.
141     uint16_t       mClass;         ///< The resource record class.
142     uint32_t       mTtl;           ///< The TTL in seconds.
143     uint32_t       mInfraIfIndex;  ///< The infrastructure network interface index.
144 } otPlatDnssdKey;
145 
146 /**
147  * Callback to notify state changes of the DNS-SD platform.
148  *
149  * The OpenThread stack will call `otPlatDnssdGetState()` (from this callback or later) to get the new state. The
150  * platform MUST therefore ensure that the returned state from `otPlatDnssdGetState()` is updated before calling this.
151  *
152  * When the platform signals a state change to `OT_PLAT_DNSSD_STOPPED` using this callback, all active browsers and
153  * resolvers are considered to be stopped, and any previously registered host, service, key entries as removed.
154  *
155  * @param[in] aInstance The OpenThread instance structure.
156  *
157  */
158 extern void otPlatDnssdStateHandleStateChange(otInstance *aInstance);
159 
160 /**
161  * Gets the current state of the DNS-SD module.
162  *
163  * The platform MUST notify the OpenThread stack whenever its state gets changed by invoking
164  * `otPlatDnssdStateHandleStateChange()`.
165  *
166  * @param[in] aInstance     The OpenThread instance.
167  *
168  * @returns The current state of the DNS-SD module.
169  *
170  */
171 otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance);
172 
173 /**
174  * Registers or updates a service on the infrastructure network's DNS-SD module.
175  *
176  * The @p aService and all its contained information (strings and buffers) are only valid during this call. The
177  * platform MUST save a copy of the information if it wants to retain the information after returning from this
178  * function.
179  *
180  * The fields in @p aService follow these rules:
181  *
182  * - The `mServiceInstance` and `mServiceType` fields specify the service instance label and service type name,
183  *   respectively. They are never NULL.
184  * - The `mHostName` field specifies the host name of the service if it is not NULL. Otherwise, if it is NULL, it
185  *   indicates that this service is for the device itself and leaves the host name selection to DNS-SD platform.
186  * - The `mSubTypeLabels` is an array of strings representing sub-types associated with the service. It can be NULL
187  *   if there are no sub-types. Otherwise, the array length is specified by `mSubTypeLabelsLength`.
188  * - The `mTxtData` and `mTxtDataLength` fields specify the encoded TXT data.
189  * - The `mPort`, `mWeight`, and `mPriority` fields specify the service's parameters (as specified in DNS SRV record).
190  * - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use.
191  * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
192  *   request. If zero, the platform implementation can decided the interface.
193  *
194  * When the `mHostName` field in @p aService is not NULL (indicating that this registration is on behalf of another
195  * host), the OpenThread stack will ensure that `otPlatDnssdRegisterHost()` is also called for the same host before any
196  * service registration requests for the same host.
197  *
198  * Once the registration request is finished, either successfully or failed, the platform reports the outcome by
199  * invoking the @p aCallback and passing the same @p aRequestId in the callback. The @p aCallback function pointer can
200  * be NULL, which indicates that the OpenThread stack does not need to be notified of the outcome of the request.
201  * If the outcome is determined, the platform implementation may invoke the @p aCallback before returning from this
202  * function. The OpenThread stack will ensure to handle such a situation.
203  *
204  * On success, the @p aCallback MUST be called (if non-NULL) with `OT_ERROR_NONE` as the `aError` input parameter. If
205  * the registration causes a name conflict on DNS-SD domain (the service instance name is already claimed by another
206  * host), the `OT_ERROR_DUPLICATED` error MUST be used. The platform implementation can use other `OT_ERROR` types for
207  * other types of errors.
208  *
209  * The platform implementation MUST not assume that the @p aRequestId used in subsequent requests will be different.
210  * OpenThread may reuse the same request ID again for a different request.
211  *
212  * The OpenThread stack will not register the same service (with no changes) that was registered successfully earlier.
213  * Therefore, the platform implementation does not need to check for duplicate/same service and can assume that calls
214  * to this function are either registering a new entry or changing some parameter in a previously registered item. As
215  * a result, these changes always need to be synced on the infrastructure DNS-SD module.
216  *
217  * The OpenThread stack does not require the platform implementation to always invoke the @p aCallback function.
218  * The OpenThread stack has its own mechanism to time out an aged request with no response. This relaxes the
219  * requirement for platform implementations.
220  *
221  * @param[in] aInstance     The OpenThread instance.
222  * @param[in] aService      Information about the service to register.
223  * @param[in] aRequestId    The ID associated with this request.
224  * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
225  *
226  */
227 void otPlatDnssdRegisterService(otInstance                 *aInstance,
228                                 const otPlatDnssdService   *aService,
229                                 otPlatDnssdRequestId        aRequestId,
230                                 otPlatDnssdRegisterCallback aCallback);
231 
232 /**
233  * Unregisters a service on the infrastructure network's DNS-SD module.
234  *
235  * The @p aService and all its contained information (strings and buffers) are only valid during this call. The
236  * platform MUST save a copy of the information if it wants to retain the information after returning from this
237  * function.
238  *
239  * The fields in @p aService follow these rules:
240  *
241  * - The `mServiceInstance` and `mServiceType` fields specify the service instance label and service type name,
242  *   respectively. They are never NULL.
243  * - The `mHostName` field specifies the host name of the service if it is not NULL. Otherwise, if it is NULL, it
244  *   indicates that this service is for the device itself and leaves the host name selection to DNS-SD platform.
245  * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
246  *   request. If zero, the platform implementation can decided the interface.
247  * - The rest of the fields in @p aService structure MUST be ignored in `otPlatDnssdUnregisterService()` call and may
248  *   be set to zero by the OpenThread stack.
249  *
250  * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
251  * rules as described in `otPlatDnssdRegisterService()`.
252  *
253  * The OpenThread stack may request the unregistration of a service that was not previously registered, and the
254  * platform implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to
255  * indicate that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. The
256  * OpenThread stack will handle either case correctly.
257  *
258  * @param[in] aInstance     The OpenThread instance.
259  * @param[in] aService      Information about the service to unregister.
260  * @param[in] aRequestId    The ID associated with this request.
261  * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
262  *
263  */
264 void otPlatDnssdUnregisterService(otInstance                 *aInstance,
265                                   const otPlatDnssdService   *aService,
266                                   otPlatDnssdRequestId        aRequestId,
267                                   otPlatDnssdRegisterCallback aCallback);
268 
269 /**
270  * Registers or updates a host on the infrastructure network's DNS-SD module.
271  *
272  * The @p aHost and all its contained information (strings and arrays) are only valid during this call. The
273  * platform MUST save a copy of the information if it wants to retain the information after returning from this
274  * function.
275  *
276  * The fields in @p aHost follow these rules:
277  *
278  * - The `mHostName` field specifies the host name to register. It is never NULL.
279  * - The `mAddresses` field is an array of IPv6 addresses to register with the host. `mAddressesLength` field provides
280  *   the number of entries in `mAddresses` array. The platform implementation MUST not filter or remove any of
281  *   addresses in the list.
282  *   The OpenThread stack will already ensure that the given addresses are externally reachable. For example, when
283  *   registering host from an SRP registration, link-local or mesh-local addresses associated with the host which are
284  *   intended for use within Thread mesh are not included in `mAddresses` array passed to this API. The `mAddresses`
285  *   array can be empty with zero `mAddressesLength`. In such a case, the platform MUST stop advertising any addresses
286  *   for this host name on the infrastructure DNS-SD.
287  * - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use.
288  * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
289  *   request. If zero, the platform implementation can decided the interface.
290  *
291  * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
292  * rules as described in `otPlatDnssdRegisterService()`.
293  *
294  * The OpenThread stack will not register the same host (with no changes) that was registered successfully earlier.
295  * Therefore, the platform implementation does not need to check for duplicate/same host and can assume that calls
296  * to this function are either registering a new entry or changing some parameter in a previously registered item. As
297  * a result, these changes always need to be synced on the infrastructure DNS-SD module.
298  *
299  * @param[in] aInstance     The OpenThread instance.
300  * @param[in] aHost         Information about the host to register.
301  * @param[in] aRequestId    The ID associated with this request.
302  * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
303  *
304  */
305 void otPlatDnssdRegisterHost(otInstance                 *aInstance,
306                              const otPlatDnssdHost      *aHost,
307                              otPlatDnssdRequestId        aRequestId,
308                              otPlatDnssdRegisterCallback aCallback);
309 
310 /**
311  * Unregisters a host on the infrastructure network's DNS-SD module.
312  *
313  * The @p aHost and all its contained information (strings and arrays) are only valid during this call. The
314  * platform MUST save a copy of the information if it wants to retain the information after returning from this
315  * function.
316  *
317  * The fields in @p aHost follow these rules:
318  *
319  * - The `mHostName` field specifies the host name to unregister. It is never NULL.
320  * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
321  *   request. If zero, the platform implementation can decided the interface.
322  * - The rest of the fields in @p aHost structure MUST be ignored in `otPlatDnssdUnregisterHost()` call and may
323  *   be set to zero by the OpenThread stack.
324  *
325  * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
326  * rules as described in `otPlatDnssdRegisterService()`.
327  *
328  * The OpenThread stack may request the unregistration of a host that was not previously registered, and the platform
329  * implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to indicate
330  * that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. OpenThread stack
331  * will handle either case correctly.
332  *
333  * When unregistering a host, the OpenThread stack will also unregister any previously registered services
334  * associated with the same host (by calling `otPlatDnssdUnregisterService()`). However, the platform implementation
335  * MAY assume that unregistering a host also unregisters all its associated services.
336  *
337  * @param[in] aInstance     The OpenThread instance.
338  * @param[in] aHost         Information about the host to unregister.
339  * @param[in] aRequestId    The ID associated with this request.
340  * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
341  *
342  */
343 void otPlatDnssdUnregisterHost(otInstance                 *aInstance,
344                                const otPlatDnssdHost      *aHost,
345                                otPlatDnssdRequestId        aRequestId,
346                                otPlatDnssdRegisterCallback aCallback);
347 
348 /**
349  * Registers or updates a key record on the infrastructure network's DNS-SD module.
350  *
351  * The @p aKey and all its contained information (strings and arrays) are only valid during this call. The
352  * platform MUST save a copy of the information if it wants to retain the information after returning from this
353  * function.
354  *
355  * The fields in @p aKey follow these rules:
356  *
357  * - If the key is associated with a host, `mName` field specifies the host name and `mServiceType` will be NULL.
358  * - If the key is associated with a service, `mName` field specifies the service instance label and `mServiceType`
359  *   field specifies the service type. In this case the DNS name for key record is `{mName}.{mServiceTye}`.
360  * - The `mKeyData` field contains the key record's data with `mKeyDataLength` as its length in byes. It is never NULL.
361  * - The `mClass` fields specifies the resource record class to use when registering key record.
362  * - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use.
363  * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
364  *   request. If zero, the platform implementation can decided the interface.
365  *
366  * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
367  * rules as described in `otPlatDnssdRegisterService()`.
368  *
369  * The OpenThread stack will not register the same key (with no changes) that was registered successfully earlier.
370  * Therefore, the platform implementation does not need to check for duplicate/same name and can assume that calls
371  * to this function are either registering a new key or changing the key data in a previously registered one. As
372  * a result, these changes always need to be synced on the infrastructure DNS-SD module.
373  *
374  * @param[in] aInstance     The OpenThread instance.
375  * @param[in] aKey          Information about the key record to register.
376  * @param[in] aRequestId    The ID associated with this request.
377  * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
378  *
379  */
380 void otPlatDnssdRegisterKey(otInstance                 *aInstance,
381                             const otPlatDnssdKey       *aKey,
382                             otPlatDnssdRequestId        aRequestId,
383                             otPlatDnssdRegisterCallback aCallback);
384 
385 /**
386  * Unregisters a key record on the infrastructure network's DNS-SD module.
387  *
388  * The @p aKey and all its contained information (strings and arrays) are only valid during this call. The
389  * platform MUST save a copy of the information if it wants to retain the information after returning from this
390  * function.
391  *
392  * The fields in @p aKey follow these rules:
393  *
394  * - If the key is associated with a host, `mName` field specifies the host name and `mServiceType` will be NULL.
395  * - If the key is associated with a service, `mName` field specifies the service instance label and `mServiceType`
396  *   field specifies the service type. In this case the DNS name for key record is `{mName}.{mServiceTye}`.
397  * - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
398  *   request. If zero, the platform implementation can decided the interface.
399  * - The rest of the fields in @p aKey structure MUST be ignored in `otPlatDnssdUnregisterKey()` call and may
400  *   be set to zero by the OpenThread stack.
401  *
402  * Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
403  * rules as described in `otPlatDnssdRegisterService()`.
404  *
405  * The OpenThread stack may request the unregistration of a key that was not previously registered, and the platform
406  * implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to indicate
407  * that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. the OpenThread
408  * stack will handle either case correctly.
409  *
410  * @param[in] aInstance     The OpenThread instance.
411  * @param[in] aKey          Information about the key to unregister.
412  * @param[in] aRequestId    The ID associated with this request.
413  * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
414  *
415  */
416 void otPlatDnssdUnregisterKey(otInstance                 *aInstance,
417                               const otPlatDnssdKey       *aKey,
418                               otPlatDnssdRequestId        aRequestId,
419                               otPlatDnssdRegisterCallback aCallback);
420 
421 //======================================================================================================================
422 
423 /**
424  * Represents a browse result.
425  *
426  */
427 typedef struct otPlatDnssdBrowseResult
428 {
429     const char *mServiceType;     ///< The service type (e.g., "_mt._udp").
430     const char *mSubTypeLabel;    ///< The sub-type label if browsing for sub-type, NULL otherwise.
431     const char *mServiceInstance; ///< Service instance label.
432     uint32_t    mTtl;             ///< TTL in seconds. Zero TTL indicates that service is removed.
433     uint32_t    mInfraIfIndex;    ///< The infrastructure network interface index.
434 } otPlatDnssdBrowseResult;
435 
436 /**
437  * Represents the callback function used to report a browse result.
438  *
439  * @param[in] aInstance    The OpenThread instance.
440  * @param[in] aResult      The browse result.
441  *
442  */
443 typedef void (*otPlatDnssdBrowseCallback)(otInstance *aInstance, const otPlatDnssdBrowseResult *aResult);
444 
445 /**
446  * Represents a service browser.
447  *
448  */
449 typedef struct otPlatDnssdBrowser
450 {
451     const char               *mServiceType;  ///< The service type (e.g., "_mt._udp"). MUST NOT include domain name.
452     const char               *mSubTypeLabel; ///< The sub-type label if browsing for sub-type, NULL otherwise.
453     uint32_t                  mInfraIfIndex; ///< The infrastructure network interface index.
454     otPlatDnssdBrowseCallback mCallback;     ///< The callback to report result.
455 } otPlatDnssdBrowser;
456 
457 /**
458  * Represents an SRV resolver result.
459  *
460  */
461 typedef struct otPlatDnssdSrvResult
462 {
463     const char *mServiceInstance; ///< The service instance name label.
464     const char *mServiceType;     ///< The service type.
465     const char *mHostName;        ///< The host name (e.g., "myhost"). Can be NULL when `mTtl` is zero.
466     uint16_t    mPort;            ///< The service port number.
467     uint16_t    mPriority;        ///< The service priority.
468     uint16_t    mWeight;          ///< The service weight.
469     uint32_t    mTtl;             ///< The service TTL in seconds. Zero TTL indicates SRV record is removed.
470     uint32_t    mInfraIfIndex;    ///< The infrastructure network interface index.
471 } otPlatDnssdSrvResult;
472 
473 /**
474  * Represents the callback function used to report an SRV resolve result.
475  *
476  * @param[in] aInstance    The OpenThread instance.
477  * @param[in] aResult      The SRV resolve result.
478  *
479  */
480 typedef void (*otPlatDnssdSrvCallback)(otInstance *aInstance, const otPlatDnssdSrvResult *aResult);
481 
482 /**
483  * Represents an SRV service resolver.
484  *
485  */
486 typedef struct otPlatDnssdSrvResolver
487 {
488     const char            *mServiceInstance; ///< The service instance label.
489     const char            *mServiceType;     ///< The service type.
490     uint32_t               mInfraIfIndex;    ///< The infrastructure network interface index.
491     otPlatDnssdSrvCallback mCallback;        ///< The callback to report result.
492 } otPlatDnssdSrvResolver;
493 
494 /**
495  * Represents a TXT resolver result.
496  *
497  */
498 typedef struct otPlatDnssdTxtResult
499 {
500     const char    *mServiceInstance; ///< The service instance name label.
501     const char    *mServiceType;     ///< The service type.
502     const uint8_t *mTxtData;         ///< Encoded TXT data bytes. Can be NULL when `mTtl` is zero.
503     uint16_t       mTxtDataLength;   ///< Length of TXT data.
504     uint32_t       mTtl;             ///< The TXT data TTL in seconds. Zero TTL indicates record is removed.
505     uint32_t       mInfraIfIndex;    ///< The infrastructure network interface index.
506 } otPlatDnssdTxtResult;
507 
508 /**
509  * Represents the callback function used to report a TXT resolve result.
510  *
511  * @param[in] aInstance    The OpenThread instance.
512  * @param[in] aResult      The TXT resolve result.
513  *
514  */
515 typedef void (*otPlatDnssdTxtCallback)(otInstance *aInstance, const otPlatDnssdTxtResult *aResult);
516 
517 /**
518  * Represents a TXT service resolver.
519  *
520  */
521 typedef struct otPlatDnssdTxtResolver
522 {
523     const char            *mServiceInstance; ///< Service instance label.
524     const char            *mServiceType;     ///< Service type.
525     uint32_t               mInfraIfIndex;    ///< The infrastructure network interface index.
526     otPlatDnssdTxtCallback mCallback;
527 } otPlatDnssdTxtResolver;
528 
529 /**
530  * Represents a discovered host address and its TTL.
531  *
532  */
533 typedef struct otPlatDnssdAddressAndTtl
534 {
535     otIp6Address mAddress; ///< The IPv6 address. For IPv4 address the IPv4-mapped IPv6 address format is used.
536     uint32_t     mTtl;     ///< The TTL in seconds.
537 } otPlatDnssdAddressAndTtl;
538 
539 /**
540  * Represents address resolver result.
541  *
542  */
543 typedef struct otPlatDnssdAddressResult
544 {
545     const char                     *mHostName;        ///< The host name.
546     const otPlatDnssdAddressAndTtl *mAddresses;       ///< Array of host addresses and their TTL. Can be NULL if empty.
547     uint16_t                        mAddressesLength; ///< Number of entries in `mAddresses` array.
548     uint32_t                        mInfraIfIndex;    ///< The infrastructure network interface index.
549 } otPlatDnssdAddressResult;
550 
551 /**
552  * Represents the callback function use to report a IPv6/IPv4 address resolve result.
553  *
554  * @param[in] aInstance    The OpenThread instance.
555  * @param[in] aResult      The address resolve result.
556  *
557  */
558 typedef void (*otPlatDnssdAddressCallback)(otInstance *aInstance, const otPlatDnssdAddressResult *aResult);
559 
560 /**
561  * Represents an address resolver.
562  *
563  */
564 typedef struct otPlatDnssdAddressResolver
565 {
566     const char                *mHostName;     ///< The host name (e.g., "myhost"). MUST NOT contain domain name.
567     uint32_t                   mInfraIfIndex; ///< The infrastructure network interface index.
568     otPlatDnssdAddressCallback mCallback;     ///< The callback to report result.
569 } otPlatDnssdAddressResolver;
570 
571 /**
572  * Starts a service browser.
573  *
574  * Initiates a continuous search for the specified `mServiceType` in @p aBrowser. For sub-type services,
575  * `mSubTypeLabel` specifies the sub-type, for base services,  `mSubTypeLabel` is set to NULL.
576  *
577  * Discovered services should be reported through the `mCallback` function in @p aBrowser. Services that have been
578  * removed are reported with a TTL value of zero. The callback may be invoked immediately with cached information
579  * (if available) and potentially before this function returns. When cached results are used, the reported TTL value
580  * should reflect the original TTL from the last received response.
581  *
582  * Multiple browsers can be started for the same service, provided they use different callback functions.
583  *
584  * The @p aBrowser and all its contained information (strings) are only valid during this call. The platform MUST save
585  * a copy of the information if it wants to retain the information after returning from this function.
586  *
587  * @param[in] aInstance   The OpenThread instance.
588  * @param[in] aBrowser    The browser to be started.
589  *
590  */
591 void otPlatDnssdStartBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser);
592 
593 /**
594  * Stops a service browser.
595  *
596  * No action is performed if no matching browser with the same service and callback is currently active.
597  *
598  * The @p aBrowser and all its contained information (strings) are only valid during this call. The platform MUST save
599  * a copy of the information if it wants to retain the information after returning from this function.
600  *
601  * @param[in] aInstance   The OpenThread instance.
602  * @param[in] aBrowser    The browser to stop.
603  *
604  */
605 void otPlatDnssdStopBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser);
606 
607 /**
608  * Starts an SRV record resolver.
609  *
610  * Initiates a continuous SRV record resolver for the specified service in @p aResolver.
611  *
612  * Discovered information should be reported through the `mCallback` function in @p aResolver. When the service is
613  * removed it is reported with a TTL value of zero. In this case, `mHostName` may be NULL and other result fields (such
614  * as `mPort`) will be ignored by the OpenThread stack.
615  *
616  * The callback may be invoked immediately with cached information (if available) and potentially before this function
617  * returns. When cached result is used, the reported TTL value should reflect the original TTL from the last received
618  * response.
619  *
620  * Multiple resolvers can be started for the same service, provided they use different callback functions.
621  *
622  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
623  * a copy of the information if it wants to retain the information after returning from this function.
624  *
625  * @param[in] aInstance    The OpenThread instance.
626  * @param[in] aResolver    The resolver to be started.
627  *
628  */
629 void otPlatDnssdStartSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver);
630 
631 /**
632  * Stops an SRV record resolver.
633  *
634  * No action is performed if no matching resolver with the same service and callback is currently active.
635  *
636  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
637  * a copy of the information if it wants to retain the information after returning from this function.
638  *
639  * @param[in] aInstance    The OpenThread instance.
640  * @param[in] aResolver    The resolver to stop.
641  *
642  */
643 void otPlatDnssdStopSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver);
644 
645 /**
646  * Starts a TXT record resolver.
647  *
648  * Initiates a continuous TXT record resolver for the specified service in @p aResolver.
649  *
650  * Discovered information should be reported through the `mCallback` function in @p aResolver. When the TXT record is
651  * removed it is reported with a TTL value of zero. In this case, `mTxtData` may be NULL, and other result fields
652  * (such as `mTxtDataLength`) will be ignored by the OpenThread stack.
653  *
654  * The callback may be invoked immediately with cached information (if available) and potentially before this function
655  * returns. When cached result is used, the reported TTL value should reflect the original TTL from the last received
656  * response.
657  *
658  * Multiple resolvers can be started for the same service, provided they use different callback functions.
659  *
660  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
661  * a copy of the information if it wants to retain the information after returning from this function.
662  *
663  * @param[in] aInstance    The OpenThread instance.
664  * @param[in] aResolver    The resolver to be started.
665  *
666  */
667 void otPlatDnssdStartTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver);
668 
669 /**
670  * Stops a TXT record resolver.
671  *
672  * No action is performed if no matching resolver with the same service and callback is currently active.
673  *
674  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
675  * a copy of the information if it wants to retain the information after returning from this function.
676  *
677  * @param[in] aInstance    The OpenThread instance.
678  * @param[in] aResolver    The resolver to stop.
679  *
680  */
681 void otPlatDnssdStopTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver);
682 
683 /**
684  * Starts an IPv6 address resolver.
685  *
686  * Initiates a continuous IPv6 address resolver for the specified host name in @p aResolver.
687  *
688  * Discovered addresses should be reported through the `mCallback` function in @p aResolver. The callback should be
689  * invoked whenever addresses are added or removed, providing an updated list. If all addresses are removed, the
690  * callback should be invoked with an empty list (`mAddressesLength` set to zero).
691  *
692  * The callback may be invoked immediately with cached information (if available) and potentially before this function
693  * returns. When cached result is used, the reported TTL values should reflect the original TTL from the last received
694  * response.
695  *
696  * Multiple resolvers can be started for the same host name, provided they use different callback functions.
697  *
698  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
699  * a copy of the information if it wants to retain the information after returning from this function.
700  *
701  * @param[in] aInstance    The OpenThread instance.
702  * @param[in] aResolver    The resolver to be started.
703  *
704  */
705 void otPlatDnssdStartIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver);
706 
707 /**
708  * Stops an IPv6 address resolver.
709  *
710  * No action is performed if no matching resolver with the same host name and callback is currently active.
711  *
712  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
713  * a copy of the information if it wants to retain the information after returning from this function.
714  *
715  * @param[in] aInstance    The OpenThread instance.
716  * @param[in] aResolver    The resolver to stop.
717  *
718  */
719 void otPlatDnssdStopIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver);
720 
721 /**
722  * Starts an IPv4 address resolver.
723  *
724  * Initiates a continuous IPv4 address resolver for the specified host name in @p aResolver.
725  *
726  * Discovered addresses should be reported through the `mCallback` function in @p aResolver. The IPv4 addresses are
727  * represented using the IPv4-mapped IPv6 address format in `mAddresses` array.  The callback should be invoked
728  * whenever addresses are added or removed, providing an updated list. If all addresses are removed, the callback
729  * should be invoked with an empty list (`mAddressesLength` set to zero).
730  *
731  * The callback may be invoked immediately with cached information (if available) and potentially before this function
732  * returns. When cached result is used, the reported TTL values will reflect the original TTL from the last received
733  * response.
734  *
735  * Multiple resolvers can be started for the same host name, provided they use different callback functions.
736  *
737  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
738  * a copy of the information if it wants to retain the information after returning from this function.
739  *
740  * @param[in] aInstance    The OpenThread instance.
741  * @param[in] aResolver    The resolver to be started.
742  *
743  */
744 void otPlatDnssdStartIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver);
745 
746 /**
747  * Stops an IPv4 address resolver.
748  *
749  * No action is performed if no matching resolver with the same host name and callback is currently active.
750  *
751  * The @p aResolver and all its contained information (strings) are only valid during this call. The platform MUST save
752  * a copy of the information if it wants to retain the information after returning from this function.
753  *
754  * @param[in] aInstance    The OpenThread instance.
755  * @param[in] aResolver    The resolver to stop.
756  *
757  */
758 void otPlatDnssdStopIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver);
759 
760 /**
761  * @}
762  *
763  */
764 
765 #ifdef __cplusplus
766 } // extern "C"
767 #endif
768 
769 #endif // OPENTHREAD_PLATFORM_DNSSD_H_
770