1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker * Copyright (c) 2018, 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 * This file implements mDNS publisher based on mDNSResponder.
32*4a64e381SAndroid Build Coastguard Worker */
33*4a64e381SAndroid Build Coastguard Worker
34*4a64e381SAndroid Build Coastguard Worker #define OTBR_LOG_TAG "MDNS"
35*4a64e381SAndroid Build Coastguard Worker
36*4a64e381SAndroid Build Coastguard Worker #include "mdns/mdns_mdnssd.hpp"
37*4a64e381SAndroid Build Coastguard Worker
38*4a64e381SAndroid Build Coastguard Worker #include <algorithm>
39*4a64e381SAndroid Build Coastguard Worker
40*4a64e381SAndroid Build Coastguard Worker #include <arpa/inet.h>
41*4a64e381SAndroid Build Coastguard Worker #include <assert.h>
42*4a64e381SAndroid Build Coastguard Worker #include <errno.h>
43*4a64e381SAndroid Build Coastguard Worker #include <inttypes.h>
44*4a64e381SAndroid Build Coastguard Worker #include <netinet/in.h>
45*4a64e381SAndroid Build Coastguard Worker #include <stdio.h>
46*4a64e381SAndroid Build Coastguard Worker #include <stdlib.h>
47*4a64e381SAndroid Build Coastguard Worker #include <string.h>
48*4a64e381SAndroid Build Coastguard Worker
49*4a64e381SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
50*4a64e381SAndroid Build Coastguard Worker #include "common/dns_utils.hpp"
51*4a64e381SAndroid Build Coastguard Worker #include "common/logging.hpp"
52*4a64e381SAndroid Build Coastguard Worker #include "common/time.hpp"
53*4a64e381SAndroid Build Coastguard Worker
54*4a64e381SAndroid Build Coastguard Worker namespace otbr {
55*4a64e381SAndroid Build Coastguard Worker
56*4a64e381SAndroid Build Coastguard Worker namespace Mdns {
57*4a64e381SAndroid Build Coastguard Worker
58*4a64e381SAndroid Build Coastguard Worker static const char kDomain[] = "local.";
59*4a64e381SAndroid Build Coastguard Worker
DNSErrorToOtbrError(DNSServiceErrorType aError)60*4a64e381SAndroid Build Coastguard Worker static otbrError DNSErrorToOtbrError(DNSServiceErrorType aError)
61*4a64e381SAndroid Build Coastguard Worker {
62*4a64e381SAndroid Build Coastguard Worker otbrError error;
63*4a64e381SAndroid Build Coastguard Worker
64*4a64e381SAndroid Build Coastguard Worker switch (aError)
65*4a64e381SAndroid Build Coastguard Worker {
66*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoError:
67*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_NONE;
68*4a64e381SAndroid Build Coastguard Worker break;
69*4a64e381SAndroid Build Coastguard Worker
70*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchKey:
71*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchName:
72*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchRecord:
73*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_NOT_FOUND;
74*4a64e381SAndroid Build Coastguard Worker break;
75*4a64e381SAndroid Build Coastguard Worker
76*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Invalid:
77*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadParam:
78*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadFlags:
79*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadInterfaceIndex:
80*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_INVALID_ARGS;
81*4a64e381SAndroid Build Coastguard Worker break;
82*4a64e381SAndroid Build Coastguard Worker
83*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NameConflict:
84*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_DUPLICATED;
85*4a64e381SAndroid Build Coastguard Worker break;
86*4a64e381SAndroid Build Coastguard Worker
87*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Unsupported:
88*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_NOT_IMPLEMENTED;
89*4a64e381SAndroid Build Coastguard Worker break;
90*4a64e381SAndroid Build Coastguard Worker
91*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_ServiceNotRunning:
92*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_INVALID_STATE;
93*4a64e381SAndroid Build Coastguard Worker break;
94*4a64e381SAndroid Build Coastguard Worker
95*4a64e381SAndroid Build Coastguard Worker default:
96*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_MDNS;
97*4a64e381SAndroid Build Coastguard Worker break;
98*4a64e381SAndroid Build Coastguard Worker }
99*4a64e381SAndroid Build Coastguard Worker
100*4a64e381SAndroid Build Coastguard Worker return error;
101*4a64e381SAndroid Build Coastguard Worker }
102*4a64e381SAndroid Build Coastguard Worker
DNSErrorToString(DNSServiceErrorType aError)103*4a64e381SAndroid Build Coastguard Worker static const char *DNSErrorToString(DNSServiceErrorType aError)
104*4a64e381SAndroid Build Coastguard Worker {
105*4a64e381SAndroid Build Coastguard Worker switch (aError)
106*4a64e381SAndroid Build Coastguard Worker {
107*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoError:
108*4a64e381SAndroid Build Coastguard Worker return "OK";
109*4a64e381SAndroid Build Coastguard Worker
110*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Unknown:
111*4a64e381SAndroid Build Coastguard Worker // 0xFFFE FFFF
112*4a64e381SAndroid Build Coastguard Worker return "Unknown";
113*4a64e381SAndroid Build Coastguard Worker
114*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchName:
115*4a64e381SAndroid Build Coastguard Worker return "No Such Name";
116*4a64e381SAndroid Build Coastguard Worker
117*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoMemory:
118*4a64e381SAndroid Build Coastguard Worker return "No Memory";
119*4a64e381SAndroid Build Coastguard Worker
120*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadParam:
121*4a64e381SAndroid Build Coastguard Worker return "Bad Param";
122*4a64e381SAndroid Build Coastguard Worker
123*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadReference:
124*4a64e381SAndroid Build Coastguard Worker return "Bad Reference";
125*4a64e381SAndroid Build Coastguard Worker
126*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadState:
127*4a64e381SAndroid Build Coastguard Worker return "Bad State";
128*4a64e381SAndroid Build Coastguard Worker
129*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadFlags:
130*4a64e381SAndroid Build Coastguard Worker return "Bad Flags";
131*4a64e381SAndroid Build Coastguard Worker
132*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Unsupported:
133*4a64e381SAndroid Build Coastguard Worker return "Unsupported";
134*4a64e381SAndroid Build Coastguard Worker
135*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NotInitialized:
136*4a64e381SAndroid Build Coastguard Worker return "Not Initialized";
137*4a64e381SAndroid Build Coastguard Worker
138*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_AlreadyRegistered:
139*4a64e381SAndroid Build Coastguard Worker return "Already Registered";
140*4a64e381SAndroid Build Coastguard Worker
141*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NameConflict:
142*4a64e381SAndroid Build Coastguard Worker return "Name Conflict";
143*4a64e381SAndroid Build Coastguard Worker
144*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Invalid:
145*4a64e381SAndroid Build Coastguard Worker return "Invalid";
146*4a64e381SAndroid Build Coastguard Worker
147*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Firewall:
148*4a64e381SAndroid Build Coastguard Worker return "Firewall";
149*4a64e381SAndroid Build Coastguard Worker
150*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Incompatible:
151*4a64e381SAndroid Build Coastguard Worker // client library incompatible with daemon
152*4a64e381SAndroid Build Coastguard Worker return "Incompatible";
153*4a64e381SAndroid Build Coastguard Worker
154*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadInterfaceIndex:
155*4a64e381SAndroid Build Coastguard Worker return "Bad Interface Index";
156*4a64e381SAndroid Build Coastguard Worker
157*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Refused:
158*4a64e381SAndroid Build Coastguard Worker return "Refused";
159*4a64e381SAndroid Build Coastguard Worker
160*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchRecord:
161*4a64e381SAndroid Build Coastguard Worker return "No Such Record";
162*4a64e381SAndroid Build Coastguard Worker
163*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoAuth:
164*4a64e381SAndroid Build Coastguard Worker return "No Auth";
165*4a64e381SAndroid Build Coastguard Worker
166*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoSuchKey:
167*4a64e381SAndroid Build Coastguard Worker return "No Such Key";
168*4a64e381SAndroid Build Coastguard Worker
169*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NATTraversal:
170*4a64e381SAndroid Build Coastguard Worker return "NAT Traversal";
171*4a64e381SAndroid Build Coastguard Worker
172*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_DoubleNAT:
173*4a64e381SAndroid Build Coastguard Worker return "Double NAT";
174*4a64e381SAndroid Build Coastguard Worker
175*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadTime:
176*4a64e381SAndroid Build Coastguard Worker // Codes up to here existed in Tiger
177*4a64e381SAndroid Build Coastguard Worker return "Bad Time";
178*4a64e381SAndroid Build Coastguard Worker
179*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadSig:
180*4a64e381SAndroid Build Coastguard Worker return "Bad Sig";
181*4a64e381SAndroid Build Coastguard Worker
182*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_BadKey:
183*4a64e381SAndroid Build Coastguard Worker return "Bad Key";
184*4a64e381SAndroid Build Coastguard Worker
185*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Transient:
186*4a64e381SAndroid Build Coastguard Worker return "Transient";
187*4a64e381SAndroid Build Coastguard Worker
188*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_ServiceNotRunning:
189*4a64e381SAndroid Build Coastguard Worker // Background daemon not running
190*4a64e381SAndroid Build Coastguard Worker return "Service Not Running";
191*4a64e381SAndroid Build Coastguard Worker
192*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NATPortMappingUnsupported:
193*4a64e381SAndroid Build Coastguard Worker // NAT doesn't support NAT-PMP or UPnP
194*4a64e381SAndroid Build Coastguard Worker return "NAT Port Mapping Unsupported";
195*4a64e381SAndroid Build Coastguard Worker
196*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NATPortMappingDisabled:
197*4a64e381SAndroid Build Coastguard Worker // NAT supports NAT-PMP or UPnP but it's disabled by the administrator
198*4a64e381SAndroid Build Coastguard Worker return "NAT Port Mapping Disabled";
199*4a64e381SAndroid Build Coastguard Worker
200*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_NoRouter:
201*4a64e381SAndroid Build Coastguard Worker // No router currently configured (probably no network connectivity)
202*4a64e381SAndroid Build Coastguard Worker return "No Router";
203*4a64e381SAndroid Build Coastguard Worker
204*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_PollingMode:
205*4a64e381SAndroid Build Coastguard Worker return "Polling Mode";
206*4a64e381SAndroid Build Coastguard Worker
207*4a64e381SAndroid Build Coastguard Worker case kDNSServiceErr_Timeout:
208*4a64e381SAndroid Build Coastguard Worker return "Timeout";
209*4a64e381SAndroid Build Coastguard Worker
210*4a64e381SAndroid Build Coastguard Worker default:
211*4a64e381SAndroid Build Coastguard Worker assert(false);
212*4a64e381SAndroid Build Coastguard Worker return nullptr;
213*4a64e381SAndroid Build Coastguard Worker }
214*4a64e381SAndroid Build Coastguard Worker }
215*4a64e381SAndroid Build Coastguard Worker
PublisherMDnsSd(StateCallback aCallback)216*4a64e381SAndroid Build Coastguard Worker PublisherMDnsSd::PublisherMDnsSd(StateCallback aCallback)
217*4a64e381SAndroid Build Coastguard Worker : mHostsRef(nullptr)
218*4a64e381SAndroid Build Coastguard Worker , mState(State::kIdle)
219*4a64e381SAndroid Build Coastguard Worker , mStateCallback(std::move(aCallback))
220*4a64e381SAndroid Build Coastguard Worker {
221*4a64e381SAndroid Build Coastguard Worker }
222*4a64e381SAndroid Build Coastguard Worker
~PublisherMDnsSd(void)223*4a64e381SAndroid Build Coastguard Worker PublisherMDnsSd::~PublisherMDnsSd(void)
224*4a64e381SAndroid Build Coastguard Worker {
225*4a64e381SAndroid Build Coastguard Worker Stop(kNormalStop);
226*4a64e381SAndroid Build Coastguard Worker }
227*4a64e381SAndroid Build Coastguard Worker
Start(void)228*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::Start(void)
229*4a64e381SAndroid Build Coastguard Worker {
230*4a64e381SAndroid Build Coastguard Worker mState = State::kReady;
231*4a64e381SAndroid Build Coastguard Worker mStateCallback(State::kReady);
232*4a64e381SAndroid Build Coastguard Worker return OTBR_ERROR_NONE;
233*4a64e381SAndroid Build Coastguard Worker }
234*4a64e381SAndroid Build Coastguard Worker
IsStarted(void) const235*4a64e381SAndroid Build Coastguard Worker bool PublisherMDnsSd::IsStarted(void) const
236*4a64e381SAndroid Build Coastguard Worker {
237*4a64e381SAndroid Build Coastguard Worker return mState == State::kReady;
238*4a64e381SAndroid Build Coastguard Worker }
239*4a64e381SAndroid Build Coastguard Worker
Stop(StopMode aStopMode)240*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::Stop(StopMode aStopMode)
241*4a64e381SAndroid Build Coastguard Worker {
242*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == State::kReady);
243*4a64e381SAndroid Build Coastguard Worker
244*4a64e381SAndroid Build Coastguard Worker // If we get a `kDNSServiceErr_ServiceNotRunning` and need to
245*4a64e381SAndroid Build Coastguard Worker // restart the `Publisher`, we should immediately de-allocate
246*4a64e381SAndroid Build Coastguard Worker // all `ServiceRef`. Otherwise, we first clear the `Registrations`
247*4a64e381SAndroid Build Coastguard Worker // list so that `DnssdHostRegisteration` destructor gets the chance
248*4a64e381SAndroid Build Coastguard Worker // to update registered records if needed.
249*4a64e381SAndroid Build Coastguard Worker
250*4a64e381SAndroid Build Coastguard Worker switch (aStopMode)
251*4a64e381SAndroid Build Coastguard Worker {
252*4a64e381SAndroid Build Coastguard Worker case kNormalStop:
253*4a64e381SAndroid Build Coastguard Worker break;
254*4a64e381SAndroid Build Coastguard Worker
255*4a64e381SAndroid Build Coastguard Worker case kStopOnServiceNotRunningError:
256*4a64e381SAndroid Build Coastguard Worker DeallocateHostsRef();
257*4a64e381SAndroid Build Coastguard Worker break;
258*4a64e381SAndroid Build Coastguard Worker }
259*4a64e381SAndroid Build Coastguard Worker
260*4a64e381SAndroid Build Coastguard Worker mServiceRegistrations.clear();
261*4a64e381SAndroid Build Coastguard Worker mHostRegistrations.clear();
262*4a64e381SAndroid Build Coastguard Worker mKeyRegistrations.clear();
263*4a64e381SAndroid Build Coastguard Worker DeallocateHostsRef();
264*4a64e381SAndroid Build Coastguard Worker
265*4a64e381SAndroid Build Coastguard Worker mSubscribedServices.clear();
266*4a64e381SAndroid Build Coastguard Worker mSubscribedHosts.clear();
267*4a64e381SAndroid Build Coastguard Worker
268*4a64e381SAndroid Build Coastguard Worker mState = State::kIdle;
269*4a64e381SAndroid Build Coastguard Worker
270*4a64e381SAndroid Build Coastguard Worker exit:
271*4a64e381SAndroid Build Coastguard Worker return;
272*4a64e381SAndroid Build Coastguard Worker }
273*4a64e381SAndroid Build Coastguard Worker
CreateSharedHostsRef(void)274*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType PublisherMDnsSd::CreateSharedHostsRef(void)
275*4a64e381SAndroid Build Coastguard Worker {
276*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType dnsError = kDNSServiceErr_NoError;
277*4a64e381SAndroid Build Coastguard Worker
278*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mHostsRef == nullptr);
279*4a64e381SAndroid Build Coastguard Worker
280*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceCreateConnection(&mHostsRef);
281*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("Created new shared DNSServiceRef: %p", mHostsRef);
282*4a64e381SAndroid Build Coastguard Worker
283*4a64e381SAndroid Build Coastguard Worker exit:
284*4a64e381SAndroid Build Coastguard Worker return dnsError;
285*4a64e381SAndroid Build Coastguard Worker }
286*4a64e381SAndroid Build Coastguard Worker
DeallocateHostsRef(void)287*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DeallocateHostsRef(void)
288*4a64e381SAndroid Build Coastguard Worker {
289*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mHostsRef != nullptr);
290*4a64e381SAndroid Build Coastguard Worker
291*4a64e381SAndroid Build Coastguard Worker HandleServiceRefDeallocating(mHostsRef);
292*4a64e381SAndroid Build Coastguard Worker DNSServiceRefDeallocate(mHostsRef);
293*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("Deallocated DNSServiceRef for hosts: %p", mHostsRef);
294*4a64e381SAndroid Build Coastguard Worker mHostsRef = nullptr;
295*4a64e381SAndroid Build Coastguard Worker
296*4a64e381SAndroid Build Coastguard Worker exit:
297*4a64e381SAndroid Build Coastguard Worker return;
298*4a64e381SAndroid Build Coastguard Worker }
299*4a64e381SAndroid Build Coastguard Worker
Update(MainloopContext & aMainloop)300*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::Update(MainloopContext &aMainloop)
301*4a64e381SAndroid Build Coastguard Worker {
302*4a64e381SAndroid Build Coastguard Worker for (auto &kv : mServiceRegistrations)
303*4a64e381SAndroid Build Coastguard Worker {
304*4a64e381SAndroid Build Coastguard Worker auto &serviceReg = static_cast<DnssdServiceRegistration &>(*kv.second);
305*4a64e381SAndroid Build Coastguard Worker
306*4a64e381SAndroid Build Coastguard Worker serviceReg.Update(aMainloop);
307*4a64e381SAndroid Build Coastguard Worker }
308*4a64e381SAndroid Build Coastguard Worker
309*4a64e381SAndroid Build Coastguard Worker if (mHostsRef != nullptr)
310*4a64e381SAndroid Build Coastguard Worker {
311*4a64e381SAndroid Build Coastguard Worker int fd = DNSServiceRefSockFD(mHostsRef);
312*4a64e381SAndroid Build Coastguard Worker
313*4a64e381SAndroid Build Coastguard Worker assert(fd != -1);
314*4a64e381SAndroid Build Coastguard Worker
315*4a64e381SAndroid Build Coastguard Worker aMainloop.AddFdToReadSet(fd);
316*4a64e381SAndroid Build Coastguard Worker }
317*4a64e381SAndroid Build Coastguard Worker
318*4a64e381SAndroid Build Coastguard Worker for (const auto &service : mSubscribedServices)
319*4a64e381SAndroid Build Coastguard Worker {
320*4a64e381SAndroid Build Coastguard Worker service->UpdateAll(aMainloop);
321*4a64e381SAndroid Build Coastguard Worker }
322*4a64e381SAndroid Build Coastguard Worker
323*4a64e381SAndroid Build Coastguard Worker for (const auto &host : mSubscribedHosts)
324*4a64e381SAndroid Build Coastguard Worker {
325*4a64e381SAndroid Build Coastguard Worker host->Update(aMainloop);
326*4a64e381SAndroid Build Coastguard Worker }
327*4a64e381SAndroid Build Coastguard Worker }
328*4a64e381SAndroid Build Coastguard Worker
Process(const MainloopContext & aMainloop)329*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::Process(const MainloopContext &aMainloop)
330*4a64e381SAndroid Build Coastguard Worker {
331*4a64e381SAndroid Build Coastguard Worker mServiceRefsToProcess.clear();
332*4a64e381SAndroid Build Coastguard Worker
333*4a64e381SAndroid Build Coastguard Worker for (auto &kv : mServiceRegistrations)
334*4a64e381SAndroid Build Coastguard Worker {
335*4a64e381SAndroid Build Coastguard Worker auto &serviceReg = static_cast<DnssdServiceRegistration &>(*kv.second);
336*4a64e381SAndroid Build Coastguard Worker
337*4a64e381SAndroid Build Coastguard Worker serviceReg.Process(aMainloop, mServiceRefsToProcess);
338*4a64e381SAndroid Build Coastguard Worker }
339*4a64e381SAndroid Build Coastguard Worker
340*4a64e381SAndroid Build Coastguard Worker if (mHostsRef != nullptr)
341*4a64e381SAndroid Build Coastguard Worker {
342*4a64e381SAndroid Build Coastguard Worker int fd = DNSServiceRefSockFD(mHostsRef);
343*4a64e381SAndroid Build Coastguard Worker
344*4a64e381SAndroid Build Coastguard Worker if (FD_ISSET(fd, &aMainloop.mReadFdSet))
345*4a64e381SAndroid Build Coastguard Worker {
346*4a64e381SAndroid Build Coastguard Worker mServiceRefsToProcess.push_back(mHostsRef);
347*4a64e381SAndroid Build Coastguard Worker }
348*4a64e381SAndroid Build Coastguard Worker }
349*4a64e381SAndroid Build Coastguard Worker
350*4a64e381SAndroid Build Coastguard Worker for (const auto &service : mSubscribedServices)
351*4a64e381SAndroid Build Coastguard Worker {
352*4a64e381SAndroid Build Coastguard Worker service->ProcessAll(aMainloop, mServiceRefsToProcess);
353*4a64e381SAndroid Build Coastguard Worker }
354*4a64e381SAndroid Build Coastguard Worker
355*4a64e381SAndroid Build Coastguard Worker for (const auto &host : mSubscribedHosts)
356*4a64e381SAndroid Build Coastguard Worker {
357*4a64e381SAndroid Build Coastguard Worker host->Process(aMainloop, mServiceRefsToProcess);
358*4a64e381SAndroid Build Coastguard Worker }
359*4a64e381SAndroid Build Coastguard Worker
360*4a64e381SAndroid Build Coastguard Worker for (DNSServiceRef serviceRef : mServiceRefsToProcess)
361*4a64e381SAndroid Build Coastguard Worker {
362*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType error;
363*4a64e381SAndroid Build Coastguard Worker
364*4a64e381SAndroid Build Coastguard Worker // As we go through the list of `mServiceRefsToProcess` the call
365*4a64e381SAndroid Build Coastguard Worker // to `DNSServiceProcessResult()` can itself invoke callbacks
366*4a64e381SAndroid Build Coastguard Worker // into `PublisherMDnsSd` and OT, which in turn, may change the
367*4a64e381SAndroid Build Coastguard Worker // state of `Publisher` and potentially trigger a previously
368*4a64e381SAndroid Build Coastguard Worker // valid `ServiceRef` in the list to be deallocated. We use
369*4a64e381SAndroid Build Coastguard Worker // `HandleServiceRefDeallocating()` which is called whenever a
370*4a64e381SAndroid Build Coastguard Worker // `ServiceRef` is being deallocated and from this we update
371*4a64e381SAndroid Build Coastguard Worker // the entry in `mServiceRefsToProcess` list to `nullptr` so to
372*4a64e381SAndroid Build Coastguard Worker // avoid calling `DNSServiceProcessResult()` on an already
373*4a64e381SAndroid Build Coastguard Worker // freed `ServiceRef`.
374*4a64e381SAndroid Build Coastguard Worker
375*4a64e381SAndroid Build Coastguard Worker if (serviceRef == nullptr)
376*4a64e381SAndroid Build Coastguard Worker {
377*4a64e381SAndroid Build Coastguard Worker continue;
378*4a64e381SAndroid Build Coastguard Worker }
379*4a64e381SAndroid Build Coastguard Worker
380*4a64e381SAndroid Build Coastguard Worker error = DNSServiceProcessResult(serviceRef);
381*4a64e381SAndroid Build Coastguard Worker
382*4a64e381SAndroid Build Coastguard Worker if (error != kDNSServiceErr_NoError)
383*4a64e381SAndroid Build Coastguard Worker {
384*4a64e381SAndroid Build Coastguard Worker otbrLogLevel logLevel = (error == kDNSServiceErr_BadReference) ? OTBR_LOG_INFO : OTBR_LOG_WARNING;
385*4a64e381SAndroid Build Coastguard Worker otbrLog(logLevel, OTBR_LOG_TAG, "DNSServiceProcessResult failed: %s (serviceRef = %p)",
386*4a64e381SAndroid Build Coastguard Worker DNSErrorToString(error), serviceRef);
387*4a64e381SAndroid Build Coastguard Worker }
388*4a64e381SAndroid Build Coastguard Worker if (error == kDNSServiceErr_ServiceNotRunning)
389*4a64e381SAndroid Build Coastguard Worker {
390*4a64e381SAndroid Build Coastguard Worker otbrLogWarning("Need to reconnect to mdnsd");
391*4a64e381SAndroid Build Coastguard Worker Stop(kStopOnServiceNotRunningError);
392*4a64e381SAndroid Build Coastguard Worker Start();
393*4a64e381SAndroid Build Coastguard Worker ExitNow();
394*4a64e381SAndroid Build Coastguard Worker }
395*4a64e381SAndroid Build Coastguard Worker }
396*4a64e381SAndroid Build Coastguard Worker exit:
397*4a64e381SAndroid Build Coastguard Worker return;
398*4a64e381SAndroid Build Coastguard Worker }
399*4a64e381SAndroid Build Coastguard Worker
HandleServiceRefDeallocating(const DNSServiceRef & aServiceRef)400*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::HandleServiceRefDeallocating(const DNSServiceRef &aServiceRef)
401*4a64e381SAndroid Build Coastguard Worker {
402*4a64e381SAndroid Build Coastguard Worker for (DNSServiceRef &entry : mServiceRefsToProcess)
403*4a64e381SAndroid Build Coastguard Worker {
404*4a64e381SAndroid Build Coastguard Worker if (entry == aServiceRef)
405*4a64e381SAndroid Build Coastguard Worker {
406*4a64e381SAndroid Build Coastguard Worker entry = nullptr;
407*4a64e381SAndroid Build Coastguard Worker }
408*4a64e381SAndroid Build Coastguard Worker }
409*4a64e381SAndroid Build Coastguard Worker }
410*4a64e381SAndroid Build Coastguard Worker
Update(MainloopContext & aMainloop) const411*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdServiceRegistration::Update(MainloopContext &aMainloop) const
412*4a64e381SAndroid Build Coastguard Worker {
413*4a64e381SAndroid Build Coastguard Worker int fd;
414*4a64e381SAndroid Build Coastguard Worker
415*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mServiceRef != nullptr);
416*4a64e381SAndroid Build Coastguard Worker
417*4a64e381SAndroid Build Coastguard Worker fd = DNSServiceRefSockFD(mServiceRef);
418*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(fd != -1);
419*4a64e381SAndroid Build Coastguard Worker
420*4a64e381SAndroid Build Coastguard Worker aMainloop.AddFdToReadSet(fd);
421*4a64e381SAndroid Build Coastguard Worker
422*4a64e381SAndroid Build Coastguard Worker exit:
423*4a64e381SAndroid Build Coastguard Worker return;
424*4a64e381SAndroid Build Coastguard Worker }
425*4a64e381SAndroid Build Coastguard Worker
Process(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const426*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdServiceRegistration::Process(const MainloopContext &aMainloop,
427*4a64e381SAndroid Build Coastguard Worker std::vector<DNSServiceRef> &aReadyServices) const
428*4a64e381SAndroid Build Coastguard Worker {
429*4a64e381SAndroid Build Coastguard Worker int fd;
430*4a64e381SAndroid Build Coastguard Worker
431*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mServiceRef != nullptr);
432*4a64e381SAndroid Build Coastguard Worker
433*4a64e381SAndroid Build Coastguard Worker fd = DNSServiceRefSockFD(mServiceRef);
434*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(fd != -1);
435*4a64e381SAndroid Build Coastguard Worker
436*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(FD_ISSET(fd, &aMainloop.mReadFdSet));
437*4a64e381SAndroid Build Coastguard Worker aReadyServices.push_back(mServiceRef);
438*4a64e381SAndroid Build Coastguard Worker
439*4a64e381SAndroid Build Coastguard Worker exit:
440*4a64e381SAndroid Build Coastguard Worker return;
441*4a64e381SAndroid Build Coastguard Worker }
442*4a64e381SAndroid Build Coastguard Worker
Register(void)443*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::DnssdServiceRegistration::Register(void)
444*4a64e381SAndroid Build Coastguard Worker {
445*4a64e381SAndroid Build Coastguard Worker std::string fullHostName;
446*4a64e381SAndroid Build Coastguard Worker std::string regType = MakeRegType(mType, mSubTypeList);
447*4a64e381SAndroid Build Coastguard Worker const char *hostNameCString = nullptr;
448*4a64e381SAndroid Build Coastguard Worker const char *serviceNameCString = nullptr;
449*4a64e381SAndroid Build Coastguard Worker DnssdKeyRegistration *keyReg;
450*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType dnsError;
451*4a64e381SAndroid Build Coastguard Worker
452*4a64e381SAndroid Build Coastguard Worker if (!mHostName.empty())
453*4a64e381SAndroid Build Coastguard Worker {
454*4a64e381SAndroid Build Coastguard Worker fullHostName = MakeFullHostName(mHostName);
455*4a64e381SAndroid Build Coastguard Worker hostNameCString = fullHostName.c_str();
456*4a64e381SAndroid Build Coastguard Worker }
457*4a64e381SAndroid Build Coastguard Worker
458*4a64e381SAndroid Build Coastguard Worker if (!mName.empty())
459*4a64e381SAndroid Build Coastguard Worker {
460*4a64e381SAndroid Build Coastguard Worker serviceNameCString = mName.c_str();
461*4a64e381SAndroid Build Coastguard Worker }
462*4a64e381SAndroid Build Coastguard Worker
463*4a64e381SAndroid Build Coastguard Worker keyReg = static_cast<DnssdKeyRegistration *>(GetPublisher().FindKeyRegistration(mName, mType));
464*4a64e381SAndroid Build Coastguard Worker
465*4a64e381SAndroid Build Coastguard Worker if (keyReg != nullptr)
466*4a64e381SAndroid Build Coastguard Worker {
467*4a64e381SAndroid Build Coastguard Worker keyReg->Unregister();
468*4a64e381SAndroid Build Coastguard Worker }
469*4a64e381SAndroid Build Coastguard Worker
470*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Registering service %s.%s", mName.c_str(), regType.c_str());
471*4a64e381SAndroid Build Coastguard Worker
472*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceRegister(&mServiceRef, kDNSServiceFlagsNoAutoRename, kDNSServiceInterfaceIndexAny,
473*4a64e381SAndroid Build Coastguard Worker serviceNameCString, regType.c_str(),
474*4a64e381SAndroid Build Coastguard Worker /* domain */ nullptr, hostNameCString, htons(mPort), mTxtData.size(), mTxtData.data(),
475*4a64e381SAndroid Build Coastguard Worker HandleRegisterResult, this);
476*4a64e381SAndroid Build Coastguard Worker
477*4a64e381SAndroid Build Coastguard Worker if (dnsError != kDNSServiceErr_NoError)
478*4a64e381SAndroid Build Coastguard Worker {
479*4a64e381SAndroid Build Coastguard Worker HandleRegisterResult(/* aFlags */ 0, dnsError);
480*4a64e381SAndroid Build Coastguard Worker }
481*4a64e381SAndroid Build Coastguard Worker
482*4a64e381SAndroid Build Coastguard Worker if (keyReg != nullptr)
483*4a64e381SAndroid Build Coastguard Worker {
484*4a64e381SAndroid Build Coastguard Worker keyReg->Register();
485*4a64e381SAndroid Build Coastguard Worker }
486*4a64e381SAndroid Build Coastguard Worker
487*4a64e381SAndroid Build Coastguard Worker return GetPublisher().DnsErrorToOtbrError(dnsError);
488*4a64e381SAndroid Build Coastguard Worker }
489*4a64e381SAndroid Build Coastguard Worker
Unregister(void)490*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdServiceRegistration::Unregister(void)
491*4a64e381SAndroid Build Coastguard Worker {
492*4a64e381SAndroid Build Coastguard Worker DnssdKeyRegistration *keyReg = mRelatedKeyReg;
493*4a64e381SAndroid Build Coastguard Worker
494*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mServiceRef != nullptr);
495*4a64e381SAndroid Build Coastguard Worker
496*4a64e381SAndroid Build Coastguard Worker // If we have a related key registration associated with this
497*4a64e381SAndroid Build Coastguard Worker // service registration, we first unregister it and after we
498*4a64e381SAndroid Build Coastguard Worker // deallocated the `mServiceRef` try to register it again
499*4a64e381SAndroid Build Coastguard Worker // (which will add it as an individual record not tied to a
500*4a64e381SAndroid Build Coastguard Worker // service registration). Note that the `keyReg->Unregister()`
501*4a64e381SAndroid Build Coastguard Worker // will clear the `mRelatedKeyReg` field, so we need to keep
502*4a64e381SAndroid Build Coastguard Worker // a local copy to it in `keyReg`.
503*4a64e381SAndroid Build Coastguard Worker
504*4a64e381SAndroid Build Coastguard Worker if (keyReg != nullptr)
505*4a64e381SAndroid Build Coastguard Worker {
506*4a64e381SAndroid Build Coastguard Worker keyReg->Unregister();
507*4a64e381SAndroid Build Coastguard Worker }
508*4a64e381SAndroid Build Coastguard Worker
509*4a64e381SAndroid Build Coastguard Worker GetPublisher().HandleServiceRefDeallocating(mServiceRef);
510*4a64e381SAndroid Build Coastguard Worker DNSServiceRefDeallocate(mServiceRef);
511*4a64e381SAndroid Build Coastguard Worker mServiceRef = nullptr;
512*4a64e381SAndroid Build Coastguard Worker
513*4a64e381SAndroid Build Coastguard Worker if (keyReg != nullptr)
514*4a64e381SAndroid Build Coastguard Worker {
515*4a64e381SAndroid Build Coastguard Worker keyReg->Register();
516*4a64e381SAndroid Build Coastguard Worker }
517*4a64e381SAndroid Build Coastguard Worker
518*4a64e381SAndroid Build Coastguard Worker exit:
519*4a64e381SAndroid Build Coastguard Worker return;
520*4a64e381SAndroid Build Coastguard Worker }
521*4a64e381SAndroid Build Coastguard Worker
HandleRegisterResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,DNSServiceErrorType aError,const char * aName,const char * aType,const char * aDomain,void * aContext)522*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdServiceRegistration::HandleRegisterResult(DNSServiceRef aServiceRef,
523*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
524*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aError,
525*4a64e381SAndroid Build Coastguard Worker const char *aName,
526*4a64e381SAndroid Build Coastguard Worker const char *aType,
527*4a64e381SAndroid Build Coastguard Worker const char *aDomain,
528*4a64e381SAndroid Build Coastguard Worker void *aContext)
529*4a64e381SAndroid Build Coastguard Worker {
530*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aServiceRef);
531*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aName);
532*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aType);
533*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aDomain);
534*4a64e381SAndroid Build Coastguard Worker
535*4a64e381SAndroid Build Coastguard Worker static_cast<DnssdServiceRegistration *>(aContext)->HandleRegisterResult(aFlags, aError);
536*4a64e381SAndroid Build Coastguard Worker }
537*4a64e381SAndroid Build Coastguard Worker
HandleRegisterResult(DNSServiceFlags aFlags,DNSServiceErrorType aError)538*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdServiceRegistration::HandleRegisterResult(DNSServiceFlags aFlags, DNSServiceErrorType aError)
539*4a64e381SAndroid Build Coastguard Worker {
540*4a64e381SAndroid Build Coastguard Worker if (mRelatedKeyReg != nullptr)
541*4a64e381SAndroid Build Coastguard Worker {
542*4a64e381SAndroid Build Coastguard Worker mRelatedKeyReg->HandleRegisterResult(aError);
543*4a64e381SAndroid Build Coastguard Worker }
544*4a64e381SAndroid Build Coastguard Worker
545*4a64e381SAndroid Build Coastguard Worker if ((aError == kDNSServiceErr_NoError) && (aFlags & kDNSServiceFlagsAdd))
546*4a64e381SAndroid Build Coastguard Worker {
547*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Successfully registered service %s.%s", mName.c_str(), mType.c_str());
548*4a64e381SAndroid Build Coastguard Worker Complete(OTBR_ERROR_NONE);
549*4a64e381SAndroid Build Coastguard Worker }
550*4a64e381SAndroid Build Coastguard Worker else
551*4a64e381SAndroid Build Coastguard Worker {
552*4a64e381SAndroid Build Coastguard Worker otbrLogErr("Failed to register service %s.%s: %s", mName.c_str(), mType.c_str(), DNSErrorToString(aError));
553*4a64e381SAndroid Build Coastguard Worker GetPublisher().RemoveServiceRegistration(mName, mType, DNSErrorToOtbrError(aError));
554*4a64e381SAndroid Build Coastguard Worker }
555*4a64e381SAndroid Build Coastguard Worker }
556*4a64e381SAndroid Build Coastguard Worker
Register(void)557*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::DnssdHostRegistration::Register(void)
558*4a64e381SAndroid Build Coastguard Worker {
559*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType dnsError = kDNSServiceErr_NoError;
560*4a64e381SAndroid Build Coastguard Worker
561*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Registering new host %s", mName.c_str());
562*4a64e381SAndroid Build Coastguard Worker
563*4a64e381SAndroid Build Coastguard Worker for (const Ip6Address &address : mAddresses)
564*4a64e381SAndroid Build Coastguard Worker {
565*4a64e381SAndroid Build Coastguard Worker DNSRecordRef recordRef = nullptr;
566*4a64e381SAndroid Build Coastguard Worker
567*4a64e381SAndroid Build Coastguard Worker dnsError = GetPublisher().CreateSharedHostsRef();
568*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(dnsError == kDNSServiceErr_NoError);
569*4a64e381SAndroid Build Coastguard Worker
570*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceRegisterRecord(GetPublisher().mHostsRef, &recordRef, kDNSServiceFlagsShared,
571*4a64e381SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexAny, MakeFullHostName(mName).c_str(),
572*4a64e381SAndroid Build Coastguard Worker kDNSServiceType_AAAA, kDNSServiceClass_IN, sizeof(address.m8), address.m8,
573*4a64e381SAndroid Build Coastguard Worker /* ttl */ 0, HandleRegisterResult, this);
574*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(dnsError == kDNSServiceErr_NoError);
575*4a64e381SAndroid Build Coastguard Worker
576*4a64e381SAndroid Build Coastguard Worker mAddrRecordRefs.push_back(recordRef);
577*4a64e381SAndroid Build Coastguard Worker mAddrRegistered.push_back(false);
578*4a64e381SAndroid Build Coastguard Worker }
579*4a64e381SAndroid Build Coastguard Worker
580*4a64e381SAndroid Build Coastguard Worker exit:
581*4a64e381SAndroid Build Coastguard Worker if ((dnsError != kDNSServiceErr_NoError) || mAddresses.empty())
582*4a64e381SAndroid Build Coastguard Worker {
583*4a64e381SAndroid Build Coastguard Worker HandleRegisterResult(/* aRecordRef */ nullptr, dnsError);
584*4a64e381SAndroid Build Coastguard Worker }
585*4a64e381SAndroid Build Coastguard Worker
586*4a64e381SAndroid Build Coastguard Worker return GetPublisher().DnsErrorToOtbrError(dnsError);
587*4a64e381SAndroid Build Coastguard Worker }
588*4a64e381SAndroid Build Coastguard Worker
Unregister(void)589*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdHostRegistration::Unregister(void)
590*4a64e381SAndroid Build Coastguard Worker {
591*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType dnsError;
592*4a64e381SAndroid Build Coastguard Worker
593*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(GetPublisher().mHostsRef != nullptr);
594*4a64e381SAndroid Build Coastguard Worker
595*4a64e381SAndroid Build Coastguard Worker for (size_t index = 0; index < mAddrRecordRefs.size(); index++)
596*4a64e381SAndroid Build Coastguard Worker {
597*4a64e381SAndroid Build Coastguard Worker const Ip6Address &address = mAddresses[index];
598*4a64e381SAndroid Build Coastguard Worker
599*4a64e381SAndroid Build Coastguard Worker if (mAddrRegistered[index])
600*4a64e381SAndroid Build Coastguard Worker {
601*4a64e381SAndroid Build Coastguard Worker // The Bonjour mDNSResponder somehow doesn't send goodbye message for the AAAA record when it is
602*4a64e381SAndroid Build Coastguard Worker // removed by `DNSServiceRemoveRecord`. Per RFC 6762, a goodbye message of a record sets its TTL
603*4a64e381SAndroid Build Coastguard Worker // to zero but the receiver should record the TTL of 1 and flushes the cache 1 second later. Here
604*4a64e381SAndroid Build Coastguard Worker // we remove the AAAA record after updating its TTL to 1 second. This has the same effect as
605*4a64e381SAndroid Build Coastguard Worker // sending a goodbye message.
606*4a64e381SAndroid Build Coastguard Worker // TODO: resolve the goodbye issue with Bonjour mDNSResponder.
607*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceUpdateRecord(GetPublisher().mHostsRef, mAddrRecordRefs[index], kDNSServiceFlagsUnique,
608*4a64e381SAndroid Build Coastguard Worker sizeof(address.m8), address.m8, /* ttl */ 1);
609*4a64e381SAndroid Build Coastguard Worker otbrLogResult(DNSErrorToOtbrError(dnsError), "Send goodbye message for host %s address %s: %s",
610*4a64e381SAndroid Build Coastguard Worker MakeFullHostName(mName).c_str(), address.ToString().c_str(), DNSErrorToString(dnsError));
611*4a64e381SAndroid Build Coastguard Worker }
612*4a64e381SAndroid Build Coastguard Worker
613*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceRemoveRecord(GetPublisher().mHostsRef, mAddrRecordRefs[index], /* flags */ 0);
614*4a64e381SAndroid Build Coastguard Worker
615*4a64e381SAndroid Build Coastguard Worker otbrLogResult(DNSErrorToOtbrError(dnsError), "Remove record for host %s address %s: %s",
616*4a64e381SAndroid Build Coastguard Worker MakeFullHostName(mName).c_str(), address.ToString().c_str(), DNSErrorToString(dnsError));
617*4a64e381SAndroid Build Coastguard Worker }
618*4a64e381SAndroid Build Coastguard Worker
619*4a64e381SAndroid Build Coastguard Worker exit:
620*4a64e381SAndroid Build Coastguard Worker mAddrRegistered.clear();
621*4a64e381SAndroid Build Coastguard Worker mAddrRecordRefs.clear();
622*4a64e381SAndroid Build Coastguard Worker }
623*4a64e381SAndroid Build Coastguard Worker
HandleRegisterResult(DNSServiceRef aServiceRef,DNSRecordRef aRecordRef,DNSServiceFlags aFlags,DNSServiceErrorType aError,void * aContext)624*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdHostRegistration::HandleRegisterResult(DNSServiceRef aServiceRef,
625*4a64e381SAndroid Build Coastguard Worker DNSRecordRef aRecordRef,
626*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
627*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aError,
628*4a64e381SAndroid Build Coastguard Worker void *aContext)
629*4a64e381SAndroid Build Coastguard Worker {
630*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aServiceRef);
631*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aFlags);
632*4a64e381SAndroid Build Coastguard Worker
633*4a64e381SAndroid Build Coastguard Worker static_cast<DnssdHostRegistration *>(aContext)->HandleRegisterResult(aRecordRef, aError);
634*4a64e381SAndroid Build Coastguard Worker }
635*4a64e381SAndroid Build Coastguard Worker
HandleRegisterResult(DNSRecordRef aRecordRef,DNSServiceErrorType aError)636*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdHostRegistration::HandleRegisterResult(DNSRecordRef aRecordRef, DNSServiceErrorType aError)
637*4a64e381SAndroid Build Coastguard Worker {
638*4a64e381SAndroid Build Coastguard Worker if (aError != kDNSServiceErr_NoError)
639*4a64e381SAndroid Build Coastguard Worker {
640*4a64e381SAndroid Build Coastguard Worker otbrLogErr("Failed to register host %s: %s", mName.c_str(), DNSErrorToString(aError));
641*4a64e381SAndroid Build Coastguard Worker GetPublisher().RemoveHostRegistration(mName, DNSErrorToOtbrError(aError));
642*4a64e381SAndroid Build Coastguard Worker }
643*4a64e381SAndroid Build Coastguard Worker else
644*4a64e381SAndroid Build Coastguard Worker {
645*4a64e381SAndroid Build Coastguard Worker bool shouldComplete = !IsCompleted();
646*4a64e381SAndroid Build Coastguard Worker
647*4a64e381SAndroid Build Coastguard Worker for (size_t index = 0; index < mAddrRecordRefs.size(); index++)
648*4a64e381SAndroid Build Coastguard Worker {
649*4a64e381SAndroid Build Coastguard Worker if ((mAddrRecordRefs[index] == aRecordRef) && !mAddrRegistered[index])
650*4a64e381SAndroid Build Coastguard Worker {
651*4a64e381SAndroid Build Coastguard Worker mAddrRegistered[index] = true;
652*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Successfully registered host %s address %s", mName.c_str(),
653*4a64e381SAndroid Build Coastguard Worker mAddresses[index].ToString().c_str());
654*4a64e381SAndroid Build Coastguard Worker }
655*4a64e381SAndroid Build Coastguard Worker
656*4a64e381SAndroid Build Coastguard Worker if (!mAddrRegistered[index])
657*4a64e381SAndroid Build Coastguard Worker {
658*4a64e381SAndroid Build Coastguard Worker shouldComplete = false;
659*4a64e381SAndroid Build Coastguard Worker }
660*4a64e381SAndroid Build Coastguard Worker }
661*4a64e381SAndroid Build Coastguard Worker
662*4a64e381SAndroid Build Coastguard Worker if (shouldComplete)
663*4a64e381SAndroid Build Coastguard Worker {
664*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Successfully registered all host %s addresses", mName.c_str());
665*4a64e381SAndroid Build Coastguard Worker Complete(OTBR_ERROR_NONE);
666*4a64e381SAndroid Build Coastguard Worker }
667*4a64e381SAndroid Build Coastguard Worker }
668*4a64e381SAndroid Build Coastguard Worker }
669*4a64e381SAndroid Build Coastguard Worker
Register(void)670*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::DnssdKeyRegistration::Register(void)
671*4a64e381SAndroid Build Coastguard Worker {
672*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType dnsError = kDNSServiceErr_NoError;
673*4a64e381SAndroid Build Coastguard Worker DnssdServiceRegistration *serviceReg;
674*4a64e381SAndroid Build Coastguard Worker
675*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Registering new key %s", mName.c_str());
676*4a64e381SAndroid Build Coastguard Worker
677*4a64e381SAndroid Build Coastguard Worker serviceReg = static_cast<DnssdServiceRegistration *>(GetPublisher().FindServiceRegistration(mName));
678*4a64e381SAndroid Build Coastguard Worker
679*4a64e381SAndroid Build Coastguard Worker if ((serviceReg != nullptr) && (serviceReg->mServiceRef != nullptr))
680*4a64e381SAndroid Build Coastguard Worker {
681*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Key %s is being registered as a record of an existing service registration", mName.c_str());
682*4a64e381SAndroid Build Coastguard Worker
683*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceAddRecord(serviceReg->mServiceRef, &mRecordRef, kDNSServiceFlagsUnique,
684*4a64e381SAndroid Build Coastguard Worker kDNSServiceType_KEY, mKeyData.size(), mKeyData.data(), /* ttl */ 0);
685*4a64e381SAndroid Build Coastguard Worker
686*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(dnsError == kDNSServiceErr_NoError);
687*4a64e381SAndroid Build Coastguard Worker
688*4a64e381SAndroid Build Coastguard Worker mRelatedServiceReg = serviceReg;
689*4a64e381SAndroid Build Coastguard Worker serviceReg->mRelatedKeyReg = this;
690*4a64e381SAndroid Build Coastguard Worker
691*4a64e381SAndroid Build Coastguard Worker if (mRelatedServiceReg->IsCompleted())
692*4a64e381SAndroid Build Coastguard Worker {
693*4a64e381SAndroid Build Coastguard Worker HandleRegisterResult(kDNSServiceErr_NoError);
694*4a64e381SAndroid Build Coastguard Worker }
695*4a64e381SAndroid Build Coastguard Worker
696*4a64e381SAndroid Build Coastguard Worker // If related service registration is not yet finished,
697*4a64e381SAndroid Build Coastguard Worker // we wait for service registration completion to signal
698*4a64e381SAndroid Build Coastguard Worker // key record registration as well.
699*4a64e381SAndroid Build Coastguard Worker }
700*4a64e381SAndroid Build Coastguard Worker else
701*4a64e381SAndroid Build Coastguard Worker {
702*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Key %s is being registered individually", mName.c_str());
703*4a64e381SAndroid Build Coastguard Worker
704*4a64e381SAndroid Build Coastguard Worker dnsError = GetPublisher().CreateSharedHostsRef();
705*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(dnsError == kDNSServiceErr_NoError);
706*4a64e381SAndroid Build Coastguard Worker
707*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceRegisterRecord(GetPublisher().mHostsRef, &mRecordRef, kDNSServiceFlagsUnique,
708*4a64e381SAndroid Build Coastguard Worker kDNSServiceInterfaceIndexAny, MakeFullKeyName(mName).c_str(),
709*4a64e381SAndroid Build Coastguard Worker kDNSServiceType_KEY, kDNSServiceClass_IN, mKeyData.size(), mKeyData.data(),
710*4a64e381SAndroid Build Coastguard Worker /* ttl */ 0, HandleRegisterResult, this);
711*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(dnsError == kDNSServiceErr_NoError);
712*4a64e381SAndroid Build Coastguard Worker }
713*4a64e381SAndroid Build Coastguard Worker
714*4a64e381SAndroid Build Coastguard Worker exit:
715*4a64e381SAndroid Build Coastguard Worker if (dnsError != kDNSServiceErr_NoError)
716*4a64e381SAndroid Build Coastguard Worker {
717*4a64e381SAndroid Build Coastguard Worker HandleRegisterResult(dnsError);
718*4a64e381SAndroid Build Coastguard Worker }
719*4a64e381SAndroid Build Coastguard Worker
720*4a64e381SAndroid Build Coastguard Worker return GetPublisher().DnsErrorToOtbrError(dnsError);
721*4a64e381SAndroid Build Coastguard Worker }
722*4a64e381SAndroid Build Coastguard Worker
Unregister(void)723*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdKeyRegistration::Unregister(void)
724*4a64e381SAndroid Build Coastguard Worker {
725*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType dnsError;
726*4a64e381SAndroid Build Coastguard Worker DNSServiceRef serviceRef;
727*4a64e381SAndroid Build Coastguard Worker
728*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mRecordRef != nullptr);
729*4a64e381SAndroid Build Coastguard Worker
730*4a64e381SAndroid Build Coastguard Worker if (mRelatedServiceReg != nullptr)
731*4a64e381SAndroid Build Coastguard Worker {
732*4a64e381SAndroid Build Coastguard Worker serviceRef = mRelatedServiceReg->mServiceRef;
733*4a64e381SAndroid Build Coastguard Worker
734*4a64e381SAndroid Build Coastguard Worker mRelatedServiceReg->mRelatedKeyReg = nullptr;
735*4a64e381SAndroid Build Coastguard Worker mRelatedServiceReg = nullptr;
736*4a64e381SAndroid Build Coastguard Worker
737*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Unregistering key %s (was registered as a record of a service)", mName.c_str());
738*4a64e381SAndroid Build Coastguard Worker }
739*4a64e381SAndroid Build Coastguard Worker else
740*4a64e381SAndroid Build Coastguard Worker {
741*4a64e381SAndroid Build Coastguard Worker serviceRef = GetPublisher().mHostsRef;
742*4a64e381SAndroid Build Coastguard Worker
743*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Unregistering key %s (was registered individually)", mName.c_str());
744*4a64e381SAndroid Build Coastguard Worker }
745*4a64e381SAndroid Build Coastguard Worker
746*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(serviceRef != nullptr);
747*4a64e381SAndroid Build Coastguard Worker
748*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceRemoveRecord(serviceRef, mRecordRef, /* flags */ 0);
749*4a64e381SAndroid Build Coastguard Worker
750*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Unregistered key %s: error:%s", mName.c_str(), DNSErrorToString(dnsError));
751*4a64e381SAndroid Build Coastguard Worker
752*4a64e381SAndroid Build Coastguard Worker exit:
753*4a64e381SAndroid Build Coastguard Worker return;
754*4a64e381SAndroid Build Coastguard Worker }
755*4a64e381SAndroid Build Coastguard Worker
HandleRegisterResult(DNSServiceRef aServiceRef,DNSRecordRef aRecordRef,DNSServiceFlags aFlags,DNSServiceErrorType aError,void * aContext)756*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdKeyRegistration::HandleRegisterResult(DNSServiceRef aServiceRef,
757*4a64e381SAndroid Build Coastguard Worker DNSRecordRef aRecordRef,
758*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
759*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aError,
760*4a64e381SAndroid Build Coastguard Worker void *aContext)
761*4a64e381SAndroid Build Coastguard Worker {
762*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aServiceRef);
763*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aRecordRef);
764*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aFlags);
765*4a64e381SAndroid Build Coastguard Worker
766*4a64e381SAndroid Build Coastguard Worker static_cast<DnssdKeyRegistration *>(aContext)->HandleRegisterResult(aError);
767*4a64e381SAndroid Build Coastguard Worker }
768*4a64e381SAndroid Build Coastguard Worker
HandleRegisterResult(DNSServiceErrorType aError)769*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::DnssdKeyRegistration::HandleRegisterResult(DNSServiceErrorType aError)
770*4a64e381SAndroid Build Coastguard Worker {
771*4a64e381SAndroid Build Coastguard Worker if (aError != kDNSServiceErr_NoError)
772*4a64e381SAndroid Build Coastguard Worker {
773*4a64e381SAndroid Build Coastguard Worker otbrLogErr("Failed to register key %s: %s", mName.c_str(), DNSErrorToString(aError));
774*4a64e381SAndroid Build Coastguard Worker GetPublisher().RemoveKeyRegistration(mName, DNSErrorToOtbrError(aError));
775*4a64e381SAndroid Build Coastguard Worker }
776*4a64e381SAndroid Build Coastguard Worker else
777*4a64e381SAndroid Build Coastguard Worker {
778*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Successfully registered key %s", mName.c_str());
779*4a64e381SAndroid Build Coastguard Worker Complete(OTBR_ERROR_NONE);
780*4a64e381SAndroid Build Coastguard Worker }
781*4a64e381SAndroid Build Coastguard Worker }
782*4a64e381SAndroid Build Coastguard Worker
PublishServiceImpl(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtData & aTxtData,ResultCallback && aCallback)783*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::PublishServiceImpl(const std::string &aHostName,
784*4a64e381SAndroid Build Coastguard Worker const std::string &aName,
785*4a64e381SAndroid Build Coastguard Worker const std::string &aType,
786*4a64e381SAndroid Build Coastguard Worker const SubTypeList &aSubTypeList,
787*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
788*4a64e381SAndroid Build Coastguard Worker const TxtData &aTxtData,
789*4a64e381SAndroid Build Coastguard Worker ResultCallback &&aCallback)
790*4a64e381SAndroid Build Coastguard Worker {
791*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
792*4a64e381SAndroid Build Coastguard Worker SubTypeList sortedSubTypeList = SortSubTypeList(aSubTypeList);
793*4a64e381SAndroid Build Coastguard Worker std::string regType = MakeRegType(aType, sortedSubTypeList);
794*4a64e381SAndroid Build Coastguard Worker DnssdServiceRegistration *serviceReg;
795*4a64e381SAndroid Build Coastguard Worker
796*4a64e381SAndroid Build Coastguard Worker if (mState != State::kReady)
797*4a64e381SAndroid Build Coastguard Worker {
798*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_INVALID_STATE;
799*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(error);
800*4a64e381SAndroid Build Coastguard Worker ExitNow();
801*4a64e381SAndroid Build Coastguard Worker }
802*4a64e381SAndroid Build Coastguard Worker
803*4a64e381SAndroid Build Coastguard Worker aCallback = HandleDuplicateServiceRegistration(aHostName, aName, aType, sortedSubTypeList, aPort, aTxtData,
804*4a64e381SAndroid Build Coastguard Worker std::move(aCallback));
805*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(!aCallback.IsNull());
806*4a64e381SAndroid Build Coastguard Worker
807*4a64e381SAndroid Build Coastguard Worker serviceReg = new DnssdServiceRegistration(aHostName, aName, aType, sortedSubTypeList, aPort, aTxtData,
808*4a64e381SAndroid Build Coastguard Worker std::move(aCallback), this);
809*4a64e381SAndroid Build Coastguard Worker AddServiceRegistration(std::unique_ptr<DnssdServiceRegistration>(serviceReg));
810*4a64e381SAndroid Build Coastguard Worker
811*4a64e381SAndroid Build Coastguard Worker error = serviceReg->Register();
812*4a64e381SAndroid Build Coastguard Worker
813*4a64e381SAndroid Build Coastguard Worker exit:
814*4a64e381SAndroid Build Coastguard Worker return error;
815*4a64e381SAndroid Build Coastguard Worker }
816*4a64e381SAndroid Build Coastguard Worker
UnpublishService(const std::string & aName,const std::string & aType,ResultCallback && aCallback)817*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::UnpublishService(const std::string &aName, const std::string &aType, ResultCallback &&aCallback)
818*4a64e381SAndroid Build Coastguard Worker {
819*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
820*4a64e381SAndroid Build Coastguard Worker
821*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
822*4a64e381SAndroid Build Coastguard Worker RemoveServiceRegistration(aName, aType, OTBR_ERROR_ABORTED);
823*4a64e381SAndroid Build Coastguard Worker
824*4a64e381SAndroid Build Coastguard Worker exit:
825*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(error);
826*4a64e381SAndroid Build Coastguard Worker }
827*4a64e381SAndroid Build Coastguard Worker
PublishHostImpl(const std::string & aName,const AddressList & aAddresses,ResultCallback && aCallback)828*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::PublishHostImpl(const std::string &aName,
829*4a64e381SAndroid Build Coastguard Worker const AddressList &aAddresses,
830*4a64e381SAndroid Build Coastguard Worker ResultCallback &&aCallback)
831*4a64e381SAndroid Build Coastguard Worker {
832*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
833*4a64e381SAndroid Build Coastguard Worker DnssdHostRegistration *hostReg;
834*4a64e381SAndroid Build Coastguard Worker
835*4a64e381SAndroid Build Coastguard Worker if (mState != State::kReady)
836*4a64e381SAndroid Build Coastguard Worker {
837*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_INVALID_STATE;
838*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(error);
839*4a64e381SAndroid Build Coastguard Worker ExitNow();
840*4a64e381SAndroid Build Coastguard Worker }
841*4a64e381SAndroid Build Coastguard Worker
842*4a64e381SAndroid Build Coastguard Worker aCallback = HandleDuplicateHostRegistration(aName, aAddresses, std::move(aCallback));
843*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(!aCallback.IsNull());
844*4a64e381SAndroid Build Coastguard Worker
845*4a64e381SAndroid Build Coastguard Worker hostReg = new DnssdHostRegistration(aName, aAddresses, std::move(aCallback), this);
846*4a64e381SAndroid Build Coastguard Worker AddHostRegistration(std::unique_ptr<DnssdHostRegistration>(hostReg));
847*4a64e381SAndroid Build Coastguard Worker
848*4a64e381SAndroid Build Coastguard Worker error = hostReg->Register();
849*4a64e381SAndroid Build Coastguard Worker
850*4a64e381SAndroid Build Coastguard Worker exit:
851*4a64e381SAndroid Build Coastguard Worker return error;
852*4a64e381SAndroid Build Coastguard Worker }
853*4a64e381SAndroid Build Coastguard Worker
UnpublishHost(const std::string & aName,ResultCallback && aCallback)854*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::UnpublishHost(const std::string &aName, ResultCallback &&aCallback)
855*4a64e381SAndroid Build Coastguard Worker {
856*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
857*4a64e381SAndroid Build Coastguard Worker
858*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
859*4a64e381SAndroid Build Coastguard Worker RemoveHostRegistration(aName, OTBR_ERROR_ABORTED);
860*4a64e381SAndroid Build Coastguard Worker
861*4a64e381SAndroid Build Coastguard Worker exit:
862*4a64e381SAndroid Build Coastguard Worker // We may failed to unregister the host from underlying mDNS publishers, but
863*4a64e381SAndroid Build Coastguard Worker // it usually means that the mDNS publisher is already not functioning. So it's
864*4a64e381SAndroid Build Coastguard Worker // okay to return success directly since the service is not advertised anyway.
865*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(error);
866*4a64e381SAndroid Build Coastguard Worker }
867*4a64e381SAndroid Build Coastguard Worker
PublishKeyImpl(const std::string & aName,const KeyData & aKeyData,ResultCallback && aCallback)868*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::PublishKeyImpl(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback)
869*4a64e381SAndroid Build Coastguard Worker {
870*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
871*4a64e381SAndroid Build Coastguard Worker DnssdKeyRegistration *keyReg;
872*4a64e381SAndroid Build Coastguard Worker
873*4a64e381SAndroid Build Coastguard Worker if (mState != State::kReady)
874*4a64e381SAndroid Build Coastguard Worker {
875*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_INVALID_STATE;
876*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(error);
877*4a64e381SAndroid Build Coastguard Worker ExitNow();
878*4a64e381SAndroid Build Coastguard Worker }
879*4a64e381SAndroid Build Coastguard Worker
880*4a64e381SAndroid Build Coastguard Worker aCallback = HandleDuplicateKeyRegistration(aName, aKeyData, std::move(aCallback));
881*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(!aCallback.IsNull());
882*4a64e381SAndroid Build Coastguard Worker
883*4a64e381SAndroid Build Coastguard Worker keyReg = new DnssdKeyRegistration(aName, aKeyData, std::move(aCallback), this);
884*4a64e381SAndroid Build Coastguard Worker AddKeyRegistration(std::unique_ptr<DnssdKeyRegistration>(keyReg));
885*4a64e381SAndroid Build Coastguard Worker
886*4a64e381SAndroid Build Coastguard Worker error = keyReg->Register();
887*4a64e381SAndroid Build Coastguard Worker
888*4a64e381SAndroid Build Coastguard Worker exit:
889*4a64e381SAndroid Build Coastguard Worker return error;
890*4a64e381SAndroid Build Coastguard Worker }
891*4a64e381SAndroid Build Coastguard Worker
UnpublishKey(const std::string & aName,ResultCallback && aCallback)892*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::UnpublishKey(const std::string &aName, ResultCallback &&aCallback)
893*4a64e381SAndroid Build Coastguard Worker {
894*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
895*4a64e381SAndroid Build Coastguard Worker
896*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == Publisher::State::kReady, error = OTBR_ERROR_INVALID_STATE);
897*4a64e381SAndroid Build Coastguard Worker RemoveKeyRegistration(aName, OTBR_ERROR_ABORTED);
898*4a64e381SAndroid Build Coastguard Worker
899*4a64e381SAndroid Build Coastguard Worker exit:
900*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(error);
901*4a64e381SAndroid Build Coastguard Worker }
902*4a64e381SAndroid Build Coastguard Worker
903*4a64e381SAndroid Build Coastguard Worker // See `regtype` parameter of the DNSServiceRegister() function for more information.
MakeRegType(const std::string & aType,SubTypeList aSubTypeList)904*4a64e381SAndroid Build Coastguard Worker std::string PublisherMDnsSd::MakeRegType(const std::string &aType, SubTypeList aSubTypeList)
905*4a64e381SAndroid Build Coastguard Worker {
906*4a64e381SAndroid Build Coastguard Worker std::string regType = aType;
907*4a64e381SAndroid Build Coastguard Worker
908*4a64e381SAndroid Build Coastguard Worker std::sort(aSubTypeList.begin(), aSubTypeList.end());
909*4a64e381SAndroid Build Coastguard Worker
910*4a64e381SAndroid Build Coastguard Worker for (const auto &subType : aSubTypeList)
911*4a64e381SAndroid Build Coastguard Worker {
912*4a64e381SAndroid Build Coastguard Worker regType += "," + subType;
913*4a64e381SAndroid Build Coastguard Worker }
914*4a64e381SAndroid Build Coastguard Worker
915*4a64e381SAndroid Build Coastguard Worker return regType;
916*4a64e381SAndroid Build Coastguard Worker }
917*4a64e381SAndroid Build Coastguard Worker
SubscribeService(const std::string & aType,const std::string & aInstanceName)918*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::SubscribeService(const std::string &aType, const std::string &aInstanceName)
919*4a64e381SAndroid Build Coastguard Worker {
920*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == Publisher::State::kReady);
921*4a64e381SAndroid Build Coastguard Worker mSubscribedServices.push_back(MakeUnique<ServiceSubscription>(*this, aType, aInstanceName));
922*4a64e381SAndroid Build Coastguard Worker
923*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Subscribe service %s.%s (total %zu)", aInstanceName.c_str(), aType.c_str(),
924*4a64e381SAndroid Build Coastguard Worker mSubscribedServices.size());
925*4a64e381SAndroid Build Coastguard Worker
926*4a64e381SAndroid Build Coastguard Worker if (aInstanceName.empty())
927*4a64e381SAndroid Build Coastguard Worker {
928*4a64e381SAndroid Build Coastguard Worker mSubscribedServices.back()->Browse();
929*4a64e381SAndroid Build Coastguard Worker }
930*4a64e381SAndroid Build Coastguard Worker else
931*4a64e381SAndroid Build Coastguard Worker {
932*4a64e381SAndroid Build Coastguard Worker mSubscribedServices.back()->Resolve(kDNSServiceInterfaceIndexAny, aInstanceName, aType, kDomain);
933*4a64e381SAndroid Build Coastguard Worker }
934*4a64e381SAndroid Build Coastguard Worker
935*4a64e381SAndroid Build Coastguard Worker exit:
936*4a64e381SAndroid Build Coastguard Worker return;
937*4a64e381SAndroid Build Coastguard Worker }
938*4a64e381SAndroid Build Coastguard Worker
UnsubscribeService(const std::string & aType,const std::string & aInstanceName)939*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::UnsubscribeService(const std::string &aType, const std::string &aInstanceName)
940*4a64e381SAndroid Build Coastguard Worker {
941*4a64e381SAndroid Build Coastguard Worker ServiceSubscriptionList::iterator it;
942*4a64e381SAndroid Build Coastguard Worker
943*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == Publisher::State::kReady);
944*4a64e381SAndroid Build Coastguard Worker it = std::find_if(mSubscribedServices.begin(), mSubscribedServices.end(),
945*4a64e381SAndroid Build Coastguard Worker [&aType, &aInstanceName](const std::unique_ptr<ServiceSubscription> &aService) {
946*4a64e381SAndroid Build Coastguard Worker return aService->mType == aType && aService->mInstanceName == aInstanceName;
947*4a64e381SAndroid Build Coastguard Worker });
948*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(it != mSubscribedServices.end());
949*4a64e381SAndroid Build Coastguard Worker
950*4a64e381SAndroid Build Coastguard Worker mSubscribedServices.erase(it);
951*4a64e381SAndroid Build Coastguard Worker
952*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Unsubscribe service %s.%s (left %zu)", aInstanceName.c_str(), aType.c_str(),
953*4a64e381SAndroid Build Coastguard Worker mSubscribedServices.size());
954*4a64e381SAndroid Build Coastguard Worker
955*4a64e381SAndroid Build Coastguard Worker exit:
956*4a64e381SAndroid Build Coastguard Worker return;
957*4a64e381SAndroid Build Coastguard Worker }
958*4a64e381SAndroid Build Coastguard Worker
OnServiceResolveFailedImpl(const std::string & aType,const std::string & aInstanceName,int32_t aErrorCode)959*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::OnServiceResolveFailedImpl(const std::string &aType,
960*4a64e381SAndroid Build Coastguard Worker const std::string &aInstanceName,
961*4a64e381SAndroid Build Coastguard Worker int32_t aErrorCode)
962*4a64e381SAndroid Build Coastguard Worker {
963*4a64e381SAndroid Build Coastguard Worker otbrLogWarning("Resolve service %s.%s failed: code=%" PRId32, aInstanceName.c_str(), aType.c_str(), aErrorCode);
964*4a64e381SAndroid Build Coastguard Worker }
965*4a64e381SAndroid Build Coastguard Worker
OnHostResolveFailedImpl(const std::string & aHostName,int32_t aErrorCode)966*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::OnHostResolveFailedImpl(const std::string &aHostName, int32_t aErrorCode)
967*4a64e381SAndroid Build Coastguard Worker {
968*4a64e381SAndroid Build Coastguard Worker otbrLogWarning("Resolve host %s failed: code=%" PRId32, aHostName.c_str(), aErrorCode);
969*4a64e381SAndroid Build Coastguard Worker }
970*4a64e381SAndroid Build Coastguard Worker
DnsErrorToOtbrError(int32_t aErrorCode)971*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::DnsErrorToOtbrError(int32_t aErrorCode)
972*4a64e381SAndroid Build Coastguard Worker {
973*4a64e381SAndroid Build Coastguard Worker return otbr::Mdns::DNSErrorToOtbrError(aErrorCode);
974*4a64e381SAndroid Build Coastguard Worker }
975*4a64e381SAndroid Build Coastguard Worker
SubscribeHost(const std::string & aHostName)976*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::SubscribeHost(const std::string &aHostName)
977*4a64e381SAndroid Build Coastguard Worker {
978*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == State::kReady);
979*4a64e381SAndroid Build Coastguard Worker mSubscribedHosts.push_back(MakeUnique<HostSubscription>(*this, aHostName));
980*4a64e381SAndroid Build Coastguard Worker
981*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Subscribe host %s (total %zu)", aHostName.c_str(), mSubscribedHosts.size());
982*4a64e381SAndroid Build Coastguard Worker
983*4a64e381SAndroid Build Coastguard Worker mSubscribedHosts.back()->Resolve();
984*4a64e381SAndroid Build Coastguard Worker
985*4a64e381SAndroid Build Coastguard Worker exit:
986*4a64e381SAndroid Build Coastguard Worker return;
987*4a64e381SAndroid Build Coastguard Worker }
988*4a64e381SAndroid Build Coastguard Worker
UnsubscribeHost(const std::string & aHostName)989*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::UnsubscribeHost(const std::string &aHostName)
990*4a64e381SAndroid Build Coastguard Worker {
991*4a64e381SAndroid Build Coastguard Worker HostSubscriptionList ::iterator it;
992*4a64e381SAndroid Build Coastguard Worker
993*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mState == Publisher::State::kReady);
994*4a64e381SAndroid Build Coastguard Worker it = std::find_if(
995*4a64e381SAndroid Build Coastguard Worker mSubscribedHosts.begin(), mSubscribedHosts.end(),
996*4a64e381SAndroid Build Coastguard Worker [&aHostName](const std::unique_ptr<HostSubscription> &aHost) { return aHost->mHostName == aHostName; });
997*4a64e381SAndroid Build Coastguard Worker
998*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(it != mSubscribedHosts.end());
999*4a64e381SAndroid Build Coastguard Worker
1000*4a64e381SAndroid Build Coastguard Worker mSubscribedHosts.erase(it);
1001*4a64e381SAndroid Build Coastguard Worker
1002*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Unsubscribe host %s (remaining %d)", aHostName.c_str(), mSubscribedHosts.size());
1003*4a64e381SAndroid Build Coastguard Worker
1004*4a64e381SAndroid Build Coastguard Worker exit:
1005*4a64e381SAndroid Build Coastguard Worker return;
1006*4a64e381SAndroid Build Coastguard Worker }
1007*4a64e381SAndroid Build Coastguard Worker
Create(StateCallback aCallback)1008*4a64e381SAndroid Build Coastguard Worker Publisher *Publisher::Create(StateCallback aCallback)
1009*4a64e381SAndroid Build Coastguard Worker {
1010*4a64e381SAndroid Build Coastguard Worker return new PublisherMDnsSd(aCallback);
1011*4a64e381SAndroid Build Coastguard Worker }
1012*4a64e381SAndroid Build Coastguard Worker
Destroy(Publisher * aPublisher)1013*4a64e381SAndroid Build Coastguard Worker void Publisher::Destroy(Publisher *aPublisher)
1014*4a64e381SAndroid Build Coastguard Worker {
1015*4a64e381SAndroid Build Coastguard Worker delete static_cast<PublisherMDnsSd *>(aPublisher);
1016*4a64e381SAndroid Build Coastguard Worker }
1017*4a64e381SAndroid Build Coastguard Worker
Release(void)1018*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceRef::Release(void)
1019*4a64e381SAndroid Build Coastguard Worker {
1020*4a64e381SAndroid Build Coastguard Worker DeallocateServiceRef();
1021*4a64e381SAndroid Build Coastguard Worker }
1022*4a64e381SAndroid Build Coastguard Worker
DeallocateServiceRef(void)1023*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceRef::DeallocateServiceRef(void)
1024*4a64e381SAndroid Build Coastguard Worker {
1025*4a64e381SAndroid Build Coastguard Worker if (mServiceRef != nullptr)
1026*4a64e381SAndroid Build Coastguard Worker {
1027*4a64e381SAndroid Build Coastguard Worker mPublisher.HandleServiceRefDeallocating(mServiceRef);
1028*4a64e381SAndroid Build Coastguard Worker DNSServiceRefDeallocate(mServiceRef);
1029*4a64e381SAndroid Build Coastguard Worker mServiceRef = nullptr;
1030*4a64e381SAndroid Build Coastguard Worker }
1031*4a64e381SAndroid Build Coastguard Worker }
1032*4a64e381SAndroid Build Coastguard Worker
Update(MainloopContext & aMainloop) const1033*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceRef::Update(MainloopContext &aMainloop) const
1034*4a64e381SAndroid Build Coastguard Worker {
1035*4a64e381SAndroid Build Coastguard Worker int fd;
1036*4a64e381SAndroid Build Coastguard Worker
1037*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mServiceRef != nullptr);
1038*4a64e381SAndroid Build Coastguard Worker
1039*4a64e381SAndroid Build Coastguard Worker fd = DNSServiceRefSockFD(mServiceRef);
1040*4a64e381SAndroid Build Coastguard Worker assert(fd != -1);
1041*4a64e381SAndroid Build Coastguard Worker aMainloop.AddFdToReadSet(fd);
1042*4a64e381SAndroid Build Coastguard Worker exit:
1043*4a64e381SAndroid Build Coastguard Worker return;
1044*4a64e381SAndroid Build Coastguard Worker }
1045*4a64e381SAndroid Build Coastguard Worker
Process(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const1046*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceRef::Process(const MainloopContext &aMainloop,
1047*4a64e381SAndroid Build Coastguard Worker std::vector<DNSServiceRef> &aReadyServices) const
1048*4a64e381SAndroid Build Coastguard Worker {
1049*4a64e381SAndroid Build Coastguard Worker int fd;
1050*4a64e381SAndroid Build Coastguard Worker
1051*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mServiceRef != nullptr);
1052*4a64e381SAndroid Build Coastguard Worker
1053*4a64e381SAndroid Build Coastguard Worker fd = DNSServiceRefSockFD(mServiceRef);
1054*4a64e381SAndroid Build Coastguard Worker assert(fd != -1);
1055*4a64e381SAndroid Build Coastguard Worker if (FD_ISSET(fd, &aMainloop.mReadFdSet))
1056*4a64e381SAndroid Build Coastguard Worker {
1057*4a64e381SAndroid Build Coastguard Worker aReadyServices.push_back(mServiceRef);
1058*4a64e381SAndroid Build Coastguard Worker }
1059*4a64e381SAndroid Build Coastguard Worker exit:
1060*4a64e381SAndroid Build Coastguard Worker return;
1061*4a64e381SAndroid Build Coastguard Worker }
1062*4a64e381SAndroid Build Coastguard Worker
Browse(void)1063*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceSubscription::Browse(void)
1064*4a64e381SAndroid Build Coastguard Worker {
1065*4a64e381SAndroid Build Coastguard Worker assert(mServiceRef == nullptr);
1066*4a64e381SAndroid Build Coastguard Worker
1067*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceBrowse %s", mType.c_str());
1068*4a64e381SAndroid Build Coastguard Worker DNSServiceBrowse(&mServiceRef, /* flags */ 0, kDNSServiceInterfaceIndexAny, mType.c_str(),
1069*4a64e381SAndroid Build Coastguard Worker /* domain */ nullptr, HandleBrowseResult, this);
1070*4a64e381SAndroid Build Coastguard Worker }
1071*4a64e381SAndroid Build Coastguard Worker
HandleBrowseResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aInstanceName,const char * aType,const char * aDomain,void * aContext)1072*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceSubscription::HandleBrowseResult(DNSServiceRef aServiceRef,
1073*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1074*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1075*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1076*4a64e381SAndroid Build Coastguard Worker const char *aInstanceName,
1077*4a64e381SAndroid Build Coastguard Worker const char *aType,
1078*4a64e381SAndroid Build Coastguard Worker const char *aDomain,
1079*4a64e381SAndroid Build Coastguard Worker void *aContext)
1080*4a64e381SAndroid Build Coastguard Worker {
1081*4a64e381SAndroid Build Coastguard Worker static_cast<ServiceSubscription *>(aContext)->HandleBrowseResult(aServiceRef, aFlags, aInterfaceIndex, aErrorCode,
1082*4a64e381SAndroid Build Coastguard Worker aInstanceName, aType, aDomain);
1083*4a64e381SAndroid Build Coastguard Worker }
1084*4a64e381SAndroid Build Coastguard Worker
HandleBrowseResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aInstanceName,const char * aType,const char * aDomain)1085*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceSubscription::HandleBrowseResult(DNSServiceRef aServiceRef,
1086*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1087*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1088*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1089*4a64e381SAndroid Build Coastguard Worker const char *aInstanceName,
1090*4a64e381SAndroid Build Coastguard Worker const char *aType,
1091*4a64e381SAndroid Build Coastguard Worker const char *aDomain)
1092*4a64e381SAndroid Build Coastguard Worker {
1093*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aServiceRef);
1094*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aDomain);
1095*4a64e381SAndroid Build Coastguard Worker
1096*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceBrowse reply: %s %s.%s inf %" PRIu32 ", flags=%" PRIu32 ", error=%" PRId32,
1097*4a64e381SAndroid Build Coastguard Worker aFlags & kDNSServiceFlagsAdd ? "add" : "remove", aInstanceName, aType, aInterfaceIndex, aFlags,
1098*4a64e381SAndroid Build Coastguard Worker aErrorCode);
1099*4a64e381SAndroid Build Coastguard Worker
1100*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1101*4a64e381SAndroid Build Coastguard Worker
1102*4a64e381SAndroid Build Coastguard Worker if (aFlags & kDNSServiceFlagsAdd)
1103*4a64e381SAndroid Build Coastguard Worker {
1104*4a64e381SAndroid Build Coastguard Worker Resolve(aInterfaceIndex, aInstanceName, aType, aDomain);
1105*4a64e381SAndroid Build Coastguard Worker }
1106*4a64e381SAndroid Build Coastguard Worker else
1107*4a64e381SAndroid Build Coastguard Worker {
1108*4a64e381SAndroid Build Coastguard Worker mPublisher.OnServiceRemoved(aInterfaceIndex, mType, aInstanceName);
1109*4a64e381SAndroid Build Coastguard Worker }
1110*4a64e381SAndroid Build Coastguard Worker
1111*4a64e381SAndroid Build Coastguard Worker exit:
1112*4a64e381SAndroid Build Coastguard Worker if (aErrorCode != kDNSServiceErr_NoError)
1113*4a64e381SAndroid Build Coastguard Worker {
1114*4a64e381SAndroid Build Coastguard Worker mPublisher.OnServiceResolveFailed(mType, mInstanceName, aErrorCode);
1115*4a64e381SAndroid Build Coastguard Worker Release();
1116*4a64e381SAndroid Build Coastguard Worker }
1117*4a64e381SAndroid Build Coastguard Worker }
1118*4a64e381SAndroid Build Coastguard Worker
Resolve(uint32_t aInterfaceIndex,const std::string & aInstanceName,const std::string & aType,const std::string & aDomain)1119*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceSubscription::Resolve(uint32_t aInterfaceIndex,
1120*4a64e381SAndroid Build Coastguard Worker const std::string &aInstanceName,
1121*4a64e381SAndroid Build Coastguard Worker const std::string &aType,
1122*4a64e381SAndroid Build Coastguard Worker const std::string &aDomain)
1123*4a64e381SAndroid Build Coastguard Worker {
1124*4a64e381SAndroid Build Coastguard Worker mResolvingInstances.push_back(
1125*4a64e381SAndroid Build Coastguard Worker MakeUnique<ServiceInstanceResolution>(*this, aInstanceName, aType, aDomain, aInterfaceIndex));
1126*4a64e381SAndroid Build Coastguard Worker mResolvingInstances.back()->Resolve();
1127*4a64e381SAndroid Build Coastguard Worker }
1128*4a64e381SAndroid Build Coastguard Worker
UpdateAll(MainloopContext & aMainloop) const1129*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceSubscription::UpdateAll(MainloopContext &aMainloop) const
1130*4a64e381SAndroid Build Coastguard Worker {
1131*4a64e381SAndroid Build Coastguard Worker Update(aMainloop);
1132*4a64e381SAndroid Build Coastguard Worker
1133*4a64e381SAndroid Build Coastguard Worker for (const auto &instance : mResolvingInstances)
1134*4a64e381SAndroid Build Coastguard Worker {
1135*4a64e381SAndroid Build Coastguard Worker instance->Update(aMainloop);
1136*4a64e381SAndroid Build Coastguard Worker }
1137*4a64e381SAndroid Build Coastguard Worker }
1138*4a64e381SAndroid Build Coastguard Worker
ProcessAll(const MainloopContext & aMainloop,std::vector<DNSServiceRef> & aReadyServices) const1139*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceSubscription::ProcessAll(const MainloopContext &aMainloop,
1140*4a64e381SAndroid Build Coastguard Worker std::vector<DNSServiceRef> &aReadyServices) const
1141*4a64e381SAndroid Build Coastguard Worker {
1142*4a64e381SAndroid Build Coastguard Worker Process(aMainloop, aReadyServices);
1143*4a64e381SAndroid Build Coastguard Worker
1144*4a64e381SAndroid Build Coastguard Worker for (const auto &instance : mResolvingInstances)
1145*4a64e381SAndroid Build Coastguard Worker {
1146*4a64e381SAndroid Build Coastguard Worker instance->Process(aMainloop, aReadyServices);
1147*4a64e381SAndroid Build Coastguard Worker }
1148*4a64e381SAndroid Build Coastguard Worker }
1149*4a64e381SAndroid Build Coastguard Worker
Resolve(void)1150*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceInstanceResolution::Resolve(void)
1151*4a64e381SAndroid Build Coastguard Worker {
1152*4a64e381SAndroid Build Coastguard Worker assert(mServiceRef == nullptr);
1153*4a64e381SAndroid Build Coastguard Worker
1154*4a64e381SAndroid Build Coastguard Worker mSubscription->mPublisher.mServiceInstanceResolutionBeginTime[std::make_pair(mInstanceName, mType)] = Clock::now();
1155*4a64e381SAndroid Build Coastguard Worker
1156*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceResolve %s %s inf %u", mInstanceName.c_str(), mType.c_str(), mNetifIndex);
1157*4a64e381SAndroid Build Coastguard Worker DNSServiceResolve(&mServiceRef, /* flags */ kDNSServiceFlagsTimeout, mNetifIndex, mInstanceName.c_str(),
1158*4a64e381SAndroid Build Coastguard Worker mType.c_str(), mDomain.c_str(), HandleResolveResult, this);
1159*4a64e381SAndroid Build Coastguard Worker }
1160*4a64e381SAndroid Build Coastguard Worker
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aFullName,const char * aHostTarget,uint16_t aPort,uint16_t aTxtLen,const unsigned char * aTxtRecord,void * aContext)1161*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceInstanceResolution::HandleResolveResult(DNSServiceRef aServiceRef,
1162*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1163*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1164*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1165*4a64e381SAndroid Build Coastguard Worker const char *aFullName,
1166*4a64e381SAndroid Build Coastguard Worker const char *aHostTarget,
1167*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
1168*4a64e381SAndroid Build Coastguard Worker uint16_t aTxtLen,
1169*4a64e381SAndroid Build Coastguard Worker const unsigned char *aTxtRecord,
1170*4a64e381SAndroid Build Coastguard Worker void *aContext)
1171*4a64e381SAndroid Build Coastguard Worker {
1172*4a64e381SAndroid Build Coastguard Worker static_cast<ServiceInstanceResolution *>(aContext)->HandleResolveResult(
1173*4a64e381SAndroid Build Coastguard Worker aServiceRef, aFlags, aInterfaceIndex, aErrorCode, aFullName, aHostTarget, aPort, aTxtLen, aTxtRecord);
1174*4a64e381SAndroid Build Coastguard Worker }
1175*4a64e381SAndroid Build Coastguard Worker
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aFullName,const char * aHostTarget,uint16_t aPort,uint16_t aTxtLen,const unsigned char * aTxtRecord)1176*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceInstanceResolution::HandleResolveResult(DNSServiceRef aServiceRef,
1177*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1178*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1179*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1180*4a64e381SAndroid Build Coastguard Worker const char *aFullName,
1181*4a64e381SAndroid Build Coastguard Worker const char *aHostTarget,
1182*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
1183*4a64e381SAndroid Build Coastguard Worker uint16_t aTxtLen,
1184*4a64e381SAndroid Build Coastguard Worker const unsigned char *aTxtRecord)
1185*4a64e381SAndroid Build Coastguard Worker {
1186*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aServiceRef);
1187*4a64e381SAndroid Build Coastguard Worker
1188*4a64e381SAndroid Build Coastguard Worker std::string instanceName, type, domain;
1189*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
1190*4a64e381SAndroid Build Coastguard Worker
1191*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceResolve reply: %s host %s:%d, TXT=%dB inf %u, flags=%u", aFullName, aHostTarget, aPort,
1192*4a64e381SAndroid Build Coastguard Worker aTxtLen, aInterfaceIndex, aFlags);
1193*4a64e381SAndroid Build Coastguard Worker
1194*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1195*4a64e381SAndroid Build Coastguard Worker
1196*4a64e381SAndroid Build Coastguard Worker SuccessOrExit(error = SplitFullServiceInstanceName(aFullName, instanceName, type, domain));
1197*4a64e381SAndroid Build Coastguard Worker
1198*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mNetifIndex = aInterfaceIndex;
1199*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mName = instanceName;
1200*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mHostName = aHostTarget;
1201*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mPort = ntohs(aPort);
1202*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mTxtData.assign(aTxtRecord, aTxtRecord + aTxtLen);
1203*4a64e381SAndroid Build Coastguard Worker // priority and weight are not given in the reply
1204*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mPriority = 0;
1205*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mWeight = 0;
1206*4a64e381SAndroid Build Coastguard Worker
1207*4a64e381SAndroid Build Coastguard Worker DeallocateServiceRef();
1208*4a64e381SAndroid Build Coastguard Worker error = GetAddrInfo(aInterfaceIndex);
1209*4a64e381SAndroid Build Coastguard Worker
1210*4a64e381SAndroid Build Coastguard Worker exit:
1211*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
1212*4a64e381SAndroid Build Coastguard Worker {
1213*4a64e381SAndroid Build Coastguard Worker otbrLogWarning("Failed to resolve service instance %s", aFullName);
1214*4a64e381SAndroid Build Coastguard Worker }
1215*4a64e381SAndroid Build Coastguard Worker
1216*4a64e381SAndroid Build Coastguard Worker if (aErrorCode != kDNSServiceErr_NoError || error != OTBR_ERROR_NONE)
1217*4a64e381SAndroid Build Coastguard Worker {
1218*4a64e381SAndroid Build Coastguard Worker mSubscription->mPublisher.OnServiceResolveFailed(mSubscription->mType, mInstanceName, aErrorCode);
1219*4a64e381SAndroid Build Coastguard Worker FinishResolution();
1220*4a64e381SAndroid Build Coastguard Worker }
1221*4a64e381SAndroid Build Coastguard Worker }
1222*4a64e381SAndroid Build Coastguard Worker
GetAddrInfo(uint32_t aInterfaceIndex)1223*4a64e381SAndroid Build Coastguard Worker otbrError PublisherMDnsSd::ServiceInstanceResolution::GetAddrInfo(uint32_t aInterfaceIndex)
1224*4a64e381SAndroid Build Coastguard Worker {
1225*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType dnsError;
1226*4a64e381SAndroid Build Coastguard Worker
1227*4a64e381SAndroid Build Coastguard Worker assert(mServiceRef == nullptr);
1228*4a64e381SAndroid Build Coastguard Worker
1229*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceGetAddrInfo %s inf %d", mInstanceInfo.mHostName.c_str(), aInterfaceIndex);
1230*4a64e381SAndroid Build Coastguard Worker
1231*4a64e381SAndroid Build Coastguard Worker dnsError = DNSServiceGetAddrInfo(&mServiceRef, /* flags */ 0, aInterfaceIndex,
1232*4a64e381SAndroid Build Coastguard Worker kDNSServiceProtocol_IPv6 | kDNSServiceProtocol_IPv4,
1233*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mHostName.c_str(), HandleGetAddrInfoResult, this);
1234*4a64e381SAndroid Build Coastguard Worker
1235*4a64e381SAndroid Build Coastguard Worker if (dnsError != kDNSServiceErr_NoError)
1236*4a64e381SAndroid Build Coastguard Worker {
1237*4a64e381SAndroid Build Coastguard Worker otbrLogWarning("DNSServiceGetAddrInfo failed: %s", DNSErrorToString(dnsError));
1238*4a64e381SAndroid Build Coastguard Worker }
1239*4a64e381SAndroid Build Coastguard Worker
1240*4a64e381SAndroid Build Coastguard Worker return dnsError == kDNSServiceErr_NoError ? OTBR_ERROR_NONE : OTBR_ERROR_MDNS;
1241*4a64e381SAndroid Build Coastguard Worker }
1242*4a64e381SAndroid Build Coastguard Worker
HandleGetAddrInfoResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl,void * aContext)1243*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceInstanceResolution::HandleGetAddrInfoResult(DNSServiceRef aServiceRef,
1244*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1245*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1246*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1247*4a64e381SAndroid Build Coastguard Worker const char *aHostName,
1248*4a64e381SAndroid Build Coastguard Worker const struct sockaddr *aAddress,
1249*4a64e381SAndroid Build Coastguard Worker uint32_t aTtl,
1250*4a64e381SAndroid Build Coastguard Worker void *aContext)
1251*4a64e381SAndroid Build Coastguard Worker {
1252*4a64e381SAndroid Build Coastguard Worker static_cast<ServiceInstanceResolution *>(aContext)->HandleGetAddrInfoResult(aServiceRef, aFlags, aInterfaceIndex,
1253*4a64e381SAndroid Build Coastguard Worker aErrorCode, aHostName, aAddress, aTtl);
1254*4a64e381SAndroid Build Coastguard Worker }
1255*4a64e381SAndroid Build Coastguard Worker
HandleGetAddrInfoResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl)1256*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceInstanceResolution::HandleGetAddrInfoResult(DNSServiceRef aServiceRef,
1257*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1258*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1259*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1260*4a64e381SAndroid Build Coastguard Worker const char *aHostName,
1261*4a64e381SAndroid Build Coastguard Worker const struct sockaddr *aAddress,
1262*4a64e381SAndroid Build Coastguard Worker uint32_t aTtl)
1263*4a64e381SAndroid Build Coastguard Worker {
1264*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aServiceRef);
1265*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aInterfaceIndex);
1266*4a64e381SAndroid Build Coastguard Worker
1267*4a64e381SAndroid Build Coastguard Worker Ip6Address address;
1268*4a64e381SAndroid Build Coastguard Worker bool isAdd = (aFlags & kDNSServiceFlagsAdd) != 0;
1269*4a64e381SAndroid Build Coastguard Worker
1270*4a64e381SAndroid Build Coastguard Worker otbrLog(aErrorCode == kDNSServiceErr_NoError ? OTBR_LOG_INFO : OTBR_LOG_WARNING, OTBR_LOG_TAG,
1271*4a64e381SAndroid Build Coastguard Worker "DNSServiceGetAddrInfo reply: flags=%" PRIu32 ", host=%s, sa_family=%u, error=%" PRId32, aFlags, aHostName,
1272*4a64e381SAndroid Build Coastguard Worker static_cast<unsigned int>(aAddress->sa_family), aErrorCode);
1273*4a64e381SAndroid Build Coastguard Worker
1274*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1275*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(aAddress->sa_family == AF_INET6);
1276*4a64e381SAndroid Build Coastguard Worker
1277*4a64e381SAndroid Build Coastguard Worker address.CopyFrom(*reinterpret_cast<const struct sockaddr_in6 *>(aAddress));
1278*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(!address.IsUnspecified() && !address.IsLinkLocal() && !address.IsMulticast() && !address.IsLoopback(),
1279*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("DNSServiceGetAddrInfo ignores address %s", address.ToString().c_str()));
1280*4a64e381SAndroid Build Coastguard Worker
1281*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceGetAddrInfo reply: %s address=%s, ttl=%" PRIu32, isAdd ? "add" : "remove",
1282*4a64e381SAndroid Build Coastguard Worker address.ToString().c_str(), aTtl);
1283*4a64e381SAndroid Build Coastguard Worker
1284*4a64e381SAndroid Build Coastguard Worker if (isAdd)
1285*4a64e381SAndroid Build Coastguard Worker {
1286*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.AddAddress(address);
1287*4a64e381SAndroid Build Coastguard Worker }
1288*4a64e381SAndroid Build Coastguard Worker else
1289*4a64e381SAndroid Build Coastguard Worker {
1290*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.RemoveAddress(address);
1291*4a64e381SAndroid Build Coastguard Worker }
1292*4a64e381SAndroid Build Coastguard Worker mInstanceInfo.mTtl = aTtl;
1293*4a64e381SAndroid Build Coastguard Worker
1294*4a64e381SAndroid Build Coastguard Worker exit:
1295*4a64e381SAndroid Build Coastguard Worker if (!mInstanceInfo.mAddresses.empty() || aErrorCode != kDNSServiceErr_NoError)
1296*4a64e381SAndroid Build Coastguard Worker {
1297*4a64e381SAndroid Build Coastguard Worker FinishResolution();
1298*4a64e381SAndroid Build Coastguard Worker }
1299*4a64e381SAndroid Build Coastguard Worker }
1300*4a64e381SAndroid Build Coastguard Worker
FinishResolution(void)1301*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::ServiceInstanceResolution::FinishResolution(void)
1302*4a64e381SAndroid Build Coastguard Worker {
1303*4a64e381SAndroid Build Coastguard Worker ServiceSubscription *subscription = mSubscription;
1304*4a64e381SAndroid Build Coastguard Worker std::string serviceName = mSubscription->mType;
1305*4a64e381SAndroid Build Coastguard Worker DiscoveredInstanceInfo instanceInfo = mInstanceInfo;
1306*4a64e381SAndroid Build Coastguard Worker
1307*4a64e381SAndroid Build Coastguard Worker // NOTE: The `ServiceSubscription` object may be freed in `OnServiceResolved`.
1308*4a64e381SAndroid Build Coastguard Worker subscription->mPublisher.OnServiceResolved(serviceName, instanceInfo);
1309*4a64e381SAndroid Build Coastguard Worker }
1310*4a64e381SAndroid Build Coastguard Worker
Resolve(void)1311*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::HostSubscription::Resolve(void)
1312*4a64e381SAndroid Build Coastguard Worker {
1313*4a64e381SAndroid Build Coastguard Worker std::string fullHostName = MakeFullHostName(mHostName);
1314*4a64e381SAndroid Build Coastguard Worker
1315*4a64e381SAndroid Build Coastguard Worker assert(mServiceRef == nullptr);
1316*4a64e381SAndroid Build Coastguard Worker
1317*4a64e381SAndroid Build Coastguard Worker mPublisher.mHostResolutionBeginTime[mHostName] = Clock::now();
1318*4a64e381SAndroid Build Coastguard Worker
1319*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceGetAddrInfo %s inf %d", fullHostName.c_str(), kDNSServiceInterfaceIndexAny);
1320*4a64e381SAndroid Build Coastguard Worker
1321*4a64e381SAndroid Build Coastguard Worker DNSServiceGetAddrInfo(&mServiceRef, /* flags */ 0, kDNSServiceInterfaceIndexAny,
1322*4a64e381SAndroid Build Coastguard Worker kDNSServiceProtocol_IPv6 | kDNSServiceProtocol_IPv4, fullHostName.c_str(),
1323*4a64e381SAndroid Build Coastguard Worker HandleResolveResult, this);
1324*4a64e381SAndroid Build Coastguard Worker }
1325*4a64e381SAndroid Build Coastguard Worker
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl,void * aContext)1326*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef aServiceRef,
1327*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1328*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1329*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1330*4a64e381SAndroid Build Coastguard Worker const char *aHostName,
1331*4a64e381SAndroid Build Coastguard Worker const struct sockaddr *aAddress,
1332*4a64e381SAndroid Build Coastguard Worker uint32_t aTtl,
1333*4a64e381SAndroid Build Coastguard Worker void *aContext)
1334*4a64e381SAndroid Build Coastguard Worker {
1335*4a64e381SAndroid Build Coastguard Worker static_cast<HostSubscription *>(aContext)->HandleResolveResult(aServiceRef, aFlags, aInterfaceIndex, aErrorCode,
1336*4a64e381SAndroid Build Coastguard Worker aHostName, aAddress, aTtl);
1337*4a64e381SAndroid Build Coastguard Worker }
1338*4a64e381SAndroid Build Coastguard Worker
HandleResolveResult(DNSServiceRef aServiceRef,DNSServiceFlags aFlags,uint32_t aInterfaceIndex,DNSServiceErrorType aErrorCode,const char * aHostName,const struct sockaddr * aAddress,uint32_t aTtl)1339*4a64e381SAndroid Build Coastguard Worker void PublisherMDnsSd::HostSubscription::HandleResolveResult(DNSServiceRef aServiceRef,
1340*4a64e381SAndroid Build Coastguard Worker DNSServiceFlags aFlags,
1341*4a64e381SAndroid Build Coastguard Worker uint32_t aInterfaceIndex,
1342*4a64e381SAndroid Build Coastguard Worker DNSServiceErrorType aErrorCode,
1343*4a64e381SAndroid Build Coastguard Worker const char *aHostName,
1344*4a64e381SAndroid Build Coastguard Worker const struct sockaddr *aAddress,
1345*4a64e381SAndroid Build Coastguard Worker uint32_t aTtl)
1346*4a64e381SAndroid Build Coastguard Worker {
1347*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aServiceRef);
1348*4a64e381SAndroid Build Coastguard Worker
1349*4a64e381SAndroid Build Coastguard Worker Ip6Address address;
1350*4a64e381SAndroid Build Coastguard Worker bool isAdd = (aFlags & kDNSServiceFlagsAdd) != 0;
1351*4a64e381SAndroid Build Coastguard Worker
1352*4a64e381SAndroid Build Coastguard Worker otbrLog(aErrorCode == kDNSServiceErr_NoError ? OTBR_LOG_INFO : OTBR_LOG_WARNING, OTBR_LOG_TAG,
1353*4a64e381SAndroid Build Coastguard Worker "DNSServiceGetAddrInfo reply: flags=%" PRIu32 ", host=%s, sa_family=%u, error=%" PRId32, aFlags, aHostName,
1354*4a64e381SAndroid Build Coastguard Worker static_cast<unsigned int>(aAddress->sa_family), aErrorCode);
1355*4a64e381SAndroid Build Coastguard Worker
1356*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(aErrorCode == kDNSServiceErr_NoError);
1357*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(aAddress->sa_family == AF_INET6);
1358*4a64e381SAndroid Build Coastguard Worker
1359*4a64e381SAndroid Build Coastguard Worker address.CopyFrom(*reinterpret_cast<const struct sockaddr_in6 *>(aAddress));
1360*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(!address.IsLinkLocal(),
1361*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("DNSServiceGetAddrInfo ignore link-local address %s", address.ToString().c_str()));
1362*4a64e381SAndroid Build Coastguard Worker
1363*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("DNSServiceGetAddrInfo reply: %s address=%s, ttl=%" PRIu32, isAdd ? "add" : "remove",
1364*4a64e381SAndroid Build Coastguard Worker address.ToString().c_str(), aTtl);
1365*4a64e381SAndroid Build Coastguard Worker
1366*4a64e381SAndroid Build Coastguard Worker if (isAdd)
1367*4a64e381SAndroid Build Coastguard Worker {
1368*4a64e381SAndroid Build Coastguard Worker mHostInfo.AddAddress(address);
1369*4a64e381SAndroid Build Coastguard Worker }
1370*4a64e381SAndroid Build Coastguard Worker else
1371*4a64e381SAndroid Build Coastguard Worker {
1372*4a64e381SAndroid Build Coastguard Worker mHostInfo.RemoveAddress(address);
1373*4a64e381SAndroid Build Coastguard Worker }
1374*4a64e381SAndroid Build Coastguard Worker mHostInfo.mHostName = aHostName;
1375*4a64e381SAndroid Build Coastguard Worker mHostInfo.mNetifIndex = aInterfaceIndex;
1376*4a64e381SAndroid Build Coastguard Worker mHostInfo.mTtl = aTtl;
1377*4a64e381SAndroid Build Coastguard Worker
1378*4a64e381SAndroid Build Coastguard Worker // NOTE: This `HostSubscription` object may be freed in `OnHostResolved`.
1379*4a64e381SAndroid Build Coastguard Worker mPublisher.OnHostResolved(mHostName, mHostInfo);
1380*4a64e381SAndroid Build Coastguard Worker
1381*4a64e381SAndroid Build Coastguard Worker exit:
1382*4a64e381SAndroid Build Coastguard Worker if (aErrorCode != kDNSServiceErr_NoError)
1383*4a64e381SAndroid Build Coastguard Worker {
1384*4a64e381SAndroid Build Coastguard Worker mPublisher.OnHostResolveFailed(aHostName, aErrorCode);
1385*4a64e381SAndroid Build Coastguard Worker }
1386*4a64e381SAndroid Build Coastguard Worker }
1387*4a64e381SAndroid Build Coastguard Worker
1388*4a64e381SAndroid Build Coastguard Worker } // namespace Mdns
1389*4a64e381SAndroid Build Coastguard Worker
1390*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
1391