From 91d066949999143d0058e226b824478b8dd0bd7e Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 17 Aug 2026 10:06:25 -0400 Subject: [PATCH] MT#55283 improve setup=actpass logic Using the FILLED flag to decide how to resolve actpass is not reliable, as during a reinvite FILLED would be set for both stream directions. Instead, immediately clear the ACTIVE flag during the offer phase (dtls_logic) and assume a strict passive role. Then if the answer indicates that the connection needs to be active instead, a reset occurs via dtls_connection_init. Closes #2156 Change-Id: I0ded94620bcaa481eea920ae0c412c7bb86bff1f --- daemon/call.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index e5950f19b..d856404bd 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1196,11 +1196,12 @@ bool __init_stream(struct packet_stream *ps) { if (MEDIA_ISSET(media, DTLS) && !PS_ISSET(ps, FALLBACK_RTCP)) { // we try to retain our role if possible, but must handle a role switch - if ((dtls_active && !MEDIA_ISSET(media, SETUP_ACTIVE)) - || (!dtls_active && !MEDIA_ISSET(media, SETUP_PASSIVE))) - dtls_active = -1; if (dtls_active == -1) - dtls_active = (PS_ISSET(ps, FILLED) && MEDIA_ISSET(media, SETUP_ACTIVE)); + dtls_active = !MEDIA_ISSET(media, SETUP_PASSIVE); + else if (dtls_active == 0 && !MEDIA_ISSET(media, SETUP_PASSIVE)) + dtls_active = 1; + else if (dtls_active == 1 && !MEDIA_ISSET(media, SETUP_ACTIVE)) + dtls_active = 0; dtls_connection_init(&ps->ice_dtls, ps, dtls_active, call->dtls_cert); for (__auto_type l = ps->sfds.head; l; l = l->next) { stream_fd *sfd = l->data; @@ -2206,17 +2207,21 @@ static void __dtls_logic(const sdp_ng_flags *flags, MEDIA_CLEAR(other_media, SETUP_PASSIVE); } - /* Special case: if this is an offer and actpass is being offered (as it should), - * we would normally choose to be active. However, if this is a reinvite and we - * were passive previously, we should retain this role. */ + // resolve setup=actpass for offers if ((flags->opmode == OP_OFFER || flags->opmode == OP_PUBLISH) - && MEDIA_ARESET2(other_media, SETUP_ACTIVE, SETUP_PASSIVE) - && (tmp & (MEDIA_FLAG_SETUP_ACTIVE | MEDIA_FLAG_SETUP_PASSIVE)) + && MEDIA_ARESET2(other_media, SETUP_ACTIVE, SETUP_PASSIVE)) + { + // if passive mode is requested, honour it + if (flags->dtls_reverse_passive) + MEDIA_CLEAR(other_media, SETUP_ACTIVE); + // if we were previously passive, retain that role + else if ((tmp & (MEDIA_FLAG_SETUP_ACTIVE | MEDIA_FLAG_SETUP_PASSIVE)) == MEDIA_FLAG_SETUP_PASSIVE) - MEDIA_CLEAR(other_media, SETUP_ACTIVE); - /* if passive mode is requested, honour it if we can */ - if (flags->dtls_reverse_passive && MEDIA_ISSET(other_media, SETUP_PASSIVE)) - MEDIA_CLEAR(other_media, SETUP_ACTIVE); + MEDIA_CLEAR(other_media, SETUP_ACTIVE); + // in all other cases: we are active + else + MEDIA_CLEAR(other_media, SETUP_PASSIVE); + } // restart DTLS? if (memcmp(&other_media->fingerprint, &sp->fingerprint, sizeof(sp->fingerprint))) {