mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Relocate PromotionResult into proto/fmp
Move the PromotionResult enum (and its impl) out of peer::mod and into proto/fmp/core.rs, alongside the cross_connection_winner tie-break helper that was relocated the same way. This is FMP connection-lifecycle result vocabulary, so it belongs in the FMP subsystem home rather than the peer module. Behavior-neutral pure type relocation: consumers import it from crate::proto::fmp, and the crate-root public path crate::PromotionResult is preserved via a re-export in lib.rs (mirroring cross_connection_winner). Full lib suite green at baseline.
This commit is contained in:
+2
-3
@@ -88,13 +88,12 @@ pub use proto::fmp::HandshakeMessageType;
|
||||
// Re-export cache types
|
||||
pub use cache::{CacheEntry, CacheError, CacheStats, CoordCache};
|
||||
|
||||
// Re-export FMP tie-break helper (relocated from peer:: to proto::fmp)
|
||||
pub use proto::fmp::cross_connection_winner;
|
||||
// Re-export FMP tie-break helper and promotion result (relocated from peer:: to proto::fmp)
|
||||
pub use proto::fmp::{PromotionResult, cross_connection_winner};
|
||||
|
||||
// Re-export peer types
|
||||
pub use peer::{
|
||||
ActivePeer, ConnectivityState, HandshakeState, PeerConnection, PeerError, PeerSlot,
|
||||
PromotionResult,
|
||||
};
|
||||
|
||||
// Re-export node types
|
||||
|
||||
@@ -5,11 +5,11 @@ use crate::PeerIdentity;
|
||||
use crate::node::acl::PeerAclContext;
|
||||
use crate::node::reject::{HandshakeReject, RejectReason};
|
||||
use crate::node::{Node, NodeError};
|
||||
use crate::peer::{ActivePeer, PeerConnection, PromotionResult};
|
||||
use crate::peer::{ActivePeer, PeerConnection};
|
||||
use crate::proto::fmp::wire::{Msg1Header, Msg2Header, build_msg2};
|
||||
use crate::proto::fmp::{
|
||||
ConnAction, EstablishSnapshot, EstablishView, InboundDecision, InboundReject, OutboundDecision,
|
||||
OutboundSnapshot, WireOutcome, cross_connection_winner,
|
||||
OutboundSnapshot, PromotionResult, WireOutcome, cross_connection_winner,
|
||||
};
|
||||
use crate::transport::{Link, LinkDirection, LinkId, ReceivedPacket};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -1002,7 +1002,7 @@ fn build_ipv6_packet(
|
||||
|
||||
#[test]
|
||||
fn test_identity_cache_populated_on_promote() {
|
||||
use crate::peer::PromotionResult;
|
||||
use crate::proto::fmp::PromotionResult;
|
||||
|
||||
let mut node = make_node();
|
||||
let transport_id = TransportId::new(1);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
use crate::nostr::{BootstrapEvent, NostrRendezvous};
|
||||
use crate::peer::PromotionResult;
|
||||
use crate::proto::fmp::PromotionResult;
|
||||
use crate::transport::udp::UdpTransport;
|
||||
use crate::transport::{TransportHandle, packet_channel};
|
||||
use std::sync::Arc;
|
||||
|
||||
+1
-60
@@ -59,66 +59,6 @@ pub enum PeerError {
|
||||
MaxPeersExceeded { max: usize },
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cross-Connection Handling
|
||||
// ============================================================================
|
||||
|
||||
/// Result of attempting to promote a connection to active peer.
|
||||
///
|
||||
/// When a handshake completes, we may discover that we already have a
|
||||
/// connection to this peer (cross-connection). The tie-breaker rule
|
||||
/// determines which connection survives.
|
||||
///
|
||||
/// Note: Returns NodeAddr instead of ActivePeer because ActivePeer cannot
|
||||
/// be cloned (it contains NoiseSession which has cryptographic state).
|
||||
/// Callers can look up the peer from the peers map using the NodeAddr.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PromotionResult {
|
||||
/// New peer created successfully.
|
||||
Promoted(NodeAddr),
|
||||
|
||||
/// Cross-connection detected. This connection lost the tie-breaker
|
||||
/// and should be closed.
|
||||
CrossConnectionLost {
|
||||
/// The link that won (existing connection).
|
||||
winner_link_id: LinkId,
|
||||
},
|
||||
|
||||
/// Cross-connection detected. This connection won the tie-breaker.
|
||||
/// The existing connection was replaced.
|
||||
CrossConnectionWon {
|
||||
/// The link that lost (previous connection, now closed).
|
||||
loser_link_id: LinkId,
|
||||
/// The node ID of the peer.
|
||||
node_addr: NodeAddr,
|
||||
},
|
||||
}
|
||||
|
||||
impl PromotionResult {
|
||||
/// Get the node ID if promotion succeeded.
|
||||
pub fn node_addr(&self) -> Option<NodeAddr> {
|
||||
match self {
|
||||
PromotionResult::Promoted(node_addr) => Some(*node_addr),
|
||||
PromotionResult::CrossConnectionWon { node_addr, .. } => Some(*node_addr),
|
||||
PromotionResult::CrossConnectionLost { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this connection should be closed.
|
||||
pub fn should_close_this_connection(&self) -> bool {
|
||||
matches!(self, PromotionResult::CrossConnectionLost { .. })
|
||||
}
|
||||
|
||||
/// Get the link that should be closed, if any.
|
||||
pub fn link_to_close(&self) -> Option<LinkId> {
|
||||
match self {
|
||||
PromotionResult::CrossConnectionLost { .. } => None, // Caller's link
|
||||
PromotionResult::CrossConnectionWon { loser_link_id, .. } => Some(*loser_link_id),
|
||||
PromotionResult::Promoted(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PeerSlot
|
||||
// ============================================================================
|
||||
@@ -240,6 +180,7 @@ impl fmt::Display for PeerSlot {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::proto::fmp::PromotionResult;
|
||||
use crate::transport::LinkId;
|
||||
use crate::{Identity, PeerIdentity};
|
||||
|
||||
|
||||
@@ -51,6 +51,62 @@ pub fn cross_connection_winner(
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of attempting to promote a connection to active peer.
|
||||
///
|
||||
/// When a handshake completes, we may discover that we already have a
|
||||
/// connection to this peer (cross-connection). The tie-breaker rule
|
||||
/// determines which connection survives.
|
||||
///
|
||||
/// Note: Returns NodeAddr instead of ActivePeer because ActivePeer cannot
|
||||
/// be cloned (it contains NoiseSession which has cryptographic state).
|
||||
/// Callers can look up the peer from the peers map using the NodeAddr.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PromotionResult {
|
||||
/// New peer created successfully.
|
||||
Promoted(NodeAddr),
|
||||
|
||||
/// Cross-connection detected. This connection lost the tie-breaker
|
||||
/// and should be closed.
|
||||
CrossConnectionLost {
|
||||
/// The link that won (existing connection).
|
||||
winner_link_id: LinkId,
|
||||
},
|
||||
|
||||
/// Cross-connection detected. This connection won the tie-breaker.
|
||||
/// The existing connection was replaced.
|
||||
CrossConnectionWon {
|
||||
/// The link that lost (previous connection, now closed).
|
||||
loser_link_id: LinkId,
|
||||
/// The node ID of the peer.
|
||||
node_addr: NodeAddr,
|
||||
},
|
||||
}
|
||||
|
||||
impl PromotionResult {
|
||||
/// Get the node ID if promotion succeeded.
|
||||
pub fn node_addr(&self) -> Option<NodeAddr> {
|
||||
match self {
|
||||
PromotionResult::Promoted(node_addr) => Some(*node_addr),
|
||||
PromotionResult::CrossConnectionWon { node_addr, .. } => Some(*node_addr),
|
||||
PromotionResult::CrossConnectionLost { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this connection should be closed.
|
||||
pub fn should_close_this_connection(&self) -> bool {
|
||||
matches!(self, PromotionResult::CrossConnectionLost { .. })
|
||||
}
|
||||
|
||||
/// Get the link that should be closed, if any.
|
||||
pub fn link_to_close(&self) -> Option<LinkId> {
|
||||
match self {
|
||||
PromotionResult::CrossConnectionLost { .. } => None, // Caller's link
|
||||
PromotionResult::CrossConnectionWon { loser_link_id, .. } => Some(*loser_link_id),
|
||||
PromotionResult::Promoted(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A snapshot of one handshake connection's lifecycle-relevant state, taken by
|
||||
/// the shell so the core decides without touching live `Node` state or reading
|
||||
/// a clock.
|
||||
|
||||
@@ -33,12 +33,12 @@ pub(crate) mod wire;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use core::cross_connection_winner;
|
||||
pub(crate) use core::{
|
||||
ConnAction, ConnSnapshot, EstablishSnapshot, EstablishView, InboundDecision, InboundReject,
|
||||
LifecycleView, OutboundDecision, OutboundSnapshot, PeerSnapshot, RekeyCfg, RekeyResendSnapshot,
|
||||
WireOutcome,
|
||||
};
|
||||
pub use core::{PromotionResult, cross_connection_winner};
|
||||
pub(crate) use limits::backoff_ms;
|
||||
pub use state::HandshakeState;
|
||||
pub(crate) use state::{ConnectionState, Fmp};
|
||||
|
||||
Reference in New Issue
Block a user