1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3 // Copyright (C) 2015 Cherokees of Idaho.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 //
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction. Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License. This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27 //
28 // This exception applies only to the code released under the name GNU
29 // ccRTP. If you copy code from other releases into a copy of GNU
30 // ccRTP, as the General Public License permits, the exception does
31 // not apply to the code that you add in this way. To avoid misleading
32 // anyone as to the status of such modified files, you must delete
33 // this exception notice from them.
34 //
35 // If you write modifications of your own for GNU ccRTP, it is your choice
36 // whether to permit this exception to apply to your modifications.
37 // If you do not wish that, delete this exception notice.
38 //
39
40 /**
41 * @file rtppkt.cpp
42 * @short StaticPayloadFormat, DynamicPayloadFormat, RTPPacket,
43 * OutgoingRTPPkt and IncomingRTPPkt classes implementation.
44 **/
45
46 #include "private.h"
47 #include <ccrtp/rtppkt.h>
48 #include <ccrtp/CryptoContext.h>
49
50 NAMESPACE_COMMONCPP
51
52 // Default to 8Khz when no value is specified.
53 const uint32 PayloadFormat::defaultRTPClockRate = 8000;
54
55 //uint32 PayloadFormat::staticRates[lastStaticPayloadType]
56 uint32 StaticPayloadFormat::staticAudioTypesRates[] = {
57 // audio types:
58 8000, // 0 - sptPCMU
59 0, // 1 - reserved
60 8000, // 2 - sptG726_32
61 8000, // 3 - sptGSM
62 8000, // 4 - sptG723
63 8000, // 5 - sptDVI4_8000
64 16000, // 6 - sptDVI4_16000
65 8000, // 7 - sptLPC
66 8000, // 8 - sptPCMA
67 8000, // 9 - sptG722
68 44100, // 10 - sptL16_DUAL
69 44100, // 11 - sptL16_MONO
70 8000, // 12 - sptQCELP
71 0, // 13 - reserved
72 90000, // 14 - sptMPA
73 8000, // 15 - sptG728
74 11015, // 16 - sptDVI4_11025
75 22050, // 17 - sptDVI4_22050
76 8000 // 18 - sptG729
77 /* 0, // reserved
78 0, // unassigned
79 0, // unassigned
80 0, // unassigned
81 0 // unassigned
82 */
83 // All video types have 90000 hz RTP clock rate.
84 // If sometime in the future a static video payload type is
85 // defined with a different RTP clock rate (quite
86 // unprobable). This table and/or the StaticPayloadType
87 // constructor must be changed.
88 };
89
StaticPayloadFormat(StaticPayloadType type)90 StaticPayloadFormat::StaticPayloadFormat(StaticPayloadType type)
91 {
92 setPayloadType( (type <= lastStaticPayloadType)? type : 0);
93 if ( type <= sptG729 ) {
94 // audio static type
95 setRTPClockRate(staticAudioTypesRates[type]);
96 } else {
97 // video static type
98 setRTPClockRate(90000);
99 }
100 }
101
DynamicPayloadFormat(PayloadType type,uint32 rate)102 DynamicPayloadFormat::DynamicPayloadFormat(PayloadType type, uint32 rate)
103 {
104 PayloadFormat::setPayloadType(type);
105 setRTPClockRate(rate);
106 }
107
108 // constructor commonly used for incoming packets
RTPPacket(const unsigned char * const block,size_t len,bool duplicate)109 RTPPacket::RTPPacket(const unsigned char* const block, size_t len, bool duplicate) :
110 total((uint32)len), duplicated(duplicate)
111 {
112 const RTPFixedHeader* const header =
113 reinterpret_cast<const RTPFixedHeader*>(block);
114 hdrSize = sizeof(RTPFixedHeader) + (header->cc << 2);
115 if ( header->extension ){
116 RTPHeaderExt *ext = (RTPHeaderExt *)(block + hdrSize);
117 hdrSize += sizeof(uint32) + (ntohs(ext->length) * 4);
118 }
119 if ( header->padding )
120 len -= block[len - 1];
121 payloadSize = (uint32)(len - hdrSize);
122
123 if ( duplicate ) {
124 buffer = new unsigned char[len];
125 setbuffer(block,len,0);
126 } else {
127 buffer = const_cast<unsigned char*>(block);
128 }
129 }
130
131 // constructor commonly used for outgoing packets
RTPPacket(size_t hdrlen,size_t plen,uint8 paddinglen,CryptoContext * pcc)132 RTPPacket::RTPPacket(size_t hdrlen, size_t plen, uint8 paddinglen, CryptoContext* pcc ) :
133 payloadSize((uint32)plen), buffer(NULL), hdrSize((uint32)hdrlen),
134 duplicated(false)
135 {
136 total = (uint32)(hdrlen + payloadSize);
137 // compute if there must be padding
138 uint8 padding = 0;
139 if ( 0 != paddinglen ) {
140 padding = paddinglen - (total % paddinglen);
141 total += padding;
142 }
143 srtpLength = 0;
144 srtpDataOffset = 0;
145 if (pcc != NULL) {
146 // compute additional memory for SRTP data
147 srtpLength = pcc->getTagLength() + pcc->getMkiLength();
148 srtpDataOffset = total; // SRTP data go behind header plus payload plus padding
149 }
150
151 // now we know the actual total length of the packet, get some memory
152 // but take SRTP data into account. Don't change total because some RTP
153 // functions rely on the fact that total is the overall size (without
154 // the SRTP data)
155 buffer = new unsigned char[total + srtpLength];
156 *(reinterpret_cast<uint32*>(getHeader())) = 0;
157 getHeader()->version = CCRTP_VERSION;
158 if ( 0 != padding ) {
159 memset(buffer + total - padding,0,padding - 1);
160 buffer[total - 1] = padding;
161 getHeader()->padding = 1;
162 } else {
163 getHeader()->padding = 0;
164 }
165 }
166
endPacket()167 void RTPPacket::endPacket()
168 {
169 #ifdef CCXX_EXCEPTIONS
170 try {
171 #endif
172 delete [] buffer;
173 #ifdef CCXX_EXCEPTIONS
174 } catch (...) { };
175 #endif
176 }
177
reComputePayLength(bool padding)178 void RTPPacket::reComputePayLength(bool padding)
179 {
180 // If payloadsize was computed without padding set then re-compute
181 // payloadSize after the padding bit was set and set padding flag
182 // in RTP header - option for SRTP
183 if (padding) {
184 size_t len = 0;
185 getHeader()->padding = 1;
186 len -= buffer[payloadSize - 1];
187 payloadSize = (uint32)(payloadSize - len);
188 }
189 }
190
OutgoingRTPPkt(const uint32 * const csrcs,uint16 numcsrc,const unsigned char * const hdrext,uint32 hdrextlen,const unsigned char * const data,size_t datalen,uint8 paddinglen,CryptoContext * pcc)191 OutgoingRTPPkt::OutgoingRTPPkt(const uint32* const csrcs, uint16 numcsrc,
192 const unsigned char* const hdrext, uint32 hdrextlen,
193 const unsigned char* const data, size_t datalen,
194 uint8 paddinglen, CryptoContext* pcc) :
195 RTPPacket((getSizeOfFixedHeader() + sizeof(uint32) * numcsrc + hdrextlen),datalen,paddinglen, pcc)
196 {
197 uint32 pointer = (uint32)getSizeOfFixedHeader();
198 // add CSCR identifiers (putting them in network order).
199 setCSRCArray(csrcs,numcsrc);
200 pointer += numcsrc * sizeof(uint32);
201
202 // add header extension.
203 setbuffer(hdrext,hdrextlen,pointer);
204 setExtension(hdrextlen > 0);
205 pointer += hdrextlen;
206
207 // add data.
208 setbuffer(data,datalen,pointer);
209 }
210
OutgoingRTPPkt(const uint32 * const csrcs,uint16 numcsrc,const unsigned char * data,size_t datalen,uint8 paddinglen,CryptoContext * pcc)211 OutgoingRTPPkt::OutgoingRTPPkt(const uint32* const csrcs, uint16 numcsrc,
212 const unsigned char* data, size_t datalen, uint8 paddinglen, CryptoContext* pcc) :
213 RTPPacket((getSizeOfFixedHeader() + sizeof(uint32) *numcsrc),datalen, paddinglen, pcc)
214 {
215 uint32 pointer = (uint32)getSizeOfFixedHeader();
216 // add CSCR identifiers (putting them in network order).
217 setCSRCArray(csrcs,numcsrc);
218 pointer += numcsrc * sizeof(uint32);
219
220 // not needed, as the RTPPacket constructor sets by default
221 // the whole fixed header to 0.
222 // getHeader()->extension = 0;
223
224 // add data.
225 setbuffer(data,datalen,pointer);
226 }
227
OutgoingRTPPkt(const unsigned char * data,size_t datalen,uint8 paddinglen,CryptoContext * pcc)228 OutgoingRTPPkt::OutgoingRTPPkt(const unsigned char* data, size_t datalen,
229 uint8 paddinglen, CryptoContext* pcc) :
230 RTPPacket(getSizeOfFixedHeader(),datalen,paddinglen, pcc)
231 {
232 // not needed, as the RTPPacket constructor sets by default
233 // the whole fixed header to 0.
234 //getHeader()->cc = 0;
235 //getHeader()->extension = 0;
236
237 setbuffer(data,datalen,getSizeOfFixedHeader());
238 }
239
setCSRCArray(const uint32 * const csrcs,uint16 numcsrc)240 void OutgoingRTPPkt::setCSRCArray(const uint32* const csrcs, uint16 numcsrc)
241 {
242 setbuffer(csrcs, numcsrc * sizeof(uint32),getSizeOfFixedHeader());
243 uint32* csrc = const_cast<uint32*>(getCSRCs());
244 for ( int i = 0; i < numcsrc; i++ )
245 csrc[i] = htonl(csrc[i]);
246 getHeader()->cc = numcsrc;
247 }
248
protect(uint32 ssrc,CryptoContext * pcc)249 void OutgoingRTPPkt::protect(uint32 ssrc, CryptoContext* pcc)
250 {
251 /* Encrypt the packet */
252 uint64 index = ((uint64)pcc->getRoc() << 16) | (uint64)getSeqNum();
253
254 pcc->srtpEncrypt(this, index, ssrc);
255
256 // NO MKI support yet - here we assume MKI is zero. To build in MKI
257 // take MKI length into account when storing the authentication tag.
258
259 /* Compute MAC */
260 pcc->srtpAuthenticate(this, pcc->getRoc(),
261 const_cast<uint8*>(getRawPacket()+srtpDataOffset) );
262 /* Update the ROC if necessary */
263 if (getSeqNum() == 0xFFFF ) {
264 pcc->setRoc(pcc->getRoc() + 1);
265 }
266 }
267
268 // These masks are valid regardless of endianness.
269 const uint16 IncomingRTPPkt::RTP_INVALID_PT_MASK = (0x7e);
270 const uint16 IncomingRTPPkt::RTP_INVALID_PT_VALUE = (0x48);
271
IncomingRTPPkt(const unsigned char * const block,size_t len)272 IncomingRTPPkt::IncomingRTPPkt(const unsigned char* const block, size_t len) :
273 RTPPacket(block,len)
274 {
275 // first, perform validity check:
276 // 1) check protocol version
277 // 2) it is not an SR nor an RR
278 // 3) consistent length field value (taking CC value and P and
279 // X bits into account)
280 if ( getProtocolVersion() != CCRTP_VERSION || (getPayloadType() & RTP_INVALID_PT_MASK) == RTP_INVALID_PT_VALUE) {
281 /*
282 ||
283 getPayloadSize() <= 0 ) {
284 */
285 headerValid = false;
286 return;
287 }
288 headerValid = true;
289 cachedTimestamp = getRawTimestamp();
290 cachedSeqNum = ntohs(getHeader()->sequence);
291 cachedSSRC = ntohl(getHeader()->sources[0]);
292 }
293
unprotect(CryptoContext * pcc)294 int32 IncomingRTPPkt::unprotect(CryptoContext* pcc)
295 {
296 if (pcc == NULL) {
297 return true;
298 }
299
300 /*
301 * This is the setting of the packet data when we come to this
302 * point:
303 *
304 * total: complete length of received data
305 * buffer: points to data as received from network
306 * hdrSize: length of header including header extension
307 * payloadSize: length of data excluding hdrSize and padding
308 *
309 * Because this is an SRTP packet we need to adjust some values here.
310 * The SRTP MKI and authentication data is always at the end of a
311 * packet. Thus compute the position of this data.
312 */
313
314 uint32 srtpDataIndex = total - (pcc->getTagLength() + pcc->getMkiLength());
315
316 // now adjust total because some RTP functions rely on the fact that
317 // total is the full length of data without SRTP data.
318 total -= pcc->getTagLength() + pcc->getMkiLength();
319
320 // recompute payloadSize by subtracting SRTP data
321 payloadSize -= pcc->getTagLength() + pcc->getMkiLength();
322
323 // unused??
324 // const uint8* mki = getRawPacket() + srtpDataIndex;
325 const uint8* tag = getRawPacket() + srtpDataIndex + pcc->getMkiLength();
326
327 /* Replay control */
328 if (!pcc->checkReplay(cachedSeqNum)) {
329 return -2;
330 }
331 /* Guess the index */
332 uint64 guessedIndex = pcc->guessIndex(cachedSeqNum);
333
334 uint32 guessedRoc = (uint32)(guessedIndex >> 16);
335 uint8* mac = new uint8[pcc->getTagLength()];
336
337 pcc->srtpAuthenticate(this, guessedRoc, mac);
338 if (memcmp(tag, mac, pcc->getTagLength()) != 0) {
339 delete[] mac;
340 return -1;
341 }
342 delete[] mac;
343
344 /* Decrypt the content */
345 pcc->srtpEncrypt( this, guessedIndex, cachedSSRC );
346
347 /* Update the Crypto-context */
348 pcc->update(cachedSeqNum);
349
350 return 1;
351 }
352
353 END_NAMESPACE
354
355 /** EMACS **
356 * Local variables:
357 * mode: c++
358 * c-basic-offset: 4
359 * End:
360 */
361