diff src/rtcp_rx.c @ 29:3e01a71b7c7c

implement RTCP Rx
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 08 Jul 2024 02:55:32 +0000
parents src/rtp_rx.c@9e477a4b485a
children
line wrap: on
line diff
--- /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,
+};