Skip to content

feat: dynamic connect/listen, relay promotion, stats counters#103

Merged
maxholman merged 8 commits intomainfrom
fix/uat-parity
Mar 22, 2026
Merged

feat: dynamic connect/listen, relay promotion, stats counters#103
maxholman merged 8 commits intomainfrom
fix/uat-parity

Conversation

@maxholman
Copy link
Copy Markdown
Contributor

Summary

  • Cumulative stats counters: total_connections and total_flows survive session close — UAT agents no longer report "stats broken". Also fixes packets_dropped missing from REST API/OpenAPI (interface parity).
  • Dynamic connect/listen/disconnect: NodeCommand channel from Handler to mode task with tokio::select! loops — peers can be added/removed at runtime via MCP/REST/REPL without restarting.
  • Exit→relay promotion: nodes started with --connect + --listen begin as exit and promote to relay when a second peer connects. Multi-hop topologies form organically.
  • Bench fixes: cross → native cargo for musl builds (container glibc too old for nightly toolchain); init.sh updated for --role flag.
  • Website fixes: Astro 6 content API migration; justfile module working-directory resolution.

How to verify

  • just check passes end to end (fmt, lint, build, test, smoke, resilience, website)
  • wallhack stats shows total_connections > 0 after traffic completes
  • wallhack connect <addr> / wallhack listen <addr> from MCP dynamically adds peers
  • Gateway with --connect + --listen starts as exit, promotes to relay on second peer

🤖 Generated with Claude Code

maxholman and others added 4 commits March 21, 2026 16:10
active_connections and active_flows are real-time gauges that return to 0
after sessions close. Every UAT agent reports "stats broken" because they
check after traffic completes. Add monotonically increasing total_*
counters alongside the existing gauges.

Also adds packets_dropped to the REST API and OpenAPI spec — it was
already present in proto, CLI, and MCP but missing from REST (interface
parity violation).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MCP/REST/REPL users can now dynamically connect, listen, and disconnect
without restarting the daemon. A NodeCommand channel from Handler to the
mode task feeds a tokio::select! loop in auto mode.

When both --connect and --listen are specified, the node starts as exit
and promotes to relay when the listener accepts a second peer — multi-hop
topologies form organically without pre-declaring relay mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cross build fails inside its Ubuntu 20.04 container because the nightly
toolchain's build scripts need glibc 2.32+. Since musl is installed
natively, use cargo directly.

Bench init.sh used removed positional subcommands (wallhack daemon entry)
instead of the unified --role flag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justfile module set working-directory to "website" which resolved to
website/website/ when loaded as a module, breaking shell resolution.

Content config was in the Astro 5 location (src/content/config.ts)
with no loader — Astro 6 requires src/content.config.ts with a glob
loader. Pages used removed .slug and .render() APIs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the dedicated mpsc channel (cmd_tx/cmd_rx) between Handler and
mode task with a command queue on SharedNodeState — which is already
threaded to both sides. Zero new fields in Handler or NodeResources.

Add From<Metrics> for proto StatsResponse and Display for StatsResponse
so IPC dispatch and MCP output use traits instead of field-by-field
mapping. Add From<proto::StatsResponse> for the REST StatsResponse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the separate hint watch channel and command queue with a single
mpsc channel carrying NodeCommand (Role, Connect, Listen, Disconnect).
Eliminates the Mutex<VecDeque> + Notify on SharedNodeState and the
watch<Option<RoleHint>> — one channel handles all Handler→mode-task
communication.

Add From<Metrics> for proto StatsResponse and Display for StatsResponse
so IPC dispatch and MCP output use traits instead of field-by-field
mapping. Add From<proto::StatsResponse> for the REST StatsResponse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
maxholman and others added 2 commits March 21, 2026 21:17
- Add AutoContext struct bundling shared state (global, cfg, metrics,
  peers, routes, route_updates_tx, node_state, tun_capable); all
  internal auto-mode functions now take Arc<AutoContext> instead of
  8-11 individual arguments

- Extract spawn_source_to_peer_bidi_bridge and
  spawn_peer_announcement_forwarder from relay.rs as pub(crate)
  non-generic helpers operating on erased types; auto.rs uses these
  instead of copy-pasted inline blocks

- Remove dead route_updates receiver parameter from auto::run; callers
  obtain fresh receivers via ctx.route_updates_tx.subscribe()

- Remove #[allow(clippy::too_many_arguments)] suppressions where fixed

Net: -298 lines across three files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aligns channel names with the NodeCommand type they carry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@maxholman maxholman merged commit 37f4d18 into main Mar 22, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant