summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlfred E. Heggestad <alfred.heggestad@gmail.com>2017-05-23 19:43:29 +0200
committerGitHub <noreply@github.com>2017-05-23 19:43:29 +0200
commitebbf920a502d6d460ff3ea8a57db0c624e3a0747 (patch)
treef809f27ad20915fa73849ae3bec53fef1d9eb01b
parent97229c0c2e13415d0fa1c808742c22adeb9b2f33 (diff)
rtpext: add RTP Header Extensions (RFC 5285) (#257)
* rtpext: add RTP Header Extensions (RFC 5285) * whitespace fix
-rw-r--r--src/core.h30
-rw-r--r--src/rtpext.c112
-rw-r--r--src/srcs.mk1
3 files changed, 143 insertions, 0 deletions
diff --git a/src/core.h b/src/core.h
index 51bfa6d..5dc5e9d 100644
--- a/src/core.h
+++ b/src/core.h
@@ -272,6 +272,36 @@ int reg_status(struct re_printf *pf, const struct reg *reg);
/*
+ * RTP Header Extensions
+ */
+
+#define RTPEXT_HDR_SIZE 4
+#define RTPEXT_TYPE_MAGIC 0xbede
+
+enum {
+ RTPEXT_ID_MIN = 1,
+ RTPEXT_ID_MAX = 14,
+};
+
+enum {
+ RTPEXT_LEN_MIN = 1,
+ RTPEXT_LEN_MAX = 16,
+};
+
+struct rtpext {
+ unsigned id:4;
+ unsigned len:4;
+ uint8_t data[RTPEXT_LEN_MAX];
+};
+
+
+int rtpext_hdr_encode(struct mbuf *mb, size_t num_bytes);
+int rtpext_encode(struct mbuf *mb, unsigned id, unsigned len,
+ const uint8_t *data);
+int rtpext_decode(struct rtpext *ext, struct mbuf *mb);
+
+
+/*
* RTP keepalive
*/
diff --git a/src/rtpext.c b/src/rtpext.c
new file mode 100644
index 0000000..82a6f6e
--- /dev/null
+++ b/src/rtpext.c
@@ -0,0 +1,112 @@
+/**
+ * @file rtpext.c RTP Header Extensions
+ *
+ * Copyright (C) 2017 Creytiv.com
+ */
+
+#include <string.h>
+#include <re.h>
+#include <baresip.h>
+#include "core.h"
+
+
+/*
+ * RFC 5285 A General Mechanism for RTP Header Extensions
+ *
+ * - One-Byte Header: Supported
+ * - Two-Byte Header: Not supported
+ */
+
+
+int rtpext_hdr_encode(struct mbuf *mb, size_t num_bytes)
+{
+ int err = 0;
+
+ if (!mb || !num_bytes)
+ return EINVAL;
+
+ if (num_bytes & 0x3) {
+ warning("rtpext: hdr_encode: num_bytes (%zu) must be multiple"
+ " of 4\n", num_bytes);
+ return EINVAL;
+ }
+
+ err |= mbuf_write_u16(mb, htons(RTPEXT_TYPE_MAGIC));
+ err |= mbuf_write_u16(mb, htons(num_bytes / 4));
+
+ return err;
+}
+
+
+int rtpext_encode(struct mbuf *mb, unsigned id, unsigned len,
+ const uint8_t *data)
+{
+ size_t start;
+ int err;
+
+ if (!mb || !data)
+ return EINVAL;
+
+ if (id < RTPEXT_ID_MIN || id > RTPEXT_ID_MAX)
+ return EINVAL;
+ if (len < RTPEXT_LEN_MIN || len > RTPEXT_LEN_MAX)
+ return EINVAL;
+
+ start = mb->pos;
+
+ err = mbuf_write_u8(mb, id << 4 | (len-1));
+ err |= mbuf_write_mem(mb, data, len);
+ if (err)
+ return err;
+
+ /* padding */
+ while ((mb->pos - start) & 0x03)
+ err |= mbuf_write_u8(mb, 0x00);
+
+ return err;
+}
+
+
+int rtpext_decode(struct rtpext *ext, struct mbuf *mb)
+{
+ uint8_t v;
+ int err;
+
+ if (!ext || !mb)
+ return EINVAL;
+
+ if (mbuf_get_left(mb) < 1)
+ return EBADMSG;
+
+ memset(ext, 0, sizeof(*ext));
+
+ v = mbuf_read_u8(mb);
+
+ ext->id = v >> 4;
+ ext->len = (v & 0x0f) + 1;
+
+ if (ext->id < RTPEXT_ID_MIN || ext->id > RTPEXT_ID_MAX) {
+ warning("rtpext: invalid ID %u\n", ext->id);
+ return EBADMSG;
+ }
+ if (ext->len > mbuf_get_left(mb)) {
+ warning("rtpext: short read\n");
+ return ENODATA;
+ }
+
+ err = mbuf_read_mem(mb, ext->data, ext->len);
+ if (err)
+ return err;
+
+ /* skip padding */
+ while (mbuf_get_left(mb)) {
+ uint8_t pad = mbuf_buf(mb)[0];
+
+ if (pad != 0x00)
+ break;
+
+ mbuf_advance(mb, 1);
+ }
+
+ return 0;
+}
diff --git a/src/srcs.mk b/src/srcs.mk
index cdb2a26..686ca7c 100644
--- a/src/srcs.mk
+++ b/src/srcs.mk
@@ -28,6 +28,7 @@ SRCS += net.c
SRCS += play.c
SRCS += realtime.c
SRCS += reg.c
+SRCS += rtpext.c
SRCS += rtpkeep.c
SRCS += sdp.c
SRCS += sipreq.c