mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
peer: remove the dead PeerSlot enum and PeerConnection resend API
PeerSlot (and its entire impl surface) was referenced only by its own module tests and the lib.rs re-export; peer storage has always used the separate connections/peers maps. PeerConnection's resend_count/ next_resend_at_ms/record_resend delegations had no production callers: the live resend counter is machine-sourced (connection_resend_count reads the per-peer machine), and the FSP session layer uses SessionEntry's own methods. ConnectionState::next_resend_at_ms is now test-only (its remaining callers are the fmp state unit tests) and marked cfg(test). The PeerSlot unit tests go with the enum; test_resend_count_tracking is dropped because the delegation target's schedule arithmetic is already covered by the fmp resend_bookkeeping test.
This commit is contained in:
+1
-3
@@ -92,9 +92,7 @@ pub use cache::{CacheEntry, CacheError, CacheStats, CoordCache};
|
||||
pub use proto::fmp::{PromotionResult, cross_connection_winner};
|
||||
|
||||
// Re-export peer types
|
||||
pub use peer::{
|
||||
ActivePeer, ConnectivityState, HandshakeState, PeerConnection, PeerError, PeerSlot,
|
||||
};
|
||||
pub use peer::{ActivePeer, ConnectivityState, HandshakeState, PeerConnection, PeerError};
|
||||
|
||||
// Re-export node types
|
||||
pub use node::{Node, NodeError, NodeState, UpdatePeersOutcome};
|
||||
|
||||
@@ -819,8 +819,6 @@ async fn test_msg1_stored_for_resend() {
|
||||
|
||||
// Verify stored msg1 matches what was built
|
||||
assert_eq!(conn.handshake_msg1().unwrap(), &wire_msg1);
|
||||
assert_eq!(conn.resend_count(), 0);
|
||||
assert!(conn.next_resend_at_ms() > now_ms);
|
||||
}
|
||||
|
||||
/// Test that resend scheduling respects max_resends and backoff.
|
||||
@@ -993,31 +991,6 @@ fn test_msg2_stored_on_connection() {
|
||||
assert_eq!(conn.handshake_msg2().unwrap(), &msg2_bytes);
|
||||
}
|
||||
|
||||
/// Test that resend_count and next_resend_at_ms track correctly.
|
||||
#[test]
|
||||
fn test_resend_count_tracking() {
|
||||
let peer_identity = make_peer_identity();
|
||||
let mut conn = PeerConnection::outbound(LinkId::new(1), peer_identity, 1000);
|
||||
|
||||
assert_eq!(conn.resend_count(), 0);
|
||||
assert_eq!(conn.next_resend_at_ms(), 0);
|
||||
|
||||
// Simulate storing msg1 and scheduling first resend
|
||||
conn.set_handshake_msg1(vec![0x01], 2000);
|
||||
assert_eq!(conn.resend_count(), 0);
|
||||
assert_eq!(conn.next_resend_at_ms(), 2000);
|
||||
|
||||
// Record first resend
|
||||
conn.record_resend(4000); // next at 4000 (2s backoff)
|
||||
assert_eq!(conn.resend_count(), 1);
|
||||
assert_eq!(conn.next_resend_at_ms(), 4000);
|
||||
|
||||
// Record second resend
|
||||
conn.record_resend(8000); // next at 8000 (4s backoff)
|
||||
assert_eq!(conn.resend_count(), 2);
|
||||
assert_eq!(conn.next_resend_at_ms(), 8000);
|
||||
}
|
||||
|
||||
/// Test that duplicate msg2 is silently dropped when pending_outbound is already cleared.
|
||||
#[tokio::test]
|
||||
async fn test_duplicate_msg2_dropped() {
|
||||
|
||||
@@ -237,21 +237,6 @@ impl PeerConnection {
|
||||
self.state.handshake_msg2()
|
||||
}
|
||||
|
||||
/// Number of resends performed.
|
||||
pub fn resend_count(&self) -> u32 {
|
||||
self.state.resend_count()
|
||||
}
|
||||
|
||||
/// When the next resend is scheduled (Unix ms).
|
||||
pub fn next_resend_at_ms(&self) -> u64 {
|
||||
self.state.next_resend_at_ms()
|
||||
}
|
||||
|
||||
/// Record a resend and schedule the next one.
|
||||
pub fn record_resend(&mut self, next_resend_at_ms: u64) {
|
||||
self.state.record_resend(next_resend_at_ms);
|
||||
}
|
||||
|
||||
// === Noise Handshake Operations (shell: drives crypto, updates pure state) ===
|
||||
|
||||
/// Start the handshake as initiator and generate message 1.
|
||||
|
||||
-167
@@ -3,9 +3,6 @@
|
||||
//! Two-phase peer lifecycle:
|
||||
//! 1. **PeerConnection** - Handshake phase, before identity is verified
|
||||
//! 2. **ActivePeer** - Authenticated phase, after successful Noise handshake
|
||||
//!
|
||||
//! The PeerSlot enum represents either phase, enabling unified storage
|
||||
//! while maintaining type safety for phase-specific operations.
|
||||
|
||||
mod active;
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
@@ -18,7 +15,6 @@ pub use connection::{HandshakeState, PeerConnection};
|
||||
|
||||
use crate::NodeAddr;
|
||||
use crate::transport::LinkId;
|
||||
use std::fmt;
|
||||
use thiserror::Error;
|
||||
|
||||
// ============================================================================
|
||||
@@ -62,127 +58,12 @@ pub enum PeerError {
|
||||
MaxPeersExceeded { max: usize },
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// PeerSlot
|
||||
// ============================================================================
|
||||
|
||||
/// A slot in the peer table, representing either connection or active phase.
|
||||
#[derive(Debug)]
|
||||
pub enum PeerSlot {
|
||||
/// Connection in handshake phase.
|
||||
Connecting(Box<PeerConnection>),
|
||||
/// Authenticated peer.
|
||||
Active(Box<ActivePeer>),
|
||||
}
|
||||
|
||||
impl PeerSlot {
|
||||
/// Create a new connecting slot (outbound).
|
||||
pub fn outbound(conn: PeerConnection) -> Self {
|
||||
PeerSlot::Connecting(Box::new(conn))
|
||||
}
|
||||
|
||||
/// Create a new connecting slot (inbound).
|
||||
pub fn inbound(conn: PeerConnection) -> Self {
|
||||
PeerSlot::Connecting(Box::new(conn))
|
||||
}
|
||||
|
||||
/// Create a new active slot.
|
||||
pub fn active(peer: ActivePeer) -> Self {
|
||||
PeerSlot::Active(Box::new(peer))
|
||||
}
|
||||
|
||||
/// Check if this is a connecting slot.
|
||||
pub fn is_connecting(&self) -> bool {
|
||||
matches!(self, PeerSlot::Connecting(_))
|
||||
}
|
||||
|
||||
/// Check if this is an active slot.
|
||||
pub fn is_active(&self) -> bool {
|
||||
matches!(self, PeerSlot::Active(_))
|
||||
}
|
||||
|
||||
/// Get the link ID for this slot.
|
||||
pub fn link_id(&self) -> LinkId {
|
||||
match self {
|
||||
PeerSlot::Connecting(conn) => conn.link_id(),
|
||||
PeerSlot::Active(peer) => peer.link_id(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get as connection reference, if connecting.
|
||||
pub fn as_connection(&self) -> Option<&PeerConnection> {
|
||||
match self {
|
||||
PeerSlot::Connecting(conn) => Some(conn),
|
||||
PeerSlot::Active(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get as mutable connection reference, if connecting.
|
||||
pub fn as_connection_mut(&mut self) -> Option<&mut PeerConnection> {
|
||||
match self {
|
||||
PeerSlot::Connecting(conn) => Some(conn),
|
||||
PeerSlot::Active(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get as active peer reference, if active.
|
||||
pub fn as_active(&self) -> Option<&ActivePeer> {
|
||||
match self {
|
||||
PeerSlot::Active(peer) => Some(peer),
|
||||
PeerSlot::Connecting(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get as mutable active peer reference, if active.
|
||||
pub fn as_active_mut(&mut self) -> Option<&mut ActivePeer> {
|
||||
match self {
|
||||
PeerSlot::Active(peer) => Some(peer),
|
||||
PeerSlot::Connecting(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the known node_addr, if any.
|
||||
///
|
||||
/// For connections, this is the expected identity (may be None for inbound).
|
||||
/// For active peers, this is always known.
|
||||
pub fn node_addr(&self) -> Option<&NodeAddr> {
|
||||
match self {
|
||||
PeerSlot::Connecting(conn) => conn.expected_identity().map(|id| id.node_addr()),
|
||||
PeerSlot::Active(peer) => Some(peer.node_addr()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PeerSlot {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
PeerSlot::Connecting(conn) => {
|
||||
write!(
|
||||
f,
|
||||
"connecting(link={}, state={})",
|
||||
conn.link_id(),
|
||||
conn.handshake_state()
|
||||
)
|
||||
}
|
||||
PeerSlot::Active(peer) => {
|
||||
write!(
|
||||
f,
|
||||
"active(node={:?}, link={})",
|
||||
peer.node_addr(),
|
||||
peer.link_id()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Tests
|
||||
// ============================================================================
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::proto::fmp::PromotionResult;
|
||||
use crate::transport::LinkId;
|
||||
use crate::{Identity, PeerIdentity};
|
||||
@@ -192,32 +73,6 @@ mod tests {
|
||||
PeerIdentity::from_pubkey(identity.pubkey())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peer_slot_connecting() {
|
||||
let identity = make_peer_identity();
|
||||
let conn = PeerConnection::outbound(LinkId::new(1), identity, 1000);
|
||||
let slot = PeerSlot::Connecting(Box::new(conn));
|
||||
|
||||
assert!(slot.is_connecting());
|
||||
assert!(!slot.is_active());
|
||||
assert!(slot.as_connection().is_some());
|
||||
assert!(slot.as_active().is_none());
|
||||
assert_eq!(slot.link_id(), LinkId::new(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peer_slot_active() {
|
||||
let identity = make_peer_identity();
|
||||
let peer = ActivePeer::new(identity, LinkId::new(2), 2000);
|
||||
let slot = PeerSlot::Active(Box::new(peer));
|
||||
|
||||
assert!(!slot.is_connecting());
|
||||
assert!(slot.is_active());
|
||||
assert!(slot.as_connection().is_none());
|
||||
assert!(slot.as_active().is_some());
|
||||
assert_eq!(slot.link_id(), LinkId::new(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_promotion_result_promoted() {
|
||||
let identity = make_peer_identity();
|
||||
@@ -255,26 +110,4 @@ mod tests {
|
||||
assert!(!result.should_close_this_connection());
|
||||
assert_eq!(result.link_to_close(), Some(LinkId::new(1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peer_slot_node_addr() {
|
||||
// Outbound connection knows expected identity
|
||||
let identity = make_peer_identity();
|
||||
let expected_node_addr = *identity.node_addr();
|
||||
let conn = PeerConnection::outbound(LinkId::new(1), identity, 1000);
|
||||
let slot = PeerSlot::Connecting(Box::new(conn));
|
||||
assert_eq!(slot.node_addr(), Some(&expected_node_addr));
|
||||
|
||||
// Inbound connection doesn't know identity yet
|
||||
let conn_inbound = PeerConnection::inbound(LinkId::new(2), 2000);
|
||||
let slot_inbound = PeerSlot::Connecting(Box::new(conn_inbound));
|
||||
assert!(slot_inbound.node_addr().is_none());
|
||||
|
||||
// Active peer always knows identity
|
||||
let identity2 = make_peer_identity();
|
||||
let active_node_addr = *identity2.node_addr();
|
||||
let peer = ActivePeer::new(identity2, LinkId::new(3), 3000);
|
||||
let slot_active = PeerSlot::Active(Box::new(peer));
|
||||
assert_eq!(slot_active.node_addr(), Some(&active_node_addr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,6 +421,7 @@ impl ConnectionState {
|
||||
}
|
||||
|
||||
/// When the next resend is scheduled (Unix ms).
|
||||
#[cfg(test)]
|
||||
pub fn next_resend_at_ms(&self) -> u64 {
|
||||
self.next_resend_at_ms
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user