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
pull/1311/head
Richard Fuchs 4 years ago
parent 8d06707a9f
commit 45bd10d323

@ -1953,6 +1953,12 @@ static int media_packet_address_check(struct packet_handler_ctx *phc)
goto out; 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; const struct endpoint *use_endpoint_confirm = &phc->mp.fsin;
if (rtpe_config.endpoint_learning == EL_IMMEDIATE) if (rtpe_config.endpoint_learning == EL_IMMEDIATE)
@ -1991,9 +1997,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 if (wait_time)
* endpoint address */
if (!phc->mp.call->last_signal || rtpe_now.tv_sec <= phc->mp.call->last_signal + 3)
goto update_peerinfo; goto update_peerinfo;
confirm_now: confirm_now:
@ -2006,11 +2010,18 @@ confirm_now:
update_peerinfo: update_peerinfo:
mutex_lock(&phc->mp.stream->out_lock); mutex_lock(&phc->mp.stream->out_lock);
endpoint = phc->mp.stream->endpoint; // if we're during the wait time, check the received address against the previously
phc->mp.stream->endpoint = *use_endpoint_confirm; // learned address. if they're the same, ignore this packet for learning purposes
if (memcmp(&endpoint, &phc->mp.stream->endpoint, sizeof(endpoint))) { if (!wait_time || !phc->mp.stream->learned_endpoint.address.family ||
phc->unkernelize = 1; memcmp(use_endpoint_confirm, &phc->mp.stream->learned_endpoint, sizeof(endpoint)))
phc->update = 1; {
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: update_addr:
mutex_unlock(&phc->mp.stream->out_lock); mutex_unlock(&phc->mp.stream->out_lock);

@ -300,6 +300,7 @@ struct packet_stream {
struct endpoint detected_endpoints[4]; /* LOCK: out_lock */ struct endpoint detected_endpoints[4]; /* LOCK: out_lock */
struct timeval ep_detect_signal; /* LOCK: out_lock */ struct timeval ep_detect_signal; /* LOCK: out_lock */
struct endpoint advertised_endpoint; /* RO */ struct endpoint advertised_endpoint; /* RO */
struct endpoint learned_endpoint; /* LOCK: out_lock */
struct crypto_context crypto; /* OUT direction, LOCK: out_lock */ struct crypto_context crypto; /* OUT direction, LOCK: out_lock */
struct ssrc_ctx *ssrc_in, /* LOCK: in_lock */ struct ssrc_ctx *ssrc_in, /* LOCK: in_lock */
*ssrc_out; /* LOCK: out_lock */ *ssrc_out; /* LOCK: out_lock */

Loading…
Cancel
Save