What's Changed
Breaking changes
setTTLremoved —MulticastSocket.setTTL(ttl)is gone. The library hardcodesIP_MULTICAST_TTL = 255at bind so the RFC 6762 §11 outbound invariant cannot be silently broken at runtime.
RFC 6762 §11
- Multicast-destination exemption now honored — Packets received on the shared multicast socket are accepted regardless of source IP, per RFC 6762 §11's carve-out for multicast-destination packets. This fixes cross-subnet-overlay multicast traffic that was previously being dropped. Packets received on per-interface unicast sockets still receive the source-subnet check.
- README §RFC 6762 §11 rewritten — Crisp SHOULD/MUST mapping, multicast-destination exemption documented, explicit note that the
IP_RECVTTLgap in Node'sdgramis upstream and not worked around from userspace.
Input validation
multicastGroupvalidated upfront — A non-multicast address now throwsmulticastGroup X is not a multicast addressbefore any socket allocation, instead of surfacing as a lateaddMembership EADDRNOTAVAIL. Newis_multicasthelper is exported from@gibme/multicast/helpers.compare_IP_addressesthrows on mixed-family inputs — Previously returned a meaningless ordering when comparing IPv4 to IPv6.
IPv6 zone-id handling
fromSelfis now zone-id-tolerant — Node 22'sdgramdelivers IPv6 link-localrinfo.addresswith a%ifacesuffix; the prior exact-string match missed it.dispatch_messagenow strips the suffix before comparing against bound addresses.srcAddressandhostnormalized — The same zone-id strip is applied at the three sites that match against bound addresses (create()host check,send()unicast-path,send()multicast-path).
Helpers
get_addressesdedup fixed — Was[...new Set(addresses)]which deduped by object reference (a no-op for freshly-constructed instances); now aMapkeyed by.addressstring.get_addressesrequiresaddr.cidr— Throws ifos.networkInterfaces()returns an entry without it. Dead-codenetmask_to_prefixfallback (IPv4-only dotted-decimal parser) removed.is_on_local_linkIPv6 link-local comment — Rewritten to acknowledge both RFC 4291 §2.4 (FE80::/10 reserved prefix) and §2.5.6 (link-local format requires middle 54 bits zero), and explain why the wider /10 check is used for inbound filtering.
Documentation
- JSDoc on
send()andSend.Options.useMulticastSocket— Concurrency note: combininguseMulticastSocket: truewithsrcAddressmutates per-socket state on the shared multicast socket viasetMulticastInterface. Concurrent calls race; serialize them in the caller, or use the default per-interface unicast path (race-free). - JSDoc on
setMulticastLoopback— Explains that it only mutatesIP_MULTICAST_LOOPon the shared multicast socket and that the authoritative user-visible loopback gate is the check insidedispatch_message.
Tests
101/101 pass. Added 8 regression tests under a new input validation and dispatch hardening block covering all of the above.
Full Changelog: v22.0.0...v22.0.1