Skip to content

Latest commit

 

History

History
304 lines (202 loc) · 8.79 KB

File metadata and controls

304 lines (202 loc) · 8.79 KB

Protocol Compliance Features

This document describes the protocol compliance features implemented in the MQTT library with configurable strict validation.

Feature Flag: strict-protocol-compliance

The library includes a feature flag strict-protocol-compliance that enables additional MQTT 5.0 protocol compliance validations. This feature is enabled by default but can be disabled if needed.

Enabling/Disabling the Feature

# In Cargo.toml - enable by default (current behavior)
[features]
default = ["strict-protocol-compliance"]
strict-protocol-compliance = []

# To disable strict compliance
cargo build --no-default-features
cargo test --no-default-features

Implemented Validations

General Validations

UTF-8 String Validation

When strict-protocol-compliance is enabled, all UTF-8 strings are validated to ensure they comply with MQTT 5.0 specification:

  • Null characters (U+0000) are rejected
  • UTF-16 surrogate pairs (U+D800-U+DFFF) are rejected
  • BOM (Byte Order Mark, U+FEFF) at the beginning of strings is rejected

Error Messages:

  • "UTF-8 string contains null character (U+0000)"
  • "UTF-8 string contains surrogate character (U+XXXX)"
  • "UTF-8 string starts with BOM (U+FEFF)"

Variable Byte Integer (VBI) Validation

Non-minimal VBI encodings are detected and rejected. A VBI is considered non-minimal if it uses more bytes than necessary to represent a value.

Error Message:

  • "Variable Byte Integer encoding is not minimal"

CONNECT Packet Validation

Reserved Flag Validation

The reserved flag in Connect Flags must be 0.

Error Message:

  • "CONNECT packet reserved flag is not 0"

Will Flag Validation

When Will Flag is not set (0):

  • Will QoS must be 0
  • Will Retain must be 0

When Will Flag is set:

  • Will QoS cannot be 3 (invalid/malformed packet)

Error Messages:

  • "Will QoS must be 0 if Will Flag is 0"
  • "Will Retain must be 0 if Will Flag is 0"
  • "Will QoS cannot be 3"

CONNACK Packet Validation

Reserved Bits Validation

The Connect Acknowledge Flags byte must have all reserved bits set to 0.

Error Message:

  • "CONNACK Connect Acknowledge Flags reserved bits must be 0"

PUBLISH Packet Validation

QoS Validation

  • QoS level 3 (11 in binary) is invalid and rejected
  • DUP flag must be 0 for QoS 0 messages

Error Messages:

  • "PUBLISH QoS bits must not be set to 11 (invalid QoS 3)"
  • "PUBLISH DUP flag must be 0 for QoS 0 messages"

Topic Name Validation

