diff --git a/README.md b/README.md index 75fa954..504ab56 100644 --- a/README.md +++ b/README.md @@ -219,8 +219,9 @@ LAN-gateway presence, route-pinning, QUIC datagram budget, TAP status/IP, broadcast frame flow, frame/datagram counters, and drops. The periodic diagnostics refresh the TAP unicast IP so DHCP results that arrive after bridging starts become visible in later status lines. Each snapshot also emits -short user-facing lines such as relay/gateway connection status, DHCP address -presence, and broadcast-flow confirmation when those signals are observed. +short user-facing lines such as relay/gateway connection status, relay-route +and TAP readiness warnings, DHCP address presence, and broadcast-flow +confirmation when those signals are observed. Relay lifecycle events are logged as they arrive, including gateway joins and peer leaves. The client remembers peer identities from join and catch-up events so later leave logs can identify a disconnected LAN gateway or client MAC when diff --git a/crates/lanparty-obs/src/lib.rs b/crates/lanparty-obs/src/lib.rs index 65d62b1..6678964 100644 --- a/crates/lanparty-obs/src/lib.rs +++ b/crates/lanparty-obs/src/lib.rs @@ -385,6 +385,25 @@ impl ClientDiagnostics { UserDiagnostic::new(UserDiagnosticLevel::Warning, "Waiting for LAN gateway") }); + if !self.relay.route_pinned() { + diagnostics.push(UserDiagnostic::new( + UserDiagnosticLevel::Warning, + "Relay route not pinned", + )); + } + + if !self.tap.adapter_found() { + diagnostics.push(UserDiagnostic::new( + UserDiagnosticLevel::Error, + "TAP adapter not found", + )); + } else if self.tap.ip().is_none() { + diagnostics.push(UserDiagnostic::new( + UserDiagnosticLevel::Warning, + "Waiting for TAP IP", + )); + } + if let Some(message) = tap_ip_user_message(self.tap.ip()) { diagnostics.push(UserDiagnostic::new(UserDiagnosticLevel::Info, message)); } @@ -597,10 +616,47 @@ mod tests { .iter() .map(UserDiagnostic::message) .collect::>(), - ["Relay not reachable", "Waiting for LAN gateway"] + [ + "Relay not reachable", + "Waiting for LAN gateway", + "Relay route not pinned", + "TAP adapter not found", + ] ); assert_eq!(user_diagnostics[0].level(), UserDiagnosticLevel::Error); assert_eq!(user_diagnostics[1].level(), UserDiagnosticLevel::Warning); + assert_eq!(user_diagnostics[2].level(), UserDiagnosticLevel::Warning); + assert_eq!(user_diagnostics[3].level(), UserDiagnosticLevel::Error); + } + + #[test] + fn reports_waiting_for_tap_ip_when_adapter_has_no_address() { + let diagnostics = ClientDiagnostics::new( + RelayDiagnostics::new(true, true, true), + QuicDiagnostics::new(true, Some(1400)), + TapDiagnostics::new( + true, + Some(MacAddr::new([0x02, 1, 2, 3, 4, 5])), + Some(1200), + None, + ), + TunnelStats::default(), + ); + + let user_diagnostics = diagnostics.user_diagnostics(); + + assert_eq!( + user_diagnostics + .iter() + .map(UserDiagnostic::message) + .collect::>(), + [ + "Connected to relay", + "Connected to LAN gateway", + "Waiting for TAP IP", + ] + ); + assert_eq!(user_diagnostics[2].level(), UserDiagnosticLevel::Warning); } #[test]