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