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  *   This file includes definitions for DNS-SD module.
32  */
33 
34 #ifndef DNSSD_HPP_
35 #define DNSSD_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE || OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
40 
41 #if !OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION
42 #if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE && OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
43 #error "Must enable either `PLATFORM_DNSSD_ENABLE` or `MULTICAST_DNS_ENABLE` and not both."
44 #endif
45 #else
46 #if !OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE || !OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
47 #error "`PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION` requires both `PLATFORM_DNSSD_ENABLE` or `MULTICAST_DNS_ENABLE`.".
48 #endif
49 #endif // !OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION
50 
51 #include <openthread/platform/dnssd.h>
52 
53 #include "common/clearable.hpp"
54 #include "common/locator.hpp"
55 #include "common/non_copyable.hpp"
56 #include "net/ip6_address.hpp"
57 
58 namespace ot {
59 
60 /**
61  * @addtogroup core-dns
62  *
63  * @brief
64  *   This module includes definitions for DNS-SD (mDNS) APIs used by other modules in OT (e.g. advertising proxy).
65  *
66  *   The DNS-SD is implemented either using the native mDNS module in OpenThread or using `otPlatDnssd` platform
67  *   APIs (delegating the DNS-SD implementation to platform layer).
68  *
69  * @{
70  *
71  */
72 
73 extern "C" void otPlatDnssdStateHandleStateChange(otInstance *aInstance);
74 
75 /**
76  * Represents DNS-SD module.
77  *
78  */
79 class Dnssd : public InstanceLocator, private NonCopyable
80 {
81     friend void otPlatDnssdStateHandleStateChange(otInstance *aInstance);
82 
83 public:
84     /**
85      * Represents state of DNS-SD platform.
86      *
87      */
88     enum State : uint8_t
89     {
90         kStopped = OT_PLAT_DNSSD_STOPPED, ///< Stopped and unable to register any service or host.
91         kReady   = OT_PLAT_DNSSD_READY    ///< Running and ready to register service or host.
92     };
93 
94     typedef otPlatDnssdRequestId        RequestId;        ///< A request ID.
95     typedef otPlatDnssdRegisterCallback RegisterCallback; ///< The registration request callback
96     typedef otPlatDnssdBrowseCallback   BrowseCallback;   ///< Browser callback.
97     typedef otPlatDnssdSrvCallback      SrvCallback;      ///< SRV callback.
98     typedef otPlatDnssdTxtCallback      TxtCallback;      ///< TXT callback.
99     typedef otPlatDnssdAddressCallback  AddressCallback;  ///< Address callback
100     typedef otPlatDnssdBrowseResult     BrowseResult;     ///< Browser result.
101     typedef otPlatDnssdSrvResult        SrvResult;        ///< SRV result.
102     typedef otPlatDnssdTxtResult        TxtResult;        ///< TXT result.
103     typedef otPlatDnssdAddressResult    AddressResult;    ///< Address result.
104     typedef otPlatDnssdAddressAndTtl    AddressAndTtl;    ///< Address and TTL.
105 
106     class Host : public otPlatDnssdHost, public Clearable<Host> ///< Host information.
107     {
108     };
109 
110     class Service : public otPlatDnssdService, public Clearable<Service> ///< Service information.
111     {
112     };
113 
114     class Key : public otPlatDnssdKey, public Clearable<Key> ///< Key information
115     {
116     };
117 
118     class Browser : public otPlatDnssdBrowser, public Clearable<Browser> ///< Browser.
119     {
120     };
121 
122     class SrvResolver : public otPlatDnssdSrvResolver, public Clearable<SrvResolver> ///< SRV resolver.
123     {
124     };
125 
126     class TxtResolver : public otPlatDnssdTxtResolver, public Clearable<TxtResolver> ///< TXT resolver.
127     {
128     };
129 
130     class AddressResolver : public otPlatDnssdAddressResolver, public Clearable<AddressResolver> ///< Address resolver.
131     {
132     };
133 
134     /**
135      * Represents a range of `RequestId` values.
136      *
137      * The range is stored using start and end ID values. The implementation handles the case when ID values roll over.
138      *
139      */
140     struct RequestIdRange : public Clearable<RequestIdRange>
141     {
142         /**
143          * Initializes a range as empty.
144          *
145          */
RequestIdRangeot::Dnssd::RequestIdRange146         RequestIdRange(void)
147             : mStart(0)
148             , mEnd(0)
149         {
150         }
151 
152         /**
153          * Adds a request ID to the range.
154          *
155          * @param[in] aId   The ID to add to the range.
156          *
157          */
158         void Add(RequestId aId);
159 
160         /**
161          * Removes a request ID from the range.
162          *
163          * @param[in] aId   The ID to remove from the range.
164          *
165          */
166         void Remove(RequestId aId);
167 
168         /**
169          * Indicates whether or not a given ID is contained within the range.
170          *
171          * @param[in] aId   The ID to check.
172          *
173          * @retval TRUE  The @p aID is contained within the range.
174          * @retval FALSE The @p aId is not contained within the range.
175          *
176          */
177         bool Contains(RequestId aId) const;
178 
179         /**
180          * Indicates whether or not the range is empty.
181          *
182          * @retval TRUE  The range is empty.
183          * @retval FALSE The range is not empty.
184          *
185          */
IsEmptyot::Dnssd::RequestIdRange186         bool IsEmpty(void) const { return (mStart == mEnd); }
187 
188     private:
189         // The range is represented as all `RequestId` values from
190         // `mStart` up to, but not including, `mEnd`. It uses serial
191         // number arithmetic logic when comparing `RequestId` values,
192         // so `Contains()` and other methods work correctly even when
193         // the ID value rolls over.
194 
195         RequestId mStart;
196         RequestId mEnd;
197     };
198 
199     /**
200      * Initializes `Dnssd` object.
201      *
202      * @param[in]  aInstance  The OpenThread instance.
203      *
204      */
205     explicit Dnssd(Instance &aInstance);
206 
207     /**
208      * Gets the current state of DNS-SD platform module.
209      *
210      * @returns The current state of DNS-SD platform.
211      *
212      */
213     State GetState(void) const;
214 
215     /**
216      * Indicates whether or not DNS-SD platform is ready (in `kReady` state).
217      *
218      * @retval TRUE   The DNS-SD platform is ready.
219      * @retval FALSE  The DNS-SD platform is not ready.
220      *
221      */
IsReady(void) const222     bool IsReady(void) const { return GetState() == kReady; }
223 
224     /**
225      * Registers or updates a service on the infrastructure network's DNS-SD module.
226      *
227      * Refer to the documentation for `otPlatDnssdRegisterService()`, for a more detailed description of the behavior
228      * of this method.
229      *
230      * @param[in] aService     Information about service to unregister.
231      * @param[in] aRequestId   The ID associated with this request.
232      * @param[in] aCallback    The callback function pointer to report the outcome (may be `nullptr`).
233      *
234      */
235     void RegisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback);
236 
237     /**
238      * Unregisters a service on the infrastructure network's DNS-SD module.
239      *
240      * Refer to the documentation for `otPlatDnssdUnregisterService()`, for a more detailed description of the behavior
241      * of this method.
242      *
243      * @param[in] aService      Information about service to unregister.
244      * @param[in] aRequestId    The ID associated with this request.
245      * @param[in] aCallback     The callback function pointer to report the outcome (may be `nullptr`).
246      *
247      */
248     void UnregisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback);
249 
250     /**
251      * Registers or updates a host on the infrastructure network's DNS-SD module.
252      *
253      * Refer to the documentation for `otPlatDnssdRegisterHost()`, for a more detailed description of the behavior
254      * of this method.
255      *
256      * @param[in] aHost         Information about host to register.
257      * @param[in] aRequestId    The ID associated with this request.
258      * @param[in] aCallback     The callback function pointer to report the outcome (may be `nullptr`).
259      *
260      */
261     void RegisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback);
262 
263     /**
264      * Unregisters a host on the infrastructure network's DNS-SD module.
265      *
266      * Refer to the documentation for `otPlatDnssdUnregisterHost()`, for a more detailed description of the behavior
267      * of this method.
268      *
269      * @param[in] aHost         Information about the host to unregister.
270      * @param[in] aRequestId    The ID associated with this request.
271      * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
272      *
273      */
274     void UnregisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback);
275 
276     /**
277      * Registers or updates a key record on the infrastructure network's DNS-SD module.
278      *
279      * Refer to the documentation for `otPlatDnssdRegisterKey()`, for a more detailed description of the behavior
280      * of this method.
281      *
282      * @param[in] aKey          Information about the key to register.
283      * @param[in] aRequestId    The ID associated with this request.
284      * @param[in] aCallback     The callback function pointer to report the outcome (may be `nullptr`).
285      *
286      */
287     void RegisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback);
288 
289     /**
290      * Unregisters a key record on the infrastructure network's DNS-SD module.
291      *
292      * Refer to the documentation for `otPlatDnssdUnregisterKey()`, for a more detailed description of the behavior
293      * of this method.
294      *
295      * @param[in] aKey          Information about the key to unregister.
296      * @param[in] aRequestId    The ID associated with this request.
297      * @param[in] aCallback     The callback function pointer to report the outcome (may be NULL if no callback needed).
298      *
299      */
300     void UnregisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback);
301 
302     /**
303      * Starts a service browser.
304      *
305      * Refer to the documentation for `otPlatDnssdStartBrowser()` for a more detailed description of the behavior
306      * of this method.
307      *
308      * @param[in] aBrowser    The browser to be started.
309      *
310      */
311     void StartBrowser(const Browser &aBrowser);
312 
313     /**
314      * Stops a service browser.
315      *
316      * Refer to the documentation for `otPlatDnssdStopBrowser()` for a more detailed description of the behavior
317      * of this method.
318      *
319      * @param[in] aBrowser    The browser to stop.
320      *
321      */
322     void StopBrowser(const Browser &aBrowser);
323 
324     /**
325      * Starts an SRV record resolver.
326      *
327      * Refer to the documentation for `otPlatDnssdStartSrvResolver()` for a more detailed description of the behavior
328      * of this method.
329      *
330      * @param[in] aResolver    The resolver to be started.
331      *
332      */
333     void StartSrvResolver(const SrvResolver &aResolver);
334 
335     /**
336      * Stops an SRV record resolver.
337      *
338      * Refer to the documentation for `otPlatDnssdStopSrvResolver()` for a more detailed description of the behavior
339      * of this method.
340      *
341      * @param[in] aResolver    The resolver to stop.
342      *
343      */
344     void StopSrvResolver(const SrvResolver &aResolver);
345 
346     /**
347      * Starts a TXT record resolver.
348      *
349      * Refer to the documentation for `otPlatDnssdStartTxtResolver()` for a more detailed description of the behavior
350      * of this method.
351      *
352      * @param[in] aResolver    The resolver to be started.
353      *
354      */
355     void StartTxtResolver(const TxtResolver &aResolver);
356 
357     /**
358      * Stops a TXT record resolver.
359      *
360      * Refer to the documentation for `otPlatDnssdStopTxtResolver()` for a more detailed description of the behavior
361      * of this method.
362      *
363      * @param[in] aResolver    The resolver to stop.
364      *
365      */
366     void StopTxtResolver(const TxtResolver &aResolver);
367 
368     /**
369      * Starts an IPv6 address resolver.
370      *
371      * Refer to the documentation for `otPlatDnssdStartIp6AddressResolver()` for a more detailed description of the
372      * behavior of this method.
373      *
374      * @param[in] aResolver    The resolver to be started.
375      *
376      */
377     void StartIp6AddressResolver(const AddressResolver &aResolver);
378 
379     /**
380      * Stops an IPv6 address resolver.
381      *
382      * Refer to the documentation for `otPlatDnssdStopIp6AddressResolver()` for a more detailed description of the
383      * behavior of this method.
384      *
385      * @param[in] aResolver    The resolver to stop.
386      *
387      */
388     void StopIp6AddressResolver(const AddressResolver &aResolver);
389 
390     /**
391      * Starts an IPv4 address resolver.
392      *
393      * Refer to the documentation for `otPlatDnssdStartIp4AddressResolver()` for a more detailed description of the
394      * behavior of this method.
395      *
396      * @param[in] aResolver    The resolver to be started.
397      *
398      */
399     void StartIp4AddressResolver(const AddressResolver &aResolver);
400 
401     /**
402      * Stops an IPv4 address resolver.
403      *
404      * Refer to the documentation for `otPlatDnssdStopIp4AddressResolver()` for a more detailed description of the
405      * behavior of this method.
406      *
407      * @param[in] aResolver    The resolver to stop.
408      *
409      */
410     void StopIp4AddressResolver(const AddressResolver &aResolver);
411 
412 #if OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
413     /**
414      * Handles native mDNS state change.
415      *
416      * This is used to notify `Dnssd` when `Multicast::Dns::Core` gets enabled or disabled.
417      *
418      */
419     void HandleMdnsCoreStateChange(void);
420 #endif
421 
422 #if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION
423     /**
424      * Selects whether to use the native mDNS or the platform `otPlatDnssd` APIs.
425      *
426      * @param[in] aUseMdns    TRUE to use the native mDNS module, FALSE to use platform APIs.
427      *
428      */
SetUseNativeMdns(bool aUseMdns)429     void SetUseNativeMdns(bool aUseMdns) { mUseNativeMdns = aUseMdns; }
430 
431     /**
432      * Indicates whether the `Dnssd` is using the native mDNS or the platform `otPlatDnssd` APIs.
433      *
434      * @retval TRUE    `Dnssd` is using the native mDSN module.
435      * @retval FALSE   `Dnssd` is using the platform `otPlatDnssd` APIs.
436      *
437      */
ShouldUseNativeMdns(void) const438     bool ShouldUseNativeMdns(void) const { return mUseNativeMdns; }
439 #endif
440 
441 private:
442     void HandleStateChange(void);
443 
444 #if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION
445     bool mUseNativeMdns;
446 #endif
447 };
448 
449 /**
450  * @}
451  *
452  */
453 
454 DefineMapEnum(otPlatDnssdState, Dnssd::State);
455 DefineCoreType(otPlatDnssdService, Dnssd::Service);
456 DefineCoreType(otPlatDnssdHost, Dnssd::Host);
457 DefineCoreType(otPlatDnssdKey, Dnssd::Key);
458 
459 } // namespace ot
460 
461 #endif // OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE || OPENTHREAD_CONFIG_MULTICAST_DNS_ENABLE
462 
463 #endif // DNSSD_HPP_
464