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 <RtcpChunk.h>
18 #include <RtpTrace.h>
19 
RtcpChunk()20 RtcpChunk::RtcpChunk() :
21         m_uiSsrc(RTP_ZERO),
22         m_stSdesItemList(std::list<tRTCP_SDES_ITEM*>())
23 {
24 }
25 
~RtcpChunk()26 RtcpChunk::~RtcpChunk()
27 {
28     // delete all tRTCP_SDES_ITEM objects from SdesItemList
29     for (const auto& pstSdesItem : m_stSdesItemList)
30     {
31         if (pstSdesItem->pValue != nullptr)
32         {
33             delete[] pstSdesItem->pValue;
34         }
35         delete pstSdesItem;
36     }
37     m_stSdesItemList.clear();
38 }
39 
setSsrc(IN RtpDt_UInt32 uiSsrc)40 RtpDt_Void RtcpChunk::setSsrc(IN RtpDt_UInt32 uiSsrc)
41 {
42     m_uiSsrc = uiSsrc;
43 }
44 
getSsrc()45 RtpDt_UInt32 RtcpChunk::getSsrc()
46 {
47     return m_uiSsrc;
48 }
49 
getSdesItemList()50 std::list<tRTCP_SDES_ITEM*>& RtcpChunk::getSdesItemList()
51 {
52     return m_stSdesItemList;
53 }
54 
decodeRtcpChunk(IN RtpDt_UChar * pucChunkBuf,IN RtpDt_UInt16 & usChunkLen,IN RtcpConfigInfo * pobjRtcpCfgInfo)55 eRTP_STATUS_CODE RtcpChunk::decodeRtcpChunk(IN RtpDt_UChar* pucChunkBuf,
56         IN RtpDt_UInt16& usChunkLen, IN RtcpConfigInfo* pobjRtcpCfgInfo)
57 {
58     // SDES items
59     RtpDt_UInt32 uiSdesItemCnt = pobjRtcpCfgInfo->getSdesItemCount();
60     eRtp_Bool bCName = eRTP_FALSE;
61 
62     while (uiSdesItemCnt > RTP_ZERO)
63     {
64         tRTCP_SDES_ITEM* pstSdesItem = new tRTCP_SDES_ITEM();
65         if (pstSdesItem == nullptr)
66         {
67             RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
68             return RTP_MEMORY_FAIL;
69         }
70         memset(pstSdesItem, RTP_ZERO, sizeof(tRTCP_SDES_ITEM));
71 
72         // type
73         pstSdesItem->ucType = *(reinterpret_cast<RtpDt_UChar*>(pucChunkBuf));
74         pucChunkBuf = pucChunkBuf + RTP_ONE;
75         usChunkLen = usChunkLen + RTP_ONE;
76 
77         if (pstSdesItem->ucType == RTP_ONE)
78         {
79             bCName = eRTP_TRUE;
80         }
81         // length
82         pstSdesItem->ucLength = *(reinterpret_cast<RtpDt_UChar*>(pucChunkBuf));
83         pucChunkBuf = pucChunkBuf + RTP_ONE;
84         usChunkLen = usChunkLen + RTP_ONE;
85 
86         RTP_TRACE_MESSAGE("decodeRtcpChunk , [Sdes item type =%d], [Sdes item length = %d]",
87                 pstSdesItem->ucType, pstSdesItem->ucLength);
88 
89         // value
90         RtpDt_UChar* pcSdesBuf = new RtpDt_UChar[pstSdesItem->ucLength];
91         if (pcSdesBuf == nullptr)
92         {
93             RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
94             delete pstSdesItem;
95             return RTP_MEMORY_FAIL;
96         }
97         memcpy(pcSdesBuf, pucChunkBuf, pstSdesItem->ucLength);
98 
99         pucChunkBuf = pucChunkBuf + pstSdesItem->ucLength;
100         usChunkLen = usChunkLen + pstSdesItem->ucLength;
101         pstSdesItem->pValue = pcSdesBuf;
102 
103         m_stSdesItemList.push_back(pstSdesItem);
104 
105         // decrement uiSdesItemCnt by 1
106         uiSdesItemCnt = uiSdesItemCnt - RTP_ONE;
107     }  // while
108 
109     if (bCName == eRTP_FALSE)
110     {
111         return RTP_DECODE_ERROR;
112     }
113 
114     return RTP_SUCCESS;
115 }  // decodeRtcpChunk
116 
formRtcpChunk(OUT RtpBuffer * pobjRtcpPktBuf)117 eRTP_STATUS_CODE RtcpChunk::formRtcpChunk(OUT RtpBuffer* pobjRtcpPktBuf)
118 {
119     RtpDt_UInt32 uiCurPos = pobjRtcpPktBuf->getLength();
120     RtpDt_UChar* pucBuffer = pobjRtcpPktBuf->getBuffer();
121 
122     pucBuffer = pucBuffer + uiCurPos;
123 
124     // m_uiSsrc
125     *(reinterpret_cast<RtpDt_UInt32*>(pucBuffer)) = RtpOsUtil::Ntohl(m_uiSsrc);
126     pucBuffer = pucBuffer + RTP_WORD_SIZE;
127     uiCurPos = uiCurPos + RTP_WORD_SIZE;
128 
129     eRtp_Bool bCName = eRTP_FALSE;
130 
131     for (auto& pstSdesItem : m_stSdesItemList)
132     {
133         // ucType
134         *(reinterpret_cast<RtpDt_UChar*>(pucBuffer)) = pstSdesItem->ucType;
135         pucBuffer = pucBuffer + RTP_ONE;
136         uiCurPos = uiCurPos + RTP_ONE;
137 
138         if (pstSdesItem->ucType == RTP_ONE)
139         {
140             bCName = eRTP_TRUE;
141         }
142 
143         // ucLength
144         *(reinterpret_cast<RtpDt_UChar*>(pucBuffer)) = pstSdesItem->ucLength;
145         pucBuffer = pucBuffer + RTP_ONE;
146         uiCurPos = uiCurPos + RTP_ONE;
147 
148         // pValue
149         memcpy(pucBuffer, pstSdesItem->pValue, pstSdesItem->ucLength);
150         pucBuffer = pucBuffer + pstSdesItem->ucLength;
151         uiCurPos = uiCurPos + pstSdesItem->ucLength;
152 
153         // to add type(0)
154         uiCurPos = uiCurPos + RTP_ONE;
155         pucBuffer[0] = (RtpDt_UChar)RTP_ZERO;
156         pucBuffer = pucBuffer + RTP_ONE;
157 
158         // to align the memory
159         RtpDt_UInt32 uiPadLen = uiCurPos % RTP_WORD_SIZE;
160         if (uiPadLen > RTP_ZERO)
161         {
162             uiPadLen = RTP_WORD_SIZE - uiPadLen;
163             uiCurPos = uiCurPos + uiPadLen;
164             memset(pucBuffer, RTP_ZERO, uiPadLen);
165             pucBuffer = pucBuffer + uiPadLen;
166         }
167     }  // for
168 
169     pobjRtcpPktBuf->setLength(uiCurPos);
170 
171     if (bCName == eRTP_FALSE)
172     {
173         return RTP_ENCODE_ERROR;
174     }
175 
176     return RTP_SUCCESS;
177 }  // formRtcpChunk
178