code wiki / (root) / nx_media_transport.nx

nx_media_transport.nx

buildroot/runtime/nx_media_transport.nx

5664 B127 linesdepth 6pulls 10 transitivereach 0 importersview sourcekind orphan librarytopic media
docsdependenciesstructsconstsfunctions

about

nx_media_transport.nx -- sovereign secure-datagram media transport. THE missing layer the rest of the media stack already expects but nobody had written yet: * nx_audio_session.nx: "Playback: caller hands us wire bytes (decoded by TRANSPORT from the remote peer)" <- this module. * nx_call.nx: "zero new transport logic here ... nx_signaling.nx -- SDP exchange + ICE candidates" <- nx_signaling never existed; this is the bytes-on-the-wire half. It is COMPOSED from primitives that already ship -- no new crypto: nx_aead (ChaCha20-Poly1305 seal/open, RFC 8439) nx_udp_rv (native-lane UDP; rv64-numbered so the compiler's syscall translation is correct) NAT traversal is the already-proven nx_turn_relay (Arc 4 A.5.2). Sovereign equivalent of WebRTC's DTLS-SRTP: AEAD-sealed media datagrams over UDP. Payload-agnostic: carries nx_voice_frame audio, video frames, or chat bytes identically. === SENDER-SCOPED NONCE (fixes the multi-party keystream-reuse bug) === Wire datagram: [0..7] seq u64 LE, cleartext, authenticated as AAD [8..11] sender_id u32 LE, cleartext, authenticated as AAD [12..] ciphertext = AEAD-sealed payload (same length as payload) [tail 16] Poly1305 tag nonce (12 B) = seq(8 LE) || sender_id(4 LE). In a multi-sender room with ONE shared room key, two peers both start seq at 0/1 -- WITHOUT the sender_id that is a catastrophic (key, nonce) reuse (ChaCha20 keystream + Poly1305 break). Binding the sender_id into the nonce makes every (sender, seq) pair unique, so the E2EE-through-hub property holds for the shared-room-key case. Each sender MUST use a distinct sender_id and a strictly increasing seq. Key exchange is OUT OF SCOPE here: x25519 + ML-KEM (kyber) already ship; this module takes the 32-byte session key they produce. PERF NOTE (honest): aead_seal/aead_open sys_mmap scratch per call. Fine for proofs; sustained real-time should arena-hoist the AEAD

dependencies 2 imports · 0 importers

nx_aead.nx nx_udp_rv.nx nx_media_transport.nx

imports: nx_aead.nxnx_udp_rv.nx

imported by: nobody (leaf or entry point)

structs

none

consts

46const NX_MXPORT_SEQ_BYTES: i64 = 8
47const NX_MXPORT_SID_BYTES: i64 = 4
48const NX_MXPORT_HDR_BYTES: i64 = 12 // seq(8) + sender_id(4) = AAD + nonce material
49const NX_MXPORT_TAG_BYTES: i64 = 16
50const NX_MXPORT_OVERHEAD: i64 = 28 // 12 header + 16 tag

functions

52func _mx_put_u64_le(buf: *u8, off: i64, v: i64) -> i64
57func _mx_get_u64_le(buf: *u8, off: i64) -> i64
called by 1: nx_mxport_open
63func _mx_put_u32_le(buf: *u8, off: i64, v: i64) -> i64
67func _mx_get_u32_le(buf: *u8, off: i64) -> i64
72func _mx_nonce(nonce: *u8, sender_id: i64, seq: i64) -> i64
80func nx_mxport_seal(key: *u8, sender_id: i64, seq: i64,
98func nx_mxport_open(key: *u8, wire: *u8, wire_len: i64,
115func nx_mxport_sender(wire: *u8, wire_len: i64) -> i64
calls 1: _mx_get_u32_le
121func nx_mxport_send(fd: i64, dest16: *u8, key: *u8, sender_id: i64, seq: i64,