session: drop dead SessionSetup/SessionAck variants

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.
This commit is contained in:
Johnathan Corgan
2026-05-08 15:02:37 +00:00
parent f32bc83034
commit c255e3f4a2
+44 -34
View File
@@ -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<Self> {
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,