Topic names in PUBLISH packets must not contain wildcard characters (# or +).

Error Message:

  • "PUBLISH Topic Name must not contain wildcard characters (# or +)"

SUBSCRIBE Packet Validation

Fixed Header Flags

SUBSCRIBE packets must have fixed header flags set to 0010 (bit 1 = 1, others = 0).

Error Message:

  • "SUBSCRIBE fixed header flags must be 0010"

Packet Identifier Validation

Packet identifier must be greater than 0.

Error Message:

  • "SUBSCRIBE packet_id must be > 0"

Payload Validation

The payload must contain at least one subscription.

Error Message:

  • "SUBSCRIBE payload must contain at least one subscription"

Subscription Options Validation

Reserved bits in Subscription Options must be 0.

Error Message:

  • "SUBSCRIBE Subscription Options reserved bits must be 0"

No Local Flag Validation

The No Local flag cannot be set on shared subscriptions (topics starting with $share/).

Error Message:

  • "SUBSCRIBE No Local flag must not be set on Shared Subscriptions"

Topic Filter Validation

Comprehensive validation of topic filter syntax including:

  • Empty topic filters are rejected
  • Multi-level wildcards (#) must be the only character in the level and the last level
  • Single-level wildcards (+) must be the only character in the level
  • Maximum length validation (65535 bytes)

Error Messages:

  • "Topic filter cannot be empty"
  • "Multi-level wildcard (#) must be the only character in topic level"
  • "Multi-level wildcard (#) must be the last level in topic filter"
  • "Single-level wildcard (+) must be the only character in topic level"

Shared Subscription Validation

Shared subscriptions must follow the format $share/ShareName/TopicFilter:

  • ShareName cannot be empty
  • TopicFilter cannot be empty
  • The TopicFilter part is validated according to normal topic filter rules

Error Messages:

  • "Invalid shared subscription format: must be $share/ShareName/TopicFilter"
  • "Shared subscription ShareName cannot be empty"
  • "Shared subscription TopicFilter cannot be empty"

SUBACK Packet Validation

Packet Identifier Validation

Packet identifier must be greater than 0.

Error Message:

  • "SUBACK packet_id must be > 0"

Payload Validation

The payload must contain at least one reason code.

Error Message:

  • "SUBACK payload must contain at least one reason code"

UNSUBSCRIBE Packet Validation

Fixed Header Flags

UNSUBSCRIBE packets must have fixed header flags set to 0010 (bit 1 = 1, others = 0).

Error Message:

  • "UNSUBSCRIBE fixed header flags must be 0010"

Packet Identifier Validation

Packet identifier must be greater than 0.

Error Message:

  • "UNSUBSCRIBE packet_id must be > 0"

Payload Validation

The payload must contain at least one topic filter.

Error Message:

  • "UNSUBSCRIBE payload must contain at least one topic filter"

UNSUBACK Packet Validation

Packet Identifier Validation

Packet identifier must be greater than 0.

Error Message:

  • "UNSUBACK packet_id must be > 0"

Payload Validation

The payload must contain at least one reason code.

Error Message:

  • "UNSUBACK payload must contain at least one reason code"

PUBREL Packet Validation

Fixed Header Flags

PUBREL packets must have fixed header flags set to 0010 (bit 1 = 1, others = 0).

Error Message:

  • "Invalid PUBREL flags: expected 0x02, got 0x{flags:02x}"

PINGREQ Packet Validation

Remaining Length Validation

PINGREQ packets must have remaining length of 0.

Error Message:

  • "PINGREQ packet must have remaining length of 0"

Fixed Header Flags

PINGREQ packets must have fixed header flags set to 0000 (all reserved bits = 0).

Error Message:

  • "PINGREQ packet has invalid fixed header flags"

PINGRESP Packet Validation

Remaining Length Validation

PINGRESP packets must have remaining length of 0.

Error Message:

  • "PINGRESP packet must have remaining length of 0"

Fixed Header Flags

PINGRESP packets must have fixed header flags set to 0000 (all reserved bits = 0).

Error Message:

  • "PINGRESP packet has invalid fixed header flags"

DISCONNECT Packet Validation

Fixed Header Flags

DISCONNECT packets must have fixed header flags set to 0000 (all reserved bits = 0).

Error Message:

  • "DISCONNECT packet has invalid fixed header flags"

AUTH Packet Validation

Fixed Header Flags

AUTH packets must have fixed header flags set to 0000 (all reserved bits = 0).

Error Message:

  • "AUTH packet has invalid fixed header flags"

Reason Code Requirement

AUTH packets with remaining length > 0 must contain a reason code.

Error Message:

  • "AUTH packet must contain a reason code"

Unimplemented Features

MQTTv5: 4.10: Request/Response

Using request/response in a pub/sub system is error-prone, use HTTP-based request/response instead.

Testing

The library includes comprehensive tests for all validation features:

# Run all tests with strict compliance (default)
cargo test

# Run all tests without strict compliance  
cargo test --no-default-features

# Run only protocol compliance tests
cargo test protocol_compliance_tests

Backward Compatibility

When strict-protocol-compliance is disabled, the library maintains backward compatibility and only performs basic validations that were already implemented. This ensures that existing code continues to work without changes.

When strict-protocol-compliance is enabled (default), the library provides maximum compliance with the MQTT 5.0 specification, which may reject some packets that were previously accepted.

Examples

use flowsdk::mqtt_serde::encode_utf8_string;

// With strict-protocol-compliance enabled (default):
let result = encode_utf8_string("hello\u{0000}world");
assert!(result.is_err()); // Rejected due to null character

// With strict-protocol-compliance disabled:
// The same string would be accepted (only length validation)
use flowsdk::mqtt_serde::mqttv5::subscribe::TopicSubscription;

// With strict-protocol-compliance enabled:
let result = TopicSubscription::from_bytes(b"$share/group/topic\x80"); // Invalid subscription options
assert!(result.is_err()); // Rejected due to reserved bits

// With strict-protocol-compliance disabled:
// Reserved bits validation is not performed