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 : 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(ServiceSubscription & aSubscription)188 explicit NsdDiscoverServiceCallback(ServiceSubscription &aSubscription) 189 : mSubscription(aSubscription) 190 { 191 } 192 193 Status onServiceDiscovered(const std::string &aName, const std::string &aType, bool aIsFound); 194 195 private: 196 ServiceSubscription &mSubscription; 197 }; 198 199 class NsdResolveServiceCallback : public BnNsdResolveServiceCallback 200 { 201 public: NsdResolveServiceCallback(ServiceSubscription & aSubscription)202 explicit NsdResolveServiceCallback(ServiceSubscription &aSubscription) 203 : mSubscription(aSubscription) 204 { 205 } 206 207 Status onServiceResolved(const std::string &aHostname, 208 const std::string &aName, 209 const std::string &aType, 210 int aPort, 211 const std::vector<std::string> &aAddresses, 212 const std::vector<DnsTxtAttribute> &aTxt, 213 int aTtlSeconds); 214 215 private: 216 ServiceSubscription &mSubscription; 217 }; 218 219 class NsdResolveHostCallback : public BnNsdResolveHostCallback 220 { 221 public: NsdResolveHostCallback(HostSubscription & aSubscription)222 explicit NsdResolveHostCallback(HostSubscription &aSubscription) 223 : mSubscription(aSubscription) 224 { 225 } 226 227 Status onHostResolved(const std::string &aName, const std::vector<std::string> &aAddresses); 228 229 private: 230 HostSubscription &mSubscription; 231 }; 232 233 protected: 234 otbrError PublishServiceImpl(const std::string &aHostName, 235 const std::string &aName, 236 const std::string &aType, 237 const SubTypeList &aSubTypeList, 238 uint16_t aPort, 239 const TxtData &aTxtData, 240 ResultCallback &&aCallback) override; 241 242 otbrError PublishHostImpl(const std::string &aName, const AddressList &aAddresses, ResultCallback &&aCallback); 243 244 otbrError PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback) override; 245 246 void OnServiceResolveFailedImpl(const std::string &aType, const std::string &aInstanceName, int32_t aErrorCode); 247 248 void OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode); 249 250 otbrError DnsErrorToOtbrError(int32_t aError); 251 252 private: 253 class NsdServiceRegistration : public ServiceRegistration 254 { 255 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)256 NsdServiceRegistration(const std::string &aHostName, 257 const std::string &aName, 258 const std::string &aType, 259 const SubTypeList &aSubTypeList, 260 uint16_t aPort, 261 const TxtData &aTxtData, 262 ResultCallback &&aCallback, 263 MdnsPublisher *aPublisher, 264 int32_t aListenerId, 265 std::weak_ptr<INsdPublisher> aINsdPublisher) 266 : ServiceRegistration(aHostName, 267 aName, 268 aType, 269 aSubTypeList, 270 aPort, 271 aTxtData, 272 std::move(aCallback), 273 aPublisher) 274 , mListenerId(aListenerId) 275 , mNsdPublisher(std::move(aINsdPublisher)) 276 277 { 278 } 279 280 ~NsdServiceRegistration(void) override; 281 282 const int32_t mListenerId; 283 std::shared_ptr<NsdStatusReceiver> mUnregisterReceiver; 284 285 private: 286 std::weak_ptr<INsdPublisher> mNsdPublisher; 287 }; 288 289 class NsdHostRegistration : public HostRegistration 290 { 291 public: NsdHostRegistration(const std::string & aName,const AddressList & aAddresses,ResultCallback && aCallback,MdnsPublisher * aPublisher,int32_t aListenerId,std::weak_ptr<INsdPublisher> aINsdPublisher)292 NsdHostRegistration(const std::string &aName, 293 const AddressList &aAddresses, 294 ResultCallback &&aCallback, 295 MdnsPublisher *aPublisher, 296 int32_t aListenerId, 297 std::weak_ptr<INsdPublisher> aINsdPublisher) 298 : HostRegistration(aName, aAddresses, std::move(aCallback), aPublisher) 299 , mListenerId(aListenerId) 300 , mNsdPublisher(aINsdPublisher) 301 { 302 } 303 304 ~NsdHostRegistration(void) override; 305 306 const int32_t mListenerId; 307 std::shared_ptr<NsdStatusReceiver> mUnregisterReceiver; 308 309 private: 310 std::weak_ptr<INsdPublisher> mNsdPublisher; 311 }; 312 313 typedef std::vector<std::unique_ptr<ServiceSubscription>> ServiceSubscriptionList; 314 typedef std::vector<std::unique_ptr<HostSubscription>> HostSubscriptionList; 315 316 static constexpr int kDefaultResolvedTtl = 10; 317 static constexpr int kMinResolvedTtl = 1; 318 static constexpr int kMaxResolvedTtl = 10; 319 320 int32_t AllocateListenerId(void); 321 322 StateCallback mStateCallback; 323 int32_t mNextListenerId; 324 std::shared_ptr<INsdPublisher> mNsdPublisher = nullptr; 325 ServiceSubscriptionList mServiceSubscriptions; 326 HostSubscriptionList mHostSubscriptions; 327 }; 328 329 } // namespace Android 330 } // namespace otbr 331 332 #endif // OTBR_ANDROID_MDNS_PUBLISHER_HPP_ 333