node: free the connection index when XX msg3 processing fails

The msg3-processing-failure cleanup read our_index from the connection
after removing it from the connections map, so the lookup always returned
None and the allocated index was never released, slowly leaking index
slots across failed XX handshakes. Capture the index before the remove,
matching the idiom used in the other cleanup paths in this file.
This commit is contained in:
Johnathan Corgan
2026-05-28 21:13:26 +00:00
parent 8e72326ec2
commit cc417a7bef
+21 -18
View File
@@ -810,25 +810,28 @@ impl Node {
// Process msg3 — learns initiator's identity and epoch
let noise_msg3 = &packet.data[header.noise_msg3_offset..];
let received_negotiation = match conn
.complete_handshake_msg3(noise_msg3, packet.timestamp_ms)
{
Ok(neg) => neg,
Err(e) => {
warn!(
link_id = %link_id,
error = %e,
"Msg3 processing failed"
);
// Clean up
self.connections.remove(&link_id);
self.remove_link(&link_id);
if let Some(idx) = self.connections.get(&link_id).and_then(|c| c.our_index()) {
let _ = self.index_allocator.free(idx);
let received_negotiation =
match conn.complete_handshake_msg3(noise_msg3, packet.timestamp_ms) {
Ok(neg) => neg,
Err(e) => {
warn!(
link_id = %link_id,
error = %e,
"Msg3 processing failed"
);
// Clean up. Capture the index before removing the
// connection; reading it after the remove would always
// return None and leak the allocated index.
let our_idx_to_free =
self.connections.get(&link_id).and_then(|c| c.our_index());
self.connections.remove(&link_id);
self.remove_link(&link_id);
if let Some(idx) = our_idx_to_free {
let _ = self.index_allocator.free(idx);
}
return;
}
return;
}
};
};
// Process peer's FMP negotiation payload from msg3
if let Some(neg_bytes) = &received_negotiation {