From f5a148f2684c6e3e8da2274da925b7512052e6d1 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 11 Jan 2022 11:47:21 -0500 Subject: [PATCH] TT#14008 change local ICE ufrag/pwd after ICE restart Implements RFC 5245 9.2.1.1 Also reset ICE role after a restart closes #786 Change-Id: Idc7ec9f409b70598e2840fb7d0a31a12f9db3c21 --- daemon/call.c | 12 ++--- daemon/ice.c | 13 +++-- include/ice.h | 37 +++++++++----- t/auto-daemon-tests.pl | 111 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 25 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index 790980686..a45642ed6 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -1439,7 +1439,7 @@ static int __init_streams(struct call_media *A, struct call_media *B, const stru } static void __ice_offer(const struct sdp_ng_flags *flags, struct call_media *this, - struct call_media *other) + struct call_media *other, bool ice_restart) { if (!flags) return; @@ -1531,7 +1531,7 @@ static void __ice_offer(const struct sdp_ng_flags *flags, struct call_media *thi /* ICE_CONTROLLING is from our POV, the other ICE flags are from peer's POV */ if (MEDIA_ISSET(this, ICE_LITE_PEER) && !MEDIA_ISSET(this, ICE_LITE_SELF)) MEDIA_SET(this, ICE_CONTROLLING); - else if (!MEDIA_ISSET(this, INITIALIZED)) { + else if (!MEDIA_ISSET(this, INITIALIZED) || ice_restart) { if (MEDIA_ISSET(this, ICE_LITE_SELF)) MEDIA_CLEAR(this, ICE_CONTROLLING); else if (flags->opmode == OP_OFFER) @@ -1544,7 +1544,7 @@ static void __ice_offer(const struct sdp_ng_flags *flags, struct call_media *thi /* roles are reversed for the other side */ if (MEDIA_ISSET(other, ICE_LITE_PEER) && !MEDIA_ISSET(other, ICE_LITE_SELF)) MEDIA_SET(other, ICE_CONTROLLING); - else if (!MEDIA_ISSET(other, INITIALIZED)) { + else if (!MEDIA_ISSET(other, INITIALIZED) || ice_restart) { if (MEDIA_ISSET(other, ICE_LITE_SELF)) MEDIA_CLEAR(other, ICE_CONTROLLING); else if (flags->opmode == OP_OFFER) @@ -2722,7 +2722,7 @@ int monologue_offer_answer(struct call_monologue *dialogue[2], GQueue *streams, } /* ICE stuff - must come after interface and address family selection */ - __ice_offer(flags, media, other_media); + __ice_offer(flags, media, other_media, ice_is_restart(other_media->ice_agent, sp)); /* we now know what's being advertised by the other side */ @@ -2912,7 +2912,7 @@ int monologue_publish(struct call_monologue *ml, GQueue *streams, struct sdp_ng_ return -1; // XXX return error code /* ICE stuff - must come after interface and address family selection */ - __ice_offer(flags, media, media); + __ice_offer(flags, media, media, ice_is_restart(media->ice_agent, sp)); MEDIA_SET(media, INITIALIZED); @@ -2982,7 +2982,7 @@ static int monologue_subscribe_request1(struct call_monologue *src_ml, struct ca if (dst_media->logical_intf == NULL) return -1; // XXX return error code - __ice_offer(flags, dst_media, src_media); + __ice_offer(flags, dst_media, src_media, ice_is_restart(src_media->ice_agent, sp)); struct endpoint_map *em = __get_endpoint_map(dst_media, sp->num_ports, NULL, flags, true); if (!em) diff --git a/daemon/ice.c b/daemon/ice.c index 68e24cd1c..d538ffe4b 100644 --- a/daemon/ice.c +++ b/daemon/ice.c @@ -295,15 +295,19 @@ static void __ice_reset(struct ice_agent *ag) { /* if the other side did a restart */ static void __ice_restart(struct ice_agent *ag) { - ilogs(ice, LOG_DEBUG, "ICE restart, resetting ICE agent"); + ilogs(ice, LOG_DEBUG, "ICE restart detected, resetting ICE agent"); ag->ufrag[0] = STR_NULL; ag->pwd[0] = STR_NULL; + ag->ufrag[1] = STR_NULL; + ag->pwd[1] = STR_NULL; __ice_reset(ag); } /* if we're doing a restart */ void ice_restart(struct ice_agent *ag) { + ilogs(ice, LOG_DEBUG, "Restarting ICE and resetting ICE agent"); + ag->ufrag[1] = STR_NULL; ag->pwd[1] = STR_NULL; __ice_reset(ag); @@ -331,12 +335,7 @@ void ice_update(struct ice_agent *ag, struct stream_params *sp) { __role_change(ag, MEDIA_ISSET(media, ICE_CONTROLLING)); if (sp) { - /* check for ICE restarts */ - if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) - __ice_restart(ag); - else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) - __ice_restart(ag); - else if (ag->logical_intf != media->logical_intf) + if (ice_is_restart(ag, sp)) __ice_restart(ag); /* update remote info */ diff --git a/include/ice.h b/include/ice.h index f08f7fd52..7885e6bf3 100644 --- a/include/ice.h +++ b/include/ice.h @@ -172,28 +172,41 @@ int ice_response(struct stream_fd *, const endpoint_t *src, /* returns 0 if ICE still has work to do, 1 otherwise */ -INLINE int ice_has_finished(struct call_media *media) { +INLINE bool ice_has_finished(struct call_media *media) { if (!media) - return 1; + return true; if (!MEDIA_ISSET(media, ICE)) - return 1; + return true; if (!media->ice_agent) - return 1; + return true; if (AGENT_ISSET(media->ice_agent, COMPLETED)) - return 1; - return 0; + return true; + return false; } /* returns 1 if media has connectivity */ -INLINE int ice_is_usable(struct call_media *media) { +INLINE bool ice_is_usable(struct call_media *media) { if (!media) - return 1; + return true; if (!MEDIA_ISSET(media, ICE)) - return 1; + return true; if (!media->ice_agent) - return 1; + return true; if (AGENT_ISSET(media->ice_agent, USABLE)) - return 1; - return 0; + return true; + return false; +} +INLINE bool ice_is_restart(struct ice_agent *ag, struct stream_params *sp) { + if (!ag || !sp) + return false; + struct call_media *media = ag->media; + if (ag->ufrag[0].s && sp->ice_ufrag.s && str_cmp_str(&ag->ufrag[0], &sp->ice_ufrag)) + return true; + else if (ag->pwd[0].s && sp->ice_pwd.s && str_cmp_str(&ag->pwd[0], &sp->ice_pwd)) + return true; + else if (ag->logical_intf != media->logical_intf) + return true; + return false; + } INLINE unsigned int ice_type_preference(enum ice_candidate_type type) { if (type >= __ICT_LAST) diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 6242cd6c6..5de8373f7 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -40,6 +40,117 @@ my ($sock_a, $sock_b, $sock_c, $sock_d, $port_a, $port_b, $ssrc, $ssrc_b, $resp, +new_call; + +offer('ICE restart', + { ICE => 'remove' }, < { strip => ['all'] } }, <