From 3f124356e1208be35fb15e91d2dbe1c96e28b39c Mon Sep 17 00:00:00 2001 From: dnygate <64208008+dnygate@users.noreply.github.com> Date: Fri, 4 Sep 2026 12:25:15 +0100 Subject: [PATCH 1/2] Add `force strip extmap` flag RTP header extensions are only processed, and unknown ones stripped, if at least one side of the call negotiated header extensions through `a=extmap` attributes. Otherwise RTP is forwarded untouched, including any header extensions an endpoint may include without having announced them. Add a `force strip extmap` flag which selects header extension processing for all streams of a call regardless of whether any extensions were negotiated, so that unannounced header extensions are removed. This is useful when forwarding media from sources that always include header extensions towards endpoints that do not cope with them. --- daemon/call.c | 2 ++ daemon/call_flags.c | 4 ++++ daemon/media_socket.c | 5 ++++- docs/ng_control_protocol.md | 9 +++++++++ include/call.h | 1 + include/call_flags.h | 4 +++- 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 1387aba24..2e5f436c1 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2762,6 +2762,8 @@ static void __call_monologue_init_from_flags(struct call_monologue *ml, struct c call->last_signal_us = rtpe_now; call->deleted_us = 0; + if (flags->force_strip_extmap) + CALL_SET(call, FORCE_STRIP_EXTMAP); call->media_rec_slots = (flags->media_rec_slots > 0 && call->media_rec_slots == 0) ? flags->media_rec_slots : call->media_rec_slots; diff --git a/daemon/call_flags.c b/daemon/call_flags.c index 0af65cedd..c072f0d64 100644 --- a/daemon/call_flags.c +++ b/daemon/call_flags.c @@ -970,6 +970,10 @@ const char *call_ng_flags_flags(str *s, unsigned int idx, helper_arg arg) { case CSH_LOOKUP("strip-extmap"): case CSH_LOOKUP("strip extmap"): return call_ng_flags_str_ht(STR_PTR("all"), 0, &out->rtpext_strip); + case CSH_LOOKUP("force-strip-extmap"): + case CSH_LOOKUP("force strip extmap"): + out->force_strip_extmap = true; + break; case CSH_LOOKUP("symmetric-codecs"): case CSH_LOOKUP("symmetric codecs"): ilog(LOG_INFO, "Ignoring obsolete flag `symmetric-codecs`"); diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 540fcdf7e..502f5afdc 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -2545,7 +2545,10 @@ static void __determine_rtpext_handler(struct call_media *in, struct call_media if (!sh || !out) return; - if (in->extmap.length || out->extmap.length) + /* With `force strip extmap` set on the call, use the extmap printer even + * if no header extensions were negotiated, so that unannounced header + * extensions are removed from forwarded RTP. */ + if (in->extmap.length || out->extmap.length || CALL_ISSET(out->call, FORCE_STRIP_EXTMAP)) sh->rtpext = &rtpext_printer_extmap; else sh->rtpext = &rtpext_printer_copy; diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index b8889303f..69fbba989 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -1361,6 +1361,15 @@ Spaces in each string may be replaced by hyphens. Legacy alias for `extmap=[strip=[all]]` to remove all `a=rtpmap` attributes from the outgoing SDP. +* `force strip extmap` + + Process RTP header extensions of forwarded media even if no header + extensions were negotiated in the SDP. Normally, RTP header extensions + are passed through untouched if neither side included any `a=extmap` + attributes. With this flag set, header extensions that were not + negotiated are removed from forwarded RTP. Once set, the flag remains + in effect for the lifetime of the call. + * `strict source` Normally, *rtpengine* attempts to learn the correct endpoint address for every stream during diff --git a/include/call.h b/include/call.h index 470ff72db..75c83decf 100644 --- a/include/call.h +++ b/include/call.h @@ -255,6 +255,7 @@ enum { #define CALL_FLAG_BLOCK_MEDIA (1LL << 28) #define CALL_FLAG_SILENCE_MEDIA (1LL << 29) #define CALL_FLAG_NO_REC_DB (1LL << 30) +#define CALL_FLAG_FORCE_STRIP_EXTMAP (1LL << 31) /* access macros */ #define SP_ISSET(p, f) bf_isset(&(p)->sp_flags, SP_FLAG_ ## f) diff --git a/include/call_flags.h b/include/call_flags.h index e738e66c3..fe99037a0 100644 --- a/include/call_flags.h +++ b/include/call_flags.h @@ -323,7 +323,9 @@ RTPE_NG_FLAGS_STR_CASE_HT_PARAMS moh_sendrecv:1, moh_reflect:1, /* prevents double MoH holds */ - moh_double_hold:1; + moh_double_hold:1, + /* process RTP header extensions even if none were negotiated */ + force_strip_extmap:1; }; From 6df5d46257b28aac88111d2c873ed046d7a87494 Mon Sep 17 00:00:00 2001 From: dnygate <64208008+dnygate@users.noreply.github.com> Date: Thu, 3 Sep 2026 17:06:11 +0100 Subject: [PATCH 2/2] Add test for `force strip extmap` --- t/auto-daemon-tests-rtp-ext.pl | 57 ++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/t/auto-daemon-tests-rtp-ext.pl b/t/auto-daemon-tests-rtp-ext.pl index 14d9cde85..cd484b299 100755 --- a/t/auto-daemon-tests-rtp-ext.pl +++ b/t/auto-daemon-tests-rtp-ext.pl @@ -4026,5 +4026,62 @@ +# force strip extmap: header extensions removed even though none were negotiated + +($sock_a, $sock_ax, $sock_b, $sock_bx) = new_call( + [qw(198.51.100.1 7690)], + [qw(198.51.100.1 7691)], + [qw(198.51.100.3 7692)], + [qw(198.51.100.3 7693)], +); + +($port_a, $port_ax) = offer('force strip extmap', { flags => ['force strip extmap'] }, <