From 434b9726aa4e2f4d2d136cbb9a80162cd004f816 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sun, 12 Jul 2026 19:22:08 +0000 Subject: [PATCH] node: establish dataplane/ and session/ concept homes (behavior-neutral) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganize the node module tree by concept rather than by message-handling verb, as the first step of the node runtime decomposition. Pure relocation: no wire, config, metric, or log semantics change; the lib test count is unchanged (1577 passed). Moves (git mv, 100% rename similarity): - handlers/{forwarding,rx_loop,connected_udp,dispatch,encrypted}.rs -> node/dataplane/ — the whole RX hot path (the select! run loop, transit/local forwarding, the link-message router, the RX decrypt path with responder K-bit cutover + roam writes, and connected-UDP fast-path activation) now lives in one home. - node/session.rs -> node/session/mod.rs — establishes the session concept home for the data/state types. The message-behavior file handlers/session.rs stays put for now (folds in with the later FSP session step). The IK/XX-divergent establishment files (handlers/{handshake,rekey, timeout}.rs) and the deferred-home files (handlers/{mmp,lookup}.rs) deliberately stay in handlers/, to move once rather than twice. Every module is reached through impl Node methods, so no call site or re-export shim was needed. Updated in lockstep with the moves: the module_path!-derived tracing targets in the two mesh-lab compose-trace overlays, a structural test's include_str! source path, doc-comments in proto/routing and the mesh-lab docs, and the stale source-location citations (node/handlers/{forwarding,rx_loop,encrypted}.rs and node/session.rs) in doc-comments and the discovery design doc. --- docs/design/fips-nostr-discovery.md | 2 +- src/control/queries.rs | 4 ++-- src/node/{handlers => dataplane}/connected_udp.rs | 0 src/node/{handlers => dataplane}/dispatch.rs | 0 src/node/{handlers => dataplane}/encrypted.rs | 0 src/node/{handlers => dataplane}/forwarding.rs | 0 src/node/dataplane/mod.rs | 15 +++++++++++++++ src/node/{handlers => dataplane}/rx_loop.rs | 0 src/node/handlers/mod.rs | 8 +------- src/node/mod.rs | 1 + src/node/reject.rs | 2 +- src/node/{session.rs => session/mod.rs} | 0 src/node/tests/decrypt_failure.rs | 4 ++-- src/node/tests/handshake.rs | 2 +- src/peer/active.rs | 2 +- src/proto/routing/core.rs | 2 +- src/proto/routing/mod.rs | 2 +- testing/mesh-lab/README.md | 2 +- testing/mesh-lab/compose-trace-nat.yml | 4 ++-- testing/mesh-lab/compose-trace.yml | 6 +++--- testing/mesh-lab/run-loop.sh | 2 +- 21 files changed, 34 insertions(+), 24 deletions(-) rename src/node/{handlers => dataplane}/connected_udp.rs (100%) rename src/node/{handlers => dataplane}/dispatch.rs (100%) rename src/node/{handlers => dataplane}/encrypted.rs (100%) rename src/node/{handlers => dataplane}/forwarding.rs (100%) create mode 100644 src/node/dataplane/mod.rs rename src/node/{handlers => dataplane}/rx_loop.rs (100%) rename src/node/{session.rs => session/mod.rs} (100%) diff --git a/docs/design/fips-nostr-discovery.md b/docs/design/fips-nostr-discovery.md index 43fe572..5b7c93f 100644 --- a/docs/design/fips-nostr-discovery.md +++ b/docs/design/fips-nostr-discovery.md @@ -477,7 +477,7 @@ The TXT record carries three keys (`src/discovery/lan/mod.rs:47-55`): Once per node tick, the node drains browser events and acts on them in `poll_lan_discovery()` (`src/node/lifecycle.rs:907`, called from -`src/node/handlers/rx_loop.rs:266`). For each discovered peer it finds +`src/node/dataplane/rx_loop.rs:266`). For each discovered peer it finds a UDP transport whose family matches the peer address, parses the `npub` into a `PeerIdentity`, skips peers it is already connected to or currently connecting to, and otherwise initiates a connection. diff --git a/src/control/queries.rs b/src/control/queries.rs index 1c796e2..fd1d6d3 100644 --- a/src/control/queries.rs +++ b/src/control/queries.rs @@ -2767,12 +2767,12 @@ mod tests { /// Structural confirmation that the rx_loop no longer dispatches `show_*`: /// the rx_loop source carries no `queries::dispatch` call and no /// `starts_with("show_")` routing branch. Reads the committed source of - /// `src/node/handlers/rx_loop.rs` and asserts both markers are absent. This + /// `src/node/dataplane/rx_loop.rs` and asserts both markers are absent. This /// is the milestone's "remove `show_*` from the data-plane dispatch path" /// invariant, guarded against regression. #[test] fn rx_loop_has_no_show_dispatch() { - let src = include_str!("../node/handlers/rx_loop.rs"); + let src = include_str!("../node/dataplane/rx_loop.rs"); assert!( !src.contains("queries::dispatch"), "rx_loop must not call queries::dispatch (show_* served off-loop)" diff --git a/src/node/handlers/connected_udp.rs b/src/node/dataplane/connected_udp.rs similarity index 100% rename from src/node/handlers/connected_udp.rs rename to src/node/dataplane/connected_udp.rs diff --git a/src/node/handlers/dispatch.rs b/src/node/dataplane/dispatch.rs similarity index 100% rename from src/node/handlers/dispatch.rs rename to src/node/dataplane/dispatch.rs diff --git a/src/node/handlers/encrypted.rs b/src/node/dataplane/encrypted.rs similarity index 100% rename from src/node/handlers/encrypted.rs rename to src/node/dataplane/encrypted.rs diff --git a/src/node/handlers/forwarding.rs b/src/node/dataplane/forwarding.rs similarity index 100% rename from src/node/handlers/forwarding.rs rename to src/node/dataplane/forwarding.rs diff --git a/src/node/dataplane/mod.rs b/src/node/dataplane/mod.rs new file mode 100644 index 0000000..48ec010 --- /dev/null +++ b/src/node/dataplane/mod.rs @@ -0,0 +1,15 @@ +//! Data plane: the RX `select!` loop and the per-packet forwarding path. +//! +//! Holds the whole hot path in one home: the `select!` run loop +//! (`rx_loop`), transit/local datagram forwarding (`forwarding`), the +//! link-message router (`dispatch`), the RX decrypt path including responder +//! K-bit cutover and address-roam writes (`encrypted`), and the per-peer +//! connected-UDP fast-path socket activation (`connected_udp`). Each module +//! contributes `impl Node` methods driven by the run loop. + +#[cfg(unix)] +pub(crate) mod connected_udp; +mod dispatch; +mod encrypted; +mod forwarding; +mod rx_loop; diff --git a/src/node/handlers/rx_loop.rs b/src/node/dataplane/rx_loop.rs similarity index 100% rename from src/node/handlers/rx_loop.rs rename to src/node/dataplane/rx_loop.rs diff --git a/src/node/handlers/mod.rs b/src/node/handlers/mod.rs index 8bcc757..3affc11 100644 --- a/src/node/handlers/mod.rs +++ b/src/node/handlers/mod.rs @@ -1,14 +1,8 @@ -//! RX event loop and message handlers. +//! Message handlers: per-message-type behavior on `impl Node`. -#[cfg(unix)] -pub(crate) mod connected_udp; -mod dispatch; -mod encrypted; -mod forwarding; mod handshake; pub(crate) mod lookup; mod mmp; mod rekey; -mod rx_loop; pub(in crate::node) mod session; mod timeout; diff --git a/src/node/mod.rs b/src/node/mod.rs index 86ea375..03ee49b 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -7,6 +7,7 @@ pub(crate) mod acl; mod bloom; pub(crate) mod context; +mod dataplane; #[cfg(unix)] pub(crate) mod decrypt_worker; #[cfg(unix)] diff --git a/src/node/reject.rs b/src/node/reject.rs index cac5ad0..46a6f74 100644 --- a/src/node/reject.rs +++ b/src/node/reject.rs @@ -222,7 +222,7 @@ pub enum MmpReject { /// Forwarding-path rejection reasons. /// /// Each variant corresponds to a silent-rejection path in -/// `src/node/handlers/forwarding.rs::handle_session_datagram`. Matching +/// `src/node/dataplane/forwarding.rs::handle_session_datagram`. Matching /// `ForwardingStats` counters already track packets and bytes for each /// outcome; `record_reject` mirrors the packet-count side of the bump /// for parity with the other rejection clusters. diff --git a/src/node/session.rs b/src/node/session/mod.rs similarity index 100% rename from src/node/session.rs rename to src/node/session/mod.rs diff --git a/src/node/tests/decrypt_failure.rs b/src/node/tests/decrypt_failure.rs index 6da703d..8509339 100644 --- a/src/node/tests/decrypt_failure.rs +++ b/src/node/tests/decrypt_failure.rs @@ -1,6 +1,6 @@ //! Tests for the consecutive-decrypt-failure threshold force-removal path. //! -//! Covers `Node::handle_decrypt_failure` (in `node/handlers/encrypted.rs`), +//! Covers `Node::handle_decrypt_failure` (in `node/dataplane/encrypted.rs`), //! which increments `ActivePeer::increment_decrypt_failures` on each AEAD //! verification failure and force-removes the peer once //! `DECRYPT_FAILURE_THRESHOLD` consecutive failures are observed. The @@ -18,7 +18,7 @@ use super::*; /// the full `peers_by_index` cleanup path (not just the bare `peers` table). #[test] fn test_decrypt_failure_threshold_removes_peer() { - // Threshold constant in node/handlers/encrypted.rs (kept in sync with + // Threshold constant in node/dataplane/encrypted.rs (kept in sync with // production code; see DECRYPT_FAILURE_THRESHOLD). const THRESHOLD: u32 = 20; diff --git a/src/node/tests/handshake.rs b/src/node/tests/handshake.rs index c7f0197..2f2e088 100644 --- a/src/node/tests/handshake.rs +++ b/src/node/tests/handshake.rs @@ -1072,7 +1072,7 @@ async fn test_should_admit_msg1_admits_rekey_when_udp_accept_off() { /// /// The carve-out predicate must also consult peer state by source /// address: `current_addr()` is updated from inbound encrypted-frame -/// source addrs (`handlers/encrypted.rs`), so an established peer can +/// source addrs (`dataplane/encrypted.rs`), so an established peer can /// be matched even when the addr_to_link key is hostname-form and the /// incoming addr is numeric. #[tokio::test] diff --git a/src/peer/active.rs b/src/peer/active.rs index 5c29c25..971150c 100644 --- a/src/peer/active.rs +++ b/src/peer/active.rs @@ -1529,7 +1529,7 @@ mod tests { // === FMP rekey cutover: authenticate-before-promote === // // IK-adapted analogue of the FSP trial-decrypt tests - // (node/session.rs `trial_decrypt_picks_pending_and_promotes` / + // (node/session/mod.rs `trial_decrypt_picks_pending_and_promotes` / // `trial_decrypt_failed_slot_leaves_replay_window_intact`). The FMP // cutover is gated on an authenticated decrypt against `pending`, not // the bare header K-bit. These tests exercise that primitive: diff --git a/src/proto/routing/core.rs b/src/proto/routing/core.rs index 68b7db1..ce48bec 100644 --- a/src/proto/routing/core.rs +++ b/src/proto/routing/core.rs @@ -1,7 +1,7 @@ //! Sans-IO routing decision core. //! //! Pure, runtime-agnostic transit-forward decision for SessionDatagrams. The -//! async I/O adapter in `node::handlers::forwarding` decodes the wire bytes, +//! async I/O adapter in `node::dataplane::forwarding` decodes the wire bytes, //! pre-resolves the next hop, builds a [`RoutingView`] over live node state, //! calls [`Router::route`], and drives the returned [`RouteOutcome`] (the //! actual encrypted sends, metrics, and logging). No I/O, no clock, no diff --git a/src/proto/routing/mod.rs b/src/proto/routing/mod.rs index fd0df29..d8d9183 100644 --- a/src/proto/routing/mod.rs +++ b/src/proto/routing/mod.rs @@ -2,7 +2,7 @@ //! //! Pure, runtime-agnostic routing state and decision core, migrated out of //! the async node shell. The async I/O handlers remain in -//! `node::handlers::forwarding`. +//! `node::dataplane::forwarding`. //! //! - `core.rs` — the `RoutingView` read-seam trait, the `NextHop` / //! `RouteOutcome` types, `Router::route`, the pure transit-forward diff --git a/testing/mesh-lab/README.md b/testing/mesh-lab/README.md index 565911a..38b61bd 100644 --- a/testing/mesh-lab/README.md +++ b/testing/mesh-lab/README.md @@ -102,7 +102,7 @@ each rep does, set them in the invoking shell: `handshake`, `forwarding`, `session`, `encrypted`, `mmp` (via `compose-trace.yml`). - nat-lan — `discovery::nostr`, `transport::udp`, - `node::lifecycle`, `handlers::handshake`, `handlers::forwarding` + `node::lifecycle`, `handlers::handshake`, `dataplane::forwarding` (via `compose-trace-nat.yml`, picked up by `testing/nat/scripts/nat-test.sh` through the `FIPS_NAT_EXTRA_COMPOSE` env-var hook). diff --git a/testing/mesh-lab/compose-trace-nat.yml b/testing/mesh-lab/compose-trace-nat.yml index 9c60921..4da307f 100644 --- a/testing/mesh-lab/compose-trace-nat.yml +++ b/testing/mesh-lab/compose-trace-nat.yml @@ -12,7 +12,7 @@ # cross-init tie-breaker # ("Ignoring established NAT # traversal..." emits here) -# - fips::node::handlers::forwarding — transit/local datagram routing +# - fips::node::dataplane::forwarding — transit/local datagram routing # (catches drops post-adoption) # # Other modules stay at info to keep log volume manageable. The base @@ -33,7 +33,7 @@ # is set and the suite is nat-lan. x-trace-rust-log: &trace-rust-log - RUST_LOG: "info,fips::nostr=trace,fips::transport::udp=trace,fips::node::lifecycle=trace,fips::node::handlers::handshake=trace,fips::node::handlers::forwarding=trace" + RUST_LOG: "info,fips::nostr=trace,fips::transport::udp=trace,fips::node::lifecycle=trace,fips::node::handlers::handshake=trace,fips::node::dataplane::forwarding=trace" services: lan-a: diff --git a/testing/mesh-lab/compose-trace.yml b/testing/mesh-lab/compose-trace.yml index e9bc450..feb0f7a 100644 --- a/testing/mesh-lab/compose-trace.yml +++ b/testing/mesh-lab/compose-trace.yml @@ -4,10 +4,10 @@ # - fips::node::handlers::rekey — FMP/FSP rekey state machine # - fips::node::handlers::handshake — Noise handshake (cross-init, # dual-init, msg1/2/3 dispatch) -# - fips::node::handlers::forwarding — transit datagram forwarding, +# - fips::node::dataplane::forwarding — transit datagram forwarding, # route lookup, drops # - fips::node::handlers::session — FSP K-bit cutover, drain -# - fips::node::handlers::encrypted — FMP K-bit flip detection +# - fips::node::dataplane::encrypted — FMP K-bit flip detection # - fips::node::handlers::mmp — link liveness, SRTT, ETX # # Other modules stay at info to keep log volume manageable. The base @@ -33,7 +33,7 @@ # environment variable FIPS_MESH_LAB_TRACE=1 is set. x-trace-rust-log: &trace-rust-log - RUST_LOG: "info,fips::node::handlers::rekey=trace,fips::node::handlers::handshake=trace,fips::node::handlers::forwarding=trace,fips::node::handlers::session=trace,fips::node::handlers::encrypted=trace,fips::node::handlers::mmp=trace" + RUST_LOG: "info,fips::node::handlers::rekey=trace,fips::node::handlers::handshake=trace,fips::node::dataplane::forwarding=trace,fips::node::handlers::session=trace,fips::node::dataplane::encrypted=trace,fips::node::handlers::mmp=trace" services: # rekey profile diff --git a/testing/mesh-lab/run-loop.sh b/testing/mesh-lab/run-loop.sh index 9fa9487..8118171 100755 --- a/testing/mesh-lab/run-loop.sh +++ b/testing/mesh-lab/run-loop.sh @@ -429,7 +429,7 @@ run_nat_lan() { # nat-test.sh at the nat-specific trace overlay via the # FIPS_NAT_EXTRA_COMPOSE env-var hook in nat-test.sh. The overlay # bumps RUST_LOG to trace on discovery::nostr, transport::udp, - # node::lifecycle, handlers::handshake, handlers::forwarding — + # node::lifecycle, handlers::handshake, dataplane::forwarding — # the modules covering the cross-init / adoption / handshake # path that the NAT-traversal flake exhibits. Path is repo-relative. local -a env_args=(FIPS_NAT_SKIP_FINAL_CLEANUP=1)