Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@phil-mitchell
Copy link
Contributor

The incoming mosquitto bridge connections add 128 to the protocol
version to indicate ras=true and nl=true.

Support for this was added in mqtt-packet with
mqttjs/mqtt-packet#106

Subscriptions from these connections will have ras=true and nl=true

When publishing to these connections, aedes will now
copy the Packet and set retain to false only if ras is not true.

Fixes #329

The incoming mosquitto bridge connections add 128 to the protocol
version to indicate ras=true and nl=true.

Support for this was added in mqtt-packet with
mqttjs/mqtt-packet#106

Subscriptions from these connections will have ras=true and nl=true

When publishing to these connections, aedes will now
copy the Packet and set retain to false only if ras is not true.
@coveralls
Copy link

coveralls commented Feb 23, 2021

Pull Request Test Coverage Report for Build 620166757

  • 19 of 19 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.008%) to 99.554%

Totals Coverage Status
Change from base Build 616989692: 0.008%
Covered Lines: 800
Relevant Lines: 801

💛 - Coveralls

}

function emitPacket (packet, done) {
packet.retain = false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? This is used to prevent other broker instances to store this packet again when it's emiitted

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this cannot be easily removed.

Copy link
Contributor Author

@phil-mitchell phil-mitchell Feb 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to keep the retain on the packet until we are able to check if "retain as published" (rap) is true. That's the whole point of the rap flag. The bridge protocol enables retain-as-published. I moved this into the subscription handler. What are the concerns with moving this into the subscription handler?

The tests are passing with my change, so if there is a problem with removing this line, it must not have been covered by the tests. I'm happy to make adjustments, but I'd like to know more about the concerns.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you link it to the block of code that replaces this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcollina this is what handlePacketSubscription in subscribe.js is doing. Instead of globally setting it to false for all subscriptions, it sets it to false only if the retain-as-published flag is not set on the subscription.

If clusters go through a different (untested?) path, then clearing the retain flag can happen on that path, or I could set up a different emitter for client subscriptions so that clusters always get the flag set to false while bridges and regular clients respect the rap flag.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should verify if this is still needed, e.g. if the packet gets stored multiple times when using a cluster.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only happens when a user sends a packet using broker.publish function. BTW I think that it could be safely removed by double checking the code, the 'worst' thing that could happen is some useless write to the db

Copy link
Contributor Author

@phil-mitchell phil-mitchell Feb 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had thought of the _stored idea, but wasn't sure whether it would cause other issues. In any case, it becomes the event listener's responsibility to not retain the packet if it's not supposed to. I guess that can be a breaking change for some custom code, so I understand it's a bit dangerous. But I don't see a good way to support bridge protocol (or, going forward, MQTT v5) without doing this.

As I've said, the tests pass, including some new ones I added, so how can I verify this concern?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I've said, the tests pass, including some new ones I added, so how can I verify this concern?

You should add a test where you do a broker subscribe followed by a broker publish to check if the received message has the retained flag cleared or not

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the test and, indeed, the retain flag was previously set to false and is now true. I've pushed a change with a proposed solution. The publish function now takes the rap parameter and applies the wrapper function that I had previously placed in subscription.js. This way all callers of subscribe have the retain-as-published functionality available to them but default to the standard behaviour of setting retain to false.

}

