diff options
Diffstat (limited to 'src/rtpext.c')
-rw-r--r-- | src/rtpext.c | 112 |
1 files changed, 112 insertions, 0 deletions
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; +} |