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