1 /**
2  * @file sdes.c  RTCP Source Description
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_sa.h>
13 #include <re_rtp.h>
14 #include "rtcp.h"
15 
16 
17 #define DEBUG_MODULE "rtcp_sdes"
18 #define DEBUG_LEVEL 5
19 #include <re_dbg.h>
20 
21 
22 enum {
23 	RTCP_SDES_MIN_SIZE = 1,
24 };
25 
26 
27 /**
28  * Encode one SDES chunk into mbuffer
29  *
30  * @param mb    Buffer to encode into
31  * @param src   First SSRC/CSRC
32  * @param itemc Number of SDES items to encode
33  *
34  * @return 0 if success, otherwise errorcode
35  */
rtcp_sdes_encode(struct mbuf * mb,uint32_t src,uint32_t itemc,...)36 int rtcp_sdes_encode(struct mbuf *mb, uint32_t src, uint32_t itemc, ...)
37 {
38 	va_list ap;
39 	size_t start;
40 	int err = 0;
41 
42 	if (!mb || !itemc)
43 		return EINVAL;
44 
45 	va_start(ap, itemc);
46 
47 	start = mb->pos;
48 	err = mbuf_write_u32(mb, htonl(src));
49 
50 	/* add all SDES items */
51 	while (itemc-- && !err) {
52 		const uint8_t type = va_arg(ap, int);
53 		const char *v = va_arg(ap, const char *);
54 		size_t len;
55 		if (!v)
56 			continue;
57 
58 		len = strlen(v); /* note: max 255 chars */
59 		if (len > 255) {
60 			err = EINVAL;
61 			goto out;
62 		}
63 
64 		err  = mbuf_write_u8(mb, type);
65 		err |= mbuf_write_u8(mb, len & 0xff);
66 		err |= mbuf_write_mem(mb, (uint8_t *)v, len);
67 	}
68 
69 	/* END padding */
70 	err |= mbuf_write_u8(mb, RTCP_SDES_END);
71 	while ((mb->pos - start) & 0x3)
72 		err |= mbuf_write_u8(mb, RTCP_SDES_END);
73 
74  out:
75 	va_end(ap);
76 
77 	return err;
78 }
79 
80 
81 /**
82  * Decode SDES items from a buffer
83  *
84  * @param mb   Buffer to decode from
85  * @param sdes RTCP SDES to decode into
86  *
87  * @return 0 if success, otherwise errorcode
88  */
rtcp_sdes_decode(struct mbuf * mb,struct rtcp_sdes * sdes)89 int rtcp_sdes_decode(struct mbuf *mb, struct rtcp_sdes *sdes)
90 {
91 	size_t start;
92 
93 	if (!sdes)
94 		return EINVAL;
95 	if (mbuf_get_left(mb) < RTCP_SRC_SIZE)
96 		return EBADMSG;
97 
98 	start = mb->pos;
99 	sdes->src = ntohl(mbuf_read_u32(mb));
100 
101 	/* Decode all SDES items */
102 	while (mbuf_get_left(mb) >= RTCP_SDES_MIN_SIZE) {
103 		uint8_t type;
104 		struct rtcp_sdes_item *item;
105 
106 		type = mbuf_read_u8(mb);
107 		if (type == RTCP_SDES_END)
108 			break;
109 
110 		if (mbuf_get_left(mb) < 1)
111 			return EBADMSG;
112 
113 		if (!sdes->itemv) {
114 			sdes->itemv = mem_alloc(sizeof(*sdes->itemv), NULL);
115 			if (!sdes->itemv)
116 				return ENOMEM;
117 		}
118 		else {
119 			const size_t sz = (sdes->n + 1) * sizeof(*sdes->itemv);
120 			struct rtcp_sdes_item *itemv;
121 
122 			itemv = mem_realloc(sdes->itemv, sz);
123 			if (!itemv)
124 				return ENOMEM;
125 
126 			sdes->itemv = itemv;
127 		}
128 
129 		item = &sdes->itemv[sdes->n];
130 
131 		item->type = (enum rtcp_sdes_type)type;
132 		item->length = mbuf_read_u8(mb);
133 		if (mbuf_get_left(mb) < item->length)
134 			return EBADMSG;
135 		item->data = mem_alloc(item->length, NULL);
136 		if (!item->data)
137 			return ENOMEM;
138 		(void)mbuf_read_mem(mb, (uint8_t *)item->data, item->length);
139 
140 		sdes->n++;
141 	}
142 
143 	/* slurp padding */
144 	while ((mb->pos - start) & 0x3 && mbuf_get_left(mb))
145 		++mb->pos;
146 
147 	return 0;
148 }
149