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 38namespace OHOS { 39namespace Storage { 40namespace DistributedFile { 41using namespace OHOS::AppFileService; 42using namespace OHOS::FileManagement; 43DaemonExecute::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 50void 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 67void 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 121void 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 151int32_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 183std::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 201std::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 237int32_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 266void 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