From 8e0cd6e446e3abebd7be42b5eb3a9065ae4e1c3a Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 3 Mar 2025 10:41:48 -0400 Subject: [PATCH] MT#61625 make recursive update_init_subs Instead of explicitly triggering an update of subscribers for A and B during an offer/answer, trigger it only for one side (A) and then iterate through all subscribers and subsriptions and update them all. This automatically triggers an update for B, as well as any other existing subscriptions that might be affected. Use a temporary hash table to track which medias have been updated so we don't run into infinite recursion. Change-Id: Ie2fba8ff9c5a011bbe932559ac06e1634029a091 --- daemon/call.c | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 34d3c5ba4..57d72f146 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2618,9 +2618,9 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi /* called with call->master_lock held in W */ -__attribute__((nonnull(1))) +__attribute__((nonnull(1, 5))) static void __update_init_subscribers(struct call_media *media, struct stream_params *sp, - sdp_ng_flags *flags, enum ng_opmode opmode) + sdp_ng_flags *flags, enum ng_opmode opmode, GHashTable *recurs_ht) { recording_setup_media(media); @@ -2636,12 +2636,24 @@ static void __update_init_subscribers(struct call_media *media, struct stream_pa /* update all subscribers */ __reset_streams(media); + g_hash_table_insert(recurs_ht, media, media); + for (__auto_type l = media->media_subscribers.head; l; l = l->next) { struct media_subscription * ms = l->data; struct call_media * sub_media = ms->media; if (!__streams_set_sinks(media, sub_media, flags, &ms->attrs)) ilog(LOG_WARN, "Error initialising streams"); + // XXX can this be done without a hash table? + if (g_hash_table_insert(recurs_ht, sub_media, sub_media)) + __update_init_subscribers(sub_media, NULL, NULL, opmode, recurs_ht); + } + for (__auto_type l = media->media_subscriptions.head; l; l = l->next) + { + struct media_subscription * ms = l->data; + struct call_media *sub_media = ms->media; + if (g_hash_table_insert(recurs_ht, sub_media, sub_media)) + __update_init_subscribers(sub_media, NULL, NULL, opmode, recurs_ht); } /* we are now ready to fire up ICE if so desired and requested */ @@ -2662,21 +2674,33 @@ static void __update_init_subscribers(struct call_media *media, struct stream_pa mqtt_timer_start(&media->mqtt_timer, media->call, media); } +__attribute__((nonnull(1))) +static void update_init_subscribers(struct call_media *media, struct stream_params *sp, + sdp_ng_flags *flags, enum ng_opmode opmode) +{ + g_autoptr(GHashTable) recurs_ht = g_hash_table_new(g_direct_hash, g_direct_equal); + __update_init_subscribers(media, sp, flags, opmode, recurs_ht); +} + /* called with call->master_lock held in W */ void update_init_monologue_subscribers(struct call_monologue *ml, enum ng_opmode opmode) { + g_autoptr(GHashTable) recurs_ht = g_hash_table_new(g_direct_hash, g_direct_equal); + for (unsigned int i = 0; i < ml->medias->len; i++) { struct call_media *media = ml->medias->pdata[i]; if (!media) continue; - __update_init_subscribers(media, NULL, NULL, opmode); + __update_init_subscribers(media, NULL, NULL, opmode, recurs_ht); } } /* called with call->master_lock held in W */ static void __update_init_medias(const medias_q *medias, enum ng_opmode opmode) { + g_autoptr(GHashTable) recurs_ht = g_hash_table_new(g_direct_hash, g_direct_equal); + for (auto_iter(l, medias->head); l; l = l->next) - __update_init_subscribers(l->data, NULL, NULL, opmode); + __update_init_subscribers(l->data, NULL, NULL, opmode, recurs_ht); } /* called with call->master_lock held in W */ @@ -3239,8 +3263,7 @@ int monologue_offer_answer(struct call_monologue *monologues[2], sdp_streams_q * goto error_ports; } - __update_init_subscribers(sender_media, sp, flags, flags->opmode); - __update_init_subscribers(receiver_media, NULL, NULL, flags->opmode); + update_init_subscribers(sender_media, sp, flags, flags->opmode); __update_init_medias(&old_medias, flags->opmode); media_update_transcoding_flag(receiver_media); @@ -3648,8 +3671,7 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca if (!__init_streams(dst_media, NULL, flags)) return -1; - __update_init_subscribers(src_media, NULL, NULL, flags->opmode); - __update_init_subscribers(dst_media, NULL, NULL, flags->opmode); + update_init_subscribers(src_media, NULL, NULL, flags->opmode); } return 0; @@ -3741,7 +3763,7 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, sdp_ng_flags *flag /* TODO: check answer SDP parameters */ MEDIA_SET(dst_media, INITIALIZED); - __update_init_subscribers(dst_media, sp, flags, flags->opmode); + update_init_subscribers(dst_media, sp, flags, flags->opmode); __media_unconfirm(dst_media, "subscribe answer event"); } @@ -3759,7 +3781,7 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, sdp_ng_flags *flag struct media_subscription * ms = sub->data; if (!g_queue_find(&mls, ms->monologue)) { media_update_transcoding_flag(ms->media); - __update_init_subscribers(ms->media, NULL, NULL, flags->opmode); + update_init_subscribers(ms->media, NULL, NULL, flags->opmode); __media_unconfirm(ms->media, "subscribe answer event"); g_queue_push_tail(&mls, ms->monologue); } @@ -3789,12 +3811,12 @@ int monologue_unsubscribe(struct call_monologue *dst_ml, sdp_ng_flags *flags) { __media_unconfirm(src_media, "media unsubscribe"); __unsubscribe_media_link(media, l); - __update_init_subscribers(src_media, NULL, NULL, flags->opmode); + update_init_subscribers(src_media, NULL, NULL, flags->opmode); l = next; } - __update_init_subscribers(media, NULL, NULL, flags->opmode); + update_init_subscribers(media, NULL, NULL, flags->opmode); } return 0; @@ -3854,8 +3876,7 @@ void dialogue_connect(struct call_monologue *src_ml, struct call_monologue *dst_ codec_handlers_update(dst_media, src_media, .allow_asymmetric = !!flags->allow_asymmetric_codecs); - __update_init_subscribers(src_media, NULL, NULL, flags->opmode); - __update_init_subscribers(dst_media, NULL, NULL, flags->opmode); + update_init_subscribers(src_media, NULL, NULL, flags->opmode); __update_init_medias(&medias, flags->opmode); } }