From 42ded6accad3df69b59a56ab58488962901496ff Mon Sep 17 00:00:00 2001 From: Ashwin Date: Tue, 4 Aug 2026 17:21:12 +0000 Subject: [PATCH] MT#55283 Mirror generate-RTCP Sender Reports to Homer (fixes #1684) Closes #2151 Closes #1684 Change-Id: Ia200369069ff5b8440bde8ec6a426e82d6e2bc1b --- daemon/rtcp.c | 61 +++++++++++++++++++++++++++++++++++++ docs/ng_control_protocol.md | 3 +- docs/rtpengine.md | 3 +- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/daemon/rtcp.c b/daemon/rtcp.c index 46336f0fc..6963e43a4 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -1407,6 +1407,62 @@ void rtcp_init(void) { +// Send generated RTCP to Homer in the same JSON format used for received RTCP. +static void rtcp_homer_generated(call_t *c, struct sender_report_packet *sr, + struct ssrc_sender_report *ssr, ssrc_rr_q *srrs, struct call_media *media, + uint32_t ssrc, const endpoint_t *src, const endpoint_t *dst) +{ + struct rtcp_process_ctx ctx; + struct sdes_chunk chunk; + struct sdes_item item; + struct source_description_packet sdes; + + if (!rtcp_handlers.homer->init) + return; + + ZERO(ctx); + rtcp_handlers.homer->init(&ctx); + + ctx.scratch_common_ssrc = ssrc; + ctx.scratch.sr = *ssr; + ctx.scratch.sr.ssrc = ssrc; + + rtcp_handlers.homer->sr(&ctx, sr); + rtcp_handlers.homer->rr_list_start(&ctx, &sr->rtcp); + + for (__auto_type l = srrs->head; l; l = l->next) { + struct ssrc_receiver_report *srr = l->data; + ctx.scratch.rr = *srr; + rtcp_handlers.homer->rr(&ctx, NULL); + } + + rtcp_handlers.homer->rr_list_end(&ctx); + + ZERO(sdes); + sdes.header.count = 1; + rtcp_handlers.homer->sdes_list_start(&ctx, &sdes); + + ZERO(chunk); + chunk.ssrc = htonl(ssrc); + + ZERO(item); + item.type = SDES_TYPE_CNAME; + item.length = rtpe_instance_id.len; + rtcp_handlers.homer->sdes_item(&ctx, &chunk, &item, rtpe_instance_id.s); + + if (media->bundle) { + ZERO(item); + item.type = SDES_TYPE_MID; + item.length = media->media_id.len; + rtcp_handlers.homer->sdes_item(&ctx, &chunk, &item, media->media_id.s); + } + + rtcp_handlers.homer->sdes_list_end(&ctx); + rtcp_handlers.homer->finish(&ctx, c, src, dst, rtpe_now); +} + + + static GString *rtcp_sender_report(struct ssrc_sender_report *ssr, uint32_t ssrc, uint32_t ssrc_out, uint32_t ts, uint32_t packets, uint32_t octets, ssrc_q *rrs, ssrc_rr_q *srrs, struct call_media *media) @@ -1608,6 +1664,11 @@ void rtcp_send_report(struct call_media *media, struct ssrc_entry_call *ssrc_out atomic64_get(&ssrc_out->stats->bytes), &rrs, &srrs, media); + // mirror generated RTCP to Homer (plaintext, before SRTCP) if configured + rtcp_homer_generated(media->call, (struct sender_report_packet *) sr->str, + &ssr, &srrs, media, ssrc_out->h.ssrc, + &ps->selected_sfd->socket.local, &ps->endpoint); + // handle crypto str rtcp_packet = STR_GS(sr); diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index 95bd55c4a..4eb291b1d 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -438,7 +438,8 @@ Optionally included keys are: received RTCP packets will not simply be passed through as usual, but instead will be consumed, and instead *rtpengine* will generate its own RTCP packets to send to the RTP peers. This flag will be effective for - both sides of a call. + both sides of a call. If Homer is configured, the generated RTCP reports + are also sent to Homer (even when no original RTCP was received). * `ICE` diff --git a/docs/rtpengine.md b/docs/rtpengine.md index 88c73f319..aeac15665 100644 --- a/docs/rtpengine.md +++ b/docs/rtpengine.md @@ -745,7 +745,8 @@ call to inject-DTMF won't be sent to __\-\-dtmf-log-dest=__ or __\-\-listen-tcp- - __\-\-homer=__*IP46*:*PORT* Enables sending the decoded contents of RTCP packets to a Homer SIP - capture server. + capture server, including RTCP reports generated by rtpengine itself + when generate RTCP is enabled (even if no original RTCP was received). The transport is HEP version 3 and payload format is JSON. This argument takes an IP address and a port number as value. Also enables sending the control NG traffic to a capturing agent.