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