From eaa5d1c672305c07f2731083c060cb138c3dce4e Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Fri, 28 Feb 2025 14:08:38 -0400 Subject: [PATCH] MT#61625 split up __init_streams Have one function to just set flags and init a single media, and another one to set up sink pointers Change-Id: I3207ea9f36a0e3575c2149e077e6106fd065fe1b --- daemon/call.c | 186 +++++++++++++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 79 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index b214599f1..ee6bcebce 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1243,7 +1243,7 @@ void free_sink_handler(struct sink_handler *sh) { /** * A transfer of flags from the subscription to the sink handlers (sink_handler) is done - * using the __init_streams() through __add_sink_handler(). + * using the __streams_set_sinks() through __add_sink_handler(). */ void __add_sink_handler(sink_handler_q *q, struct packet_stream *sink, const struct sink_attrs *attrs) { struct sink_handler *sh = g_slice_alloc0(sizeof(*sh)); @@ -1254,7 +1254,7 @@ void __add_sink_handler(sink_handler_q *q, struct packet_stream *sink, const str t_queue_push_tail(q, sh); } -// called once before calling __init_streams once for each sink +// called once before calling __streams_set_sinks once for each sink static void __reset_streams(struct call_media *media) { for (__auto_type l = media->streams.head; l; l = l->next) { struct packet_stream *ps = l->data; @@ -1264,39 +1264,20 @@ static void __reset_streams(struct call_media *media) { } } -/** Called once on media A for each sink media B. - * B can be NULL. - * attrs can be NULL. - * TODO: this function seems to do two things - stream init (with B NULL) and sink init - split up? - */ +// sets stream flags, sets endpoint addresses if available, +// initialises SRTP, starts off the state machine __attribute__((nonnull(1))) -static bool __init_streams(struct call_media *A, struct call_media *B, const struct stream_params *sp, - const sdp_ng_flags *flags, const struct sink_attrs *attrs) { - struct packet_stream *a, *ax, *b; +static bool __init_streams(struct call_media *A, const struct stream_params *sp, + const sdp_ng_flags *flags) +{ unsigned int port_off = 0; - __auto_type la = A->streams.head; - __auto_type lb = B ? B->streams.head : NULL; - - if (B) - __C_DBG("Sink init media %u -> %u", A->index, B->index); - else - __C_DBG("Stream init media %u", A->index); + __C_DBG("Stream set flags media %u", A->index); - while (la) { - a = la->data; - b = lb ? lb->data : NULL; + for (__auto_type l = A->streams.head; l; l = l->next) { + __auto_type a = l->data; /* RTP */ - // reflect media - pretend reflection also for blackhole, as otherwise - // we get SSRC flip-flops on the opposite side - // XXX still necessary for blackhole? - if (attrs && attrs->egress && b) - __add_sink_handler(&a->rtp_mirrors, b, attrs); - else if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) - __add_sink_handler(&a->rtp_sinks, a, attrs); - else if (b && MEDIA_ISSET(B, SEND)) - __add_sink_handler(&a->rtp_sinks, b, attrs); PS_SET(a, RTP); /* XXX technically not correct, could be udptl too */ __rtp_stats_update(a->rtp_stats, &A->codecs); @@ -1308,54 +1289,25 @@ static bool __init_streams(struct call_media *A, struct call_media *B, const str } bf_copy_same(&a->ps_flags, &A->media_flags, SHARED_FLAG_ICE); - if (b) { - PS_CLEAR(b, ZERO_ADDR); - if (is_addr_unspecified(&a->advertised_endpoint.address) - && !(is_trickle_ice_address(&a->advertised_endpoint) - && MEDIA_ISSET(A, TRICKLE_ICE)) - && !(flags && flags->replace_zero_address)) - PS_SET(b, ZERO_ADDR); - } - if (!__init_stream(a)) return false; /* RTCP */ - if (B && lb && b && !MEDIA_ISSET(B, RTCP_MUX)) { - lb = lb->next; - assert(lb != NULL); - b = lb->data; - } - if (!MEDIA_ISSET(A, RTCP_MUX)) PS_CLEAR(a, RTCP); else { - if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) - { /* RTCP sink handler added below */ } - else if (b) - __add_sink_handler(&a->rtcp_sinks, b, attrs); PS_SET(a, RTCP); PS_CLEAR(a, IMPLICIT_RTCP); } - ax = a; + __auto_type ax = a; /* if muxing, this is the fallback RTCP port. it also contains the RTCP * crypto context */ - la = la->next; - assert(la != NULL); - a = la->data; - - if (attrs && attrs->egress) - goto no_rtcp; + l = l->next; + assert(l != NULL); + a = l->data; - if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) { - __add_sink_handler(&a->rtcp_sinks, a, attrs); - if (MEDIA_ISSET(A, RTCP_MUX)) - __add_sink_handler(&ax->rtcp_sinks, a, attrs); - } - else if (b) - __add_sink_handler(&a->rtcp_sinks, b, attrs); PS_CLEAR(a, RTP); PS_SET(a, RTCP); a->rtcp_sibling = NULL; @@ -1378,25 +1330,100 @@ static bool __init_streams(struct call_media *A, struct call_media *B, const str bf_copy_same(&a->ps_flags, &A->media_flags, SHARED_FLAG_ICE); PS_CLEAR(a, ZERO_ADDR); - if (b) { - if (is_addr_unspecified(&b->advertised_endpoint.address) - && !(is_trickle_ice_address(&b->advertised_endpoint) - && MEDIA_ISSET(B, TRICKLE_ICE)) - && !(flags && flags->replace_zero_address)) - PS_SET(a, ZERO_ADDR); - } if (!__init_stream(a)) return false; -no_rtcp: recording_setup_stream(ax); // RTP recording_setup_stream(a); // RTCP + port_off += 2; + } + + return true; +} + +/** Called once on media A for each sink media B. + * Sets up sink pointers. + * flags can be NULL + */ +__attribute__((nonnull(1, 2, 4))) +static bool __streams_set_sinks(struct call_media *A, struct call_media *B, + const sdp_ng_flags *flags, const struct sink_attrs *attrs) { + struct packet_stream *a, *ax, *b; + + __auto_type la = A->streams.head; + __auto_type lb = B->streams.head; + + __C_DBG("Sink init media %u -> %u", A->index, B->index); + + while (la) { + if (!lb) + break; // nothing left to do + + a = la->data; + b = lb->data; + + /* RTP */ + // reflect media - pretend reflection also for blackhole, as otherwise + // we get SSRC flip-flops on the opposite side + // XXX still necessary for blackhole? + if (attrs->egress && b) + __add_sink_handler(&a->rtp_mirrors, b, attrs); + else if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) + __add_sink_handler(&a->rtp_sinks, a, attrs); + else if (b && MEDIA_ISSET(B, SEND)) + __add_sink_handler(&a->rtp_sinks, b, attrs); + + PS_CLEAR(b, ZERO_ADDR); + if (is_addr_unspecified(&a->advertised_endpoint.address) + && !(is_trickle_ice_address(&a->advertised_endpoint) + && MEDIA_ISSET(A, TRICKLE_ICE)) + && !(flags && flags->replace_zero_address)) + PS_SET(b, ZERO_ADDR); + + /* RTCP */ + if (!MEDIA_ISSET(B, RTCP_MUX)) { + lb = lb->next; + assert(lb != NULL); + b = lb->data; + } + + if (MEDIA_ISSET(A, RTCP_MUX)) { + if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) + { /* RTCP sink handler added below */ } + else if (b) + __add_sink_handler(&a->rtcp_sinks, b, attrs); + } + + ax = a; + + /* if muxing, this is the fallback RTCP port. it also contains the RTCP + * crypto context */ la = la->next; - lb = lb ? lb->next : NULL; + assert(la != NULL); + a = la->data; - port_off += 2; + if (attrs->egress) + goto no_rtcp; + + if (MEDIA_ISSET(A, ECHO) || MEDIA_ISSET(A, BLACKHOLE)) { + __add_sink_handler(&a->rtcp_sinks, a, attrs); + if (MEDIA_ISSET(A, RTCP_MUX)) + __add_sink_handler(&ax->rtcp_sinks, a, attrs); + } + else if (b) + __add_sink_handler(&a->rtcp_sinks, b, attrs); + + if (is_addr_unspecified(&b->advertised_endpoint.address) + && !(is_trickle_ice_address(&b->advertised_endpoint) + && MEDIA_ISSET(B, TRICKLE_ICE)) + && !(flags && flags->replace_zero_address)) + PS_SET(a, ZERO_ADDR); + +no_rtcp: + la = la->next; + lb = lb->next; } return true; @@ -2594,12 +2621,10 @@ void codecs_offer_answer(struct call_media *media, struct call_media *other_medi /* called with call->master_lock held in W */ +__attribute__((nonnull(1))) static void __update_init_subscribers(struct call_media *media, struct stream_params *sp, sdp_ng_flags *flags, enum ng_opmode opmode) { - if (!media) - return; - recording_setup_media(media); /* should be set on media directly? Currently absent */ @@ -2608,6 +2633,9 @@ static void __update_init_subscribers(struct call_media *media, struct stream_pa __ice_start(media); + if (!__init_streams(media, sp, flags)) + ilog(LOG_WARN, "Error setting stream flags"); + /* update all subscribers */ __reset_streams(media); @@ -2617,7 +2645,7 @@ static void __update_init_subscribers(struct call_media *media, struct stream_pa struct call_media * sub_media = ms->media; if (!sub_media) continue; - if (!__init_streams(media, sub_media, sp, flags, &ms->attrs)) + if (!__streams_set_sinks(media, sub_media, flags, &ms->attrs)) ilog(LOG_WARN, "Error initialising streams"); } @@ -3554,7 +3582,7 @@ int monologue_publish(struct call_monologue *ml, sdp_streams_q *streams, sdp_ng_ __assign_stream_fds(media, &em->intf_sfds); // XXX this should be covered by __update_init_subscribers ? - if (!__init_streams(media, NULL, sp, flags, NULL)) + if (!__init_streams(media, sp, flags)) return -1; __ice_start(media); ice_update(media->ice_agent, sp, false); @@ -3628,7 +3656,7 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca __num_media_streams(dst_media, num_ports); __assign_stream_fds(dst_media, &em->intf_sfds); - if (!__init_streams(dst_media, NULL, NULL, flags, NULL)) + if (!__init_streams(dst_media, NULL, flags)) return -1; __update_init_subscribers(src_media, NULL, NULL, flags->opmode); @@ -3718,7 +3746,7 @@ int monologue_subscribe_answer(struct call_monologue *dst_ml, sdp_ng_flags *flag __dtls_logic(flags, dst_media, sp); - if (!__init_streams(dst_media, NULL, sp, flags, NULL)) + if (!__init_streams(dst_media, sp, flags)) return -1; MEDIA_CLEAR(dst_media, RECV);