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 <RtcpByePacket.h>
18 #include <RtpTrace.h>
19 
RtcpByePacket()20 RtcpByePacket::RtcpByePacket() :
21         m_uiSsrcList(std::list<RtpDt_UInt32*>()),
22         m_pReason(nullptr)
23 {
24 }  // Constructor
25 
~RtcpByePacket()26 RtcpByePacket::~RtcpByePacket()
27 {
28     // delete all ssrc objects
29     for (const auto& puiSsrc : m_uiSsrcList)
30     {
31         delete puiSsrc;
32     }
33     m_uiSsrcList.clear();
34 
35     if (m_pReason != nullptr)
36     {
37         delete m_pReason;
38         m_pReason = nullptr;
39     }
40 }  // Destructor
41 
setRtcpHdrInfo(RtcpHeader & objRtcpHeader)42 RtpDt_Void RtcpByePacket::setRtcpHdrInfo(RtcpHeader& objRtcpHeader)
43 {
44     m_objRtcpHdr = objRtcpHeader;
45 }
46 
getRtcpHdrInfo()47 RtcpHeader* RtcpByePacket::getRtcpHdrInfo()
48 {
49     return &m_objRtcpHdr;
50 }
51 
getSsrcList()52 std::list<RtpDt_UInt32*>& RtcpByePacket::getSsrcList()
53 {
54     return m_uiSsrcList;
55 }
56 
getReason()57 RtpBuffer* RtcpByePacket::getReason()
58 {
59     return m_pReason;
60 }
61 
setReason(IN RtpBuffer * pobjReason)62 RtpDt_Void RtcpByePacket::setReason(IN RtpBuffer* pobjReason)
63 {
64     m_pReason = pobjReason;
65 }
66 
decodeByePacket(IN RtpDt_UChar * pucByeBuf,IN RtpDt_UInt16 usByeLen)67 eRTP_STATUS_CODE RtcpByePacket::decodeByePacket(IN RtpDt_UChar* pucByeBuf, IN RtpDt_UInt16 usByeLen)
68 {
69     RtpDt_UChar ucSsrcCnt = m_objRtcpHdr.getReceptionReportCount();
70     // m_uiSsrcList
71     while (ucSsrcCnt > RTP_ONE && usByeLen >= RTP_WORD_SIZE)
72     {
73         RtpDt_UInt32* puiRcvdSsrc = nullptr;
74         puiRcvdSsrc = new RtpDt_UInt32();
75         if (puiRcvdSsrc == nullptr)
76         {
77             RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
78             return RTP_MEMORY_FAIL;
79         }
80 
81         (*puiRcvdSsrc) = RtpOsUtil::Ntohl(*(reinterpret_cast<RtpDt_UInt32*>(pucByeBuf)));
82         pucByeBuf = pucByeBuf + RTP_WORD_SIZE;
83 
84         m_uiSsrcList.push_back(puiRcvdSsrc);
85         ucSsrcCnt = ucSsrcCnt - RTP_ONE;
86         usByeLen -= RTP_WORD_SIZE;
87     }  // while
88 
89     if (usByeLen >= RTP_ONE)  // check if optional length is present.
90     {
91         // m_pReason
92         RtpDt_UInt32 uiByte4Data = RtpOsUtil::Ntohl(*(reinterpret_cast<RtpDt_UInt32*>(pucByeBuf)));
93         pucByeBuf = pucByeBuf + RTP_ONE;
94         uiByte4Data = uiByte4Data >> RTP_24;  // length of "Reason for leaving"
95         if (uiByte4Data > RTP_ZERO)
96         {
97             RtpDt_UChar* pucReason = new RtpDt_UChar[uiByte4Data];
98             if (pucReason == nullptr)
99             {
100                 RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
101                 return RTP_MEMORY_FAIL;
102             }
103 
104             m_pReason = new RtpBuffer();
105             if (m_pReason == nullptr)
106             {
107                 RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
108                 delete[] pucReason;
109                 return RTP_MEMORY_FAIL;
110             }
111             memset(pucReason, RTP_ZERO, uiByte4Data);
112             memcpy(pucReason, pucByeBuf, uiByte4Data);
113             m_pReason->setBufferInfo(uiByte4Data, pucReason);
114         }  // if
115     }
116     return RTP_SUCCESS;
117 }  // decodeByePacket
118 
formByePacket(OUT RtpBuffer * pobjRtcpPktBuf)119 eRTP_STATUS_CODE RtcpByePacket::formByePacket(OUT RtpBuffer* pobjRtcpPktBuf)
120 {
121     RtpDt_UInt32 uiCurPos = pobjRtcpPktBuf->getLength();
122     RtpDt_UChar* pucBuffer = pobjRtcpPktBuf->getBuffer();
123 
124     uiCurPos = uiCurPos + RTCP_FIXED_HDR_LEN;
125     pucBuffer = pucBuffer + uiCurPos;
126 
127     for (auto& puiSsrc : m_uiSsrcList)
128     {
129         // ssrc
130         *(reinterpret_cast<RtpDt_UInt32*>(pucBuffer)) = RtpOsUtil::Ntohl(*puiSsrc);
131         pucBuffer = pucBuffer + RTP_WORD_SIZE;
132         uiCurPos = uiCurPos + RTP_WORD_SIZE;
133     }
134 
135     // m_pReason
136     if (m_pReason != nullptr)
137     {
138         // length
139         *(reinterpret_cast<RtpDt_UChar*>(pucBuffer)) = (RtpDt_UChar)m_pReason->getLength();
140         pucBuffer = pucBuffer + RTP_ONE;
141         uiCurPos = uiCurPos + RTP_ONE;
142 
143         memcpy(pucBuffer, m_pReason->getBuffer(), m_pReason->getLength());
144         uiCurPos = uiCurPos + m_pReason->getLength();
145     }
146 
147     // padding
148     {
149         RtpDt_UInt32 uiByePktPos = pobjRtcpPktBuf->getLength();
150         RtpDt_UInt32 uiByePktLen = uiCurPos - uiByePktPos;
151 
152 #ifdef ENABLE_PADDING
153         RtpDt_UInt32 uiPadLen = uiByePktLen % RTP_WORD_SIZE;
154         if (uiPadLen > RTP_ZERO)
155         {
156             uiPadLen = RTP_WORD_SIZE - uiPadLen;
157             uiByePktLen = uiByePktLen + uiPadLen;
158             uiCurPos = uiCurPos + uiPadLen;
159             pucBuffer = pucBuffer + m_pReason->getLength();
160             memset(pucBuffer, RTP_ZERO, uiPadLen);
161 
162             pucBuffer = pucBuffer + uiPadLen;
163             pucBuffer = pucBuffer - RTP_ONE;
164             *(reinterpret_cast<RtpDt_UChar*>(pucBuffer)) = (RtpDt_UChar)uiPadLen;
165 
166             // set pad bit in header
167             m_objRtcpHdr.setPadding();
168             // set length in header
169             m_objRtcpHdr.setLength(uiByePktLen);
170         }
171         else
172 #endif
173         {
174             // set length in header
175             m_objRtcpHdr.setLength(uiByePktLen);
176         }
177 
178         pobjRtcpPktBuf->setLength(uiByePktPos);
179         m_objRtcpHdr.formRtcpHeader(pobjRtcpPktBuf);
180     }  // padding
181 
182     // set the current position of the RTCP compound packet
183     pobjRtcpPktBuf->setLength(uiCurPos);
184 
185     return RTP_SUCCESS;
186 }  // formByePacket
187