• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2025, 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 implementation of OpenThread DNS-SD platform APIs on the posix platform.
32  */
33 
34 #define OTBR_LOG_TAG "DNSSD"
35 
36 #include "host/posix/dnssd.hpp"
37 
38 #include <string>
39 
40 #include <openthread/platform/dnssd.h>
41 
42 #include "common/code_utils.hpp"
43 #include "common/logging.hpp"
44 #include "common/types.hpp"
45 
MakeRegisterCallback(otInstance * aInstance,otPlatDnssdRegisterCallback aCallback)46 static otbr::DnssdPlatform::RegisterCallback MakeRegisterCallback(otInstance                 *aInstance,
47                                                                   otPlatDnssdRegisterCallback aCallback)
48 {
49     return [aInstance, aCallback](otPlatDnssdRequestId aRequestId, otError aError) {
50         if (aCallback)
51         {
52             aCallback(aInstance, aRequestId, aError);
53         }
54     };
55 }
56 
otPlatDnssdGetState(otInstance * aInstance)57 extern "C" otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance)
58 {
59     OTBR_UNUSED_VARIABLE(aInstance);
60 
61     return otbr::DnssdPlatform::Get().GetState();
62 }
63 
otPlatDnssdRegisterService(otInstance * aInstance,const otPlatDnssdService * aService,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)64 extern "C" void otPlatDnssdRegisterService(otInstance                 *aInstance,
65                                            const otPlatDnssdService   *aService,
66                                            otPlatDnssdRequestId        aRequestId,
67                                            otPlatDnssdRegisterCallback aCallback)
68 {
69     OTBR_UNUSED_VARIABLE(aInstance);
70 
71     otbr::DnssdPlatform::Get().RegisterService(*aService, aRequestId, MakeRegisterCallback(aInstance, aCallback));
72 }
73 
otPlatDnssdUnregisterService(otInstance * aInstance,const otPlatDnssdService * aService,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)74 extern "C" void otPlatDnssdUnregisterService(otInstance                 *aInstance,
75                                              const otPlatDnssdService   *aService,
76                                              otPlatDnssdRequestId        aRequestId,
77                                              otPlatDnssdRegisterCallback aCallback)
78 {
79     OTBR_UNUSED_VARIABLE(aInstance);
80 
81     otbr::DnssdPlatform::Get().UnregisterService(*aService, aRequestId, MakeRegisterCallback(aInstance, aCallback));
82 }
83 
otPlatDnssdRegisterHost(otInstance * aInstance,const otPlatDnssdHost * aHost,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)84 extern "C" void otPlatDnssdRegisterHost(otInstance                 *aInstance,
85                                         const otPlatDnssdHost      *aHost,
86                                         otPlatDnssdRequestId        aRequestId,
87                                         otPlatDnssdRegisterCallback aCallback)
88 {
89     OTBR_UNUSED_VARIABLE(aInstance);
90 
91     otbr::DnssdPlatform::Get().RegisterHost(*aHost, aRequestId, MakeRegisterCallback(aInstance, aCallback));
92 }
93 
otPlatDnssdUnregisterHost(otInstance * aInstance,const otPlatDnssdHost * aHost,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)94 extern "C" void otPlatDnssdUnregisterHost(otInstance                 *aInstance,
95                                           const otPlatDnssdHost      *aHost,
96                                           otPlatDnssdRequestId        aRequestId,
97                                           otPlatDnssdRegisterCallback aCallback)
98 {
99     OTBR_UNUSED_VARIABLE(aInstance);
100 
101     otbr::DnssdPlatform::Get().UnregisterHost(*aHost, aRequestId, MakeRegisterCallback(aInstance, aCallback));
102 }
103 
otPlatDnssdRegisterKey(otInstance * aInstance,const otPlatDnssdKey * aKey,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)104 extern "C" void otPlatDnssdRegisterKey(otInstance                 *aInstance,
105                                        const otPlatDnssdKey       *aKey,
106                                        otPlatDnssdRequestId        aRequestId,
107                                        otPlatDnssdRegisterCallback aCallback)
108 {
109     OTBR_UNUSED_VARIABLE(aInstance);
110 
111     otbr::DnssdPlatform::Get().RegisterKey(*aKey, aRequestId, MakeRegisterCallback(aInstance, aCallback));
112 }
113 
otPlatDnssdUnregisterKey(otInstance * aInstance,const otPlatDnssdKey * aKey,otPlatDnssdRequestId aRequestId,otPlatDnssdRegisterCallback aCallback)114 extern "C" void otPlatDnssdUnregisterKey(otInstance                 *aInstance,
115                                          const otPlatDnssdKey       *aKey,
116                                          otPlatDnssdRequestId        aRequestId,
117                                          otPlatDnssdRegisterCallback aCallback)
118 {
119     OTBR_UNUSED_VARIABLE(aInstance);
120 
121     otbr::DnssdPlatform::Get().UnregisterKey(*aKey, aRequestId, MakeRegisterCallback(aInstance, aCallback));
122 }
123 
otPlatDnssdStartBrowser(otInstance * aInstance,const otPlatDnssdBrowser * aBrowser)124 extern "C" void otPlatDnssdStartBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser)
125 {
126     OTBR_UNUSED_VARIABLE(aInstance);
127     OTBR_UNUSED_VARIABLE(aBrowser);
128 }
129 
otPlatDnssdStopBrowser(otInstance * aInstance,const otPlatDnssdBrowser * aBrowser)130 extern "C" void otPlatDnssdStopBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser)
131 {
132     OTBR_UNUSED_VARIABLE(aInstance);
133     OTBR_UNUSED_VARIABLE(aBrowser);
134 }
135 
otPlatDnssdStartSrvResolver(otInstance * aInstance,const otPlatDnssdSrvResolver * aResolver)136 extern "C" void otPlatDnssdStartSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver)
137 {
138     OTBR_UNUSED_VARIABLE(aInstance);
139     OTBR_UNUSED_VARIABLE(aResolver);
140 }
141 
otPlatDnssdStopSrvResolver(otInstance * aInstance,const otPlatDnssdSrvResolver * aResolver)142 extern "C" void otPlatDnssdStopSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver)
143 {
144     OTBR_UNUSED_VARIABLE(aInstance);
145     OTBR_UNUSED_VARIABLE(aResolver);
146 }
147 
otPlatDnssdStartTxtResolver(otInstance * aInstance,const otPlatDnssdTxtResolver * aResolver)148 extern "C" void otPlatDnssdStartTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver)
149 {
150     OTBR_UNUSED_VARIABLE(aInstance);
151     OTBR_UNUSED_VARIABLE(aResolver);
152 }
153 
otPlatDnssdStopTxtResolver(otInstance * aInstance,const otPlatDnssdTxtResolver * aResolver)154 extern "C" void otPlatDnssdStopTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver)
155 {
156     OTBR_UNUSED_VARIABLE(aInstance);
157     OTBR_UNUSED_VARIABLE(aResolver);
158 }
159 
otPlatDnssdStartIp6AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)160 extern "C" void otPlatDnssdStartIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
161 {
162     OTBR_UNUSED_VARIABLE(aInstance);
163     OTBR_UNUSED_VARIABLE(aResolver);
164 }
165 
otPlatDnssdStopIp6AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)166 extern "C" void otPlatDnssdStopIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
167 {
168     OTBR_UNUSED_VARIABLE(aInstance);
169     OTBR_UNUSED_VARIABLE(aResolver);
170 }
171 
otPlatDnssdStartIp4AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)172 void otPlatDnssdStartIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
173 {
174     OTBR_UNUSED_VARIABLE(aInstance);
175     OTBR_UNUSED_VARIABLE(aResolver);
176 }
177 
otPlatDnssdStopIp4AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)178 void otPlatDnssdStopIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
179 {
180     OTBR_UNUSED_VARIABLE(aInstance);
181     OTBR_UNUSED_VARIABLE(aResolver);
182 }
183 
184 //----------------------------------------------------------------------------------------------------------------------
185 
186 namespace otbr {
187 
188 DnssdPlatform *DnssdPlatform::sDnssdPlatform = nullptr;
189 
DnssdPlatform(Mdns::Publisher & aPublisher)190 DnssdPlatform::DnssdPlatform(Mdns::Publisher &aPublisher)
191     : mPublisher(aPublisher)
192     , mState(kStateStopped)
193     , mRunning(false)
194     , mPublisherState(Mdns::Publisher::State::kIdle)
195 {
196     sDnssdPlatform = this;
197 }
198 
Start(void)199 void DnssdPlatform::Start(void)
200 {
201     if (!mRunning)
202     {
203         mRunning = true;
204         UpdateState();
205     }
206 }
207 
Stop(void)208 void DnssdPlatform::Stop(void)
209 {
210     if (mRunning)
211     {
212         mRunning = false;
213         UpdateState();
214     }
215 }
216 
UpdateState(void)217 void DnssdPlatform::UpdateState(void)
218 {
219     if (mRunning && (mPublisherState == Mdns::Publisher::State::kReady))
220     {
221         VerifyOrExit(mState != kStateReady);
222 
223         mState = kStateReady;
224     }
225     else
226     {
227         VerifyOrExit(mState != kStateStopped);
228 
229         mState = kStateStopped;
230     }
231 
232     if (mStateChangeCallback)
233     {
234         mStateChangeCallback(mState);
235     }
236 
237 exit:
238     return;
239 }
240 
MakePublisherCallback(RequestId aRequestId,RegisterCallback aCallback)241 Mdns::Publisher::ResultCallback DnssdPlatform::MakePublisherCallback(RequestId aRequestId, RegisterCallback aCallback)
242 {
243     return [aRequestId, aCallback](otbrError aError) {
244         if (aCallback != nullptr)
245         {
246             aCallback(aRequestId, OtbrErrorToOtError(aError));
247         }
248     };
249 }
250 
SetDnssdStateChangedCallback(DnssdStateChangeCallback aCallback)251 void DnssdPlatform::SetDnssdStateChangedCallback(DnssdStateChangeCallback aCallback)
252 {
253     mStateChangeCallback = aCallback;
254 }
255 
RegisterService(const Service & aService,RequestId aRequestId,RegisterCallback aCallback)256 void DnssdPlatform::RegisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback)
257 {
258     Mdns::Publisher::SubTypeList subTypeList;
259     Mdns::Publisher::TxtData     txtData(aService.mTxtData, aService.mTxtData + aService.mTxtDataLength);
260 
261     for (uint16_t index = 0; index < aService.mSubTypeLabelsLength; index++)
262     {
263         subTypeList.push_back(aService.mSubTypeLabels[index]);
264     }
265 
266     mPublisher.PublishService(aService.mHostName, aService.mServiceInstance, aService.mServiceType, subTypeList,
267                               aService.mPort, txtData, MakePublisherCallback(aRequestId, aCallback));
268 }
269 
UnregisterService(const Service & aService,RequestId aRequestId,RegisterCallback aCallback)270 void DnssdPlatform::UnregisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback)
271 {
272     mPublisher.UnpublishService(aService.mServiceInstance, aService.mServiceType,
273                                 MakePublisherCallback(aRequestId, aCallback));
274 }
275 
RegisterHost(const Host & aHost,RequestId aRequestId,RegisterCallback aCallback)276 void DnssdPlatform::RegisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback)
277 {
278     Mdns::Publisher::AddressList addressList;
279 
280     for (uint16_t index = 0; index < aHost.mAddressesLength; index++)
281     {
282         addressList.push_back(Ip6Address(aHost.mAddresses[index].mFields.m8));
283     }
284 
285     mPublisher.PublishHost(aHost.mHostName, addressList, MakePublisherCallback(aRequestId, aCallback));
286 }
287 
UnregisterHost(const Host & aHost,RequestId aRequestId,RegisterCallback aCallback)288 void DnssdPlatform::UnregisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback)
289 {
290     mPublisher.UnpublishHost(aHost.mHostName, MakePublisherCallback(aRequestId, aCallback));
291 }
292 
KeyNameFor(const Key & aKey)293 std::string DnssdPlatform::KeyNameFor(const Key &aKey)
294 {
295     std::string name(aKey.mName);
296 
297     if (aKey.mServiceType != nullptr)
298     {
299         // TODO: current code would not work with service instance labels that include a '.'
300         name += ".";
301         name += aKey.mServiceType;
302     }
303 
304     return name;
305 }
306 
RegisterKey(const Key & aKey,RequestId aRequestId,RegisterCallback aCallback)307 void DnssdPlatform::RegisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback)
308 {
309     Mdns::Publisher::KeyData keyData(aKey.mKeyData, aKey.mKeyData + aKey.mKeyDataLength);
310 
311     mPublisher.PublishKey(KeyNameFor(aKey), keyData, MakePublisherCallback(aRequestId, aCallback));
312 }
313 
UnregisterKey(const Key & aKey,RequestId aRequestId,RegisterCallback aCallback)314 void DnssdPlatform::UnregisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback)
315 {
316     mPublisher.UnpublishKey(KeyNameFor(aKey), MakePublisherCallback(aRequestId, aCallback));
317 }
318 
HandleMdnsState(Mdns::Publisher::State aState)319 void DnssdPlatform::HandleMdnsState(Mdns::Publisher::State aState)
320 {
321     if (mPublisherState != aState)
322     {
323         mPublisherState = aState;
324         UpdateState();
325     }
326 }
327 
328 } // namespace otbr
329