• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 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 "daemon_execute.h"
17 
18 #include <chrono>
19 #include <ctime>
20 #include <filesystem>
21 #include <memory>
22 #include <random>
23 #include <regex>
24 
25 #include "asset_callback_manager.h"
26 #include "daemon.h"
27 #include "dfs_error.h"
28 #include "network/softbus/softbus_asset_send_listener.h"
29 #include "network/softbus/softbus_handler_asset.h"
30 #include "network/softbus/softbus_session_pool.h"
31 #include "refbase.h"
32 #include "sandbox_helper.h"
33 #include "utils_directory.h"
34 #include "utils_log.h"
35 
36 #include "all_connect/all_connect_manager.h"
37 #include "network/devsl_dispatcher.h"
38 #include "network/softbus/softbus_handler.h"
39 
40 namespace OHOS {
41 namespace Storage {
42 namespace DistributedFile {
43 using namespace OHOS::AppFileService;
44 using namespace OHOS::FileManagement;
45 using namespace std;
46 namespace {
47 const std::string FILE_MANAGER_AUTHORITY = "docs";
48 const std::string MEDIA_AUTHORITY = "media";
49 }
DaemonExecute()50 DaemonExecute::DaemonExecute()
51 {
52     LOGI("DaemonExecute begin.");
53     executeFuncMap_[DEAMON_EXECUTE_PUSH_ASSET] = &DaemonExecute::ExecutePushAsset;
54     executeFuncMap_[DEAMON_EXECUTE_REQUEST_SEND_FILE] = &DaemonExecute::ExecuteRequestSendFile;
55     executeFuncMap_[DEAMON_EXECUTE_PREPARE_SESSION] = &DaemonExecute::ExecutePrepareSession;
56 }
57 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)58 void DaemonExecute::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
59 {
60     if (event == nullptr) {
61         LOGE("event is nullptr.");
62         return;
63     }
64     std::lock_guard<std::mutex> lock(executeFuncMapMutex_);
65     auto itFunc = executeFuncMap_.find(event->GetInnerEventId());
66     if (itFunc == executeFuncMap_.end()) {
67         LOGE("not find execute func.");
68         return;
69     }
70 
71     auto executeFunc = itFunc->second;
72     (this->*executeFunc)(event);
73 }
74 
ExecutePushAsset(const AppExecFwk::InnerEvent::Pointer & event)75 void DaemonExecute::ExecutePushAsset(const AppExecFwk::InnerEvent::Pointer &event)
76 {
77     if (event == nullptr) {
78         LOGI("eventhandler fail.");
79         return;
80     }
81     auto pushData = event->GetSharedObject<PushAssetData>();
82     if (pushData == nullptr) {
83         LOGE("pushData is nullptr.");
84         return;
85     }
86     int32_t userId = pushData->userId_;
87     auto assetObj = pushData->assetObj_;
88     if (assetObj == nullptr) {
89         LOGE("assetObj is nullptr.");
90         return;
91     }
92     PushAssetInner(userId, assetObj);
93 }
94 
PushAssetInner(int32_t userId,const sptr<AssetObj> & assetObj)95 void DaemonExecute::PushAssetInner(int32_t userId, const sptr<AssetObj> &assetObj)
96 {
97     int32_t socketId;
98     auto ret = SoftBusHandlerAsset::GetInstance().AssetBind(assetObj->dstNetworkId_, socketId);
99     if (ret != E_OK) {
100         LOGE("ExecutePushAsset AssetBind failed, ret %{public}d", ret);
101         auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
102         AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
103         AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
104         return;
105     }
106     SoftBusHandlerAsset::GetInstance().AddAssetObj(socketId, assetObj);
107 
108     auto fileList = GetFileList(assetObj->uris_, userId, assetObj->srcBundleName_);
109     if (fileList.empty()) {
110         LOGE("get fileList is empty.");
111         HandlePushAssetFail(socketId, assetObj);
112         return;
113     }
114 
115     if (!DevslDispatcher::CompareDevslWithLocal(assetObj->dstNetworkId_, fileList)) {
116         LOGE("remote device cannot read this files");
117         HandlePushAssetFail(socketId, assetObj);
118         return ;
119     }
120 
121     std::string sendFileName;
122     bool isSingleFile;
123     ret = HandleZip(fileList, assetObj, sendFileName, isSingleFile);
124     if (ret != E_OK) {
125         LOGE("zip files fail. socketId is %{public}d", socketId);
126         HandlePushAssetFail(socketId, assetObj);
127         SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
128         return;
129     }
130 
131     ret = SoftBusHandlerAsset::GetInstance().AssetSendFile(socketId, sendFileName, isSingleFile);
132     if (ret != E_OK) {
133         LOGE("ExecutePushAsset send file fail, ret %{public}d", ret);
134         HandlePushAssetFail(socketId, assetObj);
135         SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
136         return;
137     }
138 }
139 
ExecuteRequestSendFile(const AppExecFwk::InnerEvent::Pointer & event)140 void DaemonExecute::ExecuteRequestSendFile(const AppExecFwk::InnerEvent::Pointer &event)
141 {
142     if (event == nullptr) {
143         LOGI("eventhandler fail.");
144         return;
145     }
146     auto requestSendFileData = event->GetSharedObject<RequestSendFileData>();
147     if (requestSendFileData == nullptr) {
148         LOGE("requestSendFileData is nullptr.");
149         return;
150     }
151 
152     auto requestSendFileBlock  = requestSendFileData->requestSendFileBlock_;
153     if (requestSendFileBlock == nullptr) {
154         LOGE("requestSendFileBlock is nullptr.");
155         return;
156     }
157     std::string srcUri = requestSendFileData->srcUri_;
158     std::string dstPath  = requestSendFileData->dstPath_;
159     std::string dstDeviceId  = requestSendFileData->dstDeviceId_;
160     std::string sessionName  = requestSendFileData->sessionName_;
161     if (srcUri.empty() || dstDeviceId.empty() || sessionName.empty()) {
162         LOGE("params empty. %{public}s, %{public}s", sessionName.c_str(), Utils::GetAnonyString(dstDeviceId).c_str());
163         requestSendFileBlock->SetValue(ERR_BAD_VALUE);
164         return;
165     }
166 
167     requestSendFileBlock->SetValue(RequestSendFileInner(srcUri, dstPath, dstDeviceId, sessionName));
168 }
169 
RequestSendFileInner(const std::string & srcUri,const std::string & dstPath,const std::string & dstDeviceId,const std::string & sessionName)170 int32_t DaemonExecute::RequestSendFileInner(const std::string &srcUri,
171                                             const std::string &dstPath,
172                                             const std::string &dstDeviceId,
173                                             const std::string &sessionName)
174 {
175     LOGI("RequestSendFile begin dstDeviceId: %{public}s", Utils::GetAnonyString(dstDeviceId).c_str());
176     auto resourceReq = AllConnectManager::GetInstance().BuildResourceRequest();
177     int32_t ret = AllConnectManager::GetInstance().ApplyAdvancedResource(dstDeviceId, resourceReq.get());
178     if (ret != E_OK) {
179         LOGE("ApplyAdvancedResource fail, ret is %{public}d", ret);
180         return ERR_APPLY_RESULT;
181     }
182 
183     int32_t socketId;
184     ret = SoftBusHandler::GetInstance().OpenSession(sessionName, sessionName, dstDeviceId, socketId);
185     if (ret != E_OK) {
186         LOGE("OpenSession failed, ret is %{public}d", ret);
187         return ret;
188     }
189     AllConnectManager::GetInstance().PublishServiceState(DfsConnectCode::COPY_FILE, dstDeviceId,
190                                                          ServiceCollaborationManagerBussinessStatus::SCM_CONNECTED);
191     LOGI("RequestSendFile OpenSession success");
192 
193     ret = SoftBusHandler::GetInstance().CopySendFile(socketId, dstDeviceId, srcUri, dstPath);
194     if (ret != E_OK) {
195         LOGE("CopySendFile failed, ret is %{public}d", ret);
196         SoftBusHandler::GetInstance().CloseSession(socketId, sessionName);
197         return ret;
198     }
199     return E_OK;
200 }
201 
ExecutePrepareSession(const AppExecFwk::InnerEvent::Pointer & event)202 void DaemonExecute::ExecutePrepareSession(const AppExecFwk::InnerEvent::Pointer &event)
203 {
204     if (event == nullptr) {
205         LOGI("eventhandler fail.");
206         return;
207     }
208     auto prepareSessionData = event->GetSharedObject<PrepareSessionData>();
209     if (prepareSessionData == nullptr) {
210         LOGE("prepareSessionData is nullptr.");
211         return;
212     }
213 
214     auto prepareSessionBlock  = prepareSessionData->prepareSessionBlock_;
215     if (prepareSessionBlock == nullptr) {
216         LOGE("prepareSessionBlock is nullptr.");
217         return;
218     }
219     std::string srcUri = prepareSessionData->srcUri_;
220     std::string physicalPath  = prepareSessionData->physicalPath_;
221     std::string sessionName  = prepareSessionData->sessionName_;
222     sptr<IDaemon> daemon  = prepareSessionData->daemon_;
223     HmdfsInfo &info = prepareSessionData->info_;
224 
225     prepareSessionBlock->SetValue(PrepareSessionInner(srcUri, physicalPath, sessionName, daemon, info));
226 }
227 
PrepareSessionInner(const std::string & srcUri,std::string & physicalPath,const std::string & sessionName,const sptr<IDaemon> & daemon,HmdfsInfo & info)228 int32_t DaemonExecute::PrepareSessionInner(const std::string &srcUri,
229                                            std::string &physicalPath,
230                                            const std::string &sessionName,
231                                            const sptr<IDaemon> &daemon,
232                                            HmdfsInfo &info)
233 {
234     LOGI("PrepareSessionInner begin.");
235     auto socketId = SoftBusHandler::GetInstance().CreateSessionServer(IDaemon::SERVICE_NAME, sessionName,
236                                                                       DFS_CHANNLE_ROLE_SINK, physicalPath);
237     if (socketId <= 0) {
238         LOGE("CreateSessionServer failed, socketId = %{public}d", socketId);
239         return E_SOFTBUS_SESSION_FAILED;
240     }
241     physicalPath.clear();
242     if (info.authority == FILE_MANAGER_AUTHORITY || info.authority == MEDIA_AUTHORITY) {
243         LOGI("authority is media or docs");
244         physicalPath = "??" + info.dstPhysicalPath;
245     }
246     auto ret = Daemon::Copy(srcUri, physicalPath, daemon, sessionName);
247     if (ret != E_OK) {
248         LOGE("Remote copy failed,ret = %{public}d", ret);
249         SoftBusHandler::GetInstance().CloseSession(socketId, sessionName);
250         return ret;
251     }
252     return ret;
253 }
254 
GetZipName(const std::string & relativePath)255 std::string DaemonExecute::GetZipName(const std::string &relativePath)
256 {
257     auto cppnow = std::chrono::system_clock::now();
258     auto cppnow_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(cppnow);
259     auto value = std::to_string(cppnow_ms.time_since_epoch().count());
260 
261     std::random_device rd;
262     std::string random = std::to_string(rd());
263     std::string zipName = value + "_" + random + ".zip";
264 
265     while (std::filesystem::exists(relativePath + zipName)) {
266         random = std::to_string(rd());
267         zipName = value + "_" + random + ".zip";
268     }
269     return zipName;
270 }
271 
GetFileList(const std::vector<std::string> & uris,int32_t userId,const std::string & srcBundleName)272 std::vector<std::string> DaemonExecute::GetFileList(const std::vector<std::string> &uris,
273                                                     int32_t userId,
274                                                     const std::string &srcBundleName)
275 {
276     std::vector<std::string> fileList;
277     for (const auto &uri : uris) {
278         size_t pos = uri.find(srcBundleName);
279         if (pos == std::string::npos) {
280             LOGE("srcBundleName not find in uri.");
281             return {};
282         }
283 
284         std::string physicalPath;
285         int32_t ret = SandboxHelper::GetPhysicalPath(uri, std::to_string(userId), physicalPath);
286         if (ret != E_OK) {
287             LOGE("invalid uri, ret = %{public}d", ret);
288             return {};
289         }
290         if (!SandboxHelper::CheckValidPath(physicalPath)) {
291             LOGE("invalid path");
292             return {};
293         }
294         if (OHOS::Storage::DistributedFile::Utils::IsFolder(physicalPath)) {
295             LOGE("uri is folder are not supported now.");
296             return {};
297         }
298 
299         fileList.emplace_back(physicalPath);
300     }
301     LOGI("GetFileList success, file num is %{public}s", std::to_string(fileList.size()).c_str());
302     return fileList;
303 }
304 
HandleZip(const std::vector<std::string> & fileList,const sptr<AssetObj> & assetObj,std::string & sendFileName,bool & isSingleFile)305 int32_t DaemonExecute::HandleZip(const std::vector<std::string> &fileList,
306                                  const sptr<AssetObj> &assetObj,
307                                  std::string &sendFileName,
308                                  bool &isSingleFile)
309 {
310     if (fileList.size() > 1) {
311         size_t pos = fileList[0].find(assetObj->srcBundleName_);
312         if (pos == std::string::npos) {
313             LOGE("srcBundleName not find in uri.");
314             return E_ZIP;
315         }
316         std::string relativePath = fileList[0].substr(0, pos + assetObj->srcBundleName_.length()) + "/";
317         sendFileName = relativePath + GetZipName(relativePath);
318         int32_t ret = SoftBusHandlerAsset::GetInstance().CompressFile(fileList, relativePath, sendFileName);
319         if (ret != E_OK) {
320             LOGE("zip ffiles fail.");
321             return E_ZIP;
322         }
323         isSingleFile = false;
324         SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, sendFileName, false);
325         return E_OK;
326     } else {
327         sendFileName = fileList[0];
328         isSingleFile = true;
329         SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, sendFileName, true);
330         return E_OK;
331     }
332 }
333 
HandlePushAssetFail(int32_t socketId,const sptr<AssetObj> & assetObj)334 void DaemonExecute::HandlePushAssetFail(int32_t socketId, const sptr<AssetObj> &assetObj)
335 {
336     auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
337     AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
338     SoftBusHandlerAsset::GetInstance().closeAssetBind(socketId);
339     AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
340     SoftBusAssetSendListener::RemoveFileMap(taskId);
341 }
342 } // namespace DistributedFile
343 } // namespace Storage
344 } // namespace OHOS
345