• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &params)
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> &params, WfdRtspM3Response &m3Response)
740 {
741     for (auto &param : 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 &param)
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