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