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