1 /*
2 * Copyright (c) 2023-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 "network/softbus/softbus_handler.h"
17
18 #include <utility>
19
20 #include "all_connect/all_connect_manager.h"
21 #include "device_manager.h"
22 #include "dfs_daemon_event_dfx.h"
23 #include "dfs_error.h"
24 #include "dm_device_info.h"
25 #include "network/softbus/softbus_file_receive_listener.h"
26 #include "network/softbus/softbus_file_send_listener.h"
27 #include "network/softbus/softbus_session_listener.h"
28 #include "trans_mananger.h"
29 #include "utils_directory.h"
30 #include "utils_log.h"
31
32 namespace OHOS {
33 namespace Storage {
34 namespace DistributedFile {
35 using namespace OHOS::FileManagement;
36 const int32_t DFS_QOS_TYPE_MIN_BW = 90 * 1024 * 1024;
37 const int32_t DFS_QOS_TYPE_MAX_LATENCY = 10000;
38 const int32_t DFS_QOS_TYPE_MIN_LATENCY = 2000;
39 const int32_t INVALID_SESSION_ID = -1;
40 #ifdef SUPPORT_SAME_ACCOUNT
41 const uint32_t MAX_ONLINE_DEVICE_SIZE = 10000;
42 #endif
43 constexpr size_t MAX_SIZE = 500;
44 std::mutex SoftBusHandler::clientSessNameMapMutex_;
45 std::map<int32_t, std::string> SoftBusHandler::clientSessNameMap_;
46 std::mutex SoftBusHandler::serverIdMapMutex_;
47 std::map<std::string, int32_t> SoftBusHandler::serverIdMap_;
48 std::mutex SoftBusHandler::networkIdMapMutex_;
49 std::map<int32_t, std::string> SoftBusHandler::networkIdMap_;
OnSinkSessionOpened(int32_t sessionId,PeerSocketInfo info)50 void SoftBusHandler::OnSinkSessionOpened(int32_t sessionId, PeerSocketInfo info)
51 {
52 if (!SoftBusHandler::IsSameAccount(info.networkId)) {
53 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
54 auto it = serverIdMap_.find(info.name);
55 if (it != serverIdMap_.end()) {
56 Shutdown(it->second);
57 serverIdMap_.erase(it);
58 LOGI("RemoveSessionServer success.");
59 }
60 Shutdown(sessionId);
61 return;
62 }
63 {
64 std::lock_guard<std::mutex> lock(SoftBusHandler::clientSessNameMapMutex_);
65 SoftBusHandler::clientSessNameMap_.insert(std::make_pair(sessionId, info.name));
66 }
67 {
68 std::lock_guard<std::mutex> lock(networkIdMapMutex_);
69 networkIdMap_.insert(std::make_pair(sessionId, info.networkId));
70 }
71
72 AllConnectManager::GetInstance().PublishServiceState(info.networkId,
73 ServiceCollaborationManagerBussinessStatus::SCM_CONNECTED);
74 }
75
IsSameAccount(const std::string & networkId)76 bool SoftBusHandler::IsSameAccount(const std::string &networkId)
77 {
78 #ifdef SUPPORT_SAME_ACCOUNT
79 std::vector<DistributedHardware::DmDeviceInfo> deviceList;
80 DistributedHardware::DeviceManager::GetInstance().GetTrustedDeviceList(SERVICE_NAME, "", deviceList);
81 if (deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) {
82 LOGE("trust device list size is invalid, size=%zu", deviceList.size());
83 return false;
84 }
85 for (const auto &deviceInfo : deviceList) {
86 if (std::string(deviceInfo.networkId) == networkId) {
87 return (deviceInfo.authForm == DistributedHardware::DmAuthForm::IDENTICAL_ACCOUNT);
88 }
89 }
90 return false;
91 #else
92 return true;
93 #endif
94 }
95
GetSessionName(int32_t sessionId)96 std::string SoftBusHandler::GetSessionName(int32_t sessionId)
97 {
98 std::string sessionName = "";
99 std::lock_guard<std::mutex> lock(clientSessNameMapMutex_);
100 auto iter = clientSessNameMap_.find(sessionId);
101 if (iter != clientSessNameMap_.end()) {
102 sessionName = iter->second;
103 return sessionName;
104 }
105 LOGE("sessionName not registered");
106 return sessionName;
107 }
108
SoftBusHandler()109 SoftBusHandler::SoftBusHandler()
110 {
111 ISocketListener fileSendListener;
112 fileSendListener.OnBind = nullptr;
113 fileSendListener.OnShutdown = DistributedFile::SoftBusFileSendListener::OnSendFileShutdown;
114 fileSendListener.OnFile = DistributedFile::SoftBusFileSendListener::OnFile;
115 fileSendListener.OnBytes = nullptr;
116 fileSendListener.OnMessage = nullptr;
117 fileSendListener.OnQos = nullptr;
118 sessionListener_[DFS_CHANNLE_ROLE_SOURCE] = fileSendListener;
119
120 ISocketListener fileReceiveListener;
121 fileReceiveListener.OnBind = DistributedFile::SoftBusFileReceiveListener::OnCopyReceiveBind;
122 fileReceiveListener.OnShutdown = DistributedFile::SoftBusFileReceiveListener::OnReceiveFileShutdown;
123 fileReceiveListener.OnFile = DistributedFile::SoftBusFileReceiveListener::OnFile;
124 fileReceiveListener.OnBytes = nullptr;
125 fileReceiveListener.OnMessage = nullptr;
126 fileReceiveListener.OnQos = nullptr;
127 sessionListener_[DFS_CHANNLE_ROLE_SINK] = fileReceiveListener;
128 }
129
130 SoftBusHandler::~SoftBusHandler() = default;
131
GetInstance()132 SoftBusHandler &SoftBusHandler::GetInstance()
133 {
134 LOGI("SoftBusHandle::GetInstance");
135 static SoftBusHandler handle;
136 return handle;
137 }
138
CreateSessionServer(const std::string & packageName,const std::string & sessionName,DFS_CHANNEL_ROLE role,const std::string physicalPath)139 int32_t SoftBusHandler::CreateSessionServer(const std::string &packageName, const std::string &sessionName,
140 DFS_CHANNEL_ROLE role, const std::string physicalPath)
141 {
142 if (packageName.empty() || sessionName.empty() || physicalPath.empty()) {
143 LOGI("The parameter is empty");
144 return FileManagement::ERR_BAD_VALUE;
145 }
146 LOGI("CreateSessionServer Enter.");
147 SocketInfo serverInfo = {
148 .name = const_cast<char*>(sessionName.c_str()),
149 .pkgName = const_cast<char*>(packageName.c_str()),
150 .dataType = DATA_TYPE_FILE,
151 };
152 int32_t socketId = Socket(serverInfo);
153 if (socketId < E_OK) {
154 LOGE("Create Socket fail socketId, socketId = %{public}d", socketId);
155 RADAR_REPORT(RadarReporter::DFX_SET_DFS, RadarReporter::DFX_SET_BIZ_SCENE, RadarReporter::DFX_FAILED,
156 RadarReporter::BIZ_STATE, RadarReporter::DFX_END, RadarReporter::ERROR_CODE,
157 RadarReporter::CREAT_SOCKET_ERROR, RadarReporter::PACKAGE_NAME,
158 RadarReporter::dSoftBus + std::to_string(socketId));
159 return FileManagement::ERR_BAD_VALUE;
160 }
161 QosTV qos[] = {
162 {.qos = QOS_TYPE_MIN_BW, .value = DFS_QOS_TYPE_MIN_BW},
163 {.qos = QOS_TYPE_MAX_LATENCY, .value = DFS_QOS_TYPE_MAX_LATENCY},
164 {.qos = QOS_TYPE_MIN_LATENCY, .value = DFS_QOS_TYPE_MIN_LATENCY},
165 };
166
167 int32_t ret = Listen(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener_[role]);
168 if (ret != E_OK) {
169 LOGE("Listen socket error for sessionName:%{public}s", sessionName.c_str());
170 Shutdown(socketId);
171 return FileManagement::ERR_BAD_VALUE;
172 }
173 {
174 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
175 serverIdMap_.insert(std::make_pair(sessionName, socketId));
176 }
177 DistributedFile::SoftBusFileReceiveListener::SetRecvPath(physicalPath);
178 LOGI("CreateSessionServer success socketId = %{public}d", socketId);
179 return socketId;
180 }
181
OpenSession(const std::string & mySessionName,const std::string & peerSessionName,const std::string & peerDevId,int32_t & socketId)182 int32_t SoftBusHandler::OpenSession(const std::string &mySessionName, const std::string &peerSessionName,
183 const std::string &peerDevId, int32_t &socketId)
184 {
185 if (mySessionName.empty() || peerSessionName.empty() || peerDevId.empty()) {
186 LOGI("The parameter is empty");
187 return FileManagement::ERR_BAD_VALUE;
188 }
189 LOGI("OpenSession Enter peerDevId: %{public}s", Utils::GetAnonyString(peerDevId).c_str());
190 if (!IsSameAccount(peerDevId)) {
191 LOGI("The source and sink device is not same account, not support.");
192 return E_OPEN_SESSION;
193 }
194 QosTV qos[] = {
195 {.qos = QOS_TYPE_MIN_BW, .value = DFS_QOS_TYPE_MIN_BW},
196 {.qos = QOS_TYPE_MAX_LATENCY, .value = DFS_QOS_TYPE_MAX_LATENCY},
197 {.qos = QOS_TYPE_MIN_LATENCY, .value = DFS_QOS_TYPE_MIN_LATENCY},
198 };
199 if (!CreatSocketId(mySessionName, peerSessionName, peerDevId, socketId)) {
200 return FileManagement::ERR_BAD_VALUE;
201 }
202 int32_t ret = Bind(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessionListener_[DFS_CHANNLE_ROLE_SOURCE]);
203 if (ret != E_OK) {
204 LOGE("Bind SocketClient error");
205 Shutdown(socketId);
206 RadarDotsOpenSession("OpenSession", mySessionName, peerSessionName, ret, Utils::StageRes::STAGE_FAIL);
207 return ret;
208 }
209 {
210 std::lock_guard<std::mutex> lock(clientSessNameMapMutex_);
211 clientSessNameMap_.insert(std::make_pair(socketId, mySessionName));
212 }
213 {
214 std::lock_guard<std::mutex> lock(networkIdMapMutex_);
215 networkIdMap_.insert(std::make_pair(socketId, peerDevId));
216 }
217 RadarDotsOpenSession("OpenSession", mySessionName, peerSessionName, ret, Utils::StageRes::STAGE_SUCCESS);
218 LOGI("OpenSession success socketId = %{public}d", socketId);
219 return E_OK;
220 }
221
CreatSocketId(const std::string & mySessionName,const std::string & peerSessionName,const std::string & peerDevId,int32_t & socketId)222 bool SoftBusHandler::CreatSocketId(const std::string &mySessionName, const std::string &peerSessionName,
223 const std::string &peerDevId, int32_t &socketId)
224 {
225 SocketInfo clientInfo = {
226 .name = const_cast<char*>((mySessionName.c_str())),
227 .peerName = const_cast<char*>(peerSessionName.c_str()),
228 .peerNetworkId = const_cast<char*>(peerDevId.c_str()),
229 .pkgName = const_cast<char*>(SERVICE_NAME.c_str()),
230 .dataType = DATA_TYPE_FILE,
231 };
232 {
233 std::lock_guard<std::mutex> lock(socketMutex_);
234 socketId = Socket(clientInfo);
235 }
236 if (socketId < E_OK) {
237 LOGE("Create OpenSoftbusChannel Socket error");
238 return false;
239 }
240 return true;
241 }
242
CopySendFile(int32_t socketId,const std::string & sessionName,const std::string & srcUri,const std::string & dstPath)243 int32_t SoftBusHandler::CopySendFile(int32_t socketId,
244 const std::string &sessionName,
245 const std::string &srcUri,
246 const std::string &dstPath)
247 {
248 LOGI("CopySendFile socketId = %{public}d", socketId);
249
250 std::string physicalPath = SoftBusSessionListener::GetRealPath(srcUri);
251 if (physicalPath.empty()) {
252 LOGE("GetRealPath failed");
253 return FileManagement::ERR_BAD_VALUE;
254 }
255 auto fileList = OHOS::Storage::DistributedFile::Utils::GetFilePath(physicalPath);
256 if (fileList.empty()) {
257 LOGE("GetFilePath failed or file is empty, path %{public}s", physicalPath.c_str());
258 return FileManagement::ERR_BAD_VALUE;
259 }
260 const char *src[MAX_SIZE] = {};
261 for (size_t i = 0; i < fileList.size() && fileList.size() < MAX_SIZE; i++) {
262 src[i] = fileList.at(i).c_str();
263 }
264
265 auto fileNameList = SoftBusSessionListener::GetFileName(fileList, physicalPath, dstPath);
266 if (fileNameList.empty()) {
267 LOGE("GetFileName failed, path %{public}s %{public}s", physicalPath.c_str(), dstPath.c_str());
268 return FileManagement::ERR_BAD_VALUE;
269 }
270 const char *dst[MAX_SIZE] = {};
271 for (size_t i = 0; i < fileNameList.size() && fileList.size() < MAX_SIZE; i++) {
272 dst[i] = fileNameList.at(i).c_str();
273 }
274
275 LOGI("Enter SendFile.");
276 auto ret = ::SendFile(socketId, src, dst, static_cast<uint32_t>(fileList.size()));
277 if (ret != E_OK) {
278 LOGE("SendFile failed, sessionId = %{public}d", socketId);
279 RadarDotsSendFile("OpenSession", sessionName, sessionName, ret, Utils::StageRes::STAGE_FAIL);
280 return ret;
281 }
282 RadarDotsSendFile("OpenSession", sessionName, sessionName, ret, Utils::StageRes::STAGE_SUCCESS);
283 return E_OK;
284 }
285
ChangeOwnerIfNeeded(int32_t sessionId,const std::string sessionName)286 void SoftBusHandler::ChangeOwnerIfNeeded(int32_t sessionId, const std::string sessionName)
287 {
288 if (sessionName.empty()) {
289 LOGI("sessionName is empty");
290 return;
291 }
292 SoftBusSessionPool::SessionInfo sessionInfo {};
293 int32_t ret = SoftBusSessionPool::GetInstance().GetSessionInfo(sessionName, sessionInfo);
294 if (!ret) {
295 LOGE("GetSessionInfo failed");
296 return;
297 }
298 if (DistributedFile::Utils::ChangeOwnerRecursive(sessionInfo.dstPath, sessionInfo.uid, sessionInfo.uid) != 0) {
299 LOGE("ChangeOwnerRecursive failed");
300 }
301 }
302
CloseSession(int32_t sessionId,const std::string sessionName)303 void SoftBusHandler::CloseSession(int32_t sessionId, const std::string sessionName)
304 {
305 LOGI("CloseSession Enter socketId = %{public}d", sessionId);
306 if (sessionName.empty() || sessionId <= 0) {
307 LOGI("sessionName is empty");
308 return;
309 }
310 if (!serverIdMap_.empty()) {
311 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
312 auto it = serverIdMap_.find(sessionName);
313 if (it != serverIdMap_.end()) {
314 int32_t serverId = it->second;
315 serverIdMap_.erase(it);
316 Shutdown(serverId);
317 LOGI("RemoveSessionServer success.");
318 }
319 }
320 if (!clientSessNameMap_.empty()) {
321 std::lock_guard<std::mutex> lock(clientSessNameMapMutex_);
322 auto it = clientSessNameMap_.find(sessionId);
323 if (it != clientSessNameMap_.end()) {
324 clientSessNameMap_.erase(it->first);
325 }
326 }
327 {
328 std::lock_guard<std::mutex> lock(socketMutex_);
329 Shutdown(sessionId);
330 }
331 RemoveNetworkId(sessionId);
332 SoftBusSessionPool::GetInstance().DeleteSessionInfo(sessionName);
333 }
334
CloseSessionWithSessionName(const std::string sessionName)335 void SoftBusHandler::CloseSessionWithSessionName(const std::string sessionName)
336 {
337 LOGI("CloseSessionWithSessionName Enter.");
338 if (sessionName.empty()) {
339 LOGI("sessionName is empty");
340 return;
341 }
342 int32_t sessionId = INVALID_SESSION_ID;
343 if (!clientSessNameMap_.empty()) {
344 std::lock_guard<std::mutex> lock(clientSessNameMapMutex_);
345 for (auto it : SoftBusHandler::clientSessNameMap_) {
346 if (it.second == sessionName) {
347 sessionId = it.first;
348 clientSessNameMap_.erase(it.first);
349 break;
350 }
351 }
352 }
353 TransManager::GetInstance().NotifyFileFailed(sessionName, E_DFS_CANCEL_SUCCESS);
354 TransManager::GetInstance().DeleteTransTask(sessionName);
355 CloseSession(sessionId, sessionName);
356 }
RemoveNetworkId(int32_t socketId)357 void SoftBusHandler::RemoveNetworkId(int32_t socketId)
358 {
359 LOGI("RemoveNetworkId begin");
360 std::lock_guard<std::mutex> lock(networkIdMapMutex_);
361 auto it = networkIdMap_.find(socketId);
362 if (it == networkIdMap_.end()) {
363 LOGE("socketId not find, socket is %{public}d", socketId);
364 return;
365 }
366 std::string peerNetworkId = it->second;
367 networkIdMap_.erase(it->first);
368 for (auto &item : networkIdMap_) {
369 if (item.second == peerNetworkId) {
370 return;
371 }
372 }
373 AllConnectManager::GetInstance().PublishServiceState(peerNetworkId,
374 ServiceCollaborationManagerBussinessStatus::SCM_IDLE);
375 }
376
GetsocketIdFromPeerNetworkId(const std::string & peerNetworkId)377 std::vector<int32_t> SoftBusHandler::GetsocketIdFromPeerNetworkId(const std::string &peerNetworkId)
378 {
379 if (peerNetworkId.empty()) {
380 LOGE("peerNetworkId is empty");
381 return {};
382 }
383 std::vector<int32_t> socketIdList;
384 std::lock_guard<std::mutex> lock(networkIdMapMutex_);
385 for (auto item : networkIdMap_) {
386 if (item.second == peerNetworkId) {
387 socketIdList.emplace_back(item.first);
388 }
389 }
390
391 return socketIdList;
392 }
393
IsService(std::string & sessionName)394 bool SoftBusHandler::IsService(std::string &sessionName)
395 {
396 std::lock_guard<std::mutex> lock(serverIdMapMutex_);
397 auto it = serverIdMap_.find(sessionName);
398 if (it == serverIdMap_.end()) {
399 return false;
400 }
401 return true;
402 }
403
CopyOnStop(const std::string & peerNetworkId)404 void SoftBusHandler::CopyOnStop(const std::string &peerNetworkId)
405 {
406 auto socketIdList = GetsocketIdFromPeerNetworkId(peerNetworkId);
407
408 for (auto socketId : socketIdList) {
409 std::string sessionName = GetSessionName(socketId);
410 if (sessionName.empty()) {
411 LOGE("sessionName is empty");
412 continue;
413 }
414
415 if (IsService(sessionName)) {
416 TransManager::GetInstance().NotifyFileFailed(sessionName, E_DFS_CANCEL_SUCCESS);
417 TransManager::GetInstance().DeleteTransTask(sessionName);
418 }
419
420 CloseSession(socketId, sessionName);
421 }
422 }
423 } // namespace DistributedFile
424 } // namespace Storage
425 } // namespace OHOS