Skip to content

Track synchronisation universes separately from data universes - #91

Open
stewartadam wants to merge 1 commit into
mainfrom
claude/project-thread-0t11p6-8-sync-universe-tracking
Open

stewartadam wants to merge 1 commit into
mainfrom
claude/project-thread-0t11p6-8-sync-universe-tracking

Conversation

@stewartadam

@stewartadam stewartadam commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Problem

When a data packet names a synchronisation address S, the receiver called listen_universes(&[S]). Joining S's multicast group is right, because the sync packets arrive there. But listen_universes also adds S to the universes the user asked for, which had three side effects:

  • data packets sent on universe S were passed to the application even though it never listened to S;
  • the group was never left, even after sources stopped using S;
  • memberships piled up. Linux caps multicast memberships per socket (igmp_max_memberships, 20 by default), so a network that cycles through many sync addresses eventually makes the join fail, and that error came back from recv for every such packet.

Change

  • New sync_universes: HashMap<u16, Instant> on SacnReceiver. It records each sync address named by a data packet and when it was last named.
  • handle_data_packet calls a new track_sync_universe. That joins the group (if it isn't already joined, multicast is enabled, and the user isn't already listening to S) and refreshes the timestamp. S is not added to the data universes.
  • handle_sync_packet accepts sync packets for universes the user listens to or that are in sync_universes.
  • recv now calls expire_sync_universes next to the existing waiting-data timeout check. It drops sync universes that haven't been named for E131_NETWORK_DATA_LOSS_TIMEOUT, and leaves their group unless the user listens to that universe.
  • listen_universes doesn't join a group already joined for sync, since a second join fails with EADDRINUSE on Linux. mute_universe doesn't leave a group still needed for sync.
  • Drop also leaves the groups joined only for sync.

Behaviour change: data sent on a universe that is only used as a sync address is no longer delivered unless the application listens to that universe.

Tests

Three unit tests in receive.rs:

  • the sync universe isn't added to the data universes, data on it is ignored, and the sync packet still releases the waiting data;
  • an expired sync universe is forgotten (its sync packets are ignored) and can be tracked again;
  • listening to and then muting a universe that's also used for sync neither joins twice nor leaves early. I checked this test fails with AddrInUse without the listen_universes guard. Its last assertion relies on leaving an unjoined group erroring, so it's skipped on Windows.

cargo test --lib passes. The #[ignore]d sync integration tests in tests/ipv4_tests.rs need specific LAN addresses, so I ran them with those addresses switched to loopback (not committed). All 11 pass.

A data packet with a sync address made the receiver call listen_universes
for that address. That joined its multicast group, which is needed for the
sync packets, but also added it to the user's data universes, so data sent
on the sync universe was passed up although the user never listened to it,
and the group was never left.

Sync addresses are now kept in their own map with the time each was last
named. Their groups are joined without adding them to the data universes,
and left once no data packet has named them for the data loss timeout.
listen_universes and mute_universe account for a group that is also in
use for synchronisation, so it isn't joined twice or left early.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KzaQVPkrkczgX2g7wGkip5
@stewartadam stewartadam self-assigned this Nov 12, 2026
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.

2 participants