• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2018, 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 definition for mDNS publisher.
32  */
33 
34 #ifndef OTBR_AGENT_MDNS_MDNSSD_HPP_
35 #define OTBR_AGENT_MDNS_MDNSSD_HPP_
36 
37 #include <array>
38 #include <map>
39 #include <memory>
40 #include <utility>
41 #include <vector>
42 
43 #include <assert.h>
44 #include <dns_sd.h>
45 
46 #include "common/code_utils.hpp"
47 #include "common/mainloop.hpp"
48 #include "common/types.hpp"
49 #include "mdns/mdns.hpp"
50 
51 namespace otbr {
52 
53 namespace Mdns {
54 
55 /**
56  * This class implements mDNS publisher with mDNSResponder.
57  *
58  */
59 class PublisherMDnsSd : public MainloopProcessor, public Publisher
60 {
61 public:
62     explicit PublisherMDnsSd(StateCallback aCallback);
63 
64     ~PublisherMDnsSd(void) override;
65 
66     // Implementation of Mdns::Publisher.
67 
68     void UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback) override;
69 
70     void      UnpublishHost(const std::string &aName, ResultCallback &&aCallback) override;
71     void      SubscribeService(const std::string &aType, const std::string &aInstanceName) override;
72     void      UnsubscribeService(const std::string &aType, const std::string &aInstanceName) override;
73     void      SubscribeHost(const std::string &aHostName) override;
74     void      UnsubscribeHost(const std::string &aHostName) override;
75     otbrError Start(void) override;
76     bool      IsStarted(void) const override;
77     void      Stop(void) override;
78 
79     // Implementation of MainloopProcessor.
80 
81     void Update(MainloopContext &aMainloop) override;
82     void Process(const MainloopContext &aMainloop) override;
83 
84 protected:
85     void      PublishServiceImpl(const std::string &aHostName,
86                                  const std::string &aName,
87                                  const std::string &aType,
88                                  const SubTypeList &aSubTypeList,
89                                  uint16_t           aPort,
90                                  const TxtList &    aTxtList,
91                                  ResultCallback &&  aCallback) override;
92     void      PublishHostImpl(const std::string &         aName,
93                               const std::vector<uint8_t> &aAddress,
94                               ResultCallback &&           aCallback) override;
95     void      OnServiceResolveFailedImpl(const std::string &aType,
96                                          const std::string &aInstanceName,
97                                          int32_t            aErrorCode) override;
98     void      OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode) override;
99     otbrError DnsErrorToOtbrError(int32_t aErrorCode) override;
100 
101 private:
102     static constexpr uint32_t kDefaultTtl = 10;
103 
104     class DnssdServiceRegistration : public ServiceRegistration
105     {
106     public:
DnssdServiceRegistration(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtList & aTxtList,ResultCallback && aCallback,DNSServiceRef aServiceRef,PublisherMDnsSd * aPublisher)107         DnssdServiceRegistration(const std::string &aHostName,
108                                  const std::string &aName,
109                                  const std::string &aType,
110                                  const SubTypeList &aSubTypeList,
111                                  uint16_t           aPort,
112                                  const TxtList &    aTxtList,
113                                  ResultCallback &&  aCallback,
114                                  DNSServiceRef      aServiceRef,
115                                  PublisherMDnsSd *  aPublisher)
116             : ServiceRegistration(aHostName,
117                                   aName,
118                                   aType,
119                                   aSubTypeList,
120                                   aPort,
121                                   aTxtList,
122                                   std::move(aCallback),
123                                   aPublisher)
124             , mServiceRef(aServiceRef)
125         {
126         }
127 
128         ~DnssdServiceRegistration(void) override;
GetServiceRef() const129         const DNSServiceRef &GetServiceRef() const { return mServiceRef; }
130 
131     private:
132         DNSServiceRef mServiceRef;
133     };
134 
135     class DnssdHostRegistration : public HostRegistration
136     {
137     public:
DnssdHostRegistration(const std::string & aName,const std::vector<uint8_t> & aAddress,ResultCallback && aCallback,DNSServiceRef aServiceRef,DNSRecordRef aRecordRef,Publisher * aPublisher)138         DnssdHostRegistration(const std::string &         aName,
139                               const std::vector<uint8_t> &aAddress,
140                               ResultCallback &&           aCallback,
141                               DNSServiceRef               aServiceRef,
142                               DNSRecordRef                aRecordRef,
143                               Publisher *                 aPublisher)
144             : HostRegistration(aName, aAddress, std::move(aCallback), aPublisher)
145             , mServiceRef(aServiceRef)
146             , mRecordRef(aRecordRef)
147         {
148         }
149 
150         ~DnssdHostRegistration(void) override;
GetServiceRef() const151         const DNSServiceRef &GetServiceRef() const { return mServiceRef; }
GetRecordRef() const152         const DNSRecordRef & GetRecordRef() const { return mRecordRef; }
153 
154     private:
155         DNSServiceRef mServiceRef;
156         DNSRecordRef  mRecordRef;
157     };
158 
159     struct ServiceRef : private ::NonCopyable
160     {
161         DNSServiceRef mServiceRef;
162 
ServiceRefotbr::Mdns::PublisherMDnsSd::ServiceRef163         explicit ServiceRef(void)
164             : mServiceRef(nullptr)
165         {
166         }
167 
~ServiceRefotbr::Mdns::PublisherMDnsSd::ServiceRef168         ~ServiceRef() { Release(); }
169 
170         void Update(MainloopContext &aMainloop) const;
171         void Process(const MainloopContext &aMainloop, std::vector<DNSServiceRef> &aReadyServices) const;
172         void Release(void);
173         void DeallocateServiceRef(void);
174     };
175 
176     struct ServiceSubscription;
177 
178     struct ServiceInstanceResolution : public ServiceRef
179     {
ServiceInstanceResolutionotbr::Mdns::PublisherMDnsSd::ServiceInstanceResolution180         explicit ServiceInstanceResolution(ServiceSubscription &aSubscription,
181                                            std::string          aInstanceName,
182                                            std::string          aType,
183                                            std::string          aDomain,
184                                            uint32_t             aNetifIndex)
185             : ServiceRef()
186             , mSubscription(&aSubscription)
187             , mInstanceName(std::move(aInstanceName))
188             , mTypeEndWithDot(std::move(aType))
189             , mDomain(std::move(aDomain))
190             , mNetifIndex(aNetifIndex)
191         {
192         }
193 
194         void      Resolve(void);
195         otbrError GetAddrInfo(uint32_t aInterfaceIndex);
196         void      FinishResolution(void);
197 
198         static void HandleResolveResult(DNSServiceRef        aServiceRef,
199                                         DNSServiceFlags      aFlags,
200                                         uint32_t             aInterfaceIndex,
201                                         DNSServiceErrorType  aErrorCode,
202                                         const char *         aFullName,
203                                         const char *         aHostTarget,
204                                         uint16_t             aPort, // In network byte order.
205                                         uint16_t             aTxtLen,
206                                         const unsigned char *aTxtRecord,
207                                         void *               aContext);
208         void        HandleResolveResult(DNSServiceRef        aServiceRef,
209                                         DNSServiceFlags      aFlags,
210                                         uint32_t             aInterfaceIndex,
211                                         DNSServiceErrorType  aErrorCode,
212                                         const char *         aFullName,
213                                         const char *         aHostTarget,
214                                         uint16_t             aPort, // In network byte order.
215                                         uint16_t             aTxtLen,
216                                         const unsigned char *aTxtRecord);
217         static void HandleGetAddrInfoResult(DNSServiceRef          aServiceRef,
218                                             DNSServiceFlags        aFlags,
219                                             uint32_t               aInterfaceIndex,
220                                             DNSServiceErrorType    aErrorCode,
221                                             const char *           aHostName,
222                                             const struct sockaddr *aAddress,
223                                             uint32_t               aTtl,
224                                             void *                 aContext);
225         void        HandleGetAddrInfoResult(DNSServiceRef          aServiceRef,
226                                             DNSServiceFlags        aFlags,
227                                             uint32_t               aInterfaceIndex,
228                                             DNSServiceErrorType    aErrorCode,
229                                             const char *           aHostName,
230                                             const struct sockaddr *aAddress,
231                                             uint32_t               aTtl);
232 
233         ServiceSubscription *  mSubscription;
234         std::string            mInstanceName;
235         std::string            mTypeEndWithDot;
236         std::string            mDomain;
237         uint32_t               mNetifIndex;
238         DiscoveredInstanceInfo mInstanceInfo;
239     };
240 
241     struct ServiceSubscription : public ServiceRef
242     {
ServiceSubscriptionotbr::Mdns::PublisherMDnsSd::ServiceSubscription243         explicit ServiceSubscription(PublisherMDnsSd &aMDnsSd, std::string aType, std::string aInstanceName)
244             : ServiceRef()
245             , mMDnsSd(&aMDnsSd)
246             , mType(std::move(aType))
247             , mInstanceName(std::move(aInstanceName))
248         {
249         }
250 
251         void Browse(void);
252         void Resolve(uint32_t           aNetifIndex,
253                      const std::string &aInstanceName,
254                      const std::string &aType,
255                      const std::string &aDomain);
256         void RemoveInstanceResolution(ServiceInstanceResolution &aInstanceResolution);
257         void UpdateAll(MainloopContext &aMainloop) const;
258         void ProcessAll(const MainloopContext &aMainloop, std::vector<DNSServiceRef> &aReadyServices) const;
259 
260         static void HandleBrowseResult(DNSServiceRef       aServiceRef,
261                                        DNSServiceFlags     aFlags,
262                                        uint32_t            aInterfaceIndex,
263                                        DNSServiceErrorType aErrorCode,
264                                        const char *        aInstanceName,
265                                        const char *        aType,
266                                        const char *        aDomain,
267                                        void *              aContext);
268         void        HandleBrowseResult(DNSServiceRef       aServiceRef,
269                                        DNSServiceFlags     aFlags,
270                                        uint32_t            aInterfaceIndex,
271                                        DNSServiceErrorType aErrorCode,
272                                        const char *        aInstanceName,
273                                        const char *        aType,
274                                        const char *        aDomain);
275 
276         PublisherMDnsSd *mMDnsSd;
277         std::string      mType;
278         std::string      mInstanceName;
279 
280         std::vector<std::unique_ptr<ServiceInstanceResolution>> mResolvingInstances;
281     };
282 
283     struct HostSubscription : public ServiceRef
284     {
HostSubscriptionotbr::Mdns::PublisherMDnsSd::HostSubscription285         explicit HostSubscription(PublisherMDnsSd &aMDnsSd, std::string aHostName)
286             : ServiceRef()
287             , mMDnsSd(&aMDnsSd)
288             , mHostName(std::move(aHostName))
289         {
290         }
291 
292         void        Resolve(void);
293         static void HandleResolveResult(DNSServiceRef          aServiceRef,
294                                         DNSServiceFlags        aFlags,
295                                         uint32_t               aInterfaceIndex,
296                                         DNSServiceErrorType    aErrorCode,
297                                         const char *           aHostName,
298                                         const struct sockaddr *aAddress,
299                                         uint32_t               aTtl,
300                                         void *                 aContext);
301         void        HandleResolveResult(DNSServiceRef          aServiceRef,
302                                         DNSServiceFlags        aFlags,
303                                         uint32_t               aInterfaceIndex,
304                                         DNSServiceErrorType    aErrorCode,
305                                         const char *           aHostName,
306                                         const struct sockaddr *aAddress,
307                                         uint32_t               aTtl);
308 
309         PublisherMDnsSd *  mMDnsSd;
310         std::string        mHostName;
311         DiscoveredHostInfo mHostInfo;
312     };
313 
314     using ServiceSubscriptionList = std::vector<std::unique_ptr<ServiceSubscription>>;
315     using HostSubscriptionList    = std::vector<std::unique_ptr<HostSubscription>>;
316 
317     static void HandleServiceRegisterResult(DNSServiceRef         aService,
318                                             const DNSServiceFlags aFlags,
319                                             DNSServiceErrorType   aError,
320                                             const char *          aName,
321                                             const char *          aType,
322                                             const char *          aDomain,
323                                             void *                aContext);
324     void        HandleServiceRegisterResult(DNSServiceRef         aService,
325                                             const DNSServiceFlags aFlags,
326                                             DNSServiceErrorType   aError,
327                                             const char *          aName,
328                                             const char *          aType,
329                                             const char *          aDomain);
330     static void HandleRegisterHostResult(DNSServiceRef       aHostsConnection,
331                                          DNSRecordRef        aHostRecord,
332                                          DNSServiceFlags     aFlags,
333                                          DNSServiceErrorType aErrorCode,
334                                          void *              aContext);
335     void        HandleRegisterHostResult(DNSServiceRef       aHostsConnection,
336                                          DNSRecordRef        aHostRecord,
337                                          DNSServiceFlags     aFlags,
338                                          DNSServiceErrorType aErrorCode);
339 
340     static std::string MakeRegType(const std::string &aType, SubTypeList aSubTypeList);
341 
342     ServiceRegistration *FindServiceRegistration(const DNSServiceRef &aServiceRef);
343     HostRegistration *   FindHostRegistration(const DNSServiceRef &aServiceRef, const DNSRecordRef &aRecordRef);
344 
345     DNSServiceRef mHostsRef;
346     State         mState;
347     StateCallback mStateCallback;
348 
349     ServiceSubscriptionList mSubscribedServices;
350     HostSubscriptionList    mSubscribedHosts;
351 };
352 
353 /**
354  * @}
355  */
356 
357 } // namespace Mdns
358 
359 } // namespace otbr
360 
361 #endif // OTBR_AGENT_MDNS_MDNSSD_HPP_
362