Hello,
Our team @AIS2Lab has been testing MQTT 5 conformance across broker
implementations, and we found
three behaviours in Apache Artemis 2.57.0 that we believe are specification
violations. Two of them
concern the Will Message and share a code path; the third is separate.
We do not have an ASF Jira account. The Jira signup page suggests raising
things on the project
mailing list first, so we are doing that. If you confirm these are bugs we
are happy to request an
account and file them, or someone with an account is welcome to file them
directly.
Every check below runs its arm and a control in the same execution against
the same broker, so a
silent result cannot be a blind spot in the test. Each was reproduced 3 out
of 3 runs with a fresh
Client Identifier and topic namespace, on a freshly started container.
1. The Will Message is not published after DISCONNECT with Reason Code 0x04
---------------------------------------------------------------------------
Section 3.14.2.1 defines Reason Code 0x04 as "Disconnect with Will
Message": the Client is
disconnecting and explicitly asks for the Will to be sent. Section 3.1.2.5
allows the Will to be
discarded only on a DISCONNECT with Reason Code 0x00.
abrupt close (TCP RST) : Will published after 0.0s <- correct,
and this is the control
DISCONNECT Reason Code 0x04 : Will NOT published
The abrupt-close arm is the control. It runs in the same execution against
the same watcher and the
same topic, which is what shows the broker does publish Wills and that the
test can see them.
2. A DISCONNECT with a reserved Reason Code is treated as a normal
disconnection
--------------------------------------------------------------------------------
A client connects with a Will and then sends four bytes: e0 02 ff 00, a
DISCONNECT with Reason
Code 0xFF. That code is not in the table of section 3.14.2.1, so by section
4.13 the packet is a
Malformed Packet and the Server is expected to close the connection with
DISCONNECT 0x81.
Section 3.1.2.5 again allows the Will to be deleted only on Reason Code
0x00.
--> DISCONNECT rc=0xff e0 02 ff 00
<-- nothing; the server closes without sending DISCONNECT 0x81
... 10 seconds of silence on the Will topic ...
So on either reading, whether the packet is rejected as malformed or
accepted as a DISCONNECT with
a non-zero Reason Code, the Will should still have been published.
To be explicit, since this is easy to misread: this is not a normal
DISCONNECT 0x00. A
DISCONNECT 0x00 correctly discards the Will and we are not reporting that.
We noticed ARTEMIS-6190, "MQTT Will message properties propagation", is
Resolved with fix version
2.58.0. It touches Will handling, so it may or may not cover these two
cases. We could not check:
2.57.0 is the newest released version, and there is no 2.58.0 image to test
against yet. If you
expect 6190 to cover them, we are glad to retest as soon as 2.58.0 ships
and report back.
3. A Message Expiry Interval deletes a QoS 2 exchange that already passed
PUBREC
--------------------------------------------------------------------------------
Section 3.3.2.3.3 applies the Message Expiry Interval to an Application
Message the Server is
holding. Once the receiver has answered PUBREC the delivery is under way
and what remains
outstanding is an acknowledgement, which section 4.4 [MQTT-4.4.0-1]
requires the Server to resend on
the resumed Session. Section 4.1 lists incomplete inbound QoS 2 exchanges
as Session State.
Two identities, identical except for the Message Expiry Interval, in the
same run: subscribe QoS 2
with Clean Start 0 and Session Expiry Interval 300, answer PUBREC, cut the
TCP connection, wait 12
seconds, reconnect Clean Start 0.
control, published with NO Message Expiry Interval : session_present=1
PUBREL resent = True
arm, Message Expiry Interval = 5 : session_present=1
PUBREL resent = False
The control recovers, so this is not a general [MQTT-4.4.0-1] problem. The
expiry is deleting an
exchange that had already started.
Note that ARTEMIS-6189, "QoS 1 & 2 message handling is not resilient", is
fixed in 2.56.0 and is
therefore already included in the version we tested. This is a different
path.
Environment
-----------
Apache Artemis 2.57.0, official image apache/artemis:2.57.0,
digest
sha256:c691a1fe64eeda556db8b550822caa6c50cd8088c70b38bc22c26cf2aa7312bb
ANONYMOUS_LOGIN=true, otherwise image defaults
Reached on the image's own MQTT acceptor, container port 1883
<acceptor name="mqtt">tcp://0.0.0.0:1883?...;protocols=MQTT</acceptor>
not the multi-protocol "artemis" acceptor on 61616
MQTT v5.0 over plain TCP, loopback only
Host: Ubuntu 22.04.5 LTS, kernel 5.15.0-191-generic, x86_64, Docker
Engine 29.4.3
Reproducers
-----------
We have two standalone programs for these, one for the Will cases and one
for the QoS 2 case. They
are Python 3, standard library only, no MQTT client library, so every byte
they send is visible in
the source, and they print every frame in both directions. Each exits 1
while the behaviour is
present and 0 once it is fixed, so they can be dropped into a regression
suite.
They are about 300 lines each, so we have not pasted them into this email.
Say the word and we will
send them inline, attach them, or put them in a Jira issue, whichever you
prefer.
Thanks for your time,
@AIS2Lab