• 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 #include "soft_bus_manager.h"
16 
17 #include <securec.h>
18 #include "constant_common.h"
19 #include "device_info_manager.h"
20 #include "softbus_bus_center.h"
21 #include "dm_device_info.h"
22 #include "remote_command_manager.h"
23 
24 namespace OHOS {
25 namespace Security {
26 namespace AccessToken {
27 namespace {
28 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "SoftBusManager"};
29 }
30 namespace {
31 static const std::string SESSION_GROUP_ID = "atm_dsoftbus_session_group_id";
32 static const SessionAttribute SESSION_ATTR = {.dataType = TYPE_BYTES};
33 
34 static const int REASON_EXIST = -3;
35 static const int OPENSESSION_RETRY_TIMES = 10 * 3;
36 static const int OPENSESSION_RETRY_INTERVAL_MS = 100;
37 static const int UDID_MAX_LENGTH = 128; // udid/uuid max length
38 } // namespace
39 
40 const std::string SoftBusManager::TOKEN_SYNC_PACKAGE_NAME = "ohos.security.distributed_access_token";
41 const std::string SoftBusManager::SESSION_NAME = "ohos.security.atm_channel";
42 
SoftBusManager()43 SoftBusManager::SoftBusManager() : isSoftBusServiceBindSuccess_(false), inited_(false), mutex_(), fulfillMutex_()
44 {
45     ACCESSTOKEN_LOG_DEBUG(LABEL, "SoftBusManager()");
46 }
47 
~SoftBusManager()48 SoftBusManager::~SoftBusManager()
49 {
50     ACCESSTOKEN_LOG_DEBUG(LABEL, "~SoftBusManager()");
51 }
52 
GetInstance()53 SoftBusManager &SoftBusManager::GetInstance()
54 {
55     static SoftBusManager instance;
56     return instance;
57 }
58 
AddTrustedDeviceInfo()59 int SoftBusManager::AddTrustedDeviceInfo()
60 {
61     std::string packageName = TOKEN_SYNC_PACKAGE_NAME;
62     std::string extra = "";
63     std::vector<DistributedHardware::DmDeviceInfo> deviceList;
64 
65     int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(packageName,
66         extra, deviceList);
67     if (ret != Constant::SUCCESS) {
68         ACCESSTOKEN_LOG_ERROR(LABEL, "AddTrustedDeviceInfo: GetTrustedDeviceList error, result: %{public}d", ret);
69         return Constant::FAILURE;
70     }
71 
72     for (const DistributedHardware::DmDeviceInfo& device : deviceList) {
73         std::string uuid = GetUuidByNodeId(device.networkId);
74         std::string udid = GetUdidByNodeId(device.networkId);
75         if (uuid.empty() || udid.empty()) {
76             ACCESSTOKEN_LOG_ERROR(LABEL, "uuid = %{public}s, udid = %{public}s, uuid or udid is empty, abort.",
77                 uuid.c_str(), ConstantCommon::EncryptDevId(udid).c_str());
78             continue;
79         }
80 
81         DeviceInfoManager::GetInstance().AddDeviceInfo(device.networkId, uuid, udid, device.deviceName,
82             std::to_string(device.deviceTypeId));
83         RemoteCommandManager::GetInstance().NotifyDeviceOnline(udid);
84     }
85 
86     return Constant::SUCCESS;
87 }
88 
DeviceInit()89 int SoftBusManager::DeviceInit()
90 {
91     std::string packageName = TOKEN_SYNC_PACKAGE_NAME;
92     std::shared_ptr<MyDmInitCallback> ptrDmInitCallback = std::make_shared<MyDmInitCallback>();
93 
94     int ret = DistributedHardware::DeviceManager::GetInstance().InitDeviceManager(packageName, ptrDmInitCallback);
95     if (ret != ERR_OK) {
96         ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: InitDeviceManager error, result: %{public}d", ret);
97         return ret;
98     }
99 
100     ret = AddTrustedDeviceInfo();
101     if (ret != ERR_OK) {
102         ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: AddTrustedDeviceInfo error, result: %{public}d", ret);
103         return ret;
104     }
105 
106     std::string extra = "";
107     std::shared_ptr<SoftBusDeviceConnectionListener> ptrDeviceStateCallback =
108         std::make_shared<SoftBusDeviceConnectionListener>();
109     ret = DistributedHardware::DeviceManager::GetInstance().RegisterDevStateCallback(packageName, extra,
110         ptrDeviceStateCallback);
111     if (ret != ERR_OK) {
112         ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: RegisterDevStateCallback error, result: %{public}d", ret);
113         return ret;
114     }
115 
116     return ERR_OK;
117 }
118 
SessionInit()119 int SoftBusManager::SessionInit()
120 {
121     // register session listener
122     ISessionListener sessionListener;
123     sessionListener.OnSessionOpened = SoftBusSessionListener::OnSessionOpened;
124     sessionListener.OnSessionClosed = SoftBusSessionListener::OnSessionClosed;
125     sessionListener.OnBytesReceived = SoftBusSessionListener::OnBytesReceived;
126     sessionListener.OnMessageReceived = SoftBusSessionListener::OnMessageReceived;
127 
128     int ret = ::CreateSessionServer(TOKEN_SYNC_PACKAGE_NAME.c_str(), SESSION_NAME.c_str(), &sessionListener);
129     ACCESSTOKEN_LOG_INFO(LABEL, "Initialize: createSessionServer, result: %{public}d", ret);
130     // REASON_EXIST
131     if ((ret != Constant::SUCCESS) && (ret != REASON_EXIST)) {
132         ACCESSTOKEN_LOG_ERROR(LABEL, "Initialize: CreateSessionServer error, result: %{public}d", ret);
133         return ret;
134     }
135 
136     return ERR_OK;
137 }
138 
Initialize()139 void SoftBusManager::Initialize()
140 {
141     bool inited = false;
142     // cas failed means already inited.
143     if (!inited_.compare_exchange_strong(inited, true)) {
144         ACCESSTOKEN_LOG_DEBUG(LABEL, "already initialized, skip");
145         return;
146     }
147 
148     std::function<void()> runner = [&]() {
149         auto sleepTime = std::chrono::milliseconds(1000);
150         while (1) {
151             std::unique_lock<std::mutex> lock(mutex_);
152 
153             int ret = DeviceInit();
154             if (ret != ERR_OK) {
155                 std::this_thread::sleep_for(sleepTime);
156                 continue;
157             }
158 
159             ret = SessionInit();
160             if (ret != ERR_OK) {
161                 std::this_thread::sleep_for(sleepTime);
162                 continue;
163             }
164 
165             isSoftBusServiceBindSuccess_ = true;
166             this->FulfillLocalDeviceInfo();
167             return;
168         }
169     };
170 
171     std::thread initThread(runner);
172     initThread.detach();
173     ACCESSTOKEN_LOG_DEBUG(LABEL, "Initialize thread started");
174 }
175 
Destroy()176 void SoftBusManager::Destroy()
177 {
178     ACCESSTOKEN_LOG_DEBUG(LABEL, "destroy, init: %{public}d, isSoftBusServiceBindSuccess: %{public}d", inited_.load(),
179         isSoftBusServiceBindSuccess_);
180 
181     if (!inited_.load()) {
182         ACCESSTOKEN_LOG_DEBUG(LABEL, "not inited, skip");
183         return;
184     }
185 
186     std::unique_lock<std::mutex> lock(mutex_);
187     if (!inited_.load()) {
188         ACCESSTOKEN_LOG_DEBUG(LABEL, "not inited, skip");
189         return;
190     }
191 
192     if (isSoftBusServiceBindSuccess_) {
193         int32_t ret = ::RemoveSessionServer(TOKEN_SYNC_PACKAGE_NAME.c_str(), SESSION_NAME.c_str());
194         ACCESSTOKEN_LOG_DEBUG(LABEL, "destroy, RemoveSessionServer: %{public}d", ret);
195         isSoftBusServiceBindSuccess_ = false;
196     }
197 
198     std::string packageName = TOKEN_SYNC_PACKAGE_NAME;
199     int ret = DistributedHardware::DeviceManager::GetInstance().UnRegisterDevStateCallback(packageName);
200     if (ret != ERR_OK) {
201         ACCESSTOKEN_LOG_ERROR(LABEL, "UnRegisterDevStateCallback failed, code: %{public}d", ret);
202     }
203     ret = DistributedHardware::DeviceManager::GetInstance().UnInitDeviceManager(packageName);
204     if (ret != ERR_OK) {
205         ACCESSTOKEN_LOG_ERROR(LABEL, "UnInitDeviceManager failed, code: %{public}d", ret);
206     }
207 
208     inited_.store(false);
209 
210     ACCESSTOKEN_LOG_DEBUG(LABEL, "destroy, done");
211 }
212 
OpenSession(const std::string & deviceId)213 int32_t SoftBusManager::OpenSession(const std::string &deviceId)
214 {
215 #ifdef DEBUG_API_PERFORMANCE
216     ACCESSTOKEN_LOG_INFO(LABEL, "api_performance:start open session");
217 #endif
218 
219     DeviceInfo info;
220     bool result = DeviceInfoManager::GetInstance().GetDeviceInfo(deviceId, DeviceIdType::UNKNOWN, info);
221     if (!result) {
222         ACCESSTOKEN_LOG_WARN(LABEL, "device info notfound for deviceId %{public}s",
223             ConstantCommon::EncryptDevId(deviceId).c_str());
224         return Constant::FAILURE;
225     }
226     std::string networkId = info.deviceId.networkId;
227     ACCESSTOKEN_LOG_INFO(LABEL, "openSession, networkId: %{public}s", networkId.c_str());
228 
229     // async open session, should waitting for OnSessionOpened event.
230     int sessionId = ::OpenSession(SESSION_NAME.c_str(), SESSION_NAME.c_str(), networkId.c_str(),
231         SESSION_GROUP_ID.c_str(), &SESSION_ATTR);
232 
233     ACCESSTOKEN_LOG_DEBUG(LABEL, "async open session");
234 
235     // wait session opening
236     int retryTimes = 0;
237     int logSpan = 10;
238     auto sleepTime = std::chrono::milliseconds(OPENSESSION_RETRY_INTERVAL_MS);
239     while (retryTimes++ < OPENSESSION_RETRY_TIMES) {
240         if (SoftBusSessionListener::GetSessionState(sessionId) < 0) {
241             std::this_thread::sleep_for(sleepTime);
242             if (retryTimes % logSpan == 0) {
243                 ACCESSTOKEN_LOG_INFO(LABEL, "openSession, waitting for: %{public}d ms",
244                     retryTimes * OPENSESSION_RETRY_INTERVAL_MS);
245             }
246             continue;
247         }
248         break;
249     }
250 #ifdef DEBUG_API_PERFORMANCE
251     ACCESSTOKEN_LOG_INFO(LABEL, "api_performance:start open session success");
252 #endif
253     int64_t state = SoftBusSessionListener::GetSessionState(sessionId);
254     if (state < 0) {
255         ACCESSTOKEN_LOG_ERROR(LABEL, "openSession, timeout, session: %{public}" PRId64, state);
256         return Constant::FAILURE;
257     }
258 
259     SoftBusSessionListener::DeleteSessionIdFromMap(sessionId);
260 
261     ACCESSTOKEN_LOG_DEBUG(LABEL, "openSession, succeed, session: %{public}" PRId64, state);
262     return sessionId;
263 }
264 
CloseSession(int sessionId)265 int SoftBusManager::CloseSession(int sessionId)
266 {
267     if (sessionId < 0) {
268         ACCESSTOKEN_LOG_INFO(LABEL, "closeSession: session is invalid");
269         return Constant::FAILURE;
270     }
271 
272     ::CloseSession(sessionId);
273     ACCESSTOKEN_LOG_INFO(LABEL, "closeSession ");
274     return Constant::SUCCESS;
275 }
276 
GetUniversallyUniqueIdByNodeId(const std::string & nodeId)277 std::string SoftBusManager::GetUniversallyUniqueIdByNodeId(const std::string &nodeId)
278 {
279     if (!DataValidator::IsDeviceIdValid(nodeId)) {
280         ACCESSTOKEN_LOG_ERROR(LABEL, "invalid nodeId: %{public}s", ConstantCommon::EncryptDevId(nodeId).c_str());
281         return "";
282     }
283 
284     std::string uuid = GetUuidByNodeId(nodeId);
285     if (uuid.empty()) {
286         ACCESSTOKEN_LOG_ERROR(LABEL, "softbus return null or empty string");
287         return "";
288     }
289 
290     DeviceInfo info;
291     bool result = DeviceInfoManager::GetInstance().GetDeviceInfo(uuid, DeviceIdType::UNIVERSALLY_UNIQUE_ID, info);
292     if (!result) {
293         ACCESSTOKEN_LOG_DEBUG(LABEL, "local device info not found for uuid %{public}s", uuid.c_str());
294     } else {
295         std::string dimUuid = info.deviceId.universallyUniqueId;
296         if (uuid == dimUuid) {
297             // refresh cache
298             std::function<void()> fulfillDeviceInfo = std::bind(&SoftBusManager::FulfillLocalDeviceInfo, this);
299             std::thread fulfill(fulfillDeviceInfo);
300             fulfill.detach();
301         }
302     }
303 
304     return uuid;
305 }
306 
GetUniqueDeviceIdByNodeId(const std::string & nodeId)307 std::string SoftBusManager::GetUniqueDeviceIdByNodeId(const std::string &nodeId)
308 {
309     if (!DataValidator::IsDeviceIdValid(nodeId)) {
310         ACCESSTOKEN_LOG_ERROR(LABEL, "invalid nodeId: %{public}s", ConstantCommon::EncryptDevId(nodeId).c_str());
311         return "";
312     }
313     std::string udid = GetUdidByNodeId(nodeId);
314     if (udid.empty()) {
315         ACCESSTOKEN_LOG_ERROR(LABEL, "softbus return null or empty string: %{public}s",
316             ConstantCommon::EncryptDevId(udid).c_str());
317         return "";
318     }
319     std::string localUdid = ConstantCommon::GetLocalDeviceId();
320     if (udid == localUdid) {
321         // refresh cache
322         std::function<void()> fulfillDeviceInfo = std::bind(&SoftBusManager::FulfillLocalDeviceInfo, this);
323         std::thread fulfill(fulfillDeviceInfo);
324         fulfill.detach();
325     }
326     return udid;
327 }
328 
GetUuidByNodeId(const std::string & nodeId) const329 std::string SoftBusManager::GetUuidByNodeId(const std::string &nodeId) const
330 {
331     uint8_t *info = new (std::nothrow) uint8_t[UDID_MAX_LENGTH + 1];
332     if (info == nullptr) {
333         ACCESSTOKEN_LOG_ERROR(LABEL, "no enough memory: %{public}d", UDID_MAX_LENGTH);
334         return "";
335     }
336     (void)memset_s(info, UDID_MAX_LENGTH + 1, 0, UDID_MAX_LENGTH + 1);
337     int32_t ret = ::GetNodeKeyInfo(TOKEN_SYNC_PACKAGE_NAME.c_str(), nodeId.c_str(),
338         NodeDeviceInfoKey::NODE_KEY_UUID, info, UDID_MAX_LENGTH);
339     if (ret != Constant::SUCCESS) {
340         delete[] info;
341         ACCESSTOKEN_LOG_WARN(LABEL, "GetNodeKeyInfo error, return code: %{public}d", ret);
342         return "";
343     }
344     std::string uuid(reinterpret_cast<char *>(info));
345     delete[] info;
346     ACCESSTOKEN_LOG_DEBUG(LABEL, "call softbus finished. nodeId(in): %{public}s, uuid: %{public}s",
347         ConstantCommon::EncryptDevId(nodeId).c_str(), uuid.c_str());
348     return uuid;
349 }
350 
GetUdidByNodeId(const std::string & nodeId) const351 std::string SoftBusManager::GetUdidByNodeId(const std::string &nodeId) const
352 {
353     uint8_t *info = new (std::nothrow) uint8_t[UDID_MAX_LENGTH + 1];
354     if (info == nullptr) {
355         ACCESSTOKEN_LOG_ERROR(LABEL, "no enough memory: %{public}d", UDID_MAX_LENGTH);
356         return "";
357     }
358     (void)memset_s(info, UDID_MAX_LENGTH + 1, 0, UDID_MAX_LENGTH + 1);
359     int32_t ret = ::GetNodeKeyInfo(TOKEN_SYNC_PACKAGE_NAME.c_str(), nodeId.c_str(),
360         NodeDeviceInfoKey::NODE_KEY_UDID, info, UDID_MAX_LENGTH);
361     if (ret != Constant::SUCCESS) {
362         delete[] info;
363         ACCESSTOKEN_LOG_WARN(LABEL, "GetNodeKeyInfo error, code: %{public}d", ret);
364         return "";
365     }
366     std::string udid(reinterpret_cast<char *>(info));
367     delete[] info;
368     ACCESSTOKEN_LOG_DEBUG(LABEL, "call softbus finished: nodeId(in): %{public}s",
369         ConstantCommon::EncryptDevId(nodeId).c_str());
370     return udid;
371 }
372 
FulfillLocalDeviceInfo()373 int SoftBusManager::FulfillLocalDeviceInfo()
374 {
375     // repeated task will just skip
376     if (!fulfillMutex_.try_lock()) {
377         ACCESSTOKEN_LOG_INFO(LABEL, "FulfillLocalDeviceInfo already running, skip.");
378         return Constant::SUCCESS;
379     }
380 
381     NodeBasicInfo info;
382     int32_t ret = ::GetLocalNodeDeviceInfo(TOKEN_SYNC_PACKAGE_NAME.c_str(), &info);
383     if (ret != Constant::SUCCESS) {
384         ACCESSTOKEN_LOG_ERROR(LABEL, "GetLocalNodeDeviceInfo error");
385         fulfillMutex_.unlock();
386         return Constant::FAILURE;
387     }
388 
389     ACCESSTOKEN_LOG_DEBUG(LABEL, "call softbus finished, type:%{public}d", info.deviceTypeId);
390 
391     std::string uuid = GetUuidByNodeId(info.networkId);
392     std::string udid = GetUdidByNodeId(info.networkId);
393     if (uuid.empty() || udid.empty()) {
394         ACCESSTOKEN_LOG_ERROR(LABEL, "FulfillLocalDeviceInfo: uuid or udid is empty, abort.");
395         fulfillMutex_.unlock();
396         return Constant::FAILURE;
397     }
398 
399     DeviceInfoManager::GetInstance().AddDeviceInfo(info.networkId, uuid, udid, info.deviceName,
400         std::to_string(info.deviceTypeId));
401     ACCESSTOKEN_LOG_DEBUG(LABEL, "AddDeviceInfo finished");
402 
403     fulfillMutex_.unlock();
404     return Constant::SUCCESS;
405 }
406 } // namespace AccessToken
407 } // namespace Security
408 } // namespace OHOS
409