feat(mesh): let one node hold several rooms - #23
Merged
Conversation
A host that gives each conversation its own room had to start a node per conversation. Node identity is per process, so all of those nodes present the SAME peer id from different ports, and a remote peer keeps one session per identity — it closes the rest on arrival and declines to dial the others at all. Measured across three clients over three days: 33,715 sessions, 32,330 of them dead inside one second (95%), sustained at 205 / 131 / 113 discarded Noise handshakes an hour, against only 6-8 distinct peers each. One identity was seen on 27 different ports within a single hour. A node is still born in one room and every room-less call still means that one, so nothing existing changes. It can now join more: Moss_JoinRoom / Moss_LeaveRoom Moss_SubscribeRoom / Moss_UnsubscribeRoom / Moss_PublishRoom The crypto is untouched — same derivation, same HMAC topic, same AEAD seal. What changed is which key is selected, and that never needs guessing: a wire topic is an HMAC, so delivery reads the room off the subscription that created it rather than trying keys. Rooms therefore stay isolated on one node, and a joined room is byte-identical to the same room owned outright, which is what keeps a consolidated client talking to every already-released one. A room that was never joined is refused (MOSS_ERR_NOT_IN_ROOM) rather than quietly falling back to the node's own — that fallback would publish where the intended peers are not listening and surface as lost messages much later. Four tests, each verified to fail when the key selection is reverted to single-room.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A host that gives each conversation its own room has to start a node per conversation. Node identity is per process, so every one of those nodes presents the same peer id from a different port. A remote peer keeps one session per identity: it closes the rest on arrival, and
connectPeerdeclines to dial the others at all because it already has that peer id connected.Measured over three days, mosh clients only:
95%+ of every session an active client opens dies inside a second, against only 6–8 distinct peers each. One identity appeared on 27 different ports inside a single hour. Those are full Noise handshakes — asymmetric crypto — thrown away.
What changed
A node is still born in one room, and every room-less call still means that room, so no existing behaviour moves. It can now join more:
Moss_JoinRoom/Moss_LeaveRoomMoss_SubscribeRoom/Moss_UnsubscribeRoom/Moss_PublishRoomThe crypto is untouched — same derivation, same HMAC topic, same AEAD seal. What changed is which key is selected. That never needs guessing: a wire topic is an HMAC, so delivery reads the room off the subscription that created the topic instead of trying keys.
A room that was never joined is refused with
MOSS_ERR_NOT_IN_ROOMrather than falling back to the node's own room — the fallback would publish where the intended peers are not listening and surface as lost messages hours later.Compatibility
TestJoinedRoomIsWireIdenticalToOwningItpins exactly this: a consolidated client and an already-released one compute the same topic and can talk. Without it this change would silently cut off every shipped version.Verification
go vet ./...clean; c-shared build ok.