1 /*
2 
3   This file is a part of JRTPLIB
4   Copyright (c) 1999-2017 Jori Liesenborgs
5 
6   Contact: jori.liesenborgs@gmail.com
7 
8   This library was developed at the Expertise Centre for Digital Media
9   (http://www.edm.uhasselt.be), a research center of the Hasselt University
10   (http://www.uhasselt.be). The library is based upon work done for
11   my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
12 
13   Permission is hereby granted, free of charge, to any person obtaining a
14   copy of this software and associated documentation files (the "Software"),
15   to deal in the Software without restriction, including without limitation
16   the rights to use, copy, modify, merge, publish, distribute, sublicense,
17   and/or sell copies of the Software, and to permit persons to whom the
18   Software is furnished to do so, subject to the following conditions:
19 
20   The above copyright notice and this permission notice shall be included
21   in all copies or substantial portions of the Software.
22 
23   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
26   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29   IN THE SOFTWARE.
30 
31 */
32 
33 #include "rtppacket.h"
34 #include "rtpstructs.h"
35 #include "rtpdefines.h"
36 #include "rtperrors.h"
37 #include "rtprawpacket.h"
38 #ifdef RTP_SUPPORT_NETINET_IN
39 	#include <netinet/in.h>
40 #endif // RTP_SUPPORT_NETINET_IN
41 #include <string.h>
42 
43 #ifdef RTPDEBUG
44 	#include <stdio.h>
45 #endif // RTPDEBUG
46 
47 #include "rtpdebug.h"
48 
49 namespace jrtplib
50 {
51 
Clear()52 void RTPPacket::Clear()
53 {
54 	hasextension = false;
55 	hasmarker = false;
56 	numcsrcs = 0;
57 	payloadtype = 0;
58 	extseqnr = 0;
59 	timestamp = 0;
60 	ssrc = 0;
61 	packet = 0;
62 	payload = 0;
63 	packetlength = 0;
64 	payloadlength = 0;
65 	extid = 0;
66 	extension = 0;
67 	extensionlength = 0;
68 	error = 0;
69 	externalbuffer = false;
70 }
71 
RTPPacket(RTPRawPacket & rawpack,RTPMemoryManager * mgr)72 RTPPacket::RTPPacket(RTPRawPacket &rawpack,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(rawpack.GetReceiveTime())
73 {
74 	Clear();
75 	error = ParseRawPacket(rawpack);
76 }
77 
RTPPacket(uint8_t payloadtype,const void * payloaddata,size_t payloadlen,uint16_t seqnr,uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t * csrcs,bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void * extensiondata,size_t maxpacksize,RTPMemoryManager * mgr)78 RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
79 		  uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
80 		  bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
81 		  size_t maxpacksize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
82 {
83 	Clear();
84 	error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
85 	       	            csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,0,maxpacksize);
86 }
87 
RTPPacket(uint8_t payloadtype,const void * payloaddata,size_t payloadlen,uint16_t seqnr,uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t * csrcs,bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void * extensiondata,void * buffer,size_t buffersize,RTPMemoryManager * mgr)88 RTPPacket::RTPPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
89 		  uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
90 		  bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
91 		  void *buffer,size_t buffersize, RTPMemoryManager *mgr) : RTPMemoryObject(mgr),receivetime(0,0)
92 {
93 	Clear();
94 	if (buffer == 0)
95 		error = ERR_RTP_PACKET_EXTERNALBUFFERNULL;
96 	else if (buffersize <= 0)
97 		error = ERR_RTP_PACKET_ILLEGALBUFFERSIZE;
98 	else
99 		error = BuildPacket(payloadtype,payloaddata,payloadlen,seqnr,timestamp,ssrc,gotmarker,numcsrcs,
100 		                    csrcs,gotextension,extensionid,extensionlen_numwords,extensiondata,buffer,buffersize);
101 }
102 
ParseRawPacket(RTPRawPacket & rawpack)103 int RTPPacket::ParseRawPacket(RTPRawPacket &rawpack)
104 {
105 	uint8_t *packetbytes;
106 	size_t packetlen;
107 	uint8_t payloadtype;
108 	RTPHeader *rtpheader;
109 	bool marker;
110 	int csrccount;
111 	bool hasextension;
112 	int payloadoffset,payloadlength;
113 	int numpadbytes;
114 	RTPExtensionHeader *rtpextheader;
115 
116 	if (!rawpack.IsRTP()) // If we didn't receive it on the RTP port, we'll ignore it
117 		return ERR_RTP_PACKET_INVALIDPACKET;
118 
119 	// The length should be at least the size of the RTP header
120 	packetlen = rawpack.GetDataLength();
121 	if (packetlen < sizeof(RTPHeader))
122 		return ERR_RTP_PACKET_INVALIDPACKET;
123 
124 	packetbytes = (uint8_t *)rawpack.GetData();
125 	rtpheader = (RTPHeader *)packetbytes;
126 
127 	// The version number should be correct
128 	if (rtpheader->version != RTP_VERSION)
129 		return ERR_RTP_PACKET_INVALIDPACKET;
130 
131 	// We'll check if this is possibly a RTCP packet. For this to be possible
132 	// the marker bit and payload type combined should be either an SR or RR
133 	// identifier
134 	marker = (rtpheader->marker == 0)?false:true;
135 	payloadtype = rtpheader->payloadtype;
136 	if (marker)
137 	{
138 		if (payloadtype == (RTP_RTCPTYPE_SR & 127)) // don't check high bit (this was the marker!!)
139 			return ERR_RTP_PACKET_INVALIDPACKET;
140 		if (payloadtype == (RTP_RTCPTYPE_RR & 127))
141 			return ERR_RTP_PACKET_INVALIDPACKET;
142 	}
143 
144 	csrccount = rtpheader->csrccount;
145 	payloadoffset = sizeof(RTPHeader)+(int)(csrccount*sizeof(uint32_t));
146 
147 	if (rtpheader->padding) // adjust payload length to take padding into account
148 	{
149 		numpadbytes = (int)packetbytes[packetlen-1]; // last byte contains number of padding bytes
150 		if (numpadbytes <= 0)
151 			return ERR_RTP_PACKET_INVALIDPACKET;
152 	}
153 	else
154 		numpadbytes = 0;
155 
156 	hasextension = (rtpheader->extension == 0)?false:true;
157 	if (hasextension) // got header extension
158 	{
159 		rtpextheader = (RTPExtensionHeader *)(packetbytes+payloadoffset);
160 		payloadoffset += sizeof(RTPExtensionHeader);
161 
162 		uint16_t exthdrlen = ntohs(rtpextheader->length);
163 		payloadoffset += ((int)exthdrlen)*sizeof(uint32_t);
164 	}
165 	else
166 	{
167 		rtpextheader = 0;
168 	}
169 
170 	payloadlength = packetlen-numpadbytes-payloadoffset;
171 	if (payloadlength < 0)
172 		return ERR_RTP_PACKET_INVALIDPACKET;
173 
174 	// Now, we've got a valid packet, so we can create a new instance of RTPPacket
175 	// and fill in the members
176 
177 	RTPPacket::hasextension = hasextension;
178 	if (hasextension)
179 	{
180 		RTPPacket::extid = ntohs(rtpextheader->extid);
181 		RTPPacket::extensionlength = ((int)ntohs(rtpextheader->length))*sizeof(uint32_t);
182 		RTPPacket::extension = ((uint8_t *)rtpextheader)+sizeof(RTPExtensionHeader);
183 	}
184 
185 	RTPPacket::hasmarker = marker;
186 	RTPPacket::numcsrcs = csrccount;
187 	RTPPacket::payloadtype = payloadtype;
188 
189 	// Note: we don't fill in the EXTENDED sequence number here, since we
190 	// don't have information about the source here. We just fill in the low
191 	// 16 bits
192 	RTPPacket::extseqnr = (uint32_t)ntohs(rtpheader->sequencenumber);
193 
194 	RTPPacket::timestamp = ntohl(rtpheader->timestamp);
195 	RTPPacket::ssrc = ntohl(rtpheader->ssrc);
196 	RTPPacket::packet = packetbytes;
197 	RTPPacket::payload = packetbytes+payloadoffset;
198 	RTPPacket::packetlength = packetlen;
199 	RTPPacket::payloadlength = payloadlength;
200 
201 	// We'll zero the data of the raw packet, since we're using it here now!
202 	rawpack.ZeroData();
203 
204 	return 0;
205 }
206 
GetCSRC(int num) const207 uint32_t RTPPacket::GetCSRC(int num) const
208 {
209 	if (num >= numcsrcs)
210 		return 0;
211 
212 	uint8_t *csrcpos;
213 	uint32_t *csrcval_nbo;
214 	uint32_t csrcval_hbo;
215 
216 	csrcpos = packet+sizeof(RTPHeader)+num*sizeof(uint32_t);
217 	csrcval_nbo = (uint32_t *)csrcpos;
218 	csrcval_hbo = ntohl(*csrcval_nbo);
219 	return csrcval_hbo;
220 }
221 
BuildPacket(uint8_t payloadtype,const void * payloaddata,size_t payloadlen,uint16_t seqnr,uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t * csrcs,bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void * extensiondata,void * buffer,size_t maxsize)222 int RTPPacket::BuildPacket(uint8_t payloadtype,const void *payloaddata,size_t payloadlen,uint16_t seqnr,
223 		  uint32_t timestamp,uint32_t ssrc,bool gotmarker,uint8_t numcsrcs,const uint32_t *csrcs,
224 		  bool gotextension,uint16_t extensionid,uint16_t extensionlen_numwords,const void *extensiondata,
225 		  void *buffer,size_t maxsize)
226 {
227 	if (numcsrcs > RTP_MAXCSRCS)
228 		return ERR_RTP_PACKET_TOOMANYCSRCS;
229 
230 	if (payloadtype > 127) // high bit should not be used
231 		return ERR_RTP_PACKET_BADPAYLOADTYPE;
232 	if (payloadtype == 72 || payloadtype == 73) // could cause confusion with rtcp types
233 		return ERR_RTP_PACKET_BADPAYLOADTYPE;
234 
235 	packetlength = sizeof(RTPHeader);
236 	packetlength += sizeof(uint32_t)*((size_t)numcsrcs);
237 	if (gotextension)
238 	{
239 		packetlength += sizeof(RTPExtensionHeader);
240 		packetlength += sizeof(uint32_t)*((size_t)extensionlen_numwords);
241 	}
242 	packetlength += payloadlen;
243 
244 	if (maxsize > 0 && packetlength > maxsize)
245 	{
246 		packetlength = 0;
247 		return ERR_RTP_PACKET_DATAEXCEEDSMAXSIZE;
248 	}
249 
250 	// Ok, now we'll just fill in...
251 
252 	RTPHeader *rtphdr;
253 
254 	if (buffer == 0)
255 	{
256 		packet = RTPNew(GetMemoryManager(),RTPMEM_TYPE_BUFFER_RTPPACKET) uint8_t [packetlength];
257 		if (packet == 0)
258 		{
259 			packetlength = 0;
260 			return ERR_RTP_OUTOFMEM;
261 		}
262 		externalbuffer = false;
263 	}
264 	else
265 	{
266 		packet = (uint8_t *)buffer;
267 		externalbuffer = true;
268 	}
269 
270 	RTPPacket::hasmarker = gotmarker;
271 	RTPPacket::hasextension = gotextension;
272 	RTPPacket::numcsrcs = numcsrcs;
273 	RTPPacket::payloadtype = payloadtype;
274 	RTPPacket::extseqnr = (uint32_t)seqnr;
275 	RTPPacket::timestamp = timestamp;
276 	RTPPacket::ssrc = ssrc;
277 	RTPPacket::payloadlength = payloadlen;
278 	RTPPacket::extid = extensionid;
279 	RTPPacket::extensionlength = ((size_t)extensionlen_numwords)*sizeof(uint32_t);
280 
281 	rtphdr = (RTPHeader *)packet;
282 	rtphdr->version = RTP_VERSION;
283 	rtphdr->padding = 0;
284 	if (gotmarker)
285 		rtphdr->marker = 1;
286 	else
287 		rtphdr->marker = 0;
288 	if (gotextension)
289 		rtphdr->extension = 1;
290 	else
291 		rtphdr->extension = 0;
292 	rtphdr->csrccount = numcsrcs;
293 	rtphdr->payloadtype = payloadtype&127; // make sure high bit isn't set
294 	rtphdr->sequencenumber = htons(seqnr);
295 	rtphdr->timestamp = htonl(timestamp);
296 	rtphdr->ssrc = htonl(ssrc);
297 
298 	uint32_t *curcsrc;
299 	int i;
300 
301 	curcsrc = (uint32_t *)(packet+sizeof(RTPHeader));
302 	for (i = 0 ; i < numcsrcs ; i++,curcsrc++)
303 		*curcsrc = htonl(csrcs[i]);
304 
305 	payload = packet+sizeof(RTPHeader)+((size_t)numcsrcs)*sizeof(uint32_t);
306 	if (gotextension)
307 	{
308 		RTPExtensionHeader *rtpexthdr = (RTPExtensionHeader *)payload;
309 
310 		rtpexthdr->extid = htons(extensionid);
311 		rtpexthdr->length = htons((uint16_t)extensionlen_numwords);
312 
313 		payload += sizeof(RTPExtensionHeader);
314 		memcpy(payload,extensiondata,RTPPacket::extensionlength);
315 
316 		payload += RTPPacket::extensionlength;
317 	}
318 	memcpy(payload,payloaddata,payloadlen);
319 	return 0;
320 }
321 
322 #ifdef RTPDEBUG
Dump()323 void RTPPacket::Dump()
324 {
325 	int i;
326 
327 	printf("Payload type:                %d\n",(int)GetPayloadType());
328 	printf("Extended sequence number:    0x%08x\n",GetExtendedSequenceNumber());
329 	printf("Timestamp:                   0x%08x\n",GetTimestamp());
330 	printf("SSRC:                        0x%08x\n",GetSSRC());
331 	printf("Marker:                      %s\n",HasMarker()?"yes":"no");
332 	printf("CSRC count:                  %d\n",GetCSRCCount());
333 	for (i = 0 ; i < GetCSRCCount() ; i++)
334 		printf("    CSRC[%02d]:                0x%08x\n",i,GetCSRC(i));
335 	printf("Payload:                     %s\n",GetPayloadData());
336 	printf("Payload length:              %d\n",GetPayloadLength());
337 	printf("Packet length:               %d\n",GetPacketLength());
338 	printf("Extension:                   %s\n",HasExtension()?"yes":"no");
339 	if (HasExtension())
340 	{
341 		printf("    Extension ID:            0x%04x\n",GetExtensionID());
342 		printf("    Extension data:          %s\n",GetExtensionData());
343 		printf("    Extension length:        %d\n",GetExtensionLength());
344 	}
345 }
346 #endif // RTPDEBUG
347 
348 } // end namespace
349 
350