1 /*
2  *  Copyright (c) 2024, 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 mDNS related APIs.
33  */
34 
35 #ifndef OPENTHREAD_MULTICAST_DNS_H_
36 #define OPENTHREAD_MULTICAST_DNS_H_
37 
38 #include <stdint.h>
39 
40 #include <openthread/error.h>
41 #include <openthread/instance.h>
42 #include <openthread/ip6.h>
43 #include <openthread/platform/dnssd.h>
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 /**
50  * @addtogroup api-mdns
51  *
52  * @brief
53  *   This module includes APIs for Multicast DNS (mDNS).
54  *
55  * @{
56  *
57  * The mDNS APIs are available when the mDNS support `OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE` is enabled and the
58  * `OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE` is also enabled.
59  */
60 
61 /**
62  * Represents a request ID (`uint32_t` value) for registering a host, a service, or a key service.
63  */
64 typedef otPlatDnssdRequestId otMdnsRequestId;
65 
66 /**
67  * Represents the callback function to report the outcome of a host, service, or key registration request.
68  *
69  * The outcome of a registration request is reported back by invoking this callback with one of the following `aError`
70  * inputs:
71  *
72  * - `OT_ERROR_NONE` indicates registration was successful.
73  * - `OT_ERROR_DUPLICATED` indicates a name conflict while probing, i.e., name is claimed by another mDNS responder.
74  *
75  * See `otMdnsRegisterHost()`, `otMdnsRegisterService()`, and `otMdnsRegisterKey()` for more details about when
76  * the callback will be invoked.
77  *
78  * @param[in] aInstance     The OpenThread instance.
79  * @param[in] aRequestId    The request ID.
80  * @param[in] aError        Error indicating the outcome of request.
81  */
82 typedef otPlatDnssdRegisterCallback otMdnsRegisterCallback;
83 
84 /**
85  * Represents the callback function to report a detected name conflict after successful registration of an entry.
86  *
87  * If a conflict is detected while registering an entry, it is reported through the provided `otMdnsRegisterCallback`.
88  * The `otMdnsConflictCallback` is used only when a name conflict is detected after an entry has been successfully
89  * registered.
90  *
91  * A non-NULL @p aServiceType indicates that conflict is for a service entry. In this case @p aName specifies the
92  * service instance label (treated as as a single DNS label and can potentially include dot `.` character).
93  *
94  * A NULL @p aServiceType indicates that conflict is for a host entry. In this case @p Name specifies the host name. It
95  * does not include the domain name.
96  *
97  * @param[in] aInstance      The OpenThread instance.
98  * @param[in] aName          The host name or the service instance label.
99  * @param[in] aServiceType   The service type (e.g., `_tst._udp`).
100  */
101 typedef void (*otMdnsConflictCallback)(otInstance *aInstance, const char *aName, const char *aServiceType);
102 
103 /**
104  * Represents an mDNS host.
105  *
106  * This type is used to register or unregister a host (`otMdnsRegisterHost()` and `otMdnsUnregisterHost()`).
107  *
108  * See the description of each function for more details on how different fields are used in each case.
109  */
110 typedef otPlatDnssdHost otMdnsHost;
111 
112 /**
113  * Represents an mDNS service.
114  *
115  * This type is used to register or unregister a service (`otMdnsRegisterService()` and `otMdnsUnregisterService()`).
116  *
117  * See the description of each function for more details on how different fields are used in each case.
118  */
119 typedef otPlatDnssdService otMdnsService;
120 
121 /**
122  * Represents an mDNS key record.
123  *
124  * See `otMdnsRegisterKey()`, `otMdnsUnregisterKey()` for more details about fields in each case.
125  */
126 typedef otPlatDnssdKey otMdnsKey;
127 
128 /**
129  * Represents an mDNS entry iterator.
130  */
131 typedef struct otMdnsIterator otMdnsIterator;
132 
133 /**
134  * Represents a host/service/key entry state.
135  */
136 typedef enum otMdnsEntryState
137 {
138     OT_MDNS_ENTRY_STATE_PROBING,    ///< Probing to claim the name.
139     OT_MDNS_ENTRY_STATE_REGISTERED, ///< Entry is successfully registered.
140     OT_MDNS_ENTRY_STATE_CONFLICT,   ///< Name conflict was detected.
141     OT_MDNS_ENTRY_STATE_REMOVING,   ///< Entry is being removed (sending "goodbye" announcements).
142 } otMdnsEntryState;
143 
144 /**
145  * Enables or disables the mDNS module.
146  *
147  * The mDNS module should be enabled before registration any host, service, or key entries. Disabling mDNS will
148  * immediately stop all operations and any communication (multicast or unicast tx) and remove any previously registered
149  * entries without sending any "goodbye" announcements or invoking their callback. Once disabled, all currently active
150  * browsers and resolvers are stopped.
151  *
152  * @param[in] aInstance      The OpenThread instance.
153  * @param[in] aEnable        Boolean to indicate whether to enable (on `TRUE`) or disable (on `FALSE`).
154  * @param[in] aInfraIfIndex  The network interface index for mDNS operation. Value is ignored when disabling
155  *
156  * @retval OT_ERROR_NONE     Enabled or disabled the mDNS module successfully.
157  * @retval OT_ERROR_ALREADY  mDNS is already enabled on an enable request or is already disabled on a disable request.
158  */
159 otError otMdnsSetEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex);
160 
161 /**
162  * Indicates whether the mDNS module is enabled.
163  *
164  * @param[in] aInstance     The OpenThread instance.
165  *
166  * @retval TRUE    The mDNS module is enabled
167  * @retval FALSE   The mDNS module is disabled.
168  */
169 bool otMdnsIsEnabled(otInstance *aInstance);
170 
171 /**
172  * Sets whether the mDNS module is allowed to send questions requesting unicast responses referred to as "QU" questions.
173  *
174  * The "QU" questions request unicast responses, in contrast to "QM" questions which request multicast responses.
175  *
176  * When allowed, the first probe will be sent as a "QU" question. This API can be used to address platform limitation
177  * where platform socket cannot accept unicast response received on mDNS port (due to it being already bound).
178  *
179  * @param[in] aInstance     The OpenThread instance.
180  * @param[in] aAllow        Indicates whether or not to allow "QU" questions.
181  */
182 void otMdnsSetQuestionUnicastAllowed(otInstance *aInstance, bool aAllow);
183 
184 /**
185  * Indicates whether mDNS module is allowed to send "QU" questions requesting unicast response.
186  *
187  * @retval TRUE  The mDNS module is allowed to send "QU" questions.
188  * @retval FALSE The mDNS module is not allowed to send "QU" questions.
189  */
190 bool otMdnsIsQuestionUnicastAllowed(otInstance *aInstance);
191 
192 /**
193  * Sets the post-registration conflict callback.
194  *
195  * If a conflict is detected while registering an entry, it is reported through the provided `otMdnsRegisterCallback`.
196  * The `otMdnsConflictCallback` is used only when a name conflict is detected after an entry has been successfully
197  * registered.
198  *
199  * @p aCallback can be set to `NULL` if not needed. Subsequent calls will replace any previously set callback.
200  *
201  * @param[in] aInstance     The OpenThread instance.
202  * @param[in] aCallback     The conflict callback.
203  */
204 void otMdnsSetConflictCallback(otInstance *aInstance, otMdnsConflictCallback aCallback);
205 
206 /**
207  * Registers or updates a host on mDNS.
208  *
209  * The fields in @p aHost follow these rules:
210  *
211  * - The `mHostName` field specifies the host name to register (e.g., "myhost"). MUST NOT contain the domain name.
212  * - The `mAddresses` is array of IPv6 addresses to register with the host. `mAddressesLength` provides the number of
213  *   entries in `mAddresses` array.
214  * - The `mAddresses` array can be empty with zero `mAddressesLength`. In this case, mDNS will treat it as if host is
215  *   unregistered and stops advertising any addresses for this the host name.
216  * - The `mTtl` specifies the TTL if non-zero. If zero, the mDNS core will choose the default TTL of 120 seconds.
217  * - Other fields in @p aHost structure are ignored in an `otMdnsRegisterHost()` call.
218  *
219  * This function can be called again for the same `mHostName` to update a previously registered host entry, for example,
220  * to change the list of addresses of the host. In this case, the mDNS module will send "goodbye" announcements for any
221  * previously registered and now removed addresses and announce any newly added addresses.
222  *
223  * The outcome of the registration request is reported back by invoking the provided @p aCallback with @p aRequestId
224  * as its input and one of the following `aError` inputs:
225  *
226  * - `OT_ERROR_NONE` indicates registration was successful.
227  * - `OT_ERROR_DULICATED` indicates a name conflict while probing, i.e., name is claimed by another mDNS responder.
228  *
229  * For caller convenience, the OpenThread mDNS module guarantees that the callback will be invoked after this function
230  * returns, even in cases of immediate registration success. The @p aCallback can be `NULL` if caller does not want to
231  * be notified of the outcome.
232  *
233  * @param[in] aInstance     The OpenThread instance.
234  * @param[in] aHost         Information about the host to register.
235  * @param[in] aRequestId    The ID associated with this request.
236  * @param[in] aCallback     The callback function pointer to report the outcome (can be NULL if not needed).
237  *
238  * @retval OT_ERROR_NONE            Successfully started registration. @p aCallback will report the outcome.
239  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
240  */
241 otError otMdnsRegisterHost(otInstance            *aInstance,
242                            const otMdnsHost      *aHost,
243                            otMdnsRequestId        aRequestId,
244                            otMdnsRegisterCallback aCallback);
245 
246 /**
247  * Unregisters a host on mDNS.
248  *
249  * The fields in @p aHost follow these rules:
250  *
251  * - The `mHostName` field specifies the host name to unregister (e.g., "myhost"). MUST NOT contain the domain name.
252  * - Other fields in @p aHost structure are ignored in an `otMdnsUnregisterHost()` call.
253  *
254  * If there is no previously registered host with the same name, no action is performed.
255  *
256  * If there is a previously registered host with the same name, the mDNS module will send "goodbye" announcement for
257  * all previously advertised address records.
258  *
259  * @param[in] aInstance     The OpenThread instance.
260  * @param[in] aHost         Information about the host to unregister.
261  *
262  * @retval OT_ERROR_NONE            Successfully unregistered host.
263  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
264  */
265 otError otMdnsUnregisterHost(otInstance *aInstance, const otMdnsHost *aHost);
266 
267 /**
268  * Registers or updates a service on mDNS.
269  *
270  * The fields in @p aService follow these rules:
271  *
272  * - The `mServiceInstance` specifies the service instance label. It is treated as a single DNS name label. It may
273  *   contain dot `.` character which is allowed in a service instance label.
274  * - The `mServiceType` specifies the service type (e.g., "_tst._udp"). It is treated as multiple dot `.` separated
275  *   labels. It MUST NOT contain the domain name.
276  * - The `mHostName` field specifies the host name of the service. MUST NOT contain the domain name.
277  * - The `mSubTypeLabels` is an array of strings representing sub-types associated with the service. Each array entry
278  *   is a sub-type label. The `mSubTypeLabels can be NULL if there is no sub-type. Otherwise, the array length is
279  *   specified by `mSubTypeLabelsLength`.
280  * - The `mTxtData` and `mTxtDataLength` specify the encoded TXT data. The `mTxtData` can be NULL or `mTxtDataLength`
281  *   can be zero to specify an empty TXT data. In this case mDNS module will use a single zero byte `[ 0 ]` as the
282  *   TXT data.
283  * - The `mPort`, `mWeight`, and `mPriority` specify the service's parameters as specified in DNS SRV record.
284  * - The `mTtl` specifies the TTL if non-zero. If zero, the mDNS module will use the default TTL of 120 seconds.
285  * - Other fields in @p aService structure are ignored in an `otMdnsRegisterService()` call.
286  *
287  * This function can be called again for the same `mServiceInstance` and `mServiceType` to update a previously
288  * registered service entry, for example, to change the sub-types list, or update any parameter such as port, weight,
289  * priority, TTL, or host name. The mDNS module will send announcements for any changed info, e.g., will send "goodbye"
290  * announcements for any removed sub-types and announce any newly added sub-types.
291  *
292  * Regarding the invocation of the @p aCallback, this function behaves in the same way as described in
293  * `otMdnsRegisterHost()`.
294  *
295  * @param[in] aInstance     The OpenThread instance.
296  * @param[in] aService      Information about the service to register.
297  * @param[in] aRequestId    The ID associated with this request.
298  * @param[in] aCallback     The callback function pointer to report the outcome (can be NULL if not needed).
299  *
300  * @retval OT_ERROR_NONE            Successfully started registration. @p aCallback will report the outcome.
301  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
302  */
303 otError otMdnsRegisterService(otInstance            *aInstance,
304                               const otMdnsService   *aService,
305                               otMdnsRequestId        aRequestId,
306                               otMdnsRegisterCallback aCallback);
307 
308 /**
309  * Unregisters a service on mDNS module.
310  *
311  * The fields in @p aService follow these rules:
312 
313  * - The `mServiceInstance` specifies the service instance label. It is treated as a single DNS name label. It may
314  *   contain dot `.` character which is allowed in a service instance label.
315  * - The `mServiceType` specifies the service type (e.g., "_tst._udp"). It is treated as multiple dot `.` separated
316  *   labels. It MUST NOT contain the domain name.
317  * - Other fields in @p aService structure are ignored in an `otMdnsUnregisterService()` call.
318  *
319  * If there is no previously registered service with the same name, no action is performed.
320  *
321  * If there is a previously registered service with the same name, the mDNS module will send "goodbye" announcements
322  * for all related records.
323  *
324  * @param[in] aInstance     The OpenThread instance.
325  * @param[in] aService      Information about the service to unregister.
326  *
327  * @retval OT_ERROR_NONE            Successfully unregistered service.
328  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
329  */
330 otError otMdnsUnregisterService(otInstance *aInstance, const otMdnsService *aService);
331 
332 /**
333  * Registers or updates a key record on mDNS module.
334  *
335  * The fields in @p aKey follow these rules:
336  *
337  * - If the key is associated with a host entry, the `mName` field specifies the host name and the `mServiceType` MUST
338  *   be NULL.
339  * - If the key is associated with a service entry, the `mName` filed specifies the service instance label (always
340  *   treated as a single label) and the `mServiceType` filed specifies the service type (e.g., "_tst._udp"). In this
341  *   case the DNS name for key record is `<mName>.<mServiceTye>`.
342  * - The `mKeyData` field contains the key record's data with `mKeyDataLength` as its length in byes.
343  * - The `mTtl` specifies the TTL if non-zero. If zero, the mDNS module will use the default TTL of 120 seconds.
344  * - Other fields in @p aKey structure are ignored in an `otMdnsRegisterKey()` call.
345  *
346  * This function can be called again for the same name to updated a previously registered key entry, for example, to
347  * change the key data or TTL.
348  *
349  * Regarding the invocation of the @p aCallback, this function behaves in the same way as described in
350  * `otMdnsRegisterHost()`.
351  *
352  * @param[in] aInstance     The OpenThread instance.
353  * @param[in] aKey          Information about the key record to register.
354  * @param[in] aRequestId    The ID associated with this request.
355  * @param[in] aCallback     The callback function pointer to report the outcome (can be NULL if not needed).
356  *
357  * @retval OT_ERROR_NONE            Successfully started registration. @p aCallback will report the outcome.
358  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
359  */
360 otError otMdnsRegisterKey(otInstance            *aInstance,
361                           const otMdnsKey       *aKey,
362                           otMdnsRequestId        aRequestId,
363                           otMdnsRegisterCallback aCallback);
364 
365 /**
366  * Unregisters a key record on mDNS.
367  *
368  * The fields in @p aKey follow these rules:
369  *
370  * - If the key is associated with a host entry, the `mName` field specifies the host name and the `mServiceType` MUST
371  *   be NULL.
372  * - If the key is associated with a service entry, the `mName` filed specifies the service instance label (always
373  *   treated as a single label) and the `mServiceType` filed specifies the service type (e.g., "_tst._udp"). In this
374  *   case the DNS name for key record is `<mName>.<mServiceTye>`.
375  * - Other fields in @p aKey structure are ignored in an `otMdnsUnregisterKey()` call.
376  *
377  * If there is no previously registered key with the same name, no action is performed.
378  *
379  * If there is a previously registered key with the same name, the mDNS module will send "goodbye" announcements for
380  * the key record.
381  *
382  * @param[in] aInstance     The OpenThread instance.
383  * @param[in] aKey          Information about the key to unregister.
384  *
385  * @retval OT_ERROR_NONE            Successfully unregistered key
386  * @retval OT_ERROR_INVALID_STATE   mDNS module is not enabled.
387  */
388 otError otMdnsUnregisterKey(otInstance *aInstance, const otMdnsKey *aKey);
389 
390 /**
391  * Allocates a new iterator.
392  *
393  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
394  *
395  * An allocated iterator must be freed by the caller using `otMdnsFreeIterator()`.
396  *
397  * @param[in] aInstance    The OpenThread instance.
398  *
399  * @returns A pointer to the allocated iterator, or `NULL` if it fails to allocate.
400  */
401 otMdnsIterator *otMdnsAllocateIterator(otInstance *aInstance);
402 
403 /**
404  * Frees a previously allocated iterator.
405  *
406  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
407  *
408  * @param[in] aInstance    The OpenThread instance.
409  * @param[in] aIterator    The iterator to free.
410  */
411 void otMdnsFreeIterator(otInstance *aInstance, otMdnsIterator *aIterator);
412 
413 /**
414  * Iterates over registered host entries.
415  *
416  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
417  *
418  * On success, @p aHost is populated with information about the next host. Pointers within the `otMdnsHost` structure
419  * (like `mName`) remain valid until the next call to any OpenThread stack's public or platform API/callback.
420  *
421  * @param[in]  aInstance   The OpenThread instance.
422  * @param[in]  aIterator   Pointer to the iterator.
423  * @param[out] aHost       Pointer to an `otMdnsHost` to return the information about the next host entry.
424  * @param[out] aState      Pointer to an `otMdnsEntryState` to return the entry state.
425  *
426  * @retval OT_ERROR_NONE         @p aHost, @p aState, & @p aIterator are updated successfully.
427  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
428  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
429  */
430 otError otMdnsGetNextHost(otInstance       *aInstance,
431                           otMdnsIterator   *aIterator,
432                           otMdnsHost       *aHost,
433                           otMdnsEntryState *aState);
434 
435 /**
436  * Iterates over registered service entries.
437  *
438  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
439  *
440  * On success, @p aService is populated with information about the next service . Pointers within the `otMdnsService`
441  * structure (like `mServiceType`, `mSubTypeLabels`) remain valid until the next call to any OpenThread stack's public
442  * or platform API/callback.
443  *
444  * @param[in]  aInstance    The OpenThread instance.
445  * @param[in]  aIterator    Pointer to the iterator to use.
446  * @param[out] aService     Pointer to an `otMdnsService` to return the information about the next service entry.
447  * @param[out] aState       Pointer to an `otMdnsEntryState` to return the entry state.
448  *
449  * @retval OT_ERROR_NONE         @p aService, @p aState, & @p aIterator are updated successfully.
450  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
451  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
452  */
453 otError otMdnsGetNextService(otInstance       *aInstance,
454                              otMdnsIterator   *aIterator,
455                              otMdnsService    *aService,
456                              otMdnsEntryState *aState);
457 
458 /**
459  * Iterates over registered key entries.
460  *
461  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
462  *
463  * On success, @p aKey is populated with information about the next key.  Pointers within the `otMdnsKey` structure
464  * (like `mName`) remain valid until the next call to any OpenThread stack's public or platform API/callback.
465  *
466  * @param[in]  aInstance    The OpenThread instance.
467  * @param[in]  aIterator    Pointer to the iterator to use.
468  * @param[out] aKey         Pointer to an `otMdnsKey` to return the information about the next key entry.
469  * @param[out] aState       Pointer to an `otMdnsEntryState` to return the entry state.
470  *
471  * @retval OT_ERROR_NONE         @p aKey, @p aState, & @p aIterator are updated successfully.
472  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
473  * @retval OT_ERROR_INVALID_ARG  Iterator is not valid.
474  */
475 otError otMdnsGetNextKey(otInstance *aInstance, otMdnsIterator *aIterator, otMdnsKey *aKey, otMdnsEntryState *aState);
476 
477 /**
478  * Represents a service browser.
479  *
480  * Refer to `otPlatDnssdBrowser` for documentation of member fields and `otMdnsStartBrowser()` for how they are used.
481  */
482 typedef otPlatDnssdBrowser otMdnsBrowser;
483 
484 /**
485  * Represents the callback function pointer type used to report a browse result.
486  */
487 typedef otPlatDnssdBrowseCallback otMdnsBrowseCallback;
488 
489 /**
490  * Represents a browse result.
491  */
492 typedef otPlatDnssdBrowseResult otMdnsBrowseResult;
493 
494 /**
495  * Represents an SRV service resolver.
496  *
497  * Refer to `otPlatDnssdSrvResolver` for documentation of member fields and `otMdnsStartSrvResolver()` for how they are
498  * used.
499  */
500 typedef otPlatDnssdSrvResolver otMdnsSrvResolver;
501 
502 /**
503  * Represents the callback function pointer type used to report an SRV resolve result.
504  */
505 typedef otPlatDnssdSrvCallback otMdnsSrvCallback;
506 
507 /**
508  * Represents an SRV resolver result.
509  */
510 typedef otPlatDnssdSrvResult otMdnsSrvResult;
511 
512 /**
513  * Represents a TXT service resolver.
514  *
515  * Refer to `otPlatDnssdTxtResolver` for documentation of member fields and `otMdnsStartTxtResolver()` for how they are
516  * used.
517  */
518 typedef otPlatDnssdTxtResolver otMdnsTxtResolver;
519 
520 /**
521  * Represents the callback function pointer type used to report a TXT resolve result.
522  */
523 typedef otPlatDnssdTxtCallback otMdnsTxtCallback;
524 
525 /**
526  * Represents a TXT resolver result.
527  */
528 typedef otPlatDnssdTxtResult otMdnsTxtResult;
529 
530 /**
531  * Represents an address resolver.
532  *
533  * Refer to `otPlatDnssdAddressResolver` for documentation of member fields and `otMdnsStartIp6AddressResolver()` or
534  * `otMdnsStartIp4AddressResolver()` for how they are used.
535  */
536 typedef otPlatDnssdAddressResolver otMdnsAddressResolver;
537 
538 /**
539  * Represents the callback function pointer type use to report an IPv6/IPv4 address resolve result.
540  */
541 typedef otPlatDnssdAddressCallback otMdnsAddressCallback;
542 
543 /**
544  * Represents a discovered host address and its TTL.
545  */
546 typedef otPlatDnssdAddressAndTtl otMdnsAddressAndTtl;
547 
548 /**
549  * Represents address resolver result.
550  */
551 typedef otPlatDnssdAddressResult otMdnsAddressResult;
552 
553 /**
554  * Starts a service browser.
555  *
556  * Initiates a continuous search for the specified `mServiceType` in @p aBrowser. For sub-type services, use
557  * `mSubTypeLabel` to define the sub-type, for base services, set `mSubTypeLabel` to NULL.
558  *
559  * Discovered services are reported through the `mCallback` function in @p aBrowser. Services that have been removed
560  * are reported with a TTL value of zero. The callback may be invoked immediately with cached information (if available)
561  * and potentially before this function returns. When cached results are used, the reported TTL value will reflect
562  * the original TTL from the last received response.
563  *
564  * Multiple browsers can be started for the same service, provided they use different callback functions.
565  *
566  * @param[in] aInstance   The OpenThread instance.
567  * @param[in] aBrowser    The browser to be started.
568  *
569  * @retval OT_ERROR_NONE           Browser started successfully.
570  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
571  * @retval OT_ERROR_ALREADY        An identical browser (same service and callback) is already active.
572  */
573 otError otMdnsStartBrowser(otInstance *aInstance, const otMdnsBrowser *aBrowser);
574 
575 /**
576  * Stops a service browser.
577  *
578  * No action is performed if no matching browser with the same service and callback is currently active.
579  *
580  * @param[in] aInstance   The OpenThread instance.
581  * @param[in] aBrowser    The browser to stop.
582  *
583  * @retval OT_ERROR_NONE           Browser stopped successfully.
584  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
585  */
586 otError otMdnsStopBrowser(otInstance *aInstance, const otMdnsBrowser *aBroswer);
587 
588 /**
589  * Starts an SRV record resolver.
590  *
591  * Initiates a continuous SRV record resolver for the specified service in @p aResolver.
592  *
593  * Discovered information is reported through the `mCallback` function in @p aResolver. When the service is removed
594  * it is reported with a TTL value of zero. In this case, `mHostName` may be NULL and other result fields (such as
595  * `mPort`) should be ignored.
596  *
597  * The callback may be invoked immediately with cached information (if available) and potentially before this function
598  * returns. When cached result is used, the reported TTL value will reflect the original TTL from the last received
599  * response.
600  *
601  * Multiple resolvers can be started for the same service, provided they use different callback functions.
602  *
603  * @param[in] aInstance    The OpenThread instance.
604  * @param[in] aResolver    The resolver to be started.
605  *
606  * @retval OT_ERROR_NONE           Resolver started successfully.
607  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
608  * @retval OT_ERROR_ALREADY        An identical resolver (same service and callback) is already active.
609  */
610 otError otMdnsStartSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *aResolver);
611 
612 /**
613  * Stops an SRV record resolver.
614  *
615  * No action is performed if no matching resolver with the same service and callback is currently active.
616  *
617  * @param[in] aInstance    The OpenThread instance.
618  * @param[in] aResolver    The resolver to stop.
619  *
620  * @retval OT_ERROR_NONE           Resolver stopped successfully.
621  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
622  */
623 otError otMdnsStopSrvResolver(otInstance *aInstance, const otMdnsSrvResolver *aResolver);
624 
625 /**
626  * Starts a TXT record resolver.
627  *
628  * Initiates a continuous TXT record resolver for the specified service in @p aResolver.
629  *
630  * Discovered information is reported through the `mCallback` function in @p aResolver. When the TXT record is removed
631  * it is reported with a TTL value of zero. In this case, `mTxtData` may be NULL, and other result fields (such as
632  * `mTxtDataLength`) should be ignored.
633  *
634  * The callback may be invoked immediately with cached information (if available) and potentially before this function
635  * returns. When cached result is used, the reported TTL value will reflect the original TTL from the last received
636  * response.
637  *
638  * Multiple resolvers can be started for the same service, provided they use different callback functions.
639  *
640  * @param[in] aInstance    The OpenThread instance.
641  * @param[in] aResolver    The resolver to be started.
642  *
643  * @retval OT_ERROR_NONE           Resolver started successfully.
644  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
645  * @retval OT_ERROR_ALREADY        An identical resolver (same service and callback) is already active.
646  */
647 otError otMdnsStartTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *aResolver);
648 
649 /**
650  * Stops a TXT record resolver.
651  *
652  * No action is performed if no matching resolver with the same service and callback is currently active.
653  *
654  * @param[in] aInstance    The OpenThread instance.
655  * @param[in] aResolver    The resolver to stop.
656  *
657  * @retval OT_ERROR_NONE           Resolver stopped successfully.
658  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
659  */
660 otError otMdnsStopTxtResolver(otInstance *aInstance, const otMdnsTxtResolver *aResolver);
661 
662 /**
663  * Starts an IPv6 address resolver.
664  *
665  * Initiates a continuous IPv6 address resolver for the specified host name in @p aResolver.
666  *
667  * Discovered addresses are reported through the `mCallback` function in @p aResolver. The callback is invoked
668  * whenever addresses are added or removed, providing an updated list. If all addresses are removed, the callback is
669  * invoked with an empty list (`mAddresses` will be NULL, and `mAddressesLength` will be zero).
670  *
671  * The callback may be invoked immediately with cached information (if available) and potentially before this function
672  * returns. When cached result is used, the reported TTL values will reflect the original TTL from the last received
673  * response.
674  *
675  * Multiple resolvers can be started for the same host name, provided they use different callback functions.
676  *
677  * @param[in] aInstance    The OpenThread instance.
678  * @param[in] aResolver    The resolver to be started.
679  *
680  * @retval OT_ERROR_NONE           Resolver started successfully.
681  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
682  * @retval OT_ERROR_ALREADY        An identical resolver (same host and callback) is already active.
683  */
684 otError otMdnsStartIp6AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
685 
686 /**
687  * Stops an IPv6 address resolver.
688  *
689  * No action is performed if no matching resolver with the same host name and callback is currently active.
690  *
691  * @param[in] aInstance    The OpenThread instance.
692  * @param[in] aResolver    The resolver to stop.
693  *
694  * @retval OT_ERROR_NONE           Resolver stopped successfully.
695  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
696  */
697 otError otMdnsStopIp6AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
698 
699 /**
700  * Starts an IPv4 address resolver.
701  *
702  * Initiates a continuous IPv4 address resolver for the specified host name in @p aResolver.
703  *
704  * Discovered addresses are reported through the `mCallback` function in @p aResolver. The IPv4 addresses are
705  * represented using the IPv4-mapped IPv6 address format in `mAddresses` array.  The callback is invoked  whenever
706  * addresses are added or removed, providing an updated list. If all addresses are removed, the callback is invoked
707  * with an empty list (`mAddresses` will be NULL, and `mAddressesLength` will be zero).
708  *
709  * The callback may be invoked immediately with cached information (if available) and potentially before this function
710  * returns. When cached result is used, the reported TTL values will reflect the original TTL from the last received
711  * response.
712  *
713  * Multiple resolvers can be started for the same host name, provided they use different callback functions.
714  *
715  * @param[in] aInstance    The OpenThread instance.
716  * @param[in] aResolver    The resolver to be started.
717  *
718  * @retval OT_ERROR_NONE           Resolver started successfully.
719  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
720  * @retval OT_ERROR_ALREADY        An identical resolver (same host and callback) is already active.
721  */
722 otError otMdnsStartIp4AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
723 
724 /**
725  * Stops an IPv4 address resolver.
726  *
727  * No action is performed if no matching resolver with the same host name and callback is currently active.
728  *
729  * @param[in] aInstance    The OpenThread instance.
730  * @param[in] aResolver    The resolver to stop.
731  *
732  * @retval OT_ERROR_NONE           Resolver stopped successfully.
733  * @retval OT_ERROR_INVALID_STATE  mDNS module is not enabled.
734  */
735 otError otMdnsStopIp4AddressResolver(otInstance *aInstance, const otMdnsAddressResolver *aResolver);
736 
737 /**
738  * Represents additional information about a browser/resolver and its cached results.
739  */
740 typedef struct otMdnsCacheInfo
741 {
742     bool mIsActive;         ///< Whether this is an active browser/resolver vs an opportunistic cached one.
743     bool mHasCachedResults; ///< Whether there is any cached results.
744 } otMdnsCacheInfo;
745 
746 /**
747  * Iterates over browsers.
748  *
749  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
750  *
751  * On success, @p aBrowser is populated with information about the next browser. The `mCallback` field is always
752  * set to `NULL` as there may be multiple active browsers with different callbacks. Other pointers within the
753  * `otMdnsBrowser` structure remain valid until the next call to any OpenThread stack's public or platform API/callback.
754  *
755  * @param[in]  aInstance   The OpenThread instance.
756  * @param[in]  aIterator   Pointer to the iterator.
757  * @param[out] aBrowser    Pointer to an `otMdnsBrowser` to return the information about the next browser.
758  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
759  *
760  * @retval OT_ERROR_NONE         @p aBrowser, @p aInfo, & @p aIterator are updated successfully.
761  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
762  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
763  */
764 otError otMdnsGetNextBrowser(otInstance      *aInstance,
765                              otMdnsIterator  *aIterator,
766                              otMdnsBrowser   *aBrowser,
767                              otMdnsCacheInfo *aInfo);
768 
769 /**
770  * Iterates over SRV resolvers.
771  *
772  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
773  *
774  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
775  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
776  * `otMdnsSrvResolver` structure remain valid until the next call to any OpenThread stack's public or platform
777  * API/callback.
778  *
779  * @param[in]  aInstance   The OpenThread instance.
780  * @param[in]  aIterator   Pointer to the iterator.
781  * @param[out] aResolver   Pointer to an `otMdnsSrvResolver` to return the information about the next resolver.
782  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
783  *
784  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
785  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
786  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
787  */
788 otError otMdnsGetNextSrvResolver(otInstance        *aInstance,
789                                  otMdnsIterator    *aIterator,
790                                  otMdnsSrvResolver *aResolver,
791                                  otMdnsCacheInfo   *aInfo);
792 
793 /**
794  * Iterates over TXT resolvers.
795  *
796  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
797  *
798  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
799  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
800  * `otMdnsTxtResolver` structure remain valid until the next call to any OpenThread stack's public or platform
801  * API/callback.
802  *
803  * @param[in]  aInstance   The OpenThread instance.
804  * @param[in]  aIterator   Pointer to the iterator.
805  * @param[out] aResolver   Pointer to an `otMdnsTxtResolver` to return the information about the next resolver.
806  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
807  *
808  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
809  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
810  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
811  */
812 otError otMdnsGetNextTxtResolver(otInstance        *aInstance,
813                                  otMdnsIterator    *aIterator,
814                                  otMdnsTxtResolver *aResolver,
815                                  otMdnsCacheInfo   *aInfo);
816 
817 /**
818  * Iterates over IPv6 address resolvers.
819  *
820  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
821  *
822  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
823  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
824  * `otMdnsAddressResolver` structure remain valid until the next call to any OpenThread stack's public or platform
825  * API/callback.
826  *
827  * @param[in]  aInstance   The OpenThread instance.
828  * @param[in]  aIterator   Pointer to the iterator.
829  * @param[out] aResolver   Pointer to an `otMdnsAddressResolver` to return the information about the next resolver.
830  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
831  *
832  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
833  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
834  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
835  */
836 otError otMdnsGetNextIp6AddressResolver(otInstance            *aInstance,
837                                         otMdnsIterator        *aIterator,
838                                         otMdnsAddressResolver *aResolver,
839                                         otMdnsCacheInfo       *aInfo);
840 
841 /**
842  * Iterates over IPv4 address resolvers.
843  *
844  * Requires `OPENTHREAD_CONFIG_MULTICAST_DNS_ENTRY_ITERATION_API_ENABLE`.
845  *
846  * On success, @p aResolver is populated with information about the next resolver. The `mCallback` field is always
847  * set to `NULL` as there may be multiple active resolvers with different callbacks. Other pointers within the
848  * `otMdnsAddressResolver` structure remain valid until the next call to any OpenThread stack's public or platform
849  * API/callback.
850  *
851  * @param[in]  aInstance   The OpenThread instance.
852  * @param[in]  aIterator   Pointer to the iterator.
853  * @param[out] aResolver   Pointer to an `otMdnsAddressResolver` to return the information about the next resolver.
854  * @param[out] aInfo       Pointer to an `otMdnsCacheInfo` to return additional information.
855  *
856  * @retval OT_ERROR_NONE         @p aResolver, @p aInfo, & @p aIterator are updated successfully.
857  * @retval OT_ERROR_NOT_FOUND    Reached the end of the list.
858  * @retval OT_ERROR_INVALID_ARG  @p aIterator is not valid.
859  */
860 otError otMdnsGetNextIp4AddressResolver(otInstance            *aInstance,
861                                         otMdnsIterator        *aIterator,
862                                         otMdnsAddressResolver *aResolver,
863                                         otMdnsCacheInfo       *aInfo);
864 
865 /**
866  * @}
867  */
868 
869 #ifdef __cplusplus
870 } // extern "C"
871 #endif
872 
873 #endif // OPENTHREAD_MULTICAST_DNS_H_
874