From ac4f2ef64151c94ea82773b07f78e6ed1199728d Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 17 Jan 2024 11:00:33 -0500 Subject: [PATCH] MT#55283 reverse handling of session attributes Store SDP session attributes in the monologue that were received instead of the ones to be sent out. Look up the corresponding source monologue when creating an outgoing SDP and insert that one's attributes. Change-Id: Ic2e57db71b0e0b48b9868940d326b5a951d89e92 --- daemon/call.c | 30 ++++++++++-------------------- daemon/call_interfaces.c | 5 +++-- daemon/janus.c | 4 ++-- daemon/sdp.c | 22 ++++++++++------------ include/call.h | 6 +++--- include/call_interfaces.h | 1 + include/sdp.h | 2 -- 7 files changed, 29 insertions(+), 41 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 83eb86ed0..aac3e96ed 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -2571,6 +2571,11 @@ static void __call_monologue_init_from_flags(struct call_monologue *ml, sdp_ng_f call->last_signal = rtpe_now.tv_sec; call->deleted = 0; + // consume session attributes + t_queue_clear_full(&ml->sdp_attributes, sdp_attr_free); + ml->sdp_attributes = flags->session_attributes; + t_queue_init(&flags->session_attributes); + // reset offer ipv4/ipv6/mixed media stats if (flags->opmode == OP_OFFER) { statistics_update_ip46_inc_dec(call, CMC_DECREMENT); @@ -3042,7 +3047,7 @@ static void __unsubscribe_medias_from_all(struct call_monologue *ml) { /** * Check whether this monologue medias are subscribed to a single other monologue medias. */ -static struct call_monologue * ml_medias_subscribed_to_single_ml(struct call_monologue *ml) { +struct call_monologue * ml_medias_subscribed_to_single_ml(struct call_monologue *ml) { /* detect monologues multiplicity */ struct call_monologue * return_ml = NULL; for (unsigned int i = 0; i < ml->medias->len; i++) @@ -3222,14 +3227,10 @@ int monologue_publish(struct call_monologue *ml, sdp_streams_q *streams, sdp_ng_ /* called with call->master_lock held in W */ __attribute__((nonnull(1, 2, 3, 4))) static int monologue_subscribe_request1(struct call_monologue *src_ml, struct call_monologue *dst_ml, - sdp_ng_flags *flags, unsigned int *index, bool print_extra_sess_attrs) + sdp_ng_flags *flags, unsigned int *index) { unsigned int idx_diff = 0, rev_idx_diff = 0; - /* additional attributes to be carried for `sdp_create()` */ - if (print_extra_sess_attrs) - sdp_copy_session_attributes(src_ml, dst_ml); - for (__auto_type l = src_ml->last_in_sdp_streams.head; l; l = l->next) { struct stream_params *sp = l->data; @@ -3299,9 +3300,7 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca } /* called with call->master_lock held in W */ __attribute__((nonnull(1, 2, 3))) -int monologue_subscribe_request(const subscription_q *srms, struct call_monologue *dst_ml, - sdp_ng_flags *flags, bool print_extra_sess_attrs) -{ +int monologue_subscribe_request(const subscription_q *srms, struct call_monologue *dst_ml, sdp_ng_flags *flags) { unsigned int index = 1; /* running counter for output/dst medias */ __unsubscribe_medias_from_all(dst_ml); @@ -3316,7 +3315,7 @@ int monologue_subscribe_request(const subscription_q *srms, struct call_monologu continue; if (!g_queue_find(&mls, src_ml)) { - int ret = monologue_subscribe_request1(src_ml, dst_ml, flags, &index, print_extra_sess_attrs); + int ret = monologue_subscribe_request1(src_ml, dst_ml, flags, &index); g_queue_push_tail(&mls, src_ml); if (ret) return -1; @@ -3327,11 +3326,8 @@ int monologue_subscribe_request(const subscription_q *srms, struct call_monologu /* called with call->master_lock held in W */ __attribute__((nonnull(1, 2, 3))) -int monologue_subscribe_answer(struct call_monologue *dst_ml, sdp_ng_flags *flags, sdp_streams_q *streams, - bool print_extra_sess_attrs) -{ +int monologue_subscribe_answer(struct call_monologue *dst_ml, sdp_ng_flags *flags, sdp_streams_q *streams) { struct media_subscription *rev_ms = NULL; - g_auto(GQueue) attr_mls = G_QUEUE_INIT; /* to avoid duplications */ for (__auto_type l = streams->head; l; l = l->next) { @@ -3351,12 +3347,6 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, sdp_ng_flags *flag if (!src_media) continue; - /* additional attributes to be carried for `sdp_create()` */ - if (print_extra_sess_attrs && !g_queue_find(&attr_mls, ms->monologue)) { - sdp_copy_session_attributes(ms->monologue, dst_ml); - g_queue_push_tail(&attr_mls, ms->monologue); - } - rev_ms = call_get_media_subscription(src_media->media_subscribers_ht, dst_media); if (rev_ms) rev_ms->attrs.transcoding = 0; diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 2c3fc1c83..6ed2ee907 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1932,6 +1932,7 @@ void call_ng_free_flags(sdp_ng_flags *flags) { t_queue_clear_full(&flags->codec_mask, str_free); t_queue_clear_full(&flags->sdes_order, str_free); t_queue_clear_full(&flags->sdes_offerer_pref, str_free); + t_queue_clear_full(&flags->session_attributes, sdp_attr_free); ng_sdp_attr_manipulations_free(flags->sdp_manipulations); } @@ -3568,7 +3569,7 @@ const char *call_subscribe_request_ng(bencode_item_t *input, bencode_item_t *out bencode_buffer_destroy_add(output->buffer, (free_func_t) sdp_chopper_destroy, chopper); } - int ret = monologue_subscribe_request(&srms, dest_ml, &flags, false); + int ret = monologue_subscribe_request(&srms, dest_ml, &flags); if (ret) return "Failed to request subscription"; @@ -3682,7 +3683,7 @@ const char *call_subscribe_answer_ng(ng_buffer *ngbuf, bencode_item_t *input, be if (sdp_streams(&parsed, &streams, &flags)) return "Incomplete SDP specification"; - int ret = monologue_subscribe_answer(dest_ml, &flags, &streams, false); + int ret = monologue_subscribe_answer(dest_ml, &flags, &streams); if (ret) return "Failed to process subscription answer"; diff --git a/daemon/janus.c b/daemon/janus.c index 505e1b3a1..21f390d38 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -645,7 +645,7 @@ static const char *janus_videoroom_join(struct websocket_message *wm, struct jan flags.rtcp_mux_demux = 1; } - int ret = monologue_subscribe_request(&srms, dest_ml, &flags, true); + int ret = monologue_subscribe_request(&srms, dest_ml, &flags); if (ret) return "Subscribe error"; @@ -998,7 +998,7 @@ static const char *janus_videoroom_start(struct websocket_message *wm, struct ja if (!dest_ml) return "Subscriber not found"; - int ret = monologue_subscribe_answer(dest_ml, &flags, &streams, true); + int ret = monologue_subscribe_answer(dest_ml, &flags, &streams); if (ret) return "Failed to process subscription answer"; diff --git a/daemon/sdp.c b/daemon/sdp.c index db4a9a83f..06ce5e48c 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -1802,6 +1802,8 @@ int sdp_streams(const sdp_sessions_q *sessions, sdp_streams_q *streams, sdp_ng_f for (auto_iter(l, sessions->head); l; l = l->next) { session = l->data; + sdp_attr_append_other(&flags->session_attributes, &session->attributes); + for (__auto_type k = session->media_streams.head; k; k = k->next) { media = k->data; @@ -2166,7 +2168,14 @@ void sdp_insert_media_attributes(GString *gs, union sdp_attr_print_arg a, const } } void sdp_insert_monologue_attributes(GString *gs, union sdp_attr_print_arg a, const sdp_ng_flags *flags) { - for (__auto_type l = a.ml->sdp_attributes.head; l; l = l->next) { + // Look up the source monologue. This must be a single source monologue for all medias. If + // there's a mismatch or multiple source monologues, we skip this step. + + struct call_monologue *source_ml = ml_medias_subscribed_to_single_ml(a.ml); + if (!source_ml) + return; + + for (__auto_type l = source_ml->sdp_attributes.head; l; l = l->next) { __auto_type s = l->data; if (s->type == SDP_ATTR_TYPE_EXTMAP && flags->strip_extmap) continue; @@ -3022,17 +3031,6 @@ struct packet_stream *print_rtcp(GString *s, struct call_media *media, packet_st return ps_rtcp; } -/* copy sdp session attributes to the correlated monologue, as a plain text objects (str) */ -void sdp_copy_session_attributes(struct call_monologue * src, struct call_monologue * dst) { - struct sdp_session *src_session = src->last_in_sdp_parsed.head->data; - attributes_q *src_attributes = attr_list_get_by_id(&src_session->attributes, ATTR_OTHER); - t_queue_clear_full(&dst->sdp_attributes, sdp_attr_free); - for (__auto_type ll = src_attributes ? src_attributes->head : NULL; ll; ll = ll->next) { - struct sdp_attribute *attr = ll->data; - struct sdp_attr *ac = sdp_attr_dup(attr); - t_queue_push_tail(&dst->sdp_attributes, ac); - } -} static void print_sdp_session_section(GString *s, sdp_ng_flags *flags, struct call_media *call_media) { diff --git a/include/call.h b/include/call.h index 12c0a57b9..725c54ce6 100644 --- a/include/call.h +++ b/include/call.h @@ -748,6 +748,7 @@ struct packet_stream *__packet_stream_new(call_t *call); void __add_media_subscription(struct call_media * which, struct call_media * to, const struct sink_attrs *attrs); struct media_subscription *call_get_media_subscription(subscription_ht ht, struct call_media * cm); +struct call_monologue * ml_medias_subscribed_to_single_ml(struct call_monologue *ml); void free_sink_handler(struct sink_handler *); void __add_sink_handler(sink_handler_q *, struct packet_stream *, const struct sink_attrs *); @@ -772,10 +773,9 @@ __attribute__((nonnull(1, 2, 3, 4))) void codecs_offer_answer(struct call_media *media, struct call_media *other_media, struct stream_params *sp, sdp_ng_flags *flags); int monologue_publish(struct call_monologue *ml, sdp_streams_q *streams, sdp_ng_flags *flags); -int monologue_subscribe_request(const subscription_q *srms, struct call_monologue *dst, sdp_ng_flags *flags, - bool print_extra_sess_attrs); +int monologue_subscribe_request(const subscription_q *srms, struct call_monologue *dst, sdp_ng_flags *flags); int monologue_subscribe_answer(struct call_monologue *dst, sdp_ng_flags *flags, - sdp_streams_q *streams, bool print_extra_sess_attrs); + sdp_streams_q *streams); int monologue_unsubscribe(struct call_monologue *dst, sdp_ng_flags *); void monologue_destroy(struct call_monologue *ml); int call_delete_branch_by_id(const str *callid, const str *branch, diff --git a/include/call_interfaces.h b/include/call_interfaces.h index 0b509b284..9f5f604dc 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -59,6 +59,7 @@ struct sdp_ng_flags { str_q sdes_order; /* the order, in which crypto suites are being added to the SDP */ str_q sdes_offerer_pref; /* preferred crypto suites to be selected for the offerer */ str dtls_fingerprint; + sdp_attr_q session_attributes; // top-level (not part of an m= section) SDP session attributes /* commands to manipulate attr lines in SDP */ struct sdp_manipulations * sdp_manipulations[__MT_MAX]; diff --git a/include/sdp.h b/include/sdp.h index 48689393e..8a19d75cf 100644 --- a/include/sdp.h +++ b/include/sdp.h @@ -74,8 +74,6 @@ struct sdp_chopper *sdp_chopper_new(str *input); void sdp_chopper_destroy(struct sdp_chopper *chop); void sdp_chopper_destroy_ret(struct sdp_chopper *chop, str *ret); -void sdp_copy_session_attributes(struct call_monologue * src, struct call_monologue * dst); - G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(sdp_streams_q, sdp_streams_clear) G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(sdp_sessions_q, sdp_sessions_clear)