Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b
Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/rtp/sdes.c b/src/rtp/sdes.c
new file mode 100644
index 0000000..711d8a9
--- /dev/null
+++ b/src/rtp/sdes.c
@@ -0,0 +1,148 @@
+/**
+ * @file sdes.c RTCP Source Description
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <string.h>
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_mem.h>
+#include <re_mbuf.h>
+#include <re_list.h>
+#include <re_sa.h>
+#include <re_rtp.h>
+#include "rtcp.h"
+
+
+#define DEBUG_MODULE "rtcp_sdes"
+#define DEBUG_LEVEL 5
+#include <re_dbg.h>
+
+
+enum {
+ RTCP_SDES_MIN_SIZE = 1,
+};
+
+
+/**
+ * Encode one SDES chunk into mbuffer
+ *
+ * @param mb Buffer to encode into
+ * @param src First SSRC/CSRC
+ * @param itemc Number of SDES items to encode
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtcp_sdes_encode(struct mbuf *mb, uint32_t src, uint32_t itemc, ...)
+{
+ va_list ap;
+ size_t start;
+ int err = 0;
+
+ if (!mb || !itemc)
+ return EINVAL;
+
+ va_start(ap, itemc);
+
+ start = mb->pos;
+ err = mbuf_write_u32(mb, htonl(src));
+
+ /* add all SDES items */
+ while (itemc-- && !err) {
+ const uint8_t type = va_arg(ap, int);
+ const char *v = va_arg(ap, const char *);
+ size_t len;
+ if (!v)
+ continue;
+
+ len = strlen(v); /* note: max 255 chars */
+ if (len > 255) {
+ err = EINVAL;
+ goto out;
+ }
+
+ err = mbuf_write_u8(mb, type);
+ err |= mbuf_write_u8(mb, len & 0xff);
+ err |= mbuf_write_mem(mb, (uint8_t *)v, len);
+ }
+
+ /* END padding */
+ err |= mbuf_write_u8(mb, RTCP_SDES_END);
+ while ((mb->pos - start) & 0x3)
+ err |= mbuf_write_u8(mb, RTCP_SDES_END);
+
+ out:
+ va_end(ap);
+
+ return err;
+}
+
+
+/**
+ * Decode SDES items from a buffer
+ *
+ * @param mb Buffer to decode from
+ * @param sdes RTCP SDES to decode into
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int rtcp_sdes_decode(struct mbuf *mb, struct rtcp_sdes *sdes)
+{
+ size_t start;
+
+ if (!sdes)
+ return EINVAL;
+ if (mbuf_get_left(mb) < RTCP_SRC_SIZE)
+ return EBADMSG;
+
+ start = mb->pos;
+ sdes->src = ntohl(mbuf_read_u32(mb));
+
+ /* Decode all SDES items */
+ while (mbuf_get_left(mb) >= RTCP_SDES_MIN_SIZE) {
+ uint8_t type;
+ struct rtcp_sdes_item *item;
+
+ type = mbuf_read_u8(mb);
+ if (type == RTCP_SDES_END)
+ break;
+
+ if (mbuf_get_left(mb) < 1)
+ return EBADMSG;
+
+ if (!sdes->itemv) {
+ sdes->itemv = mem_alloc(sizeof(*sdes->itemv), NULL);
+ if (!sdes->itemv)
+ return ENOMEM;
+ }
+ else {
+ const size_t sz = (sdes->n + 1) * sizeof(*sdes->itemv);
+ struct rtcp_sdes_item *itemv;
+
+ itemv = mem_realloc(sdes->itemv, sz);
+ if (!itemv)
+ return ENOMEM;
+
+ sdes->itemv = itemv;
+ }
+
+ item = &sdes->itemv[sdes->n];
+
+ item->type = (enum rtcp_sdes_type)type;
+ item->length = mbuf_read_u8(mb);
+ if (mbuf_get_left(mb) < item->length)
+ return EBADMSG;
+ item->data = mem_alloc(item->length, NULL);
+ if (!item->data)
+ return ENOMEM;
+ (void)mbuf_read_mem(mb, (uint8_t *)item->data, item->length);
+
+ sdes->n++;
+ }
+
+ /* slurp padding */
+ while ((mb->pos - start) & 0x3 && mbuf_get_left(mb))
+ ++mb->pos;
+
+ return 0;
+}