1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker * Copyright (c) 2021, 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 includes implementation of mDNS publisher.
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.hpp"
37*4a64e381SAndroid Build Coastguard Worker
38*4a64e381SAndroid Build Coastguard Worker #if OTBR_ENABLE_MDNS
39*4a64e381SAndroid Build Coastguard Worker
40*4a64e381SAndroid Build Coastguard Worker #include <assert.h>
41*4a64e381SAndroid Build Coastguard Worker
42*4a64e381SAndroid Build Coastguard Worker #include <algorithm>
43*4a64e381SAndroid Build Coastguard Worker #include <functional>
44*4a64e381SAndroid Build Coastguard Worker
45*4a64e381SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
46*4a64e381SAndroid Build Coastguard Worker #include "utils/dns_utils.hpp"
47*4a64e381SAndroid Build Coastguard Worker
48*4a64e381SAndroid Build Coastguard Worker namespace otbr {
49*4a64e381SAndroid Build Coastguard Worker
50*4a64e381SAndroid Build Coastguard Worker namespace Mdns {
51*4a64e381SAndroid Build Coastguard Worker
PublishService(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtData & aTxtData,ResultCallback && aCallback)52*4a64e381SAndroid Build Coastguard Worker void Publisher::PublishService(const std::string &aHostName,
53*4a64e381SAndroid Build Coastguard Worker const std::string &aName,
54*4a64e381SAndroid Build Coastguard Worker const std::string &aType,
55*4a64e381SAndroid Build Coastguard Worker const SubTypeList &aSubTypeList,
56*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
57*4a64e381SAndroid Build Coastguard Worker const TxtData &aTxtData,
58*4a64e381SAndroid Build Coastguard Worker ResultCallback &&aCallback)
59*4a64e381SAndroid Build Coastguard Worker {
60*4a64e381SAndroid Build Coastguard Worker otbrError error;
61*4a64e381SAndroid Build Coastguard Worker
62*4a64e381SAndroid Build Coastguard Worker mServiceRegistrationBeginTime[std::make_pair(aName, aType)] = Clock::now();
63*4a64e381SAndroid Build Coastguard Worker
64*4a64e381SAndroid Build Coastguard Worker error = PublishServiceImpl(aHostName, aName, aType, aSubTypeList, aPort, aTxtData, std::move(aCallback));
65*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
66*4a64e381SAndroid Build Coastguard Worker {
67*4a64e381SAndroid Build Coastguard Worker UpdateMdnsResponseCounters(mTelemetryInfo.mServiceRegistrations, error);
68*4a64e381SAndroid Build Coastguard Worker }
69*4a64e381SAndroid Build Coastguard Worker }
70*4a64e381SAndroid Build Coastguard Worker
PublishHost(const std::string & aName,const AddressList & aAddresses,ResultCallback && aCallback)71*4a64e381SAndroid Build Coastguard Worker void Publisher::PublishHost(const std::string &aName, const AddressList &aAddresses, ResultCallback &&aCallback)
72*4a64e381SAndroid Build Coastguard Worker {
73*4a64e381SAndroid Build Coastguard Worker otbrError error;
74*4a64e381SAndroid Build Coastguard Worker
75*4a64e381SAndroid Build Coastguard Worker mHostRegistrationBeginTime[aName] = Clock::now();
76*4a64e381SAndroid Build Coastguard Worker
77*4a64e381SAndroid Build Coastguard Worker error = PublishHostImpl(aName, aAddresses, std::move(aCallback));
78*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
79*4a64e381SAndroid Build Coastguard Worker {
80*4a64e381SAndroid Build Coastguard Worker UpdateMdnsResponseCounters(mTelemetryInfo.mHostRegistrations, error);
81*4a64e381SAndroid Build Coastguard Worker }
82*4a64e381SAndroid Build Coastguard Worker }
83*4a64e381SAndroid Build Coastguard Worker
PublishKey(const std::string & aName,const KeyData & aKeyData,ResultCallback && aCallback)84*4a64e381SAndroid Build Coastguard Worker void Publisher::PublishKey(const std::string &aName, const KeyData &aKeyData, ResultCallback &&aCallback)
85*4a64e381SAndroid Build Coastguard Worker {
86*4a64e381SAndroid Build Coastguard Worker otbrError error;
87*4a64e381SAndroid Build Coastguard Worker
88*4a64e381SAndroid Build Coastguard Worker mKeyRegistrationBeginTime[aName] = Clock::now();
89*4a64e381SAndroid Build Coastguard Worker
90*4a64e381SAndroid Build Coastguard Worker error = PublishKeyImpl(aName, aKeyData, std::move(aCallback));
91*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
92*4a64e381SAndroid Build Coastguard Worker {
93*4a64e381SAndroid Build Coastguard Worker UpdateMdnsResponseCounters(mTelemetryInfo.mKeyRegistrations, error);
94*4a64e381SAndroid Build Coastguard Worker }
95*4a64e381SAndroid Build Coastguard Worker }
96*4a64e381SAndroid Build Coastguard Worker
OnServiceResolveFailed(std::string aType,std::string aInstanceName,int32_t aErrorCode)97*4a64e381SAndroid Build Coastguard Worker void Publisher::OnServiceResolveFailed(std::string aType, std::string aInstanceName, int32_t aErrorCode)
98*4a64e381SAndroid Build Coastguard Worker {
99*4a64e381SAndroid Build Coastguard Worker UpdateMdnsResponseCounters(mTelemetryInfo.mServiceResolutions, DnsErrorToOtbrError(aErrorCode));
100*4a64e381SAndroid Build Coastguard Worker UpdateServiceInstanceResolutionEmaLatency(aInstanceName, aType, DnsErrorToOtbrError(aErrorCode));
101*4a64e381SAndroid Build Coastguard Worker OnServiceResolveFailedImpl(aType, aInstanceName, aErrorCode);
102*4a64e381SAndroid Build Coastguard Worker }
103*4a64e381SAndroid Build Coastguard Worker
OnHostResolveFailed(std::string aHostName,int32_t aErrorCode)104*4a64e381SAndroid Build Coastguard Worker void Publisher::OnHostResolveFailed(std::string aHostName, int32_t aErrorCode)
105*4a64e381SAndroid Build Coastguard Worker {
106*4a64e381SAndroid Build Coastguard Worker UpdateMdnsResponseCounters(mTelemetryInfo.mHostResolutions, DnsErrorToOtbrError(aErrorCode));
107*4a64e381SAndroid Build Coastguard Worker UpdateHostResolutionEmaLatency(aHostName, DnsErrorToOtbrError(aErrorCode));
108*4a64e381SAndroid Build Coastguard Worker OnHostResolveFailedImpl(aHostName, aErrorCode);
109*4a64e381SAndroid Build Coastguard Worker }
110*4a64e381SAndroid Build Coastguard Worker
EncodeTxtData(const TxtList & aTxtList,std::vector<uint8_t> & aTxtData)111*4a64e381SAndroid Build Coastguard Worker otbrError Publisher::EncodeTxtData(const TxtList &aTxtList, std::vector<uint8_t> &aTxtData)
112*4a64e381SAndroid Build Coastguard Worker {
113*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
114*4a64e381SAndroid Build Coastguard Worker
115*4a64e381SAndroid Build Coastguard Worker aTxtData.clear();
116*4a64e381SAndroid Build Coastguard Worker
117*4a64e381SAndroid Build Coastguard Worker for (const TxtEntry &txtEntry : aTxtList)
118*4a64e381SAndroid Build Coastguard Worker {
119*4a64e381SAndroid Build Coastguard Worker size_t entryLength = txtEntry.mKey.length();
120*4a64e381SAndroid Build Coastguard Worker
121*4a64e381SAndroid Build Coastguard Worker if (!txtEntry.mIsBooleanAttribute)
122*4a64e381SAndroid Build Coastguard Worker {
123*4a64e381SAndroid Build Coastguard Worker entryLength += txtEntry.mValue.size() + sizeof(uint8_t); // for `=` char.
124*4a64e381SAndroid Build Coastguard Worker }
125*4a64e381SAndroid Build Coastguard Worker
126*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(entryLength <= kMaxTextEntrySize, error = OTBR_ERROR_INVALID_ARGS);
127*4a64e381SAndroid Build Coastguard Worker
128*4a64e381SAndroid Build Coastguard Worker aTxtData.push_back(static_cast<uint8_t>(entryLength));
129*4a64e381SAndroid Build Coastguard Worker aTxtData.insert(aTxtData.end(), txtEntry.mKey.begin(), txtEntry.mKey.end());
130*4a64e381SAndroid Build Coastguard Worker
131*4a64e381SAndroid Build Coastguard Worker if (!txtEntry.mIsBooleanAttribute)
132*4a64e381SAndroid Build Coastguard Worker {
133*4a64e381SAndroid Build Coastguard Worker aTxtData.push_back('=');
134*4a64e381SAndroid Build Coastguard Worker aTxtData.insert(aTxtData.end(), txtEntry.mValue.begin(), txtEntry.mValue.end());
135*4a64e381SAndroid Build Coastguard Worker }
136*4a64e381SAndroid Build Coastguard Worker }
137*4a64e381SAndroid Build Coastguard Worker
138*4a64e381SAndroid Build Coastguard Worker if (aTxtData.empty())
139*4a64e381SAndroid Build Coastguard Worker {
140*4a64e381SAndroid Build Coastguard Worker aTxtData.push_back(0);
141*4a64e381SAndroid Build Coastguard Worker }
142*4a64e381SAndroid Build Coastguard Worker
143*4a64e381SAndroid Build Coastguard Worker exit:
144*4a64e381SAndroid Build Coastguard Worker return error;
145*4a64e381SAndroid Build Coastguard Worker }
146*4a64e381SAndroid Build Coastguard Worker
DecodeTxtData(Publisher::TxtList & aTxtList,const uint8_t * aTxtData,uint16_t aTxtLength)147*4a64e381SAndroid Build Coastguard Worker otbrError Publisher::DecodeTxtData(Publisher::TxtList &aTxtList, const uint8_t *aTxtData, uint16_t aTxtLength)
148*4a64e381SAndroid Build Coastguard Worker {
149*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
150*4a64e381SAndroid Build Coastguard Worker
151*4a64e381SAndroid Build Coastguard Worker aTxtList.clear();
152*4a64e381SAndroid Build Coastguard Worker
153*4a64e381SAndroid Build Coastguard Worker for (uint16_t r = 0; r < aTxtLength;)
154*4a64e381SAndroid Build Coastguard Worker {
155*4a64e381SAndroid Build Coastguard Worker uint16_t entrySize = aTxtData[r];
156*4a64e381SAndroid Build Coastguard Worker uint16_t keyStart = r + 1;
157*4a64e381SAndroid Build Coastguard Worker uint16_t entryEnd = keyStart + entrySize;
158*4a64e381SAndroid Build Coastguard Worker uint16_t keyEnd = keyStart;
159*4a64e381SAndroid Build Coastguard Worker
160*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(entryEnd <= aTxtLength, error = OTBR_ERROR_PARSE);
161*4a64e381SAndroid Build Coastguard Worker
162*4a64e381SAndroid Build Coastguard Worker while (keyEnd < entryEnd && aTxtData[keyEnd] != '=')
163*4a64e381SAndroid Build Coastguard Worker {
164*4a64e381SAndroid Build Coastguard Worker keyEnd++;
165*4a64e381SAndroid Build Coastguard Worker }
166*4a64e381SAndroid Build Coastguard Worker
167*4a64e381SAndroid Build Coastguard Worker if (keyEnd == entryEnd)
168*4a64e381SAndroid Build Coastguard Worker {
169*4a64e381SAndroid Build Coastguard Worker if (keyEnd > keyStart)
170*4a64e381SAndroid Build Coastguard Worker {
171*4a64e381SAndroid Build Coastguard Worker // No `=`, treat as a boolean attribute.
172*4a64e381SAndroid Build Coastguard Worker aTxtList.emplace_back(reinterpret_cast<const char *>(&aTxtData[keyStart]), keyEnd - keyStart);
173*4a64e381SAndroid Build Coastguard Worker }
174*4a64e381SAndroid Build Coastguard Worker }
175*4a64e381SAndroid Build Coastguard Worker else
176*4a64e381SAndroid Build Coastguard Worker {
177*4a64e381SAndroid Build Coastguard Worker uint16_t valStart = keyEnd + 1; // To skip over `=`
178*4a64e381SAndroid Build Coastguard Worker
179*4a64e381SAndroid Build Coastguard Worker aTxtList.emplace_back(reinterpret_cast<const char *>(&aTxtData[keyStart]), keyEnd - keyStart,
180*4a64e381SAndroid Build Coastguard Worker &aTxtData[valStart], entryEnd - valStart);
181*4a64e381SAndroid Build Coastguard Worker }
182*4a64e381SAndroid Build Coastguard Worker
183*4a64e381SAndroid Build Coastguard Worker r += entrySize + 1;
184*4a64e381SAndroid Build Coastguard Worker }
185*4a64e381SAndroid Build Coastguard Worker
186*4a64e381SAndroid Build Coastguard Worker exit:
187*4a64e381SAndroid Build Coastguard Worker return error;
188*4a64e381SAndroid Build Coastguard Worker }
189*4a64e381SAndroid Build Coastguard Worker
RemoveSubscriptionCallbacks(uint64_t aSubscriberId)190*4a64e381SAndroid Build Coastguard Worker void Publisher::RemoveSubscriptionCallbacks(uint64_t aSubscriberId)
191*4a64e381SAndroid Build Coastguard Worker {
192*4a64e381SAndroid Build Coastguard Worker mDiscoverCallbacks.remove_if(
193*4a64e381SAndroid Build Coastguard Worker [aSubscriberId](const DiscoverCallback &aCallback) { return (aCallback.mId == aSubscriberId); });
194*4a64e381SAndroid Build Coastguard Worker }
195*4a64e381SAndroid Build Coastguard Worker
AddSubscriptionCallbacks(Publisher::DiscoveredServiceInstanceCallback aInstanceCallback,Publisher::DiscoveredHostCallback aHostCallback)196*4a64e381SAndroid Build Coastguard Worker uint64_t Publisher::AddSubscriptionCallbacks(Publisher::DiscoveredServiceInstanceCallback aInstanceCallback,
197*4a64e381SAndroid Build Coastguard Worker Publisher::DiscoveredHostCallback aHostCallback)
198*4a64e381SAndroid Build Coastguard Worker {
199*4a64e381SAndroid Build Coastguard Worker uint64_t id = mNextSubscriberId++;
200*4a64e381SAndroid Build Coastguard Worker
201*4a64e381SAndroid Build Coastguard Worker assert(id > 0);
202*4a64e381SAndroid Build Coastguard Worker mDiscoverCallbacks.emplace_back(id, aInstanceCallback, aHostCallback);
203*4a64e381SAndroid Build Coastguard Worker
204*4a64e381SAndroid Build Coastguard Worker return id;
205*4a64e381SAndroid Build Coastguard Worker }
206*4a64e381SAndroid Build Coastguard Worker
OnServiceResolved(std::string aType,DiscoveredInstanceInfo aInstanceInfo)207*4a64e381SAndroid Build Coastguard Worker void Publisher::OnServiceResolved(std::string aType, DiscoveredInstanceInfo aInstanceInfo)
208*4a64e381SAndroid Build Coastguard Worker {
209*4a64e381SAndroid Build Coastguard Worker bool checkToInvoke = false;
210*4a64e381SAndroid Build Coastguard Worker
211*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Service %s is resolved successfully: %s %s host %s addresses %zu", aType.c_str(),
212*4a64e381SAndroid Build Coastguard Worker aInstanceInfo.mRemoved ? "remove" : "add", aInstanceInfo.mName.c_str(), aInstanceInfo.mHostName.c_str(),
213*4a64e381SAndroid Build Coastguard Worker aInstanceInfo.mAddresses.size());
214*4a64e381SAndroid Build Coastguard Worker
215*4a64e381SAndroid Build Coastguard Worker if (!aInstanceInfo.mRemoved)
216*4a64e381SAndroid Build Coastguard Worker {
217*4a64e381SAndroid Build Coastguard Worker std::string addressesString;
218*4a64e381SAndroid Build Coastguard Worker
219*4a64e381SAndroid Build Coastguard Worker for (const auto &address : aInstanceInfo.mAddresses)
220*4a64e381SAndroid Build Coastguard Worker {
221*4a64e381SAndroid Build Coastguard Worker addressesString += address.ToString() + ",";
222*4a64e381SAndroid Build Coastguard Worker }
223*4a64e381SAndroid Build Coastguard Worker if (addressesString.size())
224*4a64e381SAndroid Build Coastguard Worker {
225*4a64e381SAndroid Build Coastguard Worker addressesString.pop_back();
226*4a64e381SAndroid Build Coastguard Worker }
227*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("addresses: [ %s ]", addressesString.c_str());
228*4a64e381SAndroid Build Coastguard Worker }
229*4a64e381SAndroid Build Coastguard Worker
230*4a64e381SAndroid Build Coastguard Worker DnsUtils::CheckServiceNameSanity(aType);
231*4a64e381SAndroid Build Coastguard Worker
232*4a64e381SAndroid Build Coastguard Worker assert(aInstanceInfo.mNetifIndex > 0);
233*4a64e381SAndroid Build Coastguard Worker
234*4a64e381SAndroid Build Coastguard Worker if (!aInstanceInfo.mRemoved)
235*4a64e381SAndroid Build Coastguard Worker {
236*4a64e381SAndroid Build Coastguard Worker DnsUtils::CheckHostnameSanity(aInstanceInfo.mHostName);
237*4a64e381SAndroid Build Coastguard Worker }
238*4a64e381SAndroid Build Coastguard Worker
239*4a64e381SAndroid Build Coastguard Worker UpdateMdnsResponseCounters(mTelemetryInfo.mServiceResolutions, OTBR_ERROR_NONE);
240*4a64e381SAndroid Build Coastguard Worker UpdateServiceInstanceResolutionEmaLatency(aInstanceInfo.mName, aType, OTBR_ERROR_NONE);
241*4a64e381SAndroid Build Coastguard Worker
242*4a64e381SAndroid Build Coastguard Worker // The `mDiscoverCallbacks` list can get updated as the callbacks
243*4a64e381SAndroid Build Coastguard Worker // are invoked. We first mark `mShouldInvoke` on all non-null
244*4a64e381SAndroid Build Coastguard Worker // service callbacks. We clear it before invoking the callback
245*4a64e381SAndroid Build Coastguard Worker // and restart the iteration over the `mDiscoverCallbacks` list
246*4a64e381SAndroid Build Coastguard Worker // to find the next one to signal, since the list may have changed.
247*4a64e381SAndroid Build Coastguard Worker
248*4a64e381SAndroid Build Coastguard Worker for (DiscoverCallback &callback : mDiscoverCallbacks)
249*4a64e381SAndroid Build Coastguard Worker {
250*4a64e381SAndroid Build Coastguard Worker if (callback.mServiceCallback != nullptr)
251*4a64e381SAndroid Build Coastguard Worker {
252*4a64e381SAndroid Build Coastguard Worker callback.mShouldInvoke = true;
253*4a64e381SAndroid Build Coastguard Worker checkToInvoke = true;
254*4a64e381SAndroid Build Coastguard Worker }
255*4a64e381SAndroid Build Coastguard Worker }
256*4a64e381SAndroid Build Coastguard Worker
257*4a64e381SAndroid Build Coastguard Worker while (checkToInvoke)
258*4a64e381SAndroid Build Coastguard Worker {
259*4a64e381SAndroid Build Coastguard Worker checkToInvoke = false;
260*4a64e381SAndroid Build Coastguard Worker
261*4a64e381SAndroid Build Coastguard Worker for (DiscoverCallback &callback : mDiscoverCallbacks)
262*4a64e381SAndroid Build Coastguard Worker {
263*4a64e381SAndroid Build Coastguard Worker if (callback.mShouldInvoke)
264*4a64e381SAndroid Build Coastguard Worker {
265*4a64e381SAndroid Build Coastguard Worker callback.mShouldInvoke = false;
266*4a64e381SAndroid Build Coastguard Worker checkToInvoke = true;
267*4a64e381SAndroid Build Coastguard Worker callback.mServiceCallback(aType, aInstanceInfo);
268*4a64e381SAndroid Build Coastguard Worker break;
269*4a64e381SAndroid Build Coastguard Worker }
270*4a64e381SAndroid Build Coastguard Worker }
271*4a64e381SAndroid Build Coastguard Worker }
272*4a64e381SAndroid Build Coastguard Worker }
273*4a64e381SAndroid Build Coastguard Worker
OnServiceRemoved(uint32_t aNetifIndex,std::string aType,std::string aInstanceName)274*4a64e381SAndroid Build Coastguard Worker void Publisher::OnServiceRemoved(uint32_t aNetifIndex, std::string aType, std::string aInstanceName)
275*4a64e381SAndroid Build Coastguard Worker {
276*4a64e381SAndroid Build Coastguard Worker DiscoveredInstanceInfo instanceInfo;
277*4a64e381SAndroid Build Coastguard Worker
278*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Service %s.%s is removed from netif %u.", aInstanceName.c_str(), aType.c_str(), aNetifIndex);
279*4a64e381SAndroid Build Coastguard Worker
280*4a64e381SAndroid Build Coastguard Worker instanceInfo.mRemoved = true;
281*4a64e381SAndroid Build Coastguard Worker instanceInfo.mNetifIndex = aNetifIndex;
282*4a64e381SAndroid Build Coastguard Worker instanceInfo.mName = aInstanceName;
283*4a64e381SAndroid Build Coastguard Worker
284*4a64e381SAndroid Build Coastguard Worker OnServiceResolved(aType, instanceInfo);
285*4a64e381SAndroid Build Coastguard Worker }
286*4a64e381SAndroid Build Coastguard Worker
OnHostResolved(std::string aHostName,Publisher::DiscoveredHostInfo aHostInfo)287*4a64e381SAndroid Build Coastguard Worker void Publisher::OnHostResolved(std::string aHostName, Publisher::DiscoveredHostInfo aHostInfo)
288*4a64e381SAndroid Build Coastguard Worker {
289*4a64e381SAndroid Build Coastguard Worker bool checkToInvoke = false;
290*4a64e381SAndroid Build Coastguard Worker
291*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Host %s is resolved successfully: host %s addresses %zu ttl %u", aHostName.c_str(),
292*4a64e381SAndroid Build Coastguard Worker aHostInfo.mHostName.c_str(), aHostInfo.mAddresses.size(), aHostInfo.mTtl);
293*4a64e381SAndroid Build Coastguard Worker
294*4a64e381SAndroid Build Coastguard Worker if (!aHostInfo.mHostName.empty())
295*4a64e381SAndroid Build Coastguard Worker {
296*4a64e381SAndroid Build Coastguard Worker DnsUtils::CheckHostnameSanity(aHostInfo.mHostName);
297*4a64e381SAndroid Build Coastguard Worker }
298*4a64e381SAndroid Build Coastguard Worker
299*4a64e381SAndroid Build Coastguard Worker UpdateMdnsResponseCounters(mTelemetryInfo.mHostResolutions, OTBR_ERROR_NONE);
300*4a64e381SAndroid Build Coastguard Worker UpdateHostResolutionEmaLatency(aHostName, OTBR_ERROR_NONE);
301*4a64e381SAndroid Build Coastguard Worker
302*4a64e381SAndroid Build Coastguard Worker // The `mDiscoverCallbacks` list can get updated as the callbacks
303*4a64e381SAndroid Build Coastguard Worker // are invoked. We first mark `mShouldInvoke` on all non-null
304*4a64e381SAndroid Build Coastguard Worker // host callbacks. We clear it before invoking the callback
305*4a64e381SAndroid Build Coastguard Worker // and restart the iteration over the `mDiscoverCallbacks` list
306*4a64e381SAndroid Build Coastguard Worker // to find the next one to signal, since the list may have changed.
307*4a64e381SAndroid Build Coastguard Worker
308*4a64e381SAndroid Build Coastguard Worker for (DiscoverCallback &callback : mDiscoverCallbacks)
309*4a64e381SAndroid Build Coastguard Worker {
310*4a64e381SAndroid Build Coastguard Worker if (callback.mHostCallback != nullptr)
311*4a64e381SAndroid Build Coastguard Worker {
312*4a64e381SAndroid Build Coastguard Worker callback.mShouldInvoke = true;
313*4a64e381SAndroid Build Coastguard Worker checkToInvoke = true;
314*4a64e381SAndroid Build Coastguard Worker }
315*4a64e381SAndroid Build Coastguard Worker }
316*4a64e381SAndroid Build Coastguard Worker
317*4a64e381SAndroid Build Coastguard Worker while (checkToInvoke)
318*4a64e381SAndroid Build Coastguard Worker {
319*4a64e381SAndroid Build Coastguard Worker checkToInvoke = false;
320*4a64e381SAndroid Build Coastguard Worker
321*4a64e381SAndroid Build Coastguard Worker for (DiscoverCallback &callback : mDiscoverCallbacks)
322*4a64e381SAndroid Build Coastguard Worker {
323*4a64e381SAndroid Build Coastguard Worker if (callback.mShouldInvoke)
324*4a64e381SAndroid Build Coastguard Worker {
325*4a64e381SAndroid Build Coastguard Worker callback.mShouldInvoke = false;
326*4a64e381SAndroid Build Coastguard Worker checkToInvoke = true;
327*4a64e381SAndroid Build Coastguard Worker callback.mHostCallback(aHostName, aHostInfo);
328*4a64e381SAndroid Build Coastguard Worker break;
329*4a64e381SAndroid Build Coastguard Worker }
330*4a64e381SAndroid Build Coastguard Worker }
331*4a64e381SAndroid Build Coastguard Worker }
332*4a64e381SAndroid Build Coastguard Worker }
333*4a64e381SAndroid Build Coastguard Worker
SortSubTypeList(SubTypeList aSubTypeList)334*4a64e381SAndroid Build Coastguard Worker Publisher::SubTypeList Publisher::SortSubTypeList(SubTypeList aSubTypeList)
335*4a64e381SAndroid Build Coastguard Worker {
336*4a64e381SAndroid Build Coastguard Worker std::sort(aSubTypeList.begin(), aSubTypeList.end());
337*4a64e381SAndroid Build Coastguard Worker return aSubTypeList;
338*4a64e381SAndroid Build Coastguard Worker }
339*4a64e381SAndroid Build Coastguard Worker
SortAddressList(AddressList aAddressList)340*4a64e381SAndroid Build Coastguard Worker Publisher::AddressList Publisher::SortAddressList(AddressList aAddressList)
341*4a64e381SAndroid Build Coastguard Worker {
342*4a64e381SAndroid Build Coastguard Worker std::sort(aAddressList.begin(), aAddressList.end());
343*4a64e381SAndroid Build Coastguard Worker return aAddressList;
344*4a64e381SAndroid Build Coastguard Worker }
345*4a64e381SAndroid Build Coastguard Worker
MakeFullServiceName(const std::string & aName,const std::string & aType)346*4a64e381SAndroid Build Coastguard Worker std::string Publisher::MakeFullServiceName(const std::string &aName, const std::string &aType)
347*4a64e381SAndroid Build Coastguard Worker {
348*4a64e381SAndroid Build Coastguard Worker return aName + "." + aType + ".local";
349*4a64e381SAndroid Build Coastguard Worker }
350*4a64e381SAndroid Build Coastguard Worker
MakeFullName(const std::string & aName)351*4a64e381SAndroid Build Coastguard Worker std::string Publisher::MakeFullName(const std::string &aName)
352*4a64e381SAndroid Build Coastguard Worker {
353*4a64e381SAndroid Build Coastguard Worker return aName + ".local";
354*4a64e381SAndroid Build Coastguard Worker }
355*4a64e381SAndroid Build Coastguard Worker
AddServiceRegistration(ServiceRegistrationPtr && aServiceReg)356*4a64e381SAndroid Build Coastguard Worker void Publisher::AddServiceRegistration(ServiceRegistrationPtr &&aServiceReg)
357*4a64e381SAndroid Build Coastguard Worker {
358*4a64e381SAndroid Build Coastguard Worker mServiceRegistrations.emplace(MakeFullServiceName(aServiceReg->mName, aServiceReg->mType), std::move(aServiceReg));
359*4a64e381SAndroid Build Coastguard Worker }
360*4a64e381SAndroid Build Coastguard Worker
RemoveServiceRegistration(const std::string & aName,const std::string & aType,otbrError aError)361*4a64e381SAndroid Build Coastguard Worker void Publisher::RemoveServiceRegistration(const std::string &aName, const std::string &aType, otbrError aError)
362*4a64e381SAndroid Build Coastguard Worker {
363*4a64e381SAndroid Build Coastguard Worker auto it = mServiceRegistrations.find(MakeFullServiceName(aName, aType));
364*4a64e381SAndroid Build Coastguard Worker ServiceRegistrationPtr serviceReg;
365*4a64e381SAndroid Build Coastguard Worker
366*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removing service %s.%s", aName.c_str(), aType.c_str());
367*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(it != mServiceRegistrations.end());
368*4a64e381SAndroid Build Coastguard Worker
369*4a64e381SAndroid Build Coastguard Worker // Keep the ServiceRegistration around before calling `Complete`
370*4a64e381SAndroid Build Coastguard Worker // to invoke the callback. This is for avoiding invalid access
371*4a64e381SAndroid Build Coastguard Worker // to the ServiceRegistration when it's freed from the callback.
372*4a64e381SAndroid Build Coastguard Worker serviceReg = std::move(it->second);
373*4a64e381SAndroid Build Coastguard Worker mServiceRegistrations.erase(it);
374*4a64e381SAndroid Build Coastguard Worker serviceReg->Complete(aError);
375*4a64e381SAndroid Build Coastguard Worker
376*4a64e381SAndroid Build Coastguard Worker exit:
377*4a64e381SAndroid Build Coastguard Worker return;
378*4a64e381SAndroid Build Coastguard Worker }
379*4a64e381SAndroid Build Coastguard Worker
FindServiceRegistration(const std::string & aName,const std::string & aType)380*4a64e381SAndroid Build Coastguard Worker Publisher::ServiceRegistration *Publisher::FindServiceRegistration(const std::string &aName, const std::string &aType)
381*4a64e381SAndroid Build Coastguard Worker {
382*4a64e381SAndroid Build Coastguard Worker auto it = mServiceRegistrations.find(MakeFullServiceName(aName, aType));
383*4a64e381SAndroid Build Coastguard Worker
384*4a64e381SAndroid Build Coastguard Worker return it != mServiceRegistrations.end() ? it->second.get() : nullptr;
385*4a64e381SAndroid Build Coastguard Worker }
386*4a64e381SAndroid Build Coastguard Worker
FindServiceRegistration(const std::string & aNameAndType)387*4a64e381SAndroid Build Coastguard Worker Publisher::ServiceRegistration *Publisher::FindServiceRegistration(const std::string &aNameAndType)
388*4a64e381SAndroid Build Coastguard Worker {
389*4a64e381SAndroid Build Coastguard Worker auto it = mServiceRegistrations.find(MakeFullName(aNameAndType));
390*4a64e381SAndroid Build Coastguard Worker
391*4a64e381SAndroid Build Coastguard Worker return it != mServiceRegistrations.end() ? it->second.get() : nullptr;
392*4a64e381SAndroid Build Coastguard Worker }
393*4a64e381SAndroid Build Coastguard Worker
HandleDuplicateServiceRegistration(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtData & aTxtData,ResultCallback && aCallback)394*4a64e381SAndroid Build Coastguard Worker Publisher::ResultCallback Publisher::HandleDuplicateServiceRegistration(const std::string &aHostName,
395*4a64e381SAndroid Build Coastguard Worker const std::string &aName,
396*4a64e381SAndroid Build Coastguard Worker const std::string &aType,
397*4a64e381SAndroid Build Coastguard Worker const SubTypeList &aSubTypeList,
398*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
399*4a64e381SAndroid Build Coastguard Worker const TxtData &aTxtData,
400*4a64e381SAndroid Build Coastguard Worker ResultCallback &&aCallback)
401*4a64e381SAndroid Build Coastguard Worker {
402*4a64e381SAndroid Build Coastguard Worker ServiceRegistration *serviceReg = FindServiceRegistration(aName, aType);
403*4a64e381SAndroid Build Coastguard Worker
404*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(serviceReg != nullptr);
405*4a64e381SAndroid Build Coastguard Worker
406*4a64e381SAndroid Build Coastguard Worker if (serviceReg->IsOutdated(aHostName, aName, aType, aSubTypeList, aPort, aTxtData))
407*4a64e381SAndroid Build Coastguard Worker {
408*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removing existing service %s.%s: outdated", aName.c_str(), aType.c_str());
409*4a64e381SAndroid Build Coastguard Worker RemoveServiceRegistration(aName, aType, OTBR_ERROR_ABORTED);
410*4a64e381SAndroid Build Coastguard Worker }
411*4a64e381SAndroid Build Coastguard Worker else if (serviceReg->IsCompleted())
412*4a64e381SAndroid Build Coastguard Worker {
413*4a64e381SAndroid Build Coastguard Worker // Returns success if the same service has already been
414*4a64e381SAndroid Build Coastguard Worker // registered with exactly the same parameters.
415*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(OTBR_ERROR_NONE);
416*4a64e381SAndroid Build Coastguard Worker }
417*4a64e381SAndroid Build Coastguard Worker else
418*4a64e381SAndroid Build Coastguard Worker {
419*4a64e381SAndroid Build Coastguard Worker // If the same service is being registered with the same parameters,
420*4a64e381SAndroid Build Coastguard Worker // let's join the waiting queue for the result.
421*4a64e381SAndroid Build Coastguard Worker serviceReg->mCallback = std::bind(
422*4a64e381SAndroid Build Coastguard Worker [](std::shared_ptr<ResultCallback> aExistingCallback, std::shared_ptr<ResultCallback> aNewCallback,
423*4a64e381SAndroid Build Coastguard Worker otbrError aError) {
424*4a64e381SAndroid Build Coastguard Worker std::move (*aExistingCallback)(aError);
425*4a64e381SAndroid Build Coastguard Worker std::move (*aNewCallback)(aError);
426*4a64e381SAndroid Build Coastguard Worker },
427*4a64e381SAndroid Build Coastguard Worker std::make_shared<ResultCallback>(std::move(serviceReg->mCallback)),
428*4a64e381SAndroid Build Coastguard Worker std::make_shared<ResultCallback>(std::move(aCallback)), std::placeholders::_1);
429*4a64e381SAndroid Build Coastguard Worker }
430*4a64e381SAndroid Build Coastguard Worker
431*4a64e381SAndroid Build Coastguard Worker exit:
432*4a64e381SAndroid Build Coastguard Worker return std::move(aCallback);
433*4a64e381SAndroid Build Coastguard Worker }
434*4a64e381SAndroid Build Coastguard Worker
HandleDuplicateHostRegistration(const std::string & aName,const AddressList & aAddresses,ResultCallback && aCallback)435*4a64e381SAndroid Build Coastguard Worker Publisher::ResultCallback Publisher::HandleDuplicateHostRegistration(const std::string &aName,
436*4a64e381SAndroid Build Coastguard Worker const AddressList &aAddresses,
437*4a64e381SAndroid Build Coastguard Worker ResultCallback &&aCallback)
438*4a64e381SAndroid Build Coastguard Worker {
439*4a64e381SAndroid Build Coastguard Worker HostRegistration *hostReg = FindHostRegistration(aName);
440*4a64e381SAndroid Build Coastguard Worker
441*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(hostReg != nullptr);
442*4a64e381SAndroid Build Coastguard Worker
443*4a64e381SAndroid Build Coastguard Worker if (hostReg->IsOutdated(aName, aAddresses))
444*4a64e381SAndroid Build Coastguard Worker {
445*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removing existing host %s: outdated", aName.c_str());
446*4a64e381SAndroid Build Coastguard Worker RemoveHostRegistration(hostReg->mName, OTBR_ERROR_ABORTED);
447*4a64e381SAndroid Build Coastguard Worker }
448*4a64e381SAndroid Build Coastguard Worker else if (hostReg->IsCompleted())
449*4a64e381SAndroid Build Coastguard Worker {
450*4a64e381SAndroid Build Coastguard Worker // Returns success if the same service has already been
451*4a64e381SAndroid Build Coastguard Worker // registered with exactly the same parameters.
452*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(OTBR_ERROR_NONE);
453*4a64e381SAndroid Build Coastguard Worker }
454*4a64e381SAndroid Build Coastguard Worker else
455*4a64e381SAndroid Build Coastguard Worker {
456*4a64e381SAndroid Build Coastguard Worker // If the same service is being registered with the same parameters,
457*4a64e381SAndroid Build Coastguard Worker // let's join the waiting queue for the result.
458*4a64e381SAndroid Build Coastguard Worker hostReg->mCallback = std::bind(
459*4a64e381SAndroid Build Coastguard Worker [](std::shared_ptr<ResultCallback> aExistingCallback, std::shared_ptr<ResultCallback> aNewCallback,
460*4a64e381SAndroid Build Coastguard Worker otbrError aError) {
461*4a64e381SAndroid Build Coastguard Worker std::move (*aExistingCallback)(aError);
462*4a64e381SAndroid Build Coastguard Worker std::move (*aNewCallback)(aError);
463*4a64e381SAndroid Build Coastguard Worker },
464*4a64e381SAndroid Build Coastguard Worker std::make_shared<ResultCallback>(std::move(hostReg->mCallback)),
465*4a64e381SAndroid Build Coastguard Worker std::make_shared<ResultCallback>(std::move(aCallback)), std::placeholders::_1);
466*4a64e381SAndroid Build Coastguard Worker }
467*4a64e381SAndroid Build Coastguard Worker
468*4a64e381SAndroid Build Coastguard Worker exit:
469*4a64e381SAndroid Build Coastguard Worker return std::move(aCallback);
470*4a64e381SAndroid Build Coastguard Worker }
471*4a64e381SAndroid Build Coastguard Worker
AddHostRegistration(HostRegistrationPtr && aHostReg)472*4a64e381SAndroid Build Coastguard Worker void Publisher::AddHostRegistration(HostRegistrationPtr &&aHostReg)
473*4a64e381SAndroid Build Coastguard Worker {
474*4a64e381SAndroid Build Coastguard Worker mHostRegistrations.emplace(MakeFullHostName(aHostReg->mName), std::move(aHostReg));
475*4a64e381SAndroid Build Coastguard Worker }
476*4a64e381SAndroid Build Coastguard Worker
RemoveHostRegistration(const std::string & aName,otbrError aError)477*4a64e381SAndroid Build Coastguard Worker void Publisher::RemoveHostRegistration(const std::string &aName, otbrError aError)
478*4a64e381SAndroid Build Coastguard Worker {
479*4a64e381SAndroid Build Coastguard Worker auto it = mHostRegistrations.find(MakeFullHostName(aName));
480*4a64e381SAndroid Build Coastguard Worker HostRegistrationPtr hostReg;
481*4a64e381SAndroid Build Coastguard Worker
482*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removing host %s", aName.c_str());
483*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(it != mHostRegistrations.end());
484*4a64e381SAndroid Build Coastguard Worker
485*4a64e381SAndroid Build Coastguard Worker // Keep the HostRegistration around before calling `Complete`
486*4a64e381SAndroid Build Coastguard Worker // to invoke the callback. This is for avoiding invalid access
487*4a64e381SAndroid Build Coastguard Worker // to the HostRegistration when it's freed from the callback.
488*4a64e381SAndroid Build Coastguard Worker hostReg = std::move(it->second);
489*4a64e381SAndroid Build Coastguard Worker mHostRegistrations.erase(it);
490*4a64e381SAndroid Build Coastguard Worker hostReg->Complete(aError);
491*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removed host %s", aName.c_str());
492*4a64e381SAndroid Build Coastguard Worker
493*4a64e381SAndroid Build Coastguard Worker exit:
494*4a64e381SAndroid Build Coastguard Worker return;
495*4a64e381SAndroid Build Coastguard Worker }
496*4a64e381SAndroid Build Coastguard Worker
FindHostRegistration(const std::string & aName)497*4a64e381SAndroid Build Coastguard Worker Publisher::HostRegistration *Publisher::FindHostRegistration(const std::string &aName)
498*4a64e381SAndroid Build Coastguard Worker {
499*4a64e381SAndroid Build Coastguard Worker auto it = mHostRegistrations.find(MakeFullHostName(aName));
500*4a64e381SAndroid Build Coastguard Worker
501*4a64e381SAndroid Build Coastguard Worker return it != mHostRegistrations.end() ? it->second.get() : nullptr;
502*4a64e381SAndroid Build Coastguard Worker }
503*4a64e381SAndroid Build Coastguard Worker
HandleDuplicateKeyRegistration(const std::string & aName,const KeyData & aKeyData,ResultCallback && aCallback)504*4a64e381SAndroid Build Coastguard Worker Publisher::ResultCallback Publisher::HandleDuplicateKeyRegistration(const std::string &aName,
505*4a64e381SAndroid Build Coastguard Worker const KeyData &aKeyData,
506*4a64e381SAndroid Build Coastguard Worker ResultCallback &&aCallback)
507*4a64e381SAndroid Build Coastguard Worker {
508*4a64e381SAndroid Build Coastguard Worker KeyRegistration *keyReg = FindKeyRegistration(aName);
509*4a64e381SAndroid Build Coastguard Worker
510*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(keyReg != nullptr);
511*4a64e381SAndroid Build Coastguard Worker
512*4a64e381SAndroid Build Coastguard Worker if (keyReg->IsOutdated(aName, aKeyData))
513*4a64e381SAndroid Build Coastguard Worker {
514*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removing existing key %s: outdated", aName.c_str());
515*4a64e381SAndroid Build Coastguard Worker RemoveKeyRegistration(keyReg->mName, OTBR_ERROR_ABORTED);
516*4a64e381SAndroid Build Coastguard Worker }
517*4a64e381SAndroid Build Coastguard Worker else if (keyReg->IsCompleted())
518*4a64e381SAndroid Build Coastguard Worker {
519*4a64e381SAndroid Build Coastguard Worker // Returns success if the same key has already been
520*4a64e381SAndroid Build Coastguard Worker // registered with exactly the same parameters.
521*4a64e381SAndroid Build Coastguard Worker std::move(aCallback)(OTBR_ERROR_NONE);
522*4a64e381SAndroid Build Coastguard Worker }
523*4a64e381SAndroid Build Coastguard Worker else
524*4a64e381SAndroid Build Coastguard Worker {
525*4a64e381SAndroid Build Coastguard Worker // If the same key is being registered with the same parameters,
526*4a64e381SAndroid Build Coastguard Worker // let's join the waiting queue for the result.
527*4a64e381SAndroid Build Coastguard Worker keyReg->mCallback = std::bind(
528*4a64e381SAndroid Build Coastguard Worker [](std::shared_ptr<ResultCallback> aExistingCallback, std::shared_ptr<ResultCallback> aNewCallback,
529*4a64e381SAndroid Build Coastguard Worker otbrError aError) {
530*4a64e381SAndroid Build Coastguard Worker std::move (*aExistingCallback)(aError);
531*4a64e381SAndroid Build Coastguard Worker std::move (*aNewCallback)(aError);
532*4a64e381SAndroid Build Coastguard Worker },
533*4a64e381SAndroid Build Coastguard Worker std::make_shared<ResultCallback>(std::move(keyReg->mCallback)),
534*4a64e381SAndroid Build Coastguard Worker std::make_shared<ResultCallback>(std::move(aCallback)), std::placeholders::_1);
535*4a64e381SAndroid Build Coastguard Worker }
536*4a64e381SAndroid Build Coastguard Worker
537*4a64e381SAndroid Build Coastguard Worker exit:
538*4a64e381SAndroid Build Coastguard Worker return std::move(aCallback);
539*4a64e381SAndroid Build Coastguard Worker }
540*4a64e381SAndroid Build Coastguard Worker
AddKeyRegistration(KeyRegistrationPtr && aKeyReg)541*4a64e381SAndroid Build Coastguard Worker void Publisher::AddKeyRegistration(KeyRegistrationPtr &&aKeyReg)
542*4a64e381SAndroid Build Coastguard Worker {
543*4a64e381SAndroid Build Coastguard Worker mKeyRegistrations.emplace(MakeFullKeyName(aKeyReg->mName), std::move(aKeyReg));
544*4a64e381SAndroid Build Coastguard Worker }
545*4a64e381SAndroid Build Coastguard Worker
RemoveKeyRegistration(const std::string & aName,otbrError aError)546*4a64e381SAndroid Build Coastguard Worker void Publisher::RemoveKeyRegistration(const std::string &aName, otbrError aError)
547*4a64e381SAndroid Build Coastguard Worker {
548*4a64e381SAndroid Build Coastguard Worker auto it = mKeyRegistrations.find(MakeFullKeyName(aName));
549*4a64e381SAndroid Build Coastguard Worker KeyRegistrationPtr keyReg;
550*4a64e381SAndroid Build Coastguard Worker
551*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removing key %s", aName.c_str());
552*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(it != mKeyRegistrations.end());
553*4a64e381SAndroid Build Coastguard Worker
554*4a64e381SAndroid Build Coastguard Worker // Keep the KeyRegistration around before calling `Complete`
555*4a64e381SAndroid Build Coastguard Worker // to invoke the callback. This is for avoiding invalid access
556*4a64e381SAndroid Build Coastguard Worker // to the KeyRegistration when it's freed from the callback.
557*4a64e381SAndroid Build Coastguard Worker keyReg = std::move(it->second);
558*4a64e381SAndroid Build Coastguard Worker mKeyRegistrations.erase(it);
559*4a64e381SAndroid Build Coastguard Worker keyReg->Complete(aError);
560*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("Removed key %s", aName.c_str());
561*4a64e381SAndroid Build Coastguard Worker
562*4a64e381SAndroid Build Coastguard Worker exit:
563*4a64e381SAndroid Build Coastguard Worker return;
564*4a64e381SAndroid Build Coastguard Worker }
565*4a64e381SAndroid Build Coastguard Worker
FindKeyRegistration(const std::string & aName)566*4a64e381SAndroid Build Coastguard Worker Publisher::KeyRegistration *Publisher::FindKeyRegistration(const std::string &aName)
567*4a64e381SAndroid Build Coastguard Worker {
568*4a64e381SAndroid Build Coastguard Worker auto it = mKeyRegistrations.find(MakeFullKeyName(aName));
569*4a64e381SAndroid Build Coastguard Worker
570*4a64e381SAndroid Build Coastguard Worker return it != mKeyRegistrations.end() ? it->second.get() : nullptr;
571*4a64e381SAndroid Build Coastguard Worker }
572*4a64e381SAndroid Build Coastguard Worker
FindKeyRegistration(const std::string & aName,const std::string & aType)573*4a64e381SAndroid Build Coastguard Worker Publisher::KeyRegistration *Publisher::FindKeyRegistration(const std::string &aName, const std::string &aType)
574*4a64e381SAndroid Build Coastguard Worker {
575*4a64e381SAndroid Build Coastguard Worker auto it = mKeyRegistrations.find(MakeFullServiceName(aName, aType));
576*4a64e381SAndroid Build Coastguard Worker
577*4a64e381SAndroid Build Coastguard Worker return it != mKeyRegistrations.end() ? it->second.get() : nullptr;
578*4a64e381SAndroid Build Coastguard Worker }
579*4a64e381SAndroid Build Coastguard Worker
~Registration(void)580*4a64e381SAndroid Build Coastguard Worker Publisher::Registration::~Registration(void)
581*4a64e381SAndroid Build Coastguard Worker {
582*4a64e381SAndroid Build Coastguard Worker TriggerCompleteCallback(OTBR_ERROR_ABORTED);
583*4a64e381SAndroid Build Coastguard Worker }
584*4a64e381SAndroid Build Coastguard Worker
IsOutdated(const std::string & aHostName,const std::string & aName,const std::string & aType,const SubTypeList & aSubTypeList,uint16_t aPort,const TxtData & aTxtData) const585*4a64e381SAndroid Build Coastguard Worker bool Publisher::ServiceRegistration::IsOutdated(const std::string &aHostName,
586*4a64e381SAndroid Build Coastguard Worker const std::string &aName,
587*4a64e381SAndroid Build Coastguard Worker const std::string &aType,
588*4a64e381SAndroid Build Coastguard Worker const SubTypeList &aSubTypeList,
589*4a64e381SAndroid Build Coastguard Worker uint16_t aPort,
590*4a64e381SAndroid Build Coastguard Worker const TxtData &aTxtData) const
591*4a64e381SAndroid Build Coastguard Worker {
592*4a64e381SAndroid Build Coastguard Worker return !(mHostName == aHostName && mName == aName && mType == aType && mSubTypeList == aSubTypeList &&
593*4a64e381SAndroid Build Coastguard Worker mPort == aPort && mTxtData == aTxtData);
594*4a64e381SAndroid Build Coastguard Worker }
595*4a64e381SAndroid Build Coastguard Worker
Complete(otbrError aError)596*4a64e381SAndroid Build Coastguard Worker void Publisher::ServiceRegistration::Complete(otbrError aError)
597*4a64e381SAndroid Build Coastguard Worker {
598*4a64e381SAndroid Build Coastguard Worker OnComplete(aError);
599*4a64e381SAndroid Build Coastguard Worker Registration::TriggerCompleteCallback(aError);
600*4a64e381SAndroid Build Coastguard Worker }
601*4a64e381SAndroid Build Coastguard Worker
OnComplete(otbrError aError)602*4a64e381SAndroid Build Coastguard Worker void Publisher::ServiceRegistration::OnComplete(otbrError aError)
603*4a64e381SAndroid Build Coastguard Worker {
604*4a64e381SAndroid Build Coastguard Worker if (!IsCompleted())
605*4a64e381SAndroid Build Coastguard Worker {
606*4a64e381SAndroid Build Coastguard Worker mPublisher->UpdateMdnsResponseCounters(mPublisher->mTelemetryInfo.mServiceRegistrations, aError);
607*4a64e381SAndroid Build Coastguard Worker mPublisher->UpdateServiceRegistrationEmaLatency(mName, mType, aError);
608*4a64e381SAndroid Build Coastguard Worker }
609*4a64e381SAndroid Build Coastguard Worker }
610*4a64e381SAndroid Build Coastguard Worker
IsOutdated(const std::string & aName,const AddressList & aAddresses) const611*4a64e381SAndroid Build Coastguard Worker bool Publisher::HostRegistration::IsOutdated(const std::string &aName, const AddressList &aAddresses) const
612*4a64e381SAndroid Build Coastguard Worker {
613*4a64e381SAndroid Build Coastguard Worker return !(mName == aName && mAddresses == aAddresses);
614*4a64e381SAndroid Build Coastguard Worker }
615*4a64e381SAndroid Build Coastguard Worker
Complete(otbrError aError)616*4a64e381SAndroid Build Coastguard Worker void Publisher::HostRegistration::Complete(otbrError aError)
617*4a64e381SAndroid Build Coastguard Worker {
618*4a64e381SAndroid Build Coastguard Worker OnComplete(aError);
619*4a64e381SAndroid Build Coastguard Worker Registration::TriggerCompleteCallback(aError);
620*4a64e381SAndroid Build Coastguard Worker }
621*4a64e381SAndroid Build Coastguard Worker
OnComplete(otbrError aError)622*4a64e381SAndroid Build Coastguard Worker void Publisher::HostRegistration::OnComplete(otbrError aError)
623*4a64e381SAndroid Build Coastguard Worker {
624*4a64e381SAndroid Build Coastguard Worker if (!IsCompleted())
625*4a64e381SAndroid Build Coastguard Worker {
626*4a64e381SAndroid Build Coastguard Worker mPublisher->UpdateMdnsResponseCounters(mPublisher->mTelemetryInfo.mHostRegistrations, aError);
627*4a64e381SAndroid Build Coastguard Worker mPublisher->UpdateHostRegistrationEmaLatency(mName, aError);
628*4a64e381SAndroid Build Coastguard Worker }
629*4a64e381SAndroid Build Coastguard Worker }
630*4a64e381SAndroid Build Coastguard Worker
IsOutdated(const std::string & aName,const KeyData & aKeyData) const631*4a64e381SAndroid Build Coastguard Worker bool Publisher::KeyRegistration::IsOutdated(const std::string &aName, const KeyData &aKeyData) const
632*4a64e381SAndroid Build Coastguard Worker {
633*4a64e381SAndroid Build Coastguard Worker return !(mName == aName && mKeyData == aKeyData);
634*4a64e381SAndroid Build Coastguard Worker }
635*4a64e381SAndroid Build Coastguard Worker
Complete(otbrError aError)636*4a64e381SAndroid Build Coastguard Worker void Publisher::KeyRegistration::Complete(otbrError aError)
637*4a64e381SAndroid Build Coastguard Worker {
638*4a64e381SAndroid Build Coastguard Worker OnComplete(aError);
639*4a64e381SAndroid Build Coastguard Worker Registration::TriggerCompleteCallback(aError);
640*4a64e381SAndroid Build Coastguard Worker }
641*4a64e381SAndroid Build Coastguard Worker
OnComplete(otbrError aError)642*4a64e381SAndroid Build Coastguard Worker void Publisher::KeyRegistration::OnComplete(otbrError aError)
643*4a64e381SAndroid Build Coastguard Worker {
644*4a64e381SAndroid Build Coastguard Worker if (!IsCompleted())
645*4a64e381SAndroid Build Coastguard Worker {
646*4a64e381SAndroid Build Coastguard Worker mPublisher->UpdateMdnsResponseCounters(mPublisher->mTelemetryInfo.mKeyRegistrations, aError);
647*4a64e381SAndroid Build Coastguard Worker mPublisher->UpdateKeyRegistrationEmaLatency(mName, aError);
648*4a64e381SAndroid Build Coastguard Worker }
649*4a64e381SAndroid Build Coastguard Worker }
650*4a64e381SAndroid Build Coastguard Worker
UpdateMdnsResponseCounters(otbr::MdnsResponseCounters & aCounters,otbrError aError)651*4a64e381SAndroid Build Coastguard Worker void Publisher::UpdateMdnsResponseCounters(otbr::MdnsResponseCounters &aCounters, otbrError aError)
652*4a64e381SAndroid Build Coastguard Worker {
653*4a64e381SAndroid Build Coastguard Worker switch (aError)
654*4a64e381SAndroid Build Coastguard Worker {
655*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_NONE:
656*4a64e381SAndroid Build Coastguard Worker ++aCounters.mSuccess;
657*4a64e381SAndroid Build Coastguard Worker break;
658*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_NOT_FOUND:
659*4a64e381SAndroid Build Coastguard Worker ++aCounters.mNotFound;
660*4a64e381SAndroid Build Coastguard Worker break;
661*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_INVALID_ARGS:
662*4a64e381SAndroid Build Coastguard Worker ++aCounters.mInvalidArgs;
663*4a64e381SAndroid Build Coastguard Worker break;
664*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_DUPLICATED:
665*4a64e381SAndroid Build Coastguard Worker ++aCounters.mDuplicated;
666*4a64e381SAndroid Build Coastguard Worker break;
667*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_NOT_IMPLEMENTED:
668*4a64e381SAndroid Build Coastguard Worker ++aCounters.mNotImplemented;
669*4a64e381SAndroid Build Coastguard Worker break;
670*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_ABORTED:
671*4a64e381SAndroid Build Coastguard Worker ++aCounters.mAborted;
672*4a64e381SAndroid Build Coastguard Worker break;
673*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_INVALID_STATE:
674*4a64e381SAndroid Build Coastguard Worker ++aCounters.mInvalidState;
675*4a64e381SAndroid Build Coastguard Worker break;
676*4a64e381SAndroid Build Coastguard Worker case OTBR_ERROR_MDNS:
677*4a64e381SAndroid Build Coastguard Worker default:
678*4a64e381SAndroid Build Coastguard Worker ++aCounters.mUnknownError;
679*4a64e381SAndroid Build Coastguard Worker break;
680*4a64e381SAndroid Build Coastguard Worker }
681*4a64e381SAndroid Build Coastguard Worker }
682*4a64e381SAndroid Build Coastguard Worker
UpdateEmaLatency(uint32_t & aEmaLatency,uint32_t aLatency,otbrError aError)683*4a64e381SAndroid Build Coastguard Worker void Publisher::UpdateEmaLatency(uint32_t &aEmaLatency, uint32_t aLatency, otbrError aError)
684*4a64e381SAndroid Build Coastguard Worker {
685*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(aError != OTBR_ERROR_ABORTED);
686*4a64e381SAndroid Build Coastguard Worker
687*4a64e381SAndroid Build Coastguard Worker if (!aEmaLatency)
688*4a64e381SAndroid Build Coastguard Worker {
689*4a64e381SAndroid Build Coastguard Worker aEmaLatency = aLatency;
690*4a64e381SAndroid Build Coastguard Worker }
691*4a64e381SAndroid Build Coastguard Worker else
692*4a64e381SAndroid Build Coastguard Worker {
693*4a64e381SAndroid Build Coastguard Worker aEmaLatency =
694*4a64e381SAndroid Build Coastguard Worker (aLatency * MdnsTelemetryInfo::kEmaFactorNumerator +
695*4a64e381SAndroid Build Coastguard Worker aEmaLatency * (MdnsTelemetryInfo::kEmaFactorDenominator - MdnsTelemetryInfo::kEmaFactorNumerator)) /
696*4a64e381SAndroid Build Coastguard Worker MdnsTelemetryInfo::kEmaFactorDenominator;
697*4a64e381SAndroid Build Coastguard Worker }
698*4a64e381SAndroid Build Coastguard Worker
699*4a64e381SAndroid Build Coastguard Worker exit:
700*4a64e381SAndroid Build Coastguard Worker return;
701*4a64e381SAndroid Build Coastguard Worker }
702*4a64e381SAndroid Build Coastguard Worker
UpdateServiceRegistrationEmaLatency(const std::string & aInstanceName,const std::string & aType,otbrError aError)703*4a64e381SAndroid Build Coastguard Worker void Publisher::UpdateServiceRegistrationEmaLatency(const std::string &aInstanceName,
704*4a64e381SAndroid Build Coastguard Worker const std::string &aType,
705*4a64e381SAndroid Build Coastguard Worker otbrError aError)
706*4a64e381SAndroid Build Coastguard Worker {
707*4a64e381SAndroid Build Coastguard Worker auto it = mServiceRegistrationBeginTime.find(std::make_pair(aInstanceName, aType));
708*4a64e381SAndroid Build Coastguard Worker
709*4a64e381SAndroid Build Coastguard Worker if (it != mServiceRegistrationBeginTime.end())
710*4a64e381SAndroid Build Coastguard Worker {
711*4a64e381SAndroid Build Coastguard Worker uint32_t latency = std::chrono::duration_cast<Milliseconds>(Clock::now() - it->second).count();
712*4a64e381SAndroid Build Coastguard Worker UpdateEmaLatency(mTelemetryInfo.mServiceRegistrationEmaLatency, latency, aError);
713*4a64e381SAndroid Build Coastguard Worker mServiceRegistrationBeginTime.erase(it);
714*4a64e381SAndroid Build Coastguard Worker }
715*4a64e381SAndroid Build Coastguard Worker }
716*4a64e381SAndroid Build Coastguard Worker
UpdateHostRegistrationEmaLatency(const std::string & aHostName,otbrError aError)717*4a64e381SAndroid Build Coastguard Worker void Publisher::UpdateHostRegistrationEmaLatency(const std::string &aHostName, otbrError aError)
718*4a64e381SAndroid Build Coastguard Worker {
719*4a64e381SAndroid Build Coastguard Worker auto it = mHostRegistrationBeginTime.find(aHostName);
720*4a64e381SAndroid Build Coastguard Worker
721*4a64e381SAndroid Build Coastguard Worker if (it != mHostRegistrationBeginTime.end())
722*4a64e381SAndroid Build Coastguard Worker {
723*4a64e381SAndroid Build Coastguard Worker uint32_t latency = std::chrono::duration_cast<Milliseconds>(Clock::now() - it->second).count();
724*4a64e381SAndroid Build Coastguard Worker UpdateEmaLatency(mTelemetryInfo.mHostRegistrationEmaLatency, latency, aError);
725*4a64e381SAndroid Build Coastguard Worker mHostRegistrationBeginTime.erase(it);
726*4a64e381SAndroid Build Coastguard Worker }
727*4a64e381SAndroid Build Coastguard Worker }
728*4a64e381SAndroid Build Coastguard Worker
UpdateKeyRegistrationEmaLatency(const std::string & aKeyName,otbrError aError)729*4a64e381SAndroid Build Coastguard Worker void Publisher::UpdateKeyRegistrationEmaLatency(const std::string &aKeyName, otbrError aError)
730*4a64e381SAndroid Build Coastguard Worker {
731*4a64e381SAndroid Build Coastguard Worker auto it = mKeyRegistrationBeginTime.find(aKeyName);
732*4a64e381SAndroid Build Coastguard Worker
733*4a64e381SAndroid Build Coastguard Worker if (it != mKeyRegistrationBeginTime.end())
734*4a64e381SAndroid Build Coastguard Worker {
735*4a64e381SAndroid Build Coastguard Worker uint32_t latency = std::chrono::duration_cast<Milliseconds>(Clock::now() - it->second).count();
736*4a64e381SAndroid Build Coastguard Worker UpdateEmaLatency(mTelemetryInfo.mKeyRegistrationEmaLatency, latency, aError);
737*4a64e381SAndroid Build Coastguard Worker mKeyRegistrationBeginTime.erase(it);
738*4a64e381SAndroid Build Coastguard Worker }
739*4a64e381SAndroid Build Coastguard Worker }
740*4a64e381SAndroid Build Coastguard Worker
UpdateServiceInstanceResolutionEmaLatency(const std::string & aInstanceName,const std::string & aType,otbrError aError)741*4a64e381SAndroid Build Coastguard Worker void Publisher::UpdateServiceInstanceResolutionEmaLatency(const std::string &aInstanceName,
742*4a64e381SAndroid Build Coastguard Worker const std::string &aType,
743*4a64e381SAndroid Build Coastguard Worker otbrError aError)
744*4a64e381SAndroid Build Coastguard Worker {
745*4a64e381SAndroid Build Coastguard Worker auto it = mServiceInstanceResolutionBeginTime.find(std::make_pair(aInstanceName, aType));
746*4a64e381SAndroid Build Coastguard Worker
747*4a64e381SAndroid Build Coastguard Worker if (it != mServiceInstanceResolutionBeginTime.end())
748*4a64e381SAndroid Build Coastguard Worker {
749*4a64e381SAndroid Build Coastguard Worker uint32_t latency = std::chrono::duration_cast<Milliseconds>(Clock::now() - it->second).count();
750*4a64e381SAndroid Build Coastguard Worker UpdateEmaLatency(mTelemetryInfo.mServiceResolutionEmaLatency, latency, aError);
751*4a64e381SAndroid Build Coastguard Worker mServiceInstanceResolutionBeginTime.erase(it);
752*4a64e381SAndroid Build Coastguard Worker }
753*4a64e381SAndroid Build Coastguard Worker }
754*4a64e381SAndroid Build Coastguard Worker
UpdateHostResolutionEmaLatency(const std::string & aHostName,otbrError aError)755*4a64e381SAndroid Build Coastguard Worker void Publisher::UpdateHostResolutionEmaLatency(const std::string &aHostName, otbrError aError)
756*4a64e381SAndroid Build Coastguard Worker {
757*4a64e381SAndroid Build Coastguard Worker auto it = mHostResolutionBeginTime.find(aHostName);
758*4a64e381SAndroid Build Coastguard Worker
759*4a64e381SAndroid Build Coastguard Worker if (it != mHostResolutionBeginTime.end())
760*4a64e381SAndroid Build Coastguard Worker {
761*4a64e381SAndroid Build Coastguard Worker uint32_t latency = std::chrono::duration_cast<Milliseconds>(Clock::now() - it->second).count();
762*4a64e381SAndroid Build Coastguard Worker UpdateEmaLatency(mTelemetryInfo.mHostResolutionEmaLatency, latency, aError);
763*4a64e381SAndroid Build Coastguard Worker mHostResolutionBeginTime.erase(it);
764*4a64e381SAndroid Build Coastguard Worker }
765*4a64e381SAndroid Build Coastguard Worker }
766*4a64e381SAndroid Build Coastguard Worker
AddAddress(AddressList & aAddressList,const Ip6Address & aAddress)767*4a64e381SAndroid Build Coastguard Worker void Publisher::AddAddress(AddressList &aAddressList, const Ip6Address &aAddress)
768*4a64e381SAndroid Build Coastguard Worker {
769*4a64e381SAndroid Build Coastguard Worker aAddressList.push_back(aAddress);
770*4a64e381SAndroid Build Coastguard Worker }
771*4a64e381SAndroid Build Coastguard Worker
RemoveAddress(AddressList & aAddressList,const Ip6Address & aAddress)772*4a64e381SAndroid Build Coastguard Worker void Publisher::RemoveAddress(AddressList &aAddressList, const Ip6Address &aAddress)
773*4a64e381SAndroid Build Coastguard Worker {
774*4a64e381SAndroid Build Coastguard Worker auto it = std::find(aAddressList.begin(), aAddressList.end(), aAddress);
775*4a64e381SAndroid Build Coastguard Worker
776*4a64e381SAndroid Build Coastguard Worker if (it != aAddressList.end())
777*4a64e381SAndroid Build Coastguard Worker {
778*4a64e381SAndroid Build Coastguard Worker aAddressList.erase(it);
779*4a64e381SAndroid Build Coastguard Worker }
780*4a64e381SAndroid Build Coastguard Worker }
781*4a64e381SAndroid Build Coastguard Worker
782*4a64e381SAndroid Build Coastguard Worker } // namespace Mdns
783*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
784*4a64e381SAndroid Build Coastguard Worker
785*4a64e381SAndroid Build Coastguard Worker #endif // OTBR_ENABLE_MDNS
786