• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mdns_protocol_impl.h"
17 
18 #include <arpa/inet.h>
19 #include <iostream>
20 #include <numeric>
21 #include <random>
22 #include <unistd.h>
23 
24 #include "mdns_packet_parser.h"
25 #include "netmgr_ext_log_wrapper.h"
26 
27 namespace OHOS {
28 namespace NetManagerStandard {
29 
30 namespace {
31 
32 constexpr uint32_t DEFAULT_TTL = 120;
33 constexpr uint16_t MDNS_FLUSH_CACHE_BIT = 0x8000;
34 
35 constexpr int PHASE_PTR = 1;
36 constexpr int PHASE_SRV = 2;
37 constexpr int PHASE_DOMAIN = 3;
38 
AddrToString(const std::any & addr)39 std::string AddrToString(const std::any &addr)
40 {
41     char buf[INET6_ADDRSTRLEN] = {0};
42     if (std::any_cast<in_addr>(&addr)) {
43         if (inet_ntop(AF_INET, std::any_cast<in_addr>(&addr), buf, sizeof(buf)) == nullptr) {
44             return std::string{};
45         }
46     } else if (std::any_cast<in6_addr>(&addr)) {
47         if (inet_ntop(AF_INET6, std::any_cast<in6_addr>(&addr), buf, sizeof(buf)) == nullptr) {
48             return std::string{};
49         }
50     } else {
51         return std::string{};
52     }
53     return std::string(buf);
54 }
55 
56 } // namespace
57 
MDnsProtocolImpl()58 MDnsProtocolImpl::MDnsProtocolImpl()
59 {
60     Init();
61 }
62 
Init()63 void MDnsProtocolImpl::Init()
64 {
65     listener_.CloseAllSocket();
66     if (config_.configAllIface) {
67         listener_.OpenSocketForEachIface(config_.ipv6Support, config_.configLo);
68     } else {
69         listener_.OpenSocketForDefault(config_.ipv6Support);
70     }
71     listener_.SetReceiveHandler(
72         [this](int sock, const MDnsPayload &payload) { return this->ReceivePacket(sock, payload); });
73     listener_.SetRefreshHandler([this](int sock) { return this->OnRefresh(sock); });
74 }
75 
SetConfig(const MDnsConfig & config)76 void MDnsProtocolImpl::SetConfig(const MDnsConfig &config)
77 {
78     config_ = config;
79 }
80 
GetConfig() const81 const MDnsConfig &MDnsProtocolImpl::GetConfig() const
82 {
83     return config_;
84 }
85 
SetHandler(const Handler & handler)86 void MDnsProtocolImpl::SetHandler(const Handler &handler)
87 {
88     handler_ = handler;
89 }
90 
Decorated(const std::string & name) const91 std::string MDnsProtocolImpl::Decorated(const std::string &name) const
92 {
93     return name + config_.topDomain;
94 }
95 
ExtractInstance(const Result & info) const96 std::string MDnsProtocolImpl::ExtractInstance(const Result &info) const
97 {
98     return Decorated(info.serviceName + MDNS_DOMAIN_SPLITER_STR + info.serviceType);
99 }
100 
Register(const Result & info)101 int32_t MDnsProtocolImpl::Register(const Result &info)
102 {
103     if (!(IsNameValid(info.serviceName) && IsTypeValid(info.serviceType) && IsPortValid(info.port))) {
104         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
105     }
106     std::string name = ExtractInstance(info);
107     if (!IsDomainValid(name)) {
108         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
109     }
110     {
111         std::lock_guard<std::recursive_mutex> guard(mutex_);
112         if (srvMap_.find(name) != srvMap_.end()) {
113             return NET_MDNS_ERR_SERVICE_INSTANCE_DUPLICATE;
114         }
115         srvMap_.emplace(name, info);
116     }
117 
118     listener_.Start();
119     return Announce(info, false);
120 }
121 
Discovery(const std::string & serviceType)122 int32_t MDnsProtocolImpl::Discovery(const std::string &serviceType)
123 {
124     if (!IsTypeValid(serviceType)) {
125         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
126     }
127     std::string name = Decorated(serviceType);
128     if (!IsDomainValid(name)) {
129         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
130     }
131     {
132         std::lock_guard<std::recursive_mutex> guard(mutex_);
133         ++reqMap_[name];
134     }
135     MDnsPayloadParser parser;
136     MDnsMessage msg{};
137     msg.questions.emplace_back(DNSProto::Question{
138         .name = name,
139         .qtype = DNSProto::RRTYPE_PTR,
140         .qclass = DNSProto::RRCLASS_IN,
141     });
142     msg.header.qdcount = msg.questions.size();
143 
144     listener_.Start();
145     ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
146 
147     return size > 0 ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
148 }
149 
HandleResolveInstanceLater(const Result & result)150 void MDnsProtocolImpl::HandleResolveInstanceLater(const Result &result)
151 {
152     cacheMap_[result.domain];
153     ResolveFromNet(result.domain);
154     RunTaskLater(
155         [r = result, this]() mutable {
156             if (cacheMap_.find(r.domain) == cacheMap_.end() || cacheMap_[r.domain].addr.empty()) {
157                 NETMGR_EXT_LOG_D("instance %{public}s, domain: %{public}s not found", r.serviceName.c_str(),
158                                  r.domain.c_str());
159                 return false;
160             }
161             r.ipv6 = cacheMap_[r.domain].ipv6;
162             r.addr = cacheMap_[r.domain].addr;
163             handler_(r, NETMANAGER_EXT_SUCCESS);
164             return true;
165         },
166         false);
167 }
168 
ResolveInstanceFromCache(const std::string & name)169 bool MDnsProtocolImpl::ResolveInstanceFromCache(const std::string &name)
170 {
171     std::lock_guard<std::recursive_mutex> guard(mutex_);
172     if (cacheMap_.find(name) != cacheMap_.end() && !cacheMap_[name].domain.empty()) {
173         Result r = cacheMap_[name];
174         if (cacheMap_.find(r.domain) != cacheMap_.end() && !cacheMap_[r.domain].addr.empty()) {
175             r.ipv6 = cacheMap_[r.domain].ipv6;
176             r.addr = cacheMap_[r.domain].addr;
177             RunTaskLater([r, this]() {
178                 handler_(r, NETMANAGER_EXT_SUCCESS);
179                 return true;
180             });
181         } else {
182             HandleResolveInstanceLater(r);
183         }
184         return true;
185     }
186     return false;
187 }
188 
ResolveInstanceFromNet(const std::string & name)189 bool MDnsProtocolImpl::ResolveInstanceFromNet(const std::string &name)
190 {
191     MDnsPayloadParser parser;
192     MDnsMessage msg{};
193     msg.questions.emplace_back(DNSProto::Question{
194         .name = name,
195         .qtype = DNSProto::RRTYPE_SRV,
196         .qclass = DNSProto::RRCLASS_IN,
197     });
198     msg.questions.emplace_back(DNSProto::Question{
199         .name = name,
200         .qtype = DNSProto::RRTYPE_TXT,
201         .qclass = DNSProto::RRCLASS_IN,
202     });
203     msg.header.qdcount = msg.questions.size();
204 
205     listener_.Start();
206     ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
207 
208     return size > 0;
209 }
210 
ResolveFromCache(const std::string & domain)211 bool MDnsProtocolImpl::ResolveFromCache(const std::string &domain)
212 {
213     if (cacheMap_.find(domain) != cacheMap_.end() && !cacheMap_[domain].addr.empty()) {
214         RunTaskLater([r = cacheMap_[domain], this]() {
215             handler_(r, NETMANAGER_EXT_SUCCESS);
216             return true;
217         });
218         return true;
219     }
220     return false;
221 }
222 
ResolveFromNet(const std::string & domain)223 bool MDnsProtocolImpl::ResolveFromNet(const std::string &domain)
224 {
225     MDnsPayloadParser parser;
226     MDnsMessage msg{};
227     msg.questions.emplace_back(DNSProto::Question{
228         .name = domain,
229         .qtype = DNSProto::RRTYPE_A,
230         .qclass = DNSProto::RRCLASS_IN,
231     });
232     msg.questions.emplace_back(DNSProto::Question{
233         .name = domain,
234         .qtype = DNSProto::RRTYPE_AAAA,
235         .qclass = DNSProto::RRCLASS_IN,
236     });
237     msg.header.qdcount = msg.questions.size();
238 
239     listener_.Start();
240     ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
241 
242     return size > 0;
243 }
244 
ResolveInstance(const std::string & instance)245 int32_t MDnsProtocolImpl::ResolveInstance(const std::string &instance)
246 {
247     if (!IsInstanceValid(instance)) {
248         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
249     }
250     std::string name = Decorated(instance);
251     if (!IsDomainValid(name)) {
252         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
253     }
254     std::lock_guard<std::recursive_mutex> guard(mutex_);
255     if (ResolveInstanceFromCache(name)) {
256         return NETMANAGER_EXT_SUCCESS;
257     }
258     ++reqMap_[name];
259     return ResolveInstanceFromNet(name) ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
260 }
261 
Resolve(const std::string & domain)262 int32_t MDnsProtocolImpl::Resolve(const std::string &domain)
263 {
264     if (!IsDomainValid(domain)) {
265         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
266     }
267     std::string name = domain;
268     if (!IsDomainValid(name)) {
269         return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
270     }
271     std::lock_guard<std::recursive_mutex> guard(mutex_);
272     if (ResolveFromCache(name)) {
273         return NETMANAGER_EXT_SUCCESS;
274     }
275     ++reqMap_[name];
276     return ResolveFromNet(name) ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
277 }
278 
UnRegister(const std::string & key)279 int32_t MDnsProtocolImpl::UnRegister(const std::string &key)
280 {
281     std::string name = Decorated(key);
282     std::lock_guard<std::recursive_mutex> guard(mutex_);
283     if (srvMap_.find(name) != srvMap_.end()) {
284         Announce(srvMap_[name], true);
285         srvMap_.erase(name);
286         return NETMANAGER_EXT_SUCCESS;
287     }
288     return NET_MDNS_ERR_SERVICE_INSTANCE_NOT_FOUND;
289 }
290 
StopDiscovery(const std::string & key)291 int32_t MDnsProtocolImpl::StopDiscovery(const std::string &key)
292 {
293     return Stop(Decorated(key));
294 }
295 
StopResolveInstance(const std::string & key)296 int32_t MDnsProtocolImpl::StopResolveInstance(const std::string &key)
297 {
298     return Stop(Decorated(key));
299 }
300 
StopResolve(const std::string & key)301 int32_t MDnsProtocolImpl::StopResolve(const std::string &key)
302 {
303     return Stop(key);
304 }
305 
Stop(const std::string & key)306 int32_t MDnsProtocolImpl::Stop(const std::string &key)
307 {
308     std::lock_guard<std::recursive_mutex> guard(mutex_);
309     if (reqMap_.find(key) != reqMap_.end() && reqMap_[key] > 0) {
310         --reqMap_[key];
311     }
312     return NETMANAGER_EXT_SUCCESS;
313 }
314 
Announce(const Result & info,bool off)315 int32_t MDnsProtocolImpl::Announce(const Result &info, bool off)
316 {
317     MDnsMessage response{};
318     response.header.flags = DNSProto::MDNS_ANSWER_FLAGS;
319     std::string name = Decorated(info.serviceName + MDNS_DOMAIN_SPLITER_STR + info.serviceType);
320     response.answers.emplace_back(DNSProto::ResourceRecord{.name = Decorated(info.serviceType),
321                                                            .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_PTR),
322                                                            .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
323                                                            .ttl = off ? 0U : DEFAULT_TTL,
324                                                            .rdata = name});
325     response.answers.emplace_back(DNSProto::ResourceRecord{.name = name,
326                                                            .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_SRV),
327                                                            .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
328                                                            .ttl = off ? 0U : DEFAULT_TTL,
329                                                            .rdata = DNSProto::RDataSrv{
330                                                                .priority = 0,
331                                                                .weight = 0,
332                                                                .port = static_cast<uint16_t>(info.port),
333                                                                .name = GetHostDomain(),
334                                                            }});
335     response.answers.emplace_back(DNSProto::ResourceRecord{.name = name,
336                                                            .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_TXT),
337                                                            .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
338                                                            .ttl = off ? 0U : DEFAULT_TTL,
339                                                            .rdata = info.txt});
340     MDnsPayloadParser parser;
341     ssize_t size = listener_.MulticastAll(parser.ToBytes(response));
342     return size > 0 ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
343 }
344 
ReceivePacket(int sock,const MDnsPayload & payload)345 void MDnsProtocolImpl::ReceivePacket(int sock, const MDnsPayload &payload)
346 {
347     if (payload.size() == 0) {
348         NETMGR_EXT_LOG_W("empty payload received");
349         return;
350     }
351     MDnsPayloadParser parser;
352     MDnsMessage msg = parser.FromBytes(payload);
353     if (parser.GetError() != 0) {
354         NETMGR_EXT_LOG_W("payload parse failed");
355         return;
356     }
357     if ((msg.header.flags & DNSProto::HEADER_FLAGS_QR_MASK) == 0) {
358         ProcessQuestion(sock, msg);
359     } else {
360         ProcessAnswer(sock, msg);
361     }
362 }
363 
OnRefresh(int sock)364 void MDnsProtocolImpl::OnRefresh(int sock)
365 {
366     std::lock_guard<std::recursive_mutex> guard(mutex_);
367     std::queue<Task> tmp;
368     while (taskQueue_.size() > 0) {
369         auto func = taskQueue_.front();
370         taskQueue_.pop();
371         if (!func()) {
372             tmp.push(func);
373         }
374     }
375     tmp.swap(taskQueue_);
376 }
377 
AppendRecord(std::vector<DNSProto::ResourceRecord> & rrlist,DNSProto::RRType type,const std::string & name,const std::any & rdata)378 void MDnsProtocolImpl::AppendRecord(std::vector<DNSProto::ResourceRecord> &rrlist, DNSProto::RRType type,
379                                     const std::string &name, const std::any &rdata)
380 {
381     rrlist.emplace_back(DNSProto::ResourceRecord{.name = name,
382                                                  .rtype = static_cast<uint16_t>(type),
383                                                  .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
384                                                  .ttl = DEFAULT_TTL,
385                                                  .rdata = rdata});
386 }
387 
ProcessQuestion(int sock,const MDnsMessage & msg)388 void MDnsProtocolImpl::ProcessQuestion(int sock, const MDnsMessage &msg)
389 {
390     const sockaddr *saddrIf = listener_.GetSockAddr(sock);
391     if (saddrIf == nullptr) {
392         return;
393     }
394     std::any anyAddr;
395     DNSProto::RRType anyAddrType;
396     if (saddrIf->sa_family == AF_INET6) {
397         anyAddr = reinterpret_cast<const sockaddr_in6 *>(saddrIf)->sin6_addr;
398         anyAddrType = DNSProto::RRTYPE_AAAA;
399     } else {
400         anyAddr = reinterpret_cast<const sockaddr_in *>(saddrIf)->sin_addr;
401         anyAddrType = DNSProto::RRTYPE_A;
402     }
403     int phase = 0;
404     MDnsMessage response{};
405     response.header.flags = DNSProto::MDNS_ANSWER_FLAGS;
406     for (size_t i = 0; i < msg.header.qdcount; ++i) {
407         ProcessQuestionRecord(anyAddr, anyAddrType, msg.questions[i], phase, response);
408     }
409     if (phase < PHASE_DOMAIN) {
410         AppendRecord(response.additional, anyAddrType, GetHostDomain(), anyAddr);
411     }
412     if (phase != 0 && response.answers.size() > 0) {
413         listener_.Multicast(sock, MDnsPayloadParser().ToBytes(response));
414     }
415 }
416 
ProcessQuestionRecord(const std::any & anyAddr,const DNSProto::RRType & anyAddrType,const DNSProto::Question & qu,int & phase,MDnsMessage & response)417 void MDnsProtocolImpl::ProcessQuestionRecord(const std::any &anyAddr, const DNSProto::RRType &anyAddrType,
418                                              const DNSProto::Question &qu, int &phase, MDnsMessage &response)
419 {
420     std::lock_guard<std::recursive_mutex> guard(mutex_);
421     std::string name = qu.name;
422     if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_PTR) {
423         std::for_each(srvMap_.begin(), srvMap_.end(), [&](const auto &elem) -> void {
424             if (EndsWith(elem.first, name)) {
425                 AppendRecord(response.answers, DNSProto::RRTYPE_PTR, name, elem.first);
426                 AppendRecord(response.additional, DNSProto::RRTYPE_SRV, elem.first,
427                              DNSProto::RDataSrv{
428                                  .priority = 0,
429                                  .weight = 0,
430                                  .port = static_cast<uint16_t>(elem.second.port),
431                                  .name = GetHostDomain(),
432                              });
433                 AppendRecord(response.additional, DNSProto::RRTYPE_TXT, elem.first, elem.second.txt);
434             }
435         });
436         phase = std::max(phase, PHASE_PTR);
437     }
438     if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_SRV) {
439         auto iter = srvMap_.find(name);
440         if (iter == srvMap_.end()) {
441             return;
442         }
443         AppendRecord(response.answers, DNSProto::RRTYPE_SRV, name,
444                      DNSProto::RDataSrv{
445                          .priority = 0,
446                          .weight = 0,
447                          .port = static_cast<uint16_t>(iter->second.port),
448                          .name = GetHostDomain(),
449                      });
450         phase = std::max(phase, PHASE_SRV);
451     }
452     if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_TXT) {
453         auto iter = srvMap_.find(name);
454         if (iter == srvMap_.end()) {
455             return;
456         }
457         AppendRecord(response.answers, DNSProto::RRTYPE_TXT, name, iter->second.txt);
458         phase = std::max(phase, PHASE_SRV);
459     }
460     if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_A || qu.qtype == DNSProto::RRTYPE_AAAA) {
461         if (name != GetHostDomain() || (qu.qtype != DNSProto::RRTYPE_ANY && anyAddrType != qu.qtype)) {
462             return;
463         }
464         AppendRecord(response.answers, anyAddrType, name, anyAddr);
465         phase = std::max(phase, PHASE_DOMAIN);
466     }
467 }
468 
ProcessAnswer(int sock,const MDnsMessage & msg)469 void MDnsProtocolImpl::ProcessAnswer(int sock, const MDnsMessage &msg)
470 {
471     const sockaddr *saddrIf = listener_.GetSockAddr(sock);
472     if (saddrIf == nullptr) {
473         return;
474     }
475     bool v6 = (saddrIf->sa_family == AF_INET6);
476 
477     std::vector<Result> matches;
478     std::set<std::string> changed;
479     for (size_t i = 0; i < msg.answers.size(); ++i) {
480         ProcessAnswerRecord(v6, msg.answers[i], &matches, changed);
481     }
482 
483     for (size_t i = 0; i < msg.additional.size(); ++i) {
484         ProcessAnswerRecord(v6, msg.additional[i], nullptr, changed);
485     }
486 
487     for (size_t i = 0; i < msg.additional.size(); ++i) {
488         ProcessAnswerRecord(v6, msg.additional[i], nullptr, changed);
489     }
490 
491     for (auto i = matches.begin(); i != matches.end() && handler_ != nullptr; ++i) {
492         handler_(*i, NETMANAGER_EXT_SUCCESS);
493     }
494 
495     for (auto i = changed.begin(); i != changed.end() && handler_ != nullptr; ++i) {
496         if (cacheMap_.find(*i) == cacheMap_.end()) {
497             continue;
498         }
499         cacheMap_[*i].iface = listener_.GetIface(sock);
500         if (cacheMap_[*i].type == INSTANCE_RESOLVED && ResolveInstanceFromCache(*i)) {
501             continue;
502         }
503         handler_(cacheMap_[*i], NETMANAGER_EXT_SUCCESS);
504     }
505 }
506 
ProcessPtrRecord(bool v6,const DNSProto::ResourceRecord & rr,std::vector<Result> * matches)507 void MDnsProtocolImpl::ProcessPtrRecord(bool v6, const DNSProto::ResourceRecord &rr, std::vector<Result> *matches)
508 {
509     const std::string *data = std::any_cast<std::string>(&rr.rdata);
510     if (data == nullptr) {
511         return;
512     }
513     Result result;
514     ExtractNameAndType(*data, result.serviceName, result.serviceType);
515     if (std::find_if(matches->begin(), matches->end(), [&](const auto &elem) {
516             return elem.serviceName == result.serviceName && elem.serviceType == result.serviceType;
517         }) == matches->end()) {
518         result.type = (rr.ttl == 0) ? SERVICE_LOST : SERVICE_FOUND;
519         matches->emplace_back(std::move(result));
520         if (rr.ttl == 0) {
521             cacheMap_.erase(*data);
522         } else {
523             cacheMap_[*data];
524         }
525     }
526 }
527 
ProcessAnswerRecord(bool v6,const DNSProto::ResourceRecord & rr,std::vector<Result> * matches,std::set<std::string> & changed)528 void MDnsProtocolImpl::ProcessAnswerRecord(bool v6, const DNSProto::ResourceRecord &rr, std::vector<Result> *matches,
529                                            std::set<std::string> &changed)
530 {
531     std::lock_guard<std::recursive_mutex> guard(mutex_);
532     std::string name = rr.name;
533     bool isReq = reqMap_.find(name) != reqMap_.end() && reqMap_[name] > 0;
534     if (!isReq && cacheMap_.find(name) == cacheMap_.end()) {
535         return;
536     }
537     if (rr.rtype == DNSProto::RRTYPE_PTR && matches) {
538         ProcessPtrRecord(v6, rr, matches);
539     } else if (rr.rtype == DNSProto::RRTYPE_SRV) {
540         const DNSProto::RDataSrv *srv = std::any_cast<DNSProto::RDataSrv>(&rr.rdata);
541         if (rr.ttl == 0) {
542             return cacheMap_[name].domain.clear();
543         }
544         if (srv == nullptr) {
545             return;
546         }
547         Result &result = cacheMap_[name];
548         result.type = INSTANCE_RESOLVED;
549         ExtractNameAndType(name, result.serviceName, result.serviceType);
550         result.domain = srv->name;
551         result.port = srv->port;
552         cacheMap_[srv->name];
553         if (isReq) {
554             changed.emplace(name);
555         }
556     } else if (rr.rtype == DNSProto::RRTYPE_TXT) {
557         const TxtRecordEncoded *txt = std::any_cast<TxtRecordEncoded>(&rr.rdata);
558         if (rr.ttl == 0 || txt == nullptr) {
559             return;
560         }
561         Result &result = cacheMap_[name];
562         result.txt = *txt;
563     } else if (rr.rtype == DNSProto::RRTYPE_A || rr.rtype == DNSProto::RRTYPE_AAAA) {
564         if (v6 != (rr.rtype == DNSProto::RRTYPE_AAAA)) {
565             return;
566         }
567         if (rr.ttl == 0) {
568             return cacheMap_[name].domain.clear();
569         }
570         Result &result = cacheMap_[name];
571         result.type = DOMAIN_RESOLVED;
572         result.domain = name;
573         result.ipv6 = (rr.rtype == DNSProto::RRTYPE_AAAA);
574         result.addr = AddrToString(rr.rdata);
575         if (isReq) {
576             changed.emplace(name);
577         }
578     } else {
579         NETMGR_EXT_LOG_D("Unknown packet received, type=[%{public}d]", rr.rtype);
580     }
581 }
582 
GetHostDomain()583 std::string MDnsProtocolImpl::GetHostDomain()
584 {
585     if (config_.hostname.empty()) {
586         char buffer[MDNS_MAX_DOMAIN_LABEL];
587         if (gethostname(buffer, sizeof(buffer)) == 0) {
588             config_.hostname = buffer;
589             static auto uid = []() {
590                 std::random_device rd;
591                 return rd();
592             }();
593             config_.hostname += std::to_string(uid);
594         }
595     }
596     return Decorated(config_.hostname);
597 }
598 
RunTaskLater(const Task & task,bool atonce)599 void MDnsProtocolImpl::RunTaskLater(const Task &task, bool atonce)
600 {
601     {
602         std::lock_guard<std::recursive_mutex> guard(mutex_);
603         taskQueue_.push(task);
604     }
605     if (atonce) {
606         listener_.TriggerRefresh();
607     }
608 }
609 
610 } // namespace NetManagerStandard
611 } // namespace OHOS
612