18e745fdaSopenharmony_ci/*
28e745fdaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
38e745fdaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48e745fdaSopenharmony_ci * you may not use this file except in compliance with the License.
58e745fdaSopenharmony_ci * You may obtain a copy of the License at
68e745fdaSopenharmony_ci *
78e745fdaSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88e745fdaSopenharmony_ci *
98e745fdaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108e745fdaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118e745fdaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128e745fdaSopenharmony_ci * See the License for the specific language governing permissions and
138e745fdaSopenharmony_ci * limitations under the License.
148e745fdaSopenharmony_ci */
158e745fdaSopenharmony_ci
168e745fdaSopenharmony_ci#include "mdns_protocol_impl.h"
178e745fdaSopenharmony_ci
188e745fdaSopenharmony_ci#include <arpa/inet.h>
198e745fdaSopenharmony_ci#include <cstddef>
208e745fdaSopenharmony_ci#include <iostream>
218e745fdaSopenharmony_ci#include <random>
228e745fdaSopenharmony_ci#include <sys/types.h>
238e745fdaSopenharmony_ci#include <unistd.h>
248e745fdaSopenharmony_ci#include <fcntl.h>
258e745fdaSopenharmony_ci
268e745fdaSopenharmony_ci#include "mdns_manager.h"
278e745fdaSopenharmony_ci#include "mdns_packet_parser.h"
288e745fdaSopenharmony_ci#include "net_conn_client.h"
298e745fdaSopenharmony_ci#include "netmgr_ext_log_wrapper.h"
308e745fdaSopenharmony_ci
318e745fdaSopenharmony_ci#include "securec.h"
328e745fdaSopenharmony_ci
338e745fdaSopenharmony_cinamespace OHOS {
348e745fdaSopenharmony_cinamespace NetManagerStandard {
358e745fdaSopenharmony_ci
368e745fdaSopenharmony_ciconstexpr uint32_t DEFAULT_INTEVAL_MS = 2000;
378e745fdaSopenharmony_ciconstexpr uint32_t DEFAULT_LOST_MS = 10000;
388e745fdaSopenharmony_ciconstexpr uint32_t DEFAULT_TTL = 120;
398e745fdaSopenharmony_ciconstexpr uint16_t MDNS_FLUSH_CACHE_BIT = 0x8000;
408e745fdaSopenharmony_ci
418e745fdaSopenharmony_ciconstexpr int PHASE_PTR = 1;
428e745fdaSopenharmony_ciconstexpr int PHASE_SRV = 2;
438e745fdaSopenharmony_ciconstexpr int PHASE_DOMAIN = 3;
448e745fdaSopenharmony_ci
458e745fdaSopenharmony_cistd::string AddrToString(const std::any &addr)
468e745fdaSopenharmony_ci{
478e745fdaSopenharmony_ci    char buf[INET6_ADDRSTRLEN] = {0};
488e745fdaSopenharmony_ci    if (std::any_cast<in_addr>(&addr)) {
498e745fdaSopenharmony_ci        if (inet_ntop(AF_INET, std::any_cast<in_addr>(&addr), buf, sizeof(buf)) == nullptr) {
508e745fdaSopenharmony_ci            return std::string{};
518e745fdaSopenharmony_ci        }
528e745fdaSopenharmony_ci    } else if (std::any_cast<in6_addr>(&addr)) {
538e745fdaSopenharmony_ci        if (inet_ntop(AF_INET6, std::any_cast<in6_addr>(&addr), buf, sizeof(buf)) == nullptr) {
548e745fdaSopenharmony_ci            return std::string{};
558e745fdaSopenharmony_ci        }
568e745fdaSopenharmony_ci    }
578e745fdaSopenharmony_ci    return std::string(buf);
588e745fdaSopenharmony_ci}
598e745fdaSopenharmony_ci
608e745fdaSopenharmony_ciint64_t MilliSecondsSinceEpoch()
618e745fdaSopenharmony_ci{
628e745fdaSopenharmony_ci    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
638e745fdaSopenharmony_ci        .count();
648e745fdaSopenharmony_ci}
658e745fdaSopenharmony_ci
668e745fdaSopenharmony_ciMDnsProtocolImpl::MDnsProtocolImpl()
678e745fdaSopenharmony_ci{
688e745fdaSopenharmony_ci    Init();
698e745fdaSopenharmony_ci}
708e745fdaSopenharmony_ci
718e745fdaSopenharmony_civoid MDnsProtocolImpl::Init()
728e745fdaSopenharmony_ci{
738e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log MDnsProtocolImpl init");
748e745fdaSopenharmony_ci    listener_.Stop();
758e745fdaSopenharmony_ci    listener_.CloseAllSocket();
768e745fdaSopenharmony_ci
778e745fdaSopenharmony_ci    if (config_.configAllIface) {
788e745fdaSopenharmony_ci        listener_.OpenSocketForEachIface(config_.ipv6Support, config_.configLo);
798e745fdaSopenharmony_ci    } else {
808e745fdaSopenharmony_ci        listener_.OpenSocketForDefault(config_.ipv6Support);
818e745fdaSopenharmony_ci    }
828e745fdaSopenharmony_ci    listener_.SetReceiveHandler(
838e745fdaSopenharmony_ci        [this](int sock, const MDnsPayload &payload) { return this->ReceivePacket(sock, payload); });
848e745fdaSopenharmony_ci    listener_.SetFinishedHandler([this](int sock) {
858e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
868e745fdaSopenharmony_ci        RunTaskQueue(taskQueue_);
878e745fdaSopenharmony_ci    });
888e745fdaSopenharmony_ci    listener_.Start();
898e745fdaSopenharmony_ci
908e745fdaSopenharmony_ci    taskQueue_.clear();
918e745fdaSopenharmony_ci    taskOnChange_.clear();
928e745fdaSopenharmony_ci    AddTask([this]() { return Browse(); }, false);
938e745fdaSopenharmony_ci}
948e745fdaSopenharmony_ci
958e745fdaSopenharmony_cibool MDnsProtocolImpl::Browse()
968e745fdaSopenharmony_ci{
978e745fdaSopenharmony_ci    if (lastRunTime != -1 && MilliSecondsSinceEpoch() - lastRunTime < DEFAULT_INTEVAL_MS) {
988e745fdaSopenharmony_ci        return false;
998e745fdaSopenharmony_ci    }
1008e745fdaSopenharmony_ci    lastRunTime = MilliSecondsSinceEpoch();
1018e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
1028e745fdaSopenharmony_ci    for (auto &&[key, res] : browserMap_) {
1038e745fdaSopenharmony_ci        NETMGR_EXT_LOG_D("mdns_log Browse browserMap_ key[%{public}s] res.size[%{public}zu]", key.c_str(), res.size());
1048e745fdaSopenharmony_ci        if (nameCbMap_.find(key) != nameCbMap_.end() &&
1058e745fdaSopenharmony_ci            !MDnsManager::GetInstance().IsAvailableCallback(nameCbMap_[key])) {
1068e745fdaSopenharmony_ci            continue;
1078e745fdaSopenharmony_ci        }
1088e745fdaSopenharmony_ci        handleOfflineService(key, res);
1098e745fdaSopenharmony_ci        MDnsPayloadParser parser;
1108e745fdaSopenharmony_ci        MDnsMessage msg{};
1118e745fdaSopenharmony_ci        msg.questions.emplace_back(DNSProto::Question{
1128e745fdaSopenharmony_ci            .name = key,
1138e745fdaSopenharmony_ci            .qtype = DNSProto::RRTYPE_PTR,
1148e745fdaSopenharmony_ci            .qclass = DNSProto::RRCLASS_IN,
1158e745fdaSopenharmony_ci        });
1168e745fdaSopenharmony_ci        listener_.MulticastAll(parser.ToBytes(msg));
1178e745fdaSopenharmony_ci    }
1188e745fdaSopenharmony_ci    return false;
1198e745fdaSopenharmony_ci}
1208e745fdaSopenharmony_ci
1218e745fdaSopenharmony_ciint32_t MDnsProtocolImpl::ConnectControl(int32_t sockfd, sockaddr* serverAddr)
1228e745fdaSopenharmony_ci{
1238e745fdaSopenharmony_ci    uint32_t flags = static_cast<uint32_t>(fcntl(sockfd, F_GETFL, 0));
1248e745fdaSopenharmony_ci    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
1258e745fdaSopenharmony_ci    int32_t ret = connect(sockfd, serverAddr, sizeof(sockaddr));
1268e745fdaSopenharmony_ci    if ((ret < 0) && (errno != EINPROGRESS)) {
1278e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("connect error: %{public}d", errno);
1288e745fdaSopenharmony_ci        return NETMANAGER_EXT_ERR_INTERNAL;
1298e745fdaSopenharmony_ci    }
1308e745fdaSopenharmony_ci    if (ret == 0) {
1318e745fdaSopenharmony_ci        fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
1328e745fdaSopenharmony_ci        NETMGR_EXT_LOG_I("connect success.");
1338e745fdaSopenharmony_ci        return NETMANAGER_EXT_SUCCESS;
1348e745fdaSopenharmony_ci    }
1358e745fdaSopenharmony_ci
1368e745fdaSopenharmony_ci    fd_set rset;
1378e745fdaSopenharmony_ci    FD_ZERO(&rset);
1388e745fdaSopenharmony_ci    FD_SET(sockfd, &rset);
1398e745fdaSopenharmony_ci    fd_set wset = rset;
1408e745fdaSopenharmony_ci    timeval tval {1, 0};
1418e745fdaSopenharmony_ci    ret = select(sockfd + 1, &rset, &wset, NULL, &tval);
1428e745fdaSopenharmony_ci    if (ret < 0) { // select error.
1438e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("select error: %{public}d", errno);
1448e745fdaSopenharmony_ci        return NETMANAGER_EXT_ERR_INTERNAL;
1458e745fdaSopenharmony_ci    }
1468e745fdaSopenharmony_ci    if (ret == 0) { // timeout
1478e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("connect timeout...");
1488e745fdaSopenharmony_ci        return NETMANAGER_EXT_ERR_INTERNAL;
1498e745fdaSopenharmony_ci    }
1508e745fdaSopenharmony_ci    if (!FD_ISSET(sockfd, &rset) && !FD_ISSET(sockfd, &wset)) {
1518e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("select error: sockfd not set");
1528e745fdaSopenharmony_ci        return NETMANAGER_EXT_ERR_INTERNAL;
1538e745fdaSopenharmony_ci    }
1548e745fdaSopenharmony_ci
1558e745fdaSopenharmony_ci    int32_t result = NETMANAGER_EXT_ERR_INTERNAL;
1568e745fdaSopenharmony_ci    socklen_t len = sizeof(result);
1578e745fdaSopenharmony_ci    if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &result, &len) < 0) {
1588e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("getsockopt error: %{public}d", errno);
1598e745fdaSopenharmony_ci        return NETMANAGER_EXT_ERR_INTERNAL;
1608e745fdaSopenharmony_ci    }
1618e745fdaSopenharmony_ci    if (result != 0) { // connect failed.
1628e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("connect failed. error: %{public}d", result);
1638e745fdaSopenharmony_ci        return NETMANAGER_EXT_ERR_INTERNAL;
1648e745fdaSopenharmony_ci    }
1658e745fdaSopenharmony_ci    fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
1668e745fdaSopenharmony_ci    NETMGR_EXT_LOG_I("lost but connect success.");
1678e745fdaSopenharmony_ci    return NETMANAGER_EXT_SUCCESS;
1688e745fdaSopenharmony_ci}
1698e745fdaSopenharmony_ci
1708e745fdaSopenharmony_cibool MDnsProtocolImpl::IsConnectivity(const std::string &ip, int32_t port)
1718e745fdaSopenharmony_ci{
1728e745fdaSopenharmony_ci    if (ip.empty()) {
1738e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("ip is empty");
1748e745fdaSopenharmony_ci        return false;
1758e745fdaSopenharmony_ci    }
1768e745fdaSopenharmony_ci
1778e745fdaSopenharmony_ci    int32_t sockfd = socket(AF_INET, SOCK_STREAM, 0);
1788e745fdaSopenharmony_ci    if (sockfd < 0) {
1798e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("create socket error: %{public}d", errno);
1808e745fdaSopenharmony_ci        return false;
1818e745fdaSopenharmony_ci    }
1828e745fdaSopenharmony_ci
1838e745fdaSopenharmony_ci    struct sockaddr_in serverAddr;
1848e745fdaSopenharmony_ci    if (memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr)) != EOK) {
1858e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("memset_s serverAddr failed!");
1868e745fdaSopenharmony_ci        close(sockfd);
1878e745fdaSopenharmony_ci        return false;
1888e745fdaSopenharmony_ci    }
1898e745fdaSopenharmony_ci
1908e745fdaSopenharmony_ci    serverAddr.sin_family = AF_INET;
1918e745fdaSopenharmony_ci    serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
1928e745fdaSopenharmony_ci    serverAddr.sin_port = htons(port);
1938e745fdaSopenharmony_ci    if (ConnectControl(sockfd, (struct sockaddr*)&serverAddr) != NETMANAGER_EXT_SUCCESS) {
1948e745fdaSopenharmony_ci        NETMGR_EXT_LOG_I("connect error: %{public}d", errno);
1958e745fdaSopenharmony_ci        close(sockfd);
1968e745fdaSopenharmony_ci        return false;
1978e745fdaSopenharmony_ci    }
1988e745fdaSopenharmony_ci
1998e745fdaSopenharmony_ci    close(sockfd);
2008e745fdaSopenharmony_ci    return true;
2018e745fdaSopenharmony_ci}
2028e745fdaSopenharmony_ci
2038e745fdaSopenharmony_civoid MDnsProtocolImpl::handleOfflineService(const std::string &key, std::vector<Result> &res)
2048e745fdaSopenharmony_ci{
2058e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log handleOfflineService key:[%{public}s]", key.c_str());
2068e745fdaSopenharmony_ci    for (auto it = res.begin(); it != res.end();) {
2078e745fdaSopenharmony_ci        if (lastRunTime - it->refrehTime > DEFAULT_LOST_MS && it->state == State::LIVE) {
2088e745fdaSopenharmony_ci            std::string fullName = Decorated(it->serviceName + MDNS_DOMAIN_SPLITER_STR + it->serviceType);
2098e745fdaSopenharmony_ci            if ((cacheMap_.find(fullName) != cacheMap_.end()) &&
2108e745fdaSopenharmony_ci                IsConnectivity(cacheMap_[fullName].addr, cacheMap_[fullName].port)) {
2118e745fdaSopenharmony_ci                it++;
2128e745fdaSopenharmony_ci                continue;
2138e745fdaSopenharmony_ci            }
2148e745fdaSopenharmony_ci
2158e745fdaSopenharmony_ci            it->state = State::DEAD;
2168e745fdaSopenharmony_ci            if (nameCbMap_.find(key) != nameCbMap_.end() && nameCbMap_[key] != nullptr) {
2178e745fdaSopenharmony_ci                NETMGR_EXT_LOG_W("mdns_log HandleServiceLost");
2188e745fdaSopenharmony_ci                nameCbMap_[key]->HandleServiceLost(ConvertResultToInfo(*it), NETMANAGER_EXT_SUCCESS);
2198e745fdaSopenharmony_ci            }
2208e745fdaSopenharmony_ci            it = res.erase(it);
2218e745fdaSopenharmony_ci            cacheMap_.erase(fullName);
2228e745fdaSopenharmony_ci        } else {
2238e745fdaSopenharmony_ci            it++;
2248e745fdaSopenharmony_ci        }
2258e745fdaSopenharmony_ci    }
2268e745fdaSopenharmony_ci}
2278e745fdaSopenharmony_ci
2288e745fdaSopenharmony_civoid MDnsProtocolImpl::SetConfig(const MDnsConfig &config)
2298e745fdaSopenharmony_ci{
2308e745fdaSopenharmony_ci    config_ = config;
2318e745fdaSopenharmony_ci}
2328e745fdaSopenharmony_ci
2338e745fdaSopenharmony_ciconst MDnsConfig &MDnsProtocolImpl::GetConfig() const
2348e745fdaSopenharmony_ci{
2358e745fdaSopenharmony_ci    return config_;
2368e745fdaSopenharmony_ci}
2378e745fdaSopenharmony_ci
2388e745fdaSopenharmony_cistd::string MDnsProtocolImpl::Decorated(const std::string &name) const
2398e745fdaSopenharmony_ci{
2408e745fdaSopenharmony_ci    return name + config_.topDomain;
2418e745fdaSopenharmony_ci}
2428e745fdaSopenharmony_ci
2438e745fdaSopenharmony_ciint32_t MDnsProtocolImpl::Register(const Result &info)
2448e745fdaSopenharmony_ci{
2458e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log Register");
2468e745fdaSopenharmony_ci    if (!(IsNameValid(info.serviceName) && IsTypeValid(info.serviceType) && IsPortValid(info.port))) {
2478e745fdaSopenharmony_ci        return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
2488e745fdaSopenharmony_ci    }
2498e745fdaSopenharmony_ci    std::string name = Decorated(info.serviceName + MDNS_DOMAIN_SPLITER_STR + info.serviceType);
2508e745fdaSopenharmony_ci    if (!IsDomainValid(name)) {
2518e745fdaSopenharmony_ci        return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
2528e745fdaSopenharmony_ci    }
2538e745fdaSopenharmony_ci    {
2548e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
2558e745fdaSopenharmony_ci        if (srvMap_.find(name) != srvMap_.end()) {
2568e745fdaSopenharmony_ci            return NET_MDNS_ERR_SERVICE_INSTANCE_DUPLICATE;
2578e745fdaSopenharmony_ci        }
2588e745fdaSopenharmony_ci        srvMap_.emplace(name, info);
2598e745fdaSopenharmony_ci    }
2608e745fdaSopenharmony_ci    return Announce(info, false);
2618e745fdaSopenharmony_ci}
2628e745fdaSopenharmony_ci
2638e745fdaSopenharmony_ciint32_t MDnsProtocolImpl::UnRegister(const std::string &key)
2648e745fdaSopenharmony_ci{
2658e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log UnRegister");
2668e745fdaSopenharmony_ci    std::string name = Decorated(key);
2678e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
2688e745fdaSopenharmony_ci    if (srvMap_.find(name) != srvMap_.end()) {
2698e745fdaSopenharmony_ci        Announce(srvMap_[name], true);
2708e745fdaSopenharmony_ci        srvMap_.erase(name);
2718e745fdaSopenharmony_ci        return NETMANAGER_EXT_SUCCESS;
2728e745fdaSopenharmony_ci    }
2738e745fdaSopenharmony_ci    return NET_MDNS_ERR_SERVICE_INSTANCE_NOT_FOUND;
2748e745fdaSopenharmony_ci}
2758e745fdaSopenharmony_ci
2768e745fdaSopenharmony_cibool MDnsProtocolImpl::DiscoveryFromCache(const std::string &serviceType, const sptr<IDiscoveryCallback> &cb)
2778e745fdaSopenharmony_ci{
2788e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log DiscoveryFromCache");
2798e745fdaSopenharmony_ci    std::string name = Decorated(serviceType);
2808e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
2818e745fdaSopenharmony_ci    if (!IsBrowserAvailable(name)) {
2828e745fdaSopenharmony_ci        return false;
2838e745fdaSopenharmony_ci    }
2848e745fdaSopenharmony_ci
2858e745fdaSopenharmony_ci    if (browserMap_.find(name) == browserMap_.end()) {
2868e745fdaSopenharmony_ci        NETMGR_EXT_LOG_D("mdns_log DiscoveryFromCache browserMap_ not find name");
2878e745fdaSopenharmony_ci        return false;
2888e745fdaSopenharmony_ci    }
2898e745fdaSopenharmony_ci
2908e745fdaSopenharmony_ci    for (auto &res : browserMap_[name]) {
2918e745fdaSopenharmony_ci        if (res.state == State::REMOVE || res.state == State::DEAD) {
2928e745fdaSopenharmony_ci            continue;
2938e745fdaSopenharmony_ci        }
2948e745fdaSopenharmony_ci        AddTask([cb, info = ConvertResultToInfo(res)]() {
2958e745fdaSopenharmony_ci            NETMGR_EXT_LOG_W("mdns_log DiscoveryFromCache ConvertResultToInfo HandleServiceFound");
2968e745fdaSopenharmony_ci            if (MDnsManager::GetInstance().IsAvailableCallback(cb)) {
2978e745fdaSopenharmony_ci                cb->HandleServiceFound(info, NETMANAGER_EXT_SUCCESS);
2988e745fdaSopenharmony_ci            }
2998e745fdaSopenharmony_ci            return true;
3008e745fdaSopenharmony_ci        });
3018e745fdaSopenharmony_ci    }
3028e745fdaSopenharmony_ci    return true;
3038e745fdaSopenharmony_ci}
3048e745fdaSopenharmony_ci
3058e745fdaSopenharmony_cibool MDnsProtocolImpl::DiscoveryFromNet(const std::string &serviceType, const sptr<IDiscoveryCallback> &cb)
3068e745fdaSopenharmony_ci{
3078e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log DiscoveryFromNet");
3088e745fdaSopenharmony_ci    std::string name = Decorated(serviceType);
3098e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
3108e745fdaSopenharmony_ci    browserMap_.insert({name, std::vector<Result>{}});
3118e745fdaSopenharmony_ci    nameCbMap_[name] = cb;
3128e745fdaSopenharmony_ci    // key is serviceTYpe
3138e745fdaSopenharmony_ci    AddEvent(name, [this, name, cb]() {
3148e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
3158e745fdaSopenharmony_ci        if (!IsBrowserAvailable(name)) {
3168e745fdaSopenharmony_ci            return false;
3178e745fdaSopenharmony_ci        }
3188e745fdaSopenharmony_ci        if (!MDnsManager::GetInstance().IsAvailableCallback(cb)) {
3198e745fdaSopenharmony_ci            return true;
3208e745fdaSopenharmony_ci        }
3218e745fdaSopenharmony_ci        for (auto &res : browserMap_[name]) {
3228e745fdaSopenharmony_ci            std::string fullName = Decorated(res.serviceName + MDNS_DOMAIN_SPLITER_STR + res.serviceType);
3238e745fdaSopenharmony_ci            NETMGR_EXT_LOG_W("mdns_log DiscoveryFromNet name:[%{public}s] fullName:[%{public}s]", name.c_str(),
3248e745fdaSopenharmony_ci                             fullName.c_str());
3258e745fdaSopenharmony_ci            if (cacheMap_.find(fullName) == cacheMap_.end() ||
3268e745fdaSopenharmony_ci                (res.state == State::ADD || res.state == State::REFRESH)) {
3278e745fdaSopenharmony_ci                NETMGR_EXT_LOG_W("mdns_log HandleServiceFound");
3288e745fdaSopenharmony_ci                cb->HandleServiceFound(ConvertResultToInfo(res), NETMANAGER_EXT_SUCCESS);
3298e745fdaSopenharmony_ci                res.state = State::LIVE;
3308e745fdaSopenharmony_ci            }
3318e745fdaSopenharmony_ci            if (res.state == State::REMOVE) {
3328e745fdaSopenharmony_ci                res.state = State::DEAD;
3338e745fdaSopenharmony_ci                NETMGR_EXT_LOG_D("mdns_log HandleServiceLost");
3348e745fdaSopenharmony_ci                cb->HandleServiceLost(ConvertResultToInfo(res), NETMANAGER_EXT_SUCCESS);
3358e745fdaSopenharmony_ci                if (cacheMap_.find(fullName) != cacheMap_.end()) {
3368e745fdaSopenharmony_ci                    cacheMap_.erase(fullName);
3378e745fdaSopenharmony_ci                }
3388e745fdaSopenharmony_ci            }
3398e745fdaSopenharmony_ci        }
3408e745fdaSopenharmony_ci        return false;
3418e745fdaSopenharmony_ci    });
3428e745fdaSopenharmony_ci
3438e745fdaSopenharmony_ci    AddTask([=]() {
3448e745fdaSopenharmony_ci            MDnsPayloadParser parser;
3458e745fdaSopenharmony_ci            MDnsMessage msg{};
3468e745fdaSopenharmony_ci            msg.questions.emplace_back(DNSProto::Question{
3478e745fdaSopenharmony_ci                .name = name,
3488e745fdaSopenharmony_ci                .qtype = DNSProto::RRTYPE_PTR,
3498e745fdaSopenharmony_ci                .qclass = DNSProto::RRCLASS_IN,
3508e745fdaSopenharmony_ci            });
3518e745fdaSopenharmony_ci            listener_.MulticastAll(parser.ToBytes(msg));
3528e745fdaSopenharmony_ci            return true;
3538e745fdaSopenharmony_ci        }, false);
3548e745fdaSopenharmony_ci    return true;
3558e745fdaSopenharmony_ci}
3568e745fdaSopenharmony_ci
3578e745fdaSopenharmony_ciint32_t MDnsProtocolImpl::Discovery(const std::string &serviceType, const sptr<IDiscoveryCallback> &cb)
3588e745fdaSopenharmony_ci{
3598e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log Discovery");
3608e745fdaSopenharmony_ci    DiscoveryFromCache(serviceType, cb);
3618e745fdaSopenharmony_ci    DiscoveryFromNet(serviceType, cb);
3628e745fdaSopenharmony_ci    return NETMANAGER_EXT_SUCCESS;
3638e745fdaSopenharmony_ci}
3648e745fdaSopenharmony_ci
3658e745fdaSopenharmony_cibool MDnsProtocolImpl::ResolveInstanceFromCache(const std::string &name, const sptr<IResolveCallback> &cb)
3668e745fdaSopenharmony_ci{
3678e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log ResolveInstanceFromCache");
3688e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
3698e745fdaSopenharmony_ci    if (!IsInstanceCacheAvailable(name)) {
3708e745fdaSopenharmony_ci        NETMGR_EXT_LOG_W("mdns_log ResolveInstanceFromCache cacheMap_ has no element [%{public}s]", name.c_str());
3718e745fdaSopenharmony_ci        return false;
3728e745fdaSopenharmony_ci    }
3738e745fdaSopenharmony_ci
3748e745fdaSopenharmony_ci    NETMGR_EXT_LOG_I("mdns_log rr.name : [%{public}s]", name.c_str());
3758e745fdaSopenharmony_ci    Result r = cacheMap_[name];
3768e745fdaSopenharmony_ci    if (IsDomainCacheAvailable(r.domain)) {
3778e745fdaSopenharmony_ci        r.ipv6 = cacheMap_[r.domain].ipv6;
3788e745fdaSopenharmony_ci        r.addr = cacheMap_[r.domain].addr;
3798e745fdaSopenharmony_ci
3808e745fdaSopenharmony_ci        NETMGR_EXT_LOG_D("mdns_log Add Task DomainCache Available, [%{public}s]", r.domain.c_str());
3818e745fdaSopenharmony_ci        AddTask([cb, info = ConvertResultToInfo(r)]() {
3828e745fdaSopenharmony_ci            if (nullptr != cb) {
3838e745fdaSopenharmony_ci                cb->HandleResolveResult(info, NETMANAGER_EXT_SUCCESS);
3848e745fdaSopenharmony_ci            }
3858e745fdaSopenharmony_ci            return true;
3868e745fdaSopenharmony_ci        });
3878e745fdaSopenharmony_ci    } else {
3888e745fdaSopenharmony_ci        ResolveFromNet(r.domain, nullptr);
3898e745fdaSopenharmony_ci        NETMGR_EXT_LOG_D("mdns_log Add Event DomainCache UnAvailable, [%{public}s]", r.domain.c_str());
3908e745fdaSopenharmony_ci        AddEvent(r.domain, [this, cb, r]() mutable {
3918e745fdaSopenharmony_ci            if (!IsDomainCacheAvailable(r.domain)) {
3928e745fdaSopenharmony_ci                return false;
3938e745fdaSopenharmony_ci            }
3948e745fdaSopenharmony_ci            r.ipv6 = cacheMap_[r.domain].ipv6;
3958e745fdaSopenharmony_ci            r.addr = cacheMap_[r.domain].addr;
3968e745fdaSopenharmony_ci            if (nullptr != cb) {
3978e745fdaSopenharmony_ci                cb->HandleResolveResult(ConvertResultToInfo(r), NETMANAGER_EXT_SUCCESS);
3988e745fdaSopenharmony_ci            }
3998e745fdaSopenharmony_ci            return true;
4008e745fdaSopenharmony_ci        });
4018e745fdaSopenharmony_ci    }
4028e745fdaSopenharmony_ci    return true;
4038e745fdaSopenharmony_ci}
4048e745fdaSopenharmony_ci
4058e745fdaSopenharmony_cibool MDnsProtocolImpl::ResolveInstanceFromNet(const std::string &name, const sptr<IResolveCallback> &cb)
4068e745fdaSopenharmony_ci{
4078e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log ResolveInstanceFromNet");
4088e745fdaSopenharmony_ci    {
4098e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
4108e745fdaSopenharmony_ci        cacheMap_[name].state = State::ADD;
4118e745fdaSopenharmony_ci        ExtractNameAndType(name, cacheMap_[name].serviceName, cacheMap_[name].serviceType);
4128e745fdaSopenharmony_ci    }
4138e745fdaSopenharmony_ci    MDnsPayloadParser parser;
4148e745fdaSopenharmony_ci    MDnsMessage msg{};
4158e745fdaSopenharmony_ci    msg.questions.emplace_back(DNSProto::Question{
4168e745fdaSopenharmony_ci        .name = name,
4178e745fdaSopenharmony_ci        .qtype = DNSProto::RRTYPE_SRV,
4188e745fdaSopenharmony_ci        .qclass = DNSProto::RRCLASS_IN,
4198e745fdaSopenharmony_ci    });
4208e745fdaSopenharmony_ci    msg.questions.emplace_back(DNSProto::Question{
4218e745fdaSopenharmony_ci        .name = name,
4228e745fdaSopenharmony_ci        .qtype = DNSProto::RRTYPE_TXT,
4238e745fdaSopenharmony_ci        .qclass = DNSProto::RRCLASS_IN,
4248e745fdaSopenharmony_ci    });
4258e745fdaSopenharmony_ci    msg.header.qdcount = msg.questions.size();
4268e745fdaSopenharmony_ci    AddEvent(name, [this, name, cb]() { return ResolveInstanceFromCache(name, cb); });
4278e745fdaSopenharmony_ci    ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
4288e745fdaSopenharmony_ci    return size > 0;
4298e745fdaSopenharmony_ci}
4308e745fdaSopenharmony_ci
4318e745fdaSopenharmony_cibool MDnsProtocolImpl::ResolveFromCache(const std::string &domain, const sptr<IResolveCallback> &cb)
4328e745fdaSopenharmony_ci{
4338e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log ResolveFromCache");
4348e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
4358e745fdaSopenharmony_ci    if (!IsDomainCacheAvailable(domain)) {
4368e745fdaSopenharmony_ci        return false;
4378e745fdaSopenharmony_ci    }
4388e745fdaSopenharmony_ci    AddTask([this, cb, info = ConvertResultToInfo(cacheMap_[domain])]() {
4398e745fdaSopenharmony_ci        if (nullptr != cb) {
4408e745fdaSopenharmony_ci            cb->HandleResolveResult(info, NETMANAGER_EXT_SUCCESS);
4418e745fdaSopenharmony_ci        }
4428e745fdaSopenharmony_ci        return true;
4438e745fdaSopenharmony_ci    });
4448e745fdaSopenharmony_ci    return true;
4458e745fdaSopenharmony_ci}
4468e745fdaSopenharmony_ci
4478e745fdaSopenharmony_cibool MDnsProtocolImpl::ResolveFromNet(const std::string &domain, const sptr<IResolveCallback> &cb)
4488e745fdaSopenharmony_ci{
4498e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log ResolveFromNet");
4508e745fdaSopenharmony_ci    {
4518e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
4528e745fdaSopenharmony_ci        cacheMap_[domain];
4538e745fdaSopenharmony_ci        cacheMap_[domain].domain = domain;
4548e745fdaSopenharmony_ci    }
4558e745fdaSopenharmony_ci    MDnsPayloadParser parser;
4568e745fdaSopenharmony_ci    MDnsMessage msg{};
4578e745fdaSopenharmony_ci    msg.questions.emplace_back(DNSProto::Question{
4588e745fdaSopenharmony_ci        .name = domain,
4598e745fdaSopenharmony_ci        .qtype = DNSProto::RRTYPE_A,
4608e745fdaSopenharmony_ci        .qclass = DNSProto::RRCLASS_IN,
4618e745fdaSopenharmony_ci    });
4628e745fdaSopenharmony_ci    msg.questions.emplace_back(DNSProto::Question{
4638e745fdaSopenharmony_ci        .name = domain,
4648e745fdaSopenharmony_ci        .qtype = DNSProto::RRTYPE_AAAA,
4658e745fdaSopenharmony_ci        .qclass = DNSProto::RRCLASS_IN,
4668e745fdaSopenharmony_ci    });
4678e745fdaSopenharmony_ci    // key is serviceName
4688e745fdaSopenharmony_ci    AddEvent(domain, [this, cb, domain]() { return ResolveFromCache(domain, cb); });
4698e745fdaSopenharmony_ci    ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
4708e745fdaSopenharmony_ci    return size > 0;
4718e745fdaSopenharmony_ci}
4728e745fdaSopenharmony_ci
4738e745fdaSopenharmony_ciint32_t MDnsProtocolImpl::ResolveInstance(const std::string &instance, const sptr<IResolveCallback> &cb)
4748e745fdaSopenharmony_ci{
4758e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log execute ResolveInstance");
4768e745fdaSopenharmony_ci    if (!IsInstanceValid(instance)) {
4778e745fdaSopenharmony_ci        return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
4788e745fdaSopenharmony_ci    }
4798e745fdaSopenharmony_ci    std::string name = Decorated(instance);
4808e745fdaSopenharmony_ci    if (!IsDomainValid(name)) {
4818e745fdaSopenharmony_ci        return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
4828e745fdaSopenharmony_ci    }
4838e745fdaSopenharmony_ci    if (ResolveInstanceFromCache(name, cb)) {
4848e745fdaSopenharmony_ci        return NETMANAGER_EXT_SUCCESS;
4858e745fdaSopenharmony_ci    }
4868e745fdaSopenharmony_ci    return ResolveInstanceFromNet(name, cb) ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
4878e745fdaSopenharmony_ci}
4888e745fdaSopenharmony_ci
4898e745fdaSopenharmony_ciint32_t MDnsProtocolImpl::Announce(const Result &info, bool off)
4908e745fdaSopenharmony_ci{
4918e745fdaSopenharmony_ci    NETMGR_EXT_LOG_I("mdns_log Announce message");
4928e745fdaSopenharmony_ci    MDnsMessage response{};
4938e745fdaSopenharmony_ci    response.header.flags = DNSProto::MDNS_ANSWER_FLAGS;
4948e745fdaSopenharmony_ci    std::string name = Decorated(info.serviceName + MDNS_DOMAIN_SPLITER_STR + info.serviceType);
4958e745fdaSopenharmony_ci    response.answers.emplace_back(DNSProto::ResourceRecord{.name = Decorated(info.serviceType),
4968e745fdaSopenharmony_ci                                                           .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_PTR),
4978e745fdaSopenharmony_ci                                                           .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
4988e745fdaSopenharmony_ci                                                           .ttl = off ? 0U : DEFAULT_TTL,
4998e745fdaSopenharmony_ci                                                           .rdata = name});
5008e745fdaSopenharmony_ci    response.answers.emplace_back(DNSProto::ResourceRecord{.name = name,
5018e745fdaSopenharmony_ci                                                           .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_SRV),
5028e745fdaSopenharmony_ci                                                           .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
5038e745fdaSopenharmony_ci                                                           .ttl = off ? 0U : DEFAULT_TTL,
5048e745fdaSopenharmony_ci                                                           .rdata = DNSProto::RDataSrv{
5058e745fdaSopenharmony_ci                                                               .priority = 0,
5068e745fdaSopenharmony_ci                                                               .weight = 0,
5078e745fdaSopenharmony_ci                                                               .port = static_cast<uint16_t>(info.port),
5088e745fdaSopenharmony_ci                                                               .name = GetHostDomain(),
5098e745fdaSopenharmony_ci                                                           }});
5108e745fdaSopenharmony_ci    response.answers.emplace_back(DNSProto::ResourceRecord{.name = name,
5118e745fdaSopenharmony_ci                                                           .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_TXT),
5128e745fdaSopenharmony_ci                                                           .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
5138e745fdaSopenharmony_ci                                                           .ttl = off ? 0U : DEFAULT_TTL,
5148e745fdaSopenharmony_ci                                                           .rdata = info.txt});
5158e745fdaSopenharmony_ci    MDnsPayloadParser parser;
5168e745fdaSopenharmony_ci    ssize_t size = listener_.MulticastAll(parser.ToBytes(response));
5178e745fdaSopenharmony_ci    return size > 0 ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
5188e745fdaSopenharmony_ci}
5198e745fdaSopenharmony_ci
5208e745fdaSopenharmony_civoid MDnsProtocolImpl::ReceivePacket(int sock, const MDnsPayload &payload)
5218e745fdaSopenharmony_ci{
5228e745fdaSopenharmony_ci    if (payload.size() == 0) {
5238e745fdaSopenharmony_ci        return;
5248e745fdaSopenharmony_ci    }
5258e745fdaSopenharmony_ci    MDnsPayloadParser parser;
5268e745fdaSopenharmony_ci    MDnsMessage msg = parser.FromBytes(payload);
5278e745fdaSopenharmony_ci    if (parser.GetError() != 0) {
5288e745fdaSopenharmony_ci        NETMGR_EXT_LOG_E("parser payload failed");
5298e745fdaSopenharmony_ci        return;
5308e745fdaSopenharmony_ci    }
5318e745fdaSopenharmony_ci    if ((msg.header.flags & DNSProto::HEADER_FLAGS_QR_MASK) == 0) {
5328e745fdaSopenharmony_ci        ProcessQuestion(sock, msg);
5338e745fdaSopenharmony_ci    } else {
5348e745fdaSopenharmony_ci        ProcessAnswer(sock, msg);
5358e745fdaSopenharmony_ci    }
5368e745fdaSopenharmony_ci}
5378e745fdaSopenharmony_ci
5388e745fdaSopenharmony_civoid MDnsProtocolImpl::AppendRecord(std::vector<DNSProto::ResourceRecord> &rrlist, DNSProto::RRType type,
5398e745fdaSopenharmony_ci                                    const std::string &name, const std::any &rdata)
5408e745fdaSopenharmony_ci{
5418e745fdaSopenharmony_ci    rrlist.emplace_back(DNSProto::ResourceRecord{.name = name,
5428e745fdaSopenharmony_ci                                                 .rtype = static_cast<uint16_t>(type),
5438e745fdaSopenharmony_ci                                                 .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
5448e745fdaSopenharmony_ci                                                 .ttl = DEFAULT_TTL,
5458e745fdaSopenharmony_ci                                                 .rdata = rdata});
5468e745fdaSopenharmony_ci}
5478e745fdaSopenharmony_ci
5488e745fdaSopenharmony_civoid MDnsProtocolImpl::ProcessQuestion(int sock, const MDnsMessage &msg)
5498e745fdaSopenharmony_ci{
5508e745fdaSopenharmony_ci    const sockaddr *saddrIf = listener_.GetSockAddr(sock);
5518e745fdaSopenharmony_ci    if (saddrIf == nullptr) {
5528e745fdaSopenharmony_ci        NETMGR_EXT_LOG_W("mdns_log ProcessQuestion saddrIf is null");
5538e745fdaSopenharmony_ci        return;
5548e745fdaSopenharmony_ci    }
5558e745fdaSopenharmony_ci    std::any anyAddr;
5568e745fdaSopenharmony_ci    DNSProto::RRType anyAddrType;
5578e745fdaSopenharmony_ci    if (saddrIf->sa_family == AF_INET6) {
5588e745fdaSopenharmony_ci        anyAddr = reinterpret_cast<const sockaddr_in6 *>(saddrIf)->sin6_addr;
5598e745fdaSopenharmony_ci        anyAddrType = DNSProto::RRTYPE_AAAA;
5608e745fdaSopenharmony_ci    } else {
5618e745fdaSopenharmony_ci        anyAddr = reinterpret_cast<const sockaddr_in *>(saddrIf)->sin_addr;
5628e745fdaSopenharmony_ci        anyAddrType = DNSProto::RRTYPE_A;
5638e745fdaSopenharmony_ci    }
5648e745fdaSopenharmony_ci    int phase = 0;
5658e745fdaSopenharmony_ci    MDnsMessage response{};
5668e745fdaSopenharmony_ci    response.header.flags = DNSProto::MDNS_ANSWER_FLAGS;
5678e745fdaSopenharmony_ci    for (size_t i = 0; i < msg.header.qdcount; ++i) {
5688e745fdaSopenharmony_ci        ProcessQuestionRecord(anyAddr, anyAddrType, msg.questions[i], phase, response);
5698e745fdaSopenharmony_ci    }
5708e745fdaSopenharmony_ci    if (phase < PHASE_DOMAIN) {
5718e745fdaSopenharmony_ci        AppendRecord(response.additional, anyAddrType, GetHostDomain(), anyAddr);
5728e745fdaSopenharmony_ci    }
5738e745fdaSopenharmony_ci
5748e745fdaSopenharmony_ci    if (phase != 0 && response.answers.size() > 0) {
5758e745fdaSopenharmony_ci        listener_.Multicast(sock, MDnsPayloadParser().ToBytes(response));
5768e745fdaSopenharmony_ci    }
5778e745fdaSopenharmony_ci}
5788e745fdaSopenharmony_ci
5798e745fdaSopenharmony_civoid MDnsProtocolImpl::ProcessQuestionRecord(const std::any &anyAddr, const DNSProto::RRType &anyAddrType,
5808e745fdaSopenharmony_ci                                             const DNSProto::Question &qu, int &phase, MDnsMessage &response)
5818e745fdaSopenharmony_ci{
5828e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log ProcessQuestionRecord");
5838e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
5848e745fdaSopenharmony_ci    std::string name = qu.name;
5858e745fdaSopenharmony_ci    if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_PTR) {
5868e745fdaSopenharmony_ci        std::for_each(srvMap_.begin(), srvMap_.end(), [&](const auto &elem) -> void {
5878e745fdaSopenharmony_ci            if (EndsWith(elem.first, name)) {
5888e745fdaSopenharmony_ci                AppendRecord(response.answers, DNSProto::RRTYPE_PTR, name, elem.first);
5898e745fdaSopenharmony_ci                AppendRecord(response.additional, DNSProto::RRTYPE_SRV, elem.first,
5908e745fdaSopenharmony_ci                             DNSProto::RDataSrv{
5918e745fdaSopenharmony_ci                                 .priority = 0,
5928e745fdaSopenharmony_ci                                 .weight = 0,
5938e745fdaSopenharmony_ci                                 .port = static_cast<uint16_t>(elem.second.port),
5948e745fdaSopenharmony_ci                                 .name = GetHostDomain(),
5958e745fdaSopenharmony_ci                             });
5968e745fdaSopenharmony_ci                AppendRecord(response.additional, DNSProto::RRTYPE_TXT, elem.first, elem.second.txt);
5978e745fdaSopenharmony_ci            }
5988e745fdaSopenharmony_ci        });
5998e745fdaSopenharmony_ci        phase = std::max(phase, PHASE_PTR);
6008e745fdaSopenharmony_ci    }
6018e745fdaSopenharmony_ci    if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_SRV) {
6028e745fdaSopenharmony_ci        auto iter = srvMap_.find(name);
6038e745fdaSopenharmony_ci        if (iter == srvMap_.end()) {
6048e745fdaSopenharmony_ci            return;
6058e745fdaSopenharmony_ci        }
6068e745fdaSopenharmony_ci        AppendRecord(response.answers, DNSProto::RRTYPE_SRV, name,
6078e745fdaSopenharmony_ci                     DNSProto::RDataSrv{
6088e745fdaSopenharmony_ci                         .priority = 0,
6098e745fdaSopenharmony_ci                         .weight = 0,
6108e745fdaSopenharmony_ci                         .port = static_cast<uint16_t>(iter->second.port),
6118e745fdaSopenharmony_ci                         .name = GetHostDomain(),
6128e745fdaSopenharmony_ci                     });
6138e745fdaSopenharmony_ci        phase = std::max(phase, PHASE_SRV);
6148e745fdaSopenharmony_ci    }
6158e745fdaSopenharmony_ci    if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_TXT) {
6168e745fdaSopenharmony_ci        auto iter = srvMap_.find(name);
6178e745fdaSopenharmony_ci        if (iter == srvMap_.end()) {
6188e745fdaSopenharmony_ci            return;
6198e745fdaSopenharmony_ci        }
6208e745fdaSopenharmony_ci        AppendRecord(response.answers, DNSProto::RRTYPE_TXT, name, iter->second.txt);
6218e745fdaSopenharmony_ci        phase = std::max(phase, PHASE_SRV);
6228e745fdaSopenharmony_ci    }
6238e745fdaSopenharmony_ci    if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_A || qu.qtype == DNSProto::RRTYPE_AAAA) {
6248e745fdaSopenharmony_ci        if (name != GetHostDomain() || (qu.qtype != DNSProto::RRTYPE_ANY && anyAddrType != qu.qtype)) {
6258e745fdaSopenharmony_ci            return;
6268e745fdaSopenharmony_ci        }
6278e745fdaSopenharmony_ci        AppendRecord(response.answers, anyAddrType, name, anyAddr);
6288e745fdaSopenharmony_ci        phase = std::max(phase, PHASE_DOMAIN);
6298e745fdaSopenharmony_ci    }
6308e745fdaSopenharmony_ci}
6318e745fdaSopenharmony_ci
6328e745fdaSopenharmony_civoid MDnsProtocolImpl::ProcessAnswer(int sock, const MDnsMessage &msg)
6338e745fdaSopenharmony_ci{
6348e745fdaSopenharmony_ci    const sockaddr *saddrIf = listener_.GetSockAddr(sock);
6358e745fdaSopenharmony_ci    if (saddrIf == nullptr) {
6368e745fdaSopenharmony_ci        return;
6378e745fdaSopenharmony_ci    }
6388e745fdaSopenharmony_ci    bool v6 = (saddrIf->sa_family == AF_INET6);
6398e745fdaSopenharmony_ci    std::set<std::string> changed;
6408e745fdaSopenharmony_ci    for (const auto &answer : msg.answers) {
6418e745fdaSopenharmony_ci        ProcessAnswerRecord(v6, answer, changed);
6428e745fdaSopenharmony_ci    }
6438e745fdaSopenharmony_ci    for (const auto &i : msg.additional) {
6448e745fdaSopenharmony_ci        ProcessAnswerRecord(v6, i, changed);
6458e745fdaSopenharmony_ci    }
6468e745fdaSopenharmony_ci    for (const auto &i : changed) {
6478e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
6488e745fdaSopenharmony_ci        RunTaskQueue(taskOnChange_[i]);
6498e745fdaSopenharmony_ci        KillCache(i);
6508e745fdaSopenharmony_ci    }
6518e745fdaSopenharmony_ci}
6528e745fdaSopenharmony_ci
6538e745fdaSopenharmony_civoid MDnsProtocolImpl::UpdatePtr(bool v6, const DNSProto::ResourceRecord &rr, std::set<std::string> &changed)
6548e745fdaSopenharmony_ci{
6558e745fdaSopenharmony_ci    const std::string *data = std::any_cast<std::string>(&rr.rdata);
6568e745fdaSopenharmony_ci    if (data == nullptr) {
6578e745fdaSopenharmony_ci        return;
6588e745fdaSopenharmony_ci    }
6598e745fdaSopenharmony_ci
6608e745fdaSopenharmony_ci    std::string name = rr.name;
6618e745fdaSopenharmony_ci    if (browserMap_.find(name) == browserMap_.end()) {
6628e745fdaSopenharmony_ci        return;
6638e745fdaSopenharmony_ci    }
6648e745fdaSopenharmony_ci    auto &results = browserMap_[name];
6658e745fdaSopenharmony_ci    std::string srvName;
6668e745fdaSopenharmony_ci    std::string srvType;
6678e745fdaSopenharmony_ci    ExtractNameAndType(*data, srvName, srvType);
6688e745fdaSopenharmony_ci    if (srvName.empty() || srvType.empty()) {
6698e745fdaSopenharmony_ci        return;
6708e745fdaSopenharmony_ci    }
6718e745fdaSopenharmony_ci    auto res =
6728e745fdaSopenharmony_ci        std::find_if(results.begin(), results.end(), [&](const auto &elem) { return elem.serviceName == srvName; });
6738e745fdaSopenharmony_ci    if (res == results.end()) {
6748e745fdaSopenharmony_ci        results.emplace_back(Result{
6758e745fdaSopenharmony_ci            .serviceName = srvName,
6768e745fdaSopenharmony_ci            .serviceType = srvType,
6778e745fdaSopenharmony_ci            .state = State::ADD,
6788e745fdaSopenharmony_ci        });
6798e745fdaSopenharmony_ci    }
6808e745fdaSopenharmony_ci    res = std::find_if(results.begin(), results.end(), [&](const auto &elem) { return elem.serviceName == srvName; });
6818e745fdaSopenharmony_ci    if (res->serviceName != srvName || res->state == State::DEAD) {
6828e745fdaSopenharmony_ci        res->state = State::REFRESH;
6838e745fdaSopenharmony_ci        res->serviceName = srvName;
6848e745fdaSopenharmony_ci    }
6858e745fdaSopenharmony_ci    if (rr.ttl == 0) {
6868e745fdaSopenharmony_ci        res->state = State::REMOVE;
6878e745fdaSopenharmony_ci    }
6888e745fdaSopenharmony_ci    if (res->state != State::LIVE && res->state != State::DEAD) {
6898e745fdaSopenharmony_ci        changed.emplace(name);
6908e745fdaSopenharmony_ci    }
6918e745fdaSopenharmony_ci    res->ttl = rr.ttl;
6928e745fdaSopenharmony_ci    res->refrehTime = MilliSecondsSinceEpoch();
6938e745fdaSopenharmony_ci}
6948e745fdaSopenharmony_ci
6958e745fdaSopenharmony_civoid MDnsProtocolImpl::UpdateSrv(bool v6, const DNSProto::ResourceRecord &rr, std::set<std::string> &changed)
6968e745fdaSopenharmony_ci{
6978e745fdaSopenharmony_ci    const DNSProto::RDataSrv *srv = std::any_cast<DNSProto::RDataSrv>(&rr.rdata);
6988e745fdaSopenharmony_ci    if (srv == nullptr) {
6998e745fdaSopenharmony_ci        return;
7008e745fdaSopenharmony_ci    }
7018e745fdaSopenharmony_ci    std::string name = rr.name;
7028e745fdaSopenharmony_ci    if (cacheMap_.find(name) == cacheMap_.end()) {
7038e745fdaSopenharmony_ci        ExtractNameAndType(name, cacheMap_[name].serviceName, cacheMap_[name].serviceType);
7048e745fdaSopenharmony_ci        cacheMap_[name].state = State::ADD;
7058e745fdaSopenharmony_ci        cacheMap_[name].domain = srv->name;
7068e745fdaSopenharmony_ci        cacheMap_[name].port = srv->port;
7078e745fdaSopenharmony_ci    }
7088e745fdaSopenharmony_ci    Result &result = cacheMap_[name];
7098e745fdaSopenharmony_ci    if (result.domain != srv->name || result.port != srv->port || result.state == State::DEAD) {
7108e745fdaSopenharmony_ci        if (result.state != State::ADD) {
7118e745fdaSopenharmony_ci            result.state = State::REFRESH;
7128e745fdaSopenharmony_ci        }
7138e745fdaSopenharmony_ci        result.domain = srv->name;
7148e745fdaSopenharmony_ci        result.port = srv->port;
7158e745fdaSopenharmony_ci    }
7168e745fdaSopenharmony_ci    if (rr.ttl == 0) {
7178e745fdaSopenharmony_ci        result.state = State::REMOVE;
7188e745fdaSopenharmony_ci    }
7198e745fdaSopenharmony_ci    if (result.state != State::LIVE && result.state != State::DEAD) {
7208e745fdaSopenharmony_ci        changed.emplace(name);
7218e745fdaSopenharmony_ci    }
7228e745fdaSopenharmony_ci    result.ttl = rr.ttl;
7238e745fdaSopenharmony_ci    result.refrehTime = MilliSecondsSinceEpoch();
7248e745fdaSopenharmony_ci}
7258e745fdaSopenharmony_ci
7268e745fdaSopenharmony_civoid MDnsProtocolImpl::UpdateTxt(bool v6, const DNSProto::ResourceRecord &rr, std::set<std::string> &changed)
7278e745fdaSopenharmony_ci{
7288e745fdaSopenharmony_ci    const TxtRecordEncoded *txt = std::any_cast<TxtRecordEncoded>(&rr.rdata);
7298e745fdaSopenharmony_ci    if (txt == nullptr) {
7308e745fdaSopenharmony_ci        return;
7318e745fdaSopenharmony_ci    }
7328e745fdaSopenharmony_ci    std::string name = rr.name;
7338e745fdaSopenharmony_ci    if (cacheMap_.find(name) == cacheMap_.end()) {
7348e745fdaSopenharmony_ci        ExtractNameAndType(name, cacheMap_[name].serviceName, cacheMap_[name].serviceType);
7358e745fdaSopenharmony_ci        cacheMap_[name].state = State::ADD;
7368e745fdaSopenharmony_ci        cacheMap_[name].txt = *txt;
7378e745fdaSopenharmony_ci    }
7388e745fdaSopenharmony_ci    Result &result = cacheMap_[name];
7398e745fdaSopenharmony_ci    if (result.txt != *txt || result.state == State::DEAD) {
7408e745fdaSopenharmony_ci        if (result.state != State::ADD) {
7418e745fdaSopenharmony_ci            result.state = State::REFRESH;
7428e745fdaSopenharmony_ci        }
7438e745fdaSopenharmony_ci        result.txt = *txt;
7448e745fdaSopenharmony_ci    }
7458e745fdaSopenharmony_ci    if (rr.ttl == 0) {
7468e745fdaSopenharmony_ci        result.state = State::REMOVE;
7478e745fdaSopenharmony_ci    }
7488e745fdaSopenharmony_ci    if (result.state != State::LIVE && result.state != State::DEAD) {
7498e745fdaSopenharmony_ci        changed.emplace(name);
7508e745fdaSopenharmony_ci    }
7518e745fdaSopenharmony_ci    result.ttl = rr.ttl;
7528e745fdaSopenharmony_ci    result.refrehTime = MilliSecondsSinceEpoch();
7538e745fdaSopenharmony_ci}
7548e745fdaSopenharmony_ci
7558e745fdaSopenharmony_civoid MDnsProtocolImpl::UpdateAddr(bool v6, const DNSProto::ResourceRecord &rr, std::set<std::string> &changed)
7568e745fdaSopenharmony_ci{
7578e745fdaSopenharmony_ci    if (v6 != (rr.rtype == DNSProto::RRTYPE_AAAA)) {
7588e745fdaSopenharmony_ci        return;
7598e745fdaSopenharmony_ci    }
7608e745fdaSopenharmony_ci    const std::string addr = AddrToString(rr.rdata);
7618e745fdaSopenharmony_ci    bool v6rr = (rr.rtype == DNSProto::RRTYPE_AAAA);
7628e745fdaSopenharmony_ci    if (addr.empty()) {
7638e745fdaSopenharmony_ci        return;
7648e745fdaSopenharmony_ci    }
7658e745fdaSopenharmony_ci    std::string name = rr.name;
7668e745fdaSopenharmony_ci    if (cacheMap_.find(name) == cacheMap_.end()) {
7678e745fdaSopenharmony_ci        ExtractNameAndType(name, cacheMap_[name].serviceName, cacheMap_[name].serviceType);
7688e745fdaSopenharmony_ci        cacheMap_[name].state = State::ADD;
7698e745fdaSopenharmony_ci        cacheMap_[name].ipv6 = v6rr;
7708e745fdaSopenharmony_ci        cacheMap_[name].addr = addr;
7718e745fdaSopenharmony_ci    }
7728e745fdaSopenharmony_ci    Result &result = cacheMap_[name];
7738e745fdaSopenharmony_ci    if (result.addr != addr || result.ipv6 != v6rr || result.state == State::DEAD) {
7748e745fdaSopenharmony_ci        result.state = State::REFRESH;
7758e745fdaSopenharmony_ci        result.addr = addr;
7768e745fdaSopenharmony_ci        result.ipv6 = v6rr;
7778e745fdaSopenharmony_ci    }
7788e745fdaSopenharmony_ci    if (rr.ttl == 0) {
7798e745fdaSopenharmony_ci        result.state = State::REMOVE;
7808e745fdaSopenharmony_ci    }
7818e745fdaSopenharmony_ci    if (result.state != State::LIVE && result.state != State::DEAD) {
7828e745fdaSopenharmony_ci        changed.emplace(name);
7838e745fdaSopenharmony_ci    }
7848e745fdaSopenharmony_ci    result.ttl = rr.ttl;
7858e745fdaSopenharmony_ci    result.refrehTime = MilliSecondsSinceEpoch();
7868e745fdaSopenharmony_ci}
7878e745fdaSopenharmony_ci
7888e745fdaSopenharmony_civoid MDnsProtocolImpl::ProcessAnswerRecord(bool v6, const DNSProto::ResourceRecord &rr, std::set<std::string> &changed)
7898e745fdaSopenharmony_ci{
7908e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log ProcessAnswerRecord, type=[%{public}d]", rr.rtype);
7918e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
7928e745fdaSopenharmony_ci    std::string name = rr.name;
7938e745fdaSopenharmony_ci    if (cacheMap_.find(name) == cacheMap_.end() && browserMap_.find(name) == browserMap_.end() &&
7948e745fdaSopenharmony_ci        srvMap_.find(name) != srvMap_.end()) {
7958e745fdaSopenharmony_ci        return;
7968e745fdaSopenharmony_ci    }
7978e745fdaSopenharmony_ci    if (rr.rtype == DNSProto::RRTYPE_PTR) {
7988e745fdaSopenharmony_ci        UpdatePtr(v6, rr, changed);
7998e745fdaSopenharmony_ci    } else if (rr.rtype == DNSProto::RRTYPE_SRV) {
8008e745fdaSopenharmony_ci        UpdateSrv(v6, rr, changed);
8018e745fdaSopenharmony_ci    } else if (rr.rtype == DNSProto::RRTYPE_TXT) {
8028e745fdaSopenharmony_ci        UpdateTxt(v6, rr, changed);
8038e745fdaSopenharmony_ci    } else if (rr.rtype == DNSProto::RRTYPE_A || rr.rtype == DNSProto::RRTYPE_AAAA) {
8048e745fdaSopenharmony_ci        UpdateAddr(v6, rr, changed);
8058e745fdaSopenharmony_ci    } else {
8068e745fdaSopenharmony_ci        NETMGR_EXT_LOG_D("mdns_log Unknown packet received, type=[%{public}d]", rr.rtype);
8078e745fdaSopenharmony_ci    }
8088e745fdaSopenharmony_ci}
8098e745fdaSopenharmony_ci
8108e745fdaSopenharmony_cistd::string MDnsProtocolImpl::GetHostDomain()
8118e745fdaSopenharmony_ci{
8128e745fdaSopenharmony_ci    if (config_.hostname.empty()) {
8138e745fdaSopenharmony_ci        char buffer[MDNS_MAX_DOMAIN_LABEL];
8148e745fdaSopenharmony_ci        if (gethostname(buffer, sizeof(buffer)) == 0) {
8158e745fdaSopenharmony_ci            config_.hostname = buffer;
8168e745fdaSopenharmony_ci            static auto uid = []() {
8178e745fdaSopenharmony_ci                std::random_device rd;
8188e745fdaSopenharmony_ci                return rd();
8198e745fdaSopenharmony_ci            }();
8208e745fdaSopenharmony_ci            config_.hostname += std::to_string(uid);
8218e745fdaSopenharmony_ci        }
8228e745fdaSopenharmony_ci    }
8238e745fdaSopenharmony_ci    return Decorated(config_.hostname);
8248e745fdaSopenharmony_ci}
8258e745fdaSopenharmony_ci
8268e745fdaSopenharmony_civoid MDnsProtocolImpl::AddTask(const Task &task, bool atonce)
8278e745fdaSopenharmony_ci{
8288e745fdaSopenharmony_ci    {
8298e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
8308e745fdaSopenharmony_ci        taskQueue_.emplace_back(task);
8318e745fdaSopenharmony_ci    }
8328e745fdaSopenharmony_ci    if (atonce) {
8338e745fdaSopenharmony_ci        listener_.TriggerRefresh();
8348e745fdaSopenharmony_ci    }
8358e745fdaSopenharmony_ci}
8368e745fdaSopenharmony_ci
8378e745fdaSopenharmony_ciMDnsServiceInfo MDnsProtocolImpl::ConvertResultToInfo(const MDnsProtocolImpl::Result &result)
8388e745fdaSopenharmony_ci{
8398e745fdaSopenharmony_ci    MDnsServiceInfo info;
8408e745fdaSopenharmony_ci    info.name = result.serviceName;
8418e745fdaSopenharmony_ci    info.type = result.serviceType;
8428e745fdaSopenharmony_ci    if (!result.addr.empty()) {
8438e745fdaSopenharmony_ci        info.family = result.ipv6 ? MDnsServiceInfo::IPV6 : MDnsServiceInfo::IPV4;
8448e745fdaSopenharmony_ci    }
8458e745fdaSopenharmony_ci    info.addr = result.addr;
8468e745fdaSopenharmony_ci    info.port = result.port;
8478e745fdaSopenharmony_ci    info.txtRecord = result.txt;
8488e745fdaSopenharmony_ci    return info;
8498e745fdaSopenharmony_ci}
8508e745fdaSopenharmony_ci
8518e745fdaSopenharmony_cibool MDnsProtocolImpl::IsCacheAvailable(const std::string &key)
8528e745fdaSopenharmony_ci{
8538e745fdaSopenharmony_ci    constexpr int64_t ms2S = 1000LL;
8548e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log IsCacheAvailable, ttl=[%{public}u]", cacheMap_[key].ttl);
8558e745fdaSopenharmony_ci    return cacheMap_.find(key) != cacheMap_.end() &&
8568e745fdaSopenharmony_ci           (ms2S * cacheMap_[key].ttl) > static_cast<uint32_t>(MilliSecondsSinceEpoch() - cacheMap_[key].refrehTime);
8578e745fdaSopenharmony_ci}
8588e745fdaSopenharmony_ci
8598e745fdaSopenharmony_cibool MDnsProtocolImpl::IsDomainCacheAvailable(const std::string &key)
8608e745fdaSopenharmony_ci{
8618e745fdaSopenharmony_ci    return IsCacheAvailable(key) && !cacheMap_[key].addr.empty();
8628e745fdaSopenharmony_ci}
8638e745fdaSopenharmony_ci
8648e745fdaSopenharmony_cibool MDnsProtocolImpl::IsInstanceCacheAvailable(const std::string &key)
8658e745fdaSopenharmony_ci{
8668e745fdaSopenharmony_ci    return IsCacheAvailable(key) && !cacheMap_[key].domain.empty();
8678e745fdaSopenharmony_ci}
8688e745fdaSopenharmony_ci
8698e745fdaSopenharmony_cibool MDnsProtocolImpl::IsBrowserAvailable(const std::string &key)
8708e745fdaSopenharmony_ci{
8718e745fdaSopenharmony_ci    return browserMap_.find(key) != browserMap_.end() && !browserMap_[key].empty();
8728e745fdaSopenharmony_ci}
8738e745fdaSopenharmony_ci
8748e745fdaSopenharmony_civoid MDnsProtocolImpl::AddEvent(const std::string &key, const Task &task)
8758e745fdaSopenharmony_ci{
8768e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
8778e745fdaSopenharmony_ci    taskOnChange_[key].emplace_back(task);
8788e745fdaSopenharmony_ci}
8798e745fdaSopenharmony_ci
8808e745fdaSopenharmony_civoid MDnsProtocolImpl::RunTaskQueue(std::list<Task> &queue)
8818e745fdaSopenharmony_ci{
8828e745fdaSopenharmony_ci    std::list<Task> tmp;
8838e745fdaSopenharmony_ci    for (auto &&func : queue) {
8848e745fdaSopenharmony_ci        if (!func()) {
8858e745fdaSopenharmony_ci            tmp.emplace_back(func);
8868e745fdaSopenharmony_ci        }
8878e745fdaSopenharmony_ci    }
8888e745fdaSopenharmony_ci    tmp.swap(queue);
8898e745fdaSopenharmony_ci}
8908e745fdaSopenharmony_ci
8918e745fdaSopenharmony_civoid MDnsProtocolImpl::KillCache(const std::string &key)
8928e745fdaSopenharmony_ci{
8938e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log KillCache");
8948e745fdaSopenharmony_ci    if (IsBrowserAvailable(key) && browserMap_.find(key) != browserMap_.end()) {
8958e745fdaSopenharmony_ci        for (auto it = browserMap_[key].begin(); it != browserMap_[key].end();) {
8968e745fdaSopenharmony_ci            KillBrowseCache(key, it);
8978e745fdaSopenharmony_ci        }
8988e745fdaSopenharmony_ci    }
8998e745fdaSopenharmony_ci    if (IsCacheAvailable(key)) {
9008e745fdaSopenharmony_ci        std::lock_guard<std::recursive_mutex> guard(mutex_);
9018e745fdaSopenharmony_ci        auto &elem = cacheMap_[key];
9028e745fdaSopenharmony_ci        if (elem.state == State::REMOVE) {
9038e745fdaSopenharmony_ci            elem.state = State::DEAD;
9048e745fdaSopenharmony_ci            cacheMap_.erase(key);
9058e745fdaSopenharmony_ci        } else if (elem.state == State::ADD || elem.state == State::REFRESH) {
9068e745fdaSopenharmony_ci            elem.state = State::LIVE;
9078e745fdaSopenharmony_ci        }
9088e745fdaSopenharmony_ci    }
9098e745fdaSopenharmony_ci}
9108e745fdaSopenharmony_ci
9118e745fdaSopenharmony_civoid MDnsProtocolImpl::KillBrowseCache(const std::string &key, std::vector<Result>::iterator &it)
9128e745fdaSopenharmony_ci{
9138e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log KillBrowseCache");
9148e745fdaSopenharmony_ci    if (it->state == State::REMOVE) {
9158e745fdaSopenharmony_ci        it->state = State::DEAD;
9168e745fdaSopenharmony_ci        if (nameCbMap_.find(key) != nameCbMap_.end()) {
9178e745fdaSopenharmony_ci            NETMGR_EXT_LOG_D("mdns_log HandleServiceLost");
9188e745fdaSopenharmony_ci            nameCbMap_[key]->HandleServiceLost(ConvertResultToInfo(*it), NETMANAGER_EXT_SUCCESS);
9198e745fdaSopenharmony_ci        }
9208e745fdaSopenharmony_ci        std::string fullName = Decorated(it->serviceName + MDNS_DOMAIN_SPLITER_STR + it->serviceType);
9218e745fdaSopenharmony_ci        cacheMap_.erase(fullName);
9228e745fdaSopenharmony_ci        it = browserMap_[key].erase(it);
9238e745fdaSopenharmony_ci    } else if (it->state == State::ADD || it->state == State::REFRESH) {
9248e745fdaSopenharmony_ci        it->state = State::LIVE;
9258e745fdaSopenharmony_ci        it++;
9268e745fdaSopenharmony_ci    } else {
9278e745fdaSopenharmony_ci        it++;
9288e745fdaSopenharmony_ci    }
9298e745fdaSopenharmony_ci}
9308e745fdaSopenharmony_ci
9318e745fdaSopenharmony_ciint32_t MDnsProtocolImpl::StopCbMap(const std::string &serviceType)
9328e745fdaSopenharmony_ci{
9338e745fdaSopenharmony_ci    NETMGR_EXT_LOG_D("mdns_log StopCbMap");
9348e745fdaSopenharmony_ci    std::lock_guard<std::recursive_mutex> guard(mutex_);
9358e745fdaSopenharmony_ci    std::string name = Decorated(serviceType);
9368e745fdaSopenharmony_ci    sptr<IDiscoveryCallback> cb = nullptr;
9378e745fdaSopenharmony_ci    if (nameCbMap_.find(name) != nameCbMap_.end()) {
9388e745fdaSopenharmony_ci        cb = nameCbMap_[name];
9398e745fdaSopenharmony_ci        nameCbMap_.erase(name);
9408e745fdaSopenharmony_ci    }
9418e745fdaSopenharmony_ci    taskOnChange_.erase(name);
9428e745fdaSopenharmony_ci    auto it = browserMap_.find(name);
9438e745fdaSopenharmony_ci    if (it != browserMap_.end()) {
9448e745fdaSopenharmony_ci        if (cb != nullptr) {
9458e745fdaSopenharmony_ci            NETMGR_EXT_LOG_I("mdns_log StopCbMap res size:[%{public}zu]", it->second.size());
9468e745fdaSopenharmony_ci            for (auto &&res : it->second) {
9478e745fdaSopenharmony_ci                NETMGR_EXT_LOG_W("mdns_log HandleServiceLost");
9488e745fdaSopenharmony_ci                cb->HandleServiceLost(ConvertResultToInfo(res), NETMANAGER_EXT_SUCCESS);
9498e745fdaSopenharmony_ci            }
9508e745fdaSopenharmony_ci        }
9518e745fdaSopenharmony_ci        browserMap_.erase(name);
9528e745fdaSopenharmony_ci    }
9538e745fdaSopenharmony_ci    return NETMANAGER_SUCCESS;
9548e745fdaSopenharmony_ci}
9558e745fdaSopenharmony_ci} // namespace NetManagerStandard
9568e745fdaSopenharmony_ci} // namespace OHOS
957