/** * Listen on an RTP/RTCP Socket * * @param rsp Pointer to returned RTP socket * @param proto Transport protocol * @param ip Local IP address * @param min_port Minimum port range * @param max_port Maximum port range * @param enable_rtcp True to enable RTCP Session * @param recvh RTP Receive handler * @param rtcph RTCP Receive handler * @param arg Handler argument * * @return 0 for success, otherwise errorcode */ int rtp_listen(struct rtp_sock **rsp, int proto, const struct sa *ip, uint16_t min_port, uint16_t max_port, bool enable_rtcp, rtp_recv_h *recvh, rtcp_recv_h *rtcph, void *arg) { struct rtp_sock *rs; int err; if (!ip || min_port >= max_port || !recvh) return EINVAL; err = rtp_alloc(&rs); if (err) return err; rs->proto = proto; rs->recvh = recvh; rs->rtcph = rtcph; rs->arg = arg; /* Optional RTCP */ if (enable_rtcp) { err = rtcp_sess_alloc(&rs->rtcp, rs); if (err) goto out; } switch (proto) { case IPPROTO_UDP: err = udp_range_listen(rs, ip, min_port, max_port); break; default: err = EPROTONOSUPPORT; break; } out: if (err) mem_deref(rs); else *rsp = rs; return err; }
int test_rtp(void) { struct rtp_sock *rtp = NULL; struct mbuf *mb = NULL; uint8_t payload[PAYLOAD_SIZE]; int j; int err; memset(payload, 0, sizeof(payload)); mb = mbuf_alloc(RTP_HEADER_SIZE); if (!mb) return ENOMEM; err = rtp_alloc(&rtp); if (err) goto out; for (j=0; j<100; j++) { struct rtp_header hdr, hdr2; memset(&hdr, 0, sizeof(hdr)); hdr.m = rand_u16() & 0x01; hdr.pt = rand_u16() & 0x7f; hdr.ts = rand_u32(); rand_bytes(payload, sizeof(payload)); mb->pos = mb->end = RTP_HEADER_SIZE; err = mbuf_write_mem(mb, payload, sizeof(payload)); if (err) break; mb->pos = 0; err = rtp_encode(rtp, hdr.m, hdr.pt, hdr.ts, mb); if (err) break; mb->pos = 0; err = rtp_decode(rtp, mb, &hdr2); if (err) break; if (hdr.m != hdr2.m) { DEBUG_WARNING("marker bit mismatch (%d != %d)\n", hdr.m, hdr2.m); err = EBADMSG; break; } if (hdr.pt != hdr2.pt) { DEBUG_WARNING("payload type mismatch (%u != %u)\n", hdr.pt, hdr2.pt); err = EBADMSG; break; } if (hdr.ts != hdr2.ts) { DEBUG_WARNING("timestamp mismatch (%lu != %lu)\n", hdr.ts, hdr2.ts); err = EBADMSG; break; } if (hdr2.pad) { DEBUG_WARNING("unexpected padding bit\n"); err = EBADMSG; break; } if (hdr2.ext) { DEBUG_WARNING("unexpected extension bit\n"); err = EBADMSG; break; } if (RTP_HEADER_SIZE != mb->pos || (RTP_HEADER_SIZE + PAYLOAD_SIZE) != mb->end) { DEBUG_WARNING("invalid mbuf size (pos=%u end=%u)\n", mb->pos, mb->end); err = EBADMSG; break; } if (0 != memcmp(mbuf_buf(mb), payload, sizeof(payload))) { DEBUG_WARNING("RTP payload mismatch\n"); err = EBADMSG; break; } } out: mem_deref(rtp); mem_deref(mb); return err; }