From 4a19714cd1d225560703bcf78bf55afab3620b71 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Fri, 26 Aug 2022 17:01:41 -0400 Subject: [PATCH] TT#189201 support per-sink media blocking/silencing Change-Id: I2b71816d97c4f6f1e1b290e5321d8ea1c106772a --- README.md | 7 +++++ daemon/call.c | 6 +++++ daemon/call_interfaces.c | 55 +++++++++++++++++++++++++++++++--------- daemon/codec.c | 4 +-- daemon/media_socket.c | 5 +++- include/call.h | 1 + include/media_socket.h | 3 +++ 7 files changed, 66 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 7ad009ac9..389707de4 100644 --- a/README.md +++ b/README.md @@ -2009,6 +2009,13 @@ Analogous to `block DTMF` and `unblock DTMF` but blocks media packets instead of can still pass through when media blocking is enabled. Media packets can be blocked for an entire call, or directionally for individual participants. See `block DTMF` above for details. +In addition to blocking media for just one call participant, it's possible to +block media for just a single media flow. This is relevant to scenarios that +involve forked media that were established with one or more `subscribe +request`. To select just one media flow for media blocking, in addition to +selecting a source call participant as above, a destination call participant +must be specified using the `to-tag` key in the message. + `silence media` and `unsilence media` Messages ---------------------------------------------- diff --git a/daemon/call.c b/daemon/call.c index 8778610aa..80b1b80e9 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2590,6 +2590,12 @@ static void __update_init_subscribers(struct call_monologue *ml, GQueue *streams } } +/* called with call->master_lock held in W */ +void update_init_subscribers(struct call_monologue *ml, enum call_opmode opmode) { + __update_init_subscribers(ml, NULL, NULL, opmode); +} + + static void __call_monologue_init_from_flags(struct call_monologue *ml, struct sdp_ng_flags *flags) { struct call *call = ml->call; diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 25cbe1921..4c2d7e44b 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -2646,7 +2646,8 @@ const char *call_unblock_dtmf_ng(bencode_item_t *input, bencode_item_t *output) } static const char *call_block_silence_media(bencode_item_t *input, bool on_off, const char *ucase_verb, - size_t call_offset, size_t ml_offset) + const char *lcase_verb, + size_t call_offset, size_t ml_offset, size_t attr_offset) { AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); struct call_monologue *monologue; @@ -2658,10 +2659,38 @@ static const char *call_block_silence_media(bencode_item_t *input, bool on_off, return errstr; if (monologue) { - ilog(LOG_INFO, "%s directional media (tag '" STR_FORMAT_M "')", - ucase_verb, - STR_FMT_M(&monologue->tag)); - G_STRUCT_MEMBER(bool, monologue, ml_offset) = on_off; + if (flags.to_tag.len) { + struct call_monologue *sink = g_hash_table_lookup(call->tags, &flags.to_tag); + if (!sink) { + ilog(LOG_WARN, "Media flow '" STR_FORMAT_M "' -> '" STR_FORMAT_M "' doesn't " + "exist for media %s (to-tag not found)", + STR_FMT_M(&monologue->tag), STR_FMT_M(&flags.to_tag), + lcase_verb); + return "Media flow not found (to-tag not found)"; + } + GList *link = g_hash_table_lookup(monologue->subscribers_ht, sink); + if (!link) { + ilog(LOG_WARN, "Media flow '" STR_FORMAT_M "' -> '" STR_FORMAT_M "' doesn't " + "exist for media %s (to-tag not subscribed)", + STR_FMT_M(&monologue->tag), STR_FMT_M(&flags.to_tag), + lcase_verb); + return "Media flow not found (to-tag not subscribed)"; + } + struct call_subscription *cs = link->data; + + ilog(LOG_INFO, "%s directional media flow " + "(tag '" STR_FORMAT_M "' -> '" STR_FORMAT_M "')", + ucase_verb, + STR_FMT_M(&monologue->tag), STR_FMT_M(&sink->tag)); + G_STRUCT_MEMBER(bool, &cs->attrs, attr_offset) = on_off; + update_init_subscribers(monologue, OP_OTHER); + } + else { + ilog(LOG_INFO, "%s directional media (tag '" STR_FORMAT_M "')", + ucase_verb, + STR_FMT_M(&monologue->tag)); + G_STRUCT_MEMBER(bool, monologue, ml_offset) = on_off; + } __monologue_unkernelize(monologue); } else { @@ -2683,21 +2712,23 @@ static const char *call_block_silence_media(bencode_item_t *input, bool on_off, return NULL; } -#define CALL_BLOCK_SILENCE_MEDIA(input, on_off, ucase_verb, member_name) \ - call_block_silence_media(input, on_off, ucase_verb, G_STRUCT_OFFSET(struct call, member_name), \ - G_STRUCT_OFFSET(struct call_monologue, member_name)) +#define CALL_BLOCK_SILENCE_MEDIA(input, on_off, ucase_verb, lcase_verb, member_name) \ + call_block_silence_media(input, on_off, ucase_verb, lcase_verb, \ + G_STRUCT_OFFSET(struct call, member_name), \ + G_STRUCT_OFFSET(struct call_monologue, member_name), \ + G_STRUCT_OFFSET(struct sink_attrs, member_name)) const char *call_block_media_ng(bencode_item_t *input, bencode_item_t *output) { - return CALL_BLOCK_SILENCE_MEDIA(input, true, "Blocking", block_media); + return CALL_BLOCK_SILENCE_MEDIA(input, true, "Blocking", "blocking", block_media); } const char *call_unblock_media_ng(bencode_item_t *input, bencode_item_t *output) { - return CALL_BLOCK_SILENCE_MEDIA(input, false, "Unblocking", block_media); + return CALL_BLOCK_SILENCE_MEDIA(input, false, "Unblocking", "unblocking", block_media); } const char *call_silence_media_ng(bencode_item_t *input, bencode_item_t *output) { - return CALL_BLOCK_SILENCE_MEDIA(input, true, "Silencing", silence_media); + return CALL_BLOCK_SILENCE_MEDIA(input, true, "Silencing", "silencing", silence_media); } const char *call_unsilence_media_ng(bencode_item_t *input, bencode_item_t *output) { - return CALL_BLOCK_SILENCE_MEDIA(input, false, "Unsilencing", silence_media); + return CALL_BLOCK_SILENCE_MEDIA(input, false, "Unsilencing", "unsilencing", silence_media); } diff --git a/daemon/codec.c b/daemon/codec.c index 223a7b71f..5548d95b8 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -1483,9 +1483,9 @@ void codec_add_raw_packet(struct media_packet *mp, unsigned int clockrate) { g_queue_push_tail(&mp->packets_out, p); } static bool handler_silence_block(struct codec_handler *h, struct media_packet *mp) { - if (mp->call->block_media || mp->media->monologue->block_media) + if (mp->call->block_media || mp->media->monologue->block_media || mp->sink.attrs.block_media) return false; - if (mp->call->silence_media || mp->media->monologue->silence_media) { + if (mp->call->silence_media || mp->media->monologue->silence_media || mp->sink.attrs.silence_media) { if (h->source_pt.codec_def && h->source_pt.codec_def->silence_pattern.len) { if (h->source_pt.codec_def->silence_pattern.len == 1) memset(mp->payload.s, h->source_pt.codec_def->silence_pattern.s[0], diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 608db7987..d753840f2 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1305,7 +1305,8 @@ output: redi->output.tos = call->tos; // media silencing - bool silenced = call->silence_media || media->monologue->silence_media; + bool silenced = call->silence_media || media->monologue->silence_media + || sink_handler->attrs.silence_media; if (silenced) { int i = 0; for (GList *l = *payload_types; l; l = l->next) { @@ -1408,6 +1409,8 @@ void kernelize(struct packet_stream *stream) { else { for (GList *l = sinks->head; l; l = l->next) { struct sink_handler *sh = l->data; + if (sh->attrs.block_media) + continue; struct packet_stream *sink = sh->sink; if (PS_ISSET(sink, NAT_WAIT) && !PS_ISSET(sink, RECEIVED)) continue; diff --git a/include/call.h b/include/call.h index 92dcbfab4..1edffb4a3 100644 --- a/include/call.h +++ b/include/call.h @@ -684,6 +684,7 @@ void call_media_state_machine(struct call_media *m); void call_media_unkernelize(struct call_media *media); void dialogue_unkernelize(struct call_monologue *ml); void __monologue_unkernelize(struct call_monologue *monologue); +void update_init_subscribers(struct call_monologue *ml, enum call_opmode opmode); int call_stream_address46(char *o, struct packet_stream *ps, enum stream_address_format format, int *len, const struct local_intf *ifa, bool keep_unspec); diff --git a/include/media_socket.h b/include/media_socket.h index 0f637dc37..ac33d7a2c 100644 --- a/include/media_socket.h +++ b/include/media_socket.h @@ -128,6 +128,9 @@ struct stream_fd { struct poller *poller; }; struct sink_attrs { + bool block_media; + bool silence_media; + unsigned int offer_answer:1; // bidirectional, exclusive unsigned int rtcp_only:1; unsigned int transcoding:1;