FreeCalypso > hg > themwi-rtp-lib
comparison 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 |
comparison
equal
deleted
inserted
replaced
28:defe58aa537c | 29:3e01a71b7c7c |
---|---|
1 /* | |
2 * Here we implement RTCP Rx path via osmo_io callback. | |
3 */ | |
4 | |
5 #include <stdint.h> | |
6 #include <stdbool.h> | |
7 #include <arpa/inet.h> /* for network byte order functions */ | |
8 | |
9 #include <osmocom/core/msgb.h> | |
10 #include <osmocom/core/osmo_io.h> | |
11 #include <osmocom/core/socket.h> | |
12 #include <osmocom/core/timer.h> | |
13 | |
14 #include <themwi/rtp/endp.h> | |
15 #include <themwi/rtp/rtcp_defs.h> | |
16 #include "endp_internal.h" | |
17 | |
18 static void parse_rtcp(struct twrtp_endp *endp, struct msgb *msg) | |
19 { | |
20 struct twrtp_endp_rtcp_rx *rxs = &endp->rtcp_rx; | |
21 struct rtcp_sr_rr_hdr *base_hdr; | |
22 struct rtcp_sr_block *sr; | |
23 struct rtcp_rr_block *rr; | |
24 unsigned rc, i; | |
25 | |
26 if (msg->len < sizeof(struct rtcp_sr_rr_hdr)) { | |
27 invalid: endp->stats.rx_rtcp_invalid++; | |
28 return; | |
29 } | |
30 base_hdr = (struct rtcp_sr_rr_hdr *) | |
31 msgb_pull(msg, sizeof(struct rtcp_sr_rr_hdr)); | |
32 if ((base_hdr->v_p_rc & 0xC0) != 0x80) | |
33 goto invalid; | |
34 switch (base_hdr->pt) { | |
35 case RTCP_PT_SR: | |
36 if (msg->len < sizeof(struct rtcp_sr_block)) | |
37 goto invalid; | |
38 sr = (struct rtcp_sr_block *) | |
39 msgb_pull(msg, sizeof(struct rtcp_sr_block)); | |
40 rxs->got_sr = true; | |
41 osmo_clock_gettime(CLOCK_MONOTONIC, &rxs->sr_rx_time); | |
42 rxs->sr_ssrc = ntohl(base_hdr->ssrc); | |
43 rxs->sr_ntp_sec = ntohl(sr->ntp_sec); | |
44 rxs->sr_ntp_fract = ntohl(sr->ntp_fract) >> 16; | |
45 break; | |
46 case RTCP_PT_RR: | |
47 break; | |
48 default: | |
49 goto invalid; | |
50 } | |
51 rc = base_hdr->v_p_rc & 0x1F; | |
52 if (msg->len < sizeof(struct rtcp_rr_block) * rc) | |
53 goto invalid; | |
54 for (i = 0; i < rc; i++) { | |
55 rr = (struct rtcp_rr_block *) | |
56 msgb_pull(msg, sizeof(struct rtcp_rr_block)); | |
57 if (ntohl(rr->ssrc) != endp->tx.ssrc) { | |
58 endp->stats.rx_rtcp_wrong_ssrc++; | |
59 continue; | |
60 } | |
61 rxs->got_rr = true; | |
62 rxs->rr_lost_word = ntohl(rr->lost_word); | |
63 rxs->rr_jitter = ntohl(rr->jitter); | |
64 } | |
65 } | |
66 | |
67 static void rtcp_rx_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg, | |
68 const struct osmo_sockaddr *saddr) | |
69 { | |
70 struct twrtp_endp *endp = osmo_iofd_get_data(iofd); | |
71 | |
72 if (!msg) | |
73 return; | |
74 if (!endp->remote_set) { | |
75 msgb_free(msg); | |
76 return; | |
77 } | |
78 if (osmo_sockaddr_cmp(saddr, &endp->rtcp_remote)) { | |
79 endp->stats.rx_rtcp_badsrc++; | |
80 msgb_free(msg); | |
81 return; | |
82 } | |
83 endp->stats.rx_rtcp_pkt++; | |
84 parse_rtcp(endp, msg); | |
85 msgb_free(msg); | |
86 } | |
87 | |
88 const struct osmo_io_ops _twrtp_endp_iops_rtcp = { | |
89 .recvfrom_cb = rtcp_rx_cb, | |
90 }; |