FreeCalypso > hg > themwi-rtp-lib
changeset 29:3e01a71b7c7c
implement RTCP Rx
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 08 Jul 2024 02:55:32 +0000 |
parents | defe58aa537c |
children | 9fd693f234f8 |
files | include/endp.h include/rtcp_defs.h src/Makefile src/rtcp_rx.c |
diffstat | 4 files changed, 146 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- 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 <osmocom/core/osmo_io.h> #include <osmocom/core/socket.h> +#include <osmocom/core/timer.h> #include <themwi/rtp/twjit.h> @@ -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;
--- /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 <stdint.h> + +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
--- 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
--- /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 <stdint.h> +#include <stdbool.h> +#include <arpa/inet.h> /* for network byte order functions */ + +#include <osmocom/core/msgb.h> +#include <osmocom/core/osmo_io.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/timer.h> + +#include <themwi/rtp/endp.h> +#include <themwi/rtp/rtcp_defs.h> +#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, +};