Skip to content

fix: enforce per-channel MQTT connection state guard - #6983

Open
wy471x wants to merge 2 commits into
apache:masterfrom
wy471x:fix_connection-state-guard-is-dead
Open

fix: enforce per-channel MQTT connection state guard#6983
wy471x wants to merge 2 commits into
apache:masterfrom
wy471x:fix_connection-state-guard-is-dead

Conversation

@wy471x

@wy471x wy471x commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Make sure that:

  • You have read the contribution guidelines.
  • You submit test cases (unit or integration tests) that back your changes.
  • Your local test passed ./mvnw clean install -Dmaven.javadoc.skip=true.

Summary

Changes:

  1. MessageType.java — connection state moved from a per-instance volatile boolean (dead: MqttFactory builds a fresh MessageType per inbound message, so the state set by Connect.connect() never propagated to other handlers) to a per-channel AttributeKey<Boolean>; isConnected(Channel) / setConnected(Channel, boolean) now read/write the channel attribute.
  2. Publish.java, Unsubscribe.java, PingReq.java — guards inverted to if (!isConnected(ctx.channel())); like Subscribe, the channel is now closed (FIRE_EXCEPTION_ON_FAILURE) instead of silently dropping the packet.
  3. Subscribe.java — inverted the dead if (isConnected()) guard.
  4. Connect.java — duplicate CONNECT on the same channel is rejected by closing the connection without sending a CONNACK ([MQTT-3.1.0-2]).

Test Cases:

  1. ConnectTest — migrated from Mockito mocks to a real EmbeddedChannel (per-channel attributes require a real channel); added duplicateConnectIsRejected (second CONNECT receives no CONNACK and closes the channel).
  2. PublishTest — added publishBeforeConnectClosesChannel and the end-to-end publishAfterConnectOnSameChannelIsAccepted (real Connect.connect() followed by Publish.publish() on the same channel).
  3. New PingReqTestpingReqBeforeConnectClosesChannel, pingReqAfterConnectSendsPingResp.
  4. New UnsubscribeTestunsubscribeBeforeConnectClosesChannel.

Verification

  • shenyu-protocol-mqtt module: 13 tests passed (ConnectTest 5, PublishTest 5, PingReqTest 2, UnsubscribeTest 1), JDK 21.
  • Checkstyle and RAT (license header) checks passed.

close #6638

…nnect operations and duplicate connect

Co-Authored-By: Claude <noreply@anthropic.com>
@wy471x wy471x changed the title [ISSUE #6638] fix: enforce per-channel MQTT connection state guard fix: enforce per-channel MQTT connection state guard Aug 24, 2026

@Aias00 Aias00 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The duplicate-CONNECT path looks like it needs cleanup before closing the channel. A successful first CONNECT registers the channel in , but this new early return only calls . I only see repository cleanup in the explicit DISCONNECT flow, and there does not appear to be centralized \ cleanup for MQTT channels, so a client that sends CONNECT twice can leave a closed channel referenced in . Could you remove the channel from \ before closing here, or add centralized channel-inactive cleanup for all server/client close paths?

@Aias00

Aias00 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Correction to my previous review comment, where inline code formatting was stripped by my local shell:

The duplicate-CONNECT path looks like it needs cleanup before closing the channel. A successful first CONNECT registers the channel in ChannelRepository, but this new early return only calls ctx.close(). I only see repository cleanup in the explicit DISCONNECT flow, and there does not appear to be centralized channelInactive cleanup for MQTT channels, so a client that sends CONNECT twice can leave a closed channel referenced in ChannelRepository. Could you remove the channel from ChannelRepository before closing here, or add centralized channel-inactive cleanup for all server/client close paths?

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.

[BUG] Connection-state guard is dead; unconnected clients can PUBLISH/SUBSCRIBE

2 participants