/* * Copyright 2020 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "pc/peer_connection_message_handler.h" #include #include "api/jsep.h" #include "api/media_stream_interface.h" #include "api/peer_connection_interface.h" #include "pc/stats_collector_interface.h" #include "rtc_base/synchronization/sequence_checker.h" namespace webrtc { namespace { enum { MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, MSG_SET_SESSIONDESCRIPTION_FAILED, MSG_CREATE_SESSIONDESCRIPTION_FAILED, MSG_GETSTATS, MSG_REPORT_USAGE_PATTERN, MSG_ON_ERROR_DEMUXING_PACKET, }; struct SetSessionDescriptionMsg : public rtc::MessageData { explicit SetSessionDescriptionMsg( webrtc::SetSessionDescriptionObserver* observer) : observer(observer) {} rtc::scoped_refptr observer; RTCError error; }; struct CreateSessionDescriptionMsg : public rtc::MessageData { explicit CreateSessionDescriptionMsg( webrtc::CreateSessionDescriptionObserver* observer) : observer(observer) {} rtc::scoped_refptr observer; RTCError error; }; struct GetStatsMsg : public rtc::MessageData { GetStatsMsg(webrtc::StatsObserver* observer, StatsCollectorInterface* stats, webrtc::MediaStreamTrackInterface* track) : observer(observer), stats(stats), track(track) {} rtc::scoped_refptr observer; StatsCollectorInterface* stats; rtc::scoped_refptr track; }; struct RequestUsagePatternMsg : public rtc::MessageData { explicit RequestUsagePatternMsg(std::function func) : function(func) {} std::function function; }; struct OnErrorDemuxingPacketMsg : public rtc::MessageData { explicit OnErrorDemuxingPacketMsg(webrtc::ErrorDemuxingPacketObserver* observer, uint32_t ssrc) : observer(observer), ssrc(ssrc) {} rtc::scoped_refptr observer; uint32_t ssrc; }; } // namespace PeerConnectionMessageHandler::~PeerConnectionMessageHandler() { // Process all pending notifications in the message queue. If we don't do // this, requests will linger and not know they succeeded or failed. rtc::MessageList list; signaling_thread()->Clear(this, rtc::MQID_ANY, &list); for (auto& msg : list) { if (msg.message_id == MSG_CREATE_SESSIONDESCRIPTION_FAILED) { // Processing CreateOffer() and CreateAnswer() messages ensures their // observers are invoked even if the PeerConnection is destroyed early. OnMessage(&msg); } else { // TODO(hbos): Consider processing all pending messages. This would mean // that SetLocalDescription() and SetRemoteDescription() observers are // informed of successes and failures; this is currently NOT the case. delete msg.pdata; } } } void PeerConnectionMessageHandler::OnMessage(rtc::Message* msg) { RTC_DCHECK_RUN_ON(signaling_thread()); switch (msg->message_id) { case MSG_SET_SESSIONDESCRIPTION_SUCCESS: { SetSessionDescriptionMsg* param = static_cast(msg->pdata); param->observer->OnSuccess(); delete param; break; } case MSG_SET_SESSIONDESCRIPTION_FAILED: { SetSessionDescriptionMsg* param = static_cast(msg->pdata); param->observer->OnFailure(std::move(param->error)); delete param; break; } case MSG_CREATE_SESSIONDESCRIPTION_FAILED: { CreateSessionDescriptionMsg* param = static_cast(msg->pdata); param->observer->OnFailure(std::move(param->error)); delete param; break; } case MSG_GETSTATS: { GetStatsMsg* param = static_cast(msg->pdata); StatsReports reports; param->stats->GetStats(param->track, &reports); param->observer->OnComplete(reports); delete param; break; } case MSG_REPORT_USAGE_PATTERN: { RequestUsagePatternMsg* param = static_cast(msg->pdata); param->function(); delete param; break; } case MSG_ON_ERROR_DEMUXING_PACKET: { OnErrorDemuxingPacketMsg* param = static_cast(msg->pdata); param->observer->OnErrorDemuxingPacket(param->ssrc); delete param; break; } default: RTC_NOTREACHED() << "Not implemented"; break; } } void PeerConnectionMessageHandler::PostSetSessionDescriptionSuccess( SetSessionDescriptionObserver* observer) { SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); signaling_thread()->Post(RTC_FROM_HERE, this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); } void PeerConnectionMessageHandler::PostSetSessionDescriptionFailure( SetSessionDescriptionObserver* observer, RTCError&& error) { RTC_DCHECK(!error.ok()); SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); msg->error = std::move(error); signaling_thread()->Post(RTC_FROM_HERE, this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); } void PeerConnectionMessageHandler::PostCreateSessionDescriptionFailure( CreateSessionDescriptionObserver* observer, RTCError error) { RTC_DCHECK(!error.ok()); CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); msg->error = std::move(error); signaling_thread()->Post(RTC_FROM_HERE, this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); } void PeerConnectionMessageHandler::PostGetStats( StatsObserver* observer, StatsCollectorInterface* stats, MediaStreamTrackInterface* track) { signaling_thread()->Post(RTC_FROM_HERE, this, MSG_GETSTATS, new GetStatsMsg(observer, stats, track)); } void PeerConnectionMessageHandler::RequestUsagePatternReport( std::function func, int delay_ms) { signaling_thread()->PostDelayed(RTC_FROM_HERE, delay_ms, this, MSG_REPORT_USAGE_PATTERN, new RequestUsagePatternMsg(func)); } void PeerConnectionMessageHandler::PostErrorDemuxingPacket( ErrorDemuxingPacketObserver* observer, uint32_t ssrc) { signaling_thread()->Post(RTC_FROM_HERE, this, MSG_ON_ERROR_DEMUXING_PACKET, new OnErrorDemuxingPacketMsg(observer, ssrc)); } } // namespace webrtc