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 "dfs_error.h"
27 #include "network/softbus/softbus_asset_send_listener.h"
28 #include "network/softbus/softbus_handler_asset.h"
29 #include "network/softbus/softbus_session_pool.h"
30 #include "refbase.h"
31 #include "sandbox_helper.h"
32 #include "utils_directory.h"
33 #include "utils_log.h"
34
35 #include "all_connect/all_connect_manager.h"
36 #include "network/softbus/softbus_handler.h"
37
38 namespace OHOS {
39 namespace Storage {
40 namespace DistributedFile {
41 using namespace OHOS::AppFileService;
42 using namespace OHOS::FileManagement;
DaemonExecute()43 DaemonExecute::DaemonExecute()
44 {
45 LOGI("DaemonExecute begin.");
46 executeFuncMap_[DEAMON_EXECUTE_PUSH_ASSET] = &DaemonExecute::ExecutePushAsset;
47 executeFuncMap_[DEAMON_EXECUTE_REQUEST_SEND_FILE] = &DaemonExecute::ExecuteRequestSendFile;
48 }
49
ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)50 void DaemonExecute::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
51 {
52 if (event == nullptr) {
53 LOGE("event is nullptr.");
54 return;
55 }
56 std::lock_guard<std::mutex> lock(executeFuncMapMutex_);
57 auto itFunc = executeFuncMap_.find(event->GetInnerEventId());
58 if (itFunc == executeFuncMap_.end()) {
59 LOGE("not find execute func.");
60 return;
61 }
62
63 auto executeFunc = itFunc->second;
64 (this->*executeFunc)(event);
65 }
66
ExecutePushAsset(const AppExecFwk::InnerEvent::Pointer &event)67 void DaemonExecute::ExecutePushAsset(const AppExecFwk::InnerEvent::Pointer &event)
68 {
69 if (event == nullptr) {
70 LOGI("eventhandler fail.");
71 return;
72 }
73 auto pushData = event->GetSharedObject<PushAssetData>();
74 if (pushData == nullptr) {
75 LOGE("pushData is nullptr.");
76 return;
77 }
78 int32_t userId = pushData->userId_;
79 auto assetObj = pushData->assetObj_;
80 if (assetObj == nullptr) {
81 LOGE("assetObj is nullptr.");
82 return;
83 }
84 int32_t socketId;
85 auto ret = SoftBusHandlerAsset::GetInstance().AssetBind(assetObj->dstNetworkId_, socketId);
86 if (ret != E_OK) {
87 LOGE("ExecutePushAsset AssetBind failed, ret %{public}d", ret);
88 auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
89 AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
90 AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
91 return;
92 }
93 SoftBusHandlerAsset::GetInstance().AddAssetObj(socketId, assetObj);
94
95 auto fileList = GetFileList(assetObj->uris_, userId, assetObj->srcBundleName_);
96 if (fileList.empty()) {
97 LOGE("get fileList is empty.");
98 HandlePushAssetFail(socketId, assetObj);
99 return;
100 }
101
102 std::string sendFileName;
103 bool isSingleFile;
104 ret = HandleZip(fileList, assetObj, sendFileName, isSingleFile);
105 if (ret != E_OK) {
106 LOGE("zip files fail. socketId is %{public}d", socketId);
107 HandlePushAssetFail(socketId, assetObj);
108 SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
109 return;
110 }
111
112 ret = SoftBusHandlerAsset::GetInstance().AssetSendFile(socketId, sendFileName, isSingleFile);
113 if (ret != E_OK) {
114 LOGE("ExecutePushAsset send file fail, ret %{public}d", ret);
115 HandlePushAssetFail(socketId, assetObj);
116 SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
117 return;
118 }
119 }
120
ExecuteRequestSendFile(const AppExecFwk::InnerEvent::Pointer &event)121 void DaemonExecute::ExecuteRequestSendFile(const AppExecFwk::InnerEvent::Pointer &event)
122 {
123 if (event == nullptr) {
124 LOGI("eventhandler fail.");
125 return;
126 }
127 auto requestSendFileData = event->GetSharedObject<RequestSendFileData>();
128 if (requestSendFileData == nullptr) {
129 LOGE("requestSendFileData is nullptr.");
130 return;
131 }
132
133 auto requestSendFileBlock = requestSendFileData->requestSendFileBlock_;
134 if (requestSendFileBlock == nullptr) {
135 LOGE("requestSendFileBlock is nullptr.");
136 return;
137 }
138 std::string srcUri = requestSendFileData->srcUri_;
139 std::string dstPath = requestSendFileData->dstPath_;
140 std::string dstDeviceId = requestSendFileData->dstDeviceId_;
141 std::string sessionName = requestSendFileData->sessionName_;
142 if (srcUri.empty() || dstDeviceId.empty() || sessionName.empty()) {
143 LOGE("params empty. %{public}s, %{public}s", sessionName.c_str(), Utils::GetAnonyString(dstDeviceId).c_str());
144 requestSendFileBlock->SetValue(ERR_BAD_VALUE);
145 return;
146 }
147
148 requestSendFileBlock->SetValue(RequestSendFileInner(srcUri, dstPath, dstDeviceId, sessionName));
149 }
150
RequestSendFileInner(const std::string &srcUri, const std::string &dstPath, const std::string &dstDeviceId, const std::string &sessionName)151 int32_t DaemonExecute::RequestSendFileInner(const std::string &srcUri,
152 const std::string &dstPath,
153 const std::string &dstDeviceId,
154 const std::string &sessionName)
155 {
156 LOGI("RequestSendFile begin dstDeviceId: %{public}s", Utils::GetAnonyString(dstDeviceId).c_str());
157 auto resourceReq = AllConnectManager::GetInstance().BuildResourceRequest();
158 int32_t ret = AllConnectManager::GetInstance().ApplyAdvancedResource(dstDeviceId, resourceReq.get());
159 if (ret != E_OK) {
160 LOGE("ApplyAdvancedResource fail, ret is %{public}d", ret);
161 return ERR_APPLY_RESULT;
162 }
163
164 int32_t socketId;
165 ret = SoftBusHandler::GetInstance().OpenSession(sessionName, sessionName, dstDeviceId, socketId);
166 if (ret != E_OK) {
167 LOGE("OpenSession failed, ret is %{public}d", ret);
168 return ret;
169 }
170 AllConnectManager::GetInstance().PublishServiceState(dstDeviceId,
171 ServiceCollaborationManagerBussinessStatus::SCM_CONNECTED);
172 LOGI("RequestSendFile OpenSession success");
173
174 ret = SoftBusHandler::GetInstance().CopySendFile(socketId, sessionName, srcUri, dstPath);
175 if (ret != E_OK) {
176 LOGE("CopySendFile failed, ret is %{public}d", ret);
177 SoftBusHandler::GetInstance().CloseSession(socketId, sessionName);
178 return ret;
179 }
180 return E_OK;
181 }
182
GetZipName(const std::string &relativePath)183 std::string DaemonExecute::GetZipName(const std::string &relativePath)
184 {
185 auto cppnow = std::chrono::system_clock::now();
186 auto cppnow_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(cppnow);
187 auto value = std::to_string(cppnow_ms.time_since_epoch().count());
188
189 std::random_device rd;
190 std::string random = std::to_string(rd());
191 std::string zipName = value + "_" + random + ".zip";
192
193 while (std::filesystem::exists(relativePath + zipName)) {
194 random = std::to_string(rd());
195 zipName = value + "_" + random + ".zip";
196 }
197 LOGI("zipName is %{public}s", zipName.c_str());
198 return zipName;
199 }
200
GetFileList(const std::vector<std::string> &uris, int32_t userId, const std::string &srcBundleName)201 std::vector<std::string> DaemonExecute::GetFileList(const std::vector<std::string> &uris,
202 int32_t userId,
203 const std::string &srcBundleName)
204 {
205 std::vector<std::string> fileList;
206 std::regex pattern("/mnt/hmdfs/\\d{3,}/account/device_view/local/data/.*");
207 for (const auto &uri : uris) {
208 size_t pos = uri.find(srcBundleName);
209 if (pos == std::string::npos) {
210 LOGE("srcBundleName not find in uri.");
211 return {};
212 }
213
214 std::string physicalPath;
215 int32_t ret = SandboxHelper::GetPhysicalPath(uri, std::to_string(userId), physicalPath);
216 if (ret != E_OK) {
217 LOGE("invalid uri, ret = %{public}d", ret);
218 return {};
219 }
220 if (!SandboxHelper::CheckValidPath(physicalPath)) {
221 LOGE("invalid path : %{public}s", GetAnonyString(physicalPath).c_str());
222 return {};
223 }
224 if (OHOS::Storage::DistributedFile::Utils::IsFolder(physicalPath)) {
225 LOGE("uri is folder are not supported now.");
226 return {};
227 }
228 if (!std::regex_match(physicalPath, pattern)) {
229 LOGE("physicalPath is not hmdfs path.");
230 }
231 fileList.emplace_back(physicalPath);
232 }
233 LOGI("GetFileList success, file num is %{public}s", std::to_string(fileList.size()).c_str());
234 return fileList;
235 }
236
HandleZip(const std::vector<std::string> &fileList, const sptr<AssetObj> &assetObj, std::string &sendFileName, bool &isSingleFile)237 int32_t DaemonExecute::HandleZip(const std::vector<std::string> &fileList,
238 const sptr<AssetObj> &assetObj,
239 std::string &sendFileName,
240 bool &isSingleFile)
241 {
242 if (fileList.size() > 1) {
243 size_t pos = fileList[0].find(assetObj->srcBundleName_);
244 if (pos == std::string::npos) {
245 LOGE("srcBundleName not find in uri.");
246 return E_ZIP;
247 }
248 std::string relativePath = fileList[0].substr(0, pos + assetObj->srcBundleName_.length()) + "/";
249 sendFileName = relativePath + GetZipName(relativePath);
250 int32_t ret = SoftBusHandlerAsset::GetInstance().CompressFile(fileList, relativePath, sendFileName);
251 if (ret != E_OK) {
252 LOGE("zip ffiles fail.");
253 return E_ZIP;
254 }
255 isSingleFile = false;
256 SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, false);
257 return E_OK;
258 } else {
259 sendFileName = fileList[0];
260 isSingleFile = true;
261 SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, true);
262 return E_OK;
263 }
264 }
265
HandlePushAssetFail(int32_t socketId, const sptr<AssetObj> &assetObj)266 void DaemonExecute::HandlePushAssetFail(int32_t socketId, const sptr<AssetObj> &assetObj)
267 {
268 auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
269 AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
270 SoftBusHandlerAsset::GetInstance().closeAssetBind(socketId);
271 AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
272 SoftBusAssetSendListener::RemoveFileMap(taskId);
273 }
274 } // namespace DistributedFile
275 } // namespace Storage
276 } // namespace OHOS
277