Skip to main content

Crate o_sfu_protocol

Crate o_sfu_protocol 

Source
Expand description

browser and native signaling protocol for o-sfu

o-sfu-protocol keeps client-side protocol state pure the core state machine accepts host events and returns ordered command vectors that the embedding host executes through its own WebSocket, RTCPeerConnection and timer APIs

the crate has 3 public facades:

  • host is the state-machine surface for browser, native and test hosts
  • wire contains JSON envelope and signaling payload types
  • bundle preserves the browser bundle compatibility API used by Odoo

Hosts execute every command in each returned vector before reporting the resulting socket and peer-connection events to the same host::ProtocolCore. The host creates the peer connection when applying an initial offer. While that negotiation is pending, the host submits its correlated answer then reports readiness after the peer connection becomes usable.

use o_sfu_protocol::host::{Command, ConnectionState, NegotiationKind, ProtocolCore};
let mut core = ProtocolCore::new();
let connect = core.connect("wss://sfu.test/ws", "signed-token", None);
assert!(matches!(
    connect.as_slice(),
    [
        Command::SetAvailableFeatures { .. },
        Command::SetRecordingState { .. },
        Command::EmitStateChange { state: ConnectionState::Connecting, .. },
        Command::Connect { .. },
    ]
));

let auth = core.on_ws_open();
assert!(matches!(auth.as_slice(), [Command::SendWebSocket { .. }]));
let welcome = core.on_ws_message(welcome);
assert!(matches!(welcome.get(2),
    Some(Command::EmitStateChange { state: ConnectionState::Authenticated, .. })
));

let offer = r#"[{"t":"offer","q":"offer-1","p":{"sdp":"v=0\r\n","uploadSlots":[]}}]"#;
let negotiation = core.on_ws_message(offer);
let [Command::ApplyNegotiation { request_id, kind, .. }] = negotiation.as_slice()
else {
    return Err("unexpected negotiation command order".into());
};

assert!(core.on_transport_ready().is_empty());

let answer = core.submit_negotiation_answer(request_id, *kind, "v=0\r\ns=answer\r\n");
assert_eq!(*kind, NegotiationKind::Offer);
assert!(matches!(answer.as_slice(), [Command::SendWebSocket { .. }]));

// The host sends `answer` then waits until the peer connection is usable.
let ready = core.on_transport_ready();
assert_eq!(
    ready.as_slice(),
    &[Command::EmitStateChange { state: ConnectionState::Connected, cause: None }]
);

Modulesยง

bundle
browser bundle compatibility API
bundle_api ๐Ÿ”’
rust payloads for odoo browser bundle state and updates
core ๐Ÿ”’
Pure client-side signaling state machine for the o-sfu protocol.
host
host-owned protocol state machine and side-effect commands
host_bridge ๐Ÿ”’
shared ๐Ÿ”’
signaling ๐Ÿ”’
Native signaling protocol surface and wire codec.
wire
JSON wire envelopes and signaling payloads