Skip to content

Will Delay Interval: a reconnect within the delay does not suppress the Will (MQTT-3.1.3-9) #154

Description

@fabracht

Severity: major (MQTT v5 conformance / spurious Will publication).

Spec: MQTT v5 §3.1.3.2.2 (Will Delay Interval): "If a new Network Connection to this Session is made before the Will Delay Interval has passed, the Server MUST NOT send the Will Message" [MQTT-3.1.3-9]. The Will is published when the Will Delay Interval elapses or the Session ends, whichever is first.

Current behavior: In crates/mqtt5/src/broker/client_handler/lifecycle.rs, publish_will_message handles a will_delay_interval > 0 by spawning a detached task that tokio::time::sleep(delay)s, re-authorizes, and then routes the Will unconditionally:

if delay > 0 {
    tokio::spawn(async move {
        tokio::time::sleep(Duration::from_secs(u64::from(delay))).await;
        // re-authorize, then route the will — no check that the client reconnected
        ...
    });
}

There is no cancellation handle and no check of whether the same client_id re-established the session during the delay window. So a client that drops abnormally and reconnects (resumes its session) before the Will Delay Interval elapses still has its Will published — a spurious Will. This is exactly the case Will Delay exists to prevent (flaky/mobile clients using a delay to avoid transient-disconnect Wills).

Proposed fix: Track pending delayed-Will tasks keyed by client_id (e.g. a JoinHandle map on the broker/router), and cancel/abort the pending task when a new connection resumes that session before the delay elapses — the resume point is register_session / handle_session. On a clean-start takeover the Will handling should follow the same rules (the prior session ends, so its Will fires per spec unless a delay is pending and the session is resumed). Add a test: connect with a will + delay N, drop abnormally, reconnect within N, assert the Will is never published; and a second test asserting it IS published if no reconnect occurs within N.

Found while reviewing the broker's connect/disconnect event + LWT + timeout paths.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions