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