1 /*
2  * Copyright (c) 2022-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 "softbus_adapter.h"
17 
18 #include <securec.h>
19 #include <unistd.h>
20 
21 #include "softbus_bus_center.h"
22 #include "softbus_common.h"
23 
24 #include "dscreen_errcode.h"
25 #include "dscreen_hisysevent.h"
26 #include "dscreen_util.h"
27 
28 namespace OHOS {
29 namespace DistributedHardware {
30 IMPLEMENT_SINGLE_INSTANCE(SoftbusAdapter);
ScreenOnSoftbusSessionOpened(int32_t sessionId,PeerSocketInfo info)31 static void ScreenOnSoftbusSessionOpened(int32_t sessionId, PeerSocketInfo info)
32 {
33     SoftbusAdapter::GetInstance().OnSoftbusSessionOpened(sessionId, info);
34 }
35 
ScreenOnSoftbusSessionClosed(int32_t sessionId,ShutdownReason reason)36 static void ScreenOnSoftbusSessionClosed(int32_t sessionId, ShutdownReason reason)
37 {
38     SoftbusAdapter::GetInstance().OnSoftbusSessionClosed(sessionId, reason);
39 }
40 
ScreenOnBytesReceived(int32_t sessionId,const void * data,uint32_t dataLen)41 static void ScreenOnBytesReceived(int32_t sessionId, const void *data, uint32_t dataLen)
42 {
43     SoftbusAdapter::GetInstance().OnBytesReceived(sessionId, data, dataLen);
44 }
45 
ScreenOnStreamReceived(int32_t sessionId,const StreamData * data,const StreamData * ext,const StreamFrameInfo * frameInfo)46 static void ScreenOnStreamReceived(int32_t sessionId, const StreamData *data, const StreamData *ext,
47     const StreamFrameInfo *frameInfo)
48 {
49     SoftbusAdapter::GetInstance().OnStreamReceived(sessionId, data, ext, frameInfo);
50 }
51 
ScreenOnMessageReceived(int sessionId,const void * data,unsigned int dataLen)52 static void ScreenOnMessageReceived(int sessionId, const void *data, unsigned int dataLen)
53 {
54     SoftbusAdapter::GetInstance().OnMessageReceived(sessionId, data, dataLen);
55 }
56 
SoftbusAdapter()57 SoftbusAdapter::SoftbusAdapter()
58 {
59     DHLOGI("SoftbusAdapter");
60     sessListener_.OnBind = ScreenOnSoftbusSessionOpened;
61     sessListener_.OnShutdown = ScreenOnSoftbusSessionClosed;
62     sessListener_.OnBytes = ScreenOnBytesReceived;
63     sessListener_.OnStream = ScreenOnStreamReceived;
64     sessListener_.OnMessage = ScreenOnMessageReceived;
65     sessListener_.OnFile = nullptr;
66     sessListener_.OnQos = nullptr;
67     sessListener_.OnError = nullptr;
68     sessListener_.OnNegotiate = nullptr;
69 }
70 
~SoftbusAdapter()71 SoftbusAdapter::~SoftbusAdapter()
72 {
73     DHLOGI("~SoftbusAdapter");
74 }
75 
RegisterSoftbusListener(const std::shared_ptr<ISoftbusListener> & listener,const std::string & sessionName,const std::string & peerDevId)76 int32_t SoftbusAdapter::RegisterSoftbusListener(const std::shared_ptr<ISoftbusListener> &listener,
77     const std::string &sessionName, const std::string &peerDevId)
78 {
79     if (listener == nullptr) {
80         DHLOGE("%{public}s: listener is nullptr.", DSCREEN_LOG_TAG);
81         return ERR_DH_SCREEN_ADAPTER_REGISTER_SOFTBUS_LISTENER_FAIL;
82     }
83     DHLOGI("%{public}s: RegisterListener sess:%{public}s id:%{public}s.", DSCREEN_LOG_TAG, sessionName.c_str(),
84         GetAnonyString(peerDevId).c_str());
85     std::string strListenerKey = sessionName + "_" + peerDevId;
86     std::lock_guard<std::mutex> lisLock(listenerMtx_);
87     if (mapListeners_.find(strListenerKey) != mapListeners_.end()) {
88         DHLOGE("%{public}s: Session listener already register.", DSCREEN_LOG_TAG);
89         return ERR_DH_SCREEN_ADAPTER_REGISTER_SOFTBUS_LISTENER_FAIL;
90     }
91     mapListeners_.insert(std::make_pair(strListenerKey, listener));
92 
93     return DH_SUCCESS;
94 }
95 
UnRegisterSoftbusListener(const std::string & sessionName,const std::string & peerDevId)96 int32_t SoftbusAdapter::UnRegisterSoftbusListener(const std::string &sessionName, const std::string &peerDevId)
97 {
98     DHLOGI("%{public}s: UnRegisterListener sess:%{public}s id:%{public}s.", DSCREEN_LOG_TAG, sessionName.c_str(),
99         GetAnonyString(peerDevId).c_str());
100     std::string strListenerKey = sessionName + "_" + peerDevId;
101 
102     std::lock_guard<std::mutex> lisLock(listenerMtx_);
103     mapListeners_.erase(strListenerKey);
104 
105     return DH_SUCCESS;
106 }
107 
CreateSoftbusSessionServer(const std::string & pkgname,const std::string & sessionName,const std::string & peerDevId)108 int32_t SoftbusAdapter::CreateSoftbusSessionServer(const std::string &pkgname, const std::string &sessionName,
109     const std::string &peerDevId)
110 {
111     DHLOGI("%{public}s: CreateSessionServer sess:%{public}s id:%{public}s.", DSCREEN_LOG_TAG, sessionName.c_str(),
112         GetAnonyString(peerDevId).c_str());
113     {
114         std::lock_guard<std::mutex> lock(serverIdMapMutex_);
115         std::string idMapValue = sessionName + "_" + peerDevId;
116         for (auto it = serverIdMap_.begin(); it != serverIdMap_.end(); it++) {
117             if (((it->second).find(idMapValue) != std::string::npos)) {
118                 DHLOGI("%{public}s: Session already create.", sessionName.c_str());
119                 return DH_SUCCESS;
120             }
121         }
122     }
123 
124     SocketInfo serverInfo = {
125         .name = const_cast<char*>(sessionName.c_str()),
126         .pkgName = const_cast<char*>(pkgname.c_str()),
127         .dataType = DATA_TYPE_VIDEO_STREAM,
128     };
129     int32_t socketId = Socket(serverInfo);
130     if (socketId < 0) {
131         DHLOGE("Create Socket fail socketId:%{public}" PRId32, socketId);
132         return ERR_DH_SCREEN_ADAPTER_BAD_VALUE;
133     }
134     QosTV qos[] = {
135         {.qos = QOS_TYPE_MIN_BW,        .value = 40 * 1024 * 1024},
136         {.qos = QOS_TYPE_MAX_LATENCY,        .value = 8000},
137         {.qos = QOS_TYPE_MIN_LATENCY,        .value = 2000},
138     };
139 
140     int32_t ret = Listen(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessListener_);
141     if (ret != DH_SUCCESS) {
142         DHLOGE("Listen socket error for sessionName:%{public}s", sessionName.c_str());
143         return ERR_DH_SCREEN_ADAPTER_BAD_VALUE;
144     }
145     {
146         std::lock_guard<std::mutex> lock(serverIdMapMutex_);
147         serverIdMap_.insert(std::make_pair(socketId, sessionName + "_" + peerDevId));
148     }
149     DHLOGI("%{public}s: CreateSessionServer success sessionId. %{public}" PRId32, DSCREEN_LOG_TAG, socketId);
150     return DH_SUCCESS;
151 }
152 
RemoveSoftbusSessionServer(const std::string & pkgname,const std::string & sessionName,const std::string & peerDevId)153 int32_t SoftbusAdapter::RemoveSoftbusSessionServer(const std::string &pkgname, const std::string &sessionName,
154     const std::string &peerDevId)
155 {
156     (void)pkgname;
157     if (sessionName.empty() || peerDevId.empty()) {
158         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
159     }
160     DHLOGI("%{public}s: RemoveSessionServer sess:%{public}s id:%{public}s", DSCREEN_LOG_TAG, sessionName.c_str(),
161         GetAnonyString(peerDevId).c_str());
162     int32_t serverSocketId = INVALID_SESSION_ID;
163     {
164         std::lock_guard<std::mutex> lock(serverIdMapMutex_);
165         std::string idMapValue = sessionName + "_" + peerDevId;
166         for (auto it = serverIdMap_.begin(); it != serverIdMap_.end();) {
167             if (((it->second).find(idMapValue) != std::string::npos)) {
168                 serverSocketId = it->first;
169                 it = serverIdMap_.erase(it);
170             } else {
171                 ++it;
172             }
173         }
174     }
175     Shutdown(serverSocketId);
176     DHLOGI("%{public}s: RemoveSessionServer success.", DSCREEN_LOG_TAG);
177     return DH_SUCCESS;
178 }
179 
OpenSoftbusSession(const std::string & mySessionName,const std::string & peerSessionName,const std::string & peerDevId)180 int32_t SoftbusAdapter::OpenSoftbusSession(const std::string &mySessionName, const std::string &peerSessionName,
181     const std::string &peerDevId)
182 {
183     DHLOGI("%{public}s: OpenSoftbusSession mysess:%{public}s peersess:%{public}s id:%{public}s.", DSCREEN_LOG_TAG,
184         mySessionName.c_str(), peerSessionName.c_str(), GetAnonyString(peerDevId).c_str());
185 
186     QosTV qos[] = {
187         {.qos = QOS_TYPE_MIN_BW,        .value = 40 * 1024 * 1024},
188         {.qos = QOS_TYPE_MAX_LATENCY,        .value = 8000},
189         {.qos = QOS_TYPE_MIN_LATENCY,        .value = 2000},
190     };
191     std::string localSesionName = mySessionName + "_" + std::to_string(GetCurrentTimeUs());
192     SocketInfo clientInfo = {
193         .name = const_cast<char*>((localSesionName.c_str())),
194         .peerName = const_cast<char*>(peerSessionName.c_str()),
195         .peerNetworkId = const_cast<char*>(peerDevId.c_str()),
196         .pkgName = const_cast<char*>(PKG_NAME.c_str()),
197         .dataType = DATA_TYPE_VIDEO_STREAM,
198     };
199     int32_t socketId = Socket(clientInfo);
200     if (socketId < 0) {
201         DHLOGE("Create OpenSoftbusChannel Socket error");
202         return ERR_DH_SCREEN_ADAPTER_PARA_ERROR;
203     }
204     int32_t ret = Bind(socketId, qos, sizeof(qos) / sizeof(qos[0]), &sessListener_);
205     if (ret != DH_SUCCESS) {
206         DHLOGE("Bind SocketClient error");
207         return ERR_DH_SCREEN_ADAPTER_PARA_ERROR;
208     }
209     {
210         std::lock_guard<std::mutex> lock(idMapMutex_);
211         devId2SessIdMap_.insert(std::make_pair(socketId, mySessionName + "_" + peerDevId));
212     }
213     std::shared_ptr<ISoftbusListener> &listener = GetSoftbusListenerByName(socketId);
214     if (listener == nullptr) {
215         DHLOGE("Get softbus listener failed.");
216         return ERR_DH_SCREEN_TRANS_ERROR;
217     }
218     PeerSocketInfo info;
219     ret = OnSoftbusSessionOpened(socketId, info);
220     if (ret != DH_SUCCESS) {
221         return ret;
222     }
223     DHLOGI("%{public}s: OpenSoftbusSession success sessionId: %{public}" PRId32, DSCREEN_LOG_TAG, socketId);
224     return socketId;
225 }
226 
CloseSoftbusSession(const int32_t sessionId)227 int32_t SoftbusAdapter::CloseSoftbusSession(const int32_t sessionId)
228 {
229     DHLOGI("%{public}s: CloseSoftbusSession, sessid:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
230     Shutdown(sessionId);
231     {
232         std::lock_guard<std::mutex> lock(idMapMutex_);
233         devId2SessIdMap_.erase(sessionId);
234     }
235     std::lock_guard<std::mutex> lisLock(listenerMtx_);
236     mapSessListeners_.erase(sessionId);
237 
238     DHLOGI("%{public}s: CloseSoftbusSession success.", DSCREEN_LOG_TAG);
239     return DH_SUCCESS;
240 }
241 
SendSoftbusBytes(int32_t sessionId,const void * data,int32_t dataLen) const242 int32_t SoftbusAdapter::SendSoftbusBytes(int32_t sessionId, const void *data, int32_t dataLen) const
243 {
244     DHLOGD("%{public}s: SendSoftbusBytes, sessid:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
245     int32_t ret = SendBytes(sessionId, data, dataLen);
246     if (ret != DH_SUCCESS) {
247         DHLOGE("%{public}s: SendBytes failed ret:%{public}" PRId32, DSCREEN_LOG_TAG, ret);
248         return ERR_DH_SCREEN_TRANS_ERROR;
249     }
250 
251     return DH_SUCCESS;
252 }
253 
SendSoftbusStream(int32_t sessionId,const StreamData * data,const StreamData * ext,const StreamFrameInfo * param) const254 int32_t SoftbusAdapter::SendSoftbusStream(int32_t sessionId, const StreamData *data, const StreamData *ext,
255     const StreamFrameInfo *param) const
256 {
257     DHLOGD("%{public}s: SendSoftbusStream, sessid:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
258     int32_t ret = SendStream(sessionId, data, ext, param);
259     if (ret != DH_SUCCESS) {
260         DHLOGE("%{public}s: SendStream failed ret:%{public}" PRId32, DSCREEN_LOG_TAG, ret);
261         return ERR_DH_SCREEN_TRANS_ERROR;
262     }
263 
264     return DH_SUCCESS;
265 }
266 
GetSoftbusListenerByName(int32_t sessionId)267 std::shared_ptr<ISoftbusListener> &SoftbusAdapter::GetSoftbusListenerByName(int32_t sessionId)
268 {
269     DHLOGD("%{public}s: GetSoftbusListenerByName, sessionId:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
270     std::string strListenerKey = "";
271     {
272         std::lock_guard<std::mutex> lock(idMapMutex_);
273         for (auto it = devId2SessIdMap_.begin(); it != devId2SessIdMap_.end(); it++) {
274             if (it->first == sessionId) {
275                 strListenerKey = it->second;
276                 break;
277             }
278         }
279     }
280     std::lock_guard<std::mutex> lisLock(listenerMtx_);
281     if (mapListeners_.find(strListenerKey) == mapListeners_.end()) {
282         DHLOGE("%{public}s: Find listener failed.", DSCREEN_LOG_TAG);
283         return nullListener_;
284     }
285     return mapListeners_[strListenerKey];
286 }
287 
GetSoftbusListenerById(int32_t sessionId)288 std::shared_ptr<ISoftbusListener> &SoftbusAdapter::GetSoftbusListenerById(int32_t sessionId)
289 {
290     std::lock_guard<std::mutex> lisLock(listenerMtx_);
291     if (mapSessListeners_.find(sessionId) == mapSessListeners_.end()) {
292         DHLOGE("%{public}s: Find listener failed.", DSCREEN_LOG_TAG);
293         return nullListener_;
294     }
295 
296     return mapSessListeners_[sessionId];
297 }
298 
OnSoftbusSessionOpened(int32_t sessionId,PeerSocketInfo info)299 int32_t SoftbusAdapter::OnSoftbusSessionOpened(int32_t sessionId, PeerSocketInfo info)
300 {
301     DHLOGI("%{public}s: OnSoftbusSessionOpened session:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
302     {
303         std::lock_guard<std::mutex> lock(serverIdMapMutex_);
304         for (auto it = serverIdMap_.begin(); it != serverIdMap_.end(); it++) {
305             if (info.networkId == nullptr) {
306                 break;
307             }
308             std::string peerDevId(info.networkId);
309             if ((it->second).find(peerDevId) != std::string::npos) {
310                 std::lock_guard<std::mutex> sessionLock(idMapMutex_);
311                 devId2SessIdMap_.insert(std::make_pair(sessionId, it->second));
312                 break;
313             }
314         }
315     }
316 
317     std::shared_ptr<ISoftbusListener> &listener = GetSoftbusListenerByName(sessionId);
318     if (listener == nullptr) {
319         DHLOGE("Get softbus listener failed.");
320         return ERR_DH_SCREEN_TRANS_ERROR;
321     }
322     listener->OnSessionOpened(sessionId, info);
323 
324     std::lock_guard<std::mutex> lisLock(listenerMtx_);
325     mapSessListeners_.insert(std::make_pair(sessionId, listener));
326 
327     return DH_SUCCESS;
328 }
329 
OnSoftbusSessionClosed(int32_t sessionId,ShutdownReason reason)330 void SoftbusAdapter::OnSoftbusSessionClosed(int32_t sessionId, ShutdownReason reason)
331 {
332     DHLOGI("%{public}s: OnSessionClosed sessionId:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
333     std::shared_ptr<ISoftbusListener> &listener = GetSoftbusListenerById(sessionId);
334     if (listener == nullptr) {
335         DHLOGE("Get softbus listener failed.");
336         return;
337     }
338     listener->OnSessionClosed(sessionId, reason);
339     {
340         std::lock_guard<std::mutex> lock(idMapMutex_);
341         devId2SessIdMap_.erase(sessionId);
342     }
343     std::lock_guard<std::mutex> lisLock(listenerMtx_);
344     mapSessListeners_.erase(sessionId);
345 }
346 
OnBytesReceived(int32_t sessionId,const void * data,uint32_t dataLen)347 void SoftbusAdapter::OnBytesReceived(int32_t sessionId, const void *data, uint32_t dataLen)
348 {
349     DHLOGD("%{public}s: OnBytesReceived, sessionId:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
350     if (data == nullptr) {
351         DHLOGE("BytesData is null.");
352         return;
353     }
354     if (dataLen == 0 || dataLen > DSCREEN_MAX_RECV_DATA_LEN) {
355         DHLOGE("BytesData length is too large, dataLen:%{public}" PRIu32, dataLen);
356         return;
357     }
358 
359     std::shared_ptr<ISoftbusListener> &listener = GetSoftbusListenerByName(sessionId);
360     if (listener == nullptr) {
361         DHLOGE("Get softbus listener failed.");
362         return;
363     }
364     listener->OnBytesReceived(sessionId, data, dataLen);
365 }
366 
OnStreamReceived(int32_t sessionId,const StreamData * data,const StreamData * ext,const StreamFrameInfo * frameInfo)367 void SoftbusAdapter::OnStreamReceived(int32_t sessionId, const StreamData *data, const StreamData *ext,
368     const StreamFrameInfo *frameInfo)
369 {
370     DHLOGD("%{public}s OnStreamReceived, sessionId:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
371     if (data == nullptr) {
372         DHLOGE("StreamData is null.");
373         return;
374     }
375     if (data->bufLen <= 0 || data->bufLen > static_cast<int32_t>(DSCREEN_MAX_RECV_DATA_LEN)) {
376         DHLOGE("StreamData length is too large, dataLen:%{public}" PRId32, data->bufLen);
377         return;
378     }
379 
380     std::shared_ptr<ISoftbusListener> &listener = GetSoftbusListenerByName(sessionId);
381     if (listener == nullptr) {
382         DHLOGE("Get softbus listener failed.");
383         return;
384     }
385     listener->OnStreamReceived(sessionId, data, ext, frameInfo);
386 }
387 
OnMessageReceived(int sessionId,const void * data,unsigned int dataLen) const388 void SoftbusAdapter::OnMessageReceived(int sessionId, const void *data, unsigned int dataLen) const
389 {
390     (void)data;
391     (void)dataLen;
392     DHLOGD("%{public}s OnMessageReceived, sessionId:%{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
393 }
394 } // namespace DistributedHardware
395 } // namespace OHOS