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