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