From 3be3baa209b314fdda2d72da40243adfc4d5eb3c Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 8 Jul 2021 11:09:23 -0400 Subject: [PATCH] TT#14008 delay learning of endpoint address after re-invite This fixes a race condition: Peer sends updated SDP with new address, but an older RTP packet from the old address is received afterwards. Thsi triggers learning of this old address is the "correct" endpoint. Afterwards the peer stops sending RTP until a packet to the new endpoint is received there, which never happens because the new endpoint has been discarded in favour of the "learned" old one. closes #817 Change-Id: I508f465a669f03e35ddcc6e770d5e7859e57569f (cherry picked from commit 45bd10d3237ec00f0240d48a0367958a4c174d0e) --- daemon/media_socket.c | 28 ++++++++++++++++++++-------- include/call.h | 1 + 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 26cbb2ab5..c9f3fbd21 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "str.h" #include "ice.h" #include "socket.h" @@ -1798,6 +1799,12 @@ static int media_packet_address_check(struct packet_handler_ctx *phc) goto out; } + /* wait at least 3 seconds after last signal before committing to a particular + * endpoint address */ + bool wait_time = false; + if (!phc->mp.call->last_signal || rtpe_now.tv_sec <= phc->mp.call->last_signal + 3) + wait_time = true; + const struct endpoint *use_endpoint_confirm = &phc->mp.fsin; if (rtpe_config.endpoint_learning == EL_IMMEDIATE) @@ -1836,9 +1843,7 @@ static int media_packet_address_check(struct packet_handler_ctx *phc) } } - /* wait at least 3 seconds after last signal before committing to a particular - * endpoint address */ - if (!phc->mp.call->last_signal || rtpe_now.tv_sec <= phc->mp.call->last_signal + 3) + if (wait_time) goto update_peerinfo; confirm_now: @@ -1851,11 +1856,18 @@ confirm_now: update_peerinfo: mutex_lock(&phc->mp.stream->out_lock); - endpoint = phc->mp.stream->endpoint; - phc->mp.stream->endpoint = *use_endpoint_confirm; - if (memcmp(&endpoint, &phc->mp.stream->endpoint, sizeof(endpoint))) { - phc->unkernelize = 1; - phc->update = 1; + // if we're during the wait time, check the received address against the previously + // learned address. if they're the same, ignore this packet for learning purposes + if (!wait_time || !phc->mp.stream->learned_endpoint.address.family || + memcmp(use_endpoint_confirm, &phc->mp.stream->learned_endpoint, sizeof(endpoint))) + { + endpoint = phc->mp.stream->endpoint; + phc->mp.stream->endpoint = *use_endpoint_confirm; + phc->mp.stream->learned_endpoint = *use_endpoint_confirm; + if (memcmp(&endpoint, &phc->mp.stream->endpoint, sizeof(endpoint))) { + phc->unkernelize = 1; + phc->update = 1; + } } update_addr: mutex_unlock(&phc->mp.stream->out_lock); diff --git a/include/call.h b/include/call.h index c12432505..762bda32d 100644 --- a/include/call.h +++ b/include/call.h @@ -277,6 +277,7 @@ struct packet_stream { struct endpoint detected_endpoints[4]; /* LOCK: out_lock */ struct timeval ep_detect_signal; /* LOCK: out_lock */ struct endpoint advertised_endpoint; /* RO */ + struct endpoint learned_endpoint; /* LOCK: out_lock */ struct crypto_context crypto; /* OUT direction, LOCK: out_lock */ struct ssrc_ctx *ssrc_in, /* LOCK: in_lock */ // XXX eliminate these *ssrc_out; /* LOCK: out_lock */