From 2540c5d501b8fb98a3b972cbc69b2af34a84bffb Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Fri, 5 Jan 2018 11:25:19 -0500 Subject: [PATCH] TT#30403 support codec-offer only codecs from the original list for now Change-Id: I884775a5b337ed3533972f4361ecb50e329b126e --- README.md | 13 ++++++++++ daemon/call.c | 52 ++++++++++++++++++++++++++++----------- utils/rtpengine-ng-client | 4 +++ 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index edff85a05..443996d34 100644 --- a/README.md +++ b/README.md @@ -1193,6 +1193,19 @@ Optionally included keys are: an `a=rtpmap` attribute, or can be from the list of RFC-defined codecs. Examples are `PCMU`, `opus`, or `telephone-event`. + As a special keyword, `all` can be used to remove all codecs, except the ones + that should explicitly offered (see below). Note that it is an error to strip + all codecs and leave none that could be offered. In this case, the original + list of codecs will be left unchanged. + + * `offer` + + Contains a list of strings. Each string is the name of a codec that should be + included in the list of codecs offered. This is primarily useful to block all + codecs (`strip -> all`) except the ones given in the `offer` whitelist. + Currently codecs that were not present in the original list of codecs + offered by the client will be ignored. + An example of a complete `offer` request dictionary could be (SDP body abbreviated): diff --git a/daemon/call.c b/daemon/call.c index a548fbc06..ed1580da5 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1419,32 +1419,56 @@ static void __dtls_logic(const struct sdp_ng_flags *flags, MEDIA_SET(other_media, DTLS); } -static void __rtp_payload_types(struct call_media *media, GQueue *types, GHashTable *strip) { - struct rtp_payload_type *pt; +static void __rtp_payload_type_add(struct call_media *media, struct rtp_payload_type *pt) { struct call *call = media->call; - static const str __all = STR_CONST_INIT("all"); + /* we must duplicate the contents */ + call_str_cpy(call, &pt->encoding_with_params, &pt->encoding_with_params); + call_str_cpy(call, &pt->encoding, &pt->encoding); + call_str_cpy(call, &pt->encoding_parameters, &pt->encoding_parameters); + call_str_cpy(call, &pt->format_parameters, &pt->format_parameters); + g_hash_table_replace(media->rtp_payload_types, &pt->payload_type, pt); + g_queue_push_tail(&media->rtp_payload_types_prefs, pt); +} + +static void __rtp_payload_types(struct call_media *media, GQueue *types, GHashTable *strip, + const GQueue *offer) +{ + struct rtp_payload_type *pt; + static const str str_all = STR_CONST_INIT("all"); + GHashTable *removed = g_hash_table_new_full(str_hash, str_equal, NULL, __payload_type_free); + int remove_all = 0; // start fresh g_queue_clear(&media->rtp_payload_types_prefs); + if (strip && g_hash_table_lookup(strip, &str_all)) + remove_all = 1; + /* we steal the entire list to avoid duplicate allocs */ while ((pt = g_queue_pop_head(types))) { // codec stripping if (strip) { - if (g_hash_table_lookup(strip, &pt->encoding) - || g_hash_table_lookup(strip, &__all)) { - __payload_type_free(pt); + if (remove_all || g_hash_table_lookup(strip, &pt->encoding)) { + g_hash_table_replace(removed, &pt->encoding, pt); continue; } } - /* we must duplicate the contents */ - call_str_cpy(call, &pt->encoding_with_params, &pt->encoding_with_params); - call_str_cpy(call, &pt->encoding, &pt->encoding); - call_str_cpy(call, &pt->encoding_parameters, &pt->encoding_parameters); - call_str_cpy(call, &pt->format_parameters, &pt->format_parameters); - g_hash_table_replace(media->rtp_payload_types, &pt->payload_type, pt); - g_queue_push_tail(&media->rtp_payload_types_prefs, pt); + __rtp_payload_type_add(media, pt); } + + if (offer) { + // now restore codecs that have been removed, but should be offered + for (GList *l = offer->head; l; l = l->next) { + str *codec = l->data; + pt = g_hash_table_lookup(removed, codec); + if (!pt) + continue; + g_hash_table_steal(removed, codec); + __rtp_payload_type_add(media, pt); + } + } + + g_hash_table_destroy(removed); } static void __ice_start(struct call_media *media) { @@ -1567,7 +1591,7 @@ int monologue_offer_answer(struct call_monologue *other_ml, GQueue *streams, MEDIA_SET(other_media, SDES); } - __rtp_payload_types(media, &sp->rtp_payload_types, flags->codec_strip); + __rtp_payload_types(media, &sp->rtp_payload_types, flags->codec_strip, &flags->codec_offer); /* send and recv are from our POV */ bf_copy_same(&media->media_flags, &sp->sp_flags, diff --git a/utils/rtpengine-ng-client b/utils/rtpengine-ng-client index f778d5ce2..6082bf5ec 100755 --- a/utils/rtpengine-ng-client +++ b/utils/rtpengine-ng-client @@ -45,6 +45,7 @@ GetOptions( 'port-latching' => \$options{'port latching'}, 'media-address=s' => \$options{'media address'}, 'codec-strip=s@' => \$options{'codec-strip'}, + 'codec-offer=s@' => \$options{'codec-offer'}, 'flags=s@' => \$options{'flags'}, ) or die; @@ -75,6 +76,9 @@ if (defined($options{direction})) { if ($options{'codec-strip'} && @{$options{'codec-strip'}}) { $packet{codec}{strip} = $options{'codec-strip'}; } +if ($options{'codec-offer'} && @{$options{'codec-offer'}}) { + $packet{codec}{offer} = $options{'codec-offer'}; +} if ($options{'flags'} && @{$options{'flags'}}) { push(@{$packet{flags}}, @{$options{'flags'}}); }