xref: /aosp_15_r20/external/ot-br-posix/src/sdp_proxy/advertising_proxy.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker  *    Copyright (c) 2020, The OpenThread Authors.
3*4a64e381SAndroid Build Coastguard Worker  *    All rights reserved.
4*4a64e381SAndroid Build Coastguard Worker  *
5*4a64e381SAndroid Build Coastguard Worker  *    Redistribution and use in source and binary forms, with or without
6*4a64e381SAndroid Build Coastguard Worker  *    modification, are permitted provided that the following conditions are met:
7*4a64e381SAndroid Build Coastguard Worker  *    1. Redistributions of source code must retain the above copyright
8*4a64e381SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer.
9*4a64e381SAndroid Build Coastguard Worker  *    2. Redistributions in binary form must reproduce the above copyright
10*4a64e381SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer in the
11*4a64e381SAndroid Build Coastguard Worker  *       documentation and/or other materials provided with the distribution.
12*4a64e381SAndroid Build Coastguard Worker  *    3. Neither the name of the copyright holder nor the
13*4a64e381SAndroid Build Coastguard Worker  *       names of its contributors may be used to endorse or promote products
14*4a64e381SAndroid Build Coastguard Worker  *       derived from this software without specific prior written permission.
15*4a64e381SAndroid Build Coastguard Worker  *
16*4a64e381SAndroid Build Coastguard Worker  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*4a64e381SAndroid Build Coastguard Worker  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*4a64e381SAndroid Build Coastguard Worker  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*4a64e381SAndroid Build Coastguard Worker  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*4a64e381SAndroid Build Coastguard Worker  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*4a64e381SAndroid Build Coastguard Worker  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*4a64e381SAndroid Build Coastguard Worker  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*4a64e381SAndroid Build Coastguard Worker  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*4a64e381SAndroid Build Coastguard Worker  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*4a64e381SAndroid Build Coastguard Worker  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*4a64e381SAndroid Build Coastguard Worker  *    POSSIBILITY OF SUCH DAMAGE.
27*4a64e381SAndroid Build Coastguard Worker  */
28*4a64e381SAndroid Build Coastguard Worker 
29*4a64e381SAndroid Build Coastguard Worker /**
30*4a64e381SAndroid Build Coastguard Worker  * @file
31*4a64e381SAndroid Build Coastguard Worker  *   The file implements the Advertising Proxy.
32*4a64e381SAndroid Build Coastguard Worker  */
33*4a64e381SAndroid Build Coastguard Worker 
34*4a64e381SAndroid Build Coastguard Worker #define OTBR_LOG_TAG "ADPROXY"
35*4a64e381SAndroid Build Coastguard Worker 
36*4a64e381SAndroid Build Coastguard Worker #include "sdp_proxy/advertising_proxy.hpp"
37*4a64e381SAndroid Build Coastguard Worker 
38*4a64e381SAndroid Build Coastguard Worker #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
39*4a64e381SAndroid Build Coastguard Worker 
40*4a64e381SAndroid Build Coastguard Worker #if !OTBR_ENABLE_MDNS_AVAHI && !OTBR_ENABLE_MDNS_MDNSSD && !OTBR_ENABLE_MDNS_MOJO
41*4a64e381SAndroid Build Coastguard Worker #error "The Advertising Proxy requires OTBR_ENABLE_MDNS_AVAHI, OTBR_ENABLE_MDNS_MDNSSD or OTBR_ENABLE_MDNS_MOJO"
42*4a64e381SAndroid Build Coastguard Worker #endif
43*4a64e381SAndroid Build Coastguard Worker 
44*4a64e381SAndroid Build Coastguard Worker #include <string>
45*4a64e381SAndroid Build Coastguard Worker 
46*4a64e381SAndroid Build Coastguard Worker #include <assert.h>
47*4a64e381SAndroid Build Coastguard Worker 
48*4a64e381SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
49*4a64e381SAndroid Build Coastguard Worker #include "common/dns_utils.hpp"
50*4a64e381SAndroid Build Coastguard Worker #include "common/logging.hpp"
51*4a64e381SAndroid Build Coastguard Worker 
52*4a64e381SAndroid Build Coastguard Worker namespace otbr {
53*4a64e381SAndroid Build Coastguard Worker 
AdvertisingProxy(Ncp::RcpHost & aHost,Mdns::Publisher & aPublisher)54*4a64e381SAndroid Build Coastguard Worker AdvertisingProxy::AdvertisingProxy(Ncp::RcpHost &aHost, Mdns::Publisher &aPublisher)
55*4a64e381SAndroid Build Coastguard Worker     : mHost(aHost)
56*4a64e381SAndroid Build Coastguard Worker     , mPublisher(aPublisher)
57*4a64e381SAndroid Build Coastguard Worker     , mIsEnabled(false)
58*4a64e381SAndroid Build Coastguard Worker {
59*4a64e381SAndroid Build Coastguard Worker     mHost.RegisterResetHandler(
60*4a64e381SAndroid Build Coastguard Worker         [this]() { otSrpServerSetServiceUpdateHandler(GetInstance(), AdvertisingHandler, this); });
61*4a64e381SAndroid Build Coastguard Worker }
62*4a64e381SAndroid Build Coastguard Worker 
SetEnabled(bool aIsEnabled)63*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::SetEnabled(bool aIsEnabled)
64*4a64e381SAndroid Build Coastguard Worker {
65*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aIsEnabled != IsEnabled());
66*4a64e381SAndroid Build Coastguard Worker     mIsEnabled = aIsEnabled;
67*4a64e381SAndroid Build Coastguard Worker     if (mIsEnabled)
68*4a64e381SAndroid Build Coastguard Worker     {
69*4a64e381SAndroid Build Coastguard Worker         Start();
70*4a64e381SAndroid Build Coastguard Worker     }
71*4a64e381SAndroid Build Coastguard Worker     else
72*4a64e381SAndroid Build Coastguard Worker     {
73*4a64e381SAndroid Build Coastguard Worker         Stop();
74*4a64e381SAndroid Build Coastguard Worker     }
75*4a64e381SAndroid Build Coastguard Worker 
76*4a64e381SAndroid Build Coastguard Worker exit:
77*4a64e381SAndroid Build Coastguard Worker     return;
78*4a64e381SAndroid Build Coastguard Worker }
79*4a64e381SAndroid Build Coastguard Worker 
Start(void)80*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::Start(void)
81*4a64e381SAndroid Build Coastguard Worker {
82*4a64e381SAndroid Build Coastguard Worker     otSrpServerSetServiceUpdateHandler(GetInstance(), AdvertisingHandler, this);
83*4a64e381SAndroid Build Coastguard Worker 
84*4a64e381SAndroid Build Coastguard Worker     otbrLogInfo("Started");
85*4a64e381SAndroid Build Coastguard Worker }
86*4a64e381SAndroid Build Coastguard Worker 
Stop(void)87*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::Stop(void)
88*4a64e381SAndroid Build Coastguard Worker {
89*4a64e381SAndroid Build Coastguard Worker     // Outstanding updates will fail on the SRP server because of timeout.
90*4a64e381SAndroid Build Coastguard Worker     // TODO: handle this case gracefully.
91*4a64e381SAndroid Build Coastguard Worker 
92*4a64e381SAndroid Build Coastguard Worker     // Stop receiving SRP server events.
93*4a64e381SAndroid Build Coastguard Worker     if (GetInstance() != nullptr)
94*4a64e381SAndroid Build Coastguard Worker     {
95*4a64e381SAndroid Build Coastguard Worker         otSrpServerSetServiceUpdateHandler(GetInstance(), nullptr, nullptr);
96*4a64e381SAndroid Build Coastguard Worker     }
97*4a64e381SAndroid Build Coastguard Worker 
98*4a64e381SAndroid Build Coastguard Worker     otbrLogInfo("Stopped");
99*4a64e381SAndroid Build Coastguard Worker }
100*4a64e381SAndroid Build Coastguard Worker 
AdvertisingHandler(otSrpServerServiceUpdateId aId,const otSrpServerHost * aHost,uint32_t aTimeout,void * aContext)101*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::AdvertisingHandler(otSrpServerServiceUpdateId aId,
102*4a64e381SAndroid Build Coastguard Worker                                           const otSrpServerHost     *aHost,
103*4a64e381SAndroid Build Coastguard Worker                                           uint32_t                   aTimeout,
104*4a64e381SAndroid Build Coastguard Worker                                           void                      *aContext)
105*4a64e381SAndroid Build Coastguard Worker {
106*4a64e381SAndroid Build Coastguard Worker     static_cast<AdvertisingProxy *>(aContext)->AdvertisingHandler(aId, aHost, aTimeout);
107*4a64e381SAndroid Build Coastguard Worker }
108*4a64e381SAndroid Build Coastguard Worker 
AdvertisingHandler(otSrpServerServiceUpdateId aId,const otSrpServerHost * aHost,uint32_t aTimeout)109*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::AdvertisingHandler(otSrpServerServiceUpdateId aId,
110*4a64e381SAndroid Build Coastguard Worker                                           const otSrpServerHost     *aHost,
111*4a64e381SAndroid Build Coastguard Worker                                           uint32_t                   aTimeout)
112*4a64e381SAndroid Build Coastguard Worker {
113*4a64e381SAndroid Build Coastguard Worker     OTBR_UNUSED_VARIABLE(aTimeout);
114*4a64e381SAndroid Build Coastguard Worker 
115*4a64e381SAndroid Build Coastguard Worker     OutstandingUpdate *update = nullptr;
116*4a64e381SAndroid Build Coastguard Worker     otbrError          error  = OTBR_ERROR_NONE;
117*4a64e381SAndroid Build Coastguard Worker 
118*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(IsEnabled());
119*4a64e381SAndroid Build Coastguard Worker 
120*4a64e381SAndroid Build Coastguard Worker     mOutstandingUpdates.emplace_back();
121*4a64e381SAndroid Build Coastguard Worker     update      = &mOutstandingUpdates.back();
122*4a64e381SAndroid Build Coastguard Worker     update->mId = aId;
123*4a64e381SAndroid Build Coastguard Worker 
124*4a64e381SAndroid Build Coastguard Worker     error = PublishHostAndItsServices(aHost, update);
125*4a64e381SAndroid Build Coastguard Worker 
126*4a64e381SAndroid Build Coastguard Worker     if (error != OTBR_ERROR_NONE || update->mCallbackCount == 0)
127*4a64e381SAndroid Build Coastguard Worker     {
128*4a64e381SAndroid Build Coastguard Worker         mOutstandingUpdates.pop_back();
129*4a64e381SAndroid Build Coastguard Worker         otSrpServerHandleServiceUpdateResult(GetInstance(), aId, OtbrErrorToOtError(error));
130*4a64e381SAndroid Build Coastguard Worker     }
131*4a64e381SAndroid Build Coastguard Worker 
132*4a64e381SAndroid Build Coastguard Worker exit:
133*4a64e381SAndroid Build Coastguard Worker     return;
134*4a64e381SAndroid Build Coastguard Worker }
135*4a64e381SAndroid Build Coastguard Worker 
OnMdnsPublishResult(otSrpServerServiceUpdateId aUpdateId,otbrError aError)136*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::OnMdnsPublishResult(otSrpServerServiceUpdateId aUpdateId, otbrError aError)
137*4a64e381SAndroid Build Coastguard Worker {
138*4a64e381SAndroid Build Coastguard Worker     for (auto update = mOutstandingUpdates.begin(); update != mOutstandingUpdates.end(); ++update)
139*4a64e381SAndroid Build Coastguard Worker     {
140*4a64e381SAndroid Build Coastguard Worker         if (update->mId != aUpdateId)
141*4a64e381SAndroid Build Coastguard Worker         {
142*4a64e381SAndroid Build Coastguard Worker             continue;
143*4a64e381SAndroid Build Coastguard Worker         }
144*4a64e381SAndroid Build Coastguard Worker 
145*4a64e381SAndroid Build Coastguard Worker         if (aError != OTBR_ERROR_NONE || update->mCallbackCount == 1)
146*4a64e381SAndroid Build Coastguard Worker         {
147*4a64e381SAndroid Build Coastguard Worker             // Erase before notifying OpenThread, because there are chances that new
148*4a64e381SAndroid Build Coastguard Worker             // elements may be added to `otSrpServerHandleServiceUpdateResult` and
149*4a64e381SAndroid Build Coastguard Worker             // the iterator will be invalidated.
150*4a64e381SAndroid Build Coastguard Worker             mOutstandingUpdates.erase(update);
151*4a64e381SAndroid Build Coastguard Worker             otSrpServerHandleServiceUpdateResult(GetInstance(), aUpdateId, OtbrErrorToOtError(aError));
152*4a64e381SAndroid Build Coastguard Worker         }
153*4a64e381SAndroid Build Coastguard Worker         else
154*4a64e381SAndroid Build Coastguard Worker         {
155*4a64e381SAndroid Build Coastguard Worker             --update->mCallbackCount;
156*4a64e381SAndroid Build Coastguard Worker             otbrLogInfo("Waiting for more publishing callbacks %d", update->mCallbackCount);
157*4a64e381SAndroid Build Coastguard Worker         }
158*4a64e381SAndroid Build Coastguard Worker         break;
159*4a64e381SAndroid Build Coastguard Worker     }
160*4a64e381SAndroid Build Coastguard Worker }
161*4a64e381SAndroid Build Coastguard Worker 
GetEligibleAddresses(const otIp6Address * aHostAddresses,uint8_t aHostAddressNum)162*4a64e381SAndroid Build Coastguard Worker std::vector<Ip6Address> AdvertisingProxy::GetEligibleAddresses(const otIp6Address *aHostAddresses,
163*4a64e381SAndroid Build Coastguard Worker                                                                uint8_t             aHostAddressNum)
164*4a64e381SAndroid Build Coastguard Worker {
165*4a64e381SAndroid Build Coastguard Worker     std::vector<Ip6Address> addresses;
166*4a64e381SAndroid Build Coastguard Worker     const otIp6Address     *meshLocalEid = otThreadGetMeshLocalEid(GetInstance());
167*4a64e381SAndroid Build Coastguard Worker 
168*4a64e381SAndroid Build Coastguard Worker     addresses.reserve(aHostAddressNum);
169*4a64e381SAndroid Build Coastguard Worker     for (size_t i = 0; i < aHostAddressNum; ++i)
170*4a64e381SAndroid Build Coastguard Worker     {
171*4a64e381SAndroid Build Coastguard Worker         Ip6Address address(aHostAddresses[i].mFields.m8);
172*4a64e381SAndroid Build Coastguard Worker 
173*4a64e381SAndroid Build Coastguard Worker         if (otIp6PrefixMatch(meshLocalEid, &aHostAddresses[i]) >= OT_IP6_PREFIX_BITSIZE)
174*4a64e381SAndroid Build Coastguard Worker         {
175*4a64e381SAndroid Build Coastguard Worker             continue;
176*4a64e381SAndroid Build Coastguard Worker         }
177*4a64e381SAndroid Build Coastguard Worker         if (address.IsLinkLocal())
178*4a64e381SAndroid Build Coastguard Worker         {
179*4a64e381SAndroid Build Coastguard Worker             continue;
180*4a64e381SAndroid Build Coastguard Worker         }
181*4a64e381SAndroid Build Coastguard Worker         addresses.push_back(address);
182*4a64e381SAndroid Build Coastguard Worker     }
183*4a64e381SAndroid Build Coastguard Worker 
184*4a64e381SAndroid Build Coastguard Worker     return addresses;
185*4a64e381SAndroid Build Coastguard Worker }
186*4a64e381SAndroid Build Coastguard Worker 
HandleMdnsState(Mdns::Publisher::State aState)187*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::HandleMdnsState(Mdns::Publisher::State aState)
188*4a64e381SAndroid Build Coastguard Worker {
189*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(IsEnabled());
190*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aState == Mdns::Publisher::State::kReady);
191*4a64e381SAndroid Build Coastguard Worker 
192*4a64e381SAndroid Build Coastguard Worker     PublishAllHostsAndServices();
193*4a64e381SAndroid Build Coastguard Worker 
194*4a64e381SAndroid Build Coastguard Worker exit:
195*4a64e381SAndroid Build Coastguard Worker     return;
196*4a64e381SAndroid Build Coastguard Worker }
197*4a64e381SAndroid Build Coastguard Worker 
PublishAllHostsAndServices(void)198*4a64e381SAndroid Build Coastguard Worker void AdvertisingProxy::PublishAllHostsAndServices(void)
199*4a64e381SAndroid Build Coastguard Worker {
200*4a64e381SAndroid Build Coastguard Worker     const otSrpServerHost *host = nullptr;
201*4a64e381SAndroid Build Coastguard Worker 
202*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(IsEnabled());
203*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(mPublisher.IsStarted());
204*4a64e381SAndroid Build Coastguard Worker 
205*4a64e381SAndroid Build Coastguard Worker     otbrLogInfo("Publish all hosts and services");
206*4a64e381SAndroid Build Coastguard Worker     while ((host = otSrpServerGetNextHost(GetInstance(), host)))
207*4a64e381SAndroid Build Coastguard Worker     {
208*4a64e381SAndroid Build Coastguard Worker         PublishHostAndItsServices(host, nullptr);
209*4a64e381SAndroid Build Coastguard Worker     }
210*4a64e381SAndroid Build Coastguard Worker 
211*4a64e381SAndroid Build Coastguard Worker exit:
212*4a64e381SAndroid Build Coastguard Worker     return;
213*4a64e381SAndroid Build Coastguard Worker }
214*4a64e381SAndroid Build Coastguard Worker 
PublishHostAndItsServices(const otSrpServerHost * aHost,OutstandingUpdate * aUpdate)215*4a64e381SAndroid Build Coastguard Worker otbrError AdvertisingProxy::PublishHostAndItsServices(const otSrpServerHost *aHost, OutstandingUpdate *aUpdate)
216*4a64e381SAndroid Build Coastguard Worker {
217*4a64e381SAndroid Build Coastguard Worker     otbrError                  error = OTBR_ERROR_NONE;
218*4a64e381SAndroid Build Coastguard Worker     std::string                hostName;
219*4a64e381SAndroid Build Coastguard Worker     std::string                hostDomain;
220*4a64e381SAndroid Build Coastguard Worker     const otIp6Address        *hostAddresses;
221*4a64e381SAndroid Build Coastguard Worker     uint8_t                    hostAddressNum;
222*4a64e381SAndroid Build Coastguard Worker     bool                       hostDeleted;
223*4a64e381SAndroid Build Coastguard Worker     const otSrpServerService  *service;
224*4a64e381SAndroid Build Coastguard Worker     otSrpServerServiceUpdateId updateId     = 0;
225*4a64e381SAndroid Build Coastguard Worker     bool                       hasUpdate    = false;
226*4a64e381SAndroid Build Coastguard Worker     std::string                fullHostName = otSrpServerHostGetFullName(aHost);
227*4a64e381SAndroid Build Coastguard Worker 
228*4a64e381SAndroid Build Coastguard Worker     otbrLogInfo("Advertise SRP service updates: host=%s", fullHostName.c_str());
229*4a64e381SAndroid Build Coastguard Worker 
230*4a64e381SAndroid Build Coastguard Worker     SuccessOrExit(error = SplitFullHostName(fullHostName, hostName, hostDomain));
231*4a64e381SAndroid Build Coastguard Worker     hostAddresses = otSrpServerHostGetAddresses(aHost, &hostAddressNum);
232*4a64e381SAndroid Build Coastguard Worker     hostDeleted   = otSrpServerHostIsDeleted(aHost);
233*4a64e381SAndroid Build Coastguard Worker 
234*4a64e381SAndroid Build Coastguard Worker     if (aUpdate)
235*4a64e381SAndroid Build Coastguard Worker     {
236*4a64e381SAndroid Build Coastguard Worker         hasUpdate = true;
237*4a64e381SAndroid Build Coastguard Worker         updateId  = aUpdate->mId;
238*4a64e381SAndroid Build Coastguard Worker         aUpdate->mCallbackCount++;
239*4a64e381SAndroid Build Coastguard Worker         aUpdate->mHostName = hostName;
240*4a64e381SAndroid Build Coastguard Worker         service            = nullptr;
241*4a64e381SAndroid Build Coastguard Worker         while ((service = otSrpServerHostGetNextService(aHost, service)) != nullptr)
242*4a64e381SAndroid Build Coastguard Worker         {
243*4a64e381SAndroid Build Coastguard Worker             aUpdate->mCallbackCount++;
244*4a64e381SAndroid Build Coastguard Worker         }
245*4a64e381SAndroid Build Coastguard Worker     }
246*4a64e381SAndroid Build Coastguard Worker 
247*4a64e381SAndroid Build Coastguard Worker     service = nullptr;
248*4a64e381SAndroid Build Coastguard Worker     while ((service = otSrpServerHostGetNextService(aHost, service)) != nullptr)
249*4a64e381SAndroid Build Coastguard Worker     {
250*4a64e381SAndroid Build Coastguard Worker         std::string fullServiceName = otSrpServerServiceGetInstanceName(service);
251*4a64e381SAndroid Build Coastguard Worker         std::string serviceName;
252*4a64e381SAndroid Build Coastguard Worker         std::string serviceType;
253*4a64e381SAndroid Build Coastguard Worker         std::string serviceDomain;
254*4a64e381SAndroid Build Coastguard Worker 
255*4a64e381SAndroid Build Coastguard Worker         SuccessOrExit(error = SplitFullServiceInstanceName(fullServiceName, serviceName, serviceType, serviceDomain));
256*4a64e381SAndroid Build Coastguard Worker 
257*4a64e381SAndroid Build Coastguard Worker         if (!hostDeleted && !otSrpServerServiceIsDeleted(service))
258*4a64e381SAndroid Build Coastguard Worker         {
259*4a64e381SAndroid Build Coastguard Worker             Mdns::Publisher::TxtData     txtData     = MakeTxtData(service);
260*4a64e381SAndroid Build Coastguard Worker             Mdns::Publisher::SubTypeList subTypeList = MakeSubTypeList(service);
261*4a64e381SAndroid Build Coastguard Worker 
262*4a64e381SAndroid Build Coastguard Worker             otbrLogDebug("Publish SRP service '%s'", fullServiceName.c_str());
263*4a64e381SAndroid Build Coastguard Worker             mPublisher.PublishService(
264*4a64e381SAndroid Build Coastguard Worker                 hostName, serviceName, serviceType, subTypeList, otSrpServerServiceGetPort(service), txtData,
265*4a64e381SAndroid Build Coastguard Worker                 [this, hasUpdate, updateId, fullServiceName](otbrError aError) {
266*4a64e381SAndroid Build Coastguard Worker                     otbrLogResult(aError, "Handle publish SRP service '%s'", fullServiceName.c_str());
267*4a64e381SAndroid Build Coastguard Worker                     if (hasUpdate)
268*4a64e381SAndroid Build Coastguard Worker                     {
269*4a64e381SAndroid Build Coastguard Worker                         OnMdnsPublishResult(updateId, aError);
270*4a64e381SAndroid Build Coastguard Worker                     }
271*4a64e381SAndroid Build Coastguard Worker                 });
272*4a64e381SAndroid Build Coastguard Worker         }
273*4a64e381SAndroid Build Coastguard Worker         else
274*4a64e381SAndroid Build Coastguard Worker         {
275*4a64e381SAndroid Build Coastguard Worker             otbrLogDebug("Unpublish SRP service '%s'", fullServiceName.c_str());
276*4a64e381SAndroid Build Coastguard Worker             mPublisher.UnpublishService(
277*4a64e381SAndroid Build Coastguard Worker                 serviceName, serviceType, [this, hasUpdate, updateId, fullServiceName](otbrError aError) {
278*4a64e381SAndroid Build Coastguard Worker                     // Treat `NOT_FOUND` as success when unpublishing service
279*4a64e381SAndroid Build Coastguard Worker                     aError = (aError == OTBR_ERROR_NOT_FOUND) ? OTBR_ERROR_NONE : aError;
280*4a64e381SAndroid Build Coastguard Worker                     otbrLogResult(aError, "Handle unpublish SRP service '%s'", fullServiceName.c_str());
281*4a64e381SAndroid Build Coastguard Worker                     if (hasUpdate)
282*4a64e381SAndroid Build Coastguard Worker                     {
283*4a64e381SAndroid Build Coastguard Worker                         OnMdnsPublishResult(updateId, aError);
284*4a64e381SAndroid Build Coastguard Worker                     }
285*4a64e381SAndroid Build Coastguard Worker                 });
286*4a64e381SAndroid Build Coastguard Worker         }
287*4a64e381SAndroid Build Coastguard Worker     }
288*4a64e381SAndroid Build Coastguard Worker 
289*4a64e381SAndroid Build Coastguard Worker     if (!hostDeleted)
290*4a64e381SAndroid Build Coastguard Worker     {
291*4a64e381SAndroid Build Coastguard Worker         std::vector<Ip6Address> addresses;
292*4a64e381SAndroid Build Coastguard Worker 
293*4a64e381SAndroid Build Coastguard Worker         // TODO: select a preferred address or advertise all addresses from SRP client.
294*4a64e381SAndroid Build Coastguard Worker         otbrLogDebug("Publish SRP host '%s'", fullHostName.c_str());
295*4a64e381SAndroid Build Coastguard Worker 
296*4a64e381SAndroid Build Coastguard Worker         addresses = GetEligibleAddresses(hostAddresses, hostAddressNum);
297*4a64e381SAndroid Build Coastguard Worker         mPublisher.PublishHost(
298*4a64e381SAndroid Build Coastguard Worker             hostName, addresses,
299*4a64e381SAndroid Build Coastguard Worker             Mdns::Publisher::ResultCallback([this, hasUpdate, updateId, fullHostName](otbrError aError) {
300*4a64e381SAndroid Build Coastguard Worker                 otbrLogResult(aError, "Handle publish SRP host '%s'", fullHostName.c_str());
301*4a64e381SAndroid Build Coastguard Worker                 if (hasUpdate)
302*4a64e381SAndroid Build Coastguard Worker                 {
303*4a64e381SAndroid Build Coastguard Worker                     OnMdnsPublishResult(updateId, aError);
304*4a64e381SAndroid Build Coastguard Worker                 }
305*4a64e381SAndroid Build Coastguard Worker             }));
306*4a64e381SAndroid Build Coastguard Worker     }
307*4a64e381SAndroid Build Coastguard Worker     else
308*4a64e381SAndroid Build Coastguard Worker     {
309*4a64e381SAndroid Build Coastguard Worker         otbrLogDebug("Unpublish SRP host '%s'", fullHostName.c_str());
310*4a64e381SAndroid Build Coastguard Worker         mPublisher.UnpublishHost(hostName, [this, hasUpdate, updateId, fullHostName](otbrError aError) {
311*4a64e381SAndroid Build Coastguard Worker             // Treat `NOT_FOUND` as success when unpublishing host.
312*4a64e381SAndroid Build Coastguard Worker             aError = (aError == OTBR_ERROR_NOT_FOUND) ? OTBR_ERROR_NONE : aError;
313*4a64e381SAndroid Build Coastguard Worker             otbrLogResult(aError, "Handle unpublish SRP host '%s'", fullHostName.c_str());
314*4a64e381SAndroid Build Coastguard Worker             if (hasUpdate)
315*4a64e381SAndroid Build Coastguard Worker             {
316*4a64e381SAndroid Build Coastguard Worker                 OnMdnsPublishResult(updateId, aError);
317*4a64e381SAndroid Build Coastguard Worker             }
318*4a64e381SAndroid Build Coastguard Worker         });
319*4a64e381SAndroid Build Coastguard Worker     }
320*4a64e381SAndroid Build Coastguard Worker 
321*4a64e381SAndroid Build Coastguard Worker exit:
322*4a64e381SAndroid Build Coastguard Worker     if (error != OTBR_ERROR_NONE)
323*4a64e381SAndroid Build Coastguard Worker     {
324*4a64e381SAndroid Build Coastguard Worker         if (hasUpdate)
325*4a64e381SAndroid Build Coastguard Worker         {
326*4a64e381SAndroid Build Coastguard Worker             otbrLogInfo("Failed to advertise SRP service updates (id = %u)", updateId);
327*4a64e381SAndroid Build Coastguard Worker         }
328*4a64e381SAndroid Build Coastguard Worker     }
329*4a64e381SAndroid Build Coastguard Worker     return error;
330*4a64e381SAndroid Build Coastguard Worker }
331*4a64e381SAndroid Build Coastguard Worker 
MakeTxtData(const otSrpServerService * aSrpService)332*4a64e381SAndroid Build Coastguard Worker Mdns::Publisher::TxtData AdvertisingProxy::MakeTxtData(const otSrpServerService *aSrpService)
333*4a64e381SAndroid Build Coastguard Worker {
334*4a64e381SAndroid Build Coastguard Worker     const uint8_t *data;
335*4a64e381SAndroid Build Coastguard Worker     uint16_t       length = 0;
336*4a64e381SAndroid Build Coastguard Worker 
337*4a64e381SAndroid Build Coastguard Worker     data = otSrpServerServiceGetTxtData(aSrpService, &length);
338*4a64e381SAndroid Build Coastguard Worker 
339*4a64e381SAndroid Build Coastguard Worker     return Mdns::Publisher::TxtData(data, data + length);
340*4a64e381SAndroid Build Coastguard Worker }
341*4a64e381SAndroid Build Coastguard Worker 
MakeSubTypeList(const otSrpServerService * aSrpService)342*4a64e381SAndroid Build Coastguard Worker Mdns::Publisher::SubTypeList AdvertisingProxy::MakeSubTypeList(const otSrpServerService *aSrpService)
343*4a64e381SAndroid Build Coastguard Worker {
344*4a64e381SAndroid Build Coastguard Worker     Mdns::Publisher::SubTypeList subTypeList;
345*4a64e381SAndroid Build Coastguard Worker 
346*4a64e381SAndroid Build Coastguard Worker     for (uint16_t index = 0;; index++)
347*4a64e381SAndroid Build Coastguard Worker     {
348*4a64e381SAndroid Build Coastguard Worker         const char *subTypeName = otSrpServerServiceGetSubTypeServiceNameAt(aSrpService, index);
349*4a64e381SAndroid Build Coastguard Worker         char        subLabel[OT_DNS_MAX_LABEL_SIZE];
350*4a64e381SAndroid Build Coastguard Worker 
351*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(subTypeName != nullptr);
352*4a64e381SAndroid Build Coastguard Worker         SuccessOrExit(otSrpServerParseSubTypeServiceName(subTypeName, subLabel, sizeof(subLabel)));
353*4a64e381SAndroid Build Coastguard Worker         subTypeList.emplace_back(subLabel);
354*4a64e381SAndroid Build Coastguard Worker     }
355*4a64e381SAndroid Build Coastguard Worker 
356*4a64e381SAndroid Build Coastguard Worker exit:
357*4a64e381SAndroid Build Coastguard Worker     return subTypeList;
358*4a64e381SAndroid Build Coastguard Worker }
359*4a64e381SAndroid Build Coastguard Worker 
360*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
361*4a64e381SAndroid Build Coastguard Worker 
362*4a64e381SAndroid Build Coastguard Worker #endif // OTBR_ENABLE_SRP_ADVERTISING_PROXY
363