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