SPICA SFU / Native real-time media

SOURCE REVIEWED / IMPLEMENTATION STARTING POINT

Forward the media. Keep the signaling flexible.

A C++23 selective forwarding architecture that keeps room control, signaling and protected media responsibilities explicit. WebSocket and raw QUIC share one signaling handler; the media remains on an ICE, DTLS and SRTP path.

ROOM / SIGNALING ACTIVEMEDIA / PACKET FORWARDING
RESTRoom controlCrow · MongoDB
WS / QUICSignalingShared handler
SPICA SFU COREParticipant registry + RoomGLib worker assignment · connection cleanup
01ICEConnectivity
02DTLSKey exchange
03SRTPProtected RTP
QUIC = SIGNALINGRTP = MEDIA
C++23Native single-process architecture
WebSocket + QUICShared signaling logic
ICE + DTLS + SRTPProtected real-time media
No decode / mix / transcodePacket-level forwarding

Architecture / Source evidence

One process. Clear subsystem ownership.

The supplied source separates room persistence, signaling transport, event-loop execution, media security and forwarding. MongoDB stays out of the real-time packet path, and both signaling transports reuse the same join and disconnect behavior.

  1. 01ROOM CONTROL

    Crow + MongoDB

    POST and GET room routes create and list room metadata while the real-time media path stays outside the database.

    REST · /rooms · ROOMSTORE
  2. 02SIGNALING

    One handler, two transports

    Crow WebSocket and a native raw-QUIC stream both adapt into the same SignalingHandler for join, SDP answer and disconnect logic.

    WEBSOCKET · QUIC · JSON
  3. 03EVENT LOOPS

    GLib worker pool

    A least-loaded pool of GMainContext and GMainLoop workers matches libnice's native execution model and removes the need for Boost.Asio.

    GLIB · LIBNICE · LEAST LOADED
  4. 04MEDIA SECURITY

    ICE + DTLS + SRTP

    libnice establishes connectivity, OpenSSL drives DTLS over memory BIOs and libsrtp protects and unprotects RTP packets.

    LIBNICE · OPENSSL · LIBSRTP
  5. 05FORWARDING

    Room-level RTP fan-out

    A packet arriving from participant A is forwarded to every other participant in that room without decoding, mixing, transcoding or re-encoding.

    PACKET IN → OTHER PARTICIPANTS

Two-way join flow

From room request to protected RTP.

A participant registry and a reverse connection lookup keep join, SDP-answer routing and disconnect cleanup transport-neutral.

  1. 01

    Create or list a room

    The control plane persists room metadata and creates the corresponding live Room object.

  2. 02

    Join over WebSocket or QUIC

    A compact JSON envelope identifies the room and participant through the shared signaling handler.

  3. 03

    Gather ICE + return local SDP

    The assigned GLib worker prepares ICE credentials, local candidates and a session fingerprint.

  4. 04

    Apply the SDP answer

    The participant registry routes the answer to the correct IceSession and establishes ICE, DTLS and SRTP state.

  5. 05

    Forward protected media

    Inbound SRTP is unprotected, handed to the Room forwarding rule and protected again for every other participant.

Selective forwarding / Explicit boundary

Forward packets. Do not rebuild the media.

Each Room owns participant IceSession objects. Once an inbound SRTP packet is authenticated and unprotected, Room::forward sends it to every other participant, whose session protects it for egress.

That is deliberately different from a mixer, transcoder or CDN. The current rule is simple all-to-all forwarding; congestion policy, stream selection and large-room scaling remain engineering tracks.

PARTICIPANT ASRTP packetICE-selected path
ROOMUnprotect + forwardNo decode · no mix · no transcode
OTHER PARTICIPANTSProtected egressOne send per recipient

QUIC / Native signaling channel

Keep QUIC—and finish the reason it was chosen.

Native clients do not need to imitate WebSocket over HTTP/3. The source instead uses a raw bidirectional QUIC stream with newline-delimited JSON, ngtcp2 and OpenSSL, feeding the same SignalingHandler used by WebSocket.

Readiness / Honest engineering boundary

Detailed source is not the same as a verified runtime.

The architecture and responsibilities are concrete, but this source snapshot is not build-verified: it has not been compiled or run against the actual dependency headers, and it contains no automated tests.

SOURCE EVIDENCEREVIEWED

What the supplied implementation establishes.

  • C++23 single-process server shape with Crow HTTP and WebSocket entry points
  • MongoDB-backed RoomStore using mongocxx and bsoncxx patterns
  • Transport-neutral participant registry and disconnect reverse lookup
  • GLib-driven libnice ICE sessions with DTLS key export into libsrtp
  • ngtcp2 + OpenSSL raw-QUIC signaling with newline-delimited JSON framing
  • Explicit packet-forwarding rule in Room::forward
HARDENING TRACKREQUIRED

What must happen before operational dependence.

  • Compile and run against the actual Crow, libnice, ngtcp2, OpenSSL, libsrtp and MongoDB headers
  • Verify the remote DTLS fingerprint and negotiate the DTLS role from SDP
  • Negotiate current SRTP profiles instead of assuming one fixed profile
  • Complete QUIC connection migration and resolve local-address selection on multi-interface hosts
  • Marshal disconnect cleanup onto the Room's owning GLib context
  • Add authentication, authorization, accounts, quotas and durable room lifecycle policy
  • Add RTCP feedback, congestion control, simulcast or SVC selection and egress isolation
  • Build automated tests, interoperability tests, soak tests, load tests, metrics and failure injection

SPICA Networks engineering

Design the media path and its operational boundary together.

Talk to Engineering