mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-11 17:17:54 +00:00
Add a transport-agnostic seam for an embedding platform (e.g. an Android Wi-Fi Aware radio) to push "peer npub reachable at addr over transport T" events into a running node — the generalization of the UDP-only LAN mDNS drain. A process-global queue (fips::discovery::platform) is drained each tick by poll_platform_discovery, which selects the transport family-aware (an IPv6 target picks an IPv6 socket) and initiates a Noise IK handshake; the pushed npub is only a routing hint, the handshake authenticates. An event for an already-active peer starts an alternate-path handshake, and a Lost event closes the pooled connection.
106 lines
3.8 KiB
Rust
106 lines
3.8 KiB
Rust
//! Bootstrap handoff types.
|
|
//!
|
|
//! These types model the boundary between an external rendezvous/bootstrap
|
|
//! runtime and the core FIPS transport/handshake stack. The rendezvous side
|
|
//! owns Nostr/STUN/UDP hole punching; once a direct UDP path is established,
|
|
//! it hands the live socket and selected remote endpoint to FIPS so the
|
|
//! existing Noise/FMP transport path can take over.
|
|
|
|
pub mod lan;
|
|
pub mod nostr;
|
|
pub mod platform;
|
|
|
|
use crate::config::UdpConfig;
|
|
use crate::{NodeAddr, TransportId};
|
|
use std::net::{SocketAddr, UdpSocket};
|
|
|
|
/// Punch-probe magic ("NPTC", network byte order). First byte `0x4E`
|
|
/// collides with FMP's prefix-version high-nibble check, so the UDP
|
|
/// transport silently filters packets carrying this magic to keep
|
|
/// post-adoption handshake logs clean. Defined at the top-level
|
|
/// `discovery` module so the UDP filter and the nostr submodule's
|
|
/// punch sender share the same constant.
|
|
pub const PUNCH_MAGIC: u32 = 0x4E505443;
|
|
|
|
/// Punch-probe-ack magic ("NPTA", network byte order). Same filter as
|
|
/// [`PUNCH_MAGIC`].
|
|
pub const PUNCH_ACK_MAGIC: u32 = 0x4E505441;
|
|
|
|
/// Returns `true` if the first four bytes of `data` match a punch-probe or
|
|
/// punch-ack magic. Used by the UDP transport's receive loop to silently
|
|
/// drop stray probes that arrive on an adopted socket after the remote
|
|
/// peer's punch attempt has already timed out.
|
|
pub fn is_punch_packet(data: &[u8]) -> bool {
|
|
if data.len() < 4 {
|
|
return false;
|
|
}
|
|
let magic = u32::from_be_bytes([data[0], data[1], data[2], data[3]]);
|
|
magic == PUNCH_MAGIC || magic == PUNCH_ACK_MAGIC
|
|
}
|
|
|
|
/// Result of handing an established traversal session into FIPS.
|
|
#[derive(Debug, Clone)]
|
|
pub struct BootstrapHandoffResult {
|
|
/// Newly allocated transport ID used for the adopted UDP socket.
|
|
pub transport_id: TransportId,
|
|
/// Local socket address now owned by the FIPS UDP transport.
|
|
pub local_addr: SocketAddr,
|
|
/// Confirmed remote UDP endpoint selected by traversal.
|
|
pub remote_addr: SocketAddr,
|
|
/// Peer node address derived from the supplied peer identity.
|
|
pub peer_node_addr: NodeAddr,
|
|
/// Nostr session identifier used by the bootstrap runtime.
|
|
pub session_id: String,
|
|
}
|
|
|
|
/// Established UDP traversal ready to be handed into FIPS.
|
|
///
|
|
/// The socket must already be bound and must be the same socket used for the
|
|
/// traversal runtime's STUN and punch traffic so the NAT mapping is preserved.
|
|
#[derive(Debug)]
|
|
pub struct EstablishedTraversal {
|
|
/// Rendezvous session identifier for logging/correlation.
|
|
pub session_id: String,
|
|
/// Remote peer identity in `npub` form.
|
|
pub peer_npub: String,
|
|
/// The selected remote UDP endpoint to use for the FIPS handshake.
|
|
pub remote_addr: SocketAddr,
|
|
/// The live UDP socket carrying the established mapping.
|
|
pub socket: UdpSocket,
|
|
/// Optional name for the adopted UDP transport.
|
|
pub transport_name: Option<String>,
|
|
/// Optional UDP transport tuning overrides.
|
|
pub transport_config: Option<UdpConfig>,
|
|
}
|
|
|
|
impl EstablishedTraversal {
|
|
/// Construct an established traversal handoff.
|
|
pub fn new(
|
|
session_id: impl Into<String>,
|
|
peer_npub: impl Into<String>,
|
|
remote_addr: SocketAddr,
|
|
socket: UdpSocket,
|
|
) -> Self {
|
|
Self {
|
|
session_id: session_id.into(),
|
|
peer_npub: peer_npub.into(),
|
|
remote_addr,
|
|
socket,
|
|
transport_name: None,
|
|
transport_config: None,
|
|
}
|
|
}
|
|
|
|
/// Attach an explicit transport name to the adopted UDP transport.
|
|
pub fn with_transport_name(mut self, name: impl Into<String>) -> Self {
|
|
self.transport_name = Some(name.into());
|
|
self
|
|
}
|
|
|
|
/// Override UDP transport tuning for the adopted socket.
|
|
pub fn with_transport_config(mut self, config: UdpConfig) -> Self {
|
|
self.transport_config = Some(config);
|
|
self
|
|
}
|
|
}
|