From c255e3f4a2c2250476bd1796b32f8dc0ea11478d Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Fri, 8 May 2026 14:58:53 +0000 Subject: [PATCH] session: drop dead SessionSetup/SessionAck variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both variants of SessionMessageType were never emitted anywhere in src/, and the production from_byte dispatch sites lacked Some-arms for them — any 0x00/0x01 byte that reached either dispatcher would log "Unknown..." and drop. The matching rustdoc tables described an Offset 0 msg_type byte that the encode() path has never written; the actual wire format is the FSP common prefix [ver_phase][flags][payload_len:2 LE] with body keyed by phase nibble, as documented in docs/reference/wire-formats.md. Drop the variants, drop their from_byte/to_byte/Display arms, fix the two stale rustdoc tables to describe the real wire shape, and trim the variant-iteration unit test that enumerated them. Zero on-wire behaviour change. --- src/protocol/session.rs | 78 +++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/protocol/session.rs b/src/protocol/session.rs index b5efa6e..6fa9465 100644 --- a/src/protocol/session.rs +++ b/src/protocol/session.rs @@ -16,15 +16,14 @@ use std::fmt; /// encrypted with session keys via the FSP pipeline. Error signals /// (CoordsRequired, PathBroken) are plaintext messages generated by transit /// routers that cannot establish e2e sessions with the source. +/// +/// Handshake messages (SessionSetup, SessionAck, SessionMsg3) are **not** +/// identified by a message-type byte; they are dispatched by the FSP phase +/// nibble in the common prefix (0x1, 0x2, 0x3 respectively). The 0x00-0x0F +/// range is therefore unallocated in this enum. #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(u8)] pub enum SessionMessageType { - // Session establishment (0x00-0x0F) - /// Session setup with coordinates (warms router caches). - SessionSetup = 0x00, - /// Session acknowledgement. - SessionAck = 0x01, - // Data and metrics (0x10-0x1F) — encrypted, inner header msg_type /// Port-multiplexed service payload: `[src_port:2 LE][dst_port:2 LE][service data...]`. /// Port 256 = IPv6 shim (compressed header). Receiver dispatches by dst_port. @@ -51,8 +50,6 @@ impl SessionMessageType { /// Try to convert from a byte. pub fn from_byte(b: u8) -> Option { match b { - 0x00 => Some(SessionMessageType::SessionSetup), - 0x01 => Some(SessionMessageType::SessionAck), 0x10 => Some(SessionMessageType::DataPacket), 0x11 => Some(SessionMessageType::SenderReport), 0x12 => Some(SessionMessageType::ReceiverReport), @@ -74,8 +71,6 @@ impl SessionMessageType { impl fmt::Display for SessionMessageType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let name = match self { - SessionMessageType::SessionSetup => "SessionSetup", - SessionMessageType::SessionAck => "SessionAck", SessionMessageType::DataPacket => "DataPacket", SessionMessageType::SenderReport => "SenderReport", SessionMessageType::ReceiverReport => "ReceiverReport", @@ -330,20 +325,29 @@ impl FspInnerFlags { /// /// Carried inside a SessionDatagram envelope which provides src_addr and /// dest_addr. The SessionSetup payload contains coordinates, session flags, -/// and the Noise IK handshake message for session establishment. +/// and the Noise XK handshake message for session establishment. +/// +/// SessionSetup, SessionAck, and SessionMsg3 are identified by the **phase** +/// field in the FSP common prefix (0x1, 0x2, 0x3), not by a message-type byte. +/// The `msg_type` field in the encrypted inner header applies only to +/// established-phase (0x0) messages. /// /// ## Wire Format /// -/// | Offset | Field | Size | Description | -/// |--------|------------------|---------|-------------------------------------| -/// | 0 | msg_type | 1 byte | 0x00 | -/// | 1 | flags | 1 byte | Bit 0: REQUEST_ACK, Bit 1: BIDIR | -/// | 2 | src_coords_count | 2 bytes | u16 LE, number of src coord entries | -/// | 4 | src_coords | 16 × n | NodeAddr array (self → root) | -/// | ... | dest_coords_count| 2 bytes | u16 LE, number of dest coord entries| -/// | ... | dest_coords | 16 × m | NodeAddr array (dest → root) | -/// | ... | handshake_len | 2 bytes | u16 LE, Noise payload length | -/// | ... | handshake_payload| variable| Noise IK msg1 (82 bytes typical) | +/// Encoded with FSP common prefix: `[ver_phase:1][flags:1][payload_len:2 LE][body]`, +/// where `ver_phase = 0x01` (version 0, phase MSG1) and `flags = 0` for handshake. +/// +/// **Body** (after 4-byte FSP prefix): +/// +/// | Offset | Field | Size | Description | +/// |--------|-------------------|------------|-----------------------------------------------------| +/// | 0 | flags | 1 byte | Bit 0: REQUEST_ACK, Bit 1: BIDIRECTIONAL | +/// | 1 | src_coords_count | 2 bytes LE | Number of source coordinate entries | +/// | 3 | src_coords | 16 × n | Source's ancestry (NodeAddr, self → root) | +/// | ... | dest_coords_count | 2 bytes LE | Number of dest coordinate entries | +/// | ... | dest_coords | 16 × m | Destination's ancestry | +/// | ... | handshake_len | 2 bytes LE | Noise payload length | +/// | ... | handshake_payload | variable | Noise XK msg1 (33 bytes — ephemeral key only) | #[derive(Clone, Debug)] pub struct SessionSetup { /// Source coordinates (for return path caching). @@ -456,20 +460,27 @@ impl SessionSetup { /// dest_addr. The SessionAck payload contains both the acknowledger's and /// initiator's coordinates for route cache warming (ensuring return-path /// transit nodes can route independently of the forward path) and the Noise -/// IK handshake response. +/// XK handshake response. +/// +/// SessionSetup, SessionAck, and SessionMsg3 are identified by the **phase** +/// field in the FSP common prefix (0x1, 0x2, 0x3), not by a message-type byte. /// /// ## Wire Format /// -/// | Offset | Field | Size | Description | -/// |--------|------------------|---------|-------------------------------------| -/// | 0 | msg_type | 1 byte | 0x01 | -/// | 1 | flags | 1 byte | Reserved | -/// | 2 | src_coords_count | 2 bytes | u16 LE | -/// | 4 | src_coords | 16 × n | Acknowledger's coords (for caching) | -/// | ... | dest_coords_count| 2 bytes | u16 LE | -/// | ... | dest_coords | 16 × m | Initiator's coords (for return path)| -/// | ... | handshake_len | 2 bytes | u16 LE, Noise payload length | -/// | ... | handshake_payload| variable| Noise IK msg2 (33 bytes typical) | +/// Encoded with FSP common prefix: `[ver_phase:1][flags:1][payload_len:2 LE][body]`, +/// where `ver_phase = 0x02` (version 0, phase MSG2) and `flags = 0` for handshake. +/// +/// **Body** (after 4-byte FSP prefix): +/// +/// | Offset | Field | Size | Description | +/// |--------|-------------------|------------|--------------------------------------------------------------| +/// | 0 | flags | 1 byte | Reserved | +/// | 1 | src_coords_count | 2 bytes LE | Number of acknowledger coordinate entries | +/// | 3 | src_coords | 16 × n | Acknowledger's ancestry (for cache warming) | +/// | ... | dest_coords_count | 2 bytes LE | Number of initiator coordinate entries | +/// | ... | dest_coords | 16 × m | Initiator's ancestry (for return-path cache warming) | +/// | ... | handshake_len | 2 bytes LE | Noise payload length | +/// | ... | handshake_payload | variable | Noise XK msg2 (57 bytes — ephemeral key + encrypted epoch) | #[derive(Clone, Debug)] pub struct SessionAck { /// Acknowledger's coordinates. @@ -1156,12 +1167,11 @@ mod tests { #[test] fn test_session_message_type_roundtrip() { let types = [ - SessionMessageType::SessionSetup, - SessionMessageType::SessionAck, SessionMessageType::DataPacket, SessionMessageType::SenderReport, SessionMessageType::ReceiverReport, SessionMessageType::PathMtuNotification, + SessionMessageType::CoordsWarmup, SessionMessageType::CoordsRequired, SessionMessageType::PathBroken, SessionMessageType::MtuExceeded,