/* * 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 "rtc_base/logging.h" namespace cricket { 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 cricket