|
|
|
@ -11,6 +11,17 @@ struct rtp_exthdr { |
|
|
|
uint16_t length; |
|
|
|
} __attribute__ ((packed)); |
|
|
|
|
|
|
|
struct rtp_rfc8285_hdr { |
|
|
|
uint8_t be; |
|
|
|
uint8_t de; |
|
|
|
uint16_t length; |
|
|
|
} __attribute__ ((packed)); |
|
|
|
|
|
|
|
struct rtp_rfc8285_item { |
|
|
|
uint8_t id; |
|
|
|
uint8_t length; |
|
|
|
} __attribute__ ((packed)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -55,8 +66,71 @@ const struct rtp_payload_type rfc_rtp_payload_types[] = |
|
|
|
const int num_rfc_rtp_payload_types = G_N_ELEMENTS(rfc_rtp_payload_types); |
|
|
|
|
|
|
|
|
|
|
|
static void rtp_rfc8285_iterate_short(str s, const struct rtp_rfc8285_hdr *hdr, |
|
|
|
rtp_rfc8285_handler cb, struct packet_handler_ctx *arg) |
|
|
|
{ |
|
|
|
str_shift(&s, sizeof(*hdr)); |
|
|
|
|
|
|
|
while (s.len) { |
|
|
|
uint8_t id_len = s.s[0]; |
|
|
|
if (id_len == '\0') { |
|
|
|
// padding |
|
|
|
str_shift(&s, 1); |
|
|
|
continue; |
|
|
|
} |
|
|
|
uint8_t id = id_len >> 4; |
|
|
|
uint8_t len = (id_len & 0xf) + 1; |
|
|
|
str_shift(&s, 1); |
|
|
|
|
|
|
|
if (s.len < len) |
|
|
|
return; |
|
|
|
|
|
|
|
cb(arg, id, &STR_LEN(s.s, len)); |
|
|
|
|
|
|
|
str_shift(&s, len); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void rtp_rfc8285_iterate_long(str s, const struct rtp_rfc8285_hdr *hdr, |
|
|
|
rtp_rfc8285_handler cb, struct packet_handler_ctx *arg) |
|
|
|
{ |
|
|
|
str_shift(&s, sizeof(*hdr)); |
|
|
|
|
|
|
|
struct rtp_rfc8285_item *item; |
|
|
|
|
|
|
|
while (s.len >= sizeof(*item)) { |
|
|
|
if (s.s[0] == '\0') { |
|
|
|
// padding |
|
|
|
str_shift(&s, 1); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
item = (struct rtp_rfc8285_item *) s.s; |
|
|
|
|
|
|
|
str_shift(&s, sizeof(*item)); |
|
|
|
|
|
|
|
if (s.len < item->length) |
|
|
|
return; |
|
|
|
|
|
|
|
cb(arg, item->id, &STR_LEN(s.s, item->length)); |
|
|
|
|
|
|
|
str_shift(&s, item->length); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void rtp_rfc8285_iterate(const str *extensions, rtp_rfc8285_handler cb, struct packet_handler_ctx *arg) { |
|
|
|
const struct rtp_rfc8285_hdr *hdr; |
|
|
|
|
|
|
|
if (extensions->len < sizeof(*hdr)) |
|
|
|
return; |
|
|
|
|
|
|
|
hdr = (struct rtp_rfc8285_hdr *) extensions->s; |
|
|
|
|
|
|
|
if (hdr->be == 0xbe && hdr->de == 0xde) |
|
|
|
rtp_rfc8285_iterate_short(*extensions, hdr, cb, arg); |
|
|
|
else if (hdr->be == 0x10 && (hdr->de & 0xf0) == 0x00) |
|
|
|
rtp_rfc8285_iterate_long(*extensions, hdr, cb, arg); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct rtp_header *rtp_payload(str *p, const str *s, str *exts) { |
|
|
|
|