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 "softbus_adapter.h"
17
18 #include <cinttypes>
19 #include <cstddef>
20 #include <mutex>
21
22 #include "dfs_error.h"
23 #include "utils_log.h"
24
25
26 namespace OHOS::FileManagement::CloudSync {
27 using namespace std;
28 constexpr int MIN_BW = 1024 * 1024 * 40;
29 constexpr int MAX_WAIT_TIMEOUT = 10000;
30 constexpr int MIN_LATENCY = 1000;
31 const string SERVICE_NAME = "OHOS.Filemanagement.Dfs.ICloudSyncService";
32 const std::string HMDFS_PERV_PATH = "/mnt/hmdfs/";
33 const std::string DATA_DIR_PATH = "/account/device_view/local/data/";
GetInstance()34 SoftbusAdapter &SoftbusAdapter::GetInstance()
35 {
36 static SoftbusAdapter instance;
37 return instance;
38 }
39
CreateSessionServer(const char * packageName,const char * sessionName)40 int32_t SoftbusAdapter::CreateSessionServer(const char *packageName, const char *sessionName)
41 {
42 SocketInfo info = {
43 .name = const_cast<char*>(sessionName),
44 .pkgName = const_cast<char*>(packageName),
45 };
46 int socket = ::Socket(info);
47 if (socket <= 0) {
48 LOGE("Failed to CreateSessionServer ret:%{public}d, sessionName:%{public}s", socket, sessionName);
49 return ERR_BAD_VALUE;
50 }
51 std::string saveKey = std::string(sessionName) + std::string(packageName);
52 {
53 lock_guard<mutex> lock(sessionMutex_);
54 auto sessionAndPackage = sessionAndPackageMap_.find(socket);
55 if (sessionAndPackage == sessionAndPackageMap_.end()) {
56 sessionAndPackageMap_.insert({socket, saveKey});
57 }
58 }
59 QosTV serverQos[] = {
60 { .qos = QOS_TYPE_MIN_BW, .value = MIN_BW},
61 { .qos = QOS_TYPE_MAX_WAIT_TIMEOUT, .value = MAX_WAIT_TIMEOUT },
62 { .qos = QOS_TYPE_MIN_LATENCY, .value = MIN_LATENCY},
63 };
64
65 ISocketListener listener = {
66 .OnBind = SoftbusAdapter::OnBind,
67 .OnShutdown = SoftbusAdapter::OnShutdown,
68 .OnBytes = SoftbusAdapter::OnBytes,
69 .OnMessage = nullptr,
70 .OnStream = nullptr,
71 .OnFile = SoftbusAdapter::OnFile,
72 };
73
74 int32_t ret = ::Listen(socket, serverQos, QOS_COUNT, &listener);
75 if (ret != 0) {
76 LOGE("Failed to CreateSessionServer sessionName:%{public}s", sessionName);
77 return ret;
78 }
79 LOGD("Succeed to CreateSessionServer, sessionName:%{public}s", sessionName);
80 return E_OK;
81 }
82
RemoveSessionServer(const char * packageName,const char * sessionName)83 int32_t SoftbusAdapter::RemoveSessionServer(const char *packageName, const char *sessionName)
84 {
85 std::string val = std::string(sessionName) + std::string(packageName);
86 int32_t socket = SoftbusAdapter::GetInstance().GetSocketNameFromMap(val);
87 string existSessionName = SoftbusAdapter::GetInstance().GetSessionNameFromMap(socket);
88 if (strcmp(existSessionName.c_str(), sessionName) != 0) {
89 LOGE("Failed to RemoveSessionServer sessionName:%{public}s", sessionName);
90 return ERR_BAD_VALUE;
91 }
92 SoftbusAdapter::GetInstance().RemoveSesion(socket);
93 ::Shutdown(socket);
94 LOGD("Succeed to RemoveSessionServer, sessionName:%{public}s", sessionName);
95 return E_OK;
96 }
97
OnBind(int socket,PeerSocketInfo info)98 void SoftbusAdapter::OnBind(int socket, PeerSocketInfo info)
99 {
100 string sessionName = info.name;
101 string networkId = info.networkId;
102 if (sessionName.empty()) {
103 LOGE("get session name failed");
104 return;
105 }
106
107 auto listener = SoftbusAdapter::GetInstance().GetListener(sessionName);
108 if (!listener) {
109 LOGD("UnRegisterListener for session %{public}d", socket);
110 return;
111 }
112
113 listener->OnSessionOpened(socket, 0);
114 SoftbusAdapter::GetInstance().AcceptSesion(socket, sessionName, networkId);
115 }
116
OnShutdown(int32_t socket,ShutdownReason reason)117 void SoftbusAdapter::OnShutdown(int32_t socket, ShutdownReason reason)
118 {
119 LOGD("Session OnShutdown, sessionId:%{public}d, reason:%{public}d", socket, reason);
120 string sessionName = SoftbusAdapter::GetInstance().GetSessionNameFromMap(socket);
121 if (sessionName.empty()) {
122 LOGE("get session name failed");
123 return;
124 }
125
126 auto listener = SoftbusAdapter::GetInstance().GetListener(sessionName);
127 if (!listener) {
128 LOGD("UnRegisterListener for session %{public}d", socket);
129 return;
130 }
131
132 listener->OnSessionClosed(socket);
133 SoftbusAdapter::GetInstance().RemoveSesion(socket);
134 }
135
OnBytes(int socket,const void * data,unsigned int dataLen)136 void SoftbusAdapter::OnBytes(int socket, const void *data, unsigned int dataLen)
137 {
138 LOGD("OnBytes invoked, dataLen:%{public}d", dataLen);
139 string sessionName = SoftbusAdapter::GetInstance().GetSessionNameFromMap(socket);
140 if (sessionName.empty()) {
141 LOGE("get session name failed");
142 return;
143 }
144
145 string peerDeviceId = SoftbusAdapter::GetInstance().GetPeerNetworkId(socket);
146 if (peerDeviceId.empty()) {
147 LOGE("get peerDeviceId name failed");
148 return;
149 }
150
151 auto listener = SoftbusAdapter::GetInstance().GetListener(sessionName);
152 if (!listener) {
153 LOGD("UnRegisterListener for session %{public}d", socket);
154 return;
155 }
156
157 listener->OnDataReceived(peerDeviceId, socket, data, dataLen);
158 }
159
OnReceiveFileProcess(int sessionId,const char * firstFile,uint64_t bytesUpload,uint64_t bytesTotal)160 int SoftbusAdapter::OnReceiveFileProcess(int sessionId,
161 const char *firstFile,
162 uint64_t bytesUpload,
163 uint64_t bytesTotal)
164 {
165 LOGD(
166 "File receive process sessionId = %{public}d, first file:%{public}s, bytesUpload:%{public}" PRIu64 ", "
167 "bytesTotal:%{public}" PRIu64 "",
168 sessionId, GetAnonyString(firstFile).c_str(), bytesUpload, bytesTotal);
169 return E_OK;
170 }
171
OnReceiveFileFinished(int sessionId,const char * files,int fileCnt)172 void SoftbusAdapter::OnReceiveFileFinished(int sessionId, const char *files, int fileCnt)
173 {
174 LOGD("OnReceiveFileFinished invoked, files:%{public}s, fileCnt:%{public}d", files, fileCnt);
175 string sessionName = SoftbusAdapter::GetInstance().GetSessionNameFromMap(sessionId);
176 if (sessionName.empty()) {
177 LOGE("get session name failed");
178 return;
179 }
180
181 string peerNetworkId = SoftbusAdapter::GetInstance().GetPeerNetworkId(sessionId);
182 if (peerNetworkId.empty()) {
183 LOGE("get peerDeviceId name failed");
184 return;
185 }
186
187 auto listener = SoftbusAdapter::GetInstance().GetListener(sessionName);
188 if (!listener) {
189 LOGD("UnRegisterListener for session %{public}d", sessionId);
190 return;
191 }
192
193 listener->OnFileReceived(peerNetworkId, files, E_OK);
194 }
195
GetRecvPath()196 const char* SoftbusAdapter::GetRecvPath()
197 {
198 const char *path = pathDir_.c_str();
199 return path;
200 }
201
OnFile(int32_t socket,FileEvent * event)202 void SoftbusAdapter::OnFile(int32_t socket, FileEvent *event)
203 {
204 if (event->type == FILE_EVENT_RECV_UPDATE_PATH) {
205 event->UpdateRecvPath = GetRecvPath;
206 }
207 }
208
OpenSession(char * sessionName,char * peerDeviceId,char * groupId,TransDataType dataType)209 int SoftbusAdapter::OpenSession(char *sessionName,
210 char *peerDeviceId,
211 char *groupId,
212 TransDataType dataType)
213 {
214 SocketInfo info = {
215 .name = sessionName,
216 .peerName = sessionName,
217 .peerNetworkId = peerDeviceId,
218 .pkgName = const_cast<char*>(SERVICE_NAME.c_str()),
219 .dataType = dataType,
220 };
221 int32_t socket = Socket(info);
222 if (socket <= 0) {
223 return ERR_BAD_VALUE;
224 }
225 std::string saveKey = std::string(sessionName) + std::string(SERVICE_NAME);
226 {
227 lock_guard<mutex> lock(sessionMutex_);
228 auto sessionAndPackage = sessionAndPackageMap_.find(socket);
229 if (sessionAndPackage == sessionAndPackageMap_.end()) {
230 sessionAndPackageMap_.insert({socket, saveKey});
231 }
232 }
233 QosTV clientQos[] = {
234 { .qos = QOS_TYPE_MIN_BW, .value = MIN_BW},
235 { .qos = QOS_TYPE_MAX_WAIT_TIMEOUT, .value = MAX_WAIT_TIMEOUT },
236 { .qos = QOS_TYPE_MIN_LATENCY, .value = MIN_LATENCY},
237 };
238
239 ISocketListener listener = {
240 .OnBind = SoftbusAdapter::OnBind,
241 .OnShutdown = SoftbusAdapter::OnShutdown,
242 .OnBytes = SoftbusAdapter::OnBytes,
243 .OnFile = SoftbusAdapter::OnFile,
244 };
245 SoftbusAdapter::GetInstance().AcceptSesion(socket, sessionName, peerDeviceId);
246 int32_t ret = ::Bind(socket, clientQos, QOS_COUNT, &listener);
247 if (ret != 0) {
248 ::Shutdown(socket);
249 }
250 return socket;
251 }
252
OpenSessionByP2P(char * sessionName,char * peerDeviceId,char * groupId,bool isFileType)253 int SoftbusAdapter::OpenSessionByP2P(char *sessionName,
254 char *peerDeviceId,
255 char *groupId,
256 bool isFileType)
257 {
258 TransDataType dataType;
259 if (isFileType) {
260 dataType = DATA_TYPE_FILE;
261 } else {
262 dataType = DATA_TYPE_BYTES;
263 }
264 return OpenSession(sessionName, peerDeviceId, groupId, dataType);
265 }
266
CloseSession(int sessionId)267 void SoftbusAdapter::CloseSession(int sessionId)
268 {
269 ::CloseSession(sessionId);
270 }
271
SendBytes(int sessionId,const void * data,unsigned int dataLen)272 int SoftbusAdapter::SendBytes(int sessionId, const void *data, unsigned int dataLen)
273 {
274 return ::SendBytes(sessionId, data, dataLen);
275 }
276
SendFile(int sessionId,const std::vector<std::string> & sFileList,const std::vector<std::string> & dFileList)277 int SoftbusAdapter::SendFile(int sessionId,
278 const std::vector<std::string> &sFileList,
279 const std::vector<std::string> &dFileList)
280 {
281 vector<const char *> sourceFileList;
282 vector<const char *> destFileList;
283
284 for (const string &file : sFileList) {
285 sourceFileList.push_back(file.data());
286 }
287
288 for (const string &file : dFileList) {
289 destFileList.push_back(file.data());
290 }
291
292 return ::SendFile(sessionId, sourceFileList.data(), destFileList.data(), sourceFileList.size());
293 }
294
295 /* should use this interface when session closed */
GetSessionNameFromMap(int sessionId)296 std::string SoftbusAdapter::GetSessionNameFromMap(int sessionId)
297 {
298 lock_guard<mutex> lock(sessionMutex_);
299 auto iter = sessionNameMap_.find(sessionId);
300 if (iter != sessionNameMap_.end()) {
301 return iter->second;
302 }
303 return "";
304 }
305
GetSocketNameFromMap(std::string sessionAndPack)306 int32_t SoftbusAdapter::GetSocketNameFromMap(std::string sessionAndPack)
307 {
308 lock_guard<mutex> lock(sessionMutex_);
309 int32_t socket = -1;
310 for (const auto& pair : sessionAndPackageMap_) {
311 if (pair.second == sessionAndPack) {
312 socket = pair.first;
313 break;
314 }
315 }
316 return socket;
317 }
318
GetPeerNetworkId(int sessionId)319 std::string SoftbusAdapter::GetPeerNetworkId(int sessionId)
320 {
321 lock_guard<mutex> lock(sessionMutex_);
322 auto iter = networkIdMap_.find(sessionId);
323 if (iter != networkIdMap_.end()) {
324 return iter->second;
325 }
326 return "";
327 }
328
RegisterSessionListener(std::string sessionName,std::shared_ptr<ISoftbusListener> listener)329 void SoftbusAdapter::RegisterSessionListener(std::string sessionName, std::shared_ptr<ISoftbusListener> listener)
330 {
331 std::unique_lock<shared_mutex> lock(listenerMutex_);
332 listeners_[sessionName] = listener;
333 }
334
UnRegisterSessionListener(std::string sessionName)335 void SoftbusAdapter::UnRegisterSessionListener(std::string sessionName)
336 {
337 std::unique_lock<shared_mutex> lock(listenerMutex_);
338 listeners_.erase(sessionName);
339 }
340
GetListener(std::string sessionName)341 std::shared_ptr<ISoftbusListener> SoftbusAdapter::GetListener(std::string sessionName)
342 {
343 shared_lock<shared_mutex> lock(listenerMutex_);
344 if (listeners_.count(sessionName) == 0) {
345 return nullptr;
346 }
347 return listeners_[sessionName];
348 }
349
IsSessionOpened(int sessionId)350 bool SoftbusAdapter::IsSessionOpened(int sessionId)
351 {
352 lock_guard<mutex> lock(sessionMutex_);
353 auto iter = sessionOpenedMap_.find(sessionId);
354 if (iter == sessionOpenedMap_.end()) {
355 return false;
356 }
357 return iter->second;
358 }
359
AcceptSesion(int sessionId,const std::string & sessionName,const std::string & networkId)360 void SoftbusAdapter::AcceptSesion(int sessionId, const std::string &sessionName, const std::string &networkId)
361 {
362 lock_guard<mutex> lock(sessionMutex_);
363 auto iter = sessionOpenedMap_.find(sessionId);
364 if (iter == sessionOpenedMap_.end()) {
365 sessionOpenedMap_.insert({sessionId, true});
366 }
367
368 auto sessionNameMap = sessionNameMap_.find(sessionId);
369 if (sessionNameMap == sessionNameMap_.end()) {
370 sessionNameMap_.insert({sessionId, sessionName});
371 }
372
373 auto networkIdMap = networkIdMap_.find(sessionId);
374 if (networkIdMap == networkIdMap_.end()) {
375 networkIdMap_.insert({sessionId, networkId});
376 }
377 }
378
RemoveSesion(int sessionId)379 void SoftbusAdapter::RemoveSesion(int sessionId)
380 {
381 lock_guard<mutex> lock(sessionMutex_);
382 auto iter = sessionOpenedMap_.find(sessionId);
383 if (iter != sessionOpenedMap_.end()) {
384 sessionOpenedMap_.erase(iter);
385 }
386
387 auto sessionNameMap = sessionNameMap_.find(sessionId);
388 if (sessionNameMap != sessionNameMap_.end()) {
389 sessionNameMap_.erase(sessionNameMap);
390 }
391
392 auto networkIdMap = networkIdMap_.find(sessionId);
393 if (networkIdMap != networkIdMap_.end()) {
394 networkIdMap_.erase(networkIdMap);
395 }
396 }
397
UpdateFileRecvPath(const std::string & bundleName,int32_t userId)398 void SoftbusAdapter::UpdateFileRecvPath(const std::string &bundleName, int32_t userId)
399 {
400 pathDir_ = HMDFS_PERV_PATH + std::to_string(userId) + DATA_DIR_PATH + bundleName;
401 LOGI("recv path: %{public}s", GetAnonyString(pathDir_).c_str());
402 }
403 } // namespace OHOS::FileManagement::CloudSync