Skip to main content

Crate o_sfu

Crate o_sfu 

Source
Expand description

Odoo’s Selective Forwarding Unit (SFU) for audio/video calls.

o-sfu receives participants’ audio and video and forwards selected streams to other participants in the same room. Each sender uploads media to the SFU instead of sending a separate copy to every receiver.

Alice -- audio/video --> SFU --+--> Bob
                               |
                               +--> Carol

A room groups the participants, published media and subscriptions for a call. One server can host independently authenticated rooms for multiple tenants, such as different Odoo databases. This fits the Odoo saas and Odoo.sh architecture.

§A call through the SFU

The application backend provisions a room and gives participants credentials to join it. Browser clients use WebSocket signaling to join, publish media and choose what to receive. Media travels separately from signaling, over WebRTC.

Odoo backend -- HTTP ------> room creation and access
                                      |
                                      v
Browser <---- WebSocket ---> room membership and media requests
                                      |
                                      v
Browser <---- WebRTC/UDP --> media workers <----> other browsers

This separates decisions about the call from the work of forwarding its media. Signaling changes which streams should flow. Media workers deliver those streams as packets arrive.

§Architecture

Runtime brings together the HTTP/WebSocket servers, rooms and media workers. The HTTP control API manages rooms through RoomManager. WebSocket sessions admit participants through SfuCore and use a MediaSession for each connection to publish media and manage subscriptions.

HTTP control API ------------------------------> RoomManager
                                                      |
WebSocket session -> SfuCore -> MediaSession          |
                                   \                  /
                                    +----> Room <----+
                                            |
                                            +<----> Router
                                            |
                                            v
                                      MediaTransport
                                       |    |    |
                                       v    v    v
                         RTC workers / packet loops
                          (one thread per worker)
                        |            |             |
                     UDP socket   UDP socket   UDP socket
                        |            |             |
                        v            v             v
                     fanout       fanout        fanout
                     UDP OUT      UDP OUT       UDP OUT

A Room manages who is present and which media they publish or receive. The Router keeps track of the connections needed to deliver that media. Its decisions do not perform network I/O, so routing behavior can be tested without sockets.

MediaTransport runs the worker threads and uses str0m for WebRTC. Room policy selects media using subscriptions, video layout, active speakers and receiver bandwidth. Each worker forwards incoming media to the selected receivers, shown as fanout in the diagram.

Rooms start with one worker. config::RoomWorkerPolicy can spread new joins across additional workers in the same process. Participants still belong to one room and can receive media from participants on other workers.

§Access and encryption

The backend signs tokens for room creation and disconnect requests with the server’s AUTH_KEY. Participant tokens are verified with their room’s signing key. This lets a tenant authorize its participants without giving them the server key. See auth for token types and verification.

Admission establishes participant identity and room scope. It does not enforce the per-user permissions claim supplied by the tenant.

Signaling and media need separate transport protection:

  • An external reverse proxy terminates HTTPS and WSS. Proxy mode requires configured trusted proxies and the public edge must overwrite client-supplied forwarded host and protocol headers. See config and http::resolve_request_origin.
  • str0m encrypts media between each browser and the SFU with DTLS-SRTP. Media UDP must reach the server’s configured ANNOUNCED_IP.

§Browser client

The JavaScript bundle exposes SfuClient, the Odoo-facing API for joining calls, publishing media and subscribing to other participants. For example, with a room token supplied by the application:

import { SfuClient } from "/bundle/odoo_sfu.js";

const sfu = new SfuClient();
sfu.connect("https://sfu.example.com/ws", jsonWebToken, {
    channelUUID: "mail-channel-uuid",
});

connect() returns before authentication and media negotiation finish. The application observes stateChange and handledError for the result.

The client shares its signaling logic through o_sfu_protocol::host::ProtocolCore. The browser adapter runs that Rust logic as WebAssembly and connects it to browser WebSocket and WebRTC APIs. This keeps protocol decisions separate from browser-specific operations.

§Running and observing the server

run starts the server from configuration. Use Runtime to embed it with a caller-provided listener and shutdown signal. config controls network addresses, admission limits and media worker policy at runtime. The default Cargo feature otel-tracing enables OpenTelemetry tracing.

http::telemetry::metrics exposes Prometheus metrics for monitoring over time. http::telemetry::diagnostics exposes room, participant and worker state for investigating a call. These operator endpoints require separate access control, described in http.

AreaEntry point
Configuration and server lifecycleconfig, Runtime and run
Authentication and signaling messagesauth, http and websocket
Room behavior and media transporto_sfu_core
Connections and media routingo_sfu_router
Client signaling and Odoo bundle compatibilityo_sfu_protocol
Metrics, diagnostics and tracingo_sfu_telemetry
Shared call identifierso-sfu-model, including o_sfu_protocol::wire::UserId
Protocol constants and typeso_sfu_rfc

Modules§

application 🔒
auth
config
core
http
HTTP route and payload contracts.
runtime 🔒
Wires process services and drains them during shutdown.
websocket

Structs§

Runtime
Process services and lifecycle configuration.

Enums§

ServeError
Failure to serve or fully drain a Runtime.

Functions§

run
Errors