| /* | |
| * Copyright 2004 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/rtcp_mux_filter.h" | |
| #include "pc/session_description.h" | |
| #include "rtc_base/logging.h" | |
| namespace webrtc { | |
| RtcpMuxFilter::RtcpMuxFilter() : state_(ST_INIT), offer_enable_(false) {} | |
| bool RtcpMuxFilter::IsFullyActive() const { | |
| return state_ == ST_ACTIVE; | |
| } | |
| bool RtcpMuxFilter::IsProvisionallyActive() const { | |
| return state_ == ST_SENTPRANSWER || state_ == ST_RECEIVEDPRANSWER; | |
| } | |
| bool RtcpMuxFilter::IsActive() const { | |
| return IsFullyActive() || IsProvisionallyActive(); | |
| } | |
| void RtcpMuxFilter::SetActive() { | |
| state_ = ST_ACTIVE; | |
| } | |
| bool RtcpMuxFilter::SetOffer(bool offer_enable, ContentSource src) { | |
| if (state_ == ST_ACTIVE) { | |
| // Fail if we try to deactivate and no-op if we try and activate. | |
| return offer_enable; | |
| } | |
| if (!ExpectOffer(offer_enable, src)) { | |
| RTC_LOG(LS_ERROR) << "Invalid state for change of RTCP mux offer"; | |
| return false; | |
| } | |
| offer_enable_ = offer_enable; | |
| state_ = (src == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER; | |
| return true; | |
| } | |
| bool RtcpMuxFilter::SetProvisionalAnswer(bool answer_enable, | |
| ContentSource src) { | |
| if (state_ == ST_ACTIVE) { | |
| // Fail if we try to deactivate and no-op if we try and activate. | |
| return answer_enable; | |
| } | |
| if (!ExpectAnswer(src)) { | |
| RTC_LOG(LS_ERROR) << "Invalid state for RTCP mux provisional answer"; | |
| return false; | |
| } | |
| if (offer_enable_) { | |
| if (answer_enable) { | |
| if (src == CS_REMOTE) | |
| state_ = ST_RECEIVEDPRANSWER; | |
| else // CS_LOCAL | |
| state_ = ST_SENTPRANSWER; | |
| } else { | |
| // The provisional answer doesn't want to use RTCP mux. | |
| // Go back to the original state after the offer was set and wait for next | |
| // provisional or final answer. | |
| if (src == CS_REMOTE) | |
| state_ = ST_SENTOFFER; | |
| else // CS_LOCAL | |
| state_ = ST_RECEIVEDOFFER; | |
| } | |
| } else if (answer_enable) { | |
| // If the offer didn't specify RTCP mux, the answer shouldn't either. | |
| RTC_LOG(LS_WARNING) << "Invalid parameters in RTCP mux provisional answer"; | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool RtcpMuxFilter::SetAnswer(bool answer_enable, ContentSource src) { | |
| if (state_ == ST_ACTIVE) { | |
| // Fail if we try to deactivate and no-op if we try and activate. | |
| return answer_enable; | |
| } | |
| if (!ExpectAnswer(src)) { | |
| RTC_LOG(LS_ERROR) << "Invalid state for RTCP mux answer, state is " | |
| << state_ << ", source is " << src; | |
| return false; | |
| } | |
| if (offer_enable_ && answer_enable) { | |
| state_ = ST_ACTIVE; | |
| } else if (answer_enable) { | |
| // If the offer didn't specify RTCP mux, the answer shouldn't either. | |
| RTC_LOG(LS_WARNING) << "Invalid parameters in RTCP mux answer"; | |
| return false; | |
| } else { | |
| state_ = ST_INIT; | |
| } | |
| return true; | |
| } | |
| bool RtcpMuxFilter::ExpectOffer(bool offer_enable, ContentSource source) { | |
| return ((state_ == ST_INIT) || | |
| (state_ == ST_ACTIVE && offer_enable == offer_enable_) || | |
| (state_ == ST_SENTOFFER && source == CS_LOCAL) || | |
| (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE)); | |
| } | |
| bool RtcpMuxFilter::ExpectAnswer(ContentSource source) { | |
| return ((state_ == ST_SENTOFFER && source == CS_REMOTE) || | |
| (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) || | |
| (state_ == ST_SENTPRANSWER && source == CS_LOCAL) || | |
| (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE)); | |
| } | |
| } // namespace webrtc |