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