• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <thread>
17 #include <queue>
18 #include "scan_mdns_service.h"
19 #include "scan_system_data.h"
20 #include "securec.h"
21 #include "mdns_common.h"
22 
23 #define TXT_MAX 256
24 
25 namespace OHOS::Scan {
26 using namespace OHOS::NetManagerStandard;
27 namespace {
28 std::map<std::string, ScanDeviceInfoTCP> g_ipToScannerInfo;
29 std::mutex g_ipToScannerInfoLock;
30 std::queue<ScanDeviceInfoSync> g_infoQueue;
31 std::mutex g_infoQueueLock;
GetServiceAttribute(MDnsServiceInfo & info,const std::string & key)32 static std::string GetServiceAttribute(MDnsServiceInfo &info, const std::string& key)
33 {
34     TxtRecord attrMap = info.GetAttrMap();
35     auto attrArrSize = attrMap.size();
36     if (attrArrSize < 1) {
37         SCAN_HILOGE("can not get attr");
38         return "";
39     }
40     auto it = attrMap.find(key);
41     if (it == attrMap.end() || it->second.empty()) {
42         SCAN_HILOGE("can not find key, key = [%{public}s]", key.c_str());
43         return "";
44     }
45     return std::string(it->second.begin(), it->second.end());
46 }
47 }
48 std::map<std::string, sptr<ScanMDnsDiscoveryObserver>> ScanMdnsService::discoveryCallBackPtrs_;
49 bool ScanMdnsService::isListening_ = false;
50 std::mutex ScanMdnsService::discoveryCallBackPtrsLock_;
51 
InsertIpToScannerInfo(const std::string & ip,ScanDeviceInfoTCP & scanDeviceInfoTCP)52 void ScanMdnsService::InsertIpToScannerInfo(const std::string& ip, ScanDeviceInfoTCP& scanDeviceInfoTCP)
53 {
54     std::lock_guard<std::mutex> autoLock(g_ipToScannerInfoLock);
55     g_ipToScannerInfo.insert(std::make_pair(ip, scanDeviceInfoTCP));
56 }
57 
OnStartDiscoverService()58 bool ScanMdnsService::OnStartDiscoverService()
59 {
60     if (isListening_) {
61         SCAN_HILOGD("scanner's mdns discovery is already started.");
62         return true;
63     }
64     const std::vector<std::string> scannerServiceTypes = { "_scanner._tcp" };
65     constexpr int32_t MDNS_PORT = 5353;
66     {
67         std::lock_guard<std::mutex> autoLock(g_ipToScannerInfoLock);
68         g_ipToScannerInfo.clear();
69     }
70     for (const auto& type : scannerServiceTypes) {
71         MDnsServiceInfo mdnsInfo;
72         mdnsInfo.type = type;
73         mdnsInfo.port = MDNS_PORT;
74         sptr<ScanMDnsDiscoveryObserver> callbackPtr = new (std::nothrow) ScanMDnsDiscoveryObserver(mdnsInfo);
75         if (callbackPtr == nullptr) {
76             SCAN_HILOGE("scanMDnsDiscoveryCallBack_ is a nullptr.");
77             OnStopDiscoverService();
78             return false;
79         }
80         int32_t ret = DelayedSingleton<MDnsClient>::GetInstance()->StartDiscoverService(
81             mdnsInfo.type, callbackPtr);
82         if (ret != NETMANAGER_EXT_SUCCESS) {
83             SCAN_HILOGE("mdns service [%{public}s] startDiscover failed, ret = [%{public}d].",
84                 mdnsInfo.type.c_str(), ret);
85             OnStopDiscoverService();
86             return false;
87         }
88         {
89             std::lock_guard<std::mutex> autoLock(discoveryCallBackPtrsLock_);
90             auto it = discoveryCallBackPtrs_.find(type);
91             if (it == discoveryCallBackPtrs_.end()) {
92                 discoveryCallBackPtrs_.insert(std::make_pair(type, callbackPtr));
93             } else {
94                 it->second = callbackPtr;
95             }
96             isListening_ = true;
97             std::thread updateScannerId(UpdateScannerIdThread);
98             updateScannerId.detach();
99         }
100     }
101     return true;
102 }
103 
UpdateScannerIdThread()104 void ScanMdnsService::UpdateScannerIdThread()
105 {
106     auto saPtr = ScanServiceAbility::GetInstance();
107     if (saPtr == nullptr) {
108         SCAN_HILOGE("saPtr is a nullptr");
109         return;
110     }
111     while (isListening_) {
112         {
113             std::lock_guard<std::mutex> autoLock(g_infoQueueLock);
114             while (!g_infoQueue.empty()) {
115                 saPtr->UpdateScannerId(g_infoQueue.front());
116                 g_infoQueue.pop();
117             }
118         }
119         constexpr int32_t sleepTime = 100000; // 100ms
120         usleep(sleepTime);
121     }
122 }
123 
OnStopDiscoverService()124 bool ScanMdnsService::OnStopDiscoverService()
125 {
126     for (auto& [serviceName, discoveryCallBackPtr] : discoveryCallBackPtrs_) {
127         if (discoveryCallBackPtr == nullptr) {
128             continue;
129         }
130         int32_t ret = DelayedSingleton<MDnsClient>::GetInstance()->StopDiscoverService(discoveryCallBackPtr);
131         if (ret != NETMANAGER_EXT_SUCCESS) {
132             SCAN_HILOGE("mdns service [%{public}s] startDiscover failed, ret = [%{public}d].",
133                 serviceName.c_str(), ret);
134             return false;
135         }
136         discoveryCallBackPtr = nullptr;
137     }
138     {
139         std::lock_guard<std::mutex> autoLock(discoveryCallBackPtrsLock_);
140         discoveryCallBackPtrs_.clear();
141         isListening_ = false;
142     }
143     return true;
144 }
145 
FindNetScannerInfoByIp(const std::string & ip,ScanDeviceInfoTCP & netScannerInfo)146 bool ScanMdnsService::FindNetScannerInfoByIp(const std::string& ip, ScanDeviceInfoTCP& netScannerInfo)
147 {
148     std::lock_guard<std::mutex> autoLock(g_ipToScannerInfoLock);
149     auto it = g_ipToScannerInfo.find(ip);
150     if (it == g_ipToScannerInfo.end()) {
151         SCAN_HILOGW("cannot find scanner info in map.");
152         return false;
153     }
154     netScannerInfo = it->second;
155     return true;
156 }
157 
HandleServiceFound(const MDnsServiceInfo & info,int32_t retCode)158 int32_t ScanMDnsDiscoveryObserver::HandleServiceFound(const MDnsServiceInfo &info, int32_t retCode)
159 {
160     SCAN_HILOGD("Found mdns service info, name = [%{private}s]", info.name.c_str());
161     sptr<ScanMDnsResolveObserver> scanMDnsResolveCallBack_ = new (std::nothrow) ScanMDnsResolveObserver(info);
162     if (scanMDnsResolveCallBack_ == nullptr) {
163         SCAN_HILOGE("scanMDnsResolveCallBack_ is a nullptr.");
164         return NETMANAGER_EXT_ERR_INTERNAL;
165     }
166     int32_t ret = DelayedSingleton<MDnsClient>::GetInstance()->ResolveService(info, scanMDnsResolveCallBack_);
167     if (ret != NETMANAGER_EXT_SUCCESS) {
168         SCAN_HILOGE("mdns ResolveService failed, ret = [%{public}d].", ret);
169     }
170     return NETMANAGER_EXT_SUCCESS;
171 }
172 
HandleResolveResult(const MDnsServiceInfo & info,int32_t retCode)173 int32_t ScanMDnsResolveObserver::HandleResolveResult(const MDnsServiceInfo &info, int32_t retCode)
174 {
175     MDnsServiceInfo tempInfo = info;
176     SCAN_HILOGD("MDnsInfo name = [%{private}s], type = [%{private}s]", info.name.c_str(), info.type.c_str());
177     std::unique_ptr<ScanDeviceInfoTCP> scannerInfo = std::make_unique<ScanDeviceInfoTCP>();
178     scannerInfo->addr = tempInfo.addr;
179     scannerInfo->deviceName = tempInfo.name;
180     scannerInfo->port = std::to_string(tempInfo.port);
181     const std::string uuidKey = "UUID";
182     std::string uuidValue = GetServiceAttribute(tempInfo, uuidKey);
183     scannerInfo->uuid = uuidValue;
184     {
185         std::lock_guard<std::mutex> autoLock(g_ipToScannerInfoLock);
186         auto it = g_ipToScannerInfo.find(scannerInfo->addr);
187         if (it == g_ipToScannerInfo.end()) {
188             g_ipToScannerInfo.insert(std::make_pair(scannerInfo->addr, *scannerInfo));
189         } else {
190             it->second = *scannerInfo;
191         }
192     }
193     ScanSystemData &scanData = ScanSystemData::GetInstance();
194     auto pair = scanData.UpdateNetScannerByUuid(uuidValue, scannerInfo->addr);
195     if (pair.second == "") {
196         SCAN_HILOGE("UpdateNetScannerByUuid fail.");
197         return NETMANAGER_EXT_ERR_INTERNAL;
198     }
199     if (!scanData.SaveScannerMap()) {
200         SCAN_HILOGW("SaveScannerMap fail");
201     }
202     ScanDeviceInfoSync syncInfo;
203     syncInfo.deviceId = pair.second;
204     syncInfo.oldDeviceId = pair.first;
205     syncInfo.discoverMode = "TCP";
206     syncInfo.uniqueId = scannerInfo->addr;
207     syncInfo.syncMode = "update";
208     {
209         std::lock_guard<std::mutex> autoLock(g_infoQueueLock);
210         g_infoQueue.push(syncInfo);
211     }
212     {
213         std::lock_guard<std::mutex> autoLock(g_ipToScannerInfoLock);
214         auto it = g_ipToScannerInfo.find(scannerInfo->addr);
215         if (it == g_ipToScannerInfo.end()) {
216             g_ipToScannerInfo.insert(std::make_pair(scannerInfo->addr, *scannerInfo));
217         } else {
218             it->second = *scannerInfo;
219         }
220     }
221     return NETMANAGER_EXT_SUCCESS;
222 }
223 
HandleServiceLost(const MDnsServiceInfo & info,int32_t retCode)224 int32_t ScanMDnsDiscoveryObserver::HandleServiceLost(const MDnsServiceInfo &info, int32_t retCode)
225 {
226     SCAN_HILOGD("Loss mdns service info, name = [%{private}s]", info.name.c_str());
227     sptr<ScanMDnsLossResolveObserver> callBack = new (std::nothrow) ScanMDnsLossResolveObserver(info);
228     if (callBack == nullptr) {
229         SCAN_HILOGE("callBack is a nullptr");
230         return NETMANAGER_EXT_ERR_INTERNAL;
231     }
232     int32_t ret = DelayedSingleton<MDnsClient>::GetInstance()->ResolveService(info, callBack);
233     if (ret != NETMANAGER_EXT_SUCCESS) {
234         SCAN_HILOGE("mdns ResolveService failed, ret = %{public}d", ret);
235     }
236     return NETMANAGER_EXT_SUCCESS;
237 }
238 
HandleResolveResult(const MDnsServiceInfo & info,int32_t retCode)239 int32_t ScanMDnsLossResolveObserver::HandleResolveResult(const MDnsServiceInfo &info, int32_t retCode)
240 {
241     MDnsServiceInfo tempInfo = info;
242     SCAN_HILOGD("mdnsloss name = [%{private}s], type = [%{private}s]", info.name.c_str(), info.type.c_str());
243     {
244         std::lock_guard<std::mutex> autoLock(g_ipToScannerInfoLock);
245         std::string ip = info.addr;
246         auto it = g_ipToScannerInfo.find(ip);
247         if (it != g_ipToScannerInfo.end()) {
248             g_ipToScannerInfo.erase(it);
249         }
250     }
251     return NETMANAGER_EXT_SUCCESS;
252 }
253 
HandleStopDiscover(const MDnsServiceInfo & serviceInfo,int32_t retCode)254 int32_t ScanMDnsDiscoveryObserver::HandleStopDiscover(const MDnsServiceInfo &serviceInfo, int32_t retCode)
255 {
256     SCAN_HILOGD("Stop mdns service info, name = [%{private}s]", serviceInfo.name.c_str());
257     return NETMANAGER_EXT_SUCCESS;
258 }
259 
260 }  // namespace OHOS::Scan
261