eclipse / mosquitto

Eclipse Mosquitto - An open source MQTT broker
https://mosquitto.org
Other
8.93k stars 2.37k forks source link

Mosquitto Bridge is not receiving Retain flag from remote broker #2300

Open canique opened 3 years ago

canique commented 3 years ago

My mosquitto bridge (v2.0.11) is setup with TLSv1.3 and mqttv31 bridge protocol.

I have a topic setup as inbound+outbound, with QoS 1 and a remote-prefix. If I publish a message with QoS 1, and retain flag set on the remote broker (HiveMQ), it forwards the message to Mosquitto. The client connected to mosquitto sees the message - so far so good. But as soon as the client reconnects (with a new client ID, and new subscription), it does not receive the message although the message had its retain flag set.

Peculiarly enough, after a restart of Mosquitto the message that was missing is now sent to new clients.

The log file looks like this when sending the first publish msg with retain flag set via the remote broker:

1630690797: Received PUBLISH from local.xxx.cnq-gw1-br (d0, q1, r0, m1751, 'sensors/air/91/label', ... (12 bytes)) 1630690797: Sending PUBLISH to mqttjs_7b2f8909 (d0, q0, r0, m0, 'sensors/air/91/label', ... (12 bytes)) 1630690797: Sending PUBACK to local.xxx.cnq-gw1-br (m1751, rc0)

So, the retain flag seems to be 0 here...

After a restart of Mosquitto the log file looks like this.

1630690881: Received PUBLISH from local.xxx.cnq-gw1-br (d0, q1, r1, m56, 'sensors/air/91/label', ... (12 bytes)) 1630690883: Sending PUBLISH to local.xxx.cnq-gw1-br (d0, q1, r1, m64197, 'c32545675/sensors/air/91/label', ... (13 bytes)) 1630690883: Received PUBLISH from local.xxx.cnq-gw1-br (d0, q1, r0, m651, 'sensors/air/91/label', ... (13 bytes)) 1630690883: Sending PUBLISH to mqttjs_7b2f8909 (d0, q0, r1, m0, 'sensors/air/91/label', ... (12 bytes)) 1630690884: Sending PUBLISH to local.xxx.cnq-gw1-br (d0, q1, r1, m64240, 'c32545675/sensors/air/91/label', ... (13 bytes)) 1630690884: Received PUBLISH from local.xxx.cnq-gw1-br (d0, q1, r0, m1351, 'sensors/air/91/label', ... (13 bytes)) 1630690884: Sending PUBLISH to mqttjs_7b2f8909 (d0, q0, r0, m0, 'sensors/air/91/label', ... (13 bytes))

I think what's happening here is:

  1. Mosquitto receives a Publish again - this time with Retain flag set (because the bridge has opened a new connection to the remote broker).
  2. Mosquitto sends the publish back to the remote broker because the topic is also set to outbound
  3. Mosquitto receives once again a publish - this time without retain flag because the connection has not changed since step 1)
  4. like step 2) but it's not clear why Retain=1
  5. like step 3) Retain=0

So it's kind of a ping-pong (configuration issue). The interesting point is: Mosquitto initially does not get the incoming msg with retain flag set on a persistent bridge connection. Mosquitto is probably seen as a normal client to the remote broker. Normal clients get messages without the retain flag set, unless it's a new subscription.

Is there any configuration parameter that forces the retain flag to be set with MQTTv31? I'd love to use v5 but the bug @ https://github.com/eclipse/mosquitto/issues/2248 prevents me from doing so.

canique commented 3 years ago

The problem does not occur when bridge protocol v50 is used. The initial received publish has the retain flag set and there is no ping pong between Mosquitto and the remote broker.

ralight commented 3 years ago

Does HiveMQ definitely support the non-standard v3 bridge protocol, because if not then what should happen is that the bridge will initially try to connect with the bridge protocol, but when it fails will reconnect as a standard client. Connecting as a standard client means that the retain bit operates as normal. That is to say, the retained bit will only be set when a client receives messages that are "stale" - i.e. immediately on subscribe. Subsequent messages received are effectively straight from the client and are fresh, so the retained bit is not set. That matches the snippets of your logs. You would be able to see more clearly by looking at the initial bridge connection to the remote broker.