function emitPacket (packet, done) {
packet.retain = false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this cannot be easily removed.

README.md Outdated
## Bridge connections

Normally, when publishing a message, the `retain` flag is consumed by Aedes and
then set to `false` so that recipients of the message do not retain it as well.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not really correct, it is set to false because Aedes can be used in a cluster env, in such cases the mqemitter is used to share a message between different broker instances, the retain is set to false to prevent other instances to store it again

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robertsLando that's correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably also true, but my understanding of the MQTT spec is that the retain flag needs to be false when received through a subscribe.

http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

It MUST set the RETAIN flag to 0 when a PUBLISH Packet is sent to a Client because it matches an established subscription regardless of how the flag was set in the message it received [MQTT-3.3.1-9].

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all I would add this comment there, then sincerly I dunno what's the best way to continue as both seems to have a reson to be accepted. I see no reference on bridge retain handling on specs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bridge retain handling is outside of the standard, so the only spec about bridge retain handling is here: https://github.com/mqtt/mqtt.github.io/wiki/bridge_protocol

However, MQTT v5 does mention retain handling: https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html

The setting of the RETAIN flag in an Application Message forwarded by the Server from an established connection is controlled by the Retain As Published subscription option. Refer to section 3.8.3.1 for a definition of the Subscription Options.
· If the value of Retain As Published subscription option is set to 0, the Server MUST set the RETAIN flag to 0 when forwarding an Application Message regardless of how the RETAIN flag was set in the received PUBLISH packet [MQTT-3.3.1-12].
· If the value of Retain As Published subscription option is set to 1, the Server MUST set the RETAIN flag equal to the RETAIN flag in the received PUBLISH packet [MQTT-3.3.1-13].

phil-mitchell and others added 2 commits February 25, 2021 07:42
This allows all callers of subscribe to receive the retain flag
set to false unless explicitly requested by passing rap=true
Copy link
Collaborator

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can move the wrapper inside lib/handlers/subscribe instead.

@phil-mitchell
Copy link
Contributor Author

I think you can move the wrapper inside lib/handlers/subscribe instead.

To be clear, you'd like me to put it back the way it was, knowing the behaviour change to those who subscribe directly to the broker?

@mcollina
Copy link
Collaborator

To be clear, you'd like me to put it back the way it was, knowing the behaviour change to those who subscribe directly to the broker?

No, I didn't really understand why the function was moved out of subscribe.

@phil-mitchell
Copy link
Contributor Author

To be clear, you'd like me to put it back the way it was, knowing the behaviour change to those who subscribe directly to the broker?

No, I didn't really understand why the function was moved out of subscribe.

It was moved out because the broker subscribe doesn't go through lib/handlers/subscribe. So it was moved to share the functionality with broker subscribe.

@mcollina
Copy link
Collaborator

Why does the broker subscribe need it?

@phil-mitchell
Copy link
Contributor Author

Why does the broker subscribe need it?

@robertsLando said so?

@phil-mitchell
Copy link
Contributor Author

Why does the broker subscribe need it?

If broker.subscribe doesn't add this wrapper, then when I remove the retain = false from emitPacket the subscribers who call broker.subscribe have retain = true. There has been a long conversation with you and @robertsLando saying that would be a bad thing.

@phil-mitchell
Copy link
Contributor Author

Ultimately I don't care, but if you can give me consistent direction, I'll do it. Otherwise, I'll just use my fork of this repo the way it works for me.

@mcollina
Copy link
Collaborator

Why does the broker subscribe need it?

@robertsLando said so?

Multiple maintainers can have different view about the project, that's the good/bad side of having open governance.

To recap, I would recommend:

  • no modification in emitPacket
  • no modification in broker.subscribe

WDYT @robertsLando?

What will leave us with then? I'm sorry but you are probably more into this feature than me at this point - I'd need some guidance.

@robertsLando
Copy link
Member

To recap, I would recommend:
no modification in emitPacket
no modification in broker.subscribe

I agree with @mcollina expecially latest commit has introduced some complexity that makes the code hard to read. I think i may have explained wrong in my comment, my idea was to create a strict test for the packet.retain = false that you removed (as it seems was not covered as the tests works with and without it). I would revert b4ad77d (#584) except for the changes on readme that are ok

@phil-mitchell
Copy link
Contributor Author

Okay, so I guess I misinterpreted your request to add that test. You wanted me to test the new behaviour where retain is not set to false in broker.subscribe. I have reverted to the behaviour where retain is not modified in emitPacket.

@mcollina
Copy link
Collaborator

I think we keep misinterpreting ourselves (maybe it's the language).

  • no code changes in emitPacket, retain = false should be kept there.
  • no code changes in subscribe, there should be no automatic wrapping.

Is this doable while supporting the protocol?

@phil-mitchell
Copy link
Contributor Author

I think we keep misinterpreting ourselves (maybe it's the language).

  • no code changes in emitPacket, retain = false should be kept there.
  • no code changes in subscribe, there should be no automatic wrapping.

Is this doable while supporting the protocol?

If retain is false when it reaches subscriber.js (which subscribes to the event via broker.subscribe), then it is not possible to know what its value was in order to set it back to true. If we introduce another field in the Packet to indicate that it was retained, then we could use that, but that might have other side-effects.

Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry pressed the approve changes by error... From a code side it looks almost all good to me, @phil-mitchell I think that @mcollina would prefer to don't create the wrapping function in the doSubscribe function but to clear the retained flag in the client deliverQoS and deliver0 functions instead. This is the only missing thing right now I think?

@phil-mitchell
Copy link
Contributor Author

Sorry pressed the approve changes by error... From a code side it looks almost all good to me, @phil-mitchell I think that @mcollina would prefer to don't create the wrapping function in the doSubscribe function but to clear the retained flag in the client deliverQoS and deliver0 functions instead. This is the only missing thing right now I think?

I don't see where @mcollina requested that. Sorry, but I don't see how this is feasible unless we pass another parameter to these methods. The subscription coming out of mqtt-packet is the thing that knows about the rap flag, not the client.

Copy link
Collaborator

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I thought a bit more about this and I think this code is ok.

@robertsLando robertsLando changed the title feat(bridge): Support incoming mosquitto bridge connections feat(bridge): support incoming mosquitto bridge connections Mar 4, 2021
@robertsLando robertsLando merged commit 7c70ab4 into moscajs:master Mar 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] Bridge

4 participants