Skip to content

Architecture

Tobias Vorwachs edited this page Oct 24, 2026 · 1 revision

Architecture

Overview

flowchart TB
    subgraph UI["ui/ (React 19 + TypeScript)"]
        F[Features: channels, chat, members, settings, wizard]
        API["getApi() client + generated bindings"]
    end
    subgraph Shell["src-tauri/ (Tauri 2 shell)"]
        CMD[Commands and events]
        OS[Tray, deep links, push-to-talk, window]
    end
    subgraph Engine["crates/engine"]
        SES[Session state machine]
        VOX[Voice, chat, follow, people, profile, diag]
    end
    PROTO[crates/protocol]
    AUDIO[crates/audio]
    STORE[crates/store]
    SRV[(Mumble server)]
    KR[(OS keyring)]
    DB[(SQLite)]

    F --> API --> CMD
    CMD --> SES
    OS --> CMD
    SES --> PROTO
    VOX --> AUDIO
    SES --> STORE
    PROTO <-->|"TLS control + UDP voice"| SRV
    STORE --> DB
    STORE --> KR
Loading

Layers

  • UI (ui/): React 19, TypeScript in strict mode, i18next for en/es/de, DOMPurify and marked for rendering sanitized chat. It only talks to the engine through getApi() (ui/src/api), which uses the generated tauri-specta bindings or a mock for tests. It never touches the network.
  • App shell (src-tauri/): Tauri commands (src-tauri/src/commands/*.rs) and events that convert between UI types and engine types. Also owns platform integration: tray, mumble:// deep links, single instance, push-to-talk backends (global shortcut plugin, XDG desktop portal on Wayland via ashpd, evdev for mouse buttons on Wayland, X11 XInput2, macOS event tap), window handling.
  • Engine (crates/engine): app state, the server session (connect, reconnect, certificate trust), voice, text chat, following channels, people, profile and avatars, notification sounds, diagnostics. The shell talks only to Engine.
  • Protocol (crates/protocol): TLS control channel (rustls), protobuf messages (prost, from Mumble's BSD-licensed Mumble.proto in proto/), permission handling, and the voice transport.
  • Audio (crates/audio): device I/O, DSP, Opus, jitter buffer, mixer, bitrate controller.
  • Store (crates/store): SQLite (mumcord.sqlite3) for servers, trust decisions, followed channels, chat history, per-person settings and app settings; the identity certificate and passwords in the OS secure storage.
  • Positional (crates/positional): placeholder for stage 1b.

The interface between UI and engine is documented in docs/engine-api.md.

Audio pipeline

Send path: capture (cpal) → echo cancellation → AI noise suppression → automatic gain → voice-activity detection or push-to-talk gate → Opus encoding.

  • Echo cancellation and gain use WebRTC audio processing (the sonora crate); noise suppression uses RNNoise (nnnoiseless).
  • Opus is the only send codec. The bitrate controller picks the highest bitrate the server allows and lowers it when packet loss rises.
  • Receive path: decode, adaptive jitter buffer, mixer (per-person volume and mute), playback. Resampling uses rubato; lock-free ring buffers (rtrb) connect threads.
  • Audio runs on dedicated real-time threads that never block: no allocation, locks or I/O in the audio callback.
  • Latency target: at most 150 ms mouth-to-ear on a stable connection, excluding network transit.

Network

  • Control channel: TLS over TCP with the client certificate. First connection to an unknown or self-signed server certificate asks for trust; a changed certificate blocks the connection with a warning.
  • Voice: UDP encrypted with OCB2-AES128 as the Mumble protocol defines it. If UDP is blocked, voice is tunnelled through the TCP connection automatically. Both the legacy and the 1.5 UDP packet formats are supported.
  • Compatibility: client protocol version 1.5; servers 1.4+ fully supported; older servers best-effort. No protocol extensions.
sequenceDiagram
    participant C as Mumcord
    participant S as Mumble server
    C->>S: TLS connect (client certificate)
    C->>S: Version, Authenticate
    S-->>C: CryptSetup (UDP keys)
    S-->>C: ChannelState / UserState
    S-->>C: ServerSync
    C-)S: Voice (UDP, encrypted)
    Note over C,S: UDP ping fails: voice tunnelled via TCP
Loading

Storage and secrets

  • App data and logs live in the OS-standard app folders for the identifier app.mumcord.client.
  • The identity certificate and server passwords are kept only in the OS secure storage (keyring: Secret Service on Linux, Credential Manager on Windows, Keychain on macOS).
  • No secrets in settings files, logs or builds. Chat history is stored locally only and can be deleted.

Testing hooks

The test-backend Cargo feature replaces real audio devices with a null or file backend for E2E tests (see Testing).

Clone this wiki locally