mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 18:18:55 +00:00
fix(connlib): resend candidates on connection upsert (#9986)
Due to network partitions between the Client and the Portal, it is possible that a Client requests a new connection, then disconnects from the portal and re-requests the connection once it is reconnected. On the Gateway, we would have already authorized the first request and initialise our ICE agents with our local candidates. The second time around, the connection would be reused. The Client however has lost its state and therefore, we need to tell it our candidates again. --------- Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
@@ -257,9 +257,23 @@ where
|
||||
.is_some_and(|c| c == &remote_creds)
|
||||
&& c.tunnel.remote_static_public() == remote
|
||||
{
|
||||
tracing::info!(local = ?local_creds, "Reusing existing connection");
|
||||
|
||||
c.state.on_upsert(cid, &mut c.agent, now);
|
||||
|
||||
tracing::info!(local = ?local_creds, "Reusing existing connection");
|
||||
for candidate in c.agent.local_candidates() {
|
||||
signal_candidate_to_remote(cid, candidate, &mut self.pending_events);
|
||||
}
|
||||
|
||||
// Server-reflexive candidates are not in the local candidates of the ICE agent so those need special handling.
|
||||
for candidate in self
|
||||
.shared_candidates
|
||||
.iter()
|
||||
.filter(|c| c.kind() == CandidateKind::ServerReflexive)
|
||||
{
|
||||
signal_candidate_to_remote(cid, candidate, &mut self.pending_events);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -1398,12 +1412,7 @@ fn add_local_candidate<TId>(
|
||||
{
|
||||
// srflx candidates don't need to be added to the local agent because we always send from the `base` anyway.
|
||||
if candidate.kind() == CandidateKind::ServerReflexive {
|
||||
tracing::info!(?candidate, "Signalling candidate to remote");
|
||||
|
||||
pending_events.push_back(Event::NewIceCandidate {
|
||||
connection: id,
|
||||
candidate: candidate.to_sdp_string(),
|
||||
});
|
||||
signal_candidate_to_remote(id, &candidate, pending_events);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1411,6 +1420,14 @@ fn add_local_candidate<TId>(
|
||||
return;
|
||||
};
|
||||
|
||||
signal_candidate_to_remote(id, candidate, pending_events);
|
||||
}
|
||||
|
||||
fn signal_candidate_to_remote<TId>(
|
||||
id: TId,
|
||||
candidate: &Candidate,
|
||||
pending_events: &mut VecDeque<Event<TId>>,
|
||||
) {
|
||||
tracing::info!(?candidate, "Signalling candidate to remote");
|
||||
|
||||
pending_events.push_back(Event::NewIceCandidate {
|
||||
|
||||
@@ -23,6 +23,10 @@ export default function Gateway() {
|
||||
return (
|
||||
<Entries downloadLinks={downloadLinks} title="Gateway">
|
||||
<Unreleased>
|
||||
<ChangeItem pull="9986">
|
||||
Fixes an issue where a Client could not establish a connection unless
|
||||
their first attempt succeeded.
|
||||
</ChangeItem>
|
||||
<ChangeItem pull="9979">
|
||||
Fixes an issue where connections in low-latency networks (between
|
||||
Client and Gateway) would fail to establish reliably.
|
||||
|
||||
Reference in New Issue
Block a user