Architecture

Remora is a Rust workspace with three crates.

text
crates/
  proto/    wire protocol: framing, rendezvous + session messages,
            SPAKE2 handshake and the encrypted channel
  server/   remora-server: ID registry, NAT traversal, relay
  app/      remora: egui desktop app, host and viewer in one

The app

ModuleResponsibility
host.rsRegisters with the server, listens for direct connections, authenticates viewers, runs capture and input threads
viewer.rsConnects, decodes frames on a background thread, tracks stats
net.rsRoute selection (LAN direct → peer-to-peer → relay) and the port-443 fallback
p2p.rsUDP hole punching and the QUIC transport
codec.rsThe tile codec
capture.rs / input.rsScreen capture (xcap) and input injection (enigo)
channel.rsPrioritized outgoing queue
common.rsChat, file transfer, clipboard sync
logo.rsThe logo, rasterized for the window icon, the sidebar and the .exe icon
ui/egui interface: theme, vector icons, components, pages and the session view

Screen codec

The screen is cut into 64 × 64 tiles. Each frame, only tiles that changed since the previous frame are sent, each encoded as one of:

  • Solid colour, for flat areas (3 bytes),
  • JPEG, in the speed and balanced modes,
  • LZ4-compressed RGB, in lossless mode.

Tiles are encoded and decoded in parallel with rayon. A static desktop costs almost nothing; a full-screen video is where a hardware video codec would do better (see the roadmap).

Flow control: the viewer acknowledges each frame after decoding it, and the host never has more than two frames in flight. The frame rate therefore adapts to the slower of the network and the viewer's CPU, instead of queueing up latency.

Message priority

Each session has three outgoing queues, drained in strict order:

  1. Control: input, chat, acknowledgements, clipboard;
  2. Video: at most two frames;
  3. Bulk: file chunks of 64 KB.

So a large file transfer never delays a mouse click.

Wire protocol

Everything is length-prefixed postcard messages. The rendezvous protocol between apps and the server is plaintext and small: register, heartbeat, connect, join relay, plus the UDP hello used for hole punching. Session messages travel only inside the encrypted channel. The protocol carries a version number, and peers with different versions refuse to connect.

The docs site

This site lives in docs/: Next.js with MDX pages, shadcn/ui components, exported as static files for GitHub Pages.