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;
+}