# HG changeset patch # User Mychaela Falconia # Date 1720407332 0 # Node ID 3e01a71b7c7c90b2845ec93b75128cbb4d81ff9d # Parent defe58aa537c1d0bda53e338f2dc409daee91bb9 implement RTCP Rx diff -r defe58aa537c -r 3e01a71b7c7c include/endp.h --- a/include/endp.h Mon Jul 08 01:59:49 2024 +0000 +++ b/include/endp.h Mon Jul 08 02:55:32 2024 +0000 @@ -11,6 +11,7 @@ #include #include +#include #include @@ -22,11 +23,24 @@ bool restart; }; +struct twrtp_endp_rtcp_rx { + uint32_t sr_ssrc; + uint16_t sr_ntp_sec; + uint16_t sr_ntp_fract; + struct timespec sr_rx_time; + uint32_t rr_lost_word; + uint32_t rr_jitter; + bool got_sr; + bool got_rr; +}; + struct twrtp_endp_stats { uint32_t rx_rtp_pkt; uint32_t rx_rtp_badsrc; uint32_t rx_rtcp_pkt; uint32_t rx_rtcp_badsrc; + uint32_t rx_rtcp_invalid; + uint32_t rx_rtcp_wrong_ssrc; uint32_t tx_rtp_pkt; uint32_t tx_rtp_bytes; uint32_t tx_rtcp_pkt; @@ -42,7 +56,7 @@ struct osmo_sockaddr rtcp_remote; /* Rx and Tx state */ struct twrtp_jibuf_inst *twjit; - /* RTCP Rx structure to be inserted here */ + struct twrtp_endp_rtcp_rx rtcp_rx; struct twrtp_endp_tx tx; /* always have to have stats */ struct twrtp_endp_stats stats; diff -r defe58aa537c -r 3e01a71b7c7c include/rtcp_defs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/rtcp_defs.h Mon Jul 08 02:55:32 2024 +0000 @@ -0,0 +1,38 @@ +/* + * Some definitions for RTCP, just enough to implement the subset + * planned for libtwrtp. + */ + +#pragma once + +#include + +struct rtcp_sr_rr_hdr { + uint8_t v_p_rc; + uint8_t pt; + uint16_t len; + uint32_t ssrc; +}; + +struct rtcp_sr_block { + uint32_t ntp_sec; + uint32_t ntp_fract; + uint32_t rtp_ts; + uint32_t pkt_count; + uint32_t octet_count; +}; + +struct rtcp_rr_block { + uint32_t ssrc; + uint32_t lost_word; + uint32_t max_seq_ext; + uint32_t jitter; + uint16_t lsr_sec; + uint16_t lsr_fract; + uint16_t dlsr_sec; + uint16_t dlsr_fract; +}; + +#define RTCP_PT_SR 200 +#define RTCP_PT_RR 201 +#define RTCP_PT_SDES 202 diff -r defe58aa537c -r 3e01a71b7c7c src/Makefile --- a/src/Makefile Mon Jul 08 01:59:49 2024 +0000 +++ b/src/Makefile Mon Jul 08 02:55:32 2024 +0000 @@ -1,5 +1,6 @@ -OBJS= bind_fdpair.o endp_bind.o endp_create.o endp_register.o rtp_rx.o \ - rtp_tx.o set_remote.o twjit.o twjit_in.o twjit_out.o twjit_vty.o +OBJS= bind_fdpair.o endp_bind.o endp_create.o endp_register.o rtcp_rx.o \ + rtp_rx.o rtp_tx.o set_remote.o twjit.o twjit_in.o twjit_out.o \ + twjit_vty.o LIB= libtwrtp.a include ../config.defs diff -r defe58aa537c -r 3e01a71b7c7c src/rtcp_rx.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rtcp_rx.c Mon Jul 08 02:55:32 2024 +0000 @@ -0,0 +1,90 @@ +/* + * Here we implement RTCP Rx path via osmo_io callback. + */ + +#include +#include +#include /* for network byte order functions */ + +#include +#include +#include +#include + +#include +#include +#include "endp_internal.h" + +static void parse_rtcp(struct twrtp_endp *endp, struct msgb *msg) +{ + struct twrtp_endp_rtcp_rx *rxs = &endp->rtcp_rx; + struct rtcp_sr_rr_hdr *base_hdr; + struct rtcp_sr_block *sr; + struct rtcp_rr_block *rr; + unsigned rc, i; + + if (msg->len < sizeof(struct rtcp_sr_rr_hdr)) { +invalid: endp->stats.rx_rtcp_invalid++; + return; + } + base_hdr = (struct rtcp_sr_rr_hdr *) + msgb_pull(msg, sizeof(struct rtcp_sr_rr_hdr)); + if ((base_hdr->v_p_rc & 0xC0) != 0x80) + goto invalid; + switch (base_hdr->pt) { + case RTCP_PT_SR: + if (msg->len < sizeof(struct rtcp_sr_block)) + goto invalid; + sr = (struct rtcp_sr_block *) + msgb_pull(msg, sizeof(struct rtcp_sr_block)); + rxs->got_sr = true; + osmo_clock_gettime(CLOCK_MONOTONIC, &rxs->sr_rx_time); + rxs->sr_ssrc = ntohl(base_hdr->ssrc); + rxs->sr_ntp_sec = ntohl(sr->ntp_sec); + rxs->sr_ntp_fract = ntohl(sr->ntp_fract) >> 16; + break; + case RTCP_PT_RR: + break; + default: + goto invalid; + } + rc = base_hdr->v_p_rc & 0x1F; + if (msg->len < sizeof(struct rtcp_rr_block) * rc) + goto invalid; + for (i = 0; i < rc; i++) { + rr = (struct rtcp_rr_block *) + msgb_pull(msg, sizeof(struct rtcp_rr_block)); + if (ntohl(rr->ssrc) != endp->tx.ssrc) { + endp->stats.rx_rtcp_wrong_ssrc++; + continue; + } + rxs->got_rr = true; + rxs->rr_lost_word = ntohl(rr->lost_word); + rxs->rr_jitter = ntohl(rr->jitter); + } +} + +static void rtcp_rx_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg, + const struct osmo_sockaddr *saddr) +{ + struct twrtp_endp *endp = osmo_iofd_get_data(iofd); + + if (!msg) + return; + if (!endp->remote_set) { + msgb_free(msg); + return; + } + if (osmo_sockaddr_cmp(saddr, &endp->rtcp_remote)) { + endp->stats.rx_rtcp_badsrc++; + msgb_free(msg); + return; + } + endp->stats.rx_rtcp_pkt++; + parse_rtcp(endp, msg); + msgb_free(msg); +} + +const struct osmo_io_ops _twrtp_endp_iops_rtcp = { + .recvfrom_cb = rtcp_rx_cb, +};