1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "wfd_sink_session.h"
17 #include <memory>
18 #include "common/common.h"
19 #include "common/common_macro.h"
20 #include "common/reflect_registration.h"
21 #include "common/sharing_log.h"
22 #include "extend/magic_enum/magic_enum.hpp"
23 #include "mediachannel/media_channel_def.h"
24 #include "utils/utils.h"
25 #include "wfd_media_def.h"
26 #include "common/sharing_sink_hisysevent.h"
27
28 namespace OHOS {
29 namespace Sharing {
30 #define WFD_INTERACTION_TIMEOUT 10
31
32 #define WFD_TIMEOUT_5_SECOND 5
33 #define WFD_TIMEOUT_6_SECOND 6
34 #define WFD_KEEP_ALIVE_TIMEOUT_MIN 10
35 #define WFD_KEEP_ALIVE_TIMEOUT_DEFAULT 60
36
WfdSinkSession()37 WfdSinkSession::WfdSinkSession()
38 {
39 SHARING_LOGI("sessionId: %{public}u.", GetId());
40 }
41
~WfdSinkSession()42 WfdSinkSession::~WfdSinkSession()
43 {
44 SHARING_LOGI("sessionId: %{public}u.", GetId());
45
46 if (rtspClient_) {
47 connected_ = false;
48 rtspClient_->Disconnect();
49 rtspClient_.reset();
50 }
51
52 timeoutTimer_.reset();
53 keepAliveTimer_.reset();
54 }
55
HandleEvent(SharingEvent & event)56 int32_t WfdSinkSession::HandleEvent(SharingEvent &event)
57 {
58 SHARING_LOGD("trace.");
59 RETURN_INVALID_IF_NULL(event.eventMsg);
60 if (interrupting_ && status_ == SESSION_INTERRUPT) {
61 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
62 NotifySessionInterrupted();
63 return 0;
64 }
65
66 SHARING_LOGI("eventType: %{public}s, wfd sessionId: %{public}u.",
67 std::string(magic_enum::enum_name(event.eventMsg->type)).c_str(), GetId());
68 switch (event.eventMsg->type) {
69 case EventType::EVENT_SESSION_INIT:
70 HandleSessionInit(event);
71 break;
72 case EventType::EVENT_AGENT_STATE_PROSUMER_INIT:
73 HandleProsumerInitState(event);
74 break;
75 case EventType::EVENT_AGENT_KEYMODE_STOP:
76 case EventType::EVENT_WFD_REQUEST_IDR:
77 SendIDRRequest();
78 break;
79 case EventType::EVENT_SESSION_TEARDOWN:
80 SendM8Request();
81 break;
82 case EventType::EVENT_AGENT_STATE_WRITE_WARNING:
83 NotifyServiceError(ERR_INTAKE_TIMEOUT);
84 break;
85 default:
86 SHARING_LOGI("none process case.");
87 break;
88 }
89
90 if (interrupting_ && status_ == SESSION_INTERRUPT) {
91 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
92 NotifySessionInterrupted();
93 }
94
95 return 0;
96 }
97
HandleSessionInit(SharingEvent & event)98 void WfdSinkSession::HandleSessionInit(SharingEvent &event)
99 {
100 SHARING_LOGD("trace.");
101 RETURN_IF_NULL(event.eventMsg);
102 auto inputMsg = ConvertEventMsg<WfdSinkSessionEventMsg>(event);
103 if (inputMsg) {
104 remoteMac_ = inputMsg->mac;
105 remoteRtspIp_ = inputMsg->remoteIp;
106 remoteRtspPort_ = inputMsg->remotePort != 0 ? inputMsg->remotePort : DEFAULT_WFD_CTRLPORT;
107 localRtpPort_ = inputMsg->localPort;
108 localIp_ = inputMsg->localIp;
109 videoFormat_ = inputMsg->videoFormat;
110 audioFormat_ = inputMsg->audioFormat;
111 wfdParamsInfo_ = inputMsg->wfdParamsInfo;
112 } else {
113 SHARING_LOGE("unknow event msg.");
114 }
115
116 SHARING_LOGI("sessionInit localIp: %{public}s, remoteIp: %{public}s", GetAnonymousIp(localIp_).c_str(),
117 GetAnonymousIp(remoteRtspIp_).c_str());
118 }
119
HandleProsumerInitState(SharingEvent & event)120 void WfdSinkSession::HandleProsumerInitState(SharingEvent &event)
121 {
122 SHARING_LOGD("trace.");
123 RETURN_IF_NULL(event.eventMsg);
124
125 auto inputMsg = ConvertEventMsg<WfdSinkSessionEventMsg>(event);
126 auto statusMsg = std::make_shared<SessionStatusMsg>();
127 statusMsg->msg = std::make_shared<EventMsg>();
128 statusMsg->status = STATE_SESSION_ERROR;
129 statusMsg->msg->errorCode = ERR_SESSION_START;
130
131 if (inputMsg) {
132 statusMsg->msg->requestId = inputMsg->requestId;
133 if (inputMsg->errorCode == ERR_OK) {
134 statusMsg->status = STATE_SESSION_STARTED;
135 statusMsg->msg->errorCode = ERR_OK;
136 } else {
137 SHARING_LOGE("producer inited failed, producerId: %{public}u.", inputMsg->prosumerId);
138 }
139 } else {
140 SHARING_LOGE("producer inited failed: unknow msg.");
141 }
142
143 NotifyAgentSessionStatus(statusMsg);
144 }
145
UpdateOperation(SessionStatusMsg::Ptr & statusMsg)146 void WfdSinkSession::UpdateOperation(SessionStatusMsg::Ptr &statusMsg)
147 {
148 SHARING_LOGD("trace.");
149 RETURN_IF_NULL(statusMsg);
150 RETURN_IF_NULL(statusMsg->msg);
151
152 status_ = static_cast<SessionRunningStatus>(statusMsg->status);
153 SHARING_LOGI("status: %{public}s.", std::string(magic_enum::enum_name(status_)).c_str());
154 if (interrupting_ && status_ == SESSION_INTERRUPT) {
155 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
156 NotifySessionInterrupted();
157 return;
158 }
159
160 switch (status_) {
161 case SESSION_START: {
162 if (!StartWfdSession()) {
163 SHARING_LOGE("session start connection failed, sessionId: %{public}u.", GetId());
164 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "dsoftbus", SinkStage::SESSION_NEGOTIATION,
165 SinkErrorCode::WIFI_DISPLAY_TCP_FAILED);
166 statusMsg->msg->errorCode = ERR_CONNECTION_FAILURE;
167 statusMsg->status = STATE_SESSION_ERROR;
168 break;
169 }
170 connected_ = true;
171 if (interrupting_ && status_ == SESSION_INTERRUPT) {
172 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
173 connected_ = false;
174 NotifySessionInterrupted();
175 }
176
177 return;
178 }
179 case SESSION_STOP:
180 statusMsg->status = STATE_SESSION_STOPED;
181 StopWfdSession();
182 break;
183 case SESSION_PAUSE:
184 statusMsg->status = STATE_SESSION_PAUSED;
185 break;
186 case SESSION_RESUME:
187 statusMsg->status = STATE_SESSION_RESUMED;
188 break;
189 case SESSION_DESTROY:
190 statusMsg->status = STATE_SESSION_DESTROYED;
191 break;
192 case SESSION_INTERRUPT:
193 interrupting_ = true;
194 return;
195 default:
196 SHARING_LOGI("none process case.");
197 break;
198 }
199
200 if (interrupting_ && (status_ != SESSION_STOP && status_ != SESSION_DESTROY)) {
201 if (status_ == SESSION_INTERRUPT) {
202 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
203 NotifySessionInterrupted();
204 }
205 SHARING_LOGW("session: %{public}u has been interrupted.", GetId());
206 return;
207 }
208
209 NotifyAgentSessionStatus(statusMsg);
210 }
211
UpdateMediaStatus(SessionStatusMsg::Ptr & statusMsg)212 void WfdSinkSession::UpdateMediaStatus(SessionStatusMsg::Ptr &statusMsg)
213 {
214 SHARING_LOGD("trace.");
215 RETURN_IF_NULL(statusMsg);
216 RETURN_IF_NULL(statusMsg->msg);
217 if (interrupting_ && status_ == SESSION_INTERRUPT) {
218 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
219 NotifySessionInterrupted();
220 return;
221 }
222
223 SHARING_LOGD("update media notify status: %{public}s.",
224 std::string(magic_enum::enum_name(static_cast<MediaNotifyStatus>(statusMsg->status))).c_str());
225 switch (statusMsg->status) {
226 case STATE_PROSUMER_CREATE_SUCCESS:
227 NotifyProsumerInit(statusMsg);
228 break;
229 case STATE_PROSUMER_START_SUCCESS:
230 break;
231 case STATE_PROSUMER_STOP_SUCCESS:
232 break;
233 case STATE_PROSUMER_DESTROY_SUCCESS:
234 break;
235 case STATE_PROSUMER_RESUME_SUCCESS:
236 SendIDRRequest();
237 break;
238 default:
239 SHARING_LOGI("none process case.");
240 break;
241 }
242
243 if (interrupting_ && status_ == SESSION_INTERRUPT) {
244 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
245 NotifySessionInterrupted();
246 }
247 }
248
NotifyProsumerInit(SessionStatusMsg::Ptr & statusMsg)249 void WfdSinkSession::NotifyProsumerInit(SessionStatusMsg::Ptr &statusMsg)
250 {
251 SHARING_LOGD("trace.");
252 RETURN_IF_NULL(statusMsg);
253 RETURN_IF_NULL(statusMsg->msg);
254
255 auto eventMsg = std::make_shared<WfdConsumerEventMsg>();
256 eventMsg->type = EventType::EVENT_WFD_MEDIA_INIT;
257 eventMsg->toMgr = ModuleType::MODULE_MEDIACHANNEL;
258 eventMsg->port = localRtpPort_;
259 eventMsg->ip = localIp_;
260 eventMsg->audioTrack = audioTrack_;
261 eventMsg->videoTrack = videoTrack_;
262
263 statusMsg->msg = std::move(eventMsg);
264 statusMsg->status = NOTIFY_SESSION_PRIVATE_EVENT;
265
266 NotifyAgentSessionStatus(statusMsg);
267 }
268
NotifyAgentSessionStatus(SessionStatusMsg::Ptr & statusMsg)269 void WfdSinkSession::NotifyAgentSessionStatus(SessionStatusMsg::Ptr &statusMsg)
270 {
271 SHARING_LOGD("trace.");
272 RETURN_IF_NULL(statusMsg);
273 if (statusMsg->status == NOTIFY_PROSUMER_CREATE) {
274 statusMsg->className = "WfdRtpConsumer";
275 }
276
277 Notify(statusMsg);
278 }
279
StartWfdSession()280 bool WfdSinkSession::StartWfdSession()
281 {
282 SHARING_LOGD("trace.");
283 if (NetworkFactory::CreateTcpClient(remoteRtspIp_, remoteRtspPort_, shared_from_this(), rtspClient_)) {
284 SHARING_LOGI("sessionId: %{public}u, wfds session connected ip: %{public}s.", GetId(),
285 GetAnonymousIp(remoteRtspIp_).c_str());
286 } else {
287 // try connect again
288 for (int32_t i = 0; i < 5; i++) { // 5: retry time
289 if (interrupting_) {
290 if (status_ == SESSION_INTERRUPT) {
291 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
292 NotifySessionInterrupted();
293 }
294 SHARING_LOGW("session: %{public}u has been interrupted.", GetId());
295 return false;
296 }
297
298 usleep(1000 * 200); // 1000 * 200: sleep 200ms
299 if (rtspClient_) {
300 if (rtspClient_->Connect(remoteRtspIp_, remoteRtspPort_, "::", 0)) {
301 SHARING_LOGW("sessionId: %{public}u, reconnected successfully, ip: %{public}s, times: %{public}d.",
302 GetId(), GetAnonymousIp(remoteRtspIp_).c_str(), i);
303 break;
304 } else {
305 SHARING_LOGE("sessionId: %{public}u, Failed to connect wfd rtsp server %{public}s:%{public}d.",
306 GetId(), GetAnonymousIp(remoteRtspIp_).c_str(), remoteRtspPort_);
307 if (i == 4) { // 4: stop try
308 return false;
309 }
310 }
311 }
312 }
313 }
314
315 timeoutTimer_ = std::make_unique<TimeoutTimer>();
316 timeoutTimer_->SetTimeoutCallback([this]() {
317 if (interrupting_) {
318 if (status_ == SESSION_INTERRUPT) {
319 NotifySessionInterrupted();
320 }
321 } else {
322 NotifyServiceError(ERR_PROTOCOL_INTERACTION_TIMEOUT);
323 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "dsoftbus", SinkStage::SESSION_NEGOTIATION,
324 SinkErrorCode::WIFI_DISPLAY_RTSP_FAILED);
325 }
326 });
327
328 timeoutTimer_->StartTimer(WFD_TIMEOUT_6_SECOND, "Waiting for WFD source M1/OPTIONS request");
329 return true;
330 }
331
StopWfdSession()332 bool WfdSinkSession::StopWfdSession()
333 {
334 SHARING_LOGI("sessionId: %{public}u.", GetId());
335 SendM8Request();
336 connected_ = false;
337
338 WfdSinkHiSysEvent::GetInstance().ThirdSceneEndReport(__func__, "", SinkStage::DISCONNECT_COMPLETE);
339 return true;
340 }
341
OnClientReadData(int32_t fd,DataBuffer::Ptr buf)342 void WfdSinkSession::OnClientReadData(int32_t fd, DataBuffer::Ptr buf)
343 {
344 SHARING_LOGD("trace.");
345 RETURN_IF_NULL(buf);
346 if (interrupting_) {
347 if (status_ == SESSION_INTERRUPT) {
348 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
349 NotifySessionInterrupted();
350 }
351 SHARING_LOGW("session: %{public}u has been interrupted.", GetId());
352 return;
353 }
354
355 std::string message(buf->Peek(), buf->Size());
356 RtspResponse response;
357 RtspRequest request;
358
359 SHARING_LOGD("sessionId: %{public}u, Recv WFD source message:\n%{public}s.", GetId(), message.c_str());
360 auto ret = response.Parse(message);
361 if (ret.code == RtspErrorType::OK) {
362 SHARING_LOGD("Recv RTSP Response message.");
363
364 int32_t incommingCSeq = response.GetCSeq();
365 auto funcIndex = responseHandlers_.find(incommingCSeq);
366 if (funcIndex != responseHandlers_.end() && funcIndex->second) {
367 if (!lastMessage_.empty()) {
368 lastMessage_.clear();
369 }
370
371 funcIndex->second(response, message);
372 responseHandlers_.erase(funcIndex);
373 } else {
374 SHARING_LOGE("Can't find response handler for cseq(%{public}d)", incommingCSeq);
375 return;
376 }
377
378 if (ret.info.size() > 2 && ret.info.back() == '$') { // 2: size of int
379 ret.info.pop_back();
380 SHARING_LOGW("*packet splicing need parse again\n%{public}s.", ret.info.c_str());
381 ret = request.Parse(ret.info);
382 if (ret.code == RtspErrorType::OK) {
383 SHARING_LOGD("Recv RTSP Request [method:%{public}s] message.", request.GetMethod().c_str());
384 HandleRequest(request, message);
385 return;
386 }
387 }
388
389 return;
390 }
391
392 ret = request.Parse(message);
393 if (ret.code == RtspErrorType::OK) {
394 SHARING_LOGD("Recv RTSP Request [method:%{public}s] message.", request.GetMethod().c_str());
395 HandleRequest(request, message);
396 return;
397 }
398
399 SHARING_LOGD("invalid WFD rtsp message.");
400 if (ret.code == RtspErrorType::INCOMPLETE_MESSAGE) {
401 lastMessage_ = message;
402 SHARING_LOGD("return with '%{public}s'.", ret.info.c_str());
403 return;
404 } else {
405 message = lastMessage_ + message;
406 ret = request.Parse(message);
407 if (ret.code == RtspErrorType::OK) {
408 SHARING_LOGD("spliced the Request message Successfully.");
409 HandleRequest(request, message);
410 return;
411 } else {
412 lastMessage_.clear();
413 return;
414 }
415 }
416 }
417
OnClientClose(int32_t fd)418 void WfdSinkSession::OnClientClose(int32_t fd)
419 {
420 SHARING_LOGD("sessionId: %{public}u, RTSP TCP Client socket close %{public}d.", GetId(), fd);
421 rtspClient_.reset();
422
423 if (interrupting_) {
424 if (status_ == SESSION_INTERRUPT) {
425 SHARING_LOGE("session: %{public}u, to notify be interrupted.", GetId());
426 NotifySessionInterrupted();
427 }
428 SHARING_LOGW("session: %{public}u has been interrupted.", GetId());
429 return;
430 }
431
432 if (wfdState_ < WfdSessionState::STOPPING) {
433 NotifyServiceError(ERR_NETWORK_ERROR);
434 }
435 }
436
HandleRequest(const RtspRequest & request,const std::string & message)437 void WfdSinkSession::HandleRequest(const RtspRequest &request, const std::string &message)
438 {
439 SHARING_LOGD("trace.");
440 if (!lastMessage_.empty()) {
441 lastMessage_.clear();
442 }
443
444 int32_t incomingCSeq = request.GetCSeq();
445 std::string rtspMethod = request.GetMethod();
446 if (rtspMethod == RTSP_METHOD_OPTIONS) {
447 // this is M1 request
448 SHARING_LOGD("Handle M1 request.");
449 if (timeoutTimer_) {
450 timeoutTimer_->StopTimer();
451 }
452 isFirstCast = true;
453 isFirstCreateProsumer_ = true;
454 SendM1Response(incomingCSeq);
455 SendM2Request();
456 return;
457 }
458
459 if (rtspMethod == RTSP_METHOD_GET_PARAMETER) {
460 std::list<std::string> params = request.GetBody();
461 if (!params.empty()) {
462 // this is M3 request
463 SHARING_LOGD("Handle M3 request.");
464 if (timeoutTimer_) {
465 timeoutTimer_->StopTimer();
466 }
467 SendM3Response(incomingCSeq, params);
468 } else {
469 // M16: Keep-Alive message
470 SHARING_LOGD("Handle M16/Keep-Alive request.");
471 if (keepAliveTimer_ == nullptr) {
472 return;
473 }
474 keepAliveTimer_->StopTimer();
475 SendCommonResponse(incomingCSeq);
476 keepAliveTimer_->StartTimer(keepAliveTimeout_,
477 "Waiting for WFD source M16/GET_PARAMETER KeepAlive request");
478 }
479
480 return;
481 }
482
483 if (rtspMethod == RTSP_METHOD_SET_PARAMETER) {
484 // this is M4 or M5 request
485 HandleSetParamRequest(request, message);
486 return;
487 }
488 SHARING_LOGE("RTSP Request [method:%{public}s] message shouldn't be here.", request.GetMethod().c_str());
489 }
490
HandleSetParamRequest(const RtspRequest & request,const std::string & message)491 void WfdSinkSession::HandleSetParamRequest(const RtspRequest &request, const std::string &message)
492 {
493 SHARING_LOGD("trace.");
494 int32_t incomingCSeq = request.GetCSeq();
495
496 std::list<std::string> paramSet = request.GetBody();
497 std::list<std::pair<std::string, std::string>> paramMap;
498 RtspCommon::SplitParameter(paramSet, paramMap);
499 if (paramMap.empty()) {
500 SHARING_LOGE("invalid SET_PARAMETER request without body.");
501 return;
502 }
503
504 // Triger request
505 auto it = std::find_if(paramMap.begin(), paramMap.end(),
506 [](std::pair<std::string, std::string> value) { return value.first == WFD_PARAM_TRIGGER; });
507 if (it != paramMap.end()) {
508 HandleTriggerMethod(incomingCSeq, it->second);
509 return;
510 }
511
512 // M4 request
513 if (timeoutTimer_) {
514 timeoutTimer_->StopTimer();
515 }
516
517 bool ret = HandleM4Request(message);
518 if (ret && isFirstCreateProsumer_) {
519 isFirstCreateProsumer_ = false;
520 SessionStatusMsg::Ptr statusMsg = std::make_shared<SessionStatusMsg>();
521 statusMsg->msg = std::make_shared<EventMsg>();
522 statusMsg->msg->requestId = 0;
523 statusMsg->msg->errorCode = ERR_OK;
524 statusMsg->status = NOTIFY_PROSUMER_CREATE;
525
526 NotifyAgentSessionStatus(statusMsg);
527 }
528
529 return;
530 }
531
HandleM2Response(const RtspResponse & response,const std::string & message)532 void WfdSinkSession::HandleM2Response(const RtspResponse &response, const std::string &message)
533 {
534 SHARING_LOGD("trace.");
535 if (timeoutTimer_) {
536 timeoutTimer_->StopTimer();
537 timeoutTimer_->StartTimer(WFD_TIMEOUT_6_SECOND, "Waiting for M3/GET_PARAMETER request");
538 }
539
540 if (response.GetStatus() != RTSP_STATUS_OK) {
541 SHARING_LOGE("WFD source peer handle 'OPTIONS' method error.");
542 NotifyServiceError();
543 return;
544 }
545
546 std::string publics = response.GetToken(RTSP_TOKEN_PUBLIC);
547 if (publics.empty() || publics.find(RTSP_METHOD_WFD) == std::string::npos ||
548 publics.find(RTSP_METHOD_SET_PARAMETER) == std::string::npos ||
549 publics.find(RTSP_METHOD_GET_PARAMETER) == std::string::npos ||
550 publics.find(RTSP_METHOD_SETUP) == std::string::npos || publics.find(RTSP_METHOD_PLAY) == std::string::npos ||
551 publics.find(RTSP_METHOD_TEARDOWN) == std::string::npos) {
552 SHARING_LOGE("WFD source peer do not support all methods.");
553 NotifyServiceError();
554 }
555 }
556
HandleM6Response(const RtspResponse & response,const std::string & message)557 void WfdSinkSession::HandleM6Response(const RtspResponse &response, const std::string &message)
558 {
559 SHARING_LOGD("trace.");
560 if (timeoutTimer_) {
561 timeoutTimer_->StopTimer();
562 }
563
564 if (response.GetStatus() != RTSP_STATUS_OK) {
565 SHARING_LOGE("WFD source peer handle 'SETUP' method error.");
566 NotifyServiceError();
567 return;
568 }
569
570 rtspSession_ = response.GetSession();
571 keepAliveTimeout_ = response.GetTimeout();
572 if (keepAliveTimeout_ < WFD_KEEP_ALIVE_TIMEOUT_MIN) {
573 keepAliveTimeout_ = WFD_KEEP_ALIVE_TIMEOUT_DEFAULT;
574 }
575
576 SendM7Request();
577 }
578
HandleM7Response(const RtspResponse & response,const std::string & message)579 void WfdSinkSession::HandleM7Response(const RtspResponse &response, const std::string &message)
580 {
581 SHARING_LOGD("trace.");
582
583 if (timeoutTimer_) {
584 timeoutTimer_->StopTimer();
585 }
586
587 if (response.GetStatus() != RTSP_STATUS_OK) {
588 SHARING_LOGE("WFD source peer handle 'PLAY' method error.");
589 NotifyServiceError();
590 return;
591 }
592 NotifyAgentPrivateEvent(EVENT_WFD_NOTIFY_RTSP_PLAYED);
593
594 wfdState_ = WfdSessionState::PLAYING;
595 SHARING_LOGI("WFD RTSP PLAY ok, start receiver to recv the stream.");
596
597 // Cause the interaction has already been completed,
598 // then set a new callback for the next operations.
599 if (timeoutTimer_) {
600 timeoutTimer_->SetTimeoutCallback([this]() { NotifyServiceError(ERR_NETWORK_ERROR); });
601 }
602
603 keepAliveTimer_ = std::make_unique<TimeoutTimer>();
604 keepAliveTimer_->SetTimeoutCallback([this]() {
605 NotifyServiceError(ERR_NETWORK_ERROR);
606 WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::SEND_M7_MSG,
607 SinkErrorCode::WIFI_DISPLAY_RTSP_KEEPALIVE_TIMEOUT);
608 });
609 keepAliveTimer_->StartTimer(keepAliveTimeout_, "Waiting for WFD source M16/GET_PARAMETER KeepAlive request");
610 }
611
HandleM8Response(const RtspResponse & response,const std::string & message)612 void WfdSinkSession::HandleM8Response(const RtspResponse &response, const std::string &message)
613 {
614 SHARING_LOGD("trace.");
615
616 WfdSinkHiSysEvent::GetInstance().ChangeHisysEventScene(SinkBizScene::DISCONNECT_MIRRORING);
617 WfdSinkHiSysEvent::GetInstance().StartReport(__func__, "", SinkStage::RECEIVE_DISCONNECT_EVENT,
618 SinkStageRes::SUCCESS);
619 if (response.GetStatus() != RTSP_STATUS_OK) {
620 SHARING_LOGE("WFD source peer handle 'TEARDOWN' method error.");
621 NotifyServiceError();
622 return;
623 }
624
625 // notify wfd scene rtsp teardown
626 NotifyAgentPrivateEvent(EVENT_WFD_NOTIFY_RTSP_TEARDOWN);
627 SHARING_LOGI("WFD RTSP TEARDOWN ok, stop recv the stream, disconnect socket.");
628 }
629
NotifyAgentPrivateEvent(EventType type)630 void WfdSinkSession::NotifyAgentPrivateEvent(EventType type)
631 {
632 auto statusMsg = std::make_shared<SessionStatusMsg>();
633 auto eventMsg = std::make_shared<WfdSceneEventMsg>();
634 eventMsg->type = type;
635 eventMsg->toMgr = ModuleType::MODULE_INTERACTION;
636 eventMsg->mac = remoteMac_;
637 statusMsg->msg = std::move(eventMsg);
638 statusMsg->status = NOTIFY_SESSION_PRIVATE_EVENT;
639 NotifyAgentSessionStatus(statusMsg);
640 }
641
HandleCommonResponse(const RtspResponse & response,const std::string & message)642 void WfdSinkSession::HandleCommonResponse(const RtspResponse &response, const std::string &message)
643 {
644 SHARING_LOGD("trace.");
645
646 if (timeoutTimer_) {
647 timeoutTimer_->StopTimer();
648 }
649
650 if (response.GetStatus() != RTSP_STATUS_OK) {
651 SHARING_LOGI("WFD source peer handle method error.");
652 NotifyServiceError();
653 return;
654 }
655 }
656
SendM1Response(int32_t cseq)657 bool WfdSinkSession::SendM1Response(int32_t cseq)
658 {
659 SHARING_LOGD("trace.");
660 if (!rtspClient_) {
661 return false;
662 }
663
664 WfdRtspM1Response m1Response(cseq, RTSP_STATUS_OK);
665 std::string m1Res(m1Response.Stringify());
666
667 WfdSinkHiSysEvent::GetInstance().Report(__func__, "dsoftbus", SinkStage::SESSION_NEGOTIATION,
668 SinkStageRes::SUCCESS);
669 SHARING_LOGI("sessionId: %{public}d send M1 response, cseq: %{public}d.", GetId(), cseq);
670 bool ret = rtspClient_->Send(m1Res.data(), m1Res.length());
671 if (!ret) {
672 SHARING_LOGE("Failed to send M1 response, cseq: %{public}d.", cseq);
673 }
674
675 cseq_ = cseq;
676 return ret;
677 }
678
SendM2Request()679 bool WfdSinkSession::SendM2Request()
680 {
681 SHARING_LOGD("trace.");
682 if (!rtspClient_) {
683 return false;
684 }
685
686 WfdRtspM2Request m2Request(++cseq_);
687
688 responseHandlers_[cseq_] = [this](auto &&PH1, auto &&PH2) {
689 HandleM2Response(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2));
690 };
691 if (timeoutTimer_) {
692 timeoutTimer_->StartTimer(WFD_TIMEOUT_5_SECOND, "Waiting for M2/OPTIONS response");
693 }
694
695 SHARING_LOGI("sessionId: %{public}d send M2 request, cseq: %{public}d.", GetId(), cseq_);
696 std::string m2Req(m2Request.Stringify());
697 bool ret = rtspClient_->Send(m2Req.data(), m2Req.length());
698 if (!ret) {
699 SHARING_LOGE("Failed to send M2 request, cseq: %{public}d", cseq_);
700 responseHandlers_.erase(cseq_);
701 if (timeoutTimer_) {
702 timeoutTimer_->StopTimer();
703 }
704 NotifyServiceError();
705 return false;
706 }
707
708 return true;
709 }
710
SendM3Response(int32_t cseq,std::list<std::string> & params)711 bool WfdSinkSession::SendM3Response(int32_t cseq, std::list<std::string> ¶ms)
712 {
713 SHARING_LOGD("trace.");
714 if (!rtspClient_ || params.empty()) {
715 return false;
716 }
717
718 WfdRtspM3Response m3Response(cseq, RTSP_STATUS_OK);
719 SetM3ResponseParam(params, m3Response);
720 if (timeoutTimer_) {
721 timeoutTimer_->StartTimer(WFD_TIMEOUT_6_SECOND, "Waiting for M4/SET_PARAMETER request");
722 }
723
724 SHARING_LOGI("sessionId: %{public}d send M3 response, cseq: %{public}d.", GetId(), cseq);
725 std::string m3Req(m3Response.Stringify());
726 bool ret = rtspClient_->Send(m3Req.data(), m3Req.length());
727 if (!ret) {
728 SHARING_LOGE("Failed to send M3 response, cseq: %{public}d", cseq);
729 if (timeoutTimer_) {
730 timeoutTimer_->StopTimer();
731 }
732 NotifyServiceError();
733 return ret;
734 }
735
736 return true;
737 }
738
SetM3ResponseParam(std::list<std::string> & params,WfdRtspM3Response & m3Response)739 void WfdSinkSession::SetM3ResponseParam(std::list<std::string> ¶ms, WfdRtspM3Response &m3Response)
740 {
741 for (auto ¶m : params) {
742 if (param == WFD_PARAM_VIDEO_FORMATS) {
743 m3Response.SetVideoFormats(videoFormat_);
744 } else if (param == WFD_PARAM_AUDIO_CODECS) {
745 m3Response.SetAudioCodecs(audioFormat_);
746 } else if (param == WFD_PARAM_VIDEO_FORMATS_2) {
747 m3Response.SetVideoFormats2FromSystem();
748 } else if (param == WFD_PARAM_AUDIO_CODECS_2) {
749 m3Response.SetAudioCodec2FromSystem();
750 } else if (param == WFD_PARAM_RTP_PORTS) {
751 m3Response.SetClientRtpPorts(localRtpPort_);
752 } else if (param == WFD_PARAM_CONTENT_PROTECTION) {
753 m3Response.SetContentProtection(wfdParamsInfo_.contentProtection);
754 } else if (param == WFD_PARAM_COUPLED_SINK) {
755 m3Response.SetCoupledSink();
756 } else if (param == WFD_PARAM_UIBC_CAPABILITY) {
757 m3Response.SetUibcCapability(wfdParamsInfo_.uibcCapability);
758 } else if (param == WFD_PARAM_STANDBY_RESUME) {
759 m3Response.SetStandbyResumeCapability();
760 } else if (param == WFD_PARAM_CONNECTOR_TYPE) {
761 m3Response.SetCustomParam(WFD_PARAM_CONNECTOR_TYPE, wfdParamsInfo_.connectorType);
762 } else if (param == WFD_PARAM_DISPLAY_EDID) {
763 m3Response.SetCustomParam(WFD_PARAM_DISPLAY_EDID, wfdParamsInfo_.displayEdid);
764 } else if (param == WFD_PARAM_RTCP_CAPABILITY) {
765 m3Response.SetCustomParam(WFD_PARAM_RTCP_CAPABILITY, wfdParamsInfo_.microsofRtcpCapability);
766 } else if (param == WFD_PARAM_IDR_REQUEST_CAPABILITY) {
767 m3Response.SetCustomParam(WFD_PARAM_IDR_REQUEST_CAPABILITY, wfdParamsInfo_.idrRequestCapablity);
768 }
769 }
770 }
771
SetM3HweParam(WfdRtspM3Response & m3Response,std::string & param)772 void WfdSinkSession::SetM3HweParam(WfdRtspM3Response &m3Response, std::string ¶m)
773 {
774 if (param == WFD_PARAM_HWE_VERSION) {
775 m3Response.SetCustomParam(WFD_PARAM_HWE_VERSION, wfdParamsInfo_.hweVersion);
776 } else if (param == WFD_PARAM_HWE_VENDER_ID) {
777 m3Response.SetCustomParam(WFD_PARAM_HWE_VENDER_ID, wfdParamsInfo_.hweVenderId);
778 } else if (param == WFD_PARAM_HWE_PRODUCT_ID) {
779 m3Response.SetCustomParam(WFD_PARAM_HWE_PRODUCT_ID, wfdParamsInfo_.hweProductId);
780 } else if (param == WFD_PARAM_HWE_VTP) {
781 m3Response.SetCustomParam(WFD_PARAM_HWE_VTP, wfdParamsInfo_.hweVtp);
782 } else if (param == WFD_PARAM_HWE_HEVC_FORMATS) {
783 m3Response.SetCustomParam(WFD_PARAM_HWE_HEVC_FORMATS, wfdParamsInfo_.hweHevcFormats);
784 } else if (param == WFD_PARAM_HWE_VIDEO_60FPS) {
785 m3Response.SetCustomParam(WFD_PARAM_HWE_VIDEO_60FPS, wfdParamsInfo_.hweVideo60FPS);
786 } else if (param == WFD_PARAM_HWE_AVSYNC_SINK) {
787 m3Response.SetCustomParam(WFD_PARAM_HWE_AVSYNC_SINK, wfdParamsInfo_.hweAvSyncSink);
788 } else {
789 m3Response.SetCustomParam(param);
790 }
791 }
792
HandleM4Request(const std::string & message)793 bool WfdSinkSession::HandleM4Request(const std::string &message)
794 {
795 SHARING_LOGD("trace.");
796
797 WfdRtspM4Request m4Request;
798 m4Request.Parse(message);
799 rtspUrl_ = m4Request.GetPresentationUrl();
800 m4Request.GetVideoTrack(videoTrack_);
801 m4Request.GetAudioTrack(audioTrack_);
802 int incomingCSeq = m4Request.GetCSeq();
803 if (timeoutTimer_ && isFirstCast) {
804 timeoutTimer_->StartTimer(WFD_TIMEOUT_6_SECOND, "Waiting for M5/SET_PARAMETER Triger request");
805 }
806 // Send M4 response
807 if (!SendCommonResponse(incomingCSeq)) {
808 if (timeoutTimer_) {
809 timeoutTimer_->StopTimer();
810 }
811 NotifyServiceError();
812 return false;
813 }
814
815 isFirstCast = false;
816 return true;
817 }
818
SendCommonResponse(int32_t cseq)819 bool WfdSinkSession::SendCommonResponse(int32_t cseq)
820 {
821 SHARING_LOGD("trace.");
822 if (!rtspClient_) {
823 return false;
824 }
825
826 RtspResponse response(cseq, RTSP_STATUS_OK);
827 std::string res(response.Stringify());
828
829 SHARING_LOGI("sessionId: %{public}d send common response, cseq: %{public}d.", GetId(), cseq);
830 bool ret = rtspClient_->Send(res.data(), res.length());
831 if (!ret) {
832 SHARING_LOGE("Failed to send common response.");
833 }
834
835 return ret;
836 }
837
HandleTriggerMethod(int32_t cseq,const std::string & method)838 bool WfdSinkSession::HandleTriggerMethod(int32_t cseq, const std::string &method)
839 {
840 SHARING_LOGD("trace.");
841 if (method == RTSP_METHOD_SETUP) {
842 // this is M5 request
843 if (timeoutTimer_) {
844 timeoutTimer_->StopTimer();
845 }
846 if (!SendCommonResponse(cseq)) {
847 NotifyServiceError();
848 return false;
849 }
850 SendM6Request();
851 } else if (method == RTSP_METHOD_TEARDOWN) {
852 SHARING_LOGW("sessionId: %{public}u, receive Tearndown msg: %{public}s.", GetId(), method.c_str());
853 if (!SendCommonResponse(cseq)) {
854 NotifyServiceError();
855 return false;
856 }
857 SendM8Request();
858 } else {
859 SHARING_LOGE("ignore UNSUPPORTED triggered method '%{public}s'.", method.c_str());
860 }
861
862 return true;
863 }
864
SendM6Request()865 bool WfdSinkSession::SendM6Request()
866 {
867 SHARING_LOGD("trace.");
868 if (!rtspClient_) {
869 return false;
870 }
871
872 WfdRtspM6Request m6Request(++cseq_, rtspUrl_);
873 m6Request.SetClientPort(localRtpPort_);
874
875 responseHandlers_[cseq_] = [this](auto &&PH1, auto &&PH2) {
876 HandleM6Response(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2));
877 };
878 if (timeoutTimer_) {
879 timeoutTimer_->StartTimer(WFD_TIMEOUT_5_SECOND, "Waiting for M6/SETUP response");
880 }
881
882 SHARING_LOGI("sessionId: %{public}d send M6 request, cseq: %{public}d.", GetId(), cseq_);
883 std::string m6Req(m6Request.Stringify());
884 bool ret = rtspClient_->Send(m6Req.data(), m6Req.length());
885 if (!ret) {
886 SHARING_LOGE("Failed to send M6 request, cseq: %{public}d.", cseq_);
887 responseHandlers_.erase(cseq_);
888 if (timeoutTimer_) {
889 timeoutTimer_->StopTimer();
890 }
891
892 NotifyServiceError();
893 return false;
894 }
895
896 wfdState_ = WfdSessionState::READY;
897 return ret;
898 }
899
SendM7Request()900 bool WfdSinkSession::SendM7Request()
901 {
902 SHARING_LOGD("trace.");
903 if (!rtspClient_) {
904 return false;
905 }
906
907 WfdRtspM7Request m7Request(++cseq_, rtspUrl_);
908 if (!rtspSession_.empty()) {
909 m7Request.SetSession(rtspSession_);
910 }
911
912 responseHandlers_[cseq_] = [this](auto &&PH1, auto &&PH2) {
913 HandleM7Response(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2));
914 };
915
916 if (timeoutTimer_) {
917 timeoutTimer_->StartTimer(WFD_TIMEOUT_5_SECOND, "Waiting for M7/PLAY response");
918 }
919 SHARING_LOGI("sessionId: %{public}d send M7 request, cseq: %{public}d.", GetId(), cseq_);
920 std::string m7Req(m7Request.Stringify());
921 bool ret = rtspClient_->Send(m7Req.data(), m7Req.length());
922 if (!ret) {
923 SHARING_LOGE("Failed to send M7 request cseq: %{public}d.", cseq_);
924 responseHandlers_.erase(cseq_);
925 if (timeoutTimer_) {
926 timeoutTimer_->StopTimer();
927 }
928 NotifyServiceError();
929 return false;
930 }
931 WfdSinkHiSysEvent::GetInstance().Report(__func__, "", SinkStage::SEND_M7_MSG, SinkStageRes::SUCCESS);
932
933 return ret;
934 }
935
SendM8Request()936 bool WfdSinkSession::SendM8Request()
937 {
938 SHARING_LOGD("trace.");
939 if (wfdState_ == WfdSessionState::STOPPING) {
940 SHARING_LOGI("already send m8 reqeust.");
941 return true;
942 }
943
944 if (!rtspClient_ || !connected_) {
945 SHARING_LOGW("client null or disconnecting.");
946 return false;
947 }
948
949 WfdRtspM8Request m8Request(++cseq_, rtspUrl_);
950 if (!rtspSession_.empty()) {
951 m8Request.SetSession(rtspSession_);
952 }
953
954 responseHandlers_[cseq_] = [this](auto &&PH1, auto &&PH2) {
955 HandleM8Response(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2));
956 };
957
958 SHARING_LOGI("sessionId: %{public}d send M8 request, cseq: %{public}d.", GetId(), cseq_);
959 std::string m8Req(m8Request.Stringify());
960 bool ret = rtspClient_->Send(m8Req.data(), m8Req.length());
961 if (!ret) {
962 SHARING_LOGE("sessionId: %{public}u, failed to send M8 request, cseq: %{public}d.", GetId(), cseq_);
963 responseHandlers_.erase(cseq_);
964 } else {
965 SHARING_LOGI("sessionId: %{public}u,Send TEARDOWN ok.", GetId());
966 }
967 wfdState_ = WfdSessionState::STOPPING;
968 return ret;
969 }
970
SendIDRRequest()971 bool WfdSinkSession::SendIDRRequest()
972 {
973 SHARING_LOGD("trace.");
974 if (wfdState_ != WfdSessionState::PLAYING) {
975 return false;
976 }
977
978 if (!rtspClient_) {
979 return false;
980 }
981
982 WfdRtspIDRRequest idrRequest(++cseq_, rtspUrl_);
983 if (!rtspSession_.empty()) {
984 idrRequest.SetSession(rtspSession_);
985 }
986
987 responseHandlers_[cseq_] = [this](auto &&PH1, auto &&PH2) {
988 HandleCommonResponse(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2));
989 };
990 if (timeoutTimer_) {
991 timeoutTimer_->StartTimer(WFD_TIMEOUT_6_SECOND, "Waiting for WFD SET_PARAMETER/wfd_idr_request response");
992 }
993
994 std::string idrReq(idrRequest.Stringify());
995 bool ret = rtspClient_->Send(idrReq.data(), idrReq.length());
996 if (!ret) {
997 SHARING_LOGE("Failed to send IDR request.");
998 }
999
1000 return ret;
1001 }
1002
NotifyServiceError(SharingErrorCode errorCode)1003 void WfdSinkSession::NotifyServiceError(SharingErrorCode errorCode)
1004 {
1005 SHARING_LOGD("trace.");
1006 auto statusMsg = std::make_shared<SessionStatusMsg>();
1007 statusMsg->msg = std::make_shared<EventMsg>();
1008 statusMsg->status = STATE_SESSION_ERROR;
1009 statusMsg->msg->requestId = 0;
1010 statusMsg->msg->errorCode = errorCode;
1011
1012 NotifyAgentSessionStatus(statusMsg);
1013 }
1014
NotifySessionInterrupted()1015 void WfdSinkSession::NotifySessionInterrupted()
1016 {
1017 SHARING_LOGD("trace.");
1018 auto statusMsg = std::make_shared<SessionStatusMsg>();
1019 statusMsg->status = STATE_SESSION_INTERRUPTED;
1020
1021 NotifyAgentSessionStatus(statusMsg);
1022 }
1023
1024 REGISTER_CLASS_REFLECTOR(WfdSinkSession);
1025 } // namespace Sharing
1026 } // namespace OHOS
1027