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 <RtcpRrPacket.h>
18 #include <RtcpReportBlock.h>
19 #include <RtpTrace.h>
20 
RtcpRrPacket()21 RtcpRrPacket::RtcpRrPacket() :
22         m_objReportBlkList(std::list<RtcpReportBlock*>()),
23         m_pobjExt(nullptr)
24 {
25 }
26 
~RtcpRrPacket()27 RtcpRrPacket::~RtcpRrPacket()
28 {
29     // delete all RtcpReportBlock objects
30     for (const auto& pobjReptBlk : m_objReportBlkList)
31     {
32         delete pobjReptBlk;
33     }
34     m_objReportBlkList.clear();
35 
36     if (m_pobjExt != nullptr)
37     {
38         delete m_pobjExt;
39         m_pobjExt = nullptr;
40     }
41 }
42 
addReportBlkElm(IN RtcpReportBlock * pobjReptBlk)43 RtpDt_Void RtcpRrPacket::addReportBlkElm(IN RtcpReportBlock* pobjReptBlk)
44 {
45     m_objReportBlkList.push_back(pobjReptBlk);
46 }
47 
setRtcpHdrInfo(RtcpHeader & objRtcpHdr)48 RtpDt_Void RtcpRrPacket::setRtcpHdrInfo(RtcpHeader& objRtcpHdr)
49 {
50     m_objRtcpHdr = objRtcpHdr;
51 }
52 
getRtcpHdrInfo()53 RtcpHeader* RtcpRrPacket::getRtcpHdrInfo()
54 {
55     return &m_objRtcpHdr;
56 }
57 
getReportBlockList()58 std::list<RtcpReportBlock*>& RtcpRrPacket::getReportBlockList()
59 {
60     return m_objReportBlkList;
61 }
62 
getExtHdrInfo()63 RtpBuffer* RtcpRrPacket::getExtHdrInfo()
64 {
65     return m_pobjExt;
66 }
67 
setExtHdrInfo(IN RtpBuffer * pobjExtHdr)68 RtpDt_Void RtcpRrPacket::setExtHdrInfo(IN RtpBuffer* pobjExtHdr)
69 {
70     m_pobjExt = pobjExtHdr;
71 }
72 
decodeRrPacket(IN RtpDt_UChar * pucRrBuf,IN RtpDt_UInt16 & usRrLen,IN RtpDt_UInt16 usProfExtLen)73 eRTP_STATUS_CODE RtcpRrPacket::decodeRrPacket(
74         IN RtpDt_UChar* pucRrBuf, IN RtpDt_UInt16& usRrLen, IN RtpDt_UInt16 usProfExtLen)
75 {
76     RtpDt_UInt16 usRepBlkLen = usRrLen - usProfExtLen;
77     while (usRepBlkLen >= RTP_24)
78     {
79         RtcpReportBlock* pobjRptBlk = new RtcpReportBlock();
80         if (pobjRptBlk == nullptr)
81         {
82             RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
83             return RTP_MEMORY_FAIL;
84         }
85         pobjRptBlk->decodeReportBlock(pucRrBuf);
86         pucRrBuf = pucRrBuf + RTP_24;
87         usRepBlkLen = usRepBlkLen - RTP_24;
88         addReportBlkElm(pobjRptBlk);
89     }
90 
91     // profile specific extensions
92     if (usProfExtLen > RTP_ZERO)
93     {
94         RtpDt_UChar* pcProfExtBuf = new RtpDt_UChar[usProfExtLen];
95         if (pcProfExtBuf == nullptr)
96         {
97             RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
98             return RTP_MEMORY_FAIL;
99         }
100 
101         m_pobjExt = new RtpBuffer();
102         if (m_pobjExt == nullptr)
103         {
104             RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
105             delete[] pcProfExtBuf;
106             return RTP_MEMORY_FAIL;
107         }
108 
109         memcpy(pcProfExtBuf, pucRrBuf, usProfExtLen);
110         m_pobjExt->setBufferInfo(usProfExtLen, pcProfExtBuf);
111     }
112 
113     return RTP_SUCCESS;
114 }  // decodeRrPacket
115 
formRrPacket(OUT RtpBuffer * pobjRtcpPktBuf,IN eRtp_Bool bHdrInfo)116 eRTP_STATUS_CODE RtcpRrPacket::formRrPacket(OUT RtpBuffer* pobjRtcpPktBuf, IN eRtp_Bool bHdrInfo)
117 {
118     RTP_TRACE_MESSAGE("formRrPacket", 0, 0);
119     RtpDt_UInt32 uiRtPktPos = pobjRtcpPktBuf->getLength();
120 
121     if (bHdrInfo == RTP_TRUE)
122     {
123         RtpDt_UInt32 uiRepBlkPos = uiRtPktPos + RTP_EIGHT;
124         pobjRtcpPktBuf->setLength(uiRepBlkPos);
125     }
126 
127     // m_objReportBlkList
128     for (auto& pobjRepBlk : m_objReportBlkList)
129     {
130         pobjRepBlk->formReportBlock(pobjRtcpPktBuf);
131     }  // for
132 
133     RtpDt_UInt32 uiCurPos = pobjRtcpPktBuf->getLength();
134 #ifdef ENABLE_RTCPEXT
135     if (m_pobjExt != nullptr)
136     {
137         RtpDt_UChar* pucExtHdr = m_pobjExt->getBuffer();
138         RtpDt_UInt32 uiExtHdrLen = m_pobjExt->getLength();
139         RtpDt_UChar* pucBuffer = pobjRtcpPktBuf->getBuffer();
140         memcpy(pucBuffer + uiCurPos, pucExtHdr, uiExtHdrLen);
141         uiCurPos = uiCurPos + uiExtHdrLen;
142         pobjRtcpPktBuf->setLength(uiCurPos);
143     }  // extension header
144 #endif
145     if (bHdrInfo == RTP_TRUE)
146     {
147         RtpDt_UInt32 uiRrPktLen = uiCurPos - uiRtPktPos;
148 
149 #ifdef ENABLE_PADDING
150         RtpDt_UInt32 uiPadLen = uiRrPktLen % RTP_WORD_SIZE;
151         if (uiPadLen > RTP_ZERO)
152         {
153             uiPadLen = RTP_WORD_SIZE - uiPadLen;
154             uiRrPktLen = uiRrPktLen + uiPadLen;
155             uiCurPos = uiCurPos + uiPadLen;
156             RtpDt_UChar* pucBuffer = pobjRtcpPktBuf->getBuffer();
157             pucBuffer = pucBuffer + uiCurPos;
158             memset(pucBuffer, RTP_ZERO, uiPadLen);
159 
160             pucBuffer = pucBuffer + uiPadLen;
161             pucBuffer = pucBuffer - RTP_ONE;
162             *(reinterpret_cast<RtpDt_UChar*>(pucBuffer)) = (RtpDt_UChar)uiPadLen;
163 
164             // set pad bit in header
165             m_objRtcpHdr.setPadding();
166             // set length in header
167             m_objRtcpHdr.setLength(uiRrPktLen);
168         }
169         else
170 #endif
171         {
172             // set length in header
173             m_objRtcpHdr.setLength(uiRrPktLen);
174         }
175 
176         pobjRtcpPktBuf->setLength(uiRtPktPos);
177         m_objRtcpHdr.formRtcpHeader(pobjRtcpPktBuf);
178     }
179     // set the actual position of the RTCP compound packet
180     pobjRtcpPktBuf->setLength(uiCurPos);
181 
182     return RTP_SUCCESS;
183 }  // formRrPacket
184