int test_rtcp_decode(void) { struct rtcp_msg *msg = NULL; struct mbuf *mb; int err = 0; mb = mbuf_alloc(512); if (!mb) return ENOMEM; err |= mbuf_write_u8(mb, 0x55); /* overhead -- test padding */ err |= mbuf_write_mem(mb, rtcp_sdes, sizeof(rtcp_sdes)); err |= mbuf_write_u8(mb, 0xaa); /* junk */ mb->pos = 1; while (mbuf_get_left(mb) >= 4 && !err) { err = rtcp_decode(&msg, mb); msg = mem_deref(msg); } mem_deref(msg); mem_deref(mb); if (err) return err; err = test_rtcp_decode_badmsg(); if (err) return err; return err; }
static int test_rtcp_decode_badmsg(void) { struct rtcp_msg *msg = NULL; uint32_t ssrc = 0xcafebabe; struct mbuf *mb; int err = 0; mb = mbuf_alloc(128); if (!mb) { err = ENOMEM; goto out; } err = rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_SLI, ssrc, ssrc, NULL, NULL); if (err) goto out; /* simulate a corrupt RTCP packet */ mb->pos = 2; (void)mbuf_write_u16(mb, htons(0)); mb->pos = 0; if (EBADMSG != rtcp_decode(&msg, mb)) { err = EBADMSG; goto out; } out: mem_deref(msg); mem_deref(mb); return err; }
int test_rtcp_encode(void) { struct mbuf *mb; const size_t sz = sizeof(rtcp_msg) - 1; const uint32_t srcv[2] = {0x12345678, 0x00abcdef}; int err = 0; mb = mbuf_alloc(512); if (!mb) return ENOMEM; err |= rtcp_encode(mb, RTCP_SR, 1, 0x12345678, 0x00112233, 0x44556677, 0x22332233, 0x00001111, 0x00002222, encode_handler, 0); err |= rtcp_encode(mb, RTCP_RR, 1, 0x12345678, encode_handler, 0); err |= rtcp_encode(mb, RTCP_SDES, 1, sdes_encode_handler, 0); err |= rtcp_encode(mb, RTCP_BYE, 2, srcv, "ciao"); err |= rtcp_encode(mb, RTCP_APP, 0, 0x12345678, "name", "data", (size_t)4); err |= rtcp_encode(mb, RTCP_FIR, 0, 0x12345678); err |= rtcp_encode(mb, RTCP_NACK, 0, 0x12345678, 0x89ab, 0xcdef); err |= rtcp_encode(mb, RTCP_RTPFB, RTCP_RTPFB_GNACK, 0x12345678, 0xfedcba98, gnack_encode, 0); err |= rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_PLI, 0x12345678, 0xfedcba98, NULL, 0); err |= rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_SLI, 0x12345678, 0xfedcba98, sli_encode, 0); if (err) goto out; if (mb->end != sz) { err = EPROTO; } if (0 != memcmp(mb->buf, rtcp_msg, mb->end)) { err = EBADMSG; } if (err) { DEBUG_WARNING("encode error: %m\n", err); hexdump(stderr, mb->buf, mb->end); } mb->pos = 0; while (mbuf_get_left(mb) >= 4 && !err) { struct rtcp_msg *msg = NULL; err = rtcp_decode(&msg, mb); msg = mem_deref(msg); } if (err) goto out; /* verify that rtcp_decode() read the whole buffer */ TEST_EQUALS(mb->end, mb->pos); out: mem_deref(mb); return err; }
static void rtcp_recv_handler(const struct sa *src, struct mbuf *mb, void *arg) { struct rtp_sock *rs = arg; struct rtcp_msg *msg; while (0 == rtcp_decode(&msg, mb)) { /* handle internally first */ rtcp_handler(rs->rtcp, msg); /* then relay to application */ if (rs->rtcph) rs->rtcph(src, msg, rs->arg); mem_deref(msg); } }
int test_rtcp_encode_afb(void) { uint32_t ssrc_packet_sender, ssrc_media_source; const char *afb_payload = "AFB tull"; struct rtcp_msg *msg = NULL; struct mbuf *mb; int err = 0; mb = mbuf_alloc(512); if (!mb) return ENOMEM; ssrc_packet_sender = 0xbad00bad; ssrc_media_source = 0; /* always 0 */ err = rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_AFB, ssrc_packet_sender, ssrc_media_source, afb_encode_handler, afb_payload); if (err) goto out; mb->pos = 0; err = rtcp_decode(&msg, mb); if (err) goto out; if (msg->hdr.count != RTCP_PSFB_AFB) { DEBUG_WARNING("expected AFB, got fmt=%u\n", msg->hdr.count); err = EPROTO; goto out; } if (msg->r.fb.ssrc_packet != ssrc_packet_sender || msg->r.fb.ssrc_media != ssrc_media_source) { DEBUG_WARNING("error in SSRC encoding\n"); err = EBADMSG; goto out; } if (!msg->r.fb.fci.afb || mbuf_get_left(msg->r.fb.fci.afb) != strlen(afb_payload)) { DEBUG_WARNING("error in AFB mbuf (left=%u, size=%u)\n", mbuf_get_left(msg->r.fb.fci.afb), strlen(afb_payload)); err = EBADMSG; goto out; } if (0 != memcmp(mbuf_buf(msg->r.fb.fci.afb), afb_payload, strlen(afb_payload))) { DEBUG_WARNING("error in AFB mbuf content\n"); err = EBADMSG; goto out; } /* verify that rtcp_decode() read the whole buffer */ TEST_EQUALS(mb->end, mb->pos); out: mem_deref(mb); mem_deref(msg); return err; }