xref: /aosp_15_r20/external/ot-br-posix/src/mdns/mdns.hpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2017, 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 mDNS publisher.
32  */
33 
34 #ifndef OTBR_AGENT_MDNS_HPP_
35 #define OTBR_AGENT_MDNS_HPP_
36 
37 #include "openthread-br/config.h"
38 
39 #ifndef OTBR_ENABLE_MDNS
40 #define OTBR_ENABLE_MDNS (OTBR_ENABLE_MDNS_AVAHI || OTBR_ENABLE_MDNS_MDNSSD)
41 #endif
42 
43 #include <functional>
44 #include <list>
45 #include <map>
46 #include <memory>
47 #include <string>
48 #include <vector>
49 
50 #include <sys/select.h>
51 
52 #include "common/callback.hpp"
53 #include "common/code_utils.hpp"
54 #include "common/time.hpp"
55 #include "common/types.hpp"
56 
57 namespace otbr {
58 
59 namespace Mdns {
60 
61 /**
62  * @addtogroup border-router-mdns
63  *
64  * @brief
65  *   This module includes definition for mDNS publisher.
66  *
67  * @{
68  */
69 
70 /**
71  * This interface defines the functionality of mDNS publisher.
72  */
73 class Publisher : private NonCopyable
74 {
75 public:
76     /**
77      * This structure represents a key/value pair of the TXT record.
78      */
79     struct TxtEntry
80     {
81         std::string          mKey;                ///< The key of the TXT entry.
82         std::vector<uint8_t> mValue;              ///< The value of the TXT entry. Can be empty.
83         bool                 mIsBooleanAttribute; ///< This entry is boolean attribute (encoded as `key` without `=`).
84 
TxtEntryotbr::Mdns::Publisher::TxtEntry85         TxtEntry(const char *aKey, const char *aValue)
86             : TxtEntry(aKey, reinterpret_cast<const uint8_t *>(aValue), strlen(aValue))
87         {
88         }
89 
TxtEntryotbr::Mdns::Publisher::TxtEntry90         TxtEntry(const char *aKey, const uint8_t *aValue, size_t aValueLength)
91             : TxtEntry(aKey, strlen(aKey), aValue, aValueLength)
92         {
93         }
94 
TxtEntryotbr::Mdns::Publisher::TxtEntry95         TxtEntry(const char *aKey, size_t aKeyLength, const uint8_t *aValue, size_t aValueLength)
96             : mKey(aKey, aKeyLength)
97             , mValue(aValue, aValue + aValueLength)
98             , mIsBooleanAttribute(false)
99         {
100         }
101 
TxtEntryotbr::Mdns::Publisher::TxtEntry102         TxtEntry(const char *aKey)
103             : TxtEntry(aKey, strlen(aKey))
104         {
105         }
106 
TxtEntryotbr::Mdns::Publisher::TxtEntry107         TxtEntry(const char *aKey, size_t aKeyLength)
108             : mKey(aKey, aKeyLength)
109             , mIsBooleanAttribute(true)
110         {
111         }
112 
operator ==otbr::Mdns::Publisher::TxtEntry113         bool operator==(const TxtEntry &aOther) const
114         {
115             return (mKey == aOther.mKey) && (mValue == aOther.mValue) &&
116                    (mIsBooleanAttribute == aOther.mIsBooleanAttribute);
117         }
118     };
119 
120     typedef std::vector<uint8_t>     TxtData;
121     typedef std::vector<TxtEntry>    TxtList;
122     typedef std::vector<std::string> SubTypeList;
123     typedef std::vector<Ip6Address>  AddressList;
124     typedef std::vector<uint8_t>     KeyData;
125 
126     /**
127      * This structure represents information of a discovered service instance.
128      */
129     struct DiscoveredInstanceInfo
130     {
131         bool        mRemoved    = false; ///< The Service Instance is removed.
132         uint32_t    mNetifIndex = 0;     ///< Network interface.
133         std::string mName;               ///< Instance name.
134         std::string mHostName;           ///< Full host name.
135         AddressList mAddresses;          ///< IPv6 addresses.
136         uint16_t    mPort     = 0;       ///< Port.
137         uint16_t    mPriority = 0;       ///< Service priority.
138         uint16_t    mWeight   = 0;       ///< Service weight.
139         TxtData     mTxtData;            ///< TXT RDATA bytes.
140         uint32_t    mTtl = 0;            ///< Service TTL.
141 
AddAddressotbr::Mdns::Publisher::DiscoveredInstanceInfo142         void AddAddress(const Ip6Address &aAddress) { Publisher::AddAddress(mAddresses, aAddress); }
RemoveAddressotbr::Mdns::Publisher::DiscoveredInstanceInfo143         void RemoveAddress(const Ip6Address &aAddress) { Publisher::RemoveAddress(mAddresses, aAddress); }
144     };
145 
146     /**
147      * This structure represents information of a discovered host.
148      */
149     struct DiscoveredHostInfo
150     {
151         std::string mHostName;       ///< Full host name.
152         AddressList mAddresses;      ///< IP6 addresses.
153         uint32_t    mNetifIndex = 0; ///< Network interface.
154         uint32_t    mTtl        = 0; ///< Host TTL.
155 
AddAddressotbr::Mdns::Publisher::DiscoveredHostInfo156         void AddAddress(const Ip6Address &aAddress) { Publisher::AddAddress(mAddresses, aAddress); }
RemoveAddressotbr::Mdns::Publisher::DiscoveredHostInfo157         void RemoveAddress(const Ip6Address &aAddress) { Publisher::RemoveAddress(mAddresses, aAddress); }
158     };
159 
160     /**
161      * This function is called to notify a discovered service instance.
162      */
163     using DiscoveredServiceInstanceCallback =
164         std::function<void(const std::string &aType, const DiscoveredInstanceInfo &aInstanceInfo)>;
165 
166     /**
167      * This function is called to notify a discovered host.
168      */
169     using DiscoveredHostCallback =
170         std::function<void(const std::string &aHostName, const DiscoveredHostInfo &aHostInfo)>;
171 
172     /**
173      * mDNS state values.
174      */
175     enum class State
176     {
177         kIdle,  ///< Unable to publish service.
178         kReady, ///< Ready to publish service.
179     };
180 
181     /** The callback for receiving mDNS publisher state changes. */
182     using StateCallback = std::function<void(State aNewState)>;
183 
184     /** The callback for receiving the result of a operation. */
185     using ResultCallback = OnceCallback<void(otbrError aError)>;
186 
187     /**
188      * This method starts the mDNS publisher.
189      *
190      * @retval OTBR_ERROR_NONE  Successfully started mDNS publisher;
191      * @retval OTBR_ERROR_MDNS  Failed to start mDNS publisher.
192      */
193     virtual otbrError Start(void) = 0;
194 
195     /**
196      * This method stops the mDNS publisher.
197      */
198     virtual void Stop(void) = 0;
199 
200     /**
201      * This method checks if publisher has been started.
202      *
203      * @retval true   Already started.
204      * @retval false  Not started.
205      */
206     virtual bool IsStarted(void) const = 0;
207 
208     /**
209      * This method publishes or updates a service.
210      *
211      * @param[in] aHostName     The name of the host which this service resides on. If an empty string is
212      *                          provided, this service resides on local host and it is the implementation
213      *                          to provide specific host name. Otherwise, the caller MUST publish the host
214      *                          with method PublishHost.
215      * @param[in] aName         The name of this service. If an empty string is provided, the service's name will be the
216      *                          same as the platform's hostname.
217      * @param[in] aType         The type of this service, e.g., "_srv._udp" (MUST NOT end with dot).
218      * @param[in] aSubTypeList  A list of service subtypes.
219      * @param[in] aPort         The port number of this service.
220      * @param[in] aTxtData      The encoded TXT data for this service.
221      * @param[in] aCallback     The callback for receiving the publishing result. `OTBR_ERROR_NONE` will be
222      *                          returned if the operation is successful and all other values indicate a
223      *                          failure. Specifically, `OTBR_ERROR_DUPLICATED` indicates that the name has
224      *                          already been published and the caller can re-publish with a new name if an
225      *                          alternative name is available/acceptable.
226      */
227     void PublishService(const std::string &aHostName,
228                         const std::string &aName,
229                         const std::string &aType,
230                         const SubTypeList &aSubTypeList,
231                         uint16_t           aPort,
232                         const TxtData     &aTxtData,
233                         ResultCallback   &&aCallback);
234 
235     /**
236      * This method un-publishes a service.
237      *
238      * @param[in] aName      The name of this service.
239      * @param[in] aType      The type of this service, e.g., "_srv._udp" (MUST NOT end with dot).
240      * @param[in] aCallback  The callback for receiving the publishing result.
241      */
242     virtual void UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback) = 0;
243 
244     /**
245      * This method publishes or updates a host.
246      *
247      * Publishing a host is advertising an AAAA RR for the host name. This method should be called
248      * before a service with non-empty host name is published.
249      *
250      * @param[in] aName       The name of the host.
251      * @param[in] aAddresses  The addresses of the host.
252      * @param[in] aCallback   The callback for receiving the publishing result.`OTBR_ERROR_NONE` will be
253      *                        returned if the operation is successful and all other values indicate a
254      *                        failure. Specifically, `OTBR_ERROR_DUPLICATED` indicates that the name has
255      *                        already been published and the caller can re-publish with a new name if an
256      *                        alternative name is available/acceptable.
257      */
258     void PublishHost(const std::string &aName, const AddressList &aAddresses, ResultCallback &&aCallback);
259 
260     /**
261      * This method un-publishes a host.
262      *
263      * @param[in] aName      A host name (MUST not end with dot).
264      * @param[in] aCallback  The callback for receiving the publishing result.
265      */
266     virtual void UnpublishHost(const std::string &aName, ResultCallback &&aCallback) = 0;
267 
268     /**
269      * This method publishes or updates a key record for a name.
270      *
271      * @param[in] aName       The name associated with key record (can be host name or service instance name).
272      * @param[in] aKeyData    The key data to publish.
273      * @param[in] aCallback   The callback for receiving the publishing result.`OTBR_ERROR_NONE` will be
274      *                        returned if the operation is successful and all other values indicate a
275      *                        failure. Specifically, `OTBR_ERROR_DUPLICATED` indicates that the name has
276      *                        already been published and the caller can re-publish with a new name if an
277      *                        alternative name is available/acceptable.
278      */
279     void PublishKey(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback);
280 
281     /**
282      * This method un-publishes a key record
283      *
284      * @param[in] aName      The name associated with key record.
285      * @param[in] aCallback  The callback for receiving the publishing result.
286      */
287     virtual void UnpublishKey(const std::string &aName, ResultCallback &&aCallback) = 0;
288 
289     /**
290      * This method subscribes a given service or service instance.
291      *
292      * If @p aInstanceName is not empty, this method subscribes the service instance. Otherwise, this method subscribes
293      * the service. mDNS implementations should use the `DiscoveredServiceInstanceCallback` function to notify
294      * discovered service instances.
295      *
296      * @note Discovery Proxy implementation guarantees no duplicate subscriptions for the same service or service
297      * instance.
298      *
299      * @param[in] aType          The service type, e.g., "_srv._udp" (MUST NOT end with dot).
300      * @param[in] aInstanceName  The service instance to subscribe, or empty to subscribe the service.
301      */
302     virtual void SubscribeService(const std::string &aType, const std::string &aInstanceName) = 0;
303 
304     /**
305      * This method unsubscribes a given service or service instance.
306      *
307      * If @p aInstanceName is not empty, this method unsubscribes the service instance. Otherwise, this method
308      * unsubscribes the service.
309      *
310      * @note Discovery Proxy implementation guarantees no redundant unsubscription for a service or service instance.
311      *
312      * @param[in] aType          The service type, e.g., "_srv._udp" (MUST NOT end with dot).
313      * @param[in] aInstanceName  The service instance to unsubscribe, or empty to unsubscribe the service.
314      */
315     virtual void UnsubscribeService(const std::string &aType, const std::string &aInstanceName) = 0;
316 
317     /**
318      * This method subscribes a given host.
319      *
320      * mDNS implementations should use the `DiscoveredHostCallback` function to notify discovered hosts.
321      *
322      * @note Discovery Proxy implementation guarantees no duplicate subscriptions for the same host.
323      *
324      * @param[in] aHostName  The host name (without domain).
325      */
326     virtual void SubscribeHost(const std::string &aHostName) = 0;
327 
328     /**
329      * This method unsubscribes a given host.
330      *
331      * @note Discovery Proxy implementation guarantees no redundant unsubscription for a host.
332      *
333      * @param[in] aHostName  The host name (without domain).
334      */
335     virtual void UnsubscribeHost(const std::string &aHostName) = 0;
336 
337     /**
338      * This method sets the callbacks for subscriptions.
339      *
340      * @param[in] aInstanceCallback  The callback function to receive discovered service instances.
341      * @param[in] aHostCallback      The callback function to receive discovered hosts.
342      *
343      * @returns  The Subscriber ID for the callbacks.
344      */
345     uint64_t AddSubscriptionCallbacks(DiscoveredServiceInstanceCallback aInstanceCallback,
346                                       DiscoveredHostCallback            aHostCallback);
347 
348     /**
349      * This method cancels callbacks for subscriptions.
350      *
351      * @param[in] aSubscriberId  The Subscriber ID previously returned by `AddSubscriptionCallbacks`.
352      */
353     void RemoveSubscriptionCallbacks(uint64_t aSubscriberId);
354 
355     /**
356      * This method returns the mDNS statistics information of the publisher.
357      *
358      * @returns  The MdnsTelemetryInfo of the publisher.
359      */
GetMdnsTelemetryInfo(void) const360     const MdnsTelemetryInfo &GetMdnsTelemetryInfo(void) const { return mTelemetryInfo; }
361 
362     virtual ~Publisher(void) = default;
363 
364     /**
365      * This function creates a mDNS publisher.
366      *
367      * @param[in] aCallback  The callback for receiving mDNS publisher state changes.
368      *
369      * @returns A pointer to the newly created mDNS publisher.
370      */
371     static Publisher *Create(StateCallback aCallback);
372 
373     /**
374      * This function destroys the mDNS publisher.
375      *
376      * @param[in] aPublisher  A pointer to the publisher.
377      */
378     static void Destroy(Publisher *aPublisher);
379 
380     /**
381      * This function writes the TXT entry list to a TXT data buffer. The TXT entries
382      * will be sorted by their keys.
383      *
384      * The output data is in standard DNS-SD TXT data format.
385      * See RFC 6763 for details: https://tools.ietf.org/html/rfc6763#section-6.
386      *
387      * @param[in]  aTxtList  A TXT entry list.
388      * @param[out] aTxtData  A TXT data buffer. Will be cleared.
389      *
390      * @retval OTBR_ERROR_NONE          Successfully write the TXT entry list.
391      * @retval OTBR_ERROR_INVALID_ARGS  The @p aTxtList includes invalid TXT entry.
392      *
393      * @sa DecodeTxtData
394      */
395     static otbrError EncodeTxtData(const TxtList &aTxtList, TxtData &aTxtData);
396 
397     /**
398      * This function decodes a TXT entry list from a TXT data buffer.
399      *
400      * The input data should be in standard DNS-SD TXT data format.
401      * See RFC 6763 for details: https://tools.ietf.org/html/rfc6763#section-6.
402      *
403      * @param[out]  aTxtList    A TXT entry list.
404      * @param[in]   aTxtData    A pointer to TXT data.
405      * @param[in]   aTxtLength  The TXT data length.
406      *
407      * @retval OTBR_ERROR_NONE          Successfully decoded the TXT data.
408      * @retval OTBR_ERROR_INVALID_ARGS  The @p aTxtdata has invalid TXT format.
409      *
410      * @sa EncodeTxtData
411      */
412     static otbrError DecodeTxtData(TxtList &aTxtList, const uint8_t *aTxtData, uint16_t aTxtLength);
413 
414 protected:
415     static constexpr uint8_t kMaxTextEntrySize = 255;
416 
417     class Registration
418     {
419     public:
420         ResultCallback mCallback;
421         Publisher     *mPublisher;
422 
Registration(ResultCallback && aCallback,Publisher * aPublisher)423         Registration(ResultCallback &&aCallback, Publisher *aPublisher)
424             : mCallback(std::move(aCallback))
425             , mPublisher(aPublisher)
426         {
427         }
428         virtual ~Registration(void);
429 
430         // Tells whether the service registration has been completed (typically by calling
431         // `ServiceRegistration::Complete`).
IsCompleted() const432         bool IsCompleted() const { return mCallback.IsNull(); }
433 
434     protected:
435         // Completes the service registration with given result/error.
TriggerCompleteCallback(otbrError aError)436         void TriggerCompleteCallback(otbrError aError)
437         {
438             if (!IsCompleted())
439             {
440                 std::move(mCallback)(aError);
441             }
442         }
443     };
444 
445     // TODO: We may need a registration ID to fetch the information of a registration.
446     class ServiceRegistration : public Registration
447     {
448     public:
449         std::string mHostName;
450         std::string mName;
451         std::string mType;
452         SubTypeList mSubTypeList;
453         uint16_t    mPort;
454         TxtData     mTxtData;
455 
ServiceRegistration(std::string aHostName,std::string aName,std::string aType,SubTypeList aSubTypeList,uint16_t aPort,TxtData aTxtData,ResultCallback && aCallback,Publisher * aPublisher)456         ServiceRegistration(std::string      aHostName,
457                             std::string      aName,
458                             std::string      aType,
459                             SubTypeList      aSubTypeList,
460                             uint16_t         aPort,
461                             TxtData          aTxtData,
462                             ResultCallback &&aCallback,
463                             Publisher       *aPublisher)
464             : Registration(std::move(aCallback), aPublisher)
465             , mHostName(std::move(aHostName))
466             , mName(std::move(aName))
467             , mType(std::move(aType))
468             , mSubTypeList(SortSubTypeList(std::move(aSubTypeList)))
469             , mPort(aPort)
470             , mTxtData(std::move(aTxtData))
471         {
472         }
~ServiceRegistration(void)473         ~ServiceRegistration(void) override { OnComplete(OTBR_ERROR_ABORTED); }
474 
475         void Complete(otbrError aError);
476 
477         // Tells whether this `ServiceRegistration` object is outdated comparing to the given parameters.
478         bool IsOutdated(const std::string &aHostName,
479                         const std::string &aName,
480                         const std::string &aType,
481                         const SubTypeList &aSubTypeList,
482                         uint16_t           aPort,
483                         const TxtData     &aTxtData) const;
484 
485     private:
486         void OnComplete(otbrError aError);
487     };
488 
489     class HostRegistration : public Registration
490     {
491     public:
492         std::string mName;
493         AddressList mAddresses;
494 
HostRegistration(std::string aName,AddressList aAddresses,ResultCallback && aCallback,Publisher * aPublisher)495         HostRegistration(std::string aName, AddressList aAddresses, ResultCallback &&aCallback, Publisher *aPublisher)
496             : Registration(std::move(aCallback), aPublisher)
497             , mName(std::move(aName))
498             , mAddresses(SortAddressList(std::move(aAddresses)))
499         {
500         }
501 
~HostRegistration(void)502         ~HostRegistration(void) override { OnComplete(OTBR_ERROR_ABORTED); }
503 
504         void Complete(otbrError aError);
505 
506         // Tells whether this `HostRegistration` object is outdated comparing to the given parameters.
507         bool IsOutdated(const std::string &aName, const AddressList &aAddresses) const;
508 
509     private:
510         void OnComplete(otbrError aError);
511     };
512 
513     class KeyRegistration : public Registration
514     {
515     public:
516         std::string mName;
517         KeyData     mKeyData;
518 
KeyRegistration(std::string aName,KeyData aKeyData,ResultCallback && aCallback,Publisher * aPublisher)519         KeyRegistration(std::string aName, KeyData aKeyData, ResultCallback &&aCallback, Publisher *aPublisher)
520             : Registration(std::move(aCallback), aPublisher)
521             , mName(std::move(aName))
522             , mKeyData(std::move(aKeyData))
523         {
524         }
525 
~KeyRegistration(void)526         ~KeyRegistration(void) { OnComplete(OTBR_ERROR_ABORTED); }
527 
528         void Complete(otbrError aError);
529 
530         // Tells whether this `KeyRegistration` object is outdated comparing to the given parameters.
531         bool IsOutdated(const std::string &aName, const KeyData &aKeyData) const;
532 
533     private:
534         void OnComplete(otbrError aError);
535     };
536 
537     using ServiceRegistrationPtr = std::unique_ptr<ServiceRegistration>;
538     using ServiceRegistrationMap = std::map<std::string, ServiceRegistrationPtr>;
539     using HostRegistrationPtr    = std::unique_ptr<HostRegistration>;
540     using HostRegistrationMap    = std::map<std::string, HostRegistrationPtr>;
541     using KeyRegistrationPtr     = std::unique_ptr<KeyRegistration>;
542     using KeyRegistrationMap     = std::map<std::string, KeyRegistrationPtr>;
543 
544     static SubTypeList SortSubTypeList(SubTypeList aSubTypeList);
545     static AddressList SortAddressList(AddressList aAddressList);
546     static std::string MakeFullName(const std::string &aName);
547     static std::string MakeFullServiceName(const std::string &aName, const std::string &aType);
MakeFullHostName(const std::string & aName)548     static std::string MakeFullHostName(const std::string &aName) { return MakeFullName(aName); }
MakeFullKeyName(const std::string & aName)549     static std::string MakeFullKeyName(const std::string &aName) { return MakeFullName(aName); }
550 
551     virtual otbrError PublishServiceImpl(const std::string &aHostName,
552                                          const std::string &aName,
553                                          const std::string &aType,
554                                          const SubTypeList &aSubTypeList,
555                                          uint16_t           aPort,
556                                          const TxtData     &aTxtData,
557                                          ResultCallback   &&aCallback) = 0;
558 
559     virtual otbrError PublishHostImpl(const std::string &aName,
560                                       const AddressList &aAddresses,
561                                       ResultCallback   &&aCallback) = 0;
562 
563     virtual otbrError PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) = 0;
564 
565     virtual void OnServiceResolveFailedImpl(const std::string &aType,
566                                             const std::string &aInstanceName,
567                                             int32_t            aErrorCode) = 0;
568 
569     virtual void OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode) = 0;
570 
571     virtual otbrError DnsErrorToOtbrError(int32_t aError) = 0;
572 
573     void AddServiceRegistration(ServiceRegistrationPtr &&aServiceReg);
574     void RemoveServiceRegistration(const std::string &aName, const std::string &aType, otbrError aError);
575     ServiceRegistration *FindServiceRegistration(const std::string &aName, const std::string &aType);
576     ServiceRegistration *FindServiceRegistration(const std::string &aNameAndType);
577 
578     void OnServiceResolved(std::string aType, DiscoveredInstanceInfo aInstanceInfo);
579     void OnServiceResolveFailed(std::string aType, std::string aInstanceName, int32_t aErrorCode);
580     void OnServiceRemoved(uint32_t aNetifIndex, std::string aType, std::string aInstanceName);
581     void OnHostResolved(std::string aHostName, DiscoveredHostInfo aHostInfo);
582     void OnHostResolveFailed(std::string aHostName, int32_t aErrorCode);
583 
584     // Handles the cases that there is already a registration for the same service.
585     // If the returned callback is completed, current registration should be considered
586     // success and no further action should be performed.
587     ResultCallback HandleDuplicateServiceRegistration(const std::string &aHostName,
588                                                       const std::string &aName,
589                                                       const std::string &aType,
590                                                       const SubTypeList &aSubTypeList,
591                                                       uint16_t           aPort,
592                                                       const TxtData     &aTxtData,
593                                                       ResultCallback   &&aCallback);
594 
595     ResultCallback HandleDuplicateHostRegistration(const std::string &aName,
596                                                    const AddressList &aAddresses,
597                                                    ResultCallback   &&aCallback);
598 
599     ResultCallback HandleDuplicateKeyRegistration(const std::string &aName,
600                                                   const KeyData     &aKeyData,
601                                                   ResultCallback   &&aCallback);
602 
603     void              AddHostRegistration(HostRegistrationPtr &&aHostReg);
604     void              RemoveHostRegistration(const std::string &aName, otbrError aError);
605     HostRegistration *FindHostRegistration(const std::string &aName);
606 
607     void             AddKeyRegistration(KeyRegistrationPtr &&aKeyReg);
608     void             RemoveKeyRegistration(const std::string &aName, otbrError aError);
609     KeyRegistration *FindKeyRegistration(const std::string &aName);
610     KeyRegistration *FindKeyRegistration(const std::string &aName, const std::string &aType);
611 
612     static void UpdateMdnsResponseCounters(MdnsResponseCounters &aCounters, otbrError aError);
613     static void UpdateEmaLatency(uint32_t &aEmaLatency, uint32_t aLatency, otbrError aError);
614 
615     void UpdateServiceRegistrationEmaLatency(const std::string &aInstanceName,
616                                              const std::string &aType,
617                                              otbrError          aError);
618     void UpdateHostRegistrationEmaLatency(const std::string &aHostName, otbrError aError);
619     void UpdateKeyRegistrationEmaLatency(const std::string &aKeyName, otbrError aError);
620     void UpdateServiceInstanceResolutionEmaLatency(const std::string &aInstanceName,
621                                                    const std::string &aType,
622                                                    otbrError          aError);
623     void UpdateHostResolutionEmaLatency(const std::string &aHostName, otbrError aError);
624 
625     static void AddAddress(AddressList &aAddressList, const Ip6Address &aAddress);
626     static void RemoveAddress(AddressList &aAddressList, const Ip6Address &aAddress);
627 
628     ServiceRegistrationMap mServiceRegistrations;
629     HostRegistrationMap    mHostRegistrations;
630     KeyRegistrationMap     mKeyRegistrations;
631 
632     struct DiscoverCallback
633     {
DiscoverCallbackotbr::Mdns::Publisher::DiscoverCallback634         DiscoverCallback(uint64_t                          aId,
635                          DiscoveredServiceInstanceCallback aServiceCallback,
636                          DiscoveredHostCallback            aHostCallback)
637             : mId(aId)
638             , mServiceCallback(std::move(aServiceCallback))
639             , mHostCallback(std::move(aHostCallback))
640             , mShouldInvoke(false)
641         {
642         }
643 
644         uint64_t                          mId;
645         DiscoveredServiceInstanceCallback mServiceCallback;
646         DiscoveredHostCallback            mHostCallback;
647         bool                              mShouldInvoke;
648     };
649 
650     uint64_t mNextSubscriberId = 1;
651 
652     std::list<DiscoverCallback> mDiscoverCallbacks;
653 
654     // {instance name, service type} -> the timepoint to begin service registration
655     std::map<std::pair<std::string, std::string>, Timepoint> mServiceRegistrationBeginTime;
656     // host name -> the timepoint to begin host registration
657     std::map<std::string, Timepoint> mHostRegistrationBeginTime;
658     // key name -> the timepoint to begin key registration
659     std::map<std::string, Timepoint> mKeyRegistrationBeginTime;
660     // {instance name, service type} -> the timepoint to begin service resolution
661     std::map<std::pair<std::string, std::string>, Timepoint> mServiceInstanceResolutionBeginTime;
662     // host name -> the timepoint to begin host resolution
663     std::map<std::string, Timepoint> mHostResolutionBeginTime;
664 
665     MdnsTelemetryInfo mTelemetryInfo{};
666 };
667 
668 /**
669  * @}
670  */
671 
672 } // namespace Mdns
673 
674 } // namespace otbr
675 
676 #endif // OTBR_AGENT_MDNS_HPP_
677