ntex-mqtt v9.3.0
-
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-service5.3,ntex-util4.5, andntex-io4.5. Use the unified io filter-pause state to suspend read and write timeouts.
ntex-mqtt v9.1.1
-
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 whenConnectAckreported them as not available, instead of closing the connection with a protocol error
ntex-mqtt v9.1.0
-
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::WrBackpressuremessages that wait behind pending control calls, a slow control handler kept the sink blocked after backpressure was released.Control::WrBackpressureno 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 ofOption<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::DisconnectandPacket::Authkeep 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()andstream_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 newSendPacketError::NotAllowederror -
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
Disconnectedwhen 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()andstream_at_least_onceget 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_receivelimits 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, and0disables its limit instead of blocking every packet -
v5: Receive Maximum counts
QoS 1andQoS 2PUBLISH 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 2publish ifsend_exactly_oncefuture 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()returnsUnexpectedRelease(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]
-
TopicFiltersupports 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 aSystemlevel, addTopicFilter::share_name() -
TopicFiltercreated from levels rejects a singleBlanklevel, 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
TopicFilterpanicking inDisplaywhen created without levels,TryFromrejects an empty list of levels andDeserializevalidates the levels likeTryFrom -
TopicFiltercreated from levels rejects levels that parsing never produces, an empty or/-containingNormallevel, aNormalfirst level starting with$and aSystemlevel 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()andis_chunk()are replaced byhas_more_chunks() -
Default
MqttServiceConfig::max_sizeis 256 KB instead of unlimited, the v5 server advertises it as Maximum Packet Size in CONNACK, useset_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_secif the client's keep-alive is 0 [MQTT-3.2.2-22], and close the connection after 1.2 times of the advertisedserver_keepalive_secinstead of exactly it, a not advertisedConnectAck::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 clientinto_inner()keeps the limits from the server's CONNACK -
codec: Accept a v5 Message Expiry Interval of 0,
PublishProperties::message_expiry_intervalandLastWill::message_expiry_intervalareOption<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::MaxSizeExceededreports 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