xref: /aosp_15_r20/external/ot-br-posix/src/android/mdns_publisher.hpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2024, 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 #ifndef OTBR_ANDROID_MDNS_PUBLISHER_HPP_
30 #define OTBR_ANDROID_MDNS_PUBLISHER_HPP_
31 
32 #include "mdns/mdns.hpp"
33 
34 #include <aidl/com/android/server/thread/openthread/BnNsdDiscoverServiceCallback.h>
35 #include <aidl/com/android/server/thread/openthread/BnNsdResolveHostCallback.h>
36 #include <aidl/com/android/server/thread/openthread/BnNsdResolveServiceCallback.h>
37 #include <aidl/com/android/server/thread/openthread/BnNsdStatusReceiver.h>
38 #include <aidl/com/android/server/thread/openthread/DnsTxtAttribute.h>
39 #include <aidl/com/android/server/thread/openthread/INsdPublisher.h>
40 #include <set>
41 
42 namespace otbr {
43 namespace Android {
44 using Status = ::ndk::ScopedAStatus;
45 using aidl::com::android::server::thread::openthread::BnNsdDiscoverServiceCallback;
46 using aidl::com::android::server::thread::openthread::BnNsdResolveHostCallback;
47 using aidl::com::android::server::thread::openthread::BnNsdResolveServiceCallback;
48 using aidl::com::android::server::thread::openthread::BnNsdStatusReceiver;
49 using aidl::com::android::server::thread::openthread::DnsTxtAttribute;
50 using aidl::com::android::server::thread::openthread::INsdPublisher;
51 
52 class MdnsPublisher : public Mdns::Publisher
53 {
54 public:
MdnsPublisher(Publisher::StateCallback aCallback)55     explicit MdnsPublisher(Publisher::StateCallback aCallback)
56         : mStateCallback(std::move(aCallback))
57         , mNextListenerId(0)
58 
59     {
60     }
61 
~MdnsPublisher(void)62     ~MdnsPublisher(void) { Stop(); }
63 
64     /** Sets the INsdPublisher which forwards the mDNS API requests to the NsdManager in system_server. */
65     void SetINsdPublisher(std::shared_ptr<INsdPublisher> aINsdPublisher);
66 
Start(void)67     otbrError Start(void) override { return OTBR_ERROR_NONE; }
68 
Stop(void)69     void Stop(void) override
70     {
71         mServiceRegistrations.clear();
72         mHostRegistrations.clear();
73         if (mNsdPublisher != nullptr)
74         {
75             mNsdPublisher->reset();
76         }
77     }
78 
IsStarted(void) const79     bool IsStarted(void) const override { return mNsdPublisher != nullptr; }
80 
81     void UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback) override;
82 
83     void UnpublishHost(const std::string &aName, ResultCallback &&aCallback) override;
84 
85     void UnpublishKey(const std::string &aName, ResultCallback &&aCallback) override;
86 
87     void SubscribeService(const std::string &aType, const std::string &aInstanceName) override;
88 
89     void UnsubscribeService(const std::string &aType, const std::string &aInstanceName) override;
90 
91     void SubscribeHost(const std::string &aHostName) override;
92 
93     void UnsubscribeHost(const std::string &aHostName) override;
94 
95     class NsdStatusReceiver : public BnNsdStatusReceiver
96     {
97     public:
NsdStatusReceiver(Mdns::Publisher::ResultCallback aCallback)98         explicit NsdStatusReceiver(Mdns::Publisher::ResultCallback aCallback)
99             : mCallback(std::move(aCallback))
100         {
101         }
102 
103         Status onSuccess(void) override;
104 
105         Status onError(int aError) override;
106 
107     private:
108         Mdns::Publisher::ResultCallback mCallback;
109     };
110 
111     struct ServiceResolver : private ::NonCopyable
112     {
ServiceResolverotbr::Android::MdnsPublisher::ServiceResolver113         explicit ServiceResolver(int aListenerId, std::shared_ptr<INsdPublisher> aNsdPublisher)
114             : mListenerId(aListenerId)
115             , mNsdPublisher(std::move(aNsdPublisher))
116         {
117         }
118 
~ServiceResolverotbr::Android::MdnsPublisher::ServiceResolver119         ~ServiceResolver(void)
120         {
121             if (mNsdPublisher)
122             {
123                 mNsdPublisher->stopServiceResolution(mListenerId);
124             }
125         }
126 
127         int                            mListenerId;
128         std::shared_ptr<INsdPublisher> mNsdPublisher;
129     };
130 
131     struct ServiceSubscription : public std::enable_shared_from_this<ServiceSubscription>, private ::NonCopyable
132     {
ServiceSubscriptionotbr::Android::MdnsPublisher::ServiceSubscription133         explicit ServiceSubscription(std::string                    aType,
134                                      std::string                    aName,
135                                      MdnsPublisher                 &aPublisher,
136                                      std::shared_ptr<INsdPublisher> aNsdPublisher)
137             : mType(std::move(aType))
138             , mName(std::move(aName))
139             , mPublisher(aPublisher)
140             , mNsdPublisher(std::move(aNsdPublisher))
141             , mBrowseListenerId(-1)
142         {
143         }
144 
~ServiceSubscriptionotbr::Android::MdnsPublisher::ServiceSubscription145         ~ServiceSubscription(void) { Release(); }
146 
147         void Release(void);
148         void Browse(void);
149         void Resolve(const std::string &aName, const std::string &aType);
150         void AddServiceResolver(const std::string &aName, ServiceResolver *aResolver);
151         void RemoveServiceResolver(const std::string &aInstanceName);
152 
153         std::string                    mType;
154         std::string                    mName;
155         MdnsPublisher                 &mPublisher;
156         std::shared_ptr<INsdPublisher> mNsdPublisher;
157         int32_t                        mBrowseListenerId;
158 
159         std::map<std::string, std::set<ServiceResolver *>> mResolvers;
160     };
161 
162     struct HostSubscription : private ::NonCopyable
163     {
HostSubscriptionotbr::Android::MdnsPublisher::HostSubscription164         explicit HostSubscription(std::string                    aName,
165                                   MdnsPublisher                 &aPublisher,
166                                   std::shared_ptr<INsdPublisher> aNsdPublisher,
167                                   int                            listenerId)
168             : mName(std::move(aName))
169             , mPublisher(aPublisher)
170             , mNsdPublisher(std::move(aNsdPublisher))
171             , mListenerId(listenerId)
172         {
173         }
174 
~HostSubscriptionotbr::Android::MdnsPublisher::HostSubscription175         ~HostSubscription(void) { Release(); }
176 
Releaseotbr::Android::MdnsPublisher::HostSubscription177         void Release(void) { mNsdPublisher->stopHostResolution(mListenerId); }
178 
179         std::string                    mName;
180         MdnsPublisher                 &mPublisher;
181         std::shared_ptr<INsdPublisher> mNsdPublisher;
182         const int32_t                  mListenerId;
183     };
184 
185     class NsdDiscoverServiceCallback : public BnNsdDiscoverServiceCallback
186     {
187     public:
NsdDiscoverServiceCallback(std::weak_ptr<ServiceSubscription> aSubscription)188         explicit NsdDiscoverServiceCallback(std::weak_ptr<ServiceSubscription> aSubscription)
189             : mSubscription(std::move(aSubscription))
190         {
191         }
192 
193         Status onServiceDiscovered(const std::string &aName, const std::string &aType, bool aIsFound);
194 
195     private:
196         std::weak_ptr<ServiceSubscription> mSubscription;
197     };
198 
199     class NsdResolveServiceCallback : public BnNsdResolveServiceCallback
200     {
201     public:
NsdResolveServiceCallback(std::weak_ptr<ServiceSubscription> aSubscription)202         explicit NsdResolveServiceCallback(std::weak_ptr<ServiceSubscription> aSubscription)
203             : mSubscription(std::move(aSubscription))
204         {
205         }
206 
207         Status onServiceResolved(const std::string                  &aHostname,
208                                  int                                 aNetifIndex,
209                                  const std::string                  &aName,
210                                  const std::string                  &aType,
211                                  int                                 aPort,
212                                  const std::vector<std::string>     &aAddresses,
213                                  const std::vector<DnsTxtAttribute> &aTxt,
214                                  int                                 aTtlSeconds);
215 
216     private:
217         std::weak_ptr<ServiceSubscription> mSubscription;
218     };
219 
220     class NsdResolveHostCallback : public BnNsdResolveHostCallback
221     {
222     public:
NsdResolveHostCallback(std::weak_ptr<HostSubscription> aSubscription)223         explicit NsdResolveHostCallback(std::weak_ptr<HostSubscription> aSubscription)
224             : mSubscription(std::move(aSubscription))
225         {
226         }
227 
228         Status onHostResolved(const std::string &aName, const std::vector<std::string> &aAddresses);
229 
230     private:
231         std::weak_ptr<HostSubscription> mSubscription;
232     };
233 
234 protected:
235     otbrError PublishServiceImpl(const std::string &aHostName,
236                                  const std::string &aName,
237                                  const std::string &aType,
238                                  const SubTypeList &aSubTypeList,
239                                  uint16_t           aPort,
240                                  const TxtData     &aTxtData,
241                                  ResultCallback   &&aCallback) override;
242 
243     otbrError PublishHostImpl(const std::string &aName, const AddressList &aAddresses, ResultCallback &&aCallback);
244 
245     otbrError PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) override;
246 
247     void OnServiceResolveFailedImpl(const std::string &aType, const std::string &aInstanceName, int32_t aErrorCode);
248 
249     void OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode);
250 
251     otbrError DnsErrorToOtbrError(int32_t aError);
252 
253 private:
254     class NsdServiceRegistration : public ServiceRegistration
255     {
256     public:
NsdServiceRegistration(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtData & aTxtData,ResultCallback && aCallback,MdnsPublisher * aPublisher,int32_t aListenerId,std::weak_ptr<INsdPublisher> aINsdPublisher)257         NsdServiceRegistration(const std::string           &aHostName,
258                                const std::string           &aName,
259                                const std::string           &aType,
260                                const SubTypeList           &aSubTypeList,
261                                uint16_t                     aPort,
262                                const TxtData               &aTxtData,
263                                ResultCallback             &&aCallback,
264                                MdnsPublisher               *aPublisher,
265                                int32_t                      aListenerId,
266                                std::weak_ptr<INsdPublisher> aINsdPublisher)
267             : ServiceRegistration(aHostName,
268                                   aName,
269                                   aType,
270                                   aSubTypeList,
271                                   aPort,
272                                   aTxtData,
273                                   std::move(aCallback),
274                                   aPublisher)
275             , mListenerId(aListenerId)
276             , mNsdPublisher(std::move(aINsdPublisher))
277 
278         {
279         }
280 
281         ~NsdServiceRegistration(void) override;
282 
283         const int32_t                      mListenerId;
284         std::shared_ptr<NsdStatusReceiver> mUnregisterReceiver;
285 
286     private:
287         std::weak_ptr<INsdPublisher> mNsdPublisher;
288     };
289 
290     class NsdHostRegistration : public HostRegistration
291     {
292     public:
NsdHostRegistration(const std::string & aName,const AddressList & aAddresses,ResultCallback && aCallback,MdnsPublisher * aPublisher,int32_t aListenerId,std::weak_ptr<INsdPublisher> aINsdPublisher)293         NsdHostRegistration(const std::string           &aName,
294                             const AddressList           &aAddresses,
295                             ResultCallback             &&aCallback,
296                             MdnsPublisher               *aPublisher,
297                             int32_t                      aListenerId,
298                             std::weak_ptr<INsdPublisher> aINsdPublisher)
299             : HostRegistration(aName, aAddresses, std::move(aCallback), aPublisher)
300             , mListenerId(aListenerId)
301             , mNsdPublisher(aINsdPublisher)
302         {
303         }
304 
305         ~NsdHostRegistration(void) override;
306 
307         const int32_t                      mListenerId;
308         std::shared_ptr<NsdStatusReceiver> mUnregisterReceiver;
309 
310     private:
311         std::weak_ptr<INsdPublisher> mNsdPublisher;
312     };
313 
314     typedef std::vector<std::shared_ptr<ServiceSubscription>> ServiceSubscriptionList;
315     typedef std::vector<std::shared_ptr<HostSubscription>>    HostSubscriptionList;
316 
317     static constexpr int kDefaultResolvedTtl = 10;
318     static constexpr int kMinResolvedTtl     = 1;
319     static constexpr int kMaxResolvedTtl     = 10;
320 
321     int32_t AllocateListenerId(void);
322 
323     StateCallback                  mStateCallback;
324     int32_t                        mNextListenerId;
325     std::shared_ptr<INsdPublisher> mNsdPublisher = nullptr;
326     ServiceSubscriptionList        mServiceSubscriptions;
327     HostSubscriptionList           mHostSubscriptions;
328 };
329 
330 } // namespace Android
331 } // namespace otbr
332 
333 #endif // OTBR_ANDROID_MDNS_PUBLISHER_HPP_
334