ntex-rs/ntex-mqtt
 Watch   
 Star   
 Fork   
2 days ago
ntex-mqtt

ntex-mqtt v9.3.1

Changes

  • Use optimized spawn_detached()
8 days ago
ntex-mqtt

ntex-mqtt v9.3.0

Changes

  • Reuse notification-invalidated readiness across MQTT packets and calls. Wire handshake, routing, publish, protocol-message, and connection-control services into the bind-time readiness graph. Custom mutable readiness must notify changes.

  • Replace the in-flight limiter's once-per-call readiness flag with an independent inner service cache. Preserve publish-slot ordering, ack/ping progress, and the size-limit exception until a streaming publish's handler completes.

  • Notify payload backpressure, terminal states, and receiver drops through a stable source shared by successive streams and every bound dispatcher.

  • Require ntex-service 5.3, ntex-util 4.5, and ntex-io 4.5. Use the unified io filter-pause state to suspend read and write timeouts.

22 days ago
ntex-mqtt

ntex-mqtt v9.2.1

Changes

  • InFlightService ignores the size limit until a streaming publish completes, the readiness check after the last payload chunk waited for the limit held by the publish
22 days ago
ntex-mqtt

ntex-mqtt v9.2.0

Changes

  • InFlightService checks readiness of the inner service once per call, the call skips the check if no call entered the service since its last readiness check and the call did not wait for a slot
24 days ago
ntex-mqtt

ntex-mqtt v9.1.1

Changes

  • Suspend keep-alive and frame read timers while the filter chain pauses reads, and the write timeout while it pauses writes, the peer is not charged for the pause

  • v5: Add MqttServiceConfig::set_check_subs_availability(), disabled check passes shared and wildcard subscriptions to the control service when ConnectAck reported them as not available, instead of closing the connection with a protocol error

25 days ago
ntex-mqtt

ntex-mqtt v9.1.0

