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