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