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)