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> ¶ms)
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> ¶ms, WfdRtspM3Response &m3Response)
713 {
714 for (auto ¶m : 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 ¶m)
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