• 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 definition for mDNS publisher based on avahi.
32  */
33 
34 #ifndef OTBR_AGENT_MDNS_AVAHI_HPP_
35 #define OTBR_AGENT_MDNS_AVAHI_HPP_
36 
37 #include <memory>
38 #include <set>
39 #include <vector>
40 
41 #include <avahi-client/client.h>
42 #include <avahi-client/lookup.h>
43 #include <avahi-client/publish.h>
44 #include <avahi-common/domain.h>
45 #include <avahi-common/watch.h>
46 
47 #include "mdns.hpp"
48 #include "common/code_utils.hpp"
49 #include "common/mainloop.hpp"
50 #include "common/time.hpp"
51 
52 /**
53  * @addtogroup border-router-mdns
54  *
55  * @brief
56  *   This module includes definition for avahi-based mDNS publisher.
57  *
58  * @{
59  */
60 
61 namespace otbr {
62 
63 namespace Mdns {
64 
65 class AvahiPoller;
66 
67 /**
68  * This class implements mDNS publisher with avahi.
69  *
70  */
71 class PublisherAvahi : public Publisher
72 {
73 public:
74     PublisherAvahi(StateCallback aStateCallback);
75     ~PublisherAvahi(void) override;
76 
77     void      UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback) override;
78     void      UnpublishHost(const std::string &aName, ResultCallback &&aCallback) override;
79     void      SubscribeService(const std::string &aType, const std::string &aInstanceName) override;
80     void      UnsubscribeService(const std::string &aType, const std::string &aInstanceName) override;
81     void      SubscribeHost(const std::string &aHostName) override;
82     void      UnsubscribeHost(const std::string &aHostName) override;
83     otbrError Start(void) override;
84     bool      IsStarted(void) const override;
85     void      Stop(void) override;
86 
87 protected:
88     void      PublishServiceImpl(const std::string &aHostName,
89                                  const std::string &aName,
90                                  const std::string &aType,
91                                  const SubTypeList &aSubTypeList,
92                                  uint16_t           aPort,
93                                  const TxtList &    aTxtList,
94                                  ResultCallback &&  aCallback) override;
95     void      PublishHostImpl(const std::string &         aName,
96                               const std::vector<uint8_t> &aAddress,
97                               ResultCallback &&           aCallback) override;
98     void      OnServiceResolveFailedImpl(const std::string &aType,
99                                          const std::string &aInstanceName,
100                                          int32_t            aErrorCode) override;
101     void      OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode) override;
102     otbrError DnsErrorToOtbrError(int32_t aErrorCode) override;
103 
104 private:
105     static constexpr size_t   kMaxSizeOfTxtRecord = 1024;
106     static constexpr uint32_t kDefaultTtl         = 10; // In seconds.
107 
108     class AvahiServiceRegistration : public ServiceRegistration
109     {
110     public:
AvahiServiceRegistration(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtList & aTxtList,ResultCallback && aCallback,AvahiEntryGroup * aEntryGroup,PublisherAvahi * aPublisher)111         AvahiServiceRegistration(const std::string &aHostName,
112                                  const std::string &aName,
113                                  const std::string &aType,
114                                  const SubTypeList &aSubTypeList,
115                                  uint16_t           aPort,
116                                  const TxtList &    aTxtList,
117                                  ResultCallback &&  aCallback,
118                                  AvahiEntryGroup *  aEntryGroup,
119                                  PublisherAvahi *   aPublisher)
120             : ServiceRegistration(aHostName,
121                                   aName,
122                                   aType,
123                                   aSubTypeList,
124                                   aPort,
125                                   aTxtList,
126                                   std::move(aCallback),
127                                   aPublisher)
128             , mEntryGroup(aEntryGroup)
129         {
130         }
131 
132         ~AvahiServiceRegistration(void) override;
GetEntryGroup(void) const133         const AvahiEntryGroup *GetEntryGroup(void) const { return mEntryGroup; }
134 
135     private:
136         AvahiEntryGroup *mEntryGroup;
137     };
138 
139     class AvahiHostRegistration : public HostRegistration
140     {
141     public:
AvahiHostRegistration(const std::string & aName,const std::vector<uint8_t> & aAddress,ResultCallback && aCallback,AvahiEntryGroup * aEntryGroup,PublisherAvahi * aPublisher)142         AvahiHostRegistration(const std::string &         aName,
143                               const std::vector<uint8_t> &aAddress,
144                               ResultCallback &&           aCallback,
145                               AvahiEntryGroup *           aEntryGroup,
146                               PublisherAvahi *            aPublisher)
147             : HostRegistration(aName, aAddress, std::move(aCallback), aPublisher)
148             , mEntryGroup(aEntryGroup)
149         {
150         }
151 
152         ~AvahiHostRegistration(void) override;
GetEntryGroup(void) const153         const AvahiEntryGroup *GetEntryGroup(void) const { return mEntryGroup; }
154 
155     private:
156         AvahiEntryGroup *mEntryGroup;
157     };
158 
159     struct Subscription : private ::NonCopyable
160     {
161         PublisherAvahi *mPublisherAvahi;
162 
Subscriptionotbr::Mdns::PublisherAvahi::Subscription163         explicit Subscription(PublisherAvahi &aPublisherAvahi)
164             : mPublisherAvahi(&aPublisherAvahi)
165         {
166         }
167     };
168 
169     struct ServiceSubscription : public Subscription
170     {
ServiceSubscriptionotbr::Mdns::PublisherAvahi::ServiceSubscription171         explicit ServiceSubscription(PublisherAvahi &aPublisherAvahi, std::string aType, std::string aInstanceName)
172             : Subscription(aPublisherAvahi)
173             , mType(std::move(aType))
174             , mInstanceName(std::move(aInstanceName))
175             , mServiceBrowser(nullptr)
176         {
177         }
178 
~ServiceSubscriptionotbr::Mdns::PublisherAvahi::ServiceSubscription179         ~ServiceSubscription() { Release(); }
180 
181         void Release(void);
182         void Browse(void);
183         void Resolve(uint32_t           aInterfaceIndex,
184                      AvahiProtocol      aProtocol,
185                      const std::string &aInstanceName,
186                      const std::string &aType);
187         void AddServiceResolver(AvahiServiceResolver *aServiceResolver);
188         void RemoveServiceResolver(AvahiServiceResolver *aServiceResolver);
189 
190         static void HandleBrowseResult(AvahiServiceBrowser *  aServiceBrowser,
191                                        AvahiIfIndex           aInterfaceIndex,
192                                        AvahiProtocol          aProtocol,
193                                        AvahiBrowserEvent      aEvent,
194                                        const char *           aName,
195                                        const char *           aType,
196                                        const char *           aDomain,
197                                        AvahiLookupResultFlags aFlags,
198                                        void *                 aContext);
199 
200         void HandleBrowseResult(AvahiServiceBrowser *  aServiceBrowser,
201                                 AvahiIfIndex           aInterfaceIndex,
202                                 AvahiProtocol          aProtocol,
203                                 AvahiBrowserEvent      aEvent,
204                                 const char *           aName,
205                                 const char *           aType,
206                                 const char *           aDomain,
207                                 AvahiLookupResultFlags aFlags);
208 
209         static void HandleResolveResult(AvahiServiceResolver * aServiceResolver,
210                                         AvahiIfIndex           aInterfaceIndex,
211                                         AvahiProtocol          Protocol,
212                                         AvahiResolverEvent     aEvent,
213                                         const char *           aName,
214                                         const char *           aType,
215                                         const char *           aDomain,
216                                         const char *           aHostName,
217                                         const AvahiAddress *   aAddress,
218                                         uint16_t               aPort,
219                                         AvahiStringList *      aTxt,
220                                         AvahiLookupResultFlags aFlags,
221                                         void *                 aContext);
222 
223         void HandleResolveResult(AvahiServiceResolver * aServiceResolver,
224                                  AvahiIfIndex           aInterfaceIndex,
225                                  AvahiProtocol          Protocol,
226                                  AvahiResolverEvent     aEvent,
227                                  const char *           aName,
228                                  const char *           aType,
229                                  const char *           aDomain,
230                                  const char *           aHostName,
231                                  const AvahiAddress *   aAddress,
232                                  uint16_t               aPort,
233                                  AvahiStringList *      aTxt,
234                                  AvahiLookupResultFlags aFlags);
235 
236         std::string                      mType;
237         std::string                      mInstanceName;
238         AvahiServiceBrowser *            mServiceBrowser;
239         std::set<AvahiServiceResolver *> mServiceResolvers;
240     };
241 
242     struct HostSubscription : public Subscription
243     {
HostSubscriptionotbr::Mdns::PublisherAvahi::HostSubscription244         explicit HostSubscription(PublisherAvahi &aAvahiPublisher, std::string aHostName)
245             : Subscription(aAvahiPublisher)
246             , mHostName(std::move(aHostName))
247             , mRecordBrowser(nullptr)
248         {
249         }
250 
~HostSubscriptionotbr::Mdns::PublisherAvahi::HostSubscription251         ~HostSubscription() { Release(); }
252 
253         void        Release(void);
254         void        Resolve(void);
255         static void HandleResolveResult(AvahiRecordBrowser *   aRecordBrowser,
256                                         AvahiIfIndex           aInterfaceIndex,
257                                         AvahiProtocol          aProtocol,
258                                         AvahiBrowserEvent      aEvent,
259                                         const char *           aName,
260                                         uint16_t               aClazz,
261                                         uint16_t               aType,
262                                         const void *           aRdata,
263                                         size_t                 aSize,
264                                         AvahiLookupResultFlags aFlags,
265                                         void *                 aContext);
266 
267         void HandleResolveResult(AvahiRecordBrowser *   aRecordBrowser,
268                                  AvahiIfIndex           aInterfaceIndex,
269                                  AvahiProtocol          aProtocol,
270                                  AvahiBrowserEvent      aEvent,
271                                  const char *           aName,
272                                  uint16_t               aClazz,
273                                  uint16_t               aType,
274                                  const void *           aRdata,
275                                  size_t                 aSize,
276                                  AvahiLookupResultFlags aFlags);
277 
278         std::string         mHostName;
279         DiscoveredHostInfo  mHostInfo;
280         AvahiRecordBrowser *mRecordBrowser;
281     };
282 
283     typedef std::vector<std::unique_ptr<ServiceSubscription>> ServiceSubscriptionList;
284     typedef std::vector<std::unique_ptr<HostSubscription>>    HostSubscriptionList;
285 
286     static void HandleClientState(AvahiClient *aClient, AvahiClientState aState, void *aContext);
287     void        HandleClientState(AvahiClient *aClient, AvahiClientState aState);
288 
289     AvahiEntryGroup *CreateGroup(AvahiClient *aClient);
290     static void      ReleaseGroup(AvahiEntryGroup *aGroup);
291 
292     static void HandleGroupState(AvahiEntryGroup *aGroup, AvahiEntryGroupState aState, void *aContext);
293     void        HandleGroupState(AvahiEntryGroup *aGroup, AvahiEntryGroupState aState);
294     void        CallHostOrServiceCallback(AvahiEntryGroup *aGroup, otbrError aError);
295 
296     static otbrError TxtListToAvahiStringList(const TxtList &   aTxtList,
297                                               AvahiStringList * aBuffer,
298                                               size_t            aBufferSize,
299                                               AvahiStringList *&aHead);
300 
301     ServiceRegistration *FindServiceRegistration(const AvahiEntryGroup *aEntryGroup);
302     HostRegistration *   FindHostRegistration(const AvahiEntryGroup *aEntryGroup);
303 
304     AvahiClient *                mClient;
305     std::unique_ptr<AvahiPoller> mPoller;
306     State                        mState;
307     StateCallback                mStateCallback;
308 
309     ServiceSubscriptionList mSubscribedServices;
310     HostSubscriptionList    mSubscribedHosts;
311 };
312 
313 } // namespace Mdns
314 
315 } // namespace otbr
316 
317 /**
318  * @}
319  */
320 #endif // OTBR_AGENT_MDNS_AVAHI_HPP_
321