From 9b36d4962ec79eb1caa838cc8efb4881e861a63d Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 5 Mar 2025 10:03:31 -0400 Subject: [PATCH] MT#55283 streamline subscription handling Grab source monologue and source media only once, and pass the object down to the various functions, instead of doing the retrieval several times in multiple places. Change-Id: I88d019dbf9493fa0037161390fdb9efda58f5441 (cherry picked from commit cabd5e4676481e550015b9d30caf97e8324cb90f) (cherry picked from commit a38d7ed411c8bf213b89746c644c2cc1289a3434) --- daemon/sdp.c | 121 +++++++++++++++++++++++------------------------- daemon/t38.c | 4 +- include/sdp.h | 2 +- include/types.h | 2 +- 4 files changed, 63 insertions(+), 66 deletions(-) diff --git a/daemon/sdp.c b/daemon/sdp.c index e44896058..ae83053eb 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -307,6 +307,7 @@ static struct sdp_attr *sdp_attr_dup(const struct sdp_attribute *c); static void attr_free(struct sdp_attribute *p); static void attr_insert(struct sdp_attributes *attrs, struct sdp_attribute *attr); static struct call_media *sdp_out_set_source_media_address(struct call_media *media, + struct call_media *source_media, struct packet_stream *rtp_ps, struct sdp_ng_flags *flags, endpoint_t *sdp_address); @@ -2068,21 +2069,19 @@ static void insert_codec_parameters(GString *s, struct call_media *cm, } } -void sdp_insert_media_attributes(GString *gs, struct call_media *media, const sdp_ng_flags *flags) { +void sdp_insert_media_attributes(GString *gs, struct call_media *media, struct call_media *source_media, + const sdp_ng_flags *flags) +{ // Look up the source media. We copy the source's attributes if there is only one source // media. Otherwise we skip this step. - if (media->media_subscriptions.length != 1) + if (!source_media) return; - - __auto_type sub = media->media_subscriptions.head->data; - __auto_type sub_m = sub->media; - - for (__auto_type l = sub_m->generic_attributes.head; l; l = l->next) { + for (__auto_type l = source_media->generic_attributes.head; l; l = l->next) { __auto_type s = l->data; - if (s->other == ATTR_OTHER_EXTMAP && flags->strip_extmap && !MEDIA_ISSET(media, PASSTHRU)) + if (s->other == ATTR_OTHER_EXTMAP && flags->strip_extmap && !MEDIA_ISSET(source_media, PASSTHRU)) continue; - append_str_attr_to_gstring(gs, &s->strs.name, &s->strs.value, flags, media->type_id); + append_str_attr_to_gstring(gs, &s->strs.name, &s->strs.value, flags, source_media->type_id); } } void sdp_insert_monologue_attributes(GString *gs, struct call_monologue *ml, const sdp_ng_flags *flags) { @@ -2456,6 +2455,7 @@ static void sdp_version_replace(GString *s, sdp_origin *src_orig, sdp_origin *ot * SDP session version manipulations. */ static void sdp_version_check(GString *s, struct call_monologue *monologue, + struct call_monologue *source_ml, bool force_increase) { if (!monologue->session_last_sdp_orig) @@ -2464,9 +2464,8 @@ static void sdp_version_check(GString *s, struct call_monologue *monologue, sdp_origin *origin = monologue->session_last_sdp_orig; sdp_origin *other_origin = NULL; - struct media_subscription *ms = call_ml_get_top_ms(monologue); - if (ms && ms->monologue && ms->monologue->session_sdp_orig) - other_origin = ms->monologue->session_sdp_orig; + if (source_ml && source_ml->session_sdp_orig) + other_origin = source_ml->session_sdp_orig; /* We really expect only a single session here, but we treat all the same regardless, * and use the same version number on all of them */ @@ -2637,16 +2636,17 @@ static struct packet_stream *print_rtcp(GString *s, struct call_media *media, pa /* TODO: rework an appending of parameters in terms of sdp attribute manipulations */ static void print_sdp_media_section(GString *s, struct call_media *media, - const endpoint_t *address, struct call_media *source_media, + const endpoint_t *address, struct call_media *copy_media, + struct call_media *source_media, struct packet_stream *rtp_ps, packet_stream_list *rtp_ps_link, sdp_ng_flags *flags) { struct packet_stream *ps_rtcp = NULL; bool inactive_media = (!address->port || !rtp_ps->selected_sfd); /* audio is accepted? */ - if (source_media) { + if (copy_media) { /* just print out all original values and attributes */ - sdp_out_original_media_attributes(s, media, address, source_media, rtp_ps, flags); + sdp_out_original_media_attributes(s, media, address, copy_media, rtp_ps, flags); return; } @@ -2655,7 +2655,7 @@ static void print_sdp_media_section(GString *s, struct call_media *media, sdp_out_add_media_connection(s, media, rtp_ps, (inactive_media ? NULL : &address->address), flags); /* add per media bandwidth */ - sdp_out_add_media_bandwidth(s, media, flags); + sdp_out_add_media_bandwidth(s, source_media, flags); /* mid and label must be added even for inactive streams (see #1361 and #1362). */ if (media->media_id.s) @@ -2671,7 +2671,7 @@ static void print_sdp_media_section(GString *s, struct call_media *media, insert_codec_parameters(s, media, flags); /* all unknown type attributes will be added here */ - media->sdp_attr_print(s, media, flags); + media->sdp_attr_print(s, media, source_media, flags); /* print sendrecv */ if (!flags->original_sendrecv) @@ -2704,7 +2704,7 @@ static void print_sdp_media_section(GString *s, struct call_media *media, media->type_id); } if (MEDIA_ISSET(media, ICE)) { - insert_candidates(s, rtp_ps, ps_rtcp, flags, source_media); + insert_candidates(s, rtp_ps, ps_rtcp, flags, NULL); } if ((MEDIA_ISSET(media, TRICKLE_ICE) && media->ice_agent)) { @@ -2715,16 +2715,12 @@ static void print_sdp_media_section(GString *s, struct call_media *media, } static void sdp_out_add_origin(GString *out, struct call_monologue *monologue, + struct call_monologue *source_ml, struct packet_stream *first_ps, sdp_ng_flags *flags) { - struct call_monologue *ml = monologue; - - /* for the offer/answer model or subscribe don't use the given monologues SDP, - * but try the one of the subscription, because the given monologue itself - * has likely no session attributes set yet */ - struct media_subscription *ms = call_ml_get_top_ms(monologue); - if (ms && ms->monologue) - ml = ms->monologue; + __auto_type ml = source_ml; + if (!ml) + ml = monologue; /* orig username * session_last_sdp_orig is stored on the other media always, @@ -2747,7 +2743,7 @@ static void sdp_out_add_origin(GString *out, struct call_monologue *monologue, /* orig IP family and address */ str orig_address_type; str orig_address; - if (!ms || flags->replace_origin || flags->replace_origin_full) { + if (!source_ml || flags->replace_origin || flags->replace_origin_full) { /* replacing flags or PUBLISH */ orig_address_type = STR(first_ps->selected_sfd->local_intf->advertised_address.addr.family->rfc_name); orig_address = STR(sockaddr_print_buf(&first_ps->selected_sfd->local_intf->advertised_address.addr)); @@ -2766,7 +2762,8 @@ static void sdp_out_add_origin(GString *out, struct call_monologue *monologue, STR_FMT(&orig_address)); } -static void sdp_out_add_session_name(GString *out, struct call_monologue *monologue) +static void sdp_out_add_session_name(GString *out, struct call_monologue *monologue, + struct call_monologue *source_ml) { g_string_append(out, "s="); @@ -2774,17 +2771,13 @@ static void sdp_out_add_session_name(GString *out, struct call_monologue *monolo * The session name and other values should be copied only from a source SDP, * if that is also a media source. For a publish request that's not the case. */ - /* for the offer/answer model or subscribe don't use the given monologues SDP, - * but try the one of the subscription, because the given monologue itself - * has likely no session attributes set yet */ - struct media_subscription *ms = call_ml_get_top_ms(monologue); - if (ms && ms->monologue) + if (source_ml) { /* if a session name was empty in the s= attr of the coming message, * while processing this ml in `__call_monologue_init_from_flags()`, * then just keep it empty. */ - if (ms->monologue->sdp_session_name.len) - g_string_append_len(out, ms->monologue->sdp_session_name.s, ms->monologue->sdp_session_name.len); + if (source_ml->sdp_session_name.len) + g_string_append_len(out, source_ml->sdp_session_name.s, source_ml->sdp_session_name.len); } else g_string_append(out, rtpe_config.software_id); @@ -2797,9 +2790,8 @@ static void sdp_out_add_timing(GString *out, struct call_monologue *monologue) /* sdp timing per session level */ g_string_append(out, "t="); - struct media_subscription *ms = call_ml_get_top_ms(monologue); - if (ms && ms->monologue && ms->monologue->sdp_session_timing.len) - g_string_append_len(out, ms->monologue->sdp_session_timing.s, ms->monologue->sdp_session_timing.len); + if (monologue && monologue->sdp_session_timing.len) + g_string_append_len(out, monologue->sdp_session_timing.s, monologue->sdp_session_timing.len); else g_string_append(out, "0 0"); /* default */ @@ -2807,14 +2799,13 @@ static void sdp_out_add_timing(GString *out, struct call_monologue *monologue) } static void sdp_out_add_other(GString *out, struct call_monologue *monologue, + struct call_monologue *source_ml, struct call_media *media, sdp_ng_flags *flags) { bool media_has_ice = MEDIA_ISSET(media, ICE); bool media_has_ice_lite_self = MEDIA_ISSET(media, ICE_LITE_SELF); - struct media_subscription *ms = call_ml_get_top_ms(monologue); - /* add loop protectio if required */ if (flags->loop_protect) append_attr_to_gstring(out, "rtpengine", &rtpe_instance_id, flags, media->type_id); @@ -2828,8 +2819,8 @@ static void sdp_out_add_other(GString *out, struct call_monologue *monologue, append_attr_to_gstring(out, "ice-lite", NULL, flags, media->type_id); /* group */ - if (ms && ms->monologue && ms->monologue->sdp_session_group.len && flags->ice_option == ICE_FORCE_RELAY) - append_attr_to_gstring(out, "group", &ms->monologue->sdp_session_group, flags, media->type_id); + if (source_ml && source_ml->sdp_session_group.len && flags->ice_option == ICE_FORCE_RELAY) + append_attr_to_gstring(out, "group", &source_ml->sdp_session_group, flags, media->type_id); /* carry other session level a= attributes to the outgoing SDP */ monologue->sdp_attr_print(out, monologue, flags); @@ -2857,21 +2848,18 @@ static void sdp_out_add_session_bandwidth(GString *out, struct call_monologue *m { /* sdp bandwidth per session/media level * 0 value is supported (e.g. b=RR:0 and b=RS:0), to be able to disable rtcp */ - struct media_subscription *ms = call_ml_get_top_ms(monologue); /* don't add session level bandwidth for subscribe requests */ - if (!ms || flags->opmode == OP_SUBSCRIBE_REQ) + if (!monologue || flags->opmode == OP_SUBSCRIBE_REQ) return; - sdp_out_print_bandwidth(out, &ms->monologue->sdp_session_bandwidth); + sdp_out_print_bandwidth(out, &monologue->sdp_session_bandwidth); } static void sdp_out_add_media_bandwidth(GString *out, struct call_media *media, sdp_ng_flags *flags) { - /* sdp bandwidth per media level */ - struct media_subscription *ms = call_media_get_top_ms(media); - if (!ms) + if (!media) return; - sdp_out_print_bandwidth(out, &ms->media->sdp_media_bandwidth); + sdp_out_print_bandwidth(out, &media->sdp_media_bandwidth); } static void sdp_out_add_media_connection(GString *out, struct call_media *media, @@ -2971,7 +2959,7 @@ static void sdp_out_handle_osrtp1(GString *out, struct call_media *media, sdp_out_add_osrtp_media(out, media, prtp, address); /* print media level attributes */ - print_sdp_media_section(out, media, address, NULL, rtp_ps, rtp_ps_link, flags); + print_sdp_media_section(out, media, address, NULL, NULL, rtp_ps, rtp_ps_link, flags); media->protocol = proto; } @@ -2996,7 +2984,7 @@ static void sdp_out_original_media_attributes(GString *out, struct call_media *m struct packet_stream *rtp_ps, sdp_ng_flags *flags) { sdp_out_add_media_connection(out, media, rtp_ps, &address->address, flags); - sdp_out_add_media_bandwidth(out, media, flags); + sdp_out_add_media_bandwidth(out, source_media, flags); sdp_insert_all_attributes(out, source_media, flags); if (MEDIA_ISSET(source_media, ICE)) { struct packet_stream *rtcp_ps = rtp_ps->rtcp_sibling; @@ -3014,20 +3002,18 @@ static void sdp_out_original_media_attributes(GString *out, struct call_media *m * then we need to look up the source media. */ static struct call_media *sdp_out_set_source_media_address(struct call_media *media, + struct call_media *source_media, struct packet_stream *rtp_ps, struct sdp_ng_flags *flags, endpoint_t *sdp_address) { - struct call_media *source_media = NULL; /* the port and address that goes into the SDP also depends on this */ if (rtp_ps->selected_sfd) { sdp_address->port = rtp_ps->selected_sfd->socket.local.port; sdp_address->address = rtp_ps->selected_sfd->local_intf->advertised_address.addr; } - struct media_subscription *ms = call_media_get_top_ms(media); - if (ms && ms->media) { - source_media = ms->media; + if (source_media) { /* cases with message, force relay and pass through */ if (media->type_id == MT_MESSAGE || flags->ice_option == ICE_FORCE_RELAY || MEDIA_ISSET(media, PASSTHRU)) { if (source_media->streams.head) { @@ -3093,26 +3079,30 @@ int sdp_create(str *out, struct call_monologue *monologue, sdp_ng_flags *flags) if (!first_ps || !first_ps->selected_sfd) goto err; + // consume SDP data from ... + __auto_type ml_ms = call_ml_get_top_ms(monologue); + __auto_type source_ml = ml_ms ? ml_ms->monologue : NULL; + /* init new sdp */ s = g_string_new("v=0\r\n"); /* add origin including name and version */ - sdp_out_add_origin(s, monologue, first_ps, flags); + sdp_out_add_origin(s, monologue, source_ml, first_ps, flags); /* add an actual sdp session name */ - sdp_out_add_session_name(s, monologue); + sdp_out_add_session_name(s, monologue, source_ml); /* don't set connection on the session level * but instead per media, below */ /* add bandwidth control per session level */ - sdp_out_add_session_bandwidth(s, monologue, flags); + sdp_out_add_session_bandwidth(s, source_ml, flags); /* set timing to always be: 0 0 */ - sdp_out_add_timing(s, monologue); + sdp_out_add_timing(s, source_ml); /* add other session level attributes */ - sdp_out_add_other(s, monologue, media, flags); + sdp_out_add_other(s, monologue, source_ml, media, flags); /* print media sections */ for (unsigned int i = 0; i < monologue->medias->len; i++) @@ -3132,8 +3122,12 @@ int sdp_create(str *out, struct call_monologue *monologue, sdp_ng_flags *flags) __auto_type rtp_ps_link = media->streams.head; struct packet_stream *rtp_ps = rtp_ps_link->data; + __auto_type media_ms = call_media_get_top_ms(media); + __auto_type source_media = media_ms ? media_ms->media : NULL; + endpoint_t sdp_address = {0}; - struct call_media *source_media = sdp_out_set_source_media_address(media, rtp_ps, flags, + struct call_media *copy_media = sdp_out_set_source_media_address(media, source_media, + rtp_ps, flags, &sdp_address); unsigned int port = sdp_address.port; @@ -3150,7 +3144,8 @@ int sdp_create(str *out, struct call_monologue *monologue, sdp_ng_flags *flags) goto err; /* print media level attributes */ - print_sdp_media_section(s, media, &sdp_address, source_media, rtp_ps, rtp_ps_link, flags); + print_sdp_media_section(s, media, &sdp_address, copy_media, source_media, + rtp_ps, rtp_ps_link, flags); /* handle second OSRTP part */ sdp_out_handle_osrtp2(s, media, prtp); @@ -3166,7 +3161,7 @@ int sdp_create(str *out, struct call_monologue *monologue, sdp_ng_flags *flags) * which forces version increase regardless changes in the SDP information. */ if (flags->force_inc_sdp_ver || flags->replace_sdp_version || flags->replace_origin_full) - sdp_version_check(s, monologue, !!flags->force_inc_sdp_ver); + sdp_version_check(s, monologue, source_ml, !!flags->force_inc_sdp_ver); out->len = s->len; out->s = g_string_free(s, FALSE); diff --git a/daemon/t38.c b/daemon/t38.c index a574efcfd..6fbf8b263 100644 --- a/daemon/t38.c +++ b/daemon/t38.c @@ -332,7 +332,9 @@ static int span_log_level_map(int level) { return level; } -static void t38_insert_media_attributes(GString *gs, struct call_media *media, const sdp_ng_flags *flags) { +static void t38_insert_media_attributes(GString *gs, struct call_media *media, struct call_media *source_media, + const sdp_ng_flags *flags) +{ struct t38_gateway *tg = media->t38_gateway; if (!tg) return; diff --git a/include/sdp.h b/include/sdp.h index 6b4807f37..84f699396 100644 --- a/include/sdp.h +++ b/include/sdp.h @@ -32,7 +32,7 @@ extern const str rtpe_instance_id; void sdp_init(void); -void sdp_insert_media_attributes(GString *, struct call_media *, const sdp_ng_flags *); +void sdp_insert_media_attributes(GString *, struct call_media *, struct call_media *, const sdp_ng_flags *); void sdp_insert_monologue_attributes(GString *, struct call_monologue *, const sdp_ng_flags *); void sdp_append_str_attr(GString *s, const sdp_ng_flags *flags, enum media_type media_type, diff --git a/include/types.h b/include/types.h index 2138fc60b..51172c136 100644 --- a/include/types.h +++ b/include/types.h @@ -35,7 +35,7 @@ struct sdp_origin { typedef struct sdp_origin sdp_origin; typedef void sdp_monologue_attr_print_f(GString *, struct call_monologue *, const sdp_ng_flags *flags); -typedef void sdp_media_attr_print_f(GString *, struct call_media *, const sdp_ng_flags *flags); +typedef void sdp_media_attr_print_f(GString *, struct call_media *, struct call_media *, const sdp_ng_flags *flags); typedef struct ng_parser ng_parser_t; typedef struct ng_parser_ctx ng_parser_ctx_t;