mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-12 09:33:23 +00:00
Fix cross-connection session alignment for simultaneous auto-connect
When both nodes simultaneously initiate connections, each promotes its inbound handshake first, leaving both sides with mismatched Noise sessions and session indices. Resolve this in handle_msg2 using the existing tie-breaker (smaller node_addr's outbound wins): - Winner (smaller node): swaps ActivePeer to outbound session + indices via new replace_session() method - Loser (larger node): keeps inbound session and original their_index (already references winner's outbound our_index from msg1) Key insight: the loser must NOT update their_index from msg2, because the msg2 sender_idx carries the winner's inbound index which becomes stale after the winner swaps. Defer outbound connection cleanup from promote_connection() to handle_msg2() so outbound session state is available for the swap. Verified with live two-node test over UDP in network namespaces: both nodes connect, exchange TreeAnnounce, and converge to spanning tree within ~2s.
This commit is contained in:
@@ -287,6 +287,34 @@ impl ActivePeer {
|
||||
self.their_index
|
||||
}
|
||||
|
||||
/// Update their session index (used during cross-connection resolution
|
||||
/// when the losing node keeps its inbound session but needs the peer's
|
||||
/// outbound index).
|
||||
pub fn set_their_index(&mut self, index: SessionIndex) {
|
||||
self.their_index = Some(index);
|
||||
}
|
||||
|
||||
/// Replace the Noise session and indices during cross-connection resolution.
|
||||
///
|
||||
/// When both nodes simultaneously initiate, each promotes its inbound
|
||||
/// handshake first. When the peer's msg2 arrives, we learn the correct
|
||||
/// session — the outbound handshake that pairs with the peer's inbound.
|
||||
/// This replaces the entire session so both nodes use matching keys.
|
||||
///
|
||||
/// Returns the old our_index so the caller can update peers_by_index.
|
||||
pub fn replace_session(
|
||||
&mut self,
|
||||
new_session: NoiseSession,
|
||||
new_our_index: SessionIndex,
|
||||
new_their_index: SessionIndex,
|
||||
) -> Option<SessionIndex> {
|
||||
let old_our_index = self.our_index;
|
||||
self.noise_session = Some(new_session);
|
||||
self.our_index = Some(new_our_index);
|
||||
self.their_index = Some(new_their_index);
|
||||
old_our_index
|
||||
}
|
||||
|
||||
/// Get the transport ID for this peer.
|
||||
pub fn transport_id(&self) -> Option<TransportId> {
|
||||
self.transport_id
|
||||
|
||||
Reference in New Issue
Block a user