Changes

  • A failed call during write backpressure stops the dispatcher, previously the stop waited until the peer read enough to release backpressure

  • v3, v5: Acks are matched by packet id, acks of different flows may arrive in any order (MQTT 3.1.1 and 5.0, 4.6). Previously an ack that did not match the oldest in-flight packet closed the connection with a protocol error. An ack of a packet id that is not in flight is a protocol error. On disconnect, the in-flight publishes are reported to the ack callback in no particular order

  • Sink uses the io write backpressure state directly, waiting publishes and payload chunks are released as soon as the write buffer drains. Previously the state was updated by Control::WrBackpressure messages that wait behind pending control calls, a slow control handler kept the sink blocked after backpressure was released. Control::WrBackpressure no longer changes sink readiness

  • v3: Woken sink waiters check send credit and write backpressure again, previously a packet sent without waiting could take the freed credit and the woken waiter exceeded the receive maximum. A larger receive maximum wakes waiters within the new credit only

  • Document read pause, handlers that await acks from the same peer can stall the connection while reading is paused

  • v3, v5: Publish service and publish middleware return Option<Packet> instead of Option<Encoded> (breaking), the response queue keeps packets, a queue slot is 32 bytes instead of 64 for v3. v5 queue keeps publish acks, other responses of ordered calls are boxed, a queue slot is 64 bytes instead of 200

  • v3, v5: Response of an unordered call that completes immediately is written right away, previously it waited for pending ordered calls when the response queue was not empty

  • v3, v5: Response queue releases its memory once it drains after a burst of more than 16 responses, previously it kept the capacity of the largest burst

  • v5: Packet::Disconnect and Packet::Auth keep boxed packets (breaking)

  • v5: AUTH responses are not ordered behind pending publish acks, MQTT orders publish acks only and allows other packets during re-authentication

  • v3, v5: send_at_most_once() and stream_at_most_once() are async (breaking), they wait for write backpressure to be released and for an outgoing streaming payload to complete, previously QoS 0 publishes ignored write backpressure and failed during streaming

  • v3, v5: Client closes the connection with DISCONNECT when PINGRESP is not received within the keep-alive interval, the interval starts once PINGREQ can be written

  • v3, v5: A QoS 2 PUBLISH with a packet id awaiting PUBREL is acked by PUBREC and is not delivered whether or not DUP is set, previously a PUBLISH without DUP was a protocol error

  • v3, v5: Publishes waiting for write backpressure behind a streaming publish payload are released once the payload is complete, previously they waited for the next ack

  • v3, v5: Server sink does not send SUBSCRIBE and UNSUBSCRIBE packets, these are client packets, the builders' send() returns the new SendPacketError::NotAllowed error

  • v3, v5: Client returns a protocol error for a payload chunk without a pending publish, such as the chunks of a rejected streaming publish, instead of panicking

  • v3, v5: Payload chunks do not keep response queue slots, previously each chunk received while the publish handler was pending kept a slot until the publish completed, filled the queue and paused reading

  • v3, v5: Payload of a streaming publish is read while the publish fills the response queue, previously reading paused and the publish handler waiting for the payload stalled the connection

  • v3, v5: Restore payload backpressure, reading pauses while the unread part of a streamed payload reaches max_payload_buffer_size, the connection is closed if the publish handler drops the payload before the stream ends. Previously the whole payload was buffered and the readiness error of a service waited for the payload handler

  • v3, v5: Payload chunk of a streaming publish that waits for write backpressure fails with Disconnected when the connection is closed, previously it waited forever

  • v5: Send credit released by an ack is reserved for the first waiting publish, waiting publishes, ready() and stream_at_least_once get the credit in the order of the calls, previously a new publish could take the credit of a woken one and the peer received more publishes than its Receive Maximum [MQTT-4.9.0-1]. is_ready() is false while publishes wait, a cancelled waiter passes the credit on and waiters fail on disconnect

  • v3: max_receive limits incoming PUBLISH packets only, publishes over the limit wait for a slot while acks, pings and other packets are still read, previously a publish handler that awaited the ack of its own publish deadlocked at the limit. The v3 client no longer blocks the payload chunks of a streaming publish, and 0 disables its limit instead of blocking every packet

  • v5: Receive Maximum counts QoS 1 and QoS 2 PUBLISH packets only, pending SUBSCRIBE and UNSUBSCRIBE packets no longer use send credit or cause a false 0x93 disconnect, and SUBSCRIBE/UNSUBSCRIBE wait for io write backpressure only (IoRef::write_ready())

  • v3: Round up 1.5 times of the client keep-alive, previously odd keep-alive values closed the connection early

  • v3, v5: Release QoS 2 publish if send_exactly_once future is dropped, previously PUBREL was never sent and the packet id and in-flight slot leaked

  • v3: Default protocol-message service no longer logs a "Subscribe is not supported" warning for every message, only unsupported messages are logged

  • v3, v5: Drop the payload chunks of a PUBLISH that is dropped after disconnect, previously the next chunk failed with an unexpected payload error

  • v5: Use DISCONNECT 0x94 (Topic Alias invalid) for a Topic Alias greater than the maximum and the error's reason code, 0x82 (Protocol Error), for invalid acks instead of 0x83 (MQTT 5.0, 3.3.2.3.4, 4.13.1)

  • v5: PUBREC with a reason code of 0x80 or greater ends the QoS 2 flow, PUBREL is not sent, the packet id is released and PublishReceived::release() returns UnexpectedRelease (MQTT 5.0, 4.3.3)

  • v3, v5: Several received QoS 2 publishes can be released at the same time, previously only the most recent PUBREC could be released and earlier ones never sent PUBREL

  • v3, v5: Close the connection with a protocol error when PUBREC or PUBCOMP does not match the type of the in-flight packet, previously publish and subscribe futures could panic

  • v5: Server closes the connection with DISCONNECT 0x9E or 0xA2 when a SUBSCRIBE contains a Shared or Wildcard Subscription that is not available in CONNACK (MQTT 5.0, 3.2.2.3.11, 3.2.2.3.13)

  • v5: Server rejects a QoS 0 PUBLISH with RETAIN set when retain is not available [MQTT-3.2.2-14], previously only QoS 1 and QoS 2 were checked

  • v3, v5: Server closes the connection on a second CONNECT [MQTT-3.1.0-2] and on CONNACK, SUBACK, UNSUBACK or PINGRESP from client, client closes the connection on CONNECT or a second CONNACK from server, control service is called with an unexpected packet protocol error, previously these packets were ignored

  • v3: Client handles a re-delivered PUBLISH (DUP) with a packet id in use instead of closing the connection, it is ignored until PUBACK [MQTT-4.3.2-2] or acked by PUBREC without delivery until PUBREL [MQTT-4.3.3-2], payload chunks of a not delivered PUBLISH are discarded

  • v5: Server and client handle a re-delivered PUBLISH (DUP) with a packet id in use, it is ignored until PUBACK [MQTT-4.3.2-5] or acked by PUBREC without delivery until PUBREL [MQTT-4.3.3-10]. Other packet id conflicts are answered by PUBREC for QoS 2 (server sent PUBACK) and payload chunks of a not delivered PUBLISH are discarded

  • v3, v5: Server default protocol service acknowledges PUBREL instead of closing the connection

  • v5: Server releases the packet id of a received QoS 2 PUBLISH after PUBCOMP [MQTT-4.3.3-12] or after PUBREC with an error reason code [MQTT-4.3.3-9], previously the id stayed in use and consumed receive maximum quota. PUBREL before PUBREC is a protocol violation

  • v5: Client acknowledges a received QoS 2 PUBLISH with PUBREC instead of PUBACK, the packet id stays in use until PUBCOMP [MQTT-4.3.3-10] or is released after PUBREC with an error reason code [MQTT-4.3.3-9], PUBREL before PUBREC is a protocol violation. ClientRouter::start_default() acknowledges PUBREL instead of closing the connection

  • v3: Client acknowledges a received QoS 2 PUBLISH with PUBREC instead of PUBACK, the packet id stays in use until PUBREL [MQTT-4.3.3-2], PUBREL before PUBREC is a protocol violation. ClientRouter::start_default() acknowledges PUBREL instead of closing the connection

  • v3: Server accepts a re-delivered PUBLISH (DUP) with a packet id in use instead of closing the connection, it is ignored until PUBACK [MQTT-4.3.2-2] or acked by PUBREC until PUBREL without delivery [MQTT-4.3.3-2], PUBREL before PUBREC is a protocol violation

  • v3: Reply with PUBCOMP to a PUBREL with an unknown packet id instead of closing the connection, PUBREL is re-sent after a session resumes [MQTT-4.4.0-1]

  • TopicFilter supports Shared Subscriptions $share/{ShareName}/{filter}, malformed ones are rejected [MQTT-4.8.2-1], [MQTT-4.8.2-2], matching uses the filter after the prefix, a $ first level of the filter is a System level, add TopicFilter::share_name()

  • TopicFilter created from levels rejects a single Blank level, an empty topic filter

  • Fix TopicFilter::matches_filter() matching a filter that starts with a $ level by a wildcard at the first level [MQTT-4.7.2-1]

  • Encoders reject SUBSCRIBE and UNSUBSCRIBE with malformed topic filters, misplaced wildcards [MQTT-4.7.1-*] and, for v5, malformed Shared Subscriptions [MQTT-4.8.2-1], [MQTT-4.8.2-2]

  • Client dispatchers reject PUBLISH with wildcards in the Topic Name [MQTT-3.3.2-2] and, for v5, in the Response Topic [MQTT-3.3.2-14]

  • Fix TopicFilter panicking in Display when created without levels, TryFrom rejects an empty list of levels and Deserialize validates the levels like TryFrom

  • TopicFilter created from levels rejects levels that parsing never produces, an empty or /-containing Normal level, a Normal first level starting with $ and a System level without $

  • Fix in-flight limits being skipped for the request after a PUBLISH with a complete payload or after the last payload chunk, SizedRequest::is_publish() and is_chunk() are replaced by has_more_chunks()

  • Default MqttServiceConfig::max_size is 256 KB instead of unlimited, the v5 server advertises it as Maximum Packet Size in CONNACK, use set_max_size(0) for no limit

  • v5: Reject a non-minimal Variable Byte Integer encoding [MQTT-1.5.5-1]

  • codec: Reject a QoS 0 PUBLISH with the DUP flag set [MQTT-3.3.1-2]

  • codec: Reject a CONNACK with Session Present set and a non-zero return code [MQTT-3.2.2-4] (v3), [MQTT-3.2.2-6] (v5)

  • v5: Send server_keepalive_sec if the client's keep-alive is 0 [MQTT-3.2.2-22], and close the connection after 1.2 times of the advertised server_keepalive_sec instead of exactly it, a not advertised ConnectAck::keep_alive() timeout is enforced as is

  • v5: Default keep-alive timeout is 1.2 times of the client's keep-alive rounded up

  • codec: v5 Codec::clone() copies the decode state and flags, the codec returned by client into_inner() keeps the limits from the server's CONNACK

  • codec: Accept a v5 Message Expiry Interval of 0, PublishProperties::message_expiry_interval and LastWill::message_expiry_interval are Option<u32>

  • Reject a CONNECT with an empty Will Topic or a Will Topic with wildcards, v5 server also rejects a Will Response Topic with wildcards and sends CONNACK 0x82 Protocol Error, v3 server closes the connection without CONNACK

  • codec: Check the v5 max inbound and outbound packet size against the total packet size, Codec::max_outbound_size() returns the configured size, DecodeError::MaxSizeExceeded reports the total packet size

  • codec: Fix limit underflow for v5 PUBACK, PUBREC, PUBREL, PUBCOMP and SUBACK with small max packet size

  • Reject a v5 PUBLISH from a client with a Subscription Identifier or a Response Topic with wildcards, reject a malformed ShareName and No Local on a Shared Subscription

  • codec: Clear Session Present in a CONNACK with a non-zero reason code

  • codec: Drop Session Expiry Interval from a v5 DISCONNECT sent by the server

  • codec: Require a v5 Authentication Method in AUTH and with CONNECT Authentication Data, encode AUTH Success without properties with a Remaining Length of 0

  • codec: Reject a v5 CONNACK Maximum QoS other than 0 or 1

  • codec: Reject a v5 CONNACK Maximum Packet Size of zero on decode and encode

  • codec: Reject encoding a v5 Shared Subscription with No Local set

  • codec: Reject encoding a v5 Response Topic with wildcard characters

  • codec: Check string and binary data lengths before encoding, packets with fields over 65,535 bytes fail without writing partial data

  • codec: Fail encoding subscription identifiers over 268,435,455 instead of panicking

  • v5: Send CONNACK 0x84 for an unsupported protocol level, v3 CONNACK 0x01 for MQTT 3.1.1 clients

  • codec: Reject publish packets with a header longer than the packet, reject encoding a publish with a payload bigger than its payload size

  • codec: Fail encoding packets over the protocol size limit instead of panicking

  • codec: Fail encoding packets while a publish payload is incomplete

  • Write acks, pings and other packets sent while a publish payload is streamed after the payload instead of failing with ExpectPayload

  • codec: Reserve at most 8kb of read buffer ahead for non-publish packets

  • codec: Reject SUBSCRIBE packets with reserved subscription options bits set

  • codec: Reject SUBSCRIBE and UNSUBSCRIBE packets without topic filters

  • codec: Reject CONNECT packets with invalid will or password flags

  • codec: Reject trailing bytes in CONNECT, CONNACK, PINGREQ, PINGRESP and DISCONNECT packets

  • codec: Reject PUBLISH packets with an empty topic name (v5: unless a topic alias is set)

  • codec: Enforce sender-side rules in the encoder: valid topic names in PUBLISH and Will, no DUP flag for QoS 0, non-empty topic filter lists, v3 password requires username and empty client id requires clean session

  • Fix sink being stuck in streaming state after a failed publish encode

  • codec: Reject strings containing the null character U+0000, on decode and encode

  • v3: Send CONNACK 0x01 for an unsupported protocol level and CONNACK 0x02 for an empty client id without clean session before closing the connection

  • Update to ntex-io 4.1, ntex-codec 2.0

  • Stop the dispatcher on clean peer eof while the service is not ready

  • Api docs fixes

  • Support IoConfig::write_timeout(), add MqttProtocolError::WriteTimeout

  • Limit dispatcher response queue, add MqttServiceConfig::set_max_queue()

  • Refactor dispatcher timers, frame read rate counts bytes consumed by the codec

  • Keep-alive and frame read rate timeouts apply to the whole streamed publish, not each payload chunk

  • v5: Send PacketIdentifierInUse publish acks in the order packets are received

  • Control service readiness pauses reading only, readiness errors shut down the service and io

  • Report the first service call error to the control service, later errors no longer overwrite it

  • Release write backpressure and stop the write timer once output is flushed, even if the service is not ready

  • Deliver write backpressure changes to the control service in order and before the stop message, write their responses, control errors shut down the dispatcher

  • Stop dispatcher on response encode errors in spawned service calls

  • Only publish acks keep the order of incoming packets, other responses are sent once ready, pending ones count towards max queue

  • Set default MqttServiceConfig connect timeout to 5 seconds

2026-09-14 18:05:10
ntex-mqtt

ntex-mqtt v9.0.0

Changes

  • Refactor state management

  • Update to ntex-service 5.0

2026-06-19 20:01:58
ntex-mqtt

ntex-mqtt v8.2.1

Changes

  • Fix keep-alive flag setting #253
2026-06-13 07:15:17
ntex-mqtt

ntex-mqtt v8.2.0

Changes

  • Fix tight loop when service is not ready and write back-pressure is enabled
2026-06-05 17:37:57
ntex-mqtt

ntex-mqtt v8.1.0

Changes

  • Allow to specify ConnectAckReason for failed v3 handshake