1/*
2 * Copyright (c) 2024 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 "dm_softbus_cache.h"
17#include "dm_anonymous.h"
18#include "dm_crypto.h"
19#include "dm_constants.h"
20#include "dm_device_info.h"
21#include "dm_log.h"
22namespace OHOS {
23namespace DistributedHardware {
24DM_IMPLEMENT_SINGLE_INSTANCE(SoftbusCache);
25bool g_online = false;
26bool g_getLocalDevInfo = false;
27DmDeviceInfo localDeviceInfo_;
28std::mutex localDevInfoMutex_;
29void SoftbusCache::SaveLocalDeviceInfo()
30{
31    LOGI("SoftbusCache::SaveLocalDeviceInfo");
32    std::lock_guard<std::mutex> mutexLock(localDevInfoMutex_);
33    if (g_online) {
34        return;
35    }
36    NodeBasicInfo nodeBasicInfo;
37    int32_t ret = GetLocalNodeDeviceInfo(DM_PKG_NAME, &nodeBasicInfo);
38    if (ret != DM_OK) {
39        LOGE("[SOFTBUS]GetLocalNodeDeviceInfo failed, ret: %{public}d.", ret);
40        return;
41    }
42    ConvertNodeBasicInfoToDmDevice(nodeBasicInfo, localDeviceInfo_);
43    LOGI("SoftbusCache::SaveLocalDeviceInfo networkid %{public}s.",
44        GetAnonyString(std::string(localDeviceInfo_.networkId)).c_str());
45    SaveDeviceInfo(localDeviceInfo_);
46    SaveDeviceSecurityLevel(localDeviceInfo_.networkId);
47    g_online = true;
48    g_getLocalDevInfo = true;
49}
50
51void SoftbusCache::DeleteLocalDeviceInfo()
52{
53    LOGI("SoftbusCache::DeleteLocalDeviceInfo networkid %{public}s.",
54        GetAnonyString(std::string(localDeviceInfo_.networkId)).c_str());
55    std::lock_guard<std::mutex> mutexLock(localDevInfoMutex_);
56    g_online = false;
57    g_getLocalDevInfo = false;
58}
59
60int32_t SoftbusCache::GetLocalDeviceInfo(DmDeviceInfo &nodeInfo)
61{
62    std::lock_guard<std::mutex> mutexLock(localDevInfoMutex_);
63    if (g_getLocalDevInfo) {
64        nodeInfo = localDeviceInfo_;
65        LOGI("SoftbusCache::GetLocalDeviceInfo from dm cache.");
66        return DM_OK;
67    }
68    NodeBasicInfo nodeBasicInfo;
69    int32_t ret = GetLocalNodeDeviceInfo(DM_PKG_NAME, &nodeBasicInfo);
70    if (ret != DM_OK) {
71        LOGE("[SOFTBUS]GetLocalNodeDeviceInfo failed, ret: %{public}d.", ret);
72        return ret;
73    }
74    ConvertNodeBasicInfoToDmDevice(nodeBasicInfo, localDeviceInfo_);
75    nodeInfo = localDeviceInfo_;
76    SaveDeviceInfo(localDeviceInfo_);
77    SaveDeviceSecurityLevel(localDeviceInfo_.networkId);
78    g_getLocalDevInfo = true;
79    LOGI("SoftbusCache::GetLocalDeviceInfo from softbus.");
80    return DM_OK;
81}
82
83void SoftbusCache::UpDataLocalDevInfo()
84{
85    LOGI("SoftbusCache::UpDataLocalDevInfo");
86    NodeBasicInfo nodeBasicInfo;
87    int32_t ret = GetLocalNodeDeviceInfo(DM_PKG_NAME, &nodeBasicInfo);
88    if (ret != DM_OK) {
89        LOGE("[SOFTBUS]GetLocalNodeDeviceInfo failed, ret: %{public}d.", ret);
90        return;
91    }
92    std::lock_guard<std::mutex> mutexLock(localDevInfoMutex_);
93    ConvertNodeBasicInfoToDmDevice(nodeBasicInfo, localDeviceInfo_);
94    ChangeDeviceInfo(localDeviceInfo_);
95}
96
97int32_t SoftbusCache::GetUdidByNetworkId(const char *networkId, std::string &udid)
98{
99    uint8_t mUdid[UDID_BUF_LEN] = {0};
100    int32_t ret = GetNodeKeyInfo(DM_PKG_NAME, networkId, NodeDeviceInfoKey::NODE_KEY_UDID, mUdid, sizeof(mUdid));
101    if (ret != DM_OK) {
102        LOGE("[SOFTBUS]GetNodeKeyInfo failed, ret: %{public}d.", ret);
103        return ret;
104    }
105    udid = reinterpret_cast<char *>(mUdid);
106    return ret;
107}
108
109int32_t SoftbusCache::GetUuidByNetworkId(const char *networkId, std::string &uuid)
110{
111    uint8_t mUuid[UUID_BUF_LEN] = {0};
112    int32_t ret = GetNodeKeyInfo(DM_PKG_NAME, networkId, NodeDeviceInfoKey::NODE_KEY_UUID, mUuid, sizeof(mUuid));
113    if (ret != DM_OK) {
114        LOGE("[SOFTBUS]GetNodeKeyInfo failed, ret: %{public}d.", ret);
115        return ret;
116    }
117    uuid = reinterpret_cast<char *>(mUuid);
118    return ret;
119}
120
121void SoftbusCache::SaveDeviceInfo(DmDeviceInfo deviceInfo)
122{
123    LOGI("SoftbusCache::SaveDeviceInfo");
124    std::string udid = "";
125    std::string uuid = "";
126    GetUdidByNetworkId(deviceInfo.networkId, udid);
127    GetUuidByNetworkId(deviceInfo.networkId, uuid);
128    char udidHash[DM_MAX_DEVICE_ID_LEN] = {0};
129    if (Crypto::GetUdidHash(udid, reinterpret_cast<uint8_t *>(udidHash)) != DM_OK) {
130        LOGE("get udidhash by udid: %{public}s failed.", GetAnonyString(udid).c_str());
131        return;
132    }
133    if (memcpy_s(deviceInfo.deviceId, sizeof(deviceInfo.deviceId), udidHash,
134        std::min(sizeof(deviceInfo.deviceId), sizeof(udidHash))) != DM_OK) {
135        LOGE("SaveDeviceInfo copy deviceId failed.");
136        return;
137    }
138    std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
139    deviceInfo_[udid] = std::pair<std::string, DmDeviceInfo>(uuid, deviceInfo);
140    LOGI("SaveDeviceInfo success udid %{public}s, networkId %{public}s",
141        GetAnonyString(udid).c_str(), GetAnonyString(std::string(deviceInfo.networkId)).c_str());
142}
143
144void SoftbusCache::DeleteDeviceInfo(const DmDeviceInfo &nodeInfo)
145{
146    LOGI("SoftbusCache::DeleteDeviceInfo networkId %{public}s",
147        GetAnonyString(std::string(nodeInfo.networkId)).c_str());
148    std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
149    for (const auto &item : deviceInfo_) {
150        if (std::string(item.second.second.networkId) == std::string(nodeInfo.networkId)) {
151            LOGI("DeleteDeviceInfo success udid %{public}s", GetAnonyString(item.first).c_str());
152            deviceInfo_.erase(item.first);
153            break;
154        }
155    }
156}
157
158void SoftbusCache::ChangeDeviceInfo(const DmDeviceInfo deviceInfo)
159{
160    LOGI("SoftbusCache::ChangeDeviceInfo");
161    std::string udid = "";
162    GetUdidByNetworkId(deviceInfo.networkId, udid);
163    std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
164    if (deviceInfo_.find(udid) != deviceInfo_.end()) {
165        if (memcpy_s(deviceInfo_[udid].second.deviceName, sizeof(deviceInfo_[udid].second.deviceName),
166            deviceInfo.deviceName, sizeof(deviceInfo.deviceName)) != DM_OK) {
167            LOGE("ChangeDeviceInfo deviceInfo copy deviceName failed");
168        }
169        if (memcpy_s(deviceInfo_[udid].second.networkId, sizeof(deviceInfo_[udid].second.networkId),
170            deviceInfo.networkId, sizeof(deviceInfo.networkId)) != DM_OK) {
171            LOGE("ChangeDeviceInfo deviceInfo copy networkId failed");
172        }
173        deviceInfo_[udid].second.deviceTypeId = deviceInfo.deviceTypeId;
174        std::string uuid = "";
175        GetUuidByNetworkId(deviceInfo.networkId, uuid);
176        deviceInfo_[udid].first = uuid;
177    }
178    LOGI("ChangeDeviceInfo sucess udid %{public}s, networkId %{public}s.",
179        GetAnonyString(udid).c_str(), GetAnonyString(std::string(deviceInfo.networkId)).c_str());
180}
181
182int32_t SoftbusCache::GetDeviceInfoFromCache(std::vector<DmDeviceInfo> &deviceInfoList)
183{
184    std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
185    for (const auto &item : deviceInfo_) {
186        if (std::string(item.second.second.networkId) == std::string(localDeviceInfo_.networkId)) {
187            continue;
188        }
189        deviceInfoList.push_back(item.second.second);
190    }
191    return DM_OK;
192}
193
194void SoftbusCache::UpdateDeviceInfoCache()
195{
196    LOGI("SoftbusCache::UpdateDeviceInfoCache");
197    int32_t deviceCount = 0;
198    NodeBasicInfo *nodeInfo = nullptr;
199    int32_t ret = GetAllNodeDeviceInfo(DM_PKG_NAME, &nodeInfo, &deviceCount);
200    if (ret != DM_OK) {
201        LOGE("[SOFTBUS]GetAllNodeDeviceInfo failed, ret: %{public}d.", ret);
202        return;
203    }
204    SaveLocalDeviceInfo();
205    for (int32_t i = 0; i < deviceCount; ++i) {
206        NodeBasicInfo *nodeBasicInfo = nodeInfo + i;
207        DmDeviceInfo deviceInfo;
208        ConvertNodeBasicInfoToDmDevice(*nodeBasicInfo, deviceInfo);
209        SaveDeviceInfo(deviceInfo);
210    }
211    FreeNodeInfo(nodeInfo);
212    LOGI("UpdateDeviceInfoCache success, deviceCount: %{public}d.", deviceCount);
213    return;
214}
215
216int32_t SoftbusCache::GetUdidFromCache(const char *networkId, std::string &udid)
217{
218    std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
219    for (const auto &item : deviceInfo_) {
220        if (std::string(item.second.second.networkId) == std::string(networkId)) {
221            udid = item.first;
222            LOGI("Get udid from cache success, networkId %{public}s, udid %{public}s.",
223                GetAnonyString(std::string(networkId)).c_str(), GetAnonyString(udid).c_str());
224            return DM_OK;
225        }
226    }
227    int32_t ret = GetUdidByNetworkId(networkId, udid);
228    if (ret == DM_OK) {
229        LOGI("Get udid from bus success, networkId %{public}s, udid %{public}s.",
230            GetAnonyString(std::string(networkId)).c_str(), GetAnonyString(udid).c_str());
231        return DM_OK;
232    }
233    return ret;
234}
235
236int32_t SoftbusCache::GetUuidFromCache(const char *networkId, std::string &uuid)
237{
238    std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
239    for (const auto &item : deviceInfo_) {
240        if (std::string(item.second.second.networkId) == std::string(networkId)) {
241            uuid = item.second.first;
242            LOGI("Get uuid from cache success, networkId %{public}s, uuid %{public}s.",
243                GetAnonyString(std::string(networkId)).c_str(), GetAnonyString(uuid).c_str());
244            return DM_OK;
245        }
246    }
247    int32_t ret = GetUuidByNetworkId(networkId, uuid);
248    if (ret == DM_OK) {
249        LOGI("Get uuid from bus success, networkId %{public}s, uuid %{public}s.",
250            GetAnonyString(std::string(networkId)).c_str(), GetAnonyString(uuid).c_str());
251        return DM_OK;
252    }
253    return ret;
254}
255
256int32_t SoftbusCache::ConvertNodeBasicInfoToDmDevice(const NodeBasicInfo &nodeInfo, DmDeviceInfo &devInfo)
257{
258    if (memset_s(&devInfo, sizeof(DmDeviceInfo), 0, sizeof(DmDeviceInfo)) != DM_OK) {
259        LOGE("ConvertNodeBasicInfoToDmDevice memset_s failed.");
260        return ERR_DM_FAILED;
261    }
262
263    if (memcpy_s(devInfo.networkId, sizeof(devInfo.networkId), nodeInfo.networkId,
264        std::min(sizeof(devInfo.networkId), sizeof(nodeInfo.networkId))) != DM_OK) {
265        LOGE("ConvertNodeBasicInfoToDmDevice copy networkId data failed.");
266        return ERR_DM_FAILED;
267    }
268
269    if (memcpy_s(devInfo.deviceName, sizeof(devInfo.deviceName), nodeInfo.deviceName,
270        std::min(sizeof(devInfo.deviceName), sizeof(nodeInfo.deviceName))) != DM_OK) {
271        LOGE("ConvertNodeBasicInfoToDmDevice copy deviceName data failed.");
272        return ERR_DM_FAILED;
273    }
274
275    devInfo.deviceTypeId = nodeInfo.deviceTypeId;
276    nlohmann::json extraJson;
277    extraJson[PARAM_KEY_OS_TYPE] = nodeInfo.osType;
278    extraJson[PARAM_KEY_OS_VERSION] = ConvertCharArray2String(nodeInfo.osVersion, OS_VERSION_BUF_LEN);
279    devInfo.extraData = to_string(extraJson);
280    return DM_OK;
281}
282
283void SoftbusCache::SaveDeviceSecurityLevel(const char *networkId)
284{
285    LOGI("SoftbusCache::SaveDeviceSecurityLevel networkId %{public}s.", GetAnonyString(std::string(networkId)).c_str());
286    std::lock_guard<std::mutex> mutexLock(deviceSecurityLevelMutex_);
287    if (deviceSecurityLevel_.find(std::string(networkId)) != deviceSecurityLevel_.end()) {
288        return;
289    }
290    int32_t tempSecurityLevel = -1;
291    if (GetNodeKeyInfo(DM_PKG_NAME, networkId, NodeDeviceInfoKey::NODE_KEY_DEVICE_SECURITY_LEVEL,
292        reinterpret_cast<uint8_t *>(&tempSecurityLevel), LNN_COMMON_LEN) != DM_OK) {
293        LOGE("[SOFTBUS]GetNodeKeyInfo networkType failed.");
294        return;
295    }
296    deviceSecurityLevel_[std::string(networkId)] = tempSecurityLevel;
297}
298
299void SoftbusCache::DeleteDeviceSecurityLevel(const char *networkId)
300{
301    LOGI("SoftbusCache::DeleteDeviceSecurityLevel networkId %{public}s.",
302        GetAnonyString(std::string(networkId)).c_str());
303    std::lock_guard<std::mutex> mutexLock(deviceSecurityLevelMutex_);
304    if (deviceSecurityLevel_.find(std::string(networkId)) != deviceSecurityLevel_.end()) {
305        deviceSecurityLevel_.erase(std::string(networkId));
306    }
307}
308
309int32_t SoftbusCache::GetSecurityDeviceLevel(const char *networkId, int32_t &securityLevel)
310{
311    std::lock_guard<std::mutex> mutexLock(deviceSecurityLevelMutex_);
312    for (const auto &item : deviceSecurityLevel_) {
313        if (item.first == std::string(networkId)) {
314            securityLevel = item.second;
315            LOGI("Get dev level from cache success, networkId is %{public}s.",
316                GetAnonyString(std::string(networkId)).c_str());
317            return DM_OK;
318        }
319    }
320    return GetDevLevelFromBus(networkId, securityLevel);
321}
322
323int32_t SoftbusCache::GetDevLevelFromBus(const char *networkId, int32_t &securityLevel)
324{
325    int32_t tempSecurityLevel = -1;
326    if (GetNodeKeyInfo(DM_PKG_NAME, networkId, NodeDeviceInfoKey::NODE_KEY_DEVICE_SECURITY_LEVEL,
327        reinterpret_cast<uint8_t *>(&tempSecurityLevel), LNN_COMMON_LEN) != DM_OK) {
328        LOGE("[SOFTBUS]GetNodeKeyInfo networkType failed.");
329        return ERR_DM_FAILED;
330    }
331    securityLevel = tempSecurityLevel;
332    deviceSecurityLevel_[std::string(networkId)] = tempSecurityLevel;
333    LOGI("Get dev level from softbus success, networkId is %{public}s.",
334        GetAnonyString(std::string(networkId)).c_str());
335    return DM_OK;
336}
337
338int32_t SoftbusCache::GetDevInfoByNetworkId(const std::string &networkId, DmDeviceInfo &nodeInfo)
339{
340    {
341        std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
342        for (const auto &item : deviceInfo_) {
343            if (std::string(item.second.second.networkId) == networkId) {
344                nodeInfo = item.second.second;
345                LOGI("GetDevInfoByNetworkId success networkId %{public}s, udid %{public}s.",
346                    GetAnonyString(networkId).c_str(), GetAnonyString(item.first).c_str());
347                return DM_OK;
348            }
349        }
350    }
351    int32_t ret = GetDevInfoFromBus(networkId, nodeInfo);
352    if (ret != DM_OK) {
353        LOGE("GetDevInfoFromBus failed.");
354        return ret;
355    }
356    SaveDeviceInfo(nodeInfo);
357    return DM_OK;
358}
359
360int32_t SoftbusCache::GetDevInfoFromBus(const std::string &networkId, DmDeviceInfo &devInfo)
361{
362    int32_t nodeInfoCount = 0;
363    NodeBasicInfo *nodeInfo = nullptr;
364    int32_t ret = GetAllNodeDeviceInfo(DM_PKG_NAME, &nodeInfo, &nodeInfoCount);
365    if (ret != DM_OK) {
366        LOGE("[SOFTBUS]GetAllNodeDeviceInfo failed, ret: %{public}d.", ret);
367        return ret;
368    }
369    for (int32_t i = 0; i < nodeInfoCount; ++i) {
370        NodeBasicInfo *nodeBasicInfo = nodeInfo + i;
371        if (networkId == std::string(nodeBasicInfo->networkId)) {
372            ConvertNodeBasicInfoToDmDevice(*nodeBasicInfo, devInfo);
373            break;
374        }
375    }
376    FreeNodeInfo(nodeInfo);
377    LOGI("GetDeviceInfo complete, deviceName : %{public}s, deviceTypeId : %{public}d.",
378        GetAnonyString(devInfo.deviceName).c_str(), devInfo.deviceTypeId);
379    return ret;
380}
381
382int32_t SoftbusCache::GetUdidByUdidHash(const std::string &udidHash, std::string &udid)
383{
384    LOGI("udidHash %{public}s.", GetAnonyString(udidHash).c_str());
385    {
386        std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
387        for (const auto &item : deviceInfo_) {
388            if (std::string(item.second.second.deviceId) == udidHash) {
389                udid = item.first;
390                LOGI("GetUdidByUdidHash success udid %{public}s.", GetAnonyString(udid).c_str());
391                return DM_OK;
392            }
393        }
394    }
395    return ERR_DM_FAILED;
396}
397
398int32_t SoftbusCache::GetUuidByUdid(const std::string &udid, std::string &uuid)
399{
400    LOGI("udid %{public}s.", GetAnonyString(udid).c_str());
401    {
402        std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
403        if (deviceInfo_.find(udid) != deviceInfo_.end()) {
404            uuid = deviceInfo_[udid].first;
405            LOGI("success uuid %{public}s.", GetAnonyString(uuid).c_str());
406            return DM_OK;
407        }
408    }
409    return ERR_DM_FAILED;
410}
411
412int32_t SoftbusCache::GetNetworkIdFromCache(const std::string &udid, std::string &networkId)
413{
414    LOGI("udid %{public}s.", GetAnonyString(udid).c_str());
415    {
416        std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
417        if (deviceInfo_.find(udid) != deviceInfo_.end()) {
418            networkId = deviceInfo_[udid].second.networkId;
419            LOGI("GetNetworkIdFromCache success networkId %{public}s, udid %{public}s.",
420                GetAnonyString(networkId).c_str(), GetAnonyString(udid).c_str());
421            return DM_OK;
422        }
423    }
424    return ERR_DM_FAILED;
425}
426
427bool SoftbusCache::CheckIsOnline(const std::string &deviceId)
428{
429    LOGI("deviceId %{public}s.", GetAnonyString(deviceId).c_str());
430    {
431        std::lock_guard<std::mutex> mutexLock(deviceInfosMutex_);
432        for (const auto &item : deviceInfo_) {
433            if (std::string(item.second.second.deviceId) == deviceId) {
434                LOGI("CheckIsOnline is true.");
435                return true;
436            }
437        }
438    }
439    return false;
440}
441} // namespace DistributedHardware
442} // namespace OHOS
443