1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <RtcpHeader.h>
18 #include <RtpTrace.h>
19 
RtcpHeader()20 RtcpHeader::RtcpHeader() :
21         m_ucVersion(RTP_ZERO),
22         m_ucIsPadding(eRTP_FALSE),
23         m_ucReceptionReportCount(RTP_ZERO),
24         m_ucPacketType(RTP_ZERO),
25         m_usLength(RTP_ZERO),
26         m_uiSsrc(RTP_ZERO)
27 {
28 }
29 
~RtcpHeader()30 RtcpHeader::~RtcpHeader() {}
31 
setVersion(IN RtpDt_UChar ucVersion)32 eRtp_Bool RtcpHeader::setVersion(IN RtpDt_UChar ucVersion)
33 {
34     if (ucVersion > MAX_RTP_VERSION)
35     {
36         RTP_TRACE_ERROR("Invalid RTP version %d", ucVersion, 0);
37         return eRTP_FALSE;
38     }
39 
40     m_ucVersion = ucVersion;
41     return eRTP_TRUE;
42 }
43 
getVersion()44 RtpDt_UChar RtcpHeader::getVersion()
45 {
46     return m_ucVersion;
47 }
48 
setPadding(eRtp_Bool padding)49 RtpDt_Void RtcpHeader::setPadding(eRtp_Bool padding)
50 {
51     m_ucIsPadding = padding;
52 }
53 
getPadding()54 eRtp_Bool RtcpHeader::getPadding()
55 {
56     return m_ucIsPadding;
57 }
58 
setReceptionReportCount(IN RtpDt_UChar ucReceptionReportCount)59 eRtp_Bool RtcpHeader::setReceptionReportCount(IN RtpDt_UChar ucReceptionReportCount)
60 {
61     if (ucReceptionReportCount > MAX_RECEPTION_REPORT_COUNT)
62     {
63         RTP_TRACE_ERROR("Invalid Reception Report Count %d", ucReceptionReportCount, 0);
64         return eRTP_FALSE;
65     }
66 
67     m_ucReceptionReportCount = ucReceptionReportCount;
68     return eRTP_TRUE;
69 }
70 
getReceptionReportCount()71 RtpDt_UChar RtcpHeader::getReceptionReportCount()
72 {
73     return m_ucReceptionReportCount;
74 }
75 
setPacketType(IN RtpDt_UChar ucPacketType)76 RtpDt_Void RtcpHeader::setPacketType(IN RtpDt_UChar ucPacketType)
77 {
78     m_ucPacketType = ucPacketType;
79 }
80 
getPacketType()81 RtpDt_UChar RtcpHeader::getPacketType()
82 {
83     return m_ucPacketType;
84 }
85 
setLength(IN RtpDt_UInt32 usLength)86 RtpDt_Void RtcpHeader::setLength(IN RtpDt_UInt32 usLength)
87 {
88     m_usLength = usLength;
89 }
90 
getLength()91 RtpDt_UInt32 RtcpHeader::getLength()
92 {
93     return m_usLength;
94 }
95 
setSsrc(IN RtpDt_UInt32 uiSsrc)96 RtpDt_Void RtcpHeader::setSsrc(IN RtpDt_UInt32 uiSsrc)
97 {
98     m_uiSsrc = uiSsrc;
99 }
100 
getSsrc()101 RtpDt_UInt32 RtcpHeader::getSsrc()
102 {
103     return m_uiSsrc;
104 }
105 
operator ==(const RtcpHeader & objRtcpHeader) const106 bool RtcpHeader::operator==(const RtcpHeader& objRtcpHeader) const
107 {
108     return (m_ucVersion == objRtcpHeader.m_ucVersion &&
109             m_ucIsPadding == objRtcpHeader.m_ucIsPadding &&
110             m_ucReceptionReportCount == objRtcpHeader.m_ucReceptionReportCount &&
111             m_ucPacketType == objRtcpHeader.m_ucPacketType &&
112             m_usLength == objRtcpHeader.m_usLength && m_uiSsrc == objRtcpHeader.m_uiSsrc);
113 }
114 
decodeRtcpHeader(IN RtpDt_UChar * pRtcpBuffer,RtpDt_Int32 length)115 eRtp_Bool RtcpHeader::decodeRtcpHeader(IN RtpDt_UChar* pRtcpBuffer, RtpDt_Int32 length)
116 {
117     if (length < RTP_WORD_SIZE)
118         return eRTP_FALSE;
119 
120     RtpDt_UInt32 uiTemp4Data = RtpOsUtil::Ntohl(*(reinterpret_cast<RtpDt_UInt32*>(pRtcpBuffer)));
121 
122     // Packet Length
123     m_usLength = uiTemp4Data & 0x0000FFFF;
124     m_usLength *= RTP_WORD_SIZE;  // Convert length from WORD count to Bytes count
125 
126     // Packet Type
127     m_ucPacketType = (uiTemp4Data >> RTP_16) & 0x000000FF;
128 
129     // 8-MSB bits of 32-bit data.
130     uiTemp4Data = uiTemp4Data >> RTP_24;
131 
132     // version. 2-MSB bits
133     m_ucVersion = (RtpDt_UInt8)(uiTemp4Data >> RTP_SIX) & 0x00000003;
134 
135     // padding
136     m_ucIsPadding = ((uiTemp4Data >> RTP_FIVE) & 0x00000001) ? eRTP_TRUE : eRTP_FALSE;
137 
138     // RC
139     m_ucReceptionReportCount = RtpDt_UInt8(uiTemp4Data & 0x0000001F);
140 
141     // SSRC
142     if (m_usLength)
143     {
144         pRtcpBuffer = pRtcpBuffer + RTP_WORD_SIZE;
145         m_uiSsrc = RtpOsUtil::Ntohl(*(reinterpret_cast<RtpDt_UInt32*>(pRtcpBuffer)));
146     }
147 
148     return eRTP_SUCCESS;
149 }  // decodeRtcpHeader
150 
formRtcpHeader(OUT RtpBuffer * pobjRtcpPktBuf)151 eRtp_Bool RtcpHeader::formRtcpHeader(OUT RtpBuffer* pobjRtcpPktBuf)
152 {
153     // do partial encoding
154     formPartialRtcpHeader(pobjRtcpPktBuf);
155 
156     RtpDt_UChar* pcRtcpHdrBuf = pobjRtcpPktBuf->getBuffer();
157     RtpDt_UInt32 uiBufPos = pobjRtcpPktBuf->getLength();
158     pcRtcpHdrBuf = pcRtcpHdrBuf + uiBufPos;
159 
160     // ssrc
161     *(reinterpret_cast<RtpDt_UInt32*>(pcRtcpHdrBuf)) = RtpOsUtil::Ntohl(m_uiSsrc);
162 
163     uiBufPos = uiBufPos + RTP_WORD_SIZE;
164     pobjRtcpPktBuf->setLength(uiBufPos);
165 
166     return eRTP_SUCCESS;
167 }  // formRtcpHeader
168 
formPartialRtcpHeader(OUT RtpBuffer * pobjRtcpPktBuf)169 eRtp_Bool RtcpHeader::formPartialRtcpHeader(OUT RtpBuffer* pobjRtcpPktBuf)
170 {
171     RtpDt_UInt16 usUtlData = RTP_ZERO;
172     RtpDt_UInt16 usTmpData = RTP_ZERO;
173     RtpDt_UChar* pcRtcpHdrBuf = pobjRtcpPktBuf->getBuffer();
174     RtpDt_UInt32 uiBufPos = pobjRtcpPktBuf->getLength();
175 
176     pcRtcpHdrBuf = pcRtcpHdrBuf + uiBufPos;
177 
178     // version 2 bits
179     RTP_FORM_HDR_UTL(usUtlData, m_ucVersion, RTP_VER_SHIFT_VAL, usTmpData);
180     // padding 1 bit
181     RTP_FORM_HDR_UTL(usUtlData, m_ucIsPadding, RTP_PAD_SHIFT_VAL, usTmpData);
182     // RC 5 bits
183     RTP_FORM_HDR_UTL(usUtlData, m_ucReceptionReportCount, RTCP_RC_SHIFT_VAL, usTmpData);
184     // PT 8 bits
185     RTP_FORM_HDR_UTL(usUtlData, m_ucPacketType, RTCP_PT_SHIFT_VAL, usTmpData);
186 
187     RtpDt_UInt32 uiByte4Data = usTmpData;
188     uiByte4Data = uiByte4Data << RTP_SIXTEEN;
189 
190     // convert m_usLength into words - 1
191     m_usLength = m_usLength / RTP_WORD_SIZE;
192     m_usLength = m_usLength - RTP_ONE;
193 
194     // length 16 bits
195     uiByte4Data = uiByte4Data | m_usLength;
196 
197     *(reinterpret_cast<RtpDt_UInt32*>(pcRtcpHdrBuf)) = RtpOsUtil::Ntohl(uiByte4Data);
198 
199     uiBufPos = uiBufPos + RTP_WORD_SIZE;
200     pobjRtcpPktBuf->setLength(uiBufPos);
201 
202     return eRTP_SUCCESS;
203 
204 }  // end formPartialRtcpHeader
205 
populateRtcpHeader(IN RtpDt_UChar ucReceptionReportCount,IN RtpDt_UChar ucPacketType,IN RtpDt_UInt32 uiSsrc)206 RtpDt_Void RtcpHeader::populateRtcpHeader(
207         IN RtpDt_UChar ucReceptionReportCount, IN RtpDt_UChar ucPacketType, IN RtpDt_UInt32 uiSsrc)
208 {
209     m_ucVersion = RTP_VERSION_NUM;
210     m_ucReceptionReportCount = ucReceptionReportCount;
211     m_ucPacketType = ucPacketType;
212     m_uiSsrc = uiSsrc;
213 }
214