• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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