mcrx-core
mcrx-core is a runtime-agnostic and portable multicast receiver library for
IPv4 and IPv6 ASM/SSM.
It is built for applications and integrations that want a small multicast receive core with explicit lifecycle and socket ownership control.
The receive path supports IPv4 and IPv6 ASM/SSM, including pktinfo-style receive metadata on platforms that expose it.
Highlights
- IPv4 ASM and SSM receive support
- IPv6 ASM and SSM receive support
- Non-blocking receive API
- Explicit subscription lifecycle:
add,join,leave,remove - Multiple concurrent subscriptions with fair receive across them
- Caller-provided socket support
- Event-loop friendly socket borrowing and extraction APIs
- Optional Tokio adapter via the
tokiofeature - Optional Python bindings with an asyncio helper via the sibling
mcrx-core-pycrate - Optional receive metadata on platforms that expose it
- Optional metrics via the
metricsfeature
Install
With the optional Tokio adapter:
With optional metrics:
Python Bindings
Python bindings live in the sibling workspace crate
mcrx-core-py.
That split keeps mcrx-core as a pure Rust crate while still shipping a
Python-friendly API with:
ContextandSubscription- packet and receive metadata objects
AsyncSubscriptionadd_reader()for callback-style asyncio integration
Quick Start
use ;
use Ipv4Addr;
let mut ctx = new;
let config = asm;
let id = ctx.add_subscription ?;
ctx.join_subscription ?;
if let Some = ctx.try_recv_any ?
Existing Sockets
Use add_subscription_with_socket() when you need to create or bind the socket
yourself:
use ;
use ;
use ;
let mut ctx = new;
let config = asm;
let socket = new ?;
socket.set_reuse_address ?;
socket.bind ?;
let id = ctx.add_subscription_with_socket ?;
ctx.join_subscription ?;
Event Loop Integration
Borrow the live socket from a subscription:
let subscription = ctx.get_subscription.unwrap;
let socket = subscription.socket;
let raw = subscription.as_raw_fd;
Or extract the subscription and move it into another loop or runtime:
let subscription = ctx.take_subscription.unwrap;
let parts = subscription.into_parts;
let socket = parts.socket;
Tokio Integration
With the tokio feature enabled, you can wrap an extracted subscription and
await packets asynchronously:
use TokioSubscription;
let subscription = ctx.take_subscription.unwrap;
let mut subscription = new ?;
let packet = subscription.recv.await?;
TokioSubscription is an owned single-consumer receive handle, so its async
receive methods take &mut self.
Run the Tokio example with:
Optional Receive Metadata
If you need more delivery context than source, group, port, and payload, use the metadata-aware receive APIs:
let subscription = ctx.get_subscription.unwrap;
if let Some = subscription.try_recv_with_metadata ?
Demo Binaries
Basic receiver:
Sender:
Tokio receiver:
Metadata inspection receiver:
IPv6 SSM Notes
For IPv6 SSM, use ff3x::/32 groups. The x nibble is the multicast scope:
ff31::/16→ interface-local, good for same-host testsff32::/16→ link-local, only for the local L2 linkff35::/16→ site-localff38::/16→ organization-localff3e::/16→ global scope
Prefer dynamic SSM group IDs such as ff31::8000:1234 or ff3e::8000:1234.
For receivers:
- the SSM
sourceis the sender's IP address - the
interfaceis the receiver's local join interface - on one machine those may be the same
- across machines they usually differ
- for IPv6 ASM or SSM, the receiver CLIs accept
--interface ::1,--interface fe80::1%7,--interface fe80::1%en0, or a bare interface index such as--interface 7
For senders:
- when you pass an IPv6 address to
mcrx_send, the sender binds to that exact local IPv6 address and also selects the corresponding multicast interface - this matters for SSM, because the receiver filters on the exact packet source
- for link-local SSM groups such as
ff32::/16, send from a link-localfe80::...source - for wider-scope groups such as
ff35::/16orff3e::/16, use a ULA or global IPv6 source that is valid on that network
Same-host IPv6 SSM example:
Cross-machine IPv6 SSM example on the same network:
# sender host
# receiver host
Documentation
Platform Support
| OS | ASM | SSM | Notes |
|---|---|---|---|
| macOS | ✅ | ✅ | Verified |
| Linux | ✅ | ✅ | Verified |
| Windows | ✅ | ✅ | Verified |
IPv6 ASM/SSM support and pktinfo-style receive metadata are wired into the receive path on the same platforms.
Compatibility
ASM cross-platform compatibility:
| Sender / Receiver | macOS | Windows | Linux | Android | iOS |
|---|---|---|---|---|---|
| macOS | ✅ | ✅ | ✅ | ⏳ | ⏳ |
| Windows | ✅ | ✅ | ✅ | ⏳ | ⏳ |
| Linux | ✅ | ✅ | ✅ | ⏳ | ⏳ |
| Android | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ |
| iOS | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ |
SSM cross-platform compatibility:
| Sender / Receiver | macOS | Windows | Linux | Android | iOS |
|---|---|---|---|---|---|
| macOS | ✅ | ✅ | ✅ | ⏳ | ⏳ |
| Windows | ✅ | ✅ | ✅ | ⏳ | ⏳ |
| Linux | ✅ | ✅ | ✅ | ⏳ | ⏳ |
| Android | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ |
| iOS | ⏳ | ⏳ | ⏳ | ⏳ | ⏳ |
Notes
- macOS may temporarily emit IGMPv2 reports in some SSM setups
- that can break SSM behavior on the network until the host state recovers
License
BSD 2-Clause