1 /**
2  * @file pkt.c  RTCP Packet handling
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <string.h>
7 #include <re_types.h>
8 #include <re_fmt.h>
9 #include <re_mem.h>
10 #include <re_mbuf.h>
11 #include <re_list.h>
12 #include <re_sys.h>
13 #include <re_sa.h>
14 #include <re_rtp.h>
15 #include "rtcp.h"
16 
17 
18 #define DEBUG_MODULE "rtcp_pkt"
19 #define DEBUG_LEVEL 5
20 #include <re_dbg.h>
21 
22 
rtcp_destructor(void * data)23 static void rtcp_destructor(void *data)
24 {
25 	struct rtcp_msg *msg = data;
26 	size_t i, j;
27 
28 	switch (msg->hdr.pt) {
29 
30 	case RTCP_SR:
31 		mem_deref(msg->r.sr.rrv);
32 		break;
33 
34 	case RTCP_RR:
35 		mem_deref(msg->r.rr.rrv);
36 		break;
37 
38 	case RTCP_SDES:
39 		if (!msg->r.sdesv)
40 			break;
41 
42 		for (i=0; i<msg->hdr.count; i++) {
43 			struct rtcp_sdes *sdes = &msg->r.sdesv[i];
44 
45 			for (j=0; j<sdes->n; j++) {
46 
47 				mem_deref(sdes->itemv[j].data);
48 			}
49 			mem_deref(sdes->itemv);
50 		}
51 		mem_deref(msg->r.sdesv);
52 		break;
53 
54 	case RTCP_BYE:
55 		mem_deref(msg->r.bye.srcv);
56 		mem_deref(msg->r.bye.reason);
57 		break;
58 
59 	case RTCP_APP:
60 		mem_deref(msg->r.app.data);
61 		break;
62 
63 	case RTCP_RTPFB:
64 	case RTCP_PSFB:
65 		mem_deref(msg->r.fb.fci.p);
66 		break;
67 
68 	default:
69 		/* nothing allocated */
70 		break;
71 	}
72 }
73 
74 
75 /**
76  * Encode the RTCP Header
77  *
78  * @param mb     Buffer to encode into
79  * @param count  Number of sub-elemements
80  * @param type   RTCP Packet type
81  * @param length Packet length in words
82  *
83  * @return 0 for success, otherwise errorcode
84  */
rtcp_hdr_encode(struct mbuf * mb,uint8_t count,enum rtcp_type type,uint16_t length)85 int rtcp_hdr_encode(struct mbuf *mb, uint8_t count, enum rtcp_type type,
86 		    uint16_t length)
87 {
88 	int err;
89 
90 	if (!mb)
91 		return EINVAL;
92 
93 	err  = mbuf_write_u8(mb, RTCP_VERSION<<6 | count);
94 	err |= mbuf_write_u8(mb, type);
95 	err |= mbuf_write_u16(mb, htons(length));
96 
97 	return err;
98 }
99 
100 
101 /**
102  * Decode the RTCP Header
103  *
104  * @param mb  Buffer to decode from
105  * @param hdr RTCP Header to decode into
106  *
107  * @return 0 for success, otherwise errorcode
108  */
rtcp_hdr_decode(struct mbuf * mb,struct rtcp_hdr * hdr)109 int rtcp_hdr_decode(struct mbuf *mb, struct rtcp_hdr *hdr)
110 {
111 	uint8_t b;
112 
113 	if (!hdr)
114 		return EINVAL;
115 	if (mbuf_get_left(mb) < RTCP_HDR_SIZE)
116 		return EBADMSG;
117 
118 	b = mbuf_read_u8(mb);
119 	hdr->pt = mbuf_read_u8(mb);
120 	hdr->length = ntohs(mbuf_read_u16(mb));
121 
122 	hdr->version = (b >> 6) & 0x3;
123 	hdr->p       = (b >> 5) & 0x1;
124 	hdr->count   = (b >> 0) & 0x1f;
125 
126 	return 0;
127 }
128 
129 
rtcp_vencode(struct mbuf * mb,enum rtcp_type type,uint32_t count,va_list ap)130 int rtcp_vencode(struct mbuf *mb, enum rtcp_type type, uint32_t count,
131 		 va_list ap)
132 {
133 	size_t i, pos;
134 	uint16_t len;
135 	const uint8_t *data;
136 	size_t data_len;
137 	const uint32_t *srcv;
138 	const char *reason;
139 	rtcp_encode_h *ench;
140 	void *arg;
141 	int err = 0;
142 
143 	if (!mb)
144 		return EINVAL;
145 
146 	pos = mb->pos;
147 
148 	/* Skip header - encoded last */
149 	mb->pos = mb->end = (mb->pos + RTCP_HDR_SIZE);
150 
151 	switch (type) {
152 
153 	case RTCP_SR:
154 		for (i=0; i<6; i++)
155 			err |= mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
156 		ench = va_arg(ap, rtcp_encode_h *);
157 		arg = va_arg(ap, void *);
158 		if (ench)
159 			err |= ench(mb, arg);
160 		break;
161 
162 	case RTCP_RR:
163 		err = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
164 		ench = va_arg(ap, rtcp_encode_h *);
165 		arg = va_arg(ap, void *);
166 		if (ench)
167 			err |= ench(mb, arg);
168 		break;
169 
170 	case RTCP_SDES:
171 		ench = va_arg(ap, rtcp_encode_h *);
172 		arg = va_arg(ap, void *);
173 		if (ench)
174 			err |= ench(mb, arg);
175 		break;
176 
177 	case RTCP_BYE:
178 		srcv   = va_arg(ap, uint32_t *);
179 		reason = va_arg(ap, char *);
180 		for (i=0; i<count && !err; i++) {
181 			err = mbuf_write_u32(mb, htonl(srcv[i]));
182 		}
183 		if (reason) {
184 			err |= mbuf_write_u8(mb, strlen(reason));
185 			err |= mbuf_write_str(mb, reason);
186 		}
187 		break;
188 
189 	case RTCP_APP:
190 		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
191 		err |= mbuf_write_mem(mb, va_arg(ap, uint8_t *), 4);
192 		data = va_arg(ap, const uint8_t *);
193 		data_len = va_arg(ap, size_t);
194 		if (data) {
195 			if (data_len % 4) {
196 				DEBUG_WARNING("not a multiple of 32bits\n");
197 				return EBADMSG;
198 			}
199 			err |= mbuf_write_mem(mb, data, data_len);
200 		}
201 		break;
202 
203 	case RTCP_FIR:
204 		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
205 		break;
206 
207 	case RTCP_NACK:
208 		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
209 		err |= mbuf_write_u16(mb, htons(va_arg(ap, uint32_t)));
210 		err |= mbuf_write_u16(mb, htons(va_arg(ap, uint32_t)));
211 		break;
212 
213 	case RTCP_RTPFB:
214 	case RTCP_PSFB:
215 		err  = mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
216 		err |= mbuf_write_u32(mb, htonl(va_arg(ap, uint32_t)));
217 		ench = va_arg(ap, rtcp_encode_h *);
218 		arg = va_arg(ap, void *);
219 		if (ench)
220 			err |= ench(mb, arg);
221 		break;
222 
223 	default:
224 		return EINVAL;
225 	}
226 	if (err)
227 		return err;
228 
229 	/* padding to 32 bits */
230 	while ((mb->end - pos) & 0x3)
231 		err |= mbuf_write_u8(mb, 0x00);
232 	if (err)
233 		return err;
234 
235 	/* Encode RTCP Header */
236 	mb->pos = pos;
237 	len = (mb->end - pos - RTCP_HDR_SIZE)/sizeof(uint32_t);
238 	err = rtcp_hdr_encode(mb, count, type, len);
239 	if (err)
240 		return err;
241 
242 	mb->pos = mb->end;
243 
244 	return 0;
245 }
246 
247 
248 /**
249  * Encode an RTCP Packet into a buffer
250  *
251  * @param mb    Buffer to encode into
252  * @param type  RTCP Packet type
253  * @param count Packet-specific count
254  *
255  * @return 0 for success, otherwise errorcode
256  */
rtcp_encode(struct mbuf * mb,enum rtcp_type type,uint32_t count,...)257 int rtcp_encode(struct mbuf *mb, enum rtcp_type type, uint32_t count, ...)
258 {
259 	va_list ap;
260 	int err;
261 
262 	va_start(ap, count);
263 	err = rtcp_vencode(mb, type, count, ap);
264 	va_end(ap);
265 
266 	return err;
267 }
268 
269 
270 /**
271  * Decode one RTCP message from a buffer
272  *
273  * @param msgp Pointer to allocated RTCP Message
274  * @param mb   Buffer to decode from
275  *
276  * @return 0 for success, otherwise errorcode
277  */
rtcp_decode(struct rtcp_msg ** msgp,struct mbuf * mb)278 int rtcp_decode(struct rtcp_msg **msgp, struct mbuf *mb)
279 {
280 	struct rtcp_msg *msg = NULL;
281 	size_t start, i, sz, count, rem;
282 	int err;
283 
284 	if (!msgp)
285 		return EINVAL;
286 	if (mbuf_get_left(mb) < RTCP_HDR_SIZE)
287 		return EBADMSG;
288 
289 	msg = mem_zalloc(sizeof(*msg), rtcp_destructor);
290 	if (!msg)
291 		return ENOMEM;
292 
293 	start = mb->pos;
294 
295 	/* decode and check header */
296 	err = rtcp_hdr_decode(mb, &msg->hdr);
297 	if (err)
298 		goto out;
299 
300 	if (msg->hdr.version != RTCP_VERSION)
301 		goto badmsg;
302 
303 	/* check length and remaining */
304 	rem = msg->hdr.length * sizeof(uint32_t);
305 	if (mbuf_get_left(mb) < rem)
306 		goto badmsg;
307 
308 	count = msg->hdr.count;
309 
310 	switch (msg->hdr.pt) {
311 
312 	case RTCP_SR:
313 		if (mbuf_get_left(mb) < (RTCP_SRC_SIZE + RTCP_SR_SIZE))
314 			goto badmsg;
315 		msg->r.sr.ssrc     = ntohl(mbuf_read_u32(mb));
316 		msg->r.sr.ntp_sec  = ntohl(mbuf_read_u32(mb));
317 		msg->r.sr.ntp_frac = ntohl(mbuf_read_u32(mb));
318 		msg->r.sr.rtp_ts   = ntohl(mbuf_read_u32(mb));
319 		msg->r.sr.psent    = ntohl(mbuf_read_u32(mb));
320 		msg->r.sr.osent    = ntohl(mbuf_read_u32(mb));
321 
322 		err = rtcp_rr_alloc(&msg->r.sr.rrv, count);
323 		if (err)
324 			goto out;
325 		for (i=0; i<count && !err; i++)
326 			err = rtcp_rr_decode(mb, &msg->r.sr.rrv[i]);
327 		break;
328 
329 	case RTCP_RR:
330 		if (mbuf_get_left(mb) < RTCP_SRC_SIZE)
331 			goto badmsg;
332 		msg->r.rr.ssrc = ntohl(mbuf_read_u32(mb));
333 
334 		err = rtcp_rr_alloc(&msg->r.rr.rrv, count);
335 		if (err)
336 			goto out;
337 		for (i=0; i<count && !err; i++)
338 			err = rtcp_rr_decode(mb, &msg->r.rr.rrv[i]);
339 		break;
340 
341 	case RTCP_SDES:
342 		if (count == 0)
343 			break;
344 
345 		sz = count * sizeof(*msg->r.sdesv);
346 		msg->r.sdesv = mem_zalloc(sz, NULL);
347 		if (!msg->r.sdesv) {
348 			err = ENOMEM;
349 			goto out;
350 		}
351 
352 		for (i=0; i<msg->hdr.count && !err; i++)
353 			err = rtcp_sdes_decode(mb, &msg->r.sdesv[i]);
354 		break;
355 
356 	case RTCP_BYE:
357 		sz = count * sizeof(*msg->r.bye.srcv);
358 		msg->r.bye.srcv = mem_alloc(sz, NULL);
359 		if (!msg->r.bye.srcv) {
360 			err = ENOMEM;
361 			goto out;
362 		}
363 		if (mbuf_get_left(mb) < sz)
364 			goto badmsg;
365 		for (i=0; i<count; i++)
366 			msg->r.bye.srcv[i] = ntohl(mbuf_read_u32(mb));
367 
368 		/* decode reason (optional) */
369 		if (rem > count*sizeof(uint32_t)) {
370 			const size_t len = mbuf_read_u8(mb);
371 			if (mbuf_get_left(mb) < len)
372 				goto badmsg;
373 
374 			err = mbuf_strdup(mb, &msg->r.bye.reason, len);
375 		}
376 		break;
377 
378 	case RTCP_APP:
379 		if (mbuf_get_left(mb) < RTCP_APP_SIZE)
380 			goto badmsg;
381 		msg->r.app.src = ntohl(mbuf_read_u32(mb));
382 		(void)mbuf_read_mem(mb, (uint8_t *)msg->r.app.name,
383 				    sizeof(msg->r.app.name));
384 		if (rem > RTCP_APP_SIZE) {
385 			msg->r.app.data_len = rem - RTCP_APP_SIZE;
386 			msg->r.app.data = mem_alloc(msg->r.app.data_len, NULL);
387 			if (!msg->r.app.data) {
388 				err = ENOMEM;
389 				goto out;
390 			}
391 			if (mbuf_get_left(mb) < msg->r.app.data_len)
392 				goto badmsg;
393 			(void)mbuf_read_mem(mb, msg->r.app.data,
394 					    msg->r.app.data_len);
395 		}
396 		break;
397 
398 	case RTCP_FIR:
399 		if (mbuf_get_left(mb) < RTCP_FIR_SIZE)
400 			goto badmsg;
401 		msg->r.fir.ssrc = ntohl(mbuf_read_u32(mb));
402 		break;
403 
404 	case RTCP_NACK:
405 		if (mbuf_get_left(mb) < RTCP_NACK_SIZE)
406 			goto badmsg;
407 		msg->r.nack.ssrc = ntohl(mbuf_read_u32(mb));
408 		msg->r.nack.fsn  = ntohs(mbuf_read_u16(mb));
409 		msg->r.nack.blp  = ntohs(mbuf_read_u16(mb));
410 		break;
411 
412 	case RTCP_RTPFB:
413 		if (mbuf_get_left(mb) < RTCP_FB_SIZE)
414 			goto badmsg;
415 
416 		if (msg->hdr.length < 2)
417 			goto badmsg;
418 
419 		msg->r.fb.ssrc_packet = ntohl(mbuf_read_u32(mb));
420 		msg->r.fb.ssrc_media = ntohl(mbuf_read_u32(mb));
421 		msg->r.fb.n = msg->hdr.length - 2;
422 
423 		err = rtcp_rtpfb_decode(mb, msg);
424 		break;
425 
426 	case RTCP_PSFB:
427 		if (mbuf_get_left(mb) < RTCP_FB_SIZE)
428 			goto badmsg;
429 
430 		if (msg->hdr.length < 2)
431 			goto badmsg;
432 
433 		msg->r.fb.ssrc_packet = ntohl(mbuf_read_u32(mb));
434 		msg->r.fb.ssrc_media = ntohl(mbuf_read_u32(mb));
435 		msg->r.fb.n = msg->hdr.length - 2;
436 
437 		err = rtcp_psfb_decode(mb, msg);
438 		break;
439 
440 	default:
441 		/* unknown message type */
442 		mbuf_advance(mb, rem);
443 		break;
444 	}
445 	if (err)
446 		goto out;
447 
448 	/* slurp padding */
449 	while ((mb->pos - start) & 0x3 && mbuf_get_left(mb))
450 		++mb->pos;
451 
452  out:
453 	if (err)
454 		mem_deref(msg);
455 	else
456 		*msgp = msg;
457 
458 	return err;
459 
460  badmsg:
461 	mem_deref(msg);
462 	return EBADMSG;
463 }
464