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