node/wire: Refactor precedence

No change in the logic here, just making this slightly easer to read and
understand.
This commit is contained in:
Lorenz Leutgeb 2025-08-24 18:11:20 +02:00 committed by Fintan Halpenny
parent cb7bed5562
commit 633059040c
1 changed files with 32 additions and 38 deletions

View File

@ -623,61 +623,55 @@ where
let mut disconnect = Vec::new(); let mut disconnect = Vec::new();
// Handle conflicting connections. // Handle conflicting connections.
// This is typical when nodes have mutually configured their nodes to connect to // This is typical when users have mutually configured their nodes to connect to
// each other on startup. We handle this by deterministically choosing one node // each other on startup. We handle this by deterministically choosing one node
// whos outbound connection is the one that is kept. The other connections are // whose outbound connection is the one that is kept. The other connections are
// dropped. // dropped.
{ {
// Whether we have precedence in case of conflicting connections.
// Having precedence means that our outbound connection will win over // Having precedence means that our outbound connection will win over
// the other node's outbound connection. // the other node's outbound connection.
let precedence = *self.signer.public_key() > nid; enum Precedence {
Ours,
Theirs,
}
// Pre-existing connections that conflict with this newly established session. use Link::*;
// Note that we can't know whether a connection is conflicting before we get the use Precedence::*;
// remote static key.
let mut conflicting = Vec::new();
// Active sessions with the same NID but a different Resource ID are conflicting. // Whether we have precedence in case of conflicting connections.
conflicting.extend( let precedence = if *self.signer.public_key() > nid {
self.peers Ours
.active() } else {
.filter(|(c_id, d, _)| **d == nid && *c_id != token) Theirs
.map(|(c_id, _, link)| (c_id, link)), };
);
// Active sessions with the same NID but a different token are conflicting.
let peers = self.peers.active().filter_map(|(c_id, d, link)| {
(*d == nid && c_id != token).then_some((c_id, link))
});
// Outbound connection attempts with the same remote key but a different file // Outbound connection attempts with the same remote key but a different file
// descriptor are conflicting. // descriptor are conflicting.
conflicting.extend(self.outbound.iter().filter_map(|(c_id, other)| { let outbound = self.outbound.iter().filter_map(|(c_id, other)| {
(other.nid == nid && *c_id != token).then_some((*c_id, Link::Outbound)) (other.nid == nid && *c_id != token).then_some((*c_id, Outbound))
})); });
for (c_token, c_link) in conflicting { for (c_token, c_link) in peers.chain(outbound) {
// If we have precedence, the inbound connection is closed. // If we have precedence, the inbound connection is closed.
// In the case where both connections are inbound or outbound, // In the case where both connections are inbound or outbound,
// we close the newer connection, ie. the one with the higher // we close the newer connection, ie. the one with the higher
// resource id. // token.
let close = match (link, c_link) { let close = match (link, c_link, &precedence) {
(Link::Inbound, Link::Outbound) => { (Inbound, Outbound, Ours) => token,
if precedence { (Inbound, Outbound, Theirs) => c_token,
token (Outbound, Inbound, Ours) => c_token,
} else { (Outbound, Inbound, Theirs) => token,
c_token (Inbound, Inbound, _) => token.max(c_token),
} (Outbound, Outbound, _) => token.max(c_token),
}
(Link::Outbound, Link::Inbound) => {
if precedence {
c_token
} else {
token
}
}
(Link::Inbound, Link::Inbound) => token.max(c_token),
(Link::Outbound, Link::Outbound) => token.max(c_token),
}; };
log::warn!( log::warn!(
target: "wire", "Established session with token {} conflicts with existing session with token {} for {nid}", token.0, c_token.0 target: "wire", "Established session with token {} conflicts with existing session with token {} for {nid}. Disconnecting session with token {}.", token.0, c_token.0, close.0
); );
disconnect.push(close); disconnect.push(close);
} }