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