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 cabd5e4676)
(cherry picked from commit a38d7ed411)
mr13.2.1
Richard Fuchs 2 months ago
parent c9183d7ae9
commit 9b36d4962e

@ -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_free(struct sdp_attribute *p);
static void attr_insert(struct sdp_attributes *attrs, struct sdp_attribute *attr); 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, 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 packet_stream *rtp_ps,
struct sdp_ng_flags *flags, struct sdp_ng_flags *flags,
endpoint_t *sdp_address); 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 // Look up the source media. We copy the source's attributes if there is only one source
// media. Otherwise we skip this step. // media. Otherwise we skip this step.
if (media->media_subscriptions.length != 1) if (!source_media)
return; return;
for (__auto_type l = source_media->generic_attributes.head; l; l = l->next) {
__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) {
__auto_type s = l->data; __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; 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) { 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. * SDP session version manipulations.
*/ */
static void sdp_version_check(GString *s, struct call_monologue *monologue, static void sdp_version_check(GString *s, struct call_monologue *monologue,
struct call_monologue *source_ml,
bool force_increase) bool force_increase)
{ {
if (!monologue->session_last_sdp_orig) 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 *origin = monologue->session_last_sdp_orig;
sdp_origin *other_origin = NULL; sdp_origin *other_origin = NULL;
struct media_subscription *ms = call_ml_get_top_ms(monologue); if (source_ml && source_ml->session_sdp_orig)
if (ms && ms->monologue && ms->monologue->session_sdp_orig) other_origin = source_ml->session_sdp_orig;
other_origin = ms->monologue->session_sdp_orig;
/* We really expect only a single session here, but we treat all the same regardless, /* 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 */ * 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 */ /* TODO: rework an appending of parameters in terms of sdp attribute manipulations */
static void print_sdp_media_section(GString *s, struct call_media *media, 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, struct packet_stream *rtp_ps,
packet_stream_list *rtp_ps_link, sdp_ng_flags *flags) packet_stream_list *rtp_ps_link, sdp_ng_flags *flags)
{ {
struct packet_stream *ps_rtcp = NULL; struct packet_stream *ps_rtcp = NULL;
bool inactive_media = (!address->port || !rtp_ps->selected_sfd); /* audio is accepted? */ 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 */ /* 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; 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); sdp_out_add_media_connection(s, media, rtp_ps, (inactive_media ? NULL : &address->address), flags);
/* add per media bandwidth */ /* 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). */ /* mid and label must be added even for inactive streams (see #1361 and #1362). */
if (media->media_id.s) 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); insert_codec_parameters(s, media, flags);
/* all unknown type attributes will be added here */ /* 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 */ /* print sendrecv */
if (!flags->original_sendrecv) if (!flags->original_sendrecv)
@ -2704,7 +2704,7 @@ static void print_sdp_media_section(GString *s, struct call_media *media,
media->type_id); media->type_id);
} }
if (MEDIA_ISSET(media, ICE)) { 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)) { 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, 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 packet_stream *first_ps, sdp_ng_flags *flags)
{ {
struct call_monologue *ml = monologue; __auto_type ml = source_ml;
if (!ml)
/* for the offer/answer model or subscribe don't use the given monologues SDP, ml = monologue;
* 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;
/* orig username /* orig username
* session_last_sdp_orig is stored on the other media always, * 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 */ /* orig IP family and address */
str orig_address_type; str orig_address_type;
str orig_address; 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 */ /* replacing flags or PUBLISH */
orig_address_type = STR(first_ps->selected_sfd->local_intf->advertised_address.addr.family->rfc_name); 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)); 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)); 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="); 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, * 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. */ * 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, if (source_ml)
* 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 a session name was empty in the s= attr of the coming message, /* if a session name was empty in the s= attr of the coming message,
* while processing this ml in `__call_monologue_init_from_flags()`, * while processing this ml in `__call_monologue_init_from_flags()`,
* then just keep it empty. */ * then just keep it empty. */
if (ms->monologue->sdp_session_name.len) if (source_ml->sdp_session_name.len)
g_string_append_len(out, ms->monologue->sdp_session_name.s, ms->monologue->sdp_session_name.len); g_string_append_len(out, source_ml->sdp_session_name.s, source_ml->sdp_session_name.len);
} }
else else
g_string_append(out, rtpe_config.software_id); 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 */ /* sdp timing per session level */
g_string_append(out, "t="); g_string_append(out, "t=");
struct media_subscription *ms = call_ml_get_top_ms(monologue); if (monologue && monologue->sdp_session_timing.len)
if (ms && ms->monologue && ms->monologue->sdp_session_timing.len) g_string_append_len(out, monologue->sdp_session_timing.s, monologue->sdp_session_timing.len);
g_string_append_len(out, ms->monologue->sdp_session_timing.s, ms->monologue->sdp_session_timing.len);
else else
g_string_append(out, "0 0"); /* default */ 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, static void sdp_out_add_other(GString *out, struct call_monologue *monologue,
struct call_monologue *source_ml,
struct call_media *media, struct call_media *media,
sdp_ng_flags *flags) sdp_ng_flags *flags)
{ {
bool media_has_ice = MEDIA_ISSET(media, ICE); bool media_has_ice = MEDIA_ISSET(media, ICE);
bool media_has_ice_lite_self = MEDIA_ISSET(media, ICE_LITE_SELF); 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 */ /* add loop protectio if required */
if (flags->loop_protect) if (flags->loop_protect)
append_attr_to_gstring(out, "rtpengine", &rtpe_instance_id, flags, media->type_id); 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); append_attr_to_gstring(out, "ice-lite", NULL, flags, media->type_id);
/* group */ /* group */
if (ms && ms->monologue && ms->monologue->sdp_session_group.len && flags->ice_option == ICE_FORCE_RELAY) if (source_ml && source_ml->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); 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 */ /* carry other session level a= attributes to the outgoing SDP */
monologue->sdp_attr_print(out, monologue, flags); 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 /* 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 */ * 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 */ /* don't add session level bandwidth for subscribe requests */
if (!ms || flags->opmode == OP_SUBSCRIBE_REQ) if (!monologue || flags->opmode == OP_SUBSCRIBE_REQ)
return; 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, static void sdp_out_add_media_bandwidth(GString *out,
struct call_media *media, sdp_ng_flags *flags) struct call_media *media, sdp_ng_flags *flags)
{ {
/* sdp bandwidth per media level */ if (!media)
struct media_subscription *ms = call_media_get_top_ms(media);
if (!ms)
return; 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, 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); sdp_out_add_osrtp_media(out, media, prtp, address);
/* print media level attributes */ /* 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; 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) 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_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); sdp_insert_all_attributes(out, source_media, flags);
if (MEDIA_ISSET(source_media, ICE)) { if (MEDIA_ISSET(source_media, ICE)) {
struct packet_stream *rtcp_ps = rtp_ps->rtcp_sibling; 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. * then we need to look up the source media.
*/ */
static struct call_media *sdp_out_set_source_media_address(struct call_media *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 packet_stream *rtp_ps,
struct sdp_ng_flags *flags, struct sdp_ng_flags *flags,
endpoint_t *sdp_address) endpoint_t *sdp_address)
{ {
struct call_media *source_media = NULL;
/* the port and address that goes into the SDP also depends on this */ /* the port and address that goes into the SDP also depends on this */
if (rtp_ps->selected_sfd) { if (rtp_ps->selected_sfd) {
sdp_address->port = rtp_ps->selected_sfd->socket.local.port; sdp_address->port = rtp_ps->selected_sfd->socket.local.port;
sdp_address->address = rtp_ps->selected_sfd->local_intf->advertised_address.addr; sdp_address->address = rtp_ps->selected_sfd->local_intf->advertised_address.addr;
} }
struct media_subscription *ms = call_media_get_top_ms(media); if (source_media) {
if (ms && ms->media) {
source_media = ms->media;
/* cases with message, force relay and pass through */ /* 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 (media->type_id == MT_MESSAGE || flags->ice_option == ICE_FORCE_RELAY || MEDIA_ISSET(media, PASSTHRU)) {
if (source_media->streams.head) { 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) if (!first_ps || !first_ps->selected_sfd)
goto err; 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 */ /* init new sdp */
s = g_string_new("v=0\r\n"); s = g_string_new("v=0\r\n");
/* add origin including name and version */ /* 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 */ /* 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 /* don't set connection on the session level
* but instead per media, below */ * but instead per media, below */
/* add bandwidth control per session level */ /* 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 */ /* 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 */ /* 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 */ /* print media sections */
for (unsigned int i = 0; i < monologue->medias->len; i++) 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; __auto_type rtp_ps_link = media->streams.head;
struct packet_stream *rtp_ps = rtp_ps_link->data; 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}; 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); &sdp_address);
unsigned int port = sdp_address.port; 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; goto err;
/* print media level attributes */ /* 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 */ /* handle second OSRTP part */
sdp_out_handle_osrtp2(s, media, prtp); 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. * which forces version increase regardless changes in the SDP information.
*/ */
if (flags->force_inc_sdp_ver || flags->replace_sdp_version || flags->replace_origin_full) 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->len = s->len;
out->s = g_string_free(s, FALSE); out->s = g_string_free(s, FALSE);

@ -332,7 +332,9 @@ static int span_log_level_map(int level) {
return 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; struct t38_gateway *tg = media->t38_gateway;
if (!tg) if (!tg)
return; return;

@ -32,7 +32,7 @@ extern const str rtpe_instance_id;
void sdp_init(void); 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_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, void sdp_append_str_attr(GString *s, const sdp_ng_flags *flags, enum media_type media_type,

@ -35,7 +35,7 @@ struct sdp_origin {
typedef struct sdp_origin 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_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 ng_parser_t;
typedef struct ng_parser_ctx ng_parser_ctx_t; typedef struct ng_parser_ctx ng_parser_ctx_t;

Loading…
Cancel
Save