diff --git a/crates/wzp-proto/src/error.rs b/crates/wzp-proto/src/error.rs index 0b006f0..45dc24d 100644 --- a/crates/wzp-proto/src/error.rs +++ b/crates/wzp-proto/src/error.rs @@ -53,6 +53,15 @@ pub enum TransportError { Timeout { ms: u64 }, #[error("io error: {0}")] Io(#[from] std::io::Error), + /// Parsed wire bytes successfully but the payload didn't + /// deserialize into a known `SignalMessage` variant. Usually + /// means the peer is running a newer build with a variant we + /// don't know yet. Callers should **log and continue** rather + /// than tearing down the connection, so that forward-compat + /// additions to `SignalMessage` don't silently kill old + /// clients/relays. + #[error("signal deserialize: {0}")] + Deserialize(String), #[error("internal transport error: {0}")] Internal(String), } diff --git a/crates/wzp-relay/src/main.rs b/crates/wzp-relay/src/main.rs index d37333b..f0b64da 100644 --- a/crates/wzp-relay/src/main.rs +++ b/crates/wzp-relay/src/main.rs @@ -1307,6 +1307,16 @@ async fn main() -> anyhow::Result<()> { info!(%addr, "signal connection closed"); break; } + Err(wzp_proto::TransportError::Deserialize(e)) => { + // Forward-compat: the peer sent a + // SignalMessage variant we don't know + // (newer client, newer federation peer). + // Log and continue — tearing down the + // connection on unknown variants would + // silently kill interop across minor + // protocol version bumps. + warn!(%addr, "signal deserialize (unknown variant?), continuing: {e}"); + } Err(e) => { warn!(%addr, "signal recv error: {e}"); break; diff --git a/crates/wzp-transport/src/reliable.rs b/crates/wzp-transport/src/reliable.rs index 0b088a7..61691f1 100644 --- a/crates/wzp-transport/src/reliable.rs +++ b/crates/wzp-transport/src/reliable.rs @@ -53,6 +53,13 @@ pub async fn recv_signal(recv: &mut quinn::RecvStream) -> Result { + // Forward-compat: the relay sent us a + // SignalMessage variant we don't know yet + // (older client against a newer relay). + // Log and keep the signal connection alive — + // otherwise direct-call registration would + // silently die on any protocol bump. + tracing::warn!(error = %e, "signal recv: unknown variant, continuing"); + } Err(e) => { tracing::warn!(error = %e, "signal recv error — breaking loop"); break;