From c4b81b644c233bc0945567a13738b9dff9f5376a Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 8 Oct 2024 13:50:33 -0400 Subject: [PATCH] MT#55283 add option `allow no codec media` Change-Id: I516972d85a26d68b9f9c2a9613294a02448391b6 --- daemon/call.c | 6 ++-- daemon/call_interfaces.c | 6 ++++ daemon/codec.c | 5 ++- daemon/sdp.c | 15 ++++++-- docs/ng_control_protocol.md | 12 +++++++ include/call_interfaces.h | 1 + include/codec.h | 4 +-- t/auto-daemon-tests.pl | 71 +++++++++++++++++++++++++++++++++++++ utils/rtpengine-ng-client | 1 + 9 files changed, 113 insertions(+), 8 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 60518f1c18..92f6866af2 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2456,7 +2456,7 @@ static void codecs_offer(struct call_media *media, struct call_media *other_medi codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs); if (!other_media->codecs.strip_full) codec_store_offer(&other_media->codecs, &flags->codec_transcode, &sp->codecs); - codec_store_check_empty(&other_media->codecs, &sp->codecs); + codec_store_check_empty(&other_media->codecs, &sp->codecs, flags); codec_store_accept(&other_media->codecs, &flags->codec_accept, NULL); codec_store_accept(&other_media->codecs, &flags->codec_consume, &sp->codecs); codec_store_track(&other_media->codecs, &flags->codec_mask); @@ -2489,7 +2489,7 @@ static void codecs_offer(struct call_media *media, struct call_media *other_medi codec_store_strip(&media->codecs, &flags->codec_mask, flags->codec_except); codec_store_offer(&media->codecs, &flags->codec_offer, &sp->codecs); codec_store_transcode(&media->codecs, &flags->codec_transcode, &sp->codecs); - codec_store_check_empty(&media->codecs, &sp->codecs); + codec_store_check_empty(&media->codecs, &sp->codecs, flags); codec_store_synthesise(&media->codecs, &other_media->codecs); // update supp codecs based on actions so far @@ -2535,7 +2535,7 @@ static void codecs_answer(struct call_media *media, struct call_media *other_med .allow_asymmetric = !!flags->allow_asymmetric_codecs); codec_store_strip(&other_media->codecs, &flags->codec_strip, flags->codec_except); codec_store_offer(&other_media->codecs, &flags->codec_offer, &sp->codecs); - codec_store_check_empty(&other_media->codecs, &sp->codecs); + codec_store_check_empty(&other_media->codecs, &sp->codecs, flags); // update callee side codec handlers again (second pass after the offer) as we // might need to update some handlers, e.g. when supplemental codecs have been diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 6f3d49ef57..92f52a91f4 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -976,6 +976,12 @@ void call_ng_flags_flags(str *s, unsigned int idx, helper_arg arg) { case CSH_LOOKUP("allow-asymmetric-codec"): out->allow_asymmetric_codecs = 1; break; + case CSH_LOOKUP("allow-no-codec-media"): + case CSH_LOOKUP("allow-no-codec-medias"): + case CSH_LOOKUP("allow-empty-codec-media"): + case CSH_LOOKUP("allow-empty-codec-medias"): + out->allow_no_codec_media = 1; + break; case CSH_LOOKUP("allow-transcoding"): out->allow_transcoding = 1; break; diff --git a/daemon/codec.c b/daemon/codec.c index 1dd85cf3fa..6ea60b4648 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -5160,10 +5160,13 @@ void __codec_store_populate_reuse(struct codec_store *dst, struct codec_store *s } } -void codec_store_check_empty(struct codec_store *dst, struct codec_store *src) { +void codec_store_check_empty(struct codec_store *dst, struct codec_store *src, sdp_ng_flags *flags) { if (dst->codec_prefs.length) return; + if (flags->allow_no_codec_media) + return; + ilog(LOG_WARN, "Usage error: List of codecs empty. Restoring original list of codecs. " "Results may be unexpected."); diff --git a/daemon/sdp.c b/daemon/sdp.c index 9e1b067ba5..5b039b27cd 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -2032,8 +2032,11 @@ static void print_codec_list(GString *s, struct call_media *media) { return; } - if (media->codecs.codec_prefs.length == 0) - return; // legacy protocol or usage error + if (media->codecs.codec_prefs.length == 0) { + // legacy protocol, usage error, or allow-no-codec-media set. Print something and bail + g_string_append(s, "0"); + return; + } for (__auto_type l = media->codecs.codec_prefs.head; l; l = l->next) { rtp_payload_type *pt = l->data; @@ -3052,6 +3055,14 @@ static struct call_media *sdp_out_set_source_media_address(struct call_media *me return source_media; } + // handle special case: allow-no-codec-media + if (flags->allow_no_codec_media && media->codecs.codec_prefs.length == 0 + && proto_is_rtp(media->protocol)) + { + // convert to rejected/removed stream + *sdp_address = NULL; + } + return NULL; } diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index f98cea1b5f..c34c2b0f21 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -883,6 +883,18 @@ Spaces in each string may be replaced by hyphens. Note that payload type number translation will not be performed in this situation. +* `allow no codec media` + + Enables special handling for SDP media sections (`m=` lines) that are left + without any codecs after codec manipulation operations (in particular codec + stripping) have been performed. By default without this option set, a media + section without any codecs would be considered a usage error, and the + original list of codecs would be restored so that media flow can be + established. With this option set, a media section without any codecs would + be considered intentionally so, and would be converted to a rejected or + removed media section, that is a media section with a zero port, a dummy + format list, and further attributes. + * `allow transcoding` This flag is only useful in commands that provide an explicit answer SDP to *rtpengine* diff --git a/include/call_interfaces.h b/include/call_interfaces.h index e04c36781e..e12eaedd6c 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -190,6 +190,7 @@ struct sdp_ng_flags { single_codec:1, reuse_codec:1, static_codecs:1, + allow_no_codec_media:1, allow_transcoding:1, allow_asymmetric_codecs:1, early_media:1, diff --git a/include/codec.h b/include/codec.h index 3208f42947..2103ba76f4 100644 --- a/include/codec.h +++ b/include/codec.h @@ -141,8 +141,8 @@ __attribute__((nonnull(1, 2))) void codec_store_strip(struct codec_store *, str_q *strip, str_case_ht except); __attribute__((nonnull(1, 2, 3))) void codec_store_offer(struct codec_store *, str_q *, struct codec_store *); -__attribute__((nonnull(1, 2))) -void codec_store_check_empty(struct codec_store *, struct codec_store *); +__attribute__((nonnull(1, 2, 3))) +void codec_store_check_empty(struct codec_store *, struct codec_store *, sdp_ng_flags *); __attribute__((nonnull(1, 2))) void codec_store_accept(struct codec_store *, str_q *, struct codec_store *); __attribute__((nonnull(1, 2))) diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 0f53d7a5cb..dce3568249 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -24672,5 +24672,76 @@ sub stun_succ { like($resp->{sdp}, qr/\r\na=foobar\r\na=sendrecv\r\na=rtcp:\d+\r\n$/s, 'SDP matches'); +new_call; + +offer('allow-no-codec-media control', { + codec => { strip => ['all'], except => ['PCMA'] }, + }, < { strip => ['all'], except => ['PCMA'] }, + flags => ['allow no codec media'], + }, <